Implement vertex normals
This commit is contained in:
parent
146223a144
commit
da36cd20da
@ -53,6 +53,7 @@ int yearabs = 365;
|
||||
int day;
|
||||
int dayabs = 30;
|
||||
HE_obj *obj;
|
||||
bool show_normals = false;
|
||||
|
||||
/*
|
||||
* static function declaration
|
||||
@ -63,8 +64,37 @@ static void draw_obj(int32_t const myxrot,
|
||||
static void draw_Planet_1(void);
|
||||
static void draw_Planet_2(void);
|
||||
static void gl_destroy(void);
|
||||
static void draw_normals(HE_obj const * const obj);
|
||||
|
||||
|
||||
static void draw_normals(HE_obj const * const obj)
|
||||
{
|
||||
vector vec;
|
||||
|
||||
for (uint32_t i = 0; i < obj->vc; i++) {
|
||||
if ((vec_normal(&(obj->vertices[i]), &vec))) {
|
||||
glPushMatrix();
|
||||
|
||||
glLineWidth(3);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(obj->vertices[i].vec->x,
|
||||
obj->vertices[i].vec->y,
|
||||
obj->vertices[i].vec->z);
|
||||
glVertex3f(obj->vertices[i].vec->x + (vec.x),
|
||||
obj->vertices[i].vec->y + (vec.y),
|
||||
obj->vertices[i].vec->z + (vec.z));
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
} else {
|
||||
fprintf(stderr, "Failed drawing the normals!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call glVertex3f on all of the vertices of the object,
|
||||
* in appropriate order.
|
||||
@ -99,10 +129,11 @@ static void draw_obj(int32_t const myxrot,
|
||||
yrot = 0,
|
||||
zrot = 0;
|
||||
vector center_vert;
|
||||
float scalefactor = get_normalized_scale_factor(obj) * VISIBILITY_FACTOR;
|
||||
|
||||
if (!find_center(obj, ¢er_vert))
|
||||
return; /* TODO: better error handling */
|
||||
if (!find_center(obj, ¢er_vert)) {
|
||||
fprintf(stderr, "Failed drawing the object!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
xrot += myxrot;
|
||||
yrot += myyrot;
|
||||
@ -112,24 +143,28 @@ static void draw_obj(int32_t const myxrot,
|
||||
|
||||
/* rotate according to static members */
|
||||
glTranslatef(0.0f, 0.0f, SYSTEM_POS_Z);
|
||||
glScalef(scalefactor,
|
||||
scalefactor,
|
||||
scalefactor);
|
||||
glScalef(VISIBILITY_FACTOR,
|
||||
VISIBILITY_FACTOR,
|
||||
VISIBILITY_FACTOR);
|
||||
glRotatef(xrot, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef(yrot, 0.0f, 1.0f, 0.0f);
|
||||
glRotatef(zrot, 0.0f, 0.0f, 1.0f);
|
||||
glTranslatef(0.0f, 0.0f, SYSTEM_POS_Z_BACK);
|
||||
|
||||
|
||||
/* pull into middle of universe */
|
||||
glTranslatef(-center_vert.x,
|
||||
-center_vert.y,
|
||||
-center_vert.z + SYSTEM_POS_Z);
|
||||
|
||||
if (show_normals)
|
||||
draw_normals(obj);
|
||||
glBegin(GL_POLYGON);
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
draw_vertices(obj);
|
||||
glEnd();
|
||||
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
@ -438,6 +473,12 @@ void keyboard(unsigned char key, int x, int y)
|
||||
case 'd':
|
||||
glTranslatef(1.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
case 'n':
|
||||
if (show_normals)
|
||||
show_normals = false;
|
||||
else
|
||||
show_normals = true;
|
||||
break;
|
||||
case '+':
|
||||
glTranslatef(0.0f, 0.0f, 1.0f);
|
||||
break;
|
||||
|
146
src/half_edge.c
146
src/half_edge.c
@ -24,6 +24,7 @@
|
||||
* @brief operations on half-edge data structs
|
||||
*/
|
||||
|
||||
|
||||
#include "err.h"
|
||||
#include "filereader.h"
|
||||
#include "half_edge.h"
|
||||
@ -36,15 +37,133 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
* static declarations
|
||||
*/
|
||||
static HE_edge **get_all_emanating_edges(HE_vert const * const vert,
|
||||
uint32_t *ec_out);
|
||||
|
||||
|
||||
/**
|
||||
* Get all edges that emanate from vertice.
|
||||
* Get all edges that emanate from vertice and return a pointer
|
||||
* to that array with the size of ec_out.
|
||||
*
|
||||
* @param vertice the vertice to get the emanating edges of
|
||||
* @return pointer to a NULL-terminated array of half-edges
|
||||
* @param ec the edge counter is saved here [out]
|
||||
* @return pointer to an array of half-edges, size ec_out
|
||||
*/
|
||||
HE_edge **get_all_emanating_edges(HE_vert *vertice)
|
||||
static HE_edge **get_all_emanating_edges(HE_vert const * const vert,
|
||||
uint32_t *ec_out)
|
||||
{
|
||||
return NULL;
|
||||
uint32_t ec = 0, /* edge count */
|
||||
rc = 0; /* realloc count */
|
||||
uint32_t const approx_ec = 20; /* allocation chunk */
|
||||
HE_edge **edge_array = malloc(sizeof(HE_edge*) * approx_ec);
|
||||
HE_edge **tmp_ptr;
|
||||
|
||||
if (!vert)
|
||||
return NULL;
|
||||
|
||||
HE_edge *edge = vert->edge;
|
||||
|
||||
/* build an array of emanating edges */
|
||||
do {
|
||||
edge_array[ec] = edge;
|
||||
|
||||
edge = edge->pair->next;
|
||||
ec++;
|
||||
|
||||
/* allocate more chunks */
|
||||
if (ec >= approx_ec) {
|
||||
tmp_ptr = realloc(edge_array, sizeof(HE_edge*)
|
||||
* approx_ec * (rc + 2));
|
||||
CHECK_PTR_VAL(tmp_ptr);
|
||||
edge_array = tmp_ptr;
|
||||
rc++;
|
||||
}
|
||||
|
||||
} while (edge != vert->edge);
|
||||
|
||||
/* this is the real size, not the x[ec] value */
|
||||
*ec_out = ec;
|
||||
|
||||
return edge_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the approximated normal of a vertex.
|
||||
*
|
||||
* @param vert the vertex
|
||||
* @param vec the vector to store the result in [out]
|
||||
* @return true/false for success/failure
|
||||
*/
|
||||
bool vec_normal(HE_vert const * const vert, vector *vec)
|
||||
{
|
||||
HE_edge **edge_array;
|
||||
uint32_t ec,
|
||||
vc = 0,
|
||||
j;
|
||||
vector he_base;
|
||||
|
||||
if (!vert || !vec)
|
||||
return false;
|
||||
|
||||
/* get all emanating edges */
|
||||
if (!(edge_array = get_all_emanating_edges(vert, &ec)))
|
||||
return false;
|
||||
|
||||
copy_vector(edge_array[0]->vert->vec, &he_base);
|
||||
|
||||
vector vec_array[ec];
|
||||
|
||||
/* iterate over all unique(!)
|
||||
* tuples and calculate their product */
|
||||
for (uint32_t i = 0; i < ec; i++) {
|
||||
j = (i + 1) % ec;
|
||||
|
||||
/* printf("\nTUPLE %d\n", vc + 1); */
|
||||
vector he_vec1,
|
||||
he_vec2,
|
||||
new_vec;
|
||||
|
||||
copy_vector(edge_array[i]->next->vert->vec, &he_vec1);
|
||||
copy_vector(edge_array[j]->next->vert->vec, &he_vec2);
|
||||
|
||||
if (!(set_null_vector(&new_vec)))
|
||||
return false;
|
||||
|
||||
/* calculate vector between vertices */
|
||||
sub_vectors(&he_vec1, &he_base, &he_vec1);
|
||||
sub_vectors(&he_vec2, &he_base, &he_vec2);
|
||||
|
||||
/* calculate vector product */
|
||||
if (!(vector_product(&he_vec2, &he_vec1, &new_vec)))
|
||||
/* if (!(vector_product(&he_vec1, &he_vec2, &new_vec))) */
|
||||
return false;
|
||||
|
||||
/* normalize vector */
|
||||
if (!(normalize_vector(&new_vec, &new_vec)))
|
||||
return false;
|
||||
|
||||
/* save into array */
|
||||
copy_vector(&new_vec, &(vec_array[vc]));
|
||||
vc++;
|
||||
}
|
||||
|
||||
/* avoid side effects due to junk data */
|
||||
if (!(set_null_vector(vec)))
|
||||
return false;
|
||||
|
||||
/* now add all the vectors up */
|
||||
for (uint32_t i = 0; i < vc; i++)
|
||||
if (!(add_vectors(vec, &(vec_array[i]), vec)))
|
||||
return false;
|
||||
|
||||
/* normalize the result */
|
||||
if (!(normalize_vector(vec, vec)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,6 +237,24 @@ float get_normalized_scale_factor(HE_obj const * const obj)
|
||||
return 1 / (max - min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales down the object to the size of 1. The parameter
|
||||
* is modified!
|
||||
*
|
||||
* @param obj the object we want to scale [mod]
|
||||
*/
|
||||
void normalize_object(HE_obj *obj)
|
||||
{
|
||||
float scale_factor;
|
||||
scale_factor = get_normalized_scale_factor(obj);
|
||||
|
||||
for (uint32_t i = 0; i < obj->vc; i++) {
|
||||
obj->vertices[i].vec->x = obj->vertices[i].vec->x * scale_factor;
|
||||
obj->vertices[i].vec->y = obj->vertices[i].vec->y * scale_factor;
|
||||
obj->vertices[i].vec->z = obj->vertices[i].vec->z * scale_factor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an .obj string and return a HE_obj
|
||||
* that represents the whole object.
|
||||
@ -219,7 +356,6 @@ HE_obj *parse_obj(char const * const obj_string)
|
||||
str_tmp_ptr = strtok_r(NULL, "\n", &str_ptr_newline);
|
||||
}
|
||||
|
||||
|
||||
faces = (HE_face*) malloc(sizeof(HE_face) * fc);
|
||||
CHECK_PTR_VAL(faces);
|
||||
edges = (HE_edge*) malloc(sizeof(HE_edge) * ec);
|
||||
|
@ -128,9 +128,10 @@ struct HE_obj {
|
||||
};
|
||||
|
||||
|
||||
HE_edge **get_all_emanating_edges(HE_vert *vertice);
|
||||
bool vec_normal(HE_vert const * const vert, vector *vec);
|
||||
bool find_center(HE_obj const * const obj, vector *vec);
|
||||
float get_normalized_scale_factor(HE_obj const * const obj);
|
||||
void normalize_object(HE_obj *obj);
|
||||
HE_obj *parse_obj(char const * const filename);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user