Three.js如何在地形上移动对象,以便对象旋转以匹配轮廓

时间:2015-06-16 14:44:30

标签: three.js

在我的例子中,我正在一座桥上移动坦克。我可以看到这个问题有两种方法,一种是让物理处理数学,另一种是手动计算车辆的高度和旋转值(这是我想采取的方法)。

到目前为止,我已经通过各种不同的方法取得了一些成功,我将在下面对其进行描述:

首先我使用的是轴对齐边界框(AABB)。从这里我设置一个任意高度并从4个角向下投射,找到4个与地面相交的点。在这4个点处,使用x轴和z轴的叉积计算向上矢量:

// slopePoints[4] are the 4 points that interset the ground from the downward raycast
// vec2, vec6, vec7 make up the x and z axis for the base of the tank 

var xDirSlope = slopePoints[3].clone().sub( slopePoints[0] ).normalize();
var zDirSlope = slopePoints[2].clone().sub( slopePoints[3] ).normalize();

var slopeNormalVector = new THREE.Vector3().crossVectors( xDirSlope, zDirSlope );

var xDirObjectBase = vec6.clone().sub( vec7 ).normalize();
var zDirObjectBase = vec2.clone().sub( vec6 ).normalize();

var baseNormalVector  = new THREE.Vector3().crossVectors( xDirObjectBase, zDirObjectBase );

所以现在我有两个归一化向量(1)代表坦克的位置的向上向量"应该"在(2)代表坦克"的位置的向上矢量"现在。

(1)源自击中地形的光线 (2)是坦克的AABB边界框的基础

我的下一步是计算两个向量之间的角度和转换所需的轴,如下所示:

var radians = Math.acos( baseNormalVector.dot( slopeNormalVector ) );

var axis = new THREE.Vector3().crossVectors( baseNormalVector, slopeNormalVector );

所以现在已经计算了以弧度表示的角度和转换轴我应该能够使用以下方法在所需轴上旋转我的坦克:

var matrix = new THREE.Matrix4().makeRotationAxis( axis, radians );

object.applyMatrix( matrix );

当我应用这个逻辑时,我可以看到坦克旋转以匹配桥梁的轮廓但是它有点拉动一个轮子并最终正确地安置在桥梁的另一侧。

我的观察结果是坦克在进入桥的起点时应该在其x轴上旋转,但是当它接近中间标记时,旋转应该从正三角形变为负三角形,但是它不会。它只是继续上升。

其他方法是:

//使用Quaternion Tank奇怪的是,在进入Verticle之前甚至没有移动到桥上

quaternion = new THREE.Quaternion().setFromUnitVectors( baseNormalVector, slopeNormalVector );
matrix = new THREE.Matrix4().makeRotationFromQuaternion( quaternion );

// By calculating the rotational delta as I move over the bridge

radians = baseNormalVector.angleTo( slopeNormalVector );
object.rotateX( radians )

当我在桥上移动时,我已经尝试计算旋转增量,所以当我开始时我有一个+角度并且当我超过45度标记时,我改变为角度以使坦克在它移动时变回平坦桥的中心点然后反向使油箱下降。虽然我对这种方法不满意,但是当你改变坦克和桥梁的方向时它也会引起问题。

非常感谢任何帮助指导。

1 个答案:

答案 0 :(得分:0)

所以我有一个有效的解决方案,虽然它可能不是最可靠的方式。

  1. 创建一个向量,以世界单位表示对象本地x轴,而不是向量(1,0,0),此向量必须在对象旋转时移动。
  2. 获取前向向量作为slopeNormalVector与当地x轴向量
  3. 的叉积
  4. 向前投射一个指向距离的点。
  5. 使用object.lookAt指向前方轨迹
  6. 见下文

    var xObject   = object.getObjectByName( "xObject" );
    var xPosition = new THREE.Vector3();
    
    xPosition.setFromMatrixPosition( xObject.matrixWorld );
    
    var xVector       = new THREE.Vector3().copy( xPosition ).sub( object.position ).normalize();
    var forwardVector = new THREE.Vector3().crossVectors( xVector, slopeNormalVector ).normalize();
    var pointForward  = new THREE.Vector3().copy( forwardVector ).multiplyScalar( 2000 ).add( object.position );
    

    我在加载时添加一个不可见的对象并将translateX添加到对象中以用于计算我的xVector。

    此解决方案适用于对象和地形的所有方向。