205 lines
4.3 KiB
C#
205 lines
4.3 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Godot;
|
|
using System;
|
|
|
|
|
|
|
|
namespace Rokojori
|
|
{
|
|
[Tool]
|
|
[GlobalClass]
|
|
public partial class MeshCombiner:Node3D
|
|
{
|
|
[Export]
|
|
public Node3D[] sourceNodes;
|
|
|
|
[ExportGroup( "Mesh")]
|
|
[Export]
|
|
public bool combineMeshes = true;
|
|
|
|
public enum UVCombineMode
|
|
{
|
|
Keep,
|
|
Adjust_To_Combined_Material
|
|
}
|
|
|
|
[Export]
|
|
public UVCombineMode uVCombineMode = UVCombineMode.Adjust_To_Combined_Material;
|
|
|
|
[Export]
|
|
public Node3D pivot;
|
|
|
|
[ExportGroup( "Material")]
|
|
[Export]
|
|
public bool combineMaterials = true;
|
|
|
|
public enum TextureSizeMode
|
|
{
|
|
KeepOriginal,
|
|
Custom
|
|
}
|
|
|
|
[Export]
|
|
public TextureSizeMode textureSizeMode = TextureSizeMode.Custom;
|
|
|
|
[Export]
|
|
public Vector2I customTextureSize = new Vector2I( 1024, 1024 );
|
|
|
|
|
|
[ExportGroup( "Output")]
|
|
[Export]
|
|
public MeshInstance3D outputMesh;
|
|
[Export]
|
|
public Material[] outputMaterials;
|
|
[Export]
|
|
public bool combine = false;
|
|
|
|
public override void _Process( double delta )
|
|
{
|
|
if ( ! combine )
|
|
{
|
|
return;
|
|
}
|
|
|
|
combine = false;
|
|
|
|
Combine();
|
|
}
|
|
|
|
MultiMap<Mesh,int,MeshGeometry> _meshGeometryCache = new MultiMap<Mesh,int,MeshGeometry>();
|
|
|
|
MeshGeometry GetMeshGeometry( MeshSurface surface )
|
|
{
|
|
if ( ! _meshGeometryCache.Has( surface.mesh, surface.index ) )
|
|
{
|
|
var mg = MeshGeometry.From( surface.mesh as ArrayMesh, null, surface.index );
|
|
_meshGeometryCache.Set( surface.mesh, surface.index, mg );
|
|
|
|
this.LogInfo( "Created mesh with triangles:", mg.numTriangles );
|
|
}
|
|
|
|
return _meshGeometryCache[ surface.mesh ][ surface.index ];
|
|
}
|
|
|
|
List<Transformable<MeshSurface>> _surfaces;
|
|
List<Material> _materials;
|
|
MapList<Material,Transformable<MeshSurface>> _materiaList = new MapList<Material, Transformable<MeshSurface>>() ;
|
|
Dictionary<Material,Transform2D> _uvTransform = new Dictionary<Material, Transform2D>();
|
|
|
|
|
|
public void Combine()
|
|
{
|
|
GrabSurfaces();
|
|
GrabMaterials();
|
|
|
|
CombineMaterials();
|
|
CombineMeshes();
|
|
}
|
|
|
|
void GrabSurfaces()
|
|
{
|
|
_surfaces = new List<Transformable<MeshSurface>>();
|
|
|
|
foreach ( var n in sourceNodes )
|
|
{
|
|
|
|
MeshExtractor.ExtractSurfacesInHierarchy( n, _surfaces );
|
|
}
|
|
}
|
|
|
|
void GrabMaterials()
|
|
{
|
|
_materials = new List<Material>();
|
|
_materiaList = new MapList<Material, Transformable<MeshSurface>>();
|
|
|
|
var set = new HashSet<Material>();
|
|
|
|
_surfaces.ForEach(
|
|
( s )=>
|
|
{
|
|
_materiaList.Add( s.item.material, s );
|
|
|
|
if ( set.Contains( s.item.material ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
set.Add( s.item.material );
|
|
_materials.Add( s.item.material );
|
|
|
|
}
|
|
);
|
|
|
|
|
|
}
|
|
|
|
void CombineMaterials()
|
|
{
|
|
|
|
}
|
|
|
|
void CombineMeshes()
|
|
{
|
|
var arrayMesh = new ArrayMesh();
|
|
|
|
this.LogInfo( "Combining", _surfaces.Count, "meshes" );
|
|
|
|
var index = 0;
|
|
var nm = 0;
|
|
var max = 100;
|
|
_materials.ForEach(
|
|
( m )=>
|
|
{
|
|
Transform2D? uvTransform = _uvTransform.ContainsKey( m ) ? _uvTransform[ m ] : null;
|
|
|
|
var surfaces = _materiaList[ m ];
|
|
|
|
this.LogInfo( "Combining for Material", m, surfaces.Count, "meshes" );
|
|
|
|
var meshGeometry = new MeshGeometry();
|
|
|
|
surfaces.ForEach(
|
|
( s )=>
|
|
{
|
|
var smg = GetMeshGeometry( s.item ).Clone();
|
|
|
|
if ( uvTransform != null )
|
|
{
|
|
smg.ApplyUVTransform( (Transform2D) uvTransform );
|
|
}
|
|
|
|
var trsf = s.transform;
|
|
|
|
if ( pivot != null )
|
|
{
|
|
trsf.Origin -= pivot.GlobalPosition;
|
|
}
|
|
|
|
smg.ApplyTransform( trsf );
|
|
|
|
meshGeometry.Add( smg );
|
|
}
|
|
);
|
|
|
|
meshGeometry.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh );
|
|
|
|
|
|
arrayMesh.SurfaceSetMaterial( index, m );
|
|
index ++;
|
|
|
|
}
|
|
);
|
|
|
|
if ( outputMesh == null )
|
|
{
|
|
outputMesh = this.CreateChild<MeshInstance3D>();
|
|
}
|
|
|
|
outputMesh.Mesh = arrayMesh;
|
|
outputMaterials = _materials.ToArray();
|
|
}
|
|
|
|
|
|
}
|
|
} |