Needle Engine

Changes between version 3.44.0-beta.1 and 3.44.0-beta.2
Files changed (14) hide show
  1. src/engine-components/postprocessing/Effects/Antialiasing.ts +1 -1
  2. src/engine/api.ts +2 -1
  3. src/engine-components/webxr/Avatar.ts +2 -1
  4. src/engine-components/postprocessing/Effects/DepthOfField.ts +3 -3
  5. src/engine/engine_three_utils.ts +18 -2
  6. src/engine-components/GridHelper.ts +3 -3
  7. src/engine/webcomponents/needle menu/needle-menu.ts +3 -3
  8. src/engine-components/postprocessing/PostProcessingHandler.ts +3 -1
  9. src/engine-components/ReflectionProbe.ts +5 -1
  10. src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts +4 -1
  11. src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +51 -8
  12. src/engine-components/SyncedTransform.ts +0 -30
  13. src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +11 -7
  14. src/engine-components/postprocessing/Effects/Vignette.ts +3 -3
src/engine-components/postprocessing/Effects/Antialiasing.ts CHANGED
@@ -24,7 +24,7 @@
24
24
  // edgeDetectionThreshold!: VolumeParameter;
25
25
 
26
26
  @serializable(VolumeParameter)
27
- readonly preset: VolumeParameter = new VolumeParameter();
27
+ readonly preset: VolumeParameter = new VolumeParameter(SMAAPreset.HIGH);
28
28
 
29
29
 
30
30
  onCreateEffect(): EffectProviderResult {
src/engine/api.ts CHANGED
@@ -2,8 +2,9 @@
2
2
  export * from "./debug/index.js";
3
3
  export * from "./engine_addressables.js";
4
4
  export * from "./engine_application.js";
5
+ export { AnimationUtils } from "./engine_animation.js";
5
6
  export * from "./engine_assetdatabase.js";
6
- export { getCameraController,setAutoFitEnabled, setCameraController, useForAutoFit } from "./engine_camera.js"
7
+ export { getCameraController, setAutoFitEnabled, setCameraController, useForAutoFit } from "./engine_camera.js"
7
8
  export * from "./engine_components.js";
8
9
  export * from "./engine_components_internal.js";
9
10
  export * from "./engine_components_internal.js";
src/engine-components/webxr/Avatar.ts CHANGED
@@ -38,7 +38,7 @@
38
38
 
39
39
  const playerstate = PlayerState.getFor(this);
40
40
  if (playerstate?.owner) {
41
- const marker = this.gameObject.addNewComponent(AvatarMarker)!;
41
+ const marker = this.gameObject.addComponent(AvatarMarker)!;
42
42
  marker.avatar = this.gameObject;
43
43
  marker.connectionId = playerstate.owner;
44
44
  }
@@ -86,6 +86,7 @@
86
86
  if (this.head && this.context.mainCamera) {
87
87
  const headObj = this.head.asset as IGameObject;
88
88
  headObj.position.copy(this.context.mainCamera.position);
89
+ headObj.position.z *= -1;
89
90
  headObj.quaternion.copy(this.context.mainCamera.quaternion);
90
91
  headObj.quaternion.x *= -1;
91
92
 
src/engine-components/postprocessing/Effects/DepthOfField.ts CHANGED
@@ -25,13 +25,13 @@
25
25
  mode!: DepthOfFieldMode;
26
26
 
27
27
  @serializable(VolumeParameter)
28
- readonly focusDistance: VolumeParameter = new VolumeParameter();
28
+ readonly focusDistance: VolumeParameter = new VolumeParameter(1);
29
29
 
30
30
  @serializable(VolumeParameter)
31
- readonly focalLength: VolumeParameter = new VolumeParameter();
31
+ readonly focalLength: VolumeParameter = new VolumeParameter(.2);
32
32
 
33
33
  @serializable(VolumeParameter)
34
- readonly aperture: VolumeParameter = new VolumeParameter();
34
+ readonly aperture: VolumeParameter = new VolumeParameter(20);
35
35
 
36
36
  @serializable(VolumeParameter)
37
37
  readonly gaussianMaxRadius: VolumeParameter = new VolumeParameter();
src/engine/engine_three_utils.ts CHANGED
@@ -637,8 +637,19 @@
637
637
  /**
638
638
  * Postprocesses the material of an object loaded by THREE.FBXLoader. It will apply some conversions to the material and will assign a MeshStandardMaterial to the object.
639
639
  */
640
- export function postprocessFBXMaterials(obj: Mesh, material: Material): boolean {
640
+ export function postprocessFBXMaterials(obj: Mesh, material: Material | Material[], index?: number, array?: Material[]): boolean {
641
641
 
642
+ if (Array.isArray(material)) {
643
+ let success = true;
644
+ for (let i = 0; i < material.length; i++) {
645
+ const res = postprocessFBXMaterials(obj, material[i], i, material);
646
+ if (!res) success = false;
647
+ }
648
+ return success;
649
+ }
650
+
651
+
652
+
642
653
  // ignore if the material is already a MeshStandardMaterial
643
654
  if (material.type === "MeshStandardMaterial") {
644
655
  return false;
@@ -685,7 +696,12 @@
685
696
  newMaterial.needsUpdate = true;
686
697
  }
687
698
 
688
- obj.material = newMaterial;
699
+ if (index === undefined) {
700
+ obj.material = newMaterial;
701
+ }
702
+ else {
703
+ array![index] = newMaterial;
704
+ }
689
705
  return true;
690
706
  }
691
707
 
src/engine-components/GridHelper.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Color, GridHelper as _GridHelper } from "three";
1
+ import { Color, ColorRepresentation, GridHelper as _GridHelper } from "three";
2
2
 
3
3
  import * as params from "../engine/engine_default_parameters.js";
4
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
@@ -12,9 +12,9 @@
12
12
  @serializable()
13
13
  public isGizmo: boolean = false;
14
14
  @serializable(Color)
15
- private color0!: Color;
15
+ color0!: Color | ColorRepresentation;
16
16
  @serializable(Color)
17
- private color1!: Color;
17
+ color1!: Color | ColorRepresentation;
18
18
 
19
19
  private gridHelper!: _GridHelper | null;
20
20
  private size!: number;
src/engine/webcomponents/needle menu/needle-menu.ts CHANGED
@@ -185,7 +185,7 @@
185
185
 
186
186
 
187
187
  appendChild(child: HTMLElement | ButtonInfo) {
188
- this._menu.appendChild(child);
188
+ return this._menu.appendChild(child);
189
189
  }
190
190
 
191
191
  }
@@ -640,7 +640,7 @@
640
640
 
641
641
  private onOptionsChildrenChanged(_mut: MutationRecord) {
642
642
  this.logoContainer.classList.toggle("any-options", this.hasAnyVisibleOptions);
643
- this.handleSizeChange();
643
+ this.handleSizeChange(undefined, true);
644
644
 
645
645
  if (_mut.type === "childList") {
646
646
  let needsSorting = false;
@@ -743,7 +743,7 @@
743
743
  this.root.classList.add("compact")
744
744
  }
745
745
  }
746
- }, 200) as unknown as number;
746
+ }, 5) as unknown as number;
747
747
 
748
748
  const getCurrentWidth = () => {
749
749
  return this.options.clientWidth + this.logoContainer.clientWidth;
src/engine-components/postprocessing/PostProcessingHandler.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { N8AOPostPass } from "n8ao";
2
2
  import {
3
3
  BloomEffect, BrightnessContrastEffect, ChromaticAberrationEffect, DepthDownsamplingPass, DepthOfFieldEffect, Effect, EffectComposer, EffectPass, HueSaturationEffect, NormalPass, Pass, PixelationEffect, RenderPass, SelectiveBloomEffect, SMAAEffect, SSAOEffect,
4
- ToneMappingEffect as _TonemappingEffect, VignetteEffect
4
+ ToneMappingEffect as _TonemappingEffect, VignetteEffect,
5
+ TiltShiftEffect
5
6
  } from "postprocessing";
6
7
  import { HalfFloatType, NoToneMapping } from "three";
7
8
 
@@ -279,6 +280,7 @@
279
280
  SMAAEffect,
280
281
  SSAOEffect,
281
282
  N8AOPostPass,
283
+ TiltShiftEffect,
282
284
  DepthOfFieldEffect,
283
285
  ChromaticAberrationEffect,
284
286
  BloomEffect,
src/engine-components/ReflectionProbe.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { EquirectangularReflectionMapping, Material, Object3D, SRGBColorSpace, Texture, Vector3 } from "three";
1
+ import { EquirectangularReflectionMapping, Material, MeshBasicMaterial, Object3D, SRGBColorSpace, Texture, Vector3 } from "three";
2
2
 
3
3
  import { serializable } from "../engine/engine_serialization.js";
4
4
  import { Context } from "../engine/engine_setup.js";
@@ -136,6 +136,10 @@
136
136
  continue;
137
137
  }
138
138
 
139
+ if (material instanceof MeshBasicMaterial) {
140
+ continue;
141
+ }
142
+
139
143
  let cached = rendererCache[i];
140
144
 
141
145
  // make sure we have the currently assigned material cached (and an up to date clone of that)
src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts CHANGED
@@ -6,7 +6,10 @@
6
6
  import { VolumeParameter } from "../VolumeParameter.js";
7
7
  import { registerCustomEffectType } from "../VolumeProfile.js";
8
8
 
9
-
9
+ /** Screenspace Ambient Occlusion post-processing effect.
10
+ * We recommend using ScreenSpaceAmbientOcclusionN8 instead.
11
+ * @category Postprocessing
12
+ */
10
13
  export class ScreenSpaceAmbientOcclusion extends PostProcessingEffect {
11
14
 
12
15
  get typeName() {
src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { N8AOPostPass } from "n8ao";
2
- import { Color, NeverDepth, PerspectiveCamera } from "three";
2
+ import { Color, PerspectiveCamera } from "three";
3
3
 
4
4
  import { serializable } from "../../../engine/engine_serialization.js";
5
5
  import { validate } from "../../../engine/engine_util_decorator.js";
@@ -18,7 +18,10 @@
18
18
  Ultra = 4,
19
19
  }
20
20
 
21
- /**See [N8AO documentation](https://github.com/N8python/n8ao) */
21
+ /** Screen Space Ambient Occlusion (SSAO) effect.
22
+ * @category Postprocessing
23
+ * @link [N8AO documentation](https://github.com/N8python/n8ao)
24
+ */
22
25
  export class ScreenSpaceAmbientOcclusionN8 extends PostProcessingEffect {
23
26
 
24
27
  get typeName() {
@@ -29,22 +32,62 @@
29
32
  @serializable()
30
33
  gammaCorrection: boolean = true;
31
34
 
35
+ /** The most important parameter for your ambient occlusion effect.
36
+ * Controls the radius/size of the ambient occlusion in world units.
37
+ * Should be set to how far you want the occlusion to extend from a given object.
38
+ * Set it too low, and AO becomes an edge detector.
39
+ * Too high, and the AO becomes "soft" and might not highlight the details you want.
40
+ * The radius should be one or two magnitudes less than scene scale:
41
+ * if your scene is 10 units across, the radius should be between 0.1 and 1. If its 100, 1 to 10.
42
+ * @default 1
43
+ */
32
44
  @serializable(VolumeParameter)
33
- intensity!: VolumeParameter;
45
+ aoRadius: VolumeParameter = new VolumeParameter(1);
34
46
 
47
+ /** The second most important parameter for your ambient occlusion effect.
48
+ * Controls how fast the ambient occlusion fades away with distance in proportion to its radius.
49
+ * Defaults to 1, and behind-the-scenes, is a calculated as a ratio of your radius (0.2 * distanceFalloff is the size used for attenuation).
50
+ * Decreasing it reduces "haloing" artifacts and improves the accuracy of your occlusion,
51
+ * but making it too small makes the ambient occlusion disappear entirely.
52
+ * @default 1
53
+ */
35
54
  @serializable(VolumeParameter)
36
- falloff!: VolumeParameter;
55
+ falloff: VolumeParameter = new VolumeParameter(1);
37
56
 
57
+ /** A purely artistic control for the intensity of the AO - runs the ao through the function pow(ao, intensity),
58
+ * which has the effect of darkening areas with more ambient occlusion.
59
+ * Useful to make the effect more pronounced.
60
+ * An intensity of 2 generally produces soft ambient occlusion that isn't too noticeable,
61
+ * whereas one of 5 produces heavily prominent ambient occlusion.
62
+ * @default 1
63
+ */
38
64
  @serializable(VolumeParameter)
39
- aoRadius!: VolumeParameter;
65
+ intensity: VolumeParameter = new VolumeParameter(1);
40
66
 
67
+ /** The color of the ambient occlusion. By default, it is black, but it can be changed to any color
68
+ * to offer a crude approximation of global illumination.
69
+ * Recommended in scenes where bounced light has a uniform "color",
70
+ * for instance a scene that is predominantly lit by a blue sky.
71
+ * The color is expected to be in the sRGB color space, and is automatically converted to linear space for you.
72
+ * Keep the color pretty dark for sensible results.
73
+ * @default new Color(0, 0, 0)
74
+ */
75
+ @serializable(VolumeParameter)
76
+ color: VolumeParameter = new VolumeParameter(new Color(0, 0, 0));
77
+
78
+ /** If you want the AO to calculate the radius based on screen space, you can do so by setting configuration.screenSpaceRadius to true.
79
+ * This is useful for scenes where the camera is moving across different scales a lot,
80
+ * or for scenes where the camera is very close to the objects.
81
+ * @default false
82
+ */
41
83
  @validate()
42
84
  @serializable()
43
85
  screenspaceRadius: boolean = false;
44
86
 
45
- @serializable(VolumeParameter)
46
- color!: VolumeParameter;
47
-
87
+ /**
88
+ * The quality of the ambient occlusion effect.
89
+ * @default ScreenSpaceAmbientOcclusionN8QualityMode.Medium
90
+ */
48
91
  @validate()
49
92
  @serializable()
50
93
  quality: ScreenSpaceAmbientOcclusionN8QualityMode = ScreenSpaceAmbientOcclusionN8QualityMode.Medium;
src/engine-components/SyncedTransform.ts CHANGED
@@ -312,10 +312,6 @@
312
312
  if (debug)
313
313
  console.log("send update", this.context.connection.connectionId, this.guid, this.gameObject.name, this.gameObject.guid);
314
314
 
315
- if (this.overridePhysics && this.rb) {
316
- // this.rb.setBodyFromGameObject();
317
- }
318
-
319
315
  this._needsUpdate = false;
320
316
  const st = createTransformModel(this.guid, this, fastUpdate ? true : false);
321
317
  // this._state.update(this, this.rb);
@@ -323,30 +319,4 @@
323
319
  this.context.connection.sendBinary(st);
324
320
  }
325
321
  }
326
-
327
-
328
- // private lastPosition: Vector3 = new Vector3();
329
-
330
- // private async setPosition(pt: Vector3) {
331
-
332
- // if (this._model.isConnected && !this._model?.hasOwnership) {
333
- // await this._model?.requestOwnershipAsync();
334
- // }
335
-
336
- // if (pt.distanceTo(this.lastPosition) < .001) {
337
- // return;
338
- // }
339
- // this.lastPosition.copy(pt);
340
-
341
- // if(this.gameObject.parent) this.gameObject.parent.worldToLocal(pt);
342
- // // this.gameObject.position.copy(pt);
343
- // this.gameObject.position.set(pt.x, pt.y, pt.z);
344
- // this._target.set(pt.x, pt.y, pt.z);
345
- // this._needsUpdate = true;
346
- // if (this.rb) {
347
- // this.gameObject.position.set(pt.x, pt.y + .5, pt.z);
348
- // this.rb.setVelocity(0, 0, 0);
349
- // this.rb.setBodyFromGameObject();
350
- // }
351
- // }
352
322
  }
src/engine-components/postprocessing/Effects/TiltShiftEffect.ts CHANGED
@@ -12,17 +12,17 @@
12
12
  }
13
13
 
14
14
  @serializable(VolumeParameter)
15
- offset!: VolumeParameter;
15
+ offset: VolumeParameter = new VolumeParameter(0);
16
16
  @serializable(VolumeParameter)
17
- rotation!: VolumeParameter;
17
+ rotation: VolumeParameter = new VolumeParameter(0);
18
18
  @serializable(VolumeParameter)
19
- focusArea!: VolumeParameter;
19
+ focusArea: VolumeParameter = new VolumeParameter(0.4);
20
20
  @serializable(VolumeParameter)
21
- feather!: VolumeParameter
21
+ feather: VolumeParameter = new VolumeParameter(0.3);
22
22
  @serializable(VolumeParameter)
23
- kernelSize!: VolumeParameter;
23
+ kernelSize: VolumeParameter = new VolumeParameter(KernelSize.MEDIUM);
24
24
  @serializable(VolumeParameter)
25
- resolutionScale!: VolumeParameter;
25
+ resolutionScale: VolumeParameter = new VolumeParameter(1 / window.devicePixelRatio);
26
26
 
27
27
  init(): void {
28
28
  this.offset.defaultValue = 0;
@@ -38,8 +38,12 @@
38
38
 
39
39
  const effect = new TiltShift({
40
40
  kernelSize: KernelSize.VERY_LARGE,
41
+ offset: this.offset.value,
42
+ rotation: this.rotation.value,
43
+ focusArea: this.focusArea.value,
44
+ feather: this.feather.value,
41
45
  });
42
-
46
+
43
47
  this.offset.onValueChanged = v => effect.offset = v;
44
48
  this.rotation.onValueChanged = v => effect.rotation = v;
45
49
  this.focusArea.onValueChanged = v => effect.focusArea = v;
src/engine-components/postprocessing/Effects/Vignette.ts CHANGED
@@ -12,13 +12,13 @@
12
12
  }
13
13
 
14
14
  @serializable(VolumeParameter)
15
- color!: VolumeParameter;
15
+ color: VolumeParameter = new VolumeParameter({ r: 0, g: 0, b: 0, a: 1 });
16
16
 
17
17
  @serializable(VolumeParameter)
18
- intensity!: VolumeParameter;
18
+ intensity: VolumeParameter = new VolumeParameter(0);
19
19
 
20
20
  @serializable(VolumeParameter)
21
- center!: VolumeParameter;
21
+ center: VolumeParameter = new VolumeParameter({ x: 0.5, y: 0.5 });
22
22
 
23
23
  init(){
24
24
  this.color.defaultValue = { r: 0, g: 0, b: 0, a: 1 };