如何高效地将 THREE.Geometry 转换为 ArrayBuffer、File 或 Blob?

3
我想将我构建 THREE.Geometry 对象的一部分代码转移到 HTML5 Web Worker 中。
因为我不想将其序列化为字符串(出于明显的性能原因),所以我想将其转换为 Transferable Object,例如ArrayBuffer、File或Blob,这样我就可以通过“引用”传递它。
你知道将 THREE.Geometry 转换为这些对象的有效方法吗?
1个回答

7

最有效的方法是使用现有的几何缓冲区,例如:

geometryGroup.__vertexArray
geometryGroup.__normalArray

它们是在 WebGLRenderer.initMeshBuffers 中创建的。

其工作原理:

  1. Create a Worker and import three.js using importScripts("/js/lib/mrdoob-three.js-35db421/build/three.js");

  2. In the worker you create another instance of the geometry you want to process.

  3. Trigger one initial rendering in the main thred renderer.render(scene, camera); now the buffers are available...

  4. Send the required buffers from the main thread to the worker

  5. Do the hard work on the geometry at the worker thread

  6. Manually (there is no support for that in threejs) fill the required buffers (see WebGLRenderer.setMeshBuffers) e.g.:

    var vertexArray = new Float32Array(vertexBuffer);
    var normalArray = new Float32Array(normalBuffer);
    
    var vertices : Array = geometry.vertices;
    var obj_faces : Array = geometry.faces;
    
    var offset = 0;
    var offset_normal = 0;
    
    for (f in 0...obj_faces.length) {
    
        var face = obj_faces[ f ];
    
        var v1 = vertices[ face.a ];
        var v2 = vertices[ face.b ];
        var v3 = vertices[ face.c ];
        var v4 = vertices[ face.d ];
    
        vertexArray[ offset ]     = v1.x;
        vertexArray[ offset + 1 ] = v1.y;
        vertexArray[ offset + 2 ] = v1.z;
    
        vertexArray[ offset + 3 ] = v2.x;
        vertexArray[ offset + 4 ] = v2.y;
        vertexArray[ offset + 5 ] = v2.z;
    
        vertexArray[ offset + 6 ] = v3.x;
        vertexArray[ offset + 7 ] = v3.y;
        vertexArray[ offset + 8 ] = v3.z;
    
        vertexArray[ offset + 9 ]  = v4.x;
        vertexArray[ offset + 10 ] = v4.y;
        vertexArray[ offset + 11 ] = v4.z;
    
        offset += 12;
    }
    
  7. send the buffers back to the main thread and update the geometry there:

    var geometryGroup = mesh.geometry.geometryGroupsList[0];
    
    var _gl = renderer.context;
    _gl.bindBuffer(_gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
    _gl.bufferData(_gl.ARRAY_BUFFER, transferVertexArray, _gl.DYNAMIC_DRAW );
    

如果您正在对几何图形进行复杂的操作,这将非常有效。了解缓冲区是如何由WebGLRenderer创建和使用的非常重要。


回答非常好而且很完整,看起来值得获得赏金。 - Sebastien
我不确定是否应该直接在ArrayBuffers上进行艰苦的工作,并在Worker之外构建正确的THREE.Geometry(来自这些数组)的工作。 - Sebastien
“for (f in 0...obj_faces.length) {” 这段代码是如何工作的?根据 Google Chrome 的提示,它是无效语法。在 2013 年回答时,您考虑了哪些浏览器? - Ferrybig

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