public static BasicMeshData GenerateTorus(int divsMinor, int divsMajor, float rMinor = 1, float rMajor = 1) { BasicMeshData mesh = new BasicMeshData(); mesh.normals = new List <Vector3>(); for (int iMaj = 0; iMaj < divsMajor; iMaj++) { float tMaj = iMaj / (float)divsMajor; Vector2 dirMaj = ShapesMath.AngToDir(tMaj * ShapesMath.TAU); for (int iMin = 0; iMin < divsMinor; iMin++) { float tMin = iMin / (float)divsMinor; Vector2 dirMinLocal = ShapesMath.AngToDir(tMin * ShapesMath.TAU); Vector3 dirMin = (Vector3)dirMaj * dirMinLocal.x + new Vector3(0, 0, dirMinLocal.y); mesh.normals.Add(dirMin); mesh.verts.Add((Vector3)dirMaj * rMajor + dirMin * rMinor); int maj0min0 = iMaj * divsMinor + iMin; int maj1min0 = (iMaj + 1) % divsMajor * divsMinor + iMin; int maj0min1 = iMaj * divsMinor + (iMin + 1) % divsMinor; int maj1min1 = (iMaj + 1) % divsMajor * divsMinor + (iMin + 1) % divsMinor; mesh.tris.Add(maj0min1); mesh.tris.Add(maj0min0); mesh.tris.Add(maj1min1); mesh.tris.Add(maj1min0); mesh.tris.Add(maj1min1); mesh.tris.Add(maj0min0); } } return(mesh); }
public static BasicMeshData GenerateIcosphere(int divs) { BasicMeshData mesh = new BasicMeshData(); mesh.normals = new List <Vector3>(); // foreach face, generate all vertices and triangles for (int i = 0; i < 20; i++) { Vector3 v0 = Icosahedron.verts[Icosahedron.tris[i * 3]]; Vector3 v1 = Icosahedron.verts[Icosahedron.tris[i * 3 + 1]]; Vector3 v2 = Icosahedron.verts[Icosahedron.tris[i * 3 + 2]]; // add this icosa face to the global list int n = divs + 1; // n is number of verts along one side of the triangle int prevVertCount = mesh.verts.Count; Vector3[] verts = BarycentricVertices(n, v0, v1, v2).ToArray(); mesh.verts.AddRange(verts); mesh.normals.AddRange(verts); mesh.tris.AddRange(BarycentricTriangulation(n, globalOffset: prevVertCount)); } // cleanup duplicate verts mesh.RemoveDuplicateVertices(); return(mesh); }
public static BasicMeshData GenerateCone(int divs, bool generateCap) { BasicMeshData mesh = new BasicMeshData(); mesh.verts.Add(Vector3.forward); for (int i = 1; i < divs + 1; i++) { float t = i / (float)divs; int iNext = i == divs ? 1 : i + 1; mesh.verts.Add(ShapesMath.AngToDir(t * ShapesMath.TAU)); mesh.tris.Add(0); // vertex 0 is the tip mesh.tris.Add(i); mesh.tris.Add(iNext); if (generateCap && i > 1 && i < divs) { mesh.tris.Add(1); // vertex 1 is the root edge vert mesh.tris.Add(iNext); mesh.tris.Add(i); } } mesh.normals = mesh.verts.Select(v => v).ToList(); // already normalized return(mesh); }
public static BasicMeshData GenerateCylinder(int divs) { BasicMeshData mesh = new BasicMeshData(); mesh.normals = new List <Vector3>(); for (int z = 0; z < 2; z++) { for (int i = 0; i < divs; i++) { float t = i / (float)divs; Vector3 v = ShapesMath.AngToDir(t * ShapesMath.TAU); mesh.normals.Add(v); v.z = z; mesh.verts.Add(v); } } // sides for (int i = 0; i < divs; i++) { int low0 = i; int top0 = divs + i; int low1 = (i + 1) % divs; int top1 = divs + (i + 1) % divs; mesh.tris.Add(low0); mesh.tris.Add(low1); mesh.tris.Add(top1); mesh.tris.Add(top1); mesh.tris.Add(top0); mesh.tris.Add(low0); } // cap bottom for (int i = 1; i < divs - 1; i++) { mesh.tris.Add(0); mesh.tris.Add((i + 1) % divs); mesh.tris.Add(i); } // cap top for (int i = 1; i < divs - 1; i++) { mesh.tris.Add(divs + 0); mesh.tris.Add(divs + i); mesh.tris.Add(divs + (i + 1) % divs); } return(mesh); }
private BasicMeshData GenerateBasicMesh(Dictionary <Vector3Int, ShipTile> inChunk) { List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); List <Color32> colors = new List <Color32>(); Vector3 adjustment = (Vector3.up) / 2; foreach (ShipTile tile in inChunk.Values) { Vector3 pos = new Vector3(tile.location.x, tile.location.z, tile.location.y); int firstVert = vertices.Count; if (tile.wall) { foreach (Vector3 v in cubeVerts) { vertices.Add(v + pos); colors.Add(tile.col); } foreach (int t in cubeTriangles) { triangles.Add(t + firstVert); } } else { foreach (Vector3 v in quadVerts) { vertices.Add(v + pos); colors.Add(tile.col); } foreach (int t in quadTriangles) { triangles.Add(t + firstVert); } } } BasicMeshData mData = new BasicMeshData(vertices.ToArray(), triangles.ToArray(), colors.ToArray()); return(mData); }
static Mesh UpdatePrimitiveMesh(string primitive, int detail, float boundsSize, BasicMeshData meshData, ref Mesh[] meshArray, int detailLevelCount = 5) { // make sure array is prepared if (meshArray == null || meshArray.Length != detailLevelCount) { // array incorrectly set up meshArray = new Mesh[detailLevelCount]; Debug.Log($"reinitialized {primitive} mesh array to {detailLevelCount}"); } // field is missing a ref if (meshArray[detail] == null) { string meshName = $"{primitive}_{detail}"; // find existing mesh string assetPath = AssetDatabase.GetAssetPath(ShapesAssets.Instance); Mesh[] assetsAtPath = AssetDatabase.LoadAllAssetsAtPath(assetPath).OfType <Mesh>().ToArray(); Mesh existingMesh = assetsAtPath.FirstOrDefault(x => x.name == meshName); if (existingMesh != null) { // assign existing mesh Debug.Log("Assigning missing mesh ref " + meshName); meshArray[detail] = existingMesh; } else { // create it if it's not found Debug.Log("Creating missing mesh " + meshName); meshArray[detail] = new Mesh { name = meshName }; AssetDatabase.AddObjectToAsset(meshArray[detail], ShapesAssets.Instance); } } Mesh m = meshArray[detail]; meshData.ApplyTo(m); m.bounds = new Bounds(Vector3.zero, Vector3.one * boundsSize); meshArray[detail] = m; return(m); }
public static BasicMeshData GenerateUVSphere(int divsLong, int divsLat) { BasicMeshData mesh = new BasicMeshData(); mesh.normals = new List <Vector3>(); int vertCount = divsLong * divsLat; int triCount = divsLong * (divsLat - 1) * 2 - divsLong * 2; // subtracting is to remove quads at the pole Vector3[] verts = new Vector3[vertCount]; int iVert = 0; // generate verts for (int iLo = 0; iLo < divsLong; iLo++) { float tLong = iLo / (float)divsLong; float angLong = tLong * ShapesMath.TAU; Vector2 dirXZ = ShapesMath.AngToDir(angLong); Vector3 dirLong = new Vector3(dirXZ.x, 0f, dirXZ.y); for (int iLa = 0; iLa < divsLat; iLa++) { float tLat = iLa / (divsLat - 1f); float angLat = Mathf.Lerp(-0.25f, 0.25f, tLat) * ShapesMath.TAU; Vector2 dirProj = ShapesMath.AngToDir(angLat); verts[iVert++] = dirLong * dirProj.x + Vector3.up * dirProj.y; } } // generate tris int[] tris = new int[triCount * 3]; int iTri = 0; for (int iLo = 0; iLo < divsLong; iLo++) { for (int iLa = 0; iLa < divsLat - 1; iLa++) { int iRoot = iLo * divsLat + iLa; int iRootNext = (iRoot + divsLat) % vertCount; if (iLa < divsLat - 2) // skip first and last (triangles at the poles) { tris[iTri++] = iRoot; tris[iTri++] = iRoot + 1; tris[iTri++] = iRootNext + 1; } if (iLa > 0) { tris[iTri++] = iRootNext + 1; tris[iTri++] = iRootNext; tris[iTri++] = iRoot; } } } mesh.verts.AddRange(verts); mesh.tris.AddRange(tris); mesh.normals.AddRange(verts); mesh.RemoveDuplicateVertices(); return(mesh); }
public static BasicMeshData GenerateCapsule(int divs) { BasicMeshData mesh = new BasicMeshData(); mesh.normals = new List <Vector3>(); int sides = divs * 4; for (int z = 0; z < 2; z++) { for (int i = 0; i < sides; i++) { float t = i / (float)sides; Vector3 v = ShapesMath.AngToDir(t * ShapesMath.TAU); mesh.normals.Add(v); v.z = z; mesh.verts.Add(v); } } // sides for (int i = 0; i < sides; i++) { int low0 = i; int top0 = sides + i; int low1 = (i + 1) % sides; int top1 = sides + (i + 1) % sides; mesh.tris.Add(low0); mesh.tris.Add(low1); mesh.tris.Add(top1); mesh.tris.Add(top1); mesh.tris.Add(top0); mesh.tris.Add(low0); } // round caps! int n = divs + 1; Vector3[] octaBaseVerts = { Vector3.right, Vector3.up, Vector3.left, Vector3.down }; for (int z = 0; z < 2; z++) { // half-octahedron for (int s = 0; s < 4; s++) { Vector3 v0 = z == 0 ? Vector3.back : Vector3.forward; // reverse depending on z Vector3 v1 = octaBaseVerts[s]; Vector3 v2 = octaBaseVerts[(s + 1) % 4]; Vector3[] verts = BarycentricVertices(n, v0, v1, v2).ToArray(); mesh.normals.AddRange(verts); if (z == 0) { mesh.tris.AddRange(BarycentricTriangulation(n, mesh.verts.Count).Reverse()); mesh.verts.AddRange(verts.Select(x => x)); } else { mesh.tris.AddRange(BarycentricTriangulation(n, mesh.verts.Count)); mesh.verts.AddRange(verts.Select(x => x + Vector3.forward)); } } } mesh.RemoveDuplicateVertices(); return(mesh); }