using System;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
namespace UnityEngine.ProBuilder.Csg
{
///
/// Representation of a mesh in CSG terms. Contains methods for translating to and from UnityEngine.Mesh.
///
sealed class Model
{
List m_Vertices;
List m_Materials;
List> m_Indices;
public List materials
{
get { return m_Materials; }
set { m_Materials = value; }
}
public List vertices
{
get { return m_Vertices; }
set { m_Vertices = value; }
}
public List> indices
{
get { return m_Indices; }
set { m_Indices = value; }
}
public Mesh mesh
{
get { return (Mesh)this; }
}
public Model(GameObject gameObject) :
this(gameObject.GetComponent()?.sharedMesh,
gameObject.GetComponent()?.sharedMaterials,
gameObject.GetComponent())
{
}
///
/// Initialize a Model from a UnityEngine.Mesh and transform.
///
public Model(Mesh mesh, Material[] materials, Transform transform)
{
if(mesh == null)
throw new ArgumentNullException("mesh");
if(transform == null)
throw new ArgumentNullException("transform");
m_Vertices = VertexUtility.GetVertices(mesh).Select(x => transform.TransformVertex(x)).ToList();
m_Materials = new List(materials);
m_Indices = new List>();
for (int i = 0, c = mesh.subMeshCount; i < c; i++)
{
if (mesh.GetTopology(i) != MeshTopology.Triangles)
continue;
var indices = new List();
mesh.GetIndices(indices, i);
m_Indices.Add(indices);
}
}
internal Model(List polygons)
{
m_Vertices = new List();
Dictionary> submeshes = new Dictionary>();
int p = 0;
for (int i = 0; i < polygons.Count; i++)
{
Polygon poly = polygons[i];
List indices;
if (!submeshes.TryGetValue(poly.material, out indices))
submeshes.Add(poly.material, indices = new List());
for (int j = 2; j < poly.vertices.Count; j++)
{
m_Vertices.Add(poly.vertices[0]);
indices.Add(p++);
m_Vertices.Add(poly.vertices[j - 1]);
indices.Add(p++);
m_Vertices.Add(poly.vertices[j]);
indices.Add(p++);
}
}
m_Materials = submeshes.Keys.ToList();
m_Indices = submeshes.Values.ToList();
}
internal List ToPolygons()
{
List list = new List();
for (int s = 0, c = m_Indices.Count; s < c; s++)
{
var indices = m_Indices[s];
for (int i = 0, ic = indices.Count; i < indices.Count; i += 3)
{
List triangle = new List()
{
m_Vertices[indices[i + 0]],
m_Vertices[indices[i + 1]],
m_Vertices[indices[i + 2]]
};
list.Add(new Polygon(triangle, m_Materials[s]));
}
}
return list;
}
public static explicit operator Mesh(Model model)
{
var mesh = new Mesh();
VertexUtility.SetMesh(mesh, model.m_Vertices);
mesh.subMeshCount = model.m_Indices.Count;
for (int i = 0, c = mesh.subMeshCount; i < c; i++)
mesh.SetIndices(model.m_Indices[i], MeshTopology.Triangles, i);
return mesh;
}
}
}