MorphTargets

From Unify Community Wiki
Revision as of 12:12, 1 October 2009 by Skahlert (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

C# - MorphTargets.cs

Here's trypho's MorphTarget script from the Unity Forum in a C# version. It is far more versatile than the MeshMorpher script.

<csharp> /**

* Just a 20min port of trypho's JS script to C# by skahlert
* In my experience the performance improved significantly (about 57x the speed of the JavaScript).
* Have fun with it!!
* 
* If you find a nicer way of compensating the lack of dynamic arrays (line 84 and following) it would be nice to hear!
* 
*/


using System; using UnityEngine;

[RequireComponent(typeof(MeshFilter))] [RequireComponent(typeof(MeshRenderer))]

class MorphTargets : MonoBehaviour {

   internal class BlendShapeVertex
   {
       public int originalIndex;
       public Vector3 position;
       public Vector3 normal;
   }
   internal class BlendShape
   {
       public BlendShapeVertex[] vertices;// = new Array();
   }
   public String[] attributes; //Names for the attributes to be morphed
   public Mesh sourceMesh; //The original mesh
   public Mesh[] attributeMeshes; //The destination meshes for each attribute.
   public float[] attributeProgress;
   private BlendShape[] blendShapes;
   private Mesh workingMesh;
   void Awake()
   {
       for (int i = 0; i < attributeMeshes.Length; i++)
       {
           if (attributeMeshes[i] == null)
           {
               Debug.Log("Attribute " + i + " has not been assigned.");
               return;
           }
       }
       //Populate the working mesh
       MeshFilter filter = gameObject.GetComponent(typeof(MeshFilter)) as MeshFilter;
       filter.sharedMesh = sourceMesh;
       workingMesh = filter.mesh;
       //Check attribute meshes to be sure vertex count is the same.
       int vertexCount = sourceMesh.vertexCount;
       //Debug.Log("Vertex Count Source:"+vertexCount);
       for (int i = 0; i < attributeMeshes.Length; i++)
       {
           //Debug.Log("Vertex Mesh "+i+":"+attributeMeshes[i].vertexCount); 
           if (attributeMeshes[i].vertexCount != vertexCount)
           {
               Debug.Log("Mesh " + i + " doesn't have the same number of vertices as the first mesh");
               return;
           }
       }
       //Build blend shapes
       BuildBlendShapes();
   }
   void BuildBlendShapes()
   {
       blendShapes = new BlendShape[attributes.Length];
       //For each attribute figure out which vertices are affected, then store their info in the blend shape object.
       for (int i = 0; i < attributes.Length; i++)
       {
           //Populate blendShapes array with new blend shapes
           blendShapes[i] = new BlendShape();
           /** TODO: Make this a little more stylish!
            *  UGLY hack to compensate the lack of dynamic arrays in C#. Feel free to improve!
            */
           int blendShapeCounter = 0;
           for (int j = 0; j < workingMesh.vertexCount; j++)
           {
               
               if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j])
               {
                   blendShapeCounter++;
               }
           }
           
           blendShapes[i].vertices = new BlendShapeVertex[blendShapeCounter];
           blendShapeCounter = 0;
           for (int j = 0; j < workingMesh.vertexCount; j++)
           {
               //If the vertex is affected, populate a blend shape vertex with that info
               if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j])
               {
                   //Create a blend shape vertex and populate its data.
                   
                   BlendShapeVertex blendShapeVertex = new BlendShapeVertex();
                   blendShapeVertex.originalIndex = j;
                   blendShapeVertex.position = attributeMeshes[i].vertices[j] - workingMesh.vertices[j];
                   blendShapeVertex.normal = attributeMeshes[i].normals[j] - workingMesh.normals[j];
                   //Add new blend shape vertex to blendShape object.
                   blendShapes[i].vertices[blendShapeCounter]=blendShapeVertex;
                   blendShapeCounter++;
               }
           }
           //Convert blendShapes.vertices to builtin array
           //blendShapes[i].vertices = blendShapes[i].vertices.ToBuiltin(BlendShapeVertex);
       }
   }


   public void SetMorph()
   {
       //Set up working data to store mesh offset information.
       Vector3[] morphedVertices = sourceMesh.vertices;
       Vector3[] morphedNormals = sourceMesh.normals;
       //For each attribute...
       for (int j = 0; j < attributes.Length; j++)
       {
           //If the weight of this attribute isn't 0	
           if (!Mathf.Approximately(attributeProgress[j], 0))
           {
               //For each vertex in this attribute's blend shape...
               for (int i = 0; i < blendShapes[j].vertices.Length; i++)
               {
                   //...adjust the mesh according to the offset value and weight
                   morphedVertices[blendShapes[j].vertices[i].originalIndex] += blendShapes[j].vertices[i].position * attributeProgress[j];
                   //Adjust normals as well
                   morphedNormals[blendShapes[j].vertices[i].originalIndex] += blendShapes[j].vertices[i].normal * attributeProgress[j];
               }
           }
       }
       //Update the actual mesh with new vertex and normal information, then recalculate the mesh bounds.		
       workingMesh.vertices = morphedVertices;
       workingMesh.normals = morphedNormals;
       workingMesh.RecalculateBounds();
   }


}

</csharp>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox