vector operations and backface culling

This commit is contained in:
jasobake 2025-07-08 00:19:10 -07:00
parent f2c976c4c1
commit 9bb767b58f
6 changed files with 221 additions and 12 deletions

46
assets/cube.obj Normal file
View File

@ -0,0 +1,46 @@
# Blender v2.76 (sub 0) OBJ File: ''
# www.blender.org
mtllib cube.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 1.000000 0.333333
vt 1.000000 0.666667
vt 0.666667 0.666667
vt 0.666667 0.333333
vt 0.666667 0.000000
vt 0.000000 0.333333
vt 0.000000 0.000000
vt 0.333333 0.000000
vt 0.333333 1.000000
vt 0.000000 1.000000
vt 0.000000 0.666667
vt 0.333333 0.333333
vt 0.333333 0.666667
vt 1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -0.000000 0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl Material
s off
f 2/1/1 3/2/1 4/3/1
f 8/1/2 7/4/2 6/5/2
f 5/6/3 6/7/3 2/8/3
f 6/8/4 7/5/4 3/4/4
f 3/9/5 7/10/5 8/11/5
f 1/12/6 4/13/6 8/11/6
f 1/4/1 2/1/1 4/3/1
f 5/14/2 8/1/2 6/5/2
f 1/12/3 5/6/3 2/8/3
f 2/12/4 6/8/4 3/4/4
f 4/13/5 3/9/5 8/11/5
f 5/6/6 1/12/6 8/11/6

View File

@ -11,7 +11,7 @@
triangle_t* triangles_to_render = NULL; //[N_MESH_FACES];
vec3_t camera_position = { .x = 0, .y = 0, .z = -5 };
vec3_t camera_position = { 0, 0, 0 };
float fov_factor = 640;
@ -84,9 +84,9 @@ void update(void) {
previous_frame_time = SDL_GetTicks();
//mesh.rotation.y += 0.01;
mesh.rotation.y += 0.01;
mesh.rotation.x -= 0.01;
//mesh.rotation.z += 0.01;
mesh.rotation.z += 0.01;
triangles_to_render = NULL;
@ -94,25 +94,57 @@ void update(void) {
for (int i = 0; i < num_faces; i++) {
face_t mesh_face = mesh.faces[i];
vec3_t face_verticies[3];
face_verticies[0] = mesh.vertices[mesh_face.a - 1];
face_verticies[1] = mesh.vertices[mesh_face.b - 1];
face_verticies[2] = mesh.vertices[mesh_face.c - 1];
vec3_t face_vertices[3];
face_vertices[0] = mesh.vertices[mesh_face.a - 1];
face_vertices[1] = mesh.vertices[mesh_face.b - 1];
face_vertices[2] = mesh.vertices[mesh_face.c - 1];
triangle_t projected_triangle;
vec3_t transformed_vertices[3];
for (int j = 0; j < 3; j++) {
vec3_t transformed_vertex = face_verticies[j];
vec3_t transformed_vertex = face_vertices[j];
transformed_vertex = vec3_rotate_x(transformed_vertex, mesh.rotation.x);
transformed_vertex = vec3_rotate_y(transformed_vertex, mesh.rotation.y);
transformed_vertex = vec3_rotate_z(transformed_vertex, mesh.rotation.z);
// translate away from camera in z
transformed_vertex.z -= camera_position.z;
transformed_vertex.z += 5;
// save translated vertex in the array of transformed vertices
transformed_vertices[j] = transformed_vertex;
}
// check backface culling
vec3_t vector_a = transformed_vertices[0]; /* A */
vec3_t vector_b = transformed_vertices[1]; /* / \ */
vec3_t vector_c = transformed_vertices[2]; /* C---B */
// get the vector subtraction of B-A and C-A
vec3_t vector_ab = vec3_subtract(vector_b, vector_a);
vec3_t vector_ac = vec3_subtract(vector_c, vector_a);
vec3_normalize(&vector_ab);
vec3_normalize(&vector_ac);
// compute the face normal using the cross product to find perpindicular
vec3_t normal = vec3_cross(vector_ab, vector_ac);
vec3_normalize(&normal);
// find the vector between a point in the triangle and the camera origin
vec3_t camera_ray = vec3_subtract(camera_position, vector_a);
// calculate how aligned the camera ray is with the face normal
float dot_normal_camera = vec3_dot(normal, camera_ray);
if (dot_normal_camera < 0) {
continue;
}
triangle_t projected_triangle;
for (int j = 0; j < 3; j++) {
// project the current vertex
vec2_t projected_point = project(transformed_vertex);
vec2_t projected_point = project(transformed_vertices[j]);
// scale and translate the projected points to the center of the screen
projected_point.x += (window_width / 2);
@ -124,6 +156,21 @@ void update(void) {
// save the projected triangle in the array of triangles
array_push(triangles_to_render, projected_triangle);
triangle_t normal_triangle;
for (int j = 0; j < 3; j++) {
// project the current vertex
vec2_t projected_point = project(transformed_vertices[j]);
// scale and translate the projected points to the center of the screen
projected_point.x += (window_width / 2);
projected_point.y += (window_height / 2);
normal_triangle.points[j] = projected_point;
}
array_push(triangles_to_render, normal_triangle);
}
}

View File

@ -75,7 +75,7 @@ void load_file(void) {
FILE* fp;
char* tok;
fp = fopen("..\\assets\\f22.obj", "r");
fp = fopen("..\\assets\\cube.obj", "r");
if (fp == NULL) {
exit(EXIT_FAILURE);

View File

@ -21,6 +21,8 @@ struct mesh_t {
extern mesh_t mesh;
void parse_face(const char* buffer, face_t* face);
void load_cube_mesh_data(void);
void load_file(void);

View File

@ -25,4 +25,101 @@ vec3_t vec3_rotate_z(vec3_t v, float angle) {
.y = v.x * sin(angle) + v.y * cos(angle),
.z = v.z,
};
}
float vec2_length(const vec2_t vector) {
return sqrt((vector.x * vector.x) + (vector.y * vector.y));
}
vec2_t vec2_add(const vec2_t a, const vec2_t b) {
return (vec2_t) {
.x = a.x + b.x,
.y = a.y + b.y,
};
}
vec2_t vec2_subtract(const vec2_t a, const vec2_t b) {
return (vec2_t) {
.x = a.x - b.x,
.y = a.y - b.y,
};
}
vec2_t vec2_multiply(const vec2_t vector, float scalar) {
return (vec2_t) {
.x = vector.x * scalar,
.y = vector.y * scalar,
};
}
vec2_t vec2_divide(const vec2_t vector, float scalar) {
return (vec2_t) {
.x = vector.x / scalar,
.y = vector.y / scalar,
};
}
float vec2_dot(const vec2_t a, const vec2_t b) {
return (a.x * b.x) + (a.y * b.y);
}
float vec3_length(const vec3_t vector) {
return sqrtf((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z));
}
void vec2_normalize(vec2_t* vertex) {
float length = vec2_length(*vertex);
vertex->x /= length;
vertex->y /= length;
}
vec3_t vec3_add(const vec3_t a, const vec3_t b) {
return (vec3_t) {
.x = a.x + b.x,
.y = a.y + b.y,
.z = a.z + b.z,
};
}
vec3_t vec3_subtract(const vec3_t a, const vec3_t b) {
return (vec3_t) {
.x = a.x - b.x,
.y = a.y - b.y,
.z = a.z - b.z,
};
}
vec3_t vec3_multiply(const vec3_t vector, const float scalar) {
return (vec3_t) {
.x = vector.x * scalar,
.y = vector.y * scalar,
.z = vector.z * scalar,
};
}
vec3_t vec3_divide(const vec3_t vector, const float scalar) {
return (vec3_t) {
.x = vector.x / scalar,
.y = vector.y / scalar,
.z = vector.z / scalar,
};
}
vec3_t vec3_cross(const vec3_t a, const vec3_t b) {
return (vec3_t) {
.x = a.y * b.z - a.z * b.y,
.y = a.z * b.x - a.x * b.z,
.z = a.x * b.y - a.y * b.x,
};
}
float vec3_dot(const vec3_t a, const vec3_t b) {
return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
}
void vec3_normalize(vec3_t* vertex) {
float length = vec3_length(*vertex);
vertex->x /= length;
vertex->y /= length;
vertex->z /= length;
}

View File

@ -19,4 +19,21 @@ vec3_t vec3_rotate_x(vec3_t v, float angle);
vec3_t vec3_rotate_y(vec3_t v, float angle);
vec3_t vec3_rotate_z(vec3_t v, float angle);
vec2_t vec2_add(const vec2_t a, const vec2_t b);
vec2_t vec2_subtract(const vec2_t a, const vec2_t b);
vec2_t vec2_multiply(const vec2_t vector, float scalar);
vec2_t vec2_divide(const vec2_t vector, float scalar);
float vec2_length(const vec2_t vector);
float vec2_dot(const vec2_t a, const vec2_t b);
void vec2_normalize(vec2_t* vertex);
vec3_t vec3_add(const vec3_t a, const vec3_t b);
vec3_t vec3_subtract(const vec3_t a, const vec3_t b);
vec3_t vec3_multiply(const vec3_t vector, const float scalar);
vec3_t vec3_divide(const vec3_t vector, const float scalar);
vec3_t vec3_cross(const vec3_t a, const vec3_t b);
float vec3_length(const vec3_t vector);
float vec3_dot(const vec3_t a, const vec3_t b);
void vec3_normalize(vec3_t* vertex);
#endif