Needle Engine

Changes between version 3.10.1-beta and 3.10.2-beta
Files changed (4) hide show
  1. src/engine/engine_input.ts +2 -2
  2. src/engine-components/Renderer.ts +1 -1
  3. src/engine-components/RendererLightmap.ts +13 -17
  4. src/engine-components/webxr/WebXRController.ts +101 -80
src/engine/engine_input.ts CHANGED
@@ -529,10 +529,10 @@
529
529
  if (evt.pointerType === PointerType.Mouse) {
530
530
  const upTime = this._pointerUpTimestamp[evt.button];
531
531
  if (upTime > 0 && evt.source?.timeStamp !== undefined) {
532
- const diff = (upTime - evt.source.timeStamp);
532
+ const diff = (evt.source.timeStamp - upTime);
533
533
  // on android touch up and mouse up have the exact same value
534
534
  // but on iOS they are not the same but a few milliseconds apart
535
- if (diff < 30 && diff > 0) {
535
+ if (diff < 60 && diff >= 0) {
536
536
  // we received an UP event for a touch, ignore this DOWN event
537
537
  if (debug) console.log("Ignoring mouse.down for touch.up");
538
538
  return;
src/engine-components/Renderer.ts CHANGED
@@ -317,9 +317,9 @@
317
317
  }
318
318
  return null;
319
319
  }
320
+ /** set undefined to return to default lightmap */
320
321
  public set lightmap(tex: Texture | null | undefined) {
321
322
  this._lightmapTextureOverride = tex;
322
- // set undefined to return to default
323
323
  if (tex === undefined) {
324
324
  tex = this.context.lightmaps.tryGetLightmap(this.sourceId, this.lightmapIndex);
325
325
  }
src/engine-components/RendererLightmap.ts CHANGED
@@ -20,8 +20,8 @@
20
20
  }
21
21
  }
22
22
 
23
- lightmapIndex: number = -1;
24
- lightmapScaleOffset: THREE.Vector4 = new Vector4(1, 1, 0, 0);
23
+ private lightmapIndex: number = -1;
24
+ private lightmapScaleOffset: THREE.Vector4 = new Vector4(1, 1, 0, 0);
25
25
 
26
26
  private context: Context;
27
27
  private gameObject: Mesh;
@@ -50,8 +50,6 @@
50
50
  const uniforms = material["uniforms"];
51
51
  if (uniforms && uniforms.lightmap) {
52
52
  this.lightmapScaleOffsetUniform.value = this.lightmapScaleOffset;
53
- this.lightmapUniform.value = this.lightmapTexture;
54
- uniforms.lightmap = this.lightmapUniform;
55
53
  uniforms.lightmapScaleOffset = this.lightmapScaleOffsetUniform;
56
54
  }
57
55
  }
@@ -90,24 +88,22 @@
90
88
  this.gameObject.material.onBeforeCompile = this.onBeforeCompile;
91
89
  }
92
90
 
93
- if (this.lightmapIndex >= 0) {
94
- const lightmap = this.lightmapTexture;
91
+ if (this.lightmapIndex >= 0 && this.lightmapTexture) {
95
92
  const mat = this.gameObject.material as any;
96
- if (mat && lightmap) {
97
- if (!mat.uniforms) mat.uniforms = {};
98
- mat.lightMap = lightmap;
99
- mat.uniforms.lightmap = { value: lightmap };
93
+ if (mat) {
94
+ mat.lightMap = this.lightmapTexture;
95
+ mat.needsUpdate = true;
100
96
  }
101
97
  }
102
98
  }
103
99
 
104
100
  private onBeforeCompile = (shader: Shader, _) => {
105
- if(debug) console.log("Lightmaps, before compile")
101
+ if (debug) console.log("Lightmaps, before compile", shader)
106
102
  //@ts-ignore
107
103
  shader.lightMapUv = "uv1";
108
104
  this.lightmapScaleOffsetUniform.value = this.lightmapScaleOffset;
109
105
  this.lightmapUniform.value = this.lightmapTexture;
110
- shader.uniforms.lightmap = this.lightmapUniform;
106
+ // shader.uniforms.lightmap = this.lightmapUniform;
111
107
  shader.uniforms.lightmapScaleOffset = this.lightmapScaleOffsetUniform;
112
108
  }
113
109
 
@@ -124,7 +120,7 @@
124
120
  }
125
121
  `,
126
122
  fragmentShader: `
127
- uniform sampler2D lightmap;
123
+ uniform sampler2D lightMap;
128
124
  uniform float lightMapIntensity;
129
125
  uniform vec4 lightmapScaleOffset;
130
126
  varying vec2 vUv1;
@@ -137,11 +133,11 @@
137
133
  void main() {
138
134
  vec2 lUv = vUv1.xy * lightmapScaleOffset.xy + vec2(lightmapScaleOffset.z, (1. - (lightmapScaleOffset.y + lightmapScaleOffset.w)));
139
135
 
140
- vec4 lightMapTexel = texture2D( lightmap, lUv);
136
+ vec4 lightMapTexel = texture2D( lightMap, lUv);
141
137
  // The range of RGBM lightmaps goes from 0 to 34.49 (5^2.2) in linear space, and from 0 to 5 in gamma space.
142
- //lightMapTexel.rgb *= lightMapTexel.a * 8.; // no idea where that "8" comes from... heuristically derived
143
- //lightMapTexel.a = 1.;
144
- //lightMapTexel = conv_sRGBToLinear(lightMapTexel);
138
+ // lightMapTexel.rgb *= lightMapTexel.a * 8.; // no idea where that "8" comes from... heuristically derived
139
+ // lightMapTexel.a = 1.;
140
+ // lightMapTexel = conv_sRGBToLinear(lightMapTexel);
145
141
  // lightMapTexel.rgb = vec3(1.);
146
142
 
147
143
  // gl_FragColor = vec4(vUv1.xy, 0, 1);
src/engine-components/webxr/WebXRController.ts CHANGED
@@ -18,6 +18,7 @@
18
18
  import { SyncedTransform } from "../SyncedTransform";
19
19
  import { UIRaycastUtils } from "../ui/RaycastUtils";
20
20
  import { WebXR } from "./WebXR";
21
+ import { XRRig } from "./WebXRRig";
21
22
 
22
23
  const debug = getParam("debugwebxrcontroller");
23
24
 
@@ -165,7 +166,7 @@
165
166
  public grabbed: AttachedObject | null = null;
166
167
  public input: XRInputSource | null = null;
167
168
  public type: ControllerType = ControllerType.PhysicalDevice;
168
- public showRaycastLine : boolean = true;
169
+ public showRaycastLine: boolean = true;
169
170
 
170
171
  get isUsingHands(): boolean {
171
172
  const r = this.input?.hand;
@@ -353,6 +354,33 @@
353
354
 
354
355
  rayRotation: Quaternion = new Quaternion();
355
356
 
357
+ private raycastUpdate(raycastLine: Line, wp: Vector3) {
358
+ const allowRaycastLineVisible = this.showRaycastLine && this.type !== ControllerType.Touch;
359
+ if (this.type === ControllerType.Touch) {
360
+ raycastLine.visible = false;
361
+ }
362
+ else if (this.isUsingHands) {
363
+ raycastLine.visible = !this.grabbed && allowRaycastLineVisible;
364
+ setWorldPosition(raycastLine, wp);
365
+ const jnts = this.hand!['joints'];
366
+ if (jnts) {
367
+ const wrist = jnts['wrist'];
368
+ if (wrist && this.grabbed && this.grabbed.isCloseGrab) {
369
+ const wr = this.getWristQuaternion();
370
+ if (wr)
371
+ this.rayRotation.copy(wr);
372
+ // this.rayRotation.slerp(wr, this.useSmoothing ? t * 2 : 1);
373
+ }
374
+ }
375
+ setWorldQuaternion(raycastLine, this.rayRotation);
376
+ }
377
+ else {
378
+ raycastLine.visible = allowRaycastLineVisible;
379
+ setWorldQuaternion(raycastLine, this.rayRotation);
380
+ setWorldPosition(raycastLine, wp);
381
+ }
382
+ }
383
+
356
384
  update(): void {
357
385
 
358
386
  // TODO: we should wait until we actually have models, this is just a workaround
@@ -381,30 +409,7 @@
381
409
  }
382
410
 
383
411
  if (this.raycastLine) {
384
- const allowRaycastLineVisible = this.showRaycastLine && this.type !== ControllerType.Touch;
385
- if (this.type === ControllerType.Touch) {
386
- this.raycastLine.visible = false;
387
- }
388
- else if (this.isUsingHands) {
389
- this.raycastLine.visible = !this.grabbed && allowRaycastLineVisible;
390
- setWorldPosition(this.raycastLine, wp);
391
- const jnts = this.hand!['joints'];
392
- if (jnts) {
393
- const wrist = jnts['wrist'];
394
- if (wrist && this.grabbed && this.grabbed.isCloseGrab) {
395
- const wr = this.getWristQuaternion();
396
- if (wr)
397
- this.rayRotation.copy(wr);
398
- // this.rayRotation.slerp(wr, this.useSmoothing ? t * 2 : 1);
399
- }
400
- }
401
- setWorldQuaternion(this.raycastLine, this.rayRotation);
402
- }
403
- else {
404
- this.raycastLine.visible = allowRaycastLineVisible;
405
- setWorldQuaternion(this.raycastLine, this.rayRotation);
406
- setWorldPosition(this.raycastLine, wp);
407
- }
412
+ this.raycastUpdate(this.raycastLine, wp);
408
413
  }
409
414
 
410
415
  this.lastHit = this.updateLastHit();
@@ -420,8 +425,6 @@
420
425
  }
421
426
  }
422
427
 
423
- private _pinchStartTime: number | undefined = undefined;
424
-
425
428
  onUpdate(session: XRSession) {
426
429
  this.lastHit = null;
427
430
 
@@ -446,52 +449,61 @@
446
449
 
447
450
  switch (this.input.handedness) {
448
451
  case "left":
449
- const speedFactor = 3 * WebXRController.MovementSpeedFactor;
450
- const powFactor = 2;
451
- const speed = Mathf.clamp01(this.joystick.length() * 2);
452
+ this.movementUpdate(rig, buttons);
453
+ break;
452
454
 
453
- const sideDir = this.joystick.x > 0 ? 1 : -1;
454
- let side = Math.pow(this.joystick.x, powFactor);
455
- side *= sideDir;
456
- side *= speed;
455
+ case "right":
456
+ this.rotationUpdate(rig, buttons);
457
+ break;
458
+ }
459
+ }
457
460
 
458
461
 
459
- const forwardDir = this.joystick.y > 0 ? 1 : -1;
460
- let forward = Math.pow(this.joystick.y, powFactor);
461
- forward *= forwardDir;
462
- side *= speed;
462
+ private movementUpdate(rig: Object3D, buttons?: readonly GamepadButton[]) {
463
+ const speedFactor = 3 * WebXRController.MovementSpeedFactor;
464
+ const powFactor = 2;
465
+ const speed = Mathf.clamp01(this.joystick.length() * 2);
463
466
 
464
- rig.getWorldQuaternion(this.worldRot);
465
- this.movementVector.set(side, 0, forward);
466
- this.movementVector.applyQuaternion(this.webXR.TransformOrientation);
467
- this.movementVector.y = 0;
468
- this.movementVector.applyQuaternion(this.worldRot);
469
- this.movementVector.multiplyScalar(speedFactor * this.context.time.deltaTime);
470
- rig.position.add(this.movementVector);
467
+ const sideDir = this.joystick.x > 0 ? 1 : -1;
468
+ let side = Math.pow(this.joystick.x, powFactor);
469
+ side *= sideDir;
470
+ side *= speed;
471
471
 
472
- if (this.isUsingHands)
473
- this.runTeleport(rig, buttons);
474
- break;
475
472
 
476
- case "right":
477
- const rotate = this.joystick.x;
478
- const rotAbs = Math.abs(rotate);
479
- if (rotAbs < 0.4) {
480
- this.didRotate = false;
481
- }
482
- else if (rotAbs > .5 && !this.didRotate) {
483
- const dir = rotate > 0 ? -1 : 1;
484
- rig.rotateY(Mathf.toRadians(30 * dir));
485
- this.didRotate = true;
486
- }
473
+ const forwardDir = this.joystick.y > 0 ? 1 : -1;
474
+ let forward = Math.pow(this.joystick.y, powFactor);
475
+ forward *= forwardDir;
476
+ side *= speed;
487
477
 
488
- this.runTeleport(rig, buttons);
478
+ rig.getWorldQuaternion(this.worldRot);
479
+ this.movementVector.set(side, 0, forward);
480
+ this.movementVector.applyQuaternion(this.webXR.TransformOrientation);
481
+ this.movementVector.y = 0;
482
+ this.movementVector.applyQuaternion(this.worldRot);
483
+ this.movementVector.multiplyScalar(speedFactor * this.context.time.deltaTime);
484
+ rig.position.add(this.movementVector);
489
485
 
490
- break;
486
+ if (this.isUsingHands)
487
+ this.runTeleport(rig, buttons);
488
+ }
489
+
490
+ private rotationUpdate(rig: Object3D, buttons?: readonly GamepadButton[]) {
491
+ const rotate = this.joystick.x;
492
+ const rotAbs = Math.abs(rotate);
493
+ if (rotAbs < 0.4) {
494
+ this.didRotate = false;
491
495
  }
496
+ else if (rotAbs > .5 && !this.didRotate) {
497
+ const dir = rotate > 0 ? -1 : 1;
498
+ rig.rotateY(Mathf.toRadians(30 * dir));
499
+ this.didRotate = true;
500
+ }
501
+
502
+ this.runTeleport(rig, buttons);
492
503
  }
504
+ private _pinchStartTime: number | undefined = undefined;
493
505
 
494
- private runTeleport(rig, buttons) {
506
+ private runTeleport(rig: Object3D, buttons?: readonly GamepadButton[]) {
495
507
  let teleport = -this.joystick.y;
496
508
  if (this.hand?.visible && !this.grabbed) {
497
509
  const pinched = this.handPointerModel.isPinched();
@@ -526,24 +538,10 @@
526
538
  this.didChangeScale = true;
527
539
  const rig = this.webXR.Rig;
528
540
  if (rig) {
529
- if (!isInMiniatureMode) {
530
- isInMiniatureMode = true;
531
- doTeleport = true;
532
- newRigScale = .1;
533
- WebXRController.MovementSpeedFactor = newRigScale * 2;
534
- const cam = this.context.mainCamera as PerspectiveCamera;
535
- WebXRController.PreviousCameraFarDistance = cam.far;
536
- cam.far /= newRigScale;
537
- }
538
- else {
539
- isInMiniatureMode = false;
540
- rig.scale.set(1, 1, 1);
541
- newRigScale = 1;
542
- WebXRController.MovementSpeedFactor = 1;
543
- const cam = this.context.mainCamera as PerspectiveCamera;
544
- if (WebXRController.PreviousCameraFarDistance)
545
- cam.far = WebXRController.PreviousCameraFarDistance;
546
- }
541
+ let args = this.switchScale(rig, doTeleport, isInMiniatureMode, newRigScale);
542
+ doTeleport = args.doTeleport;
543
+ isInMiniatureMode = args.isInMiniatureMode;
544
+ newRigScale = args.newRigScale;
547
545
  }
548
546
  }
549
547
  else if (!btn.pressed)
@@ -575,10 +573,33 @@
575
573
  }
576
574
  }
577
575
 
576
+
578
577
  private isValidTeleportTarget(obj: Object3D): boolean {
579
578
  return GameObject.getComponentInParent(obj, TeleportTarget) != null;
580
579
  }
581
580
 
581
+ private switchScale(rig: Object3D, doTeleport: boolean, isInMiniatureMode: boolean, newRigScale: number | null) {
582
+ if (!isInMiniatureMode) {
583
+ isInMiniatureMode = true;
584
+ doTeleport = true;
585
+ newRigScale = .1;
586
+ WebXRController.MovementSpeedFactor = newRigScale * 2;
587
+ const cam = this.context.mainCamera as PerspectiveCamera;
588
+ WebXRController.PreviousCameraFarDistance = cam.far;
589
+ cam.far /= newRigScale;
590
+ }
591
+ else {
592
+ isInMiniatureMode = false;
593
+ rig.scale.set(1, 1, 1);
594
+ newRigScale = 1;
595
+ WebXRController.MovementSpeedFactor = 1;
596
+ const cam = this.context.mainCamera as PerspectiveCamera;
597
+ if (WebXRController.PreviousCameraFarDistance)
598
+ cam.far = WebXRController.PreviousCameraFarDistance;
599
+ }
600
+ return { doTeleport, isInMiniatureMode, newRigScale }
601
+ }
602
+
582
603
  private updateStick(inputSource: XRInputSource) {
583
604
  if (!inputSource || !inputSource.gamepad || inputSource.gamepad.axes?.length < 4) return;
584
605
  this.joystick.x = inputSource.gamepad.axes[2];