Goo physics

Hi!

I’m trying to create a character similar to the character in Gish and have looked at Verlet integration to create the required dynamics for it.

What I am currently doing is creating a sphere object in Unity3d and applying the algorithm to the vertices that makes up the sphere.

The first problem I have is that the sphere doesn’t deform into the expected shape caused by the gravity pulling on it and secondly the sphere starts to vibrate wildly after a while.

I believe this problem to be caused by how I have created the constraints that link up the vertices.

private var vertices:Vector3[];
private var old_vertices:Vector3[];
private var forces:Vector3[];
private var num_vertices:int;
private var mesh:Mesh;
private var fTimeStep:float = 0.01;
private var num_iterations = 1;
private var bounds:Bounds;
private var num_constraints:int;
private var constraints:Array;

private var origin:Vector3 = Vector3.zero;

var gravity:Vector3 = new Vector3(0, -1, 0);

function TimeStep() {
	AccumulateForces();
	Verlet();
	SatisfyConstraints();
}

function Verlet() {
	for(i = 0; i < num_vertices; i++) {
		var temp:Vector3 = vertices[i];
		vertices[i] += vertices[i]-old_vertices[i]+forces[i]*fTimeStep*fTimeStep;
		old_vertices[i] = temp;
	}
}

// constraint class
class Constraint {
	var m_v1:int;
	var m_v2:int;
	var m_length:float;
	
	function Constraint(v1:int, v2:int, length:float) {
		m_v1 = v1;
		m_v2 = v2;
		m_length = length;
	}
}

// calculates the distance between 2 vertices
function RestLength(v1:int, v2:int) {
	return Vector3.Distance(vertices[v1], vertices[v2]);
}

function DistanceToOrigin(v:int) {
	return Vector3.Distance(vertices[v], origin);
}

function SatisfyConstraints() {
	for(j = 0; j < num_iterations; j++) {
		// keep vertices within the sphere
		// without any constraints in place, the sphere should collapse
		for(i = 0; i < num_vertices; i++) {
			vertices[i] = Vector3.Min(Vector3.Max(vertices[i], bounds.min), bounds.max);
		}
		// adjustment of constraints
		for(i = 0; i < num_constraints; i++) {
			if(constraints[i].m_v2 == -1) {
				var o_delta:Vector3 = vertices[constraints[i].m_v1]-origin;
				var o_deltaLength:float = DistanceToOrigin(constraints[i].m_v1);
				var o_diff = (o_deltaLength-constraints[i].m_length)/o_deltaLength;
				vertices[constraints[i].m_v1] -= o_delta*0.5*o_diff;
				origin += o_delta*0.5*o_diff;
			}
			else {
				var delta:Vector3 = vertices[constraints[i].m_v1]-vertices[constraints[i].m_v2];
				var deltaLength:float = RestLength(constraints[i].m_v1, constraints[i].m_v2);
				var diff = (deltaLength-constraints[i].m_length)/deltaLength;
				vertices[constraints[i].m_v1] -= delta*0.5*diff;
				vertices[constraints[i].m_v2] += delta*0.5*diff;
			}
		}
	}
}

function AccumulateForces() {
	for(i = 0; i < num_vertices; i++) {
		forces[i] = gravity;
	}
}

function Start() {
	mesh = GetComponent(MeshFilter).mesh;
	num_vertices = mesh.vertexCount;
	vertices = mesh.vertices;
	old_vertices = mesh.vertices; // or should it be initialized zero vectors
	forces = new Vector3[num_vertices];
	
	bounds = mesh.bounds;
	
	// build constraints
	// how many constraints do we need?
	// let's try building a constraint for each edge of a triangle first
	constraints = new Array();
	var triangles:int[] = mesh.triangles;
	for(i = 0; i < triangles.Length; i+=3) {
		var v1 = triangles[i];
		var v2 = triangles[i+1];
		var v3 = triangles[i+2];
		
		/*constraints.Add(Constraint(v1, -1, DistanceToOrigin(v1)));
		constraints.Add(Constraint(v1, v2, RestLength(v1, v2)));
		constraints.Add(Constraint(v2, -1, DistanceToOrigin(v2)));
		constraints.Add(Constraint(v2, v3, RestLength(v2, v3)));
		constraints.Add(Constraint(v3, -1, DistanceToOrigin(v3)));
		constraints.Add(Constraint(v3, v1, RestLength(v3, v1)));*/
		
		constraints.Add(Constraint(v1, -1, DistanceToOrigin(v1)));
		constraints.Add(Constraint(v1, v3, RestLength(v1, v3)));
		constraints.Add(Constraint(v3, -1, DistanceToOrigin(v3)));
		constraints.Add(Constraint(v3, v2, RestLength(v3, v2)));
		constraints.Add(Constraint(v2, -1, DistanceToOrigin(v2)));
		constraints.Add(Constraint(v2, v1, RestLength(v2, v1)));
	}
	num_constraints = constraints.length;
}

function Update () {
	TimeStep();
	mesh.vertices = vertices;
	mesh.RecalculateNormals();
}

The part that links up to the origin is a bit messy but i’m working on it.

Above is my code. To try out, create a sphere and link it with this script.

My question is

  1. Should I create constrains for every edge of each triangle of the sphere?

  2. Should I create constraints for every vertex to the origin?

  3. How should the indices in the triangles array be read? I am asking this because the commented-out code block gives a different effect.

  4. What would be the simplest way to create a goo like character in Unity3D other than using the softbody script that is available?

Any help would be greatly appreciated!
Thanks!

Looks interesting! I’m gonna take some time to read up on this technique and see what I can come up with. If I find anything useful I’ll let you know.

Good luck!

Now i have no coding knowledge at all, so i can’t make heads or tails of what you just posted. However, i watched a thread over at scirra.com with a chap trying to make a (2d) blob. I don’t know how relevant it would be for 3d, but the ideas might translate. Generally they had a central point connected to the skin, and having a double skin increased stability a hell of a lot.

Take a look at Blob Physics « Cowboy Programming might help. The idea involves building a lattice of inner and outer springs. You might be able to do this with a rig in Maya and let Unity’s physics handle it. Might be more efficient than doing it in script

Interesting topic!

http://forum.unity3d.com/viewtopic.php?t=44369&highlight=cell

Wox you didn’t include a sample, is this how you did it? Though it’s not quite as tar like as Gish.

276977–9936–$jellyball_720.unitypackage (56.4 KB)

That’s how I did my jelly fish example. But put the Blend weights in the Quality settings to 4 Bones if you haven’t.
Maybe with some tweaking or some coding you can get it feel/look more like tar/Gish.

(For fun I change the gravity to -35.81 and played a little with the rigidbody mass on the bones, joint1 3 all other 0.4, and it gave a much more compact feeling)

If I remember right Gish had different states also, sticky and another he got “squashed” and some more stuff (if I remember right). Fun game :slight_smile: but I only played the trail version a long long time ago.

Hi guys! Thanks for the suggestions. I’ve tried out Wox suggestion and it worked great.

I’ll post mine after I’m done with it.

CHeers!

Good that you liked the idea, looking forward to see what u end up whit.

Hi guys!

Here’s my setup.
You can move the blob around with the arrow keys.

Hi Wox,
How did you manage the movement and rotation of the jellyfish in your example?

For mine, I have some rotational problems with my blob and that causes instability.

I have tried stiffening the springs but the character loses the blob feeling and becomes more like a rubber ball. LOL.

I have also checked my local orientation axes in maya.

280042–10053–$blob_634.unitypackage (1.01 MB)

Hello fgs

I can’t configure this properly, I know that char_setup should be added to the joint1. What about the rest?
What is “bonesCloserToGround”?
Hope you still have the file since so much time has passed.