Babylongjs - height map, sky box, picture wizard and K-frame animation

Posted by snafudawn on Thu, 16 Dec 2021 02:12:19 +0100

We want to build the village in the valley. You can create hills from a mesh, but there is another way to add vertical heights to the ground mesh. This is achieved using a height map that uses gray shadows to determine the height of the ground. The white area is the highest and the black area is the lowest. This simple height map:

 

There is a large black area in the middle to accommodate the village, the white area creates the hills, and the gray area is the road from the valley.

In this picture, the camera is pulled further and the vertical height is exaggerated.

const largeGround = BABYLON.MeshBuilder.CreateGroundFromHeightMap("largeGround", "url to height map", 
    {width:150, height:150, subdivisions: 20, minHeight:0, maxHeight: 10});

The subdivision attribute of the option divides the ground into 20 x 20 = 400 parts. The more subdivisions, the finer the level of height calculation. The minHeight and maxHeight attributes determine the vertical height of the black and white areas respectively, and the gray areas are scaled accordingly.

But obviously, our ground should not only have height change, but also have Grassland:

//Create Village ground
const groundMat = new BABYLON.StandardMaterial("groundMat");
groundMat.diffuseTexture = new BABYLON.Texture("url to ground texture");
groundMat.diffuseTexture.hasAlpha = true;

const ground = BABYLON.MeshBuilder.CreateGround("ground", {width:24, height:24});
ground.material = groundMat;

//large ground
const largeGroundMat = new BABYLON.StandardMaterial("largeGroundMat");
largeGroundMat.diffuseTexture = new BABYLON.Texture("url to large ground texture");

const largeGround = BABYLON.MeshBuilder.CreateGroundFromHeightMap("largeGround", "url to heightmap", 
    {width:150, height:150, subdivisions: 20, minHeight:0, maxHeight: 4});
largeGround.material = largeGroundMat;
//To prevent flashing
largeGround.position.y = -0.01;

Skybox:

We can apply Six suitable images to large-scale images Sky box Inside the cube to simulate the appearance of the sky. (images are easier and faster to render than 3D objects, and are just as good for distant landscapes.)

Skybox images usually use CubeTexture load. The cube texture constructor takes a base URL and (by default) appends "px.jpg", nx.jpg ", py.jpg", ny.jpg ", pz.jpg" and "nz.jpg" to load the + X, - x, + y, - y, + z and - z faces of the cube.

You must use the sky box even if it is not a reflection map reflectionTexture Apply a cube texture. take coordinate The MODE is set to SKYBOX_ MODE will paint the texture directly on the cube instead of simulating reflection.

const skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {size:150}, scene);
const skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
skyboxMaterial.backFaceCulling = false;
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/skybox", scene);
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
skybox.material = skyboxMaterial;

//Restrict the camera from crossing the ground
camera.upperBetaLimit = Math.PI / 2.2;

Image Sprite:

We will plant several trees in our world, each with 500 trees. To maintain rendering speed, we will use sprites. These are two-dimensional images that are always facing the camera. The figure is as follows:

We need to set up a manager for the sprite Atlas:

const spriteManagerTrees = new BABYLON.SpriteManager("treesManager", "url to tree image", 2000, {width: 512, height: 1024}, scene);


//500 trees are randomly generated in a certain range
for (let i = 0; i < 500; i++) {
    const tree = new BABYLON.Sprite("tree", spriteManagerTrees);
    tree.position.x = Math.random() * (-30);
    tree.position.z = Math.random() * 20 + 8;
    tree.position.y = 0.5;
}

for (let i = 0; i < 500; i++) {
    const tree = new BABYLON.Sprite("tree", spriteManagerTrees);
    tree.position.x = Math.random() * (25) + 7;
    tree.position.z = Math.random() * -35  + 8;
    tree.position.y = 0.5;
}

The parameters are the name of the manager, the url of the image, the maximum number of sprites, and the object that specifies the width and height of the sprite, in which case it is the width and height of the image.

sprite animation

You can animate using a set of images in a sprite map.

The map above consists of a frame of cells of the same size, 5 horizontal and 4 lower. The width and height given in the manager this time is the width and height of a cell.

The animation of the sprite is set by giving the first and last cells to be used, whether it loops (true) or not and the time between cell frames:
 

const spriteManagerUFO = new BABYLON.SpriteManager("UFOManager","url to ufo image", 1, {width: 128, height: 76});

const ufo = new BABYLON.Sprite("ufo", spriteManagerUFO);
ufo.playAnimation(0, 16, true, 125);

Topics: Javascript Front-end