public void GenerateCrystal() { //Debug.Log("Generating crystal"); List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <int> tris = new List <int>(); for (int lobe = 0; lobe < numCrystals; lobe++) { // compute lobe parameters given randomness int lobeNumCenters = Mathf.Max(1, (int)(numCenters - randomness * numCenters * NextRandomFloat)); int lobeNumSides = Mathf.Max(MinNumSides, (int)(numCenters - randomness * numCenters * NextRandomFloat)); float lobeScale = 1f - 0.75f * randomness * NextRandomFloat; // limit maximum randomness on scale float lobeWidth = lobeScale * crystalWidth * (1f - randomness + 2f * randomness * NextRandomFloat); float lobeLength = lobeScale * crystalLength * (1f - randomness + 2f * randomness * NextRandomFloat); float maxRotation = 2f * Mathf.PI / lobeNumSides; Vector3 lobeRoot = 0.25f * randomness * new Vector3(-1f + 2f * NextRandomFloat, 0, -1f + 2f * NextRandomFloat); //Debug.Log("Generating a crystal lobe " + lobe); Vector3 lobeDir = Samplers.sampleRandomCosineHemisphere(NextRandomFloat, NextRandomFloat); Quaternion rotation = Quaternion.LookRotation(lobeDir); List <Vector3> sides = new List <Vector3>(); for (int j = 0; j < lobeNumCenters; j++) { float ratio = lobeNumCenters == 1 ? 0.5f: 1f * j / (lobeNumCenters - 1); Vector3 centerPos = lobeRoot + lobeLength * lobeDir * evaluateDensityCurve(ratio); for (int side = 0; side < lobeNumSides; side++) { float angle = maxRotation * side; Vector3 sideDir = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)); //todo rotate to crystalDir Vector3 sidePos = centerPos + lobeWidth * sideDir * crystalSizeCurve.Evaluate(ratio); //sidePos = rotation * sidePos; sides.Add(sidePos); } } Vector3 crystalTop = lobeRoot + lobeLength * lobeDir; //Debug.Log("ROOT: " + lobeRoot); //Debug.Log("SIDES: " + sides.Count); //foreach (var v in sides) // Debug.Log(v); //Debug.Log("TOP: " + crystalTop); int index, s1, s2, s3; // generate triangles for the sides for (int j = 0; j < lobeNumCenters - 1; j++) { for (int side = 0; side < lobeNumSides; side++) { index = j * lobeNumSides + side; s1 = index; bool b = (side + 1) % lobeNumSides == 0; // need to generate 2 triangles per side for (int tri = 0; tri < 2; tri++) { if (tri == 0) // triangle 1 { s2 = b ? index + lobeNumSides : index + lobeNumSides; s3 = b ? index + 1 : index + lobeNumSides + 1; } else // triangle 2 { s2 = b ? index + 1 : index + lobeNumSides + 1; s3 = b ? index - lobeNumSides + 1 : index + 1; } //Debug.Log("Indices" + s1 + " " + s2 + " " + s3); List <Vector3> verticesLocal = new List <Vector3>() { sides[s1], sides[s2], sides[s3] }; MeshTriAdder.addTriangle(new Vector3Int(0, 1, 2), verticesLocal, vertices, tris, false); } } } bool isBottom = true; Vector3 v1; // bottom and top triangles for (int c = 0; c < 2; c++) { if (isBottom) { v1 = lobeRoot; index = 0; // index is now used as an offset for the vertex indices } else { v1 = crystalTop; index = (lobeNumCenters - 1) * lobeNumSides; } for (int j = 0; j < lobeNumSides; j++) { if (isBottom) { s2 = index + j; s3 = (index + 1 + j) % lobeNumSides; } else { s2 = index + (1 + j) % lobeNumSides; s3 = index + j; } List <Vector3> verticesLocal = new List <Vector3>() { v1, sides[s2], sides[s3] }; MeshTriAdder.addTriangle(new Vector3Int(0, 1, 2), verticesLocal, vertices, tris, false); } isBottom = false; } } Mesh mesh = new Mesh(); mesh.Clear(); mesh.subMeshCount = 2; mesh.SetVertices(vertices); mesh.SetTriangles(tris.ToArray(), 0); Vector2[] uvs = Unwrapping.GeneratePerTriangleUV(mesh); mesh.SetUVs(0, new List <Vector2>(uvs)); mesh.RecalculateNormals(); mesh.RecalculateBounds(); // assign back to meshFilter MeshFilter meshFilter = GetComponent <MeshFilter>(); //mesh.Optimize(); meshFilter.mesh = mesh; }
public void InitializeMesh(Region region) { Debug.Log("Initializing region Mesh..."); // compute mesh parameters Dictionary <Vector3, int> verticesDict = new Dictionary <Vector3, int>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> tris = new List <int>(); // copy vertice vectors Tile[,] tiles = region.getTiles(); Dictionary <string, bool> trisDict = new Dictionary <string, bool>(); float yTotal = 0; int trisCount = 0; int length = tiles.GetLength(0); for (int i = 0; i < length; i++) { for (int j = 0; j < length; j++) { if (tiles[i, j] != null) { // add 2 triangles per tile // * * // * * // bottom left star is the current tile, will generate connections to 3 adjacent tiles Vector2Int ind1, ind2; for (int c = 0; c < 2; c++) { if (c == 0) { ind1 = SquareDirections.Top; ind2 = SquareDirections.TopRight; } else { ind1 = SquareDirections.TopRight; ind2 = SquareDirections.Right; } try { ind1 += new Vector2Int(i, j); ind2 += new Vector2Int(i, j); // compute string key for the triangle int[] triInds = new int[] { (i * length + j), (ind1.x * length + ind1.y), (ind2.x * length + ind2.y) }; Array.Sort(triInds); string triStringKey = ""; foreach (float f in triInds) { triStringKey += f + "-"; } // add triangle only if it wasnt added already if (!trisDict.ContainsKey(triStringKey)) { trisDict.Add(triStringKey, true); yTotal += tiles[i, j].pos.y + tiles[ind1.x, ind1.y].pos.y + tiles[ind2.x, ind2.y].pos.y; List <Vector3> verticesLocal = new List <Vector3>(); verticesLocal.Add(tiles[i, j].pos); verticesLocal.Add(tiles[ind1.x, ind1.y].pos); verticesLocal.Add(tiles[ind2.x, ind2.y].pos); List <Vector2> uvsLocal = new List <Vector2>(); uvsLocal.Add(region.pos2UV(tiles[i, j].pos)); uvsLocal.Add(region.pos2UV(tiles[ind1.x, ind1.y].pos)); uvsLocal.Add(region.pos2UV(tiles[ind2.x, ind2.y].pos)); MeshTriAdder.addTriangle(new Vector3Int(0, 1, 2), verticesLocal, verticesDict, tris, normals, uvsLocal, uvs); trisCount++; } } catch (IndexOutOfRangeException e) { } catch (NullReferenceException e) { } } } } } Debug.Log("Tiles with size " + length); Debug.Log("Built a mesh with " + verticesDict.Keys.Count + " vertices and " + trisCount + " triangles; total height " + yTotal + "."); Mesh mesh = new Mesh(); mesh.Clear(); mesh.subMeshCount = 2; mesh.SetVertices(verticesDict.Keys.ToList <Vector3>()); mesh.SetTriangles(tris.ToArray(), 0); mesh.SetUVs(0, uvs); mesh.RecalculateNormals(); mesh.RecalculateBounds(); // assign back to meshFilter MeshFilter meshFilter = GetComponent <MeshFilter>(); MeshCollider meshCollider = GetComponent <MeshCollider>(); mesh.Optimize(); meshFilter.mesh = mesh; meshCollider.sharedMesh = meshFilter.sharedMesh; }