Files
renderer/mesh.odin

247 lines
8.7 KiB
Odin

package renderer
import "core:math"
import "core:log"
Mesh :: struct {
amount_of_indices: u32,
backend: Mesh_Backend,
}
Mesh_Handle :: distinct u32
Buffer_Handle :: distinct u32
Mesh_Layout :: struct {
name: string,
amount: u8,
type_size: u32,
}
create_mesh :: proc {
create_mesh_layout_vertices_indices,
create_mesh_from_primitive,
}
create_mesh_layout_vertices_indices :: proc(renderer: ^Renderer, layout: []Mesh_Layout, vertices: []f32, indices: []u32) -> (Mesh, bool) { // TODO: SS - Should probably return a Mesh_Handle.
mesh: Mesh
if len(vertices) == 0 {
return {}, false
}
if len(indices) == 0 {
return {}, false
}
m: Mesh
m.amount_of_indices = u32(len(indices))
when RENDER_BACKEND_OPENGL {
opengl_mesh, ok := opengl_create_mesh(renderer, layout, vertices, indices)
if !ok {
return {}, false
}
m.backend = opengl_mesh
}
else {
#assert(false)
}
return m, true
}
Primitive_Mesh_Type :: enum {
Cube,
Quad,
Sphere,
}
create_mesh_from_primitive :: proc(renderer: ^Renderer, primitive_mesh_type: Primitive_Mesh_Type) -> (Mesh, bool) {
switch primitive_mesh_type {
case .Cube: {
m, ok := create_mesh(
renderer = renderer,
layout = {
{ "position", 3, size_of(f32), },
{ "normal", 3, size_of(f32), },
{ "texture_coords", 2, size_of(f32), },
{ "tangent", 3, size_of(f32), },
},
vertices = []f32{
// Positions // Normals // UV // Tangent
// Back face
-0.5, -0.5, -0.5, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
0.5, -0.5, -0.5, 0.0, 0.0, -1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
0.5, 0.5, -0.5, 0.0, 0.0, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0,
-0.5, 0.5, -0.5, 0.0, 0.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0,
// Front face
-0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,
0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0,
-0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0,
// Left face
-0.5, 0.5, 0.5, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0,
-0.5, 0.5, -0.5, -1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0,
-0.5, -0.5, -0.5, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
-0.5, -0.5, 0.5, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
// Right face
0.5, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0,
0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0,
0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0,
0.5, 0.5, -0.5, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, -1.0,
// Bottom face
-0.5, -0.5, -0.5, 0.0,-1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,
0.5, -0.5, -0.5, 0.0,-1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0,
0.5, -0.5, 0.5, 0.0,-1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,
-0.5, -0.5, 0.5, 0.0,-1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
// Top face
-0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,
0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0,
0.5, 0.5, 0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,
-0.5, 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
},
indices = []u32 {
// Back face
0, 3, 1,
1, 3, 2,
// Front face
4, 5, 7,
5, 6, 7,
// Left face
8, 9, 11,
9, 10, 11,
// Right face
12, 13, 15,
13, 14, 15,
// Bottom face
16, 17, 18,
16, 18, 19,
// Top face
20, 22, 21,
20, 23, 22
}
)
return m, ok
}
case .Quad: {
m, ok := create_mesh(
renderer = renderer,
layout = {
{ "position", 3, size_of(f32), },
{ "normal", 3, size_of(f32), },
{ "texture_coords", 2, size_of(f32), },
{ "tangent", 3, size_of(f32), },
},
vertices = []f32 {
// Positions. // Normals // Texture Coordinates. // Tangent.
0.5, 0.5, 0.0, 0, 0, 0, 1.0, 1.0, 1, 0, 0, // Top right.
0.5, -0.5, 0.0, 0, 0, 0, 1.0, 0.0, 1, 0, 0, // Bottom right.
-0.5, -0.5, 0.0, 0, 0, 0, 0.0, 0.0, 1, 0, 0, // Bottom left.
-0.5, 0.5, 0.0, 0, 0, 0, 0.0, 1.0, 1, 0, 0, // Top left.
},
indices = []u32 {
0, 1, 3,
1, 2, 3,
}
)
return m, ok
}
case .Sphere: {
X_SEGMENTS :: 64
Y_SEGMENTS :: 32
vertices := make([dynamic]f32, 0)
indices := make([dynamic]u32, 0)
defer delete(vertices)
defer delete(indices)
for y in 0..=Y_SEGMENTS {
y_segment := f32(y) / f32(Y_SEGMENTS)
phi := y_segment * math.PI
for x in 0..=X_SEGMENTS {
x_segment := f32(x) / f32(X_SEGMENTS)
theta := x_segment * math.TAU
px := math.cos(theta) * math.sin(phi)
py := math.cos(phi)
pz := math.sin(theta) * math.sin(phi)
// Position.
append(&vertices, px * 0.5)
append(&vertices, py * 0.5)
append(&vertices, pz * 0.5)
// Normal.
append(&vertices, px)
append(&vertices, py)
append(&vertices, pz)
// UV.
append(&vertices, x_segment)
append(&vertices, 1.0 - y_segment)
// Tangent.
tx := -math.sin(theta)
ty := f32(0.0)
tz := math.cos(theta)
append(&vertices, tx)
append(&vertices, ty)
append(&vertices, tz)
}
}
for y in 0..<Y_SEGMENTS {
for x in 0..<X_SEGMENTS {
i0 := u32(y * (X_SEGMENTS + 1) + x)
i1 := u32((y + 1) * (X_SEGMENTS + 1) + x)
i2 := u32((y + 1) * (X_SEGMENTS + 1) + x + 1)
i3 := u32(y * (X_SEGMENTS + 1) + x + 1)
append(&indices, i0)
append(&indices, i3)
append(&indices, i1)
append(&indices, i1)
append(&indices, i3)
append(&indices, i2)
}
}
m, ok := create_mesh(
renderer = renderer,
layout = {
{ "position", 3, size_of(f32), },
{ "normal", 3, size_of(f32), },
{ "texture_coords", 2, size_of(f32), },
{ "tangent", 3, size_of(f32), },
},
vertices = vertices[:],
indices = indices[:],
)
return m, ok
}
}
return {}, false
}
delete_mesh :: proc(renderer: ^Renderer, mesh: ^Mesh) {
assert(renderer != nil)
assert(mesh != nil)
when RENDER_BACKEND_OPENGL {
opengl_delete_mesh(renderer, mesh)
}
}