使用 gltf-transform 合并具有一些公共节点的多个 GLTF

Nil*_*ilu 1 webgl gltf

这个问题是服务器端多个GLTF加载和合并的扩展。

我正在尝试合并也具有一些公共节点的多个 GLTF 文件。答案帮助我合并文件,我通过以下代码组合了场景,它完美地呈现

const scenes = root.listScenes()
const scene0 = scenes[0]
root.setDefaultScene(scene0);
if (scenes.length > 1) {
    for (let i = 1; i < scenes.length; i++) {
        let scene = scenes[i];
        let nodes = scene.listChildren()
        for (let j = 0; j < nodes.length; j++) {
            scene0.addChild(nodes[j]);
        }
    }
}

root.listScenes().forEach((b, index) => index > 0 ? b.dispose() : null); 
Run Code Online (Sandbox Code Playgroud)

我的问题是 GLTF 中常见的所有数据都是重复的,当需要更改根骨骼时,这将在动画中产生问题。有没有办法合并以使公共节点不重复?我也在尝试一些自定义合并。

const gltfLoader = () => {
    const document = new Document();
    const root = document.getRoot();
    document.merge(io.read(filePaths[0]));
    let model;
    for (let i = 1; i < filePaths.length; i++) {
        const inDoc = new Document();
        inDoc.merge(io.read(filePaths[i]));
        model = inDoc.getRoot().listScenes()[0];
        model.listChildren().forEach((child) => {
            mergeStructure(root.listScenes()[0], child);
        });
    }

    io.write('output.gltf', document);
}

const mergeStructure = (parent, childToMerge) => {
    let contains = false;
    parent.listChildren().forEach((child) => {
        if (child.t === childToMerge.t && !contains && child.getName() === childToMerge.getName()) {

            childToMerge.listChildren().forEach((subChild) => {
                mergeStructure(child, subChild);
            });
            contains = true;
        }
    });
    if (!contains) {
        console.log("Adding " + childToMerge.getName() + " to  " + parent.getName() + "  as child")
        parent.addChild(childToMerge);
    }
}
Run Code Online (Sandbox Code Playgroud)

但由于 ,此合并不起作用Error: Cannot link disconnected graphs/documents。我是 3D 建模新手。一些方向会很棒。

谢谢!

Don*_*rdy 5

您在上面看到的错误是因为代码尝试将单个资源 \xe2\x80\x94 例如节点\xe2\x80\x94 从一个 glTF文档移动到另一个。这是不可能的,每个文档在内部管理其资源图,但等效的工作流程是:

\n
    \n
  1. 加载 N 个文件并合并为一个文档(包含 N 个场景)。
  2. \n
\n
import { Document, NodeIO } from \'@gltf-transform/core\';\n\nconst io = new NodeIO();\nconst document = new Document();\n\nfor (const path of paths) {\n  document.merge(io.read(path));\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 迭代所有场景,将子级移至某个常见场景:
  2. \n
\n
const root = document.getRoot();\nconst mainScene = root.listScenes()[0];\n\nfor (const scene of root.listScenes()) {\n  if (scene === mainScene) continue;\n\n  for (const child of scene.listChildren()) {\n    // If conditions are met, append child to `mainScene`. \n    // Doing so will automatically detach it from the\n    // previous scene.\n  }\n\n  scene.dispose();\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 清理所有剩余的未合并资源。
  2. \n
\n
import { prune } from \'@gltf-transform/functions\';\n\nawait document.transform(prune());\n
Run Code Online (Sandbox Code Playgroud)\n