Three.js : 在一个表面上创建一个物体并沿着这个表面的法线对齐

Three.js : Create an object on a surface and align it along the normal of this surface

我想在单击某个对象时在其上放置箭头。

JsFiddle 胜过长篇大论:

https://jsfiddle.net/p820c246/4/

我的消息来源:https://github.com/mrdoob/three.js/issues/1486

它在surface的上半部分很好用,但在下半部分有bug,我不明白为什么。当法线的角度太低时,它似乎会出错。如果您尝试使用这样的球体,效果很好:

new T.SphereGeometry(1, 3, 2)

提前致谢

那个函数 orientAlongNormal 做了太多数学运算。如果我用这个替换它:

function orientAlongNormal(object, coords, normal, scalar) {

  var up = new T.Vector3(0, 0, 1);
  object.up = up;//Z axis up

  //create a point to lookAt
  var newPoint = new THREE.Vector3(
      coords.x + normal.x,
      coords.y + normal.y,
      coords.z + normal.z
  );

  //aim object in direction of vector "normal" using lookAt
  object.lookAt(newPoint ); 

  //in this case the cone model is a bit wrong so we have to rotate it by 90 degrees
    object.rotateX( 0.5*Math.PI );

  //put object to coords
    object.position.addVectors(coords, normal.clone().multiplyScalar(scalar));
}

有效:https://jsfiddle.net/hanalulu/j9Lgeys7/

这个线程一路帮助我:Issue aligning faces in Three.JS from two seperate objects

但对您而言,关键是不要自己做复杂的向量数学运算,而是在 3d 引擎中寻找可以为您完成的方法:)

如果您记录轴的长度 axis.length(),您会注意到它随着您从 up 增加角度而减小。从底部数第 3 行仍然接近 1,但第二行接近 0.7。

改变

var axis = new T.Vector3().crossVectors(up, normal)
.normalize(); //add this

它会起作用

为了安全起见,您始终可以在转换后对这些轴、法线等进行归一化,然后进行优化。叉积的大小取决于角度,您在期望它是单位长度的操作中进一步使用它。