@volter/editor-threejs 0.5.145 → 0.5.146
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/editor-threejs",
|
|
3
3
|
"author": "Volter AI, Inc.",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.146",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -135,12 +135,12 @@
|
|
|
135
135
|
"serving": "./dist-node/serving.mjs"
|
|
136
136
|
},
|
|
137
137
|
"dependencies": {
|
|
138
|
-
"@volter/editor-project": "0.5.
|
|
138
|
+
"@volter/editor-project": "0.5.146",
|
|
139
139
|
"@sparkjsdev/spark": "^2.1.0",
|
|
140
140
|
"three.quarks": "^0.16.0",
|
|
141
141
|
"zod": "^4.3.6",
|
|
142
142
|
"typescript": "5.9.3",
|
|
143
|
-
"@volter/editor-sdk": "0.5.
|
|
143
|
+
"@volter/editor-sdk": "0.5.146",
|
|
144
144
|
"postprocessing": "6.38.3",
|
|
145
145
|
"quarks.core": "0.16.0",
|
|
146
146
|
"@fortawesome/free-solid-svg-icons": "^7.2.0"
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from '@volter/editor-threejs/render/viewport-shading';
|
|
12
12
|
import type { EffectComposer, EffectPass, RenderPass } from 'postprocessing';
|
|
13
13
|
import * as THREE from 'three';
|
|
14
|
+
import { DepthDrawMaterials } from '../../render/depth-draw-materials';
|
|
14
15
|
import { threeObject } from '../../adapter/three-contract';
|
|
15
16
|
import { axisViewName, cameraPresetDirection, type ModelCameraPreset } from '../asset-workflow/model-inspection';
|
|
16
17
|
import { activeKeymapNavigation } from '@volter/editor-sdk/kit/keymap-presets';
|
|
@@ -118,6 +119,7 @@ const TOPOLOGY_WIRE_COLOR = 0x11161d;
|
|
|
118
119
|
export class Object3DDocumentSession {
|
|
119
120
|
readonly profiler = createPerformanceProfiler();
|
|
120
121
|
private readonly shading = new ViewportShadingRenderer();
|
|
122
|
+
private readonly depthDrawMaterials = new DepthDrawMaterials();
|
|
121
123
|
private readonly helpers: THREE.Object3D[] = [];
|
|
122
124
|
private skeletonHelper: THREE.SkeletonHelper | null = null;
|
|
123
125
|
private boundsHelper: THREE.BoxHelper | null = null;
|
|
@@ -1340,6 +1342,7 @@ export class Object3DDocumentSession {
|
|
|
1340
1342
|
|
|
1341
1343
|
render(renderSolid: (camera: THREE.Camera) => void, interactive = false): void {
|
|
1342
1344
|
const finishDraw = this.beforeRender?.(interactive);
|
|
1345
|
+
const restoreDepthDraw = this.depthDrawMaterials.bind(this.renderer);
|
|
1343
1346
|
try {
|
|
1344
1347
|
this.boneSelectionHighlight?.update();
|
|
1345
1348
|
const camera = this.camera();
|
|
@@ -1386,6 +1389,7 @@ export class Object3DDocumentSession {
|
|
|
1386
1389
|
}
|
|
1387
1390
|
this.shading.render(this.scene, mode, () => renderSolid(camera), isEditorViewportShadingTarget);
|
|
1388
1391
|
} finally {
|
|
1392
|
+
restoreDepthDraw();
|
|
1389
1393
|
finishDraw?.();
|
|
1390
1394
|
}
|
|
1391
1395
|
}
|
|
@@ -1576,6 +1580,7 @@ export class Object3DDocumentSession {
|
|
|
1576
1580
|
this.selectionOutlinePass = null;
|
|
1577
1581
|
this.composer = null;
|
|
1578
1582
|
this.shading.dispose();
|
|
1583
|
+
this.depthDrawMaterials.dispose();
|
|
1579
1584
|
this.listeners.clear();
|
|
1580
1585
|
}
|
|
1581
1586
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
type Variant = {material: THREE.MeshDepthMaterial; frame: number; version: number};
|
|
4
|
+
|
|
5
|
+
/** Keep ordinary, instanced and batched depth draws from invalidating one
|
|
6
|
+
* another's current program. Only the material argument of an already selected
|
|
7
|
+
* draw changes: Three still owns visibility, groups, order and override rules.
|
|
8
|
+
* Custom hooks and deforming/textured depth materials take the original path. */
|
|
9
|
+
export class DepthDrawMaterials {
|
|
10
|
+
private readonly sources = new Map<THREE.MeshDepthMaterial, Map<number, Variant>>();
|
|
11
|
+
private frame = 0;
|
|
12
|
+
private count = 0;
|
|
13
|
+
|
|
14
|
+
bind(renderer: THREE.WebGLRenderer): () => void {
|
|
15
|
+
this.frame++;
|
|
16
|
+
const original = renderer.renderBufferDirect;
|
|
17
|
+
const cache = this;
|
|
18
|
+
renderer.renderBufferDirect = function (camera, scene, geometry, material, object, group) {
|
|
19
|
+
const selected = scene?.overrideMaterial === material
|
|
20
|
+
? cache.get(material, geometry, object) : material;
|
|
21
|
+
return original.call(this, camera, scene, geometry, selected, object, group);
|
|
22
|
+
};
|
|
23
|
+
return () => { renderer.renderBufferDirect = original; };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private get(source: THREE.Material, geometry: THREE.BufferGeometry, object: THREE.Object3D): THREE.Material {
|
|
27
|
+
if (!(source instanceof THREE.MeshDepthMaterial) || source.transparent ||
|
|
28
|
+
source.map || source.alphaMap || source.displacementMap || source.clippingPlanes ||
|
|
29
|
+
source.onBeforeCompile !== THREE.Material.prototype.onBeforeCompile ||
|
|
30
|
+
source.customProgramCacheKey !== THREE.Material.prototype.customProgramCacheKey ||
|
|
31
|
+
source.onBeforeRender !== THREE.Material.prototype.onBeforeRender ||
|
|
32
|
+
!(object instanceof THREE.Mesh) || object instanceof THREE.SkinnedMesh ||
|
|
33
|
+
Object.keys(geometry.morphAttributes).length ||
|
|
34
|
+
object.onAfterRender !== THREE.Object3D.prototype.onAfterRender) return source;
|
|
35
|
+
const batched = object instanceof THREE.BatchedMesh;
|
|
36
|
+
const instanced = object instanceof THREE.InstancedMesh;
|
|
37
|
+
if (object.onBeforeRender !== (batched ? THREE.BatchedMesh.prototype.onBeforeRender : THREE.Object3D.prototype.onBeforeRender) ||
|
|
38
|
+
(instanced && (object.instanceColor || object.morphTexture))) return source;
|
|
39
|
+
// A batch's color-texture presence must be explicit. Unknown/custom batches
|
|
40
|
+
// keep their original material rather than relying on Three's internals.
|
|
41
|
+
if (batched && Reflect.get(object, 'colorTexture') !== null) return source;
|
|
42
|
+
const key = (batched ? 1 : instanced ? 2 : 0) +
|
|
43
|
+
(source.vertexColors && geometry.getAttribute('color')?.itemSize === 4 ? 4 : 0);
|
|
44
|
+
let variants = this.sources.get(source);
|
|
45
|
+
if (!variants) {
|
|
46
|
+
if (this.count >= 32) return source;
|
|
47
|
+
variants = new Map();
|
|
48
|
+
this.sources.set(source, variants);
|
|
49
|
+
}
|
|
50
|
+
let variant = variants.get(key);
|
|
51
|
+
if (!variant) {
|
|
52
|
+
if (this.count >= 32) return source;
|
|
53
|
+
variant = {material: source.clone(), frame: this.frame, version: source.version};
|
|
54
|
+
variants.set(key, variant);
|
|
55
|
+
this.count++;
|
|
56
|
+
} else if (variant.frame !== this.frame) {
|
|
57
|
+
variant.material.copy(source);
|
|
58
|
+
if (variant.version !== source.version) variant.material.needsUpdate = true;
|
|
59
|
+
variant.version = source.version;
|
|
60
|
+
variant.frame = this.frame;
|
|
61
|
+
}
|
|
62
|
+
return variant.material;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
dispose(): void {
|
|
66
|
+
for (const variants of this.sources.values()) for (const {material} of variants.values()) material.dispose();
|
|
67
|
+
this.sources.clear();
|
|
68
|
+
this.count = 0;
|
|
69
|
+
}
|
|
70
|
+
}
|