@needle-tools/engine 4.4.0-alpha.4 → 4.4.0-beta
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 +19 -1
- package/dist/needle-engine.bundle.js +5067 -4828
- package/dist/needle-engine.bundle.light.js +5062 -4823
- package/dist/needle-engine.bundle.light.min.js +129 -116
- package/dist/needle-engine.bundle.light.umd.cjs +125 -112
- package/dist/needle-engine.bundle.min.js +129 -116
- package/dist/needle-engine.bundle.umd.cjs +127 -114
- package/dist/needle-engine.d.ts +9 -9
- package/dist/needle-engine.js +91 -90
- package/dist/needle-engine.light.d.ts +9 -9
- package/dist/needle-engine.light.js +91 -90
- package/dist/needle-engine.light.min.js +1 -1
- package/dist/needle-engine.light.umd.cjs +1 -1
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/three.js +1 -0
- package/dist/three.light.js +1 -0
- package/dist/three.light.min.js +16 -16
- package/dist/three.light.umd.cjs +15 -15
- package/dist/three.min.js +16 -16
- package/dist/three.umd.cjs +15 -15
- package/lib/engine/engine_input.d.ts +7 -0
- package/lib/engine/engine_input.js +12 -0
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_serialization_decorator.js +4 -0
- package/lib/engine/engine_serialization_decorator.js.map +1 -1
- package/lib/engine/engine_three_utils.d.ts +26 -1
- package/lib/engine/engine_three_utils.js +43 -0
- package/lib/engine/engine_three_utils.js.map +1 -1
- package/lib/engine/engine_utils_format.js +11 -5
- package/lib/engine/engine_utils_format.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +1 -0
- package/lib/engine/webcomponents/needle menu/needle-menu.js +3 -3
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +2 -2
- package/lib/engine-components/Camera.js +4 -6
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/CameraUtils.js +32 -13
- package/lib/engine-components/CameraUtils.js.map +1 -1
- package/lib/engine-components/Component.d.ts +4 -1
- package/lib/engine-components/Component.js +4 -1
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/ContactShadows.js +8 -2
- package/lib/engine-components/ContactShadows.js.map +1 -1
- package/lib/engine-components/OrbitControls.d.ts +3 -0
- package/lib/engine-components/OrbitControls.js +34 -10
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/SyncedTransform.d.ts +3 -2
- package/lib/engine-components/SyncedTransform.js +28 -18
- package/lib/engine-components/SyncedTransform.js.map +1 -1
- package/lib/engine-components/utils/EnvironmentScene.d.ts +5 -0
- package/lib/engine-components/utils/EnvironmentScene.js +206 -0
- package/lib/engine-components/utils/EnvironmentScene.js.map +1 -0
- package/package.json +1 -1
- package/src/engine/engine_input.ts +13 -0
- package/src/engine/engine_serialization_decorator.ts +4 -0
- package/src/engine/engine_three_utils.ts +52 -1
- package/src/engine/engine_utils_format.ts +13 -5
- package/src/engine/webcomponents/needle menu/needle-menu.ts +3 -3
- package/src/engine-components/Camera.ts +9 -6
- package/src/engine-components/CameraUtils.ts +35 -13
- package/src/engine-components/Component.ts +5 -2
- package/src/engine-components/ContactShadows.ts +8 -2
- package/src/engine-components/OrbitControls.ts +35 -10
- package/src/engine-components/SyncedTransform.ts +37 -25
- package/src/engine-components/utils/EnvironmentScene.ts +246 -0
- package/src/engine/webcomponents/needle menu/dist/needle-menu.js +0 -662
|
@@ -59,13 +59,21 @@ export async function tryDetermineFileTypeFromURL(url: string, useExtension: boo
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
|
|
62
63
|
// If the URL doesnt contain a filetype we need to check the header
|
|
63
64
|
// This is the case for example if we load a file from a data url
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
|
|
66
|
+
if(url.startsWith("blob:")) {
|
|
67
|
+
// We can't modify the blob URL
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const newUrl = new URL(url);
|
|
71
|
+
// Adding a URL parameter to avoid the brower to bust the full cache
|
|
72
|
+
// If we don't do this the file that might already be disc cached will be deleted from the cache
|
|
73
|
+
newUrl.searchParams.append("range", "true");
|
|
74
|
+
url = newUrl.toString();
|
|
75
|
+
}
|
|
76
|
+
const header = await fetch(url, {
|
|
69
77
|
method: "GET",
|
|
70
78
|
headers: {
|
|
71
79
|
"range": "bytes=0-32"
|
|
@@ -697,7 +697,7 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
697
697
|
if (res == true && hasCommercialLicense() && !debugNonCommercial) {
|
|
698
698
|
let visible = this._userRequestedLogoVisible;
|
|
699
699
|
if (visible === undefined) visible = false;
|
|
700
|
-
this
|
|
700
|
+
this.___onSetLogoVisible(visible);
|
|
701
701
|
}
|
|
702
702
|
}));
|
|
703
703
|
} catch (e) {
|
|
@@ -827,10 +827,10 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
827
827
|
if (!localNetwork) return;
|
|
828
828
|
}
|
|
829
829
|
}
|
|
830
|
-
this
|
|
830
|
+
this.___onSetLogoVisible(visible);
|
|
831
831
|
}
|
|
832
832
|
|
|
833
|
-
|
|
833
|
+
private ___onSetLogoVisible(visible: boolean) {
|
|
834
834
|
this.logoContainer.style.display = "";
|
|
835
835
|
this.logoContainer.style.opacity = "1";
|
|
836
836
|
this.logoContainer.style.visibility = "visible";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EquirectangularReflectionMapping, Euler, Frustum, Matrix4, OrthographicCamera, PerspectiveCamera, Ray, Vector3 } from "three";
|
|
1
|
+
import { Color, EquirectangularReflectionMapping, Euler, Frustum, Matrix4, OrthographicCamera, PerspectiveCamera, Ray, Vector3 } from "three";
|
|
2
2
|
import { Texture } from "three";
|
|
3
3
|
|
|
4
4
|
import { showBalloonMessage } from "../engine/debug/index.js";
|
|
@@ -289,15 +289,18 @@ export class Camera extends Behaviour implements ICamera {
|
|
|
289
289
|
public get backgroundColor(): RGBAColor | null {
|
|
290
290
|
return this._backgroundColor ?? null;
|
|
291
291
|
}
|
|
292
|
-
public set backgroundColor(val: RGBAColor | null) {
|
|
292
|
+
public set backgroundColor(val: RGBAColor | Color | null) {
|
|
293
293
|
if (!val) return;
|
|
294
294
|
if (!this._backgroundColor) {
|
|
295
|
-
|
|
296
|
-
this._backgroundColor = val.clone();
|
|
295
|
+
this._backgroundColor = new RGBAColor(1, 1, 1, 1);
|
|
297
296
|
}
|
|
298
|
-
|
|
297
|
+
|
|
298
|
+
this._backgroundColor.copy(val);
|
|
299
|
+
|
|
299
300
|
// set background color to solid if provided color doesnt have any alpha channel
|
|
300
|
-
if (val.alpha === undefined)
|
|
301
|
+
if ((!("alpha" in val) || val.alpha === undefined)) {
|
|
302
|
+
this._backgroundColor.alpha = 1;
|
|
303
|
+
}
|
|
301
304
|
this.applyClearFlagsIfIsActiveCamera();
|
|
302
305
|
}
|
|
303
306
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { PerspectiveCamera } from "three";
|
|
1
|
+
import { Color, PerspectiveCamera, PMREMGenerator } from "three";
|
|
2
2
|
|
|
3
3
|
import { getCameraController } from "../engine/engine_camera.js";
|
|
4
4
|
import { addNewComponent, getOrAddComponent } from "../engine/engine_components.js";
|
|
5
5
|
import { Context } from "../engine/engine_context.js";
|
|
6
6
|
import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
|
|
7
7
|
import { NeedleEngineHTMLElement } from "../engine/engine_element.js";
|
|
8
|
+
import { createFlatTexture, createTrilightTexture } from "../engine/engine_shaders.js";
|
|
8
9
|
import type { ICamera, IContext } from "../engine/engine_types.js";
|
|
9
10
|
import { getParam } from "../engine/engine_utils.js";
|
|
10
11
|
import { RGBAColor } from "../engine/js-extensions/index.js";
|
|
11
12
|
import { Camera, ClearFlags } from "./Camera.js";
|
|
12
13
|
import { OrbitControls } from "./OrbitControls.js";
|
|
14
|
+
import EnvironmentScene from "./utils/EnvironmentScene.js";
|
|
13
15
|
|
|
14
16
|
const debug = getParam("debugmissingcamera");
|
|
15
17
|
|
|
@@ -30,27 +32,47 @@ ContextRegistry.registerCallback(ContextEvent.MissingCamera, (evt) => {
|
|
|
30
32
|
|
|
31
33
|
const camInstance = new Camera();
|
|
32
34
|
camInstance.sourceId = evt.files?.[0]?.src ?? "unknown"
|
|
35
|
+
camInstance.fieldOfView = 35;
|
|
33
36
|
|
|
37
|
+
const transparentAttribute = evt.context.domElement.getAttribute("transparent");
|
|
38
|
+
if (transparentAttribute != undefined) {
|
|
39
|
+
camInstance.clearFlags = ClearFlags.Uninitialized;
|
|
40
|
+
}
|
|
34
41
|
// Set the clearFlags to a skybox if we have one OR if the user set a skybox image attribute
|
|
35
|
-
if (evt.context.domElement.getAttribute("skybox-image")?.length || evt.context.domElement.getAttribute("background-image")?.length || (evt.context as Context).lightmaps.tryGetSkybox(camInstance.sourceId)) {
|
|
42
|
+
else if (evt.context.domElement.getAttribute("skybox-image")?.length || evt.context.domElement.getAttribute("background-image")?.length || (evt.context as Context).lightmaps.tryGetSkybox(camInstance.sourceId)) {
|
|
36
43
|
camInstance.clearFlags = ClearFlags.Skybox;
|
|
44
|
+
// TODO: can we store the backgroundBlurriness in the gltf file somewhere except inside the camera?
|
|
45
|
+
// e.g. when we export a scene from blender without a camera in the scene
|
|
46
|
+
camInstance.backgroundBlurriness = .2; // same as in blender 0.5
|
|
37
47
|
}
|
|
38
|
-
else
|
|
39
|
-
// TODO provide a nice default skybox
|
|
48
|
+
else {
|
|
40
49
|
camInstance.clearFlags = ClearFlags.SolidColor;
|
|
41
|
-
camInstance.backgroundColor = new RGBAColor(0.5, 0.5, 0.5, 1);
|
|
42
|
-
camInstance.fieldOfView = 35;
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
let backgroundColor = "#efefef";
|
|
52
|
+
if(typeof window !== undefined && (window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
53
|
+
backgroundColor = "#1f1f1f";
|
|
54
|
+
}
|
|
55
|
+
scene.background = new Color(backgroundColor); // dont set it on the camera because this might be controlled from "background-color" attribute which is set on the scene directly. If the camera has a background color, it will override the scene's background color
|
|
56
|
+
|
|
57
|
+
// Generate a default environment map if none is set
|
|
58
|
+
if (!scene.environment) {
|
|
59
|
+
// const backgroundColorAttribute = evt.context.domElement.getAttribute("background-color") ?? "#fff";
|
|
60
|
+
// const backgroundColor = new Color(backgroundColorAttribute);
|
|
61
|
+
const pmremGenerator = new PMREMGenerator(evt.context.renderer);
|
|
62
|
+
const env = new EnvironmentScene("neutral");
|
|
63
|
+
// const background = scene.background;
|
|
64
|
+
// const col0 = new Color(.1, .1, .1);
|
|
65
|
+
// const col1 = new Color(.3, .3, .3);
|
|
66
|
+
// const col2 = new Color(1, 1, 1);
|
|
67
|
+
// const envmap = createTrilightTexture(col0, col1, col2, 32, 32);
|
|
68
|
+
// scene.background = envmap;
|
|
69
|
+
scene.environment = pmremGenerator.fromScene(env, .025).texture;
|
|
70
|
+
// scene.background = background;
|
|
71
|
+
}
|
|
47
72
|
}
|
|
48
73
|
|
|
49
|
-
// TODO: can we store the backgroundBlurriness in the gltf file somewhere except inside the camera?
|
|
50
|
-
// e.g. when we export a scene from blender without a camera in the scene
|
|
51
|
-
camInstance.backgroundBlurriness = .2; // same as in blender 0.5
|
|
52
|
-
const cam = addNewComponent(cameraObject, camInstance, true) as ICamera;
|
|
53
74
|
|
|
75
|
+
const cam = addNewComponent(cameraObject, camInstance, true) as ICamera;
|
|
54
76
|
cameraObject.position.x = 0;
|
|
55
77
|
cameraObject.position.y = 1;
|
|
56
78
|
cameraObject.position.z = 2;
|
|
@@ -1128,7 +1128,8 @@ export abstract class Component implements IComponent, EventTarget,
|
|
|
1128
1128
|
}
|
|
1129
1129
|
|
|
1130
1130
|
/**
|
|
1131
|
-
* Gets the position of this component's GameObject in world space
|
|
1131
|
+
* Gets the position of this component's GameObject in world space.
|
|
1132
|
+
* Note: This is equivalent to calling `this.gameObject.worldPosition`
|
|
1132
1133
|
*/
|
|
1133
1134
|
get worldPosition(): Vector3 {
|
|
1134
1135
|
return threeutils.getWorldPosition(this.gameObject);
|
|
@@ -1154,6 +1155,7 @@ export abstract class Component implements IComponent, EventTarget,
|
|
|
1154
1155
|
|
|
1155
1156
|
/**
|
|
1156
1157
|
* Gets the rotation of this component's GameObject in world space as a quaternion
|
|
1158
|
+
* Note: This is equivalent to calling `this.gameObject.worldQuaternion`
|
|
1157
1159
|
*/
|
|
1158
1160
|
get worldQuaternion(): Quaternion {
|
|
1159
1161
|
return threeutils.getWorldQuaternion(this.gameObject);
|
|
@@ -1194,7 +1196,8 @@ export abstract class Component implements IComponent, EventTarget,
|
|
|
1194
1196
|
}
|
|
1195
1197
|
|
|
1196
1198
|
/**
|
|
1197
|
-
* Gets the rotation of this component's GameObject in world space as Euler angles (in degrees)
|
|
1199
|
+
* Gets the rotation of this component's GameObject in world space as Euler angles (in degrees)
|
|
1200
|
+
* Note: This is equivalent to calling `this.gameObject.worldRotation`
|
|
1198
1201
|
*/
|
|
1199
1202
|
get worldRotation(): Vector3 {
|
|
1200
1203
|
return this.gameObject.worldRotation;
|
|
@@ -17,9 +17,15 @@ import { Behaviour, GameObject } from "./Component.js";
|
|
|
17
17
|
const debug = getParam("debugcontactshadows");
|
|
18
18
|
|
|
19
19
|
onStart(ctx => {
|
|
20
|
-
const val = ctx.domElement.getAttribute("contactshadows");
|
|
20
|
+
const val = ctx.domElement.getAttribute("contactshadows") || ctx.domElement.getAttribute("contact-shadows");
|
|
21
21
|
if (val != undefined && val != "0" && val != "false") {
|
|
22
|
-
|
|
22
|
+
console.debug("Auto-creating ContactShadows because of `contactshadows` attribute");
|
|
23
|
+
const shadows = ContactShadows.auto(ctx);
|
|
24
|
+
const intensity = parseFloat(val);
|
|
25
|
+
if (!isNaN(intensity)) {
|
|
26
|
+
shadows.opacity = intensity;
|
|
27
|
+
shadows.darkness = intensity;
|
|
28
|
+
}
|
|
23
29
|
}
|
|
24
30
|
})
|
|
25
31
|
|
|
@@ -316,6 +316,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
316
316
|
if (DeviceUtilities.isMobileDevice()) this.doubleClickToFocus = true;
|
|
317
317
|
}
|
|
318
318
|
this._controls.addEventListener("start", this.onControlsChangeStarted);
|
|
319
|
+
this._controls.addEventListener("end", this.onControlsChangeEnded);
|
|
319
320
|
|
|
320
321
|
if (!this._startedListeningToKeyEvents && this.enableKeys) {
|
|
321
322
|
this._startedListeningToKeyEvents = true;
|
|
@@ -346,6 +347,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
346
347
|
this._controls.enabled = false;
|
|
347
348
|
this._controls.autoRotate = false;
|
|
348
349
|
this._controls.removeEventListener("start", this.onControlsChangeStarted);
|
|
350
|
+
this._controls.removeEventListener("end", this.onControlsChangeEnded);
|
|
349
351
|
try {
|
|
350
352
|
this._controls.stopListenToKeyEvents();
|
|
351
353
|
} catch { /** this fails if we never listened to key events... */ }
|
|
@@ -366,7 +368,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
366
368
|
this._activePointerEvents.push(_evt);
|
|
367
369
|
}
|
|
368
370
|
private _onPointerDownLate = (evt: NEPointerEvent) => {
|
|
369
|
-
if(evt.used && this._controls) {
|
|
371
|
+
if (evt.used && this._controls) {
|
|
370
372
|
// Disabling orbit controls here because otherwise we get a slight movement when e.g. using DragControls
|
|
371
373
|
this._controls.enabled = false;
|
|
372
374
|
}
|
|
@@ -413,22 +415,45 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
413
415
|
this.setTargetFromRaycast();
|
|
414
416
|
}
|
|
415
417
|
// Automatically update the camera focus
|
|
416
|
-
else if (!evt.used && this.autoTarget) {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
const hit = hits.length > 0 ? hits[0] : undefined;
|
|
420
|
-
if(hit && hit.distance > this.minZoom && hit.distance < this.maxZoom) {
|
|
421
|
-
if(debug) Gizmos.DrawWireSphere(hit.point, 0.1, 0xff0000, 2);
|
|
422
|
-
this._controls?.target.copy(hits[0].point);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
418
|
+
// else if (!evt.used && this.autoTarget) {
|
|
419
|
+
// this.updateTargetNow();
|
|
420
|
+
// }
|
|
425
421
|
};
|
|
426
422
|
|
|
423
|
+
private updateTargetNow() {
|
|
424
|
+
const ray = new Ray(this._cameraObject?.worldPosition, this._cameraObject?.worldForward.multiplyScalar(-1));
|
|
425
|
+
const hits = this.context.physics.raycastFromRay(ray);
|
|
426
|
+
const hit = hits.length > 0 ? hits[0] : undefined;
|
|
427
|
+
if (hit && hit.distance > this.minZoom && hit.distance < this.maxZoom) {
|
|
428
|
+
if (debug) Gizmos.DrawWireSphere(hit.point, 0.1, 0xff0000, 2);
|
|
429
|
+
this._controls?.target.copy(hits[0].point);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private _orbitStartAngle: number = 0;
|
|
427
434
|
private onControlsChangeStarted = () => {
|
|
435
|
+
if (this._controls) {
|
|
436
|
+
this._orbitStartAngle = this._controls.getAzimuthalAngle() + this._controls.getPolarAngle();
|
|
437
|
+
}
|
|
428
438
|
if (this._syncedTransform) {
|
|
429
439
|
this._syncedTransform.requestOwnership();
|
|
430
440
|
}
|
|
431
441
|
}
|
|
442
|
+
private onControlsChangeEnded = () => {
|
|
443
|
+
|
|
444
|
+
if (this._controls) {
|
|
445
|
+
if (this.autoTarget) {
|
|
446
|
+
const newAngle = this._controls.getAzimuthalAngle() + this._controls.getPolarAngle();
|
|
447
|
+
const delta = newAngle - this._orbitStartAngle;
|
|
448
|
+
if (Math.abs(delta) < .01) {
|
|
449
|
+
if (debug) console.debug("OrbitControls: No movement detected, updating target now");
|
|
450
|
+
this.updateTargetNow();
|
|
451
|
+
}
|
|
452
|
+
else if(debug) console.debug("OrbitControls: Movement detected", delta);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
}
|
|
432
457
|
|
|
433
458
|
private _shouldDisable: boolean = false;
|
|
434
459
|
private afterHandleInput(evt: CustomEvent<AfterHandleInputEvent>) {
|
|
@@ -51,7 +51,7 @@ onUpdate((ctx) => {
|
|
|
51
51
|
const threshold = isRunningOnGlitch ? 10 : 40;
|
|
52
52
|
FAST_INTERVAL = Math.floor(FAST_ACTIVE_SYNCTRANSFORMS / threshold);
|
|
53
53
|
FAST_ACTIVE_SYNCTRANSFORMS = 0;
|
|
54
|
-
if(debug && FAST_INTERVAL > 0) console.log("Sync Transform Fast Interval", FAST_INTERVAL);
|
|
54
|
+
if (debug && FAST_INTERVAL > 0) console.log("Sync Transform Fast Interval", FAST_INTERVAL);
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
/**
|
|
@@ -62,20 +62,20 @@ onUpdate((ctx) => {
|
|
|
62
62
|
*/
|
|
63
63
|
export class SyncedTransform extends Behaviour {
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
// public autoOwnership: boolean = true;
|
|
67
67
|
/** When true, overrides physics behavior when this object is owned by the local user */
|
|
68
68
|
public overridePhysics: boolean = true
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
/** Whether to smoothly interpolate position changes when receiving updates */
|
|
71
71
|
public interpolatePosition: boolean = true;
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
/** Whether to smoothly interpolate rotation changes when receiving updates */
|
|
74
74
|
public interpolateRotation: boolean = true;
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
/** When true, sends updates at a higher frequency, useful for fast-moving objects */
|
|
77
77
|
public fastMode: boolean = false;
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
/** When true, notifies other clients when this object is destroyed */
|
|
80
80
|
public syncDestroy: boolean = false;
|
|
81
81
|
|
|
@@ -135,8 +135,9 @@ export class SyncedTransform extends Behaviour {
|
|
|
135
135
|
this._targetRotation = new Quaternion();
|
|
136
136
|
|
|
137
137
|
// sync instantiate issue was because they shared the same last pos vector!
|
|
138
|
-
this.
|
|
139
|
-
this.
|
|
138
|
+
this.lastPosition = new Vector3();
|
|
139
|
+
this.lastRotation = new Quaternion();
|
|
140
|
+
this.lastScale = new Vector3();
|
|
140
141
|
|
|
141
142
|
this.rb = GameObject.getComponentInChildren(this.gameObject, Rigidbody);
|
|
142
143
|
if (this.rb) {
|
|
@@ -207,6 +208,11 @@ export class SyncedTransform extends Behaviour {
|
|
|
207
208
|
if (!this.interpolateRotation || !this._receivedDataBefore)
|
|
208
209
|
setWorldEuler(this.gameObject, this.tempEuler);
|
|
209
210
|
}
|
|
211
|
+
|
|
212
|
+
const scale = transform.scale();
|
|
213
|
+
if (scale) {
|
|
214
|
+
this.gameObject.scale.set(scale.x(), scale.y(), scale.z());
|
|
215
|
+
}
|
|
210
216
|
}
|
|
211
217
|
this._receivedDataBefore = true;
|
|
212
218
|
|
|
@@ -221,8 +227,9 @@ export class SyncedTransform extends Behaviour {
|
|
|
221
227
|
* Initializes tracking of position and rotation when component is enabled
|
|
222
228
|
*/
|
|
223
229
|
onEnable(): void {
|
|
224
|
-
this.
|
|
225
|
-
this.
|
|
230
|
+
this.lastPosition.copy(this.worldPosition);
|
|
231
|
+
this.lastRotation.copy(this.worldQuaternion);
|
|
232
|
+
this.lastScale.copy(this.gameObject.scale);
|
|
226
233
|
this._needsUpdate = true;
|
|
227
234
|
// console.log("ENABLE", this.guid, this.gameObject.guid, this.lastWorldPos);
|
|
228
235
|
if (this._model) {
|
|
@@ -241,8 +248,9 @@ export class SyncedTransform extends Behaviour {
|
|
|
241
248
|
|
|
242
249
|
|
|
243
250
|
private receivedUpdate = false;
|
|
244
|
-
private
|
|
245
|
-
private
|
|
251
|
+
private lastPosition!: Vector3;
|
|
252
|
+
private lastRotation!: Quaternion;
|
|
253
|
+
private lastScale!: Vector3;
|
|
246
254
|
|
|
247
255
|
/**
|
|
248
256
|
* @internal
|
|
@@ -264,24 +272,27 @@ export class SyncedTransform extends Behaviour {
|
|
|
264
272
|
this._model.requestOwnership();
|
|
265
273
|
}
|
|
266
274
|
|
|
267
|
-
const
|
|
268
|
-
const
|
|
275
|
+
const pos = this.worldPosition;
|
|
276
|
+
const rot = this.worldQuaternion;
|
|
277
|
+
const scale = this.gameObject.scale;
|
|
269
278
|
if (this._model.isOwned && !this.receivedUpdate) {
|
|
270
|
-
const worlddiff = wp.distanceTo(this.lastWorldPos);
|
|
271
|
-
const worldRot = wr.angleTo(this.lastWorldRotation);
|
|
272
279
|
const threshold = this._model.hasOwnership || this.fastMode ? .0001 : .001;
|
|
273
|
-
if (
|
|
280
|
+
if (pos.distanceTo(this.lastPosition) > threshold ||
|
|
281
|
+
rot.angleTo(this.lastRotation) > threshold ||
|
|
282
|
+
scale.distanceTo(this.lastScale) > threshold) {
|
|
274
283
|
// console.log(worlddiff, worldRot);
|
|
275
284
|
if (!this._model.hasOwnership) {
|
|
276
285
|
|
|
277
286
|
if (debug)
|
|
278
|
-
console.log(this.guid, "reset because not owned but", this.gameObject.name, this.
|
|
287
|
+
console.log(this.guid, "reset because not owned but", this.gameObject.name, this.lastPosition);
|
|
279
288
|
|
|
280
|
-
this.worldPosition = this.
|
|
281
|
-
|
|
289
|
+
this.worldPosition = this.lastPosition;
|
|
290
|
+
pos.copy(this.lastPosition);
|
|
282
291
|
|
|
283
|
-
this.worldQuaternion = this.
|
|
284
|
-
|
|
292
|
+
this.worldQuaternion = this.lastRotation;
|
|
293
|
+
rot.copy(this.lastRotation);
|
|
294
|
+
|
|
295
|
+
this.gameObject.scale.copy(this.lastScale);
|
|
285
296
|
|
|
286
297
|
InstancingUtil.markDirty(this.gameObject, true);
|
|
287
298
|
this._needsUpdate = false;
|
|
@@ -323,12 +334,13 @@ export class SyncedTransform extends Behaviour {
|
|
|
323
334
|
|
|
324
335
|
|
|
325
336
|
this.receivedUpdate = false;
|
|
326
|
-
this.
|
|
327
|
-
this.
|
|
337
|
+
this.lastPosition.copy(pos);
|
|
338
|
+
this.lastRotation.copy(rot);
|
|
339
|
+
this.lastScale.copy(scale);
|
|
328
340
|
|
|
329
341
|
|
|
330
342
|
if (!this._model) return;
|
|
331
|
-
|
|
343
|
+
|
|
332
344
|
if (!this._model || this._model.hasOwnership === undefined || !this._model.hasOwnership) {
|
|
333
345
|
// if we're not the owner of this synced transform then don't send any data
|
|
334
346
|
return;
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// https://github.com/google/model-viewer/blob/c61dd1459b59cd74f539eb31658f943fd13c702e/packages/model-viewer/src/three-components/EnvironmentScene.ts#L198
|
|
2
|
+
|
|
3
|
+
/* @license
|
|
4
|
+
* Copyright 2021 Google LLC. All Rights Reserved.
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the 'License');
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an 'AS IS' BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import {BackSide, BoxGeometry, Mesh, MeshBasicMaterial, MeshStandardMaterial, PointLight, Scene} from 'three';
|
|
19
|
+
|
|
20
|
+
interface Box {
|
|
21
|
+
position: [number, number, number];
|
|
22
|
+
rotation: number;
|
|
23
|
+
scale: [number, number, number];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface Light {
|
|
27
|
+
intensity: number;
|
|
28
|
+
position: [number, number, number];
|
|
29
|
+
scale: [number, number, number];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface Env {
|
|
33
|
+
topLight: {
|
|
34
|
+
intensity: number,
|
|
35
|
+
position: [number, number, number],
|
|
36
|
+
};
|
|
37
|
+
room: {
|
|
38
|
+
position: [number, number, number],
|
|
39
|
+
scale: [number, number, number],
|
|
40
|
+
};
|
|
41
|
+
boxes: Box[];
|
|
42
|
+
lights: Light[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const legacy = {
|
|
46
|
+
topLight: {
|
|
47
|
+
intensity: 500,
|
|
48
|
+
position: [0.418, 16.199, 0.300],
|
|
49
|
+
},
|
|
50
|
+
room: {
|
|
51
|
+
position: [-0.757, 13.219, 0.717],
|
|
52
|
+
scale: [31.713, 28.305, 28.591],
|
|
53
|
+
},
|
|
54
|
+
boxes: [
|
|
55
|
+
{
|
|
56
|
+
position: [-10.906, 2.009, 1.846],
|
|
57
|
+
rotation: -0.195,
|
|
58
|
+
scale: [2.328, 7.905, 4.651],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
position: [-5.607, -0.754, -0.758],
|
|
62
|
+
rotation: 0.994,
|
|
63
|
+
scale: [1.970, 1.534, 3.955],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
position: [6.167, 0.857, 7.803],
|
|
67
|
+
rotation: 0.561,
|
|
68
|
+
scale: [3.927, 6.285, 3.687],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
position: [-2.017, 0.018, 6.124],
|
|
72
|
+
rotation: 0.333,
|
|
73
|
+
scale: [2.002, 4.566, 2.064],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
position: [2.291, -0.756, -2.621],
|
|
77
|
+
rotation: -0.286,
|
|
78
|
+
scale: [1.546, 1.552, 1.496],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
position: [-2.193, -0.369, -5.547],
|
|
82
|
+
rotation: 0.516,
|
|
83
|
+
scale: [3.875, 3.487, 2.986],
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
lights: [
|
|
87
|
+
{
|
|
88
|
+
intensity: 50,
|
|
89
|
+
position: [-16.116, 14.37, 8.208],
|
|
90
|
+
scale: [0.1, 2.428, 2.739],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
intensity: 50,
|
|
94
|
+
position: [-16.109, 18.021, -8.207],
|
|
95
|
+
scale: [0.1, 2.425, 2.751],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
intensity: 17,
|
|
99
|
+
position: [14.904, 12.198, -1.832],
|
|
100
|
+
scale: [0.15, 4.265, 6.331],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
intensity: 43,
|
|
104
|
+
position: [-0.462, 8.89, 14.520],
|
|
105
|
+
scale: [4.38, 5.441, 0.088],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
intensity: 20,
|
|
109
|
+
position: [3.235, 11.486, -12.541],
|
|
110
|
+
scale: [2.5, 2.0, 0.1],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
intensity: 100,
|
|
114
|
+
position: [0.0, 20.0, 0.0],
|
|
115
|
+
scale: [1.0, 0.1, 1.0],
|
|
116
|
+
},
|
|
117
|
+
]
|
|
118
|
+
} as Env;
|
|
119
|
+
|
|
120
|
+
const neutral = {
|
|
121
|
+
topLight: {
|
|
122
|
+
intensity: 400,
|
|
123
|
+
position: [0.5, 14.0, 0.5],
|
|
124
|
+
},
|
|
125
|
+
room: {
|
|
126
|
+
position: [0.0, 13.2, 0.0],
|
|
127
|
+
scale: [31.5, 28.5, 31.5],
|
|
128
|
+
},
|
|
129
|
+
boxes: [
|
|
130
|
+
{
|
|
131
|
+
position: [-10.906, -1.0, 1.846],
|
|
132
|
+
rotation: -0.195,
|
|
133
|
+
scale: [2.328, 7.905, 4.651],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
position: [-5.607, -0.754, -0.758],
|
|
137
|
+
rotation: 0.994,
|
|
138
|
+
scale: [1.970, 1.534, 3.955],
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
position: [6.167, -0.16, 7.803],
|
|
142
|
+
rotation: 0.561,
|
|
143
|
+
scale: [3.927, 6.285, 3.687],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
position: [-2.017, 0.018, 6.124],
|
|
147
|
+
rotation: 0.333,
|
|
148
|
+
scale: [2.002, 4.566, 2.064],
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
position: [2.291, -0.756, -2.621],
|
|
152
|
+
rotation: -0.286,
|
|
153
|
+
scale: [1.546, 1.552, 1.496],
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
position: [-2.193, -0.369, -5.547],
|
|
157
|
+
rotation: 0.516,
|
|
158
|
+
scale: [3.875, 3.487, 2.986],
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
lights: [
|
|
162
|
+
{
|
|
163
|
+
intensity: 80,
|
|
164
|
+
position: [-14.0, 10.0, 8.0],
|
|
165
|
+
scale: [0.1, 2.5, 2.5],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
intensity: 80,
|
|
169
|
+
position: [-14.0, 14.0, -4.0],
|
|
170
|
+
scale: [0.1, 2.5, 2.5],
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
intensity: 23,
|
|
174
|
+
position: [14.0, 12.0, 0.0],
|
|
175
|
+
scale: [0.1, 5.0, 5.0],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
intensity: 16,
|
|
179
|
+
position: [0.0, 9.0, 14.0],
|
|
180
|
+
scale: [5.0, 5.0, 0.1],
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
intensity: 80,
|
|
184
|
+
position: [7.0, 8.0, -14.0],
|
|
185
|
+
scale: [2.5, 2.5, 0.1],
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
intensity: 80,
|
|
189
|
+
position: [-7.0, 16.0, -14.0],
|
|
190
|
+
scale: [2.5, 2.5, 0.1],
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
intensity: 1,
|
|
194
|
+
position: [0.0, 20.0, 0.0],
|
|
195
|
+
scale: [0.1, 0.1, 0.1],
|
|
196
|
+
},
|
|
197
|
+
]
|
|
198
|
+
} as Env;
|
|
199
|
+
|
|
200
|
+
export default class EnvironmentScene extends Scene {
|
|
201
|
+
constructor(name: 'legacy'|'neutral') {
|
|
202
|
+
super();
|
|
203
|
+
|
|
204
|
+
this.position.y = -3.5;
|
|
205
|
+
|
|
206
|
+
const geometry = new BoxGeometry();
|
|
207
|
+
geometry.deleteAttribute('uv');
|
|
208
|
+
|
|
209
|
+
const roomMaterial =
|
|
210
|
+
new MeshStandardMaterial({metalness: 0, side: BackSide});
|
|
211
|
+
const boxMaterial = new MeshStandardMaterial({metalness: 0});
|
|
212
|
+
|
|
213
|
+
const data = name == 'legacy' ? legacy : neutral;
|
|
214
|
+
|
|
215
|
+
const mainLight = new PointLight(0xffffff, data.topLight.intensity, 28, 2);
|
|
216
|
+
mainLight.position.set(...data.topLight.position);
|
|
217
|
+
this.add(mainLight);
|
|
218
|
+
|
|
219
|
+
const room = new Mesh(geometry, roomMaterial);
|
|
220
|
+
room.position.set(...data.room.position);
|
|
221
|
+
room.scale.set(...data.room.scale);
|
|
222
|
+
this.add(room);
|
|
223
|
+
|
|
224
|
+
for (const box of data.boxes) {
|
|
225
|
+
const box1 = new Mesh(geometry, boxMaterial);
|
|
226
|
+
box1.position.set(...box.position);
|
|
227
|
+
box1.rotation.set(0, box.rotation, 0);
|
|
228
|
+
box1.scale.set(...box.scale);
|
|
229
|
+
this.add(box1);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
for (const light of data.lights) {
|
|
233
|
+
const light1 =
|
|
234
|
+
new Mesh(geometry, this.createAreaLightMaterial(light.intensity));
|
|
235
|
+
light1.position.set(...light.position);
|
|
236
|
+
light1.scale.set(...light.scale);
|
|
237
|
+
this.add(light1);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
createAreaLightMaterial(intensity: number): MeshBasicMaterial {
|
|
242
|
+
const material = new MeshBasicMaterial();
|
|
243
|
+
material.color.setScalar(intensity);
|
|
244
|
+
return material;
|
|
245
|
+
}
|
|
246
|
+
}
|