commit c89e7b3fb6f79bd3ef1661a15ab9d0acb487e54f
parent c95cc1f4a73e7b0fa2ee84378fba4fc4118db209
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 26 Feb 2018 13:12:56 +0100
Refactoring of the build result step.
Diffstat:
5 files changed, 157 insertions(+), 97 deletions(-)
diff --git a/src/senc_device_c.h b/src/senc_device_c.h
@@ -19,10 +19,6 @@
#include <rsys/free_list.h>
#include <rsys/ref_count.h>
-#define OK(expr)\
- res = expr;\
- if(res != RES_OK) goto error;
-
struct name { FITEM; };
#define FITEM_TYPE name
#include <rsys/free_list.h>
diff --git a/src/senc_enclosure_data.h b/src/senc_enclosure_data.h
@@ -41,14 +41,23 @@ struct enclosure_data {
struct darray_triangle_in sides;
/* Index of vertices in scene's unique vertices */
struct darray_vrtx_id vertices;
+ /* TODO: use only 1 bit per side (now 1 char per triangle) */
+ struct darray_char side_membership;
+ /* Number of components involved in this enclosure */
+ component_id_t cc_count;
+ /* Linked list of the components */
+ component_id_t first_component;
};
static FINLINE void
enclosure_data_init(struct mem_allocator* alloc, struct enclosure_data* enc) {
ASSERT(enc);
init_header(&enc->header);
+ enc->cc_count = 0;
+ enc->first_component = COMPONENT_NULL__;
darray_triangle_in_init(alloc, &enc->sides);
darray_vrtx_id_init(alloc, &enc->vertices);
+ darray_char_init(alloc, &enc->side_membership);
}
static FINLINE res_T
@@ -59,9 +68,13 @@ enclosure_data_copy
res_T res = RES_OK;
ASSERT(src && dst);
dst->header = src->header;
- res = darray_triangle_in_copy(&dst->sides, &src->sides);
- if(res != RES_OK) return res;
- return darray_vrtx_id_copy(&dst->vertices, &src->vertices);
+ dst->cc_count = src->cc_count;
+ dst->first_component = src->first_component;
+ OK(darray_triangle_in_copy(&dst->sides, &src->sides));
+ OK(darray_vrtx_id_copy(&dst->vertices, &src->vertices));
+ OK(darray_char_copy(&dst->side_membership, &src->side_membership));
+error:
+ return res;
}
static FINLINE void
@@ -69,6 +82,7 @@ enclosure_data_release(struct enclosure_data* n) {
ASSERT(n);
darray_triangle_in_release(&n->sides);
darray_vrtx_id_release(&n->vertices);
+ darray_char_release(&n->side_membership);
}
static FINLINE res_T
@@ -79,9 +93,13 @@ enclosure_data_copy_and_release
res_T res = RES_OK;
ASSERT(src && dst);
dst->header = src->header;
- res = darray_triangle_in_copy_and_release(&dst->sides, &src->sides);
- if(res != RES_OK) return res;
- return darray_vrtx_id_copy_and_release(&dst->vertices, &src->vertices);
+ dst->cc_count = src->cc_count;
+ dst->first_component = src->first_component;
+ OK(darray_triangle_in_copy_and_release(&dst->sides, &src->sides));
+ OK(darray_vrtx_id_copy_and_release(&dst->vertices, &src->vertices));
+ OK(darray_char_copy(&dst->side_membership, &src->side_membership));
+error:
+ return res;
}
#endif /* SENC_ENCLOSURE_DATA_H */
diff --git a/src/senc_internal_types.h b/src/senc_internal_types.h
@@ -20,6 +20,12 @@
#include <stdint.h>
+/* Utility macro */
+#define OK(expr)\
+ res = expr;\
+ if(res != RES_OK) goto error;
+
+
/* Side IDs are uint32_t */
typedef uint32_t side_id_t;
#define SIDE_MAX__ (UINT32_MAX-1)
diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c
@@ -35,7 +35,8 @@
#define CC_DESCRIPTOR_NULL__ {\
{0,0,-DBL_MAX}, -1, SIDE_NULL__, VRTX_NULL__, 0, MEDIUM_NULL__,\
- CC_ID_NONE, CC_GROUP_ROOT_NONE, CC_GROUP_ID_NONE\
+ CC_ID_NONE, CC_GROUP_ROOT_NONE, CC_GROUP_ID_NONE, CC_ID_NONE, TRG_NULL__,\
+ TRG_NULL__\
}
const struct cc_descriptor CC_DESCRIPTOR_NULL = CC_DESCRIPTOR_NULL__;
@@ -268,6 +269,7 @@ extract_connex_components
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;
+ side_id_t last_side_id = start_side_id;
char* side_membership;
size_t sz;
@@ -280,7 +282,9 @@ extract_connex_components
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) */
+ /* 1 char per triangle (2 sides); allow uint64_t* access */
+ OK(darray_char_reserve(¤t_cc->side_membership,
+ ((scn->nutris + 7) / 8) * 8));
OK(darray_char_resize(¤t_cc->side_membership, scn->nutris));
side_membership = darray_char_data_get(¤t_cc->side_membership);
memset(side_membership, 0, scn->nutris * sizeof(char));
@@ -288,6 +292,7 @@ extract_connex_components
ASSERT(sz <= COMPONENT_MAX__);
current_cc->cc_id = (component_id_t)sz;
current_cc->medium = m;
+ current_cc->first_member_id = TRGSIDE_2_TRG(start_side_id);
for(;;) {
int i;
@@ -366,9 +371,11 @@ extract_connex_components
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 */
find_component_Zmax(scn, triangles_tmp_array, current_cc);
+ current_cc->last_member_id = TRGSIDE_2_TRG(last_side_id);
}
exit:
@@ -449,6 +456,7 @@ group_connex_components
side_id_t infinite_medium_first_side = SIDE_MAX__;
char infinite_medium_is_known = 0;
(void)trgsides;
+ ASSERT(desc && trgsides && triangles_comp && connex_components);
alloc = descriptor_get_allocator(desc);
descriptors = darray_cc_descriptor_data_get(connex_components);
@@ -583,8 +591,7 @@ group_connex_components
}
#endif
if(hit_trg_in->medium[hit_side] != cc->medium) {
- /* Medium mismatch!
- * Model topology is broken. */
+ /* Medium mismatch! Model topology is broken. */
const trg_id_t t1 = TRGSIDE_2_TRG(hit_side_id);
const trg_id_t t2 = TRGSIDE_2_TRG(hit_side);
const struct triangle_in* triangles_in
@@ -619,9 +626,13 @@ group_connex_components
}
/* Post-process links to group connex components */
+ OK(darray_enclosure_resize(&desc->enclosures, desc->enclosures_count));
FOR_EACH(c, 0, cc_count) {
struct cc_descriptor* const cc = descriptors + c;
const struct cc_descriptor* other_desc = cc;
+ struct enclosure_data* enclosures
+ = darray_enclosure_data_get(&desc->enclosures);
+ component_id_t fst;
while(other_desc->enclosure_id == CC_GROUP_ID_NONE) {
other_desc = darray_cc_descriptor_cdata_get(connex_components)
@@ -631,6 +642,11 @@ group_connex_components
ASSERT(other_desc->enclosure_id != CC_GROUP_ID_NONE);
cc->cc_group_root = other_desc->cc_group_root;
cc->enclosure_id = other_desc->enclosure_id;
+ ++enclosures[cc->enclosure_id].cc_count;
+ /* Linked list of componnents */
+ fst = enclosures[cc->enclosure_id].first_component;
+ cc->next_component = fst;
+ enclosures[cc->enclosure_id].first_component = cc->cc_id;
}
exit:
@@ -1084,16 +1100,16 @@ build_result
{
res_T res = RES_OK;
struct mem_allocator* alloc;
- const struct cc_descriptor* cc_descriptors;
+ struct cc_descriptor* cc_descriptors;
struct enclosure_data* enclosures;
- char* side_membership = NULL;
const struct triangle_in* triangles_in;
struct triangle_enc* triangles_enc;
struct htable_vrtx_id vtable;
size_t tmp;
- component_id_t cc_count, c;
+ component_id_t cc_count;
enclosure_id_t e;
- side_id_t* side_counts = NULL;
+ trg_id_t fst_ixd = 0;
+ trg_id_t sgd_ixd;
ASSERT(desc && connex_components);
@@ -1101,125 +1117,132 @@ build_result
tmp = darray_cc_descriptor_size_get(connex_components);
ASSERT(tmp < COMPONENT_MAX__);
cc_count = (component_id_t)tmp;
- cc_descriptors = darray_cc_descriptor_cdata_get(connex_components);
- OK(darray_enclosure_resize(&desc->enclosures, desc->enclosures_count));
+ cc_descriptors = darray_cc_descriptor_data_get(connex_components);
enclosures = darray_enclosure_data_get(&desc->enclosures);
triangles_in = darray_triangle_in_cdata_get(&desc->scene->triangles_in);
- /* Set some enclosure data */
- side_counts = MEM_CALLOC(alloc, desc->enclosures_count, sizeof(side_id_t));
- if(!side_counts) {
- res = RES_MEM_ERR;
- goto error;
- }
- FOR_EACH(e, 0, desc->enclosures_count) {
- struct enclosure_data* enc = enclosures + e;
- ASSERT(e < UINT_MAX);
- enc->header.enclosure_id = (unsigned)e; /* Back to API type */
- enc->header.is_infinite = (e == 0);
- }
- /* Process components to feed enclosures */
- FOR_EACH(c, 0, cc_count) {
- const struct cc_descriptor* cc = cc_descriptors + c;
- const enclosure_id_t e_id = cc->enclosure_id;
- struct enclosure_data* enc = enclosures + e_id;
- ASSERT(enc->header.enclosed_medium == MEDIUM_NULL__ /* Unset */
- || enc->header.enclosed_medium == cc->medium); /* Same medium */
- ASSERT(enc->header.enclosed_medium < UINT_MAX);
- enc->header.enclosed_medium = (unsigned)cc->medium; /* Back to API type */
- side_counts[e_id] += cc->side_count;
- }
- side_membership
- = MEM_ALLOC(alloc, desc->scene->nutris * sizeof(*side_membership));
- if(!side_membership) {
- res = RES_MEM_ERR;
- 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);
+
+ /* Merge enclosures' membership information */
FOR_EACH(e, 0, desc->enclosures_count) {
struct enclosure_data* enc = enclosures + e;
+ struct cc_descriptor* current = cc_descriptors + enc->first_component;
+ const char* enc_memb;
+ uint64_t* enc_memb64;
trg_id_t t;
- memset(side_membership, 0, desc->scene->nutris * sizeof(*side_membership));
- /* Process all CC enclosures_count times to limit memory footprint. */
- FOR_EACH(c, 0, cc_count) {
- const struct cc_descriptor* cc = cc_descriptors + c;
- const char* cc_membership
- = darray_char_cdata_get(&cc->side_membership);
- if(cc->enclosure_id != e) continue;
- FOR_EACH(t, 0, desc->scene->nutris) side_membership[t] |= cc_membership[t];
+ trg_id_t first_member_id = desc->scene->nutris;
+ trg_id_t last_member_id = 0;
+ side_id_t side_count = 0;
+ ASSERT(enc->cc_count != 0 && enc->cc_count <= cc_count);
+ ASSERT(enc->first_component <= cc_count);
+ ASSERT(current != NULL);
+ enc->header.enclosure_id = (unsigned)e; /* Back to API type */
+ 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);
+ /* Get side_membership information from component */
+ darray_char_copy_and_clear(&enc->side_membership,
+ ¤t->side_membership);
+ enc_memb = darray_char_cdata_get(&enc->side_membership);
+ enc_memb64 = (uint64_t*)enc_memb;
+ /* Check we can use uint64_t to merge bit vectors */
+ ASSERT(darray_char_capacity(&enc->side_membership)
+ % sizeof(*enc_memb64) == 0);
+ ASSERT(darray_char_size_get(&enc->side_membership)
+ == desc->scene->nutris);
+ for(;;) {
+ uint64_t* cc_memb64;
+ trg_id_t t64;
+ size_t tmin, tmax;
+ ASSERT(enc->header.enclosed_medium == (unsigned)current->medium);
+ side_count += current->side_count;
+ first_member_id = MMIN(first_member_id, current->first_member_id);
+ last_member_id = MMAX(last_member_id, current->last_member_id);
+ if(current->next_component == COMPONENT_NULL__) break;
+ ASSERT(current->next_component <= cc_count);
+ current = cc_descriptors + current->next_component;
+ ASSERT(darray_char_size_get(¤t->side_membership)
+ == desc->scene->nutris);
+ cc_memb64 = (uint64_t*)darray_char_cdata_get(¤t->side_membership);
+ ASSERT(darray_char_capacity(¤t->side_membership)
+ % sizeof(*enc_memb64) == 0);
+ tmin = current->first_member_id / sizeof(*enc_memb64);
+ tmax = (darray_char_size_get(&enc->side_membership) + sizeof(*enc_memb64) - 1)
+ / sizeof(*enc_memb64);
+ ASSERT(tmin <= tmax);
+ ASSERT(tmax < TRG_MAX__);
+ FOR_EACH(t64, (trg_id_t)tmin, (trg_id_t)tmax) {
+ enc_memb64[t64] |= cc_memb64[t64];
+ }
+ darray_char_purge(¤t->side_membership);
}
- /* Translate membership into a side and vertex lists. */
- OK(darray_triangle_in_reserve(&enc->sides, side_counts[e]));
- OK(darray_vrtx_id_reserve(&enc->vertices, side_counts[e] / 2));
+
+ /* Translate membership into side and vertex lists. */
+ OK(darray_triangle_in_resize(&enc->sides, side_count));
+ OK(darray_vrtx_id_reserve(&enc->vertices, side_count / 2));
/* 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));
- /* Proceed in 2 steps; the second step puts at the end the back-faces
- * of triangles that also have front-face in the list. */
- FOR_EACH(t, 0, desc->scene->nutris) {
+ fst_ixd = 0;
+ sgd_ixd = side_count;
+ /* Put at the end the back-faces of triangles that also have their
+ * front-face in the list. */
+ FOR_EACH(t, first_member_id, desc->scene->nutris) {
const struct triangle_in* trg_in = triangles_in + t;
- struct triangle_in trg;
+ struct triangle_in* trg;
+ unsigned vertice_id[3];
int i;
- if(!side_membership[t]) continue;
+ if(!enc_memb[t]) 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) {
- trg.vertice_id[i] = *id; /* Known vertex */
+ vertice_id[i] = *id; /* Known vertex */
} else {
/* Create new association */
tmp = htable_vrtx_id_size_get(&vtable);
ASSERT(tmp == darray_vrtx_id_size_get(&enc->vertices));
ASSERT(tmp < VRTX_MAX__);
- trg.vertice_id[i] = (vrtx_id_t)tmp;
+ vertice_id[i] = (vrtx_id_t)tmp;
OK(htable_vrtx_id_set(&vtable, trg_in->vertice_id + i,
- trg.vertice_id + i));
- OK(darray_vrtx_id_push_back(&enc->vertices, trg_in->vertice_id + i));
+ vertice_id + i));
+ OK(darray_vrtx_id_push_back(&enc->vertices, vertice_id + i));
++enc->header.vertices_count;
}
}
- FOR_EACH(i, 0, 2) trg.medium[i] = trg_in->medium[i];
- trg.global_id = trg_in->global_id;
- if(side_membership[t] & FLAG_FRONT) {
+ ASSERT((enc_memb[t] & FLAG_FRONT) || (enc_memb[t] & FLAG_BACK));
+ if(enc_memb[t] & FLAG_FRONT) {
++enc->header.triangle_count;
- OK(darray_triangle_in_push_back(&enc->sides, &trg));
+ trg = darray_triangle_in_data_get(&enc->sides) + fst_ixd++;
+
+ 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];
ASSERT(triangles_enc[t].enclosure[SIDE_FRONT] == ENCLOSURE_NULL__);
triangles_enc[t].enclosure[SIDE_FRONT] = e;
- } else if(side_membership[t] & FLAG_BACK) {
+ }
+ if(enc_memb[t] & FLAG_BACK) {
++enc->header.triangle_count;
- triangle_in_flip(&trg);
- OK(darray_triangle_in_push_back(&enc->sides, &trg));
+ trg = darray_triangle_in_data_get(&enc->sides) +
+ ((enc_memb[t] & FLAG_FRONT) ? --sgd_ixd : fst_ixd++);
+
+ 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];
ASSERT(triangles_enc[t].enclosure[SIDE_BACK] == ENCLOSURE_NULL__);
triangles_enc[t].enclosure[SIDE_BACK] = e;
}
+ if(fst_ixd == sgd_ixd) break;
}
- FOR_EACH(t, 0, desc->scene->nutris) {
- const struct triangle_in* trg_in = triangles_in + t;
- struct triangle_in trg;
- int i;
- if(!((side_membership[t] & FLAG_FRONT) && (side_membership[t] & FLAG_BACK)))
- continue;
- ++enc->header.triangle_count;
- FOR_EACH(i, 0, 3) {
- vrtx_id_t* id = htable_vrtx_id_find(&vtable, trg_in->vertice_id + i);
- ASSERT(id);
- trg.vertice_id[2-i] = *id; /* Known vertex */
- }
- FOR_EACH(i, 0, 2) trg.medium[1-i] = trg_in->medium[i];
- trg.global_id = trg_in->global_id;
- OK(darray_triangle_in_push_back(&enc->sides, &trg));
- ASSERT(triangles_enc[t].enclosure[SIDE_BACK] == ENCLOSURE_NULL__);
- triangles_enc[t].enclosure[SIDE_BACK] = e;
- }
- ASSERT(darray_triangle_in_size_get(&enc->sides) == side_counts[e]);
+ darray_char_purge(&enc->side_membership);
}
exit:
htable_vrtx_id_release(&vtable);
- if(side_membership) MEM_RM(alloc, side_membership);
- if(side_counts) MEM_RM(alloc, side_counts);
return res;
error:
goto exit;
diff --git a/src/senc_scene_analyze_c.h b/src/senc_scene_analyze_c.h
@@ -153,8 +153,13 @@ struct cc_descriptor {
component_id_t cc_id;
component_id_t cc_group_root;
enclosure_id_t enclosure_id;
+ /* To create linked lists of componnents */
+ component_id_t next_component;
/* TODO: use only 1 bit per side (now 1 char per triangle) */
+ trg_id_t first_member_id;
+ trg_id_t last_member_id;
struct darray_char side_membership;
+
};
extern const struct cc_descriptor CC_DESCRIPTOR_NULL;
@@ -185,6 +190,9 @@ cc_descriptor_clear(struct cc_descriptor* data)
data->cc_id = CC_DESCRIPTOR_NULL.cc_id;
data->cc_group_root = CC_DESCRIPTOR_NULL.cc_group_root;
data->enclosure_id = CC_DESCRIPTOR_NULL.enclosure_id;
+ data->next_component = CC_DESCRIPTOR_NULL.next_component;
+ data->first_member_id = CC_DESCRIPTOR_NULL.first_member_id;
+ data->last_member_id = CC_DESCRIPTOR_NULL.last_member_id;
darray_char_clear(&data->side_membership);
}
@@ -200,6 +208,9 @@ cc_descriptor_purge(struct cc_descriptor* data)
data->cc_id = CC_DESCRIPTOR_NULL.cc_id;
data->cc_group_root = CC_DESCRIPTOR_NULL.cc_group_root;
data->enclosure_id = CC_DESCRIPTOR_NULL.enclosure_id;
+ data->next_component = CC_DESCRIPTOR_NULL.next_component;
+ data->first_member_id = CC_DESCRIPTOR_NULL.first_member_id;
+ data->last_member_id = CC_DESCRIPTOR_NULL.last_member_id;
darray_char_purge(&data->side_membership);
}
@@ -216,6 +227,9 @@ cc_descriptor_copy(struct cc_descriptor* dst, const struct cc_descriptor* src)
dst->cc_id = src->cc_id;
dst->cc_group_root = src->cc_group_root;
dst->enclosure_id = src->enclosure_id;
+ dst->next_component = src->next_component;
+ dst->first_member_id = src->first_member_id;
+ dst->last_member_id = src->last_member_id;
return darray_char_copy(&dst->side_membership, &src->side_membership);
}
@@ -234,6 +248,9 @@ cc_descriptor_copy_and_release
dst->cc_id = src->cc_id;
dst->cc_group_root = src->cc_group_root;
dst->enclosure_id = src->enclosure_id;
+ dst->next_component = src->next_component;
+ dst->first_member_id = src->first_member_id;
+ dst->last_member_id = src->last_member_id;
return darray_char_copy_and_release(&dst->side_membership,
&src->side_membership);
}