BLACKISH DEV BLOG Support
 

 

Unity: How to blow up a mesh like a balloon

Say you wanted to blow up a mesh like a ballon – simply scaling it up isn’t good enough. There’s an example in the documentation that teaches you how to move vertices along normals, but it doesn’t quite do what I want it to, since the mesh falls apart in the process:
Here’s the slightly modified code of the example, as seen in the video above:
function Update () {
var meF : MeshFilter = GetComponent(MeshFilter);
if(meF) mesh = meF.mesh;
     var vertices = mesh.vertices;
     var normals = mesh.normals;
     for (var i=0; i<vertices.length; i++) {
          vertices[i] += normals[i] * 2.0 * Time.deltaTime;
     }
     mesh.vertices = vertices;
}

To prevent this disintegration from happening we need to find all vertices that share identical positions and find one average normal per group of identicals. First the result, then the code:

private var mesh : Mesh;
private var vertices = new Vector3[0];
private var normals = new Vector3[0];
var finalNormals = new Vector3[0];

function Start () {
var meF : MeshFilter = GetComponent(MeshFilter);
mesh = meF.mesh;

vertices = mesh.vertices;
normals = mesh.normals;

//Find identical vertices
var vertexIDs = new int[vertices.length]; //this will hold an ID for each vertex, vertices at the same position will share the same ID!
var counter : int = 0;
for (var i = 0; i < vertices.length; i++) {
for (var j = 0; j < vertices.length; j++) {
 if(vertexIDs[i] == 0) {
  counter++;
  vertexIDs[i] = counter;
 }
 if(i != j) {
  if(vertices[i] == vertices[j] && vertices[i] != 0) {
   vertexIDs[j] = vertexIDs[i];
  }
     print(i + ", " + j + ":" + vertices[j] + " (" + vertexIDs[j] + ")");
 }
}
}

finalNormals = normals;

//Calcualte average normals
for(k = 1; k <= counter; k++) { //counter is the highest vertexID, now go through all the groups and collect normal data
var curAvgNormal : Vector3 = Vector3.zero;
for(l = 0; l < vertexIDs.length; l++) {
 if(vertexIDs[l] == k) {
  curAvgNormal += normals[l]; //Add up all the normals of the vertices with identical positions
 }
}
curAvgNormal.Normalize(); //Normalize the result
for(m = 0; m < vertexIDs.length; m++) {
 if(vertexIDs[m] == k) finalNormals[m] = curAvgNormal;
}
}
}

function Update () {
for (var i = 0; i < vertices.length; i++) {
   vertices[i] += finalNormals[i] * 2.0 * Time.deltaTime;
}
mesh.vertices = vertices;
}

This code is horribly inefficient though and calculating the average normals will take forever. (Unity will hang and the little colorful wheel will spin until it’s done) So don’t try this on any object with more than 200 or so triangles unless you have a lot of time… (please add your optimization tips in the comments below :])

Since the mesh is known from the start we could just as well pre-calculate the normals though, so that they don’t have to be calculated each time at startup.
A Simple and crude way of doing this: Run the game in the Editor >> copy the gameObject once the finalNormals have been calculated >> stop the Editor >> paste gameObject >> replace script with a version that lacks the normal-calculations and is only good for use with a script that already has the finalNormals set:
private var mesh : Mesh;
private var vertices = new Vector3[0];
private var normals = new Vector3[0];
var finalNormals = new Vector3[0];

function Start () {
    var meF : MeshFilter = GetComponent(MeshFilter);
    mesh = meF.mesh;

    vertices = mesh.vertices;
    normals = mesh.normals;
}

function Update () {
    for (var i = 0; i < vertices.length; i++) {
        vertices[i] += finalNormals[i] * 2.0 * Time.deltaTime;
    }
    mesh.vertices = vertices;
}

Okay, not bad. There’s still room for improvement though: It will look even more realistic (well, that is if you would classify “blowing up a wooden table” as “realistic”) if you also slowly scale up the gameObject with transform.localScale:

Bookmark the permalink. Follow any comments here with the RSS feed for this post. Trackbacks are closed, but you can post a comment.

2 Comments

    M Hughes on October 22, 2009 at 18:14 | Permalink

    if you were planning on only running this on a desktop and not an iPhone, I'd recommend doing the actual manipulation of vertex positions within a vertex shader program.

    I'd pass along with the position data its normal to move along and perform the "blow up" from there — as long as you submit your averaged normals rather than the mesh normals I don't see why this wouldn't work out for you

    col000r on October 22, 2009 at 19:15 | Permalink

    yeah, this is for an iPhone game… And to my surprise it even runs well!
    plus I don't know enough about vertex shaders… :) Thanks for the tip though!

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>