3

I'm using a web-worker to load a .json file of an animated 3D model. For each of the big arrays (vertices, normals, etc.), I'm transferring an Float32Array buffer back to the UI thread. Since such buffers are transferable objects, this will take (almost) zero time.

Now, it turns out that WebGL (and therefore, Three.js) use Float32Array buffers internally, too. This means I could probably load this 3D animation without copying anything, spending almost zero time in the main thread. Isn't that nice?

But it's not clear how to do that part: In the main thread, we have array buffers available for the vertices, normals (the main ones, and the 'morph' ones) and faces. How do I create a working Geometry (or BufferGeometry) from these, without translating or copying the data?

var scene,
    vertices, normals, faces,
    morphVertices, morphNormals; // <-- we have all these as typed arrays

var geometry = ...; // <-- insert code here

var material = new THREE.MeshLambertMaterial({ morphTargets: true });
var object3D = new THREE.MorphAnimMesh(geometry, material);
scene.add(object3D);

This answer gives a hint, but only point 7 seems relevant, it assumes there is already some Geometry instance, and it doesn't handle morph-targets.

Community
  • 1
  • 1
mhelvens
  • 4,225
  • 4
  • 31
  • 55

1 Answers1

1

Here's an example based on the mesh loading portion of THREE.GLTF2Loader.

// Create BufferGeometry and assign vertices and normals.
var geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
geometry.setIndex( new THREE.BufferAttribute( faces, 3 ) );

// Create material.
var material = new THREE.MeshStandardMaterial({
  morphTargets: true,
  morphNormals: true
});

// Set up morph target attributes.
var posAttr = new THREE.BufferAttribute( morphVertices, 3 );
var normAttr = new THREE.BufferAttribute( morphNormals, 3 );
for (var i = 0; i < posAttr.array.length; i++) {
  posAttr.array[i] += geometry.attributes.position.array[i];
}
for (var j = 0; j < normAttr.array.length; j++) {
  normAttr.array[j] += geometry.attributes.normal.array[j];
}

// Assign morph target attributes.
geometry.morphAttributes.position = [ posAttr ];
geometry.morphAttributes.normal = [ normAttr ];

// Create Mesh.
var mesh = new THREE.Mesh(geometry, material);
mesh.updateMorphTargets();

// Apply 50/50 blend of morph targets and default position/normals.
mesh.morphTargetInfluences[0] = 0.5;

three.js r86-dev.

Don McCurdy
  • 10,975
  • 2
  • 37
  • 75
  • I was trying to do something similar with THREE.Point. But unfortunately, the updateMorphTargets() is not available on THREE.Point. I guess Point is not really a mesh? I will post it as a separate question – Ravi Gidwani May 17 '18 at 22:44