Android及ARCore中如何隐藏渲染3D模型的特定子节点?
Hey there! I've worked with ARCore on Android quite a bit, so let's walk through how to hide specific child nodes of a 3D model—including replicating that ARKit-style "find by name" functionality you're looking for. Here's what you need to know, broken down by the most common ARCore rendering frameworks:
Sceneform was the go-to for ARCore model rendering for a long time, and it makes node management straightforward. Here's how to find a child node by name and hide it:
Step 1: Load your model and get the root node
First, load your glTF/glb model and attach it to an AnchorNode (or a regular Node). Once loaded, grab the root node of your model:
ModelRenderable.builder() .setSource(context, R.raw.your_3d_model) .build() .thenAccept { renderable -> val modelRootNode = Node().apply { this.renderable = renderable name = "ModelRoot" // Optional: Name the root for easier debugging } // Attach the model node to your AR anchor node yourAnchorNode.addChild(modelRootNode) // Now find and hide your target child node val targetNode = findNodeByName(modelRootNode, "YourTargetChildName") targetNode?.isEnabled = false } .exceptionally { throwable -> Log.e("ARCore", "Failed to load model", throwable) null }
Step 2: Recursive node lookup method
Sceneform doesn't have a built-in findChildByName method, so we'll write a recursive function to search the node tree:
private fun findNodeByName(rootNode: Node?, targetName: String): Node? { if (rootNode == null) return null // Check if the current node matches the target name if (rootNode.name == targetName) { return rootNode } // Recursively check all child nodes for (childNode in rootNode.children) { val foundNode = findNodeByName(childNode, targetName) if (foundNode != null) return foundNode } return null }
How it works
Setting isEnabled = false will completely hide the node and all its children, plus disable any interaction with it. If you only want to hide the node's renderable but keep interactions active, you can set targetNode.renderable = null instead.
Google now recommends using Filament for ARCore rendering, as it's more lightweight and flexible. Here's how to achieve the same result with Filament:
Step 1: Load your model and get the root entity
Filament uses an entity-component system, so your model will be represented as a tree of Entity objects. Load your model first:
val filamentEngine = ArCoreSession.getSession(context).engine val assetLoader = AssetLoader.create(filamentEngine) val gltfLoader = GltfLoader.create(filamentEngine) val resourceLoader = ResourceLoader.create(filamentEngine) // Load the model from raw resources context.resources.openRawResource(R.raw.your_3d_model).use { inputStream -> val asset = gltfLoader.loadAsset(inputStream) assetLoader.loadResources(asset, resourceLoader) val rootEntity = asset.root // Find and hide the target entity val targetEntity = findEntityByName(filamentEngine, rootEntity, "YourTargetChildName") targetEntity?.let { hideEntity(filamentEngine, it) } }
Step 2: Recursive entity lookup and hide methods
// Find an entity by name in the entity tree private fun findEntityByName(engine: Engine, root: Entity, targetName: String): Entity? { val nameManager = engine.nameComponentManager // Check if the current entity has a name matching the target if (nameManager.hasComponent(root)) { if (nameManager.getName(root) == targetName) { return root } } // Recursively check all child entities val transformManager = engine.transformManager val childCount = transformManager.getChildCount(root) for (i in 0 until childCount) { val childEntity = transformManager.getChild(root, i) val foundEntity = findEntityByName(engine, childEntity, targetName) if (foundEntity != null) return foundEntity } return null } // Hide the target entity private fun hideEntity(engine: Engine, entity: Entity) { val transformManager = engine.transformManager val currentVisibility = transformManager.getVisibility(entity) // Remove the VISIBLE flag from the entity's visibility mask transformManager.setVisibility(entity, currentVisibility and ~TransformManager.Visibility.VISIBLE) }
- Model Naming: Make sure your 3D model's child components have clear, unique names set in your 3D editor (like Blender or Maya) before exporting to glTF/glb. Without proper names, the lookup will fail.
- Submeshes vs. Nodes: If your model's child parts are submeshes within a single node (not separate nodes), use Sceneform's
setSubmeshEnabledmethod instead:val renderable = modelRootNode.renderable as ModelRenderable val submeshIndex = renderable.submeshNames.indexOf("TargetSubmesh") if (submeshIndex != -1) { renderable.setSubmeshEnabled(submeshIndex, false) }
内容的提问来源于stack exchange,提问作者raviteja

