Przeglądaj źródła

Merge remote-tracking branch 'BabylonJS/master'

MackeyK24 8 lat temu
rodzic
commit
95318d7c84

+ 2 - 1
Tools/Npm/getfiles.bat

@@ -3,5 +3,6 @@ xcopy /Y /F "../../dist/preview release/babylon.js" .
 xcopy /Y /F "../../dist/preview release/babylon.max.js"  .
 xcopy /Y /F "../../dist/preview release/babylon.noworker.js" . 
 xcopy /Y /F "../../dist/preview release/babylon.core.js" . 
+xcopy /Y /F "../../dist/preview release/canvas2D/babylon.canvas2d.js" . 
 xcopy /Y /F "../../dist/preview release/oimo.js" . 
-pause
+pause

+ 2 - 1
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -287,7 +287,8 @@ declare module BABYLON {
         materials: Object;
         animations: Object;
         skins: Object;
-        currentScene: Object;
+        currentScene?: Object;
+        scenes: Object;
         extensionsUsed: string[];
         extensionsRequired?: string[];
         buffersCount: number;

+ 61 - 22
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -233,13 +233,24 @@ var BABYLON;
                 if (!sampler) {
                     continue;
                 }
-                var inputData = animation.parameters[sampler.input];
-                var outputData = animation.parameters[sampler.output];
+                var inputData = null;
+                var outputData = null;
+                if (animation.parameters) {
+                    inputData = animation.parameters[sampler.input];
+                    outputData = animation.parameters[sampler.output];
+                }
+                else {
+                    inputData = sampler.input;
+                    outputData = sampler.output;
+                }
                 var bufferInput = BABYLON.GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]);
                 var bufferOutput = BABYLON.GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]);
                 var targetID = channel.target.id;
                 var targetNode = gltfRuntime.scene.getNodeByID(targetID);
                 if (targetNode === null) {
+                    targetNode = gltfRuntime.scene.getNodeByName(targetID);
+                }
+                if (targetNode === null) {
                     BABYLON.Tools.Warn("Creating animation named " + anim + ". But cannot find node named " + targetID + " to attach to");
                     continue;
                 }
@@ -336,10 +347,10 @@ var BABYLON;
     */
     var configureBoneTransformation = function (node) {
         var mat = null;
-        if (node.translation && node.rotation && node.scale) {
-            var scale = BABYLON.Vector3.FromArray(node.scale);
-            var rotation = BABYLON.Quaternion.FromArray(node.rotation);
-            var position = BABYLON.Vector3.FromArray(node.translation);
+        if (node.translation || node.rotation || node.scale) {
+            var scale = BABYLON.Vector3.FromArray(node.scale || [1, 1, 1]);
+            var rotation = BABYLON.Quaternion.FromArray(node.rotation || [0, 0, 0, 1]);
+            var position = BABYLON.Vector3.FromArray(node.translation || [0, 0, 0]);
             // Y is Up
             if (GLTFFileLoader.MakeYUP) {
                 rotation = rotation.multiply(new BABYLON.Quaternion(-0.707107, 0, 0, 0.707107));
@@ -357,7 +368,7 @@ var BABYLON;
     var getParentBone = function (gltfRuntime, skins, jointName, newSkeleton) {
         // Try to find
         for (var i = 0; i < newSkeleton.bones.length; i++) {
-            if (newSkeleton.bones[i].id === jointName) {
+            if (newSkeleton.bones[i].name === jointName) {
                 return newSkeleton.bones[i];
             }
         }
@@ -549,7 +560,7 @@ var BABYLON;
                 var invertMesh = BABYLON.Matrix.Invert(mesh.getWorldMatrix());
                 mat = mat.multiply(mesh.getWorldMatrix());
             }
-            var bone = new BABYLON.Bone(node.name, newSkeleton, parentBone, mat);
+            var bone = new BABYLON.Bone(node.jointName, newSkeleton, parentBone, mat);
             bone.id = id;
         }
         // Polish
@@ -900,8 +911,10 @@ var BABYLON;
                 newNode.parent = parent;
             }
         }
-        for (var i = 0; i < node.children.length; i++) {
-            traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
+        if (node.children) {
+            for (var i = 0; i < node.children.length; i++) {
+                traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
+            }
         }
     };
     /**
@@ -910,8 +923,18 @@ var BABYLON;
     var postLoad = function (gltfRuntime) {
         // Nodes
         var currentScene = gltfRuntime.currentScene;
-        for (var i = 0; i < currentScene.nodes.length; i++) {
-            traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+        if (currentScene) {
+            for (var i = 0; i < currentScene.nodes.length; i++) {
+                traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+            }
+        }
+        else {
+            for (var thing in gltfRuntime.scenes) {
+                currentScene = gltfRuntime.scenes[thing];
+                for (var i = 0; i < currentScene.nodes.length; i++) {
+                    traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                }
+            }
         }
         // Set animations
         loadAnimations(gltfRuntime);
@@ -924,6 +947,7 @@ var BABYLON;
     * onBind shaderrs callback to set uniforms and matrices
     */
     var onBindShaderMaterial = function (mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess) {
+        var materialValues = material.values || technique.parameters;
         for (var unif in unTreatedUniforms) {
             var uniform = unTreatedUniforms[unif];
             var type = uniform.type;
@@ -943,12 +967,12 @@ var BABYLON;
                 }
             }
             else {
-                var value = material.values[technique.uniforms[unif]];
+                var value = materialValues[technique.uniforms[unif]];
                 if (!value) {
                     continue;
                 }
                 if (type === BABYLON.EParameterType.SAMPLER_2D) {
-                    var texture = gltfRuntime.textures[value].babylonTexture;
+                    var texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;
                     if (texture === null || texture === undefined) {
                         continue;
                     }
@@ -966,7 +990,7 @@ var BABYLON;
     * Loads the appropriate textures
     */
     var prepareShaderMaterialUniforms = function (gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms) {
-        var materialValues = material.values;
+        var materialValues = material.values || technique.parameters;
         var techniqueUniforms = technique.uniforms;
         /**
         * Prepare values here (not matrices)
@@ -993,10 +1017,10 @@ var BABYLON;
             };
             // Texture (sampler2D)
             if (type === BABYLON.EParameterType.SAMPLER_2D) {
-                BABYLON.GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, value, onLoadTexture(unif), function () { return onLoadTexture(null); });
+                BABYLON.GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, material.values ? value : uniform.value, onLoadTexture(unif), function () { return onLoadTexture(null); });
             }
             else {
-                if (uniform.value && BABYLON.GLTFUtils.SetUniform(shaderMaterial, unif, value, type)) {
+                if (uniform.value && BABYLON.GLTFUtils.SetUniform(shaderMaterial, unif, material.values ? value : uniform.value, type)) {
                     // Static uniform
                     delete unTreatedUniforms[unif];
                 }
@@ -1076,8 +1100,8 @@ var BABYLON;
                 materials: {},
                 animations: {},
                 skins: {},
-                currentScene: {},
                 extensionsUsed: [],
+                scenes: {},
                 buffersCount: 0,
                 shaderscount: 0,
                 scene: scene,
@@ -1140,6 +1164,9 @@ var BABYLON;
             if (parsedData.skins) {
                 parseObject(parsedData.skins, "skins", gltfRuntime);
             }
+            if (parsedData.scenes) {
+                gltfRuntime.scenes = parsedData.scenes;
+            }
             if (parsedData.scene && parsedData.scenes) {
                 gltfRuntime.currentScene = parsedData.scenes[parsedData.scene];
             }
@@ -1295,7 +1322,7 @@ var BABYLON;
                 attributes: attributes,
                 uniforms: uniforms,
                 samplers: samplers,
-                needAlphaBlending: states.enable && states.enable.indexOf(3042) !== -1
+                needAlphaBlending: states && states.enable && states.enable.indexOf(3042) !== -1
             };
             BABYLON.Effect.ShadersStore[program.vertexShader + id + "VertexShader"] = newVertexShader;
             BABYLON.Effect.ShadersStore[program.fragmentShader + id + "PixelShader"] = newPixelShader;
@@ -1303,7 +1330,7 @@ var BABYLON;
             shaderMaterial.onError = onShaderCompileError(program, shaderMaterial, onError);
             shaderMaterial.onCompiled = onShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess);
             shaderMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
-            if (states.functions) {
+            if (states && states.functions) {
                 var functions = states.functions;
                 if (functions.cullFace && functions.cullFace[0] !== BABYLON.ECullingType.BACK) {
                     shaderMaterial.backFaceCulling = false;
@@ -1490,8 +1517,20 @@ var BABYLON;
         // Creates nodes before loading buffers and shaders
         GLTFFileLoader.prototype._createNodes = function (gltfRuntime) {
             var currentScene = gltfRuntime.currentScene;
-            for (var i = 0; i < currentScene.nodes.length; i++) {
-                traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+            if (currentScene) {
+                // Only one scene even if multiple scenes are defined
+                for (var i = 0; i < currentScene.nodes.length; i++) {
+                    traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                }
+            }
+            else {
+                // Load all scenes
+                for (var thing in gltfRuntime.scenes) {
+                    currentScene = gltfRuntime.scenes[thing];
+                    for (var i = 0; i < currentScene.nodes.length; i++) {
+                        traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                    }
+                }
             }
         };
         return GLTFFileLoader;

Plik diff jest za duży
+ 2 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 1 - 0
dist/preview release/what's new.md

@@ -2,6 +2,7 @@
 
 ### Major updates
  - WebGL2 context support.WebGL2 is initialized instead of WebGL 1 when available ([deltakosh](https://github.com/deltakosh))
+ - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))
  - New DebugLayer. [Doc](TODO) - ([temechon](https://github.com/temechon))
  - New `VideoTexture.CreateFromWebCam` to generate video texture using WebRTC. [Demo](https://www.babylonjs-playground.com#1R77YT#2) - (Sebastien Vandenberghe)(https://github.com/sebavanmicrosoft) / ([deltakosh](https://github.com/deltakosh))

+ 69 - 22
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -166,8 +166,17 @@ module BABYLON {
                     continue;
                 }
 
-                var inputData = animation.parameters[sampler.input];
-                var outputData = animation.parameters[sampler.output];
+                var inputData: string = null;
+                var outputData: string = null;
+
+                if (animation.parameters) {
+                    inputData = animation.parameters[sampler.input];
+                    outputData = animation.parameters[sampler.output];
+                }
+                else {
+                    inputData = sampler.input;
+                    outputData = sampler.output;
+                }
 
                 var bufferInput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]);
                 var bufferOutput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]);
@@ -176,6 +185,10 @@ module BABYLON {
                 var targetNode: any = gltfRuntime.scene.getNodeByID(targetID);
 
                 if (targetNode === null) {
+                    targetNode = gltfRuntime.scene.getNodeByName(targetID);
+                }
+
+                if (targetNode === null) {
                     Tools.Warn("Creating animation named " + anim + ". But cannot find node named " + targetID + " to attach to");
                     continue;
                 }
@@ -293,10 +306,11 @@ module BABYLON {
     */
     var configureBoneTransformation = (node: IGLTFNode): Matrix => {
         var mat: Matrix = null;
-        if (node.translation && node.rotation && node.scale) {
-            var scale = Vector3.FromArray(node.scale);
-            var rotation = Quaternion.FromArray(node.rotation);
-            var position = Vector3.FromArray(node.translation);
+
+        if (node.translation || node.rotation || node.scale) {
+            var scale = Vector3.FromArray(node.scale || [1, 1, 1]);
+            var rotation = Quaternion.FromArray(node.rotation || [0, 0, 0, 1]);
+            var position = Vector3.FromArray(node.translation || [0, 0, 0]);
 
             // Y is Up
             if (GLTFFileLoader.MakeYUP) {
@@ -318,7 +332,7 @@ module BABYLON {
     var getParentBone = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, jointName: string, newSkeleton: Skeleton): Bone => {
         // Try to find
         for (var i = 0; i < newSkeleton.bones.length; i++) {
-            if (newSkeleton.bones[i].id === jointName) {
+            if (newSkeleton.bones[i].name === jointName) {
                 return newSkeleton.bones[i];
             }
         }
@@ -557,7 +571,7 @@ module BABYLON {
                 mat = mat.multiply(mesh.getWorldMatrix());
             }
 
-            var bone = new Bone(node.name, newSkeleton, parentBone, mat);
+            var bone = new Bone(node.jointName, newSkeleton, parentBone, mat);
             bone.id = id;
         }
 
@@ -991,8 +1005,10 @@ module BABYLON {
             }
         }
 
-        for (var i = 0; i < node.children.length; i++) {
-            traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
+        if (node.children) {
+            for (var i = 0; i < node.children.length; i++) {
+                traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
+            }
         }
     };
 
@@ -1003,8 +1019,19 @@ module BABYLON {
         // Nodes
         var currentScene: IGLTFScene = <IGLTFScene>gltfRuntime.currentScene;
 
-        for (var i = 0; i < currentScene.nodes.length; i++) {
-            traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+        if (currentScene) {
+            for (var i = 0; i < currentScene.nodes.length; i++) {
+                traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+            }
+        }
+        else {
+            for (var thing in gltfRuntime.scenes) {
+                currentScene = <IGLTFScene>gltfRuntime.scenes[thing];
+
+                for (var i = 0; i < currentScene.nodes.length; i++) {
+                    traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                }
+            }
         }
 
         // Set animations
@@ -1020,6 +1047,8 @@ module BABYLON {
     * onBind shaderrs callback to set uniforms and matrices
     */
     var onBindShaderMaterial = (mesh: Mesh, gltfRuntime: IGLTFRuntime, unTreatedUniforms: Object, shaderMaterial: ShaderMaterial, technique: IGLTFTechnique, material: IGLTFMaterial, onSuccess: (shaderMaterial: ShaderMaterial) => void) => {
+        var materialValues = material.values || technique.parameters;
+
         for (var unif in unTreatedUniforms) {
             var uniform: IGLTFTechniqueParameter = unTreatedUniforms[unif];
             var type = uniform.type;
@@ -1041,13 +1070,13 @@ module BABYLON {
                 }
             }
             else {
-                var value = material.values[technique.uniforms[unif]];
+                var value = materialValues[technique.uniforms[unif]];
                 if (!value) {
                     continue;
                 }
 
                 if (type === EParameterType.SAMPLER_2D) {
-                    var texture: Texture = gltfRuntime.textures[value].babylonTexture;
+                    var texture: Texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;
 
                     if (texture === null || texture === undefined) {
                         continue;
@@ -1069,7 +1098,7 @@ module BABYLON {
     * Loads the appropriate textures
     */
     var prepareShaderMaterialUniforms = (gltfRuntime: IGLTFRuntime, shaderMaterial: ShaderMaterial, technique: IGLTFTechnique, material: IGLTFMaterial, unTreatedUniforms: Object) => {
-        var materialValues = material.values;
+        var materialValues = material.values || technique.parameters;
         var techniqueUniforms = technique.uniforms;
 
         /**
@@ -1101,11 +1130,11 @@ module BABYLON {
 
             // Texture (sampler2D)
             if (type === EParameterType.SAMPLER_2D) {
-                GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, <string>value, onLoadTexture(unif), () => onLoadTexture(null));
+                GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, material.values ? value : uniform.value, onLoadTexture(unif), () => onLoadTexture(null));
             }
             // Others
             else {
-                if (uniform.value && GLTFUtils.SetUniform(shaderMaterial, unif, value, type)) {
+                if (uniform.value && GLTFUtils.SetUniform(shaderMaterial, unif, material.values ? value : uniform.value, type)) {
                     // Static uniform
                     delete unTreatedUniforms[unif];
                 }
@@ -1192,9 +1221,10 @@ module BABYLON {
                 materials: {},
                 animations: {},
                 skins: {},
-                currentScene: {},
                 extensionsUsed: [],
 
+                scenes: {},
+
                 buffersCount: 0,
                 shaderscount: 0,
 
@@ -1280,6 +1310,10 @@ module BABYLON {
                 parseObject(parsedData.skins, "skins", gltfRuntime);
             }
 
+            if (parsedData.scenes) {
+                gltfRuntime.scenes = parsedData.scenes;
+            }
+
             if (parsedData.scene && parsedData.scenes) {
                 gltfRuntime.currentScene = parsedData.scenes[parsedData.scene];
             }
@@ -1475,7 +1509,7 @@ module BABYLON {
                 attributes: attributes,
                 uniforms: uniforms,
                 samplers: samplers,
-                needAlphaBlending: states.enable && states.enable.indexOf(3042) !== -1
+                needAlphaBlending: states && states.enable && states.enable.indexOf(3042) !== -1
             };
 
             Effect.ShadersStore[program.vertexShader + id + "VertexShader"] = newVertexShader;
@@ -1486,7 +1520,7 @@ module BABYLON {
             shaderMaterial.onCompiled = onShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess);
             shaderMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
 
-            if (states.functions) {
+            if (states && states.functions) {
                 var functions = states.functions;
                 if (functions.cullFace && functions.cullFace[0] !== ECullingType.BACK) {
                     shaderMaterial.backFaceCulling = false;
@@ -1717,8 +1751,21 @@ module BABYLON {
         private _createNodes(gltfRuntime: IGLTFRuntime): void {
             var currentScene = <IGLTFScene>gltfRuntime.currentScene;
 
-            for (var i = 0; i < currentScene.nodes.length; i++) {
-                traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+            if (currentScene) {
+                // Only one scene even if multiple scenes are defined
+                for (var i = 0; i < currentScene.nodes.length; i++) {
+                    traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                }
+            }
+            else {
+                // Load all scenes
+                for (var thing in gltfRuntime.scenes) {
+                    currentScene = <IGLTFScene>gltfRuntime.scenes[thing];
+
+                    for (var i = 0; i < currentScene.nodes.length; i++) {
+                        traverseNodes(gltfRuntime, currentScene.nodes[i], null);
+                    }
+                }
             }
         }
     };

+ 3 - 1
loaders/src/glTF/babylon.glTFFileLoaderInterfaces.ts

@@ -345,7 +345,9 @@ module BABYLON {
         materials: Object;
         animations: Object;
         skins: Object;
-        currentScene: Object;
+
+        currentScene?: Object;
+        scenes: Object; // v1.1
 
         extensionsUsed: string[];
         extensionsRequired?: string[]; // v1.1

+ 1 - 0
src/Cameras/babylon.camera.ts

@@ -353,6 +353,7 @@
                         result.push(i);
                         continue;
                     }
+                    index = atIndices[i];
                     this._postProcesses.splice(index, 1);
                 }
             }

+ 1 - 25
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -43,7 +43,7 @@
             var worldPoint = new CANNON.Vec3(contactPoint.x, contactPoint.y, contactPoint.z);
             var impulse = new CANNON.Vec3(force.x, force.y, force.z);
 
-            impostor.physicsBody.applyImpulse(impulse, worldPoint);
+            impostor.physicsBody.applyForce(impulse, worldPoint);
         }
 
         public generatePhysicsBody(impostor: PhysicsImpostor) {
@@ -153,21 +153,6 @@
                 maxForce: jointData.nativeParams.maxForce,
                 collideConnected: !!jointData.collision
             };
-            //Not needed, Cannon has a collideConnected flag
-            /*if (!jointData.collision) {
-                //add 1st body to a collision group of its own, if it is not in 1
-                if (mainBody.collisionFilterGroup === 1) {
-                    mainBody.collisionFilterGroup = this._currentCollisionGroup;
-                    this._currentCollisionGroup <<= 1;
-                }
-                if (connectedBody.collisionFilterGroup === 1) {
-                    connectedBody.collisionFilterGroup = this._currentCollisionGroup;
-                    this._currentCollisionGroup <<= 1;
-                }
-                //add their mask to the collisionFilterMask of each other:
-                connectedBody.collisionFilterMask = connectedBody.collisionFilterMask | ~mainBody.collisionFilterGroup;
-                mainBody.collisionFilterMask = mainBody.collisionFilterMask | ~connectedBody.collisionFilterGroup;
-            }*/
             switch (impostorJoint.joint.type) {
                 case PhysicsJoint.HingeJoint:
                 case PhysicsJoint.Hinge2Joint:
@@ -477,15 +462,6 @@
                 if (maxForce) {
                     this.setLimit(joint, maxForce);
                 }
-                //a hack for force application
-                /*var torque = new CANNON.Vec3();
-                var axis = joint.physicsJoint.axisB;
-                var body = joint.physicsJoint.bodyB;
-                var bodyTorque = body.torque;
-
-                axis.scale(force, torque);
-                body.vectorToWorldFrame(torque, torque);
-                bodyTorque.vadd(torque, bodyTorque);*/
             }
         }
 

+ 2 - 2
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -1,7 +1,7 @@
 module BABYLON {
     declare var OIMO;
 
-    export class OimoJSPlugin {
+    export class OimoJSPlugin implements IPhysicsEnginePlugin {
 
         public world: any;
         public name: string = "OimoJSPlugin";
@@ -365,7 +365,7 @@ module BABYLON {
             impostor.physicsBody.awake();
         }
 
-        public updateDistanceJoint(joint: IMotorEnabledJoint, maxDistance: number, minDistance?: number) {
+        public updateDistanceJoint(joint: PhysicsJoint, maxDistance: number, minDistance?: number) {
             joint.physicsJoint.limitMotor.upperLimit = maxDistance;
             if (minDistance !== void 0) {
                 joint.physicsJoint.limitMotor.lowerLimit = minDistance;

+ 1 - 1
src/Physics/babylon.physicsEngine.ts

@@ -195,7 +195,7 @@
         sleepBody(impostor: PhysicsImpostor);
         wakeUpBody(impostor: PhysicsImpostor);
         //Joint Update
-        updateDistanceJoint(joint: DistanceJoint, maxDistance:number, minDistance?: number);
+        updateDistanceJoint(joint: PhysicsJoint, maxDistance:number, minDistance?: number);
         setMotor(joint: IMotorEnabledJoint, speed: number, maxForce?: number, motorIndex?: number);
         setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number);
         dispose();

+ 0 - 6
src/Physics/babylon.physicsImpostor.ts

@@ -212,9 +212,6 @@ module BABYLON {
             return this._physicsEngine.getPhysicsPlugin().getLinearVelocity(this);
         }
 
-        /**
-         * Set the body's linear velocity.
-         */
         public setLinearVelocity(velocity: Vector3) {
             this._physicsEngine.getPhysicsPlugin().setLinearVelocity(this, velocity);
         }
@@ -223,9 +220,6 @@ module BABYLON {
             return this._physicsEngine.getPhysicsPlugin().getAngularVelocity(this);
         }
 
-        /**
-         * Set the body's linear velocity.
-         */
         public setAngularVelocity(velocity: Vector3) {
             this._physicsEngine.getPhysicsPlugin().setAngularVelocity(this, velocity);
         }

+ 110 - 155
src/babylon.engine.ts

@@ -11,20 +11,6 @@
         return shader;
     };
 
-    var HALF_FLOAT_OES = 0x8D61;
-
-    var getWebGLTextureType = (gl: WebGLRenderingContext, type: number): number => {
-        if (type === Engine.TEXTURETYPE_FLOAT) {
-            return gl.FLOAT;
-        }
-        else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
-            // Add Half Float Constant.
-            return HALF_FLOAT_OES;
-        }
-
-        return gl.UNSIGNED_BYTE;
-    };
-
     var getSamplingParameters = (samplingMode: number, generateMipMaps: boolean, gl: WebGLRenderingContext): { min: number; mag: number } => {
         var magFilter = gl.NEAREST;
         var minFilter = gl.NEAREST;
@@ -197,6 +183,7 @@
         public textureHalfFloatRender: boolean;
         public textureLOD: boolean;
         public drawBuffersExtension;
+        public colorBufferFloat: boolean;
     }
 
     export interface EngineOptions extends WebGLContextAttributes {
@@ -244,6 +231,10 @@
         private static _GEQUAL = 0x0206; //	Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value.
         private static _NOTEQUAL = 0x0205; //  Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is not equal to the stored value.
 
+        private static HALF_FLOAT_OES = 0x8D61; // Half floating-point type (16-bit).
+        private static RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized format.
+        private static RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized format.
+
         public static get NEVER(): number {
             return Engine._NEVER;
         }
@@ -560,10 +551,6 @@
             if (!this._gl) {
                 throw new Error("WebGL not supported");
             }
-
-            // Checks if some of the format renders first to allow the use of webgl inspector.
-            var renderToFullFloat = this._canRenderToFloatTexture();
-            var renderToHalfFloat = this._canRenderToHalfFloatTexture();
             
             this._onBlur = () => {
                 this._windowIsBackground = true;
@@ -621,20 +608,25 @@
                                this._gl.getExtension('WEBGL_compressed_texture_es3_0'); // also a requirement of OpenGL ES 3
             this._caps.atc   = this._gl.getExtension('WEBGL_compressed_texture_atc'  ) || this._gl.getExtension('WEBKIT_WEBGL_compressed_texture_atc'  );
             
-            this._caps.textureFloat = this._webGLVersion > 1 || (this._gl.getExtension('OES_texture_float') !== null);
             this._caps.textureAnisotropicFilterExtension = this._gl.getExtension('EXT_texture_filter_anisotropic') || this._gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || this._gl.getExtension('MOZ_EXT_texture_filter_anisotropic');
             this._caps.maxAnisotropy = this._caps.textureAnisotropicFilterExtension ? this._gl.getParameter(this._caps.textureAnisotropicFilterExtension.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0;
             this._caps.uintIndices = this._webGLVersion > 1 || this._gl.getExtension('OES_element_index_uint') !== null;
             this._caps.fragmentDepthSupported = this._webGLVersion > 1 || this._gl.getExtension('EXT_frag_depth') !== null;
             this._caps.highPrecisionShaderSupported = true;
             this._caps.drawBuffersExtension = this._webGLVersion > 1 || this._gl.getExtension('WEBGL_draw_buffers');
+
+            // Checks if some of the format renders first to allow the use of webgl inspector.
+            this._caps.colorBufferFloat = this._webGLVersion > 1 && this._gl.getExtension('EXT_color_buffer_float')
+
+            this._caps.textureFloat = this._webGLVersion > 1 || (this._gl.getExtension('OES_texture_float') !== null);
             this._caps.textureFloatLinearFiltering = this._gl.getExtension('OES_texture_float_linear');
-            this._caps.textureLOD = this._webGLVersion > 1 || this._gl.getExtension('EXT_shader_texture_lod');
-            this._caps.textureFloatRender = renderToFullFloat;
+            this._caps.textureFloatRender = this._caps.textureFloat && this._canRenderToFloatFramebuffer();            
 
             this._caps.textureHalfFloat = this._webGLVersion > 1 || (this._gl.getExtension('OES_texture_half_float') !== null);
             this._caps.textureHalfFloatLinearFiltering = this._webGLVersion > 1 || this._gl.getExtension('OES_texture_half_float_linear');
-            this._caps.textureHalfFloatRender = renderToHalfFloat;
+            this._caps.textureHalfFloatRender = this._caps.textureHalfFloat && this._canRenderToHalfFloatFramebuffer();
+            
+            this._caps.textureLOD = this._webGLVersion > 1 || this._gl.getExtension('EXT_shader_texture_lod');
 
             // Vertex array object 
             if ( this._webGLVersion > 1) {
@@ -2439,7 +2431,7 @@
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
 
-            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, getWebGLTextureType(gl, type), null);
+            gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(type), width, height, 0, gl.RGBA, this._getWebGLTextureType(type), null);
 
             var depthStencilBuffer: WebGLRenderbuffer;
 
@@ -2733,13 +2725,14 @@
             texture.references = 1;
             texture.url = url;
 
-            var internalFormat = this._getInternalFormat(format);
-
             var textureType = gl.UNSIGNED_BYTE;
             if (type === Engine.TEXTURETYPE_FLOAT) {
                 textureType = gl.FLOAT;
             }
 
+            var internalFormat = this._getInternalFormat(format);
+            var internalSizedFomat = this._getRGBABufferInternalSizedFormat(type);
+
             var width = size;
             var height = width;
             var isPot = (Tools.IsExponentOfTwo(width) && Tools.IsExponentOfTwo(height));
@@ -2784,30 +2777,19 @@
                             var mipSize = width >> level;
 
                             // mipData is order in +X -X +Y -Y +Z -Z
-                            gl.texImage2D(facesIndex[0], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][0]);
-                            gl.texImage2D(facesIndex[1], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][2]);
-                            gl.texImage2D(facesIndex[2], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][4]);
-                            gl.texImage2D(facesIndex[3], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][1]);
-                            gl.texImage2D(facesIndex[4], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][3]);
-                            gl.texImage2D(facesIndex[5], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][5]);
+                            gl.texImage2D(facesIndex[0], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][0]);
+                            gl.texImage2D(facesIndex[1], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][2]);
+                            gl.texImage2D(facesIndex[2], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][4]);
+                            gl.texImage2D(facesIndex[3], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][1]);
+                            gl.texImage2D(facesIndex[4], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][3]);
+                            gl.texImage2D(facesIndex[5], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][5]);
                         }
                     }
                     else {
-                        // Data are known to be in +X +Y +Z -X -Y -Z
-                        for (let index = 0; index < facesIndex.length; index++) {
-                            let faceData = rgbeDataArrays[index];
-                            gl.texImage2D(facesIndex[index], 0, internalFormat, width, height, 0, internalFormat, textureType, faceData);
-                        }
-
-                        gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
-
-                        // Workaround firefox bug fix https://bugzilla.mozilla.org/show_bug.cgi?id=1221822
-                        // By following the webgl standard changes from Revision 7, 2014/11/24
-                        // Firefox Removed the support for RGB32F, since it is not natively supported on all platforms where WebGL is implemented.
-                        if (textureType === gl.FLOAT && internalFormat === gl.RGB && gl.getError() === 1282) {
-                            Tools.Log("RGB32F not renderable on Firefox, trying fallback to RGBA32F.");
+                        if (internalFormat === gl.RGB) {
+                            internalFormat = gl.RGBA;
 
-                            // Data are known to be in +X +Y +Z -X -Y -Z
+                             // Data are known to be in +X +Y +Z -X -Y -Z
                             for (let index = 0; index < facesIndex.length; index++) {
                                 let faceData = <Float32Array>rgbeDataArrays[index];
 
@@ -2829,12 +2811,18 @@
                                 }
 
                                 // Reupload the face.
-                                gl.texImage2D(facesIndex[index], 0, gl.RGBA, width, height, 0, gl.RGBA, textureType, newFaceData);
+                                gl.texImage2D(facesIndex[index], 0, internalSizedFomat, width, height, 0, internalFormat, textureType, newFaceData);
+                            }
+                        }
+                        else {
+                            // Data are known to be in +X +Y +Z -X -Y -Z
+                            for (let index = 0; index < facesIndex.length; index++) {
+                                let faceData = rgbeDataArrays[index];
+                                gl.texImage2D(facesIndex[index], 0, internalSizedFomat, width, height, 0, internalFormat, textureType, faceData);
                             }
-
-                            // Try to generate mipmap again.
-                            gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
                         }
+
+                        gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
                     }
                 }
                 else {
@@ -2845,7 +2833,7 @@
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                 }
-                else if (textureType === HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
+                else if (textureType === Engine.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                 }
@@ -3274,130 +3262,97 @@
             }
         }
 
-        private _canRenderToFloatTexture(): boolean {
+        private _canRenderToFloatFramebuffer(): boolean {
             if (this._webGLVersion > 1) {
-                return true;
+                return this._caps.colorBufferFloat;
             }
-            return this._canRenderToTextureOfType(BABYLON.Engine.TEXTURETYPE_FLOAT, 'OES_texture_float');
+            return this._canRenderToFramebuffer(BABYLON.Engine.TEXTURETYPE_FLOAT);
         }
 
-        private _canRenderToHalfFloatTexture(): boolean {       
+        private _canRenderToHalfFloatFramebuffer(): boolean {       
             if (this._webGLVersion > 1) {
-                return true;
+                return this._caps.colorBufferFloat;
             }     
-            return this._canRenderToTextureOfType(BABYLON.Engine.TEXTURETYPE_HALF_FLOAT, 'OES_texture_half_float');
+            return this._canRenderToFramebuffer(BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
         }
 
         // Thank you : http://stackoverflow.com/questions/28827511/webgl-ios-render-to-floating-point-texture
-        private _canRenderToTextureOfType(format: number, extension: string): boolean {
-            try {
-                var tempcanvas = document.createElement("canvas");
-                tempcanvas.height = 16;
-                tempcanvas.width = 16;
-                var gl = <WebGLRenderingContext>(tempcanvas.getContext("webgl") || tempcanvas.getContext("experimental-webgl"));
-
-                // extension.
-                var ext = gl.getExtension(extension);
-                if (!ext) {
-                    return false;
-                }
+        private _canRenderToFramebuffer(type: number): boolean {
+            let gl = this._gl;
 
-                // setup GLSL program
-                var vertexCode = `attribute vec4 a_position;
-                    void main() {
-                        gl_Position = a_position;
-                    }`;
-                var fragmentCode = `precision mediump float;
-                    uniform vec4 u_color;
-                    uniform sampler2D u_texture;
-
-                    void main() {
-                        gl_FragColor = texture2D(u_texture, vec2(0.5, 0.5)) * u_color;
-                    }`;
-                var program = this.createShaderProgram(vertexCode, fragmentCode, null, gl);
-                gl.useProgram(program);
-
-                // look up where the vertex data needs to go.
-                var positionLocation = gl.getAttribLocation(program, "a_position");
-                var colorLoc = gl.getUniformLocation(program, "u_color");
-
-                // provide texture coordinates for the rectangle.
-                var positionBuffer = gl.createBuffer();
-                gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
-                gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-                    -1.0, -1.0,
-                    1.0, -1.0,
-                    -1.0, 1.0,
-                    -1.0, 1.0,
-                    1.0, -1.0,
-                    1.0, 1.0]), gl.STATIC_DRAW);
-                gl.enableVertexAttribArray(positionLocation);
-                gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
-
-                var whiteTex = gl.createTexture();
-                gl.bindTexture(gl.TEXTURE_2D, whiteTex);
-                gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 255, 255, 255]));
-
-                var tex = gl.createTexture();
-                gl.bindTexture(gl.TEXTURE_2D, tex);
-                gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, getWebGLTextureType(gl, format), null);
-                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
-                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-
-                var fb = gl.createFramebuffer();
-                gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
-                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
-                gl.viewport(0, 0, 1, 1);
-
-                var cleanup = () => {
-                    gl.deleteProgram(program);
-                    gl.disableVertexAttribArray(positionLocation);
-                    gl.deleteBuffer(positionBuffer);
-                    gl.deleteFramebuffer(fb);
-                    gl.deleteTexture(whiteTex);
-                    gl.deleteTexture(tex);
-                };
+            //clear existing errors
+            while(gl.getError() !== gl.NO_ERROR){}
 
-                var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
-                if (status !== gl.FRAMEBUFFER_COMPLETE) {
-                    Tools.Log("GL Support: can **NOT** render to " + format + " texture");
-                    cleanup();
-                    return false;
-                }
+            let successful = true;
 
-                // Draw the rectangle.
-                gl.bindTexture(gl.TEXTURE_2D, whiteTex);
-                gl.uniform4fv(colorLoc, <any>[0, 10, 20, 1]);
-                gl.drawArrays(gl.TRIANGLES, 0, 6);
+            let texture = gl.createTexture();
+            gl.bindTexture(gl.TEXTURE_2D, texture);
+            gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(type), 1, 1, 0, gl.RGBA, this._getWebGLTextureType(type), null);
+            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
 
-                gl.bindTexture(gl.TEXTURE_2D, tex);
-                gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+            let fb = gl.createFramebuffer();
+            gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+            let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+
+            successful = successful && (status === gl.FRAMEBUFFER_COMPLETE);
+            successful = successful && (gl.getError() === gl.NO_ERROR);
 
-                gl.clearColor(1, 0, 0, 1);
+            //try render by clearing frame buffer's color buffer
+            if(successful){
                 gl.clear(gl.COLOR_BUFFER_BIT);
+                successful = successful && (gl.getError() === gl.NO_ERROR);
+            }
 
-                gl.uniform4fv(colorLoc, <any>[0, 1 / 10, 1 / 20, 1]);
-                gl.drawArrays(gl.TRIANGLES, 0, 6);
-
-                var pixel = new Uint8Array(4);
-                gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
-                if (pixel[0] !== 0 ||
-                    pixel[1] < 248 ||
-                    pixel[2] < 248 ||
-                    pixel[3] < 254) {
-                    BABYLON.Tools.Log("GL Support: Was not able to actually render to " + format + " texture");
-                    cleanup();
-                    return false;
-                }
+            //try reading from frame to ensure render occurs (just creating the FBO is not sufficient to determine if rendering is supported)
+            if(successful){
+                //in practice it's sufficient to just read from the backbuffer rather than handle potentially issues reading from the texture
+                gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+                let readFormat = gl.RGBA;
+                let readType = gl.UNSIGNED_BYTE;
+                let buffer = new Uint8Array(4);
+                gl.readPixels(0, 0, 1, 1, readFormat, readType, buffer);
+                successful = successful && (gl.getError() === gl.NO_ERROR);
+            }
 
-                // Succesfully rendered to "format" texture.
-                cleanup();
-                return true;
+            //clean up
+            gl.deleteTexture(texture);
+            gl.deleteFramebuffer(fb);
+            gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+            //clear accumulated errors
+            while(!successful && (gl.getError() !== gl.NO_ERROR)) { }
+
+            return successful;
+        }
+
+        private _getWebGLTextureType(type: number) : number {
+            if (type === Engine.TEXTURETYPE_FLOAT) {
+                return this._gl.FLOAT;
             }
-            catch (e) {
-                return false;
+            else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
+                // Add Half Float Constant.
+                return Engine.HALF_FLOAT_OES;
             }
-        }
+
+            return this._gl.UNSIGNED_BYTE;
+        };
+
+        private _getRGBABufferInternalSizedFormat(type: number) : number {
+            if (this._webGLVersion === 1) {
+                return this._gl.RGBA;
+            }
+
+            if (type === Engine.TEXTURETYPE_FLOAT) {
+                return Engine.RGBA32F;
+            }
+            else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
+                return Engine.RGBA16F;
+            }
+
+            return this._gl.RGBA;
+        };
 
         // Statics
         public static isSupported(): boolean {