rayzee 9.3.1 → 9.3.2
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/dist/rayzee.es.js +57 -16
- package/dist/rayzee.umd.js +3 -3
- package/package.json +1 -1
- package/src/PathTracerApp.js +2 -2
- package/src/Processor/SceneProcessor.js +8 -1
- package/src/Stages/PathTracerStage.js +8 -3
- package/src/managers/AnimationManager.js +52 -1
- package/src/managers/CameraManager.js +31 -5
package/package.json
CHANGED
package/src/PathTracerApp.js
CHANGED
|
@@ -1925,9 +1925,9 @@ export class PathTracerApp extends EventDispatcher {
|
|
|
1925
1925
|
async refitBVH( newPositions, newNormals ) {
|
|
1926
1926
|
|
|
1927
1927
|
await this.ensureSceneResident();
|
|
1928
|
-
const result = await this._sdf.refitBVH( newPositions, newNormals );
|
|
1928
|
+
const { triRanges, ...result } = await this._sdf.refitBVH( newPositions, newNormals );
|
|
1929
1929
|
|
|
1930
|
-
this.stages.pathTracer.updateTriangleData( this._sdf.triangles );
|
|
1930
|
+
this.stages.pathTracer.updateTriangleData( this._sdf.triangles, triRanges );
|
|
1931
1931
|
this.stages.pathTracer.updateBVHData( this._sdf.bvh );
|
|
1932
1932
|
this.reset( false, { motion: true } );
|
|
1933
1933
|
|
|
@@ -2648,6 +2648,8 @@ export class SceneProcessor {
|
|
|
2648
2648
|
// can be released as soon as it is read. Callers hand over world space; triangles are
|
|
2649
2649
|
// stored per instance, so each mesh comes back through its own inverse.
|
|
2650
2650
|
const table = this.instanceTable;
|
|
2651
|
+
const FPT = TRIANGLE_DATA_LAYOUT.FLOATS_PER_TRIANGLE;
|
|
2652
|
+
const triRanges = [];
|
|
2651
2653
|
for ( let i = 0; i < table.count; i ++ ) {
|
|
2652
2654
|
|
|
2653
2655
|
if ( ! table.isSet[ i ] || ! table.isOwner( i ) ) continue;
|
|
@@ -2664,6 +2666,11 @@ export class SceneProcessor {
|
|
|
2664
2666
|
|
|
2665
2667
|
}
|
|
2666
2668
|
|
|
2669
|
+
const offset = table.triOffsetOf( i ) * FPT, count = table.triCountOf( i ) * FPT;
|
|
2670
|
+
const last = triRanges.at( - 1 );
|
|
2671
|
+
if ( last && last.offset + last.count === offset ) last.count += count;
|
|
2672
|
+
else triRanges.push( { offset, count } );
|
|
2673
|
+
|
|
2667
2674
|
}
|
|
2668
2675
|
|
|
2669
2676
|
return new Promise( ( resolve, reject ) => {
|
|
@@ -2673,7 +2680,7 @@ export class SceneProcessor {
|
|
|
2673
2680
|
const msg = e.data;
|
|
2674
2681
|
if ( msg.type === 'refitComplete' ) {
|
|
2675
2682
|
|
|
2676
|
-
resolve( { refitTimeMs: msg.refitTimeMs } );
|
|
2683
|
+
resolve( { refitTimeMs: msg.refitTimeMs, triRanges } );
|
|
2677
2684
|
|
|
2678
2685
|
} else if ( msg.type === 'error' ) {
|
|
2679
2686
|
|
|
@@ -1088,12 +1088,17 @@ export class PathTracerStage extends RenderStage {
|
|
|
1088
1088
|
|
|
1089
1089
|
}
|
|
1090
1090
|
|
|
1091
|
-
/**
|
|
1092
|
-
|
|
1091
|
+
/**
|
|
1092
|
+
* Re-uploads triangles from the CPU records, adopting `triangleData` as them when given.
|
|
1093
|
+
* @param {Object} [triangleData]
|
|
1094
|
+
* @param {Array<{offset:number,count:number}>} [ranges] - only these, in record lanes; every triangle when omitted
|
|
1095
|
+
*/
|
|
1096
|
+
updateTriangleData( triangleData, ranges ) {
|
|
1093
1097
|
|
|
1094
1098
|
if ( triangleData?.chunks?.length > 1 ) this._triangleRecords = triangleData;
|
|
1095
1099
|
else if ( triangleData ) this._triangleFlat = triangleData.chunks ? triangleData.chunks[ 0 ] : triangleData;
|
|
1096
|
-
this.
|
|
1100
|
+
if ( ranges ) this.updateBufferRanges( ranges, [] );
|
|
1101
|
+
else this._uploadTriangles( 0, this._triangleRecordCount );
|
|
1097
1102
|
|
|
1098
1103
|
}
|
|
1099
1104
|
|
|
@@ -39,6 +39,8 @@ export class AnimationManager extends EventDispatcher {
|
|
|
39
39
|
this._slotOf = null; // meshIndex -> row in the two caches below, or -1
|
|
40
40
|
this._lastWorld = null; // world matrix last handed to applyPoseCallback, 16 per row
|
|
41
41
|
this._lastVisible = null; // 0 / 1, or 2 before the first pose
|
|
42
|
+
this._lastMeshWorld = null; // deforming clips: world matrix at each mesh's last read, 16 per mesh
|
|
43
|
+
this._lastMorphWeights = null;
|
|
42
44
|
|
|
43
45
|
/** Injected by PathTracerApp — wakes the render loop after play/resume. */
|
|
44
46
|
this.wakeCallback = null;
|
|
@@ -135,6 +137,8 @@ export class AnimationManager extends EventDispatcher {
|
|
|
135
137
|
// 9 floats × every triangle — 1,030 MB at 30M, past what a renderer can allocate.
|
|
136
138
|
this._skinnedCache = [];
|
|
137
139
|
this._meshPositions = [];
|
|
140
|
+
this._lastMeshWorld = this._rigid ? null : new Float64Array( meshes.length * 16 ).fill( NaN );
|
|
141
|
+
this._lastMorphWeights = [];
|
|
138
142
|
|
|
139
143
|
const skinnedCount = meshes.filter( m => m.isSkinnedMesh ).length;
|
|
140
144
|
console.debug( `[AnimationManager] Init: ${animations.length} clips, ${meshes.length} meshes (${skinnedCount} skinned), ${offset} triangles, ${this._rigid ? 'rigid' : 'deforming'}` );
|
|
@@ -499,7 +503,52 @@ export class AnimationManager extends EventDispatcher {
|
|
|
499
503
|
const cameras = this._planFor( this._activeClip )?.cameras;
|
|
500
504
|
if ( cameras?.length ) this.applyPoseCallback?.( { meshIndices: [], visibilityChanged: false, cameras } );
|
|
501
505
|
|
|
502
|
-
|
|
506
|
+
// Decided once per reader: an expanded instanced emitter asks for one mesh several times.
|
|
507
|
+
const moved = new Int8Array( this._meshes.length );
|
|
508
|
+
return m => {
|
|
509
|
+
|
|
510
|
+
if ( moved[ m ] === 0 ) moved[ m ] = this._meshes[ m ].isSkinnedMesh || this._poseChanged( m ) ? 1 : - 1;
|
|
511
|
+
return moved[ m ] > 0 ? this._computeMeshPositions( m ) : null;
|
|
512
|
+
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/** Whether a mesh's world matrix or morph weights differ from when its positions were last read. @private */
|
|
518
|
+
_poseChanged( m ) {
|
|
519
|
+
|
|
520
|
+
const mesh = this._meshes[ m ];
|
|
521
|
+
const last = this._lastMeshWorld;
|
|
522
|
+
const e = mesh.matrixWorld.elements;
|
|
523
|
+
const o = m * 16;
|
|
524
|
+
let changed = false;
|
|
525
|
+
|
|
526
|
+
for ( let i = 0; i < 16; i ++ ) {
|
|
527
|
+
|
|
528
|
+
if ( last[ o + i ] !== e[ i ] ) {
|
|
529
|
+
|
|
530
|
+
for ( let j = 0; j < 16; j ++ ) last[ o + j ] = e[ j ];
|
|
531
|
+
changed = true;
|
|
532
|
+
break;
|
|
533
|
+
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const weights = mesh.morphTargetInfluences;
|
|
539
|
+
if ( weights?.length ) {
|
|
540
|
+
|
|
541
|
+
const lastWeights = this._lastMorphWeights[ m ];
|
|
542
|
+
if ( ! lastWeights || lastWeights.length !== weights.length || lastWeights.some( ( w, i ) => w !== weights[ i ] ) ) {
|
|
543
|
+
|
|
544
|
+
this._lastMorphWeights[ m ] = Float64Array.from( weights );
|
|
545
|
+
changed = true;
|
|
546
|
+
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
return changed;
|
|
503
552
|
|
|
504
553
|
}
|
|
505
554
|
|
|
@@ -640,6 +689,8 @@ export class AnimationManager extends EventDispatcher {
|
|
|
640
689
|
this._slotOf = null;
|
|
641
690
|
this._lastWorld = null;
|
|
642
691
|
this._lastVisible = null;
|
|
692
|
+
this._lastMeshWorld = null;
|
|
693
|
+
this._lastMorphWeights = null;
|
|
643
694
|
|
|
644
695
|
}
|
|
645
696
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventDispatcher, MathUtils, OrthographicCamera, PerspectiveCamera, Quaternion, Vector3 } from 'three';
|
|
1
|
+
import { EventDispatcher, MathUtils, Matrix4, OrthographicCamera, PerspectiveCamera, Quaternion, Vector3 } from 'three';
|
|
2
2
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
3
3
|
import { EngineEvents, } from '../EngineEvents.js';
|
|
4
4
|
import { AF_DEFAULTS, CAMERA_PROJECTION_IDS } from '../EngineDefaults.js';
|
|
@@ -62,6 +62,7 @@ export class CameraManager extends EventDispatcher {
|
|
|
62
62
|
this._smoothedFocusDistance = null;
|
|
63
63
|
this._afPointDirty = false;
|
|
64
64
|
this._afSuspended = false;
|
|
65
|
+
this._afPick = null;
|
|
65
66
|
|
|
66
67
|
// Saved state for default camera when switching to model cameras
|
|
67
68
|
this._defaultCameraState = null;
|
|
@@ -833,13 +834,12 @@ export class CameraManager extends EventDispatcher {
|
|
|
833
834
|
&& stage.frameCount > 0
|
|
834
835
|
&& ! stage.isComplete ) return;
|
|
835
836
|
|
|
836
|
-
|
|
837
|
-
const validHit = this.interactionManager.pickSurface( this.afScreenPoint.x * 2 - 1, 1 - this.afScreenPoint.y * 2 );
|
|
837
|
+
const hitPoint = this._pickFocusPoint( stage.resetCount );
|
|
838
838
|
|
|
839
839
|
let rawDistance;
|
|
840
|
-
if (
|
|
840
|
+
if ( hitPoint ) {
|
|
841
841
|
|
|
842
|
-
rawDistance = viewDepth(
|
|
842
|
+
rawDistance = viewDepth( hitPoint, this.camera );
|
|
843
843
|
this._lastValidFocusDistance = rawDistance;
|
|
844
844
|
|
|
845
845
|
} else {
|
|
@@ -910,6 +910,32 @@ export class CameraManager extends EventDispatcher {
|
|
|
910
910
|
|
|
911
911
|
}
|
|
912
912
|
|
|
913
|
+
/** Picks again only on a new view or AF point, or a render reset, which every scene change makes. @private */
|
|
914
|
+
_pickFocusPoint( resetCount ) {
|
|
915
|
+
|
|
916
|
+
const camera = this.camera;
|
|
917
|
+
const { x, y } = this.afScreenPoint;
|
|
918
|
+
const last = this._afPick ??= { point: new Vector3(), hit: false, resetCount: NaN, x: NaN, y: NaN, view: new Matrix4(), projection: new Matrix4() };
|
|
919
|
+
|
|
920
|
+
if ( this._afPointDirty || resetCount !== last.resetCount || x !== last.x || y !== last.y
|
|
921
|
+
|| ! last.view.equals( camera.matrixWorld ) || ! last.projection.equals( camera.projectionMatrix ) ) {
|
|
922
|
+
|
|
923
|
+
// AF screen point (0 to 1, y down) to NDC.
|
|
924
|
+
const hit = this.interactionManager.pickSurface( x * 2 - 1, 1 - y * 2 );
|
|
925
|
+
last.hit = !! hit;
|
|
926
|
+
if ( hit ) last.point.copy( hit.point );
|
|
927
|
+
last.resetCount = resetCount;
|
|
928
|
+
last.x = x;
|
|
929
|
+
last.y = y;
|
|
930
|
+
last.view.copy( camera.matrixWorld );
|
|
931
|
+
last.projection.copy( camera.projectionMatrix );
|
|
932
|
+
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
return last.hit ? last.point : null;
|
|
936
|
+
|
|
937
|
+
}
|
|
938
|
+
|
|
913
939
|
/**
|
|
914
940
|
* Deferred dependency injection — InteractionManager needs the camera
|
|
915
941
|
* in its constructor, so it can't be passed during CameraManager creation.
|