2025-11-24 15:14:10 +00:00

258 lines
8.4 KiB
C#

namespace TheLabs;
public static class ShapeFactory
{
public static Mesh CreateTexturedCube()
{
float[] vertices = {
// Format: X, Y, Z, NX, NY, NZ, U, V
// --- Front Face (Normal points +Z: 0, 0, 1) ---
-0.5f, -0.5f, 0.5f, 0f, 0f, 1f, 0f, 0f, // Bottom-left
0.5f, -0.5f, 0.5f, 0f, 0f, 1f, 1f, 0f, // Bottom-right
0.5f, 0.5f, 0.5f, 0f, 0f, 1f, 1f, 1f, // Top-right
-0.5f, 0.5f, 0.5f, 0f, 0f, 1f, 0f, 1f, // Top-left
// --- Back Face (Normal points -Z: 0, 0, -1) ---
-0.5f, -0.5f, -0.5f, 0f, 0f, -1f, 1f, 0f,
0.5f, -0.5f, -0.5f, 0f, 0f, -1f, 0f, 0f,
0.5f, 0.5f, -0.5f, 0f, 0f, -1f, 0f, 1f,
-0.5f, 0.5f, -0.5f, 0f, 0f, -1f, 1f, 1f,
// --- Left Face (Normal points -X: -1, 0, 0) ---
-0.5f, -0.5f, -0.5f, -1f, 0f, 0f, 0f, 0f,
-0.5f, -0.5f, 0.5f, -1f, 0f, 0f, 1f, 0f,
-0.5f, 0.5f, 0.5f, -1f, 0f, 0f, 1f, 1f,
-0.5f, 0.5f, -0.5f, -1f, 0f, 0f, 0f, 1f,
// --- Right Face (Normal points +X: 1, 0, 0) ---
0.5f, -0.5f, -0.5f, 1f, 0f, 0f, 1f, 0f,
0.5f, -0.5f, 0.5f, 1f, 0f, 0f, 0f, 0f,
0.5f, 0.5f, 0.5f, 1f, 0f, 0f, 0f, 1f,
0.5f, 0.5f, -0.5f, 1f, 0f, 0f, 1f, 1f,
// --- Top Face (Normal points +Y: 0, 1, 0) ---
-0.5f, 0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f,
0.5f, 0.5f, -0.5f, 0f, 1f, 0f, 1f, 1f,
0.5f, 0.5f, 0.5f, 0f, 1f, 0f, 1f, 0f,
-0.5f, 0.5f, 0.5f, 0f, 1f, 0f, 0f, 0f,
// --- Bottom Face (Normal points -Y: 0, -1, 0) ---
-0.5f, -0.5f, -0.5f, 0f, -1f, 0f, 1f, 1f,
0.5f, -0.5f, -0.5f, 0f, -1f, 0f, 0f, 1f,
0.5f, -0.5f, 0.5f, 0f, -1f, 0f, 0f, 0f,
-0.5f, -0.5f, 0.5f, 0f, -1f, 0f, 1f, 0f
};
uint[] indices = {
// Front face
0, 2, 1,
0, 2, 3,
// Back face
4, 5, 6,
4, 6, 7,
// Left face
8, 9, 10,
8, 10, 11,
// Right face
12, 14, 13,
12, 14, 15,
// Top face
16, 17, 18,
16, 18, 19,
// Bottom face
20, 22, 21,
20, 22, 23
};
return new Mesh(vertices, indices, Mesh.VertexLayout.PosTexNormal);
}
public static Mesh CreateColouredCircle()
{
float[] vertices = {
};
int segments = 100;
for (int i = 0; i <= segments; i++)
{
float angle = i * 2.0f * MathF.PI / segments;
float x = 0.5f * MathF.Cos(angle);
float y = 0.5f * MathF.Sin(angle);
Array.Resize(ref vertices, vertices.Length + 7);
vertices[^7] = x;
vertices[^6] = y;
vertices[^5] = 0f;
}
return new Mesh(vertices, Mesh.VertexLayout.PosColor);
}
public static Mesh CreateTexturedCircle()
{
var vertices = new List<float>();
int segments = 100;
vertices.Add(0f); // Center X
vertices.Add(0f); // Center Y
vertices.Add(0f); // Center Z
vertices.Add(0.5f); // Center U
vertices.Add(0.5f); // Center V
for (int i = 0; i <= segments; i++)
{
float angle = i * 2.0f * MathF.PI / segments;
float x = 0.5f * MathF.Cos(angle);
float y = 0.5f * MathF.Sin(angle);
vertices.Add(x); // X
vertices.Add(y); // Y
vertices.Add(0f); // Z
vertices.Add((x + 0.5f)); // U
vertices.Add((y + 0.5f)); // V
}
return new Mesh(vertices.ToArray(), Mesh.VertexLayout.PosTex);
}
public static Mesh CreateColorCube()
{
float[] vertices = {
-0.5f, -0.5f, 0.5f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, // Bottom-left
0.5f, -0.5f, 0.5f, 0f, 1f, 0f, 1f, 0f, 0f, 1f, // Bottom-right
0.5f, 0.5f, 0.5f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, // Top-right
-0.5f, 0.5f, 0.5f, 1f, 1f, 0f, 1f, 0f, 0f, 1f, // Top-left
// Back face (z = -0.5)
-0.5f, -0.5f, -0.5f, 1f, 0f, 1f, 1f, 0f, 0f, -1f, // Bottom-left
0.5f, -0.5f, -0.5f, 0f, 1f, 1f, 1f, 0f, 0f, -1f, // Bottom-right
0.5f, 0.5f, -0.5f, 1f, 1f, 1f, 1f, 0f, 0f, -1f, // Top-right
-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 1f, 0f, 0f, -1f, // Top-left
};
uint[] indices = {
// Front face
0, 1, 2,
2, 3, 0,
// Back face
4, 5, 6,
6, 7, 4,
// Left face
4, 0, 3,
3, 7, 4,
// Right face
1, 5, 6,
6, 2, 1,
// Top face
3, 2, 6,
6, 7, 3,
// Bottom face
4, 5, 1,
1, 0, 4
};
return new Mesh(vertices, indices, Mesh.VertexLayout.PosColor);
}
public static Mesh CreateTexturedCylinder(int segments = 32, float height = 1.0f, float radius = 0.5f)
{
var vertices = new List<float>();
var indices = new List<uint>();
uint vertexIndex = 0;
float halfHeight = height / 2.0f;
uint topCenterIndex = vertexIndex;
vertices.AddRange(new[]
{
0.0f, halfHeight, 0.0f, // Position
0.5f, 0.5f
}); // Top center vertex
vertexIndex++;
uint topStartIndex = vertexIndex;
for (int i = 0; i <= segments; i++)
{
float angle = i * 2.0f * MathF.PI / segments;
float x = radius * MathF.Cos(angle);
float z = radius * MathF.Sin(angle);
// UV coordinates are mapped from model space (-0.5 to +0.5)
// to texture space (0.0 to 1.0)
float u = x / (radius * 2) + 0.5f;
float v = z / (radius * 2) + 0.5f;
vertices.AddRange(new[] { x, halfHeight, z, u, v });
vertexIndex++;
}
// Add Top Cap Indices (Triangle Fan)
for (int i = 0; i < segments; i++)
{
indices.Add(topCenterIndex);
indices.Add(topStartIndex + (uint)i);
indices.Add(topStartIndex + (uint)((i + 1) % segments)); // Wrap around
}
uint sideStartIndex = vertexIndex;
// Loop from 0 to segments (inclusive) to get (segments + 1)
// vertices for wrapping the texture seamlessly.
for (int i = 0; i <= segments; i++)
{
float angle = i * 2.0f * MathF.PI / segments;
float x = radius * MathF.Cos(angle);
float z = radius * MathF.Sin(angle);
// The U coordinate goes from 0.0 to 1.0 around the cylinder
float u = (float)i / segments;
// Add Top Side Vertex
vertices.AddRange(new[] { x, halfHeight, z, u, 1.0f }); // V = 1.0 (top)
vertexIndex++;
// Add Bottom Side Vertex
vertices.AddRange(new[] { x, -halfHeight, z, u, 0.0f }); // V = 0.0 (bottom)
vertexIndex++;
}
// Add Side Wall Indices (Quad Strip)
for (int i = 0; i < segments; i++)
{
// Each segment has 2 vertices (top, bottom)
// We reference the vertices we just created.
uint topCurrent = sideStartIndex + (uint)(i * 2);
uint bottomCurrent = topCurrent + 1;
uint topNext = sideStartIndex + (uint)((i + 1) * 2);
uint bottomNext = topNext + 1;
// Triangle 1 (CCW)
indices.Add(topCurrent);
indices.Add(bottomCurrent);
indices.Add(topNext);
// Triangle 2 (CCW)
indices.Add(bottomCurrent);
indices.Add(bottomNext);
indices.Add(topNext);
}
// --- 4. Create the Mesh ---
return new Mesh(vertices.ToArray(), indices.ToArray(), Mesh.VertexLayout.PosTex);
}
}