Babylon.js-5 位置,旋转与缩放

参考链接:https://doc.babylonjs.com/babylon101/position

位置,旋转与缩放

位置(Position)旋转(Rotation)缩放(Scaling)是基本的三种变换。

在其他环境中也称为平移(Translation),旋转(Rotation)与缩放(Scaling)

在本例中,我们使用BABYLON官网提供的场景生成器来生成一个包含一个领航员(Pilot)的场景,其中领航员的形状如下图:

位置 (Position)

mesh.position表示一个mesh的位置,类型是BABYLON.Vector3

我们使用如下代码来演示位置的变化,领航员的初始位置为(2,3,4),我们将其的x轴位置平滑移动到8,再移动回3,接着将y轴位置平滑移动到12,再将z轴位置平滑移动到16,再移动会4,使用如下代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const canvasPosition = document.getElementById('renderCanvas-5-position')
const enginePosition = new BABYLON.Engine(canvasPosition,true)
const objPosition = createScene(enginePosition,canvasPosition)
const scenePosition=objPosition.scene
const animePosition=(pilot)=>{
let state=0
const anime=()=>{
if(state===0){
pilot.position.x+=0.1
if(pilot.position.x>=8){
state=1
}
}else if(state===1){
pilot.position.x-=0.1
if(pilot.position.x<=2){
state=2
}
}
else if(state===2){
pilot.position.y+=0.1
if(pilot.position.y>=12){
state=3
}
}else if(state===3){
pilot.position.y-=0.1
if(pilot.position.y<=3){
state=4
}
}
else if(state===4){
pilot.position.z+=0.1
if(pilot.position.z>=16){
state=5
}
}else if(state===5){
pilot.position.z-=0.1
if(pilot.position.z<=4){
state=0
}
}
requestAnimationFrame(anime)
}
anime()
}
animePosition(objPosition.pilot)
enginePosition.runRenderLoop(function(){scenePosition.render()})

效果如下:

旋转 (Rotation)

mesh.rotation表示一个mesh的旋转,类型是BABYLON.Vector3,x,y,z分别表示沿着某个轴的旋转的弧度值,方向是当旋转轴指向自己时针旋转为正数(增加)。

我们使用如下代码来演示位置的变化,领航员的初始位置为(2,3,4),首先沿着x轴旋转一周,再沿着y轴旋转一周,再沿着z轴旋转一周,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const canvasRotation = document.getElementById('renderCanvas-5-rotation')
const engineRotation = new BABYLON.Engine(canvasRotation,true)
const objRotation = createScene(engineRotation,canvasRotation)
const sceneRotation=objRotation.scene
const animeRotation=(pilot)=>{
let state=0
const anime=()=>{
if(state===0){
pilot.rotation.x+=2*Math.PI/180
if(pilot.rotation.x>=2*Math.PI){
state=1
pilot.rotation.x=0
}
}else if(state===1){
pilot.rotation.y+=2*Math.PI/180
if(pilot.rotation.y>=2*Math.PI){
state=2
pilot.rotation.y=0
}
}
else if(state===2){
pilot.rotation.z+=2*Math.PI/180
if(pilot.rotation.z>=2*Math.PI){
state=0
pilot.rotation.z=0
}
}
requestAnimationFrame(anime)
}
anime()
}
animeRotation(objRotation.pilot)
engineRotation.runRenderLoop(function(){sceneRotation.render()})

效果如下:

我们还可以使用mesh.addRotation(x,y,z)来进行mesh的连贯旋转,其返回值是mesh自身。

缩放 (Scaling)

mesh.scaling表示一个mesh的缩放,类型是BABYLON.Vector3,x,y,z分别表示沿着某个轴的缩放倍数。

我们使用如下代码来演示位置的变化,领航员的初始位置为(2,3,4),首先沿着x轴缩放3倍,再沿着y轴缩放3倍,再沿着z轴缩放3倍(注:缩放3倍等于变为原来的4倍),代码如下:

注意:由于局部坐标轴已经是领航员Pilot的一部分,所以进行缩放时局部坐标轴也会变化,此处为了简化代码没有进行局部坐标轴的修改。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const canvasScaling = document.getElementById('renderCanvas-5-scaling')
const engineScaling = new BABYLON.Engine(canvasScaling,true)
const objScaling = createScene(engineScaling,canvasScaling)
const sceneScaling=objScaling.scene
const animeScaling=(pilot)=>{
let state=0
const anime=()=>{
if(state===0){
pilot.scaling.x+=0.04
if(pilot.scaling.x>=4){
state=1
}
}else if(state===1){
pilot.scaling.x-=0.04
if(pilot.scaling.x<=1){
state=2
}
}
else if(state===2){
pilot.scaling.y+=0.04
if(pilot.scaling.y>=4){
state=3
}
}else if(state===3){
pilot.scaling.y-=0.04
if(pilot.scaling.y<=1){
state=4
}
}
else if(state===4){
pilot.scaling.z+=0.04
if(pilot.scaling.z>=4){
state=5
}
}else if(state===5){
pilot.scaling.z-=0.04
if(pilot.scaling.z<=1){
state=0
}
}
requestAnimationFrame(anime)
}
anime()
}
animeScaling(objScaling.pilot)
engineScaling.runRenderLoop(function(){sceneScaling.render()})

效果如下:

我们还可以通过设置mesh的updatable属性为true,然后更新顶点坐标来进行位置,旋转与缩放的变换,在接下来的章节将会介绍。

createScene方法代码(修改过的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
    var createScene = function (engine,canvas) {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(.5, .5, .5);

// camera
var camera = new BABYLON.ArcRotateCamera("camera1", 0, 0, 0, new BABYLON.Vector3(2, 3, 4), scene);
camera.setPosition(new BABYLON.Vector3(10, 3, -10));
camera.attachControl(canvas, false);
// lights
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 0.5, 0), scene);
light.intensity = 0.8;


/************Start Pilot*********************************/
var body = BABYLON.MeshBuilder.CreateCylinder("body", { height: 0.75, diameterTop: 0.2, diameterBottom: 0.5, tessellation: 6, subdivisions: 1 }, scene);
var arm = BABYLON.MeshBuilder.CreateBox("arm", { height: 0.75, width: 0.3, depth: 0.1875 }, scene);
arm.position.x = 0.125;
var pilot = BABYLON.Mesh.MergeMeshes([body, arm], true);

var localOrigin = localAxes(2);
localOrigin.parent = pilot;
/*************End Pilot****************************************/

//#####################BABYLON 101 DEMO CODE POSITION###################

pilot.position = new BABYLON.Vector3(2, 3, 4);

//#############################################################

/*********************************Start World Axes********************/
var showAxis = function (size) {
var makeTextPlane = function (text, color, size) {
var dynamicTexture = new BABYLON.DynamicTexture("DynamicTexture", 50, scene, true);
dynamicTexture.hasAlpha = true;
dynamicTexture.drawText(text, 5, 40, "bold 36px Arial", color, "transparent", true);
var plane = new BABYLON.Mesh.CreatePlane("TextPlane", size, scene, true);
plane.material = new BABYLON.StandardMaterial("TextPlaneMaterial", scene);
plane.material.backFaceCulling = false;
plane.material.specularColor = new BABYLON.Color3(0, 0, 0);
plane.material.diffuseTexture = dynamicTexture;
return plane;
};

var axisX = BABYLON.Mesh.CreateLines("axisX", [
new BABYLON.Vector3.Zero(), new BABYLON.Vector3(size, 0, 0), new BABYLON.Vector3(size * 0.95, 0.05 * size, 0),
new BABYLON.Vector3(size, 0, 0), new BABYLON.Vector3(size * 0.95, -0.05 * size, 0)
], scene);
axisX.color = new BABYLON.Color3(1, 0, 0);
var xChar = makeTextPlane("X", "red", size / 10);
xChar.position = new BABYLON.Vector3(0.9 * size, -0.05 * size, 0);
var axisY = BABYLON.Mesh.CreateLines("axisY", [
new BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, size, 0), new BABYLON.Vector3(-0.05 * size, size * 0.95, 0),
new BABYLON.Vector3(0, size, 0), new BABYLON.Vector3(0.05 * size, size * 0.95, 0)
], scene);
axisY.color = new BABYLON.Color3(0, 1, 0);
var yChar = makeTextPlane("Y", "green", size / 10);
yChar.position = new BABYLON.Vector3(0, 0.9 * size, -0.05 * size);
var axisZ = BABYLON.Mesh.CreateLines("axisZ", [
new BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, 0, size), new BABYLON.Vector3(0, -0.05 * size, size * 0.95),
new BABYLON.Vector3(0, 0, size), new BABYLON.Vector3(0, 0.05 * size, size * 0.95)
], scene);
axisZ.color = new BABYLON.Color3(0, 0, 1);
var zChar = makeTextPlane("Z", "blue", size / 10);
zChar.position = new BABYLON.Vector3(0, 0.05 * size, 0.9 * size);
};
/***************************End World Axes***************************/

showAxis(8);

/*******************************Local Axes****************************/
function localAxes(size) {
var pilot_local_axisX = BABYLON.Mesh.CreateLines("pilot_local_axisX", [
new BABYLON.Vector3.Zero(), new BABYLON.Vector3(size, 0, 0), new BABYLON.Vector3(size * 0.95, 0.05 * size, 0),
new BABYLON.Vector3(size, 0, 0), new BABYLON.Vector3(size * 0.95, -0.05 * size, 0)
], scene);
pilot_local_axisX.color = new BABYLON.Color3(1, 0, 0);

pilot_local_axisY = BABYLON.Mesh.CreateLines("pilot_local_axisY", [
new BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, size, 0), new BABYLON.Vector3(-0.05 * size, size * 0.95, 0),
new BABYLON.Vector3(0, size, 0), new BABYLON.Vector3(0.05 * size, size * 0.95, 0)
], scene);
pilot_local_axisY.color = new BABYLON.Color3(0, 1, 0);

var pilot_local_axisZ = BABYLON.Mesh.CreateLines("pilot_local_axisZ", [
new BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, 0, size), new BABYLON.Vector3(0, -0.05 * size, size * 0.95),
new BABYLON.Vector3(0, 0, size), new BABYLON.Vector3(0, 0.05 * size, size * 0.95)
], scene);
pilot_local_axisZ.color = new BABYLON.Color3(0, 0, 1);

var local_origin = BABYLON.MeshBuilder.CreateBox("local_origin", { size: 1 }, scene);
local_origin.isVisible = false;

pilot_local_axisX.parent = local_origin;
pilot_local_axisY.parent = local_origin;
pilot_local_axisZ.parent = local_origin;

return local_origin;

}
/*******************************End Local Axes****************************/

return {scene,pilot};
}