diff --git a/src/gl_draw.c b/src/gl_draw.c index 44417c7..306ecdc 100644 --- a/src/gl_draw.c +++ b/src/gl_draw.c @@ -99,6 +99,42 @@ void draw_normals(HE_obj const * const obj, glPopMatrix(); } +/** + * Draws the vertex normals of the object, using + * the information given by the .obj file. + * + * @param obj the object to draw the vertex normals of + * @param scale_inc the incrementor for scaling the normals + */ +void draw_given_normals(HE_obj const * const obj, + float const scale_inc) +{ + static float normals_scale_factor = 0.1f; + static float line_width = 2; + + normals_scale_factor += scale_inc; + + glPushMatrix(); + + glLineWidth(line_width); + glColor3f(1.0, 0.0, 0.0); + + glBegin(GL_LINES); + for (uint32_t i = 0; i < obj->vc; i++) { + glVertex3f(obj->vertices[i].vec->x, + obj->vertices[i].vec->y, + obj->vertices[i].vec->z); + glVertex3f(obj->vertices[i].vec->x + + (obj->vn[i].x * normals_scale_factor), + obj->vertices[i].vec->y + + (obj->vn[i].y * normals_scale_factor), + obj->vertices[i].vec->z + + (obj->vn[i].z * normals_scale_factor)); + } + glEnd(); + glPopMatrix(); +} + /** * Draws all vertices of the object by * assembling a polygon for each face. @@ -390,7 +426,7 @@ void draw_obj(int32_t const myxrot, if (obj->ec != 0) { if (show_normals) - draw_normals(obj, 0); + draw_given_normals(obj, 0); draw_vertices(obj, false); } diff --git a/src/half_edge.c b/src/half_edge.c index 3398e66..62ed6c7 100644 --- a/src/half_edge.c +++ b/src/half_edge.c @@ -306,4 +306,5 @@ void delete_object(HE_obj *obj) free(obj->vertices); free(obj->faces); free(obj->bez_curves); + free(obj->vn); } diff --git a/src/half_edge.h b/src/half_edge.h index 3ad1a1a..7fdb806 100644 --- a/src/half_edge.h +++ b/src/half_edge.h @@ -101,6 +101,11 @@ typedef double** V_TEXTURES; * that describe a bezier curve. */ typedef int** BEZIER_CURV; +/** + * 2d array which can hold the vertices normals + * as they are in the .obj file. + */ +typedef double** V_NORMALS; typedef struct FACES FACES; typedef struct HE_edge HE_edge; @@ -134,6 +139,10 @@ struct obj_items { * Bezier curve */ BEZIER_CURV bez; + /** + * Vertices normals + */ + V_NORMALS vn; }; /** @@ -276,6 +285,10 @@ struct HE_obj { * Array of bezier curves. */ bez_curv *bez_curves; + /** + * Vertices normals + */ + vector *vn; /** * Count of edges. */ @@ -300,6 +313,10 @@ struct HE_obj { * Count of dummy edges. */ uint32_t dec; + /** + * Count of vertice normals. + */ + uint32_t vnc; }; /** diff --git a/src/half_edge_AS.c b/src/half_edge_AS.c index 8461644..3682453 100644 --- a/src/half_edge_AS.c +++ b/src/half_edge_AS.c @@ -49,8 +49,9 @@ static void delete_accel_struct(HE_obj *he_obj); static void delete_raw_object(obj_items *raw_obj, uint32_t fc, uint32_t vc, - uint32_t vt, - uint32_t bzc); + uint32_t vtc, + uint32_t bzc, + uint32_t vnc); /** @@ -84,17 +85,20 @@ static bool assemble_obj_arrays(char const * const obj_string, *str_tmp_ptr = NULL; /* these will be assigned later to the out structs */ - uint32_t vc = 0, fc = 0, ec = 0, vtc = 0, bzc = 0; + uint32_t vc = 0, fc = 0, ec = 0, vtc = 0, bzc = 0, vnc = 0; VERTICES obj_v = NULL; FACES *obj_f = malloc(sizeof(*obj_f)); uint32_t **obj_f_v = NULL; /* tmp v member of obj_f */ uint32_t **obj_f_vt = NULL; /* tmp vt member of obj_f */ V_TEXTURES obj_vt = NULL; BEZIER_CURV bez = NULL; + V_NORMALS obj_vn = NULL; /* allocator chunks/counts */ const int32_t obj_v_alloc_chunk = 200; int32_t obj_v_alloc_c = 0; + const int32_t obj_vn_alloc_chunk = 200; + int32_t obj_vn_alloc_c = 0; const int32_t obj_vt_alloc_chunk = 200; int32_t obj_vt_alloc_c = 0; const int32_t obj_f_v_alloc_chunk = 200; @@ -145,6 +149,31 @@ static bool assemble_obj_arrays(char const * const obj_string, vc++; obj_v[vc] = NULL; /* trailing NULL pointer */ + /* + * VERTICES NORMALS + */ + } else if (!strcmp(str_tmp_ptr, "vn")) { + char *myint = NULL; + uint8_t i = 0; + + MAYBE_REALLOC(obj_vn, + sizeof(*obj_vn), + (int32_t)vnc > (obj_vn_alloc_c - 2), + obj_vn_alloc_c, + obj_vn_alloc_chunk); + + obj_vn[vnc] = malloc(sizeof(**obj_vn) * 4); + + while ((myint = strtok_r(NULL, " ", &str_ptr_space))) { + obj_vn[vnc][i] = atof(myint); + i++; + + if (i > 3) + ABORT("Malformed vertice exceeds 3 dimensions!\n"); + } + vnc++; + obj_vn[vnc] = NULL; /* trailing NULL pointer */ + /* * VERTEX TEXTURES */ @@ -283,6 +312,9 @@ static bool assemble_obj_arrays(char const * const obj_string, raw_obj->f = obj_f; raw_obj->vt = obj_vt; raw_obj->bez = bez; + raw_obj->vn = obj_vn; + he_obj->vn = NULL; /* will be filled in assemble_HE_stage1() */ + he_obj->vnc = vnc; /* cleanup */ free(string); @@ -314,11 +346,14 @@ static void assemble_HE_stage1(obj_items const * const raw_obj, uint8_t const zpos = 2; int8_t default_color = -1; HE_vert *vertices = he_obj->vertices; + vector *v_normals = NULL; bez_curv *bez_curves = NULL; /* allocator chunks/counts */ const int32_t bez_curves_alloc_chunk = 3; int32_t bez_curves_alloc_c = 0; + const int32_t v_normals_alloc_chunk = 200; + int32_t v_normals_alloc_c = 0; while (raw_obj->v[vc]) { vector *tmp_vec; @@ -351,6 +386,18 @@ static void assemble_HE_stage1(obj_items const * const raw_obj, vc++; } + for (uint32_t i = 0; i < he_obj->vnc; i++) { + MAYBE_REALLOC(v_normals, + sizeof(*v_normals), + (int32_t)i > v_normals_alloc_c - 2, + v_normals_alloc_c, + v_normals_alloc_chunk); + + v_normals[i].x = raw_obj->vn[i][xpos]; + v_normals[i].y = raw_obj->vn[i][ypos]; + v_normals[i].z = raw_obj->vn[i][zpos]; + } + while (raw_obj->bez && raw_obj->bez[bzc]) { uint32_t i = 0; const int32_t bez_vec_alloc_chunk = 5; @@ -382,6 +429,7 @@ static void assemble_HE_stage1(obj_items const * const raw_obj, he_obj->bez_curves = bez_curves; he_obj->bzc = bzc; he_obj->vertices = vertices; + he_obj->vn = v_normals; } /** @@ -612,7 +660,7 @@ HE_obj *parse_obj(char const * const obj_string) /* cleanup */ delete_raw_object(&raw_obj, he_obj->fc, - he_obj->vc, he_obj->vtc, he_obj->bzc); + he_obj->vc, he_obj->vtc, he_obj->bzc, he_obj->vnc); delete_accel_struct(he_obj); free(string); @@ -642,11 +690,14 @@ static void delete_raw_object(obj_items *raw_obj, uint32_t fc, uint32_t vc, uint32_t vtc, - uint32_t bzc) + uint32_t bzc, + uint32_t vnc) { if (!raw_obj) return; + for (uint32_t i = 0; i < vnc; i++) + free(raw_obj->vn[i]); for (uint32_t i = 0; i < bzc; i++) free(raw_obj->bez[i]); for (uint32_t i = 0; i < vtc; i++) @@ -661,6 +712,7 @@ static void delete_raw_object(obj_items *raw_obj, free(raw_obj->f->v); free(raw_obj->f->vt); free(raw_obj->v); + free(raw_obj->vn); free(raw_obj->vt); free(raw_obj->f); }