- Home /
Want to create a new mesh (single triangle) "cloned" from an already existing triangle ....
Hi,
I have a sort of a planet earth object, a mesh when i click on a it, i register the triangle i clicked on (i got to get its triangle index) from there i want to "create" a new mesh that is based on that very same triangle but would be like "hovering" over the original mesh (to achieve like a "floating" white clone of that triangle , this would show that the tile was selected, as it will turn into a white material)
(originally i planned to do it thru shader - but it's too hard for me now and i thought doing it with a mesh would make me learn about them - i thought about a Decal , but they are not in standard Unity yet, ....)
I have been struggling but i learned a lot about vertices and all, which is good, still i am at a stuck :
the new object is created and all, but it is empty and at the center of the world instead of being hovering the original triangle

here is the code of the function that does it all :
// WHEN WHE click on a triangle on the "Earth Mesh", a new one is created, like a clone of that triange, just a bit hovering it, and as a separate object
void SelectedTile(int triangleindex)
{
//check if a "Selected Tile" was already created (previous click) if yes, destroy it
GameObject[] olderTiles;
olderTiles = GameObject.FindGameObjectsWithTag("stile");
if (olderTiles.Length != 0)
{
Debug.Log("OLDER TILE FOUND, must destroy it0");
Destroy(olderTiles[0]);
}
Debug.Log("TILE SELECTED");
Debug.Log("Triangle id : " + triangleindex);
//get the whole mesh we clicked on, single out the vertices and the normals and the triangles
Mesh mesh = transform.GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
Vector3[] normals = mesh.normals;
int[] triangles = mesh.triangles;
//Single out the 3 vertices from a specific triangle (the one that has the index passed as a parameter triangleindex in the method)
Vector3 p0 = vertices[triangles[triangleindex * 3 + 0]];
Vector3 p1 = vertices[triangles[triangleindex * 3 + 1]];
Vector3 p2 = vertices[triangles[triangleindex * 3 + 2]];
//
Transform hitTransform = transform;
p0 = hitTransform.TransformPoint(p0);
p1 = hitTransform.TransformPoint(p1);
p2 = hitTransform.TransformPoint(p2);
// Draw the triangle debug lines
Color color = new Color(1f, 0f, 0f);
Debug.DrawLine(p0, p1, color);
Debug.DrawLine(p1, p2, color);
Debug.DrawLine(p2, p0, color);
// CREATE a new MESH to create a flat triangle
// Set up game object with mesh;
GameObject Selectedtile = new GameObject("Selectedtile_"+triangleindex);
Selectedtile.tag = "stile";
// add the right needed components
Mesh newmesh = new Mesh();
Selectedtile.AddComponent<MeshFilter>();
Selectedtile.AddComponent<MeshRenderer>().material.color = Color.white;
Selectedtile.GetComponent<MeshFilter>().mesh = newmesh;
//create temp arrays for vertices and UVS and triangle
Vector3[] newVertices = new Vector3[3]; //just need 3 i guess....
Vector2[] newUV = new Vector2[3]; // same thing?
int[] newTriangles = new int[3]; //i guess one would even be enough... ??
//tell these vertices to be like the ones we got from the original target triangle but with little displacement so it "hovers" over it
for (int i = 0; i < 3; i++)
{
newVertices[i] += vertices[triangles[triangleindex * 3 + 0]] + new Vector3(0.5f,0.5f,0.5f); //not sure about that....
}
//same thing for UVs....not sure about what i am doing.....
for (int i = 0; i < 3; i++)
{
newUV[i] = new Vector2(vertices[i].x, vertices[i].z);
}
// assign the temp calculated arrays into the arrays of the new Mesh.
newmesh.vertices = newVertices;
newmesh.uv = newUV;
newmesh.triangles = newTriangles;
newmesh.RecalculateNormals();
newmesh.RecalculateBounds();
}
actually.... it is kinda working
i was just thinking it didnt worked because the inspector field mesh filter was empty....
but here I have my new triangle !!!
i guess i was missing the newmesh.Clear(); .....
Answer by Ya7yasugari · Jan 20, 2019 at 05:15 PM
just an update
i modified this line
newVertices[i] += vertices[triangles[triangleindex * 3 + 0]] + new Vector3(0.5f,0.5f,0.5f); //not sure about that....
as (change the 0 into i, in the vertices[.....] :
newVertices[i] += vertices[triangles[triangleindex * 3 + i]] + new Vector3(0.5f,0.5f,0.5f); //not sure about that....
still, same problem new object is empty... and i can see that the Mesh Filter component in the inspector is empty ....
i also modified the declaration of the newtriangles, which was i think empty...
int[] newTriangles = new int[] { 0, 1, 2 };
still, no luck, mesh is empty....
Answer by Eno-Khaon · Jan 20, 2019 at 10:11 PM
To offer an idea to improve efficiency a little bit first, AddComponent<> returns the component that was added:
MeshRenderer mr = Selectedtile.AddComponent<MeshRenderer>();
MeshFilter mf = Selectedtile.AddComponent<MeshFilter>();
mr.material.color = Color.white;
mf.mesh = newmesh;
This way, if there are further changes needing to be made to either the MeshRenderer or MeshFilter's attributes, you don't have to call GetComponent<> on them afterward.
For vertex positioning, you can use the normal of the triangle you're creating to dictate its new position:
// Condensing names to shorten the line a bit:
// v = vertices
// t = triangles
// ti = triangleindex
// new variable: oldTriangles, to mark which three
// are part of the new triangle being made
// ot = oldTriangles
int[] ot = new int[3];
for(int i = 0; i < 3; i++)
{
ot[i] = t[ti * 3 + i];
}
Vector3 triNormal = Vector3.Cross(v[ot[1]] - v[ot[0]], v[ot[2]] - v[ot[0]]).normalized;
Because vertex winding order is clockwise, you can reliably get a face's normal relative to its vertices.
1
/
/
/
0 ------ 2
Then, applying that normal becomes simple:
// Again, condensing names for readability here
// nv = newVertices
for (int i = 0; i < 3; i++)
{
// Push each vertex in the direction of triNormal
// and by a determined "distance" (e.g. 0.5f)
nv[i] += v[ot[i]] + triNormal * distance;
}
If you want to utilize the texture that's applied to the object you're copying from, your triangle's UVs can copy the UVs of the original object. Otherwise, if you want a large amount of UV space available (in case you still want to apply a texture), you can make use of the entire UV space instead:
Vector2[] uvs = mesh.uvs;
// ...
// Copy existing uvs
for(int i = 0; i < 3; i++)
{
newUV[i] = uvs[ot[i]];
}
// Or, to create new uvs at corners...
newUV[0] = Vector2.zero;
newUV[1] = Vector2.up;
newUV[2] = Vector2.right;
To note, you can also give individual meshes their own names, if you don't want those fields to appear blank:
newMesh.name = "Selectedtile_"+triangleindex+"_mesh";
Your answer
Follow this Question
Related Questions
contains two different ids for the same vertex 0 Answers
Problem drawing a mesh with Graphics.DrawMeshNow 1 Answer
Easy way to convert a bunch of vertices to triangles or uv's? 1 Answer
Save only visible part of mesh 1 Answer
Highmap on a cube. 0 Answers