MeshMerger

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Removing all content from page)
m (Reverted edits by Joseph05408 (Talk); changed back to last version by AmazingRuss)
Line 1: Line 1:
 +
<javascript>
 +
// Mesh Merger Script
 +
// Copyright 2009, Russ Menapace
 +
// http://humanpoweredgames.com
  
 +
// Summary:
 +
//  This script allows you to draw a large number of meshes with a single
 +
//  draw call.  This is particularly useful for iPhone games.
 +
 +
// License:
 +
//  Free to use as you see fit, but I would appreciate one of the following:
 +
//  * A credit for Human Powered Games, or even a link to humanpoweredgames.com
 +
//    in whatever you make with this
 +
//  * Hire me to make games or simulations
 +
//  * A donation to the PayPal account at russ@databar.com.  I'm very poor, so
 +
//    even a small donation would be greatly appreciated!
 +
//  * A thank you note to russ@databar.com
 +
//  * Suggestions on how the script could be improved mailed to russ@databar.com
 +
 +
// Warranty:
 +
//  This software carries no warranty, and I don't guarantee anything about it.
 +
//  If it burns down your house or gets your cat pregnant, don't look at me.
 +
 +
// Acnowledgements:
 +
//  This was pieced together out of code I found onthe UnifyCommunity wiki, and
 +
//  the Unity forum.  I did not keep track of names, but I do recall gaining
 +
//  a lot of insight from the posts of PirateNinjaAlliance. 
 +
//  Thanks to anybody that may have been involved.
 +
 +
// Requirements: 
 +
//  All the meshes you want to use must use the same material. 
 +
//  This material may be a texture atlas and the meshes UV to portions of the atlas.
 +
//  The texture atlas technique works particularly well for GUI stuff.
 +
 +
// Usage:
 +
//  There are two ways to use this script:
 +
 +
//  Implicit: 
 +
//    Simply drop the script into a GameObject that has a number of
 +
//    child objects containing mesh filters.
 +
 +
//  Explicit:
 +
//    Populate the meshFilter array with the meshes you want merged
 +
//    Optionally, set the material to be used.  If no material is selected,
 +
//    The script will apply the first material it encounters to all subsequent
 +
//    meshes
 +
 +
// To see if it's working:
 +
//  Move the camera so you can see several of your objects in the Game pane
 +
//  Note the number of draw calls
 +
//  Hit play. You should see the number of draw calls for those meshes reduced to one
 +
 +
using UnityEngine;
 +
using System;
 +
 +
//==============================================================================
 +
public class MeshMerger : MonoBehaviour
 +
{
 +
  public MeshFilter[] meshFilters;
 +
  public Material material;
 +
 
 +
  //----------------------------------------------------------------------------
 +
  void Start ()
 +
  {
 +
    // if not specified, go find meshes
 +
    if(meshFilters.Length == 0)
 +
    {
 +
      // find all the mesh filters
 +
      Component[] comps = GetComponentsInChildren(typeof(MeshFilter));
 +
      meshFilters = new MeshFilter[comps.Length];
 +
 
 +
      int mfi = 0;
 +
      foreach(Component comp in comps)
 +
        meshFilters[mfi++] = (MeshFilter) comp;
 +
    }
 +
   
 +
    // figure out array sizes
 +
    int vertCount = 0;
 +
    int normCount = 0;
 +
    int triCount = 0;
 +
    int uvCount = 0;
 +
 +
    foreach(MeshFilter mf in meshFilters)
 +
    {
 +
      vertCount += mf.mesh.vertices.Length;
 +
      normCount += mf.mesh.normals.Length;
 +
      triCount += mf.mesh.triangles.Length;
 +
      uvCount += mf.mesh.uv.Length;
 +
      if(material == null)
 +
        material = mf.gameObject.renderer.material;     
 +
    }
 +
   
 +
    // allocate arrays
 +
    Vector3[] verts = new Vector3[vertCount];
 +
    Vector3[] norms = new Vector3[normCount];
 +
    Transform[] aBones = new Transform[meshFilters.Length];
 +
    Matrix4x4[] bindPoses = new Matrix4x4[meshFilters.Length];
 +
    BoneWeight[] weights = new BoneWeight[vertCount];
 +
    int[] tris  = new int[triCount];
 +
    Vector2[] uvs = new Vector2[uvCount];
 +
   
 +
    int vertOffset = 0;
 +
    int normOffset = 0;
 +
    int triOffset = 0;
 +
    int uvOffset = 0;
 +
    int meshOffset = 0;
 +
   
 +
    // merge the meshes and set up bones
 +
    foreach(MeshFilter mf in meshFilters)
 +
    {   
 +
      foreach(int i in mf.mesh.triangles)
 +
        tris[triOffset++] = i + vertOffset;
 +
   
 +
      aBones[meshOffset] = mf.transform;
 +
      bindPoses[meshOffset] = Matrix4x4.identity;
 +
     
 +
      foreach(Vector3 v in mf.mesh.vertices)
 +
      {
 +
        weights[vertOffset].weight0 = 1.0f;
 +
        weights[vertOffset].boneIndex0 = meshOffset;
 +
        verts[vertOffset++] = v;
 +
      }
 +
 +
      foreach(Vector3 n in mf.mesh.normals)
 +
        norms[normOffset++] = n;
 +
             
 +
      foreach(Vector2 uv in mf.mesh.uv)
 +
        uvs[uvOffset++] = uv;
 +
 
 +
      meshOffset++;
 +
     
 +
      MeshRenderer mr =
 +
        mf.gameObject.GetComponent(typeof(MeshRenderer))
 +
        as MeshRenderer;
 +
 +
      if(mr)
 +
        mr.enabled = false;
 +
    }
 +
 +
    // hook up the mesh
 +
    Mesh me = new Mesh();     
 +
    me.name = gameObject.name;
 +
    me.vertices = verts;
 +
    me.normals = norms;
 +
    me.boneWeights = weights;
 +
    me.uv = uvs;
 +
    me.triangles = tris;
 +
    me.bindposes = bindPoses;
 +
 +
    // hook up the mesh renderer       
 +
    SkinnedMeshRenderer smr =
 +
      gameObject.AddComponent(typeof(SkinnedMeshRenderer))
 +
      as SkinnedMeshRenderer;
 +
 
 +
    smr.sharedMesh = me;
 +
    smr.bones = aBones;
 +
    renderer.material = material;
 +
 +
  }
 +
}
 +
 +
</javascript>

Revision as of 19:01, 19 October 2009

<javascript> // Mesh Merger Script // Copyright 2009, Russ Menapace // http://humanpoweredgames.com

// Summary: // This script allows you to draw a large number of meshes with a single // draw call. This is particularly useful for iPhone games.

// License: // Free to use as you see fit, but I would appreciate one of the following: // * A credit for Human Powered Games, or even a link to humanpoweredgames.com // in whatever you make with this // * Hire me to make games or simulations // * A donation to the PayPal account at russ@databar.com. I'm very poor, so // even a small donation would be greatly appreciated! // * A thank you note to russ@databar.com // * Suggestions on how the script could be improved mailed to russ@databar.com

// Warranty: // This software carries no warranty, and I don't guarantee anything about it. // If it burns down your house or gets your cat pregnant, don't look at me.

// Acnowledgements: // This was pieced together out of code I found onthe UnifyCommunity wiki, and // the Unity forum. I did not keep track of names, but I do recall gaining // a lot of insight from the posts of PirateNinjaAlliance. // Thanks to anybody that may have been involved.

// Requirements: // All the meshes you want to use must use the same material. // This material may be a texture atlas and the meshes UV to portions of the atlas. // The texture atlas technique works particularly well for GUI stuff.

// Usage: // There are two ways to use this script:

// Implicit: // Simply drop the script into a GameObject that has a number of // child objects containing mesh filters.

// Explicit: // Populate the meshFilter array with the meshes you want merged // Optionally, set the material to be used. If no material is selected, // The script will apply the first material it encounters to all subsequent // meshes

// To see if it's working: // Move the camera so you can see several of your objects in the Game pane // Note the number of draw calls // Hit play. You should see the number of draw calls for those meshes reduced to one

using UnityEngine; using System;

//============================================================================== public class MeshMerger : MonoBehaviour {

 public MeshFilter[] meshFilters;
 public Material material;
 
 //----------------------------------------------------------------------------
 void Start () 
 { 
   // if not specified, go find meshes
   if(meshFilters.Length == 0)
   {
     // find all the mesh filters
     Component[] comps = GetComponentsInChildren(typeof(MeshFilter));
     meshFilters = new MeshFilter[comps.Length];
 
     int mfi = 0;
     foreach(Component comp in comps)
       meshFilters[mfi++] = (MeshFilter) comp;
   }
   
   // figure out array sizes
   int vertCount = 0;
   int normCount = 0;
   int triCount = 0;
   int uvCount = 0;
   foreach(MeshFilter mf in meshFilters)
   {
     vertCount += mf.mesh.vertices.Length; 
     normCount += mf.mesh.normals.Length;
     triCount += mf.mesh.triangles.Length; 
     uvCount += mf.mesh.uv.Length;
     if(material == null)
       material = mf.gameObject.renderer.material;       
   }
   
   // allocate arrays
   Vector3[] verts = new Vector3[vertCount];
   Vector3[] norms = new Vector3[normCount];
   Transform[] aBones = new Transform[meshFilters.Length];
   Matrix4x4[] bindPoses = new Matrix4x4[meshFilters.Length];
   BoneWeight[] weights = new BoneWeight[vertCount];
   int[] tris  = new int[triCount];
   Vector2[] uvs = new Vector2[uvCount];
   
   int vertOffset = 0;
   int normOffset = 0;
   int triOffset = 0;
   int uvOffset = 0;
   int meshOffset = 0;
   
   // merge the meshes and set up bones
   foreach(MeshFilter mf in meshFilters)
   {     
     foreach(int i in mf.mesh.triangles)
       tris[triOffset++] = i + vertOffset;
   
     aBones[meshOffset] = mf.transform;
     bindPoses[meshOffset] = Matrix4x4.identity;
     
     foreach(Vector3 v in mf.mesh.vertices)
     {
       weights[vertOffset].weight0 = 1.0f;
       weights[vertOffset].boneIndex0 = meshOffset;
       verts[vertOffset++] = v;
     }
     foreach(Vector3 n in mf.mesh.normals)
       norms[normOffset++] = n;
             
     foreach(Vector2 uv in mf.mesh.uv)
       uvs[uvOffset++] = uv;
 
     meshOffset++;
     
     MeshRenderer mr = 
       mf.gameObject.GetComponent(typeof(MeshRenderer)) 
       as MeshRenderer;
     if(mr)
       mr.enabled = false;
   }
   // hook up the mesh
   Mesh me = new Mesh();       
   me.name = gameObject.name;
   me.vertices = verts;
   me.normals = norms;
   me.boneWeights = weights;
   me.uv = uvs;
   me.triangles = tris;
   me.bindposes = bindPoses;
   // hook up the mesh renderer        
   SkinnedMeshRenderer smr = 
     gameObject.AddComponent(typeof(SkinnedMeshRenderer)) 
     as SkinnedMeshRenderer;
 
   smr.sharedMesh = me;
   smr.bones = aBones;
   renderer.material = material;
 }

}

</javascript>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox