@needle-tools/engine 3.2.5-alpha.1 → 3.2.7-alpha
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/CHANGELOG.md +13 -0
- package/dist/needle-engine.js +6145 -6019
- package/dist/needle-engine.min.js +275 -275
- package/dist/needle-engine.umd.cjs +273 -273
- package/lib/engine/api.d.ts +3 -1
- package/lib/engine/api.js +2 -1
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/engine_context.d.ts +4 -2
- package/lib/engine/engine_context.js +5 -3
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_element_loading.js +0 -1
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.js +4 -2
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_physics.js +24 -1
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_scenelighting.d.ts +68 -0
- package/lib/engine/{engine_rendererdata.js → engine_scenelighting.js} +94 -24
- package/lib/engine/engine_scenelighting.js.map +1 -0
- package/lib/engine/engine_serialization_core.d.ts +5 -8
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lighting_settings.d.ts +4 -1
- package/lib/engine/extensions/NEEDLE_lighting_settings.js +45 -21
- package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +3 -3
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine/extensions/index.d.ts +5 -0
- package/lib/engine/extensions/index.js +6 -0
- package/lib/engine/extensions/index.js.map +1 -0
- package/lib/engine-components/Component.js +28 -3
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/Renderer.js +1 -1
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.d.ts +2 -0
- package/lib/engine-components/SceneSwitcher.js +16 -4
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/api.d.ts +1 -0
- package/lib/engine-components/api.js +1 -0
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/postprocessing/PostProcessingHandler.d.ts +1 -1
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +1 -1
- package/lib/engine-components/postprocessing/VolumeParameter.js +7 -6
- package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
- package/lib/engine-components/webxr/index.d.ts +1 -0
- package/lib/engine-components/webxr/index.js +1 -0
- package/lib/engine-components/webxr/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/engine/api.ts +3 -1
- package/src/engine/codegen/register_types.js +2 -2
- package/src/engine/engine_context.ts +5 -3
- package/src/engine/engine_element_loading.ts +0 -1
- package/src/engine/engine_mainloop_utils.ts +4 -2
- package/src/engine/engine_physics.ts +20 -1
- package/src/engine/{engine_rendererdata.ts → engine_scenelighting.ts} +95 -24
- package/src/engine/engine_serialization_core.ts +7 -8
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +53 -26
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +3 -3
- package/src/engine/extensions/index.ts +5 -0
- package/src/engine-components/Component.ts +28 -3
- package/src/engine-components/Renderer.ts +1 -1
- package/src/engine-components/SceneSwitcher.ts +14 -4
- package/src/engine-components/api.ts +1 -0
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +1 -1
- package/src/engine-components/postprocessing/VolumeParameter.ts +7 -6
- package/src/engine-components/webxr/index.ts +1 -0
- package/lib/engine/engine_rendererdata.d.ts +0 -49
- package/lib/engine/engine_rendererdata.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.7-alpha",
|
|
4
4
|
"description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in",
|
|
5
5
|
"main": "dist/needle-engine.umd.cjs",
|
|
6
6
|
"type": "module",
|
package/src/engine/api.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
export * from "./extensions
|
|
2
|
+
export * from "./extensions"
|
|
3
3
|
export * from "./engine_addressables";
|
|
4
4
|
export * from "./engine_application"
|
|
5
5
|
export * from "./engine_assetdatabase"
|
|
@@ -27,11 +27,13 @@ export * from "./engine_patcher"
|
|
|
27
27
|
export * from "./engine_playerview"
|
|
28
28
|
export * from "./engine_physics"
|
|
29
29
|
export * from "./engine_physics.types"
|
|
30
|
+
export * from "./engine_scenelighting"
|
|
30
31
|
export * from "./engine_input";
|
|
31
32
|
export * from "./engine_math";
|
|
32
33
|
export * from "./js-extensions";
|
|
33
34
|
export * from "./engine_scenetools";
|
|
34
35
|
export * from "./engine_serialization";
|
|
36
|
+
export { type ISerializable } from "./engine_serialization_core";
|
|
35
37
|
export * from "./engine_texture";
|
|
36
38
|
export * from "./engine_three_utils";
|
|
37
39
|
export * from "./engine_time";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TypeStore } from "./../engine_typestore"
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
// Import types
|
|
4
4
|
import { __Ignore } from "../../engine-components/codegen/components";
|
|
5
5
|
import { AlignmentConstraint } from "../../engine-components/AlignmentConstraint";
|
|
@@ -187,7 +187,7 @@ import { XRGrabModel } from "../../engine-components/webxr/WebXRGrabRendering";
|
|
|
187
187
|
import { XRGrabRendering } from "../../engine-components/webxr/WebXRGrabRendering";
|
|
188
188
|
import { XRRig } from "../../engine-components/webxr/WebXRRig";
|
|
189
189
|
import { XRState } from "../../engine-components/XRFlag";
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
// Register types
|
|
192
192
|
TypeStore.add("__Ignore", __Ignore);
|
|
193
193
|
TypeStore.add("AlignmentConstraint", AlignmentConstraint);
|
|
@@ -18,7 +18,7 @@ import { AssetDatabase } from './engine_assetdatabase';
|
|
|
18
18
|
import { logHierarchy } from './engine_three_utils';
|
|
19
19
|
|
|
20
20
|
import * as Stats from 'three/examples/jsm/libs/stats.module';
|
|
21
|
-
import { RendererData } from './
|
|
21
|
+
import { RendererData as SceneLighting } from './engine_scenelighting';
|
|
22
22
|
import { Addressables } from './engine_addressables';
|
|
23
23
|
import { Application } from './engine_application';
|
|
24
24
|
import { LightDataRegistry, ILightDataRegistry } from './engine_lightdata';
|
|
@@ -225,7 +225,9 @@ export class Context implements IContext {
|
|
|
225
225
|
*/
|
|
226
226
|
assets: AssetDatabase;
|
|
227
227
|
mainLight: ILight | null = null;
|
|
228
|
-
|
|
228
|
+
/** @deprecated Use sceneLighting */
|
|
229
|
+
get rendererData() { return this.sceneLighting }
|
|
230
|
+
sceneLighting: SceneLighting;
|
|
229
231
|
addressables: Addressables;
|
|
230
232
|
lightmaps: ILightDataRegistry;
|
|
231
233
|
players: PlayerViewManager;
|
|
@@ -278,7 +280,7 @@ export class Context implements IContext {
|
|
|
278
280
|
this.physics = new Physics(this);
|
|
279
281
|
this.connection = new NetworkConnection(this);
|
|
280
282
|
this.assets = new AssetDatabase();
|
|
281
|
-
this.
|
|
283
|
+
this.sceneLighting = new SceneLighting(this);
|
|
282
284
|
this.addressables = new Addressables(this);
|
|
283
285
|
this.lightmaps = new LightDataRegistry(this);
|
|
284
286
|
this.players = new PlayerViewManager(this);
|
|
@@ -176,7 +176,6 @@ export class EngineLoadingView implements ILoadingViewHandler {
|
|
|
176
176
|
this._loadingElement = existing || document.createElement("div");
|
|
177
177
|
|
|
178
178
|
const loadingStyle: LoadingStyleOption = this._element.getAttribute("loading-style") as LoadingStyleOption;
|
|
179
|
-
console.log(loadingStyle);
|
|
180
179
|
|
|
181
180
|
const hasLicense = hasProLicense();
|
|
182
181
|
if (!existing) {
|
|
@@ -267,8 +267,10 @@ function updateIsActiveInHierarchyRecursiveRuntime(go: Object3D, activeInHierarc
|
|
|
267
267
|
if (activeInHierarchy) {
|
|
268
268
|
if (comp.enabled) {
|
|
269
269
|
utils.safeInvoke(comp.__internalAwake.bind(comp));
|
|
270
|
-
comp
|
|
271
|
-
|
|
270
|
+
if (comp.enabled) {
|
|
271
|
+
comp["__didEnable"] = true;
|
|
272
|
+
comp.onEnable();
|
|
273
|
+
}
|
|
272
274
|
}
|
|
273
275
|
}
|
|
274
276
|
else {
|
|
@@ -1082,7 +1082,7 @@ class PhysicsCollisionHandler {
|
|
|
1082
1082
|
// if one is a trigger we dont get collisions but want to raise the trigger events
|
|
1083
1083
|
if (self.isTrigger || other.isTrigger) {
|
|
1084
1084
|
foreachComponent(self.gameObject, (c: IComponent) => {
|
|
1085
|
-
if (c.onTriggerEnter) {
|
|
1085
|
+
if (c.onTriggerEnter && !c.destroyed) {
|
|
1086
1086
|
c.onTriggerEnter(other);
|
|
1087
1087
|
}
|
|
1088
1088
|
this.activeTriggers.push({ collider: self, component: c, otherCollider: other });
|
|
@@ -1093,6 +1093,7 @@ class PhysicsCollisionHandler {
|
|
|
1093
1093
|
// TODO: we dont respect the flip value here!
|
|
1094
1094
|
this.world.contactPair(selfBody, otherBody, (manifold, _flipped) => {
|
|
1095
1095
|
foreachComponent(object, (c: IComponent) => {
|
|
1096
|
+
if(c.destroyed) return;
|
|
1096
1097
|
const hasDeclaredEventMethod = c.onCollisionEnter || c.onCollisionStay || c.onCollisionExit;
|
|
1097
1098
|
if (hasDeclaredEventMethod || debugCollisions) {
|
|
1098
1099
|
if (!collision) {
|
|
@@ -1137,6 +1138,7 @@ class PhysicsCollisionHandler {
|
|
|
1137
1138
|
private onHandleCollisionStay() {
|
|
1138
1139
|
for (const active of this.activeCollisionsStay) {
|
|
1139
1140
|
const c = active.component;
|
|
1141
|
+
if(c.destroyed) continue;
|
|
1140
1142
|
if (c.activeAndEnabled && c.onCollisionStay) {
|
|
1141
1143
|
const arg = active.collision;
|
|
1142
1144
|
c.onCollisionStay(arg);
|
|
@@ -1144,6 +1146,7 @@ class PhysicsCollisionHandler {
|
|
|
1144
1146
|
}
|
|
1145
1147
|
for (const active of this.activeTriggers) {
|
|
1146
1148
|
const c = active.component;
|
|
1149
|
+
if(c.destroyed) continue;
|
|
1147
1150
|
if (c.activeAndEnabled && c.onTriggerStay) {
|
|
1148
1151
|
const arg = active.otherCollider;
|
|
1149
1152
|
c.onTriggerStay(arg);
|
|
@@ -1152,9 +1155,15 @@ class PhysicsCollisionHandler {
|
|
|
1152
1155
|
}
|
|
1153
1156
|
|
|
1154
1157
|
private onCollisionEnded(self: ICollider, other: ICollider) {
|
|
1158
|
+
if(self.destroyed || other.destroyed) return;
|
|
1155
1159
|
for (let i = 0; i < this.activeCollisions.length; i++) {
|
|
1156
1160
|
const active = this.activeCollisions[i];
|
|
1157
1161
|
const collider = active.collider;
|
|
1162
|
+
if(collider.destroyed) {
|
|
1163
|
+
this.activeCollisions.splice(i, 1);
|
|
1164
|
+
i--;
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1158
1167
|
if (collider === self && active.collision.collider === other) {
|
|
1159
1168
|
const c = active.component;
|
|
1160
1169
|
this.activeCollisions.splice(i, 1);
|
|
@@ -1168,6 +1177,11 @@ class PhysicsCollisionHandler {
|
|
|
1168
1177
|
for (let i = 0; i < this.activeCollisionsStay.length; i++) {
|
|
1169
1178
|
const active = this.activeCollisionsStay[i];
|
|
1170
1179
|
const collider = active.collider;
|
|
1180
|
+
if(collider.destroyed) {
|
|
1181
|
+
this.activeCollisionsStay.splice(i, 1);
|
|
1182
|
+
i--;
|
|
1183
|
+
continue;
|
|
1184
|
+
}
|
|
1171
1185
|
if (collider === self && active.collision.collider === other) {
|
|
1172
1186
|
const c = active.component;
|
|
1173
1187
|
this.activeCollisionsStay.splice(i, 1);
|
|
@@ -1181,6 +1195,11 @@ class PhysicsCollisionHandler {
|
|
|
1181
1195
|
for (let i = 0; i < this.activeTriggers.length; i++) {
|
|
1182
1196
|
const active = this.activeTriggers[i];
|
|
1183
1197
|
const collider = active.collider;
|
|
1198
|
+
if(collider.destroyed) {
|
|
1199
|
+
this.activeTriggers.splice(i, 1);
|
|
1200
|
+
i--;
|
|
1201
|
+
continue;
|
|
1202
|
+
}
|
|
1184
1203
|
if (collider === self && active.otherCollider === other) {
|
|
1185
1204
|
const c = active.component;
|
|
1186
1205
|
this.activeTriggers.splice(i, 1);
|
|
@@ -5,6 +5,7 @@ import { SceneLightSettings } from "./extensions/NEEDLE_lighting_settings";
|
|
|
5
5
|
import { createFlatTexture, createTrilightTexture } from "./engine_shaders";
|
|
6
6
|
import { getParam } from "./engine_utils";
|
|
7
7
|
import { SourceIdentifier } from "./engine_types";
|
|
8
|
+
import { AssetReference } from "./engine_addressables";
|
|
8
9
|
|
|
9
10
|
const debug = getParam("debugenvlight");
|
|
10
11
|
|
|
@@ -36,8 +37,8 @@ export class RendererData {
|
|
|
36
37
|
this.context.pre_update_callbacks.push(this.preUpdate.bind(this))
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
private
|
|
40
|
-
private
|
|
40
|
+
private _currentLightSettingsId?: SourceIdentifier;
|
|
41
|
+
private _sceneLightSettings?: Map<SourceIdentifier, SceneLightSettings>;
|
|
41
42
|
|
|
42
43
|
private preUpdate() {
|
|
43
44
|
const time = this.context.time;
|
|
@@ -52,40 +53,103 @@ export class RendererData {
|
|
|
52
53
|
return this._timevec4;
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
/** the current environment intensity */
|
|
55
57
|
get environmentIntensity(): number {
|
|
56
|
-
if (!this.
|
|
57
|
-
if (!this.
|
|
58
|
-
const settings = this.
|
|
59
|
-
if(settings)
|
|
58
|
+
if (!this._sceneLightSettings) return 1;
|
|
59
|
+
if (!this._currentLightSettingsId) return 1;
|
|
60
|
+
const settings = this._sceneLightSettings.get(this._currentLightSettingsId);
|
|
61
|
+
if (settings)
|
|
60
62
|
return settings.ambientIntensity;// * Math.PI * .5;
|
|
61
63
|
return 1;
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
/** Get all currently registered scene light settings */
|
|
67
|
+
get sceneLightSettings() { return this._sceneLightSettings?.values() }
|
|
68
|
+
|
|
69
|
+
/** set the scene lighting from a specific scene. Will disable any previously enabled lighting settings */
|
|
70
|
+
enable(sourceId: SourceIdentifier | AssetReference) {
|
|
71
|
+
if(sourceId instanceof AssetReference)
|
|
72
|
+
sourceId = sourceId.uri;
|
|
73
|
+
const settings = this._sceneLightSettings?.get(sourceId);
|
|
74
|
+
if (!settings) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (debug) console.log("Enable scene light settings", sourceId, settings);
|
|
78
|
+
if (sourceId !== this._currentLightSettingsId && this._currentLightSettingsId) {
|
|
79
|
+
this.disable(this._currentLightSettingsId);
|
|
80
|
+
}
|
|
81
|
+
this._currentLightSettingsId = sourceId;
|
|
82
|
+
settings.enabled = true;
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** disable the lighting of a specific scene, will only have any effect if it is currently active */
|
|
87
|
+
disable(sourceId: SourceIdentifier | AssetReference) {
|
|
88
|
+
if(sourceId instanceof AssetReference)
|
|
89
|
+
sourceId = sourceId.uri;
|
|
90
|
+
if (sourceId === null || sourceId === undefined) return false;
|
|
91
|
+
const settings = this._sceneLightSettings?.get(sourceId);
|
|
92
|
+
if (!settings) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
if (debug) console.log("Disable scene light settings", sourceId, settings);
|
|
96
|
+
settings.enabled = false;
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Disables the currently active scene lighting (if any), returns the id of the previously active lighting */
|
|
101
|
+
disableCurrent() : SourceIdentifier | null {
|
|
102
|
+
if (this._currentLightSettingsId) {
|
|
103
|
+
const prev = this._currentLightSettingsId;
|
|
104
|
+
this.disable(this._currentLightSettingsId);
|
|
105
|
+
return prev
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
/** @internal */
|
|
112
|
+
internalRegisterSceneLightSettings(sceneLightSettings: SceneLightSettings) {
|
|
65
113
|
const sourceId = sceneLightSettings.sourceId;
|
|
66
|
-
if(!sourceId){
|
|
114
|
+
if (!sourceId) {
|
|
67
115
|
console.error("Missing source id for scene light settings, can not register:", sceneLightSettings);
|
|
68
116
|
return;
|
|
69
117
|
}
|
|
70
|
-
if (debug) console.log("Register
|
|
71
|
-
if (!this.
|
|
72
|
-
this.
|
|
118
|
+
if (debug) console.log("Register " + sceneLightSettings?.sourceId + " lighting", sceneLightSettings);
|
|
119
|
+
if (!this._sceneLightSettings) this._sceneLightSettings = new Map();
|
|
120
|
+
this._sceneLightSettings.set(sourceId, sceneLightSettings);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** @internal */
|
|
124
|
+
internalUnregisterSceneLightSettings(sceneLightSettings: SceneLightSettings) {
|
|
125
|
+
const sourceId = sceneLightSettings.sourceId;
|
|
126
|
+
if (!sourceId) {
|
|
127
|
+
console.error("Missing source id for scene light settings, can not unregister:", sceneLightSettings);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (debug) console.log("Unregister " + sceneLightSettings?.sourceId + " lighting", sceneLightSettings);
|
|
131
|
+
if (!this._sceneLightSettings) return;
|
|
132
|
+
this._sceneLightSettings.delete(sourceId);
|
|
73
133
|
}
|
|
74
134
|
|
|
75
|
-
|
|
135
|
+
/** @internal */
|
|
136
|
+
internalRegisterReflection(sourceId: SourceIdentifier, reflectionTexture: Texture) {
|
|
76
137
|
if (debug) console.log("Register reflection", sourceId, reflectionTexture);
|
|
77
138
|
const h = new LightData(this.context, reflectionTexture, 1);
|
|
78
139
|
this._lighting[sourceId] = h;
|
|
79
140
|
}
|
|
80
141
|
|
|
81
|
-
|
|
142
|
+
/** @internal */
|
|
143
|
+
internalGetReflection(sourceId: SourceIdentifier): LightData | null | undefined {
|
|
82
144
|
return this._lighting[sourceId];
|
|
83
145
|
}
|
|
84
146
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
147
|
+
private __currentReflectionId: SourceIdentifier | null = null;
|
|
148
|
+
|
|
149
|
+
/** @internal */
|
|
150
|
+
internalEnableReflection(sourceId: SourceIdentifier) {
|
|
151
|
+
this.__currentReflectionId = sourceId;
|
|
152
|
+
const settings = this._sceneLightSettings?.get(sourceId);
|
|
89
153
|
|
|
90
154
|
if (debug) {
|
|
91
155
|
console.log("Enable reflection", sourceId, settings ? AmbientMode[settings.ambientMode] : "Unknown ambient mode");
|
|
@@ -95,9 +159,9 @@ export class RendererData {
|
|
|
95
159
|
case AmbientMode.Skybox:
|
|
96
160
|
case AmbientMode.Custom:
|
|
97
161
|
// only set environment reflection when ambient mode is skybox or custom
|
|
98
|
-
const existing = this.
|
|
162
|
+
const existing = this.internalGetReflection(sourceId);
|
|
99
163
|
if (existing && existing.Source) {
|
|
100
|
-
if (debug) console.log("Setting environment reflection", existing
|
|
164
|
+
if (debug) console.log("Setting environment reflection", existing);
|
|
101
165
|
const scene = this.context.scene;
|
|
102
166
|
const tex = existing.Source;
|
|
103
167
|
tex.encoding = sRGBEncoding;
|
|
@@ -136,13 +200,19 @@ export class RendererData {
|
|
|
136
200
|
}
|
|
137
201
|
}
|
|
138
202
|
|
|
139
|
-
|
|
140
|
-
|
|
203
|
+
/** @internal */
|
|
204
|
+
internalDisableReflection(sourceId?: SourceIdentifier) {
|
|
205
|
+
if (sourceId && sourceId !== this.__currentReflectionId) {
|
|
206
|
+
if(debug) console.log("Not disabling reflection for", sourceId, "because it is not the current light settings id", this.__currentReflectionId)
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (debug) console.log("Disable reflection", sourceId)
|
|
141
210
|
const scene = this.context.scene;
|
|
142
211
|
scene.environment = null;
|
|
143
212
|
}
|
|
144
213
|
|
|
145
|
-
|
|
214
|
+
/** @internal */
|
|
215
|
+
async internalGetSceneLightingData(sourceId: SourceIdentifier): Promise<SphericalHarmonicsData> {
|
|
146
216
|
if (debug)
|
|
147
217
|
console.log("GET SCENE LIGHT DATA", sourceId);
|
|
148
218
|
|
|
@@ -157,7 +227,7 @@ export class RendererData {
|
|
|
157
227
|
if (this._waitPromise) return this._waitPromise;
|
|
158
228
|
this._waitPromise = new Promise((res, _rej) => {
|
|
159
229
|
let interval = setInterval(async () => {
|
|
160
|
-
const ex = this.
|
|
230
|
+
const ex = this.internalGetReflection(sourceId);
|
|
161
231
|
if (ex) {
|
|
162
232
|
clearInterval(interval);
|
|
163
233
|
res(ex.getSphericalHarmonicsArray(this.environmentIntensity ?? 1)!);
|
|
@@ -205,7 +275,8 @@ export class LightData {
|
|
|
205
275
|
const size = Math.min(reflection.image.width, 512);
|
|
206
276
|
const target = new WebGLCubeRenderTarget(size);
|
|
207
277
|
rt = target.fromEquirectangularTexture(this._context.renderer, reflection);
|
|
208
|
-
this.
|
|
278
|
+
// Not sure why we did assign the resulting texture here again but this causes rendering to break when toggling env lighting (e.g. on website) because this texture will then be set as the scene.environment
|
|
279
|
+
// this._source = rt.texture;
|
|
209
280
|
}
|
|
210
281
|
|
|
211
282
|
this._sphericalHarmonicsArray = [];
|
|
@@ -3,7 +3,7 @@ import { getParam } from "./engine_utils";
|
|
|
3
3
|
import { AnimationClip, Material, Mesh, Object3D, Texture } from "three";
|
|
4
4
|
import { Context } from "./engine_setup";
|
|
5
5
|
import { isPersistentAsset } from "./extensions/NEEDLE_persistent_assets";
|
|
6
|
-
import { SourceIdentifier } from "./engine_types";
|
|
6
|
+
import { ConstructorConcrete, SourceIdentifier } from "./engine_types";
|
|
7
7
|
import { debugExtension } from "../engine/engine_default_parameters";
|
|
8
8
|
import { LogType, addLog } from "./debug/debug_overlay";
|
|
9
9
|
import { isLocalNetwork } from "./engine_networking_utils";
|
|
@@ -12,7 +12,6 @@ import { $BuiltInTypeFlag } from "./engine_typestore";
|
|
|
12
12
|
const debug = getParam("debugserializer");
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
export type Constructor<T> = { new(...args: any[]): T };
|
|
16
15
|
export declare type NodeToObjectMap = { [nodeId: string]: Object3D };
|
|
17
16
|
export declare type ObjectToNodeMap = { [uuid: string]: number };
|
|
18
17
|
|
|
@@ -125,7 +124,7 @@ export abstract class TypeSerializer implements ITypeSerializer {
|
|
|
125
124
|
// }
|
|
126
125
|
// }
|
|
127
126
|
|
|
128
|
-
constructor(type:
|
|
127
|
+
constructor(type: ConstructorConcrete<any> | ConstructorConcrete<any>[]) {
|
|
129
128
|
if (Array.isArray(type)) {
|
|
130
129
|
for (const key of type)
|
|
131
130
|
helper.register(key.name, this);
|
|
@@ -141,7 +140,7 @@ export abstract class TypeSerializer implements ITypeSerializer {
|
|
|
141
140
|
|
|
142
141
|
|
|
143
142
|
export interface ITypeInformation {
|
|
144
|
-
type?:
|
|
143
|
+
type?: ConstructorConcrete<any>;
|
|
145
144
|
}
|
|
146
145
|
|
|
147
146
|
/** holds information if a field was undefined before serialization. This gives us info if we might want to warn the user about missing attributes */
|
|
@@ -182,7 +181,7 @@ export class SerializationContext {
|
|
|
182
181
|
objectToNode?: ObjectToNodeMap;
|
|
183
182
|
context?: Context;
|
|
184
183
|
path?: string;
|
|
185
|
-
type?:
|
|
184
|
+
type?: ConstructorConcrete<any>;
|
|
186
185
|
/** holds information if a field was undefined before serialization. This gives us info if we might want to warn the user about missing attributes */
|
|
187
186
|
implementationInformation?: ImplementationInformation;
|
|
188
187
|
|
|
@@ -193,7 +192,7 @@ export class SerializationContext {
|
|
|
193
192
|
|
|
194
193
|
|
|
195
194
|
export interface ISerializable {
|
|
196
|
-
$serializedTypes?: { [key: string]:
|
|
195
|
+
$serializedTypes?: { [key: string]: ConstructorConcrete<any> | ITypeInformation | null };
|
|
197
196
|
// onDeserialize?(context: SerializationContext): void;
|
|
198
197
|
// example:
|
|
199
198
|
/* $serializedTypes : {
|
|
@@ -337,7 +336,7 @@ export function deserializeObject(obj: ISerializable, serializedData: object, co
|
|
|
337
336
|
}
|
|
338
337
|
// it can also just contain a constructor
|
|
339
338
|
else {
|
|
340
|
-
const constructor = typeInfoOrConstructor as
|
|
339
|
+
const constructor = typeInfoOrConstructor as ConstructorConcrete<any>;
|
|
341
340
|
return deserializeObjectWithType(data, constructor, context, undefined, obj[key]);
|
|
342
341
|
}
|
|
343
342
|
}
|
|
@@ -460,7 +459,7 @@ declare type TypeDeserializeReference = {
|
|
|
460
459
|
serializer?: ITypeSerializer
|
|
461
460
|
}
|
|
462
461
|
|
|
463
|
-
function deserializeObjectWithType(data: any, typeOrConstructor:
|
|
462
|
+
function deserializeObjectWithType(data: any, typeOrConstructor: ConstructorConcrete<any>, context: SerializationContext, typeContext?: TypeDeserializeReference, currentValue?: any): any {
|
|
464
463
|
|
|
465
464
|
// e.g. @serializable((data) => { })
|
|
466
465
|
let typeIsFunction = typeof typeOrConstructor === "function" && (typeOrConstructor.prototype === undefined);
|
|
@@ -2,11 +2,13 @@ import { AmbientLight, Color, HemisphereLight, Object3D } from "three";
|
|
|
2
2
|
import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader";
|
|
3
3
|
import { SourceIdentifier } from "../engine_types";
|
|
4
4
|
import { Behaviour, GameObject } from "../../engine-components/Component";
|
|
5
|
-
import { AmbientMode, DefaultReflectionMode } from "../
|
|
5
|
+
import { AmbientMode, DefaultReflectionMode } from "../engine_scenelighting";
|
|
6
6
|
import { LightmapType } from "./NEEDLE_lightmaps";
|
|
7
7
|
import { getParam } from "../engine_utils";
|
|
8
8
|
import { Context } from "../engine_setup";
|
|
9
9
|
import { LightProbe } from "three";
|
|
10
|
+
import { ContextEvent, ContextRegistry } from "../engine_context_registry";
|
|
11
|
+
import { Mathf } from "../engine_math";
|
|
10
12
|
|
|
11
13
|
export const EXTENSION_NAME = "NEEDLE_lighting_settings";
|
|
12
14
|
const debug = getParam("debugenvlight");
|
|
@@ -42,7 +44,7 @@ export class NEEDLE_lighting_settings implements GLTFLoaderPlugin {
|
|
|
42
44
|
const ext: LightingSettings = extensions[EXTENSION_NAME];
|
|
43
45
|
if (ext) {
|
|
44
46
|
if (debug)
|
|
45
|
-
console.log("
|
|
47
|
+
console.log("Loaded \"" + this.name + "\", src: \"" + this.sourceId + "\"", ext);
|
|
46
48
|
let settings: SceneLightSettings | undefined = undefined;
|
|
47
49
|
// If the result scene has only one child we add the LightingSettingsComponent to that child
|
|
48
50
|
if (_result.scene.children.length === 1) {
|
|
@@ -50,10 +52,9 @@ export class NEEDLE_lighting_settings implements GLTFLoaderPlugin {
|
|
|
50
52
|
settings = GameObject.addNewComponent(_result.scene.children[0], SceneLightSettings, false);
|
|
51
53
|
}
|
|
52
54
|
// if the scene already has multiple children we add it as a new object
|
|
53
|
-
else
|
|
54
|
-
{
|
|
55
|
+
else {
|
|
55
56
|
const lightSettings = new Object3D();
|
|
56
|
-
lightSettings.name = "
|
|
57
|
+
lightSettings.name = "LightSettings " + this.sourceId;
|
|
57
58
|
_result.scene.add(lightSettings);
|
|
58
59
|
settings = GameObject.addNewComponent(lightSettings, SceneLightSettings, false);
|
|
59
60
|
}
|
|
@@ -64,7 +65,6 @@ export class NEEDLE_lighting_settings implements GLTFLoaderPlugin {
|
|
|
64
65
|
settings.ambientTrilight = ext.ambientTrilight.map(c => new Color().fromArray(c));
|
|
65
66
|
settings.ambientMode = ext.ambientMode;
|
|
66
67
|
settings.environmentReflectionSource = ext.environmentReflectionSource;
|
|
67
|
-
if (this.context) this.context.rendererData.registerSceneLightSettings(settings);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
return null;
|
|
@@ -72,6 +72,12 @@ export class NEEDLE_lighting_settings implements GLTFLoaderPlugin {
|
|
|
72
72
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
ContextRegistry.registerCallback(ContextEvent.ContextCreated, e => {
|
|
76
|
+
const ctx = e.context as Context;
|
|
77
|
+
const lightingSettings = GameObject.findObjectOfType(SceneLightSettings, ctx as Context);
|
|
78
|
+
if (lightingSettings?.sourceId) ctx.sceneLighting.enable(lightingSettings.sourceId);
|
|
79
|
+
})
|
|
80
|
+
|
|
75
81
|
// exists once per gltf scene root (if it contains reflection)
|
|
76
82
|
// when enabled it does currently automatically set the reflection
|
|
77
83
|
// this might not be desireable
|
|
@@ -85,6 +91,7 @@ export class SceneLightSettings extends Behaviour {
|
|
|
85
91
|
|
|
86
92
|
private _hasReflection: boolean = false;
|
|
87
93
|
private _ambientLightObj?: AmbientLight;
|
|
94
|
+
private _hemisphereLightObj?: HemisphereLight;
|
|
88
95
|
// used when skybox is used to support ambient intensity for "non custom shaders"
|
|
89
96
|
private _lightProbeObj?: LightProbe;
|
|
90
97
|
|
|
@@ -94,11 +101,15 @@ export class SceneLightSettings extends Behaviour {
|
|
|
94
101
|
const tex = this.context.lightmaps.tryGet(this.sourceId, type, 0);
|
|
95
102
|
this._hasReflection = tex !== null && tex !== undefined;
|
|
96
103
|
if (tex)
|
|
97
|
-
this.context.
|
|
104
|
+
this.context.sceneLighting.internalRegisterReflection(this.sourceId, tex);
|
|
98
105
|
}
|
|
99
106
|
|
|
107
|
+
this.enabled = false;
|
|
108
|
+
this.context.sceneLighting.internalRegisterSceneLightSettings(this);
|
|
109
|
+
|
|
100
110
|
if (debug) {
|
|
101
111
|
window.addEventListener("keydown", evt => {
|
|
112
|
+
if(this.destroyed) return;
|
|
102
113
|
switch (evt.key) {
|
|
103
114
|
case "l":
|
|
104
115
|
this.enabled = !this.enabled;
|
|
@@ -108,17 +119,26 @@ export class SceneLightSettings extends Behaviour {
|
|
|
108
119
|
}
|
|
109
120
|
}
|
|
110
121
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
122
|
+
onDestroy(): void {
|
|
123
|
+
this.context.sceneLighting.internalUnregisterSceneLightSettings(this);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private calculateIntensityFactor(col:Color){
|
|
127
|
+
const intensity = Math.max(col.r, col.g, col.b);// * 0.2126 + col.g * 0.7152 + col.b * 0.0722;
|
|
128
|
+
const factor = 2.2 * Mathf.lerp(0, 1.33, intensity); // scale based on intensity
|
|
129
|
+
return factor;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
onEnable(): void {
|
|
133
|
+
if (debug) console.warn("💡🟡 >>> Enable lighting", this.sourceId, this);
|
|
134
|
+
|
|
119
135
|
if (this.ambientMode == AmbientMode.Flat) {
|
|
120
136
|
if (this.ambientLight && !this._ambientLightObj) {
|
|
121
|
-
|
|
137
|
+
// TODO: currently ambient intensity is always exported as 1? The exported values are not correct in threejs
|
|
138
|
+
// the following calculation is a workaround to get the correct intensity
|
|
139
|
+
const factor = this.calculateIntensityFactor(this.ambientLight);
|
|
140
|
+
this._ambientLightObj = new AmbientLight(this.ambientLight, this.ambientIntensity * factor);
|
|
141
|
+
if (debug) console.log("Created ambient light", this.sourceId, this._ambientLightObj, this.ambientIntensity, factor)
|
|
122
142
|
}
|
|
123
143
|
if (this._ambientLightObj) {
|
|
124
144
|
this.gameObject.add(this._ambientLightObj)
|
|
@@ -129,23 +149,26 @@ export class SceneLightSettings extends Behaviour {
|
|
|
129
149
|
if (this.ambientTrilight) {
|
|
130
150
|
const ground = this.ambientTrilight[0];
|
|
131
151
|
const sky = this.ambientTrilight[this.ambientTrilight.length - 1];
|
|
132
|
-
const
|
|
133
|
-
this.
|
|
152
|
+
const factor = this.calculateIntensityFactor(sky);
|
|
153
|
+
this._hemisphereLightObj = new HemisphereLight(sky, ground, this.ambientIntensity * factor);
|
|
154
|
+
this.gameObject.add(this._hemisphereLightObj)
|
|
155
|
+
if (debug) console.log("Created hemisphere ambient light", this.sourceId, this._hemisphereLightObj, this.ambientIntensity, factor)
|
|
134
156
|
}
|
|
135
157
|
}
|
|
136
158
|
else {
|
|
137
159
|
if (this._ambientLightObj)
|
|
138
160
|
this._ambientLightObj.removeFromParent();
|
|
161
|
+
if (this._hemisphereLightObj)
|
|
162
|
+
this._hemisphereLightObj.removeFromParent();
|
|
139
163
|
|
|
140
164
|
// create light probe object
|
|
141
165
|
if (!this._lightProbeObj) {
|
|
142
166
|
if (this.sourceId) {
|
|
143
|
-
this.context.
|
|
167
|
+
this.context.sceneLighting.internalGetSceneLightingData(this.sourceId).then(data => {
|
|
144
168
|
if (!data) return;
|
|
145
169
|
this._lightProbeObj = data.lightProbe;
|
|
146
170
|
if (this.enabled && !this.destroyed && this._lightProbeObj) {
|
|
147
|
-
if (debug)
|
|
148
|
-
console.log("Add", this.sourceId, data);
|
|
171
|
+
if (debug) console.log("Add", this.sourceId, data);
|
|
149
172
|
this.gameObject.add(this._lightProbeObj);
|
|
150
173
|
}
|
|
151
174
|
});
|
|
@@ -159,16 +182,20 @@ export class SceneLightSettings extends Behaviour {
|
|
|
159
182
|
}
|
|
160
183
|
|
|
161
184
|
if (this.sourceId)
|
|
162
|
-
this.context.
|
|
185
|
+
this.context.sceneLighting.internalEnableReflection(this.sourceId);
|
|
163
186
|
|
|
164
187
|
}
|
|
165
188
|
|
|
166
189
|
onDisable() {
|
|
167
190
|
if (debug)
|
|
168
|
-
console.
|
|
169
|
-
if (this._lightProbeObj)
|
|
170
|
-
|
|
191
|
+
console.warn("💡⚫ <<< Disable lighting:", this.sourceId, this);
|
|
192
|
+
if (this._lightProbeObj)
|
|
193
|
+
this._lightProbeObj.removeFromParent();
|
|
194
|
+
if (this._ambientLightObj)
|
|
195
|
+
this._ambientLightObj.removeFromParent();
|
|
196
|
+
if (this._hemisphereLightObj)
|
|
197
|
+
this._hemisphereLightObj.removeFromParent();
|
|
171
198
|
if (this.sourceId)
|
|
172
|
-
this.context.
|
|
199
|
+
this.context.sceneLighting.internalDisableReflection(this.sourceId);
|
|
173
200
|
}
|
|
174
201
|
}
|
|
@@ -118,7 +118,7 @@ export class CustomShader extends RawShaderMaterial {
|
|
|
118
118
|
console.error("Missing context");
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
|
-
const data = await context.
|
|
121
|
+
const data = await context.sceneLighting.internalGetSceneLightingData(this.identifier);
|
|
122
122
|
if (!data || !data.array) {
|
|
123
123
|
console.warn("Missing lighting data for custom shader, getSceneLightingData did not return anything");
|
|
124
124
|
return;
|
|
@@ -210,10 +210,10 @@ export class CustomShader extends RawShaderMaterial {
|
|
|
210
210
|
// this._lastFrame = context.time.frame;
|
|
211
211
|
|
|
212
212
|
if (this.uniforms["_TimeParameters"]) {
|
|
213
|
-
this.uniforms["_TimeParameters"].value = context.
|
|
213
|
+
this.uniforms["_TimeParameters"].value = context.sceneLighting.timeVec4;
|
|
214
214
|
}
|
|
215
215
|
else if (this.uniforms["_Time"]) {
|
|
216
|
-
this.uniforms["_Time"].value = context.
|
|
216
|
+
this.uniforms["_Time"].value = context.sceneLighting.timeVec4;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
const mainLight: ILight | null = context.mainLight;
|