I think it might be convenient if there was a way to create grounds from height-map textures (texture objects) out of the box as for now it is only possible to load them via url leaving behinds procedural textures. Also it can be even useful in cases when one needs to create procedural levels.
I managed to come up with such sort of code, but it’s look a little bit clumsy because vertexData.applyToMesh
receives as input only unsigned RGBA buffer.
BABYLON.Mesh.CreateGroundFromHeightTexture = (name, texture, width, height, subdivisions, minHeight, maxHeight, scene, updatable, onReady, alphaFilter) => {
let options = {
width: width,
height: height,
subdivisions: subdivisions,
minHeight: minHeight,
maxHeight: maxHeight,
updatable: updatable,
onReady: onReady,
alphaFilter: alphaFilter
};
return BABYLON.GroundBuilder.CreateGroundFromHeightTexture(name, texture, options, scene);
};
BABYLON.GroundBuilder.CreateGroundFromHeightTexture = (name, texture, options, scene) => {
var width = options.width || 10.0;
var height = options.height || 10.0;
var subdivisions = options.subdivisions || 1 | 0;
var minHeight = options.minHeight || 0.0;
var maxHeight = options.maxHeight || 1.0;
var filter = options.colorFilter || new BABYLON.Color3(0.3, 0.59, 0.11);
var alphaFilter = options.alphaFilter || 0.0;
var updatable = options.updatable;
var onReady = options.onReady;
scene = scene || BABYLON.EngineStore.LastCreatedScene;
var ground = new BABYLON.GroundMesh(name, scene);
ground._setReady(false);
ground._subdivisionsX = subdivisions;
ground._subdivisionsY = subdivisions;
ground._width = width;
ground._height = height;
ground._maxX = ground._width / 2.0;
ground._maxZ = ground._height / 2.0;
ground._minX = -ground._maxX;
ground._minZ = -ground._maxZ;
if (texture.textureFormat !== BABYLON.Engine.TEXTUREFORMAT_RGBA) {
throw "GroundBuilder: texture must correspond RGBA format";
}
var buffer = texture.readPixels(0, 0, buffer);
var byteBuffer = buffer;
if (texture.textureType !== BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT) {
var length = buffer.length;
byteBuffer = Uint8Array(length);
for (i = 0; i < length; i += 4) {
byteBuffer[i] = buffer[i] * 255.0;
byteBuffer[i + 1] = buffer[i] * 255.0;
byteBuffer[i + 2] = buffer[i] * 255.0;
byteBuffer[i + 3] = buffer[i] * 255.0;
}
}
var vertexData = BABYLON.VertexData.CreateGroundFromHeightMap({
width: width, height: height,
subdivisions: subdivisions,
minHeight: minHeight, maxHeight: maxHeight, colorFilter: filter,
buffer: byteBuffer, bufferWidth: texture.getSize().width, bufferHeight: texture.getSize().height,
alphaFilter: alphaFilter
});
vertexData.applyToMesh(ground, updatable);
if (onReady) {
onReady(ground);
}
ground._setReady(true);
return ground;
};
PS I don’t know js well and am new to Babylon JS so I presume I’m missing something.