star-enclosures-3d

Extract enclosures from 3D geometry
git clone git://git.meso-star.fr/star-enclosures-3d.git
Log | Files | Refs | README | LICENSE

commit 3a39415e7b52f5803263478aebe14334d6ada621
parent e4b7efbbd5d1578ca4ffac48b197e13699bccb5e
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue,  6 Mar 2018 17:32:49 +0100

Better lifetime management for some thread related data structures.

Diffstat:
Msrc/senc_scene_analyze.c | 563++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 282 insertions(+), 281 deletions(-)

diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c @@ -149,7 +149,6 @@ extract_connex_components const struct senc_scene* scn; struct mem_allocator* alloc; ATOMIC component_count = 0; - int stack_initialised = 0; int mm; #ifndef NDEBUG trg_id_t t; @@ -179,226 +178,223 @@ extract_connex_components } #endif - #pragma omp parallel for firstprivate(stack_initialised) schedule(dynamic) - for(mm = 0; mm < scn->nmeds; mm++) { /* Process all media */ - const medium_id_t m = (medium_id_t)mm; - struct cc_descriptor* cc; + #pragma omp parallel + { struct darray_side_id stack; - /* Any not-already-used side is used as a starting point */ - side_id_t first_side_not_in_component; - if(res != RES_OK) continue; - first_side_not_in_component - = darray_side_range_cdata_get(&scn->media_use)[m].first; - if(first_side_not_in_component == SIDE_NULL__) - continue; /* Unused medium */ - ASSERT(first_side_not_in_component < 2 * scn->nutris); - if(!stack_initialised) { - stack_initialised = 1; - darray_side_id_init(alloc, &stack); - } - ASSERT(darray_side_id_size_get(&stack) == 0); - for(;;) { /* Process all components for this medium */ - const side_id_t start_side_id = get_side_not_in_connex_component(scn, - trgsides, &first_side_not_in_component, m); - side_id_t crt_side_id = start_side_id; - side_id_t last_side_id = start_side_id; - ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nutris); - if(start_side_id == SIDE_NULL__) { /* start_side_id=SIDE_NULL__ => done! */ - if(stack_initialised) { - stack_initialised = 0; /* TODO: don't recreate stack for same thread */ - darray_side_id_release(&stack); - } - break; - } - ASSERT(trgsides[start_side_id].list_id == FLAG_LIST_SIDE_LIST); + darray_side_id_init(alloc, &stack); + + #pragma omp for schedule(dynamic) + for(mm = 0; mm < scn->nmeds; mm++) { /* Process all media */ + const medium_id_t m = (medium_id_t)mm; + struct cc_descriptor* cc; + /* Any not-already-used side is used as a starting point */ + side_id_t first_side_not_in_component; + if(res != RES_OK) continue; + first_side_not_in_component + = darray_side_range_cdata_get(&scn->media_use)[m].first; + if(first_side_not_in_component == SIDE_NULL__) + continue; /* Unused medium */ + ASSERT(first_side_not_in_component < 2 * scn->nutris); + ASSERT(darray_side_id_size_get(&stack) == 0); + for(;;) { /* Process all components for this medium */ + const side_id_t start_side_id = get_side_not_in_connex_component(scn, + trgsides, &first_side_not_in_component, m); + side_id_t crt_side_id = start_side_id; + side_id_t last_side_id = start_side_id; + ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nutris); + if(start_side_id == SIDE_NULL__) /* start_side_id=SIDE_NULL__ => done! */ + break; + ASSERT(trgsides[start_side_id].list_id == FLAG_LIST_SIDE_LIST); #ifndef NDEBUG - { - trg_id_t tid = TRGSIDE_2_TRG(start_side_id); - enum side_flag s = TRGSIDE_2_SIDE(start_side_id); - medium_id_t side_med = darray_triangle_in_data_get(&desc->scene->triangles_in)[tid].medium[s]; - ASSERT(side_med == m); - } + { + trg_id_t tid = TRGSIDE_2_TRG(start_side_id); + enum side_flag s = TRGSIDE_2_SIDE(start_side_id); + medium_id_t side_med = darray_triangle_in_data_get(&desc->scene->triangles_in)[tid].medium[s]; + ASSERT(side_med == m); + } #endif - /* Create and init a new component */ - cc = MEM_ALLOC(alloc, sizeof(struct cc_descriptor)); - if(!cc) { - res = RES_MEM_ERR; - goto error; - } - cc_descriptor_init(alloc, cc); - ASSERT(m == trgsides[start_side_id].medium); - cc->cc_id = (component_id_t)(ATOMIC_INCR(&component_count) - 1); - cc->medium = m; - cc->side_range.first = start_side_id; - - for(;;) { /* Process all sides of this component */ - int i; - enum side_flag crt_side_flag = TRGSIDE_2_SIDE(crt_side_id); - struct trgside* crt_side = trgsides + crt_side_id; - const trg_id_t crt_trg_id = TRGSIDE_2_TRG(crt_side_id); - const struct triangle_in* trg_in = - darray_triangle_in_cdata_get(&scn->triangles_in) + crt_trg_id; - struct triangle_comp* trg_comp = - darray_triangle_comp_data_get(triangles_comp) + crt_trg_id; - const struct triangle_tmp* const trg_tmp = - darray_triangle_tmp_cdata_get(triangles_tmp_array) + crt_trg_id; - const union double3* vertices = - darray_position_cdata_get(&scn->vertices); - ASSERT(crt_trg_id < scn->nutris); - ASSERT(trgsides[crt_side_id].medium == m); - - /* Record Zmax information - * Keep track of the appropriate vertex/side of the connex component - * in order to cast a ray at the component grouping step of the - * algorithm. - * The most appropriate vertex is (the) one with the greater Z - * coordinate. - * If more than one vertex/side has the same Z, we want the side that - * most faces Z (that is the one with the greater nz). - * This is mandatory to select the correct side when both sides of a - * triangle are candidate. */ - if(cc->max_vrtx[2] <= trg_tmp->max_z) { - /* Can either improve z or nz */ - - if(cc->max_z_side_id == TRGSIDE_OPPOSITE(crt_side_id)) { - /* Both sides are in cc and the opposite side is currently selected - * Just keep the side with nz>0 */ - if(cc->max_z_nz < 0) { - /* Change side! */ - cc->max_z_nz = -cc->max_z_nz; - cc->max_z_side_id = crt_side_id; - } - } else { - double edge0[3], edge1[3], normal[3], norm, side_nz; - int process = 0; - - d3_sub(edge0, vertices[trg_in->vertice_id[1]].vec, - vertices[trg_in->vertice_id[0]].vec); - d3_sub(edge1, vertices[trg_in->vertice_id[2]].vec, - vertices[trg_in->vertice_id[0]].vec); - d3_cross(normal, edge0, edge1); - norm = d3_normalize(normal, normal); - ASSERT(norm); (void) norm; - - if(TRGSIDE_IS_FRONT(crt_side_id)) { - side_nz = normal[2]; - process = 1; + /* Create and init a new component */ + cc = MEM_ALLOC(alloc, sizeof(struct cc_descriptor)); + if(!cc) { + res = RES_MEM_ERR; + goto error; + } + cc_descriptor_init(alloc, cc); + ASSERT(m == trgsides[start_side_id].medium); + cc->cc_id = (component_id_t)(ATOMIC_INCR(&component_count) - 1); + cc->medium = m; + cc->side_range.first = start_side_id; + + for(;;) { /* Process all sides of this component */ + int i; + enum side_flag crt_side_flag = TRGSIDE_2_SIDE(crt_side_id); + struct trgside* crt_side = trgsides + crt_side_id; + const trg_id_t crt_trg_id = TRGSIDE_2_TRG(crt_side_id); + const struct triangle_in* trg_in = + darray_triangle_in_cdata_get(&scn->triangles_in) + crt_trg_id; + struct triangle_comp* trg_comp = + darray_triangle_comp_data_get(triangles_comp) + crt_trg_id; + const struct triangle_tmp* const trg_tmp = + darray_triangle_tmp_cdata_get(triangles_tmp_array) + crt_trg_id; + const union double3* vertices = + darray_position_cdata_get(&scn->vertices); + ASSERT(crt_trg_id < scn->nutris); + ASSERT(trgsides[crt_side_id].medium == m); + + /* Record Zmax information + * Keep track of the appropriate vertex/side of the connex component + * in order to cast a ray at the component grouping step of the + * algorithm. + * The most appropriate vertex is (the) one with the greater Z + * coordinate. + * If more than one vertex/side has the same Z, we want the side that + * most faces Z (that is the one with the greater nz). + * This is mandatory to select the correct side when both sides of a + * triangle are candidate. */ + if(cc->max_vrtx[2] <= trg_tmp->max_z) { + /* Can either improve z or nz */ + + if(cc->max_z_side_id == TRGSIDE_OPPOSITE(crt_side_id)) { + /* Both sides are in cc and the opposite side is currently selected + * Just keep the side with nz>0 */ + if(cc->max_z_nz < 0) { + /* Change side! */ + cc->max_z_nz = -cc->max_z_nz; + cc->max_z_side_id = crt_side_id; + } } else { - side_nz = -normal[2]; - process = 1; - } - - if(process) { - int change = 0; - if(cc->max_vrtx[2] < trg_tmp->max_z) { - change = 1; /* Try first to improve z */ - } else if (cc->max_z_nz <= 0 && fabs(cc->max_z_nz) < fabs(side_nz)) { - change = 1; /* If nz <= 0, the more negative the better */ - } else if (cc->max_z_nz > 0 && cc->max_z_nz < side_nz) { - change = 1; /* If nz > 0, the more positive the better */ + double edge0[3], edge1[3], normal[3], norm, side_nz; + int process = 0; + + d3_sub(edge0, vertices[trg_in->vertice_id[1]].vec, + vertices[trg_in->vertice_id[0]].vec); + d3_sub(edge1, vertices[trg_in->vertice_id[2]].vec, + vertices[trg_in->vertice_id[0]].vec); + d3_cross(normal, edge0, edge1); + norm = d3_normalize(normal, normal); + ASSERT(norm); (void) norm; + + if(TRGSIDE_IS_FRONT(crt_side_id)) { + side_nz = normal[2]; + process = 1; + } else { + side_nz = -normal[2]; + process = 1; } - if(change) { - cc->max_z_nz = side_nz; - cc->max_z_side_id = crt_side_id; - ASSERT(trg_tmp->max_z_vrtx_id < 3); - ASSERT(trg_in->vertice_id[trg_tmp->max_z_vrtx_id] < scn->nverts); - cc->max_z_vrtx_id = trg_in->vertice_id[trg_tmp->max_z_vrtx_id]; - ASSERT(trg_tmp->max_z == vertices[cc->max_z_vrtx_id].pos.z); - d3_set(cc->max_vrtx, vertices[cc->max_z_vrtx_id].vec); + if(process) { + int change = 0; + if(cc->max_vrtx[2] < trg_tmp->max_z) { + change = 1; /* Try first to improve z */ + } else if(cc->max_z_nz <= 0 && fabs(cc->max_z_nz) < fabs(side_nz)) { + change = 1; /* If nz <= 0, the more negative the better */ + } else if(cc->max_z_nz > 0 && cc->max_z_nz < side_nz) { + change = 1; /* If nz > 0, the more positive the better */ + } + + if(change) { + cc->max_z_nz = side_nz; + cc->max_z_side_id = crt_side_id; + ASSERT(trg_tmp->max_z_vrtx_id < 3); + ASSERT(trg_in->vertice_id[trg_tmp->max_z_vrtx_id] < scn->nverts); + cc->max_z_vrtx_id = trg_in->vertice_id[trg_tmp->max_z_vrtx_id]; + ASSERT(trg_tmp->max_z == vertices[cc->max_z_vrtx_id].pos.z); + d3_set(cc->max_vrtx, vertices[cc->max_z_vrtx_id].vec); + } } } } - } - /* Record crt_side both as component and triangle level */ - cc->side_count++; - trgsides[crt_side_id].list_id = FLAG_LIST_COMPONENT; - ASSERT(trg_comp->component[crt_side_flag] == COMPONENT_NULL__); - trg_comp->component[crt_side_flag] = cc->cc_id; + /* Record crt_side both as component and triangle level */ + cc->side_count++; + trgsides[crt_side_id].list_id = FLAG_LIST_COMPONENT; + ASSERT(trg_comp->component[crt_side_flag] == COMPONENT_NULL__); + trg_comp->component[crt_side_flag] = cc->cc_id; #ifndef NDEBUG - crt_side->member_of_cc = cc->cc_id; + crt_side->member_of_cc = cc->cc_id; #endif - /* Store neighbour sides in a waiting stack */ - FOR_EACH(i, 0, 3) { - side_id_t neighbour_id = crt_side->facing_side_id[i]; - trg_id_t nbour_trg_id = TRGSIDE_2_TRG(neighbour_id); - const struct trgside* neighbour = trgsides + neighbour_id; - CHK(m == crt_side->medium); - if(neighbour->medium != crt_side->medium) { - /* Found medium discontinuity! Model topology is broken. */ - const struct triangle_in* triangles_in - = darray_triangle_in_cdata_get(&scn->triangles_in); - const union double3* positions - = darray_position_cdata_get(&scn->vertices); - log_err(scn->dev, - "Medium mismatch found between neighbour triangles %lu %s" - " side and %u %s side.\n", - (unsigned long)triangles_in[crt_trg_id].global_id, - TRGSIDE_IS_FRONT(crt_side_id) ? "front" : "back", - triangles_in[nbour_trg_id].global_id, - TRGSIDE_IS_FRONT(neighbour_id) ? "front" : "back"); - log_err(scn->dev, - "Triangle %lu:\n (%g %g %g)\n (%g %g %g)\n (%g %g %g)\n", - (unsigned long)triangles_in[crt_trg_id].global_id, - SPLIT3(positions[triangles_in[crt_trg_id].vertice_id[0]].vec), - SPLIT3(positions[triangles_in[crt_trg_id].vertice_id[1]].vec), - SPLIT3(positions[triangles_in[crt_trg_id].vertice_id[2]].vec)); - log_err(scn->dev, - "Triangle %lu:\n (%g %g %g)\n (%g %g %g)\n (%g %g %g)\n", - (unsigned long)triangles_in[nbour_trg_id].global_id, - SPLIT3(positions[triangles_in[nbour_trg_id].vertice_id[0]].vec), - SPLIT3(positions[triangles_in[nbour_trg_id].vertice_id[1]].vec), - SPLIT3(positions[triangles_in[nbour_trg_id].vertice_id[2]].vec)); - log_err(desc->scene->dev, "Media: %lu VS %lu\n", - (unsigned long)neighbour->medium, (unsigned long)crt_side->medium); - res = RES_BAD_ARG; - goto error; - } - if(neighbour->list_id == FLAG_LIST_COMPONENT) { - /* Already processed */ + /* Store neighbour sides in a waiting stack */ + FOR_EACH(i, 0, 3) { + side_id_t neighbour_id = crt_side->facing_side_id[i]; + trg_id_t nbour_trg_id = TRGSIDE_2_TRG(neighbour_id); + const struct trgside* neighbour = trgsides + neighbour_id; + CHK(m == crt_side->medium); + if(neighbour->medium != crt_side->medium) { + /* Found medium discontinuity! Model topology is broken. */ + const struct triangle_in* triangles_in + = darray_triangle_in_cdata_get(&scn->triangles_in); + const union double3* positions + = darray_position_cdata_get(&scn->vertices); + log_err(scn->dev, + "Medium mismatch found between neighbour triangles %lu %s" + " side and %u %s side.\n", + (unsigned long)triangles_in[crt_trg_id].global_id, + TRGSIDE_IS_FRONT(crt_side_id) ? "front" : "back", + triangles_in[nbour_trg_id].global_id, + TRGSIDE_IS_FRONT(neighbour_id) ? "front" : "back"); + log_err(scn->dev, + "Triangle %lu:\n (%g %g %g)\n (%g %g %g)\n (%g %g %g)\n", + (unsigned long)triangles_in[crt_trg_id].global_id, + SPLIT3(positions[triangles_in[crt_trg_id].vertice_id[0]].vec), + SPLIT3(positions[triangles_in[crt_trg_id].vertice_id[1]].vec), + SPLIT3(positions[triangles_in[crt_trg_id].vertice_id[2]].vec)); + log_err(scn->dev, + "Triangle %lu:\n (%g %g %g)\n (%g %g %g)\n (%g %g %g)\n", + (unsigned long)triangles_in[nbour_trg_id].global_id, + SPLIT3(positions[triangles_in[nbour_trg_id].vertice_id[0]].vec), + SPLIT3(positions[triangles_in[nbour_trg_id].vertice_id[1]].vec), + SPLIT3(positions[triangles_in[nbour_trg_id].vertice_id[2]].vec)); + log_err(desc->scene->dev, "Media: %lu VS %lu\n", + (unsigned long)neighbour->medium, (unsigned long)crt_side->medium); + res = RES_BAD_ARG; + goto error; + } + if(neighbour->list_id == FLAG_LIST_COMPONENT) { + /* Already processed */ #ifndef NDEBUG - ASSERT(neighbour->member_of_cc == cc->cc_id); + ASSERT(neighbour->member_of_cc == cc->cc_id); #endif - continue; - } - if(neighbour->list_id == FLAG_WAITING_STACK) { - continue; /* Already processed */ + continue; + } + if(neighbour->list_id == FLAG_WAITING_STACK) { + continue; /* Already processed */ + } + add_side_to_stack(scn, &stack, trgsides, neighbour_id); } - add_side_to_stack(scn, &stack, trgsides, neighbour_id); - } - if(darray_side_id_size_get(&stack) == 0) - break; /* Empty stack => connex component is done! */ - crt_side_id = get_side_from_stack(trgsides, &stack); - last_side_id = MMAX(last_side_id, crt_side_id); - } - /* Keep track of this new connex component */ - cc->side_range.last = last_side_id; - /* Need to synchronize connex_components growth as this global structure - * is accessed by multipe threads */ - #pragma omp critical - { - struct cc_descriptor** components; - size_t sz = darray_ptr_component_descriptor_size_get(connex_components); - if(sz <= cc->cc_id) { - res_T tmp_res = darray_ptr_component_descriptor_resize(connex_components, - 1 + cc->cc_id); - if(tmp_res != RES_OK) res = tmp_res; + if(darray_side_id_size_get(&stack) == 0) + break; /* Empty stack => connex component is done! */ + crt_side_id = get_side_from_stack(trgsides, &stack); + last_side_id = MMAX(last_side_id, crt_side_id); } - if(res == RES_OK) { - /* Don't set the pointer before resize as this can lead to move data */ - components = - darray_ptr_component_descriptor_data_get(connex_components); - ASSERT(components[cc->cc_id] == NULL); - components[cc->cc_id] = cc; + /* Keep track of this new connex component */ + cc->side_range.last = last_side_id; + /* Need to synchronize connex_components growth as this global structure + * is accessed by multipe threads */ +#pragma omp critical + { + struct cc_descriptor** components; + size_t sz = darray_ptr_component_descriptor_size_get(connex_components); + if(sz <= cc->cc_id) { + res_T tmp_res = darray_ptr_component_descriptor_resize(connex_components, + 1 + cc->cc_id); + if(tmp_res != RES_OK) res = tmp_res; + } + if(res == RES_OK) { + /* Don't set the pointer before resize as this can lead to move data */ + components = + darray_ptr_component_descriptor_data_get(connex_components); + ASSERT(components[cc->cc_id] == NULL); + components[cc->cc_id] = cc; + } } } + error: + continue; /* Cannot exit openmp block */ } - error: - continue; /* Cannot exit openmp block */ + darray_side_id_release(&stack); } OK2(res, error_); @@ -968,94 +964,99 @@ build_result /* Resize/push operations on enclosure's fields are valid in the * openmp block as a given enclosure is processed by a single thread */ - #pragma omp parallel for schedule(dynamic) - for(ee = 0; ee < (int)desc->enclosures_count; ee++) { - const enclosure_id_t e = (enclosure_id_t)ee; - struct enclosure_data* enc = enclosures + e; - const struct cc_descriptor* current = cc_descriptors[enc->first_component]; - struct htable_vrtx_id vtable; /* TODO: don't recreate vtable for same thread */ - trg_id_t fst_idx = 0; - trg_id_t sgd_idx = enc->side_count;; - trg_id_t t; - ASSERT(enc->first_component - < darray_ptr_component_descriptor_size_get(connex_components)); - ASSERT(ee <= ENCLOSURE_MAX__); - ASSERT(current->cc_id == enc->first_component); - - if(res != RES_OK) continue; - ASSERT(e <= UINT_MAX); - enc->header.enclosure_id = (unsigned)e; /* Back to API type */ - ASSERT(current->enclosure_id == enc->header.enclosure_id); - enc->header.is_infinite = (e == 0); - enc->header.enclosed_medium - = (unsigned)current->medium; /* Back to API type */ - ASSERT(enc->header.enclosed_medium < desc->scene->nmeds); - - /* Build side and vertex lists. */ - OK(darray_triangle_in_resize(&enc->sides, enc->side_count)); - /* Size is just a int */ - OK(darray_vrtx_id_reserve(&enc->vertices, - enc->side_count / 2 + enc->side_count / 8)); - /* New vertex numbering scheme local to the enclosure */ + #pragma omp parallel + { + struct htable_vrtx_id vtable; htable_vrtx_id_init(alloc, &vtable); - ASSERT(desc->scene->nutris - == darray_triangle_in_size_get(&desc->scene->triangles_in)); - /* Put at the end the back-faces of triangles that also have their - * front-face in the list. */ - for(t = TRGSIDE_2_TRG(enc->side_range.first); - t <= TRGSIDE_2_TRG(enc->side_range.last); - t++) - { - const struct triangle_in* trg_in = triangles_in + t; - struct triangle_in* trg; - unsigned vertice_id[3]; - int i; - if(triangles_enc[t].enclosure[SIDE_FRONT] != e - && triangles_enc[t].enclosure[SIDE_BACK] != e) - continue; - ++enc->header.unique_triangle_count; - FOR_EACH(i, 0, 3) { - vrtx_id_t* id = htable_vrtx_id_find(&vtable, trg_in->vertice_id + i); - if(id) { - vertice_id[i] = *id; /* Known vertex */ - } else { - /* Create new association */ - size_t tmp = htable_vrtx_id_size_get(&vtable); - ASSERT(tmp == darray_vrtx_id_size_get(&enc->vertices)); - ASSERT(tmp < VRTX_MAX__); - vertice_id[i] = (vrtx_id_t)tmp; - OK(htable_vrtx_id_set(&vtable, trg_in->vertice_id + i, - vertice_id + i)); - OK(darray_vrtx_id_push_back(&enc->vertices, vertice_id + i)); - ++enc->header.vertices_count; + #pragma omp for schedule(dynamic) + for(ee = 0; ee < (int)desc->enclosures_count; ee++) { + const enclosure_id_t e = (enclosure_id_t)ee; + struct enclosure_data* enc = enclosures + e; + const struct cc_descriptor* current = cc_descriptors[enc->first_component]; + trg_id_t fst_idx = 0; + trg_id_t sgd_idx = enc->side_count;; + trg_id_t t; + ASSERT(enc->first_component + < darray_ptr_component_descriptor_size_get(connex_components)); + ASSERT(ee <= ENCLOSURE_MAX__); + ASSERT(current->cc_id == enc->first_component); + + if(res != RES_OK) continue; + ASSERT(e <= UINT_MAX); + enc->header.enclosure_id = (unsigned)e; /* Back to API type */ + ASSERT(current->enclosure_id == enc->header.enclosure_id); + enc->header.is_infinite = (e == 0); + enc->header.enclosed_medium + = (unsigned)current->medium; /* Back to API type */ + ASSERT(enc->header.enclosed_medium < desc->scene->nmeds); + + /* Build side and vertex lists. */ + OK(darray_triangle_in_resize(&enc->sides, enc->side_count)); + /* Size is just a int */ + OK(darray_vrtx_id_reserve(&enc->vertices, + enc->side_count / 2 + enc->side_count / 8)); + /* New vertex numbering scheme local to the enclosure */ + htable_vrtx_id_clear(&vtable); + ASSERT(desc->scene->nutris + == darray_triangle_in_size_get(&desc->scene->triangles_in)); + /* Put at the end the back-faces of triangles that also have their + * front-face in the list. */ + for(t = TRGSIDE_2_TRG(enc->side_range.first); + t <= TRGSIDE_2_TRG(enc->side_range.last); + t++) + { + const struct triangle_in* trg_in = triangles_in + t; + struct triangle_in* trg; + unsigned vertice_id[3]; + int i; + if(triangles_enc[t].enclosure[SIDE_FRONT] != e + && triangles_enc[t].enclosure[SIDE_BACK] != e) + continue; + ++enc->header.unique_triangle_count; + + FOR_EACH(i, 0, 3) { + vrtx_id_t* id = htable_vrtx_id_find(&vtable, trg_in->vertice_id + i); + if(id) { + vertice_id[i] = *id; /* Known vertex */ + } else { + /* Create new association */ + size_t tmp = htable_vrtx_id_size_get(&vtable); + ASSERT(tmp == darray_vrtx_id_size_get(&enc->vertices)); + ASSERT(tmp < VRTX_MAX__); + vertice_id[i] = (vrtx_id_t)tmp; + OK(htable_vrtx_id_set(&vtable, trg_in->vertice_id + i, + vertice_id + i)); + OK(darray_vrtx_id_push_back(&enc->vertices, vertice_id + i)); + ++enc->header.vertices_count; + } } + ASSERT(triangles_enc[t].enclosure[SIDE_FRONT] == e + || triangles_enc[t].enclosure[SIDE_BACK] == e); + if(triangles_enc[t].enclosure[SIDE_FRONT] == e) { + ++enc->header.triangle_count; + trg = darray_triangle_in_data_get(&enc->sides) + fst_idx++; + + FOR_EACH(i, 0, 2) trg->medium[i] = trg_in->medium[i]; + trg->global_id = trg_in->global_id; + FOR_EACH(i, 0, 3) trg->vertice_id[i] = vertice_id[i]; + } + if(triangles_enc[t].enclosure[SIDE_BACK] == e) { + ++enc->header.triangle_count; + trg = darray_triangle_in_data_get(&enc->sides) + + ((triangles_enc[t].enclosure[SIDE_FRONT] == e) ? --sgd_idx : fst_idx++); + + FOR_EACH(i, 0, 2) trg->medium[i] = trg_in->medium[1 - i]; + trg->global_id = trg_in->global_id; + FOR_EACH(i, 0, 3) trg->vertice_id[i] = vertice_id[2 - i]; + } + if(fst_idx == sgd_idx) break; } - ASSERT(triangles_enc[t].enclosure[SIDE_FRONT] == e - || triangles_enc[t].enclosure[SIDE_BACK] == e); - if(triangles_enc[t].enclosure[SIDE_FRONT] == e) { - ++enc->header.triangle_count; - trg = darray_triangle_in_data_get(&enc->sides) + fst_idx++; - - FOR_EACH(i, 0, 2) trg->medium[i] = trg_in->medium[i]; - trg->global_id = trg_in->global_id; - FOR_EACH(i, 0, 3) trg->vertice_id[i] = vertice_id[i]; - } - if(triangles_enc[t].enclosure[SIDE_BACK] == e) { - ++enc->header.triangle_count; - trg = darray_triangle_in_data_get(&enc->sides) + - ((triangles_enc[t].enclosure[SIDE_FRONT] == e) ? --sgd_idx : fst_idx++); - - FOR_EACH(i, 0, 2) trg->medium[i] = trg_in->medium[1 - i]; - trg->global_id = trg_in->global_id; - FOR_EACH(i, 0, 3) trg->vertice_id[i] = vertice_id[2 - i]; - } - if(fst_idx == sgd_idx) break; + error: + /* Cannot exit openmp block */ + continue; } htable_vrtx_id_release(&vtable); - error: - /* Cannot exit openmp block */ - continue; } OK2(res, error_);