Просмотр исходного кода

Allow Clones to be merged
VertexData.ExtractFrom() is called during the merge process. It calls
the geometry functions getVerticesData() & getIndices(). These just
returned reference variables.

The call argument, copyWhenShared? : boolean, was added to these
functions. It was also added to the VertexData extraction functions,
and those in Mesh as well. When true, a copy is returned.

In Mesh.MergeMeshes this is set to true in the call to Extract. After
the first Mesh, this unfortunately must still be true, since the
positions & normals are also transformed, requiring a private copy.

Mesh.MergeMeshes was also improved, allowing meshes array to contain
null items, which are just skipped. An additional optional argument was
added, the mesh to apply the vertex data. This allows the sub-classes
of BABYLON.Mesh to contain the result of the merge.

jeff Palmer 10 лет назад
Родитель
Сommit
bae7e6950d
3 измененных файлов с 83 добавлено и 48 удалено
  1. 24 4
      Babylon/Mesh/babylon.geometry.ts
  2. 44 29
      Babylon/Mesh/babylon.mesh.ts
  3. 15 15
      Babylon/Mesh/babylon.mesh.vertexData.ts

+ 24 - 4
Babylon/Mesh/babylon.geometry.ts

@@ -147,12 +147,22 @@
             return this._totalVertices;
         }
 
-        public getVerticesData(kind: string): number[] {
+        public getVerticesData(kind: string, copyWhenShared? : boolean): number[] {
             var vertexBuffer = this.getVertexBuffer(kind);
             if (!vertexBuffer) {
                 return null;
             }
-            return vertexBuffer.getData();
+            var orig = vertexBuffer.getData();
+            if (!copyWhenShared || this._meshes.length === 1){
+                return orig;
+            }else{
+                var len = orig.length;
+                var copy = [];
+                for (var i = 0; i < len; i++){
+                    copy.push(orig[i]);
+                }
+                return copy;
+            }
         }
 
         public getVertexBuffer(kind: string): VertexBuffer {
@@ -224,11 +234,21 @@
             return this._indices.length;
         }
 
-        public getIndices(): number[] {
+        public getIndices(copyWhenShared? : boolean): number[] {
             if (!this.isReady()) {
                 return null;
             }
-            return this._indices;
+            var orig = this._indices;
+            if (!copyWhenShared || this._meshes.length === 1){
+                return orig;
+            }else{
+                var len = orig.length;
+                var copy = [];
+                for (var i = 0; i < len; i++){
+                    copy.push(orig[i]);
+                }
+                return copy;
+            }
         }
 
         public getIndexBuffer(): any {

+ 44 - 29
Babylon/Mesh/babylon.mesh.ts

@@ -227,11 +227,11 @@
             return this._geometry.getTotalVertices();
         }
 
-        public getVerticesData(kind: string): number[] {
+        public getVerticesData(kind: string, copyWhenShared? : boolean): number[] {
             if (!this._geometry) {
                 return null;
             }
-            return this._geometry.getVerticesData(kind);
+            return this._geometry.getVerticesData(kind, copyWhenShared);
         }
 
         public getVertexBuffer(kind): VertexBuffer {
@@ -271,11 +271,11 @@
             return this._geometry.getTotalIndices();
         }
 
-        public getIndices(): number[] {
+        public getIndices(copyWhenShared? : boolean): number[] {
             if (!this._geometry) {
                 return [];
             }
-            return this._geometry.getIndices();
+            return this._geometry.getIndices(copyWhenShared);
         }
 
         public get isBlocked(): boolean {
@@ -875,7 +875,6 @@
             }
 
             data = this.getVerticesData(VertexBuffer.NormalKind);
-            temp = [];
             for (index = 0; index < data.length; index += 3) {
                 Vector3.TransformNormal(Vector3.FromArray(data, index), transform).toArray(temp, index);
             }
@@ -1739,52 +1738,68 @@
             return Vector3.Center(minMaxVector.min, minMaxVector.max);
         }
 
-        public static MergeMeshes(meshes: Array<Mesh>, disposeSource = true, allow32BitsIndices?: boolean): Mesh {
-            var source = meshes[0];
-            var material = source.material;
-            var scene = source.getScene();
-
+        /**
+         * Merge the array of meshes into a single mesh for performance reasons.
+         * @param {Array<Mesh>} meshes - The vertices source.  They should all be of the same material.  Entries can empty
+         * @param {boolean} disposeSource - When true (default), dispose of the vertices from the source meshes
+         * @param {boolean} allow32BitsIndices - When the sum of the vertices > 64k, this must be set to true.
+         * @param {Mesh} meshSubclass - When set, vertices inserted into this Mesh.  Meshes can then be merged into a Mesh sub-class.
+         */
+        public static MergeMeshes(meshes: Array<Mesh>, disposeSource = true, allow32BitsIndices?: boolean, meshSubclass?: Mesh): Mesh {
             if (!allow32BitsIndices) {
                 var totalVertices = 0;
 
                 // Counting vertices
                 for (var index = 0; index < meshes.length; index++) {
-                    totalVertices += meshes[index].getTotalVertices();
+                    if (meshes[index]){
+                        totalVertices += meshes[index].getTotalVertices();
 
-                    if (totalVertices > 65536) {
-                        Tools.Warn("Cannot merge meshes because resulting mesh will have more than 65536 vertices. Please use allow32BitsIndices = true to use 32 bits indices");
-                        return null;
+                        if (totalVertices > 65536) {
+                            Tools.Warn("Cannot merge meshes because resulting mesh will have more than 65536 vertices. Please use allow32BitsIndices = true to use 32 bits indices");
+                            return null;
+                        }
                     }
                 }
             }
 
             // Merge
-            var vertexData = VertexData.ExtractFromMesh(source);
-            vertexData.transform(source.getWorldMatrix());
-
-            for (index = 1; index < meshes.length; index++) {
-                var otherVertexData = VertexData.ExtractFromMesh(meshes[index]);
-                otherVertexData.transform(meshes[index].getWorldMatrix());
-
-                vertexData.merge(otherVertexData);
+            var vertexData      : VertexData;
+            var otherVertexData : VertexData;
+
+            var source : Mesh;
+            for (index = 0; index < meshes.length; index++) {
+                if (meshes[index]){
+                    otherVertexData = VertexData.ExtractFromMesh(meshes[index], true);
+                    otherVertexData.transform(meshes[index].getWorldMatrix());
+                
+                    if (vertexData){
+                        vertexData.merge(otherVertexData);
+                    }else{
+                        vertexData = otherVertexData;
+                        source = meshes[index];
+                    }
+                }
             }
 
-            var newMesh = new Mesh(source.name + "_merged", scene);
-
-            vertexData.applyToMesh(newMesh);
+            if (!meshSubclass){
+                meshSubclass = new Mesh(source.name + "_merged", source.getScene());
+            }
+            vertexData.applyToMesh(meshSubclass);
 
             // Setting properties
-            newMesh.material = material;
-            newMesh.checkCollisions = source.checkCollisions;
+            meshSubclass.material = source.material;
+            meshSubclass.checkCollisions = source.checkCollisions;
 
             // Cleaning
             if (disposeSource) {
                 for (index = 0; index < meshes.length; index++) {
-                    meshes[index].dispose();
+                    if (meshes[index]){
+                        meshes[index].dispose();
+                    }
                 }
             }
 
-            return newMesh;
+            return meshSubclass;
         }
     }
 } 

+ 15 - 15
Babylon/Mesh/babylon.mesh.vertexData.ts

@@ -1,8 +1,8 @@
 module BABYLON {
     export interface IGetSetVerticesData {
         isVerticesDataPresent(kind: string): boolean;
-        getVerticesData(kind: string): number[];
-        getIndices(): number[];
+        getVerticesData(kind: string, copyWhenShared? : boolean): number[];
+        getIndices(copyWhenShared? : boolean): number[];
         setVerticesData(kind: string, data: number[], updatable?: boolean): void;
         updateVerticesData(kind: string, data: number[], updateExtends?: boolean, makeItUnique?: boolean): void;
         setIndices(indices: number[]): void;
@@ -236,46 +236,46 @@
         }
 
         // Statics
-        public static ExtractFromMesh(mesh: Mesh): VertexData {
-            return VertexData._ExtractFrom(mesh);
+        public static ExtractFromMesh(mesh: Mesh, copyWhenShared? : boolean): VertexData {
+            return VertexData._ExtractFrom(mesh, copyWhenShared);
         }
 
-        public static ExtractFromGeometry(geometry: Geometry): VertexData {
-            return VertexData._ExtractFrom(geometry);
+        public static ExtractFromGeometry(geometry: Geometry, copyWhenShared? : boolean): VertexData {
+            return VertexData._ExtractFrom(geometry, copyWhenShared);
         }
 
-        private static _ExtractFrom(meshOrGeometry: IGetSetVerticesData): VertexData {
+        private static _ExtractFrom(meshOrGeometry: IGetSetVerticesData, copyWhenShared? : boolean): VertexData {
             var result = new VertexData();
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.PositionKind)) {
-                result.positions = meshOrGeometry.getVerticesData(VertexBuffer.PositionKind);
+                result.positions = meshOrGeometry.getVerticesData(VertexBuffer.PositionKind, copyWhenShared);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.NormalKind)) {
-                result.normals = meshOrGeometry.getVerticesData(VertexBuffer.NormalKind);
+                result.normals = meshOrGeometry.getVerticesData(VertexBuffer.NormalKind, copyWhenShared);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UVKind)) {
-                result.uvs = meshOrGeometry.getVerticesData(VertexBuffer.UVKind);
+                result.uvs = meshOrGeometry.getVerticesData(VertexBuffer.UVKind, copyWhenShared);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
-                result.uv2s = meshOrGeometry.getVerticesData(VertexBuffer.UV2Kind);
+                result.uv2s = meshOrGeometry.getVerticesData(VertexBuffer.UV2Kind, copyWhenShared);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.ColorKind)) {
-                result.colors = meshOrGeometry.getVerticesData(VertexBuffer.ColorKind);
+                result.colors = meshOrGeometry.getVerticesData(VertexBuffer.ColorKind, copyWhenShared);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind)) {
-                result.matricesIndices = meshOrGeometry.getVerticesData(VertexBuffer.MatricesIndicesKind);
+                result.matricesIndices = meshOrGeometry.getVerticesData(VertexBuffer.MatricesIndicesKind, copyWhenShared);
             }
 
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind)) {
-                result.matricesWeights = meshOrGeometry.getVerticesData(VertexBuffer.MatricesWeightsKind);
+                result.matricesWeights = meshOrGeometry.getVerticesData(VertexBuffer.MatricesWeightsKind, copyWhenShared);
             }
 
-            result.indices = meshOrGeometry.getIndices();
+            result.indices = meshOrGeometry.getIndices(copyWhenShared);
 
             return result;
         }