summaryrefslogtreecommitdiff
path: root/src/model.c
diff options
context:
space:
mode:
authorConnor Thomson <blumatrikz@gmail.com>2026-09-10 19:30:13 -0700
committerConnor Thomson <blumatrikz@gmail.com>2026-09-10 19:30:13 -0700
commit9419ddf6e42ccf6127c2dde7d8791c19e4511844 (patch)
tree415fe960575e3c00cd3f4709140418df310d7404 /src/model.c
parenta618f7c8d4e8df65d9d2542d9032c32973e42981 (diff)
Make model.c and model.h a little better
Diffstat (limited to 'src/model.c')
-rw-r--r--src/model.c192
1 files changed, 132 insertions, 60 deletions
diff --git a/src/model.c b/src/model.c
index b256f42..b8c0efe 100644
--- a/src/model.c
+++ b/src/model.c
@@ -38,9 +38,7 @@ static bool ta_model_push_vertex(ta_model_mesh *mesh, size_t *capacity, const ta
return true;
}
-bool ta_model_build(const float positions[][3], size_t position_count,
- const unsigned int faces[][3], size_t face_count,
- ta_model_mesh *mesh) {
+bool ta_model_build(const float positions[][TA_MODEL_DIMENSION], size_t position_count, const unsigned int faces[][TA_MODEL_DIMENSION], size_t face_count, ta_model_mesh *mesh) {
float *normal_accum = NULL;
size_t vertex_capacity = 0;
bool success = false;
@@ -51,40 +49,48 @@ bool ta_model_build(const float positions[][3], size_t position_count,
}
for (size_t index = 0; index < face_count; index++) {
- for (int corner = 0; corner < 3; corner++) {
+ for (int corner = 0; corner < TA_MODEL_DIMENSION; corner++) {
if (faces[index][corner] >= position_count) {
return false;
}
}
}
- normal_accum = calloc(position_count * 3, sizeof(*normal_accum));
+ normal_accum = calloc(position_count * TA_MODEL_DIMENSION, sizeof(*normal_accum));
if (!normal_accum) {
goto done;
}
for (size_t index = 0; index < face_count; index++) {
- const float *first = positions[faces[index][0]];
+ const float *first = positions[faces[index][0]];
const float *second = positions[faces[index][1]];
- const float *third = positions[faces[index][2]];
- float edge_a[3] = {second[0] - first[0], second[1] - first[1], second[2] - first[2]};
- float edge_b[3] = {third[0] - first[0], third[1] - first[1], third[2] - first[2]};
- float face_normal[3] = {
+ const float *third = positions[faces[index][2]];
+ float edge_a[TA_MODEL_DIMENSION] = {
+ second[0] - first[0],
+ second[1] - first[1],
+ second[2] - first[2]
+ };
+ float edge_b[TA_MODEL_DIMENSION] = {
+ third[0] - first[0],
+ third[1] - first[1],
+ third[2] - first[2]
+ };
+ float face_normal[TA_MODEL_DIMENSION] = {
edge_a[1] * edge_b[2] - edge_a[2] * edge_b[1],
edge_a[2] * edge_b[0] - edge_a[0] * edge_b[2],
edge_a[0] * edge_b[1] - edge_a[1] * edge_b[0],
};
- for (int corner = 0; corner < 3; corner++) {
+ for (int corner = 0; corner < TA_MODEL_DIMENSION; corner++) {
size_t position_index = faces[index][corner];
- normal_accum[position_index * 3 + 0] += face_normal[0];
- normal_accum[position_index * 3 + 1] += face_normal[1];
- normal_accum[position_index * 3 + 2] += face_normal[2];
+ normal_accum[position_index * TA_MODEL_DIMENSION + 0] += face_normal[0];
+ normal_accum[position_index * TA_MODEL_DIMENSION + 1] += face_normal[1];
+ normal_accum[position_index * TA_MODEL_DIMENSION + 2] += face_normal[2];
}
}
for (size_t index = 0; index < position_count; index++) {
- float *normal = &normal_accum[index * 3];
- float length = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
+ float *normal = &normal_accum[index * TA_MODEL_DIMENSION];
+ float length = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
if (length > 0.0f) {
normal[0] /= length;
normal[1] /= length;
@@ -97,11 +103,11 @@ bool ta_model_build(const float positions[][3], size_t position_count,
}
for (size_t index = 0; index < face_count; index++) {
- for (int corner = 0; corner < 3; corner++) {
+ for (int corner = 0; corner < TA_MODEL_DIMENSION; corner++) {
size_t position_index = faces[index][corner];
ta_model_vertex vertex;
memcpy(vertex.position, positions[position_index], sizeof(vertex.position));
- memcpy(vertex.normal, &normal_accum[position_index * 3], sizeof(vertex.normal));
+ memcpy(vertex.normal, &normal_accum[position_index * TA_MODEL_DIMENSION], sizeof(vertex.normal));
if (!ta_model_push_vertex(mesh, &vertex_capacity, &vertex)) {
goto done;
}
@@ -119,62 +125,84 @@ done:
void ta_model_free(ta_model_mesh *mesh) {
free(mesh->vertices);
- mesh->vertices = NULL;
+ mesh->vertices = NULL;
mesh->vertex_count = 0;
}
typedef struct ta_model_uniforms {
- float mvp[16];
- float model[16];
- float camera_position[3];
+ float mvp[16]; // TODO: Use dynamic buffer
+ float model[16]; // TODO: Use dynamic buffer
+ float camera_position[TA_MODEL_DIMENSION];
float padding;
} ta_model_uniforms;
static SDL_GPUShader *ta_model_shader(SDL_GPUDevice *device, const void *code, size_t size, SDL_GPUShaderStage stage) {
SDL_GPUShaderCreateInfo info = {
- .code = code,
- .code_size = size,
- .entrypoint = "main",
- .format = SDL_GPU_SHADERFORMAT_SPIRV,
- .stage = stage,
+ .code = code,
+ .code_size = size,
+ .entrypoint = "main",
+ .format = SDL_GPU_SHADERFORMAT_SPIRV,
+ .stage = stage,
.num_uniform_buffers = stage == SDL_GPU_SHADERSTAGE_VERTEX ? 1 : 0,
};
return ta_sdl_create_gpu_shader(device, &info);
}
static void ta_model_identity(float *matrix) {
- for (int index = 0; index < 16; index++) matrix[index] = index % 5 == 0 ? 1.0f : 0.0f;
+ for (int index = 0; index < 16; index++) {
+ matrix[index] = index % 5 == 0 ? 1.0f : 0.0f;
+ }
}
static void ta_model_multiply(float *result, const float *left, const float *right) {
float product[16];
for (int column = 0; column < 4; column++) for (int row = 0; row < 4; row++) {
product[column * 4 + row] = 0.0f;
- for (int inner = 0; inner < 4; inner++) product[column * 4 + row] += left[inner * 4 + row] * right[column * 4 + inner];
+ for (int inner = 0; inner < 4; inner++) {
+ product[column * 4 + row] += left[inner * 4 + row] * right[column * 4 + inner];
+ }
}
memcpy(result, product, sizeof(product));
}
-bool ta_model_init(ta_model *model, SDL_GPUDevice *device,
- const float positions[][3], size_t position_count,
- const unsigned int faces[][3], size_t face_count,
- SDL_GPUTextureFormat color_format, SDL_GPUTextureFormat depth_format, SDL_GPUSampleCount sample_count) {
+bool ta_model_init(ta_model *model, SDL_GPUDevice *device, const float positions[][TA_MODEL_DIMENSION], size_t position_count, const unsigned int faces[][TA_MODEL_DIMENSION], size_t face_count, SDL_GPUTextureFormat color_format, SDL_GPUTextureFormat depth_format, SDL_GPUSampleCount sample_count) {
memset(model, 0, sizeof(*model));
- if (!ta_model_build(positions, position_count, faces, face_count, &model->mesh) || model->mesh.vertex_count == 0) return false;
- float minimum[3];
- float maximum[3];
+ if (!ta_model_build(positions, position_count, faces, face_count, &model->mesh) || model->mesh.vertex_count == 0) {
+ return false;
+ }
+ float minimum[TA_MODEL_DIMENSION];
+ float maximum[TA_MODEL_DIMENSION];
memcpy(minimum, model->mesh.vertices[0].position, sizeof(minimum));
memcpy(maximum, minimum, sizeof(maximum));
- for (size_t index = 1; index < model->mesh.vertex_count; index++) for (int axis = 0; axis < 3; axis++) {
- if (model->mesh.vertices[index].position[axis] < minimum[axis]) minimum[axis] = model->mesh.vertices[index].position[axis];
- if (model->mesh.vertices[index].position[axis] > maximum[axis]) maximum[axis] = model->mesh.vertices[index].position[axis];
+ for (size_t index = 1; index < model->mesh.vertex_count; index++) for (int axis = 0; axis < TA_MODEL_DIMENSION; axis++) {
+ if (model->mesh.vertices[index].position[axis] < minimum[axis]) {
+ minimum[axis] = model->mesh.vertices[index].position[axis];
+ }
+ if (model->mesh.vertices[index].position[axis] > maximum[axis]) {
+ maximum[axis] = model->mesh.vertices[index].position[axis];
+ }
}
- float center[3] = {(minimum[0] + maximum[0]) * 0.5f, (minimum[1] + maximum[1]) * 0.5f, (minimum[2] + maximum[2]) * 0.5f};
+ float center[TA_MODEL_DIMENSION] = {
+ (minimum[0] + maximum[0]) * 0.5f,
+ (minimum[1] + maximum[1]) * 0.5f,
+ (minimum[2] + maximum[2]) * 0.5f
+ };
float extent = maximum[0] - minimum[0];
- for (int axis = 1; axis < 3; axis++) if (maximum[axis] - minimum[axis] > extent) extent = maximum[axis] - minimum[axis];
- for (size_t index = 0; index < model->mesh.vertex_count; index++) for (int axis = 0; axis < 3; axis++) model->mesh.vertices[index].position[axis] = (model->mesh.vertices[index].position[axis] - center[axis]) * (2.2f / extent);
+ for (int axis = 1; axis < TA_MODEL_DIMENSION; axis++) {
+ if (maximum[axis] - minimum[axis] > extent) {
+ extent = maximum[axis] - minimum[axis];
+ }
+ }
+ for (size_t index = 0; index < model->mesh.vertex_count; index++) {
+ for (int axis = 0; axis < TA_MODEL_DIMENSION; axis++) {
+ model->mesh.vertices[index].position[axis] = (model->mesh.vertices[index].position[axis] - center[axis]) * (2.2f / extent);
+ }
+ }
- SDL_GPUBufferCreateInfo buffer_info = {.usage = SDL_GPU_BUFFERUSAGE_VERTEX, .size = (Uint32)(model->mesh.vertex_count * sizeof(*model->mesh.vertices))};
+ SDL_GPUBufferCreateInfo buffer_info = {
+ .usage = SDL_GPU_BUFFERUSAGE_VERTEX,
+ .size = (Uint32)(model->mesh.vertex_count * sizeof(*model->mesh.vertices))
+ };
model->vertex_buffer = SDL_CreateGPUBuffer(device, &buffer_info);
if (!model->vertex_buffer) {
ta_model_free(&model->mesh);
@@ -185,19 +213,49 @@ bool ta_model_init(ta_model *model, SDL_GPUDevice *device,
SDL_GPUShader *fragment_shader = ta_model_shader(device, file_obj_frag_slang_spv_start, file_obj_frag_slang_spv_size, SDL_GPU_SHADERSTAGE_FRAGMENT);
SDL_GPUVertexBufferDescription vertex_buffer = {.slot = 0, .pitch = sizeof(ta_model_vertex), .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX};
SDL_GPUVertexAttribute attributes[2] = {
- {.location = 0, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = 0},
- {.location = 1, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = sizeof(float) * 3},
+ {
+ .location = 0,
+ .buffer_slot = 0,
+ .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3,
+ .offset = 0
+ },
+ {
+ .location = 1,
+ .buffer_slot = 0,
+ .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3,
+ .offset = sizeof(float) * TA_MODEL_DIMENSION
+ },
+ };
+ SDL_GPUColorTargetDescription color_target = {
+ .format = color_format
};
- SDL_GPUColorTargetDescription color_target = {.format = color_format};
SDL_GPUGraphicsPipelineCreateInfo pipeline_info = {
- .vertex_shader = vertex_shader,
- .fragment_shader = fragment_shader,
- .vertex_input_state = {.vertex_buffer_descriptions = &vertex_buffer, .num_vertex_buffers = 1, .vertex_attributes = attributes, .num_vertex_attributes = 2},
- .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
- .rasterizer_state = {.cull_mode = SDL_GPU_CULLMODE_NONE},
- .depth_stencil_state = {.compare_op = SDL_GPU_COMPAREOP_LESS, .enable_depth_test = true, .enable_depth_write = true},
- .multisample_state = {.sample_count = sample_count},
- .target_info = {.num_color_targets = 1, .color_target_descriptions = &color_target, .depth_stencil_format = depth_format, .has_depth_stencil_target = true},
+ .vertex_shader = vertex_shader,
+ .fragment_shader = fragment_shader,
+ .vertex_input_state = {
+ .vertex_buffer_descriptions = &vertex_buffer,
+ .num_vertex_buffers = 1,
+ .vertex_attributes = attributes,
+ .num_vertex_attributes = 2
+ },
+ .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
+ .rasterizer_state = {
+ .cull_mode = SDL_GPU_CULLMODE_NONE
+ },
+ .depth_stencil_state = {
+ .compare_op = SDL_GPU_COMPAREOP_LESS,
+ .enable_depth_test = true,
+ .enable_depth_write = true
+ },
+ .multisample_state = {
+ .sample_count = sample_count
+ },
+ .target_info = {
+ .num_color_targets = 1,
+ .color_target_descriptions = &color_target,
+ .depth_stencil_format = depth_format,
+ .has_depth_stencil_target = true
+ },
};
model->pipeline = ta_sdl_create_gpu_graphics_pipeline(device, &pipeline_info);
SDL_ReleaseGPUShader(device, vertex_shader);
@@ -206,16 +264,26 @@ bool ta_model_init(ta_model *model, SDL_GPUDevice *device,
}
void ta_model_upload(ta_model *model, SDL_GPUCommandBuffer *command_buffer, SDL_GPUDevice *device) {
- if (model->uploaded || !model->vertex_buffer) return;
+ if (model->uploaded || !model->vertex_buffer) {
+ return;
+ }
Uint32 size = (Uint32)(model->mesh.vertex_count * sizeof(*model->mesh.vertices));
- SDL_GPUTransferBufferCreateInfo transfer_info = {.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, .size = size};
+ SDL_GPUTransferBufferCreateInfo transfer_info = {
+ .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
+ .size = size
+ };
SDL_GPUTransferBuffer *transfer_buffer = ta_sdl_create_gpu_transfer_buffer(device, &transfer_info);
void *mapped = ta_sdl_map_gpu_transfer_buffer(device, transfer_buffer, false);
memcpy(mapped, model->mesh.vertices, size);
SDL_UnmapGPUTransferBuffer(device, transfer_buffer);
SDL_GPUCopyPass *copy_pass = ta_sdl_begin_gpu_copy_pass(command_buffer);
- SDL_GPUTransferBufferLocation source = {.transfer_buffer = transfer_buffer};
- SDL_GPUBufferRegion destination = {.buffer = model->vertex_buffer, .size = size};
+ SDL_GPUTransferBufferLocation source = {
+ .transfer_buffer = transfer_buffer
+ };
+ SDL_GPUBufferRegion destination = {
+ .buffer = model->vertex_buffer,
+ .size = size
+ };
SDL_UploadToGPUBuffer(copy_pass, &source, &destination, false);
SDL_EndGPUCopyPass(copy_pass);
SDL_ReleaseGPUTransferBuffer(device, transfer_buffer);
@@ -224,7 +292,9 @@ void ta_model_upload(ta_model *model, SDL_GPUCommandBuffer *command_buffer, SDL_
}
void ta_model_render(const ta_model *model, SDL_GPUCommandBuffer *command_buffer, SDL_GPURenderPass *render_pass, int window_width, int window_height) {
- if (!model->pipeline || !model->vertex_buffer || !model->uploaded) return;
+ if (!model->pipeline || !model->vertex_buffer || !model->uploaded) {
+ return;
+ }
ta_model_uniforms uniforms;
float view[16];
float projection[16] = {0};
@@ -277,7 +347,9 @@ void ta_model_render(const ta_model *model, SDL_GPUCommandBuffer *command_buffer
uniforms.padding = 0.0f;
SDL_PushGPUVertexUniformData(command_buffer, 0, &uniforms, sizeof(uniforms));
SDL_BindGPUGraphicsPipeline(render_pass, model->pipeline);
- SDL_GPUBufferBinding binding = {.buffer = model->vertex_buffer};
+ SDL_GPUBufferBinding binding = {
+ .buffer = model->vertex_buffer
+ };
SDL_BindGPUVertexBuffers(render_pass, 0, &binding, 1);
SDL_DrawGPUPrimitives(render_pass, model->vertex_count, 1, 0, 0);
}