三个JS围绕轴旋转
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三个JS围绕轴旋转相关的知识,希望对你有一定的参考价值。
我想围绕浅蓝色轴旋转这个立方体。我工作如果我改变围绕THREE.Vector3(0,0,0)
而不是THREE.Vector3(0.4,0,0.9)
的旋转
我不知道为什么立方体的形状会发生变化,为什么它会随着迭代次数的增加而变小
An fiddle showing this problem(请忽略糟糕的实施。我只是换了一个旧的)
这就是我如何进行轮换:
function rotate(deg) {
_initTranslation = new THREE.Vector3();
_initRotation = new THREE.Quaternion();
_initScale = new THREE.Vector3();
rotateMatrix = new THREE.Matrix4();
cube.matrix.decompose(_initTranslation, _initRotation, _initScale);
cube.matrix = rotateMatrix.compose(_initTranslation, new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0.4,1,0.9), THREE.Math.degToRad(deg)), _initScale);
cube.matrixAutoUpdate = false;
cube.matrixWorldNeedsUpdate = true;
}
也许有人知道我做错了什么。
var renderer, scene, camera, controls;
var geometry, material, line, vertices, last, _initTranslation, _initRotation, initScale, rotateMatrix;
var deg = 0;
init();
animate();
function init() {
document.body.style.cssText = 'margin: 0; overflow: hidden;' ;
renderer = new THREE.WebGLRenderer( { alpha: 1, antialias: true, clearColor: 0xffffff } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 5, 5, 5 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
geometry2 = new THREE.BoxGeometry( .5, .5, .5 );
material2 = new THREE.MeshNormalMaterial();
cube = new THREE.Mesh( geometry2, material2 );
scene.add( cube );
material = new THREE.LineBasicMaterial({ color: 0x0077ff });
geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3( 0, 0, 0) );
line = new THREE.Line( geometry, material )
scene.add( line );
var sphereAxis = new THREE.AxesHelper(20);
scene.add(sphereAxis);
addStep();
cube.lookAt(new THREE.Vector3(0.4,0,0.9));
}
function addStep() {
vertices = geometry.vertices;
last = vertices[ vertices.length - 1 ];
vertices.push(
new THREE.Vector3(0.4,0,0.9)
);
geometry = new THREE.Geometry();
geometry.vertices = vertices;
scene.remove( line );
line = new THREE.Line( geometry, material )
scene.add( line );
}
function animate() {
rotate(deg)
deg += 5
requestAnimationFrame( animate );
renderer.render(scene, camera);
controls.update();
}
function rotate(deg) {
_initTranslation = new THREE.Vector3();
_initRotation = new THREE.Quaternion();
_initScale = new THREE.Vector3();
rotateMatrix = new THREE.Matrix4();
cube.matrix.decompose(_initTranslation, _initRotation, _initScale);
cube.matrix = rotateMatrix.compose(_initTranslation, new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0.4,0,0.9), THREE.Math.degToRad(deg)), _initScale);
cube.matrixAutoUpdate = false;
cube.matrixWorldNeedsUpdate = true;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
答案
Quaternion的矢量分量必须是(normalize.)。标准化向量(Unit vector)的长度为1.0。
在您的情况下,矢量分量(THREE.Vector3(0.4, 0, 0.9)
)的长度小于1.0:
sqrt(0.9*0.9 + 0.0*0.0 + 0.4*0.4) = sqrt(0.81 + 0.16) = sqrt(0.97) = 0.9409
这导致立方体按时间播种。这可以通过记录缩放组件(console.log(_initScale)
)来验证。
如果您使用长度大于1.0的矢量分量(例如THREE.Vector3(0.5, 0, 0.9)
,那么立方体将按比例放大。
规范化四元数的轴,以解决问题:
let axis = new THREE.Vector3(0.4, 0, 0.9);
let q = new THREE.Quaternion().setFromAxisAngle(axis.normalize(), THREE.Math.degToRad(deg));
cube.matrix = rotateMatrix.compose(_initTranslation, q, _initScale);
如果您希望立方体的一侧与轴对齐,那么轴是正常的,那么这是完全不同的。 你要做2次旋转。首先围绕x轴连续旋转立方体(例如),然后将x轴旋转到目标轴(0.4,0,0.9)。使用.setFromAxisAngle`初始化将x轴旋转到目标轴的四元数:
let x_axis = new THREE.Vector3(1, 0, 0);
let axis = new THREE.Vector3(0.4, 0, 0.9);
let q_align = new THREE.Quaternion().setFromUnitVectors(x_axis, axis.normalize());
let q_rotate = new THREE.Quaternion().setFromAxisAngle(x_axis, THREE.Math.degToRad(deg));
let q_final = q_align.clone().multiply(q_rotate);
cube.matrix = rotateMatrix.compose(_initTranslation, q, _initScale);
请参阅示例,该示例比较了两种不同的行为:
var renderer, scene, camera, controls;
var geometry, material, line, vertices, last, _initTranslation, _initRotation, initScale, rotateMatrix;
var deg = 0;
init();
animate();
function init() {
document.body.style.cssText = 'margin: 0; overflow: hidden;' ;
renderer = new THREE.WebGLRenderer( { alpha: 1, antialias: true, clearColor: 0xffffff } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 1, 3, 3 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
geometry2 = new THREE.BoxGeometry( .5, .5, .5 );
material2 = new THREE.MeshNormalMaterial();
let shift = 0.5
cube = new THREE.Mesh( geometry2, material2 );
cube.matrix.makeTranslation(shift, 0, 0);
scene.add( cube );
cube2 = new THREE.Mesh( geometry2, material2 );
cube2.matrix.makeTranslation(-shift, 0, 0);
scene.add( cube2 );
material = new THREE.LineBasicMaterial({ color: 0x0077ff });
geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3(-0.4, 0, -0.9), new THREE.Vector3(0.4, 0, 0.9) );
line = new THREE.Line( geometry, material )
line.position.set(shift, 0, 0);
scene.add( line );
line2 = new THREE.Line( geometry, material )
line2.position.set(-shift, 0, 0);
scene.add( line2 );
var sphereAxis = new THREE.AxesHelper(20);
scene.add(sphereAxis);
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
}
function animate() {
rotate(deg)
deg += 5
requestAnimationFrame( animate );
renderer.render(scene, camera);
controls.update();
}
function rotate(deg) {
_initTranslation = new THREE.Vector3();
_initRotation = new THREE.Quaternion();
_initScale = new THREE.Vector3();
let x_axis = new THREE.Vector3(1, 0, 0);
let axis = new THREE.Vector3(0.4, 0, 0.9);
// cube
cube.matrix.decompose(_initTranslation, _initRotation, _initScale);
let q_align = new THREE.Quaternion().setFromUnitVectors(x_axis, axis.normalize());
let q_rotate = new THREE.Quaternion().setFromAxisAngle(x_axis, THREE.Math.degToRad(deg));
let q_final = q_align.clone().multiply(q_rotate);
cube.matrix.compose(_initTranslation, q_final, _initScale);
cube.matrixAutoUpdate = false;
cube.matrixWorldNeedsUpdate = true;
// cube2
cube2.matrix.decompose(_initTranslation, _initRotation, _initScale);
q = new THREE.Quaternion().setFromAxisAngle(axis.normalize(), THREE.Math.degToRad(deg));
cube2.matrix.compose(_initTranslation, q, _initScale);
cube2.matrixAutoUpdate = false;
cube2.matrixWorldNeedsUpdate = true;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
以上是关于三个JS围绕轴旋转的主要内容,如果未能解决你的问题,请参考以下文章
three.js 在它的中心围绕 Y 轴旋转 Object3d