Needle Engine

Changes between version 3.37.10-alpha.4 and 3.37.10-alpha.5
Files changed (4) hide show
  1. src/engine-components/ContactShadows.ts +14 -6
  2. src/engine/engine_loaders.ts +8 -1
  3. src/engine-components/OrbitControls.ts +33 -5
  4. src/engine-components/ReflectionProbe.ts +5 -0
src/engine-components/ContactShadows.ts CHANGED
@@ -84,11 +84,16 @@
84
84
  if (debug) console.log("Fitting shadows to scene");
85
85
  setAutoFitEnabled(this.gameObject, false);
86
86
  const box = getBoundingBox(this.context.scene.children, [this.gameObject]);
87
- if (debug) Gizmos.DrawWireBox3(box, 0xffff00, 1);
87
+ // expand box in all directions (except below ground)
88
+ // 0.01 expands by 1% in each direction
89
+ const expandFactor = .01;
90
+ box.expandByVector(new Vector3(expandFactor, 0, expandFactor));
88
91
  const min = box.min;
89
- this.gameObject.position.set((min.x + box.max.x) / 2, min.y - .01, (min.z + box.max.z) / 2);
90
- this.gameObject.scale.set(box.max.x - min.x, 1, box.max.z - min.z);
91
- this.gameObject.scale.multiplyScalar(1.5);
92
+ const offset = Math.max(0.00001, (box.max.y - min.y) * .002);
93
+ box.max.y += offset;
94
+ if (debug) Gizmos.DrawWireBox3(box, 0xffff00, 60);
95
+ this.gameObject.position.set((min.x + box.max.x) / 2, min.y - offset, (min.z + box.max.z) / 2);
96
+ this.gameObject.scale.set(box.max.x - min.x, box.max.y - min.y, box.max.z - min.z);
92
97
  }
93
98
 
94
99
  awake() {
@@ -286,11 +291,14 @@
286
291
  // and reset the override material
287
292
  scene.overrideMaterial = null;
288
293
 
289
- this.blurShadow(this.blur);
294
+ const size = this.gameObject.scale.x;
290
295
 
296
+ // take the size of the scene into account - for larger scenes we want less blur to keep it somewhat consistent
297
+ const blurAmount = Math.min(this.blur, this.blur / size);
298
+
291
299
  // a second pass to reduce the artifacts
292
300
  // (0.4 is the minimum blur amout so that the artifacts are gone)
293
- this.blurShadow(this.blur * 0.4);
301
+ this.blurShadow(blurAmount * 0.4);
294
302
 
295
303
  this.shadowGroup.visible = false;
296
304
  if (this.occluderMesh) this.occluderMesh.visible = this.occludeBelowGround;
src/engine/engine_loaders.ts CHANGED
@@ -56,7 +56,13 @@
56
56
  meshoptDecoder = _meshoptDecoder;
57
57
  }
58
58
 
59
- export function addDracoAndKTX2Loaders(loader: GLTFLoader, context: Context) {
59
+ /**
60
+ * Add Draco, Meshopt and KTX2 loaders to a GLTFLoader instance.
61
+ * @param loader The GLTFLoader instance to add the loaders to.
62
+ * @param context The context object containing the renderer.
63
+ * @returns The GLTFLoader instance with the loaders added.
64
+ */
65
+ export function addDracoAndKTX2Loaders(loader: GLTFLoader, context: Pick<Context, "renderer">) {
60
66
  if (!dracoLoader) {
61
67
  dracoLoader = new DRACOLoader();
62
68
  dracoLoader.setDecoderPath(DEFAULT_DRACO_DECODER_LOCATION);
@@ -85,4 +91,5 @@
85
91
  loader.setKTX2Loader(ktx2Loader);
86
92
  if (!(loader as any).meshoptDecoder)
87
93
  loader.setMeshoptDecoder(meshoptDecoder);
94
+ return loader;
88
95
  }
src/engine-components/OrbitControls.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Box3, Box3Helper, GridHelper, Mesh, Object3D, PerspectiveCamera, Ray,ShadowMaterial, Vector2, Vector3 } from "three";
1
+ import { Box3, Box3Helper, GridHelper, Mesh, Object3D, PerspectiveCamera, Ray, ShadowMaterial, Vector2, Vector3 } from "three";
2
2
  import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
3
3
  import { GroundedSkybox } from "three/examples/jsm/objects/GroundedSkybox.js";
4
4
 
@@ -54,12 +54,18 @@
54
54
  return true;
55
55
  }
56
56
 
57
- /** The underlying three.js OrbitControls */
57
+ /** The underlying three.js OrbitControls.
58
+ * See {@link https://threejs.org/docs/#examples/en/controls/OrbitControls}
59
+ * @returns {@type ThreeOrbitControls | null}
60
+ */
58
61
  public get controls() {
59
62
  return this._controls;
60
63
  }
61
64
 
62
- /** The object being controlled by the OrbitControls (usually the camera) */
65
+ /** The object being controlled by the OrbitControls (usually the camera)
66
+ * See {@link https://threejs.org/docs/#examples/en/controls/OrbitControls.object}
67
+ * @returns {@type Object3D | null}
68
+ */
63
69
  public get controllerObject(): Object3D | null {
64
70
  return this._cameraObject;
65
71
  }
@@ -118,6 +124,28 @@
118
124
  @serializable()
119
125
  maxZoom: number = Infinity;
120
126
 
127
+ /**
128
+ * Sets the zoom speed of the OrbitControls
129
+ * @default 1
130
+ */
131
+ set zoomSpeed(value: number) {
132
+ if (this._controls) this._controls.zoomSpeed = value;
133
+ }
134
+ get zoomSpeed() {
135
+ return this._controls?.zoomSpeed ?? 0;
136
+ }
137
+
138
+ /**
139
+ * Set to true to enable zooming to the cursor position.
140
+ * @default false
141
+ */
142
+ set zoomToCursor(value: boolean) {
143
+ if (this._controls) this._controls.zoomToCursor = value;
144
+ }
145
+ get zoomToCursor() {
146
+ return this._controls?.zoomToCursor ?? false;
147
+ }
148
+
121
149
  /** When enabled the camera can be panned */
122
150
  @serializable()
123
151
  enablePan: boolean = true;
@@ -401,7 +429,7 @@
401
429
  this._controls.enableZoom = false;
402
430
  }
403
431
  }
404
-
432
+
405
433
  // this._controls.zoomToCursor = this.zoomToCursor;
406
434
  if (!this.context.isInXR) {
407
435
  if (!freeCam && this.lookAtConstraint?.locked) this.setLookTargetFromConstraint(0, this.lookAtConstraint01);
@@ -622,7 +650,7 @@
622
650
 
623
651
  box.getSize(size);
624
652
  box.setFromCenterAndSize(center, size);
625
- if( Number.isNaN(size.x) || Number.isNaN(size.y) || Number.isNaN(size.z)){
653
+ if (Number.isNaN(size.x) || Number.isNaN(size.y) || Number.isNaN(size.z)) {
626
654
  console.warn("Camera fit size resultet in NaN", camera, box, [...objects]);
627
655
  return;
628
656
  }
src/engine-components/ReflectionProbe.ts CHANGED
@@ -172,6 +172,11 @@
172
172
  if (debug) console.log("Set reflection", _rend.name, _rend.guid);
173
173
  }
174
174
 
175
+ // See NE-4771 and NE-4856
176
+ if (cached && cached.copy) {
177
+ cached.copy.onBeforeCompile = material.onBeforeCompile;
178
+ }
179
+
175
180
  /** this is the material that we copied and that has the reflection probe */
176
181
  const copy = cached?.copy;