Export Three.js scene to STL, keeping animation intact

I have a Three.js script, and I would like to export what it looks like after rendering the animation. For example, after the animation has passed ~ 100 frames, the user hit export, and the scene should be exported to STL in the same way as at that moment.

From what I tried (using STLExporter.js , that is), it seems to export the model using only the starting positions.

If you already have a way to do this or just work, I would appreciate a push in that direction.

Update . After a bit deeper processing of the internal parts, I found out (at least superficially) why STLExporter is not working. STLExporter finds all the objects and queries them for the vertices and faces of the Geometry object. My model has a bunch of bones that are covered in skin. During the animation phase, the bones are updated, but these updates do not apply to the original Geometry object. I know that these transformed vertices are computed and exist somewhere (they are displayed on the canvas).

Question: where are these transformed vertices and faces and can I access them to export them as STL?

+5
source share
2 answers

The question is, where are these transformed vertices and faces stored, and can I access them to export them as STL?

The answer to this, unfortunately, is nowhere. All of them are calculated on the GPU by calling WebGL functions, passing several large arrays.

To explain how to calculate this, let's first look at how animation works using this knight example for reference. The SkinnedMesh object contains, among other things, a skeleton (made from Bone s) and many vertices. They begin with what is called a tie pose . Each vertex is attached to 0-4 bones, and if these bones move, the vertices will move, creating an animation.

Bind image

If you would take our chivalrous example, stop the mid-swing animation and try the standard STL exporter, the STL file generated will be this pose, not the animated one. What for? Because it just looks at mesh.geometry.vertices, which do not change from the original binding during the animation. Only the bone changes, and the GPU does some math to move the vertices corresponding to each bone.

This math is quite straightforward to move each vertex - transform the position of the binding-pose vertex into the bone space, and then from the bone space to the global space before exporting.
Adapting the code from here , we add this to the original exporter:

 vector.copy( vertices[ vertexIndex ] ); boneIndices = []; //which bones we need boneIndices[0] = mesh.geometry.skinIndices[vertexIndex].x; boneIndices[1] = mesh.geometry.skinIndices[vertexIndex].y; boneIndices[2] = mesh.geometry.skinIndices[vertexIndex].z; boneIndices[3] = mesh.geometry.skinIndices[vertexIndex].w; weights = []; //some bones impact the vertex more than others weights[0] = mesh.geometry.skinWeights[vertexIndex].x; weights[1] = mesh.geometry.skinWeights[vertexIndex].y; weights[2] = mesh.geometry.skinWeights[vertexIndex].z; weights[3] = mesh.geometry.skinWeights[vertexIndex].w; inverses = []; //boneInverses are the transform from bind-pose to some "bone space" inverses[0] = mesh.skeleton.boneInverses[ boneIndices[0] ]; inverses[1] = mesh.skeleton.boneInverses[ boneIndices[1] ]; inverses[2] = mesh.skeleton.boneInverses[ boneIndices[2] ]; inverses[3] = mesh.skeleton.boneInverses[ boneIndices[3] ]; skinMatrices = []; //each bone matrix world is the transform from "bone space" to the "global space" skinMatrices[0] = mesh.skeleton.bones[ boneIndices[0] ].matrixWorld; skinMatrices[1] = mesh.skeleton.bones[ boneIndices[1] ].matrixWorld; skinMatrices[2] = mesh.skeleton.bones[ boneIndices[2] ].matrixWorld; skinMatrices[3] = mesh.skeleton.bones[ boneIndices[3] ].matrixWorld; var finalVector = new THREE.Vector4(); for(var k = 0; k<4; k++) { var tempVector = new THREE.Vector4(vector.x, vector.y, vector.z); //weight the transformation tempVector.multiplyScalar(weights[k]); //the inverse takes the vector into local bone space tempVector.applyMatrix4(inverses[k]) //which is then transformed to the appropriate world space .applyMatrix4(skinMatrices[k]); finalVector.add(tempVector); } output += '\t\t\tvertex ' + finalVector.x + ' ' + finalVector.y + ' ' + finalVector.z + '\n'; 

This gives STL files that look like this:

enter image description here

The full code is available at https://gist.github.com/kjlubick/fb6ba9c51df63ba0951f

+7
source

After a week of stretching my hair, I managed to change the code to include morphTarget data in the last stl file. you can find the modified code to change Kevin at https://gist.github.com/jcarletto27/e271bbb7639c4bed2427

Since JS is not my favorite language, it is not very, but it manages to work without any problems. Hope someone comes in handy from this other than me!

+3
source

Source: https://habr.com/ru/post/1210157/


All Articles