如何将glTF模型朝着a型架的方向移动



我的机器人的gltf模型加载在a帧场景版本1.0.4中。到目前为止,我可以绕着它的x、y、z轴转动机器人,但当我试图向前移动它时,它仍然朝着它的初始方向移动,而不是朝着它所面对的方向移动。我希望能够在不使用任何外部库的情况下用键盘控制它的运动。我相信我必须使用四元数,但我还没有弄清楚如何使用它们。到目前为止,这是我的A帧代码。

<a-scene id="myScene">
<a-entity environment="preset:forest;"></a-entity>
<a-entity gltf-model="#humanoid" id="robot" position="0 20 0" rotation="0 0          0" 
scale="0.0001 0.0001 0.0001" static-body>
</a-entity>
</a-scene>

这是我的脚本

const robot = document.getElementById('robot');
const update = () => {
if (keys.forward) {
let {x,y,z} = robot.object3D.position;
let ry = robot.object3D.rotation.y;
z += Math.cos(ry * Math.PI/180)/12;
x += Math.sin(ry * Math.PI/180)/12;
robot.object3D.position.set(x, y, z); 
}
else if (keys.backwards) {
let {x, y, z} = robot.object3D.position;
let ry = robot.object3D.rotation.y;
z -= Math.cos(ry * Math.PI/180)/10;
x -= Math.sin(ry * Math.PI/180)/10;
robot.object3D.position.set(x, y, z);   
}
if (keys.turnLeft) {
let {x, y, z} = robot.getAttribute('rotation');
y += 0.25;
robot.setAttribute('rotation',{x,y,z});
}
else if (keys.turnRight) {
let {x, y, z} = robot.getAttribute('rotation');
y -= 0.25;
robot.setAttribute('rotation',{x,y,z});
}
}

let ry = robot.object3D.rotation.y;
z += Math.cos(ry * Math.PI/180)/12;

虽然a-frame使用度数进行旋转,但threejs使用弧度,因此无需再次转换:

const robot = document.querySelector("a-box")
document.body.addEventListener("keydown", (evt) => {
if (evt.key === 's') {
let {x,y,z} = robot.object3D.position;
let ry = robot.object3D.rotation.y;
z += Math.cos(ry)/12;
x += Math.sin(ry)/12;
robot.object3D.position.set(x, y, z); 
} else if (evt.key === 'w') {
let {x, y, z} = robot.object3D.position;
let ry = robot.object3D.rotation.y;
console.log(ry)
z -= Math.cos(ry)/10;
x -= Math.sin(ry)/10;
robot.object3D.position.set(x, y, z);   
}
if (evt.key === 'a') {
let {x, y, z} = robot.getAttribute('rotation');
y += 1;
robot.setAttribute('rotation',{x,y,z});
} else if (evt.key === 'd') {
let {x, y, z} = robot.getAttribute('rotation');
y -= 1;
robot.setAttribute('rotation',{x: x,y: y,z: z});
}
})
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<a-scene>
<a-box position="-1 0.5 -3" rotation="0 0 0" color="#4CC3D9">
<a-sphere radius="0.5" position="0 0 -1"></a-sphere>
</a-box>
<a-entity camera position="0 1.6 0"></a-entity>
</a-scene>


getWorldDirection:相同

const robot = document.querySelector("a-box")
const direction = new THREE.Vector3();
document.body.addEventListener("keydown", (evt) => {
if (evt.key === 's') {
// get robot direction
robot.object3D.getWorldDirection(direction);
// add a "speed" value
direction.multiplyScalar(0.1)
// add the new vector to the actual position
robot.object3D.position.add(direction)
} else if (evt.key === 'w') {
robot.object3D.getWorldDirection(direction);
direction.multiplyScalar(-0.1)
robot.object3D.position.add(direction) 
}
if (evt.key === 'a') {
let {x, y, z} = robot.getAttribute('rotation');
y=y+1
robot.setAttribute('rotation',{x,y,z});
} else if (evt.key === 'd') {
let {x, y, z} = robot.getAttribute('rotation');
y=y-1
robot.setAttribute('rotation',{x: x,y: y,z: z});
}
})
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<a-scene>
<a-box position="-1 0.5 -3" rotation="0 0 0" color="#4CC3D9">
<a-sphere radius="0.5" position="0 0 -1"></a-sphere>
</a-box>
<a-entity camera position="0 1.6 0"></a-entity>
</a-scene>

是的,使用四元组是解决这个问题的好方法。

您可以简单地将机器人的当前四元数应用于表示要在机器人的原始旋转中进行的移动的向量3,并将其应用于机器人的位置。

类似这样的东西:

fowardVector = new Vector3(0, 0, -0.1)
rotatedForwardVector = new Vector3();
rotatedForwardVector.copy(forwardVector);
rotatedForwardVector.applyQuaternion(robot.object3D.quaternion);
robot.object3D.position.add(rotatedForwardVector);

请注意,您只需要创建一次Vector3,然后重用它们以避免不必要的垃圾收集,而不是为每次移动创建它们。

E.g使用此处解释的闭包

您可以使用四元数和许多其他方式,但Object3D有一些有用且更简单的替代方案来在本地坐标中移动对象:

我认为最简单的是使用https://threejs.org/docs/#api/en/core/Object3D.translateZ

robot.object3D.translateZ(amountToMoveForward);

此外https://threejs.org/docs/#api/en/core/Object3D.localToWorld可以用于变换矢量。

最新更新