【问题标题】:Three.js How to move an object over terrain so the object rotates to match the contoursThree.js 如何在地形上移动对象,使对象旋转以匹配轮廓
【发布时间】:2015-06-17 17:10:10
【问题描述】:

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

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

首先我使用的是轴对齐边界框 (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 = 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 度标记时,我更改为 - 角,以使坦克在移动到中心点时恢复平坦桥,然后反向使坦克下来。虽然我对这种方法不满意,但效果还不错,而且当你改变坦克和桥梁的方向时也会导致问题。

任何帮助指导将不胜感激。

【问题讨论】:

    标签: three.js


    【解决方案1】:

    所以我有一个可行的解决方案,尽管它可能不是可靠的最佳方式。

    1. 创建一个向量,以世界单位表示对象的局部 x 轴,而不是一个向量 (1,0,0),该向量在对象旋转时必须移动。
    2. 将正向向量作为 slopeNormalVector 与局部 x 轴向量的叉积
    3. 将一个点沿前向向量投影任意距离。
    4. 使用 object.lookAt 指向前进轨迹

    见下文

    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。

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

    【讨论】:

      猜你喜欢
      • 2017-01-20
      • 2013-04-02
      • 1970-01-01
      • 2013-01-27
      • 2012-06-19
      • 2013-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多