stride icon indicating copy to clipboard operation
stride copied to clipboard

feat: Hierarchical Model Importer

Open noa7 opened this issue 3 months ago • 45 comments

This PR adds an “Split hierarchy” workflow for model import: when enabled, Stride imports one Model per mesh (named after the mesh) and automatically generates a Prefab that mirrors the FBX node hierarchy. When disabled, the import produces a single combined Model (no “(All)” suffix).

What’s in this PR-

Split hierarchy checkbox in Add asset → 3D model dialog.

Remembers last value per project.

Behavior (per mode)

Split hierarchy = ON

Imports N Model assets (one per mesh) named: "<ModelName>-<MeshName>" (sanitized; auto-uniquified with -1, -2, …).

Creates a Prefab named "<ModelName> Prefab" that replicates the FBX hierarchy (one Entity per node, correct parent/child relationships).

Each Entity that hosts a mesh gets a ModelComponent referencing the corresponding per-mesh Model.

Each per-mesh Model keeps only the material(s) it actually uses\

Split hierarchy = OFF

Imports a single Model named exactly "<ModelName>"

noa7 avatar Sep 17 '25 04:09 noa7

@noa7 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@dotnet-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@dotnet-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@dotnet-policy-service agree company="Microsoft"

Contributor License Agreement

@dotnet-policy-service agree

noa7 avatar Sep 17 '25 20:09 noa7

Looks like materials are not handled properly: every individual object is set to the same material.

The prefab's hierarchy is almost right, there is an additional RootNode created and a weird parenting issue, see the following comparison: image

Here's the file I used for testing - this is not CC0, do not use in projects.

Eideren avatar Sep 18 '25 10:09 Eideren

Thanks for sharing the test file. I’ve checked in updates, and both issues are now fixed:

  1. The prefab in Stride now exactly replicates the FBX hierarchy as seen in Blender- no extra "RootNode"
  2. Material assignments on individual sub-meshes remain intact after import

@Eideren

noa7 avatar Sep 19 '25 08:09 noa7

We're back to the previous issue with the materials, we need to only have the materials that are assigned to an object on that object, not every material that was contained in the original scene.

Also, the pivot position for individual models is not retained, they all have their pivot set to the origin instead of wherever it actually is in the file.

Eideren avatar Sep 19 '25 12:09 Eideren

are you on latest? it imports fine my side

image

noa7 avatar Sep 19 '25 12:09 noa7

The vertices are at the right position in world space, but each mesh's pivot point is not right below the model, like it is in the file, it is set to the origin. For example, if you only place the bookends model in the world, setting its entity's position to 0,0,0 should center the object around the origin image image The prefab entity for a given model should have its position moved to match wherever the model is in the imported file, the model asset itself should not have any transformation applied.

Eideren avatar Sep 19 '25 12:09 Eideren

Makes sense, thanks for pointing out, This is now fixed.

With this latest-

  1. Only the material applied on mesh are visible in inspector
  2. The relative positiong of each item in prefab based of entity data in scene by storing each mesh's TRS data at its nodeinfo object that prefab is constructed with. And each mesh pivot in scene matches to that in source model
Capture Capture1

@Eideren

noa7 avatar Sep 21 '25 03:09 noa7

You haven't thoroughly gone through the LLM's work there it seems, there's a fairly large amount of redundant logic, and comments that are clearly targeted at someone interacting with an LLM, not at describing the logic being implemented.

I'm okay with reviewing someone's work, not going over what an LLM spit out, that is your burden to carry - and you're definitely capable of that, I have seen you write better stuff than this.

I haven't gone through the whole thing yet, but do go over your entire PR and clean things up, there's a lot of low hanging fruits I have not marked.

You could also look into using/enabling nullable, there's a bunch of null checks and tests that are redundant or definitely should throw in the null case.

Got it. I was focusing on getting it fully functional before moving on to cleanup and optimization, since the prefab generation feature is a bit tricker than I anticipated. I’ve removed any mechnical commets. Committed the latest version with fixes and a cleaner codebase @Eideren

noa7 avatar Sep 23 '25 10:09 noa7

Throws in ResetMaterialsOnPrefabItems when importing into a folder, that method definitely required a second cleanup pass anyway. How about you replace those strings and pass references or ids around, this goes for other methods too. So many string manipulation and lookups, it's no wonder the whole thing throws if we so much as look at it.

Eideren avatar Sep 23 '25 20:09 Eideren

No more string manipulations by storing source mesh name variable in ModelAsset, checked in latest @Eideren

noa7 avatar Sep 26 '25 17:09 noa7

Most of my comments have not been addressed, moving this to draft while you take care of those. Feel free to set it to ready once it is actually ready for review.

Eideren avatar Sep 27 '25 11:09 Eideren

Most of my comments have not been addressed, moving this to draft while you take care of those. Feel free to set it to ready once it is actually ready for review.

Can you tell which ones specifically, I gone through all and made necessary cahnges!

noa7 avatar Sep 27 '25 12:09 noa7

Those listed below the following message https://github.com/stride3d/stride/pull/2898#issuecomment-3323404313

Eideren avatar Sep 27 '25 12:09 Eideren

Those listed below the following message #2898 (comment)

Its importing fine for me in a folder on latest and have removed strig manipulations?

noa7 avatar Sep 27 '25 12:09 noa7

Yes, I got that, but you haven't gone through the review I made below the message I linked here https://github.com/stride3d/stride/pull/2898#issuecomment-3323404313 This stuff: image

Eideren avatar Sep 27 '25 12:09 Eideren

Yes, I got that, but you haven't gone through the review I made below the message I linked here #2898 (comment) This stuff:

I really can't see that list my side of github :)

image

noa7 avatar Sep 27 '25 12:09 noa7

Ah, okay, my bad, that's on me. Give me a sec.

Eideren avatar Sep 27 '25 12:09 Eideren

Removed the filename-based mesh selection and made it an explicit part of the asset data. The chosen mesh now comes from ModelAsset.MeshName, which is passed via ModelAssetCompiler > ImportThreeDCommand to MeshConverter.KeepOnlyMeshByName. The old DecideKeptMeshIndexFromOutput logic is removed @Eideren

noa7 avatar Oct 12 '25 02:10 noa7

Did you test your changes ?

Eideren avatar Oct 12 '25 17:10 Eideren

Yes tested with the room model file

On Sun 12. Oct 2025 at 20:20, Eideren @.***> wrote:

Eideren left a comment (stride3d/stride#2898) https://github.com/stride3d/stride/pull/2898#issuecomment-3394971751

Did you test your changes ?

— Reply to this email directly, view it on GitHub https://github.com/stride3d/stride/pull/2898#issuecomment-3394971751, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF5T3BZKSPMEKIHDVGZGS2T3XKEXHAVCNFSM6AAAAACGW4SEGGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTGOJUHE3TCNZVGE . You are receiving this because you were mentioned.Message ID: @.***>

noa7 avatar Oct 12 '25 21:10 noa7

Well, not sure what you did test, but I can still repro the naming issue I mentioned

Eideren avatar Oct 12 '25 21:10 Eideren

@Eideren can you point which naming issue?

noa7 avatar Oct 12 '25 22:10 noa7

The one I mentioned there as I said https://github.com/stride3d/stride/pull/2898#discussion_r2392252314 - Changing the name of a model asset in the editor changes the actual mesh that gets imported

Eideren avatar Oct 13 '25 08:10 Eideren

My mistake, overlooked that part. I’ve checked in updates, storing mesh ID as a key pointer in ModelAsset, which is set only once at time of creation and remains unchanged on renaming etc. @Eideren

noa7 avatar Oct 13 '25 14:10 noa7

If I select this option from the context menu, the model has a bunch of new entries created for its materials instead of just the ones used image

Eideren avatar Oct 13 '25 18:10 Eideren

Fixed. It still reimports the mesh upon update from source but will not add extra materials @Eideren

noa7 avatar Oct 14 '25 03:10 noa7

If a model has multiple materials assigned it ends up being split across two models Untitled.zip - assigned a different material for one of the cushion on the bed. See what I mean by saying you should test your PR more thoroughly, we shouldn't be having this much back and forth.

Eideren avatar Oct 14 '25 09:10 Eideren

Can you tell which mesh to look for in structure? And you mean if material has multiple materials its only applying first one?

noa7 avatar Oct 14 '25 09:10 noa7

There are two cushions on the bed, one of them is of the same material as the bed, while the other has a different one assigned to it, both of them are part of the bed model in the original fbx file. When imported as a split, the bed gets separated into two model asset, one for the bed and cushion of material A and another with only the other cushion with material B

Eideren avatar Oct 14 '25 09:10 Eideren

Fixed material mapping mismatch between Stride and Assimp. Stride importer has one material per mesh, while Assimp exports multiple submeshes for multi-material meshes is what makes this tricky. Updated the mesh conversion logic to merge these correctly so materials now display correctly. @Eideren

noa7 avatar Oct 17 '25 08:10 noa7