4
votes

I attempted to use the following code I found on Stack Overflow to export an OBJ from geometry in a Three.js scene. The geometry is being displaced by a GLSL shader so the displacement of vertices doesn't seem to export with the geometry. When I import the OBJ into Blender I only get the flat plane that is not displaced. You can inspect a working version of the displacement at http://kineticvideo.co

How do I export an OBJ while using a GLSL shader to displace the geometry? Please help. I was under the impression the displacement of the vertices would actually be updated in the Three.js geometry in real time, but instead it seems like even though I set geometry.verticesNeedUpdate = true; the displacement is actually happening in the mesh and not the geometry.

If so, how do I export an OBJ using from the mesh and not the geometry?

A code snippet from the Three.js that declares the geometry and vertex shader:

videoMaterial = new THREE.ShaderMaterial( {
    uniforms: {
        "tDiffuse": { type: "t", value: texture },
        "multiplier":  { type: "f", value: 66.6 },
        "displace":  { type: "f", value: 33.3 },
        "opacity":  { type: "f", value: 1.0 },
        "originX":  { type: "f", value: 0.0 },
        "originY":  { type: "f", value: 0.0 },
        "originZ":  { type: "f", value: -2000.0 }
    },

    vertexShader: RuttEtraShader.vertexShader,
    fragmentShader: RuttEtraShader.fragmentShader,
    depthWrite: true,
    depthTest: true,
    wireframe: false, 
    transparent: true,
    overdraw: false

});
videoMaterial.renderToScreen = true;
videoMaterial.wireframe = true;
geometry = new THREE.PlaneGeometry(720, 360, 720, 360);
geometry.overdraw = false;
geometry.dynamic = true;
geometry.verticesNeedUpdate = true;

mesh = new THREE.Mesh( geometry, videoMaterial );

This is the function I used which does export the geometry, but not the displacement:

THREE.saveGeometryToObj = function (geometry) {
var s = '';
for (i = 0; i < geometry.vertices.length; i++) {
    s+= 'v '+(geometry.vertices[i].x) + ' ' +
    geometry.vertices[i].y + ' '+
    geometry.vertices[i].z + '\n';
}

for (i = 0; i < geometry.faces.length; i++) {

    s+= 'f '+ (geometry.faces[i].a+1) + ' ' +
    (geometry.faces[i].b+1) + ' '+
    (geometry.faces[i].c+1);

    if (geometry.faces[i].d !== undefined) {
        s+= ' '+ (geometry.faces[i].d+1);
    }
    s+= '\n';
}

return s;
console.log(s);
}
2
geometry.verticesNeedUpdate = true causes new vertex positions to be sent to the GPU, not to the CPU. The displacement is occurring on the GPU only. You will have to replicate the same displacement logic in your export function.WestLangley

2 Answers

2
votes

My mistake was googling this, rather than running a grep in the Three.js repo. There all sorts of functions in there to use, two of them being THREE.STLExporter and THREE.OBJExporter.

THREE.STLExporter seems to be the more robust of the two, allowing you to traverse a scene and export meshes in the scene. You can also export a singular mesh. While I don't get an OBJ, a STL is fine for my purposes.

var exportSTL = new THREE.STLExporter;
exportSTL.exportMesh(mesh);

But this only partially answers the the original question, because well the displaced mesh still doesn't export. All I get is the original plane.

2
votes

You need to modify those vertices the same way you do in your vertex shader. This may be tricky as you need to track down which attributes are attached to the vert, but basically you apply the same math from the shader.