@needle-tools/engine 2.54.2-pre → 2.55.1-pre
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 +17 -0
- package/dist/needle-engine.d.ts +39 -14
- package/dist/needle-engine.js +355 -355
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +35 -35
- package/dist/needle-engine.min.js.map +4 -4
- package/dist/needle-engine.tsbuildinfo +1 -1
- package/lib/engine/engine_lightdata.js +1 -1
- package/lib/engine/engine_lightdata.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.js +8 -0
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +1 -1
- package/lib/engine/engine_physics.js +44 -3
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics.types.d.ts +13 -0
- package/lib/engine/engine_physics.types.js +7 -0
- package/lib/engine/engine_physics.types.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +20 -10
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.js +2 -2
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_time.d.ts +1 -0
- package/lib/engine/engine_time.js +7 -0
- package/lib/engine/engine_time.js.map +1 -1
- package/lib/engine/engine_types.d.ts +4 -1
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +1 -0
- package/lib/engine/engine_utils.js +3 -0
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lightmaps.js +3 -1
- package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +1 -2
- package/lib/engine-components/Camera.js +8 -10
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +2 -0
- package/lib/engine-components/Collider.js +4 -0
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/LODGroup.js +9 -0
- package/lib/engine-components/LODGroup.js.map +1 -1
- package/lib/engine-components/OrbitControls.d.ts +8 -7
- package/lib/engine-components/OrbitControls.js +38 -7
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +1 -0
- package/lib/engine-components/ParticleSystem.js +17 -6
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +2 -2
- package/lib/engine-components/ParticleSystemModules.js +27 -21
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +1 -0
- package/lib/engine-components/Renderer.js +21 -2
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RigidBody.js +1 -19
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/SyncedTransform.js +1 -3
- package/lib/engine-components/SyncedTransform.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +2 -1
- package/lib/engine-components/VideoPlayer.js +54 -51
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.js +5 -0
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXR.js +13 -13
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRController.js +1 -2
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/js-extensions/RGBAColor.d.ts +2 -0
- package/lib/engine-components/js-extensions/RGBAColor.js +2 -0
- package/lib/engine-components/js-extensions/RGBAColor.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/engine/codegen/register_types.js +2 -2
- package/src/engine/engine_lightdata.ts +1 -1
- package/src/engine/engine_mainloop_utils.ts +6 -0
- package/src/engine/engine_physics.ts +47 -5
- package/src/engine/engine_physics.types.ts +17 -0
- package/src/engine/engine_serialization_core.ts +25 -13
- package/src/engine/engine_setup.ts +2 -2
- package/src/engine/engine_time.ts +7 -1
- package/src/engine/engine_types.ts +5 -2
- package/src/engine/engine_utils.ts +4 -0
- package/src/engine/extensions/NEEDLE_lightmaps.ts +3 -1
- package/src/engine-components/Camera.ts +10 -15
- package/src/engine-components/Collider.ts +3 -0
- package/src/engine-components/LODGroup.ts +9 -0
- package/src/engine-components/OrbitControls.ts +58 -19
- package/src/engine-components/ParticleSystem.ts +18 -6
- package/src/engine-components/ParticleSystemModules.ts +29 -22
- package/src/engine-components/Renderer.ts +25 -2
- package/src/engine-components/RigidBody.ts +1 -20
- package/src/engine-components/SyncedTransform.ts +1 -3
- package/src/engine-components/VideoPlayer.ts +55 -51
- package/src/engine-components/WebARSessionRoot.ts +5 -0
- package/src/engine-components/WebXR.ts +15 -13
- package/src/engine-components/WebXRController.ts +1 -2
- package/src/engine-components/js-extensions/RGBAColor.ts +3 -0
|
@@ -153,6 +153,7 @@ class ParticleSystemEmissionOverTime extends BaseValueGenerator {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
genValue(): number {
|
|
156
|
+
if (!this.system.emission.enabled) return 0;
|
|
156
157
|
if (this.system.currentParticles >= this.system.maxParticles) return 0;
|
|
157
158
|
// emission over time
|
|
158
159
|
let emission = this.system.emission.rateOverTime.evaluate(this.system.time / this.system.duration, Math.random());
|
|
@@ -225,9 +226,15 @@ class TextureSheetAnimationBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
225
226
|
|
|
226
227
|
}
|
|
227
228
|
|
|
229
|
+
const $particleRotation = Symbol("particleRotation")
|
|
230
|
+
|
|
228
231
|
class RotationBehaviour extends ParticleSystemBaseBehaviour {
|
|
229
232
|
type: string = "NeedleRotation"
|
|
230
233
|
|
|
234
|
+
initialize(particle: Particle) {
|
|
235
|
+
particle[$particleRotation] = Math.random();
|
|
236
|
+
}
|
|
237
|
+
|
|
231
238
|
update(particle: Particle, delta: number) {
|
|
232
239
|
if (particle.rotation === undefined) return;
|
|
233
240
|
|
|
@@ -235,7 +242,7 @@ class RotationBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
235
242
|
|
|
236
243
|
if (typeof particle.rotation === "number") {
|
|
237
244
|
if (this.system.rotationOverLifetime.enabled) {
|
|
238
|
-
particle.rotation += this.system.rotationOverLifetime.evaluate(t) * delta;
|
|
245
|
+
particle.rotation += this.system.rotationOverLifetime.evaluate(t, particle[$particleRotation]) * delta;
|
|
239
246
|
}
|
|
240
247
|
else {
|
|
241
248
|
if (this.system.renderer.renderMode === ParticleSystemRenderMode.Billboard)
|
|
@@ -548,6 +555,8 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
548
555
|
private _state?: ParticlesEmissionState;
|
|
549
556
|
emit(count: number) {
|
|
550
557
|
if (this._particleSystem) {
|
|
558
|
+
// we need to call update the matrices etc e.g. if we call emit from a physics callback
|
|
559
|
+
this.onUpdate();
|
|
551
560
|
count = Math.min(count, this.maxParticles - this.currentParticles);
|
|
552
561
|
if (!this._state) this._state = new ParticlesEmissionState();
|
|
553
562
|
this._state.waitEmiting = count;
|
|
@@ -768,6 +777,14 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
768
777
|
}
|
|
769
778
|
|
|
770
779
|
onBeforeRender() {
|
|
780
|
+
this.onUpdate();
|
|
781
|
+
const dt = this.deltaTime;
|
|
782
|
+
this._batchSystem?.update(dt);
|
|
783
|
+
this._time += dt;
|
|
784
|
+
if (this._time > this.duration) this._time = 0;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
private onUpdate() {
|
|
771
788
|
if (this._bursts) {
|
|
772
789
|
this.emission.bursts = this._bursts;
|
|
773
790
|
delete this._bursts;
|
|
@@ -796,17 +813,12 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
796
813
|
this._container.matrix.identity();
|
|
797
814
|
this._container.matrix.scale(scale);
|
|
798
815
|
}
|
|
799
|
-
|
|
800
816
|
this.emission.system = this;
|
|
801
|
-
const dt = this.deltaTime;
|
|
802
817
|
this._interface.update();
|
|
803
818
|
this.shape.update(this, this.context, this.main.simulationSpace, this.gameObject);
|
|
804
819
|
this.noise.update(this.context);
|
|
805
820
|
this.inheritVelocity?.update(this.context);
|
|
806
821
|
this.velocityOverLifetime.update(this);
|
|
807
|
-
this._batchSystem?.update(dt);
|
|
808
|
-
this._time += dt;
|
|
809
|
-
if (this._time > this.duration) this._time = 0;
|
|
810
822
|
}
|
|
811
823
|
|
|
812
824
|
private addSubParticleSystems() {
|
|
@@ -6,6 +6,11 @@ import { AnimationCurve } from "./AnimationCurve";
|
|
|
6
6
|
import { Vec2, Vec3 } from "../engine/engine_types";
|
|
7
7
|
import { Context } from "../engine/engine_setup";
|
|
8
8
|
import { EmitterShape, FrameOverLife, Particle, ShapeJSON } from "three.quarks";
|
|
9
|
+
import { createNoise4D, NoiseFunction4D } from 'simplex-noise';
|
|
10
|
+
import { Gizmos } from "../engine/engine_gizmos";
|
|
11
|
+
import { getParam } from "../engine/engine_utils";
|
|
12
|
+
|
|
13
|
+
const debug = getParam("debugparticles");
|
|
9
14
|
|
|
10
15
|
declare type Color4 = { r: number, g: number, b: number, a: number };
|
|
11
16
|
declare type ColorKey = { time: number, color: Color4 };
|
|
@@ -457,10 +462,10 @@ export class SizeOverLifetimeModule {
|
|
|
457
462
|
|
|
458
463
|
export class ShapeModule implements EmitterShape {
|
|
459
464
|
|
|
465
|
+
// Emittershape start
|
|
460
466
|
get type(): string {
|
|
461
467
|
return ParticleSystemShapeType[this.shapeType];
|
|
462
468
|
}
|
|
463
|
-
|
|
464
469
|
initialize(particle: Particle): void {
|
|
465
470
|
this.getPosition();
|
|
466
471
|
particle.position.copy(this._vector);
|
|
@@ -471,6 +476,7 @@ export class ShapeModule implements EmitterShape {
|
|
|
471
476
|
clone(): EmitterShape {
|
|
472
477
|
return new ShapeModule();
|
|
473
478
|
}
|
|
479
|
+
// EmitterShape end
|
|
474
480
|
|
|
475
481
|
@serializable()
|
|
476
482
|
shapeType: ParticleSystemShapeType = ParticleSystemShapeType.Box;
|
|
@@ -574,16 +580,12 @@ export class ShapeModule implements EmitterShape {
|
|
|
574
580
|
this.randomConePoint(this.position, this.angle, radius, this.radiusThickness, this.arc, this.arcMode, this._vector);
|
|
575
581
|
break;
|
|
576
582
|
case ParticleSystemShapeType.Sphere:
|
|
577
|
-
this.randomSpherePoint(this.position, radius, this.radiusThickness, this.arc, this._vector);
|
|
578
|
-
this._vector.x *= this.scale.x;
|
|
579
|
-
this._vector.y *= this.scale.y;
|
|
580
|
-
this._vector.z *= this.scale.z;
|
|
583
|
+
this.randomSpherePoint(this.position, radius, this.radiusThickness, this.arc, this._vector, this.scale);
|
|
581
584
|
break;
|
|
582
585
|
case ParticleSystemShapeType.Circle:
|
|
583
|
-
this.
|
|
584
|
-
this.
|
|
585
|
-
this.
|
|
586
|
-
this._vector.z *= 0;
|
|
586
|
+
this._temp.copy(this.scale);
|
|
587
|
+
this._temp.z = 0;
|
|
588
|
+
this.randomSpherePoint(this.position, radius, this.radiusThickness, this.arc, this._vector, this._temp);
|
|
587
589
|
break;
|
|
588
590
|
default:
|
|
589
591
|
this._vector.set(0, 0, 0);
|
|
@@ -600,6 +602,7 @@ export class ShapeModule implements EmitterShape {
|
|
|
600
602
|
this._vector.applyEuler(this._rotation);
|
|
601
603
|
|
|
602
604
|
if (isWorldSpace) {
|
|
605
|
+
this._vector.applyQuaternion(this.system.worldQuaternion);
|
|
603
606
|
this._vector.add(this.system.worldPos);
|
|
604
607
|
}
|
|
605
608
|
}
|
|
@@ -607,7 +610,8 @@ export class ShapeModule implements EmitterShape {
|
|
|
607
610
|
|
|
608
611
|
|
|
609
612
|
private _dir: Vector3 = new Vector3();
|
|
610
|
-
|
|
613
|
+
|
|
614
|
+
getDirection(pos: Vec3): Vector3 {
|
|
611
615
|
if (!this.enabled) {
|
|
612
616
|
this._dir.set(0, 0, 1);
|
|
613
617
|
return this._dir;
|
|
@@ -623,10 +627,11 @@ export class ShapeModule implements EmitterShape {
|
|
|
623
627
|
break;
|
|
624
628
|
case ParticleSystemShapeType.Circle:
|
|
625
629
|
case ParticleSystemShapeType.Sphere:
|
|
626
|
-
const rx =
|
|
627
|
-
const ry =
|
|
628
|
-
const rz =
|
|
629
|
-
this._dir.set(rx, ry, rz)
|
|
630
|
+
const rx = pos.x;
|
|
631
|
+
const ry = pos.y;
|
|
632
|
+
const rz = pos.z;
|
|
633
|
+
this._dir.set(rx, ry, rz)
|
|
634
|
+
this._dir.sub(this.position)
|
|
630
635
|
break;
|
|
631
636
|
default:
|
|
632
637
|
this._dir.set(0, 0, 1);
|
|
@@ -640,7 +645,10 @@ export class ShapeModule implements EmitterShape {
|
|
|
640
645
|
this._dir.normalize();
|
|
641
646
|
this.spherizeDirection(this._dir, this.sphericalDirectionAmount);
|
|
642
647
|
this.randomizeDirection(this._dir, this.randomDirectionAmount);
|
|
643
|
-
|
|
648
|
+
if (debug) {
|
|
649
|
+
Gizmos.DrawSphere(pos, .01, 0x883300, .5, true);
|
|
650
|
+
Gizmos.DrawDirection(pos, this._dir, 0x883300, .5, true);
|
|
651
|
+
}
|
|
644
652
|
return this._dir;
|
|
645
653
|
}
|
|
646
654
|
|
|
@@ -677,15 +685,15 @@ export class ShapeModule implements EmitterShape {
|
|
|
677
685
|
dir.lerp(v, amount);
|
|
678
686
|
}
|
|
679
687
|
|
|
680
|
-
private randomSpherePoint(pos: Vec3, radius: number, thickness: number, arc: number, vec: Vec3) {
|
|
688
|
+
private randomSpherePoint(pos: Vec3, radius: number, thickness: number, arc: number, vec: Vec3, scale: Vec3) {
|
|
681
689
|
const u = Math.random();
|
|
682
690
|
const v = Math.random();
|
|
683
691
|
const theta = 2 * Math.PI * u * (arc / 360);
|
|
684
692
|
const phi = Math.acos(2 * v - 1);
|
|
685
693
|
const r = Mathf.lerp(1, 1 - (Math.pow(1 - Math.random(), Math.PI)), thickness) * (radius);
|
|
686
|
-
const x = pos.x + (-r * Math.sin(phi) * Math.cos(theta));
|
|
687
|
-
const y = pos.y + (r * Math.sin(phi) * Math.sin(theta));
|
|
688
|
-
const z = pos.z + (r * Math.cos(phi));
|
|
694
|
+
const x = pos.x + scale.x * (-r * Math.sin(phi) * Math.cos(theta));
|
|
695
|
+
const y = pos.y + scale.y * (r * Math.sin(phi) * Math.sin(theta));
|
|
696
|
+
const z = pos.z + scale.z * (r * Math.cos(phi));
|
|
689
697
|
vec.x = x;
|
|
690
698
|
vec.y = y;
|
|
691
699
|
vec.z = z;
|
|
@@ -738,7 +746,6 @@ export class ShapeModule implements EmitterShape {
|
|
|
738
746
|
|
|
739
747
|
|
|
740
748
|
|
|
741
|
-
import { createNoise4D, NoiseFunction4D } from 'simplex-noise';
|
|
742
749
|
|
|
743
750
|
export class NoiseModule {
|
|
744
751
|
@serializable()
|
|
@@ -1110,10 +1117,10 @@ export class RotationOverLifetimeModule {
|
|
|
1110
1117
|
@serializable()
|
|
1111
1118
|
zMultiplier!: number;
|
|
1112
1119
|
|
|
1113
|
-
evaluate(t01: number): number {
|
|
1120
|
+
evaluate(t01: number, t:number): number {
|
|
1114
1121
|
if (!this.enabled) return 0;
|
|
1115
1122
|
if (!this.separateAxes) {
|
|
1116
|
-
const rot = this.z.evaluate(t01) * -1;
|
|
1123
|
+
const rot = this.z.evaluate(t01, t) * -1;
|
|
1117
1124
|
return rot;
|
|
1118
1125
|
}
|
|
1119
1126
|
return 0;
|
|
@@ -22,6 +22,7 @@ const debugInstancing = getParam("debuginstancing");
|
|
|
22
22
|
const debugProgressiveLoading = getParam("debugprogressive");
|
|
23
23
|
const suppressProgressiveLoading = getParam("noprogressive");
|
|
24
24
|
|
|
25
|
+
const showWireframe = getParam("wireframe");
|
|
25
26
|
|
|
26
27
|
export enum ReflectionProbeUsage {
|
|
27
28
|
Off = 0,
|
|
@@ -229,6 +230,12 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
229
230
|
|
|
230
231
|
allowProgressiveLoading: boolean = true;
|
|
231
232
|
|
|
233
|
+
registering() {
|
|
234
|
+
if (!this.enabled) {
|
|
235
|
+
this.setVisibility(false);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
232
239
|
awake() {
|
|
233
240
|
this.clearInstancingState();
|
|
234
241
|
|
|
@@ -279,15 +286,20 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
279
286
|
this._lightmaps = [];
|
|
280
287
|
|
|
281
288
|
if (type === "Mesh") {
|
|
282
|
-
|
|
289
|
+
const mat = this.gameObject["material"];
|
|
290
|
+
if (!mat?.isMeshBasicMaterial) {
|
|
283
291
|
const rm = new RendererLightmap(this.gameObject, this.context);// GameObject.addNewComponent(this.gameObject, RendererLightmap);
|
|
284
292
|
this._lightmaps.push(rm);
|
|
285
293
|
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex, debugLightmap);
|
|
286
294
|
}
|
|
295
|
+
else {
|
|
296
|
+
if (mat)
|
|
297
|
+
console.warn("Lightmapping is not supported on MeshBasicMaterial", mat.name)
|
|
298
|
+
}
|
|
287
299
|
}
|
|
288
300
|
// for multi materials we need to loop through children
|
|
289
301
|
// and then we add a lightmap renderer component to each of them
|
|
290
|
-
else if (this.isMultiMaterialObject(this.gameObject)) {
|
|
302
|
+
else if (this.isMultiMaterialObject(this.gameObject) && this.sharedMaterials.length > 0) {
|
|
291
303
|
for (const child of this.gameObject.children) {
|
|
292
304
|
if (!child["material"]?.isMeshBasicMaterial) {
|
|
293
305
|
const rm = new RendererLightmap(child as GameObject, this.context);
|
|
@@ -303,6 +315,17 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
303
315
|
}
|
|
304
316
|
}
|
|
305
317
|
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
if (showWireframe) {
|
|
321
|
+
for (let i = 0; i < this.sharedMaterials.length; i++) {
|
|
322
|
+
const mat: any = this.sharedMaterials[i];
|
|
323
|
+
if (mat) {
|
|
324
|
+
mat.wireframe = true;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
306
329
|
}
|
|
307
330
|
|
|
308
331
|
private _isInstancingEnabled: boolean = false;
|
|
@@ -359,26 +359,7 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
359
359
|
/**d
|
|
360
360
|
* @deprecated not used anymore
|
|
361
361
|
*/
|
|
362
|
-
public setBodyFromGameObject(_velocity: THREE.Vector3 | null | { x: number, y: number, z: number } = null) {
|
|
363
|
-
if (this.gameObject && !this.destroyed) {
|
|
364
|
-
// this.context.physics.updateBody(this);
|
|
365
|
-
// this._ignoreChange = true;
|
|
366
|
-
// const wp = this.worldPosition;
|
|
367
|
-
// this.body.position.set(wp.x, wp.y, wp.z);
|
|
368
|
-
// const wr = this.worldQuaternion;
|
|
369
|
-
// this.body.quaternion.set(wr.x, wr.y, wr.z, wr.w);
|
|
370
|
-
|
|
371
|
-
// if (velocity) {
|
|
372
|
-
// Rigidbody.copyVector3.set(velocity.x, velocity.y, velocity.z);
|
|
373
|
-
// this._smoothedVelocity.lerp(Rigidbody.copyVector3, this.context.time.deltaTime / .1);
|
|
374
|
-
// const sm = this._smoothedVelocity;
|
|
375
|
-
// this.body.velocity.x = sm.x;
|
|
376
|
-
// this.body.velocity.y = sm.y;
|
|
377
|
-
// this.body.velocity.z = sm.z;
|
|
378
|
-
// }
|
|
379
|
-
// this._ignoreChange = false;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
362
|
+
public setBodyFromGameObject(_velocity: THREE.Vector3 | null | { x: number, y: number, z: number } = null) { }
|
|
382
363
|
|
|
383
364
|
|
|
384
365
|
|
|
@@ -268,7 +268,6 @@ export class SyncedTransform extends Behaviour {
|
|
|
268
268
|
if (this.rb) {
|
|
269
269
|
this.rb.isKinematic = this._model.isOwned ?? false;
|
|
270
270
|
this.rb.setVelocity(0, 0, 0);
|
|
271
|
-
this.rb.setBodyFromGameObject();
|
|
272
271
|
}
|
|
273
272
|
return;
|
|
274
273
|
}
|
|
@@ -288,7 +287,6 @@ export class SyncedTransform extends Behaviour {
|
|
|
288
287
|
console.log("RESET", this.name)
|
|
289
288
|
this.gameObject.position.set(0, 1, 0);
|
|
290
289
|
this.rb.setVelocity(0, 0, 0);
|
|
291
|
-
this.rb.setBodyFromGameObject();
|
|
292
290
|
}
|
|
293
291
|
}
|
|
294
292
|
|
|
@@ -300,7 +298,7 @@ export class SyncedTransform extends Behaviour {
|
|
|
300
298
|
console.log("send update", this.context.connection.connectionId, this.guid, this.gameObject.name, this.gameObject.guid);
|
|
301
299
|
|
|
302
300
|
if (this.overridePhysics && this.rb) {
|
|
303
|
-
this.rb.setBodyFromGameObject();
|
|
301
|
+
// this.rb.setBodyFromGameObject();
|
|
304
302
|
}
|
|
305
303
|
|
|
306
304
|
this._needsUpdate = false;
|
|
@@ -73,37 +73,37 @@ export class VideoPlayer extends Behaviour {
|
|
|
73
73
|
private _playbackSpeed: number = 1;
|
|
74
74
|
@serializable()
|
|
75
75
|
get playbackSpeed(): number {
|
|
76
|
-
return this.
|
|
76
|
+
return this._videoElement?.playbackRate ?? this._playbackSpeed;
|
|
77
77
|
}
|
|
78
78
|
set playbackSpeed(val: number) {
|
|
79
79
|
this._playbackSpeed = val;
|
|
80
|
-
if (this.
|
|
81
|
-
this.
|
|
80
|
+
if (this._videoElement)
|
|
81
|
+
this._videoElement.playbackRate = val;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
private _isLooping: boolean = false;
|
|
85
85
|
get isLooping(): boolean {
|
|
86
|
-
return this.
|
|
86
|
+
return this._videoElement?.loop ?? this._isLooping;
|
|
87
87
|
}
|
|
88
88
|
@serializable()
|
|
89
89
|
set isLooping(val: boolean) {
|
|
90
90
|
this._isLooping = val;
|
|
91
|
-
if (this.
|
|
92
|
-
this.
|
|
91
|
+
if (this._videoElement)
|
|
92
|
+
this._videoElement.loop = val;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
get currentTime(): number {
|
|
96
|
-
return this.
|
|
96
|
+
return this._videoElement?.currentTime ?? this.time;
|
|
97
97
|
}
|
|
98
98
|
set currentTime(val: number) {
|
|
99
|
-
if (this.
|
|
100
|
-
this.
|
|
99
|
+
if (this._videoElement) {
|
|
100
|
+
this._videoElement.currentTime = val;
|
|
101
101
|
}
|
|
102
102
|
else this.time = val;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
get isPlaying(): boolean {
|
|
106
|
-
const video = this.
|
|
106
|
+
const video = this._videoElement;
|
|
107
107
|
if (video) {
|
|
108
108
|
return video.currentTime > 0 && !video.paused && !video.ended
|
|
109
109
|
&& video.readyState > video.HAVE_CURRENT_DATA;
|
|
@@ -112,13 +112,13 @@ export class VideoPlayer extends Behaviour {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
get crossOrigin(): string | null {
|
|
115
|
-
return this.
|
|
115
|
+
return this._videoElement?.crossOrigin ?? this._crossOrigin;
|
|
116
116
|
}
|
|
117
117
|
set crossOrigin(val: string | null) {
|
|
118
118
|
this._crossOrigin = val;
|
|
119
|
-
if (this.
|
|
120
|
-
if (val !== null) this.
|
|
121
|
-
else this.
|
|
119
|
+
if (this._videoElement) {
|
|
120
|
+
if (val !== null) this._videoElement.setAttribute("crossorigin", val);
|
|
121
|
+
else this._videoElement.removeAttribute("crossorigin");
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
@@ -126,6 +126,10 @@ export class VideoPlayer extends Behaviour {
|
|
|
126
126
|
return this._videoTexture;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
get videoElement() {
|
|
130
|
+
return this._videoElement;
|
|
131
|
+
}
|
|
132
|
+
|
|
129
133
|
private _crossOrigin: string | null = "anonymous";
|
|
130
134
|
|
|
131
135
|
private audioOutputMode: VideoAudioOutputMode = VideoAudioOutputMode.AudioSource;
|
|
@@ -134,7 +138,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
134
138
|
private clip?: string | MediaStream | null = null;
|
|
135
139
|
private url?: string | null = null;
|
|
136
140
|
|
|
137
|
-
private
|
|
141
|
+
private _videoElement: HTMLVideoElement | null = null;
|
|
138
142
|
private _videoTexture: THREE.VideoTexture | null = null;
|
|
139
143
|
private videoMaterial: Material | null = null;
|
|
140
144
|
|
|
@@ -144,12 +148,12 @@ export class VideoPlayer extends Behaviour {
|
|
|
144
148
|
setVideo(video: MediaStream) {
|
|
145
149
|
this.clip = video;
|
|
146
150
|
this.source = VideoSource.VideoClip;
|
|
147
|
-
if (!this.
|
|
151
|
+
if (!this._videoElement) this.create(true);
|
|
148
152
|
else {
|
|
149
153
|
// TODO: how to prevent interruption error when another video is already playing
|
|
150
|
-
this.
|
|
154
|
+
this._videoElement.srcObject = video;
|
|
151
155
|
if (this._isPlaying)
|
|
152
|
-
this.
|
|
156
|
+
this._videoElement.play();
|
|
153
157
|
this.updateAspect();
|
|
154
158
|
}
|
|
155
159
|
}
|
|
@@ -160,9 +164,9 @@ export class VideoPlayer extends Behaviour {
|
|
|
160
164
|
this.url = url;
|
|
161
165
|
this.source = VideoSource.Url;
|
|
162
166
|
if (debug) console.log("set url", url);
|
|
163
|
-
if (!this.
|
|
167
|
+
if (!this._videoElement) this.create(true);
|
|
164
168
|
else {
|
|
165
|
-
this.
|
|
169
|
+
this._videoElement.src = url;
|
|
166
170
|
if (this._isPlaying) {
|
|
167
171
|
this.stop();
|
|
168
172
|
this.play();
|
|
@@ -201,9 +205,9 @@ export class VideoPlayer extends Behaviour {
|
|
|
201
205
|
}
|
|
202
206
|
|
|
203
207
|
onDestroy(): void {
|
|
204
|
-
if (this.
|
|
205
|
-
this.
|
|
206
|
-
this.
|
|
208
|
+
if (this._videoElement) {
|
|
209
|
+
this._videoElement.parentElement?.removeChild(this._videoElement);
|
|
210
|
+
this._videoElement = null;
|
|
207
211
|
}
|
|
208
212
|
if (this._videoTexture) {
|
|
209
213
|
this._videoTexture.dispose();
|
|
@@ -231,27 +235,27 @@ export class VideoPlayer extends Behaviour {
|
|
|
231
235
|
}
|
|
232
236
|
|
|
233
237
|
play() {
|
|
234
|
-
if (!this.
|
|
235
|
-
if (this._isPlaying && !this.
|
|
238
|
+
if (!this._videoElement) return;
|
|
239
|
+
if (this._isPlaying && !this._videoElement?.ended && !this._videoElement?.paused) return;
|
|
236
240
|
this._isPlaying = true;
|
|
237
|
-
if (!this._receivedInput) this.
|
|
241
|
+
if (!this._receivedInput) this._videoElement.muted = true;
|
|
238
242
|
this.updateVideoElementSettings();
|
|
239
|
-
this.
|
|
243
|
+
this._videoElement?.play().catch(err => {
|
|
240
244
|
console.warn(err);
|
|
241
245
|
});
|
|
242
|
-
if (debug) console.log("play", this.
|
|
246
|
+
if (debug) console.log("play", this._videoElement);
|
|
243
247
|
}
|
|
244
248
|
|
|
245
249
|
stop() {
|
|
246
250
|
this._isPlaying = false;
|
|
247
|
-
if (!this.
|
|
248
|
-
this.
|
|
249
|
-
this.
|
|
251
|
+
if (!this._videoElement) return;
|
|
252
|
+
this._videoElement.currentTime = 0;
|
|
253
|
+
this._videoElement.pause();
|
|
250
254
|
}
|
|
251
255
|
|
|
252
256
|
pause(): void {
|
|
253
257
|
this._isPlaying = false;
|
|
254
|
-
this.
|
|
258
|
+
this._videoElement?.pause();
|
|
255
259
|
}
|
|
256
260
|
|
|
257
261
|
|
|
@@ -270,23 +274,23 @@ export class VideoPlayer extends Behaviour {
|
|
|
270
274
|
|
|
271
275
|
// console.log(src, this);
|
|
272
276
|
|
|
273
|
-
if (!this.
|
|
274
|
-
this.
|
|
275
|
-
this.context.domElement?.prepend(this.
|
|
277
|
+
if (!this._videoElement) {
|
|
278
|
+
this._videoElement = this.createVideoElement();
|
|
279
|
+
this.context.domElement?.prepend(this._videoElement);
|
|
276
280
|
// hide it because otherwise it would overlay the website with default css
|
|
277
281
|
this.updateVideoElementStyles();
|
|
278
282
|
}
|
|
279
283
|
if (typeof src === "string") {
|
|
280
|
-
this.
|
|
281
|
-
const str = this.
|
|
284
|
+
this._videoElement.src = src;
|
|
285
|
+
const str = this._videoElement["captureStream"]?.call(this._videoElement);
|
|
282
286
|
this.clip = str;
|
|
283
287
|
}
|
|
284
288
|
else
|
|
285
|
-
this.
|
|
289
|
+
this._videoElement.srcObject = src;
|
|
286
290
|
|
|
287
291
|
|
|
288
292
|
if (!this._videoTexture)
|
|
289
|
-
this._videoTexture = new THREE.VideoTexture(this.
|
|
293
|
+
this._videoTexture = new THREE.VideoTexture(this._videoElement);
|
|
290
294
|
this._videoTexture.flipY = false;
|
|
291
295
|
this._videoTexture.encoding = THREE.sRGBEncoding;
|
|
292
296
|
this.handleBeginPlaying(playAutomatically);
|
|
@@ -327,7 +331,7 @@ export class VideoPlayer extends Behaviour {
|
|
|
327
331
|
|
|
328
332
|
private handleBeginPlaying(playAutomatically: boolean) {
|
|
329
333
|
if (!this.enabled) return;
|
|
330
|
-
if (!this.
|
|
334
|
+
if (!this._videoElement) return;
|
|
331
335
|
|
|
332
336
|
this._targetObjects.length = 0;
|
|
333
337
|
|
|
@@ -385,24 +389,24 @@ export class VideoPlayer extends Behaviour {
|
|
|
385
389
|
}
|
|
386
390
|
|
|
387
391
|
private updateVideoElementSettings() {
|
|
388
|
-
if (!this.
|
|
389
|
-
this.
|
|
390
|
-
this.
|
|
391
|
-
this.
|
|
392
|
+
if (!this._videoElement) return;
|
|
393
|
+
this._videoElement.loop = this._isLooping;
|
|
394
|
+
this._videoElement.currentTime = this.currentTime;
|
|
395
|
+
this._videoElement.playbackRate = this._playbackSpeed;
|
|
392
396
|
// dont open in fullscreen on ios
|
|
393
|
-
this.
|
|
394
|
-
this.
|
|
397
|
+
this._videoElement.playsInline = true;
|
|
398
|
+
this._videoElement.muted = !this._receivedInput && this.audioOutputMode !== VideoAudioOutputMode.None;
|
|
395
399
|
if (this.playOnAwake || this.playOnEnable)
|
|
396
|
-
this.
|
|
400
|
+
this._videoElement.autoplay = true;
|
|
397
401
|
}
|
|
398
402
|
|
|
399
403
|
private updateVideoElementStyles() {
|
|
400
|
-
if (!this.
|
|
404
|
+
if (!this._videoElement) return;
|
|
401
405
|
// set style here so preview frame is rendered
|
|
402
406
|
// set display and selectable because otherwise is interfers with input/focus e.g. breaks orbit control
|
|
403
|
-
this.
|
|
404
|
-
this.
|
|
405
|
-
this.
|
|
407
|
+
this._videoElement.style.userSelect = "none";
|
|
408
|
+
this._videoElement.style.visibility = "hidden";
|
|
409
|
+
this._videoElement.style.display = "none";
|
|
406
410
|
this.updateAspect();
|
|
407
411
|
}
|
|
408
412
|
|
|
@@ -92,6 +92,9 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
92
92
|
placeAt(rig: Object3D | null, mat: Matrix4) {
|
|
93
93
|
if (!this._placementPose) this._placementPose = new Matrix4();
|
|
94
94
|
this._placementPose.copy(mat);
|
|
95
|
+
// apply session root offset
|
|
96
|
+
const invertedSessionRoot = this.gameObject.matrixWorld.clone().invert();
|
|
97
|
+
this._placementPose.premultiply(invertedSessionRoot);
|
|
95
98
|
if (rig) {
|
|
96
99
|
|
|
97
100
|
if (this.invertForward) {
|
|
@@ -146,9 +149,11 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
146
149
|
if (!rig || !this._placementPose) {
|
|
147
150
|
return;
|
|
148
151
|
}
|
|
152
|
+
// Capture the rig position before the first time we move it during a session
|
|
149
153
|
if (!this._rigStartPose) {
|
|
150
154
|
this._rigStartPose = rig.matrix.clone();
|
|
151
155
|
}
|
|
156
|
+
// we apply the transform to the rig because we want to move the user's position for easy networking
|
|
152
157
|
rig.matrixAutoUpdate = false;
|
|
153
158
|
rig.matrix.multiplyMatrices(new Matrix4().makeScale(scale, scale, scale), this._placementPose);
|
|
154
159
|
rig.matrix.decompose(rig.position, rig.quaternion, rig.scale);
|
|
@@ -143,6 +143,7 @@ export class WebXR extends Behaviour {
|
|
|
143
143
|
return this.rig;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
|
|
146
147
|
private controllers: WebXRController[] = [];
|
|
147
148
|
public get Controllers(): WebXRController[] {
|
|
148
149
|
return this.controllers;
|
|
@@ -249,17 +250,21 @@ export class WebXR extends Behaviour {
|
|
|
249
250
|
// TODO: figure out why screen is black if we enable the code written here
|
|
250
251
|
// const referenceSpace = renderer.xr.getReferenceSpace();
|
|
251
252
|
const session = this.context.renderer.xr.getSession();
|
|
253
|
+
|
|
252
254
|
|
|
253
255
|
if (session) {
|
|
254
256
|
const pose = frame.getViewerPose(this.context.renderer.xr.getReferenceSpace());
|
|
257
|
+
if(!pose) return;
|
|
255
258
|
this._currentHeadPose = pose;
|
|
256
|
-
if (!pose) return; // e.g. if user is not wearing headset
|
|
257
259
|
const transform: XRRigidTransform = pose?.transform;
|
|
258
|
-
|
|
259
260
|
if (transform) {
|
|
260
261
|
this._transformOrientation.set(transform.orientation.x, transform.orientation.y, transform.orientation.z, transform.orientation.w);
|
|
261
262
|
}
|
|
262
263
|
|
|
264
|
+
if (WebXR._isInXr === false && session) {
|
|
265
|
+
this.onEnterXR(session, frame);
|
|
266
|
+
}
|
|
267
|
+
|
|
263
268
|
for (const ctrl of this.controllers) {
|
|
264
269
|
ctrl.onUpdate(session);
|
|
265
270
|
}
|
|
@@ -269,9 +274,6 @@ export class WebXR extends Behaviour {
|
|
|
269
274
|
}
|
|
270
275
|
}
|
|
271
276
|
|
|
272
|
-
if (WebXR._isInXr === false && session) {
|
|
273
|
-
this.onEnterXR(session, frame);
|
|
274
|
-
}
|
|
275
277
|
WebXR.events.dispatchEvent({ type: WebXREvent.XRUpdate, frame: frame, xr: this.context.renderer.xr, rig: this.rig });
|
|
276
278
|
}
|
|
277
279
|
|
|
@@ -329,7 +331,7 @@ export class WebXR extends Behaviour {
|
|
|
329
331
|
if (xrRig) {
|
|
330
332
|
// make it match unity forward
|
|
331
333
|
this.rig = xrRig.gameObject;
|
|
332
|
-
this.rig.rotateY(Math.PI);
|
|
334
|
+
// this.rig.rotateY(Math.PI);
|
|
333
335
|
// this.rig.position.copy(existing.worldPosition);
|
|
334
336
|
// this.rig.quaternion.premultiply(existing.worldQuaternion);
|
|
335
337
|
}
|
|
@@ -577,7 +579,7 @@ export class WebAR {
|
|
|
577
579
|
this.reticleParent.name = "AR Reticle Parent";
|
|
578
580
|
this.reticleParent.matrixAutoUpdate = false;
|
|
579
581
|
this.reticleParent.add(this.reticle);
|
|
580
|
-
this.reticleParent.matrix.copy(this.sessionRoot.gameObject.matrixWorld);
|
|
582
|
+
// this.reticleParent.matrix.copy(this.sessionRoot.gameObject.matrixWorld);
|
|
581
583
|
|
|
582
584
|
if (this.webxr.scene) {
|
|
583
585
|
this.context.scene.add(this.reticleParent);
|
|
@@ -632,11 +634,11 @@ export class WebAR {
|
|
|
632
634
|
this.didPlaceARSessionRoot = true;
|
|
633
635
|
const rig = this.webxr.Rig;
|
|
634
636
|
const placementMatrix = arPlacementWithoutHitTestMatrix.clone();
|
|
635
|
-
if (rig) {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
}
|
|
637
|
+
// if (rig) {
|
|
638
|
+
// const positionFromRig = new Vector3(0, 0, 0).add(rig.position).divideScalar(this.sessionRoot?.arScale ?? 1);
|
|
639
|
+
// placementMatrix.multiply(new Matrix4().makeTranslation(positionFromRig.x, positionFromRig.y, positionFromRig.z));
|
|
640
|
+
// // placementMatrix.setPosition(positionFromRig);
|
|
641
|
+
// }
|
|
640
642
|
this.sessionRoot?.placeAt(rig, placementMatrix);
|
|
641
643
|
}
|
|
642
644
|
return;
|
|
@@ -676,4 +678,4 @@ export class WebAR {
|
|
|
676
678
|
}
|
|
677
679
|
}
|
|
678
680
|
|
|
679
|
-
const arPlacementWithoutHitTestMatrix = new Matrix4().identity().makeTranslation(0,
|
|
681
|
+
const arPlacementWithoutHitTestMatrix = new Matrix4().identity().makeTranslation(0, 0, 0);
|