Przeglądaj źródła

Merge pull request #10879 from edsilv/draco

Draco
Mr.doob 8 lat temu
rodzic
commit
b9b1a5349b

+ 277 - 0
examples/js/loaders/DRACOLoader.js

@@ -0,0 +1,277 @@
+// 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.
+//
+'use strict';
+
+THREE.DRACOLoader = function(manager) {
+    this.manager = (manager !== undefined) ? manager :
+        THREE.DefaultLoadingManager;
+    this.materials = null;
+    this.verbosity = 0;
+};
+
+
+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;
+    },
+
+    setVerbosity: function(level) {
+        this.verbosity = level;
+    },
+
+    decodeDracoFile: ( function() {
+        let dracoDecoder;
+
+        if (typeof DracoModule === 'function') {
+          dracoDecoder = DracoModule();
+        } else {
+          console.error('THREE.DRACOLoader: DracoModule not found.');
+          return;
+        }
+
+        return function(rawBuffer) {
+          const scope = this;
+          /*
+           * Here is how to use Draco Javascript decoder and get the geometry.
+           */
+          const buffer = new dracoDecoder.DecoderBuffer();
+          buffer.Init(new Int8Array(rawBuffer), rawBuffer.byteLength);
+          const wrapper = new dracoDecoder.WebIDLWrapper();
+
+          /*
+           * Determine what type is this file: mesh or point cloud.
+           */
+          const geometryType = wrapper.GetEncodedGeometryType(buffer);
+          if (geometryType == dracoDecoder.TRIANGULAR_MESH) {
+            if (this.verbosity > 0) {
+              console.log('Loaded a mesh.');
+            }
+          } else if (geometryType == dracoDecoder.POINT_CLOUD) {
+            if (this.verbosity > 0) {
+              console.log('Loaded a point cloud.');
+            }
+          } else {
+            const errorMsg = 'THREE.DRACOLoader: Unknown geometry type.'
+            console.error(errorMsg);
+            throw new Error(errorMsg);
+          }
+          return scope.convertDracoGeometryTo3JS(wrapper, geometryType, buffer,
+                                                 dracoDecoder);
+        }
+    } )(),
+
+    convertDracoGeometryTo3JS: function(wrapper, geometryType, buffer,
+                                        dracoDecoder) {
+        let dracoGeometry;
+        const start_time = performance.now();
+        if (geometryType == dracoDecoder.TRIANGULAR_MESH) {
+          dracoGeometry = wrapper.DecodeMeshFromBuffer(buffer);
+        } else {
+          dracoGeometry = wrapper.DecodePointCloudFromBuffer(buffer);
+        }
+        const decode_end = performance.now();
+        dracoDecoder.destroy(buffer);
+        /*
+         * Example on how to retrieve mesh and attributes.
+         */
+        let numFaces, numPoints;
+        let numVertexCoordinates, numTextureCoordinates, numAttributes;
+        // For output basic geometry information.
+        let geometryInfoStr;
+        if (geometryType == dracoDecoder.TRIANGULAR_MESH) {
+          numFaces = dracoGeometry.num_faces();
+          if (this.verbosity > 0) {
+            console.log('Number of faces loaded: ' + numFaces.toString());
+          }
+        } else {
+          numFaces = 0;
+        }
+        numPoints = dracoGeometry.num_points();
+        numVertexCoordinates = numPoints * 3;
+        numTextureCoordinates = numPoints * 2;
+        numAttributes = dracoGeometry.num_attributes();
+        if (this.verbosity > 0) {
+          console.log('Number of points loaded: ' + numPoints.toString());
+          console.log('Number of attributes loaded: ' +
+              numAttributes.toString());
+        }
+
+        // Get position attribute. Must exists.
+        const posAttId = wrapper.GetAttributeId(dracoGeometry,
+                                                dracoDecoder.POSITION);
+        if (posAttId == -1) {
+          const errorMsg = 'THREE.DRACOLoader: No position attribute found.';
+          console.error(errorMsg);
+          dracoDecoder.destroy(wrapper);
+          dracoDecoder.destroy(dracoGeometry);
+          throw new Error(errorMsg);
+        }
+        const posAttribute = wrapper.GetAttribute(dracoGeometry, posAttId);
+        const posAttributeData = new dracoDecoder.DracoFloat32Array();
+        wrapper.GetAttributeFloatForAllPoints(
+            dracoGeometry, posAttribute, posAttributeData);
+        // Get color attributes if exists.
+        const colorAttId = wrapper.GetAttributeId(dracoGeometry,
+                                                  dracoDecoder.COLOR);
+        let colAttributeData;
+        if (colorAttId != -1) {
+          if (this.verbosity > 0) {
+            console.log('Loaded color attribute.');
+          }
+          const colAttribute = wrapper.GetAttribute(dracoGeometry, colorAttId);
+          colAttributeData = new dracoDecoder.DracoFloat32Array();
+          wrapper.GetAttributeFloatForAllPoints(dracoGeometry, colAttribute,
+                                                colAttributeData);
+        }
+
+        // Get normal attributes if exists.
+        const normalAttId =
+            wrapper.GetAttributeId(dracoGeometry, dracoDecoder.NORMAL);
+        let norAttributeData;
+        if (normalAttId != -1) {
+          if (this.verbosity > 0) {
+            console.log('Loaded normal attribute.');
+          }
+          const norAttribute = wrapper.GetAttribute(dracoGeometry, normalAttId);
+          norAttributeData = new dracoDecoder.DracoFloat32Array();
+          wrapper.GetAttributeFloatForAllPoints(dracoGeometry, norAttribute,
+                                                norAttributeData);
+        }
+
+        // Get texture coord attributes if exists.
+        const texCoordAttId =
+            wrapper.GetAttributeId(dracoGeometry, dracoDecoder.TEX_COORD);
+        let textCoordAttributeData;
+        if (texCoordAttId != -1) {
+          if (this.verbosity > 0) {
+            console.log('Loaded texture coordinate attribute.');
+          }
+          const texCoordAttribute = wrapper.GetAttribute(dracoGeometry,
+                                                         texCoordAttId);
+          textCoordAttributeData = new dracoDecoder.DracoFloat32Array();
+          wrapper.GetAttributeFloatForAllPoints(dracoGeometry,
+                                                texCoordAttribute,
+                                                textCoordAttributeData);
+        }
+
+        // Structure for converting to THREEJS geometry later.
+        const numIndices = numFaces * 3;
+        const geometryBuffer = {
+            indices: new Uint32Array(numIndices),
+            vertices: new Float32Array(numVertexCoordinates),
+            normals: new Float32Array(numVertexCoordinates),
+            uvs: new Float32Array(numTextureCoordinates),
+            colors: new Float32Array(numVertexCoordinates)
+        };
+
+        for (let i = 0; i < numVertexCoordinates; i += 3) {
+            geometryBuffer.vertices[i] = posAttributeData.GetValue(i);
+            geometryBuffer.vertices[i + 1] = posAttributeData.GetValue(i + 1);
+            geometryBuffer.vertices[i + 2] = posAttributeData.GetValue(i + 2);
+            // Add color.
+            // ThreeJS vertex colors need to be normalized to properly display
+            if (colorAttId != -1) {
+              geometryBuffer.colors[i] = colAttributeData.GetValue(i) / 255;
+              geometryBuffer.colors[i + 1] =
+                  colAttributeData.GetValue(i + 1) / 255;
+              geometryBuffer.colors[i + 2] =
+                  colAttributeData.GetValue(i + 2) / 255;
+            } else {
+              // Default is white. This is faster than TypedArray.fill().
+              geometryBuffer.colors[i] = 1.0;
+              geometryBuffer.colors[i + 1] = 1.0;
+              geometryBuffer.colors[i + 2] = 1.0;
+            }
+            // Add normal.
+            if (normalAttId != -1) {
+              geometryBuffer.normals[i] = norAttributeData.GetValue(i);
+              geometryBuffer.normals[i + 1] = norAttributeData.GetValue(i + 1);
+              geometryBuffer.normals[i + 2] = norAttributeData.GetValue(i + 2);
+            }
+        }
+
+        // Add texture coordinates.
+        if (texCoordAttId != -1) {
+          for (let i = 0; i < numTextureCoordinates; i += 2) {
+            geometryBuffer.uvs[i] = textCoordAttributeData.GetValue(i);
+            geometryBuffer.uvs[i + 1] = textCoordAttributeData.GetValue(i + 1);
+          }
+        }
+
+        dracoDecoder.destroy(posAttributeData);
+        if (colorAttId != -1)
+          dracoDecoder.destroy(colAttributeData);
+        if (normalAttId != -1)
+          dracoDecoder.destroy(norAttributeData);
+        if (texCoordAttId != -1)
+          dracoDecoder.destroy(textCoordAttributeData);
+
+        // For mesh, we need to generate the faces.
+        if (geometryType == dracoDecoder.TRIANGULAR_MESH) {
+          const ia = new dracoDecoder.DracoInt32Array();
+          for (let i = 0; i < numFaces; ++i) {
+            wrapper.GetFaceFromMesh(dracoGeometry, i, ia);
+            const index = i * 3;
+            geometryBuffer.indices[index] = ia.GetValue(0);
+            geometryBuffer.indices[index + 1] = ia.GetValue(1);
+            geometryBuffer.indices[index + 2] = ia.GetValue(2);
+          }
+          dracoDecoder.destroy(ia);
+        }
+        dracoDecoder.destroy(wrapper);
+        dracoDecoder.destroy(dracoGeometry);
+
+        // Import data to Three JS geometry.
+        const geometry = new THREE.BufferGeometry();
+        if (geometryType == dracoDecoder.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));
+        }
+        if (texCoordAttId != -1) {
+          geometry.addAttribute('uv',
+              new THREE.Float32BufferAttribute(geometryBuffer.uvs, 2));
+        }
+        this.decode_time = decode_end - start_time;
+        this.import_time = performance.now() - decode_end;
+
+        if (this.verbosity > 0) {
+          console.log('Decode time: ' + this.decode_time);
+          console.log('Import time: ' + this.import_time);
+        }
+        return geometry;
+    }
+};

Plik diff jest za duży
+ 4 - 0
examples/js/loaders/draco_decoder.js


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików