Three.js大于65535个顶点的行(r71)

时间:2016-02-03 22:18:55

标签: three.js

首先,我目前仍在使用Three.js r71(目前升级到最新版本会很痛苦)。也就是说,对于我的问题,我并没有想到太多改变,所以希望仍有希望。

我试图弄清楚如何在BufferGeometry中使用索引和drawcalls。我认为我98%,但有些事情没有点击。我创建了我的BufferGeometry,并用一行包含70000个顶点填充它(位置数组有210000个项目,颜色数组有210000个项目,索引数组有139998个项目((70000 - 1) * 2 = 139998 ✓))。

我知道我无法引用65535以上的索引,因此我使用geometry.drawcalls将项目添加到BufferGeometry.addDrawCall。那些对象是:

[{"start":0,"count":65535,"index":0},{"start":65535,"count":4465,"index":65535}]

现在,当我运行65535个顶点的示例(链接和代码)时,一切都按预期工作:出现红色螺旋。但是当我尝试使用70000顶点时,会发生奇怪的事情:我在控制台中看到一个错误(下面),并且出现较小的螺旋。

控制台错误:

  

GL错误:GL_INVALID_OPERATION:glDrawElements:尝试访问属性0中超出范围的顶点

我尝试重新对齐索引(从第56行开始的评论部分),但它遇到了同样的问题。我错过了一步吗?我需要填充一些其他开关或属性吗?

脚注:我尝试使用UInt32Array作为索引,但WebGL会引发类型错误。

JSFiddle: Line Indexing Test

代码:



var numVerts = 70000; // works with 65535

var hostDiv, scene, renderer, camera, controls, light;

var WIDTH = window.innerWidth,
    HEIGHT = window.innerHeight,
    FOV = 35,
    NEAR = 1,
    FAR = 1000;

function init() {
  hostDiv = document.createElement('div');
  hostDiv.setAttribute('id', 'host');
  document.body.appendChild(hostDiv);

  renderer = new THREE.WebGLRenderer({ antialias: true, preserverDrawingBuffer: true });
  renderer.setSize(WIDTH, HEIGHT);
  hostDiv.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
  camera.position.z = 250;

  controls = new THREE.TrackballControls(camera, renderer.domElement);
  controls.rotateSpeed = 5.0;
  controls.dynamicDampingFactor = 0.5;

  light = new THREE.PointLight(0xffffff, 1, Infinity);
  light.position.copy(camera.position);

  scene = new THREE.Scene();
  scene.add(camera);
  scene.add(light);

  scene.add(createSpiral());
debugger;
  animate();
}

function createSpiral(){
  var positions = [],
      indices = [],
      colors = [];

  var vec = new THREE.Vector3(1, 0, 0),
      rotVec = new THREE.Vector3(0, 0, 1);

  for(var idx = 0, fakeIdx = 0; idx < numVerts; ++idx){
    // update position vector
    vec.setLength((idx + 1) / 1000); // slowly spiral outward
    vec.applyAxisAngle(rotVec, 0.01); // spin around the z-axis
    positions.push(vec.x, vec.y, vec.z);

    if(idx + 1 < numVerts){
      indices.push(idx, idx + 1);
    }
    //if((idx % 65535) + 1 < numVerts){
    //  indices.push((idx % 65535), (idx % 65535) + 1);
    //}

    if(idx > 65535){
      colors.push(0, 1, 0); // GREEN!
    }
    else{
      colors.push(1, 0, 0); // RED!
    }
  }

  bg = new THREE.BufferGeometry();

  if(numVerts > 65535){
    var remainingVerts = numVerts,
        start = 0,
        count = 0,
        index = 0;

    while(remainingVerts > 0){
      count = (remainingVerts < 65535)? remainingVerts : 65535;

      bg.addDrawCall(start, count, start);

      start += 65535;			
      remainingVerts -= 65535;
    }
  }

  bg.addAttribute('index', new THREE.BufferAttribute(new Uint16Array( indices ), 1));
  bg.addAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3));
  bg.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3));

  var mat = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });

  var spiral = new THREE.Line(bg, mat, THREE.LinePieces);
  spiral.name = "SPIRAL";
  debugger;
  return spiral;
}

function render() {
  light.position.copy(camera.position);
  renderer.render(scene, camera);
  controls.update();
}

function animate() {    
  requestAnimationFrame(animate);
  render();
}

init();
&#13;
html *{
	padding: 0;
	margin: 0;
	height: 100%;
	width: 100%;
	overflow: hidden;
}

#host {
	width: 100%;
	height: 100%;
}
&#13;
<script src="https://rawgithub.com/mrdoob/three.js/f73593b00e3b2c927bb1a3236240cea5597166ec/build/three.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

在r73中使用UInt32Array对我来说很好。

在r73中,他们不会在材料中使用THREE.LineStripTHREE.LinePieces,但有两个不同的类THREE.LineTHREE.LineSegments用于连续或分段绘制线条。

我做了一些其他的改变。我改为使用连续线而不是段,因为它节省了一半的索引量。我认为这也可能是你的问题之一。由于您为每个线段插入了2个索引,这意味着绘制32768个线段,您已达到最大65536个索引。

Here a fiddle,我更新了r73

请注意我的更改重要更改:

indices.push(idx);

bg.setIndex( new THREE.BufferAttribute( new Uint32Array( indices ), 1 ) );

var spiral = new THREE.Line(bg, mat);

我删除了不需要的代码行。

更新

有趣的是,我只是注意到你甚至不需要索引。它作为非索引THREE.BufferGeometry完全正常。如果我没有弄错的话,这可以为您节省所有麻烦,并且几乎可以让您拥有无限分......

Here another fiddle表明它没有大量的分数就能完全正常。

这也适用于 r71 。检查出here