我想在 Node.js 服务器上获取 GLB 文件并使用 draco3d 库对其进行压缩

问题描述 投票:0回答:1

我想在 Node.js 服务器上获取 GLB 文件并使用 draco3d 库对其进行压缩 https://www.npmjs.com/package/draco3d

同时,在console.log("inputGeometry =", inputGeometry); 我得到大约以下数据:

inputGeometry = Uint8Array(23606456) [
  103, 108,  84,  70,   2,   0,   0,   0, 184,  52, 104,   1,
   60,  39,   1,   0,  74,  83,  79,  78, 123,  34,  97,  99,
   99, 101, 115, 115, 111, 114, 115,  34,  58,  91, 123,  34,
   98, 117, 102, 102, 101, 114,  86, 105, 101, 119,  34,  58,
   50,  44,  34,  99, 111, 109, 112, 111, 110, 101, 110, 116,
   84, 121, 112, 101,  34,  58,  53,  49,  50,  54,  44,  34,
   99, 111, 117, 110, 116,  34,  58,  52,  51,  53,  54,  44,
   34, 109,  97, 120,  34,  58,  91,  50,  54,  48,  46,  48,
   44,  49,  56,  50,
  ... 23606356 more items
]

这里console.log("encodedData = ",encodedData); 我得到这样的数据: 编码数据 = 0

最后我得到了错误:

节点:缓冲区:328 抛出新的 ERR_INVALID_ARG_TYPE( ^

TypeError [ERR_INVALID_ARG_TYPE]:第一个参数必须是字符串类型或者 Buffer、ArrayBuffer、Array 或类数组对象的实例。收到的类型号 (0) 在新的 NodeError 处(节点:内部/错误:393:5) 在 Function.from (节点:缓冲区:328:9) 在/Users/mac/Documents/_Models3d/server3d__2/server3d__2/controllers/rackTypeController.js:627:58 在 FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) { 代码:'ERR_INVALID_ARG_TYPE' }

如何获取encodedData中的Draco模型?需要将哪些数据传递给 EncodeMeshToDracoBuffer?

提前非常感谢您!

以下代码:

          user = req.user.id;

          const filePath = "user" + user + "/model" + id;
          const filePathStatic = "static/" + filePath;

          if (req.files) {
            const { imgs } = req.files;
            const { glb } = req.files;

            if (glb) {
              const fileName = `model.glb`;
              const fileNameDraco = `model.drc`;

              try {
                const dirpath = path.resolve(__dirname, "..", filePathStatic);

                const pathGLB = path.resolve(dirpath, fileName);
                const pathDRC = path.resolve(dirpath, fileNameDraco);

                fs.mkdirSync(dirpath, { recursive: true });
                glb.mv(pathGLB);

                // model3d = filePath + "/" + fileName;
                model3d = filePath + "/" + fileNameDraco;

                /*********** DRACO ************** */
                const dracoEncoderModule = draco3d.createEncoderModule({});

                dracoEncoderModule
                  .then((module) => {
                    const encoder = new module.Encoder();

                    fs.readFile(pathGLB, (err, data) => {
                      if (err) {
                        console.log("ERROR ", err);
                      } else {
                        const inputBuffer = data;

                        const inputGeometry = new Uint8Array(inputBuffer);

            console.log('inputGeometry = inputGeometry')

                        const encodedData =
                          encoder.EncodeMeshToDracoBuffer(inputGeometry);

            console.log('encodedData = encodedData')

                        fs.writeFileSync(pathDRC, Buffer.from(encodedData));
                      }
                    });
                  })
                  .catch((error) => {
                    console.error("Error dracoEncoder:", error);
                  });

                /************************* */
              } catch (e) {
                console.error("upload glb ERROR", e);
              }
            }
          }

最终,我想实现这个场景: 用户上传模型 在服务器上该模型被压缩 其他用户会看到一个已经压缩的模型,加载速度更快

node.js 3d geometry
1个回答
0
投票

draco3d
包可以理解低级顶点数据,但不能理解像glTF这样的复杂文件格式。在上面的代码片段中,您似乎假设整个 GLB 的内容相当于一个“网格”,而实际上它可能是一个包含许多网格和材质的完整场景。

处理整个场景(或者更确切地说,其中的每个网格)的一种方法是结合使用 draco3d 和 glTF Transform:

import { NodeIO } from '@gltf-transform/core';
import { KHRONOS_EXTENSIONS } from '@gltf-transform/extensions';
import { draco } from '@gltf-transform/functions';
import draco3d from 'draco3d';

// Configure I/O.
const io = new NodeIO()
  .registerExtensions([KHRDracoMeshCompression])
  .registerDependencies({
    'draco3d.decoder': await draco3d.createDecoderModule(), // Optional.
    'draco3d.encoder': await draco3d.createEncoderModule(), // Optional.
  });

// Read original file.
const document = await io.read('uncompressed.glb');

// Configure compression.
await document.transform(draco({method: 'edgebreaker'}));

// Write compressed file.
await io.write('compressed.glb', document);
© www.soinside.com 2019 - 2024. All rights reserved.