我有一个二十面体网格,我正在旋转它,然后添加圆形几何形状,并在动画循环中的每一帧处将它们的位置设置为每个顶点。
geometry = new THREE.IcosahedronGeometry(isoRadius, 1);
var material = new THREE.MeshBasicMaterial({
color: wireframeColor,
wireframe: true
});
isoMesh = new THREE.Mesh(geometry, material);
scene.add(isoMesh);
在二十面体网格旋转时设置每个圆几何位置:
function animate() {
isoMesh.rotation.x += 0.005;
isoMesh.rotation.y += 0.002;
// update vertices
isoMesh.updateMatrix();
isoMesh.geometry.applyMatrix(isoMesh.matrix);
isoMesh.rotation.set(0, 0, 0);
for (var i = 0; i < geometry.vertices.length; i++) {
nodes[i].position.copy(geometry.vertices[i]);
nodes[i].lookAt(camera.position);
}
其中变量几何是二十面体的几何。如果我删除行"isoMesh.rotation.set(0, 0, 0);",二十面体可以正确旋转,但节点的旋转会复合并旋转得太快。如果我添加这条线,节点会正确旋转,但二十面体根本不移动。
我还不明白三个.js还不够明白发生了什么。为什么添加和删除它会分别影响节点和二十面体的旋转?我相信这与网格和几何体之间的差异有关,因为我使用几何体来定位节点,但网格的旋转是视觉显示的。知道这里发生了什么吗?
它多层的解决方案。
您的二十面体:
你已经完成了一半,旋转你的二十面体和它的顶点。与其将旋转应用于所有顶点(这实际上会导致一些非常极端的旋转),不如仅将旋转应用于网格。但这不会更新顶点,对吧?右。稍后会详细介绍。
您的圈子:
您有将它们放置在每个顶点的正确想法,但正如 WestLangley 所说,您不能将lookAt
用于具有旋转/平移父项的对象,因此您需要将它们直接添加到场景中。此外,如果您无法获得旋转二十面体的顶点的新位置,则圆将简单地保留在原位。因此,让我们获取这些更新的顶点。
获取更新的顶点位置:
就像我上面说的,旋转网格会更新其变换矩阵,而不是顶点。但是我们可以使用更新的转换矩阵来获取圆的更新矩阵位置。Object3D.localToWorld
允许我们将局部THREE.Vector3
(如二十面体的顶点)转换为世界坐标。(另请注意,我为每个顶点做了一个克隆,因为localToWorld
覆盖了给定的THREE.Vector3
)。
要点:
我试图将与你的问题相关的部分隔离到下面代码片段的 JavaScript 部分。
- 除非必须,否则尽量不要更新几何图形。
- 仅对世界坐标系中的对象使用
lookAt
- 使用
localToWorld
和worldToLocal
在 坐标系。
// You already had this part
var geometry = new THREE.IcosahedronGeometry(10, 1);
var material = new THREE.MeshBasicMaterial({
color: "blue",
wireframe: true
});
var isoMesh = new THREE.Mesh(geometry, material);
scene.add(isoMesh);
// Add your circles directly to the scene
var nodes = [];
for(var i = 0, l = geometry.vertices.length; i < l; ++i){
nodes.push(new THREE.Mesh(new THREE.CircleGeometry(1, 32), material));
scene.add(nodes[nodes.length - 1]);
}
// This is called in render. Get the world positions of the vertices and apply them to the circles.
var tempVector = new THREE.Vector3();
function updateVertices(){
if(typeof isoMesh !== "undefined" && typeof nodes !== "undefined" && nodes.length === isoMesh.geometry.vertices.length){
isoMesh.rotation.x += 0.005;
isoMesh.rotation.y += 0.002;
for(var i = 0, l = nodes.length; i < l; ++i){
tempVector.copy(isoMesh.geometry.vertices[i]);
nodes[i].position.copy(isoMesh.localToWorld(tempVector));
nodes[i].lookAt(camera.position);
}
}
}
html *{
padding: 0;
margin: 0;
width: 100%;
overflow: hidden;
}
#host {
width: 100%;
height: 100%;
}
<script src="http://threejs.org/build/three.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<div id="host"></div>
<script>
// INITIALIZE
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
document.getElementById('host').appendChild(renderer.domElement);
var stats= new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
var camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 50;
var trackballControl = new THREE.TrackballControls(camera, renderer.domElement);
trackballControl.rotateSpeed = 5.0; // need to speed it up a little
var scene = new THREE.Scene();
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
scene.add(light);
function render(){
if(typeof updateVertices !== "undefined"){
updateVertices();
}
renderer.render(scene, camera);
stats.update();
}
function animate(){
requestAnimationFrame(animate);
trackballControl.update();
render();
}
animate();
</script>