vsg-dev / vsgXchange

Utility library for converting data+materials to/from VulkanSceneGraph
MIT License
65 stars 40 forks source link

Node returned by vsg::read_cast() is not always the root-node of the loaded 3D asset file #155

Closed drywolf closed 4 months ago

drywolf commented 1 year ago

Hi, I am using VSG + vsgXchange to load 3D asset files (of different formats) into an application and now I am trying to show a "TreeView" of the loaded VSG graph in the app UI.

This is when I noticed that sometimes (most times?) there is one additional vsg::MatrixTransform node at the root of the scene, that is not there in the original asset-file.

I see this extra node is introduced to the scene-graph by the following code:

https://github.com/vsg-dev/vsgXchange/blob/bf17a9fb68fb06b1919ed9b1b12eec774fc0e116/src/assimp/assimp.cpp#L762-L771

(this transform-node is used to normalize the coordinate-system conventions, that are often different for the different 3D file formats, makes total sense πŸ‘)

However, in my UI I do not ever to want to see this node, I want the UI TreeView to always start with the original root node of the scene, as it was stored in the 3D asset file.

One way to fix this, could be to set a special auxiliary "marker" to the "true" scene-root node in assimp.cpp like so:

diff --git forkSrcPrefix/src/assimp/assimp.cpp forkDstPrefix/src/assimp/assimp.cpp
index 27fca07441380162edbf07e1d741a7c8852c6fd6..292ef02a5e5f50bbbe6a72a3f0d23e041337d2a4 100644
--- forkSrcPrefix/src/assimp/assimp.cpp
+++ forkDstPrefix/src/assimp/assimp.cpp
@@ -795,6 +795,8 @@ vsg::ref_ptr<vsg::Node> SceneConverter::visit(const aiScene* in_scene, vsg::ref_
         if (!vsg_scene) return {};
     }

+    // this marks the true root-node of the loaded asset file
+    vsg_scene->setValue("is_asset_root", true);

     if (auto transform = processCoordinateFrame(ext))
     {

This would allow me in my application code to check for this "marker" when I am traversing the scene-graph to build the UI TreeView, and only include nodes below the node that has the "is_asset_root" label.

@robertosfield Do you see any other / any better way for me to always know which of the nodes returned from vsgXchange is the "true" root-node of the asset-file ? (if vsgXchange could always return the "true" root-node of the 3D scene it would be preferable, but I understand that this would need a very different solution to compensate for the coordinate-system differences)

What are your thoughts on this? I would be happy to contribute a PR if we can find a solution that would work even better than the above.

Thanks

robertosfield commented 1 year ago

Quick reply as I in transit. Have a look at vsg:: Options for it coordinate frame hints

On Fri, 21 Jul 2023, 12:42 Wolfgang Steiner, @.***> wrote:

Hi, I am using VSG + vsgXchange to load 3D asset files (of different formats) into an application and now I am trying to show a "TreeView" of the loaded VSG graph in the app UI.

This is when I noticed that sometimes (most times?) there is one additional vsg::MatrixTransform node at the root of the scene, that is not there in the original asset-file as it is saved.

I see that this extra node is introduced to the scene-graph by the following code:

https://github.com/vsg-dev/vsgXchange/blob/master/src/assimp/assimp.cpp#L762,L771 (this transform-node is used to normalize the coordinate-system conventions, that are often different for the different 3D file formats, makes total sense πŸ‘)

However, in my UI I do not ever to want to see this node, I want the UI TreeView to always start with the original root node of the scene, as it was stored in the 3D asset file.

One way to fix this, could be to set a special auxiliary "marker" to the "true" scene-root node in assimp.cpp like so:

diff --git forkSrcPrefix/src/assimp/assimp.cpp forkDstPrefix/src/assimp/assimp.cpp index 27fca07441380162edbf07e1d741a7c8852c6fd6..292ef02a5e5f50bbbe6a72a3f0d23e041337d2a4 100644--- forkSrcPrefix/src/assimp/assimp.cpp+++ forkDstPrefix/src/assimp/assimp.cpp@@ -795,6 +795,8 @@ vsg::ref_ptr SceneConverter::visit(const aiScene* inscene, vsg::ref if (!vsg_scene) return {}; }

  • // this marks the true root-node of the loaded asset file+ vsg_scene->setValue("is_asset_root", true);

    if (auto transform = processCoordinateFrame(ext)) {

This would allow me in my application code to check for this "marker" when I am traversing the scene-graph to build the UI TreeView, and only include nodes below the node that has the "is_asset_root" label.

@robertosfield https://github.com/robertosfield Do you see any other / any better way for me to always know which of the nodes returned from vsgXchange is the "true" root-node of the asset-file ? (if vsgXchange could always return the "true" root-node of the 3D scene it would be preferable, but I understand that this would need a very different solution to compensate for the coordinate-system differences)

What are your thoughts on this? I would be happy to contribute a PR if we can find a solution that would work even better than the above.

Thanks

β€” Reply to this email directly, view it on GitHub https://github.com/vsg-dev/vsgXchange/issues/155, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKEGUH2I2HJPQSK4A4EGS3XRJTINANCNFSM6AAAAAA2SXG4XU . You are receiving this because you were mentioned.Message ID: @.***>

drywolf commented 1 year ago

Have a look at vsg:: Options for it coordinate frame hints

Hi, I want to keep the coordinate conversion that vsgXchange is doing (that is actually a great feature) But for showing the scene-graph in the UI, I just need a consistent & reliable! way to show only the scene-graph starting from the actual 3D asset root-node.

Right now, after loading a scene, I have no way of telling if the returned node is the "real" root of the scene-file, or it is the extra coordinate-conversion node that has been inserted by vsgXchange.

robertosfield commented 1 year ago

On Fri, 21 Jul 2023 at 14:44, Wolfgang Steiner @.***> wrote:

But for showing the scene-graph in the UI, I just need a consistent & reliable! way to show only the scene-graph starting from the 3D asset root-node ... right now after loading a scene, I can not tell if the returned node is the "real" root of the scene-file, or the extra coordinate-conversion node.

I don't think we'll ever get 1:1 mapping of a modeller tools object hierarchy represented when using Assimp, let alone after we've then done mapping of the Assump graph to the extras required fpr rendering within the VSG.

THe only way to get a 1:1 mapping would be to have a format specific loader and have custom nodes that correspond with the 3rd party tools. This is possible but obviously requires more work than just reusing a general purpose loader like Assimp.

Longer term I do wonder if GLTF might deserve treatment in this way - with native read/write support. Whether this would be as part of vsgXchange or a vsgGLTF library, or integrated into the core VSG I don't know. It's really just one of many possibilities for things we might want to do in the future.

Message ID: @.***>

drywolf commented 1 year ago

I don't think we'll ever get 1:1 mapping of a modeller tools object hierarchy represented when using Assimp, let alone after we've then done mapping of the Assump graph to the extras required fpr rendering within the VSG.

Yeah I feel that ... question will be if it can be possible to keep certain meta-data around in the VSG nodes that would allow users to still present the original scene-structure in UIs.

In my case, I am already starting to build a secondary separate tree-structure that is built from the VSG graph right after it has been loaded via vsgXchange. This is the tree-structure that I can show in the app's UI ... it is especially necessary for me to take a "snapshot" of the original tree-structure, because right after loading the VSG graph, I am doing heavy modifications to the graph to enable things like highlighting a selected node, or render the scene with a wireframe overlayed on top. (so after those changes, the VSG graph looks very much different & more complicated than what was initially produced by vsgXchange)

About the original topic: For my purposes I need to be able to tell which node is the actual root-node of the 3D asset, while still having the automatic coordinate-conversions. So I will create a fork of vsgXchange for my own purposes and just put some Auxiliary label-value on the "true" root-node, so I can handle it accordingly for the UI.

robertosfield commented 1 year ago

Branching vsgXchange is going make it awkward to keep tracking of changes to vsgXchange and the with it the VSG, as sometimes changes to the VSG require updates to vsgXchange. I would recommend only temporary branching if you really have to do it.

While it's inappropriate to graft user specific code into the core VSG and vsgXchange there may be ways of achieving what you want to do with keeping code within your application, or us coming up with a general purpose approach to these types of tasks.

FYI, my plan is write scene graph optimizes that will insert/remove/re-organize loaded scene graphs to address performance issues associated with how models are often presented from loaders. For instance the vsgXchange::assimp loader doesn't currently insert any CullGroup/CullNode into the scene graph or do any start sorting and batching, these will be something we'll want to add to improve performance out of the box, rather than rely on post processing of the loaded scene gaphs. Such optimization features will be something we'll want to control so if users don't need them they are set what optimization are permitted and what should be maintained.

This customizable optimization scheme might be a place for also tagging extra information, As I haven't started any detailed design work on the optimization side I can't say what the API might be at this point, only that it's something to be aware of as part of the evolution of the VSG, these changes sometimes can provide other opportunities as you work through refactoring the code - the multi descriptor set changes to GraphicsPipelineConfigurator is just such an example.

drywolf commented 1 year ago

Hi, I am integrating VSG into a 2D/3D content authoring application. So good performance is just one of the many features that I am looking for in the VSG library.

Some of the other features that the application needs from VSG are:

(I'm just saying this to illustrate that I need to fork VSG/vsgXchange anyway, to implement some of the features that are not there yet)

btw. @robertosfield ... do you already have some architecture in mind for doing these described forms of keyframe animations ? If I know which direction would fit best for your general design of VSG, then I might be able to submit a PR once I have those features working in my forks.

Thanks

robertosfield commented 1 year ago

I plan on adding animation support as you outline along with support for it in the vsgXchange::assimp loader. First pass would likely be to use assimp specs for specifying animations. Where possible I'd like to handle the work on the GPU.

Implementation details are completely open at this point as I haven't started any design work on it. If you get there first then I'd welcome a PR. If it heads off in a direction that I don't think fits then I can always suggest alternatives, or use the PR as a reference when implementing the final official approach.