javascript - THREE.js ArrowHelper 不服从固有的欧拉角旋转
问题描述
我想将内在旋转设置为THREE.ArrowHelper
. 据我了解,THREE.js 原生使用固有的 Tait-Bryan 欧拉角来表示 3D 旋转。
在下面的代码中,我创建了一个表示 x 轴的单位向量THREE.Vector3(1, 0, 0)
。
然后我将它绕 Y 轴和 Z 轴旋转任意量。
由于围绕 Y 和 Z 进行了一些旋转,局部坐标系的 X 轴(我假设沿红色矢量的点)也发生了变化。
所以,当我应用关于 的旋转时X
,我不希望箭头移动(除了原地旋转......但这不应该是可见的)。
相反,我看到箭头四处扫动,好像它围绕某个任意轴旋转,而不是它的局部 x 轴。
感谢您的帮助!
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var origin = new THREE.Vector3(0, 0, 0);
var xDir = new THREE.Vector3(1, 0, 0);
var length = 1;
var arrow = new THREE.ArrowHelper(xDir, origin, length, 0xff0000);
arrow.rotation.order = 'XYZ';
arrow.rotation.y = 0.5;
arrow.rotation.z = 0.5;
scene.add(arrow);
camera.position.z = 5;
var animate = function () {
requestAnimationFrame( animate );
arrow.rotation.x += 0.01;
renderer.render( scene, camera );
};
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
解决方案
问题是它ArrowHelper
正在做自己的特殊旋转数学。它会创建一个向上的单位箭头 (+Y)。它使用自定义数学来设置方向,以使该线点在本地空间中的给定方向上。
如果您只是创建箭头然后打印旋转,您可以看到这一点
var origin = new THREE.Vector3(0, 0, 0);
var xDir = new THREE.Vector3(1, 0, 0);
var length = 1;
var arrow = new THREE.ArrowHelper(xDir, origin, length, color);
console.log(arrow.rotation.x, arrow.rotation.y, arrow.rotation.z);
你会看到rotation.z 已经设置为将+Y 箭头旋转到+X,所以你去改变这些旋转,箭头不再基于朝向+X。
这意味着通过操纵箭头arrow.rotation
不会按预期工作。
如果您将箭头作为父Object3D
对象,然后旋转该对象,它将按预期工作(或按我的预期)
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene.add(new THREE.GridHelper(10, 10));
function addArrow(x, ry, rz, color) {
var origin = new THREE.Vector3(0, 0, 0);
var xDir = new THREE.Vector3(1, 0, 0);
var length = 1;
var arrow = new THREE.ArrowHelper(xDir, origin, length, color);
var ob = new THREE.Object3D();
ob.position.x = x;
ob.rotation.order = 'XYZ';
ob.rotation.y = ry;
ob.rotation.z = rz;
scene.add(ob);
ob.add(arrow);
return ob;
}
addArrow(-4, 0, 0, 0xFF0000);
addArrow(-2, 0, 0.5, 0x00FF00);
addArrow( 0, 0.5, 0.5, 0xFFFF00);
const arrow = addArrow( 2, 0.5, 0.5, 0x00FFFF);
camera.position.z = 6;
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
controls.update();
var animate = function () {
requestAnimationFrame( animate );
arrow.rotation.x += 0.01;
renderer.render( scene, camera );
};
animate();
body { margin: 0; }
canvas { display: block; }
<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/controls/OrbitControls.js"></script>
我的期望。
旋转在本地坐标系中。旋转顺序“XYZ”的意思是,假设你只有箭头,完整的矩阵计算将是
matrix = projection *
view *
obTranslation *
obXAxisRotation *
obYAxisRotation *
obZAxisRotation *
obScale *
arrowOrientation;
任何状况之下
var origin = new THREE.Vector3(0, 0, 0);
var xDir = new THREE.Vector3(1, 0, 0);
var length = 1;
var arrow = new THREE.ArrowHelper(xDir, origin, length, 0xff0000);
var ob = new THREE.Object3D();
scene.add(ob);
ob.add(arrow);
ob.rotation.order = 'XYZ';
从 0、0、5 看,这给了我们一个指向右侧的箭头。
我喜欢查看从右到左应用的矩阵,因此将应用第一个比例以上的公式。它是 1,1,1 所以没有变化
接下来应用 zAxisRotation。0.5 弧度大约是 30 度,所以箭头现在要么向上 30 度
接下来应用 yAxisRotation。向上 30 度的箭头现在指向远处 30 度。
下一个 xAxisRotation 被应用,所以这个时髦的箭头将围绕 x 旋转
运行它并拖动上面的示例以从上方查看。您会看到它与描述相符。
所以这取决于你。您可以制作一个面向 ArrowHelper 的 +X 并将其作为 Object3D 的父级,或者您可以只知道 ArrowHelper 实际上制作了一个 +Y 箭头,然后在知道这一点后适当地设置旋转。
推荐阅读
- reactjs - 为什么 React Component 在同一个页面而不是另一个页面上呈现?
- html - CSS:相对于父元素的当前高度设置高度
- sql - 跨不同相似模式的联合查询,但列排序不同
- sql - .NET Serilog 有时会在同一秒内将两次记录到 SQL,并带有附加列
- python - 从 python2.7 到 3.8 的运行时迁移
- python - tf.keras.models:load_model() ValueError:未知层:OpenCV/DNN 模块中的功能。如何在旧版本的 tf/keras 中使用预训练模型?
- python-3.x - 自定义迁移后如何在模型中添加新字段,在新字段之前访问模型?
- c# - 为什么代码不会在 Unitys 控制台中打印?
- tailwind-css - 无法在 vite 环境中使用 tailwindcss 的@layer
- c# - 在 Unity 中将动态刚体从 A 点移动到 B 点