public static pb_Object StairGenerator(Vector3 size, int steps, bool buildSides) { /// 4 vertices per quad, 2 quads per step. Vector3[] vertices = new Vector3[4 * steps * 2]; pb_Face[] faces = new pb_Face[steps * 2]; /// vertex index, face index int v = 0, t = 0; for(int i = 0; i < steps; i++) { float inc0 = i / (float) steps; float inc1 = (i + 1) / (float) steps; float x0 = size.x; float x1 = 0; float y0 = size.y * inc0; float y1 = size.y * inc1; float z0 = size.z * inc0; float z1 = size.z * inc1; vertices[v+0] = new Vector3(x0, y0, z0); vertices[v+1] = new Vector3(x1, y0, z0); vertices[v+2] = new Vector3(x0, y1, z0); vertices[v+3] = new Vector3(x1, y1, z0); vertices[v+4] = new Vector3(x0, y1, z0); vertices[v+5] = new Vector3(x1, y1, z0); vertices[v+6] = new Vector3(x0, y1, z1); vertices[v+7] = new Vector3(x1, y1, z1); faces[t+0] = new pb_Face( new int[] { v + 0, v + 1, v + 2, v + 1, v + 3, v + 2 }); faces[t+1] = new pb_Face( new int[] { v + 4, v + 5, v + 6, v + 5, v + 7, v + 6 }); v += 8; t += 2; } /// sides if(buildSides) { /// first step is special case - only needs a quad, but all other steps need /// a quad and tri. float x = 0f; for(int side = 0; side < 2; side++) { Vector3[] sides_v = new Vector3[ steps * 4 + (steps - 1) * 3 ]; pb_Face[] sides_f = new pb_Face[ steps + steps-1 ]; int sv = 0, st = 0; for(int i = 0; i < steps; i++) { float y0 = (Mathf.Max(i, 1) / (float) steps) * size.y; float y1 = ((i+1) / (float) steps) * size.y; float z0 = (i / (float)steps) * size.z; float z1 = ((i+1) / (float) steps) * size.z; sides_v[sv+0] = new Vector3(x, 0f, z0); sides_v[sv+1] = new Vector3(x, 0f, z1); sides_v[sv+2] = new Vector3(x, y0, z0); sides_v[sv+3] = new Vector3(x, y1, z1); sides_f[st++] = new pb_Face( side % 2 == 0 ? new int[] { v+0, v+1, v+2, v+1, v+3, v+2 } : new int[] { v+2, v+1, v+0, v+2, v+3, v+1 } ); sides_f[st-1].textureGroup = side + 1; v += 4; sv += 4; /// that connecting triangle if(i > 0) { sides_v[sv+0] = new Vector3(x, y0, z0); sides_v[sv+1] = new Vector3(x, y1, z0); sides_v[sv+2] = new Vector3(x, y1, z1); sides_f[st++] = new pb_Face( side % 2 == 0 ? new int[] { v+2, v+1, v+0 } : new int[] { v+0, v+1, v+2 } ); sides_f[st-1].textureGroup = side + 1; v += 3; sv += 3; } } vertices = vertices.Concat(sides_v); faces = faces.Concat(sides_f); x += size.x; } // add that last back face vertices = vertices.Concat(new Vector3[] { new Vector3(0f, 0f, size.z), new Vector3(size.x, 0f, size.z), new Vector3(0f, size.y, size.z), new Vector3(size.x, size.y, size.z) }); faces = faces.Add(new pb_Face(new int[] {v+0, v+1, v+2, v+1, v+3, v+2})); } pb_Object pb = pb_Object.CreateInstanceWithVerticesFaces(vertices, faces); pb.SetName("Stairs"); return pb; }
public static pb_Object CurvedStairGenerator(float stairWidth, float height, float innerRadius, float circumference, int steps, bool buildSides) { bool noInnerSide = innerRadius < Mathf.Epsilon; /// 4 vertices per quad, vertical step first, then floor step can be 3 or 4 verts depending on /// if the inner radius is 0 or not. Vector3[] vertices = new Vector3[(4 * steps) + ((noInnerSide ? 3 : 4) * steps)]; pb_Face[] faces = new pb_Face[steps * 2]; /// vertex index, face index int v = 0, t = 0; float cir = Mathf.Abs(circumference) * Mathf.Deg2Rad; float outerRadius = innerRadius + stairWidth; for(int i = 0; i < steps; i++) { float inc0 = (i / (float) steps) * cir; float inc1 = ((i + 1) / (float) steps) * cir; float h0 = ((i / (float) steps) * height); float h1 = (((i+1) / (float) steps) * height); Vector3 v0 = new Vector3(-Mathf.Cos(inc0), 0f, Mathf.Sin(inc0) ); Vector3 v1 = new Vector3(-Mathf.Cos(inc1), 0f, Mathf.Sin(inc1) ); /** * * /6-----/7 * / / * /5_____/4 * |3 |2 * | | * |1_____|0 * */ vertices[v+0] = v0 * innerRadius; vertices[v+1] = v0 * outerRadius; vertices[v+2] = v0 * innerRadius; vertices[v+3] = v0 * outerRadius; vertices[v+0].y = h0; vertices[v+1].y = h0; vertices[v+2].y = h1; vertices[v+3].y = h1; vertices[v+4] = vertices[v+2]; vertices[v+5] = vertices[v+3]; vertices[v+6] = v1 * outerRadius; vertices[v+6].y = h1; if(!noInnerSide) { vertices[v+7] = v1 * innerRadius; vertices[v+7].y = h1; } faces[t+0] = new pb_Face( new int[] { v + 0, v + 1, v + 2, v + 1, v + 3, v + 2 }); if(noInnerSide) { faces[t+1] = new pb_Face( new int[] { v + 4, v + 5, v + 6 }); } else { faces[t+1] = new pb_Face( new int[] { v + 4, v + 5, v + 6, v + 4, v + 6, v + 7 }); } v += noInnerSide ? 7 : 8; t += 2; } /// sides if(buildSides) { /// first step is special case - only needs a quad, but all other steps need /// a quad and tri. float x = noInnerSide ? innerRadius + stairWidth : innerRadius;; for(int side = (noInnerSide ? 1 : 0); side < 2; side++) { Vector3[] sides_v = new Vector3[ steps * 4 + (steps - 1) * 3 ]; pb_Face[] sides_f = new pb_Face[ steps + steps-1 ]; int sv = 0, st = 0; for(int i = 0; i < steps; i++) { float inc0 = (i / (float) steps) * cir; float inc1 = ((i + 1) / (float) steps) * cir; float h0 = ((Mathf.Max(i, 1) / (float) steps) * height); float h1 = (((i+1) / (float) steps) * height); Vector3 v0 = new Vector3(-Mathf.Cos(inc0), 0f, Mathf.Sin(inc0) ) * x; Vector3 v1 = new Vector3(-Mathf.Cos(inc1), 0f, Mathf.Sin(inc1) ) * x; sides_v[sv+0] = v0; sides_v[sv+1] = v1; sides_v[sv+2] = v0; sides_v[sv+3] = v1; sides_v[sv+0].y = 0f; sides_v[sv+1].y = 0f; sides_v[sv+2].y = h0; sides_v[sv+3].y = h1; sides_f[st++] = new pb_Face( side % 2 == 0 ? new int[] { v+2, v+1, v+0, v+2, v+3, v+1 } : new int[] { v+0, v+1, v+2, v+1, v+3, v+2 } ); v += 4; sv += 4; /// that connecting triangle if(i > 0) { sides_f[st-1].textureGroup = (side * steps) + i; sides_v[sv+0] = v0; sides_v[sv+1] = v1; sides_v[sv+2] = v0; sides_v[sv+0].y = h0; sides_v[sv+1].y = h1; sides_v[sv+2].y = h1; sides_f[st++] = new pb_Face( side % 2 == 0 ? new int[] { v+2, v+1, v+0 } : new int[] { v+0, v+1, v+2 } ); sides_f[st-1].textureGroup = (side * steps) + i; v += 3; sv += 3; } } vertices = vertices.Concat(sides_v); faces = faces.Concat(sides_f); x += stairWidth; } // // add that last back face float cos = -Mathf.Cos(cir), sin = Mathf.Sin(cir); vertices = vertices.Concat(new Vector3[] { new Vector3(cos, 0f, sin) * innerRadius, new Vector3(cos, 0f, sin) * outerRadius, new Vector3(cos * innerRadius, height, sin * innerRadius), new Vector3(cos * outerRadius, height, sin * outerRadius) }); faces = faces.Add(new pb_Face(new int[] {v+2, v+1, v+0, v+2, v+3, v+1})); } if(circumference < 0f) { Vector3 flip = new Vector3(-1f, 1f, 1f); for(int i = 0; i < vertices.Length; i++) { vertices[i].Scale(flip); } foreach(pb_Face f in faces) f.ReverseIndices(); } pb_Object pb = pb_Object.CreateInstanceWithVerticesFaces(vertices, faces); pb.SetName("Stairs"); return pb; }