@gnsx/three 0.184.17 → 0.184.19
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/build/three.cjs +109 -2
- package/build/three.core.js +108 -1
- package/build/three.core.min.js +1 -1
- package/build/three.module.js +1 -1
- package/build/three.module.min.js +1 -1
- package/build/three.webgpu.js +3 -3
- package/build/three.webgpu.min.js +1 -1
- package/build/three.webgpu.nodes.js +3 -3
- package/build/three.webgpu.nodes.min.js +1 -1
- package/package.json +2 -2
- package/src/core/Object3D.js +17 -0
- package/src/loaders/ObjectLoader.js +3 -0
- package/src/profiler/ProfilerService.js +88 -1
- package/src/renderers/WebGLRenderer.js +1 -1
- package/src/renderers/common/Renderer.js +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gnsx/three",
|
|
3
|
-
"version": "0.184.
|
|
3
|
+
"version": "0.184.19",
|
|
4
4
|
"description": "JavaScript 3D library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./build/three.cjs",
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"jsdoc": "^4.0.5",
|
|
109
109
|
"magic-string": "^0.30.0",
|
|
110
110
|
"pngjs": "^7.0.0",
|
|
111
|
-
"puppeteer": "^
|
|
111
|
+
"puppeteer": "^25.1.0",
|
|
112
112
|
"qunit": "^2.19.4",
|
|
113
113
|
"rollup": "^4.6.0",
|
|
114
114
|
"three": "file:.",
|
package/src/core/Object3D.js
CHANGED
|
@@ -290,6 +290,17 @@ class Object3D extends EventDispatcher {
|
|
|
290
290
|
*/
|
|
291
291
|
this.visible = true;
|
|
292
292
|
|
|
293
|
+
// WITH_GENESYS
|
|
294
|
+
/**
|
|
295
|
+
* When set to `true`, this object itself is hidden.
|
|
296
|
+
* Doesn't affect the visibility of the children.
|
|
297
|
+
*
|
|
298
|
+
* @type {boolean}
|
|
299
|
+
* @default false
|
|
300
|
+
*/
|
|
301
|
+
this.selfHidden = false;
|
|
302
|
+
// !WITH_GENESYS
|
|
303
|
+
|
|
293
304
|
/**
|
|
294
305
|
* When set to `true`, the 3D object gets rendered into shadow maps.
|
|
295
306
|
*
|
|
@@ -1303,6 +1314,9 @@ class Object3D extends EventDispatcher {
|
|
|
1303
1314
|
if ( this.castShadow === true ) object.castShadow = true;
|
|
1304
1315
|
if ( this.receiveShadow === true ) object.receiveShadow = true;
|
|
1305
1316
|
if ( this.visible === false ) object.visible = false;
|
|
1317
|
+
// WITH_GENESYS
|
|
1318
|
+
if ( this.selfHidden === true ) object.selfHidden = true;
|
|
1319
|
+
// !WITH_GENESYS
|
|
1306
1320
|
if ( this.frustumCulled === false ) object.frustumCulled = false;
|
|
1307
1321
|
if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
|
|
1308
1322
|
if ( this.static !== false ) object.static = this.static;
|
|
@@ -1604,6 +1618,9 @@ class Object3D extends EventDispatcher {
|
|
|
1604
1618
|
|
|
1605
1619
|
this.layers.mask = source.layers.mask;
|
|
1606
1620
|
this.visible = source.visible;
|
|
1621
|
+
// WITH_GENESYS
|
|
1622
|
+
this.selfHidden = source.selfHidden;
|
|
1623
|
+
// !WITH_GENESYS
|
|
1607
1624
|
|
|
1608
1625
|
this.castShadow = source.castShadow;
|
|
1609
1626
|
this.receiveShadow = source.receiveShadow;
|
|
@@ -1166,6 +1166,9 @@ class ObjectLoader extends Loader {
|
|
|
1166
1166
|
}
|
|
1167
1167
|
|
|
1168
1168
|
if ( data.visible !== undefined ) object.visible = data.visible;
|
|
1169
|
+
// WITH_GENESYS
|
|
1170
|
+
if ( data.selfHidden !== undefined ) object.selfHidden = data.selfHidden;
|
|
1171
|
+
// !WITH_GENESYS
|
|
1169
1172
|
if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
|
|
1170
1173
|
if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
|
|
1171
1174
|
if ( data.static !== undefined ) object.static = data.static;
|
|
@@ -24,7 +24,7 @@ class ProfilerServiceClass {
|
|
|
24
24
|
this._profile = 'full';
|
|
25
25
|
this._enabled = false;
|
|
26
26
|
|
|
27
|
-
/** @type {Map<string, Float64Array>} */
|
|
27
|
+
/** @type {Map<string, Float64Array>} Inclusive time ring buffers (one per label). */
|
|
28
28
|
this.buffers = new Map();
|
|
29
29
|
/** @type {Map<string, number>} */
|
|
30
30
|
this.cursors = new Map();
|
|
@@ -37,6 +37,20 @@ class ProfilerServiceClass {
|
|
|
37
37
|
this.traceStartTime = 0;
|
|
38
38
|
this._markId = 0;
|
|
39
39
|
|
|
40
|
+
/** @type {Map<string, Float64Array>} Exclusive (self) time ring buffers (one per label). */
|
|
41
|
+
this.selfBuffers = new Map();
|
|
42
|
+
/** @type {Map<string, number>} */
|
|
43
|
+
this.selfCursors = new Map();
|
|
44
|
+
/** @type {Map<string, number>} */
|
|
45
|
+
this.selfCounts = new Map();
|
|
46
|
+
/**
|
|
47
|
+
* Global call stack tracking nesting across all labels for exclusive-time computation.
|
|
48
|
+
* @type {Array<{ label: string, childTime: number }>}
|
|
49
|
+
*/
|
|
50
|
+
this.callStack = [];
|
|
51
|
+
/** @type {Map<string, number>} Total (uncapped) invocation count since last reset, for calls-per-frame. */
|
|
52
|
+
this.invocations = new Map();
|
|
53
|
+
|
|
40
54
|
if ( this._enabled ) {
|
|
41
55
|
|
|
42
56
|
this.traceStartTime = performance.now();
|
|
@@ -143,6 +157,9 @@ class ProfilerServiceClass {
|
|
|
143
157
|
performance.mark( startMark );
|
|
144
158
|
stack.push( { startTime, startMark, traced } );
|
|
145
159
|
|
|
160
|
+
// Push onto the global call stack for exclusive-time tracking.
|
|
161
|
+
this.callStack.push( { label, childTime: 0 } );
|
|
162
|
+
|
|
146
163
|
}
|
|
147
164
|
|
|
148
165
|
/**
|
|
@@ -178,6 +195,42 @@ class ProfilerServiceClass {
|
|
|
178
195
|
this.cursors.set( label, ( cursor + 1 ) % RING_SIZE );
|
|
179
196
|
this.counts.set( label, Math.min( ( this.counts.get( label ) + 1 ), RING_SIZE ) );
|
|
180
197
|
|
|
198
|
+
// Track total invocations (uncapped) for calls-per-frame computation.
|
|
199
|
+
this.invocations.set( label, ( this.invocations.get( label ) ?? 0 ) + 1 );
|
|
200
|
+
|
|
201
|
+
// Exclusive (self) time via the global call stack.
|
|
202
|
+
const top = this.callStack.length > 0 ? this.callStack[ this.callStack.length - 1 ] : undefined;
|
|
203
|
+
if ( top !== undefined && top.label === label ) {
|
|
204
|
+
|
|
205
|
+
this.callStack.pop();
|
|
206
|
+
const selfTime = Math.max( 0, duration - top.childTime );
|
|
207
|
+
|
|
208
|
+
let selfBuffer = this.selfBuffers.get( label );
|
|
209
|
+
if ( ! selfBuffer ) {
|
|
210
|
+
|
|
211
|
+
selfBuffer = new Float64Array( RING_SIZE );
|
|
212
|
+
this.selfBuffers.set( label, selfBuffer );
|
|
213
|
+
this.selfCursors.set( label, 0 );
|
|
214
|
+
this.selfCounts.set( label, 0 );
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const selfCursor = this.selfCursors.get( label );
|
|
219
|
+
selfBuffer[ selfCursor ] = selfTime;
|
|
220
|
+
this.selfCursors.set( label, ( selfCursor + 1 ) % RING_SIZE );
|
|
221
|
+
this.selfCounts.set( label, Math.min( ( this.selfCounts.get( label ) + 1 ), RING_SIZE ) );
|
|
222
|
+
|
|
223
|
+
// Propagate inclusive duration to the parent scope's child accumulator.
|
|
224
|
+
const parent = this.callStack.length > 0 ? this.callStack[ this.callStack.length - 1 ] : undefined;
|
|
225
|
+
if ( parent !== undefined ) parent.childTime += duration;
|
|
226
|
+
|
|
227
|
+
} else {
|
|
228
|
+
|
|
229
|
+
// Label mismatch — likely async interleaving. Reset to avoid corruption.
|
|
230
|
+
this.callStack.length = 0;
|
|
231
|
+
|
|
232
|
+
}
|
|
233
|
+
|
|
181
234
|
if ( traced ) {
|
|
182
235
|
|
|
183
236
|
this.traceEvents.push( {
|
|
@@ -220,6 +273,23 @@ class ProfilerServiceClass {
|
|
|
220
273
|
const sorted = [ ...samples ].sort( ( a, b ) => a - b );
|
|
221
274
|
const avg = sorted.reduce( ( a, b ) => a + b, 0 ) / sorted.length;
|
|
222
275
|
|
|
276
|
+
// Exclusive (self) time stats.
|
|
277
|
+
const selfCount = this.selfCounts.get( label ) ?? 0;
|
|
278
|
+
let selfAvg, selfMin, selfMax, selfP95, selfFrameBudget;
|
|
279
|
+
if ( selfCount > 0 ) {
|
|
280
|
+
|
|
281
|
+
const selfBuffer = this.selfBuffers.get( label );
|
|
282
|
+
const selfSamples = [ ...( selfCount < RING_SIZE
|
|
283
|
+
? selfBuffer.subarray( 0, selfCount )
|
|
284
|
+
: selfBuffer ) ].sort( ( a, b ) => a - b );
|
|
285
|
+
selfAvg = selfSamples.reduce( ( a, b ) => a + b, 0 ) / selfSamples.length;
|
|
286
|
+
selfMin = selfSamples[ 0 ];
|
|
287
|
+
selfMax = selfSamples[ selfSamples.length - 1 ];
|
|
288
|
+
selfP95 = selfSamples[ Math.floor( selfSamples.length * 0.95 ) ];
|
|
289
|
+
selfFrameBudget = ( selfAvg / FRAME_BUDGET_MS ) * 100;
|
|
290
|
+
|
|
291
|
+
}
|
|
292
|
+
|
|
223
293
|
return {
|
|
224
294
|
label,
|
|
225
295
|
samples: samples.length,
|
|
@@ -228,6 +298,12 @@ class ProfilerServiceClass {
|
|
|
228
298
|
max: sorted[ sorted.length - 1 ],
|
|
229
299
|
p95: sorted[ Math.floor( sorted.length * 0.95 ) ],
|
|
230
300
|
frameBudget: ( avg / FRAME_BUDGET_MS ) * 100,
|
|
301
|
+
totalInvocations: this.invocations.get( label ) ?? 0,
|
|
302
|
+
selfAvg,
|
|
303
|
+
selfMin,
|
|
304
|
+
selfMax,
|
|
305
|
+
selfP95,
|
|
306
|
+
selfFrameBudget,
|
|
231
307
|
};
|
|
232
308
|
|
|
233
309
|
}
|
|
@@ -350,6 +426,11 @@ class ProfilerServiceClass {
|
|
|
350
426
|
this.traceEvents = [];
|
|
351
427
|
this.traceStartTime = performance.now();
|
|
352
428
|
this._markId = 0;
|
|
429
|
+
this.selfBuffers.clear();
|
|
430
|
+
this.selfCursors.clear();
|
|
431
|
+
this.selfCounts.clear();
|
|
432
|
+
this.callStack.length = 0;
|
|
433
|
+
this.invocations.clear();
|
|
353
434
|
|
|
354
435
|
}
|
|
355
436
|
|
|
@@ -371,6 +452,12 @@ class ProfilerServiceClass {
|
|
|
371
452
|
* @property {number} max
|
|
372
453
|
* @property {number} p95
|
|
373
454
|
* @property {number} frameBudget Percentage of a 60 fps frame budget (16.67 ms)
|
|
455
|
+
* @property {number} totalInvocations Total (uncapped) call count since last reset, for calls-per-frame computation.
|
|
456
|
+
* @property {number|undefined} selfAvg Exclusive (self) avg ms — inclusive time minus child scope time.
|
|
457
|
+
* @property {number|undefined} selfMin
|
|
458
|
+
* @property {number|undefined} selfMax
|
|
459
|
+
* @property {number|undefined} selfP95
|
|
460
|
+
* @property {number|undefined} selfFrameBudget Exclusive time as percentage of a 60 fps frame budget.
|
|
374
461
|
*/
|
|
375
462
|
|
|
376
463
|
/**
|
|
@@ -1682,13 +1682,13 @@ class Renderer {
|
|
|
1682
1682
|
renderList.begin();
|
|
1683
1683
|
|
|
1684
1684
|
// WITH_GENESYS
|
|
1685
|
-
ProfilerService.begin( '
|
|
1685
|
+
ProfilerService.begin( 'projectObject' );
|
|
1686
1686
|
// !WITH_GENESYS
|
|
1687
1687
|
|
|
1688
1688
|
this._projectObject( scene, camera, 0, renderList, renderContext.clippingContext );
|
|
1689
1689
|
|
|
1690
1690
|
// WITH_GENESYS
|
|
1691
|
-
ProfilerService.end( '
|
|
1691
|
+
ProfilerService.end( 'projectObject' );
|
|
1692
1692
|
// !WITH_GENESYS
|
|
1693
1693
|
|
|
1694
1694
|
renderList.finish();
|
|
@@ -3142,7 +3142,7 @@ class Renderer {
|
|
|
3142
3142
|
|
|
3143
3143
|
const visible = object.layers.test( camera.layers );
|
|
3144
3144
|
|
|
3145
|
-
if ( visible ) {
|
|
3145
|
+
if ( visible && ! object.selfHidden /* WITH_GENESYS */ ) {
|
|
3146
3146
|
|
|
3147
3147
|
if ( object.isGroup ) {
|
|
3148
3148
|
|