Kacey Coley 6 роки тому
батько
коміт
a9bfc8cf89

+ 39 - 38
serializers/src/glTF/2.0/Extensions/KHR_lights_punctual.ts

@@ -1,5 +1,5 @@
 import { SpotLight } from "babylonjs/Lights/spotLight";
-import { Vector3 } from "babylonjs/Maths/math";
+import { Vector3, Color3 } from "babylonjs/Maths/math";
 import { Light } from "babylonjs/Lights/light";
 import { Node } from "babylonjs/node";
 import { ShadowLight } from "babylonjs/Lights/shadowLight";
@@ -7,7 +7,8 @@ import { IChildRootProperty } from "babylonjs-gltf2interface";
 import { INode } from "babylonjs-gltf2interface";
 import { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
 import { _Exporter } from "../glTFExporter";
-import { Tools, Nullable, DirectionalLight, Quaternion } from 'babylonjs';
+import { Tools, Nullable, Quaternion } from 'babylonjs';
+import { _GLTFUtilities } from "../glTFUtilities";
 
 const NAME = "KHR_lights_punctual";
 
@@ -37,7 +38,7 @@ interface ILights {
 }
 
 /**
- * [Specification](https://github.com/KhronosGroup/glTF/blob/1048d162a44dbcb05aefc1874bfd423cf60135a6/extensions/2.0/Khronos/KHR_lights_punctual/README.md) (Experimental)
+ * [Specification](https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_lights_punctual/README.md)
  */
 export class KHR_lights implements IGLTFExporterExtensionV2 {
     /** The name of this extension. */
@@ -71,14 +72,14 @@ export class KHR_lights implements IGLTFExporterExtensionV2 {
             if (this._exporter._glTF.extensionsUsed == null) {
                 this._exporter._glTF.extensionsUsed = [];
             }
-            if (this._exporter._glTF.extensionsUsed.indexOf(NAME) == -1) {
+            if (this._exporter._glTF.extensionsUsed.indexOf(NAME) === -1) {
                 this._exporter._glTF.extensionsUsed.push(NAME);
             }
             if (this.required) {
                 if (this._exporter._glTF.extensionsRequired == null) {
                     this._exporter._glTF.extensionsRequired = [];
                 }
-                if (this._exporter._glTF.extensionsRequired.indexOf(NAME) == -1) {
+                if (this._exporter._glTF.extensionsRequired.indexOf(NAME) === -1) {
                     this._exporter._glTF.extensionsRequired.push(NAME);
                 }
             }
@@ -88,76 +89,77 @@ export class KHR_lights implements IGLTFExporterExtensionV2 {
             this._exporter._glTF.extensions[NAME] = this._lights;
         }
     }
+    /**
+     * Define this method to modify the default behavior when exporting a node
+     * @param context The context when exporting the node
+     * @param node glTF node
+     * @param babylonNode BabylonJS node
+     */
     public postExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>> {
         return new Promise((resolve, reject) => {
             if (babylonNode instanceof ShadowLight) {
-                let babylonLight: ShadowLight = babylonNode;
+                const babylonLight: ShadowLight = babylonNode;
                 let light: ILight;
 
-                let lightType = (
+                const lightType = (
                     babylonLight.getTypeID() == Light.LIGHTTYPEID_POINTLIGHT ? LightType.POINT : (
                         babylonLight.getTypeID() == Light.LIGHTTYPEID_DIRECTIONALLIGHT ? LightType.DIRECTIONAL : (
                             babylonLight.getTypeID() == Light.LIGHTTYPEID_SPOTLIGHT ? LightType.SPOT : null
                         )));
                 if (lightType == null) {
-                    Tools.Warn(`${context}: Light ${babylonLight.name} is not supported in {NAME}`);
+                    Tools.Warn(`${context}: Light ${babylonLight.name} is not supported in ${NAME}`);
                 }
                 else {
-                    let lightPosition = babylonLight.position.clone();
-                    if (!lightPosition.equalsToFloats(1.0, 1.0, 1.0)) {
+                    const lightPosition = babylonLight.position.clone();
+                    if (!lightPosition.equals(Vector3.Zero())) {
                         if (this._exporter._convertToRightHandedSystem) {
-                            lightPosition.z *= -1;
+                            _GLTFUtilities._GetRightHandedPositionVector3FromRef(lightPosition);
                         }
                         node.translation = lightPosition.asArray();
                     }
-                    if (babylonLight.falloffType != Light.FALLOFF_GLTF) {
+                    if (lightType !== LightType.POINT) {
+                        const lightRotation = babylonLight.getRotation();
+                        let lightRotationQuaternion = Quaternion.RotationYawPitchRoll(lightRotation.y, lightRotation.x, lightRotation.z);
+                        if (this._exporter._convertToRightHandedSystem) {
+                            _GLTFUtilities._GetRightHandedQuaternionFromRef(lightRotationQuaternion);
+                        }
+                        if (!lightRotationQuaternion.equals(Quaternion.Identity())) {
+                            node.rotation = lightRotationQuaternion.asArray();
+                        }
+                    }
+
+                    if (babylonLight.falloffType !== Light.FALLOFF_GLTF) {
                         Tools.Warn(`${context}: Light falloff for ${babylonLight.name} does not match the ${NAME} specification!`);
                     }
                     light = {
                         type: lightType
                     };
-                    if (!babylonLight.diffuse.equalsFloats(1.0, 1.0, 1.0)) {
+                    if (!babylonLight.diffuse.equals(Color3.White())) {
                         light.color = babylonLight.diffuse.asArray();
                     }
-                    if (!(babylonLight.intensity == 1.0)) {
+                    if (babylonLight.intensity !== 1.0) {
                         light.intensity = babylonLight.intensity;
                     }
-                    if (!(babylonLight.range == Number.MAX_VALUE)) {
+                    if (babylonLight.range !== Number.MAX_VALUE) {
                         light.range = babylonLight.range;
                     }
 
                     if (lightType === LightType.SPOT) {
-                        let babylonSpotLight = babylonLight as SpotLight;
-                        if (!(babylonSpotLight.angle == Math.PI / 2.0)) {
+                        const babylonSpotLight = babylonLight as SpotLight;
+                        if (babylonSpotLight.angle !== Math.PI / 2.0) {
                             if (light.spot == null) {
                                 light.spot = {};
                             }
-                            light.spot.outerConeAngle = babylonSpotLight.angle / 4;
+                            light.spot.outerConeAngle = babylonSpotLight.angle / 2.0;
                         }
-                        if (!(babylonSpotLight.innerAngle == 0)) {
+                        if (babylonSpotLight.innerAngle !== 0) {
                             if (light.spot == null) {
                                 light.spot = {};
                             }
-                            light.spot.innerConeAngle = babylonSpotLight.innerAngle / 2;
-                        }
-                        let rotation = babylonSpotLight.getRotation().clone();
-                        if (!rotation.equals(Vector3.Zero())) {
-                            if (this._exporter._convertToRightHandedSystem) {
-                                rotation.z *= -1;
-                            }
-                            node.rotation = Quaternion.FromEulerAngles(rotation.x, rotation.y, rotation.z).asArray();
-                        }
-                    }
-                    else if (lightType === LightType.DIRECTIONAL) {
-                        let babylonDirectionalLight = babylonLight as DirectionalLight;
-                        let rotation = babylonDirectionalLight.getRotation().clone();
-                        if (!rotation.equals(Vector3.Zero())) {
-                            if (this._exporter._convertToRightHandedSystem) {
-                                rotation.z *= -1;
-                            }
-                            node.rotation = Quaternion.FromEulerAngles(rotation.x, rotation.y, rotation.z).asArray();
+                            light.spot.innerConeAngle = babylonSpotLight.innerAngle / 2.0;
                         }
                     }
+
                     if (this._lights == null) {
                         this._lights = {
                             lights: []
@@ -175,7 +177,6 @@ export class KHR_lights implements IGLTFExporterExtensionV2 {
 
                     node.extensions[NAME] = lightReference;
                 }
-
             }
             resolve(node);
         });

+ 5 - 3
serializers/src/glTF/2.0/glTFExporter.ts

@@ -1268,7 +1268,7 @@ export class _Exporter {
                 // Build Hierarchy with the node map.
                 for (let babylonNode of nodes) {
                     glTFNodeIndex = this._nodeMap[babylonNode.uniqueId];
-                    if (glTFNodeIndex != null) {
+                    if (glTFNodeIndex !== undefined) { 
                         glTFNode = this._nodes[glTFNodeIndex];
                         if (!babylonNode.parent) {
                             if (!this._shouldExportNode(babylonNode)) {
@@ -1331,15 +1331,17 @@ export class _Exporter {
             if (shouldExportNode(babylonNode)) {
                 promiseChain = promiseChain.then(() => {
                     return this.createNodeAsync(babylonNode, binaryWriter).then((node) => {
-                        let promise = this._extensionsPostExportNodeAsync("createNodeAsync", node, babylonNode);
+                        const promise = this._extensionsPostExportNodeAsync("createNodeAsync", node, babylonNode);
                         if (promise == null) {
                             Tools.Warn(`Not exporting node ${babylonNode.name}`);
+                            return Promise.resolve();
                         }
                         else {
-                            promise.then(() => {
+                            return promise.then((node) => {
                                 const directDescendents = babylonNode.getDescendants(true, (node: Node) => { return (node instanceof Node); });
                                 if (directDescendents.length || node.mesh != null || (node.extensions)) {
                                     this._nodes.push(node);
+                                    
                                     nodeIndex = this._nodes.length - 1;
                                     nodeMap[babylonNode.uniqueId] = nodeIndex;
                                 }

+ 34 - 0
tests/unit/babylon/serializers/babylon.glTFSerializer.tests.ts

@@ -366,5 +366,39 @@ describe('Babylon glTF Serializer', () => {
                 jsonData.scene.should.be.equal(0);
             });
         });
+        it('should serialize point light to glTF', () => {
+            const scene = new BABYLON.Scene(subject);
+            const pointLight = new BABYLON.PointLight("pointLight", new BABYLON.Vector3(4, 4, 0), scene);
+            const intensity = 0.2;
+            pointLight.intensity = intensity;
+
+            return BABYLON.GLTF2Export.GLTFAsync(scene, 'test').then(glTFData => {
+                const jsonString = glTFData.glTFFiles['test.gltf'] as string;
+                const jsonData = JSON.parse(jsonString);
+                console.log(jsonString);
+                // assets, extensionsUsed, extensions, nodes, scenes, scene
+                Object.keys(jsonData).length.should.be.equal(6);
+                jsonData.extensions['KHR_lights_punctual'].lights.length.should.be.equal(1);
+                jsonData.extensions['KHR_lights_punctual'].lights[0].intensity.should.be.equal(intensity);
+                jsonData.nodes.length.should.be.equal(1);
+                jsonData.nodes[0].extensions['KHR_lights_punctual']['light'].should.be.equal(0);
+            });
+        });
+        it('should serialize multiple lights to glTF', () => {
+            const scene = new BABYLON.Scene(subject);
+            const pointLight = new BABYLON.PointLight("pointLight", new BABYLON.Vector3(4, 4, 0), scene);
+            const spotLight = new BABYLON.SpotLight("spotLight", new BABYLON.Vector3(-4, 4, 0), new BABYLON.Vector3(0, Math.PI/4, 0), Math.PI/4, 2, scene);
+            const directionalLight = new BABYLON.DirectionalLight("directionalLight", BABYLON.Vector3.Forward(), scene);
+
+            return BABYLON.GLTF2Export.GLTFAsync(scene, 'test').then(glTFData => {
+                const jsonString = glTFData.glTFFiles['test.gltf'] as string;
+                const jsonData = JSON.parse(jsonString);
+                console.log(jsonString);
+                // assets, extensionsUsed, extensions, nodes, scenes, scene
+                Object.keys(jsonData).length.should.be.equal(6);
+                jsonData.extensions['KHR_lights_punctual'].lights.length.should.be.equal(3);
+                jsonData.nodes.length.should.be.equal(3);
+            });
+        });
     });
 });