どちらかをクリックしてみて下さい。非安定な場合、もしくは、安定な場合。
ソースコードは誤りを含んでいるかもしれませんが、まあ、基本的にはOKなのでしょう。私は、matrix4_from_matrix3()とかmatrix3_from_matrix4()と言った関数を自分で書く必要があるのか良く分かりません。
疑問であれば、下記のドキュメントを調べてみて下さい。
https://threejs.org/docs/api/math/Vector3.html
https://threejs.org/docs/api/math/Quaternion.html
https://threejs.org/docs/api/math/Matrix3.html
https://threejs.org/docs/api/math/Matrix4.html
<html> <head> <title>My first Three.js app</title> <style> body { margin: 0; } canvas { width: 100%; height: 100% } </style> </head> <body> <script src="https://ajax.googleapis.com/ajax/libs/threejs/r76/three.min.js"></script> <script> function matrix4_from_matrix3 (m4, m3) { var se = m3.elements; var te = m4.elements; te[0] = se[0]; te[4] = se[3]; te[ 8] = se[6]; te[12] = 0; te[1] = se[1]; te[5] = se[4]; te[ 9] = se[7]; te[13] = 0; te[2] = se[2]; te[6] = se[5]; te[10] = se[8]; te[14] = 0; te[3] = 0; te[7] = 0; te[11] = 0; te[15] = 0; } function matrix3_from_matrix4 (m3, m4) { var se = m4.elements; var te = m3.elements; te[0] = se[0]; te[3] = se[4]; te[6] = se[ 8]; te[1] = se[1]; te[4] = se[5]; te[7] = se[ 9]; te[2] = se[2]; te[5] = se[6]; te[8] = se[10]; } var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(7, window.innerWidth/window.innerHeight, 0.1, 1000 ); var renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); var geometry = new THREE.BoxGeometry( 4, 9, 1 ); var material2= new THREE.MeshLambertMaterial( { color: 0xf01010 } ); var cube= new THREE.Mesh( geometry, material2 ); cube.position.x = 0.0; scene.add( cube ); var geometry0= new THREE.BoxGeometry( 1000, 1000, 1); var material0 = new THREE.MeshBasicMaterial( { color: 0x101040 } ); var cube0 = new THREE.Mesh( geometry0, material0 ); cube0.position.z = -10; scene.add( cube0 ); camera.position.x = 100; camera.position.y = 100; camera.position.z = 250; camera.lookAt(cube.position); scene.add( camera ); var light = new THREE.DirectionalLight(0xffffff); light.position.set(250, 250, 250); scene.add( light ); var light0 = new THREE.AmbientLight( 0x404040 ); scene.add( light0 ); var Ibody = new THREE.Matrix3(); var IbodyInv = new THREE.Matrix3(); var IbodyInv4 = new THREE.Matrix4(); Ibody.set(82,0,0, 0,17,0, 0,0,97); IbodyInv.getInverse(Ibody); matrix4_from_matrix3 (IbodyInv4, IbodyInv); var q = new THREE.Quaternion(); var qq = new THREE.Quaternion(); var qdot = new THREE.Quaternion(); var axis = new THREE.Vector3(0,1,0).normalize(); var angle = Math.PI * 0.0; q.setFromAxisAngle(axis,angle); var x, y, z, w; var L = new THREE.Vector3(); var L4 = new THREE.Vector4(); L.set(13.0*2.0*Math.PI*82.0,2.0*Math.PI*0.1,2.0*Math.PI*0.1); L4.set(L.x, L.y, L.z, 0); var omega = new THREE.Vector3(); var R = new THREE.Matrix3(); var RInv = new THREE.Matrix3(); var IInv = new THREE.Matrix3(); var R4 = new THREE.Matrix4(); var RInv4 = new THREE.Matrix4(); var IInv4 = new THREE.Matrix4(); var dt = 0.001; var render = function () { requestAnimationFrame( render ); x = q.x; y = q.y; z = q.z; w = q.w; R.set(1.0-2.0*y*y-2.0*z*z, 2.0*x*y+2.0*w*z, 2.0*x*z-2.0*w*y, 2.0*x*y-2.0*w*z, 1.0-2.0*x*x-2.0*z*z, 2.0*y*z+2.0*w*x, 2.0*x*z+2.0*w*y, 2.0*y*z-2.0*w*x, 1.0-2.0*x*x-2.0*y*y); RInv.getInverse(R); matrix4_from_matrix3 (R4 , R ); matrix4_from_matrix3 (RInv4, RInv); // IInv = R * IbodyInv * RInv; IInv4.multiplyMatrices(R4, IbodyInv4); IInv4.multiply (RInv4); matrix3_from_matrix4 (IInv, IInv4); // omega = IInv * L; omega.copy(L); omega.applyMatrix3(IInv); qq.set(omega.x/2.0, omega.y/2.0, omega.z/2.0, 0.0); // qdot = qq * q; qdot.multiplyQuaternions(qq, q); // q += qdot * dt; q.set(q.x+qdot.x*dt, q.y+qdot.y*dt, q.z+qdot.z*dt, q.w+qdot.w*dt); q.normalize(); cube.rotation.setFromQuaternion(q); renderer.render(scene, camera); } render(); </script> </body> </html>