位置变换
上一章节讲述了创建一个空间并添加我们的模型文件,现在我们让世界动起来。
矢量(向量)
Babylon.js使用两个参考坐标系,世界坐标系和局部坐标系。世界坐标系就是我们在数学作图时常常画的那个坐标系,原点(0,0,0);而局部坐标系就是我们设定的任意点(X,Y,Z),通常这个点就是我们模型的本身的几何中心。
当然在我们制作模型的时候也可以做出相对应的设置。(这里使用的是Blender)
在建立了坐标系之后,我们就可以描述我们在当前坐标系的行为了,那么我们对方向和度量的描述那就是矢量了。而在babylonjs中,所有位置、旋转和缩放都使用新的BABYLON.Vector3(x,y,z)作为3维向量值,并且可以对位置、旋转和缩放单独设置。
定位,旋转,缩放
位置
object.position = new BABYLON.Vector3(x, y, z);
旋转
object.rotation = new BABYLON.Vector3(x, y, z);
缩放
object.scaling = new BABYLON.Vector3(x, y, z);
有了这三个就可以实现世界内模型变化了,想要详细的了解可以参考 101文档 ,那么问题来了,如果想要实现相对运动怎么办,按照我对 文档 的理解(比较片面),有三种方法:局部坐标、对齐轴、父节点,虽然没研究明白,但不管用哪种方法,目标都是转换参考坐标系到指定位置,这样在变化的时候就有了相对运动的效果。
使用局部轴的位置
setPositionWithLocalVector方法设置相对于局部空间的位置,该局部空间是使用世界坐标轴的原点和与网格的局部坐标轴平行的坐标轴的参考坐标系。
object.setPositionWithLocalVector(new BABYLON.Vector3(x, y, z));
对齐轴
当要旋转摄像机或网格使其与一组给定轴对齐时,可以使用RotationFromAxis方法找到所需的欧拉角以进行旋转。
var orientation = BABYLON.Vector3.RotationFromAxis(axis1, axis2, axis3);
object.rotation = orientation;
参考系变换(父节点)
如果要围绕其自身的原点以外的点定位,旋转或缩放网格,则可以使用父对象或枢轴或通过坐标变换来完成。
//父节点
childObject.parent = parentObject;
//修改枢
object.setPivotPoint(Vector3);
转换座标
object.computeWorldMatrix();
var matrix = object.getWorldMatrix();
var global_position = BABYLON.Vector3.TransformCoordinates(local_position, matrix);
对于文档中的介绍,我使用的是设置参考坐标(父节点),这样也可以实现多个部件同时运动。
//设置参考坐标节点
var pivot = new BABYLON.TransformNode("rt");
pivot.position = new BABYLON.Vector3(-3.5, 5, 18);
//将指定mesh绑定到节点
transformNodes[50].parent = pivot;
//设置相对偏移量
transformNodes[50].position = new BABYLON.Vector3.Zero().add(new BABYLON.Vector3(-3.5, -5, -18));
动画
关于动画的 文档内容 是很多的,而且相关的内容也非常多,让人无从选择,看了playground的相关示例,我主要用了三种方法:
直接驱动
直接在关键帧插入对应的参数,这种方式就像是Blender、Maya、3ds MAX制作动画一样,就是常说的“k帧”。编好整个剧本,将每段的想要实现效果设置进去,这样就能实现都能实现动作的变化了。
BABYLON.Animation.CreateAndStartAnimation(“mesh”, mesh, ‘position.y’, 30, 80, mesh.position.y, mesh.position.y + 1, 2);
参数驱动
先一步定义一个或一组动画,然后给当前动画补帧,然后就可以对这一段动画进行控制了。
此函数返回一个BABYLON.Animatable对象,您可以使用该对象来访问单个动画(例如使用getAnimationByTargetProperty函数)。该BABYLON.Animatable对象还支持以下功能:
pause()
restart()
stop()
reset()
通过将动画设置为引用(如变量)来控制上一个示例动画:
var newAnimation = scene.beginAnimation(box1, 0, 100, true);
然后暂停:
newAnimation.pause();
//设置一个30 FPS的动画
var animationBox = new BABYLON.Animation("tutoAnimation", "scaling.x", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
// 动画关键帧
var keys = [];
//第一个关键帧0处,缩放比例 1.0
keys.push({
frame: 0,value: 1});
//第二个关键帧20处,缩放比例0.2
keys.push({
frame: 20,value: 0.2});
//第三个关键帧100处,缩放比例1.0
keys.push({
frame: 100,value: 1});
animationBox.setKeys(keys);
//将动画绑定到模型“box1”
box1.animations.push(animationBox);
//启动总长100帧的动画
var anim = scene.beginAnimation(box1, 0, 100, false);
每帧读取
还有一种方法就是在每帧刷新的时候加入监听,修改模型的属性。
BABYLON.SceneLoader.ImportMesh("", "../uploads/", "facV2.glb", scene, function (meshes, particleSystems, skeletons) {
//每帧加载
scene.onBeforeRenderObservable.add(function () {
if (isMove) {
meshes[1].position.x += 0.2
}
});
});
这样用一个简单的bool变量就可以控制模型的动作了。