@shapediver/viewer.rendering-engine.light-engine 1.15.6 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/implementation/AbstractLight.d.ts +3 -3
  2. package/dist/implementation/AbstractLight.d.ts.map +1 -1
  3. package/dist/implementation/LightEngine.d.ts +9 -5
  4. package/dist/implementation/LightEngine.d.ts.map +1 -1
  5. package/dist/implementation/LightEngine.js +41 -30
  6. package/dist/implementation/LightEngine.js.map +1 -1
  7. package/dist/implementation/LightScene.d.ts +8 -3
  8. package/dist/implementation/LightScene.d.ts.map +1 -1
  9. package/dist/implementation/LightScene.js +12 -1
  10. package/dist/implementation/LightScene.js.map +1 -1
  11. package/dist/implementation/types/AmbientLight.d.ts +3 -3
  12. package/dist/implementation/types/AmbientLight.d.ts.map +1 -1
  13. package/dist/implementation/types/AmbientLight.js +1 -1
  14. package/dist/implementation/types/AmbientLight.js.map +1 -1
  15. package/dist/implementation/types/DirectionalLight.d.ts +3 -3
  16. package/dist/implementation/types/DirectionalLight.d.ts.map +1 -1
  17. package/dist/implementation/types/DirectionalLight.js +1 -1
  18. package/dist/implementation/types/DirectionalLight.js.map +1 -1
  19. package/dist/implementation/types/HemisphereLight.d.ts +3 -3
  20. package/dist/implementation/types/HemisphereLight.d.ts.map +1 -1
  21. package/dist/implementation/types/HemisphereLight.js +1 -1
  22. package/dist/implementation/types/HemisphereLight.js.map +1 -1
  23. package/dist/implementation/types/PointLight.d.ts +3 -3
  24. package/dist/implementation/types/PointLight.d.ts.map +1 -1
  25. package/dist/implementation/types/PointLight.js +1 -1
  26. package/dist/implementation/types/PointLight.js.map +1 -1
  27. package/dist/implementation/types/SpotLight.d.ts +3 -3
  28. package/dist/implementation/types/SpotLight.d.ts.map +1 -1
  29. package/dist/implementation/types/SpotLight.js +1 -1
  30. package/dist/implementation/types/SpotLight.js.map +1 -1
  31. package/dist/index.d.ts +8 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/interface/ILight.d.ts +4 -3
  36. package/dist/interface/ILight.d.ts.map +1 -1
  37. package/dist/interface/ILight.js +10 -10
  38. package/dist/interface/ILight.js.map +1 -1
  39. package/dist/interface/ILightEngine.d.ts +1 -0
  40. package/dist/interface/ILightEngine.d.ts.map +1 -1
  41. package/dist/interface/ILightScene.d.ts +3 -2
  42. package/dist/interface/ILightScene.d.ts.map +1 -1
  43. package/dist/interface/types/IAmbientLight.d.ts +5 -0
  44. package/dist/interface/types/IAmbientLight.d.ts.map +1 -0
  45. package/dist/interface/types/IAmbientLight.js +3 -0
  46. package/dist/interface/types/IAmbientLight.js.map +1 -0
  47. package/dist/interface/types/IDirectionalLight.d.ts +10 -0
  48. package/dist/interface/types/IDirectionalLight.d.ts.map +1 -0
  49. package/dist/interface/types/IDirectionalLight.js +3 -0
  50. package/dist/interface/types/IDirectionalLight.js.map +1 -0
  51. package/dist/interface/types/IHemisphereLight.d.ts +7 -0
  52. package/dist/interface/types/IHemisphereLight.d.ts.map +1 -0
  53. package/dist/interface/types/IHemisphereLight.js +3 -0
  54. package/dist/interface/types/IHemisphereLight.js.map +1 -0
  55. package/dist/interface/types/IPointLight.d.ts +9 -0
  56. package/dist/interface/types/IPointLight.d.ts.map +1 -0
  57. package/dist/interface/types/IPointLight.js +3 -0
  58. package/dist/interface/types/IPointLight.js.map +1 -0
  59. package/dist/interface/types/ISpotLight.d.ts +12 -0
  60. package/dist/interface/types/ISpotLight.d.ts.map +1 -0
  61. package/dist/interface/types/ISpotLight.js +3 -0
  62. package/dist/interface/types/ISpotLight.js.map +1 -0
  63. package/package.json +14 -10
  64. package/src/implementation/AbstractLight.ts +94 -0
  65. package/src/implementation/LightEngine.ts +312 -0
  66. package/src/implementation/LightScene.ts +128 -0
  67. package/src/implementation/types/AmbientLight.ts +41 -0
  68. package/src/implementation/types/DirectionalLight.ts +104 -0
  69. package/src/implementation/types/HemisphereLight.ts +65 -0
  70. package/src/implementation/types/PointLight.ts +90 -0
  71. package/src/implementation/types/SpotLight.ts +129 -0
  72. package/src/index.ts +28 -0
  73. package/src/interface/ILight.ts +24 -0
  74. package/src/interface/ILightEngine.ts +17 -0
  75. package/src/interface/ILightScene.ts +27 -0
  76. package/src/interface/types/IAmbientLight.ts +5 -0
  77. package/src/interface/types/IDirectionalLight.ts +12 -0
  78. package/src/interface/types/IHemisphereLight.ts +9 -0
  79. package/src/interface/types/IPointLight.ts +11 -0
  80. package/src/interface/types/ISpotLight.ts +14 -0
  81. package/tsconfig.json +17 -0
@@ -0,0 +1,312 @@
1
+ import { container, singleton } from 'tsyringe'
2
+ import { vec3 } from 'gl-matrix'
3
+ import { Converter, UuidGenerator, SettingsEngine, StateEngine } from '@shapediver/viewer.shared.services'
4
+
5
+ import { AmbientLight } from './types/AmbientLight'
6
+ import { DirectionalLight } from './types/DirectionalLight'
7
+ import { HemisphereLight } from './types/HemisphereLight'
8
+ import { PointLight } from './types/PointLight'
9
+ import { SpotLight } from './types/SpotLight'
10
+ import { LightScene } from './LightScene'
11
+ import { AbstractLight } from './AbstractLight'
12
+ import { ILightEngine } from '../interface/ILightEngine'
13
+ import { ILight, LIGHT_TYPE } from '../interface/ILight'
14
+ import { ILightScene } from '../interface/ILightScene'
15
+ import { IAmbientLightPropertiesV3, IDirectionalLightPropertiesV3, IHemisphereLightPropertiesV3, ILightSceneSettingsV3, IPointLightPropertiesV3, ISpotLightPropertiesV3 } from '@shapediver/viewer.settings'
16
+ import { ITree, ITreeNode, Tree, TreeNode } from '@shapediver/viewer.shared.node-tree'
17
+ import { IRenderingEngine } from '@shapediver/viewer.rendering-engine.rendering-engine'
18
+
19
+ export class LightEngine implements ILightEngine {
20
+ // #region Properties (6)
21
+
22
+ private readonly _converter: Converter = <Converter>container.resolve(Converter);
23
+ private readonly _lightNode: ITreeNode = new TreeNode('lights');
24
+ private readonly _tree: ITree = <ITree>container.resolve(Tree);
25
+ private readonly _uuidGenerator: UuidGenerator = <UuidGenerator>container.resolve(UuidGenerator);
26
+
27
+ private _lightScene!: LightScene;
28
+ private _lightScenes: { [key: string]: LightScene; } = {};
29
+ private _update?: () => void;
30
+
31
+ // #endregion Properties (6)
32
+
33
+ // #region Constructors (1)
34
+
35
+ constructor(private readonly _renderingEngine: IRenderingEngine) {
36
+ this._tree.root.addChild(this._lightNode);
37
+ this._lightNode.restrictViewports = [this._renderingEngine.id];
38
+ }
39
+
40
+ // #endregion Constructors (1)
41
+
42
+ // #region Public Accessors (2)
43
+
44
+ public get lightScene(): LightScene | null {
45
+ return this._lightScene;
46
+ }
47
+
48
+ public get lightScenes(): {
49
+ [key: string]: LightScene
50
+ } {
51
+ return this._lightScenes;
52
+ }
53
+
54
+ public get update(): (() => void) | undefined {
55
+ return this._update;
56
+ }
57
+
58
+ public set update(value: (() => void) | undefined) {
59
+ this._update = value;
60
+ }
61
+
62
+ // #endregion Public Accessors (2)
63
+
64
+ // #region Public Methods (6)
65
+
66
+ public applySettings(settingsEngine: SettingsEngine): void {
67
+ this._lightScenes = {};
68
+
69
+ for (let lightSceneId in settingsEngine.light.lightScenes) {
70
+ const lightSceneUUID = this._uuidGenerator.validate(lightSceneId) ? lightSceneId : this._uuidGenerator.create();
71
+ const lightSceneName = settingsEngine.light.lightScenes[lightSceneId].name ? settingsEngine.light.lightScenes[lightSceneId].name : lightSceneId;
72
+ const ls = new LightScene(this._renderingEngine, {id: lightSceneUUID, name: lightSceneName});
73
+ for (let lightId in settingsEngine.light.lightScenes[lightSceneId].lights) {
74
+ const lightUUID = this._uuidGenerator.validate(lightId) ? lightId : this._uuidGenerator.create();
75
+ const light = settingsEngine.light.lightScenes[lightSceneId].lights[lightId];
76
+ let l: AbstractLight;
77
+ switch (light.type) {
78
+ case LIGHT_TYPE.DIRECTIONAL:
79
+ l = new DirectionalLight({
80
+ color: this._converter.toColor((<IDirectionalLightPropertiesV3>light.properties).color),
81
+ intensity: (<IDirectionalLightPropertiesV3>light.properties).intensity,
82
+ direction: this._converter.toVec3((<IDirectionalLightPropertiesV3>light.properties).direction),
83
+ castShadow: (<IDirectionalLightPropertiesV3>light.properties).castShadow,
84
+ name: light.name ? light.name : lightId,
85
+ order: light.order,
86
+ id: lightUUID
87
+ });
88
+ break;
89
+ case LIGHT_TYPE.HEMISPHERE:
90
+ l = new HemisphereLight({
91
+ color: this._converter.toColor((<IHemisphereLightPropertiesV3>light.properties).skyColor),
92
+ intensity: (<IHemisphereLightPropertiesV3>light.properties).intensity,
93
+ groundColor: this._converter.toColor((<IHemisphereLightPropertiesV3>light.properties).groundColor),
94
+ name: light.name ? light.name : lightId,
95
+ order: light.order,
96
+ id: lightUUID
97
+ });
98
+ break;
99
+ case LIGHT_TYPE.POINT:
100
+ l = new PointLight({
101
+ color: this._converter.toColor((<IPointLightPropertiesV3>light.properties).color),
102
+ intensity: (<IPointLightPropertiesV3>light.properties).intensity,
103
+ position: this._converter.toVec3((<IPointLightPropertiesV3>light.properties).position),
104
+ distance: (<IPointLightPropertiesV3>light.properties).distance,
105
+ decay: (<IPointLightPropertiesV3>light.properties).decay,
106
+ name: light.name ? light.name : lightId,
107
+ order: light.order,
108
+ id: lightUUID
109
+ });
110
+ break;
111
+ case LIGHT_TYPE.SPOT:
112
+ l = new SpotLight({
113
+ color: this._converter.toColor((<ISpotLightPropertiesV3>light.properties).color),
114
+ intensity: (<ISpotLightPropertiesV3>light.properties).intensity,
115
+ position: this._converter.toVec3((<ISpotLightPropertiesV3>light.properties).position),
116
+ target: this._converter.toVec3((<ISpotLightPropertiesV3>light.properties).target),
117
+ distance: (<ISpotLightPropertiesV3>light.properties).distance,
118
+ decay: (<ISpotLightPropertiesV3>light.properties).decay,
119
+ angle: (<ISpotLightPropertiesV3>light.properties).angle,
120
+ penumbra: (<ISpotLightPropertiesV3>light.properties).penumbra,
121
+ name: light.name ? light.name : lightId,
122
+ order: light.order,
123
+ id: lightUUID
124
+ });
125
+ break;
126
+ case LIGHT_TYPE.AMBIENT:
127
+ default:
128
+ l = new AmbientLight({
129
+ color: this._converter.toColor((<IAmbientLightPropertiesV3>light.properties).color),
130
+ intensity: (<IAmbientLightPropertiesV3>light.properties).intensity,
131
+ name: light.name ? light.name : lightId,
132
+ order: light.order,
133
+ id: lightUUID
134
+ });
135
+ }
136
+ ls.addLight(l);
137
+ }
138
+ this._lightScenes[ls.id] = ls;
139
+ }
140
+
141
+ // there is a light scene but no id is saved (old viewer)
142
+ if(settingsEngine.light.lightSceneId === undefined && Object.values(settingsEngine.light.lightScenes).length > 0) {
143
+ const res = this.assignLightScene(Object.keys(settingsEngine.light.lightScenes)[0]);
144
+ if(res === false){
145
+ const ls = <LightScene>this.createLightScene({ name: settingsEngine.light.lightSceneId === 'default' ? 'default' : 'standard' });
146
+ ls.addLight(new AmbientLight({color: '#ffffff', intensity: 0.5, name: 'ambient0'}));
147
+ ls.addLight(new DirectionalLight({color: '#ffffff', intensity: 0.75, direction: vec3.fromValues(.5774, -.5774, .5774), castShadow: true, name: 'directional0'}));
148
+ ls.addLight(new DirectionalLight({color: '#ffffff', intensity: 0.35, direction: vec3.fromValues(.25, -1, 1), castShadow: false, name: 'directional1'}));
149
+ this._lightScenes[ls.id] = ls;
150
+ }
151
+ } // there is no standard light scene in the light scenes, but a light scene name is specified (old viewer)
152
+ else if (settingsEngine.light.lightSceneId) {
153
+ const res = this.assignLightScene(settingsEngine.light.lightSceneId);
154
+ if(res === false){
155
+ const ls = <LightScene>this.createLightScene({ name: settingsEngine.light.lightSceneId === 'default' ? 'default' : 'standard' });
156
+ ls.addLight(new AmbientLight({color: '#ffffff', intensity: 0.5, name: 'ambient0'}));
157
+ ls.addLight(new DirectionalLight({color: '#ffffff', intensity: 0.75, direction: vec3.fromValues(.5774, -.5774, .5774), castShadow: true, name: 'directional0'}));
158
+ ls.addLight(new DirectionalLight({color: '#ffffff', intensity: 0.35, direction: vec3.fromValues(.25, -1, 1), castShadow: false, name: 'directional1'}));
159
+ this._lightScenes[ls.id] = ls;
160
+ }
161
+ }
162
+ // this can only be the case if the settings were empty, therefore we assign the new light scene
163
+ else {
164
+ const ls = <LightScene>this.createLightScene({ name: 'standard', standard: true });
165
+ this._lightScenes[ls.id] = ls;
166
+ }
167
+ if(this._update) this._update();
168
+ }
169
+
170
+ public assignLightScene(id: string): boolean {
171
+ if (!this._lightScenes[id]) {
172
+ for(let lightSceneId in this._lightScenes) {
173
+ const lightScene = this._lightScenes[lightSceneId];
174
+ const lightSceneName = lightScene.name || lightSceneId;
175
+ if(lightSceneName === id) {
176
+ const res = this.assignLightScene(lightSceneId);
177
+ return res;
178
+ }
179
+ }
180
+ return false;
181
+ }
182
+ this._lightScene = this._lightScenes[id];
183
+ while(this._lightNode.children.length > 0)
184
+ this._lightNode.removeChild(this._lightNode.children[0]);
185
+ this._lightNode.addChild(this._lightScene!.node);
186
+ this._lightNode.updateVersion();
187
+
188
+ return true;
189
+ }
190
+
191
+ public close(): void {
192
+ this._tree.root.removeChild(this._lightNode);
193
+ }
194
+
195
+ public createLightScene(properties: {name?: string, standard?: boolean}): ILightScene {
196
+ const lightSceneId = this._uuidGenerator.create();
197
+ const lightScene = new LightScene(this._renderingEngine, {id: lightSceneId, name: properties.name});
198
+ if (properties.standard === true) {
199
+ lightScene.addLight(new DirectionalLight({color: '#ffffff', intensity: 2.5, direction: vec3.fromValues(.5774, -.5774, .5774), castShadow: true, name: 'directional0'}));
200
+ lightScene.addLight(new DirectionalLight({color: '#ffffff', intensity: 1, direction: vec3.fromValues(-.5774, -.5774, .5774), castShadow: false, name: 'directional1'}));
201
+ }
202
+ this._lightScenes[lightSceneId] = lightScene;
203
+ this._lightScene = lightScene;
204
+ while(this._lightNode.children.length > 0)
205
+ this._lightNode.removeChild(this._lightNode.children[0]);
206
+ this._lightNode.addChild(this._lightScene!.node)
207
+ this._lightNode.updateVersion();
208
+
209
+ if(this._update) this._update();
210
+ return lightScene;
211
+ }
212
+
213
+ public removeLightScene(id: string): boolean {
214
+ if (!this._lightScenes[id]) {
215
+ for(let lightSceneId in this._lightScenes) {
216
+ const lightScene = this._lightScenes[lightSceneId];
217
+ const lightSceneName = lightScene.name || lightSceneId;
218
+ if(lightSceneName === id) {
219
+ const res = this.removeLightScene(lightSceneId);
220
+ return res;
221
+ }
222
+ }
223
+ return false;
224
+ }
225
+
226
+ if(this._lightScene && this._lightScene.id === id)
227
+ (<any>this._lightScene) = undefined;
228
+ delete this._lightScenes[id];
229
+
230
+ while(this._lightNode.children.length > 0)
231
+ this._lightNode.removeChild(this._lightNode.children[0]);
232
+ this._lightNode.updateVersion();
233
+
234
+ if(this._update) this._update();
235
+ return true;
236
+ }
237
+
238
+ public saveSettings(settingsEngine: SettingsEngine) {
239
+ settingsEngine.light.lightSceneId = this.lightScene ? this.lightScene.id : 'standard';
240
+
241
+ const converted: ILightSceneSettingsV3 = {};
242
+ for(let lightSceneId in this._lightScenes) {
243
+ const lightScene = this._lightScenes[lightSceneId];
244
+ const lightSceneName = lightScene.name || lightSceneId;
245
+ converted[lightSceneId] = {
246
+ name: lightSceneName,
247
+ lights: {}
248
+ };
249
+ for(let lightId in lightScene.lights) {
250
+ const light = lightScene.lights[lightId];
251
+
252
+ let properties;
253
+ switch (light.type) {
254
+ case LIGHT_TYPE.DIRECTIONAL:
255
+ properties = {
256
+ color: light.color,
257
+ intensity: light.intensity,
258
+ direction: { x: (<DirectionalLight>light).direction[0], y: (<DirectionalLight>light).direction[1], z: (<DirectionalLight>light).direction[2] },
259
+ castShadow: (<DirectionalLight>light).castShadow,
260
+ shadowMapResolution: (<DirectionalLight>light).shadowMapResolution,
261
+ shadowMapBias: (<DirectionalLight>light).shadowMapBias
262
+ }
263
+ break;
264
+ case LIGHT_TYPE.HEMISPHERE:
265
+ properties = {
266
+ skyColor: light.color,
267
+ intensity: light.intensity,
268
+ groundColor: (<HemisphereLight>light).groundColor
269
+ }
270
+ break;
271
+ case LIGHT_TYPE.POINT:
272
+ properties = {
273
+ color: light.color,
274
+ intensity: light.intensity,
275
+ position: { x: (<PointLight>light).position[0], y: (<PointLight>light).position[1], z: (<PointLight>light).position[2] },
276
+ distance: (<PointLight>light).distance,
277
+ decay: (<PointLight>light).decay
278
+ }
279
+ break;
280
+ case LIGHT_TYPE.SPOT:
281
+ properties = {
282
+ color: light.color,
283
+ intensity: light.intensity,
284
+ position: { x: (<SpotLight>light).position[0], y: (<SpotLight>light).position[1], z: (<SpotLight>light).position[2] },
285
+ target: { x: (<SpotLight>light).target[0], y: (<SpotLight>light).target[1], z: (<SpotLight>light).target[2] },
286
+ distance: (<SpotLight>light).distance,
287
+ decay: (<SpotLight>light).decay,
288
+ angle: (<SpotLight>light).angle,
289
+ penumbra: (<SpotLight>light).penumbra
290
+ }
291
+ break;
292
+ case LIGHT_TYPE.AMBIENT:
293
+ default:
294
+ properties = {
295
+ color: light.color,
296
+ intensity: light.intensity
297
+ }
298
+ }
299
+ converted[lightSceneId].lights[lightId] = {
300
+ name: light.name,
301
+ type: light.type,
302
+ properties
303
+ }
304
+ if(light.order !== undefined)
305
+ converted[lightSceneId].lights[lightId].order = light.order;
306
+ }
307
+ }
308
+ settingsEngine.light.lightScenes = converted;
309
+ }
310
+
311
+ // #endregion Public Methods (6)
312
+ }
@@ -0,0 +1,128 @@
1
+ import { IRenderingEngine } from '@shapediver/viewer.rendering-engine.rendering-engine';
2
+ import { ITreeNode, TreeNode } from '@shapediver/viewer.shared.node-tree'
3
+ import { vec3 } from 'gl-matrix';
4
+
5
+ import { ILight } from '../interface/ILight'
6
+ import { ILightScene } from '../interface/ILightScene'
7
+ import { AbstractLight } from './AbstractLight'
8
+ import { AmbientLight } from './types/AmbientLight';
9
+ import { DirectionalLight } from './types/DirectionalLight';
10
+ import { HemisphereLight } from './types/HemisphereLight';
11
+ import { PointLight } from './types/PointLight';
12
+ import { SpotLight } from './types/SpotLight';
13
+
14
+ export class LightScene implements ILightScene {
15
+ // #region Properties (5)
16
+
17
+ private readonly _id: string;
18
+ private readonly _lights: { [key: string]: ILight; } = {};
19
+ private readonly _node: ITreeNode;
20
+
21
+ private _name: string | undefined;
22
+ private _update?: () => void;
23
+
24
+ // #endregion Properties (5)
25
+
26
+ // #region Constructors (1)
27
+
28
+ constructor(private readonly _renderingEngine: IRenderingEngine, properties: {id: string, name?: string}) {
29
+ this._id = properties.id;
30
+ this._name = properties.name;
31
+ this._node = new TreeNode(properties.name || properties.id);
32
+ }
33
+
34
+ // #endregion Constructors (1)
35
+
36
+ // #region Public Accessors (5)
37
+
38
+ public get id(): string {
39
+ return this._id;
40
+ }
41
+
42
+ public get lights(): { [key: string]: AbstractLight; } {
43
+ return <{ [key: string]: AbstractLight; }>this._lights
44
+ }
45
+
46
+ public get name(): string | undefined {
47
+ return this._name;
48
+ }
49
+
50
+ public set name(value: string | undefined) {
51
+ this._name = value;
52
+ }
53
+
54
+ public get node(): ITreeNode {
55
+ return this._node;
56
+ }
57
+
58
+ public get update(): (() => void) | undefined {
59
+ return this._update;
60
+ }
61
+
62
+ public set update(value: (() => void) | undefined) {
63
+ this._update = value;
64
+ }
65
+
66
+ // #endregion Public Accessors (5)
67
+
68
+ // #region Public Methods (8)
69
+
70
+ public addAmbientLight(properties: {color?: string, intensity?: number, name?: string}): AmbientLight {
71
+ const light = new AmbientLight(properties);
72
+ this.addLight(light);
73
+ return light;
74
+ }
75
+
76
+ public addDirectionalLight(properties: {color?: string, intensity?: number, direction?: vec3, castShadow?: boolean, shadowMapResolution?: number, shadowMapBias?: number, name?: string}): DirectionalLight {
77
+ const light = new DirectionalLight(properties);
78
+ this.addLight(light);
79
+ return light;
80
+ }
81
+
82
+ public addHemisphereLight(properties: {color?: string, intensity?: number, groundColor?: string, name?: string}): HemisphereLight {
83
+ const light = new HemisphereLight(properties);
84
+ this.addLight(light);
85
+ return light;
86
+ }
87
+
88
+ public addLight(light: AbstractLight): void {
89
+ const node = new TreeNode(light.id);
90
+ node.data.push(light);
91
+ this._node.addChild(node)
92
+ this._lights[light.id] = light;
93
+
94
+ this._node.updateVersion();
95
+ if(this._update) this._update();
96
+ }
97
+
98
+ public addPointLight(properties: {color?: string, intensity?: number, position?: vec3, distance?: number, decay?: number, name?: string}): PointLight {
99
+ const light = new PointLight(properties);
100
+ this.addLight(light);
101
+ return light;
102
+ }
103
+
104
+ public addSpotLight(properties: {color?: string, intensity?: number, position?: vec3, target?: vec3, distance?: number, decay?: number, angle?: number, penumbra?: number, name?: string}): SpotLight {
105
+ const light = new SpotLight(properties);
106
+ this.addLight(light);
107
+ return light;
108
+ }
109
+
110
+ public removeLight(id: string): boolean {
111
+ if (!this._lights[id]) return false;
112
+
113
+ for(let i = 0; i < this._node.children.length; i++) {
114
+ const node = this._node.children[i];
115
+ if(node && node.name === id) {
116
+ this._node.removeChild(node);
117
+ break;
118
+ }
119
+ }
120
+
121
+ delete this._lights[id];
122
+ this._node.updateVersion();
123
+ if(this._update) this._update();
124
+ return true;
125
+ }
126
+
127
+ // #endregion Public Methods (8)
128
+ }
@@ -0,0 +1,41 @@
1
+ import { ITreeNodeData } from '@shapediver/viewer.shared.node-tree'
2
+
3
+ import { LIGHT_TYPE } from '../../interface/ILight'
4
+ import { IAmbientLight } from '../../interface/types/IAmbientLight';
5
+ import { AbstractLight } from '../AbstractLight'
6
+
7
+ export class AmbientLight extends AbstractLight implements IAmbientLight {
8
+ // #region Constructors (1)
9
+
10
+ constructor(properties: {
11
+ color?: string,
12
+ intensity?: number,
13
+ name?: string,
14
+ order?: number,
15
+ id?: string
16
+ }) {
17
+ super({
18
+ color: properties.color || '#ffffff',
19
+ intensity: properties.intensity !== undefined ? properties.intensity : 0.5,
20
+ type: LIGHT_TYPE.AMBIENT,
21
+ name: properties.name,
22
+ order: properties.order,
23
+ id: properties.id
24
+ });
25
+ }
26
+
27
+ // #endregion Constructors (1)
28
+
29
+ // #region Public Methods (1)
30
+
31
+ public clone(): IAmbientLight {
32
+ return new AmbientLight({
33
+ color: this.color || '#ffffff',
34
+ intensity: this.intensity || 0.5,
35
+ name: this.name,
36
+ order: this.order
37
+ });
38
+ }
39
+
40
+ // #endregion Public Methods (1)
41
+ }
@@ -0,0 +1,104 @@
1
+ import { ITreeNodeData } from '@shapediver/viewer.shared.node-tree'
2
+ import { vec3 } from 'gl-matrix'
3
+
4
+ import { LIGHT_TYPE } from '../../interface/ILight'
5
+ import { IDirectionalLight } from '../../interface/types/IDirectionalLight';
6
+ import { AbstractLight } from '../AbstractLight'
7
+
8
+ export class DirectionalLight extends AbstractLight implements IDirectionalLight {
9
+ // #region Properties (4)
10
+
11
+ private _castShadow: boolean = false;
12
+ private _direction: vec3 = vec3.fromValues(-1, 0, 1);
13
+ private _shadowMapBias: number = -0.003;
14
+ private _shadowMapResolution: number = 1024;
15
+
16
+ // #endregion Properties (4)
17
+
18
+ // #region Constructors (1)
19
+
20
+ constructor(properties: {
21
+ color?: string,
22
+ intensity?: number,
23
+ direction?: vec3,
24
+ castShadow?: boolean,
25
+ shadowMapResolution?: number,
26
+ shadowMapBias?: number,
27
+ name?: string,
28
+ order?: number,
29
+ id?: string
30
+ }) {
31
+ super({
32
+ color: properties.color || '#ffffff',
33
+ intensity: properties.intensity !== undefined ? properties.intensity : 0.5,
34
+ type: LIGHT_TYPE.DIRECTIONAL,
35
+ name: properties.name,
36
+ order: properties.order,
37
+ id: properties.id
38
+ });
39
+
40
+ if(properties.direction) this._direction = properties.direction;
41
+ if(properties.castShadow) this._castShadow = properties.castShadow;
42
+ if(properties.shadowMapResolution) this._shadowMapResolution = properties.shadowMapResolution;
43
+ if(properties.shadowMapBias) this._shadowMapBias = properties.shadowMapBias;
44
+ }
45
+
46
+ // #endregion Constructors (1)
47
+
48
+ // #region Public Accessors (8)
49
+
50
+ public get castShadow(): boolean {
51
+ return this._castShadow;
52
+ }
53
+
54
+ public set castShadow(value: boolean) {
55
+ this._castShadow = value;
56
+ this.updateVersion();
57
+ }
58
+
59
+ public get direction(): vec3 {
60
+ return this._direction;
61
+ }
62
+
63
+ public set direction(value: vec3) {
64
+ this._direction = value;
65
+ this.updateVersion();
66
+ }
67
+
68
+ public get shadowMapBias(): number {
69
+ return this._shadowMapBias;
70
+ }
71
+
72
+ public set shadowMapBias(value: number) {
73
+ this._shadowMapBias = value;
74
+ this.updateVersion();
75
+ }
76
+
77
+ public get shadowMapResolution(): number {
78
+ return this._shadowMapResolution;
79
+ }
80
+
81
+ public set shadowMapResolution(value: number) {
82
+ this._shadowMapResolution = value;
83
+ this.updateVersion();
84
+ }
85
+
86
+ // #endregion Public Accessors (8)
87
+
88
+ // #region Public Methods (1)
89
+
90
+ public clone(): IDirectionalLight {
91
+ return new DirectionalLight({
92
+ color: this.color,
93
+ intensity: this.intensity,
94
+ direction: this.direction,
95
+ castShadow: this.castShadow,
96
+ shadowMapResolution: this.shadowMapResolution,
97
+ shadowMapBias: this.shadowMapBias,
98
+ name: this.name,
99
+ order: this.order
100
+ });
101
+ }
102
+
103
+ // #endregion Public Methods (1)
104
+ }
@@ -0,0 +1,65 @@
1
+ import { ITreeNodeData } from '@shapediver/viewer.shared.node-tree'
2
+ import { vec3 } from 'gl-matrix'
3
+
4
+ import { LIGHT_TYPE } from '../../interface/ILight'
5
+ import { IHemisphereLight } from '../../interface/types/IHemisphereLight';
6
+ import { AbstractLight } from '../AbstractLight'
7
+
8
+ export class HemisphereLight extends AbstractLight implements IHemisphereLight {
9
+ // #region Properties (1)
10
+
11
+ private _groundColor: string = '#ffffff';
12
+
13
+ // #endregion Properties (1)
14
+
15
+ // #region Constructors (1)
16
+
17
+ constructor(properties: {
18
+ color?: string,
19
+ groundColor?: string,
20
+ intensity?: number,
21
+ name?: string,
22
+ order?: number,
23
+ id?: string
24
+ }) {
25
+ super({
26
+ color: properties.color || '#ffffff',
27
+ intensity: properties.intensity !== undefined ? properties.intensity : 0.5,
28
+ type: LIGHT_TYPE.HEMISPHERE,
29
+ name: properties.name,
30
+ order: properties.order,
31
+ id: properties.id
32
+ });
33
+
34
+ if (properties.groundColor) this._groundColor = properties.groundColor;
35
+ }
36
+
37
+ // #endregion Constructors (1)
38
+
39
+ // #region Public Accessors (2)
40
+
41
+ public get groundColor(): string {
42
+ return this._groundColor;
43
+ }
44
+
45
+ public set groundColor(value: string) {
46
+ this._groundColor = value;
47
+ this.updateVersion();
48
+ }
49
+
50
+ // #endregion Public Accessors (2)
51
+
52
+ // #region Public Methods (1)
53
+
54
+ public clone(): IHemisphereLight {
55
+ return new HemisphereLight({
56
+ color: this.color,
57
+ groundColor: this.groundColor,
58
+ intensity: this.intensity,
59
+ name: this.name,
60
+ order: this.order
61
+ });
62
+ }
63
+
64
+ // #endregion Public Methods (1)
65
+ }