說了幾篇的數學方法,這篇放松一下,郭先生說說繞任意軸轉動。說一說其中一種方法,也是比較容易理解的一種,它的原理就是將子對象放到一個盒子中,然后改變子對象相對於父對象的位置(因為子對象的原點默認還是在盒子的中心),最后轉動盒子,這樣子對象的旋轉就不是繞盒子的中心了。如圖所示。在線案例點擊模擬門旋轉(更多three.js相關文章和案例請點擊原文)。
說到這里就不得不說THREE.Group對象了,除了isGroup和type這兩個屬性,它幾乎和Object3D是相同的。其目的是使得組中對象在語法上的結構更加清晰。它的作用就像一個容器。
下面說一下主要代碼(為了練習,門框使用THREE.Geometry())
var geometry = new THREE.Geometry();//新建門框的幾何體 var vertices = [ new THREE.Vector3(-30, 70, 4), new THREE.Vector3(30, 70, 4), new THREE.Vector3(30, -70, 4), new THREE.Vector3(-30, -70, 4), new THREE.Vector3(-30, 70, -4), new THREE.Vector3(30, 70, -4), new THREE.Vector3(30, -70, -4), new THREE.Vector3(-30, -70, -4), new THREE.Vector3(-27, 67, 4), new THREE.Vector3(27, 67, 4), new THREE.Vector3(27, -67, 4), new THREE.Vector3(-27, -67, 4), new THREE.Vector3(-27, 67, -4), new THREE.Vector3(27, 67, -4), new THREE.Vector3(27, -67, -4), new THREE.Vector3(-27, -67, -4), ]; var faces = [ new THREE.Face3(0, 8, 9), new THREE.Face3(0, 9, 1), new THREE.Face3(1, 9, 10), new THREE.Face3(1, 10, 2), new THREE.Face3(2, 10, 11), new THREE.Face3(2, 11, 3), new THREE.Face3(3, 11, 8), new THREE.Face3(3, 8, 0), new THREE.Face3(4, 5, 13), new THREE.Face3(4, 13, 12), new THREE.Face3(5, 6, 14), new THREE.Face3(5, 14, 13), new THREE.Face3(6, 7, 15), new THREE.Face3(6, 15, 14), new THREE.Face3(7, 4, 12), new THREE.Face3(7, 12, 15), new THREE.Face3(0, 1, 5), new THREE.Face3(0, 5, 4), new THREE.Face3(2, 3, 7), new THREE.Face3(2, 7, 6), new THREE.Face3(1, 2, 6), new THREE.Face3(1, 6, 5), new THREE.Face3(0, 4, 7), new THREE.Face3(0, 7, 3), new THREE.Face3(9, 8, 12), new THREE.Face3(9, 12, 13), new THREE.Face3(14, 15, 11), new THREE.Face3(14, 11, 10), new THREE.Face3(13, 14, 10), new THREE.Face3(13, 10, 9), new THREE.Face3(12, 8, 11), new THREE.Face3(12, 11, 15), ]; geometry.vertices = vertices;//幾何體添加頂點數組 geometry.faces = faces;//幾何體添加面數組 geometry.computeFaceNormals();//計算 face normals 值。 var material = new THREE.MeshPhongMaterial({ color: 0x330000, shininess: 40 });//新建和門搭調的材質 var mesh = new THREE.Mesh(geometry, material); mesh.position.x = -27;//x方向偏移27,是門寬的一般 mesh.position.y = 70;//將門框偏移一定的單位 group.add(mesh);//在group中添加門框 var doorGeom = new THREE.BoxGeometry(54, 134, 6);//新建門的幾何體,注意這里的門寬度為54 var texture = new THREE.TextureLoader().load(require('../assets/images/base/door.jpg'));//創建一個紋理貼圖 var doorMate = new THREE.MeshPhongMaterial({ color: 0xffffff, shininess: 200, specular: 0x090909, map: texture });//為門添加一個高光材質和紋理貼圖 var doorMesh = new THREE.Mesh(doorGeom, doorMate); doorMesh.position.x = -27;//給門添加偏移量和門框相同 doorMesh.position.y = 70; doorGroup.add(doorMesh);//將門添加到doorGroup中 group.add(doorGroup);然后將doorGroup添加到group中 group.position.x = 27;//因為之前的所有都添加了-27的偏移量,為了保證門在世界坐標系的中心,我在將門的Group的x方向平移27。 scene.add(group);//最后將scene中添加group。
這里主要注意的就是門的長寬高,還有門和group的移動距離需要簡單的計算一下,
接下來可以添加tween動畫進行開關門的動畫,這里就不多說了,直接上代碼。
initTween() { var config = { rotate: 0 }; tween1 = new TWEEN.Tween(config).to({ rotate: 1 }, 1000); tween2 = new TWEEN.Tween(config).to({ rotate: 0 }, 1000); tween1.easing(TWEEN.Easing.Quadratic.InOut); tween2.easing(TWEEN.Easing.Quadratic.InOut); tween1.onUpdate(onUpdate); tween2.onUpdate(onUpdate); }, function onUpdate() { let rotate = this._object.rotate; doorGroup.rotation.y = Math.PI / 3 * rotate; }
這里說的是簡單的繞中心軸的轉動,當然還有很多方法,比如骨骼動畫什么的(當然骨骼動畫的原理和這個也很相似)。
轉載請注明地址:郭先生的博客