【问题标题】:Merging Multiple GLTF having some common nodes using gltf-transform使用 gltf-transform 合并具有一些公共节点的多个 GLTF
【发布时间】:2021-09-06 22:23:58
【问题描述】:

此问题是Multiple GLTF loading and Merging on server side 的扩展。

我正在尝试合并多个具有一些公共节点的 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);

我的问题是 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);
  }
}

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

谢谢!

【问题讨论】:

    标签: gltf


    【解决方案1】:

    您在上面看到的错误是因为代码试图移动单个资源——例如Nodes — 从一个 glTF Document 到另一个。这是不可能的,每个 Document 都在内部管理其资源图,但等效的工作流程是:

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

    【讨论】:

    • 是的,之前我已经将其他场景的子场景添加到 mainScene 中,但它给了我重复的节点。作为一个骇人听闻的解决方法,我保留了 的地图,以保持给定名称的每个节点的第一次出现,并将皮肤中的所有骨架和关节节点替换为第一次出现的节点。同时,我将继续处理您的建议,并尽量避免添加重复节点。谢谢:-)
    猜你喜欢
    • 2021-06-19
    • 2021-12-24
    • 2021-11-08
    • 2021-12-27
    • 2021-09-02
    • 2018-12-17
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多