瀏覽代碼

Merge remote-tracking branch 'remotes/BabylonJS/master' into geometry

Gwenaël Hagenmuller 11 年之前
父節點
當前提交
9bef3f37ff

+ 10 - 8
Babylon/Cameras/babylon.arcRotateCamera.js

@@ -247,10 +247,11 @@ var BABYLON;
             element.addEventListener('mousewheel', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
 
-            var root = window.parent || window;
-            root.addEventListener("keydown", this._onKeyDown, false);
-            root.addEventListener("keyup", this._onKeyUp, false);
-            root.addEventListener("blur", this._onLostFocus, false);
+            BABYLON.Tools.RegisterTopRootEvents([
+                { name: "keydown", handler: this._onKeyDown },
+                { name: "keyup", handler: this._onKeyUp },
+                { name: "blur", handler: this._onLostFocus }
+            ]);
         };
 
         ArcRotateCamera.prototype.detachControl = function (element) {
@@ -268,10 +269,11 @@ var BABYLON;
             element.removeEventListener('mousewheel', this._wheel);
             element.removeEventListener('DOMMouseScroll', this._wheel);
 
-            var root = window.parent || window;
-            root.removeEventListener("keydown", this._onKeyDown);
-            root.removeEventListener("keyup", this._onKeyUp);
-            root.removeEventListener("blur", this._onLostFocus);
+            BABYLON.Tools.UnregisterTopRootEvents([
+                { name: "keydown", handler: this._onKeyDown },
+                { name: "keyup", handler: this._onKeyUp },
+                { name: "blur", handler: this._onLostFocus }
+            ]);
 
             this._MSGestureHandler = null;
             this._attachedElement = null;

+ 10 - 8
Babylon/Cameras/babylon.arcRotateCamera.ts

@@ -263,10 +263,11 @@
             element.addEventListener('mousewheel', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
 
-            var root = window.parent || window;
-            root.addEventListener("keydown", this._onKeyDown, false);
-            root.addEventListener("keyup", this._onKeyUp, false);
-            root.addEventListener("blur", this._onLostFocus, false);
+            Tools.RegisterTopRootEvents([
+                { name: "keydown", handler: this._onKeyDown },
+                { name: "keyup", handler: this._onKeyUp },
+                { name: "blur", handler: this._onLostFocus }
+            ]);
         }
 
         public detachControl(element: HTMLElement): void {
@@ -284,10 +285,11 @@
             element.removeEventListener('mousewheel', this._wheel);
             element.removeEventListener('DOMMouseScroll', this._wheel);
 
-            var root = window.parent || window;
-            root.removeEventListener("keydown", this._onKeyDown);
-            root.removeEventListener("keyup", this._onKeyUp);
-            root.removeEventListener("blur", this._onLostFocus);
+            Tools.UnregisterTopRootEvents([
+                { name: "keydown", handler: this._onKeyDown },
+                { name: "keyup", handler: this._onKeyUp },
+                { name: "blur", handler: this._onLostFocus }
+            ]);
 
             this._MSGestureHandler = null;
             this._attachedElement = null;

+ 10 - 8
Babylon/Cameras/babylon.freeCamera.js

@@ -236,10 +236,11 @@ var BABYLON;
             element.addEventListener("mouseout", this._onMouseOut, false);
             element.addEventListener("mousemove", this._onMouseMove, false);
 
-            var root = window.parent || window;
-            root.addEventListener("keydown", this._onKeyDown, false);
-            root.addEventListener("keyup", this._onKeyUp, false);
-            root.addEventListener("blur", this._onLostFocus, false);
+            BABYLON.Tools.RegisterTopRootEvents([
+                { name: "keydown", handler: this._onKeyDown },
+                { name: "keyup", handler: this._onKeyUp },
+                { name: "blur", handler: this._onLostFocus }
+            ]);
         };
 
         FreeCamera.prototype.detachControl = function (element) {
@@ -252,10 +253,11 @@ var BABYLON;
             element.removeEventListener("mouseout", this._onMouseOut);
             element.removeEventListener("mousemove", this._onMouseMove);
 
-            var root = window.parent || window;
-            root.removeEventListener("keydown", this._onKeyDown);
-            root.removeEventListener("keyup", this._onKeyUp);
-            root.removeEventListener("blur", this._onLostFocus);
+            BABYLON.Tools.UnregisterTopRootEvents([
+                { name: "keydown", handler: this._onKeyDown },
+                { name: "keyup", handler: this._onKeyUp },
+                { name: "blur", handler: this._onLostFocus }
+            ]);
 
             this._attachedElement = null;
             if (this._reset) {

+ 10 - 8
Babylon/Cameras/babylon.freeCamera.ts

@@ -251,10 +251,11 @@
             element.addEventListener("mouseout", this._onMouseOut, false);
             element.addEventListener("mousemove", this._onMouseMove, false);
 
-            var root = window.parent || window;
-            root.addEventListener("keydown", this._onKeyDown, false);
-            root.addEventListener("keyup", this._onKeyUp, false);
-            root.addEventListener("blur", this._onLostFocus, false);
+            Tools.RegisterTopRootEvents([
+                { name: "keydown", handler: this._onKeyDown },
+                { name: "keyup", handler: this._onKeyUp },
+                { name: "blur", handler: this._onLostFocus }
+            ]);
         }
 
         public detachControl(element: HTMLElement): void {
@@ -267,10 +268,11 @@
             element.removeEventListener("mouseout", this._onMouseOut);
             element.removeEventListener("mousemove", this._onMouseMove);
 
-            var root = window.parent || window;
-            root.removeEventListener("keydown", this._onKeyDown);
-            root.removeEventListener("keyup", this._onKeyUp);
-            root.removeEventListener("blur", this._onLostFocus);
+            Tools.UnregisterTopRootEvents([
+                { name: "keydown", handler: this._onKeyDown },
+                { name: "keyup", handler: this._onKeyUp },
+                { name: "blur", handler: this._onLostFocus }
+            ]);
 
             this._attachedElement = null;
             if (this._reset) {

+ 6 - 4
Babylon/Cameras/babylon.touchCamera.js

@@ -99,8 +99,9 @@ var BABYLON = BABYLON || {};
         canvas.addEventListener("pointerout", this._onPointerUp);
         canvas.addEventListener("pointermove", this._onPointerMove);
 
-        var root = window.parent || window;
-        root.addEventListener("blur", this._onLostFocus);
+        BABYLON.Tools.RegisterTopRootEvents([
+            { name: "blur", handler: this._onLostFocus }
+        ]);
     };
 
     BABYLON.TouchCamera.prototype.detachControl = function (canvas) {
@@ -113,8 +114,9 @@ var BABYLON = BABYLON || {};
         canvas.removeEventListener("pointerout", this._onPointerUp);
         canvas.removeEventListener("pointermove", this._onPointerMove);
 
-        var root = window.parent || window;
-        root.removeEventListener("blur", this._onLostFocus);
+        BABYLON.Tools.UnregisterTopRootEvents([
+            { name: "blur", handler: this._onLostFocus }
+        ]);
         
         this._attachedCanvas = null;
     };

+ 1 - 0
Babylon/Loading/babylon.sceneLoader.js

@@ -48,6 +48,7 @@ var BABYLON = BABYLON || {};
                 }
 
                 if (onsuccess) {
+                    scene.importedMeshesFiles.push(rootUrl + sceneFilename);
                     onsuccess(meshes, particleSystems, skeletons);
                 }
             }, progressCallBack, database);

+ 4 - 2
Babylon/Materials/babylon.standardMaterial.js

@@ -6,6 +6,8 @@
 };
 var BABYLON;
 (function (BABYLON) {
+    var maxSimultaneousLights = 4;
+
     var StandardMaterial = (function (_super) {
         __extends(StandardMaterial, _super);
         function StandardMaterial(name, scene) {
@@ -196,7 +198,7 @@ var BABYLON;
                     }
 
                     lightIndex++;
-                    if (lightIndex == 4)
+                    if (lightIndex == maxSimultaneousLights)
                         break;
                 }
             }
@@ -387,7 +389,7 @@ var BABYLON;
 
                     lightIndex++;
 
-                    if (lightIndex == 4)
+                    if (lightIndex == maxSimultaneousLights)
                         break;
                 }
             }

+ 4 - 2
Babylon/Materials/babylon.standardMaterial.ts

@@ -1,4 +1,6 @@
 module BABYLON {
+    var maxSimultaneousLights = 4;
+
     export class StandardMaterial extends Material {
         public diffuseTexture: Texture;
         public ambientTexture: Texture;
@@ -199,7 +201,7 @@
                     }
 
                     lightIndex++;
-                    if (lightIndex == 4)
+                    if (lightIndex == maxSimultaneousLights)
                         break;
                 }
             }
@@ -393,7 +395,7 @@
 
                     lightIndex++;
 
-                    if (lightIndex == 4)
+                    if (lightIndex == maxSimultaneousLights)
                         break;
                 }
             }

+ 1 - 1
Babylon/Materials/textures/babylon.renderTargetTexture.js

@@ -64,7 +64,7 @@ var BABYLON;
             for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
                 var mesh = this.renderList[meshIndex];
 
-                if (mesh && mesh.isEnabled() && mesh.isVisible) {
+                if (mesh && mesh.isEnabled() && mesh.isVisible && mesh.subMeshes) {
                     for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                         var subMesh = mesh.subMeshes[subIndex];
                         scene._activeVertices += subMesh.verticesCount;

+ 1 - 1
Babylon/Materials/textures/babylon.renderTargetTexture.ts

@@ -67,7 +67,7 @@
             for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
                 var mesh = this.renderList[meshIndex];
 
-                if (mesh && mesh.isEnabled() && mesh.isVisible) {
+                if (mesh && mesh.isEnabled() && mesh.isVisible && mesh.subMeshes) {
                     for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                         var subMesh = mesh.subMeshes[subIndex];
                         scene._activeVertices += subMesh.verticesCount;

+ 6 - 5
Babylon/Mesh/babylon.mesh.js

@@ -936,6 +936,12 @@ var BABYLON;
             }
 
             impostor = impostor || BABYLON.PhysicsEngine.NoImpostor;
+
+            if (impostor === BABYLON.PhysicsEngine.NoImpostor) {
+                physicsEngine._unregisterMesh(this);
+                return;
+            }
+
             options.mass = options.mass || 0;
             options.friction = options.friction || 0.2;
             options.restitution = options.restitution || 0.9;
@@ -945,11 +951,6 @@ var BABYLON;
             this._physicsFriction = options.friction;
             this._physicRestitution = options.restitution;
 
-            if (impostor === BABYLON.PhysicsEngine.NoImpostor) {
-                physicsEngine._unregisterMesh(this);
-                return;
-            }
-
             physicsEngine._registerMesh(this, impostor, options);
         };
 

+ 6 - 4
Babylon/Mesh/babylon.mesh.ts

@@ -960,6 +960,12 @@
             }
 
             impostor = impostor || PhysicsEngine.NoImpostor;
+
+            if (impostor === BABYLON.PhysicsEngine.NoImpostor) {
+                physicsEngine._unregisterMesh(this);
+                return;
+            }
+
             options.mass = options.mass || 0;
             options.friction = options.friction || 0.2;
             options.restitution = options.restitution || 0.9;
@@ -969,10 +975,6 @@
             this._physicsFriction = options.friction;
             this._physicRestitution = options.restitution;
 
-            if (impostor === BABYLON.PhysicsEngine.NoImpostor) {
-                physicsEngine._unregisterMesh(this);
-                return;
-            }
 
             physicsEngine._registerMesh(this, impostor, options);
         }

+ 4 - 4
Babylon/Shaders/default.fragment.fx

@@ -450,7 +450,7 @@ void main(void) {
 
 #ifdef LIGHT0
 #ifdef SPOTLIGHT0
-	lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0);
+	lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a);
 #endif
 #ifdef HEMILIGHT0
 	lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0);
@@ -473,7 +473,7 @@ void main(void) {
 
 #ifdef LIGHT1
 #ifdef SPOTLIGHT1
-	info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1);
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a);
 #endif
 #ifdef HEMILIGHT1
 	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1);
@@ -496,7 +496,7 @@ void main(void) {
 
 #ifdef LIGHT2
 #ifdef SPOTLIGHT2
-	info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2);
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a);
 #endif
 #ifdef HEMILIGHT2
 	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2);
@@ -519,7 +519,7 @@ void main(void) {
 
 #ifdef LIGHT3
 #ifdef SPOTLIGHT3
-	info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3);
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a);
 #endif
 #ifdef HEMILIGHT3
 	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3);

+ 30 - 0
Babylon/Tools/babylon.tools.js

@@ -285,6 +285,36 @@
             return true;
         };
 
+        Tools.RegisterTopRootEvents = function (events) {
+            for (var index = 0; index < events.length; index++) {
+                var event = events[index];
+                window.addEventListener(event.name, event.handler, false);
+
+                try  {
+                    if (window.parent) {
+                        window.parent.addEventListener(event.name, event.handler, false);
+                    }
+                } catch (e) {
+                    // Silently fails...
+                }
+            }
+        };
+
+        Tools.UnregisterTopRootEvents = function (events) {
+            for (var index = 0; index < events.length; index++) {
+                var event = events[index];
+                window.removeEventListener(event.name, event.handler);
+
+                try  {
+                    if (window.parent) {
+                        window.parent.removeEventListener(event.name, event.handler);
+                    }
+                } catch (e) {
+                    // Silently fails...
+                }
+            }
+        };
+
         Tools.GetFps = function () {
             return fps;
         };

+ 30 - 0
Babylon/Tools/babylon.tools.ts

@@ -305,6 +305,36 @@
             return true;
         }
 
+        public static RegisterTopRootEvents(events: { name: string; handler: EventListener }[]): void {
+            for (var index = 0; index < events.length; index++) {
+                var event = events[index];
+                window.addEventListener(event.name, event.handler, false);
+
+                try {
+                    if (window.parent) {
+                        window.parent.addEventListener(event.name, event.handler, false);
+                    }
+                } catch (e) {
+                    // Silently fails...
+                }
+            }
+        }
+
+        public static UnregisterTopRootEvents(events: { name: string; handler: EventListener }[]): void {
+            for (var index = 0; index < events.length; index++) {
+                var event = events[index];
+                window.removeEventListener(event.name, event.handler);
+
+                try {
+                    if (window.parent) {
+                        window.parent.removeEventListener(event.name, event.handler);
+                    }
+                } catch (e) {
+                    // Silently fails...
+                }
+            }
+        }
+
         public static GetFps(): number {
             return fps;
         }

+ 9 - 6
Babylon/babylon.engine.js

@@ -25,7 +25,7 @@
         return count;
     };
 
-    var prepareWebGLTexture = function (texture, gl, scene, width, height, invertY, noMipmap, processFunction) {
+    var prepareWebGLTexture = function (texture, gl, scene, width, height, invertY, noMipmap, isCompressed, processFunction) {
         var engine = scene.getEngine();
         var potWidth = getExponantOfTwo(width, engine.getCaps().maxTextureSize);
         var potHeight = getExponantOfTwo(height, engine.getCaps().maxTextureSize);
@@ -41,7 +41,10 @@
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
         } else {
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
-            gl.generateMipmap(gl.TEXTURE_2D);
+
+            if (!isCompressed) {
+                gl.generateMipmap(gl.TEXTURE_2D);
+            }
         }
         gl.bindTexture(gl.TEXTURE_2D, null);
 
@@ -498,8 +501,6 @@
 
         Engine.prototype.draw = function (useTriangles, indexStart, indexCount) {
             this._gl.drawElements(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, indexCount, this._gl.UNSIGNED_SHORT, indexStart * 2);
-
-            this._gl.getError();
         };
 
         // Shaders
@@ -763,13 +764,13 @@
 
                     var loadMipmap = info.mipmapCount > 1 && !noMipmap;
 
-                    prepareWebGLTexture(texture, _this._gl, scene, info.width, info.height, invertY, !loadMipmap, function () {
+                    prepareWebGLTexture(texture, _this._gl, scene, info.width, info.height, invertY, !loadMipmap, true, function () {
                         BABYLON.Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, loadMipmap);
                     });
                 }, null, scene.database, true);
             } else {
                 var onload = function (img) {
-                    prepareWebGLTexture(texture, _this._gl, scene, img.width, img.height, invertY, noMipmap, function (potWidth, potHeight) {
+                    prepareWebGLTexture(texture, _this._gl, scene, img.width, img.height, invertY, noMipmap, false, function (potWidth, potHeight) {
                         var isPot = (img.width == potWidth && img.height == potHeight);
                         if (!isPot) {
                             _this._workingCanvas.width = potWidth;
@@ -1145,6 +1146,8 @@
 
         // Dispose
         Engine.prototype.dispose = function () {
+            this.stopRenderLoop();
+
             while (this.scenes.length) {
                 this.scenes[0].dispose();
             }

+ 9 - 6
Babylon/babylon.engine.ts

@@ -24,7 +24,7 @@
         return count;
     };
 
-    var prepareWebGLTexture = (texture: WebGLTexture, gl: WebGLRenderingContext, scene: Scene, width: number, height: number, invertY: boolean, noMipmap: boolean,
+    var prepareWebGLTexture = (texture: WebGLTexture, gl: WebGLRenderingContext, scene: Scene, width: number, height: number, invertY: boolean, noMipmap: boolean, isCompressed: boolean,
         processFunction: (width: number, height: number) => void) => {
         var engine = scene.getEngine();
         var potWidth = getExponantOfTwo(width, engine.getCaps().maxTextureSize);
@@ -41,7 +41,10 @@
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
         } else {
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
-            gl.generateMipmap(gl.TEXTURE_2D);
+
+            if (!isCompressed) {
+                gl.generateMipmap(gl.TEXTURE_2D);
+            }
         }
         gl.bindTexture(gl.TEXTURE_2D, null);
 
@@ -556,8 +559,6 @@
 
         public draw(useTriangles: boolean, indexStart: number, indexCount: number): void {
             this._gl.drawElements(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, indexCount, this._gl.UNSIGNED_SHORT, indexStart * 2);
-
-            this._gl.getError();
         }
 
         // Shaders
@@ -822,13 +823,13 @@
 
                     var loadMipmap = info.mipmapCount > 1 && !noMipmap;
 
-                    prepareWebGLTexture(texture, this._gl, scene, info.width, info.height, invertY, !loadMipmap, () => {
+                    prepareWebGLTexture(texture, this._gl, scene, info.width, info.height, invertY, !loadMipmap, true, () => {
                         BABYLON.Internals.DDSTools.UploadDDSLevels(this._gl, this.getCaps().s3tc, data, loadMipmap);
                     });
                 }, null, scene.database, true);
             } else {
                 var onload = (img) => {
-                    prepareWebGLTexture(texture, this._gl, scene, img.width, img.height, invertY, noMipmap, (potWidth, potHeight) => {
+                    prepareWebGLTexture(texture, this._gl, scene, img.width, img.height, invertY, noMipmap, false, (potWidth, potHeight) => {
                         var isPot = (img.width == potWidth && img.height == potHeight);
                         if (!isPot) {
                             this._workingCanvas.width = potWidth;
@@ -1202,6 +1203,8 @@
 
         // Dispose
         public dispose(): void {
+            this.stopRenderLoop();
+
             // Release scenes
             while (this.scenes.length) {
                 this.scenes[0].dispose();

+ 4 - 2
Babylon/babylon.scene.js

@@ -65,6 +65,8 @@
             // Customs render targets
             this.renderTargetsEnabled = true;
             this.customRenderTargets = new Array();
+            // Imported meshes
+            this.importedMeshesFiles = new Array();
             this._totalVertices = 0;
             this._activeVertices = 0;
             this._activeParticles = 0;
@@ -165,7 +167,7 @@
             var _this = this;
             this._onPointerMove = function (evt) {
                 var canvas = _this._engine.getRenderingCanvas();
-                var pickResult = _this.pick(evt.clientX, evt.clientY, function (mesh) {
+                var pickResult = _this.pick(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY, function (mesh) {
                     return mesh.actionManager && mesh.isPickable;
                 });
 
@@ -179,7 +181,7 @@
             };
 
             this._onPointerDown = function (evt) {
-                var pickResult = _this.pick(evt.clientX, evt.clientY);
+                var pickResult = _this.pick(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY);
 
                 if (pickResult.hit) {
                     if (pickResult.pickedMesh.actionManager) {

+ 5 - 2
Babylon/babylon.scene.ts

@@ -97,6 +97,9 @@
         // Delay loading
         public useDelayedTextureLoading: boolean;
 
+        // Imported meshes
+        public importedMeshesFiles = new Array<String>();
+
         // Database
         public database; //ANY
 
@@ -231,7 +234,7 @@
         public attachControl() {
             this._onPointerMove = (evt: PointerEvent) => {
                 var canvas = this._engine.getRenderingCanvas();
-                var pickResult = this.pick(evt.clientX, evt.clientY, mesh => mesh.actionManager && mesh.isPickable);
+                var pickResult = this.pick(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY, mesh => mesh.actionManager && mesh.isPickable);
 
                 if (pickResult.hit) {
                     this.setPointerOverMesh(pickResult.pickedMesh);
@@ -243,7 +246,7 @@
             };
 
             this._onPointerDown = (evt: PointerEvent) => {
-                var pickResult = this.pick(evt.clientX, evt.clientY);
+                var pickResult = this.pick(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY);
 
                 if (pickResult.hit) {
                     if (pickResult.pickedMesh.actionManager) {

+ 14 - 7
Exporters/Blender/io_export_babylon.py

@@ -779,13 +779,13 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
         file_handler.write("]")         
         file_handler.write("}") 
 
-    def export_bone_matrix(armature, bone, label, file_handler):
+    def get_bone_matrix(armature, bone):
         SystemMatrix = Matrix.Scale(-1, 4, Vector((0, 0, 1))) * Matrix.Rotation(radians(-90), 4, 'X')
 
         if (bone.parent):
-            Export_babylon.write_matrix4(file_handler, label, (SystemMatrix * armature.matrix_world * bone.parent.matrix).inverted() * (SystemMatrix * armature.matrix_world * bone.matrix))
+            return (SystemMatrix * armature.matrix_world * bone.parent.matrix).inverted() * (SystemMatrix * armature.matrix_world * bone.matrix)
         else:
-            Export_babylon.write_matrix4(file_handler, label, SystemMatrix * armature.matrix_world * bone.matrix)
+            return SystemMatrix * armature.matrix_world * bone.matrix
 
 
     def export_bones(armature, scene, file_handler, id):
@@ -807,7 +807,7 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
             Export_babylon.write_string(file_handler, "name", bone.name, True)
             Export_babylon.write_int(file_handler, "index", j)
 
-            Export_babylon.export_bone_matrix(armature, bone, "matrix", file_handler)
+            Export_babylon.write_matrix4(file_handler, "matrix", Export_babylon.get_bone_matrix(armature, bone))
 
             if (bone.parent):
                 parentId = 0
@@ -844,15 +844,22 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 
         #keys
         file_handler.write(",\"keys\":[")
+
+        previousBoneMatrix = None
                         
         for Frame in range(start_frame, end_frame + 1):
                 
+            bpy.context.scene.frame_set(Frame)
+            currentBoneMatrix = Export_babylon.get_bone_matrix(armature, bone)
+
+            if (Frame != end_frame and currentBoneMatrix == previousBoneMatrix):
+                continue
+
             file_handler.write("{")
 
             Export_babylon.write_int(file_handler, "frame", Frame, True)
-            bpy.context.scene.frame_set(Frame)
-
-            Export_babylon.export_bone_matrix(armature, bone, "values", file_handler)
+            Export_babylon.write_matrix4(file_handler, "values", currentBoneMatrix)
+            previousBoneMatrix = currentBoneMatrix
 
             if Frame == end_frame:
                 file_handler.write("}")

文件差異過大導致無法顯示
+ 13 - 28
babylon.1.12-beta.js