/** * @param pDieMesh a mesh of a Die to process * @return a list of DieAreas based on all the triangles of the FIRST submesh. */ private static List <DieArea> convertMeshTrianglesToDieAreaInstances(Mesh pDieMesh) { List <DieArea> result = new List <DieArea>(); //get all mesh data int[] triangleIndices = pDieMesh.GetTriangles(0); int triangleIndicesLength = triangleIndices.Length; Vector3[] vertices = pDieMesh.vertices; Vector3[] normals = pDieMesh.normals; //convert all mesh data into a list of areas for (int i = 0; i < triangleIndicesLength; i += 3) { DieArea area = new DieArea(); int index1 = triangleIndices[i]; int index2 = triangleIndices[i + 1]; int index3 = triangleIndices[i + 2]; Vector3 vertex1 = vertices[index1]; Vector3 vertex2 = vertices[index2]; Vector3 vertex3 = vertices[index3]; //first calculate normal using cross product, this is not necessarily of length one.... area.normal = Vector3.Cross(vertex2 - vertex1, vertex3 - vertex1); //now use that normal to calculate area of the triangle spanned by v1,v2,v3: //the magnitude (or length) of the vector a×b, written as ∥a×b∥, //is the area of the parallelogram spanned by a and b, half of it gives us the triangle //a = v2-v1 here and b = v3-v1 (see Wikipedia) area.area = area.normal.magnitude / 2; //now normalize the normal since we like'm at length 1, size matters! ;). area.normal.Normalize(); //average the centerpoint area.centerPoint = (vertex1 + vertex2 + vertex3) / 3.0f; //lastly add the result to our area list result.Add(area); } return(result); }
/** * @param pAreasToCombine a list of all areas to search through for areas with similar normals * @param pMaxAreaSize (out parameter) the size of the biggest area found * @return a list of combined areas that all have unique normals */ private static List <DieArea> combineDieAreasWithSimilarNormals(List <DieArea> pAreasToCombine, out float pMaxAreaSize) { //process all areas so that we are left with //combined areas that all have a unique normal List <DieArea> uniqueAreas = new List <DieArea>(); float maxAreaSize = 0; for (int i = 0; i < pAreasToCombine.Count; i++) { DieArea currentArea = pAreasToCombine[i]; DieArea similarArea = findAreaWithSimilarNormal(uniqueAreas, currentArea.normal); if (similarArea == null) { //if there was no area that had a similar normal, create one: similarArea = new DieArea(); similarArea.area = currentArea.area; similarArea.centerPoint = currentArea.centerPoint; similarArea.normal = currentArea.normal; similarArea.areaCount = 1; uniqueAreas.Add(similarArea); } else { //if there already was an area in the uniqueArea list with a similar normal //combine it with the data for the current area similarArea.area += currentArea.area; //calculcate the new centerpoint using the weighted average of the previous centerpoint with the new one similarArea.centerPoint = (similarArea.centerPoint * similarArea.areaCount + currentArea.centerPoint) / (similarArea.areaCount + 1); similarArea.areaCount++; } //to be able to do the cutoff calculation in a later step we need to //keep track of the maximum area size thus far maxAreaSize = Mathf.Max(maxAreaSize, similarArea.area); } pMaxAreaSize = maxAreaSize; return(uniqueAreas); }