- Home /
Seemingly random results winding triangles?
Hello all.
First off, let me say I am new to unity, have some scripting experience, and battling UnityScript. Been pulling out what little hair I have left on this. I am working on a 2d game and the script I'm having trouble with is this pseudo destructible ground thing.
I Have a plane with a background image that has a scorched earth look to it, and a mesh that has a grass texture on it in front of it. All this script is supposed to do is wind the grass mesh triangle clockwise based off of the index fed from a raycast so that it looks like the ground is dissapearing.
At tops this can only happen once every 4-5 seconds, so it shouldn't eat up too much of the processor hopefully (mobile game). Eventually I want to have it wind the 2 triangles to the left and right (+ the 2 on the Z that I use for collision) of the raycasted index to make a little "crater", throw up a few pieces of ground, but for the moment this is giving me enough grief.
So what's happening is when I click on the mesh it will apparently wind whichever triangles it feels like. I am getting no errors (my syntax is improving I guess) but I have hit a wall..made of broken triangles. Here's the code:
var triangleIDX : int = 0;
function Update () {
if(Input.GetKeyDown(KeyCode.Mouse0))
{
var hit : RaycastHit;
if (Physics.Raycast (camera.ScreenPointToRay(Input.mousePosition), hit)) {
triangleIDX = hit.triangleIndex*3;
var meshCollider = hit.collider as MeshCollider;
var mesh : Mesh = meshCollider.GetComponent(MeshFilter).mesh;
var vertices = mesh.vertices;
var triangles = mesh.triangles;
var uvs : Vector2[] = new Vector2[vertices.Length];
mesh.Clear();
mesh.vertices = vertices;
for (var i = 0; i < triangleIDX; i=i+3)
{
var tmp = triangles[i];
triangles[i] = triangles[i+2];
triangles[i+2] = tmp;
}
for (i = 0 ; i < uvs.Length; i++)
uvs[i] = Vector2 (vertices[i].x, vertices[i].z);
mesh.uv = uvs;
mesh.triangles = triangles;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
//mesh.Optimize();
}
}
}
Does anyone know what is happening here? I'm guessing its something like the triangle strips are throwing off the raycast, no idea really, but after reading what I could find in the reference about these strips...I am still pretty lost. Any help with this would be greatly appreciated. Thanks.
-Ads
*update: Clarified question and updated code. *Another code update
Answer by SilverTabby · Sep 11, 2011 at 12:02 PM
I'm no expert on meshes, but the way I'm seeing it this is what this script does, correct me if I'm wrong:
It raycasts and finds a mesh
It then modifies and recreates that mesh
because of the nature of Raycast and user input, triangleIDX is going to be semi-random in nature
- You are then swapping the first and third vertices of the triangles
Why are you only swapping the first and last? If you are rotating the triangle, wouldn't you change the middle # as well?
why are you starting at i=0? Because TriangleIDX is semi-random, you are randomly going to affect somewhere between 1 and all of the triangles. Don't you only need to touch the one found by the ray cast
(i = triangleIDX; i < triangleIDX+3;i+=3)
?
you then recalculate the UVs of the mesh (I assume correctly?)
and then you apply all your changes.
Also, it seems like the line:
if (!Physics.Raycast (camera.ScreenPointToRay(Input.mousePosition), hit))
1) has a "!" when it shouldn't -- the if evaluates to true when nothing is found, and false when something is found? This seems like the code will throw a null pointer during runtime as is.
2) is missing a "{" - causing the code attached to it to not be the code you are expecting. Perhaps it's a typo from copy-paste?
I'm not an expert on meshes, so I'm mostly doing educated guess work trying to figure out what the code does.
Thanks for the reply. Yes, copy-paste and sleep deprivation don't mix well :) Raycast's are semi-random? I am only swapping the first and last vertices as per the right hand rule. And starting at i=0 because I believe you have to iterate through the array searching for the var (correct me if I'm wrong please).
It might be correct that you need to search for the var, but that is not what you are doing with your loop. A search, by definition, compares the value at position i to your target value, and moves on if the target value is not found.
You are not searching, you are just perfor$$anonymous$$g the operation for-each triangle. A search will skip incorrect results, something not happening here.
Also, they hand you an index. Why would you need to search for something that they hand you?
I have only heard of the right hand rule in Vector cross products, so I have no clue if you are correct or not for the triangles. It just seems to me like if you do the operation twice, it will cancel itself out - (1,2,3)-->(3,2,1)-->(1,2,3)
I'm not an expert. What I'm doing here is being the outside perspective (with little/no knowledge on the subject) that asks "what's that do?" You'd be surprised how effective a debugging tool it is. Also, sleep deprivation and answering questions isn't a good mix either :P
Raycasts are semi-random because humans (Input.mousePosition) are not precise nor reliable. One pixel different can produce a completely different triangle and hit location on the surface. If you were to look at the raw data from each RaycastHit, the data will look semi-random.
The right-hand rule for triangles is "wrap your fingers from verts 1,2,3; thumb points front face." So, swapping 1st and 3rd is like flipping normals. That will probably "delete" the tris, if backfaces are culled, or just give wierd lighting.
Unity has no facility for setting tri-strips, but has to be using them. $$anonymous$$y guess is that setting $$anonymous$$esh.triangles=
is secretly converting all those tris into something managable. $$anonymous$$eaning, you can ignore the thrilling tri-strip winding rules.
Your right-hand rule is the exact same as the cross product right-hand rule. Cross product right-hand rule is for finding normal vectors, not for rotating triangles. You want to be moving the second vert along with the other two so that the normal is always the same direction.
Answer by Owen-Reynolds · Sep 12, 2011 at 08:41 PM
Killing tris is going to leave hard-edged triangle shaded holes in your image. A cheesy way to also do that would be to "push back" the verts of the tri you hit, putting them behind the scortched plane and letting it show through. Ummm:
// logic: triangleIDX indexes the 1st vert in the hit tri.
// traingleIDX+1 and +2 are the other two verts
// o Maybe we could use barycentric coords to figure the closest one,
// but easier to push all three back a random amount
// o Assume scortched wall is 0.5 z behind us:
vertices[ triangles[triangleIDX+0] ].z += Random.value; // 0-1 pushback
vertices[ triangles[triangleIDX+1] ].z += Random.value;
vertices[ triangles[triangleIDX+2] ].z += Random.value;
The other way involves using the UV coords of the raycast hit to change the texture (either directly, or a system like Unity terrain, with grass, burnt and a "splat map" which changes with each hit and is used to mix them.)
Thanks for the suggestions. One reason I was wanting to use the winding method, is that the backface culled tri's with the mesh collider wouldn't collide. That would probably work well for the destructible ground.