瀏覽代碼

added draco loader and decoder

edsilv 8 年之前
父節點
當前提交
7dfdef367c
共有 2 個文件被更改,包括 201 次插入0 次删除
  1. 201 0
      src/loaders/DRACOLoader.js
  2. 0 0
      src/loaders/draco_decoder.js

+ 201 - 0
src/loaders/DRACOLoader.js

@@ -0,0 +1,201 @@
+// Copyright 2016 The Draco Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+THREE.DRACOLoader = function(manager) {
+    this.manager = (manager !== undefined) ? manager :
+        THREE.DefaultLoadingManager;
+    this.materials = null;
+};
+
+
+THREE.DRACOLoader.prototype = {
+
+    constructor: THREE.DRACOLoader,
+
+    load: function(url, onLoad, onProgress, onError) {
+        const scope = this;
+        const loader = new THREE.FileLoader(scope.manager);
+        loader.setPath(this.path);
+        loader.setResponseType('arraybuffer');
+        loader.load(url, function(blob) {
+            onLoad(scope.decodeDracoFile(blob));
+        }, onProgress, onError);
+    },
+
+    setPath: function(value) {
+        this.path = value;
+    },
+
+    decodeDracoFile: function(rawBuffer) {
+        const scope = this;
+        /*
+         * Here is how to use Draco Javascript decoder and get the geometry.
+         */
+        const buffer = new DracoModule.DecoderBuffer();
+        buffer.Init(new Int8Array(rawBuffer), rawBuffer.byteLength);
+        const wrapper = new DracoModule.WebIDLWrapper();
+
+        /*
+         * Determine what type is this file, mesh or point cloud.
+         */
+        const geometryType = wrapper.GetEncodedGeometryType(buffer);
+        if (geometryType == DracoModule.TRIANGULAR_MESH) {
+          fileDisplayArea.innerText = "Loaded a mesh.\n";
+        } else if (geometryType == DracoModule.POINT_CLOUD) {
+          fileDisplayArea.innerText = "Loaded a point cloud.\n";
+        } else {
+          const errorMsg = "Error: Unknown geometry type.";
+          fileDisplayArea.innerText = errorMsg;
+          throw new Error(errorMsg);
+        }
+        return scope.convertDracoGeometryTo3JS(wrapper, geometryType, buffer);
+    },
+
+    convertDracoGeometryTo3JS: function(wrapper, geometryType, buffer) {
+        let dracoGeometry;
+        if (geometryType == DracoModule.TRIANGULAR_MESH) {
+          dracoGeometry = wrapper.DecodeMeshFromBuffer(buffer);
+        } else {
+          dracoGeometry = wrapper.DecodePointCloudFromBuffer(buffer);
+        }
+        DracoModule.destroy(buffer);
+        /*
+         * Example on how to retrieve mesh and attributes.
+         */
+        let numFaces, numPoints, numVertexCoordinates, numAttributes;
+        // For output basic geometry information.
+        let geometryInfoStr;
+        if (geometryType == DracoModule.TRIANGULAR_MESH) {
+          numFaces = dracoGeometry.num_faces();
+          geometryInfoStr += "Number of faces loaded: " + numFaces.toString()
+              + ".\n";
+        } else {
+          numFaces = 0;
+        }
+        numPoints = dracoGeometry.num_points();
+        numVertexCoordinates = numPoints * 3;
+        numAttributes = dracoGeometry.num_attributes();
+        geometryInfoStr = "Number of points loaded: " + numPoints.toString()
+            + ".\n";
+        geometryInfoStr += "Number of attributes loaded: " +
+            numAttributes.toString() + ".\n";
+
+        // Get position attribute. Must exists.
+        const posAttId = wrapper.GetAttributeId(dracoGeometry,
+                                                Module.POSITION);
+        if (posAttId == -1) {
+          const errorMsg = "No position attribute found in the mesh.";
+          fileDisplayArea.innerText = errorMsg;
+          DracoModule.destroy(wrapper);
+          DracoModule.destroy(dracoGeometry);
+          throw new Error(errorMsg);
+        }
+        const posAttribute = wrapper.GetAttribute(dracoGeometry, posAttId);
+        const posAttributeData = new DracoModule.DracoFloat32Array();
+        wrapper.GetAttributeFloatForAllPoints(
+            dracoGeometry, posAttribute, posAttributeData);
+        // Get color attributes if exists.
+        const colorAttId = wrapper.GetAttributeId(dracoGeometry, Module.COLOR);
+        let colAttributeData;
+        if (colorAttId != -1) {
+          geometryInfoStr += "\nLoaded color attribute.\n";
+          const colAttribute = wrapper.GetAttribute(dracoGeometry, colorAttId);
+          colAttributeData = new DracoModule.DracoFloat32Array();
+          wrapper.GetAttributeFloatForAllPoints(dracoGeometry, colAttribute,
+                                                colAttributeData);
+        }
+
+        // Get normal attributes if exists.
+        const normalAttId =
+            wrapper.GetAttributeId(dracoGeometry, Module.NORMAL);
+        let norAttributeData;
+        if (normalAttId != -1) {
+          geometryInfoStr += "\nLoaded normal attribute.\n";
+          const norAttribute = wrapper.GetAttribute(dracoGeometry, normalAttId);
+          norAttributeData = new DracoModule.DracoFloat32Array();
+          wrapper.GetAttributeFloatForAllPoints(dracoGeometry, norAttribute,
+                                                norAttributeData);
+        }
+
+        // Structure for converting to THREEJS geometry later.
+        const geometryBuffer = {
+            indices: [],
+            vertices: [],
+            normals: [],
+            uvs: [],
+            colors: []
+        };
+        for (let i = 0; i < numVertexCoordinates; i += 3) {
+            geometryBuffer.vertices.push(
+                posAttributeData.GetValue(i),
+                posAttributeData.GetValue(i + 1),
+                posAttributeData.GetValue(i + 2));
+            // Add color.
+            if (colorAttId != -1) {
+              geometryBuffer.colors.push(
+                  colAttributeData.GetValue(i),
+                  colAttributeData.GetValue(i + 1),
+                  colAttributeData.GetValue(i + 2));
+            } else {
+              // Default is white.
+              geometryBuffer.colors.push(1.0, 1.0, 1.0);
+            }
+            // Add normal.
+            if (normalAttId != -1) {
+              geometryBuffer.normals.push(
+                  norAttributeData.GetValue(i),
+                  norAttributeData.GetValue(i + 1),
+                  norAttributeData.GetValue(i + 2));
+            }
+        }
+        DracoModule.destroy(posAttributeData);
+        if (colorAttId != -1)
+          DracoModule.destroy(colAttributeData);
+        if (normalAttId != -1)
+          DracoModule.destroy(norAttributeData);
+
+        // For mesh, we need to generate the faces.
+        if (geometryType == DracoModule.TRIANGULAR_MESH) {
+          const numIndices = numFaces * 3;
+          const ia = new DracoInt32Array();
+          for (let i = 0; i < numFaces; ++i) {
+            wrapper.GetFaceFromMesh(dracoGeometry, i, ia);
+            geometryBuffer.indices.push(
+                ia.GetValue(0), ia.GetValue(1), ia.GetValue(2));
+          }
+          DracoModule.destroy(ia);
+        }
+        DracoModule.destroy(wrapper);
+        DracoModule.destroy(dracoGeometry);
+
+        fileDisplayArea.innerText += geometryInfoStr;
+
+        // Import data to Three JS geometry.
+        const geometry = new THREE.BufferGeometry();
+        if (geometryType == DracoModule.TRIANGULAR_MESH) {
+          geometry.setIndex(new(geometryBuffer.indices.length > 65535 ?
+                THREE.Uint32BufferAttribute : THREE.Uint16BufferAttribute)
+              (geometryBuffer.indices, 1));
+        }
+        geometry.addAttribute('position',
+            new THREE.Float32BufferAttribute(geometryBuffer.vertices, 3));
+        geometry.addAttribute('color',
+            new THREE.Float32BufferAttribute(geometryBuffer.colors, 3));
+        if (normalAttId != -1) {
+          geometry.addAttribute('normal',
+              new THREE.Float32BufferAttribute(geometryBuffer.normals, 3));
+        }
+        return geometry;
+    }
+};

文件差異過大導致無法顯示
+ 0 - 0
src/loaders/draco_decoder.js


部分文件因文件數量過多而無法顯示