浏览代码

Merge pull request #6044 from TrevorDev/lightGizmoIcons

Light gizmo icons
David Catuhe 6 年之前
父节点
当前提交
80f6ad5d05
共有 5 个文件被更改,包括 253 次插入16 次删除
  1. 1 1
      dist/preview release/what's new.md
  2. 193 15
      src/Gizmos/lightGizmo.ts
  3. 46 0
      src/Meshes/Builders/hemisphereBuilder.ts
  4. 1 0
      src/Meshes/Builders/index.ts
  5. 12 0
      src/Meshes/mesh.ts

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

@@ -120,7 +120,7 @@
 - Added transparency support to `GlowLayer` ([Sebavan](https://github.com/Sebavan))
 - Added option `forceDisposeChildren` to multiMaterial.dispose ([danjpar](https://github.com/danjpar))
 - Added Pointer bindings for FollowCamera. ([mrdunk](https://github.com))
-- Inspector light gizmo ([TrevorDev](https://github.com/TrevorDev))
+- Inspector light gizmo with icons ([TrevorDev](https://github.com/TrevorDev))
 - Added option `multiMultiMaterials` to mesh.mergeMeshes ([danjpar](https://github.com/danjpar))
 - Expose fallback camera distortion metrics option in vrExperienceHelper ([TrevorDev](https://github.com/TrevorDev))
 - Added OnAfterEnteringVRObservable to webVRHelper ([TrevorDev](https://github.com/TrevorDev))

+ 193 - 15
src/Gizmos/lightGizmo.ts

@@ -7,12 +7,19 @@ import { UtilityLayerRenderer } from "../Rendering/utilityLayerRenderer";
 
 import { StandardMaterial } from '../Materials/standardMaterial';
 import { Light } from '../Lights/light';
+import { Scene } from '../scene';
+import { HemisphericLight } from '../Lights/hemisphericLight';
+import { DirectionalLight } from '../Lights/directionalLight';
+import { SphereBuilder } from '../Meshes/Builders/sphereBuilder';
+import { HemisphereBuilder } from '../Meshes/Builders/hemisphereBuilder';
+import { SpotLight } from '../Lights/spotLight';
 
 /**
  * Gizmo that enables viewing a light
  */
 export class LightGizmo extends Gizmo {
-    private _box: Mesh;
+    private _lightMesh: Mesh;
+    private _material: StandardMaterial;
 
     /**
      * Creates a LightGizmo
@@ -20,13 +27,10 @@ export class LightGizmo extends Gizmo {
      */
     constructor(gizmoLayer?: UtilityLayerRenderer) {
         super(gizmoLayer);
-        this._box = Mesh.CreateCylinder("light", 0.02, 0, 0.02, 16, 1, this.gizmoLayer.utilityLayerScene);
-        this._box.rotation.x = -Math.PI / 2;
-        this._box.bakeCurrentTransformIntoVertices();
-        this._box.material = new StandardMaterial("", this.gizmoLayer.utilityLayerScene);
-        (this._box.material as StandardMaterial).emissiveColor = Color3.Yellow();
-        this._rootMesh.addChild(this._box);
         this.attachedMesh = new AbstractMesh("", this.gizmoLayer.utilityLayerScene);
+        this._material = new StandardMaterial("light", this.gizmoLayer.originalScene);
+        this._material.diffuseColor = new Color3(0.5, 0.5, 0.5);
+        this._material.specularColor = new Color3(0.1, 0.1, 0.1);
     }
     private _light: Nullable<Light> = null;
 
@@ -35,11 +39,37 @@ export class LightGizmo extends Gizmo {
      */
     public set light(light: Nullable<Light>) {
         this._light = light;
-        if ((light as any).position) {
-            this.attachedMesh!.position.copyFrom((light as any).position);
-        }
-        if ((light as any).direction) {
-            this._box.setDirection((light as any).direction);
+        if (light) {
+            // Create the mesh for the given light type
+            if (this._lightMesh) {
+                this._lightMesh.dispose();
+            }
+
+            if (light instanceof HemisphericLight) {
+                this._lightMesh = LightGizmo._CreateHemisphericLightMesh(this.gizmoLayer.utilityLayerScene);
+            }else if (light instanceof DirectionalLight) {
+                this._lightMesh = LightGizmo._CreateDirectionalLightMesh(this.gizmoLayer.utilityLayerScene);
+            }else if (light instanceof SpotLight) {
+                this._lightMesh = LightGizmo._CreateSpotLightMesh(this.gizmoLayer.utilityLayerScene);
+            }else {
+                this._lightMesh = LightGizmo._CreatePointLightMesh(this.gizmoLayer.utilityLayerScene);
+            }
+            this._lightMesh.getChildMeshes(false).forEach((m) => {
+                m.material = this._material;
+            });
+            this._lightMesh.parent = this._rootMesh;
+
+            // Add lighting to the light gizmo
+            var gizmoLight = this.gizmoLayer._getSharedGizmoLight();
+            gizmoLight.includedOnlyMeshes = gizmoLight.includedOnlyMeshes.concat(this._lightMesh.getChildMeshes(false));
+
+            // Get update position and direction if the light has it
+            if ((light as any).position) {
+                this.attachedMesh!.position.copyFrom((light as any).position);
+            }
+            if ((light as any).direction) {
+                this._lightMesh.setDirection((light as any).direction);
+            }
         }
     }
     public get light() {
@@ -59,12 +89,160 @@ export class LightGizmo extends Gizmo {
             (this._light as any).position.copyFrom(this.attachedMesh!.position);
         }
         if ((this._light as any).direction) {
-            (this._light as any).direction.copyFrom(this._box.forward);
+            (this._light as any).direction.copyFrom(this._lightMesh.forward);
         }
         if (!this._light.isEnabled()) {
-            (this._box.material as StandardMaterial).emissiveColor.set(0, 0, 0);
+            this._material.diffuseColor.set(0, 0, 0);
         } else {
-            (this._box.material as StandardMaterial).emissiveColor.set(1, 1, 1);
+            this._material.diffuseColor.set(this._light.diffuse.r / 3, this._light.diffuse.g / 3, this._light.diffuse.b / 3);
+        }
+    }
+
+    // Static helper methods
+    private static _Scale = 0.007;
+
+    /**
+     * Creates the lines for a light mesh
+     */
+    private static _createLightLines = (levels: number, scene: Scene) => {
+        var distFromSphere = 1.2;
+
+        var root = new Mesh("root", scene);
+        root.rotation.x = Math.PI / 2;
+
+        // Create the top line, this will be cloned for all other lines
+        var linePivot = new Mesh("linePivot", scene);
+        linePivot.parent = root;
+        var line = Mesh.CreateCylinder("line", 2, 0.2, 0.3, 6, 1, scene);
+        line.position.y = line.scaling.y / 2 + distFromSphere;
+        line.parent = linePivot;
+
+        if (levels < 2) {
+            return linePivot;
         }
+        for (var i = 0; i < 4; i++) {
+            var l = linePivot.clone("lineParentClone");
+            l.rotation.z = Math.PI / 4;
+            l.rotation.y = (Math.PI / 2) + (Math.PI / 2 * i);
+
+            l.getChildMeshes()[0].scaling.y = 0.5;
+            l.getChildMeshes()[0].scaling.x = l.getChildMeshes()[0].scaling.z = 0.8;
+            l.getChildMeshes()[0].position.y = l.getChildMeshes()[0].scaling.y / 2 + distFromSphere;
+        }
+
+        if (levels < 3) {
+            return root;
+        }
+        for (var i = 0; i < 4; i++) {
+            var l = linePivot.clone("linePivotClone");
+            l.rotation.z = Math.PI / 2;
+            l.rotation.y = (Math.PI / 2 * i);
+        }
+
+        if (levels < 4) {
+            return root;
+        }
+        for (var i = 0; i < 4; i++) {
+            var l = linePivot.clone("linePivotClone");
+            l.rotation.z = Math.PI + (Math.PI / 4);
+            l.rotation.y = (Math.PI / 2) + (Math.PI / 2 * i);
+
+            l.getChildMeshes()[0].scaling.y = 0.5;
+            l.getChildMeshes()[0].scaling.x = l.getChildMeshes()[0].scaling.z = 0.8;
+            l.getChildMeshes()[0].position.y = l.getChildMeshes()[0].scaling.y / 2 + distFromSphere;
+        }
+
+        if (levels < 5) {
+            return root;
+        }
+        var l = linePivot.clone("linePivotClone");
+        l.rotation.z = Math.PI;
+
+        return root;
+    }
+
+    private static _CreateHemisphericLightMesh(scene: Scene) {
+        var root = new Mesh("hemisphereLight", scene);
+        var hemisphere = HemisphereBuilder.CreateHemisphere(root.name, {segments: 10, diameter: 1}, scene);
+        hemisphere.position.z = -0.15;
+        hemisphere.rotation.x = Math.PI / 2;
+        hemisphere.parent = root;
+
+        var lines = this._createLightLines(3, scene);
+        lines.parent = root;
+        lines.position.z - 0.15;
+
+        root.scaling.scaleInPlace(LightGizmo._Scale);
+        root.rotation.x = Math.PI / 2;
+
+        return root;
+    }
+
+    private static _CreatePointLightMesh(scene: Scene) {
+        var root = new Mesh("pointLight", scene);
+        var sphere = SphereBuilder.CreateSphere(root.name, {segments: 10, diameter: 1}, scene);
+        sphere.rotation.x = Math.PI / 2;
+        sphere.parent = root;
+
+        var lines = this._createLightLines(5, scene);
+        lines.parent = root;
+        root.scaling.scaleInPlace(LightGizmo._Scale);
+        root.rotation.x = Math.PI / 2;
+
+        return root;
+    }
+
+    private static _CreateSpotLightMesh(scene: Scene) {
+        var root = new Mesh("spotLight", scene);
+        var sphere = SphereBuilder.CreateSphere(root.name, {segments: 10, diameter: 1}, scene);
+        sphere.parent = root;
+
+        var hemisphere = HemisphereBuilder.CreateHemisphere(root.name, {segments: 10, diameter: 2}, scene);
+        hemisphere.parent = root;
+        hemisphere.rotation.x = -Math.PI / 2;
+
+        var lines = this._createLightLines(2, scene);
+        lines.parent = root;
+        root.scaling.scaleInPlace(LightGizmo._Scale);
+        root.rotation.x = Math.PI / 2;
+
+        return root;
+    }
+
+    private static _CreateDirectionalLightMesh(scene: Scene) {
+        var root = new Mesh("directionalLight", scene);
+
+        var mesh = new Mesh(root.name, scene);
+        mesh.parent = root;
+        var sphere  = SphereBuilder.CreateSphere(root.name, {diameter: 1.2, segments: 10}, scene);
+        sphere.parent = mesh;
+
+        var line = Mesh.CreateCylinder(root.name, 6, 0.3, 0.3, 6, 1, scene);
+        line.parent = mesh;
+
+        var left = line.clone(root.name);
+        left.scaling.y = 0.5;
+        left.position.x += 1.25;
+
+        var right = line.clone(root.name);
+        right.scaling.y = 0.5;
+        right.position.x += -1.25;
+
+        var arrowHead = Mesh.CreateCylinder(root.name, 1, 0, 0.6, 6, 1, scene);
+        arrowHead.position.y += 3;
+        arrowHead.parent = mesh;
+
+        var left = arrowHead.clone(root.name);
+        left.position.y = 1.5;
+        left.position.x += 1.25;
+
+        var right = arrowHead.clone(root.name);
+        right.position.y = 1.5;
+        right.position.x += -1.25;
+
+        mesh.scaling.scaleInPlace(LightGizmo._Scale);
+        mesh.rotation.z = Math.PI / 2;
+        mesh.rotation.y = Math.PI / 2;
+        return root;
     }
 }

+ 46 - 0
src/Meshes/Builders/hemisphereBuilder.ts

@@ -0,0 +1,46 @@
+import { Mesh, _CreationDataStorage } from "../mesh";
+import { Scene } from "../../scene";
+import { SphereBuilder } from '../Builders/sphereBuilder';
+
+/**
+ * Creates a hemispheric light
+ */
+Mesh.CreateHemisphere = (name: string, segments: number, diameter: number, scene?: Scene): Mesh => {
+    var options = {
+        segments: segments,
+        diameter: diameter
+    };
+
+    return HemisphereBuilder.CreateHemisphere(name, options, scene);
+};
+
+/**
+ * Class containing static functions to help procedurally build meshes
+ */
+export class HemisphereBuilder {
+    /**
+     * Creates a hemisphere mesh
+     * @param name defines the name of the mesh
+     * @param options defines the options used to create the mesh
+     * @param scene defines the hosting scene
+     * @returns the hemisphere mesh
+     */
+    public static CreateHemisphere(name: string, options: { segments?: number, diameter?: number, sideOrientation?: number }, scene: any): Mesh {
+        if (!options.diameter) {
+            options.diameter = 1;
+        }
+        if (!options.segments) {
+            options.segments = 16;
+        }
+
+        var halfSphere = SphereBuilder.CreateSphere("", {slice: 0.5, diameter: options.diameter, segments: options.segments}, scene);
+        var disc = Mesh.CreateDisc("", options.diameter / 2, (options.segments * 3) + (4 - options.segments), scene);
+        disc.rotation.x = -Math.PI / 2;
+        disc.parent = halfSphere;
+
+        var merged = <Mesh>Mesh.MergeMeshes([disc, halfSphere], true);
+        merged.name = name;
+
+        return merged;
+    }
+}

+ 1 - 0
src/Meshes/Builders/index.ts

@@ -2,6 +2,7 @@ export * from "./boxBuilder";
 export * from "./discBuilder";
 export * from "./ribbonBuilder";
 export * from "./sphereBuilder";
+export * from "./hemisphereBuilder";
 export * from "./cylinderBuilder";
 export * from "./torusBuilder";
 export * from "./torusKnotBuilder";

+ 12 - 0
src/Meshes/mesh.ts

@@ -3232,6 +3232,18 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
     }
 
     /**
+      * Creates a hemisphere mesh. Please consider using the same method from the MeshBuilder class instead
+      * @param name defines the name of the mesh to create
+      * @param segments sets the sphere number of horizontal stripes (positive integer, default 32)
+      * @param diameter sets the diameter size (float) of the sphere (default 1)
+      * @param scene defines the hosting scene
+      * @returns a new Mesh
+      */
+    public static CreateHemisphere(name: string, segments: number, diameter: number, scene?: Scene): Mesh {
+        throw _DevTools.WarnImport("MeshBuilder");
+    }
+
+    /**
      * Creates a cylinder or a cone mesh. Please consider using the same method from the MeshBuilder class instead
      * @param name defines the name of the mesh to create
      * @param height sets the height size (float) of the cylinder/cone (float, default 2)