Refactor parse_obj() and move some subroutines to new functions
This commit is contained in:
parent
0ecd0d8e9f
commit
dfd978f714
316
src/half_edge.c
316
src/half_edge.c
@ -62,7 +62,18 @@ static int32_t get_edge_count(FACES const faces);
|
||||
static double **parse_2d_array(char const * const obj_string,
|
||||
char *item);
|
||||
static FACES parse_face_array(char const * const obj_string);
|
||||
|
||||
static void assemble_HE_stage1(VERTICES obj_v,
|
||||
HE_vert *vertices,
|
||||
int32_t *vc);
|
||||
static void assemble_HE_stage2(FACES obj_f,
|
||||
HE_vert *vertices,
|
||||
HE_face *faces,
|
||||
HE_edge *edges,
|
||||
int32_t *fc,
|
||||
int32_t *ec);
|
||||
static void assemble_HE_stage3(HE_edge *edges,
|
||||
int32_t *ec,
|
||||
int32_t *dec);
|
||||
|
||||
/**
|
||||
* Get all edges that emanate from vertice and return a pointer
|
||||
@ -274,8 +285,28 @@ static FACES parse_face_array(char const * const obj_string)
|
||||
return arr;
|
||||
}
|
||||
|
||||
static void fill_vertices(VERTICES obj_v, HE_vert *vertices, int32_t *vc)
|
||||
/**
|
||||
* First stage of assembling the half-edge data structure.
|
||||
* Here we allocate vertices and fill their coordinates
|
||||
* with the information we have from parsing the obj file.
|
||||
* All other yet unknown members such as edge are set to
|
||||
* NULL. This function isn't really modular, but makes
|
||||
* reading parse_obj() a bit less painful.
|
||||
*
|
||||
* @param obj_v the vertices in the raw form after they are
|
||||
* parsed from the obj file
|
||||
* @param vertices pointer the actual half-edge vertices
|
||||
* @param vc pointer to the vertice count
|
||||
*/
|
||||
static void assemble_HE_stage1(VERTICES obj_v,
|
||||
HE_vert *vertices,
|
||||
int32_t *vc)
|
||||
{
|
||||
uint8_t const xpos = 1;
|
||||
uint8_t const ypos = 2;
|
||||
uint8_t const zpos = 3;
|
||||
int8_t const default_col = -1;
|
||||
|
||||
*vc = 0;
|
||||
|
||||
while (obj_v[*vc]) {
|
||||
@ -288,9 +319,9 @@ static void fill_vertices(VERTICES obj_v, HE_vert *vertices, int32_t *vc)
|
||||
tmp_vec = malloc(sizeof(vector));
|
||||
CHECK_PTR_VAL(tmp_vec);
|
||||
|
||||
tmp_vec->x = obj_v[*vc][1];
|
||||
tmp_vec->y = obj_v[*vc][2];
|
||||
tmp_vec->z = obj_v[*vc][3];
|
||||
tmp_vec->x = obj_v[*vc][xpos];
|
||||
tmp_vec->y = obj_v[*vc][ypos];
|
||||
tmp_vec->z = obj_v[*vc][zpos];
|
||||
|
||||
vertices[*vc].vec = tmp_vec;
|
||||
|
||||
@ -302,14 +333,160 @@ static void fill_vertices(VERTICES obj_v, HE_vert *vertices, int32_t *vc)
|
||||
|
||||
/* allocate color struct and set preliminary colors */
|
||||
vertices[*vc].col = malloc(sizeof(color));
|
||||
vertices[*vc].col->red = -1;
|
||||
vertices[*vc].col->green = -1;
|
||||
vertices[*vc].col->blue = -1;
|
||||
vertices[*vc].col->red = default_col;
|
||||
vertices[*vc].col->green = default_col;
|
||||
vertices[*vc].col->blue = default_col;
|
||||
|
||||
(*vc)++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Second stage of assembling the half-edge data structure.
|
||||
* Here we start creating the HE_edges and HE_faces and also
|
||||
* fill some missing information to the HE_verts along with it.
|
||||
* The edge pairs are still unknown, as well as some other
|
||||
* acceleration-structure related members like vertice->dummys.
|
||||
* This function isn't really modular, but makes
|
||||
* reading parse_obj() a bit less painful.
|
||||
*
|
||||
* @param obj_f the raw faces as they are after parsing the obj file
|
||||
* @param vertices the half-edge vertices
|
||||
* @param faces the half-edge faces
|
||||
* @param edges the half-edge edges
|
||||
* @param fc the count of half-edge faces
|
||||
* @param ec the count of half-edge edges
|
||||
*/
|
||||
static void assemble_HE_stage2(FACES obj_f,
|
||||
HE_vert *vertices,
|
||||
HE_face *faces,
|
||||
HE_edge *edges,
|
||||
int32_t *fc,
|
||||
int32_t *ec)
|
||||
{
|
||||
*ec = 0;
|
||||
/* create HE_edges and real HE_faces */
|
||||
for (uint32_t i = 0; i < (uint32_t)(*fc); i++) { /* for all faces */
|
||||
|
||||
/* for all vertices of the face */
|
||||
for (uint32_t j = 0; j < (uint32_t)obj_f[i][0]; j++) {
|
||||
uint32_t obj_f_pos = j + 1; /* first pos is reserved for length */
|
||||
uint32_t fv_arr_id =
|
||||
obj_f[i][obj_f_pos] - 1; /* fv_id starts at 1 */
|
||||
|
||||
edges[*ec].vert = &(vertices[fv_arr_id]);
|
||||
edges[*ec].face = &(faces[i]);
|
||||
edges[*ec].pair = NULL; /* preliminary */
|
||||
vertices[fv_arr_id].edge = &(edges[*ec]); /* last one wins */
|
||||
vertices[fv_arr_id].dummys = NULL; /* preliminary */
|
||||
|
||||
/* Skip j == 0 here, so we don't underrun the arrays,
|
||||
* since we always look one edge back. The first edge
|
||||
* element is taken care of below as well. */
|
||||
if (j > 0) {
|
||||
uint32_t *eac = &(edges[*ec].vert->eac);
|
||||
|
||||
/* connect previous edge to current edge */
|
||||
edges[*ec - 1].next = &(edges[*ec]);
|
||||
|
||||
/* Acceleration struct:
|
||||
* add previous edge to edge_array of current vertice */
|
||||
REALLOC(edges[*ec].vert->edge_array,
|
||||
sizeof(HE_edge*) * (*eac + 1));
|
||||
edges[*ec].vert->edge_array[*eac] = &(edges[*ec - 1]);
|
||||
(*eac)++;
|
||||
|
||||
if (obj_f_pos == (uint32_t)obj_f[i][0]) { /* no vertice left */
|
||||
uint32_t *eac;
|
||||
/* connect last edge to first edge */
|
||||
edges[*ec].next = &(edges[*ec - j]);
|
||||
eac = &(edges[*ec].next->vert->eac);
|
||||
|
||||
/* Acceleration struct:
|
||||
* add last edge to edge_array element of first vertice */
|
||||
REALLOC(edges[*ec].next->vert->edge_array,
|
||||
sizeof(HE_edge*) * (*eac + 1));
|
||||
edges[*ec].next->vert->edge_array[*eac] = &(edges[*ec]);
|
||||
(*eac)++;
|
||||
}
|
||||
}
|
||||
|
||||
(*ec)++;
|
||||
}
|
||||
|
||||
faces[i].edge = &(edges[*ec - 1]); /* "last" edge */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Third stage of assembling the half-edge data structure.
|
||||
* Here we find the pairs of edges and also account for the
|
||||
* possibility of border-edges, where we have to set up
|
||||
* dummy edges and connect them properly.
|
||||
*
|
||||
* @param edges the half-edge edges
|
||||
* @param ec the half-edge edges count
|
||||
* @param dec the dummy edges count
|
||||
*/
|
||||
static void assemble_HE_stage3(HE_edge *edges,
|
||||
int32_t *ec,
|
||||
int32_t *dec)
|
||||
{
|
||||
/* find pairs */
|
||||
for (uint32_t i = 0; i < (uint32_t)(*ec); i++) { /* for all edges */
|
||||
uint32_t eac = edges[i].vert->eac;
|
||||
bool pair_found = false;
|
||||
|
||||
for (uint32_t j = 0; j < eac; j++) { /* for all potential pairs */
|
||||
if (edges[i].vert->edge_array[j] &&
|
||||
(edges[i].next->vert ==
|
||||
edges[i].vert->edge_array[j]->vert)) {
|
||||
edges[i].pair = edges[i].vert->edge_array[j];
|
||||
edges[i].vert->edge_array[j] = NULL;
|
||||
|
||||
pair_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* create dummy pair edge if we have a border edge */
|
||||
if (!pair_found) {
|
||||
uint32_t *vert_dc = &(edges[i].next->vert->dc);
|
||||
|
||||
REALLOC(edges[i].next->vert->dummys,
|
||||
sizeof(HE_edge*) * (*vert_dc + 1));
|
||||
|
||||
/* NULL-face indicates border-edge */
|
||||
edges[*ec + *dec].face = NULL;
|
||||
/* we don't know this one yet */
|
||||
edges[*ec + *dec].next = NULL;
|
||||
/* set both pairs */
|
||||
edges[*ec + *dec].pair = &(edges[i]);
|
||||
edges[i].pair = &(edges[*ec + *dec]);
|
||||
/* set vertex */
|
||||
edges[*ec + *dec].vert = edges[i].next->vert;
|
||||
/* add the dummy edge to the dummys array of the vertex */
|
||||
edges[*ec + *dec].vert->dummys[*vert_dc] = &(edges[*ec + *dec]);
|
||||
(*vert_dc)++;
|
||||
|
||||
(*dec)++;
|
||||
}
|
||||
}
|
||||
|
||||
/* now we have to connect the dummy edges together */
|
||||
for (uint32_t i = 0; i < (uint32_t) (*dec); i++) { /* for all dummy edges */
|
||||
/* vertex the dummy edge points to */
|
||||
HE_vert *vert = edges[*ec + i].pair->vert;
|
||||
|
||||
/* iterate over the dummy array */
|
||||
for (uint32_t j = 0; j < vert->dc; j++) {
|
||||
if (vert == vert->dummys[j]->vert)
|
||||
edges[*ec + i].next = vert->dummys[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the normal of a face that corresponds
|
||||
* to edge.
|
||||
@ -507,137 +684,26 @@ HE_obj *parse_obj(char const * const obj_string)
|
||||
/* obj_vt = parse_2d_array(obj_string, "vt"); */
|
||||
obj_f = parse_face_array(string);
|
||||
|
||||
int32_t count = get_row_count((int32_t const**)obj_v);
|
||||
vertices = malloc(sizeof(HE_vert) *
|
||||
count + 1);
|
||||
|
||||
printf("row count %d\n", get_row_count((int32_t const**)obj_v));
|
||||
|
||||
/* fill the vertices */
|
||||
fill_vertices(obj_v, vertices, &vc);
|
||||
|
||||
if ((ec = get_edge_count(obj_f)) == -1)
|
||||
ABORT("Invalid edge count!\n");
|
||||
if ((fc = get_face_count(obj_f)) == -1)
|
||||
ABORT("Invalid face count!\n");
|
||||
|
||||
vertices = malloc(sizeof(HE_vert) *
|
||||
get_row_count((int32_t const**)obj_v) + 1);
|
||||
CHECK_PTR_VAL(vertices);
|
||||
faces = (HE_face*) malloc(sizeof(HE_face) * fc);
|
||||
CHECK_PTR_VAL(faces);
|
||||
/* hold enough space for possible dummy edges */
|
||||
edges = (HE_edge*) malloc(sizeof(HE_edge) * ec * 2);
|
||||
CHECK_PTR_VAL(edges);
|
||||
|
||||
ec = 0;
|
||||
/* create HE_edges and real HE_faces */
|
||||
for (uint32_t i = 0; i < (uint32_t)fc; i++) { /* for all faces */
|
||||
|
||||
/* for all vertices of the face */
|
||||
for (uint32_t j = 0; j < (uint32_t)obj_f[i][0]; j++) {
|
||||
uint32_t obj_f_pos = j + 1; /* first pos is reserved for length */
|
||||
uint32_t fv_arr_id =
|
||||
obj_f[i][obj_f_pos] - 1; /* fv_id starts at 1 */
|
||||
|
||||
edges[ec].vert = &(vertices[fv_arr_id]);
|
||||
edges[ec].face = &(faces[i]);
|
||||
edges[ec].pair = NULL; /* preliminary */
|
||||
vertices[fv_arr_id].edge = &(edges[ec]); /* last one wins */
|
||||
vertices[fv_arr_id].dummys = NULL; /* preliminary */
|
||||
|
||||
/* Skip j == 0 here, so we don't underrun the arrays,
|
||||
* since we always look one edge back. The first edge
|
||||
* element is taken care of below as well. */
|
||||
if (j > 0) {
|
||||
uint32_t *eac = &(edges[ec].vert->eac);
|
||||
|
||||
/* connect previous edge to current edge */
|
||||
edges[ec - 1].next = &(edges[ec]);
|
||||
|
||||
/* Acceleration struct:
|
||||
* add previous edge to edge_array of current vertice */
|
||||
REALLOC(edges[ec].vert->edge_array,
|
||||
sizeof(HE_edge*) * (*eac + 1));
|
||||
edges[ec].vert->edge_array[*eac] = &(edges[ec - 1]);
|
||||
(*eac)++;
|
||||
|
||||
if (obj_f_pos == (uint32_t)obj_f[i][0]) { /* no vertice left */
|
||||
uint32_t *eac;
|
||||
/* connect last edge to first edge */
|
||||
edges[ec].next = &(edges[ec - j]);
|
||||
eac = &(edges[ec].next->vert->eac);
|
||||
|
||||
/* Acceleration struct:
|
||||
* add last edge to edge_array element of first vertice */
|
||||
REALLOC(edges[ec].next->vert->edge_array,
|
||||
sizeof(HE_edge*) * (*eac + 1));
|
||||
edges[ec].next->vert->edge_array[*eac] = &(edges[ec]);
|
||||
(*eac)++;
|
||||
}
|
||||
}
|
||||
|
||||
ec++;
|
||||
}
|
||||
|
||||
faces[i].edge = &(edges[ec - 1]); /* "last" edge */
|
||||
}
|
||||
|
||||
/* find pairs */
|
||||
for (uint32_t i = 0; i < (uint32_t)ec; i++) { /* for all edges */
|
||||
uint32_t eac = edges[i].vert->eac;
|
||||
bool pair_found = false;
|
||||
|
||||
for (uint32_t j = 0; j < eac; j++) { /* for all potential pairs */
|
||||
if (edges[i].vert->edge_array[j] &&
|
||||
(edges[i].next->vert ==
|
||||
edges[i].vert->edge_array[j]->vert)) {
|
||||
edges[i].pair = edges[i].vert->edge_array[j];
|
||||
edges[i].vert->edge_array[j] = NULL;
|
||||
|
||||
pair_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* create dummy pair edge if we have a border edge */
|
||||
if (!pair_found) {
|
||||
uint32_t *vert_dc = &(edges[i].next->vert->dc);
|
||||
|
||||
REALLOC(edges[i].next->vert->dummys,
|
||||
sizeof(HE_edge*) * (*vert_dc + 1));
|
||||
|
||||
/* NULL-face indicates border-edge */
|
||||
edges[ec + dec].face = NULL;
|
||||
/* we don't know this one yet */
|
||||
edges[ec + dec].next = NULL;
|
||||
/* set both pairs */
|
||||
edges[ec + dec].pair = &(edges[i]);
|
||||
edges[i].pair = &(edges[ec + dec]);
|
||||
/* set vertex */
|
||||
edges[ec + dec].vert = edges[i].next->vert;
|
||||
/* add the dummy edge to the dummys array of the vertex */
|
||||
edges[ec + dec].vert->dummys[*vert_dc] = &(edges[ec + dec]);
|
||||
(*vert_dc)++;
|
||||
|
||||
dec++;
|
||||
}
|
||||
}
|
||||
|
||||
/* now we have to connect the dummy edges together */
|
||||
for (uint32_t i = 0; i < (uint32_t) dec; i++) { /* for all dummy edges */
|
||||
/* vertex the dummy edge points to */
|
||||
HE_vert *vert = edges[ec + i].pair->vert;
|
||||
|
||||
/* iterate over the dummy array */
|
||||
for (uint32_t j = 0; j < vert->dc; j++) {
|
||||
if (vert == vert->dummys[j]->vert)
|
||||
edges[ec + i].next = vert->dummys[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
assemble_HE_stage1(obj_v, vertices, &vc);
|
||||
assemble_HE_stage2(obj_f, vertices, faces, edges, &fc, &ec);
|
||||
assemble_HE_stage3(edges, &ec, &dec);
|
||||
|
||||
obj = (HE_obj*) malloc(sizeof(HE_obj));
|
||||
CHECK_PTR_VAL(obj);
|
||||
|
||||
obj->edges = edges;
|
||||
obj->vertices = vertices;
|
||||
obj->faces = faces;
|
||||
|
@ -93,7 +93,7 @@ void print_faces(HE_obj *obj)
|
||||
* Print all plain unconverted faces
|
||||
* as they are saved in the .obj file.
|
||||
*
|
||||
* @param face the plain face struct
|
||||
* @param faces the plain faces
|
||||
* @param fc the count of faces
|
||||
*/
|
||||
void print_plain_faces(FACES faces, uint32_t fc)
|
||||
|
Loading…
Reference in New Issue
Block a user