@tonybfox/threejs-tools 1.0.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.
- package/README.md +321 -0
- package/dist/asset-loader/index.cjs +376 -0
- package/dist/asset-loader/index.cjs.map +1 -0
- package/dist/asset-loader/index.d.mts +101 -0
- package/dist/asset-loader/index.d.ts +101 -0
- package/dist/asset-loader/index.mjs +7 -0
- package/dist/asset-loader/index.mjs.map +1 -0
- package/dist/camera/index.cjs +313 -0
- package/dist/camera/index.cjs.map +1 -0
- package/dist/camera/index.d.mts +82 -0
- package/dist/camera/index.d.ts +82 -0
- package/dist/camera/index.mjs +7 -0
- package/dist/camera/index.mjs.map +1 -0
- package/dist/chunk-5DP6WDB3.mjs +1161 -0
- package/dist/chunk-5DP6WDB3.mjs.map +1 -0
- package/dist/chunk-BJKSICFA.mjs +1579 -0
- package/dist/chunk-BJKSICFA.mjs.map +1 -0
- package/dist/chunk-BYRZCHE7.mjs +277 -0
- package/dist/chunk-BYRZCHE7.mjs.map +1 -0
- package/dist/chunk-EIROAPF7.mjs +387 -0
- package/dist/chunk-EIROAPF7.mjs.map +1 -0
- package/dist/chunk-EQDOX34V.mjs +164 -0
- package/dist/chunk-EQDOX34V.mjs.map +1 -0
- package/dist/chunk-IIAZ2WJJ.mjs +405 -0
- package/dist/chunk-IIAZ2WJJ.mjs.map +1 -0
- package/dist/chunk-L4VIIJZD.mjs +340 -0
- package/dist/chunk-L4VIIJZD.mjs.map +1 -0
- package/dist/chunk-P35QJCOG.mjs +339 -0
- package/dist/chunk-P35QJCOG.mjs.map +1 -0
- package/dist/chunk-R64RVBRM.mjs +394 -0
- package/dist/chunk-R64RVBRM.mjs.map +1 -0
- package/dist/compass/index.cjs +375 -0
- package/dist/compass/index.cjs.map +1 -0
- package/dist/compass/index.d.mts +58 -0
- package/dist/compass/index.d.ts +58 -0
- package/dist/compass/index.mjs +7 -0
- package/dist/compass/index.mjs.map +1 -0
- package/dist/grid/index.cjs +200 -0
- package/dist/grid/index.cjs.map +1 -0
- package/dist/grid/index.d.mts +43 -0
- package/dist/grid/index.d.ts +43 -0
- package/dist/grid/index.mjs +7 -0
- package/dist/grid/index.mjs.map +1 -0
- package/dist/index.cjs +5049 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.mjs +47 -0
- package/dist/index.mjs.map +1 -0
- package/dist/measurements/index.cjs +1198 -0
- package/dist/measurements/index.cjs.map +1 -0
- package/dist/measurements/index.d.mts +449 -0
- package/dist/measurements/index.d.ts +449 -0
- package/dist/measurements/index.mjs +9 -0
- package/dist/measurements/index.mjs.map +1 -0
- package/dist/sunlight/index.cjs +441 -0
- package/dist/sunlight/index.cjs.map +1 -0
- package/dist/sunlight/index.d.mts +92 -0
- package/dist/sunlight/index.d.ts +92 -0
- package/dist/sunlight/index.mjs +7 -0
- package/dist/sunlight/index.mjs.map +1 -0
- package/dist/terrain/index.cjs +423 -0
- package/dist/terrain/index.cjs.map +1 -0
- package/dist/terrain/index.d.mts +219 -0
- package/dist/terrain/index.d.ts +219 -0
- package/dist/terrain/index.mjs +7 -0
- package/dist/terrain/index.mjs.map +1 -0
- package/dist/transform-controls/index.cjs +1587 -0
- package/dist/transform-controls/index.cjs.map +1 -0
- package/dist/transform-controls/index.d.mts +162 -0
- package/dist/transform-controls/index.d.ts +162 -0
- package/dist/transform-controls/index.mjs +13 -0
- package/dist/transform-controls/index.mjs.map +1 -0
- package/dist/view-helper/index.cjs +430 -0
- package/dist/view-helper/index.cjs.map +1 -0
- package/dist/view-helper/index.d.mts +75 -0
- package/dist/view-helper/index.d.ts +75 -0
- package/dist/view-helper/index.mjs +7 -0
- package/dist/view-helper/index.mjs.map +1 -0
- package/package.json +124 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// packages/sunlight/src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
SunLightTool: () => SunLightTool
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(src_exports);
|
|
36
|
+
|
|
37
|
+
// packages/sunlight/src/SunLightTool.ts
|
|
38
|
+
var THREE = __toESM(require("three"));
|
|
39
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
40
|
+
var DEG2RAD = Math.PI / 180;
|
|
41
|
+
var RAD2DEG = 180 / Math.PI;
|
|
42
|
+
var J1970 = 2440588;
|
|
43
|
+
var J2000 = 2451545;
|
|
44
|
+
var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
45
|
+
var normalizeLongitude = (value) => {
|
|
46
|
+
const normalized = ((value + 180) % 360 + 360) % 360 - 180;
|
|
47
|
+
return normalized;
|
|
48
|
+
};
|
|
49
|
+
var isLeapYear = (year) => year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
50
|
+
var limitDayOfYear = (day, year) => {
|
|
51
|
+
const maxDay = isLeapYear(year) ? 366 : 365;
|
|
52
|
+
return clamp(Math.floor(day), 1, maxDay);
|
|
53
|
+
};
|
|
54
|
+
var normalizeHours = (hours) => {
|
|
55
|
+
const normalized = hours % 24;
|
|
56
|
+
return normalized < 0 ? normalized + 24 : normalized;
|
|
57
|
+
};
|
|
58
|
+
var TWILIGHT_SUN_COLOR = new THREE.Color(16747612);
|
|
59
|
+
var TWILIGHT_AMBIENT_COLOR = new THREE.Color(16757898);
|
|
60
|
+
var TWILIGHT_SKY_COLOR = new THREE.Color(16750950);
|
|
61
|
+
var TWILIGHT_GROUND_COLOR = new THREE.Color(3549732);
|
|
62
|
+
var toJulian = (date) => date.valueOf() / DAY_MS - 0.5 + J1970;
|
|
63
|
+
var toDays = (date) => toJulian(date) - J2000;
|
|
64
|
+
var solarMeanAnomaly = (days) => DEG2RAD * (357.5291 + 0.98560028 * days);
|
|
65
|
+
var eclipticLongitude = (meanAnomaly) => {
|
|
66
|
+
const c = DEG2RAD * (1.9148 * Math.sin(meanAnomaly) + 0.02 * Math.sin(2 * meanAnomaly) + 3e-4 * Math.sin(3 * meanAnomaly));
|
|
67
|
+
const p = DEG2RAD * 102.9372;
|
|
68
|
+
return meanAnomaly + c + p + Math.PI;
|
|
69
|
+
};
|
|
70
|
+
var declination = (longitude) => {
|
|
71
|
+
const e = DEG2RAD * 23.4397;
|
|
72
|
+
return Math.asin(Math.sin(e) * Math.sin(longitude));
|
|
73
|
+
};
|
|
74
|
+
var rightAscension = (longitude) => {
|
|
75
|
+
const e = DEG2RAD * 23.4397;
|
|
76
|
+
return Math.atan2(Math.sin(longitude) * Math.cos(e), Math.cos(longitude));
|
|
77
|
+
};
|
|
78
|
+
var siderealTime = (days, longitudeWest) => DEG2RAD * (280.16 + 360.9856235 * days) - longitudeWest;
|
|
79
|
+
var solarAzimuth = (hourAngle, latitudeRad, declinationRad) => Math.atan2(
|
|
80
|
+
Math.sin(hourAngle),
|
|
81
|
+
Math.cos(hourAngle) * Math.sin(latitudeRad) - Math.tan(declinationRad) * Math.cos(latitudeRad)
|
|
82
|
+
);
|
|
83
|
+
var solarAltitude = (hourAngle, latitudeRad, declinationRad) => Math.asin(
|
|
84
|
+
Math.sin(latitudeRad) * Math.sin(declinationRad) + Math.cos(latitudeRad) * Math.cos(declinationRad) * Math.cos(hourAngle)
|
|
85
|
+
);
|
|
86
|
+
var computeDayOfYear = (date) => {
|
|
87
|
+
const startOfYear = Date.UTC(date.getUTCFullYear(), 0, 0);
|
|
88
|
+
const diff = date.getTime() - startOfYear;
|
|
89
|
+
return Math.floor(diff / (24 * 60 * 60 * 1e3));
|
|
90
|
+
};
|
|
91
|
+
var buildWeatherPreset = (weather, solarAltitude2) => {
|
|
92
|
+
const altitudeFactor = clamp(Math.sin(solarAltitude2) + 0.1, 0, 1);
|
|
93
|
+
switch (weather) {
|
|
94
|
+
case "sunny":
|
|
95
|
+
return {
|
|
96
|
+
sunIntensity: 1.5 * altitudeFactor,
|
|
97
|
+
sunColor: new THREE.Color(16773839),
|
|
98
|
+
ambientIntensity: 0.35 + 0.45 * altitudeFactor,
|
|
99
|
+
ambientColor: new THREE.Color(16115663),
|
|
100
|
+
hemisphereIntensity: 0.4 + 0.4 * altitudeFactor,
|
|
101
|
+
hemisphereSkyColor: new THREE.Color(12114175),
|
|
102
|
+
hemisphereGroundColor: new THREE.Color(16044458),
|
|
103
|
+
shadowBias: -5e-4
|
|
104
|
+
};
|
|
105
|
+
case "partly-cloudy":
|
|
106
|
+
return {
|
|
107
|
+
sunIntensity: 1.1 * altitudeFactor,
|
|
108
|
+
sunColor: new THREE.Color(16774885),
|
|
109
|
+
ambientIntensity: 0.45 + 0.35 * altitudeFactor,
|
|
110
|
+
ambientColor: new THREE.Color(15265009),
|
|
111
|
+
hemisphereIntensity: 0.5 + 0.3 * altitudeFactor,
|
|
112
|
+
hemisphereSkyColor: new THREE.Color(13162475),
|
|
113
|
+
hemisphereGroundColor: new THREE.Color(15129026),
|
|
114
|
+
shadowBias: -3e-4
|
|
115
|
+
};
|
|
116
|
+
case "overcast":
|
|
117
|
+
return {
|
|
118
|
+
sunIntensity: 0.35 * altitudeFactor,
|
|
119
|
+
sunColor: new THREE.Color(15791359),
|
|
120
|
+
ambientIntensity: 0.75,
|
|
121
|
+
ambientColor: new THREE.Color(14278117),
|
|
122
|
+
hemisphereIntensity: 0.8,
|
|
123
|
+
hemisphereSkyColor: new THREE.Color(13489631),
|
|
124
|
+
hemisphereGroundColor: new THREE.Color(13158600),
|
|
125
|
+
shadowBias: -1e-4
|
|
126
|
+
};
|
|
127
|
+
default:
|
|
128
|
+
return {
|
|
129
|
+
sunIntensity: 1 * altitudeFactor,
|
|
130
|
+
sunColor: new THREE.Color(16767411),
|
|
131
|
+
ambientIntensity: 0.35 + 0.25 * altitudeFactor,
|
|
132
|
+
ambientColor: new THREE.Color(16769988),
|
|
133
|
+
hemisphereIntensity: 0.4 + 0.3 * altitudeFactor,
|
|
134
|
+
hemisphereSkyColor: new THREE.Color(16763043),
|
|
135
|
+
hemisphereGroundColor: new THREE.Color(6243898),
|
|
136
|
+
shadowBias: -2e-4
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var SunLightTool = class extends THREE.EventDispatcher {
|
|
141
|
+
constructor(scene, options = {}) {
|
|
142
|
+
super();
|
|
143
|
+
this.createdLight = false;
|
|
144
|
+
this.createdHemisphere = false;
|
|
145
|
+
this.scene = scene;
|
|
146
|
+
const defaultLatitude = options.latitude ?? 51.5072;
|
|
147
|
+
const defaultLongitude = options.longitude ?? -0.1276;
|
|
148
|
+
this.latitude = clamp(defaultLatitude, -90, 90);
|
|
149
|
+
this.longitude = normalizeLongitude(defaultLongitude);
|
|
150
|
+
this.referenceYear = options.referenceYear ?? (/* @__PURE__ */ new Date()).getUTCFullYear();
|
|
151
|
+
this.dayOfYear = limitDayOfYear(
|
|
152
|
+
options.dayOfYear ?? 172,
|
|
153
|
+
this.referenceYear
|
|
154
|
+
);
|
|
155
|
+
this.timeOfDay = normalizeHours(options.timeOfDay ?? 12);
|
|
156
|
+
this.timeZoneOffsetMinutes = options.timeZoneOffsetMinutes ?? 0;
|
|
157
|
+
this.weather = options.weather ?? "sunny";
|
|
158
|
+
this.useSystemTime = options.useSystemTime ?? false;
|
|
159
|
+
this.lightDistance = options.lightDistance ?? 150;
|
|
160
|
+
this.shadowCameraSize = options.shadowCameraSize ?? 100;
|
|
161
|
+
this.shadowCameraFar = options.shadowCameraFar ?? 600;
|
|
162
|
+
const existingDirectional = options.light;
|
|
163
|
+
this.light = existingDirectional ?? new THREE.DirectionalLight(16777215, 1);
|
|
164
|
+
this.createdLight = !existingDirectional;
|
|
165
|
+
if (!this.light.parent) {
|
|
166
|
+
this.scene.add(this.light);
|
|
167
|
+
}
|
|
168
|
+
if (!this.light.target.parent) {
|
|
169
|
+
this.scene.add(this.light.target);
|
|
170
|
+
}
|
|
171
|
+
this.configureShadowMap(this.light);
|
|
172
|
+
if (options.ambientLight) {
|
|
173
|
+
this.ambientLight = options.ambientLight;
|
|
174
|
+
}
|
|
175
|
+
if (options.enableHemisphereLight ?? true) {
|
|
176
|
+
this.hemisphereLight = new THREE.HemisphereLight(
|
|
177
|
+
options.hemisphereSkyColor ?? 12244223,
|
|
178
|
+
options.hemisphereGroundColor ?? 7628634,
|
|
179
|
+
options.hemisphereIntensity ?? 0.45
|
|
180
|
+
);
|
|
181
|
+
this.scene.add(this.hemisphereLight);
|
|
182
|
+
this.createdHemisphere = true;
|
|
183
|
+
}
|
|
184
|
+
if (options.showHelper) {
|
|
185
|
+
this.helper = new THREE.DirectionalLightHelper(
|
|
186
|
+
this.light,
|
|
187
|
+
options.helperSize ?? 25,
|
|
188
|
+
options.helperColor ?? 16765567
|
|
189
|
+
);
|
|
190
|
+
this.scene.add(this.helper);
|
|
191
|
+
}
|
|
192
|
+
this.state = {
|
|
193
|
+
date: /* @__PURE__ */ new Date(),
|
|
194
|
+
latitude: this.latitude,
|
|
195
|
+
longitude: this.longitude,
|
|
196
|
+
solarAzimuth: 0,
|
|
197
|
+
solarAltitude: 0,
|
|
198
|
+
weather: this.weather,
|
|
199
|
+
useSystemTime: this.useSystemTime
|
|
200
|
+
};
|
|
201
|
+
this.update();
|
|
202
|
+
}
|
|
203
|
+
getLight() {
|
|
204
|
+
return this.light;
|
|
205
|
+
}
|
|
206
|
+
getHemisphereLight() {
|
|
207
|
+
return this.hemisphereLight;
|
|
208
|
+
}
|
|
209
|
+
getState() {
|
|
210
|
+
return { ...this.state, date: new Date(this.state.date.getTime()) };
|
|
211
|
+
}
|
|
212
|
+
getDayOfYear() {
|
|
213
|
+
return this.dayOfYear;
|
|
214
|
+
}
|
|
215
|
+
getTimeOfDay() {
|
|
216
|
+
return this.timeOfDay;
|
|
217
|
+
}
|
|
218
|
+
getTimeZoneOffset() {
|
|
219
|
+
return this.timeZoneOffsetMinutes;
|
|
220
|
+
}
|
|
221
|
+
getWeather() {
|
|
222
|
+
return this.weather;
|
|
223
|
+
}
|
|
224
|
+
usesSystemTime() {
|
|
225
|
+
return this.useSystemTime;
|
|
226
|
+
}
|
|
227
|
+
setLatitude(latitude) {
|
|
228
|
+
const clamped = clamp(latitude, -90, 90);
|
|
229
|
+
if (clamped === this.latitude) return;
|
|
230
|
+
this.latitude = clamped;
|
|
231
|
+
this.update();
|
|
232
|
+
}
|
|
233
|
+
setLongitude(longitude) {
|
|
234
|
+
const normalized = normalizeLongitude(longitude);
|
|
235
|
+
if (normalized === this.longitude) return;
|
|
236
|
+
this.longitude = normalized;
|
|
237
|
+
this.update();
|
|
238
|
+
}
|
|
239
|
+
setLocation(latitude, longitude) {
|
|
240
|
+
let changed = false;
|
|
241
|
+
const lat = clamp(latitude, -90, 90);
|
|
242
|
+
if (lat !== this.latitude) {
|
|
243
|
+
this.latitude = lat;
|
|
244
|
+
changed = true;
|
|
245
|
+
}
|
|
246
|
+
const lon = normalizeLongitude(longitude);
|
|
247
|
+
if (lon !== this.longitude) {
|
|
248
|
+
this.longitude = lon;
|
|
249
|
+
changed = true;
|
|
250
|
+
}
|
|
251
|
+
if (changed) {
|
|
252
|
+
this.update();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
setDayOfYear(day) {
|
|
256
|
+
const limited = limitDayOfYear(day, this.referenceYear);
|
|
257
|
+
if (limited === this.dayOfYear) return;
|
|
258
|
+
this.dayOfYear = limited;
|
|
259
|
+
this.update();
|
|
260
|
+
}
|
|
261
|
+
setTimeOfDay(hours) {
|
|
262
|
+
const normalized = normalizeHours(hours);
|
|
263
|
+
if (normalized === this.timeOfDay) return;
|
|
264
|
+
this.timeOfDay = normalized;
|
|
265
|
+
this.update();
|
|
266
|
+
}
|
|
267
|
+
setTimeZoneOffset(minutes) {
|
|
268
|
+
if (minutes === this.timeZoneOffsetMinutes) return;
|
|
269
|
+
this.timeZoneOffsetMinutes = minutes;
|
|
270
|
+
this.update();
|
|
271
|
+
}
|
|
272
|
+
setWeather(weather) {
|
|
273
|
+
if (weather === this.weather) return;
|
|
274
|
+
this.weather = weather;
|
|
275
|
+
this.dispatchEvent({ type: "weatherChanged", weather });
|
|
276
|
+
this.update();
|
|
277
|
+
}
|
|
278
|
+
setUseSystemTime(enabled) {
|
|
279
|
+
if (enabled === this.useSystemTime) return;
|
|
280
|
+
this.useSystemTime = enabled;
|
|
281
|
+
this.dispatchEvent({
|
|
282
|
+
type: "systemTimeToggled",
|
|
283
|
+
useSystemTime: this.useSystemTime
|
|
284
|
+
});
|
|
285
|
+
this.update();
|
|
286
|
+
}
|
|
287
|
+
update(dateOverride) {
|
|
288
|
+
const date = this.computeDate(dateOverride);
|
|
289
|
+
const position = this.computeSunPosition(date);
|
|
290
|
+
this.applySunPosition(position, date);
|
|
291
|
+
this.state = {
|
|
292
|
+
date,
|
|
293
|
+
latitude: this.latitude,
|
|
294
|
+
longitude: this.longitude,
|
|
295
|
+
solarAzimuth: position.azimuth,
|
|
296
|
+
solarAltitude: position.altitude,
|
|
297
|
+
weather: this.weather,
|
|
298
|
+
useSystemTime: this.useSystemTime
|
|
299
|
+
};
|
|
300
|
+
this.applyWeather(position.altitude);
|
|
301
|
+
this.dispatchEvent({ type: "stateChanged", state: this.getState() });
|
|
302
|
+
}
|
|
303
|
+
dispose() {
|
|
304
|
+
if (this.helper) {
|
|
305
|
+
this.scene.remove(this.helper);
|
|
306
|
+
this.helper.dispose();
|
|
307
|
+
this.helper = void 0;
|
|
308
|
+
}
|
|
309
|
+
if (this.createdHemisphere && this.hemisphereLight) {
|
|
310
|
+
this.scene.remove(this.hemisphereLight);
|
|
311
|
+
this.hemisphereLight.dispose();
|
|
312
|
+
this.hemisphereLight = void 0;
|
|
313
|
+
}
|
|
314
|
+
if (this.createdLight && this.light) {
|
|
315
|
+
this.scene.remove(this.light);
|
|
316
|
+
if (this.light.shadow?.map) {
|
|
317
|
+
this.light.shadow.map.dispose();
|
|
318
|
+
}
|
|
319
|
+
this.light.dispose();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
configureShadowMap(light) {
|
|
323
|
+
light.castShadow = true;
|
|
324
|
+
const camera = light.shadow.camera;
|
|
325
|
+
if (camera instanceof THREE.OrthographicCamera && typeof this.shadowCameraSize === "number") {
|
|
326
|
+
const size = this.shadowCameraSize;
|
|
327
|
+
camera.left = -size;
|
|
328
|
+
camera.right = size;
|
|
329
|
+
camera.top = size;
|
|
330
|
+
camera.bottom = -size;
|
|
331
|
+
camera.near = 0.5;
|
|
332
|
+
camera.far = this.shadowCameraFar;
|
|
333
|
+
camera.updateProjectionMatrix();
|
|
334
|
+
}
|
|
335
|
+
light.shadow.mapSize.set(2048, 2048);
|
|
336
|
+
light.shadow.bias = -5e-4;
|
|
337
|
+
}
|
|
338
|
+
computeDate(dateOverride) {
|
|
339
|
+
if (dateOverride) {
|
|
340
|
+
return new Date(dateOverride.getTime());
|
|
341
|
+
}
|
|
342
|
+
if (this.useSystemTime) {
|
|
343
|
+
const now = /* @__PURE__ */ new Date();
|
|
344
|
+
this.referenceYear = now.getUTCFullYear();
|
|
345
|
+
this.dayOfYear = computeDayOfYear(now);
|
|
346
|
+
this.timeOfDay = now.getUTCHours() + now.getUTCMinutes() / 60 + now.getUTCSeconds() / 3600;
|
|
347
|
+
return now;
|
|
348
|
+
}
|
|
349
|
+
const daysInYear = isLeapYear(this.referenceYear) ? 366 : 365;
|
|
350
|
+
const dayIndex = clamp(this.dayOfYear, 1, daysInYear);
|
|
351
|
+
const date = new Date(Date.UTC(this.referenceYear, 0, 1, 0, 0, 0, 0));
|
|
352
|
+
const minutesFromYearStart = (dayIndex - 1) * 24 * 60 + this.timeOfDay * 60 - this.timeZoneOffsetMinutes;
|
|
353
|
+
date.setUTCMinutes(minutesFromYearStart);
|
|
354
|
+
return date;
|
|
355
|
+
}
|
|
356
|
+
computeSunPosition(date) {
|
|
357
|
+
const days = toDays(date);
|
|
358
|
+
const lw = -this.longitude * DEG2RAD;
|
|
359
|
+
const phi = this.latitude * DEG2RAD;
|
|
360
|
+
const meanAnomaly = solarMeanAnomaly(days);
|
|
361
|
+
const longitude = eclipticLongitude(meanAnomaly);
|
|
362
|
+
const decl = declination(longitude);
|
|
363
|
+
const ra = rightAscension(longitude);
|
|
364
|
+
const sidereal = siderealTime(days, lw);
|
|
365
|
+
const hourAngle = sidereal - ra;
|
|
366
|
+
return {
|
|
367
|
+
azimuth: solarAzimuth(hourAngle, phi, decl),
|
|
368
|
+
altitude: solarAltitude(hourAngle, phi, decl)
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
applySunPosition(position, date) {
|
|
372
|
+
const radius = this.lightDistance;
|
|
373
|
+
const altitude = position.altitude;
|
|
374
|
+
const azimuth = position.azimuth;
|
|
375
|
+
const x = -radius * Math.cos(altitude) * Math.sin(azimuth);
|
|
376
|
+
const y = radius * Math.sin(altitude);
|
|
377
|
+
const z = radius * Math.cos(altitude) * Math.cos(azimuth);
|
|
378
|
+
this.light.position.set(x, y, z);
|
|
379
|
+
this.light.target.position.set(0, 0, 0);
|
|
380
|
+
this.light.target.updateMatrixWorld();
|
|
381
|
+
if (this.helper) {
|
|
382
|
+
this.helper.update();
|
|
383
|
+
}
|
|
384
|
+
if (!this.useSystemTime) {
|
|
385
|
+
this.referenceYear = date.getUTCFullYear();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
applyWeather(solarAltitude2) {
|
|
389
|
+
const preset = buildWeatherPreset(this.weather, solarAltitude2);
|
|
390
|
+
const altitudeDeg = solarAltitude2 * RAD2DEG;
|
|
391
|
+
const twilightStartDeg = -6;
|
|
392
|
+
const daylightDeg = 4;
|
|
393
|
+
const daylightRange = daylightDeg - twilightStartDeg;
|
|
394
|
+
const daylightFactor = clamp(
|
|
395
|
+
(altitudeDeg - twilightStartDeg) / daylightRange,
|
|
396
|
+
0,
|
|
397
|
+
1
|
|
398
|
+
);
|
|
399
|
+
const twilightFactor = 1 - daylightFactor;
|
|
400
|
+
const sunColor = preset.sunColor.lerp(TWILIGHT_SUN_COLOR, twilightFactor);
|
|
401
|
+
const ambientColor = preset.ambientColor.lerp(
|
|
402
|
+
TWILIGHT_AMBIENT_COLOR,
|
|
403
|
+
twilightFactor
|
|
404
|
+
);
|
|
405
|
+
const skyColor = preset.hemisphereSkyColor.lerp(
|
|
406
|
+
TWILIGHT_SKY_COLOR,
|
|
407
|
+
twilightFactor
|
|
408
|
+
);
|
|
409
|
+
const groundColor = preset.hemisphereGroundColor.lerp(
|
|
410
|
+
TWILIGHT_GROUND_COLOR,
|
|
411
|
+
twilightFactor
|
|
412
|
+
);
|
|
413
|
+
const adjustedSunIntensity = preset.sunIntensity * daylightFactor;
|
|
414
|
+
const adjustedAmbientIntensity = Math.max(
|
|
415
|
+
0.05,
|
|
416
|
+
preset.ambientIntensity * (0.3 + 0.7 * daylightFactor)
|
|
417
|
+
);
|
|
418
|
+
const adjustedHemisphereIntensity = Math.max(
|
|
419
|
+
0.05,
|
|
420
|
+
preset.hemisphereIntensity * (0.35 + 0.65 * daylightFactor)
|
|
421
|
+
);
|
|
422
|
+
this.light.intensity = adjustedSunIntensity;
|
|
423
|
+
this.light.visible = adjustedSunIntensity > 1e-3;
|
|
424
|
+
this.light.color.copy(sunColor);
|
|
425
|
+
this.light.shadow.bias = preset.shadowBias;
|
|
426
|
+
if (this.ambientLight) {
|
|
427
|
+
this.ambientLight.intensity = adjustedAmbientIntensity;
|
|
428
|
+
this.ambientLight.color.copy(ambientColor);
|
|
429
|
+
}
|
|
430
|
+
if (this.hemisphereLight) {
|
|
431
|
+
this.hemisphereLight.intensity = adjustedHemisphereIntensity;
|
|
432
|
+
this.hemisphereLight.color.copy(skyColor);
|
|
433
|
+
this.hemisphereLight.groundColor.copy(groundColor);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
438
|
+
0 && (module.exports = {
|
|
439
|
+
SunLightTool
|
|
440
|
+
});
|
|
441
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../packages/sunlight/src/index.ts","../../packages/sunlight/src/SunLightTool.ts"],"sourcesContent":["export * from './SunLightTool'\n","import * as THREE from 'three'\n\nexport type SunLightWeather = 'sunny' | 'partly-cloudy' | 'overcast'\n\nexport interface SunLightToolOptions {\n light?: THREE.DirectionalLight\n ambientLight?: THREE.Light\n latitude?: number\n longitude?: number\n dayOfYear?: number\n timeOfDay?: number\n timeZoneOffsetMinutes?: number\n referenceYear?: number\n useSystemTime?: boolean\n weather?: SunLightWeather\n showHelper?: boolean\n helperSize?: number\n helperColor?: number\n enableHemisphereLight?: boolean\n hemisphereSkyColor?: number\n hemisphereGroundColor?: number\n hemisphereIntensity?: number\n lightDistance?: number\n shadowCameraSize?: number\n shadowCameraFar?: number\n}\n\nexport interface SunLightState {\n date: Date\n latitude: number\n longitude: number\n solarAzimuth: number\n solarAltitude: number\n weather: SunLightWeather\n useSystemTime: boolean\n}\n\nexport interface SunLightToolEvents {\n stateChanged: { state: SunLightState }\n weatherChanged: { weather: SunLightWeather }\n systemTimeToggled: { useSystemTime: boolean }\n}\n\ninterface WeatherPresetConfig {\n sunIntensity: number\n sunColor: THREE.Color\n ambientIntensity: number\n ambientColor: THREE.Color\n hemisphereIntensity: number\n hemisphereSkyColor: THREE.Color\n hemisphereGroundColor: THREE.Color\n shadowBias: number\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000\nconst DEG2RAD = Math.PI / 180\nconst RAD2DEG = 180 / Math.PI\nconst J1970 = 2440588\nconst J2000 = 2451545\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.min(Math.max(value, min), max)\n\nconst normalizeLongitude = (value: number): number => {\n const normalized = ((((value + 180) % 360) + 360) % 360) - 180\n return normalized\n}\n\nconst isLeapYear = (year: number): boolean =>\n (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\n\nconst limitDayOfYear = (day: number, year: number): number => {\n const maxDay = isLeapYear(year) ? 366 : 365\n return clamp(Math.floor(day), 1, maxDay)\n}\n\nconst normalizeHours = (hours: number): number => {\n const normalized = hours % 24\n return normalized < 0 ? normalized + 24 : normalized\n}\n\nconst TWILIGHT_SUN_COLOR = new THREE.Color(0xff8c5c)\nconst TWILIGHT_AMBIENT_COLOR = new THREE.Color(0xffb48a)\nconst TWILIGHT_SKY_COLOR = new THREE.Color(0xff9966)\nconst TWILIGHT_GROUND_COLOR = new THREE.Color(0x362a24)\n\nconst toJulian = (date: Date): number => date.valueOf() / DAY_MS - 0.5 + J1970\nconst toDays = (date: Date): number => toJulian(date) - J2000\n\nconst solarMeanAnomaly = (days: number): number =>\n DEG2RAD * (357.5291 + 0.98560028 * days)\n\nconst eclipticLongitude = (meanAnomaly: number): number => {\n const c =\n DEG2RAD *\n (1.9148 * Math.sin(meanAnomaly) +\n 0.02 * Math.sin(2 * meanAnomaly) +\n 0.0003 * Math.sin(3 * meanAnomaly))\n const p = DEG2RAD * 102.9372\n return meanAnomaly + c + p + Math.PI\n}\n\nconst declination = (longitude: number): number => {\n const e = DEG2RAD * 23.4397\n return Math.asin(Math.sin(e) * Math.sin(longitude))\n}\n\nconst rightAscension = (longitude: number): number => {\n const e = DEG2RAD * 23.4397\n return Math.atan2(Math.sin(longitude) * Math.cos(e), Math.cos(longitude))\n}\n\nconst siderealTime = (days: number, longitudeWest: number): number =>\n DEG2RAD * (280.16 + 360.9856235 * days) - longitudeWest\n\nconst solarAzimuth = (\n hourAngle: number,\n latitudeRad: number,\n declinationRad: number\n): number =>\n Math.atan2(\n Math.sin(hourAngle),\n Math.cos(hourAngle) * Math.sin(latitudeRad) -\n Math.tan(declinationRad) * Math.cos(latitudeRad)\n )\n\nconst solarAltitude = (\n hourAngle: number,\n latitudeRad: number,\n declinationRad: number\n): number =>\n Math.asin(\n Math.sin(latitudeRad) * Math.sin(declinationRad) +\n Math.cos(latitudeRad) * Math.cos(declinationRad) * Math.cos(hourAngle)\n )\n\nconst computeDayOfYear = (date: Date): number => {\n const startOfYear = Date.UTC(date.getUTCFullYear(), 0, 0)\n const diff = date.getTime() - startOfYear\n return Math.floor(diff / (24 * 60 * 60 * 1000))\n}\n\nconst buildWeatherPreset = (\n weather: SunLightWeather,\n solarAltitude: number\n): WeatherPresetConfig => {\n const altitudeFactor = clamp(Math.sin(solarAltitude) + 0.1, 0, 1)\n switch (weather) {\n case 'sunny':\n return {\n sunIntensity: 1.5 * altitudeFactor,\n sunColor: new THREE.Color(0xfff2cf),\n ambientIntensity: 0.35 + 0.45 * altitudeFactor,\n ambientColor: new THREE.Color(0xf5e7cf),\n hemisphereIntensity: 0.4 + 0.4 * altitudeFactor,\n hemisphereSkyColor: new THREE.Color(0xb8d8ff),\n hemisphereGroundColor: new THREE.Color(0xf4d1aa),\n shadowBias: -0.0005,\n }\n case 'partly-cloudy':\n return {\n sunIntensity: 1.1 * altitudeFactor,\n sunColor: new THREE.Color(0xfff6e5),\n ambientIntensity: 0.45 + 0.35 * altitudeFactor,\n ambientColor: new THREE.Color(0xe8ecf1),\n hemisphereIntensity: 0.5 + 0.3 * altitudeFactor,\n hemisphereSkyColor: new THREE.Color(0xc8d7eb),\n hemisphereGroundColor: new THREE.Color(0xe6d9c2),\n shadowBias: -0.0003,\n }\n case 'overcast':\n return {\n sunIntensity: 0.35 * altitudeFactor,\n sunColor: new THREE.Color(0xf0f4ff),\n ambientIntensity: 0.75,\n ambientColor: new THREE.Color(0xd9dde5),\n hemisphereIntensity: 0.8,\n hemisphereSkyColor: new THREE.Color(0xcdd5df),\n hemisphereGroundColor: new THREE.Color(0xc8c8c8),\n shadowBias: -0.0001,\n }\n default:\n return {\n sunIntensity: 1.0 * altitudeFactor,\n sunColor: new THREE.Color(0xffd9b3),\n ambientIntensity: 0.35 + 0.25 * altitudeFactor,\n ambientColor: new THREE.Color(0xffe3c4),\n hemisphereIntensity: 0.4 + 0.3 * altitudeFactor,\n hemisphereSkyColor: new THREE.Color(0xffc8a3),\n hemisphereGroundColor: new THREE.Color(0x5f463a),\n shadowBias: -0.0002,\n }\n }\n}\n\nexport class SunLightTool extends THREE.EventDispatcher<SunLightToolEvents> {\n private scene: THREE.Scene\n private light: THREE.DirectionalLight\n private ambientLight?: THREE.Light\n private hemisphereLight?: THREE.HemisphereLight\n private helper?: THREE.DirectionalLightHelper\n private createdLight: boolean = false\n private createdHemisphere: boolean = false\n private latitude: number\n private longitude: number\n private dayOfYear: number\n private timeOfDay: number\n private timeZoneOffsetMinutes: number\n private referenceYear: number\n private weather: SunLightWeather\n private useSystemTime: boolean\n private lightDistance: number\n private shadowCameraSize: number\n private shadowCameraFar: number\n private state: SunLightState\n\n constructor(scene: THREE.Scene, options: SunLightToolOptions = {}) {\n super()\n this.scene = scene\n const defaultLatitude = options.latitude ?? 51.5072\n const defaultLongitude = options.longitude ?? -0.1276\n this.latitude = clamp(defaultLatitude, -90, 90)\n this.longitude = normalizeLongitude(defaultLongitude)\n this.referenceYear = options.referenceYear ?? new Date().getUTCFullYear()\n this.dayOfYear = limitDayOfYear(\n options.dayOfYear ?? 172,\n this.referenceYear\n )\n this.timeOfDay = normalizeHours(options.timeOfDay ?? 12)\n this.timeZoneOffsetMinutes = options.timeZoneOffsetMinutes ?? 0\n this.weather = options.weather ?? 'sunny'\n this.useSystemTime = options.useSystemTime ?? false\n this.lightDistance = options.lightDistance ?? 150\n this.shadowCameraSize = options.shadowCameraSize ?? 100\n this.shadowCameraFar = options.shadowCameraFar ?? 600\n\n const existingDirectional = options.light\n this.light =\n existingDirectional ?? new THREE.DirectionalLight(0xffffff, 1.0)\n this.createdLight = !existingDirectional\n\n if (!this.light.parent) {\n this.scene.add(this.light)\n }\n\n if (!this.light.target.parent) {\n this.scene.add(this.light.target)\n }\n\n this.configureShadowMap(this.light)\n\n if (options.ambientLight) {\n this.ambientLight = options.ambientLight\n }\n\n if (options.enableHemisphereLight ?? true) {\n this.hemisphereLight = new THREE.HemisphereLight(\n options.hemisphereSkyColor ?? 0xbad4ff,\n options.hemisphereGroundColor ?? 0x74675a,\n options.hemisphereIntensity ?? 0.45\n )\n this.scene.add(this.hemisphereLight)\n this.createdHemisphere = true\n }\n\n if (options.showHelper) {\n this.helper = new THREE.DirectionalLightHelper(\n this.light,\n options.helperSize ?? 25,\n options.helperColor ?? 0xffd27f\n )\n this.scene.add(this.helper)\n }\n\n this.state = {\n date: new Date(),\n latitude: this.latitude,\n longitude: this.longitude,\n solarAzimuth: 0,\n solarAltitude: 0,\n weather: this.weather,\n useSystemTime: this.useSystemTime,\n }\n\n this.update()\n }\n\n getLight(): THREE.DirectionalLight {\n return this.light\n }\n\n getHemisphereLight(): THREE.HemisphereLight | undefined {\n return this.hemisphereLight\n }\n\n getState(): SunLightState {\n return { ...this.state, date: new Date(this.state.date.getTime()) }\n }\n\n getDayOfYear(): number {\n return this.dayOfYear\n }\n\n getTimeOfDay(): number {\n return this.timeOfDay\n }\n\n getTimeZoneOffset(): number {\n return this.timeZoneOffsetMinutes\n }\n\n getWeather(): SunLightWeather {\n return this.weather\n }\n\n usesSystemTime(): boolean {\n return this.useSystemTime\n }\n\n setLatitude(latitude: number): void {\n const clamped = clamp(latitude, -90, 90)\n if (clamped === this.latitude) return\n this.latitude = clamped\n this.update()\n }\n\n setLongitude(longitude: number): void {\n const normalized = normalizeLongitude(longitude)\n if (normalized === this.longitude) return\n this.longitude = normalized\n this.update()\n }\n\n setLocation(latitude: number, longitude: number): void {\n let changed = false\n const lat = clamp(latitude, -90, 90)\n if (lat !== this.latitude) {\n this.latitude = lat\n changed = true\n }\n const lon = normalizeLongitude(longitude)\n if (lon !== this.longitude) {\n this.longitude = lon\n changed = true\n }\n if (changed) {\n this.update()\n }\n }\n\n setDayOfYear(day: number): void {\n const limited = limitDayOfYear(day, this.referenceYear)\n if (limited === this.dayOfYear) return\n this.dayOfYear = limited\n this.update()\n }\n\n setTimeOfDay(hours: number): void {\n const normalized = normalizeHours(hours)\n if (normalized === this.timeOfDay) return\n this.timeOfDay = normalized\n this.update()\n }\n\n setTimeZoneOffset(minutes: number): void {\n if (minutes === this.timeZoneOffsetMinutes) return\n this.timeZoneOffsetMinutes = minutes\n this.update()\n }\n\n setWeather(weather: SunLightWeather): void {\n if (weather === this.weather) return\n this.weather = weather\n this.dispatchEvent({ type: 'weatherChanged', weather })\n this.update()\n }\n\n setUseSystemTime(enabled: boolean): void {\n if (enabled === this.useSystemTime) return\n this.useSystemTime = enabled\n this.dispatchEvent({\n type: 'systemTimeToggled',\n useSystemTime: this.useSystemTime,\n })\n this.update()\n }\n\n update(dateOverride?: Date): void {\n const date = this.computeDate(dateOverride)\n const position = this.computeSunPosition(date)\n this.applySunPosition(position, date)\n this.state = {\n date,\n latitude: this.latitude,\n longitude: this.longitude,\n solarAzimuth: position.azimuth,\n solarAltitude: position.altitude,\n weather: this.weather,\n useSystemTime: this.useSystemTime,\n }\n this.applyWeather(position.altitude)\n this.dispatchEvent({ type: 'stateChanged', state: this.getState() })\n }\n\n dispose(): void {\n if (this.helper) {\n this.scene.remove(this.helper)\n this.helper.dispose()\n this.helper = undefined\n }\n\n if (this.createdHemisphere && this.hemisphereLight) {\n this.scene.remove(this.hemisphereLight)\n this.hemisphereLight.dispose()\n this.hemisphereLight = undefined\n }\n\n if (this.createdLight && this.light) {\n this.scene.remove(this.light)\n if (this.light.shadow?.map) {\n this.light.shadow.map.dispose()\n }\n this.light.dispose()\n }\n }\n\n private configureShadowMap(light: THREE.DirectionalLight): void {\n light.castShadow = true\n const camera = light.shadow.camera\n if (\n camera instanceof THREE.OrthographicCamera &&\n typeof this.shadowCameraSize === 'number'\n ) {\n const size = this.shadowCameraSize\n camera.left = -size\n camera.right = size\n camera.top = size\n camera.bottom = -size\n camera.near = 0.5\n camera.far = this.shadowCameraFar\n camera.updateProjectionMatrix()\n }\n light.shadow.mapSize.set(2048, 2048)\n light.shadow.bias = -0.0005\n }\n\n private computeDate(dateOverride?: Date): Date {\n if (dateOverride) {\n return new Date(dateOverride.getTime())\n }\n\n if (this.useSystemTime) {\n const now = new Date()\n this.referenceYear = now.getUTCFullYear()\n this.dayOfYear = computeDayOfYear(now)\n this.timeOfDay =\n now.getUTCHours() +\n now.getUTCMinutes() / 60 +\n now.getUTCSeconds() / 3600\n return now\n }\n\n const daysInYear = isLeapYear(this.referenceYear) ? 366 : 365\n const dayIndex = clamp(this.dayOfYear, 1, daysInYear)\n const date = new Date(Date.UTC(this.referenceYear, 0, 1, 0, 0, 0, 0))\n const minutesFromYearStart =\n (dayIndex - 1) * 24 * 60 +\n this.timeOfDay * 60 -\n this.timeZoneOffsetMinutes\n date.setUTCMinutes(minutesFromYearStart)\n return date\n }\n\n private computeSunPosition(date: Date): {\n azimuth: number\n altitude: number\n } {\n const days = toDays(date)\n const lw = -this.longitude * DEG2RAD\n const phi = this.latitude * DEG2RAD\n const meanAnomaly = solarMeanAnomaly(days)\n const longitude = eclipticLongitude(meanAnomaly)\n const decl = declination(longitude)\n const ra = rightAscension(longitude)\n const sidereal = siderealTime(days, lw)\n const hourAngle = sidereal - ra\n return {\n azimuth: solarAzimuth(hourAngle, phi, decl),\n altitude: solarAltitude(hourAngle, phi, decl),\n }\n }\n\n private applySunPosition(\n position: { azimuth: number; altitude: number },\n date: Date\n ): void {\n const radius = this.lightDistance\n const altitude = position.altitude\n // Astronomical azimuth: 0° = South, increasing clockwise (East=90°, North=180°, West=270°)\n // Three.js coordinates: +X = East, +Z = North, -X = West, -Z = South\n // The solarAzimuth function returns azimuth measured from South, clockwise\n const azimuth = position.azimuth\n\n // Correct coordinate mapping for Three.js\n // sin(azimuth) gives us the East-West component, but we need to negate it:\n // azimuth 90° (East) should give +X, azimuth 270° (West) should give -X\n // cos(azimuth) gives us the North-South component, also needs to be positive for correct clockwise motion:\n // azimuth 0° (South) should give -Z, azimuth 180° (North) should give +Z\n const x = -radius * Math.cos(altitude) * Math.sin(azimuth)\n const y = radius * Math.sin(altitude)\n const z = radius * Math.cos(altitude) * Math.cos(azimuth)\n\n this.light.position.set(x, y, z)\n this.light.target.position.set(0, 0, 0)\n this.light.target.updateMatrixWorld()\n\n if (this.helper) {\n this.helper.update()\n }\n\n // Update cached time properties when not using real-time\n if (!this.useSystemTime) {\n this.referenceYear = date.getUTCFullYear()\n }\n }\n\n private applyWeather(solarAltitude: number): void {\n const preset = buildWeatherPreset(this.weather, solarAltitude)\n const altitudeDeg = solarAltitude * RAD2DEG\n const twilightStartDeg = -6\n const daylightDeg = 4\n const daylightRange = daylightDeg - twilightStartDeg\n\n const daylightFactor = clamp(\n (altitudeDeg - twilightStartDeg) / daylightRange,\n 0,\n 1\n )\n const twilightFactor = 1 - daylightFactor\n\n const sunColor = preset.sunColor.lerp(TWILIGHT_SUN_COLOR, twilightFactor)\n const ambientColor = preset.ambientColor.lerp(\n TWILIGHT_AMBIENT_COLOR,\n twilightFactor\n )\n const skyColor = preset.hemisphereSkyColor.lerp(\n TWILIGHT_SKY_COLOR,\n twilightFactor\n )\n const groundColor = preset.hemisphereGroundColor.lerp(\n TWILIGHT_GROUND_COLOR,\n twilightFactor\n )\n\n const adjustedSunIntensity = preset.sunIntensity * daylightFactor\n const adjustedAmbientIntensity = Math.max(\n 0.05,\n preset.ambientIntensity * (0.3 + 0.7 * daylightFactor)\n )\n const adjustedHemisphereIntensity = Math.max(\n 0.05,\n preset.hemisphereIntensity * (0.35 + 0.65 * daylightFactor)\n )\n\n this.light.intensity = adjustedSunIntensity\n this.light.visible = adjustedSunIntensity > 0.001\n this.light.color.copy(sunColor)\n this.light.shadow.bias = preset.shadowBias\n\n if (this.ambientLight) {\n this.ambientLight.intensity = adjustedAmbientIntensity\n this.ambientLight.color.copy(ambientColor)\n }\n\n if (this.hemisphereLight) {\n this.hemisphereLight.intensity = adjustedHemisphereIntensity\n this.hemisphereLight.color.copy(skyColor)\n this.hemisphereLight.groundColor.copy(groundColor)\n }\n }\n}\n"],"mappings":"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","names":["solarAltitude"]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
type SunLightWeather = 'sunny' | 'partly-cloudy' | 'overcast';
|
|
4
|
+
interface SunLightToolOptions {
|
|
5
|
+
light?: THREE.DirectionalLight;
|
|
6
|
+
ambientLight?: THREE.Light;
|
|
7
|
+
latitude?: number;
|
|
8
|
+
longitude?: number;
|
|
9
|
+
dayOfYear?: number;
|
|
10
|
+
timeOfDay?: number;
|
|
11
|
+
timeZoneOffsetMinutes?: number;
|
|
12
|
+
referenceYear?: number;
|
|
13
|
+
useSystemTime?: boolean;
|
|
14
|
+
weather?: SunLightWeather;
|
|
15
|
+
showHelper?: boolean;
|
|
16
|
+
helperSize?: number;
|
|
17
|
+
helperColor?: number;
|
|
18
|
+
enableHemisphereLight?: boolean;
|
|
19
|
+
hemisphereSkyColor?: number;
|
|
20
|
+
hemisphereGroundColor?: number;
|
|
21
|
+
hemisphereIntensity?: number;
|
|
22
|
+
lightDistance?: number;
|
|
23
|
+
shadowCameraSize?: number;
|
|
24
|
+
shadowCameraFar?: number;
|
|
25
|
+
}
|
|
26
|
+
interface SunLightState {
|
|
27
|
+
date: Date;
|
|
28
|
+
latitude: number;
|
|
29
|
+
longitude: number;
|
|
30
|
+
solarAzimuth: number;
|
|
31
|
+
solarAltitude: number;
|
|
32
|
+
weather: SunLightWeather;
|
|
33
|
+
useSystemTime: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface SunLightToolEvents {
|
|
36
|
+
stateChanged: {
|
|
37
|
+
state: SunLightState;
|
|
38
|
+
};
|
|
39
|
+
weatherChanged: {
|
|
40
|
+
weather: SunLightWeather;
|
|
41
|
+
};
|
|
42
|
+
systemTimeToggled: {
|
|
43
|
+
useSystemTime: boolean;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
declare class SunLightTool extends THREE.EventDispatcher<SunLightToolEvents> {
|
|
47
|
+
private scene;
|
|
48
|
+
private light;
|
|
49
|
+
private ambientLight?;
|
|
50
|
+
private hemisphereLight?;
|
|
51
|
+
private helper?;
|
|
52
|
+
private createdLight;
|
|
53
|
+
private createdHemisphere;
|
|
54
|
+
private latitude;
|
|
55
|
+
private longitude;
|
|
56
|
+
private dayOfYear;
|
|
57
|
+
private timeOfDay;
|
|
58
|
+
private timeZoneOffsetMinutes;
|
|
59
|
+
private referenceYear;
|
|
60
|
+
private weather;
|
|
61
|
+
private useSystemTime;
|
|
62
|
+
private lightDistance;
|
|
63
|
+
private shadowCameraSize;
|
|
64
|
+
private shadowCameraFar;
|
|
65
|
+
private state;
|
|
66
|
+
constructor(scene: THREE.Scene, options?: SunLightToolOptions);
|
|
67
|
+
getLight(): THREE.DirectionalLight;
|
|
68
|
+
getHemisphereLight(): THREE.HemisphereLight | undefined;
|
|
69
|
+
getState(): SunLightState;
|
|
70
|
+
getDayOfYear(): number;
|
|
71
|
+
getTimeOfDay(): number;
|
|
72
|
+
getTimeZoneOffset(): number;
|
|
73
|
+
getWeather(): SunLightWeather;
|
|
74
|
+
usesSystemTime(): boolean;
|
|
75
|
+
setLatitude(latitude: number): void;
|
|
76
|
+
setLongitude(longitude: number): void;
|
|
77
|
+
setLocation(latitude: number, longitude: number): void;
|
|
78
|
+
setDayOfYear(day: number): void;
|
|
79
|
+
setTimeOfDay(hours: number): void;
|
|
80
|
+
setTimeZoneOffset(minutes: number): void;
|
|
81
|
+
setWeather(weather: SunLightWeather): void;
|
|
82
|
+
setUseSystemTime(enabled: boolean): void;
|
|
83
|
+
update(dateOverride?: Date): void;
|
|
84
|
+
dispose(): void;
|
|
85
|
+
private configureShadowMap;
|
|
86
|
+
private computeDate;
|
|
87
|
+
private computeSunPosition;
|
|
88
|
+
private applySunPosition;
|
|
89
|
+
private applyWeather;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { type SunLightState, SunLightTool, type SunLightToolEvents, type SunLightToolOptions, type SunLightWeather };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
type SunLightWeather = 'sunny' | 'partly-cloudy' | 'overcast';
|
|
4
|
+
interface SunLightToolOptions {
|
|
5
|
+
light?: THREE.DirectionalLight;
|
|
6
|
+
ambientLight?: THREE.Light;
|
|
7
|
+
latitude?: number;
|
|
8
|
+
longitude?: number;
|
|
9
|
+
dayOfYear?: number;
|
|
10
|
+
timeOfDay?: number;
|
|
11
|
+
timeZoneOffsetMinutes?: number;
|
|
12
|
+
referenceYear?: number;
|
|
13
|
+
useSystemTime?: boolean;
|
|
14
|
+
weather?: SunLightWeather;
|
|
15
|
+
showHelper?: boolean;
|
|
16
|
+
helperSize?: number;
|
|
17
|
+
helperColor?: number;
|
|
18
|
+
enableHemisphereLight?: boolean;
|
|
19
|
+
hemisphereSkyColor?: number;
|
|
20
|
+
hemisphereGroundColor?: number;
|
|
21
|
+
hemisphereIntensity?: number;
|
|
22
|
+
lightDistance?: number;
|
|
23
|
+
shadowCameraSize?: number;
|
|
24
|
+
shadowCameraFar?: number;
|
|
25
|
+
}
|
|
26
|
+
interface SunLightState {
|
|
27
|
+
date: Date;
|
|
28
|
+
latitude: number;
|
|
29
|
+
longitude: number;
|
|
30
|
+
solarAzimuth: number;
|
|
31
|
+
solarAltitude: number;
|
|
32
|
+
weather: SunLightWeather;
|
|
33
|
+
useSystemTime: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface SunLightToolEvents {
|
|
36
|
+
stateChanged: {
|
|
37
|
+
state: SunLightState;
|
|
38
|
+
};
|
|
39
|
+
weatherChanged: {
|
|
40
|
+
weather: SunLightWeather;
|
|
41
|
+
};
|
|
42
|
+
systemTimeToggled: {
|
|
43
|
+
useSystemTime: boolean;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
declare class SunLightTool extends THREE.EventDispatcher<SunLightToolEvents> {
|
|
47
|
+
private scene;
|
|
48
|
+
private light;
|
|
49
|
+
private ambientLight?;
|
|
50
|
+
private hemisphereLight?;
|
|
51
|
+
private helper?;
|
|
52
|
+
private createdLight;
|
|
53
|
+
private createdHemisphere;
|
|
54
|
+
private latitude;
|
|
55
|
+
private longitude;
|
|
56
|
+
private dayOfYear;
|
|
57
|
+
private timeOfDay;
|
|
58
|
+
private timeZoneOffsetMinutes;
|
|
59
|
+
private referenceYear;
|
|
60
|
+
private weather;
|
|
61
|
+
private useSystemTime;
|
|
62
|
+
private lightDistance;
|
|
63
|
+
private shadowCameraSize;
|
|
64
|
+
private shadowCameraFar;
|
|
65
|
+
private state;
|
|
66
|
+
constructor(scene: THREE.Scene, options?: SunLightToolOptions);
|
|
67
|
+
getLight(): THREE.DirectionalLight;
|
|
68
|
+
getHemisphereLight(): THREE.HemisphereLight | undefined;
|
|
69
|
+
getState(): SunLightState;
|
|
70
|
+
getDayOfYear(): number;
|
|
71
|
+
getTimeOfDay(): number;
|
|
72
|
+
getTimeZoneOffset(): number;
|
|
73
|
+
getWeather(): SunLightWeather;
|
|
74
|
+
usesSystemTime(): boolean;
|
|
75
|
+
setLatitude(latitude: number): void;
|
|
76
|
+
setLongitude(longitude: number): void;
|
|
77
|
+
setLocation(latitude: number, longitude: number): void;
|
|
78
|
+
setDayOfYear(day: number): void;
|
|
79
|
+
setTimeOfDay(hours: number): void;
|
|
80
|
+
setTimeZoneOffset(minutes: number): void;
|
|
81
|
+
setWeather(weather: SunLightWeather): void;
|
|
82
|
+
setUseSystemTime(enabled: boolean): void;
|
|
83
|
+
update(dateOverride?: Date): void;
|
|
84
|
+
dispose(): void;
|
|
85
|
+
private configureShadowMap;
|
|
86
|
+
private computeDate;
|
|
87
|
+
private computeSunPosition;
|
|
88
|
+
private applySunPosition;
|
|
89
|
+
private applyWeather;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { type SunLightState, SunLightTool, type SunLightToolEvents, type SunLightToolOptions, type SunLightWeather };
|