Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract a submesh ? #49

Closed
EricBeetsOfficial-Opuscope opened this issue Jun 11, 2020 · 4 comments
Closed

Extract a submesh ? #49

EricBeetsOfficial-Opuscope opened this issue Jun 11, 2020 · 4 comments

Comments

@EricBeetsOfficial-Opuscope

Hi !

It's a great project !

I was wondering if it's possible to extract a sub mesh ? I mean, for instance, create a ModelRoot from a Mesh (and save it ..) ?

Thanks in advance
Eric

@vpenades
Copy link
Owner

vpenades commented Jun 11, 2020

It is possible, but not as trivial as it should.

Keep in mind that a mesh depends on its materials, the materials on textures, the textures on images, etc, so you have to take that into account when exporting a sub-mesh.

Also, it is nearly impossible to edit a loaded gltf to remove all the meshes and resources except the ones you want to export.

That being said, the best approach you can follow is this:

  • Use the glTF toolkit to access the methods and structures you need.

  • then do:

var sceneBuilder = srcModel.DefaultScene.ToSceneBuilder();      
  • Then, you can use the sceneBuilder to edit or reuse components in other editable meshes.

  • Finally, you convert it back to a new glTF and export it:

var finalScene = sceneBuilder.ToGltf2();      
finalScene.Save(...);

Some notes about Toolkit's SceneBuilder: Right now it's API is designed only to append new meshes, and it does not have any API to remove elements, yet.

But in this case, and unlike glTF, SceneBuilder elements can be shared between multiple SceneBuilder instances, so you can create a new SceneBuilder, add the mesh you want to export from the source's SceneBuilder, and then export it.

I have not tested that particular workflow, let me know if it works for you.

@vpenades
Copy link
Owner

Hi, I've added an example on how to extract and save individual meshes:

public void ExportMeshes(string path)

@EricBeetsOfficial-Opuscope
Copy link
Author

EricBeetsOfficial-Opuscope commented Jun 23, 2020

Hi,

Thanks a lot, it was what I having done and it works ;)
But, finally, I used another way (as I didn't need material, but just geometry):

    ModelRoot modelRoot = ModelRoot.CreateModel();
    // Default material
    Material materialToExport = modelRoot.CreateMaterial();
    // Create Mesh
    Mesh meshToExport = modelRoot.CreateMesh(this.name);
    foreach(MeshPrimitive meshPrimitive in mesh.Primitives)
    {
        var positions = meshPrimitive.GetVertexAccessor("POSITION").AsVector3Array().ToArray();
        var normals = meshPrimitive.GetVertexAccessor("NORMAL").AsVector3Array().ToArray();
        var texcoord = meshPrimitive.GetVertexAccessor("TEXCOORD_0").AsVector2Array().ToArray();
        var indices = (int[])(object)meshPrimitive.GetIndexAccessor().AsIndicesArray().ToArray();
        meshToExport.CreatePrimitive().WithVertexAccessor("POSITION", positions)
                                              .WithVertexAccessor("NORMAL", normals)
                                              .WithVertexAccessor("TEXCOORD_0", texcoord)
                                              .WithIndicesAccessor(PrimitiveType.TRIANGLES, indices)
                                              .WithMaterial(materialToExport);
    }
    Scene sceneModel = modelRoot.UseScene("Default");
    sceneModel.CreateNode("RootNode").WithMesh(meshToExport);
    modelRoot.SaveGLB(this.pathFile);

Thank you again for your project and your reactivity
(next step: get the model bounding box ;) )

@vpenades
Copy link
Owner

vpenades commented Jun 23, 2020

It's actually much easier if you use the Toolkit extensions:

var mesh = modelRoot.LogicalMeshes[17]; // get the mesh we want to extract

var meshBuilder = mesh.ToMeshBuilder(); // Toolkit extension extracts the mesh to a MeshBuilder

var sceneBuilder = new SceneBuilder(); // create a new scene that will act as a container of the mesh.

sceneBuilder.AddRigidMesh(meshBuilder, Matrix4x4.Indentity);

var gltf = sceneBuilder.ToGltf2();
gltf.SaveGLB(this.pathFile);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants