如何将Three.js场景中的几何体导出为已修改的OBJ?

时间:2022-04-03 05:30:50

Every time I export and save the model (SkinnedMesh) from my Three.js scene the original imported model is saved. This happens even though I modify the model by rotating a bone and changing the value of a morph target.

每次从Three.js场景导出并保存模型(SkinnedMesh)时,都会保存原始导入的模型。即使我通过旋转骨骼并更改变形目标的值来修改模型,也会发生这种情况。

I've checked for changes to the geometry's data in the console window and it shows that the bone and morph target information has been updated. But for some reason when I export and save, the updated model is not saved.

我已在控制台窗口中检查了几何体数据的更改,并显示骨骼和变形目标信息已更新。但出于某种原因,当我导出和保存时,不会保存更新的模型。

Here is my render() function where the model is exported and saved as an OBJ.

这是我的render()函数,其中模型被导出并保存为OBJ。

function render() {

    cube.rotation.x += guiControls.rotationX;
    cube.rotation.y += guiControls.rotationY;
    cube.rotation.z += guiControls.rotationZ;

    spotLight.position.x = guiControls.lightX;
    spotLight.position.y = guiControls.lightY;
    spotLight.position.z = guiControls.lightZ;

    camera.lookAt(lookAtPos);

        scene.traverse(function(child){
        if (child instanceof THREE.SkinnedMesh){  

            child.skeleton.bones[13].rotation.y = guiControls.Shoulder;
            child.scale.x = guiControls.ScaleX;
            child.scale.y = guiControls.ScaleY;
            child.scale.z = guiControls.ScaleZ;
            child.position.x = guiControls.PositionX;
            child.position.y = guiControls.PositionY;
            child.position.z = guiControls.PositionZ;

            child.geometry.dynamic = true;
            child.geometry.verticesNeedUpdate = true;
            child.geometry.elementsNeedUpdate = true;
            child.updateProjectionMatrix = true;

            if(save){
              var exporter = new THREE.OBJExporter();
              var result = exporter.parse(child);

              var saveData = (function () {
                var a = document.createElement("a");
                document.body.appendChild(a);
                a.style = "display: none";
                return function (data, fileName) {
                      var obj = data,
                      blob = new Blob([obj], {type: "octet/stream"}),
                      url = window.URL.createObjectURL(blob);
                  a.href = url;
                  a.download = fileName;
                  a.click();
                  window.URL.revokeObjectURL(url);
                };
              }());

              saveData(result, "ModelOBJExport.obj");

              save = false;
            }

        }
        else if  (child instanceof THREE.SkeletonHelper){
            child.update();
        }
    });

} 

Here is a JSFiddle containing all of my code - https://jsfiddle.net/markskelton/ord9gL1a/. I was unsure of how to upload my model so that people could use that with my code.

这是一个包含我所有代码的JSFiddle - https://jsfiddle.net/markskelton/ord9gL1a/。我不确定如何上传我的模型,以便人们可以使用我的代码。

1 个解决方案

#1


0  

I do not know if some of this is redundant in your case But this is in my save process. After setting the size, position and rotation, try:

我不知道你的情况中是否有一些是多余的但是这是在我的保存过程中。设置大小,位置和旋转后,请尝试:

    child.updateMatrix();
    child.geometry.applyMatrix(child.matrix);
    child.matrixAutoUpdate = true;
    //reset the matrix to identity if you want to be double sure the matrix is now actually ready for export.
    child.matrix.identity();

For some reason this isn't working for people. I am adding the function I run in its entirety, comments and all. I cannot say why other people cannot get this to work. This works fine for me. I would suggest if people are having issues, to show the code and example problem in a new question.

出于某种原因,这对人们不起作用。我正在添加我完整运行的功能,评论和所有。我不能说为什么其他人不能让这个工作。这对我来说很好。我会建议人们是否有问题,在新问题中显示代码和示例问题。

objSaver.prototype.modifyMeshToRhinoObj = function (mesh) {
        var exporter = new THREE.OBJExporter();
        //we do no save the original extrusion geometry. We clone it, match it's axis and scale to external settings, usually found in Rhino (non adjusted obj up), and save the clone.
        //This is so on re-import it is treated as if it came from any mesh tool.
        var polygonGeometry = new THREE.Geometry().fromBufferGeometry(mesh.geometry._bufferGeometry);
        var volumeClone = new THREE.Mesh(polygonGeometry, [
                new THREE.MeshBasicMaterial({ color: 16711680 }),
                new THREE.MeshBasicMaterial({ color: 16711680 })
        ]);
        volumeClone.scale.set(1, 1, mesh.scale.z);
        volumeClone.rotation.x = de2ra(180);
        volumeClone.rotation.z = de2ra(-90);
        volumeClone.updateMatrix();
        volumeClone.geometry.applyMatrix(volumeClone.matrix);
        volumeClone.matrixAutoUpdate = true;
        volumeClone.matrix.identity();
        volumeClone.geometry.verticesNeedUpdate = true;
        mesh.userData.cloned = true;
        mesh.userData.baseline = mesh.userData.buildingHeight;
        return exporter.parse(volumeClone);
};

#1


0  

I do not know if some of this is redundant in your case But this is in my save process. After setting the size, position and rotation, try:

我不知道你的情况中是否有一些是多余的但是这是在我的保存过程中。设置大小,位置和旋转后,请尝试:

    child.updateMatrix();
    child.geometry.applyMatrix(child.matrix);
    child.matrixAutoUpdate = true;
    //reset the matrix to identity if you want to be double sure the matrix is now actually ready for export.
    child.matrix.identity();

For some reason this isn't working for people. I am adding the function I run in its entirety, comments and all. I cannot say why other people cannot get this to work. This works fine for me. I would suggest if people are having issues, to show the code and example problem in a new question.

出于某种原因,这对人们不起作用。我正在添加我完整运行的功能,评论和所有。我不能说为什么其他人不能让这个工作。这对我来说很好。我会建议人们是否有问题,在新问题中显示代码和示例问题。

objSaver.prototype.modifyMeshToRhinoObj = function (mesh) {
        var exporter = new THREE.OBJExporter();
        //we do no save the original extrusion geometry. We clone it, match it's axis and scale to external settings, usually found in Rhino (non adjusted obj up), and save the clone.
        //This is so on re-import it is treated as if it came from any mesh tool.
        var polygonGeometry = new THREE.Geometry().fromBufferGeometry(mesh.geometry._bufferGeometry);
        var volumeClone = new THREE.Mesh(polygonGeometry, [
                new THREE.MeshBasicMaterial({ color: 16711680 }),
                new THREE.MeshBasicMaterial({ color: 16711680 })
        ]);
        volumeClone.scale.set(1, 1, mesh.scale.z);
        volumeClone.rotation.x = de2ra(180);
        volumeClone.rotation.z = de2ra(-90);
        volumeClone.updateMatrix();
        volumeClone.geometry.applyMatrix(volumeClone.matrix);
        volumeClone.matrixAutoUpdate = true;
        volumeClone.matrix.identity();
        volumeClone.geometry.verticesNeedUpdate = true;
        mesh.userData.cloned = true;
        mesh.userData.baseline = mesh.userData.buildingHeight;
        return exporter.parse(volumeClone);
};