Autodesk Forge Viewer:如何隔离自定义对象?
Got it, let's break down why your custom room objects aren't responding to the viewer.isolate() call—even though you can select them and get their DbIds correctly. The core issue here is that simply setting a DbId on your fragments doesn't register those objects with the Viewer's InstanceTree (the structure that powers selection, isolation, and other scene navigation features). Here's how to fix it:
Why the Current Approaches Aren't Working
When you use modelBuilder.changeFragmentsDbId(), you're only updating the DbId stored on the fragment itself. But the Viewer's isolate() method relies on the InstanceTree to locate and manipulate objects. If your custom DbIds (whether negative or above the max existing) aren't registered in the InstanceTree, the Viewer can't find them to isolate.
The selection event works because it directly reads the DbId from the clicked fragment, bypassing the InstanceTree check for that step.
Step-by-Step Fix
1. Use Positive DbIds (Avoid Negative Values)
Viewer's internal logic is optimized for positive DbIds (since native IFC models always use positive integers). Negative DbIds might get filtered out during operations like isolation, so stick with the "above max existing DbId" approach.
2. Get the Real Max DbId from the InstanceTree
First, correctly fetch the highest DbId used by the original model. Don't rely on a hardcoded value—use the InstanceTree to enumerate all nodes:
function getMaxDbId(model) { let maxDbId = 0; const instanceTree = model.getInstanceTree(); // Enumerate all nodes starting from the root instanceTree.enumNodeChildren(instanceTree.getRootId(), (dbId) => { if (dbId > maxDbId) maxDbId = dbId; }, true); // true = include nested children return maxDbId; }
3. Register Custom DbIds in the InstanceTree
After setting the fragment's DbId, create a corresponding node in the InstanceTree and refresh it. This tells the Viewer about your custom objects:
// Get the model and max DbId const model = this.viewer.model; const maxDbId = getMaxDbId(model); // Add your room fragment as before const roomFragId = this.modelBuilder.addFragment(roomGeometryId, materialName, transform); const customDbId = maxDbId + roomFragId; this.modelBuilder.changeFragmentsDbId(roomFragId, customDbId); // Register the custom DbId in the InstanceTree const instanceTree = model.getInstanceTree(); // Create a new node: (dbId, parentDbId, nodeName, isLeaf) instanceTree.createNode(customDbId, instanceTree.getRootId(), `Custom Room ${customDbId}`, true); // Refresh the InstanceTree and notify the Viewer to update instanceTree.refresh(); this.viewer.impl.invalidate(true); // Force a scene redraw
4. Test the Isolate Call
Now when you call viewer.isolate(customDbId), the Viewer will find the registered node in the InstanceTree and isolate your custom room object correctly.
Additional Checks
- Ensure your custom fragments are fully added to the scene before calling
isolate(). You can listen for thegeometry.loadedevent from the ModelBuilder to confirm. - Verify the DbId exists in the InstanceTree with
model.getInstanceTree().containsDbId(customDbId)before calling isolate.
内容的提问来源于stack exchange,提问作者Toni Maccheroni

