Przeglądaj źródła

Adding sounds export to Blender

David Catuhe 10 lat temu
rodzic
commit
eada442c57

+ 8 - 10
Babylon/Audio/babylon.sound.js

@@ -231,13 +231,13 @@ var BABYLON;
         };
         Sound.prototype.setPosition = function (newPosition) {
             this._position = newPosition;
-            if (this.spatialSound) {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio && this.spatialSound) {
                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
             }
         };
         Sound.prototype.setLocalDirectionToMesh = function (newLocalDirection) {
             this._localDirection = newLocalDirection;
-            if (this._connectedMesh && this.isPlaying) {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio && this._connectedMesh && this.isPlaying) {
                 this._updateDirection();
             }
         };
@@ -248,7 +248,7 @@ var BABYLON;
             this._soundPanner.setOrientation(direction.x, direction.y, direction.z);
         };
         Sound.prototype.updateDistanceFromListener = function () {
-            if (this._connectedMesh && this.useCustomAttenuation) {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio && this._connectedMesh && this.useCustomAttenuation) {
                 var distance = this._connectedMesh.getDistanceToCamera(this._scene.activeCamera);
                 this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance, this.refDistance, this.rolloffFactor);
             }
@@ -300,11 +300,9 @@ var BABYLON;
             }
         };
         Sound.prototype._onended = function () {
-            if (!this.loop) {
-                this.isPlaying = false;
-                if (this.onended) {
-                    this.onended();
-                }
+            this.isPlaying = false;
+            if (this.onended) {
+                this.onended();
             }
         };
         /**
@@ -326,7 +324,7 @@ var BABYLON;
             }
         };
         Sound.prototype.setVolume = function (newVolume, time) {
-            if (BABYLON.Engine.audioEngine.canUseWebAudio) {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio && !this.spatialSound) {
                 if (time) {
                     this._soundGain.gain.linearRampToValueAtTime(this._volume, BABYLON.Engine.audioEngine.audioContext.currentTime);
                     this._soundGain.gain.linearRampToValueAtTime(newVolume, time);
@@ -363,7 +361,7 @@ var BABYLON;
         };
         Sound.prototype._onRegisterAfterWorldMatrixUpdate = function (connectedMesh) {
             this.setPosition(connectedMesh.getBoundingInfo().boundingSphere.centerWorld);
-            if (this._isDirectional && this.isPlaying) {
+            if (BABYLON.Engine.audioEngine.canUseWebAudio && this._isDirectional && this.isPlaying) {
                 this._updateDirection();
             }
         };

+ 8 - 10
Babylon/Audio/babylon.sound.ts

@@ -251,7 +251,7 @@
         public setPosition(newPosition: Vector3) {
             this._position = newPosition;
 
-            if (this.spatialSound) {
+            if (Engine.audioEngine.canUseWebAudio && this.spatialSound) {
                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);
             }
         }
@@ -259,7 +259,7 @@
         public setLocalDirectionToMesh(newLocalDirection: Vector3) {
             this._localDirection = newLocalDirection;
 
-            if (this._connectedMesh && this.isPlaying) {
+            if (Engine.audioEngine.canUseWebAudio && this._connectedMesh && this.isPlaying) {
                 this._updateDirection();
             }
         }
@@ -272,7 +272,7 @@
         }
 
         public updateDistanceFromListener() {
-            if (this._connectedMesh && this.useCustomAttenuation) {
+            if (Engine.audioEngine.canUseWebAudio && this._connectedMesh && this.useCustomAttenuation) {
                 var distance = this._connectedMesh.getDistanceToCamera(this._scene.activeCamera);
                 this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance, this.refDistance, this.rolloffFactor);
             }
@@ -324,11 +324,9 @@
         }
 
         private _onended() {
-            if (!this.loop) {
-                this.isPlaying = false;
-                if (this.onended) {
-                    this.onended();
-                }
+            this.isPlaying = false;
+            if (this.onended) {
+                this.onended();
             }
         }
 
@@ -353,7 +351,7 @@
         }
 
         public setVolume(newVolume: number, time?: number) {
-            if (Engine.audioEngine.canUseWebAudio) {
+            if (Engine.audioEngine.canUseWebAudio && !this.spatialSound) {
                 if (time) {
                     this._soundGain.gain.linearRampToValueAtTime(this._volume, Engine.audioEngine.audioContext.currentTime);
                     this._soundGain.gain.linearRampToValueAtTime(newVolume, time);
@@ -393,7 +391,7 @@
 
         private _onRegisterAfterWorldMatrixUpdate(connectedMesh: AbstractMesh) {
             this.setPosition(connectedMesh.getBoundingInfo().boundingSphere.centerWorld);
-            if (this._isDirectional && this.isPlaying) {
+            if (Engine.audioEngine.canUseWebAudio && this._isDirectional && this.isPlaying) {
                 this._updateDirection();
             }
         }

+ 0 - 4
Babylon/Materials/Textures/Procedurals/babylon.standardProceduralTexture.js

@@ -321,10 +321,6 @@ var BABYLON;
             get: function () {
                 return this._numberOfBricksHeight;
             },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(BrickProceduralTexture.prototype, "cloudColor", {
             set: function (value) {
                 this._numberOfBricksHeight = value;
                 this.updateShaderUniforms();

+ 1 - 1
Babylon/Materials/Textures/Procedurals/babylon.standardProceduralTexture.ts

@@ -285,7 +285,7 @@
             return this._numberOfBricksHeight;
         }
 
-        public set cloudColor(value: number) {
+        public set numberOfBricksHeight(value: number) {
             this._numberOfBricksHeight = value;
             this.updateShaderUniforms();
         }

+ 9 - 0
Babylon/Math/babylon.math.js

@@ -2730,6 +2730,15 @@ var BABYLON;
         Curve3.prototype.getPoints = function () {
             return this._points;
         };
+        Curve3.prototype.continue = function (curve) {
+            var lastPoint = this._points[this._points.length - 1];
+            var continuedPoints = this._points.slice();
+            var curvePoints = curve.getPoints();
+            for (var i = 1; i < curvePoints.length; i++) {
+                continuedPoints.push(curvePoints[i].add(lastPoint));
+            }
+            return new Curve3(continuedPoints);
+        };
         return Curve3;
     })();
     BABYLON.Curve3 = Curve3;

+ 1 - 1
Babylon/Math/babylon.math.ts

@@ -3413,7 +3413,7 @@
             return this._points;
         }
 
-        public continue(curve: Curve3) {
+        public continue(curve: Curve3): Curve3 {
             var lastPoint = this._points[this._points.length - 1];
             var continuedPoints = this._points.slice();
             var curvePoints = curve.getPoints();

+ 1 - 1
Babylon/Mesh/babylon.abstractMesh.js

@@ -40,7 +40,7 @@ var BABYLON;
             this.useOctreeForRenderingSelection = true;
             this.useOctreeForPicking = true;
             this.useOctreeForCollisions = true;
-            this.layerMask = 0xFFFFFFFF;
+            this.layerMask = 0x0FFFFFFF;
             // Physics
             this._physicImpostor = BABYLON.PhysicsEngine.NoImpostor;
             // Collisions

+ 15 - 4
Babylon/PostProcess/babylon.ssaoRenderingPipeline.js

@@ -12,7 +12,7 @@ var BABYLON;
          * @constructor
          * @param {string} name - The rendering pipeline name
          * @param {BABYLON.Scene} scene - The scene linked to this pipeline
-         * @param {any} ratio - The size of the postprocesses (0.5 means that your postprocess will have a width = canvas.width 0.5 and a height = canvas.height 0.5)
+         * @param {any} ratio - The size of the postprocesses. Can be a number shared between passes or an object for more precision: { ssaoRatio: 0.5, combineRatio: 1.0 }
          * @param {BABYLON.Camera[]} cameras - The array of cameras that the rendering pipeline will be attached to
          */
         function SSAORenderingPipeline(name, scene, ratio, cameras) {
@@ -44,6 +44,15 @@ var BABYLON;
             * @type {string}
             */
             this.SSAOCombineRenderEffect = "SSAOCombineRenderEffect";
+            /**
+            The output strength of the SSAO post-process. Default value is 1.0.
+            @type {number}
+            */
+            this.totalStrength = 1.0;
+            /**
+            The radius around the analyzed pixel used by the SSAO post-process. Default value is 0.002
+            */
+            this.radius = 0.002;
             this._firstUpdate = true;
             this._scene = scene;
             // Set up assets
@@ -53,8 +62,8 @@ var BABYLON;
             var combineRatio = ratio.combineRatio || ratio;
             this._originalColorPostProcess = new BABYLON.PassPostProcess("SSAOOriginalSceneColor", combineRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
             this._createSSAOPostProcess(ssaoRatio);
-            this._blurHPostProcess = new BABYLON.BlurPostProcess("SSAOBlurH", new BABYLON.Vector2(2.0, 0.0), 1.3, ssaoRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
-            this._blurVPostProcess = new BABYLON.BlurPostProcess("SSAOBlurV", new BABYLON.Vector2(0.0, 2.0), 1.3, ssaoRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
+            this._blurHPostProcess = new BABYLON.BlurPostProcess("SSAOBlurH", new BABYLON.Vector2(1.0, 0.0), 4.0, ssaoRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
+            this._blurVPostProcess = new BABYLON.BlurPostProcess("SSAOBlurV", new BABYLON.Vector2(0.0, 1.0), 4.0, ssaoRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
             this._createSSAOCombinePostProcess(combineRatio);
             // Set up pipeline
             this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), this.SSAOOriginalSceneColorEffect, function () {
@@ -161,7 +170,7 @@ var BABYLON;
                 -0.0271
             ];
             var samplesFactor = 1.0 / 16.0;
-            this._ssaoPostProcess = new BABYLON.PostProcess("ssao", "ssao", ["sampleSphere", "samplesFactor", "randTextureTiles"], ["randomSampler"], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false);
+            this._ssaoPostProcess = new BABYLON.PostProcess("ssao", "ssao", ["sampleSphere", "samplesFactor", "randTextureTiles", "totalStrength", "radius"], ["randomSampler"], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false);
             this._ssaoPostProcess.onApply = function (effect) {
                 if (_this._firstUpdate) {
                     effect.setArray3("sampleSphere", sampleSphere);
@@ -169,6 +178,8 @@ var BABYLON;
                     effect.setFloat("randTextureTiles", 4.0 / ratio);
                     _this._firstUpdate = false;
                 }
+                effect.setFloat("totalStrength", _this.totalStrength);
+                effect.setFloat("radius", _this.radius);
                 effect.setTexture("textureSampler", _this._depthTexture);
                 effect.setTexture("randomSampler", _this._randomTexture);
             };

+ 18 - 4
Babylon/PostProcess/babylon.ssaoRenderingPipeline.ts

@@ -28,6 +28,17 @@
         */
         public SSAOCombineRenderEffect: string = "SSAOCombineRenderEffect";
 
+        /**
+        The output strength of the SSAO post-process. Default value is 1.0.
+        @type {number}
+        */
+        public totalStrength: number = 1.0;
+
+        /**
+        The radius around the analyzed pixel used by the SSAO post-process. Default value is 0.002
+        */
+        public radius: number = 0.002;
+
         private _scene: Scene;
         private _depthTexture: RenderTargetTexture;
         private _randomTexture: DynamicTexture;
@@ -44,7 +55,7 @@
          * @constructor
          * @param {string} name - The rendering pipeline name
          * @param {BABYLON.Scene} scene - The scene linked to this pipeline
-         * @param {any} ratio - The size of the postprocesses (0.5 means that your postprocess will have a width = canvas.width 0.5 and a height = canvas.height 0.5)
+         * @param {any} ratio - The size of the postprocesses. Can be a number shared between passes or an object for more precision: { ssaoRatio: 0.5, combineRatio: 1.0 }
          * @param {BABYLON.Camera[]} cameras - The array of cameras that the rendering pipeline will be attached to
          */
         constructor(name: string, scene: Scene, ratio: any, cameras?: Camera[]) {
@@ -61,8 +72,8 @@
 
             this._originalColorPostProcess = new PassPostProcess("SSAOOriginalSceneColor", combineRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
             this._createSSAOPostProcess(ssaoRatio);
-            this._blurHPostProcess = new BlurPostProcess("SSAOBlurH", new Vector2(2.0, 0.0), 1.3, ssaoRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
-            this._blurVPostProcess = new BlurPostProcess("SSAOBlurV", new Vector2(0.0, 2.0), 1.3, ssaoRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
+            this._blurHPostProcess = new BlurPostProcess("SSAOBlurH", new Vector2(1.0, 0.0), 4.0, ssaoRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
+            this._blurVPostProcess = new BlurPostProcess("SSAOBlurV", new Vector2(0.0, 1.0), 4.0, ssaoRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
             this._createSSAOCombinePostProcess(combineRatio);
 
             // Set up pipeline
@@ -135,7 +146,7 @@
             ];
             var samplesFactor = 1.0 / 16.0;
 
-            this._ssaoPostProcess = new PostProcess("ssao", "ssao", ["sampleSphere", "samplesFactor", "randTextureTiles"],
+            this._ssaoPostProcess = new PostProcess("ssao", "ssao", ["sampleSphere", "samplesFactor", "randTextureTiles", "totalStrength", "radius"],
                                                     ["randomSampler"],
                                                     ratio, null, Texture.BILINEAR_SAMPLINGMODE,
                                                     this._scene.getEngine(), false);
@@ -148,6 +159,9 @@
                     this._firstUpdate = false;
                 }
 
+                effect.setFloat("totalStrength", this.totalStrength);
+                effect.setFloat("radius", this.radius);
+
                 effect.setTexture("textureSampler", this._depthTexture);
                 effect.setTexture("randomSampler", this._randomTexture);
             };

+ 16 - 15
Babylon/Shaders/default.fragment.fx

@@ -253,28 +253,29 @@ float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, flo
 	poissonDisk[3] = vec2(0.34495938, 0.29387760);
 
 	// Poisson Sampling
-	if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] / mapSize)) + bias  <  depth.z) visibility -= 0.25;
-	if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] / mapSize)) + bias  <  depth.z) visibility -= 0.25;
-	if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] / mapSize)) + bias  <  depth.z) visibility -= 0.25;
-	if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] / mapSize)) + bias  <  depth.z) visibility -= 0.25;
+	float biasedDepth = depth.z - bias;
+
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] / mapSize)) < biasedDepth) visibility -= 0.25;
 
 	return visibility;
 }
 
 // Thanks to http://devmaster.net/
-float ChebychevInequality(vec2 moments, float t, float bias)
-{
-	if (t - bias <= moments.x)
-	{
-		return 0.0;
-	}
-
-	float variance = moments.y - (moments.x * moments.x);
-	variance = max(variance, 0.002);
+float linstep(float low, float high, float v) {
+	return clamp((v - low) / (high - low), 0.0, 1.0);
+}
 
-	float d = t - moments.x;
+float ChebychevInequality(vec2 moments, float compare, float bias)
+{
+	float p = smoothstep(compare - bias, compare, moments.x);
+	float variance = max(moments.y - moments.x * moments.x, 0.02);
+	float d = compare - moments.x;
+	float p_max = linstep(0.2, 1.0, variance / (variance + d * d));
 
-	return clamp(variance / (variance + d * d) - 0.05, 0.0, 1.0);
+	return clamp(max(p, p_max), 0.0, 1.0);
 }
 
 float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float bias)

+ 4 - 3
Babylon/Shaders/ssao.fragment.fx

@@ -11,6 +11,9 @@ uniform float randTextureTiles;
 uniform float samplesFactor;
 uniform vec3 sampleSphere[16];
 
+uniform float totalStrength;
+uniform float radius;
+
 varying vec2 vUV;
 
 const vec2 offset1 = vec2(0.0, 0.01);
@@ -31,11 +34,9 @@ vec3 normalFromDepth(const float depth, const vec2 coords) {
 
 void main(void)
 {
-	const float totalStrength = 1.0;
 	const float base = 0.2;
 	const float area = 0.0075;
 	const float fallOff = 0.000001;
-	const float radius = 0.0005;
 
 	vec3 random = texture2D(randomSampler, vUV * randTextureTiles).rgb;
 	float depth = texture2D(textureSampler, vUV).r;
@@ -52,7 +53,7 @@ void main(void)
 	for (int i = 0; i < SAMPLES; i++)
 	{
 		ray = radiusDepth * reflect(sampleSphere[i], random);
-		hemiRay = position + dot(ray, normal) * ray;
+		hemiRay = position + sign(dot(ray, normal)) * ray;
 
 		occlusionDepth = texture2D(textureSampler, clamp(hemiRay.xy, 0.0, 1.0)).r;
 		difference = depth - occlusionDepth;

+ 3 - 2
Babylon/babylon.scene.js

@@ -970,7 +970,8 @@ var BABYLON;
                     var renderTarget = this._renderTargets.data[renderIndex];
                     if (renderTarget._shouldRender()) {
                         this._renderId++;
-                        renderTarget.render(false, this.dumpNextRenderTargets);
+                        var hasSpecialRenderTargetCamera = renderTarget.activeCamera && renderTarget.activeCamera !== this.activeCamera;
+                        renderTarget.render(hasSpecialRenderTargetCamera, this.dumpNextRenderTargets);
                     }
                 }
                 BABYLON.Tools.EndPerformanceCounter("Render targets", this._renderTargets.length > 0);
@@ -1133,7 +1134,7 @@ var BABYLON;
                         engine.setViewport(this.activeCamera.viewport);
                         // Camera
                         this.updateTransformMatrix();
-                        renderTarget.render(false, this.dumpNextRenderTargets);
+                        renderTarget.render(currentActiveCamera !== this.activeCamera, this.dumpNextRenderTargets);
                     }
                 }
                 BABYLON.Tools.EndPerformanceCounter("Custom render targets", this.customRenderTargets.length > 0);

+ 1 - 1
Babylon/babylon.scene.ts

@@ -2092,4 +2092,4 @@
             return this._getByTags(this.materials, tagsQuery, forEach).concat(this._getByTags(this.multiMaterials, tagsQuery, forEach));
         }
     }
-} 
+} 

+ 86 - 5
Exporters/Blender/io_export_babylon.py

@@ -139,11 +139,33 @@ class BabylonExporter(bpy.types.Operator, bpy_extras.io_utils.ExportHelper):
         default = False,
         )
     
+    attachedSound = bpy.props.StringProperty(
+        name='Music', 
+        description='',
+        default = ''
+    )
+    loopSound = bpy.props.BoolProperty(
+        name='Loop sound', 
+        description='',
+        default = True
+    )
+    autoPlaySound = bpy.props.BoolProperty(
+        name='Auto play sound', 
+        description='',
+        default = True
+    )
+
     def draw(self, context):
         layout = self.layout
 
         layout.prop(self, 'export_onlyCurrentLayer') 
 
+        layout.separator()
+
+        layout.prop(self, 'attachedSound') 
+        layout.prop(self, 'autoPlaySound') 
+        layout.prop(self, 'loopSound') 
+
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     nWarnings = 0      
     @staticmethod
@@ -217,6 +239,16 @@ class BabylonExporter(bpy.types.Operator, bpy_extras.io_utils.ExportHelper):
             skeletonId = 0
             self.meshesAndNodes = []
             self.multiMaterials = []
+            self.meshesWithSound = []
+
+            # Music
+            if self.attachedSound != '':
+                music = type('', (), {})()  #Fake mesh object 
+                music.data = type('', (), {})() 
+                music.data.attachedSound = self.attachedSound
+                music.data.loopSound = self.loopSound
+                music.data.autoPlaySound = self.autoPlaySound
+                self.meshesWithSound.append(music)
             
             # exclude lamps in this pass, so ShadowGenerator constructor can be passed meshesAnNodes
             for object in [object for object in scene.objects]:
@@ -241,6 +273,10 @@ class BabylonExporter(bpy.types.Operator, bpy_extras.io_utils.ExportHelper):
                     while True and self.isInSelectedLayer(object, scene):
                         mesh = Mesh(object, scene, self.multiMaterials, nextStartFace, forcedParent, nameID)
                         self.meshesAndNodes.append(mesh)
+
+                        if object.data.attachedSound != '':
+                            self.meshesWithSound.append(object)
+
                         nextStartFace = mesh.offsetFace
                         if nextStartFace == 0:
                             break
@@ -251,6 +287,7 @@ class BabylonExporter(bpy.types.Operator, bpy_extras.io_utils.ExportHelper):
                             BabylonExporter.warn('WARNING: The following mesh has exceeded the maximum # of vertex elements & will be broken into multiple Babylon meshes: ' + object.name)
 
                         nameID = nameID + 1
+
                 elif object.type == 'EMPTY':
                     self.meshesAndNodes.append(Node(object))
                     
@@ -393,6 +430,26 @@ class BabylonExporter(bpy.types.Operator, bpy_extras.io_utils.ExportHelper):
             first = False
             shadowGen.to_scene_file(file_handler)
         file_handler.write(']')
+
+        # Sounds
+        if len(self.meshesWithSound) > 0:
+            file_handler.write('\n,"sounds":[')
+            first = True
+            for mesh in self.meshesWithSound:
+                if first == False:
+                    file_handler.write(',')
+                file_handler.write('{')        
+                write_string(file_handler, 'name', mesh.data.attachedSound, True)        
+                write_bool(file_handler, 'autoplay', mesh.data.autoPlaySound)
+                write_bool(file_handler, 'loop', mesh.data.loopSound) 
+
+                if hasattr(mesh, 'name'):
+                    write_string(file_handler, 'connectedMeshId', mesh.name) 
+                    write_float(file_handler, 'maxDistance', mesh.data.maxSoundDistance) 
+                
+                file_handler.write('}')   
+
+            file_handler.write(']')
         
         # Closing
         file_handler.write('}')
@@ -434,6 +491,7 @@ class World:
             write_float(file_handler, 'fogStart', self.fogStart)
             write_float(file_handler, 'fogEnd', self.fogEnd)
             write_float(file_handler, 'fogDensity', self.fogDensity)
+
 #===============================================================================
 class FCurveAnimatable:
     def __init__(self, object, supportsRotation, supportsPosition, supportsScaling, xOffsetForRotation = 0):  
@@ -564,7 +622,7 @@ class Mesh(FCurveAnimatable):
         
         world = object.matrix_world
         if object.parent and not hasSkeleton:
-            world = object.matrix_local
+            world *= object.parent.matrix_world.inverted()
             
         # use defaults when not None
         if forcedParent is None:
@@ -1370,10 +1428,6 @@ class Material:
                         # Specular
                         BabylonExporter.log('Specular texture found');
                         self.textures.append(Texture('specularTexture', mtex.specular_color_factor, mtex, filepath))
-                    else:
-                        BabylonExporter.warn('WARNING image texture type not recognized:  ' + str(mtex) + ', ignored.')
-
-                        
             else:
                  BabylonExporter.warn('WARNING texture type not currently supported:  ' + mtex.texture.type + ', ignored.')
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -                
@@ -1641,6 +1695,26 @@ bpy.types.Mesh.receiveShadows = bpy.props.BoolProperty(
     description='',
     default = False
 )
+bpy.types.Mesh.attachedSound = bpy.props.StringProperty(
+    name='Sound', 
+    description='',
+    default = ''
+)
+bpy.types.Mesh.loopSound = bpy.props.BoolProperty(
+    name='Loop sound', 
+    description='',
+    default = True
+)
+bpy.types.Mesh.autoPlaySound = bpy.props.BoolProperty(
+    name='Auto play sound', 
+    description='',
+    default = True
+)
+bpy.types.Mesh.maxSoundDistance = bpy.props.FloatProperty(
+    name='Max sound distance', 
+    description='',
+    default = 100
+)
 #===============================================================================
 bpy.types.Camera.autoAnimate = bpy.props.BoolProperty(
     name='Automatically launch animations', 
@@ -1730,6 +1804,13 @@ class ObjectPanel(bpy.types.Panel):
             layout.separator()
 
             layout.prop(ob.data, 'autoAnimate')   
+
+            layout.separator()
+
+            layout.prop(ob.data, 'attachedSound') 
+            layout.prop(ob.data, 'autoPlaySound') 
+            layout.prop(ob.data, 'loopSound') 
+            layout.prop(ob.data, 'maxSoundDistance') 
             
         elif isCamera:
             layout.prop(ob.data, 'CameraType')

Plik diff jest za duży
+ 38 - 23
babylon.2.1-alpha.debug.js


Plik diff jest za duży
+ 13 - 13
babylon.2.1-alpha.js