Refactor model instance rendering and selection logic in ViewportHost

This commit is contained in:
2026-04-27 00:13:08 +02:00
parent 28294a4a20
commit d64ac05ffe

View File

@@ -6048,6 +6048,23 @@ export class ViewportHost {
) {
this.clearModelInstances();
const displayedModelInstances = this.getDisplayedModelInstances(document);
for (const modelInstance of displayedModelInstances) {
if (!modelInstance.enabled || !modelInstance.visible) {
continue;
}
this.addModelInstanceRenderGroup(
modelInstance,
isModelInstanceSelected(selection, modelInstance.id)
);
}
this.applyShadowState();
}
private getDisplayedModelInstances(document: SceneDocument): ModelInstance[] {
const runtimeModelInstances =
this.currentSimulationScene?.modelInstances ?? null;
const authoredModelInstancesById = new Map(
@@ -6079,49 +6096,91 @@ export class ViewportHost {
animationAutoplay: runtimeModelInstance.animationAutoplay
});
}) ?? getModelInstances(document.modelInstances);
}
for (const modelInstance of displayedModelInstances) {
if (!modelInstance.enabled || !modelInstance.visible) {
continue;
}
const selected = isModelInstanceSelected(selection, modelInstance.id);
const asset = this.projectAssets[modelInstance.assetId];
const loadedAsset = this.loadedModelAssets[modelInstance.assetId];
const renderGroup = createModelInstanceRenderGroup(
modelInstance,
asset,
loadedAsset,
selected,
undefined,
this.displayMode === "wireframe" ? "wireframe" : "normal"
);
applyRendererRenderCategoryFromMaterial(renderGroup);
if (asset?.kind === "model" && modelInstance.collision.visible) {
try {
const generatedCollider = buildGeneratedModelCollider(
modelInstance,
asset,
loadedAsset
);
if (generatedCollider !== null) {
const colliderDebugGroup =
createModelColliderDebugGroup(generatedCollider);
applyRendererRenderCategory(colliderDebugGroup, "overlay");
renderGroup.add(colliderDebugGroup);
}
} catch {
// Validation surfaces unsupported collider modes; the viewport keeps rendering the model.
}
}
this.modelGroup.add(renderGroup);
this.modelRenderObjects.set(modelInstance.id, renderGroup);
private getDisplayedModelInstanceById(
modelInstanceId: string
): ModelInstance | null {
if (this.currentDocument === null) {
return null;
}
this.applyShadowState();
return (
this.getDisplayedModelInstances(this.currentDocument).find(
(modelInstance) => modelInstance.id === modelInstanceId
) ?? null
);
}
private addModelInstanceRenderGroup(
modelInstance: ModelInstance,
selected: boolean
) {
const asset = this.projectAssets[modelInstance.assetId];
const loadedAsset = this.loadedModelAssets[modelInstance.assetId];
const renderGroup = createModelInstanceRenderGroup(
modelInstance,
asset,
loadedAsset,
selected,
undefined,
this.displayMode === "wireframe" ? "wireframe" : "normal"
);
applyRendererRenderCategoryFromMaterial(renderGroup);
if (asset?.kind === "model" && modelInstance.collision.visible) {
try {
const generatedCollider = buildGeneratedModelCollider(
modelInstance,
asset,
loadedAsset
);
if (generatedCollider !== null) {
const colliderDebugGroup =
createModelColliderDebugGroup(generatedCollider);
applyRendererRenderCategory(colliderDebugGroup, "overlay");
renderGroup.add(colliderDebugGroup);
}
} catch {
// Validation surfaces unsupported collider modes; the viewport keeps rendering the model.
}
}
this.modelGroup.add(renderGroup);
this.modelRenderObjects.set(modelInstance.id, renderGroup);
}
private refreshModelInstanceSelectionPresentationForId(
modelInstanceId: string
) {
const renderGroup = this.modelRenderObjects.get(modelInstanceId);
if (renderGroup === undefined) {
return;
}
const modelInstance = this.getDisplayedModelInstanceById(modelInstanceId);
if (modelInstance === null) {
return;
}
syncModelInstanceSelectionShell(
renderGroup,
this.projectAssets[modelInstance.assetId],
isModelInstanceSelected(this.currentSelection, modelInstanceId)
);
applyRendererRenderCategoryFromMaterial(renderGroup);
applyAdvancedRenderingRenderableShadowFlags(
renderGroup,
this.currentWorld !== null &&
(this.currentSimulationScene?.world ?? this.currentWorld)
.advancedRendering.enabled &&
(this.currentSimulationScene?.world ?? this.currentWorld)
.advancedRendering.shadows.enabled &&
this.displayMode === "normal"
);
}
private createEntityRenderObjects(