topical media & game development

talk show tell print

lib-unity-tutorial-m2h-2-Assets-Standard-Assets-Scripts-MeshCombineUtility.cs / cs



  using UnityEngine;
  using System.Collections;
  
  public class MeshCombineUtility {
          
          public struct MeshInstance
          {
                  public Mesh      mesh;
                  public int       subMeshIndex;            
                  public Matrix4x4 transform;
          }
          
          public static Mesh Combine (MeshInstance[] combines, bool generateStrips)
          {
                  int vertexCount = 0;
                  int triangleCount = 0;
                  int stripCount = 0;
                  foreach( MeshInstance combine in combines )
                  {
                          if (combine.mesh)
                          {
                                  vertexCount += combine.mesh.vertexCount;
                                  
                                  if (generateStrips)
                                  {
                                          // SUBOPTIMAL FOR PERFORMANCE
                                          int curStripCount = combine.mesh.GetTriangleStrip(combine.subMeshIndex).Length;
                                          if (curStripCount != 0)
                                          {
                                                  if( stripCount != 0 )
                                                  {
                                                          if ((stripCount & 1) == 1 )
                                                                  stripCount += 3;
                                                          else
                                                                  stripCount += 2;
                                                  }
                                                  stripCount += curStripCount;
                                          }
                                          else
                                          {
                                                  generateStrips = false;
                                          }
                                  }
                          }
                  }
                  
                  // Precomputed how many triangles we need instead
                  if (!generateStrips)
                  {
                          foreach( MeshInstance combine in combines )
                          {
                                  if (combine.mesh)
                                  {
                                          triangleCount += combine.mesh.GetTriangles(combine.subMeshIndex).Length;
                                  }
                          }
                  }
                  
                  Vector3[] vertices = new Vector3[vertexCount] ;
                  Vector3[] normals = new Vector3[vertexCount] ;
                  Vector4[] tangents = new Vector4[vertexCount] ;
                  Vector2[] uv = new Vector2[vertexCount];
                  Vector2[] uv1 = new Vector2[vertexCount];
                  Color[] colors = new Color[vertexCount];
                  
                  int[] triangles = new int[triangleCount];
                  int[] strip = new int[stripCount];
                  
                  int offset;
                  
                  offset=0;
                  foreach( MeshInstance combine in combines )
                  {
                          if (combine.mesh)
                                  Copy(combine.mesh.vertexCount, combine.mesh.vertices, vertices, ref offset, combine.transform);
                  }
  
                  offset=0;
                  foreach( MeshInstance combine in combines )
                  {
                          if (combine.mesh)
                          {
                                  Matrix4x4 invTranspose = combine.transform;
                                  invTranspose = invTranspose.inverse.transpose;
                                  CopyNormal(combine.mesh.vertexCount, combine.mesh.normals, normals, ref offset, invTranspose);
                          }
                                  
                  }
                  offset=0;
                  foreach( MeshInstance combine in combines )
                  {
                          if (combine.mesh)
                          {
                                  Matrix4x4 invTranspose = combine.transform;
                                  invTranspose = invTranspose.inverse.transpose;
                                  CopyTangents(combine.mesh.vertexCount, combine.mesh.tangents, tangents, ref offset, invTranspose);
                          }
                                  
                  }
                  offset=0;
                  foreach( MeshInstance combine in combines )
                  {
                          if (combine.mesh)
                                  Copy(combine.mesh.vertexCount, combine.mesh.uv, uv, ref offset);
                  }
                  
                  offset=0;
                  foreach( MeshInstance combine in combines )
                  {
                          if (combine.mesh)
                                  Copy(combine.mesh.vertexCount, combine.mesh.uv1, uv1, ref offset);
                  }
                  
                  offset=0;
                  foreach( MeshInstance combine in combines )
                  {
                          if (combine.mesh)
                                  CopyColors(combine.mesh.vertexCount, combine.mesh.colors, colors, ref offset);
                  }
                  
                  int triangleOffset=0;
                  int stripOffset=0;
                  int vertexOffset=0;
                  foreach( MeshInstance combine in combines )
                  {
                          if (combine.mesh)
                          {
                                  if (generateStrips)
                                  {
                                          int[] inputstrip = combine.mesh.GetTriangleStrip(combine.subMeshIndex);
                                          if (stripOffset != 0)
                                          {
                                                  if ((stripOffset & 1) == 1)
                                                  {
                                                          strip[stripOffset+0] = strip[stripOffset-1];
                                                          strip[stripOffset+1] = inputstrip[0] + vertexOffset;
                                                          strip[stripOffset+2] = inputstrip[0] + vertexOffset;
                                                          stripOffset+=3;
                                                  }
                                                  else
                                                  {
                                                          strip[stripOffset+0] = strip[stripOffset-1];
                                                          strip[stripOffset+1] = inputstrip[0] + vertexOffset;
                                                          stripOffset+=2;
                                                  }
                                          }
                                          
                                          for (int i=0;i<inputstrip.Length;i++)
                                          {
                                                  strip[i+stripOffset] = inputstrip[i] + vertexOffset;
                                          }
                                          stripOffset += inputstrip.Length;
                                  }
                                  else
                                  {
                                          int[]  inputtriangles = combine.mesh.GetTriangles(combine.subMeshIndex);
                                          for (int i=0;i<inputtriangles.Length;i++)
                                          {
                                                  triangles[i+triangleOffset] = inputtriangles[i] + vertexOffset;
                                          }
                                          triangleOffset += inputtriangles.Length;
                                  }
                                  
                                  vertexOffset += combine.mesh.vertexCount;
                          }
                  }
                  
                  Mesh mesh = new Mesh();
                  mesh.name = "Combined Mesh";
                  mesh.vertices = vertices;
                  mesh.normals = normals;
                  mesh.colors = colors;
                  mesh.uv = uv;
                  mesh.uv1 = uv1;
                  mesh.tangents = tangents;
                  if (generateStrips)
                          mesh.SetTriangleStrip(strip, 0);
                  else
                          mesh.triangles = triangles;
                  
                  return mesh;
          }
          
          static void Copy (int vertexcount, Vector3[] src, Vector3[] dst, ref int offset, Matrix4x4 transform)
          {
                  for (int i=0;i<src.Length;i++)
                          dst[i+offset] = transform.MultiplyPoint(src[i]);
                  offset += vertexcount;
          }
  
          static void CopyNormal (int vertexcount, Vector3[] src, Vector3[] dst, ref int offset, Matrix4x4 transform)
          {
                  for (int i=0;i<src.Length;i++)
                          dst[i+offset] = transform.MultiplyVector(src[i]).normalized;
                  offset += vertexcount;
          }
  
          static void Copy (int vertexcount, Vector2[] src, Vector2[] dst, ref int offset)
          {
                  for (int i=0;i<src.Length;i++)
                          dst[i+offset] = src[i];
                  offset += vertexcount;
          }
  
          static void CopyColors (int vertexcount, Color[] src, Color[] dst, ref int offset)
          {
                  for (int i=0;i<src.Length;i++)
                          dst[i+offset] = src[i];
                  offset += vertexcount;
          }
          
          static void CopyTangents (int vertexcount, Vector4[] src, Vector4[] dst, ref int offset, Matrix4x4 transform)
          {
                  for (int i=0;i<src.Length;i++)
                  {
                          Vector4 p4 = src[i];
                          Vector3 p = new Vector3(p4.x, p4.y, p4.z);
                          p = transform.MultiplyVector(p).normalized;
                          dst[i+offset] = new Vector4(p.x, p.y, p.z, p4.w);
                  }
                          
                  offset += vertexcount;
          }
  }
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.