@needle-tools/engine 3.9.0-alpha → 3.9.1-alpha
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 +12 -1
- package/dist/needle-engine.js +1 -1
- package/dist/needle-engine.light.js +1 -1
- package/dist/needle-engine.light.min.js +1 -1
- package/dist/needle-engine.light.umd.cjs +1 -1
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/engine_element_overlay.js +9 -2
- package/lib/engine/engine_element_overlay.js.map +1 -1
- package/lib/engine/engine_loaders.js.map +1 -1
- package/lib/engine-components/Camera.js +3 -1
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/ParticleSystem.js +15 -14
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.d.ts +5 -0
- package/lib/engine-components/SceneSwitcher.js +25 -2
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.js +8 -2
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/package.json +2 -2
- package/plugins/vite/vite-4.4-hack.js +15 -22
- package/src/engine/engine_element_overlay.ts +9 -2
- package/src/engine/engine_loaders.ts +1 -1
- package/src/engine-components/Camera.ts +6 -3
- package/src/engine-components/ParticleSystem.ts +16 -13
- package/src/engine-components/SceneSwitcher.ts +24 -2
- package/src/engine-components/webxr/WebXR.ts +19 -14
|
@@ -13,7 +13,7 @@ const DEFAULT_DRACO_DECODER_LOCATION ='https://www.gstatic.com/draco/versioned/d
|
|
|
13
13
|
const DEFAULT_KTX2_TRANSCODER_LOCATION ='https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/';
|
|
14
14
|
|
|
15
15
|
let dracoLoader: DRACOLoader;
|
|
16
|
-
let meshoptDecoder: MeshoptDecoder;
|
|
16
|
+
let meshoptDecoder: typeof MeshoptDecoder;
|
|
17
17
|
let ktx2Loader: KTX2Loader;
|
|
18
18
|
|
|
19
19
|
export function setDracoDecoderPath(path: string | undefined) {
|
|
@@ -40,7 +40,7 @@ export class Camera extends Behaviour implements ICamera {
|
|
|
40
40
|
}
|
|
41
41
|
@serializable()
|
|
42
42
|
set fieldOfView(val: number | undefined) {
|
|
43
|
-
const changed = this.
|
|
43
|
+
const changed = this.fieldOfView != val;
|
|
44
44
|
this._fov = val;
|
|
45
45
|
if (changed && this._cam) {
|
|
46
46
|
if (this._cam instanceof PerspectiveCamera) {
|
|
@@ -300,8 +300,11 @@ export class Camera extends Behaviour implements ICamera {
|
|
|
300
300
|
if (debug) console.log("Camera does not exist (apply clear flags)")
|
|
301
301
|
return;
|
|
302
302
|
}
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
|
|
304
|
+
// restore previous fov (e.g. when user was in VR or AR and the camera's fov has changed)
|
|
305
|
+
this.fieldOfView = this._fov;
|
|
306
|
+
|
|
307
|
+
if (debug) showBalloonMessage("apply Camera clear flags: " + this._clearFlags);
|
|
305
308
|
switch (this._clearFlags) {
|
|
306
309
|
case ClearFlags.Skybox:
|
|
307
310
|
if (Camera.backgroundShouldBeTransparent(this.context)) {
|
|
@@ -75,7 +75,7 @@ export class ParticleSystemRenderer extends Behaviour {
|
|
|
75
75
|
|
|
76
76
|
if (!ParticleSystemRenderer._havePatchedQuarkShaders) {
|
|
77
77
|
ParticleSystemRenderer._havePatchedQuarkShaders = true;
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
// HACK patch three.quarks fo three152+, see https://github.com/Alchemist0823/three.quarks/issues/56#issuecomment-1560825038
|
|
80
80
|
const _rebuild = TrailBatch.prototype.rebuildMaterial;
|
|
81
81
|
TrailBatch.prototype.rebuildMaterial = function () {
|
|
@@ -130,13 +130,17 @@ export class ParticleSystemRenderer extends Behaviour {
|
|
|
130
130
|
class MinMaxCurveFunction implements FunctionValueGenerator {
|
|
131
131
|
|
|
132
132
|
private _curve: MinMaxCurve;
|
|
133
|
+
private _factor: number;
|
|
133
134
|
|
|
134
|
-
constructor(curve: MinMaxCurve
|
|
135
|
+
constructor(curve: MinMaxCurve, factor: number = 1) {
|
|
136
|
+
this._curve = curve;
|
|
137
|
+
this._factor = factor;
|
|
138
|
+
}
|
|
135
139
|
|
|
136
140
|
type: "function" = "function";
|
|
137
141
|
|
|
138
142
|
genValue(t: number): number {
|
|
139
|
-
return this._curve.evaluate(t, Math.random());
|
|
143
|
+
return this._curve.evaluate(t, Math.random()) * this._factor;
|
|
140
144
|
}
|
|
141
145
|
toJSON(): FunctionJSON {
|
|
142
146
|
throw new Error("Method not implemented.");
|
|
@@ -416,7 +420,7 @@ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
416
420
|
initialize(particle: Particle): void {
|
|
417
421
|
const simulationSpeed = this.system.main.simulationSpeed;
|
|
418
422
|
|
|
419
|
-
const factor = 1
|
|
423
|
+
const factor = 1;
|
|
420
424
|
particle.startSpeed = this.system.main.startSpeed.evaluate(Math.random(), Math.random()) * factor;
|
|
421
425
|
particle.velocity.copy(this.system.shape.getDirection(particle.position)).multiplyScalar(particle.startSpeed);
|
|
422
426
|
if (this.system.inheritVelocity?.enabled) {
|
|
@@ -425,16 +429,16 @@ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
425
429
|
if (!particle[$startVelocity]) particle[$startVelocity] = particle.velocity.clone();
|
|
426
430
|
else particle[$startVelocity].copy(particle.velocity);
|
|
427
431
|
|
|
428
|
-
const gravityFactor = this.system.main.gravityModifier.evaluate(Math.random(), Math.random())
|
|
432
|
+
const gravityFactor = this.system.main.gravityModifier.evaluate(Math.random(), Math.random());
|
|
429
433
|
particle[$gravityFactor] = gravityFactor * simulationSpeed;
|
|
430
|
-
particle[$gravitySpeed] =
|
|
434
|
+
particle[$gravitySpeed] = gravityFactor * simulationSpeed * .5
|
|
431
435
|
|
|
432
436
|
particle[$velocityLerpFactor] = Math.random();
|
|
433
437
|
this.system.velocityOverLifetime?.init(particle);
|
|
434
438
|
|
|
435
439
|
this._gravityDirection.set(0, -1, 0);
|
|
436
440
|
if (this.system.main.simulationSpace === ParticleSystemSimulationSpace.Local)
|
|
437
|
-
this._gravityDirection.applyQuaternion(this.system.worldQuaternionInverted);
|
|
441
|
+
this._gravityDirection.applyQuaternion(this.system.worldQuaternionInverted).normalize();
|
|
438
442
|
}
|
|
439
443
|
|
|
440
444
|
update(particle: Particle, delta: number): void {
|
|
@@ -444,10 +448,9 @@ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
444
448
|
const baseVelocity = particle[$startVelocity];
|
|
445
449
|
let gravityFactor = particle[$gravityFactor];
|
|
446
450
|
if (gravityFactor !== 0) {
|
|
447
|
-
|
|
448
|
-
temp3.copy(this._gravityDirection).multiplyScalar(
|
|
449
|
-
particle[$gravitySpeed] += delta;
|
|
450
|
-
if (debug) Gizmos.DrawDirection(particle.position, temp3, 0x0000ff, 0, false, 10);
|
|
451
|
+
const factor = gravityFactor * particle[$gravitySpeed];
|
|
452
|
+
temp3.copy(this._gravityDirection).multiplyScalar(factor);
|
|
453
|
+
particle[$gravitySpeed] += delta * .05;
|
|
451
454
|
baseVelocity.add(temp3);
|
|
452
455
|
}
|
|
453
456
|
particle.velocity.copy(baseVelocity);
|
|
@@ -931,10 +934,10 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
931
934
|
const duration = this.main.duration;
|
|
932
935
|
const lifetime = this.main.startLifetime.getMax();
|
|
933
936
|
const maxDurationToPrewarm = 1000;
|
|
934
|
-
const timeToSimulate = Math.min(duration, lifetime, maxDurationToPrewarm);
|
|
937
|
+
const timeToSimulate = Math.min(Math.max(duration, lifetime) / Math.max(.01, this.main.simulationSpeed), maxDurationToPrewarm);
|
|
935
938
|
const framesToSimulate = Math.ceil(timeToSimulate / dt);
|
|
936
939
|
const startTime = Date.now();
|
|
937
|
-
if (debug)
|
|
940
|
+
if (debug || this.name === "Snow")
|
|
938
941
|
console.log(`Particles ${this.name} - Prewarm for ${framesToSimulate} frames (${timeToSimulate} sec). Duration: ${duration}, Lifetime: ${lifetime}`);
|
|
939
942
|
for (let i = 0; i < framesToSimulate; i++) {
|
|
940
943
|
if (this.currentParticles >= this.maxParticles) break;
|
|
@@ -38,6 +38,13 @@ export class SceneSwitcher extends Behaviour {
|
|
|
38
38
|
@serializable()
|
|
39
39
|
queryParameterName: string = "scene";
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* when enabled the scene name will be used as the query parameter (otherwise the scene index will be used)
|
|
43
|
+
* Needs `queryParameterName` set
|
|
44
|
+
* */
|
|
45
|
+
@serializable()
|
|
46
|
+
useSceneName: boolean = true;
|
|
47
|
+
|
|
41
48
|
@serializable()
|
|
42
49
|
clamp: boolean = true;
|
|
43
50
|
|
|
@@ -281,9 +288,15 @@ export class SceneSwitcher extends Behaviour {
|
|
|
281
288
|
if (this.useSceneLighting)
|
|
282
289
|
this.context.sceneLighting.enable(scene)
|
|
283
290
|
if (this.useHistory && index >= 0) {
|
|
291
|
+
// take the index as the query parameter value
|
|
292
|
+
let queryParameterValue = index.toString();
|
|
293
|
+
// unless the user defines that he wants to use the scene name
|
|
294
|
+
if (this.useSceneName) {
|
|
295
|
+
queryParameterValue = sceneUriToName(scene.uri);
|
|
296
|
+
}
|
|
284
297
|
// save the loaded scene as an url parameter
|
|
285
298
|
if (this.queryParameterName?.length)
|
|
286
|
-
setParamWithoutReload(this.queryParameterName,
|
|
299
|
+
setParamWithoutReload(this.queryParameterName, queryParameterValue, this.useHistory);
|
|
287
300
|
// or set the history state without updating the url parameter
|
|
288
301
|
else {
|
|
289
302
|
const lastState = history.state;
|
|
@@ -328,9 +341,11 @@ export class SceneSwitcher extends Behaviour {
|
|
|
328
341
|
}
|
|
329
342
|
else {
|
|
330
343
|
// Try to find a scene with a matching name
|
|
344
|
+
// we don't care about casing. e.g. Scene1 and scene1 should both match
|
|
345
|
+
const lowerCaseValue = value.toLowerCase();
|
|
331
346
|
for (let i = 0; i < this.scenes.length; i++) {
|
|
332
347
|
const scene = this.scenes[i];
|
|
333
|
-
if (scene.uri.toLowerCase().includes(
|
|
348
|
+
if (sceneUriToName(scene.uri).toLowerCase().includes(lowerCaseValue)) {
|
|
334
349
|
return this.select(i);;
|
|
335
350
|
}
|
|
336
351
|
}
|
|
@@ -349,6 +364,13 @@ export class SceneSwitcher extends Behaviour {
|
|
|
349
364
|
}
|
|
350
365
|
|
|
351
366
|
|
|
367
|
+
function sceneUriToName(uri: string): string {
|
|
368
|
+
const name = uri.split("/").pop();
|
|
369
|
+
let value = name?.split(".").shift();
|
|
370
|
+
if (value?.length) return value;
|
|
371
|
+
return uri;
|
|
372
|
+
}
|
|
373
|
+
|
|
352
374
|
|
|
353
375
|
|
|
354
376
|
class PreLoadScheduler {
|
|
@@ -21,7 +21,7 @@ import { showBalloonWarning } from '../../engine/debug';
|
|
|
21
21
|
const debugWebXR = getParam("debugwebxr");
|
|
22
22
|
|
|
23
23
|
export async function detectARSupport() {
|
|
24
|
-
if(isMozillaXR()) return true;
|
|
24
|
+
if (isMozillaXR()) return true;
|
|
25
25
|
if ("xr" in navigator) {
|
|
26
26
|
//@ts-ignore
|
|
27
27
|
return (await navigator["xr"].isSessionSupported('immersive-ar')) === true;
|
|
@@ -136,7 +136,7 @@ export class WebXR extends Behaviour {
|
|
|
136
136
|
return arButton;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
private static onModifyAROptions(options){
|
|
139
|
+
private static onModifyAROptions(options) {
|
|
140
140
|
WebXR.dispatchEvent(WebXREvent.ModifyAROptions, options);
|
|
141
141
|
}
|
|
142
142
|
|
|
@@ -255,11 +255,10 @@ export class WebXR extends Behaviour {
|
|
|
255
255
|
this.context.appendHTMLElement(buttonsContainer);
|
|
256
256
|
|
|
257
257
|
const forceButtons = debugWebXR;
|
|
258
|
-
if(debugWebXR) console.log("ARSupported?", arSupported, "VRSupported?", vrSupported);
|
|
258
|
+
if (debugWebXR) console.log("ARSupported?", arSupported, "VRSupported?", vrSupported);
|
|
259
259
|
|
|
260
260
|
// AR support
|
|
261
|
-
if (forceButtons || (this.createARButton && this.enableAR && arSupported))
|
|
262
|
-
{
|
|
261
|
+
if (forceButtons || (this.createARButton && this.enableAR && arSupported)) {
|
|
263
262
|
arButton = WebXR.createARButton(this);
|
|
264
263
|
this._arButton = arButton;
|
|
265
264
|
buttonsContainer.appendChild(arButton);
|
|
@@ -271,7 +270,7 @@ export class WebXR extends Behaviour {
|
|
|
271
270
|
this._vrButton = vrButton;
|
|
272
271
|
buttonsContainer.appendChild(vrButton);
|
|
273
272
|
}
|
|
274
|
-
|
|
273
|
+
|
|
275
274
|
setTimeout(() => {
|
|
276
275
|
WebXR.resetButtonStyles(vrButton);
|
|
277
276
|
WebXR.resetButtonStyles(arButton);
|
|
@@ -289,11 +288,11 @@ export class WebXR extends Behaviour {
|
|
|
289
288
|
// TODO: figure out why screen is black if we enable the code written here
|
|
290
289
|
// const referenceSpace = renderer.xr.getReferenceSpace();
|
|
291
290
|
const session = this.context.renderer.xr.getSession();
|
|
292
|
-
|
|
291
|
+
|
|
293
292
|
|
|
294
293
|
if (session) {
|
|
295
294
|
const pose = frame.getViewerPose(this.context.renderer.xr.getReferenceSpace());
|
|
296
|
-
if(!pose) return;
|
|
295
|
+
if (!pose) return;
|
|
297
296
|
this._currentHeadPose = pose;
|
|
298
297
|
const transform: XRRigidTransform = pose?.transform;
|
|
299
298
|
if (transform) {
|
|
@@ -356,7 +355,7 @@ export class WebXR extends Behaviour {
|
|
|
356
355
|
this._originalCameraRotation.copy(getWorldQuaternion(this.context.mainCamera));
|
|
357
356
|
this._originalCameraParent = this.context.mainCamera.parent;
|
|
358
357
|
}
|
|
359
|
-
if(this.Rig){
|
|
358
|
+
if (this.Rig) {
|
|
360
359
|
this._originalXRRigParent = this.Rig.parent;
|
|
361
360
|
this._originalXRRigPosition.copy(this.Rig.position);
|
|
362
361
|
this._originalXRRigRotation.copy(this.Rig.quaternion);
|
|
@@ -415,9 +414,9 @@ export class WebXR extends Behaviour {
|
|
|
415
414
|
const xr = this.context.renderer.xr;
|
|
416
415
|
if (this.context.mainCamera) {
|
|
417
416
|
const cam = xr.getCamera() as WebXRArrayCamera;
|
|
418
|
-
if(debugWebXR) console.log("WebXRCamera", cam);
|
|
417
|
+
if (debugWebXR) console.log("WebXRCamera", cam);
|
|
419
418
|
const cull = this.context.mainCameraComponent?.cullingMask;
|
|
420
|
-
if(cam && cull !== undefined){
|
|
419
|
+
if (cam && cull !== undefined) {
|
|
421
420
|
for (const c of cam.cameras) {
|
|
422
421
|
c.layers.mask = cull;
|
|
423
422
|
}
|
|
@@ -467,8 +466,14 @@ export class WebXR extends Behaviour {
|
|
|
467
466
|
|
|
468
467
|
const wasInAR = this._isInAR;
|
|
469
468
|
|
|
470
|
-
if (
|
|
471
|
-
this.
|
|
469
|
+
if (session) {
|
|
470
|
+
if (this._isInAR) {
|
|
471
|
+
this.webAR?.onEnd(session);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
// if in VR we want to restore the FOV
|
|
475
|
+
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
476
|
+
}
|
|
472
477
|
}
|
|
473
478
|
|
|
474
479
|
this._isInAR = false;
|
|
@@ -491,7 +496,7 @@ export class WebXR extends Behaviour {
|
|
|
491
496
|
this.context.mainCamera.scale.set(1, 1, 1);
|
|
492
497
|
}
|
|
493
498
|
|
|
494
|
-
if(wasInAR){
|
|
499
|
+
if (wasInAR) {
|
|
495
500
|
this._originalXRRigParent?.add(this.rig);
|
|
496
501
|
this.rig.position.copy(this._originalXRRigPosition);
|
|
497
502
|
this.rig.quaternion.copy(this._originalXRRigRotation);
|