javascript - 在 Three.js 中每个顶点都有圆的旋转二十面体

标签 javascript animation graphics three.js geometry

我有一个二十面体网格,我正在旋转它,然后添加圆形几何图形并将其位置设置到动画循环中每一帧的每个顶点。

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

其中 var Geometry 是二十面体的几何形状。如果我删除“isoMesh.rotation.set(0, 0, 0);”行,二十面体会正确旋转,但节点的旋转会复合并旋转得太快。如果我添加该行,节点将正确旋转,但二十面体根本不移动。

我对 Three.js 的理解还不够深入,还不明白发生了什么。为什么添加和删除它会分别影响节点和二十面体的旋转?我相信这与网格和几何体之间的差异有关,因为我使用几何体来定位节点,但网格体的旋转是视觉上显示的。知道这里发生了什么吗?

最佳答案

该解决方案是多层的。

你的二十面体:

你已经完成了一半,旋转了二十面体及其顶点。不要将旋转应用于所有顶点(这实际上会导致一些相当极端的旋转),而应仅将旋转应用于网格。但这不会更新顶点,对吗?正确的。稍后会详细介绍。

您的圈子:

将它们放置在每个顶点的想法是正确的,但正如 WestLangley 所说,对于具有旋转/平移父级的对象,您不能使用 lookAt ,因此您需要直接添加它们到现场。另外,如果您无法获得旋转二十面体顶点的新位置,则圆将简单地保持在原位。因此,让我们获取这些更新的顶点。

获取更新的顶点位置:

正如我上面所说,旋转网格会更新其变换矩阵,而不是顶点。但是我们可以使用更新后的变换矩阵来获取圆的更新后的矩阵位置。 Object3D.localToWorld 允许我们将本地 THREE.Vector3 (如二十面体的顶点)转换为世界坐标。 (另请注意,我对每个顶点进行了克隆,因为 localToWorld 覆盖了给定的 THREE.Vector3)。

要点:

我尝试将与您的问题相关的部分隔离到下面代码片段的 JavaScript 部分中。

  • 除非必要,否则尽量不要更新几何图形。
  • 仅对世界坐标系中的对象使用lookAt
  • 使用 localToWorldworldToLocal 在之间转换向量 坐标系。

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

关于javascript - 在 Three.js 中每个顶点都有圆的旋转二十面体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43265361/

相关文章:

Javascript:如何绘制两个可由按钮控制的矩形

javascript - 动画元素,但保持容器居中

javascript - HTML 5/JS 中获取 Canvas 对象位置并 move 到 Canvas 触摸位置

javascript - Internet Explorer 跟踪保护阻止 JQuery 和其他库加载

javascript - 如果 child 数多于一个数字,则在溢出时滚动

CSS背景图片动画,CPU占用率高

graphics - 电脑怎么画线??

python - 使用wxPython绘图,填充所有像素的速度有多快?

Javascript,检查时间戳是否从现在开始超过 6 小时

javascript - Chartjs 自定义 y 轴值,每个值都有不同的文本