2017-01-25 60 views
0

我一直試圖找到改變網格的頂點與three.js所最快的方式。我發現如果我改變了mesh.geometry.attributes.position.array的部分,然後設置mesh.geometry.attributes.position.needsUpdate = true,它運行良好,不必重建數組或重新創建opengl緩衝區。我發現needsUpdate = true會更改屬性的版本號,並使屬性頂點數組重新發送到opengl緩衝區。三JS如何添加三角形BufferGeometry手動

於是,我就做我自己的,而不是調用gl.bindBuffer(),然後gl.bufferData(),但然後做每一個循環的同時崩潰在我的呼叫轉接至新Float32Array後()。這很奇怪,因爲當我檢查我的內存使用情況時,我只在使用4MB之前就崩潰了。我意識到這不是在每個循環中釋放/重新分配數組的最佳方式,只是爲了使它稍微大一些,以便在數組滿量程時可以將數組的大小加倍,但我想了解爲什麼這樣做會導致數據崩潰。

https://jsfiddle.net/q1txL19c/3/崩潰在20秒。 但是,如果我將if(0)更改爲if(1),它將起作用。

什麼是three.js所不同的方式來做這使得它不會崩潰?根據profiler,爲什麼新的Float32Array()會在沒有足夠的JavaScript內存使用時失敗?

<!doctype html> 
<html> 
    <body style='margin:0;padding:0'> 
     <script src="https://threejs.org/build/three.js"></script> 
     <script> 

var camera, scene, renderer, mesh 
var triangles = 1 
init() 

function init() 
{ 
    scene = new THREE.Scene() 

    camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, .1, 10000) 
    camera.position.z = 15 
    scene.add(camera) 

    var geometry = new THREE.BufferGeometry() 

    var material = new THREE.MeshBasicMaterial({side: THREE.FrontSide, transparent:false, vertexColors: THREE.VertexColors}) 
    mesh = new THREE.Mesh(geometry, material) 

    var positions = new Float32Array([1,1,0, 0,1,0, 0,0,0]) 
    geometry.addAttribute('position', new THREE.BufferAttribute(positions,3)) 

    var colors = new Float32Array([0,0,1, 0,0,0, 0,0,0]) 
    geometry.addAttribute('color', new THREE.BufferAttribute(colors,3)) 

    scene.add(mesh) 

    renderer = new THREE.WebGLRenderer() 
    renderer.setSize(window.innerWidth, window.innerHeight) 
    renderer.setClearColor(0x6699DD) 

    document.body.appendChild(renderer.domElement) 

    loop() 
} 

function addTriangle(geometry) 
{ 
    // Make 3 new vertices, each with x,y,z. 9 total positions. 
    var newVertices = [] 
    for(var i=0; i<9; i++) 
     newVertices[i] = Math.random()*10-5 

    appendArrayToAttribute(geometry.attributes.position, newVertices) 


    // Make 3 new colors, 1 for each new vertex, each with r,g,b. 9 total slots. 
    var newColors = [] 
    for(var i=0; i<9; i++) 
     newColors[i] = Math.random() 

    appendArrayToAttribute(geometry.attributes.color, newColors) 
} 

function appendArrayToAttribute(attribute, arrayToAppend) 
{ 
    // Make a new array for the geometry to fit the 9 extra positions at the end, since you can't resize Float32Array 
    try 
    { 
     var newArray = new Float32Array(attribute.array.length + arrayToAppend.length) 
    } 
    catch(e) 
    { 
     console.log(e) 
     if(!window.alerted) 
     { 
      alert("out of memory!? can't allocate array size="+(attribute.array.length + arrayToAppend.length)) 
      window.alerted = true 
     } 
     return false 
    } 
    newArray.set(attribute.array) 
    newArray.set(arrayToAppend, attribute.array.length) 


    attribute.setArray(newArray) 

    if(0) 
    { 
     attribute.needsUpdate = true 
    } 
    else 
    { 
     // Have the geometry use the new array and send it to opengl. 
     var gl = renderer.context 
     gl.bindBuffer(gl.ARRAY_BUFFER, renderer.properties.get(attribute).__webglBuffer) 
     gl.bufferData(gl.ARRAY_BUFFER, attribute.array, gl.STATIC_DRAW) 
    } 

} 

function loop() 
{ 
    requestAnimationFrame(loop) 

    mesh.rotation.x += 0.01 
    mesh.rotation.y += 0.02 

    renderer.render(scene, camera) 

    for(var i=0;i<10;i++) 
    { 
     addTriangle(mesh.geometry) 
     triangles++ 
    } 
    if(Math.random()<.03) 
    { 
     console.log("triangles="+triangles) 
     var gl = renderer.context 
     console.log("gl buffer size="+gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)) 
    } 
} 

     </script> 

    </body> 
</html> 

回答

2

您可以第一面後,添加到BufferGeometry渲染,但是你必須預先分配的幾何attribute緩衝區足夠大,因爲他們不能調整大小。您還將更新數組值,而不是實例化新數組。

您可以更新面的數量呈現像這樣:

geometry.setDrawRange(0, 3 * numFacesToDraw); // 3 vertices for each face 

this related answer and demo

three.js r.84