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 c95cc1f4a73e7b0fa2ee84378fba4fc4118db209
parent 2b55715df70bf7787e057b8a16c9bcecb2dac85b
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 23 Feb 2018 14:23:50 +0100

Avoid darray elts copy.

By replacing push_back by resize where possible.

Diffstat:
Msrc/senc_scene_analyze.c | 171++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 95 insertions(+), 76 deletions(-)

diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c @@ -248,13 +248,12 @@ extract_connex_components { res_T res = RES_OK; medium_id_t m; - size_t tmp; struct senc_scene* scn; struct mem_allocator* alloc; struct darray_side_id stack; /* Id of the first trgside not already in a connex component */ side_id_t first_side_not_in_component = 0; - struct cc_descriptor current_cc; + struct cc_descriptor* current_cc; ASSERT(trgsides && desc && connex_components && triangles_tmp_array); @@ -264,32 +263,31 @@ extract_connex_components /* Init stack */ darray_side_id_init(alloc, &stack); - /* Extract connex components until every side is involved */ - cc_descriptor_init(alloc, &current_cc); for(;;) { /* Any not-already-used side is used as a starting point */ const side_id_t start_side_id = get_side_not_in_connex_component(scn, trgsides, &first_side_not_in_component); side_id_t crt_side_id = start_side_id; char* side_membership; + size_t sz; ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nutris); if(start_side_id == SIDE_NULL__) break; /* start_side_id=SIDE_NULL__ => done! */ ASSERT(trgsides[start_side_id].list_id == FLAG_LIST_SIDE_LIST); - m = trgsides[start_side_id].medium; - - /* Reset CC data for a new CC */ - tmp = darray_cc_descriptor_size_get(connex_components); - ASSERT(tmp <= COMPONENT_MAX__); - cc_descriptor_clear(&current_cc); + /* Create and init a new component */ + sz = darray_cc_descriptor_size_get(connex_components); + OK(darray_cc_descriptor_resize(connex_components, 1+ sz)); + current_cc = darray_cc_descriptor_data_get(connex_components) + sz; /* 1 char per triangle (2 sides) */ - darray_char_resize(&current_cc.side_membership, scn->nutris); - side_membership = darray_char_data_get(&current_cc.side_membership); + OK(darray_char_resize(&current_cc->side_membership, scn->nutris)); + side_membership = darray_char_data_get(&current_cc->side_membership); memset(side_membership, 0, scn->nutris * sizeof(char)); - current_cc.cc_id = (component_id_t)tmp; - current_cc.medium = m; + m = trgsides[start_side_id].medium; + ASSERT(sz <= COMPONENT_MAX__); + current_cc->cc_id = (component_id_t)sz; + current_cc->medium = m; for(;;) { int i; @@ -302,21 +300,21 @@ extract_connex_components ASSERT(trgsides[crt_side_id].medium == m); /* Record crt_side both as component and triangle level */ - current_cc.side_count++; + current_cc->side_count++; trgsides[crt_side_id].list_id = FLAG_LIST_COMPONENT; if(TRGSIDE_IS_FRONT(crt_side_id)) { ASSERT(trg_comp->component[SIDE_FRONT] == USHRT_MAX); - trg_comp->component[SIDE_FRONT] = current_cc.cc_id; + trg_comp->component[SIDE_FRONT] = current_cc->cc_id; ASSERT(!(side_membership[crt_trg_id] & FLAG_FRONT)); side_membership[crt_trg_id] |= FLAG_FRONT; } else { ASSERT(trg_comp->component[SIDE_BACK] == USHRT_MAX); - trg_comp->component[SIDE_BACK] = current_cc.cc_id; + trg_comp->component[SIDE_BACK] = current_cc->cc_id; ASSERT(!(side_membership[crt_trg_id] & FLAG_BACK)); side_membership[crt_trg_id] |= FLAG_BACK; } #ifndef NDEBUG - crt_side->member_of_cc = current_cc.cc_id; + crt_side->member_of_cc = current_cc->cc_id; #endif /* Store neighbour sides in a waiting stack */ FOR_EACH(i, 0, 3) { @@ -351,13 +349,12 @@ extract_connex_components log_err(desc->scene->dev, "Media: %lu VS %lu\n", neighbour->medium, crt_side->medium); res = RES_BAD_ARG; - cc_descriptor_release(&current_cc); goto error; } if(neighbour->list_id == FLAG_LIST_COMPONENT) { /* Already processed */ #ifndef NDEBUG - ASSERT(neighbour->member_of_cc == current_cc.cc_id); + ASSERT(neighbour->member_of_cc == current_cc->cc_id); #endif continue; } @@ -371,10 +368,8 @@ extract_connex_components crt_side_id = get_side_from_stack(trgsides, &stack); } /* Keep track of this new connex component */ - find_component_Zmax(scn, triangles_tmp_array, &current_cc); - darray_cc_descriptor_push_back(connex_components, &current_cc); + find_component_Zmax(scn, triangles_tmp_array, current_cc); } - cc_descriptor_release(&current_cc); exit: darray_side_id_release(&stack); @@ -667,7 +662,7 @@ scan_edges ASSERT((size_t)scn->nuverts + (size_t)scn->nutris + 2 <= EDGE_MAX__); /* Make some room for edges. */ - max_nbedges = (edge_id_t)(scn->nuverts + scn->nutris + 2); + max_nbedges = (edge_id_t)(scn->nuverts + scn->nutris + 4); htable_edge_id_init(scn->dev->allocator, &edge_ids); OK(htable_edge_id_reserve(&edge_ids, max_nbedges)); OK(darray_neighbourhood_reserve(neighbourhood_by_edge, max_nbedges)); @@ -678,40 +673,50 @@ scan_edges triangles_tmp = darray_triangle_tmp_data_get(triangles_tmp_array); ASSERT(scn->nutris == darray_triangle_tmp_size_get(triangles_tmp_array)); FOR_EACH(t, 0, scn->nutris) { - struct darray_neighbour* neighbour_list; - struct neighbour_info neighbour; - struct edge_neighbourhood neighbourhood; + struct trg_edge edge; char e; FOR_EACH(e, 0, 3) { edge_id_t* p_id; - edge_id_t id; - /* Create edge. */ set_edge(triangles_in[t].vertice_id[e], - triangles_in[t].vertice_id[(e + 1) % 3], - &neighbourhood.edge, &triangles_tmp[t].reversed_edge[e]); + triangles_in[t].vertice_id[(e + 1) % 3], &edge, &triangles_tmp[t].reversed_edge[e]); /* Find edge id; create it if not already done. */ - p_id = htable_edge_id_find(&edge_ids, &neighbourhood.edge); + p_id = htable_edge_id_find(&edge_ids, &edge); if(p_id) { - id = *p_id; + struct edge_neighbourhood* n = + darray_neighbourhood_data_get(neighbourhood_by_edge) + *p_id; + struct neighbour_info* info; + size_t sz; + /* Add neighbour info to existing edge's neighbour list */ + ASSERT(n->edge.vrtx0 == edge.vrtx0 && n->edge.vrtx1 == edge.vrtx1); + sz = darray_neighbour_size_get(&n->neighbours); + OK(darray_neighbour_resize(&n->neighbours, 1 + sz)); + info = darray_neighbour_data_get(&n->neighbours) + sz; + info->trg_id = t; + info->edge_rank = e; } else { /* Create id */ - size_t tmp; - tmp = htable_edge_id_size_get(&edge_ids); - ASSERT(tmp <= EDGE_MAX__); - id = (edge_id_t)tmp; - OK(htable_edge_id_set(&edge_ids, &neighbourhood.edge, &id)); - darray_neighbour_init(scn->dev->allocator, &neighbourhood.neighbours); - OK(darray_neighbourhood_push_back(neighbourhood_by_edge, - &neighbourhood)); + edge_id_t id; + struct edge_neighbourhood* n; + struct neighbour_info* info; + size_t sz = htable_edge_id_size_get(&edge_ids); + ASSERT(sz <= EDGE_MAX__); + id = (edge_id_t) sz; + ASSERT(htable_edge_id_size_get(&edge_ids) + == darray_neighbourhood_size_get(neighbourhood_by_edge)); + OK(htable_edge_id_set(&edge_ids, &edge, &id)); + OK(darray_neighbourhood_resize(neighbourhood_by_edge, 1 + sz)); + n = darray_neighbourhood_data_get(neighbourhood_by_edge) + sz; + /* Add neighbour info to a newly created edge's neighbour list */ + n->edge = edge; + ASSERT(darray_neighbour_size_get(&n->neighbours) == 0); + OK(darray_neighbour_reserve(&n->neighbours, 2)); + OK(darray_neighbour_resize(&n->neighbours, 1)); + info = darray_neighbour_data_get(&n->neighbours); + info->trg_id = t; + info->edge_rank = e; } - /* Add neighbour info to edge's neighbour list */ - neighbour_list - = &darray_neighbourhood_data_get(neighbourhood_by_edge)[id].neighbours; - neighbour.trg_id = t; - neighbour.edge_rank = e; - darray_neighbour_push_back(neighbour_list, &neighbour); } } @@ -744,14 +749,14 @@ collect_and_link_neighbours /* Htable used to give an id to edges */ struct htable_edge_id edge_ids; res_T res = RES_OK; - ASSERT(scn && trgsides && triangles_tmp_array); ASSERT((size_t) scn->nuverts + (size_t) scn->nutris + 2 <= EDGE_MAX__); darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_edge); /* Make some room for edges. */ - approx_nbedges = (edge_id_t) ((scn->nuverts + scn->nutris) / num_thread); + approx_nbedges = 4 + (num_thread == 1 ? (edge_id_t)(scn->nuverts + scn->nutris) + : (edge_id_t)((scn->nuverts + scn->nutris + num_thread) / (0.75 * num_thread))); htable_edge_id_init(scn->dev->allocator, &edge_ids); OK(htable_edge_id_reserve(&edge_ids, approx_nbedges)); OK(darray_neighbourhood_reserve(&neighbourhood_by_edge, approx_nbedges)); @@ -760,42 +765,57 @@ collect_and_link_neighbours triangles_in = darray_triangle_in_cdata_get(&scn->triangles_in); triangles_tmp = darray_triangle_tmp_data_get(triangles_tmp_array); ASSERT(scn->nutris == darray_triangle_tmp_size_get(triangles_tmp_array)); + FOR_EACH(t, 0, scn->nutris) { - struct darray_neighbour* neighbour_list; - struct neighbour_info neighbour; - struct edge_neighbourhood neighbourhood; + struct trg_edge edge; char ee; + ASSERT(t < scn->nutris); FOR_EACH(ee, 0, 3) { edge_id_t* p_id; - edge_id_t id; const vrtx_id_t v0 = triangles_in[t].vertice_id[ee]; const vrtx_id_t v1 = triangles_in[t].vertice_id[(ee + 1) % 3]; /* Process only "my" edges! */ const int h = v0 + v1 + MMIN(v0,v1); /* v0,v1 and v1,v0 must give the same hash!!! */ if (h % num_thread != rank) continue; /* Create edge. */ - set_edge(v0, v1, &neighbourhood.edge, &triangles_tmp[t].reversed_edge[ee]); + set_edge(v0, v1, &edge, &triangles_tmp[t].reversed_edge[ee]); /* Find edge id; create it if not already done. */ - p_id = htable_edge_id_find(&edge_ids, &neighbourhood.edge); + p_id = htable_edge_id_find(&edge_ids, &edge); if (p_id) { - id = *p_id; + struct edge_neighbourhood* n = + darray_neighbourhood_data_get(&neighbourhood_by_edge) + *p_id; + struct neighbour_info* info; + size_t sz; + /* Add neighbour info to existing edge's neighbour list */ + ASSERT(n->edge.vrtx0 == edge.vrtx0 && n->edge.vrtx1 == edge.vrtx1); + sz = darray_neighbour_size_get(&n->neighbours); + OK(darray_neighbour_resize(&n->neighbours, 1 + sz)); + info = darray_neighbour_data_get(&n->neighbours) + sz; + info->trg_id = t; + info->edge_rank = ee; } else { /* Create id */ - tmp = htable_edge_id_size_get(&edge_ids); - ASSERT(tmp <= EDGE_MAX__); - id = (edge_id_t)tmp; - OK(htable_edge_id_set(&edge_ids, &neighbourhood.edge, &id)); - darray_neighbour_init(scn->dev->allocator, &neighbourhood.neighbours); - OK(darray_neighbourhood_push_back(&neighbourhood_by_edge, - &neighbourhood)); + edge_id_t id; + struct edge_neighbourhood* n; + struct neighbour_info* info; + size_t sz = htable_edge_id_size_get(&edge_ids); + ASSERT(sz <= EDGE_MAX__); + id = (edge_id_t)sz; + ASSERT(htable_edge_id_size_get(&edge_ids) + == darray_neighbourhood_size_get(&neighbourhood_by_edge)); + OK(htable_edge_id_set(&edge_ids, &edge, &id)); + OK(darray_neighbourhood_resize(&neighbourhood_by_edge, 1 + sz)); + n = darray_neighbourhood_data_get(&neighbourhood_by_edge) + sz; + /* Add neighbour info to a newly created edge's neighbour list */ + n->edge = edge; + ASSERT(darray_neighbour_size_get(&n->neighbours) == 0); + OK(darray_neighbour_reserve(&n->neighbours, 2)); + OK(darray_neighbour_resize(&n->neighbours, 1)); + info = darray_neighbour_data_get(&n->neighbours); + info->trg_id = t; + info->edge_rank = ee; } - /* Add neighbour info to edge's neighbour list */ - neighbour_list - = &darray_neighbourhood_data_get(&neighbourhood_by_edge)[id].neighbours; - neighbour.trg_id = t; - neighbour.edge_rank = ee; - darray_neighbour_push_back(neighbour_list, &neighbour); } } @@ -1073,7 +1093,7 @@ build_result size_t tmp; component_id_t cc_count, c; enclosure_id_t e; - side_id_t* side_counts; + side_id_t* side_counts = NULL; ASSERT(desc && connex_components); @@ -1082,7 +1102,7 @@ build_result ASSERT(tmp < COMPONENT_MAX__); cc_count = (component_id_t)tmp; cc_descriptors = darray_cc_descriptor_cdata_get(connex_components); - darray_enclosure_resize(&desc->enclosures, desc->enclosures_count); + OK(darray_enclosure_resize(&desc->enclosures, desc->enclosures_count)); enclosures = darray_enclosure_data_get(&desc->enclosures); triangles_in = darray_triangle_in_cdata_get(&desc->scene->triangles_in); /* Set some enclosure data */ @@ -1114,8 +1134,7 @@ build_result res = RES_MEM_ERR; goto error; } - res = darray_triangle_enc_resize(&desc->triangles_enc, desc->scene->nutris); - if(res != RES_OK) goto error; + OK(darray_triangle_enc_resize(&desc->triangles_enc, desc->scene->nutris)); triangles_enc = darray_triangle_enc_data_get(&desc->triangles_enc); htable_vrtx_id_init(alloc, &vtable); FOR_EACH(e, 0, desc->enclosures_count) { @@ -1259,12 +1278,10 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc) darray_triangle_tmp_init(scn->dev->allocator, &triangles_tmp); triangles_tmp_initialized = 1; - darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_edge); - neighbourhood_by_edge_initialized = 1; -#ifdef PARALLEL_EDGES +#ifndef PARALLEL_EDGES OK(darray_triangle_tmp_resize(&triangles_tmp, scn->nutris)); trgsides @@ -1287,6 +1304,8 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc) #else + darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_edge); + neighbourhood_by_edge_initialized = 1; /* Step 1: list edges and connect triangles to edges */ res = scan_edges(scn, &neighbourhood_by_edge, &triangles_tmp);