Improve normal calculation
Should now also work on more complex polygons with more than 3 adjacent faces. Also allows us to get the face normals separately.
This commit is contained in:
parent
4dade4ff2c
commit
fe2698470a
@ -506,9 +506,7 @@ void keyboard(unsigned char key, int x, int y)
|
|||||||
*/
|
*/
|
||||||
static void gl_destroy(void)
|
static void gl_destroy(void)
|
||||||
{
|
{
|
||||||
free(obj->edges);
|
delete_object(obj);
|
||||||
free(obj->vertices);
|
|
||||||
free(obj->faces);
|
|
||||||
free(obj);
|
free(obj);
|
||||||
glutDestroyWindow(glutGetWindow());
|
glutDestroyWindow(glutGetWindow());
|
||||||
}
|
}
|
||||||
|
110
src/half_edge.c
110
src/half_edge.c
@ -24,7 +24,6 @@
|
|||||||
* @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"
|
||||||
@ -90,6 +89,43 @@ static HE_edge **get_all_emanating_edges(HE_vert const * const vert,
|
|||||||
return edge_array;
|
return edge_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the normal of a face that corresponds
|
||||||
|
* to edge.
|
||||||
|
*
|
||||||
|
* @param edge to align the normalization
|
||||||
|
* @param vec the vector to store the result in [out]
|
||||||
|
* @return true/false for success/failure
|
||||||
|
*/
|
||||||
|
bool face_normal(HE_edge const * const edge,
|
||||||
|
vector *vec)
|
||||||
|
{
|
||||||
|
vector he_vec1,
|
||||||
|
he_vec2,
|
||||||
|
he_base;
|
||||||
|
|
||||||
|
if (!(copy_vector(edge->next->vert->vec, &he_base)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* calculate vector between vertices */
|
||||||
|
if (!(sub_vectors(edge->next->next->vert->vec, &he_base, &he_vec1)))
|
||||||
|
return false;
|
||||||
|
if (!(sub_vectors(edge->vert->vec, &he_base, &he_vec2)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* vector product */
|
||||||
|
if (!(vector_product(&he_vec1,
|
||||||
|
&he_vec2,
|
||||||
|
vec)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* normalize vector */
|
||||||
|
if (!(normalize_vector(vec, vec)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the approximated normal of a vertex.
|
* Calculate the approximated normal of a vertex.
|
||||||
*
|
*
|
||||||
@ -100,9 +136,7 @@ static HE_edge **get_all_emanating_edges(HE_vert const * const vert,
|
|||||||
bool vec_normal(HE_vert const * const vert, vector *vec)
|
bool vec_normal(HE_vert const * const vert, vector *vec)
|
||||||
{
|
{
|
||||||
HE_edge **edge_array;
|
HE_edge **edge_array;
|
||||||
uint32_t ec,
|
uint32_t ec;
|
||||||
vc = 0,
|
|
||||||
j;
|
|
||||||
vector he_base;
|
vector he_base;
|
||||||
|
|
||||||
if (!vert || !vec)
|
if (!vert || !vec)
|
||||||
@ -112,56 +146,32 @@ bool vec_normal(HE_vert const * const vert, vector *vec)
|
|||||||
if (!(edge_array = get_all_emanating_edges(vert, &ec)))
|
if (!(edge_array = get_all_emanating_edges(vert, &ec)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
copy_vector(edge_array[0]->vert->vec, &he_base);
|
if (!(copy_vector(edge_array[0]->vert->vec, &he_base)))
|
||||||
|
return false;
|
||||||
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;
|
|
||||||
|
|
||||||
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 */
|
/* avoid side effects due to junk data */
|
||||||
if (!(set_null_vector(vec)))
|
if (!(set_null_vector(vec)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* now add all the vectors up */
|
/* iterate over all edges, get the normalized
|
||||||
for (uint32_t i = 0; i < vc; i++)
|
* face vector and add those up */
|
||||||
if (!(add_vectors(vec, &(vec_array[i]), vec)))
|
for (uint32_t i = 0; i < ec; i++) {
|
||||||
|
vector new_vec;
|
||||||
|
|
||||||
|
/* get face normal */
|
||||||
|
if (!(face_normal(edge_array[i], &new_vec)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!(add_vectors(vec, &new_vec, vec)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* normalize the result */
|
/* normalize the result */
|
||||||
if (!(normalize_vector(vec, vec)))
|
if (!(normalize_vector(vec, vec)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
free(edge_array);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,3 +422,17 @@ HE_obj *parse_obj(char const * const obj_string)
|
|||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the inner structures of an object.
|
||||||
|
*
|
||||||
|
* @param obj the object to free
|
||||||
|
*/
|
||||||
|
void delete_object(HE_obj *obj)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < obj->vc; i++)
|
||||||
|
free(obj->vertices[i].vec);
|
||||||
|
free(obj->edges);
|
||||||
|
free(obj->vertices);
|
||||||
|
free(obj->faces);
|
||||||
|
}
|
||||||
|
@ -128,11 +128,14 @@ struct HE_obj {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool face_normal(HE_edge const * const edge,
|
||||||
|
vector *vec);
|
||||||
bool vec_normal(HE_vert const * const vert, vector *vec);
|
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);
|
void normalize_object(HE_obj *obj);
|
||||||
HE_obj *parse_obj(char const * const filename);
|
HE_obj *parse_obj(char const * const filename);
|
||||||
|
void delete_object(HE_obj *obj);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _DROW_ENGINE_HE_OPERATIONS_H */
|
#endif /* _DROW_ENGINE_HE_OPERATIONS_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user