三个js如何手动将三角形添加到BufferGeometry

时间:2017-01-25 19:57:19

标签: javascript three.js typed-arrays

我一直试图找到用three.js更改网格顶点的最快方法。我发现如果我更改了mesh.geometry.attributes.position.array的部分,然后设置mesh.geometry.attributes.position.needsUpdate = true,它运行良好,不必重建数组或重新创建opengl缓冲区。我发现needsUpdate = true会更改属性的版本号,并使其将属性顶点数组重新发送到opengl缓冲区。

所以我尝试自己这样做,而不是通过调用gl.bindBuffer()然后调用gl.bufferData(),然后在完成每个循环一段时间之后它会在我调用new Float32Array()时崩溃。这很奇怪,因为当我检查我的内存使用情况时,我只是在它崩溃之前使用了4MB。我意识到这不是每个循环释放/重新分配数组的最好方法,只是为了使它在数据大小加倍时可以加倍,但是我想知道为什么它在这样做时会崩溃。

https://jsfiddle.net/q1txL19c/3/在20秒内崩溃。 但是,如果我将if(0)更改为if(1)则可以正常工作。

什么是three.js采取不同的做法,使其不崩溃?为什么新的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>

1 个答案:

答案 0 :(得分:2)

您可以在第一次渲染后向BufferGeometry添加面,但您必须预先分配几何attribute缓冲区,因为它们无法调整大小。

此外,您将更新数组值,而不是实例化新数组。

您可以像这样更新要渲染的面数:

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

请参阅this related answer and demo

three.js r.84