我想在 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);
}
}
}
最终,我想实现这个场景: 用户上传模型 在服务器上该模型被压缩 其他用户会看到一个已经压缩的模型,加载速度更快
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);