Skip to content

Commit bf60755

Browse files
christjtChristopher  Tannum
andauthored
refactor: decouple material initialization from CadMaterialManager (#5475)
* refactor: initialize materials in cad node * refactor: cad material manager events --------- Co-authored-by: Christopher Tannum <christopher.tannum@cognitedata.com>
1 parent 4c0e2ab commit bf60755

File tree

14 files changed

+183
-198
lines changed

14 files changed

+183
-198
lines changed

viewer/packages/cad-geometry-loaders/src/CadManager.test.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@ describe(CadManager.name, () => {
1515
let updateHandlerMock: IMock<CadModelUpdateHandler>;
1616

1717
beforeEach(() => {
18-
materialManagerMock = new Mock<CadMaterialManager>()
19-
.setup(p => p.on(It.IsAny(), It.IsAny()))
20-
.returns()
21-
.setup(p => p.off(It.IsAny(), It.IsAny()))
22-
.returns()
23-
.setup(p => p.dispose())
24-
.returns();
18+
materialManagerMock = new Mock<CadMaterialManager>().setup(p => p.dispose()).returns();
2519

2620
cadModelFactoryMock = new Mock<CadModelFactory>().setup(p => p.dispose()).returns();
2721

@@ -56,10 +50,6 @@ describe(CadManager.name, () => {
5650
expect(cadManager.updateCamera).toBeDefined();
5751
});
5852

59-
test('should register materials changed listener on initialization', () => {
60-
materialManagerMock.verify(p => p.on('materialsChanged', It.IsAny()));
61-
});
62-
6353
test('should access budget correctly', () => {
6454
const budget = cadManager.budget;
6555
expect(budget).toBeDefined();
@@ -79,7 +69,6 @@ describe(CadManager.name, () => {
7969
test('should dispose properly', () => {
8070
expect(() => cadManager.dispose()).not.toThrow();
8171
updateHandlerMock.verify(p => p.dispose());
82-
materialManagerMock.verify(p => p.off('materialsChanged', It.IsAny()));
8372
});
8473

8574
test('should access material manager correctly', () => {

viewer/packages/cad-geometry-loaders/src/CadManager.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ export class CadManager {
3636
private readonly _loadingStateChangedTrigger = new EventTrigger<(loadingState: LoadingState) => void>();
3737

3838
private readonly _markNeedsRedrawBound = this.markNeedsRedraw.bind(this);
39-
private readonly _materialsChangedListener = this.handleMaterialsChanged.bind(this);
4039

4140
private readonly _sectorBufferTime = 350;
4241

@@ -68,7 +67,6 @@ export class CadManager {
6867
this._materialManager = materialManger;
6968
this._cadModelFactory = cadModelFactory;
7069
this._cadModelUpdateHandler = cadModelUpdateHandler;
71-
this._materialManager.on('materialsChanged', this._materialsChangedListener);
7270

7371
const consumeNextSector = (sector: ConsumedSector) => {
7472
const modelSymbol = sector.modelIdentifier.revealInternalId;
@@ -136,7 +134,6 @@ export class CadManager {
136134
this._unsubscribeConsumedSectors();
137135
this._unsubscribeLoadingState();
138136
this._loadingStateChangedTrigger.unsubscribeAll();
139-
this._materialManager.off('materialsChanged', this._materialsChangedListener);
140137
}
141138

142139
requestRedraw(): void {
@@ -145,11 +142,14 @@ export class CadManager {
145142

146143
resetRedraw(): void {
147144
this._needsRedraw = false;
145+
this._materialManager.resetRedraw();
148146
[...this._cadModelMap.values()].some(m => m.resetRedraw());
149147
}
150148

151149
get needsRedraw(): boolean {
152-
return this._needsRedraw || [...this._cadModelMap.values()].some(m => m.needsRedraw);
150+
return (
151+
this._needsRedraw || this._materialManager.needsRedraw || [...this._cadModelMap.values()].some(m => m.needsRedraw)
152+
);
153153
}
154154

155155
updateCamera(camera: THREE.PerspectiveCamera, cameraInMotion: boolean): void {
@@ -257,10 +257,6 @@ export class CadManager {
257257
this._needsRedraw = true;
258258
}
259259

260-
private handleMaterialsChanged() {
261-
this.requestRedraw();
262-
}
263-
264260
private updateTreeIndexToSectorsMap(cadModel: CadNode, sector: ConsumedSector): void {
265261
if (cadModel.treeIndexToSectorsMap.isCompleted(sector.metadata.id, RevealGeometryCollectionType.TriangleMesh)) {
266262
return;

viewer/packages/cad-model/src/CadModelFactory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class CadModelFactory {
3838
const geometryClipBox = determineGeometryClipBox(geometryFilter, metadata);
3939
const modelMetadata = createClippedModel(metadata, geometryClipBox);
4040

41-
const { modelIdentifier, scene, format, formatVersion } = modelMetadata;
41+
const { modelIdentifier, format, formatVersion } = modelMetadata;
4242
const modelType: SupportedModelTypes = 'cad';
4343
MetricsLogger.trackLoadModel(
4444
{
@@ -49,8 +49,8 @@ export class CadModelFactory {
4949
);
5050
const sectorRepository = this.getSectorRepository(format, formatVersion);
5151

52-
this._materialManager.addModelMaterials(modelIdentifier.revealInternalId, scene.maxTreeIndex);
5352
const cadModel = new CadNode(modelMetadata, this._materialManager, sectorRepository);
53+
this._materialManager.addModelMaterials(modelIdentifier.revealInternalId, cadModel.cadMaterial);
5454

5555
if (modelMetadata.geometryClipBox !== null) {
5656
const clipBox = transformToThreeJsSpace(modelMetadata.geometryClipBox, modelMetadata);

viewer/packages/cad-model/src/picking/PickingHandler.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import * as THREE from 'three';
66

7-
import { CadMaterialManager } from '@reveal/rendering';
7+
import { CadMaterialManager, RenderMode } from '@reveal/rendering';
88
import { IntersectInput } from '@reveal/model-base';
99

1010
import { PickingHandler } from './PickingHandler';
@@ -29,7 +29,11 @@ describe(PickingHandler.name, () => {
2929
const cadNode = createCadModel(1, 2).cadNode;
3030

3131
beforeEach(() => {
32-
const materialManagerMock = new Mock<CadMaterialManager>().setup(p => p.setRenderMode(It.IsAny())).returns();
32+
const materialManagerMock = new Mock<CadMaterialManager>()
33+
.setup(p => p.getRenderMode())
34+
.returns(RenderMode.Color)
35+
.setup(p => p.setRenderMode(It.IsAny()))
36+
.returns();
3337
pickingHandler = new PickingHandler(renderer, materialManagerMock.object(), new SceneHandler());
3438
});
3539

viewer/packages/cad-model/src/picking/PickingHandler.ts

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -230,21 +230,13 @@ export class PickingHandler {
230230
}
231231

232232
private async pickTreeIndex(input: TreeIndexPickingInput, shouldRunAsync: boolean): Promise<number | undefined> {
233-
const { cadNode } = input;
234-
const previousRenderMode = cadNode.renderMode;
235-
cadNode.renderMode = RenderMode.TreeIndex;
236-
let pixelBuffer: Uint8Array;
237-
try {
238-
pixelBuffer = await this.pickPixel(
239-
input,
240-
this._treeIndexRenderPipeline,
241-
this._clearColor,
242-
this._clearAlpha,
243-
shouldRunAsync
244-
);
245-
} finally {
246-
cadNode.renderMode = previousRenderMode;
247-
}
233+
const pixelBuffer = await this.pickPixel(
234+
input,
235+
this._treeIndexRenderPipeline,
236+
this._clearColor,
237+
this._clearAlpha,
238+
shouldRunAsync
239+
);
248240

249241
if (pixelBuffer[3] === 0) {
250242
return;
@@ -260,20 +252,15 @@ export class PickingHandler {
260252
}
261253

262254
private async pickDepth(input: PickingInput, shouldRunAsync: boolean): Promise<number> {
263-
const { cadNodes } = input;
264-
const previousRenderMode = cadNodes[0].renderMode;
265-
cadNodes.forEach(cadeNode => (cadeNode.renderMode = RenderMode.Depth));
266255
const pixelBuffer = await this.pickPixel(
267256
input,
268257
this._depthRenderPipeline,
269258
this._clearColor,
270259
this._clearAlpha,
271260
shouldRunAsync
272261
);
273-
cadNodes.forEach(cadeNode => (cadeNode.renderMode = previousRenderMode));
274262

275-
const depth = this.unpackRGBAToDepth(pixelBuffer);
276-
return depth;
263+
return this.unpackRGBAToDepth(pixelBuffer);
277264
}
278265

279266
private getPosition(input: PickingInput, viewZ: number): THREE.Vector3 {

viewer/packages/cad-model/src/wrappers/CadNode.ts

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ import {
88
PrioritizedArea,
99
type NodeTransformProvider
1010
} from '@reveal/cad-styling';
11+
import throttle from 'lodash/throttle';
1112
import { SectorScene, CadModelMetadata, RootSectorNode, WantedSector, ConsumedSector } from '@reveal/cad-parsers';
1213
import { SectorRepository } from '@reveal/sector-loader';
1314
import { ParsedGeometry } from '@reveal/sector-parser';
14-
import { CadMaterialManager, RenderMode, setModelRenderLayers, StyledTreeIndexSets } from '@reveal/rendering';
15+
import {
16+
CadMaterialManager,
17+
setModelRenderLayers,
18+
StyledTreeIndexSets,
19+
createCadMaterial,
20+
type CadMaterial
21+
} from '@reveal/rendering';
1522

1623
import { Group, Object3D, Plane, Matrix4, Object3DEventMap } from 'three';
1724

@@ -37,9 +44,10 @@ export class CadNode extends Object3D<Object3DEventMap & { update: undefined }>
3744

3845
private readonly _sourceTransform: Matrix4;
3946
private readonly _customTransform: Matrix4;
40-
private readonly _setModelRenderLayers = () => this.setModelRenderLayers();
4147
private readonly _batchedGeometryMeshGroup: Group;
4248
private readonly _styledTreeIndexSets: StyledTreeIndexSets;
49+
//cleaup type
50+
private readonly _cadMaterial: CadMaterial;
4351

4452
private _isDisposed: boolean = false;
4553

@@ -59,22 +67,37 @@ export class CadNode extends Object3D<Object3DEventMap & { update: undefined }>
5967
this._sectorRepository = sectorRepository;
6068
this._modelIdentifier = model.modelIdentifier;
6169
this.treeIndexToSectorsMap = new TreeIndexToSectorsMap(model.scene.maxTreeIndex);
62-
const back = this._materialManager.getModelBackTreeIndices(model.modelIdentifier.revealInternalId);
63-
const ghost = this._materialManager.getModelGhostedTreeIndices(model.modelIdentifier.revealInternalId);
64-
const inFront = this._materialManager.getModelInFrontTreeIndices(model.modelIdentifier.revealInternalId);
65-
const visible = this._materialManager.getModelVisibleTreeIndices(model.modelIdentifier.revealInternalId);
70+
this._cadMaterial = createCadMaterial(model.scene.maxTreeIndex);
6671

6772
this._styledTreeIndexSets = {
68-
back,
69-
ghost,
70-
inFront,
71-
visible
73+
back: this._cadMaterial.nodeAppearanceTextureBuilder.regularNodeTreeIndices,
74+
ghost: this._cadMaterial.nodeAppearanceTextureBuilder.ghostedNodeTreeIndices,
75+
inFront: this._cadMaterial.nodeAppearanceTextureBuilder.infrontNodeTreeIndices,
76+
visible: this._cadMaterial.nodeAppearanceTextureBuilder.visibleNodeTreeIndices
7277
};
7378

79+
const materialUpdateThrottleDelay = 75;
80+
const updateMaterialsCallback: () => void = throttle(
81+
() => {
82+
if (this._cadMaterial.nodeAppearanceTextureBuilder.needsUpdate) {
83+
this._cadMaterial.nodeAppearanceTextureBuilder.build();
84+
}
85+
this._needsRedraw = true;
86+
this.setModelRenderLayers();
87+
},
88+
materialUpdateThrottleDelay,
89+
{
90+
leading: true,
91+
trailing: true
92+
}
93+
);
94+
95+
this._cadMaterial.nodeAppearanceProvider.on('changed', updateMaterialsCallback);
96+
7497
this._batchedGeometryMeshGroup = new Group();
7598
this._batchedGeometryMeshGroup.name = 'Batched Geometry';
7699

77-
const materials = materialManager.getModelMaterials(model.modelIdentifier.revealInternalId);
100+
const materials = this._cadMaterial.materials;
78101
this._geometryBatchingManager = new MultiBufferBatchingManager(
79102
this._batchedGeometryMeshGroup,
80103
materials,
@@ -105,8 +128,6 @@ export class CadNode extends Object3D<Object3DEventMap & { update: undefined }>
105128

106129
this._sourceTransform = new Matrix4().copy(model.modelMatrix);
107130
this._customTransform = new Matrix4();
108-
109-
this.materialManager.on('materialsChanged', this._setModelRenderLayers);
110131
}
111132

112133
get needsRedraw(): boolean {
@@ -117,26 +138,30 @@ export class CadNode extends Object3D<Object3DEventMap & { update: undefined }>
117138
this._needsRedraw = false;
118139
}
119140

141+
// TODO: cleanup type
142+
get cadMaterial(): CadMaterial {
143+
return this._cadMaterial;
144+
}
145+
120146
get nodeTransformProvider(): NodeTransformProvider {
121-
return this._materialManager.getModelNodeTransformProvider(this._cadModelMetadata.modelIdentifier.revealInternalId);
147+
return this._cadMaterial.nodeTransformProvider;
122148
}
123149

124150
get nodeAppearanceProvider(): NodeAppearanceProvider {
125-
return this._materialManager.getModelNodeAppearanceProvider(
126-
this._cadModelMetadata.modelIdentifier.revealInternalId
127-
);
151+
return this._cadMaterial.nodeAppearanceProvider;
128152
}
129153

130154
get defaultNodeAppearance(): NodeAppearance {
131-
return this._materialManager.getModelDefaultNodeAppearance(this._cadModelMetadata.modelIdentifier.revealInternalId);
155+
return this._cadMaterial.nodeAppearanceTextureBuilder.getDefaultAppearance();
132156
}
133157

134158
set defaultNodeAppearance(appearance: NodeAppearance) {
135-
this._materialManager.setModelDefaultNodeAppearance(
136-
this._cadModelMetadata.modelIdentifier.revealInternalId,
137-
appearance
138-
);
159+
this._cadMaterial.nodeAppearanceTextureBuilder.setDefaultAppearance(appearance);
160+
if (this._cadMaterial.nodeAppearanceTextureBuilder.needsUpdate) {
161+
this._cadMaterial.nodeAppearanceTextureBuilder.build();
162+
}
139163
this.setModelRenderLayers();
164+
this._needsRedraw = true;
140165
}
141166

142167
get clippingPlanes(): Plane[] {
@@ -163,18 +188,6 @@ export class CadNode extends Object3D<Object3DEventMap & { update: undefined }>
163188
return this._rootSector;
164189
}
165190

166-
get materialManager(): CadMaterialManager {
167-
return this._materialManager;
168-
}
169-
170-
set renderMode(mode: RenderMode) {
171-
this._materialManager.setRenderMode(mode);
172-
}
173-
174-
get renderMode(): RenderMode {
175-
return this._materialManager.getRenderMode();
176-
}
177-
178191
get isDisposed(): boolean {
179192
return this._isDisposed;
180193
}
@@ -246,7 +259,6 @@ export class CadNode extends Object3D<Object3DEventMap & { update: undefined }>
246259

247260
public dispose(): void {
248261
this.nodeAppearanceProvider.dispose();
249-
this.materialManager.off('materialsChanged', this._setModelRenderLayers);
250262
this._materialManager.removeModelMaterials(this._cadModelMetadata.modelIdentifier.revealInternalId);
251263
this._geometryBatchingManager?.dispose();
252264

viewer/packages/rendering/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright 2021 Cognite AS
33
*/
44

5-
export { CadMaterialManager } from './src/CadMaterialManager';
5+
export { CadMaterialManager, createCadMaterial, CadMaterial } from './src/CadMaterialManager';
66
export { PointCloudMaterialManager } from './src/PointCloudMaterialManager';
77

88
export {

0 commit comments

Comments
 (0)