public static MeshData CreateSphere(float radius, int sliceCount, int stackCount) {
var ret = new MeshData();
ret.Vertices.Add(new Vertex(0, radius, 0, 0, 1, 0, 1, 0, 0, 0, 0));
var phiStep = MathF.PI / stackCount;
var thetaStep = 2.0f * MathF.PI / sliceCount;
for (var i = 1; i <= stackCount - 1; i++) {
var phi = i * phiStep;
for (var j = 0; j <= sliceCount; j++) {
var theta = j * thetaStep;
var p = new Vector3(
(radius * MathF.Sin(phi) * MathF.Cos(theta)),
(radius * MathF.Cos(phi)),
(radius * MathF.Sin(phi) * MathF.Sin(theta))
);
var t = new Vector3(-radius * MathF.Sin(phi) * MathF.Sin(theta), 0, radius * MathF.Sin(phi) * MathF.Cos(theta));
t.Normalize();
var n = Vector3.Normalize(p);
var uv = new Vector2(theta / (MathF.PI * 2), phi / MathF.PI);
ret.Vertices.Add(new Vertex(p, n, t, uv));
}
}
ret.Vertices.Add(new Vertex(0, -radius, 0, 0, -1, 0, 1, 0, 0, 0, 1));
for (var i = 1; i <= sliceCount; i++) {
ret.Indices.Add(0);
ret.Indices.Add(i + 1);
ret.Indices.Add(i);
}
var baseIndex = 1;
var ringVertexCount = sliceCount + 1;
for (var i = 0; i < stackCount - 2; i++) {
for (var j = 0; j < sliceCount; j++) {
ret.Indices.Add(baseIndex + i * ringVertexCount + j);
ret.Indices.Add(baseIndex + i * ringVertexCount + j + 1);
ret.Indices.Add(baseIndex + (i + 1) * ringVertexCount + j);
ret.Indices.Add(baseIndex + (i + 1) * ringVertexCount + j);
ret.Indices.Add(baseIndex + i * ringVertexCount + j + 1);
ret.Indices.Add(baseIndex + (i + 1) * ringVertexCount + j + 1);
}
}
var southPoleIndex = ret.Vertices.Count - 1;
baseIndex = southPoleIndex - ringVertexCount;
for (var i = 0; i < sliceCount; i++) {
ret.Indices.Add(southPoleIndex);
ret.Indices.Add(baseIndex + i);
ret.Indices.Add(baseIndex + i + 1);
}
return ret;
}