UNPKG

5.14 kBJavaScriptView Raw
1// Copyright 2017 The Draco Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15'use_strict';
16
17const fs = require('fs');
18const assert = require('assert');
19const draco3d = require('draco3d');
20const decoderModule = draco3d.createDecoderModule({});
21const encoderModule = draco3d.createEncoderModule({});
22
23fs.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 // Decode mesh
29 const decoder = new decoderModule.Decoder();
30 const decodedGeometry = decodeDracoData(data, decoder);
31 // Encode mesh
32 encodeMeshToFile(decodedGeometry, decoder);
33
34 decoderModule.destroy(decoder);
35 decoderModule.destroy(decodedGeometry);
36});
37
38function 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
60function encodeMeshToFile(mesh, decoder) {
61 const encoder = new encoderModule.Encoder();
62 const meshBuilder = new encoderModule.MeshBuilder();
63 // Create a mesh object for storing mesh data.
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 // Add Faces to mesh
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 // Set encoding options.
119 encoder.SetSpeedOptions(5, 5);
120 encoder.SetAttributeQuantization(encoderModule.POSITION, 10);
121 encoder.SetEncodingMethod(encoderModule.MESH_EDGEBREAKER_ENCODING);
122
123 // Encoding.
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 // Copy encoded data to buffer.
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 // Write to file. You can view the the file using webgl_loader_draco.html
144 // example.
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