@volter/blender-engine 0.1.76 → 0.1.77
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.
|
@@ -306,10 +306,18 @@ export class BlenderMotionGeometry {
|
|
|
306
306
|
for (const [source, entry] of this.cache) {
|
|
307
307
|
for (const mesh of this.groups.get(source) ?? []) {
|
|
308
308
|
if (!instanceObjectShown(mesh) || (mesh.frustumCulled && !this.frustum.intersectsObject(mesh))) continue;
|
|
309
|
-
//
|
|
310
|
-
//
|
|
309
|
+
// Bound the largest singular value by the maximum absolute row sum
|
|
310
|
+
// of AᵀA. Unlike Frobenius this is tight for orthogonal TRS columns,
|
|
311
|
+
// while still bounding shear. A uniform rotation must not inflate
|
|
312
|
+
// both error and radius by sqrt(3) and veto nearby placements.
|
|
311
313
|
const e = mesh.matrixWorld.elements;
|
|
312
|
-
const
|
|
314
|
+
const x2 = e[0]! ** 2 + e[1]! ** 2 + e[2]! ** 2;
|
|
315
|
+
const y2 = e[4]! ** 2 + e[5]! ** 2 + e[6]! ** 2;
|
|
316
|
+
const z2 = e[8]! ** 2 + e[9]! ** 2 + e[10]! ** 2;
|
|
317
|
+
const xy = Math.abs(e[0]! * e[4]! + e[1]! * e[5]! + e[2]! * e[6]!);
|
|
318
|
+
const xz = Math.abs(e[0]! * e[8]! + e[1]! * e[9]! + e[2]! * e[10]!);
|
|
319
|
+
const yz = Math.abs(e[4]! * e[8]! + e[5]! * e[9]! + e[6]! * e[10]!);
|
|
320
|
+
const scale = Math.sqrt(Math.max(x2 + xy + xz, y2 + xy + yz, z2 + xz + yz));
|
|
313
321
|
const sphere = source.boundingSphere!;
|
|
314
322
|
this.centre.copy(sphere.center).applyMatrix4(mesh.matrixWorld).applyMatrix4(camera.matrixWorldInverse);
|
|
315
323
|
const depth = (camera as THREE.PerspectiveCamera).isPerspectiveCamera
|
|
@@ -1243,12 +1243,19 @@ export class BlenderRuntimeView {
|
|
|
1243
1243
|
presenterChanged();
|
|
1244
1244
|
}
|
|
1245
1245
|
|
|
1246
|
+
private drawPreparation: {
|
|
1247
|
+
last: {opaqueMs: number; motionMs: number; transparentMs: number} | null;
|
|
1248
|
+
navigation: {opaqueMs: number; motionMs: number; transparentMs: number} | null;
|
|
1249
|
+
} = {last: null, navigation: null};
|
|
1250
|
+
|
|
1246
1251
|
/** Before the renderer uploads attributes/builds its queues, for this area's
|
|
1247
1252
|
* actual camera. Transparent instance runs are camera-order dependent. */
|
|
1248
1253
|
prepareDraw(camera: THREE.Camera, options?: {interactive: boolean; height: number}): () => void {
|
|
1249
1254
|
try {
|
|
1255
|
+
const start = performance.now();
|
|
1250
1256
|
this.instances.prepareDraw(camera);
|
|
1251
1257
|
this.root.updateMatrixWorld(true);
|
|
1258
|
+
const opaqueDone = performance.now();
|
|
1252
1259
|
const motion = this.motionGeometry.prepare(camera, !this.rendered && (this.mode ?? this.frame?.mode) === 'OBJECT' &&
|
|
1253
1260
|
options?.interactive === true, options?.height ?? 0);
|
|
1254
1261
|
// A changed navigation geometry is an ordinary-draw fallback for an
|
|
@@ -1256,7 +1263,12 @@ export class BlenderRuntimeView {
|
|
|
1256
1263
|
// runs are planned AFTER per-placement geometry selection, preserving
|
|
1257
1264
|
// their sorting barriers and compatible geometry grouping.
|
|
1258
1265
|
if (motion) this.instances.sync();
|
|
1266
|
+
const motionDone = performance.now();
|
|
1259
1267
|
this.transparentInstances.prepare(camera);
|
|
1268
|
+
const timing = {opaqueMs: opaqueDone - start, motionMs: motionDone - opaqueDone,
|
|
1269
|
+
transparentMs: performance.now() - motionDone};
|
|
1270
|
+
this.drawPreparation.last = timing;
|
|
1271
|
+
if (motion) this.drawPreparation.navigation = timing;
|
|
1260
1272
|
} catch (error) {
|
|
1261
1273
|
this.motionGeometry.finish();
|
|
1262
1274
|
this.instances.finishDraw();
|
|
@@ -2075,7 +2087,7 @@ export class BlenderRuntimeView {
|
|
|
2075
2087
|
}
|
|
2076
2088
|
|
|
2077
2089
|
drawStatistics() {
|
|
2078
|
-
return {enabled: this.drawBatching, opaque: this.instances.inspect(), transparent: this.transparentInstances.inspect(), motion: this.motionGeometry.inspect()};
|
|
2090
|
+
return {enabled: this.drawBatching, preparation: {...this.drawPreparation}, opaque: this.instances.inspect(), transparent: this.transparentInstances.inspect(), motion: this.motionGeometry.inspect()};
|
|
2079
2091
|
}
|
|
2080
2092
|
|
|
2081
2093
|
snapshot() {
|
|
@@ -29,6 +29,7 @@ export class BlenderTransparentInstances {
|
|
|
29
29
|
private readonly depth = new THREE.Vector4();
|
|
30
30
|
private batches = 0;
|
|
31
31
|
private instances = 0;
|
|
32
|
+
private excluded: Record<string, number> = {};
|
|
32
33
|
private readonly planState: (number | string)[] = [];
|
|
33
34
|
private readonly planned: Draw[] = [];
|
|
34
35
|
private stateIndex = 0;
|
|
@@ -65,6 +66,7 @@ export class BlenderTransparentInstances {
|
|
|
65
66
|
draw.members.length = 0;
|
|
66
67
|
}
|
|
67
68
|
this.batches = this.instances = 0;
|
|
69
|
+
this.excluded = {};
|
|
68
70
|
this.frustum.setFromProjectionMatrix(this.projection);
|
|
69
71
|
this.inverse.copy(this.root.matrixWorld).invert();
|
|
70
72
|
const entries: Entry[] = [];
|
|
@@ -118,6 +120,14 @@ export class BlenderTransparentInstances {
|
|
|
118
120
|
key = groupKey;
|
|
119
121
|
}
|
|
120
122
|
}
|
|
123
|
+
if (key === null) {
|
|
124
|
+
const reason = !candidate ? 'multipleMaterials'
|
|
125
|
+
: (candidate as THREE.ShaderMaterial).isShaderMaterial ? 'customShader'
|
|
126
|
+
: (candidate as THREE.MeshPhysicalMaterial).transmission > 0 ? 'transmission'
|
|
127
|
+
: candidate.side === THREE.DoubleSide && !candidate.forceSinglePass ? 'twoPass'
|
|
128
|
+
: 'geometryLayersOrTransform';
|
|
129
|
+
this.excluded[reason] = (this.excluded[reason] ?? 0) + 1;
|
|
130
|
+
}
|
|
121
131
|
entries.push({mesh, material, key, groupOrder: order, z, centre});
|
|
122
132
|
}
|
|
123
133
|
entries.sort((a, b) => a.groupOrder - b.groupOrder || a.mesh.renderOrder - b.mesh.renderOrder || b.z - a.z || a.mesh.id - b.mesh.id);
|
|
@@ -189,7 +199,7 @@ export class BlenderTransparentInstances {
|
|
|
189
199
|
}
|
|
190
200
|
}
|
|
191
201
|
|
|
192
|
-
inspect() { return {batches: this.batches, instances: this.instances}; }
|
|
202
|
+
inspect() { return {batches: this.batches, instances: this.instances, excluded: {...this.excluded}}; }
|
|
193
203
|
|
|
194
204
|
private observe(value: number | string): void {
|
|
195
205
|
if (this.planState[this.stateIndex] !== value) {
|