- Home /
Mesh Deformation
I'm attempting to create a mesh deformation script. My approach to this is to access each vertice in an object and then move it a certain amount based off its distance from the colliding object and the direction its being hit from. This is what I tried (the script is on the projectile that is supposed to be deforming the mesh that its hitting):
void OnCollisionEnter (Collision collision) {
Mesh mesh = collision.transform.GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
int i = 0;
while (i < vertices.Length) {
float distance = Vector3.Distance(vertices[i], collision.transform.position);
if(distance > hitRadius) return;
float vertMove = distance/hitRadius;
Vector3 localDirection = transform.position - collision.transform.position;
vertices[i] += (localDirection * vertMove);
i++;
}
mesh.vertices = vertices;
mesh.RecalculateBounds();
}
The problem is that it doesn't do anything until the hitRadius is larger than the object, and then on collision, it moves the whole object. What am I doing wrong here?
EDIT
Okay so after doing some research on the forums, BigMisterB wrote this script (corrected by me):
using UnityEngine;
using System.Collections;
public class MeshDeform : MonoBehaviour {
public Vector3 relativeVelocity;
void Update () {
transform.Translate(relativeVelocity * Time.deltaTime);
}
void OnCollisionEnter (Collision collision) {
MeshFilter mf = collision.collider.GetComponent<MeshFilter>();
Mesh mesh = mf.mesh;
Vector3[] vertices = mesh.vertices;
Vector3 hitPoint = transform.InverseTransformPoint(collision.contacts[0].point);
float hitRadius = relativeVelocity.magnitude;
Vector3 hitDir = transform.InverseTransformDirection(-collision.contacts[0].normal);
int i = 0;
while (i < vertices.Length) {
float distance = Vector3.Distance(vertices[i], hitPoint);
Vector3 dir = (vertices[i] - hitPoint);
if(dir.magnitude < hitRadius){
float amount = 1 - dir.magnitude / hitRadius;
Vector3 vertMove = hitDir * amount;
vertices[i] += vertMove;
}
i++;
}
mesh.vertices = vertices;
mesh.RecalculateBounds();
}
}
So the script works now, but unfortunately the wrong vertices are being affected. For some reason, when I hit the object, the vertices completely opposite of the vertices that are hit are affected. Any ideas why that happens?
Oh and the projectile is a cube and the object being hit is a primitive sphere object.
Answer by Eric5h5 · Jun 25, 2012 at 08:46 PM
if(distance > hitRadius * speed) return;
I doubt that's what you meant. Presumably "continue" rather than "return". By the way, it would be a good idea to cache collision.transform.position, also transform.position. Additionally, you could optimize somewhat by using (a-b).sqrMagnitude (and the square distance) rather than Vector3.Distance.
Well if the distance of the vertex is larger than the hitRadius than the vertex isn't inside the area of effect, therefore doesn't need to be effected. I have no idea why I put hitRadius * speed, so I corrected it in the code for the question. But basically if the vertex isn't in the area of effect, than there's no need to continue with the rest of the code.
@nighthawx349: Using "return" means it quits the function entirely. That's not what you want.
Answer by imDanOush · Jun 21, 2015 at 03:11 PM
I'm not sure but maybe if you use "transform.TransformPoint()" instead of "transform.InverseTransformPoint()", it'd be working correctly.
Your answer
Follow this Question
Related Questions
Edit SkinnedMeshRenderer 1 Answer
Flattening a mesh by deforming it 0 Answers
How do you bend a cylindrical gameobject? 1 Answer
Getting mesh length (x,z) 1 Answer
Mesh deformation simulating a fire 0 Answers