- Home /
Vertex colouring on a plane (moving plane)
In my scene I have a plane with a sphere resting on it. I have the vertices changing colour as the sphere moves across the plane. As soon as I try to move the plane instead of moving the sphere it stops working (I need it this way for a different project). Even moving the plane a tiny amount stops the vertices changing colour. I suspect its something to do with the vertex locations being different when the plane is moved. Heres the code I'm using:
using UnityEngine;
using System.Collections;
//[ExecuteInEditMode]
public class Plane : MonoBehaviour {
public Vector3 contactPoint;
public Vector3 nearestVert;
float h, v;
Mesh mesh;
Vector3[] verts;
Vector3 vertPos;
Color[] colors;
// Use this for initialization
void Start () {
mesh = GetComponent<MeshFilter>().mesh;
}
// Update is called once per frame
void Update () {
verts = mesh.vertices;
colors = mesh.colors;
//v = Input.GetAxis("Vertical");
//h = Input.GetAxis("Horizontal");
//transform.Translate(h*0.2f, 0, v*0.2f);
nearestVert = NearestVertexTo(contactPoint);
Debug.Log("NearestVert: " + nearestVert);
for( int i = 0; i < verts.Length; i++)
{
if(verts[i] == nearestVert)
{
Debug.Log("Collision Yo");
colors[i] = Color.red;
}
}
mesh.colors = colors;
mesh.vertices = verts;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
public Vector3 NearestVertexTo(Vector3 point)
{
// convert point to local space
point = transform.InverseTransformPoint(point);
float minDistanceSqr = Mathf.Infinity;
Vector3 nearestVertex = Vector3.zero;
// scan all vertices to find nearest
foreach (Vector3 vertex in mesh.vertices)
{
Vector3 diff = point-vertex;
float distSqr = diff.sqrMagnitude;
if (distSqr < minDistanceSqr)
{
minDistanceSqr = distSqr;
nearestVertex = vertex;
}
}
// convert nearest vertex back to world space
return transform.TransformPoint(nearestVertex);
}
void OnCollisionStay(Collision collision) {
foreach (ContactPoint contact in collision.contacts) {
Debug.DrawRay(contact.point, Vector3.up, Color.green, 4, false);
contactPoint = contact.point;
}
}
}
Any pointers on how I could move forward from here? What I need is the plane to move, the sphere to be stationary and the vertices to still change colour. Thanks
Answer by robertbu · Dec 17, 2013 at 06:38 AM
I believe line 79 is your issue. You are converting the point found back into world space, but you are using in a comparison of local coordinates on line 42. The only way I can see this code working is if the plane is at (0,0,0) and scaled (1,1,1). Rewrite line 79 to:
return nearestVertex;
But there are some other things here that you should consider changing. There is no reason to go through the vertices twice. You go through them once in NearestVertexTo() then again on 40. Instead, rewrite NearestVertexTo() so that it uses a for() loop instead of a foreach() loop, and then return the index of the closest vertex. You also don't need to reset the vertices or recalculate the bounds or recalculate the normals. Here is a quick, untested rewrite:
using UnityEngine;
using System.Collections;
public class Plane : MonoBehaviour {
public Vector3 contactPoint;
public Vector3 nearestVert;
Mesh mesh;
Vector3[] verts;
Vector3 vertPos;
Color[] colors;
void Start () {
mesh = GetComponent<MeshFilter>().mesh;
verts = mesh.vertices;
colors = mesh.colors;
}
void Update () {
colors[NearestVertexTo(contactPoint)] = Color.red;
mesh.colors = colors;
}
int NearestVertexTo(Vector3 point) {
point = transform.InverseTransformPoint(point);
float minDistanceSqr = Mathf.Infinity;
int nearestVertex = -1;
// scan all vertices to find nearest
for (int i = 0; i < verts.Length; i++) {
float distSqr = (point - verts[i]).sqrMagnitude;
if (distSqr < minDistanceSqr) {
minDistanceSqr = distSqr;
nearestVertex = i;
}
}
return nearestVertex;
}
void OnCollisionStay(Collision collision) {
foreach (ContactPoint contact in collision.contacts) {
Debug.DrawRay(contact.point, Vector3.up, Color.green, 4, false);
contactPoint = contact.point;
}
}
}
Works perfectly, Its was 4am and I could not for the life of me even think where I was going wrong. Thanks so much, also thanks for the other little tweaks some of that was just old code from when I was testing earlier I ought to keep it a little tidier. $$anonymous$$uch appreciated
Ive started now to use it in the way I had originally intended, with a rotating sphere ins$$anonymous$$d of a plane. I am now encountering the error "Array index is out of bounds" regarding this line
colors[NearestVertexTo(contactPoint)] = Color.red;
The code is exactly the same bar the fact the script is now attached to a sphere which rotates. Any ideas?
As a start verify the return value from NearestVertexTo(). Is it returning -1 by any chance? If so, next check the length of the 'verts' array next.
NearestVertexTo is return the correct nearest vertex, it changes as the as the sphere rotates. And the length of Verts is correct as well its returning 525. Im baffled. Would you like me to upload a package of it?
I was using the wrong shader on the sphere. I am a clutz. I need to be using the Vertex Colored Shader
Your answer
Follow this Question
Related Questions
Overlapping Prefabs 0 Answers
How to create a 2D mesh from a vertex array? 1 Answer
Boat physics 2 Answers
Strange artifacts on Vertex Color Shader 0 Answers
Vertex Color to Texture2D?? 0 Answers