1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | 'use_strict';
|
16 |
|
17 | const fs = require('fs');
|
18 | const assert = require('assert');
|
19 | const draco3d = require('draco3d');
|
20 | const decoderModule = draco3d.createDecoderModule({});
|
21 | const encoderModule = draco3d.createEncoderModule({});
|
22 |
|
23 | fs.readFile('./bunny.drc', function(err, data) {
|
24 | if (err) {
|
25 | return console.log(err);
|
26 | }
|
27 | console.log("Decoding file of size " + data.byteLength + " ..");
|
28 |
|
29 | const decoder = new decoderModule.Decoder();
|
30 | const decodedGeometry = decodeDracoData(data, decoder);
|
31 |
|
32 | encodeMeshToFile(decodedGeometry, decoder);
|
33 |
|
34 | decoderModule.destroy(decoder);
|
35 | decoderModule.destroy(decodedGeometry);
|
36 | });
|
37 |
|
38 | function decodeDracoData(rawBuffer, decoder) {
|
39 | const buffer = new decoderModule.DecoderBuffer();
|
40 | buffer.Init(new Int8Array(rawBuffer), rawBuffer.byteLength);
|
41 | const geometryType = decoder.GetEncodedGeometryType(buffer);
|
42 |
|
43 | let dracoGeometry;
|
44 | let status;
|
45 | if (geometryType === decoderModule.TRIANGULAR_MESH) {
|
46 | dracoGeometry = new decoderModule.Mesh();
|
47 | status = decoder.DecodeBufferToMesh(buffer, dracoGeometry);
|
48 | } else if (geometryType === decoderModule.POINT_CLOUD) {
|
49 | dracoGeometry = new decoderModule.PointCloud();
|
50 | status = decoder.DecodeBufferToPointCloud(buffer, dracoGeometry);
|
51 | } else {
|
52 | const errorMsg = 'Error: Unknown geometry type.';
|
53 | console.error(errorMsg);
|
54 | }
|
55 | decoderModule.destroy(buffer);
|
56 |
|
57 | return dracoGeometry;
|
58 | }
|
59 |
|
60 | function encodeMeshToFile(mesh, decoder) {
|
61 | const encoder = new encoderModule.Encoder();
|
62 | const meshBuilder = new encoderModule.MeshBuilder();
|
63 |
|
64 | const newMesh = new encoderModule.Mesh();
|
65 |
|
66 | const numFaces = mesh.num_faces();
|
67 | const numIndices = numFaces * 3;
|
68 | const numPoints = mesh.num_points();
|
69 | const indices = new Uint32Array(numIndices);
|
70 |
|
71 | console.log("Number of faces " + numFaces);
|
72 | console.log("Number of vertices " + numPoints);
|
73 |
|
74 |
|
75 | const ia = new decoderModule.DracoInt32Array();
|
76 | for (let i = 0; i < numFaces; ++i) {
|
77 | decoder.GetFaceFromMesh(mesh, i, ia);
|
78 | const index = i * 3;
|
79 | indices[index] = ia.GetValue(0);
|
80 | indices[index + 1] = ia.GetValue(1);
|
81 | indices[index + 2] = ia.GetValue(2);
|
82 | }
|
83 | decoderModule.destroy(ia);
|
84 | meshBuilder.AddFacesToMesh(newMesh, numFaces, indices);
|
85 |
|
86 | const attrs = {POSITION: 3, NORMAL: 3, COLOR: 3, TEX_COORD: 2};
|
87 |
|
88 | Object.keys(attrs).forEach((attr) => {
|
89 | const stride = attrs[attr];
|
90 | const numValues = numPoints * stride;
|
91 | const decoderAttr = decoderModule[attr];
|
92 | const encoderAttr = encoderModule[attr];
|
93 | const attrId = decoder.GetAttributeId(mesh, decoderAttr);
|
94 |
|
95 | if (attrId < 0) {
|
96 | return;
|
97 | }
|
98 |
|
99 | console.log("Adding %s attribute", attr);
|
100 |
|
101 | const attribute = decoder.GetAttribute(mesh, attrId);
|
102 | const attributeData = new decoderModule.DracoFloat32Array();
|
103 | decoder.GetAttributeFloatForAllPoints(mesh, attribute, attributeData);
|
104 |
|
105 | assert(numValues === attributeData.size(), 'Wrong attribute size.');
|
106 |
|
107 | const attributeDataArray = new Float32Array(numValues);
|
108 | for (let i = 0; i < numValues; ++i) {
|
109 | attributeDataArray[i] = attributeData.GetValue(i);
|
110 | }
|
111 |
|
112 | decoderModule.destroy(attributeData);
|
113 | meshBuilder.AddFloatAttributeToMesh(newMesh, encoderAttr, numPoints,
|
114 | stride, attributeDataArray);
|
115 | });
|
116 |
|
117 | let encodedData = new encoderModule.DracoInt8Array();
|
118 |
|
119 | encoder.SetSpeedOptions(5, 5);
|
120 | encoder.SetAttributeQuantization(encoderModule.POSITION, 10);
|
121 | encoder.SetEncodingMethod(encoderModule.MESH_EDGEBREAKER_ENCODING);
|
122 |
|
123 |
|
124 | console.log("Encoding...");
|
125 | const encodedLen = encoder.EncodeMeshToDracoBuffer(newMesh,
|
126 | encodedData);
|
127 | encoderModule.destroy(newMesh);
|
128 |
|
129 | if (encodedLen > 0) {
|
130 | console.log("Encoded size is " + encodedLen);
|
131 | } else {
|
132 | console.log("Error: Encoding failed.");
|
133 | }
|
134 |
|
135 | const outputBuffer = new ArrayBuffer(encodedLen);
|
136 | const outputData = new Int8Array(outputBuffer);
|
137 | for (let i = 0; i < encodedLen; ++i) {
|
138 | outputData[i] = encodedData.GetValue(i);
|
139 | }
|
140 | encoderModule.destroy(encodedData);
|
141 | encoderModule.destroy(encoder);
|
142 | encoderModule.destroy(meshBuilder);
|
143 |
|
144 |
|
145 | fs.writeFile("bunny_10.drc", Buffer(outputBuffer), "binary", function(err) {
|
146 | if (err) {
|
147 | console.log(err);
|
148 | } else {
|
149 | console.log("The file was saved!");
|
150 | }
|
151 | });
|
152 | }
|
153 |
|