Babylon.js101
- 创建一个基本的Demo
<style>html, body {overflow: hidden;width : 100%;height : 100%;margin : 0;padding : 0;}#renderCanvas {width : 100%;height : 100%;touch-action: none;}</style> </head> <body><canvas id="renderCanvas"></canvas> </body> <script>window.addEventListener('DOMContentLoaded', function() {// All the following code is entered here.var canvas = document.getElementById('renderCanvas');var engine = new BABYLON.Engine(canvas,true);var createScene = function(){var scene = new BABYLON.Scene(engine); // 创建场景var camera = new BABYLON.FreeCamera('camera',new BABYLON.Vector3(0,5,-10),scene); // 创建相机camera.setTarget(BABYLON.Vector3.Zero()); //设置相机方向camera.attachControl(canvas,false); // 将相机绑定到canvasvar light = new BABYLON.HemisphericLight('light1',new BABYLON.Vector3(0,1,0),scene); // 创建灯光var sphere = BABYLON.MeshBuilder.CreateSphere('sphere',{segments:16,diameter:2},scene); // 创建立方体sphere.position.y = 1; // 设置立方体位置var ground = BABYLON.MeshBuilder.CreateGround('ground1',{height:6,width:6,subdivisions:2},scene); // 创建地板var myPoints = [];var poreturn scene;}var scene = createScene();// 必要步骤。循环渲染engine.runRenderLoop(function(){scene.render();})}); </script>
网格
- 创建一个固定形状网格的一般形式:
var shape = BABYLON.MeshBuilder.CreateShape(name,potions,scene);
option参数允许你设置形状的大小以及是否可以更新它。 - 立方体模型
var box = BABYLON.MeshBuilder.CreateBox("box", {}, scene); // default box var myBox = BABYLON.MeshBuilder.CreateBox("myBox", {height: 5, width: 2, depth: 0.5}, scene);
option value 默认值 size 每个盒子的尺寸(数字) 1 height 盒子高度(数字)(设置的话会覆盖size属性) size width 宽度(数字)(设置会覆盖size属性) size depth 深度(数字)(设置会覆盖size属性) size faceColors 有六个Color4类型值的数组,每个值对应立方体的一面 含6个Color4(1,1,1,1)值的数组 faceUV 有六个Vector4类型值的数组,每个值对应立方体的一面 含6个Color4(1,1,1,1)值的数组 updatable 网格可更新则为true false sideOrientation (数字类型) 排列方向 DEFAULTSIDE
sideOrientation和Threejs的side类似,为0的时候正面隐藏只能看到形状的反面,为1时看到的是正面,为2时为双面显示
-
球型网格
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene); //default sphere var mySphere = BABYLON.MeshBuilder.CreateSphere("mySphere", {diameter: 2, diameterX: 3}, scene);
option value 默认值 segments (数字) 水平分段的数值 32 diameter 球直径(数字) 1 diameterX X轴上的直径(数字),如果设置会覆盖diameter diameter diameterY Y轴上的直径(数字),如果设置会覆盖diameter diameter diameterZ Z轴上的直径(数字),如果设置会覆盖diameter diameter arc (数字) 周长(纬度)在0和1之间的比率 1 slice (数字) 高度(经度)在0和1之间的比率 1 updatable 网格可更新则为true false sideOrientation (数字)排列方向 DEFAULTSIDE -
平面网格
var plane = BABYLON.MeshBuilder.CreatePlane("plane", {}, scene); // default plane var myPlane = BABYLON.MeshBuilder.CreatePlane("myPlane", {width: 5, height: 2}, scene);
option value 默认值 size 平面的尺寸 1 height 高(长)度 size width 宽度 size updatable 网格可更新则为true false sideOrientation (数字类型) side orientation DEFAULTSIDE faceUV 含一个Vector4类型值的数组,ONLY WHEN sideOrientation:BABYLON.Mesh.DOUBLESIDE set Vector4(0,0,1,1) backUVs 含一个Vector4类型值的数组,ONLY WHEN sideOrientation:BABYLON.Mesh.DOUBLESIDE set Vector4(0,0,1,1) sourcePlane (Plane) source plane (maths) the mesh will be transformed to null sourcePlane 对平面来说是一个唯一的选项,它提供一种排列摆放位置的方法,目前它的排列定向为向量vector(0,0,1)。如果你希望方向是向量vector(0,-1,1),那么你就创建一个源平面。
var sourcePlane = new BABYLON.Plane(0, -1, 1, 0); sourcePlane.normalize();
这就创建了一个数学平面,作为方向源。第四个参数是在方向向量方向移动的距离。
-
地面
var ground = BABYLON.MeshBuilder.CreateGround("ground", {}, scene); //default ground var myGround = BABYLON.MeshBuilder.CreateGround("myGround", {width: 6, height: 4, subdivisions: 4}, scene);
option value 默认值 height 高(长)度 size width 宽度 size updatable 网格可更新则为true false subdivisions (数字类型) 平方细分数 1 可以通过heightMap使用CreateGroundFromHeightMap创造一个形成起伏的地面而不是一个平坦的地面。
option解释
- Face Colors or UV
只在数量有限的拥有不同的面的形状可用,比如一个立方体,而不是一个球体。这允许你给这些网格的每个面添加独立的颜色或图像。详情:https://doc.babylonjs.com/how_to/createbox_per_face_textures_and_colors - Updatable
当网格的可更新参数设置为true时,意味着可以更改与网格的每个顶点关联的数据,从而更改网格的形状。详情:https://doc.babylonjs.com/how_to/updating_vertices - Side Orientation(排列顺序)
这个选项被用来描述图形的每一个面如何被观察。
这个选项有四个可能的值:
BABYLON.Mesh.FRONTSIDE,//前面
BABYLON.Mesh.BACKSIDE,// 后面
BABYLON.Mesh.DOUBLESIDE,// 双面
BABYLON.Mesh.DEFAULT 默认值,当前等于FRONTSIDE, - Front and Back UV
当一个网格有一个Side Orientation选项并被设为DOUBLESIDE ,那么它的前面和后面才可以显示不同的图像。更多内容详见https://doc.babylonjs.com/babylon101/LINK
位移和旋转
本文仅考虑设置一个网格的位置,旋转和缩放,如果想要了解多个网格的变换和旋转参考https://doc.babylonjs.com/babylon101/position#further-reading
BabylonJs的3D场景中通过特定的方法传入数值来调整物体的位置、旋转与尺寸缩放。
- 坐标系:对网格进行变换必须有一个参考系:用于描述位置,旋转,缩放,并有助于可视化应用这些方法效果。可视化可以帮助使用者建立一个不对称的形状。(Babylon.js使用左手坐标系)
坐标系有两种,世界坐标系和局部坐标系。世界坐标系的位置永远不变,局部坐标系会随网格变换而变化,无论网格的位置如何,局部坐标系原点总是位于网格创建时的中心点处。不过局部坐标系原点可以通过TransformNode或利用矩阵设置pivot point来更改。
网格进行旋转和缩放的中心点位于局部坐标系的原点处。
在所有坐标系中,x轴为红色,y轴为绿色,z轴为蓝色。当物体网格(meshes)被创建时,它们的中心点被放置在世界坐标的原点,它们的位置总是相对于世界坐标的。 - Vectors:所有的位移,旋转,和缩放的值都通过Vector(矢量)来设置。
- The Pilot(这里应该翻译为网格或模型吧):网格创建之后,其中心点在世界原点处,所有轴旋转值为0,缩放值为1,世界坐标系与网格的局部坐标系重合
- Position:使用Vector(x,y,z)使模型在世界坐标系中移动,局部坐标系随模型一起移动。
或者分别设置:(此时局部坐标系坐标轴和世界坐标系坐标轴保持相同的方向)pilot.position = new BABYLON.Vector3(2,3,4);
pilot.position.x = 2; pilot.position.y = 3; pilot.position.z = 4;
- 旋转
注意:在3D空间中旋转很棘手,模型多次旋转时,旋转的发生顺序不同,模型的最终方向将不同,你还需要注意旋转使用的是哪个坐标系。三维建模中应用旋转有很多不同的约定,Babylon中约定的相关细节详见https://doc.babylonjs.com/resources/rotation_conventions
babylon中旋转:
或者:(注意:旋转角度运用弧度制而非角度制)pilot.rotation = new BABYLON.Vector3(alpha, beta, gamma);
在这里三个旋转给出了三个不同的轴,你可能会有疑问——“它适用于哪一个参照系?它是以什么样的顺序来描述的?以及它在哪个方向?”pilot.rotation.x = alpha; //绕X轴旋转 pilot.rotation.y = beta; //绕Y轴旋转 pilot.rotation.z = gamma; //绕Z轴旋转
以下两种约定都是Babylon使用的,因为这两种约定都会导致相同的结果。
公约一(以局部坐标系来描述旋转): 对于使用局部坐标轴旋转物体时,是先以Y、X、Z轴的顺序旋转网格物体的,旋转的顺序是逆时针。
以下图像序列依次显示了图形的初始位置,然后围绕局部坐标系的Y轴旋转(顺时针还是逆时针…)90度,然后绕局部坐标系的X轴旋转90度,然后围绕局部Z轴旋转90度。 (小轴代表世界坐标轴方向)
公约二(以世界坐标系来描述旋转, 与公约1相比,旋转中心及旋转轴都没有改变。):对于使用世界坐标轴旋转物体时,是先以Z、X、Y轴的顺序旋转网格物体的,旋转的顺序是逆时针。
以下图像序列依次显示了图形的初始位置,然后绕世界坐标轴的Z轴旋转90度,然后绕世界坐标轴的X轴旋转90度,然后绕世界坐标轴的Y轴旋转90度。
当以世界坐标系来描述旋转时,以网格与世界坐标轴平行的轴,以局部坐标系原点为旋转中心来旋转,沿着坐标轴正方向看所有的旋转都是逆时针的
以下代码会产生相同的效果
pilot.rotation = new BABYLON.Vector3(alpha, beta, gamma);
pilot.rotation.x = alpha;
pilot.rotation.y = beta;
pilot.rotation.z = gamma;pilot.rotation.z = gamma;
pilot.rotation.x = alpha;
pilot.rotation.y = beta;pilot.rotation.y = beta;
pilot.rotation.z = gamma;
pilot.rotation.x = alpha;
- 旋转队列
现在的问题是:如果你想要一系列的旋转,从X轴开始,然后是Y轴,然后Z轴,该怎么做。对世界坐标轴和局部坐标轴而言,BabylonJs都有对应的rotate和addRotation方法 。.你可以使用addRotation将一系列旋转链接起来,如下所示,这个方法提供三次关于某个轴的旋转角度,然后将他们链式链接起来
mesh.addRotation(Math.PI/2, 0, 0).addRotation(0, Math.PI/2, 0).addRotation(0, 0, Math.PI/2);
下边的序列图像显示了上述代码的旋转过程: 从原始位置开始,绕局部坐标系X轴旋转90度,然后绕局部Y轴旋转90度,然后绕局部Z轴旋转90度。(小轴代表世界坐标轴方向)
在一般的网格里,使用addRotation(alpha, beta, gamma)进行旋转,通常都有其中两个属性为0。,alpha是绕局部X轴旋转,beta是绕局部Y轴旋转,gamma是绕局部Z轴旋转
- RotationQuaternions(旋转四元数)
旋转的另一个替代方法是rotationQuaternions,尽管他们使用起来很复杂,但可以克服万向节锁的问题。在一个网格上同时使用rotation和rotationQuaternions是不允许的,如果用了rotationQuaternions,那么rotation就会失效。详情https://doc.babylonjs.com/resources/rotation_conventions#warning - 缩放
沿着局部坐标系的x,y,z轴缩放设置:
mesh.scaling = new BABYLON.Vector3(scale_x, scale_y, scale_z);
或者分别设置:
mesh.scaling.y = 5;
下图显示了一个单元立方体绕Z轴旋转,并沿局部Y轴缩放