- Home /
finding vertices by distance to hit point
I cannot understand why my script is not detecting the vertices closest to the hit .point of a collider hit.
function CheckForHitVerts( hitPos : Vector3 )
{
var magRange : Vector2 = Vector2( 1, 1 );
var magRangeVerts : Vector2 = Vector2( 0, 0 );
var vertsDamaged : int = 0;
// rayhit in world space. find hit in local space.
//var hitWorldPos : Vector3; // this is passed in the function ( hitPos : Vector3 )
var hitLocalPos : Vector3 = hitPos - transform.position; // Vector3();
var vertWorldPos : Vector3;
for (var i:int = 0; i < verts.length; i ++)
{
vertWorldPos = verts[i] + transform.position;
//Debug.Log( "" + i + " vert : Localpos = " + verts[i] + " - hitLocalPos " + hitLocalPos + " . mag " + (verts[i] - hitLocalPos).magnitude + " :: vertWorldPos " + vertWorldPos + " - hitPos " + hitPos + " . mag " + (vertWorldPos - hitPos).magnitude + " :: " );
Debug.Log( "" + i + " vert : Localpos.norm = " + verts[i].normalized + " - hitLocalPos.norm " + hitLocalPos.normalized + " . mag " + (verts[i].normalized - hitLocalPos.normalized).magnitude + " :: vertWorldPos.normalized - hitPos.normalized ).mag " + (vertWorldPos.normalized - hitPos.normalized).magnitude + " :: " );
// store lowest and highest magnitude
if ( (verts[i].normalized - hitLocalPos.normalized).magnitude < magRange.x )
{
magRange.x = (verts[i].normalized - hitLocalPos.normalized).magnitude;
magRangeVerts.x = i;
}
if ( (verts[i].normalized - hitLocalPos.normalized).magnitude > magRange.y )
{
magRange.y = (verts[i].normalized - hitLocalPos.normalized).magnitude;
magRangeVerts.y = i;
}
// Find Damaged Verts
var damage : float = rescaleCurve.Evaluate( ((hitPos - transform.position) - verts[i]).magnitude );
if (damage > 0.0)
{
//verts[i] = verts[i] * damage;
Debug.Log( "verts[" + i + "] * damage of " + damage + " = " + verts[i] + " : " + ((hitPos - transform.position) - verts[i]).magnitude );
vertsDamaged ++;
}
}
Debug.Log( "magnitude range = " + magRange + " : vertsDamaged = " + vertsDamaged + " out of " + verts.length );
// Show hitPoint as point on mesh
verts[magRangeVerts.x] = verts[magRangeVerts.x] * 0.5;
verts[magRangeVerts.y] = verts[magRangeVerts.y] * 1.5;
// update vertices
myMesh.vertices = verts;
// update Collider
theMeshCollider.sharedMesh = myMesh;
}
this is my animation curve :
// 1 | -------
// | /
// | /
// | /
// | /
// | /
// | /
// |/
// .75 +--------------
// 0 1 2
and the line `if (damage > 0.0)` should read `if (damage < 0.999)` , but I'm not editing the question as UDN stuffs up the code formatting.
Have you tried to use RaycastHit.triangleIndex? If you have a RaycastHit structure, this is the easiest way to find the triangle hit. If not, I think you should use TransformPoint to convert the vertices to world space: it takes scale, rotation and position into account.
Again, I think you have seen the issue I couldn't, rotation. So :
((hitPos - transform.position) - verts[i])
breaks as soon as the object has any rotation not zero. Am looking at this now, thanks : http://docs.unity3d.com/Documentation/ScriptReference/Transform.TransformPoint.html
I am using a raycast for testing, but this will be a collider event, so I was basing everything around a World-Space Vector3.
It's all very interesting reading. To explain my aim, the verts are going to be scaled depending on their distance to the HitPoint. A vert with magnitude 0.01 will be scaled by 0.75, another with magnitude 0.5 will be scaled by 0.875, anything past magnitude 1 remains untouched at scale 1. I need to re-arrange a few things to test out TransformPoint.
$$anonymous$$y bad! You actually want to convert world points to local space, so you should use InverseTransformPoint ins$$anonymous$$d.
Hey guys ... I can't read the code, but can someone explain why you wouldn't use
RaycastHit.triangleIndex
to get started here ???
Answer by aldonaletto · Aug 28, 2012 at 11:42 AM
I rewrote your script using InverseTransformPoint, and optimized the search for the nearest and farthest vertices (whose purpose seems totally unclear to me) - hope this can help:
function CheckForHitVerts( hitPos : Vector3 )
{
// rayhit in world space. find hit in local space.
var hitLocalPos : Vector3 = transform.InverseTransformPoint(hitPos);
// get a normalized version of it:
var hitPosNorm : Vector3 = hitLocalPos.normalized;
// initialize min/max values (x = min, y = max):
var magRange : Vector2 = Vector2( Mathf.Infinity, Mathf.NegativeInfinity );
var magRangeVerts : Vector2;
var vertsDamaged : int = 0;
for (var i:int = 0; i < verts.length; i ++)
{
// I don't know why you're looking for the nearest and farthest
// vertices, but this is an optimized way to do that:
var dist : float = Vector3.Distance(verts[i].normalized, hitPosNorm);
// store lowest and highest magnitude
if ( dist < magRange.x )
{
magRange.x = dist;
magRangeVerts.x = i;
}
if ( dist > magRange.y )
{
magRange.y = dist;
magRangeVerts.y = i;
}
// Find Damaged Verts
var damage : float = rescaleCurve.Evaluate( (hitLocalPos - verts[i]).magnitude );
if (damage > 0.0)
{
// push near vertices towards mesh pivot
verts[i] = verts[i] * damage;
vertsDamaged ++;
}
}
// update vertices
myMesh.vertices = verts;
// update Collider
theMeshCollider.sharedMesh = myMesh;
}
Thankyou, I hopefully have time tonight to work on this. The nearest vert and furthest vert was simply a debugging device (show me the vert I'm hitting, show me the opposite vert). I couldn't previously understand the results I was getting, so the nearest/furthest was implemented.
The real aim is to scale down different verts of my asteroid : http://answers.unity3d.com/questions/305515/irregularities-with-procedurally-generated-sphere.html
When there is a collision, get the hitPoint. get the magnitude of each vert from the hitPoint. For all magnitudes under 0.99, read an animation curve and scale the vert depending on the anim curve value. This is the real working part of the script :
var damage : float = rescaleCurve.Evaluate( (hitLocalPos - verts[i]).magnitude );
if (damage < 0.99)
{
// push near vertices towards mesh pivot
verts[i] = verts[i] * damage;
}
Again, you have amazed me! Saw what the problem was (rotation factor) and provided an amazingy answer (also short and efficient). I got alot reading how you optimized my near/far vert debug method. This is now working perfectly with `var hitLocalPos : Vector3 = transform.InverseTransformPoint(hitPos);`
Full working function :
function CheckForHitVerts( hitPos : Vector3 )
{ // rayhit in world space. find hit in local space. var hitLocalPos : Vector3 = transform.InverseTransformPoint(hitPos); for (var i:int = 0; i < verts.length; i ++) { // Find Damaged Verts var damage : float = rescaleCurve.Evaluate( (hitLocalPos - verts[i]).magnitude ); if ( damage < 0.99 ) { // push near vertices towards mesh pivot verts[i] = verts[i] * damage; } } // update vertices my$$anonymous$$esh.vertices = verts; // update Collider the$$anonymous$$eshCollider.shared$$anonymous$$esh = my$$anonymous$$esh; }
hey guys i'm trying to do something similar, where i want to find all vertices in a radius around the hit point. But currently:
public void clearFog(Vector3 center, float radius)
{
colours = mesh.colors;
//find the point in local space
Vector3 localSpaceCenter = transform.InverseTransformPoint(center);
for(int index = 0; index < verts.Length; index ++)
{
float distance = Vector3.Distance(verts[index] , localSpaceCenter);
//if vert is within the radius
if(distance < radius)
{
colours[index].a = 0;
}
}
mesh.colors = colours;
}
Distance is being returned as strange results... while iterating through all vertices, distance only ever returns between 1 and around 1.0006 ... that makes no logical sense to me, the mesh in question is a plane. I'm clearly not doing what i think i'm doing here, as how could all verts in a plane be between 1 and 1.0006 units away from the center vert?
don't use local space at all. just go
Debug.Log( Vector3.Distance( center, verts[index] ) );
if you have more trouble. use Debug.DrawLine to find your problem quickly