Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Three.js: How to create new 'morphing' geometry if I have all necessary buffers?

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.

like image 987
mhelvens Avatar asked Dec 07 '25 03:12

mhelvens


1 Answers

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.

like image 112
Don McCurdy Avatar answered Dec 08 '25 17:12

Don McCurdy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!