@flighthq/lighting 0.1.0

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 (50) hide show
  1. package/dist/ambientLight.d.ts +8 -0
  2. package/dist/ambientLight.d.ts.map +1 -0
  3. package/dist/ambientLight.js +16 -0
  4. package/dist/ambientLight.js.map +1 -0
  5. package/dist/areaLight.d.ts +18 -0
  6. package/dist/areaLight.d.ts.map +1 -0
  7. package/dist/areaLight.js +75 -0
  8. package/dist/areaLight.js.map +1 -0
  9. package/dist/colorFromKelvin.d.ts +2 -0
  10. package/dist/colorFromKelvin.d.ts.map +1 -0
  11. package/dist/colorFromKelvin.js +44 -0
  12. package/dist/colorFromKelvin.js.map +1 -0
  13. package/dist/directionalLight.d.ts +15 -0
  14. package/dist/directionalLight.d.ts.map +1 -0
  15. package/dist/directionalLight.js +56 -0
  16. package/dist/directionalLight.js.map +1 -0
  17. package/dist/environment.d.ts +8 -0
  18. package/dist/environment.d.ts.map +1 -0
  19. package/dist/environment.js +18 -0
  20. package/dist/environment.js.map +1 -0
  21. package/dist/hemisphereLight.d.ts +9 -0
  22. package/dist/hemisphereLight.d.ts.map +1 -0
  23. package/dist/hemisphereLight.js +22 -0
  24. package/dist/hemisphereLight.js.map +1 -0
  25. package/dist/index.d.ts +10 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +10 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/lightAnalysis.d.ts +6 -0
  30. package/dist/lightAnalysis.d.ts.map +1 -0
  31. package/dist/lightAnalysis.js +91 -0
  32. package/dist/lightAnalysis.js.map +1 -0
  33. package/dist/pointLight.d.ts +14 -0
  34. package/dist/pointLight.d.ts.map +1 -0
  35. package/dist/pointLight.js +35 -0
  36. package/dist/pointLight.js.map +1 -0
  37. package/dist/spotLight.d.ts +25 -0
  38. package/dist/spotLight.d.ts.map +1 -0
  39. package/dist/spotLight.js +86 -0
  40. package/dist/spotLight.js.map +1 -0
  41. package/package.json +39 -0
  42. package/src/ambientLight.test.ts +29 -0
  43. package/src/areaLight.test.ts +100 -0
  44. package/src/colorFromKelvin.test.ts +48 -0
  45. package/src/directionalLight.test.ts +89 -0
  46. package/src/environment.test.ts +49 -0
  47. package/src/hemisphereLight.test.ts +31 -0
  48. package/src/lightAnalysis.test.ts +188 -0
  49. package/src/pointLight.test.ts +55 -0
  50. package/src/spotLight.test.ts +143 -0
@@ -0,0 +1,55 @@
1
+ import { createVector3 } from '@flighthq/geometry';
2
+ import { PointLightKind } from '@flighthq/types';
3
+
4
+ import { clonePointLight, createPointLight } from './pointLight';
5
+
6
+ describe('clonePointLight', () => {
7
+ it('creates an independent copy with a fresh position vector', () => {
8
+ const light = createPointLight({
9
+ castsShadow: true,
10
+ color: 0x112233ff,
11
+ intensity: 0.5,
12
+ normalBias: 0.1,
13
+ pcfRadius: 2,
14
+ position: createVector3(3, 4, 5),
15
+ range: 10,
16
+ shadowBias: 0.01,
17
+ });
18
+ const copy = clonePointLight(light);
19
+ expect(copy).not.toBe(light);
20
+ expect(copy.position).not.toBe(light.position);
21
+ expect(copy.castsShadow).toBe(true);
22
+ expect(copy.color).toBe(0x112233ff);
23
+ expect(copy.intensity).toBe(0.5);
24
+ expect(copy.normalBias).toBe(0.1);
25
+ expect(copy.pcfRadius).toBe(2);
26
+ expect(copy.position.x).toBe(3);
27
+ expect(copy.range).toBe(10);
28
+ expect(copy.shadowBias).toBe(0.01);
29
+ expect(copy.kind).toBe(PointLightKind);
30
+ });
31
+ });
32
+
33
+ describe('createPointLight', () => {
34
+ it('applies defaults: white, unit intensity, origin, infinite range, shadows off', () => {
35
+ const light = createPointLight();
36
+ expect(light.castsShadow).toBe(false);
37
+ expect(light.color).toBe(0xffffffff);
38
+ expect(light.intensity).toBe(1);
39
+ expect(light.normalBias).toBe(0);
40
+ expect(light.pcfRadius).toBe(0);
41
+ expect(light.position.x).toBe(0);
42
+ expect(light.position.y).toBe(0);
43
+ expect(light.position.z).toBe(0);
44
+ expect(light.range).toBe(-1);
45
+ expect(light.shadowBias).toBe(0);
46
+ expect(light.kind).toBe(PointLightKind);
47
+ });
48
+
49
+ it('copies the supplied position rather than aliasing it', () => {
50
+ const position = createVector3(1, 2, 3);
51
+ const light = createPointLight({ position });
52
+ expect(light.position).not.toBe(position);
53
+ expect(light.position.y).toBe(2);
54
+ });
55
+ });
@@ -0,0 +1,143 @@
1
+ import { createVector3 } from '@flighthq/geometry';
2
+ import { SpotLightKind } from '@flighthq/types';
3
+
4
+ import {
5
+ cloneSpotLight,
6
+ createSpotLight,
7
+ getSpotLightConeDegrees,
8
+ setSpotLightCone,
9
+ setSpotLightDirection,
10
+ setSpotLightTarget,
11
+ } from './spotLight';
12
+
13
+ describe('cloneSpotLight', () => {
14
+ it('creates an independent copy with fresh position and direction vectors', () => {
15
+ const light = createSpotLight({
16
+ castsShadow: true,
17
+ color: 0x112233ff,
18
+ direction: createVector3(1, 0, 0),
19
+ innerConeDegrees: 10,
20
+ intensity: 0.5,
21
+ normalBias: 0.1,
22
+ outerConeDegrees: 30,
23
+ pcfRadius: 2,
24
+ position: createVector3(3, 4, 5),
25
+ range: 10,
26
+ shadowBias: 0.01,
27
+ });
28
+ const copy = cloneSpotLight(light);
29
+ expect(copy).not.toBe(light);
30
+ expect(copy.position).not.toBe(light.position);
31
+ expect(copy.direction).not.toBe(light.direction);
32
+ expect(copy.castsShadow).toBe(true);
33
+ expect(copy.color).toBe(0x112233ff);
34
+ expect(copy.direction.x).toBe(1);
35
+ expect(copy.innerConeCos).toBe(light.innerConeCos);
36
+ expect(copy.intensity).toBe(0.5);
37
+ expect(copy.normalBias).toBe(0.1);
38
+ expect(copy.outerConeCos).toBe(light.outerConeCos);
39
+ expect(copy.pcfRadius).toBe(2);
40
+ expect(copy.position.z).toBe(5);
41
+ expect(copy.range).toBe(10);
42
+ expect(copy.shadowBias).toBe(0.01);
43
+ expect(copy.kind).toBe(SpotLightKind);
44
+ });
45
+ });
46
+
47
+ describe('createSpotLight', () => {
48
+ it('applies defaults: white, unit intensity, origin facing down, 0/45 cone, infinite range', () => {
49
+ const light = createSpotLight();
50
+ expect(light.castsShadow).toBe(false);
51
+ expect(light.color).toBe(0xffffffff);
52
+ expect(light.direction.y).toBe(-1);
53
+ expect(light.innerConeCos).toBeCloseTo(1, 6);
54
+ expect(light.intensity).toBe(1);
55
+ expect(light.normalBias).toBe(0);
56
+ expect(light.outerConeCos).toBeCloseTo(Math.cos((45 * Math.PI) / 180), 6);
57
+ expect(light.pcfRadius).toBe(0);
58
+ expect(light.position.x).toBe(0);
59
+ expect(light.range).toBe(-1);
60
+ expect(light.shadowBias).toBe(0);
61
+ expect(light.kind).toBe(SpotLightKind);
62
+ });
63
+
64
+ it('precomputes cone cosines from inner/outer degrees with innerConeCos >= outerConeCos', () => {
65
+ const light = createSpotLight({ innerConeDegrees: 20, outerConeDegrees: 40 });
66
+ expect(light.innerConeCos).toBeCloseTo(Math.cos((20 * Math.PI) / 180), 6);
67
+ expect(light.outerConeCos).toBeCloseTo(Math.cos((40 * Math.PI) / 180), 6);
68
+ expect(light.innerConeCos).toBeGreaterThanOrEqual(light.outerConeCos);
69
+ });
70
+
71
+ it('copies supplied position and direction rather than aliasing them', () => {
72
+ const position = createVector3(1, 2, 3);
73
+ const direction = createVector3(0, 0, 1);
74
+ const light = createSpotLight({ direction, position });
75
+ expect(light.position).not.toBe(position);
76
+ expect(light.direction).not.toBe(direction);
77
+ });
78
+ });
79
+
80
+ describe('getSpotLightConeDegrees', () => {
81
+ it('round-trips inner and outer degrees through create → get', () => {
82
+ const light = createSpotLight({ innerConeDegrees: 15, outerConeDegrees: 35 });
83
+ const angles = { innerDegrees: 0, outerDegrees: 0 };
84
+ getSpotLightConeDegrees(angles, light);
85
+ expect(angles.innerDegrees).toBeCloseTo(15, 4);
86
+ expect(angles.outerDegrees).toBeCloseTo(35, 4);
87
+ });
88
+
89
+ it('writes into the provided out object', () => {
90
+ const light = createSpotLight({ innerConeDegrees: 0, outerConeDegrees: 45 });
91
+ const out = { innerDegrees: -1, outerDegrees: -1 };
92
+ getSpotLightConeDegrees(out, light);
93
+ expect(out.innerDegrees).toBeCloseTo(0, 4);
94
+ expect(out.outerDegrees).toBeCloseTo(45, 4);
95
+ });
96
+ });
97
+
98
+ describe('setSpotLightCone', () => {
99
+ it('writes the cosines of the inner and outer half-angles into the light', () => {
100
+ const light = createSpotLight();
101
+ setSpotLightCone(light, 15, 35);
102
+ expect(light.innerConeCos).toBeCloseTo(Math.cos((15 * Math.PI) / 180), 6);
103
+ expect(light.outerConeCos).toBeCloseTo(Math.cos((35 * Math.PI) / 180), 6);
104
+ });
105
+
106
+ it('produces equal cosines when inner and outer angles match', () => {
107
+ const light = createSpotLight();
108
+ setSpotLightCone(light, 25, 25);
109
+ expect(light.innerConeCos).toBeCloseTo(light.outerConeCos, 6);
110
+ });
111
+ });
112
+
113
+ describe('setSpotLightDirection', () => {
114
+ it('writes a normalized direction into the light', () => {
115
+ const light = createSpotLight();
116
+ setSpotLightDirection(light, 0, 2, 0);
117
+ expect(light.direction.x).toBeCloseTo(0, 6);
118
+ expect(light.direction.y).toBeCloseTo(1, 6);
119
+ expect(light.direction.z).toBeCloseTo(0, 6);
120
+ });
121
+
122
+ it('leaves direction unchanged for a zero-length input', () => {
123
+ const light = createSpotLight({ direction: createVector3(0, -1, 0) });
124
+ setSpotLightDirection(light, 0, 0, 0);
125
+ expect(light.direction.y).toBeCloseTo(-1, 6);
126
+ });
127
+ });
128
+
129
+ describe('setSpotLightTarget', () => {
130
+ it('sets direction from position toward target', () => {
131
+ const light = createSpotLight({ position: createVector3(0, 0, 0) });
132
+ setSpotLightTarget(light, 0, 0, 5);
133
+ expect(light.direction.x).toBeCloseTo(0, 6);
134
+ expect(light.direction.y).toBeCloseTo(0, 6);
135
+ expect(light.direction.z).toBeCloseTo(1, 6);
136
+ });
137
+
138
+ it('leaves direction unchanged when target equals position', () => {
139
+ const light = createSpotLight({ direction: createVector3(0, -1, 0), position: createVector3(1, 2, 3) });
140
+ setSpotLightTarget(light, 1, 2, 3);
141
+ expect(light.direction.y).toBeCloseTo(-1, 6);
142
+ });
143
+ });