Implement vertex normals
This commit is contained in:
parent
146223a144
commit
da36cd20da
@ -53,6 +53,7 @@ int yearabs = 365;
|
|||||||
int day;
|
int day;
|
||||||
int dayabs = 30;
|
int dayabs = 30;
|
||||||
HE_obj *obj;
|
HE_obj *obj;
|
||||||
|
bool show_normals = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* static function declaration
|
* 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_1(void);
|
||||||
static void draw_Planet_2(void);
|
static void draw_Planet_2(void);
|
||||||
static void gl_destroy(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,
|
* Call glVertex3f on all of the vertices of the object,
|
||||||
* in appropriate order.
|
* in appropriate order.
|
||||||
@ -99,10 +129,11 @@ static void draw_obj(int32_t const myxrot,
|
|||||||
yrot = 0,
|
yrot = 0,
|
||||||
zrot = 0;
|
zrot = 0;
|
||||||
vector center_vert;
|
vector center_vert;
|
||||||
float scalefactor = get_normalized_scale_factor(obj) * VISIBILITY_FACTOR;
|
|
||||||
|
|
||||||
if (!find_center(obj, ¢er_vert))
|
if (!find_center(obj, ¢er_vert)) {
|
||||||
return; /* TODO: better error handling */
|
fprintf(stderr, "Failed drawing the object!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
xrot += myxrot;
|
xrot += myxrot;
|
||||||
yrot += myyrot;
|
yrot += myyrot;
|
||||||
@ -112,24 +143,28 @@ static void draw_obj(int32_t const myxrot,
|
|||||||
|
|
||||||
/* rotate according to static members */
|
/* rotate according to static members */
|
||||||
glTranslatef(0.0f, 0.0f, SYSTEM_POS_Z);
|
glTranslatef(0.0f, 0.0f, SYSTEM_POS_Z);
|
||||||
glScalef(scalefactor,
|
glScalef(VISIBILITY_FACTOR,
|
||||||
scalefactor,
|
VISIBILITY_FACTOR,
|
||||||
scalefactor);
|
VISIBILITY_FACTOR);
|
||||||
glRotatef(xrot, 1.0f, 0.0f, 0.0f);
|
glRotatef(xrot, 1.0f, 0.0f, 0.0f);
|
||||||
glRotatef(yrot, 0.0f, 1.0f, 0.0f);
|
glRotatef(yrot, 0.0f, 1.0f, 0.0f);
|
||||||
glRotatef(zrot, 0.0f, 0.0f, 1.0f);
|
glRotatef(zrot, 0.0f, 0.0f, 1.0f);
|
||||||
glTranslatef(0.0f, 0.0f, SYSTEM_POS_Z_BACK);
|
glTranslatef(0.0f, 0.0f, SYSTEM_POS_Z_BACK);
|
||||||
|
|
||||||
|
|
||||||
/* pull into middle of universe */
|
/* pull into middle of universe */
|
||||||
glTranslatef(-center_vert.x,
|
glTranslatef(-center_vert.x,
|
||||||
-center_vert.y,
|
-center_vert.y,
|
||||||
-center_vert.z + SYSTEM_POS_Z);
|
-center_vert.z + SYSTEM_POS_Z);
|
||||||
|
|
||||||
|
if (show_normals)
|
||||||
|
draw_normals(obj);
|
||||||
glBegin(GL_POLYGON);
|
glBegin(GL_POLYGON);
|
||||||
glColor3f(0.0f, 1.0f, 0.0f);
|
glColor3f(0.0f, 1.0f, 0.0f);
|
||||||
draw_vertices(obj);
|
draw_vertices(obj);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,6 +473,12 @@ void keyboard(unsigned char key, int x, int y)
|
|||||||
case 'd':
|
case 'd':
|
||||||
glTranslatef(1.0f, 0.0f, 0.0f);
|
glTranslatef(1.0f, 0.0f, 0.0f);
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
if (show_normals)
|
||||||
|
show_normals = false;
|
||||||
|
else
|
||||||
|
show_normals = true;
|
||||||
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
glTranslatef(0.0f, 0.0f, 1.0f);
|
glTranslatef(0.0f, 0.0f, 1.0f);
|
||||||
break;
|
break;
|
||||||
|
146
src/half_edge.c
146
src/half_edge.c
@ -24,6 +24,7 @@
|
|||||||
* @brief operations on half-edge data structs
|
* @brief operations on half-edge data structs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
#include "filereader.h"
|
#include "filereader.h"
|
||||||
#include "half_edge.h"
|
#include "half_edge.h"
|
||||||
@ -36,15 +37,133 @@
|
|||||||
#include <string.h>
|
#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
|
* @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);
|
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
|
* Parse an .obj string and return a HE_obj
|
||||||
* that represents the whole object.
|
* 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);
|
str_tmp_ptr = strtok_r(NULL, "\n", &str_ptr_newline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
faces = (HE_face*) malloc(sizeof(HE_face) * fc);
|
faces = (HE_face*) malloc(sizeof(HE_face) * fc);
|
||||||
CHECK_PTR_VAL(faces);
|
CHECK_PTR_VAL(faces);
|
||||||
edges = (HE_edge*) malloc(sizeof(HE_edge) * ec);
|
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);
|
bool find_center(HE_obj const * const obj, vector *vec);
|
||||||
float get_normalized_scale_factor(HE_obj const * const obj);
|
float get_normalized_scale_factor(HE_obj const * const obj);
|
||||||
|
void normalize_object(HE_obj *obj);
|
||||||
HE_obj *parse_obj(char const * const filename);
|
HE_obj *parse_obj(char const * const filename);
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user