@needle-tools/engine 3.5.11-beta → 3.5.13-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.
Files changed (45) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/needle-engine.js +7719 -7687
  3. package/dist/needle-engine.light.js +7444 -7412
  4. package/dist/needle-engine.light.min.js +310 -310
  5. package/dist/needle-engine.light.umd.cjs +305 -305
  6. package/dist/needle-engine.min.js +311 -311
  7. package/dist/needle-engine.umd.cjs +306 -306
  8. package/lib/engine/debug/debug.d.ts +3 -0
  9. package/lib/engine/debug/debug.js +3 -0
  10. package/lib/engine/debug/debug.js.map +1 -1
  11. package/lib/engine/engine_license.js +1 -1
  12. package/lib/engine/engine_license.js.map +1 -1
  13. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  14. package/lib/engine/engine_physics_rapier.d.ts +3 -8
  15. package/lib/engine/engine_physics_rapier.js +30 -11
  16. package/lib/engine/engine_physics_rapier.js.map +1 -1
  17. package/lib/engine/engine_serialization_builtin_serializer.js +10 -9
  18. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  19. package/lib/engine/engine_types.d.ts +10 -3
  20. package/lib/engine/engine_types.js.map +1 -1
  21. package/lib/engine/engine_utils.d.ts +6 -0
  22. package/lib/engine/engine_utils.js +6 -0
  23. package/lib/engine/engine_utils.js.map +1 -1
  24. package/lib/engine-components/CameraUtils.js +2 -1
  25. package/lib/engine-components/CameraUtils.js.map +1 -1
  26. package/lib/engine-components/OrbitControls.d.ts +1 -0
  27. package/lib/engine-components/OrbitControls.js +49 -13
  28. package/lib/engine-components/OrbitControls.js.map +1 -1
  29. package/lib/engine-components/Skybox.js +25 -1
  30. package/lib/engine-components/Skybox.js.map +1 -1
  31. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.d.ts +1 -0
  32. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js +1 -0
  33. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/engine/debug/debug.ts +3 -0
  36. package/src/engine/engine_license.ts +1 -1
  37. package/src/engine/engine_networking_instantiate.ts +1 -1
  38. package/src/engine/engine_physics_rapier.ts +26 -11
  39. package/src/engine/engine_serialization_builtin_serializer.ts +9 -9
  40. package/src/engine/engine_types.ts +13 -5
  41. package/src/engine/engine_utils.ts +6 -0
  42. package/src/engine-components/CameraUtils.ts +2 -1
  43. package/src/engine-components/OrbitControls.ts +58 -13
  44. package/src/engine-components/Skybox.ts +30 -6
  45. package/src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +1 -0
@@ -1,12 +1,12 @@
1
1
  import { Behaviour, GameObject } from "./Component";
2
2
  import { Camera } from "./Camera";
3
3
  import { LookAtConstraint } from "./LookAtConstraint";
4
- import { getWorldPosition, slerp } from "../engine/engine_three_utils";
4
+ import { getWorldPosition, getWorldRotation, setWorldPosition, setWorldRotation, slerp } from "../engine/engine_three_utils";
5
5
  import { RaycastOptions } from "../engine/engine_physics";
6
6
  import { serializable } from "../engine/engine_serialization_decorator";
7
7
  import { getParam, isMobileDevice } from "../engine/engine_utils";
8
8
 
9
- import { Camera as ThreeCamera, Box3, Object3D, PerspectiveCamera, Vector2, Vector3 } from "three";
9
+ import { Camera as ThreeCamera, Box3, Object3D, PerspectiveCamera, Vector2, Vector3, Box3Helper } from "three";
10
10
  import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls";
11
11
  import { AfterHandleInputEvent, EventSystem, EventSystemEvents } from "./ui/EventSystem";
12
12
  import { ICameraController } from "../engine/engine_types";
@@ -14,6 +14,7 @@ import { setCameraController } from "../engine/engine_camera";
14
14
  import { SyncedTransform } from "./SyncedTransform";
15
15
 
16
16
  const freeCam = getParam("freecam");
17
+ const debugCameraFit = getParam("debugcamerafit");
17
18
 
18
19
  const disabledKeys = { LEFT: "", UP: "", RIGHT: "", BOTTOM: "" };
19
20
  let defaultKeys: any = undefined;
@@ -87,7 +88,9 @@ export class OrbitControls extends Behaviour implements ICameraController {
87
88
  if (camGo && !this.setFromTargetPosition()) {
88
89
  if (this.debugLog)
89
90
  console.log("NO TARGET");
90
- const forward = new Vector3(0, 0, -10).applyMatrix4(camGo.cam.matrixWorld);
91
+ const worldPosition = getWorldPosition(camGo.cam);
92
+ const distanceToCenter = worldPosition.length();
93
+ const forward = new Vector3(0, 0, -distanceToCenter).applyMatrix4(camGo.cam.matrixWorld);
91
94
  this.setTarget(forward, true);
92
95
  }
93
96
  }
@@ -349,7 +352,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
349
352
 
350
353
  // Adapted from https://discourse.threejs.org/t/camera-zoom-to-fit-object/936/24
351
354
  // Slower but better implementation that takes bones and exact vertex positions into account: https://github.com/google/model-viewer/blob/04e900c5027de8c5306fe1fe9627707f42811b05/packages/model-viewer/src/three-components/ModelScene.ts#L321
352
- fitCameraToObjects(objects: Array<Object3D>, fitOffset: number = 1.5) {
355
+ fitCameraToObjects(objects: Array<Object3D>, fitOffset: number = 1.1) {
353
356
  const camera = this._cameraObject as PerspectiveCamera;
354
357
  const controls = this._controls as ThreeOrbitControls | null;
355
358
 
@@ -359,20 +362,43 @@ export class OrbitControls extends Behaviour implements ICameraController {
359
362
  const center = new Vector3();
360
363
  const box = new Box3();
361
364
 
365
+ // TODO would be much better to calculate the bounds in camera space instead of world space -
366
+ // we would get proper view-dependant fit.
367
+ // Right now it's independent from where the camera is actually looking from,
368
+ // and thus we're just getting some maximum that will work for sure.
369
+
362
370
  box.makeEmpty();
363
- for (const object of objects)
364
- box.expandByObject(object);
371
+ for (const object of objects) {
372
+ // ignore Box3Helpers
373
+ if (object instanceof Box3Helper) continue;
374
+ box.expandByObject(object, true);
375
+ }
376
+
377
+ camera.updateMatrixWorld();
378
+ camera.updateProjectionMatrix();
365
379
 
366
- box.getSize(size);
367
380
  box.getCenter(center);
368
381
 
369
- const maxSize = Math.max(size.x, size.y, size.z);
370
- const fitHeightDistance = maxSize / (2 * Math.atan(Math.PI * camera.fov / 360));
371
- const fitWidthDistance = fitHeightDistance / camera.aspect;
372
- const distance = fitOffset * Math.max(fitHeightDistance, fitWidthDistance);
382
+ // project this box into camera space
383
+ box.applyMatrix4(camera.matrixWorldInverse);
384
+
385
+ box.getSize(size);
386
+ box.setFromCenterAndSize(center, size);
387
+
388
+ const verticalFov = camera.fov;
389
+ const horizontalFov = 2 * Math.atan(Math.tan(verticalFov * Math.PI / 360 / 2) * camera.aspect) / Math.PI * 360;
390
+ const fitHeightDistance = size.y / (2 * Math.atan(Math.PI * verticalFov / 360));
391
+ const fitWidthDistance = size.x / (2 * Math.atan(Math.PI * horizontalFov / 360));
392
+
393
+ const distance = fitOffset * Math.max(fitHeightDistance, fitWidthDistance) + size.z / 2;
373
394
 
395
+ if (debugCameraFit) {
396
+ console.log("Fit camera to objects", fitHeightDistance, fitWidthDistance, "distance", distance);
397
+ }
398
+
399
+ const cameraWp = getWorldPosition(camera);
374
400
  const direction = controls.target.clone()
375
- .sub(camera.position)
401
+ .sub(cameraWp)
376
402
  .normalize()
377
403
  .multiplyScalar(distance);
378
404
 
@@ -382,13 +408,32 @@ export class OrbitControls extends Behaviour implements ICameraController {
382
408
 
383
409
  camera.near = distance / 100;
384
410
  camera.far = distance * 100;
411
+
412
+ camera.updateMatrixWorld();
385
413
  camera.updateProjectionMatrix();
386
414
 
387
- camera.position.copy(controls.target).sub(direction);
415
+ setWorldPosition(camera, controls.target.clone().sub(direction));
416
+
417
+ if (debugCameraFit) {
418
+ const helper = new Box3Helper(box);
419
+ this.context.scene.add(helper);
420
+ setWorldRotation(helper, getWorldRotation(camera));
421
+
422
+ if (!this._haveAttachedKeyboardEvents) {
423
+ this._haveAttachedKeyboardEvents = true;
424
+ document.body.addEventListener("keydown", (e) => {
425
+ if (e.code === "KeyF") {
426
+ this.fitCameraToObjects(objects);
427
+ }
428
+ });
429
+ }
430
+ }
388
431
 
389
432
  controls.update();
390
433
  }
391
434
 
435
+ private _haveAttachedKeyboardEvents: boolean = false;
436
+
392
437
  // private onPositionDrag(){
393
438
 
394
439
  // }
@@ -5,10 +5,34 @@ import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader";
5
5
  import { EquirectangularRefractionMapping, sRGBEncoding, Texture, TextureLoader } from "three"
6
6
  import { syncField } from "../engine/engine_networking_auto";
7
7
  import { Camera } from "./Camera";
8
- import { getParam, resolveUrl } from "../engine/engine_utils";
8
+ import { getParam } from "../engine/engine_utils";
9
+ import { ContextRegistry } from "../engine/engine_context_registry";
9
10
 
10
11
  const debug = getParam("debugskybox");
11
12
 
13
+ ContextRegistry.addContextCreatedCallback((args) => {
14
+ const context = args.context;
15
+ const skyboxImage = context.domElement.getAttribute("skybox-image");
16
+ const environmentImage = context.domElement.getAttribute("environment-image");
17
+ if (skyboxImage) {
18
+ if (debug) console.log("Creating remote skybox to load " + skyboxImage);
19
+ const remote = new RemoteSkybox();
20
+ remote.url = skyboxImage;
21
+ remote.allowDrop = false;
22
+ remote.environment = false;
23
+ remote.background = true;
24
+ GameObject.addComponent(context.scene, remote);
25
+ }
26
+ if (environmentImage) {
27
+ const remote = new RemoteSkybox();
28
+ remote.url = environmentImage;
29
+ remote.allowDrop = false;
30
+ remote.environment = true;
31
+ remote.background = false;
32
+ GameObject.addComponent(context.scene, remote);
33
+ }
34
+ });
35
+
12
36
  export class RemoteSkybox extends Behaviour {
13
37
 
14
38
  @syncField("setSkybox")
@@ -53,7 +77,7 @@ export class RemoteSkybox extends Behaviour {
53
77
  console.warn("Potentially invalid skybox url", this.url, "on", this.name);
54
78
  }
55
79
 
56
- if(debug) console.log("Remote skybox url?: " + url);
80
+ if (debug) console.log("Remote skybox url?: " + url);
57
81
 
58
82
  if (this._prevUrl === url && this._prevLoadedEnvironment) {
59
83
  this.applySkybox();
@@ -81,7 +105,7 @@ export class RemoteSkybox extends Behaviour {
81
105
  this._loader = new TextureLoader();
82
106
  }
83
107
 
84
- if(debug) console.log("Loading skybox: " + url);
108
+ if (debug) console.log("Loading skybox: " + url);
85
109
  const envMap = await this._loader.loadAsync(url);
86
110
  if (!envMap) return;
87
111
  // Check if we're still enabled
@@ -110,7 +134,7 @@ export class RemoteSkybox extends Behaviour {
110
134
  if (this.context.scene.environment !== envMap)
111
135
  this._prevEnvironment = this.context.scene.environment;
112
136
 
113
- if(debug) console.log("Set remote skybox", this.url);
137
+ if (debug) console.log("Set remote skybox", this.url);
114
138
  if (this.environment)
115
139
  this.context.scene.environment = envMap;
116
140
  if (this.background && !Camera.backgroundShouldBeTransparent(this.context))
@@ -147,12 +171,12 @@ export class RemoteSkybox extends Behaviour {
147
171
  for (const type of e.dataTransfer.types) {
148
172
  if (type === "text/uri-list") {
149
173
  const url = e.dataTransfer.getData(type);
150
- if(debug) console.log(type, url);
174
+ if (debug) console.log(type, url);
151
175
  let name = new RegExp(/polyhaven.com\/asset_img\/.+?\/(?<name>.+)\.png/).exec(url)?.groups?.name;
152
176
  if (!name) {
153
177
  name = new RegExp(/polyhaven\.com\/a\/(?<name>.+)/).exec(url)?.groups?.name;
154
178
  }
155
- if(debug) console.log(name);
179
+ if (debug) console.log(name);
156
180
  if (name) {
157
181
  const envurl = "https://dl.polyhaven.org/file/ph-assets/HDRIs/exr/1k/" + name + "_1k.exr";
158
182
  this.setSkybox(envurl);
@@ -11,6 +11,7 @@ export interface UsdzBehaviour {
11
11
  afterSerialize?(ext: BehaviorExtension, context: IContext): void;
12
12
  }
13
13
 
14
+ /** internal USDZ behaviours extension */
14
15
  export class BehaviorExtension implements IUSDExporterExtension {
15
16
 
16
17
  get extensionName(): string {