旋转二十面体,位于three.js中每个顶点的圆上 [英] Rotating icosahedron with circles located at every vertex in three.js

查看:143
本文介绍了旋转二十面体,位于three.js中每个顶点的圆上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个正在旋转的二十面体网格,然后添加圆形几何图形,并将它们的位置设置到动画循环中每一帧的每个顶点。  geometry = new THREE.IcosahedronGeometry(isoRadius,1); 
var material = new THREE.MeshBasicMaterial({
color:wireframeColor,
wireframe:true
});

isoMesh = new THREE.Mesh(geometry,material);
scene.add(isoMesh);

设置每个圆形几何位置为二十面体网格旋转:

 函数animate(){

isoMesh.rotation.x + = 0.005;
isoMesh.rotation.y + = 0.002;

//更新顶点
isoMesh.updateMatrix();
isoMesh.geometry.applyMatrix(isoMesh.matrix);
isoMesh.rotation.set(0,0,0); (var i = 0; i< geometry.vertices.length; i ++){

nodes [i] .position.copy(geometry.vertices [i])的

。 );
nodes [i] .lookAt(camera.position);
}

其中,var geometry是二十面体的几何图形。如果删除isoMesh.rotation.set(0,0,0);这一行,则二十面体正确旋转,但节点的旋转复合和旋转方式太快。如果我添加该行,节点正确旋转,但二十面体根本不移动。

我对three.js的理解还不够清楚,不知道发生了什么。为什么要添加和删除它会分别影响节点和二十面体的旋转?我相信它与网格和几何之间的差异有关,因为我使用几何来定位节点,但网格的旋转是可视化显示的。任何想法发生在这里?

解决方案

解决方案它是多层次的。


$ b $你的二十面体:



你在旋转你的二十面体及其顶点时已经到了一半。而不是将旋转应用到所有顶点(实际上会导致一些非常极端的旋转),只将旋转应用于网格。但是,这并不会更新顶点,对吧?对。更多关于这一点。



您的圈子:

但是正如WestLangley所说,你不能在父对象的旋转/翻译对象中使用 lookAt ,所以你需要直接添加它们到现场。此外,如果您无法获得旋转二十面体顶点的新位置,则圆圈将保持原位。所以让我们来获得更新的顶点。



获得更新的顶点位置:



喜欢我上面说过,旋转网格更新它的变换矩阵,而不是顶点。但是我们可以使用更新后的变换矩阵来获得圆圈的更新矩阵位置。 Object3D.localToWorld 允许我们将本地的 THREE.Vector3 (比如你的二十面体的顶点)转换成世界坐标。 (还要注意我做了每个顶点的克隆,因为 localToWorld 覆盖了给定的 THREE.Vector3 )。 p>

结论:

我试图将相对于您的问题的部分以下代码段的JavaScript部分。




  • 尝试不更新几何体,除非必须。

  • 只能在世界坐标系中使用 lookAt 和对象

  • 使用 localToWorld worldToLocal 来转换
    坐标系之间的矢量。


 

html * {padding:0;保证金:0;宽度: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> // INITIALIZEvar 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); tr ackballControl.rotateSpeed = 5.0; //需要加速一个小小的场景= 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();}函数animate(){requestAnimationFrame(animate); trackballControl.update(); render();} animate();< / script>

I have an icosahedron mesh which I am rotating and then adding circle geometries and setting their location to each vertex at every frame in the animation loop.

geometry = new THREE.IcosahedronGeometry(isoRadius, 1);
var material = new THREE.MeshBasicMaterial({
    color: wireframeColor,
    wireframe: true
});

isoMesh = new THREE.Mesh(geometry, material);
scene.add(isoMesh);

Set each circle geometries location as the icosahedron mesh rotates:

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);
    }

Where var geometry is the geometry of the icosahedron. If I remove the line "isoMesh.rotation.set(0, 0, 0);", the icosahedron rotates correctly, but the rotation of the nodes compounds and spins way too quickly. If I add that line, the nodes rotate correctly, but the icosahedron does not move at all.

I do not understand three.js well enough yet to understand what is happening. Why would adding and removing this affect the nodes' and icosahedron's rotations separately? I believe it has something to do with the difference between the mesh and the geometry since I am using the geometry to position the nodes, but the rotation of the mesh is what shows visually. Any idea what is happening here?

解决方案

The solution it multi-layered.

Your Icosahedron:

You were half-way there with rotating your icosahedron and its vertices. Rather than applying the rotation to all the vertices (which would actually cause some pretty extreme rotation), apply the rotation to the mesh only. But that doesn't update the vertices, right? Right. More on that in a moment.

Your Circles:

You have the right idea of placing them at each vertex, but as WestLangley said, you can't use lookAt for objects with rotated/translated parents, so you'll need to add them directly to the scene. Also, if you can't get the new positions of the vertices for the rotated icosahedron, the circles will simply remain in place. So let's get those updated vertices.

Getting Updated Vertex Positions:

Like I said above, rotating the mesh updates its transformation matrix, not the vertices. But we can USE that updated transformation matrix to get the updated matrix positions for the circles. Object3D.localToWorld allows us to transform a local THREE.Vector3 (like your icosahedron's vertices) into world coordinates. (Also note that I did a clone of each vertex, because localToWorld overwrites the given THREE.Vector3).

Takeaways:

I've tried to isolate the parts relative to your question into the JavaScript portion of the snippet below.

  • Try not to update geometry unless you have to.
  • Only use lookAt with objects in the world coordinate system
  • Use localToWorld and worldToLocal to transform vectors between coordinate systems.

// 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>

这篇关于旋转二十面体,位于three.js中每个顶点的圆上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆