Advertisement
Guest User

DelaunayTriangulation

a guest
Nov 18th, 2019
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 24.07 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using TriangleNet.Geometry;
  3. using TriangleNet.Meshing;
  4. using UnityEngine;
  5. using Mesh = UnityEngine.Mesh;
  6.  
  7. [RequireComponent(typeof(MeshFilter))]
  8. [RequireComponent(typeof(MeshRenderer))]
  9. [RequireComponent(typeof(MeshCollider))]
  10. public class CustomMesh : MonoBehaviour
  11. {
  12.     private static readonly int BaseMap = Shader.PropertyToID("_BaseMap");
  13.  
  14.     public MeshFilter MeshFilter { get; private set; }
  15.     public MeshRenderer MeshRenderer { get; private set; }
  16.     public MeshCollider MeshCollider { get; private set; }
  17.    
  18.     public Mesh Mesh { get; set; }
  19.  
  20.     private void Awake()
  21.     {
  22.         MeshFilter = GetComponent<MeshFilter>();
  23.         MeshRenderer = GetComponent<MeshRenderer>();
  24.         MeshCollider = GetComponent<MeshCollider>();
  25.         Mesh = new Mesh();
  26.         MeshFilter.mesh = Mesh;
  27.     }
  28.    
  29.     public void CreateCustomMesh(SerializedMesh serializedMesh)
  30.     {
  31.        
  32.         if (serializedMesh.points.Count % 2 != 0)
  33.         {
  34.             Debug.LogError($"CreateCustomMesh - Cannot have odd points count ! ({serializedMesh.points.Count.ToString()} provided)");
  35.             return;
  36.         }
  37.        
  38.         List<Transform> childrenTransform = new List<Transform>();
  39.  
  40.         for (int i = 0; i < serializedMesh.children.Count; i++)
  41.         {
  42.             Transform child = SerializedManager.Instance.InstantiateSerializedGameObject(serializedMesh.children[i]);
  43.             child.SetParent(transform);
  44.             childrenTransform.Add(child);
  45.         }
  46.  
  47.         int pointCount = serializedMesh.points.Count / 2;
  48.         int vertCount = serializedMesh.points.Count + childrenTransform.Count * 8;
  49.        
  50.         Vector3[] vertices = new Vector3[vertCount];
  51.         int[] triangles;
  52.        
  53.        
  54.         // Create vertices
  55.         for (int i = 0; i < serializedMesh.points.Count; i++)
  56.         {
  57.             vertices[i] = serializedMesh.points[i].ToVector3();
  58.         }
  59.  
  60.         Plane frontFacePlane = new Plane(vertices[0], vertices[1], vertices[2]);
  61.         Plane backFacePlane = new Plane(vertices[pointCount], vertices[pointCount+1], vertices[pointCount+2]);
  62.  
  63.         for (int i = 0; i < childrenTransform.Count; i++)
  64.         {
  65.             /*
  66.             // World space
  67.             MeshRenderer meshRenderer = childrenTransform[i].GetComponentInChildren<MeshRenderer>();
  68.             if (meshRenderer == null)
  69.             {
  70.                 Debug.LogError("CreateCustomMesh - Could not get mesh bounds of children !");
  71.                 continue;
  72.             }      
  73.             Bounds bounds = meshRenderer.bounds;
  74.             */
  75.            
  76.             // Local space
  77.             Mesh mesh = childrenTransform[i].GetComponent<MeshFilter>().mesh;
  78.             if (mesh == null)
  79.             {
  80.                 Debug.LogError("CreateCustomMesh - Could not get MeshRenderer of children !");
  81.                 continue;
  82.             }
  83.             Bounds bounds = mesh.bounds;
  84.            
  85.            
  86.        
  87.             Vector3 v0 = new Vector3(bounds.center.x - bounds.extents.x, bounds.center.y - bounds.extents.y, bounds.center.z - bounds.extents.z);
  88.             Vector3 v1 = new Vector3(bounds.center.x - bounds.extents.x, bounds.center.y + bounds.extents.y, bounds.center.z - bounds.extents.z);
  89.             Vector3 v2 = new Vector3(bounds.center.x + bounds.extents.x, bounds.center.y + bounds.extents.y, bounds.center.z - bounds.extents.z);
  90.             Vector3 v3 = new Vector3(bounds.center.x + bounds.extents.x, bounds.center.y - bounds.extents.y, bounds.center.z - bounds.extents.z);
  91.             Vector3 v4 = new Vector3(bounds.center.x - bounds.extents.x, bounds.center.y - bounds.extents.y, bounds.center.z + bounds.extents.z);
  92.             Vector3 v5 = new Vector3(bounds.center.x - bounds.extents.x, bounds.center.y + bounds.extents.y, bounds.center.z + bounds.extents.z);
  93.             Vector3 v6 = new Vector3(bounds.center.x + bounds.extents.x, bounds.center.y + bounds.extents.y, bounds.center.z + bounds.extents.z);
  94.             Vector3 v7 = new Vector3(bounds.center.x + bounds.extents.x, bounds.center.y - bounds.extents.y, bounds.center.z + bounds.extents.z);
  95.  
  96.             // This is probably one problem, I'm just trying values randomly...
  97.             Vector3 childForward = childrenTransform[i].forward;
  98.             childForward.x *= -90f;
  99.             v0 = Quaternion.Euler(0, childForward.x, 0) * v0;
  100.             v1 = Quaternion.Euler(0, childForward.x, 0) * v1;
  101.             v2 = Quaternion.Euler(0, childForward.x, 0) * v2;
  102.             v3 = Quaternion.Euler(0, childForward.x, 0) * v3;
  103.             v4 = Quaternion.Euler(0, childForward.x, 0) * v4;
  104.             v5 = Quaternion.Euler(0, childForward.x, 0) * v5;
  105.             v6 = Quaternion.Euler(0, childForward.x, 0) * v6;
  106.             v7 = Quaternion.Euler(0, childForward.x, 0) * v7;
  107.  
  108.  
  109.             // Local space only ///////////////////////////////
  110.             Vector3 childPos = childrenTransform[i].position;
  111.             childPos.x -= bounds.center.x * 2;
  112.             childPos.y -= bounds.center.y * 2;
  113.             childPos.z -= bounds.center.z * 2;
  114.             v0 += childPos;
  115.             v1 += childPos;
  116.             v2 += childPos;
  117.             v3 += childPos;
  118.             v4 += childPos;
  119.             v5 += childPos;
  120.             v6 += childPos;
  121.             v7 += childPos;
  122.             ////////////////////////////////////////////////////
  123.            
  124.             // This is so that the vertices of the holes don't "shrink" or expand the mesh, but rather stay on the same plane, it works
  125.             v0 = frontFacePlane.ClosestPointOnPlane(v0);
  126.             v1 = frontFacePlane.ClosestPointOnPlane(v1);
  127.             v2 = frontFacePlane.ClosestPointOnPlane(v2);
  128.             v3 = frontFacePlane.ClosestPointOnPlane(v3);
  129.            
  130.             v4 = backFacePlane.ClosestPointOnPlane(v4);
  131.             v5 = backFacePlane.ClosestPointOnPlane(v5);
  132.             v6 = backFacePlane.ClosestPointOnPlane(v6);
  133.             v7 = backFacePlane.ClosestPointOnPlane(v7);
  134.            
  135.             /*
  136.             // Create small sphere at each vert pos to help visualize order
  137.             var go0 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  138.             go0.transform.localScale = Vector3.one * 0.1f;
  139.             go0.transform.position = v0;
  140.             go0.name = "v0";
  141.             var go1 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  142.             go1.transform.localScale = Vector3.one * 0.1f;
  143.             go1.transform.position = v1;
  144.             go1.name = "v1";
  145.             var go2 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  146.             go2.transform.localScale = Vector3.one * 0.1f;
  147.             go2.transform.position = v2;
  148.             go2.name = "v2";
  149.             var go3 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  150.             go3.transform.localScale = Vector3.one * 0.1f;
  151.             go3.transform.position = v3;
  152.             go3.name = "v3";
  153.             var go4 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  154.             go4.transform.localScale = Vector3.one * 0.1f;
  155.             go4.transform.position = v4;
  156.             go4.name = "v4";
  157.             var go5 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  158.             go5.transform.localScale = Vector3.one * 0.1f;
  159.             go5.transform.position = v5;
  160.             go5.name = "v5";
  161.             var go6 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  162.             go6.transform.localScale = Vector3.one * 0.1f;
  163.             go6.transform.position = v6;
  164.             go6.name = "v6";
  165.             var go7 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  166.             go7.transform.localScale = Vector3.one * 0.1f;
  167.             go7.transform.position = v7;
  168.             go7.name = "v7";
  169.             */
  170.  
  171.  
  172.             vertices[serializedMesh.points.Count + 8 * i] = v0;
  173.             vertices[serializedMesh.points.Count + 8 * i + 1] = v1;
  174.             vertices[serializedMesh.points.Count + 8 * i + 2] = v2;
  175.             vertices[serializedMesh.points.Count + 8 * i + 3] = v3;
  176.             vertices[serializedMesh.points.Count + 8 * i + 4] = v4;
  177.             vertices[serializedMesh.points.Count + 8 * i + 5] = v5;
  178.             vertices[serializedMesh.points.Count + 8 * i + 6] = v6;
  179.             vertices[serializedMesh.points.Count + 8 * i + 7] = v7;
  180.            
  181.            
  182. #if UNITY_EDITOR
  183.             // Draw bounding box of the holes
  184.             Debug.DrawLine(v0, v1, Color.red, 1000);
  185.             Debug.DrawLine(v1, v2, Color.red, 1000);
  186.             Debug.DrawLine(v2, v3, Color.red, 1000);
  187.             Debug.DrawLine(v3, v0, Color.red, 1000);
  188.             Debug.DrawLine(v4, v5, Color.red, 1000);
  189.             Debug.DrawLine(v4, v7, Color.red, 1000);
  190.             Debug.DrawLine(v5, v6, Color.red, 1000);
  191.             Debug.DrawLine(v6, v7, Color.red, 1000);
  192.             Debug.DrawLine(v0, v4, Color.red, 1000);
  193.             Debug.DrawLine(v1, v5, Color.red, 1000);
  194.             Debug.DrawLine(v2, v6, Color.red, 1000);
  195.             Debug.DrawLine(v3, v7, Color.red, 1000);
  196.            
  197. #endif
  198.  
  199.         }
  200.  
  201.         // This is what doesn't work
  202.         // If we can't predict the triangulation, use Delaunay
  203.         if (serializedMesh.children.Count > 1 || serializedMesh.points.Count > 8)
  204.         {
  205.            
  206.             List<int> meshTriangles = new List<int>();
  207.            
  208.             // Outer border
  209.             for (int i = 0; i < pointCount - 1; i++)
  210.             {
  211.                 int v0 = i + pointCount + 1;
  212.                 int v1 = i + 1;
  213.                 int v2 = i;
  214.                 int v3 = i + pointCount;
  215.  
  216.                 meshTriangles.Add(v0);
  217.                 meshTriangles.Add(v1);
  218.                 meshTriangles.Add(v2);
  219.                 meshTriangles.Add(v2);
  220.                 meshTriangles.Add(v3);
  221.                 meshTriangles.Add(v0);
  222.             }
  223.            
  224.             // Bridge last face of the outer border
  225.             meshTriangles.Add(pointCount);
  226.             meshTriangles.Add(0);
  227.             meshTriangles.Add(pointCount-1);
  228.             meshTriangles.Add(pointCount-1);
  229.             meshTriangles.Add(2*pointCount-1);
  230.             meshTriangles.Add(pointCount);
  231.            
  232.             ConstraintOptions options = new ConstraintOptions
  233.             {
  234.                 ConformingDelaunay = true,
  235.                 SegmentSplitting = 2
  236.             };
  237.             /*
  238.             QualityOptions quality = new QualityOptions
  239.             {
  240.                 MaximumAngle = 25
  241.             };
  242.             */
  243.            
  244.            
  245.             Polygon polygon = new Polygon();
  246.  
  247.             Vector3 faceNormal = TriangleNormal(serializedMesh.points[0].ToVector3(),serializedMesh.points[1].ToVector3(), serializedMesh.points[2].ToVector3());
  248.             int dir = GetBoxDir(faceNormal);
  249.            
  250.             for (int i = 0; i < pointCount; i++)
  251.             {
  252.                 Vector2 tmp = GetBoxUV(serializedMesh.points[i].ToVector3(), dir);
  253.                 Vertex vertex = new Vertex(tmp.x, tmp.y);
  254.                 polygon.Add(vertex);
  255.             }
  256.             for (int i = 0; i < polygon.Points.Count; i++)
  257.             {
  258.                 polygon.Add(new Segment(polygon.Points[i], i == polygon.Points.Count - 1 ? polygon.Points[0] : polygon.Points[i+1]));
  259.             }
  260.            
  261.             // TODO : DEBUG : try to build without holes and discard every triangle that share 3 index of the same hole ? no luck so far
  262.            
  263.             // Holes
  264.             for (int i = 0; i < childrenTransform.Count; i++)
  265.             {
  266.                 // Inner border of child i
  267.                 for (int j = 0; j < 3; j++)
  268.                 {
  269.                     meshTriangles.Add(j + pointCount*2 + 4 + 8*i);
  270.                     meshTriangles.Add(j + pointCount*2 + 8*i);
  271.                     meshTriangles.Add(j + pointCount*2 + 1 + 8*i);
  272.                     meshTriangles.Add(j + pointCount*2 + 1 + 8*i);
  273.                     meshTriangles.Add(j + pointCount*2 + 5 + 8*i);
  274.                     meshTriangles.Add(j + pointCount*2 + 4 + 8*i);
  275.                 }
  276.                 // Bridge last face of the inner border of child i
  277.                 meshTriangles.Add(pointCount*4 - 1 + 8*i);
  278.                 meshTriangles.Add(pointCount*3 - 1 + 8*i);
  279.                 meshTriangles.Add(pointCount*2 + 8*i);
  280.                 meshTriangles.Add(pointCount*2 + 8*i);
  281.                 meshTriangles.Add(pointCount*3 + 8*i);
  282.                 meshTriangles.Add(pointCount*4 - 1 + 8*i);
  283.                
  284.                 Vector3 v0 = vertices[serializedMesh.points.Count + 8 * i];
  285.                 Vector3 v1 = vertices[serializedMesh.points.Count + 8 * i + 1];
  286.                 Vector3 v2 = vertices[serializedMesh.points.Count + 8 * i + 2];
  287.                 Vector3 v3 = vertices[serializedMesh.points.Count + 8 * i + 3];
  288.                
  289.                 Vector2 v0tmp = GetBoxUV(v0, dir);
  290.                 Vector2 v1tmp = GetBoxUV(v1, dir);
  291.                 Vector2 v2tmp = GetBoxUV(v2, dir);
  292.                 Vector2 v3tmp = GetBoxUV(v3, dir);
  293.                
  294.                 Vertex vertex0 = new Vertex(v0tmp.x, v0tmp.y);
  295.                 Vertex vertex1 = new Vertex(v1tmp.x, v1tmp.y);
  296.                 Vertex vertex2 = new Vertex(v2tmp.x, v2tmp.y);
  297.                 Vertex vertex3 = new Vertex(v3tmp.x, v3tmp.y);
  298.  
  299.                 /*
  300.                 polygon.Add(vertex0);
  301.                 polygon.Add(vertex1);
  302.                 polygon.Add(vertex2);
  303.                 polygon.Add(vertex3);
  304.                
  305.                 polygon.Add(new Segment(vertex0, vertex1));
  306.                 polygon.Add(new Segment(vertex1, vertex2));
  307.                 polygon.Add(new Segment(vertex2, vertex3));
  308.                 polygon.Add(new Segment(vertex3, vertex0));
  309.                 */
  310.                                
  311.                 List<Vertex> holeVertices = new List<Vertex>()
  312.                 {
  313.                     vertex0,
  314.                     vertex1,
  315.                     vertex2,
  316.                     vertex3
  317.                 };
  318.                
  319.                 // This sometimes produces an error, because I'm unable to go from 2d to 3d, so points are overlapping or idk
  320.                 Contour hole = new Contour(holeVertices);
  321.                 polygon.Add(hole, true);
  322.                
  323.                
  324.             }
  325.  
  326.             var triangulatedMesh = polygon.Triangulate(options) as TriangleNet.Mesh;
  327.  
  328.             if (triangulatedMesh == null)
  329.             {
  330.                 Debug.LogError($"CreateCustomMesh - Triangulation error of {serializedMesh.name} !");
  331.                 return;
  332.             }
  333.            
  334.             foreach(ITriangle triangle in triangulatedMesh.Triangles)
  335.             {
  336.                 var v0 = triangle.GetVertexID(2);
  337.                 var v1 = triangle.GetVertexID(1);
  338.                 var v2 = triangle.GetVertexID(0);
  339.                
  340.                 // Front face
  341.                 meshTriangles.Add(v0);
  342.                 meshTriangles.Add(v1);
  343.                 meshTriangles.Add(v2);
  344.  
  345.                 // Back face
  346.                 meshTriangles.Add(v0 + pointCount);
  347.                 meshTriangles.Add(v2 + pointCount);
  348.                 meshTriangles.Add(v1 + pointCount);
  349.                
  350.  
  351.                 var t0 = triangle.GetVertex(2);
  352.                 var t1 = triangle.GetVertex(1);
  353.                 var t2 = triangle.GetVertex(0);
  354.  
  355.                 /*
  356.                 Debug.DrawLine(new Vector3((float)t0.x, (float)t0.y), new Vector3((float)t1.x, (float)t1.y), Color.red, 1000);
  357.                 Debug.DrawLine(new Vector3((float)t1.x, (float)t1.y), new Vector3((float)t2.x, (float)t2.y), Color.red, 1000);
  358.                 Debug.DrawLine(new Vector3((float)t2.x, (float)t2.y), new Vector3((float)t0.x, (float)t0.y), Color.red, 1000);
  359.                 */
  360.  
  361.             }
  362.            
  363.             List<int> tmpTri = new List<int>();
  364.            
  365.             for (int i = 0; i < meshTriangles.Count; i++)
  366.             {
  367.                 tmpTri.Add(meshTriangles[i]);
  368.             }
  369.  
  370.             /* Tried a bit to build without holes, then discard according triangle, with no luck
  371.             print("Before discarding : " + tmpTri.Count);
  372.  
  373.             int nbTriInHole;
  374.             for (int i = 0; i < tmpTri.Count; i += 3)
  375.             {
  376.                 nbTriInHole = 0;
  377.                
  378.                 //print($"Triangle {i/3} is ({tmpTri[i]}, {tmpTri[i+1]}, {tmpTri[i+2]})");
  379.  
  380.                 for (int j = 0; j < serializedMesh.children.Count; j++)
  381.                 {
  382.                     int tmp = pointCount * 2 + j * 8;
  383.                     if (tmpTri[i] == tmp || tmpTri[i] == tmp + 1 || tmpTri[i] == tmp + 2 ||
  384.                         tmpTri[i] == tmp + 3)
  385.                     {
  386.                         nbTriInHole++;
  387.                     }
  388.                    
  389.                     if (tmpTri[i+1] == tmp || tmpTri[i+1] == tmp + 1 || tmpTri[i+1] == tmp + 2 ||
  390.                         tmpTri[i+1] == tmp + 3)
  391.                     {
  392.                         nbTriInHole++;
  393.                     }
  394.                    
  395.                     if (tmpTri[i+2] == tmp || tmpTri[i+2] == tmp + 1 || tmpTri[i+2] == tmp + 2 ||
  396.                         tmpTri[i+2] == tmp + 3)
  397.                     {
  398.                         nbTriInHole++;
  399.                     }
  400.  
  401.                 }
  402.  
  403.                 if (nbTriInHole > 2)
  404.                 {
  405.                     print($"Discarding triangle {i/3} ({tmpTri[i]}, {tmpTri[i+1]}, {tmpTri[i+2]})");
  406.                     tmpTri.RemoveRange(i, 3);
  407.                     var t0 = vertices[tmpTri[i]];
  408.                     t0.z = 0;
  409.                     var t1 = vertices[tmpTri[i+1]];
  410.                     t1.z = 0;
  411.                     var t2 = vertices[tmpTri[i+2]];
  412.                     t2.z = 0;
  413.                    
  414.                    
  415.                    
  416.                     Debug.DrawLine(t0, t1, Color.blue, 4);
  417.                     Debug.DrawLine(t1, t2, Color.blue, 4);
  418.                     Debug.DrawLine(t2, t0, Color.blue, 4);
  419.                 }
  420.                
  421.             }
  422.            
  423.             print("After discarding : " + tmpTri.Count);
  424.             */
  425.            
  426.             triangles = tmpTri.ToArray();
  427.  
  428.         }
  429.  
  430.         // Here are the no-hole / 1-hole hardcoded triangles, it works
  431.         else
  432.         {
  433.            
  434.             // Create triangles
  435.             int triCount = (12 + childrenTransform.Count * 20) * 3;
  436.  
  437.             switch (childrenTransform.Count)
  438.             {
  439.                 case 0:
  440.                     triangles = new [] {
  441.                         // Front face
  442.                         0, 1, 2,
  443.                         2, 3, 0,
  444.                
  445.                         // Back face
  446.                         7, 6, 5,
  447.                         5, 4, 7,
  448.                
  449.                         // Left face
  450.                         4, 5, 1,
  451.                         1, 0, 4,
  452.                
  453.                         // Right face
  454.                         3, 2, 6,
  455.                         6, 7, 3,
  456.                
  457.                         // Top face
  458.                         1, 5, 6,
  459.                         6, 2, 1,
  460.                
  461.                         // Bottom face
  462.                         4, 0, 3,
  463.                         3, 7, 4
  464.                     };
  465.                     break;
  466.                 case 1:
  467.                     triangles = new [] {
  468.                        
  469.                         // Front left
  470.                         0, 1, 9,
  471.                         9, 8, 0,
  472.                        
  473.                         // Front top
  474.                         9, 1, 2,
  475.                         2, 10, 9,
  476.                        
  477.                         // Front right
  478.                         11, 10, 2,
  479.                         2, 3, 11,
  480.                        
  481.                         // Front bot
  482.                         0, 8, 11,
  483.                         11, 3, 0,
  484.                        
  485.                         // Back left
  486.                         7, 6, 14,
  487.                         14, 15, 7,
  488.                        
  489.                         // Back top
  490.                         14, 6, 5,
  491.                         5, 13, 14,
  492.                        
  493.                         // Back right
  494.                         12, 13, 5,
  495.                         5, 4, 12,
  496.  
  497.                         // Back bot
  498.                         7, 15, 12,
  499.                         12, 4, 7,
  500.  
  501.                         // Outer left
  502.                         4, 5, 1,
  503.                         1, 0, 4,
  504.                        
  505.                         // Outer top
  506.                         1, 5, 6,
  507.                         6, 2, 1,
  508.                        
  509.                         // Outer right
  510.                         3, 2, 6,
  511.                         6, 7, 3,
  512.                        
  513.                         // Outer bot
  514.                         4, 0, 3,
  515.                         3, 7, 4,
  516.                        
  517.                         // Inner left
  518.                         8, 9, 13,
  519.                         13, 12, 8,
  520.                        
  521.                         // Inner top
  522.                         13, 9, 10,
  523.                         10, 14, 13,
  524.                        
  525.                         // Inner right
  526.                         14, 10, 11,
  527.                         11, 15, 14,
  528.                        
  529.                         // Inner bot
  530.                         15, 11, 8,
  531.                         8, 12, 15
  532.  
  533.                     };
  534.                     break;
  535.                 /*
  536.                 case 2:
  537.                     triangles = new [] {
  538.                        
  539.                         // Front left
  540.                         0, 1, 9,
  541.                         9, 8, 0,
  542.                        
  543.                         // Front top
  544.                         9, 1, 2,
  545.                         2, 10, 9,
  546.                        
  547.                         // Front right
  548.                         11, 10, 2,
  549.                         2, 3, 11,
  550.                        
  551.                         // Front bot left
  552.                         0, 8, 17,
  553.                         17, 16, 0,
  554.  
  555.                         // Front bot top
  556.                         17, 8, 11,
  557.                         11, 18, 17,
  558.  
  559.                         // Front bot right
  560.                         19, 18, 11,
  561.                         11, 3, 19,
  562.  
  563.                         // Front bot bot
  564.                         0, 16, 19,
  565.                         19, 3, 0,
  566.  
  567.                         // Back left
  568.                         7, 6, 14,
  569.                         14, 15, 7,
  570.                        
  571.                         // Back top
  572.                         14, 6, 5,
  573.                         5, 13, 14,
  574.                        
  575.                         // Back right
  576.                         12, 13, 5,
  577.                         5, 4, 12,
  578.                        
  579.                         // Back bot left
  580.                         7, 15, 22,
  581.                         22, 23, 7,
  582.  
  583.                         // Back bot top
  584.                         22, 15, 12,
  585.                         12, 21, 22,
  586.  
  587.                         // Back bot right
  588.                         20, 21, 12,
  589.                         12, 4, 20,
  590.  
  591.                         // Back bot bot
  592.                         7, 23, 20,
  593.                         20, 4, 7,
  594.  
  595.                         // Outer left
  596.                         4, 5, 1,
  597.                         1, 0, 4,
  598.                        
  599.                         // Outer top
  600.                         1, 5, 6,
  601.                         6, 2, 1,
  602.                        
  603.                         // Outer right
  604.                         3, 2, 6,
  605.                         6, 7, 3,
  606.                        
  607.                         // Outer bot
  608.                         4, 0, 3,
  609.                         3, 7, 4,
  610.                        
  611.                         // Inner left
  612.                         8, 9, 13,
  613.                         13, 12, 8,
  614.                        
  615.                         // Inner top
  616.                         13, 9, 10,
  617.                         10, 14, 13,
  618.                        
  619.                         // Inner right
  620.                         14, 10, 11,
  621.                         11, 15, 14,
  622.                        
  623.                         // Inner bot
  624.                         15, 11, 8,
  625.                         8, 12, 15,
  626.                        
  627.                         // Inner 2 left
  628.                         20, 16, 17,
  629.                         17, 21, 21,
  630.                        
  631.                         // Inner 2 top
  632.                         21, 17, 18,
  633.                         18, 22, 21,
  634.                        
  635.                         // Inner 2 right
  636.                         22, 18, 19,
  637.                         19, 23, 22,
  638.                        
  639.                         // Inner 2 bot
  640.                         23, 19, 16,
  641.                         16, 20, 23
  642.  
  643.                     };
  644.                     break;
  645.                     */
  646.                 default:
  647.                     triangles = new int[0];
  648.                     break;
  649.             }
  650.  
  651.             if (triangles.Length != triCount)
  652.             {
  653.                 Debug.LogError($"CreateCustomMesh - Wrong triangles count : {triangles.Length.ToString()} (expected {triCount.ToString()})");
  654.                 return;
  655.             }
  656.        
  657.         }
  658.        
  659.        
  660.         Mesh.vertices = vertices;
  661.         Mesh.triangles = triangles;
  662.         Mesh.Optimize();
  663.         Mesh.RecalculateNormals();
  664.         CalculateUVs();
  665.         Mesh.RecalculateTangents();
  666.         Mesh.RecalculateBounds();
  667.         MeshCollider.sharedMesh = Mesh;
  668.        
  669.         if(Mathf.Abs(serializedMesh.material.textureOffsetX) > 0.001f || Mathf.Abs(serializedMesh.material.textureOffsetY) > 0.001f)
  670.         {
  671.             MeshRenderer.material.SetTextureOffset(BaseMap, new Vector2(serializedMesh.material.textureOffsetX, serializedMesh.material.textureOffsetY));
  672.         }
  673.  
  674.     }
  675.    
  676.     private void CalculateUVs()
  677.     {
  678.         Matrix4x4 matrix = transform.localToWorldMatrix;
  679.  
  680.         Vector3[] vertices = Mesh.vertices;
  681.        
  682.         Vector3[] normals = Mesh.normals;
  683.  
  684.         Vector3[] worldVertices = new Vector3[vertices.Length];
  685.         for (int i = 0; i < worldVertices.Length; i++)
  686.         {
  687.             worldVertices[i] = matrix.MultiplyPoint(vertices[i]);
  688.         }
  689.  
  690.         List<Vector3> newVerts = new List<Vector3>(vertices.Length);
  691.         List<Vector3> newNormals = new List<Vector3>(vertices.Length);
  692.         List<Vector2> newUVs = new List<Vector2>(vertices.Length);
  693.         List<List<int>> newTris = new List<List<int>>();
  694.  
  695.         Dictionary<int,int[]> vertexMap = new Dictionary<int, int[]>();
  696.         for (int i = -3; i <= 3; i++)
  697.         {
  698.             if (i == 0)
  699.                 continue;
  700.            
  701.             int[] vmap = new int[vertices.Length];
  702.             for (int v = 0; v < vmap.Length; v++)
  703.             {
  704.                 vmap[v] = -1;
  705.             }
  706.             vertexMap.Add(i,vmap);
  707.         }
  708.            
  709.         // Compute triangle normal for each tri, and rebuild it with unique vertices
  710.         for (int s = 0; s < Mesh.subMeshCount; s++)
  711.         {
  712.             int[] triangles = Mesh.GetTriangles(s);
  713.             newTris.Add( new List<int>() );
  714.  
  715.             for (int t = 0; t < triangles.Length; t += 3)
  716.             {
  717.                 int v0 = triangles[t];
  718.                 int v1 = triangles[t+1];
  719.                 int v2 = triangles[t+2];
  720.  
  721.                 Vector3 triNormal = TriangleNormal(worldVertices[v0], worldVertices[v1], worldVertices[v2]);
  722.  
  723.                 int boxDir = GetBoxDir(triNormal);
  724.  
  725.                 // Remap triangle verts
  726.                 for (int i = 0; i < 3; i++)
  727.                 {
  728.                     int v = triangles[t+i];
  729.  
  730.                     // If vertex doesn't already exist in boxDir vertex map,
  731.                     // we'll add a copy of it with the correct UV
  732.                     if (vertexMap[boxDir][v] < 0)
  733.                     {
  734.                         // Compute UV
  735.                         Vector2 vertexUV = GetBoxUV(worldVertices[v], boxDir);
  736.                         vertexMap[boxDir][v] = newVerts.Count;
  737.                         newVerts.Add(vertices[v]);
  738.                         newNormals.Add(normals[v]);
  739.                         newUVs.Add(vertexUV);
  740.                     }
  741.  
  742.                     // Use remapped vertex index
  743.                     newTris[s].Add(vertexMap[boxDir][v]);
  744.                 }
  745.             }
  746.         }
  747.            
  748.         Mesh.vertices = newVerts.ToArray();
  749.         Mesh.normals = newNormals.ToArray();
  750.         Mesh.uv = newUVs.ToArray();
  751.  
  752.         for (int s = 0; s < newTris.Count; s++)
  753.         {
  754.             Mesh.SetTriangles(newTris[s].ToArray(), s);
  755.         }
  756.     }
  757.  
  758.     private static Vector3 TriangleNormal(Vector3 a, Vector3 b, Vector3 c)
  759.     {
  760.         return Vector3.Cross(b - a, c - a).normalized;
  761.     }
  762.  
  763.     private static int GetBoxDir(Vector3 v)
  764.     {
  765.         float x = Mathf.Abs(v.x);
  766.         float y = Mathf.Abs(v.y);
  767.         float z = Mathf.Abs(v.z);
  768.        
  769.         // X - axis
  770.         if (x > y && x > z)
  771.         {
  772.             return v.x < 0 ? -1 : 1;
  773.         }
  774.        
  775.         // Y - axis
  776.         if (y > z)
  777.         {
  778.             return v.y < 0 ? -2 : 2;
  779.         }
  780.        
  781.         // Z - axis
  782.         return v.z < 0 ? -3 : 3;
  783.     }
  784.  
  785.     private static Vector2 GetBoxUV(Vector3 vertex, int boxDir)
  786.     {
  787.         switch (boxDir)
  788.         {
  789.             // X - axis
  790.             case -1: case 1:
  791.                 return new Vector2(vertex.z * Mathf.Sign(boxDir), vertex.y);
  792.            
  793.             // Y - axis
  794.             case -2: case 2:
  795.                 return new Vector2(vertex.x, vertex.z * Mathf.Sign(boxDir));
  796.            
  797.             // Z - axis
  798.             default:
  799.                 return new Vector2(vertex.x * -Mathf.Sign(boxDir), vertex.y);
  800.         }
  801.     }
  802.    
  803. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement