目录
一、定位网格
网格其局部原点位于世界空间 (-1, 2, 1),即 mesh.position 位于 (-1, 2, 1);
设置网格位置方法:
mesh.position = new Vector3(2, 3, 4);//(2, 3, 4)
//(-1 + 2, 2 + 3, 1 + 4) = (1, 5, 5)
mesh.position.addInPlace(new Vector3(2, 3, 4));
mesh.translate(new BABYLON.Vector3(2, 3, 4), 1,
BABYLON.Space.WORLD); //(-1 + 2, 2 + 3, 1 + 4) = (1, 5, 5)
mesh.position.x = 2; //(2, 2, 1)
mesh.position.y = 3; //(2, 3, 1)
mesh.position.z = 4; //(2, 3, 4)
mesh.position.x += 2; //(-1 + 2, 2, 1) = (1, 2, 1)
mesh.position.y += 3; //(1, 2 + 3, 1) = (1, 5, 1)
mesh.position.z += 4; //(1, 5, 1 + 4) = (1, 5, 5)
//生成的位置取决于网格的方向。在不知道网格旋转的情况下,不可能给出结果位置。
mesh.translate(new BABYLON.Vector3(2, 3, 4), 1, BABYLON.Space.LOCAL);
mesh.setPositionWithLocalVector(new BABYLON.Vector3(2, 3, 4));
mesh.locallyTranslate(new BABYLON.Vector3(2, 3. 4));
position和setPositionWithLocalVector的向量是位置向量。translate、localTranslate和addInPlace的那些是方向向量。
二、网格旋转
1、旋转方法
旋转沿着轴设定:
mesh.rotation = new BABYLON.Vector3(alpha, beta, gamma);
beta 围绕局部 y 轴旋转,然后 alpha 围绕局部 x 轴旋转,最后 gamma 围绕局部 z 轴旋转。
2、自定义旋转
mesh.rotation.addRotation(Math.PI / 2, 0, 0)
.addRotation(0, 0, Math.PI / 3).addRotation(0, Math.PI / 8);
将形成网格的当前旋转,进一步围绕 x 轴旋转 π/2,然后围绕 z 轴旋转 π/3,然后围绕 y 轴旋转 π/8。
指定轴的方向矢量和角度是产生旋转的另一种方法。这就是在世界空间或局部空间中使用旋转方法的方式。
mesh.rotate(new BABYLON.Vector3(1, 0 -1), Math.PI / 3, BABYLON.Space.WORLD);
mesh.rotate(new BABYLON.Vector3(1, 0 -1), Math.PI / 3, BABYLON.Space.LOCAL);
3、旋转四元数
四元数是一个四维向量 (x, y, z, w),要成为旋转四元数,它必须是单位向量,即 x 2 + y 2 + z 2 + w 2 = 1,我们已经使用了 rotate 来设置网格的旋转四元数。旋转属性相同,rotationQuaternion属性以局部原点为旋转中心设置网格的方向。除了旋转,您还可以通过使用直接获得旋转四元数
mesh.rotationQuaternion = new BABYLON.Quaternion
.RotationAxis(new BABYLON.Vector3(1, 0, -1), Math.PI / 3);
RotationAxis方法的参数是轴方向和角度。轴方向矢量应在世界空间中表示。任何旋转四元数都可以转换为欧拉角以与mesh.rotation一起使用,
您不能在同一网格上使用旋转四元数后跟旋转。一旦应用了rotationQuaternion,任何后续使用的旋转都会产生错误的方向,除非rotationQuaternion首先设置为null。请注意,这通常在导入模型时适用,因为其中许多模型已经具有旋转四元数集。
从 4.0 版开始,rotationQuaternion 设置为 null 时且仅当直接使用向量设置旋转时才会自动完成
mesh.rotation = new BABYLON.Vector3(0, 0, 0)
每当您发现旋转错误时,值得在更新之前将 rotationQuaternion 设置为null 。
4、旋转约定
Mesh.rotation(alpha, beta, gamma) 使用三个欧拉角 alpha、beta 和 gamma,它们分别是围绕 X、Y 和 Z 轴的旋转。Babylon.js 使用的约定是基于 yaw、pitch 和 roll 约定,因此在局部空间中以 Y、X、Z 的顺序围绕 X、Y 和 Z 执行。
YXZ:
使用局部轴以 YXZ 顺序将独立旋转应用于新创建的网格(即具有零旋转的网格)
mesh.rotate(BABYLON.Axis.Y, yaw, BABYLON.Space.LOCAL);
mesh.rotate(BABYLON.Axis.X, pitch, BABYLON.Space.LOCAL);
mesh.rotate(BABYLON.Axis.Z, roll, BABYLON.Space.LOCAL);
mesh.rotation = new BABYLON.Vector3(pitch, yaw, roll);
ZXY:
mesh.rotate(BABYLON.Axis.Z, gamma, BABYLON.Space.WORLD);
mesh.rotate(BABYLON.Axis.X, alpha, BABYLON.Space.WORLD);
mesh.rotate(BABYLON.Axis.Y, beta, BABYLON.Space.WORLD);
mesh.rotation = new BABYLON.Vector3(alpha, beta, gamma);
使用四元数与使用RotationYawPitchRoll相同
const yprQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(yaw, pitch, roll);
ZXZ:
mesh.rotate(BABYLON.Axis.Z, alpha, BABYLON.Space.WORLD);
mesh.rotate(BABYLON.Axis.X, beta, BABYLON.Space.WORLD);
mesh.rotate(BABYLON.Axis.Z, gamma, BABYLON.Space.WORLD);
var abcQuaternion = BABYLON.Quaternion.RotationAlphaBetaGamma(alpha, beta, gamma);
三、对其目标轴
使用RotationFromAxis方法
var orientation = BABYLON.Vector3.RotationFromAxis(axis1, axis2, axis3);
mesh.rotation = orientation;
- axis1作为其局部空间中的 x 轴
- axis2作为其局部空间中的 y 轴
- axis3作为其局部空间中的 z 轴
将平面与切线对其:
let path=[]
for(let i=-100;i<100;i++){
let x=i/10
path.push(new BABYLON.Vector3(x,Math.sin(x),Math.cos(x)))
}
let Path3D=new BABYLON.Path3D(path)
//获取曲线的坐标点
let curve=Path3D.getCurve()
//获取切线
let tangents=Path3D.getTangents()
//获取法线
let normals=Path3D.getNormals()
//获取副法线
let binormals=Path3D.getBinormals()
let lines=BABYLON.Mesh.CreateLines('line',path,scene)
let plane=BABYLON.Mesh.CreatePlane('plane',2,scene)
let p=0
scene.registerBeforeRender(()=>{
plane.rotation=new
BABYLON.Vector3.RotationFromAxis(tangents[p],normals[p],binormals[p])
plane.position=path[p]
p++
p%=curve.length
})
new BABYLON.Vector3.RotationFromAxis(binormals[p], tangents[p], normals[p]);
使用以上代码会让目标Y轴沿切线方向前进。
给定两个球体,在它们之间绘制一个始终面向相机的平面。我们将设置红色和绿色球体、世界轴,显示为红色、绿色和蓝色线条,以及 xz 平面中的紫色平面。连接红色和绿色球体的是一个平面,上面有一个蓝色箭头,从绿色球体指向红色球体。
要求是箭头平面旋转使得
- 它位于箭头上的正交轴之一沿着连接两个球体的线;
- 位于箭头平面上的另一轴垂直于相机镜头;
- 垂直于平面的轴沿着将箭头中间连接到相机的线。
var axis1, axis2, axis3;
axis1 = (sphere1.position).subtract(sphere2.position);
mesh.scaling.x = axis1.length();
scene.registerBeforeRender(function() {
axis1 = (sphere1.position).subtract(sphere2.position);
axis3 = BABYLON.Vector3.Cross(camera.position, axis1);
axis2 = BABYLON.Vector3.Cross(axis3, axis1);
mesh.rotation = BABYLON.Vector3.RotationFromAxis(axis1, axis2, axis3);
pl.position = camera.position;
});
四、坐标变换
将 mesh_P 视为一个盒子,一个大小为 1 的立方体。在盒子的局部空间中,顶面的中心位于 (0, 0.5, 0)。将此框移动并旋转到新位置。我们希望 mesh_C,一个球体,位于该位置的盒子顶面的中心。
const matrix = mesh_P.computeWorldMatrix(true);//强制计算世界矩阵
const local_position = new BABYLON.Vector3(0, 0.5, ,0);//C在P中的相对位置
//获取C在空间中的位置
const global_position = BABYLON.Vector3.TransformCoordinates(
local_position, matrix);
mesh_C.position = global_position;
相较于设置的位置平移使用:
local_position.addInPlace(new BABYLON.Vector3(1, 1, 1))
示例1:
scene.registerAfterRender(function () {
box.rotate(BABYLON.Axis.Y, Math.PI / 150, BABYLON.Space.LOCAL);
box.rotate(BABYLON.Axis.X, Math.PI / 200, BABYLON.Space.LOCAL);
box.translate(new BABYLON.Vector3(-1, -1, -1)
.normalize(), 0.001, BABYLON.Space.WORLD)
small.rotationQuaternion = box.rotationQuaternion;
matrix = box.getWorldMatrix();
y += 0.001;
local_pos = new BABYLON.Vector3(0, y, 0);
small.position = BABYLON.Vector3.TransformCoordinates(local_pos, matrix);
})
示例二:
var phi = 0;
scene.registerAfterRender(function () {
matrix = disc.getWorldMatrix();
disc.rotate(BABYLON.Axis.Y, Math.PI / 150, BABYLON.Space.LOCAL);
disc.rotate(BABYLON.Axis.Z, Math.PI / 200, BABYLON.Space.LOCAL);
disc.position = new BABYLON.Vector3(15 * Math.cos(phi),
16 * Math.sin(phi), 5)
boxes.rotationQuaternion = disc.rotationQuaternion;
boxes.position = BABYLON.Vector3.TransformCoordinates(
boxes_position, matrix);
phi +=0.01;
});
五、烘培转换
最直接的方法是对网格应用变换。例如,取一个边为 1 的盒子并将其放置在 (0, 3, 0) 处。它的顶点存储为 (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (0.5, 0.5, -0.5), (-0.5, 0.5, -0.5), (-0.5, - 0.5, 0.5), (0.5, -0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, 0.5) 其局部原点 (0, 3, 0) 存储在世界矩阵中。当这个当前变换被烘焙到它的顶点时,顶点现在存储为 (-0.5, 2.5, -0.5), (0.5, 2.5, -0.5), (0.5, 3.5, -0.5), (-0.5, 3.5, -0.5), (-0.5, 2.5, 0.5), (0.5, 2.5, 0.5), (0.5, 3.5, 0.5), (-0.5, 3.5, 0.5) 存储本地原点 (0, 0, 0)在世界矩阵中。现在,任何旋转都发生在旋转中心 3 位于框的中间下方。
box.bakeCurrentTransformIntoVertices();
六、使用父子网格
1、使用父子网格关系
TransformNode 是一个未渲染但可用作变换中心的对象。与使用空网格作为父级相比,这可以减少内存使用并提高渲染速度,并且比使用枢轴矩阵更简单。将 TransformNode 设置为父节点,然后旋转 TransformNode。TransformNode 可以用作网格和一些灯光和相机的变换中心 (CoT),通过充当它们的父级来增加多功能性。
var CoT = new BABYLON.TransformNode("root");
box.parent = CoT;
2、添加父网格
有三种方式
meshC.parent = meshP; //1
meshC.setParent(meshP); //2
meshP.addChild(meshC); //3
移除子网格:
meshC.parent = null;
meshC.setParent(null);
meshP.removeChild(meshC);
七、设置枢纽中心
设置或获取枢纽中心点:
mesh.setPivotPoint(Vector3);
mesh.getPivotPoint();
mesh.getAbsolutePivotPoint();
设置枢纽中心点:
mesh.setPivotPoint(new BABYLON.Vector3(x, y, z));
使用setPivotPoint
then后,getPivotPoint
将为您提供枢轴点与本地原点的相对位置及其getAbsolutePivotPoint
在世界空间中的位置。
三种沿轴旋转
1、通过设置一个node根节点,然后旋转根节点。
let XS=new BABYLON.TransformNode('root')
XS.position=new BABYLON.Vector3(1,1,1)
sphere.parent=XS,
sphere.position=new BABYLON.Vector3(10,10,10)
scene.registerBeforeRender(()=>{
XS.rotate(new BABYLON.Vector3(10,10,0),0.02,BABYLON.Space.WORLD)
})
2、使用父子
和上面的方法一样
sphere.parent=sphere1
sphere.position=new BABYLON.Vector3(10,0,0)
scene.registerBeforeRender(()=>{
sphere1.rotate(new BABYLON.Vector3(10,5,10),0.2,BABYLON.Space.LOCAL)
})
3、使用setPivotMatrix
sphere.setPivotMatrix(BABYLON.Matrix.Translation(0,10,0))
sphere.position=new BABYLON.Vector3(10,10,0)
scene.registerBeforeRender(()=>{
sphere.rotation.x+=0.02
//sphere.rotate(new BABYLON.Vector3(10,5,10),0.02,BABYLON.Space.LOCAL)
})