Unity3D Building Damage Tutorial- Part V - Thick Mesh

Okay. Now, we have a one-sided mesh without thickness. When it is static, it may seem ok, but as soon as destruction starts, we "see" invisible interior and super-thick walls. Of course it seems impossible. So, to overcome this, i decided to give meshes thickness. My Aim here is to: You may visualise it that way: First, we have a mesh. Than, we scale it down a little and make its triangles face to the interior, as this triangles are visible only on one way. Another way, to overcome this problem would be to fizzle with shaders, but i'm not expert into this.
 * Produce an "interior" mesh facing inwards. Number of its verticles, Aliases and Triangles will be the same as outer mesh.

Anyway, to get to the aim, we will have to get through several steps.
 * 1) Make some starting method, like MakeTheMeshThick
 * 2) Make copy of ALL aliases. (I will name this copies "twins")
 * 3) Slightly change position of this twins.
 * 4) Add offseting to twins data. (I will talk about it in a moment)
 * 5) Invert Triangles of twins (to face opposite way)
 * 6) Update VerticleToAliasArray
 * 7) Update mesh.verticle (new method!)
 * 8) Update mesh.triangles(old method)

Offseting
So, when i was thinking about this, i realised of something. Lets say, that we have a simple cube, like than in  that picture. It has 8 Aliases. Lets say of numbers 1-8. '''In fact, they would have numbers 0-7, but i have made a mistake. '''

In addition 12 triangles and 36 verticles. Than, we add inside "twin cube". An offset of Aliases would be its number in pervious cube, in this case 8. An twin of Alias number 2 would be 2 + 8 = 10. In that way we can easily calculate numbers of every twin. A twin of triangle number 10 would be 10+12 = 22. etc.

MakeMeshThick Method
Well, the starting method. It will be called lets say in StartFire, so when player clicks on the building. public void MakeMeshThick{ List NewAliases = MakeAliasesTwin(Aliases); List NewTriangles = InvertTrianglesGivingListOfTriangles(Triangles); NewTriangles = AddOffsetToTriangleList(NewTriangles, mesh.vertices.Length); AddTwinsToVerticleToAliasArray; for(int i=0; i MakeAliasesTwin(List XAliases){ float Wall_Thickness = 0.005f; Vector3 TargetPosition; Vector3 NewPosition ; int offset = Aliases.Count; List NewAliases = new List; for(int i=0; i<XAliases.Count; i++){ TargetPosition = XAliases[i].positionRelative-(XAliases[i].normal); NewPosition = Vector3.MoveTowards(XAliases[i].positionRelative, TargetPosition, Wall_Thickness); NewAliases.Add(new Verticle(this,XAliases[i].number+offset,XAliases[i].Aliases,NewPosition) );//copy an alias NewAliases[i].AddOffsetToAliases(mesh.vertices.Length); }	 		return NewAliases; } Okay. This method gets a list of Aliases, this time our current Aliases. It should produce a list of new Aliases (the twins) with changed position and some variables.

			TargetPosition = XAliases[i].positionRelative-(XAliases[i].normal); NewPosition = Vector3.MoveTowards(XAliases[i].positionRelative, TargetPosition, Wall_Thickness); Two lines, two intresting things. First, i count TargetPosition, by decreasing the relativePosition of Alias by the normal value. (Decreasing!. We want a point inside the mesh, not outside.) Simple modification was made in Verticle.cs public Vector3 normal; //...................... 		public Verticle(MeshManager Owner ,int Xnumber, List XAliases, Vector3 XpositionRelative){ //................................ 		normal = OwnerManager.mesh.normals[Aliases[0]]; Well, for some reason, every verticle in the same position has the same normal, so I simply check the normal of first one. NewAliases.Add(new Verticle(this,XAliases[i].number+offset,XAliases[i].Aliases,NewPosition) );//copy an alias Here, i add a new Alias (a twin) to our List. Lets look deeper. NewAliases[i].AddOffsetToAliases(mesh.vertices.Length); We have to modify the aliases (the numbers of vertilces which form an Alias). The function code //In Verticles.cs public void AddOffsetToAliases(int offset){ for(int i=0; iList NewTriangles = InvertTrianglesGivingListOfTriangles(Triangles); We have a list of Vector3s named NewTriangles and a method InvertTrianglesGivingListOfTriangles.
 * Hard coded distance between an Alias and its twin. Later, I'll change it, and will not be hard coded of course.
 * Two Vector3. Will be used later.
 * Here I just count the offset.
 * Making a new List of Verticles. Here we will add the twins (changed Aliases)
 * This is Vertex_normals.pngsting. But before I am going to explain this, simple question. How we are going to know, which way we should move the Alias, for it to be "in" the mesh. First, i thought about scaling, but that was working well only with simple meshes with its "center" position in absolute inside. Than, I found out about vertex normals. More specific data can be found on wiki. What is intresting for us, is that in mesh.normals there are some specific vector3 for every variable. This are vectors pointing outside from the mesh, like in the picture. Using then, we can easily count the twin position.
 * Getting back to code, First we count the "targetPosition" The normal is only a direction so we cannot use it as a real point. This point first has to be calculated, and than moved from/to it.
 * And here we calculate the point. We are moving from the Alias relative position to the TargetPosition by the "Wall Thickness"
 * Using normal constructor. In more detail it is explained here. Anway, i pass the MeshManager, new number (the number of Alias + offset), aliases of this Alias (modified in a minute) and the new position.
 * Than i simply return that list.

InverttrianglesGivingListOfTriangles method
Before I'll go to code, how had I inverted them. Well, apparently one way to invert the traingles is to invert the order of verticles in mesh.triangles. From mesh.triangles = new int[] {0,1,3 , 1,2,5 ....} to {3,1,0  ,  5,2,1,  ....}. Well, it works and by doint that we preserve the original numbers of triangles (The twin triangle of triangle number 3 would be 3 + offset(the original number of triangles), but it would face other direction.) private List<Vector3> InvertTrianglesGivingListOfTriangles(List<Vector3> XTriangles = null){ if(XTriangles == null){XTriangles = Triangles;} List<Vector3> temp = new List<Vector3>; for(int i=0;i<XTriangles.Count;i++){ temp.Add( new Vector3(XTriangles[ i].z,XTriangles[  i].y,XTriangles[ i].x ) ); } 		return temp; <span style="font-family:Helvetica,Arial,sans-serif;">	}

<span style="font-family:Helvetica,Arial,sans-serif;">private List<Vector3> InvertTrianglesGivingListOfTriangles(List<Vector3> XTriangles = null){ <span style="font-family:Helvetica,Arial,sans-serif;">                   if(XTriangles == null){XTriangles = Triangles;} Here the list of Triangles is optional parameter. Maybe not allways we will want to use the current Triangles list. Using this optional we can start this method by both <span style="font-family:Helvetica,Arial,sans-serif;">		for(int i=0;i<XTriangles.Count;i++){ <span style="font-family:Helvetica,Arial,sans-serif;">			temp.Add( new Vector3(XTriangles[ i].z,XTriangles[  i].y,XTriangles[ i].x ) ); <span style="font-family:Helvetica,Arial,sans-serif;">		} return temp; And then we return this List.
 * We declare and initialise new list, and then we have loop
 * Well, we just invert the order in each Vector3 (but not invert the order of Vector3s)

AddOffsetToTriangleList method
Well, we still have to add the offset to this list. This might have been done in pervious metod, but i made additional function for this. //In MakeMeshThick NewTriangles = AddOffsetToTriangleList(NewTriangles, mesh.vertices.Length);

private List<Vector3> AddOffsetToTriangleList(List<Vector3> XTriangles, int offset){ List<Vector3> Temp = new List<Vector3>; for(int i=0; i<XTriangles.Count; i++){ Temp.Add(new Vector3(XTriangles[i].x+offset, XTriangles[i].y+offset, XTriangles[i].z+offset)); } 		return Temp; } Well, simple, we just add the offset to each variable in each Vector3.

Good, now as we will have in a moment twice as much verticles and Aliases we have to update VerticleToAliasArray

AddTwinsToVerticleToAliasArray method
private void AddTwinsToVerticleToAliasArray{ int[] NewVTAA = new int[VerticleToAliasArray.Length]; int offset = Aliases.Count; for(int i=0; i<VerticleToAliasArray.Length; i++){ NewVTAA[i] = VerticleToAliasArray[i] + offset; } 		int[] z = new int[VerticleToAliasArray.Length + NewVTAA.Length]; VerticleToAliasArray.CopyTo(z, 0); NewVTAA.CopyTo(z, VerticleToAliasArray.Length); VerticleToAliasArray = z; 	} Bear in mind that this only add twins. This is not UpdateVerticleToAliasArray. Such method would be simple, using checking the aliases (verticle numbers) of every Alias and filling it to list, but that might have taken a bit more time. So what we do here? for(int i=0; i<VerticleToAliasArray.Length; i++){ NewVTAA[i] = VerticleToAliasArray[i] + offset; } <span style="font-family:Helvetica,Arial,sans-serif;">		VerticleToAliasArray.CopyTo(z, 0); <span style="font-family:Helvetica,Arial,sans-serif;">		NewVTAA.CopyTo(z, VerticleToAliasArray.Length); <span style="font-family:Helvetica,Arial,sans-serif;">		VerticleToAliasArray = z;
 * A new array. VTAA means VerticleToAraryAlias. It has lenght of original VTAA.
 * Counting offset.
 * Filling new array.
 * <span style="font-family:Helvetica,Arial,sans-serif;">This is maybe a bit overcomplicated merging of two arrays. I am sure that there are ways to do this simpler and shorter, but at least it works.

Back To MakeMeshThick method
<span style="font-family:Helvetica,Arial,sans-serif;">		               for(int i=0; i<Aliases.Count; i++){ Aliases[i].DoHaveTwin = true; } 		Aliases.AddRange(NewAliases); Triangles.AddRange(NewTriangles); UpdateVerticlesList; UpdateTrianglesList; } First, there is that that for loop. Well, it changes a new property of Verticle Class public bool DoHaveTwin = false; to true. It is changed only in original Aliases, as every of them will have a twin. <span style="font-family:Helvetica,Arial,sans-serif;">		Aliases.AddRange(NewAliases); Triangles.AddRange(NewTriangles); This is simply adding NewAliases at the end of Aliases and the same thing at Triangles.

UpdateVerticleList method
New method, translating from List of Aliases to mesh.verticle array public void UpdateVerticlesList{ Vector3[] temp = new Vector3[VerticleToAliasArray.Length]; for(int i=0; i< VerticleToAliasArray.Length; i++){ int k = VerticleToAliasArray[i]; temp[i] = Aliases[k].positionRelative; } 		mesh.vertices = temp; } I make new Vector3 array, with lenght of VerticleToAliasArray, as VTAA lenght has been updated (doubled) before.Than we have got a for loop and <span style="font-family:Helvetica,Arial,sans-serif;">			int k = VerticleToAliasArray[i]; //Get the number of Alias having this particular verticle temp[i] = Aliases[k].positionRelative; // Set position, as Alias position is the same as position of verticle being in Alias Than, simple update of verticles array. <span style="font-family:Helvetica,Arial,sans-serif;">mesh.vertices = temp;

<span style="font-family:Helvetica,Arial,sans-serif;">Ending
<span style="font-family:Helvetica,Arial,sans-serif;">Updating triangles is the same as before. Now, if we look into a mesh there will be untextured area, as uv has not been yet changed. For files, go to Github .