@needle-tools/engine 2.29.0-pre → 2.31.0-pre
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.d.ts +847 -757
- package/dist/needle-engine.js +347 -343
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +16 -12
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/engine.d.ts +1 -0
- package/lib/engine/engine_physics.d.ts +19 -8
- package/lib/engine/engine_physics.js +57 -48
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_serialization.d.ts +1 -0
- package/lib/engine/engine_serialization.js +1 -0
- package/lib/engine/engine_serialization.js.map +1 -1
- package/lib/engine/engine_setup.d.ts +5 -0
- package/lib/engine/engine_setup.js +6 -0
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +25 -8
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_deferred_texture.d.ts +1 -1
- package/lib/engine/extensions/NEEDLE_deferred_texture.js +26 -14
- package/lib/engine/extensions/NEEDLE_deferred_texture.js.map +1 -1
- package/lib/engine/extensions/extension_utils.js +24 -13
- package/lib/engine/extensions/extension_utils.js.map +1 -1
- package/lib/engine/extensions/extensions.js +3 -1
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine-components/Camera.js +7 -1
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/Component.d.ts +10 -0
- package/lib/engine-components/Component.js +53 -0
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/OrbitControls.js +2 -1
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +1 -0
- package/lib/engine-components/Renderer.js +10 -3
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/Rigidbody.d.ts +1 -1
- package/lib/engine-components/Rigidbody.js +3 -3
- package/lib/engine-components/Rigidbody.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +35 -5
- package/lib/engine-components/ScreenCapture.js +542 -25
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.js +29 -5
- package/lib/engine-components/SpectatorCamera.js.map +1 -1
- package/lib/engine-components/SyncedRoom.js +2 -0
- package/lib/engine-components/SyncedRoom.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +14 -1
- package/lib/engine-components/VideoPlayer.js +86 -16
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/Volume.d.ts +4 -0
- package/lib/engine-components/Volume.js +44 -3
- package/lib/engine-components/Volume.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.d.ts +9 -2
- package/lib/engine-components/WebARSessionRoot.js +69 -24
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +6 -3
- package/lib/engine-components/WebXR.js +42 -7
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.js +4 -0
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.js +13 -7
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/ui/CanvasGroup.d.ts +1 -0
- package/lib/engine-components/ui/CanvasGroup.js +1 -0
- package/lib/engine-components/ui/CanvasGroup.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.js +13 -4
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/Graphic.d.ts +1 -0
- package/lib/engine-components/ui/Graphic.js +2 -0
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/Interfaces.d.ts +2 -0
- package/lib/needle-engine.d.ts +1 -0
- package/lib/needle-engine.js +1 -0
- package/lib/needle-engine.js.map +1 -1
- package/package.json +2 -2
- package/src/engine/engine_physics.ts +74 -57
- package/src/engine/engine_serialization.ts +3 -1
- package/src/engine/engine_setup.ts +6 -0
- package/src/engine/engine_utils.ts +34 -8
- package/src/engine/extensions/NEEDLE_deferred_texture.ts +25 -19
- package/src/engine/extensions/extension_utils.ts +24 -12
- package/src/engine/extensions/extensions.ts +3 -2
- package/src/engine-components/Camera.ts +9 -2
- package/src/engine-components/Component.ts +58 -0
- package/src/engine-components/OrbitControls.ts +2 -1
- package/src/engine-components/Renderer.ts +11 -3
- package/src/engine-components/RigidBody.ts +2 -2
- package/src/engine-components/ScreenCapture.ts +610 -28
- package/src/engine-components/SpectatorCamera.ts +28 -5
- package/src/engine-components/SyncedRoom.ts +1 -0
- package/src/engine-components/VideoPlayer.ts +123 -23
- package/src/engine-components/Volume.ts +47 -4
- package/src/engine-components/WebARSessionRoot.ts +78 -28
- package/src/engine-components/WebXR.ts +50 -15
- package/src/engine-components/WebXRAvatar.ts +5 -0
- package/src/engine-components/WebXRController.ts +20 -14
- package/src/engine-components/ui/CanvasGroup.ts +2 -0
- package/src/engine-components/ui/EventSystem.ts +21 -15
- package/src/engine-components/ui/Graphic.ts +3 -0
- package/src/engine-components/ui/Interfaces.ts +2 -0
- package/src/needle-engine.ts +1 -0
|
@@ -72,6 +72,11 @@ export enum FrameEvent {
|
|
|
72
72
|
PhysicsStep = 10,
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
export enum XRSessionMode {
|
|
76
|
+
ImmersiveVR = "immersive-vr",
|
|
77
|
+
ImmersiveAR = "immersive-ar",
|
|
78
|
+
}
|
|
79
|
+
|
|
75
80
|
export declare type OnBeforeRenderCallback = (renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, geometry: THREE.BufferGeometry, material: THREE.Material, group: THREE.Group) => void
|
|
76
81
|
|
|
77
82
|
export class Context {
|
|
@@ -109,6 +114,7 @@ export class Context {
|
|
|
109
114
|
get domX(): number { return this.domElement.offsetLeft; }
|
|
110
115
|
get domY(): number { return this.domElement.offsetTop; }
|
|
111
116
|
get isInXR() { return this.renderer.xr?.isPresenting || false; }
|
|
117
|
+
xrSessionMode : XRSessionMode | undefined = undefined;
|
|
112
118
|
get xrSession() { return this.renderer.xr?.getSession(); }
|
|
113
119
|
get arOverlayElement(): HTMLElement {
|
|
114
120
|
const el = this.domElement as any;
|
|
@@ -181,17 +181,43 @@ export function delay(milliseconds: number): Promise<void> {
|
|
|
181
181
|
// if a timeline is exported via menu item the audio clip path is relative to the glb (same folder)
|
|
182
182
|
// we need to detect that here and build the new audio source path relative to the new glb location
|
|
183
183
|
// the same is/might be true for any file that is/will be exported via menu item
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
184
|
+
const debugGetPath = getParam("debugsourcepath");
|
|
185
|
+
export function getPath(source: SourceIdentifier | undefined, uri: string): string {
|
|
186
|
+
if (source === undefined) {
|
|
187
|
+
if (debugGetPath) console.warn("getPath: source is undefined, returning uri", uri);
|
|
188
|
+
return uri;
|
|
189
|
+
}
|
|
190
|
+
if (uri.startsWith("http")) {
|
|
191
|
+
if (debugGetPath) console.warn("getPath: uri is absolute, returning uri", uri);
|
|
192
|
+
return uri;
|
|
193
|
+
}
|
|
194
|
+
const pathIndex = source.lastIndexOf("/");
|
|
195
|
+
if (pathIndex >= 0) {
|
|
196
|
+
let newUri = source.substring(0, pathIndex + 1);
|
|
197
|
+
|
|
198
|
+
const uriDirectoryIndex = uri.lastIndexOf("/");
|
|
199
|
+
if (uriDirectoryIndex >= 0) {
|
|
200
|
+
newUri += uri.substring(uriDirectoryIndex + 1);
|
|
201
|
+
} else {
|
|
202
|
+
newUri += uri;
|
|
191
203
|
}
|
|
204
|
+
if (debugGetPath) console.log("getPath:", source, " - changed uri from\n", uri, "\n→ ", newUri);
|
|
205
|
+
return newUri;
|
|
192
206
|
}
|
|
193
|
-
return
|
|
207
|
+
return uri;
|
|
194
208
|
}
|
|
209
|
+
// export function getPath(glbLocation: SourceIdentifier | undefined, path: string) {
|
|
210
|
+
// if (path && glbLocation && !path.includes("/")) {
|
|
211
|
+
// // get directory of glb and prepend it to the audio file path
|
|
212
|
+
// const pathIndex = glbLocation.lastIndexOf("/");
|
|
213
|
+
// if (pathIndex >= 0) {
|
|
214
|
+
// const newPath = glbLocation.substring(0, pathIndex + 1) + path;
|
|
215
|
+
// return newPath;
|
|
216
|
+
// }
|
|
217
|
+
// }
|
|
218
|
+
// return path;
|
|
219
|
+
// }
|
|
220
|
+
|
|
195
221
|
|
|
196
222
|
export type WriteCallback = (data: any) => void;
|
|
197
223
|
|
|
@@ -3,7 +3,7 @@ import { GLTF, GLTFLoader, GLTFLoaderPlugin, GLTFParser } from "three/examples/j
|
|
|
3
3
|
import { SourceIdentifier } from "../engine_gltf";
|
|
4
4
|
import { Context } from "../engine_setup";
|
|
5
5
|
import { addDracoAndKTX2Loaders } from "../engine_loaders";
|
|
6
|
-
import { getParam } from "../engine_utils";
|
|
6
|
+
import { getParam, getPath } from "../engine_utils";
|
|
7
7
|
|
|
8
8
|
export const EXTENSION_NAME = "NEEDLE_deferred_texture";
|
|
9
9
|
|
|
@@ -11,24 +11,27 @@ const debug = getParam("debugdeferredtextures")
|
|
|
11
11
|
|
|
12
12
|
declare type DeferredTextureModel = {
|
|
13
13
|
uri: string;
|
|
14
|
-
guid
|
|
14
|
+
guid: string;
|
|
15
15
|
usage?: string,
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export class NEEDLE_deferred_texture implements GLTFLoaderPlugin {
|
|
19
19
|
|
|
20
|
-
static assignTextureLOD(context: Context, material: Material, level: number = 0) {
|
|
20
|
+
static assignTextureLOD(context: Context, source : SourceIdentifier | undefined, material: Material, level: number = 0) {
|
|
21
21
|
if (!material) return;
|
|
22
22
|
for (const slot of Object.keys(material)) {
|
|
23
23
|
const val = material[slot];
|
|
24
24
|
if (val?.isTexture === true) {
|
|
25
25
|
if (debug)
|
|
26
|
-
console.log("FIND", slot, val?.name, val?.userData, val);
|
|
27
|
-
NEEDLE_deferred_texture.getOrLoadTexture(context, material, slot, val, level).then(t => {
|
|
26
|
+
console.log("-----------\n", "FIND", material.name, slot, val?.name, val?.userData, val);
|
|
27
|
+
NEEDLE_deferred_texture.getOrLoadTexture(context, source, material, slot, val, level).then(t => {
|
|
28
28
|
if (t?.isTexture === true) {
|
|
29
29
|
t.needsUpdate = true;
|
|
30
|
+
if (debug)
|
|
31
|
+
console.log("Assign LOD", material.name, slot, t.name, t["guid"], material, "Prev:", val, "Now:", t, "\n--------------");
|
|
30
32
|
material[slot] = t;
|
|
31
33
|
material.needsUpdate = true;
|
|
34
|
+
|
|
32
35
|
}
|
|
33
36
|
});
|
|
34
37
|
}
|
|
@@ -67,9 +70,8 @@ export class NEEDLE_deferred_texture implements GLTFLoaderPlugin {
|
|
|
67
70
|
// }
|
|
68
71
|
|
|
69
72
|
afterRoot(gltf: GLTF): null {
|
|
70
|
-
|
|
71
73
|
if (debug)
|
|
72
|
-
console.log("AFTER", gltf);
|
|
74
|
+
console.log("AFTER", this.sourceId, gltf);
|
|
73
75
|
this.parser.json.textures?.forEach((textureInfo, index) => {
|
|
74
76
|
if (textureInfo?.extensions) {
|
|
75
77
|
const ext: DeferredTextureModel = textureInfo?.extensions[EXTENSION_NAME];
|
|
@@ -91,29 +93,31 @@ export class NEEDLE_deferred_texture implements GLTFLoaderPlugin {
|
|
|
91
93
|
private static cache = new Map<string, DeferredTextureModel>();
|
|
92
94
|
private static resolved: { [key: string]: Texture } = {};
|
|
93
95
|
|
|
94
|
-
private static async getOrLoadTexture(context: Context, material: Material, slot: string, current: Texture, _level: number): Promise<Texture | null> {
|
|
96
|
+
private static async getOrLoadTexture(context: Context, source : SourceIdentifier | undefined, material: Material, slot: string, current: Texture, _level: number): Promise<Texture | null> {
|
|
95
97
|
|
|
96
98
|
const key = current.uuid;
|
|
97
|
-
const ext: DeferredTextureModel = NEEDLE_deferred_texture.cache.get(key) || current.userData.deferred;
|
|
99
|
+
const ext: DeferredTextureModel | undefined = NEEDLE_deferred_texture.cache.get(key);// || current.userData.deferred;
|
|
98
100
|
if (ext) {
|
|
99
101
|
if (debug)
|
|
100
102
|
console.log(key, ext.uri, ext.guid);
|
|
101
|
-
const uri = ext.uri;
|
|
103
|
+
const uri = getPath(source, ext.uri);
|
|
102
104
|
if (uri.endsWith(".glb") || uri.endsWith(".gltf")) {
|
|
103
105
|
if (!ext.guid) {
|
|
104
106
|
console.warn("missing pointer for glb/gltf texture", ext);
|
|
105
107
|
return null;
|
|
106
108
|
}
|
|
107
|
-
const resolveKey =
|
|
108
|
-
if (this.resolved[resolveKey])
|
|
109
|
+
const resolveKey = uri + "_" + ext.guid;
|
|
110
|
+
if (this.resolved[resolveKey]) {
|
|
111
|
+
if (debug) console.log("Texture has already been loaded: " + resolveKey, material.name, slot, current.name);
|
|
109
112
|
return this.resolved[resolveKey];
|
|
113
|
+
}
|
|
110
114
|
|
|
111
115
|
const loader = new GLTFLoader();
|
|
112
116
|
addDracoAndKTX2Loaders(loader, context);
|
|
113
|
-
if (debug) console.log("Load " + uri, material.name, slot);
|
|
117
|
+
if (debug) console.log("Load " + uri, material.name, slot, ext.guid);
|
|
114
118
|
const gltf = await loader.loadAsync(uri);
|
|
115
119
|
const parser = gltf.parser;
|
|
116
|
-
|
|
120
|
+
if (debug) console.log("Loading finished " + uri, material.name, slot, ext.guid);
|
|
117
121
|
let index = -1;
|
|
118
122
|
let found = false;
|
|
119
123
|
for (const tex of gltf.parser.json.textures) {
|
|
@@ -137,20 +141,22 @@ export class NEEDLE_deferred_texture implements GLTFLoaderPlugin {
|
|
|
137
141
|
|
|
138
142
|
// const index = Number.parseInt(ext.pointer.substring("textures/".length));
|
|
139
143
|
const tex = await parser.getDependency("texture", index);
|
|
144
|
+
if (tex) {
|
|
145
|
+
tex.guid = ext.guid;
|
|
146
|
+
}
|
|
140
147
|
this.resolved[resolveKey] = tex as Texture;
|
|
141
|
-
|
|
142
148
|
if (debug)
|
|
143
|
-
console.log(material.name, slot, "change \"" + current.name + "\" → \"" + tex.name + "\"", uri, index, tex, material);
|
|
149
|
+
console.log(material.name, slot, "change \"" + current.name + "\" → \"" + tex.name + "\"", uri, index, tex, material, resolveKey);
|
|
144
150
|
return tex;
|
|
145
151
|
}
|
|
146
152
|
else {
|
|
147
|
-
|
|
153
|
+
if (debug) console.log("Load texture from uri: " + uri);
|
|
148
154
|
const loader = new TextureLoader();
|
|
149
|
-
const loaded = await loader.loadAsync(
|
|
155
|
+
const loaded = await loader.loadAsync(uri);
|
|
150
156
|
if (loaded && debug) {
|
|
151
157
|
console.log(ext, loaded);
|
|
152
158
|
}
|
|
153
|
-
else console.warn("failed loading",
|
|
159
|
+
else console.warn("failed loading", uri);
|
|
154
160
|
return loaded;
|
|
155
161
|
}
|
|
156
162
|
// loader.then((h: Texture) => {
|
|
@@ -10,13 +10,20 @@ declare type DependencyInfo = {
|
|
|
10
10
|
dependencyName: string,
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const rootExtensionPrefix = "/extensions/";
|
|
13
|
+
const rootExtensionPrefix = ["/extensions/", "extensions/"];
|
|
14
14
|
const defaultDependencies = [
|
|
15
15
|
{ prefix: "/nodes/", dependencyName: "node" },
|
|
16
16
|
{ prefix: "/meshes/", dependencyName: "mesh" },
|
|
17
17
|
{ prefix: "/materials/", dependencyName: "material" },
|
|
18
18
|
{ prefix: "/textures/", dependencyName: "texture" },
|
|
19
|
-
{ prefix: "/animations/", dependencyName: "animation" }
|
|
19
|
+
{ prefix: "/animations/", dependencyName: "animation" },
|
|
20
|
+
|
|
21
|
+
// legacy support
|
|
22
|
+
{ prefix: "nodes/", dependencyName: "node" },
|
|
23
|
+
{ prefix: "meshes/", dependencyName: "mesh" },
|
|
24
|
+
{ prefix: "materials/", dependencyName: "material" },
|
|
25
|
+
{ prefix: "textures/", dependencyName: "texture" },
|
|
26
|
+
{ prefix: "animations/", dependencyName: "animation" },
|
|
20
27
|
]
|
|
21
28
|
|
|
22
29
|
export async function resolveReferences(parser: GLTFParser, obj) {
|
|
@@ -95,16 +102,21 @@ function internalResolve(paths: DependencyInfo[], parser: GLTFParser, obj, promi
|
|
|
95
102
|
|
|
96
103
|
|
|
97
104
|
function resolveExtension(parser: GLTFParser, str): Promise<void> | null {
|
|
98
|
-
if (parser && parser.plugins && typeof str === "string"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
if (parser && parser.plugins && typeof str === "string") {
|
|
106
|
+
for (const prefix of rootExtensionPrefix) {
|
|
107
|
+
if (str.startsWith(prefix)) {
|
|
108
|
+
let name = str.substring(prefix.length);
|
|
109
|
+
const endIndex = name.indexOf("/");
|
|
110
|
+
if (endIndex >= 0) name = name.substring(0, endIndex);
|
|
111
|
+
const ext = parser.plugins[name] as IExtensionReferenceResolver;
|
|
112
|
+
if (debugExtension)
|
|
113
|
+
console.log(name, ext);
|
|
114
|
+
if (typeof ext?.resolve === "function") {
|
|
115
|
+
const path = str.substring(prefix.length + name.length + 1);
|
|
116
|
+
return ext.resolve(parser, path);
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
108
120
|
}
|
|
109
121
|
}
|
|
110
122
|
return null;
|
|
@@ -26,8 +26,9 @@ export function registerComponentExtension(loader: GLTFLoader): NEEDLE_component
|
|
|
26
26
|
class PointerResolver {
|
|
27
27
|
resolvePath(path: string) {
|
|
28
28
|
if (path.includes('/extensions/builtin_components/'))
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
return path.replace('/extensions/builtin_components/', '/userData/components/');
|
|
30
|
+
if (path.includes('extensions/builtin_components/'))
|
|
31
|
+
return path.replace('extensions/builtin_components/', '/userData/components/');
|
|
31
32
|
return path;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -5,6 +5,7 @@ import { getParam } from "../engine/engine_utils";
|
|
|
5
5
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
6
6
|
import { RGBAColor } from "./js-extensions/RGBAColor";
|
|
7
7
|
import { PerspectiveCamera } from "three";
|
|
8
|
+
import { XRSessionMode } from "../engine/engine_setup";
|
|
8
9
|
|
|
9
10
|
export enum ClearFlags {
|
|
10
11
|
Skybox = 1,
|
|
@@ -159,7 +160,6 @@ export class Camera extends Behaviour {
|
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
applyClearFlagsIfIsActiveCamera() {
|
|
162
|
-
// TODO: need to differentiate between what kind of XR (set skybox in VR but not in mobile AR for example!?)
|
|
163
163
|
if (this._cam && this.context.mainCameraComponent === this) {
|
|
164
164
|
switch (this._clearFlags) {
|
|
165
165
|
case ClearFlags.Skybox:
|
|
@@ -192,13 +192,20 @@ export class Camera extends Behaviour {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
private environmentIsTransparent(): boolean {
|
|
195
|
-
const session = this.context.renderer.xr?.getSession()
|
|
195
|
+
const session = this.context.renderer.xr?.getSession();
|
|
196
196
|
if (!session) return false;
|
|
197
197
|
const environmentBlendMode = session.environmentBlendMode;
|
|
198
198
|
const transparent = environmentBlendMode === 'additive' || environmentBlendMode === 'alpha-blend';
|
|
199
|
+
// workaround for Quest 2 returning opaque when it should be alpha-blend
|
|
200
|
+
// check user agent if this is the Quest browser and return true if so
|
|
201
|
+
|
|
202
|
+
if (environmentBlendMode === "opaque" && navigator.userAgent?.includes("OculusBrowser")) {
|
|
203
|
+
if (this.context.xrSessionMode === XRSessionMode.ImmersiveAR) return true;
|
|
204
|
+
}
|
|
199
205
|
return transparent;
|
|
200
206
|
}
|
|
201
207
|
|
|
208
|
+
|
|
202
209
|
private enableSkybox() {
|
|
203
210
|
if (!this._skybox)
|
|
204
211
|
this._skybox = new CameraSkybox(this);
|
|
@@ -9,6 +9,7 @@ import * as main from "../engine/engine_mainloop_utils";
|
|
|
9
9
|
import { Object3D } from "three";
|
|
10
10
|
import { InstantiateIdProvider, syncDestroy, syncInstantiate } from "../engine/engine_networking_instantiate";
|
|
11
11
|
import { SourceIdentifier } from "../engine/engine_gltf";
|
|
12
|
+
import { Collision } from "../engine/engine_physics";
|
|
12
13
|
|
|
13
14
|
export interface UIDProvider {
|
|
14
15
|
seed: number;
|
|
@@ -835,6 +836,10 @@ class Component implements EventTarget {
|
|
|
835
836
|
onBeforeRender?(frame: THREE.XRFrame | null): void;
|
|
836
837
|
onAfterRender?(): void;
|
|
837
838
|
|
|
839
|
+
onCollisionEnter?(col: Collision);
|
|
840
|
+
onCollisionExit?(col: Collision);
|
|
841
|
+
onCollisionStay?(col: Collision);
|
|
842
|
+
|
|
838
843
|
startCoroutine(routine: Generator, evt: FrameEvent = FrameEvent.Update): Generator {
|
|
839
844
|
return this.context.registerCoroutineUpdate(this, routine, evt);
|
|
840
845
|
}
|
|
@@ -865,6 +870,7 @@ class Component implements EventTarget {
|
|
|
865
870
|
this.__didEnable = false;
|
|
866
871
|
this.__isEnabled = undefined;
|
|
867
872
|
this.__destroyed = false;
|
|
873
|
+
this.__internalResetsCachedPhysicsData();
|
|
868
874
|
}
|
|
869
875
|
|
|
870
876
|
__internalAwake() {
|
|
@@ -892,6 +898,7 @@ class Component implements EventTarget {
|
|
|
892
898
|
__internalDisable() {
|
|
893
899
|
if (!this.__didEnable) return;
|
|
894
900
|
this.__didEnable = false;
|
|
901
|
+
this._collisionExitRoutine = undefined;
|
|
895
902
|
this.onDisable();
|
|
896
903
|
}
|
|
897
904
|
|
|
@@ -899,6 +906,57 @@ class Component implements EventTarget {
|
|
|
899
906
|
this.__internalNewInstanceCreated();
|
|
900
907
|
}
|
|
901
908
|
|
|
909
|
+
private _collisionExitRoutine: any;
|
|
910
|
+
private _collisions: Map<Object3D, { col: Collision, frame: number }> | null = null;
|
|
911
|
+
|
|
912
|
+
private __internalResetsCachedPhysicsData() {
|
|
913
|
+
this._collisionExitRoutine = null;
|
|
914
|
+
this._collisions = null;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
__internalHandleCollision(col: Collision) {
|
|
918
|
+
if (this.onCollisionEnter || this.onCollisionExit || this.onCollisionStay) {
|
|
919
|
+
const otherObject = col.gameObject;
|
|
920
|
+
if (!this._collisions) this._collisions = new Map();
|
|
921
|
+
if (this._collisions.has(otherObject)) {
|
|
922
|
+
const cur = this._collisions.get(otherObject)!;
|
|
923
|
+
cur.frame = this.context.time.frameCount;
|
|
924
|
+
cur.col = col;
|
|
925
|
+
this.onCollisionStay?.call(this, col);
|
|
926
|
+
}
|
|
927
|
+
else {
|
|
928
|
+
const entry = { col, frame: this.context.time.frameCount };
|
|
929
|
+
this._collisions.set(otherObject, entry);
|
|
930
|
+
this.onCollisionEnter?.call(this, col);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
sendExitCollisionEvent(obj : Object3D) {
|
|
936
|
+
if(!this._collisions) return;
|
|
937
|
+
const col = this._collisions.get(obj);
|
|
938
|
+
if(!col) return;
|
|
939
|
+
this.onCollisionExit?.call(this, col.col);
|
|
940
|
+
this._collisions.delete(obj);
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
private __waitForCollisionExit() {
|
|
944
|
+
if (this._collisionExitRoutine) return;
|
|
945
|
+
// const self = this;
|
|
946
|
+
// function* routine() {
|
|
947
|
+
// while (self._collisions && self._collisions.size > 0) {
|
|
948
|
+
// for (let ob of self._collisions.keys()) {
|
|
949
|
+
// const entry = self._collisions!.get(ob)!;
|
|
950
|
+
// if (self.context.time.frameCount - entry.frame > 1) {
|
|
951
|
+
// self._collisions!.delete(ob);
|
|
952
|
+
// self.onCollisionExit?.call(self, entry.col);
|
|
953
|
+
// }
|
|
954
|
+
// }
|
|
955
|
+
// yield;
|
|
956
|
+
// }
|
|
957
|
+
// }
|
|
958
|
+
// this._collisionExitRoutine = this.startCoroutine(routine(), FrameEvent.EarlyUpdate);
|
|
959
|
+
}
|
|
902
960
|
|
|
903
961
|
|
|
904
962
|
// TODO move this to threeutils
|
|
@@ -102,7 +102,8 @@ export class OrbitControls extends Behaviour {
|
|
|
102
102
|
if (this._controls) {
|
|
103
103
|
const camGo = GameObject.getComponent(this.gameObject, Camera);
|
|
104
104
|
if (camGo && !this.setFromTargetPosition()) {
|
|
105
|
-
|
|
105
|
+
if(this.debugLog)
|
|
106
|
+
console.log("NO TARGET");
|
|
106
107
|
const forward = new THREE.Vector3(0, 0, -1).applyMatrix4(camGo.cam.matrixWorld);
|
|
107
108
|
this.setTarget(forward, true);
|
|
108
109
|
}
|
|
@@ -13,6 +13,7 @@ const suppressInstancing = getParam("noInstancing");
|
|
|
13
13
|
const debugLightmap = getParam("debuglightmaps") ? true : false;
|
|
14
14
|
const debugInstancing = getParam("debuginstancing");
|
|
15
15
|
const debugProgressiveLoading = getParam("debugprogressiveload");
|
|
16
|
+
const suppressProgressiveLoading = getParam("noprogressiveload");
|
|
16
17
|
|
|
17
18
|
export class FieldWithDefault {
|
|
18
19
|
public path: string | null = null;
|
|
@@ -172,6 +173,8 @@ export class Renderer extends Behaviour {
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
awake() {
|
|
176
|
+
this.clearInstancingState();
|
|
177
|
+
|
|
175
178
|
const type = this.gameObject.type;
|
|
176
179
|
if (type === "Group") {
|
|
177
180
|
for (const child of this.gameObject.children) {
|
|
@@ -245,6 +248,11 @@ export class Renderer extends Behaviour {
|
|
|
245
248
|
private handles: InstanceHandle[] | null | undefined = undefined;
|
|
246
249
|
private prevLayers: number[] | null | undefined = undefined;
|
|
247
250
|
|
|
251
|
+
private clearInstancingState() {
|
|
252
|
+
this._isInstancingEnabled = false;
|
|
253
|
+
this.handles = undefined;
|
|
254
|
+
this.prevLayers = undefined;
|
|
255
|
+
}
|
|
248
256
|
setInstancingEnabled(enabled: boolean): boolean {
|
|
249
257
|
if (this._isInstancingEnabled === enabled) return enabled && (this.handles === undefined || this.handles != null && this.handles.length > 0);
|
|
250
258
|
this._isInstancingEnabled = enabled;
|
|
@@ -338,16 +346,16 @@ export class Renderer extends Behaviour {
|
|
|
338
346
|
onBeforeRenderThree(_renderer, _scene, _camera, _geometry, material, _group) {
|
|
339
347
|
|
|
340
348
|
// progressive load before rendering so we only load textures for visible materials
|
|
341
|
-
if (material._didRequestTextureLOD === undefined) {
|
|
349
|
+
if (!suppressProgressiveLoading && material._didRequestTextureLOD === undefined) {
|
|
342
350
|
material._didRequestTextureLOD = 0;
|
|
343
351
|
if (debugProgressiveLoading) {
|
|
344
352
|
console.log("Load material LOD (with delay)", material.name);
|
|
345
353
|
setTimeout(() => {
|
|
346
|
-
NEEDLE_deferred_texture.assignTextureLOD(this.context, material);
|
|
354
|
+
NEEDLE_deferred_texture.assignTextureLOD(this.context, this.sourceId, material);
|
|
347
355
|
}, 2000);
|
|
348
356
|
}
|
|
349
357
|
else {
|
|
350
|
-
NEEDLE_deferred_texture.assignTextureLOD(this.context, material);
|
|
358
|
+
NEEDLE_deferred_texture.assignTextureLOD(this.context, this.sourceId, material);
|
|
351
359
|
}
|
|
352
360
|
}
|
|
353
361
|
|
|
@@ -29,7 +29,7 @@ export class Rigidbody extends Behaviour {
|
|
|
29
29
|
@serializeable()
|
|
30
30
|
angularDrag: number = 1;
|
|
31
31
|
@serializeable()
|
|
32
|
-
|
|
32
|
+
detectCollisions: boolean = true;
|
|
33
33
|
@serializeable()
|
|
34
34
|
sleepThreshold: number = 0.01;
|
|
35
35
|
|
|
@@ -106,7 +106,7 @@ export class Rigidbody extends Behaviour {
|
|
|
106
106
|
options.angularDrag = this.angularDrag;
|
|
107
107
|
options.mass = this.mass;
|
|
108
108
|
options.kinematic = this.isKinematic;
|
|
109
|
-
options.physicsEvents = this.
|
|
109
|
+
options.physicsEvents = this.detectCollisions;
|
|
110
110
|
options.sleepThreshold = this.sleepThreshold;
|
|
111
111
|
this._body = this.context.physics.createBody(this.gameObject, options);
|
|
112
112
|
}
|