THREE.js动态向点几何体添加点无法渲染

5

我正在使用 Three.js r83。

我试图动态向几何体添加点,但是场景从未更新。

以下代码有效:

var tmaterial = new THREE.PointsMaterial({
    color: 0xff0000,
    size: 5,
    opacity: 1
});

var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);

for(var i = 0; i< 1000; i++) {
    x = (Math.random() * 200) - 100;
    y = (Math.random() * 200) - 100;
    z = (Math.random() * 200) - 100;
    tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.computeVertexNormals();

scene.add(pointCloud);

这不起作用:
var tmaterial = new THREE.PointsMaterial({
    color: 0xff0000,
    size: 5,
    opacity: 1
});

var tgeometry = new THREE.Geometry();
var pointCloud = new THREE.Points(tgeometry, tmaterial);
scene.add(pointCloud);

for(var i = 0; i< 1000; i++) {
    x = (Math.random() * 200) - 100;
    y = (Math.random() * 200) - 100;
    z = (Math.random() * 200) - 100;
    tgeometry.vertices.push(new THREE.Vector3(x, y, z));
}
tgeometry.verticesNeedUpdate = true;
tgeometry.elementsNeedUpdate = true;
tgeometry.computeVertexNormals();
renderer.render(scene, camera);

如您所见,唯一的区别在于我在添加顶点之前添加了scene.add(pointCloud);

我错过了什么吗?

您可以在fiddle中找到。感谢 @hectate。

要看我想表达的,请将

init(); setPoints(); animate();

替换为

init(); animate(); setPoints();


2
请查看以下链接:https://dev59.com/jpbfa4cB1Zd3GeqPqDFZ#36699654 和 https://dev59.com/mV0Z5IYBdhLWcg3wfgUR#31411794。 - WestLangley
@WestLangley 我目前在探索BufferGeometry,看起来点的数量是固定的。 - Ant
1
最大的数字是。渲染的数字不是。请研究我发布的第二个链接。 - WestLangley
@WestLangley 谢谢 - 我已经使用最大点数和BufferGeometry使其正常工作。现在正在更新并撰写答案。 - Ant
1
从试错方法来看,在渲染之前请求动画帧就像是你能做的最糟糕的事情,完全错误,自担风险。如果真的如此,为什么没有人注意到呢? - greenthings
显示剩余2条评论
2个回答

5

我不确定为什么THREE.Geometry对象在初始渲染后不会更新点,但我使用了THREE.BufferGeometry就行了。

感谢@Hectate为我提供了一个可用的示例和@WestLangley指引我的提示,这是可用的示例

BufferGeometry具有固定数量的顶点,但您可以决定要渲染多少个顶点。诀窍是利用geometry.attributes.position.needsUpdate = true;geometry.setDrawRange( 0, nbPointsYouWantToDisplay );

var MAX_POINTS = 1000000;
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array( MAX_POINTS * 3 ); 
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );

然后,您可以创建您的云点并将其添加到场景中:
//material and scene defined in question
pointCloud = new THREE.Points(geometry, material);
scene.add(pointCloud);

现在我想要每隔10毫秒添加和渲染500个新点。
var nbPoints = 500;
var INTERVAL_DURATION = 10;

我所需要做的只是:

var interval = setInterval(function() {
  setPoints();
}, INTERVAL_DURATION)

function setPoints() {

  var positions = pointCloud.geometry.attributes.position.array;

  var x, y, z, index;

  var l  = currentPoints + nbPoints;
  if(l >= MAX_POINTS) {
    clearInterval(interval);
  }

  for ( var i = currentPoints; i < l; i ++ ) {
    x = ( Math.random() - 0.5 ) * 300;
    y = ( Math.random() - 0.5 ) * 300;
    z = ( Math.random() - 0.5 ) * 300;
    positions[ currentPointsIndex ++ ] = x;
    positions[ currentPointsIndex ++ ] = y;
    positions[ currentPointsIndex ++ ] = z;
  }
  currentPoints = l;
  pointCloud.geometry.attributes.position.needsUpdate = true;   
  pointCloud.geometry.setDrawRange( 0, currentPoints );  
  controls.update();
  renderer.render(scene, camera);

}

three.js在你发现之后,已经放弃了Geometry,转而采用BufferGeometry。当然,这对我来说在2021年很容易说(; - Jacksonkr

3

这是一个包含初始设置的示例代码:https://jsfiddle.net/87wg5z27/236/

var scene, renderer, camera;
var cube;
var controls;

init();
animate();

function init()
{
    renderer = new THREE.WebGLRenderer( {antialias:true} );
    var width = window.innerWidth;
    var height = window.innerHeight;
    renderer.setSize (width, height);
    document.body.appendChild (renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
    camera.position.y = 160;
    camera.position.z = 400;
    camera.lookAt (new THREE.Vector3(0,0,0));

    controls = new THREE.OrbitControls (camera, renderer.domElement);

    var tmaterial = new THREE.PointsMaterial({
      color: 0xff0000,
      size: 5,
      opacity: 1
   });

   var tgeometry = new THREE.Geometry();
   var pointCloud = new THREE.Points(tgeometry, tmaterial);

   for(var i = 0; i< 1000; i++) {
     x = (Math.random() * 200) - 100;
     y = (Math.random() * 200) - 100;
     z = (Math.random() * 200) - 100;
     tgeometry.vertices.push(new THREE.Vector3(x, y, z));
   }
   tgeometry.verticesNeedUpdate = true;
   tgeometry.computeVertexNormals();

   scene.add(pointCloud);

   window.addEventListener ('resize', onWindowResize, false);
}

function onWindowResize ()
{
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize (window.innerWidth, window.innerHeight);
}

function animate()
{
    controls.update();
    requestAnimationFrame ( animate );  
    renderer.render (scene, camera);
}

以下是与您的第二个问题相关的内容:https://jsfiddle.net/87wg5z27/237/

var scene, renderer, camera;
var cube;
var controls;

init();
animate();

function init()
{
    renderer = new THREE.WebGLRenderer( {antialias:true} );
    var width = window.innerWidth;
    var height = window.innerHeight;
    renderer.setSize (width, height);
    document.body.appendChild (renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
    camera.position.y = 160;
    camera.position.z = 400;
    camera.lookAt (new THREE.Vector3(0,0,0));

    controls = new THREE.OrbitControls (camera, renderer.domElement);

    var tmaterial = new THREE.PointsMaterial({
      color: 0xff0000,
      size: 5,
      opacity: 1
    });

    var tgeometry = new THREE.Geometry();
    var pointCloud = new THREE.Points(tgeometry, tmaterial);
    scene.add(pointCloud);

    for(var i = 0; i< 1000; i++) {
     x = (Math.random() * 200) - 100;
     y = (Math.random() * 200) - 100;
     z = (Math.random() * 200) - 100;
     tgeometry.vertices.push(new THREE.Vector3(x, y, z));
    }
    tgeometry.verticesNeedUpdate = true;
    tgeometry.elementsNeedUpdate = true;
    tgeometry.computeVertexNormals();
    renderer.render(scene, camera);

    window.addEventListener ('resize', onWindowResize, false);
}

function onWindowResize ()
{
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize (window.innerWidth, window.innerHeight);
}

function animate()
{
    controls.update();
    requestAnimationFrame ( animate );  
    renderer.render (scene, camera);
}

在两种情况下,点云对我来说都显示得很好(版本82)。也许你忽略了某些地方没有渲染出来的东西?我注意到你的第一个示例没有显示你调用render()的步骤。希望这可以帮助你!


1
嗨@Hectate,非常感谢您提供的那个代码片段,我应该自己创建一个 - 真的很感谢。我又做了一个演示我的问题的代码片段 - 请看更新后的问题。https://jsfiddle.net/jjjaLv3e/2/我想在渲染点云后更新它。 - Ant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接