Add model loading from OBJ and wireframe rendering
This commit is contained in:
parent
f88b74912b
commit
e266879a4f
105
src/obj.c
Normal file
105
src/obj.c
Normal file
@ -0,0 +1,105 @@
|
||||
#include "obj.h"
|
||||
#include "aliases.h"
|
||||
#include "img.h"
|
||||
#include "mem_arena.h"
|
||||
#include "typed_list.h"
|
||||
#include "utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
internal void render_wireframe_triangle(const Triangle *triangle,
|
||||
const Model *model, Image *img,
|
||||
Colour colour);
|
||||
internal void get_image_coordinates(const Vertex *vertex, const Image *img,
|
||||
u64 *x, u64 *y);
|
||||
internal u64 ndc_to_image_coordinate(f32 value, u64 max);
|
||||
|
||||
Model load_obj_file(Arena *arena, const char *filename) {
|
||||
if (!arena) {
|
||||
return NULL_MODEL;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
return NULL_MODEL;
|
||||
}
|
||||
|
||||
Model model = (Model){
|
||||
.vertices = list_create(Vertex, arena),
|
||||
.triangles = list_create(Triangle, arena),
|
||||
};
|
||||
if (!(model.vertices) || !(model.triangles)) {
|
||||
return NULL_MODEL;
|
||||
}
|
||||
|
||||
char line[8192];
|
||||
char identifier[8];
|
||||
Vertex vertex;
|
||||
Triangle triangle;
|
||||
f32 vx, vy, vz;
|
||||
u64 fp0, fp1, fp2;
|
||||
u64 ign_0_1, ign_0_2;
|
||||
u64 ign_1_1, ign_1_2;
|
||||
u64 ign_2_1, ign_2_2;
|
||||
while (fgets(line, 8191, fp) != NULL) {
|
||||
sscanf(line, "%s", identifier);
|
||||
if (strncmp(identifier, "v", 8) == 0) {
|
||||
sscanf(line + 2, "%f %f %f", &vx, &vy, &vz);
|
||||
vertex.x = vx;
|
||||
vertex.y = vy;
|
||||
vertex.z = vz;
|
||||
list_append(Vertex, arena, model.vertices, vertex);
|
||||
} else if (strncmp(identifier, "f", 8) == 0) {
|
||||
sscanf(line + 2, "%lu/%lu/%lu %lu/%lu/%lu %lu/%lu/%lu", &fp0, &ign_0_1,
|
||||
&ign_0_2, &fp1, &ign_1_1, &ign_1_2, &fp2, &ign_2_1, &ign_2_2);
|
||||
// OBJ indices start from 1
|
||||
triangle.p0 = fp0 - 1;
|
||||
triangle.p1 = fp1 - 1;
|
||||
triangle.p2 = fp2 - 1;
|
||||
list_append(Triangle, arena, model.triangles, triangle);
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
void render_wireframe_model(const Model *model, Image *img, Colour colour) {
|
||||
Triangle triangle;
|
||||
|
||||
for (u64 i = 0; i < model->triangles->count; ++i) {
|
||||
triangle = list_get(model->triangles, i);
|
||||
render_wireframe_triangle(&triangle, model, img, colour);
|
||||
}
|
||||
}
|
||||
|
||||
internal void render_wireframe_triangle(const Triangle *triangle,
|
||||
const Model *model, Image *img,
|
||||
Colour colour) {
|
||||
Vertex vertices[3] = {
|
||||
list_get(model->vertices, triangle->p0),
|
||||
list_get(model->vertices, triangle->p1),
|
||||
list_get(model->vertices, triangle->p2),
|
||||
};
|
||||
|
||||
Vertex v0, v1;
|
||||
u64 x0, y0, x1, y1;
|
||||
for (u64 i = 0; i < 3; ++i) {
|
||||
v0 = vertices[i];
|
||||
v1 = vertices[(i + 1) % 3];
|
||||
|
||||
get_image_coordinates(&v0, img, &x0, &y0);
|
||||
get_image_coordinates(&v1, img, &x1, &y1);
|
||||
|
||||
draw_line(img, x0, y0, x1, y1, colour);
|
||||
}
|
||||
}
|
||||
|
||||
internal void get_image_coordinates(const Vertex *vertex, const Image *img,
|
||||
u64 *x, u64 *y) {
|
||||
*x = ndc_to_image_coordinate(vertex->x, img->width);
|
||||
*y = ndc_to_image_coordinate(0.0f - vertex->y, img->height);
|
||||
}
|
||||
|
||||
internal u64 ndc_to_image_coordinate(f32 value, u64 max) {
|
||||
f32 result = (value + 1.0f) * max / 2.0f;
|
||||
return clamp((u64)result, 0, max);
|
||||
}
|
38
src/obj.h
Normal file
38
src/obj.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef OBJ_H
|
||||
#define OBJ_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "img.h"
|
||||
#include "mem_arena.h"
|
||||
#include "typed_list.h"
|
||||
|
||||
#define NULL_MODEL ((Model){0})
|
||||
#define IS_NULL_MODEL(m) (m.vertices == NULL || m.triangles == NULL)
|
||||
|
||||
typedef struct vertex Vertex;
|
||||
struct vertex {
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 z;
|
||||
};
|
||||
|
||||
typedef struct triangle Triangle;
|
||||
struct triangle {
|
||||
u64 p0;
|
||||
u64 p1;
|
||||
u64 p2;
|
||||
};
|
||||
|
||||
MAKE_LIST_TYPE(Vertex);
|
||||
MAKE_LIST_TYPE(Triangle);
|
||||
|
||||
typedef struct model Model;
|
||||
struct model {
|
||||
LIST_TYPE(Vertex) * vertices;
|
||||
LIST_TYPE(Triangle) * triangles;
|
||||
};
|
||||
|
||||
Model load_obj_file(Arena *arena, const char *filename);
|
||||
void render_wireframe_model(const Model *model, Image *img, Colour colour);
|
||||
|
||||
#endif // OBJ_H
|
Loading…
Reference in New Issue
Block a user