rj-action-library/Runtime/Procedural/Mesh/MeshExtractor.cs

219 lines
5.6 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
namespace Rokojori
{
public class MeshExtractor
{
public static List<MaterialSurfaceContainer> ExtractMaterialContainersInHierarchy( Node n, List<MaterialSurfaceContainer> list = null, bool ownersOnly = false )
{
list = list == null ? new List<MaterialSurfaceContainer>() : list;
Nodes.ForEach<Node3D>( n,
n =>
{
ExtractMaterialContainers( n, list, ownersOnly );
}
);
return list;
}
public static List<MaterialSurfaceContainer> ExtractMaterialContainers( Node n, List<MaterialSurfaceContainer> list = null, bool ownersOnly = false )
{
list = list == null ? new List<MaterialSurfaceContainer>() : list;
if ( n is MeshInstance3D mi && mi.Mesh != null )
{
if ( ! ownersOnly )
{
for ( int i = 0; i < mi.Mesh.GetSurfaceCount(); i++ )
{
list.Add( new MeshSurfaceContainer( mi, i ) );
}
}
else
{
list.Add( new MeshSurfaceContainer( mi, -1 ) );
}
}
if ( n is MultiMeshInstance3D mmi && mmi.Multimesh != null && mmi.Multimesh.Mesh != null )
{
if ( ! ownersOnly )
{
for ( int i = 0; i < mmi.Multimesh.Mesh.GetSurfaceCount(); i++ )
{
list.Add( new MultiMeshSurfaceContainer( mmi, i ) );
}
}
else
{
list.Add( new MultiMeshSurfaceContainer( mmi, -1 ) );
}
}
return list;
}
public static bool CanExtract( Node3D n )
{
if ( n is MeshInstance3D mi )
{
return mi.Mesh != null;
}
if ( n is MultiMeshInstance3D mmi )
{
var mm = mmi.Multimesh;
return mm.Mesh != null;
}
return false;
}
public static List<Transformable<SingleMaterialMesh>> ExtractMeshesInHierarchy( Node n, List<Transformable<SingleMaterialMesh>> list = null )
{
list = list == null ? new List<Transformable<SingleMaterialMesh>>() : list;
Nodes.ForEach<Node3D>( n,
n =>
{
ExtractMeshes( n, list );
}
);
return list;
}
public static List<Transformable<SingleMaterialMesh>> ExtractMeshes( Node n, List<Transformable<SingleMaterialMesh>> list = null )
{
list = list == null ? new List<Transformable<SingleMaterialMesh>>() : list;
if ( n is MeshInstance3D mi )
{
var mesh = mi.Mesh;
var singleMaterialMesh = new SingleMaterialMesh( mesh );
if ( mi.GetSurfaceOverrideMaterialCount() > 0 && mi.GetSurfaceOverrideMaterial( 0 ) != null )
{
singleMaterialMesh.material = mi.GetSurfaceOverrideMaterial( 0 );
}
if ( mi.MaterialOverride != null )
{
singleMaterialMesh.material = mi.MaterialOverride;
}
list.Add( new Transformable<SingleMaterialMesh>( singleMaterialMesh, mi.GlobalTransform ) );
}
if ( n is MultiMeshInstance3D mmi )
{
var mm = mmi.Multimesh;
for ( var j = 0; j < mm.InstanceCount; j++ )
{
var mesh = mm.Mesh;
var transform = mm.GetInstanceTransform( j );
var singleMaterialMesh = new SingleMaterialMesh( mesh );
if ( mmi.MaterialOverride != null )
{
singleMaterialMesh.material = mmi.MaterialOverride;
}
list.Add( new Transformable<SingleMaterialMesh>( singleMaterialMesh, transform ) );
}
}
return list;
}
public static List<Transformable<MeshSurface>> ExtractSurfacesInHierarchy( Node n, List<Transformable<MeshSurface>> list = null )
{
list = list == null ? new List<Transformable<MeshSurface>>() : list;
Nodes.ForEach<Node3D>( n,
n =>
{
ExtractSurfaces( n, list );
}
);
return list;
}
public static List<Transformable<MeshSurface>> ExtractSurfaces( Node n, List<Transformable<MeshSurface>> list = null )
{
list = list == null ? new List<Transformable<MeshSurface>>() : list;
if ( n is MeshInstance3D mi )
{
var owner = mi;
var mesh = mi.Mesh;
for ( int i = 0; i < mesh.GetSurfaceCount(); i++ )
{
var surface = new MeshSurface( mesh, mesh.SurfaceGetMaterial( i ), i, owner );
if ( i < mi.GetSurfaceOverrideMaterialCount() && mi.GetSurfaceOverrideMaterial( i ) != null )
{
surface.material = mi.GetSurfaceOverrideMaterial( i );
}
if ( mi.MaterialOverride != null )
{
surface.material = mi.MaterialOverride;
}
list.Add( new Transformable<MeshSurface>( surface, mi.GlobalTransform ) );
}
}
if ( n is MultiMeshInstance3D mmi )
{
var owner = mmi;
var mm = mmi.Multimesh;
for ( var j = 0; j < mm.InstanceCount; j++ )
{
var mesh = mm.Mesh;
var transform = mm.GetInstanceTransform( j );
for ( int i = 0; i < mesh.GetSurfaceCount(); i++ )
{
var surface = new MeshSurface( mesh, mesh.SurfaceGetMaterial( i ), i, mmi, j );
if ( mmi.MaterialOverride != null )
{
surface.material = mmi.MaterialOverride;
}
list.Add( new Transformable<MeshSurface>( surface, transform ) );
}
}
}
return list;
}
}
}