Advertisement
Krythic

Generate Sphere

Jan 26th, 2021
2,068
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.96 KB | None | 0 0
  1. public static GraphicsMesh GenerateSphere(Device device, int numLatitudeLines, int numLongitudeLines, int radius)
  2.         {
  3.             // One vertex at every latitude-longitude intersection,
  4.             // plus one for the north pole and one for the south.
  5.             // One meridian serves as a UV seam, so we double the vertices there.
  6.             int numVertices = (numLatitudeLines * (numLongitudeLines + 1)) + 2;
  7.             Vector3[] positions = new Vector3[numVertices];
  8.             Vector2[] texcoords = new Vector2[numVertices]; // Not needed for me; just don't care to delete it.
  9.             // North pole.
  10.             positions[0] = new Vector3(0, radius, 0);
  11.             texcoords[0] = new Vector2(0, 1);
  12.             // South pole.
  13.             positions[numVertices - 1] = new Vector3(0, -radius, 0);
  14.             texcoords[numVertices - 1] = new Vector2(0, 0);
  15.             // +1.0f because there's a gap between the poles and the first parallel.
  16.             float latitudeSpacing = 1.0f / (numLatitudeLines + 1.0f);
  17.             float longitudeSpacing = 1.0f / numLongitudeLines;
  18.             // start writing new vertices at position 1
  19.             int v = 1;
  20.             for (int latitude = 0; latitude < numLatitudeLines; latitude++)
  21.             {
  22.                 for (int longitude = 0; longitude <= numLongitudeLines; longitude++)
  23.                 {
  24.                     // Scale coordinates into the 0...1 texture coordinate range,
  25.                     // with north at the top (y = 1).
  26.                     texcoords[v] = new Vector2(
  27.                                       longitude * longitudeSpacing,
  28.                                       1.0f - ((latitude + 1) * latitudeSpacing)
  29.                                    );
  30.                     // Convert to spherical coordinates:
  31.                     // theta is a longitude angle (around the equator) in radians.
  32.                     // phi is a latitude angle (north or south of the equator).
  33.                     float theta = (float)(texcoords[v].X * 2.0f * Math.PI);
  34.                     float phi = (float)((texcoords[v].Y - 0.5f) * Math.PI);
  35.                     // This determines the radius of the ring of this line of latitude.
  36.                     // It's widest at the equator, and narrows as phi increases/decreases.
  37.                     float c = (float)Math.Cos(phi);
  38.                     // Usual formula for a vector in spherical coordinates.
  39.                     // You can exchange x & z to wind the opposite way around the sphere.
  40.                     positions[v] = new Vector3(
  41.                         (float)(c * Math.Cos(theta)),
  42.                         (float)Math.Sin(phi),
  43.                         (float)(c * Math.Sin(theta))) * radius;
  44.                     // Proceed to the next vertex.
  45.                     v++;
  46.                 }
  47.             }
  48.             // Convert Vertices to triangles
  49.             int numTriangles = numLatitudeLines * numLongitudeLines * 2;
  50.             Vertex[] vertices = new Vertex[numTriangles * 3];
  51.             v = 0;
  52.             for (int i = 0; i < numLongitudeLines; i++)
  53.             {
  54.                 vertices[v++] = new Vertex(positions[0]);
  55.                 vertices[v++] = new Vertex(positions[i + 2]);
  56.                 vertices[v++] = new Vertex(positions[i + 1]);
  57.             }
  58.             // Each row has one more unique vertex than there are lines of longitude,
  59.             // since we double a vertex at the texture seam.
  60.             int rowLength = numLongitudeLines + 1;
  61.             for (int latitude = 0; latitude < numLatitudeLines - 1; latitude++)
  62.             {
  63.                 // Plus one for the pole.
  64.                 int rowStart = (latitude * rowLength) + 1;
  65.                 for (int longitude = 0; longitude < numLongitudeLines; longitude++)
  66.                 {
  67.                     int firstCorner = rowStart + longitude;
  68.                     // First triangle of quad: Top-Left, Bottom-Left, Bottom-Right
  69.                     vertices[v++] = new Vertex(positions[firstCorner]);
  70.                     vertices[v++] = new Vertex(positions[firstCorner + rowLength + 1]);
  71.                     vertices[v++] = new Vertex(positions[firstCorner + rowLength]);
  72.                     // Second triangle of quad: Top-Left, Bottom-Right, Top-Right
  73.                     vertices[v++] = new Vertex(positions[firstCorner]);
  74.                     vertices[v++] = new Vertex(positions[firstCorner + 1]);
  75.                     vertices[v++] = new Vertex(positions[firstCorner + rowLength + 1]);
  76.                 }
  77.             }
  78.             int pole = positions.Length - 1;
  79.             int bottomRow = ((numLatitudeLines - 1) * rowLength) + 1;
  80.             for (int i = 0; i < numLongitudeLines; i++)
  81.             {
  82.                 vertices[v++] = new Vertex(positions[pole]);
  83.                 vertices[v++] = new Vertex(positions[bottomRow + i]);
  84.                 vertices[v++] = new Vertex(positions[bottomRow + i + 1]);
  85.             }
  86.             return new GraphicsMesh(device, vertices);
  87.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement