void db_dup_full_path(struct db_full_path *newp, const struct db_full_path *oldp) { unsigned int i = 0; RT_CK_FULL_PATH(newp); RT_CK_FULL_PATH(oldp); newp->fp_maxlen = oldp->fp_maxlen; newp->fp_len = oldp->fp_len; if (oldp->fp_len <= 0) { newp->fp_names = (struct directory **)0; newp->fp_bool = (int *)0; return; } newp->fp_names = (struct directory **)bu_malloc(newp->fp_maxlen * sizeof(struct directory *), "db_full_path array (duplicate)"); memcpy((char *)newp->fp_names, (char *)oldp->fp_names, newp->fp_len * sizeof(struct directory *)); newp->fp_bool = (int *)bu_malloc(newp->fp_maxlen * sizeof(int), "db_full_path bool array (duplicate)"); memcpy((char *)newp->fp_bool, (char *)oldp->fp_bool, newp->fp_len * sizeof(int)); newp->fp_mat = (matp_t *)bu_calloc(newp->fp_maxlen, sizeof(matp_t), "db_full_path mat array (duplicate)"); for (i = 0; i < newp->fp_len; i++) { if (oldp->fp_mat[i]) { newp->fp_mat[i] = (matp_t)bu_calloc(1, sizeof(mat_t), "transformation matrix"); MAT_COPY(newp->fp_mat[i], oldp->fp_mat[i]); } } }
void db_add_node_to_full_path(struct db_full_path *pp, struct directory *dp) { RT_CK_FULL_PATH(pp); if (pp->fp_maxlen <= 0) { pp->fp_maxlen = 32; pp->fp_names = (struct directory **)bu_malloc( pp->fp_maxlen * sizeof(struct directory *), "db_full_path array"); pp->fp_bool = (int *)bu_calloc(pp->fp_maxlen, sizeof(int), "db_full_path bool array"); pp->fp_mat = (matp_t *)bu_calloc(pp->fp_maxlen, sizeof(matp_t), "db_full_path matrices array"); } else if (pp->fp_len >= pp->fp_maxlen) { pp->fp_maxlen *= 4; pp->fp_names = (struct directory **)bu_realloc( (char *)pp->fp_names, pp->fp_maxlen * sizeof(struct directory *), "enlarged db_full_path array"); pp->fp_bool = (int *)bu_realloc( (char *)pp->fp_bool, pp->fp_maxlen * sizeof(int), "enlarged db_full_path bool array"); pp->fp_mat = (matp_t *)bu_realloc( (char *)pp->fp_mat, pp->fp_maxlen * sizeof(matp_t), "enlarged db_full_path matrices array"); } pp->fp_names[pp->fp_len++] = dp; }
static union tree * facetize_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { struct bu_list vhead; union tree **facetize_tree; if (tsp) RT_CK_DBTS(tsp); if (pathp) RT_CK_FULL_PATH(pathp); facetize_tree = (union tree **)client_data; BU_LIST_INIT(&vhead); if (curtree->tr_op == OP_NOP) return curtree; if (*facetize_tree) { union tree *tr; BU_ALLOC(tr, union tree); RT_TREE_INIT(tr); tr->tr_op = OP_UNION; tr->tr_b.tb_regionp = REGION_NULL; tr->tr_b.tb_left = *facetize_tree; tr->tr_b.tb_right = curtree; *facetize_tree = tr; } else { *facetize_tree = curtree; } /* Tree has been saved, and will be freed later */ return TREE_NULL; }
/* TODO - make the identical test incorporate booleans and matrices as well, if present */ int db_identical_full_paths(const struct db_full_path *a, const struct db_full_path *b) { long i; RT_CK_FULL_PATH(a); RT_CK_FULL_PATH(b); BU_ASSERT_SIZE_T(a->fp_len, <, LONG_MAX); if (a->fp_len != b->fp_len) return 0; for (i = a->fp_len-1; i >= 0; i--) { if (a->fp_names[i] != b->fp_names[i]) return 0; } return 1; }
/* return 0 when IS a light or an error occurred. regions are skipped * when this function returns 0. */ static int select_non_lights(struct db_tree_state *UNUSED(tsp), const struct db_full_path *pathp, const struct rt_comb_internal *UNUSED(combp), void *UNUSED(client_data)) { struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; RT_CK_FULL_PATH(pathp); dp = DB_FULL_PATH_CUR_DIR(pathp); id = rt_db_get_internal(&intern, dp, dbip, (matp_t)NULL, &rt_uniresource); if (id < 0) { /* error occurred retrieving object */ bu_log("Warning: Can not load internal form of %s\n", dp->d_namep); return 0; } if ((dp->d_flags & RT_DIR_COMB) && (id == ID_COMBINATION)) { comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); if (BU_STR_EQUAL(bu_vls_addr(&comb->shader), "light")) { rt_db_free_internal(&intern); return 0; } } return 1; }
union tree * gcv_bottess_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { union tree *ret_tree = TREE_NULL; void (*write_region)(struct nmgregion *, const struct db_full_path *, int, int, float [3]); if (!tsp || !curtree || !pathp || !client_data) { bu_log("INTERNAL ERROR: gcv_region_end missing parameters\n"); return TREE_NULL; } write_region = ((struct gcv_data *)client_data)->func; if (!write_region) { bu_log("INTERNAL ERROR: gcv_region_end missing conversion callback function\n"); return TREE_NULL; } RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); splitz=0; splitty=0; RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); if (curtree->tr_op == OP_NOP) return curtree; ret_tree = evaluate(curtree, tsp->ts_ttol, tsp->ts_tol); lsplitz+=splitz; lsplitz+=splitz; lsplitty+=splitty; splitz=0; splitty=0; return ret_tree; }
/* TODO - make the match top test incorporate booleans and matrices as well, if present */ int db_full_path_match_top( const struct db_full_path *a, const struct db_full_path *b) { size_t i; RT_CK_FULL_PATH(a); RT_CK_FULL_PATH(b); if (a->fp_len > b->fp_len) return 0; for (i = 0; i < a->fp_len; i++) { if (a->fp_names[i] != b->fp_names[i]) return 0; } return 1; }
static union tree * wireframe_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { if (tsp) RT_CK_DBTS(tsp); if (pathp) RT_CK_FULL_PATH(pathp); if (curtree) RT_CK_TREE(curtree); return curtree; }
/* TODO - make the subset test incorporate booleans (and matrices?), if present */ int db_full_path_subset( const struct db_full_path *a, const struct db_full_path *b, const int skip_first) { size_t i = 0; RT_CK_FULL_PATH(a); RT_CK_FULL_PATH(b); if (b->fp_len > a->fp_len) return 0; if (skip_first) i = 1; else i = 0; for (; i < a->fp_len; i++) { size_t j; if (a->fp_names[i] != b->fp_names[0]) continue; /* First element matches, check remaining length */ if (b->fp_len > a->fp_len - i) return 0; /* Check remainder of 'b' */ for (j = 1; j < b->fp_len; j++) { if (a->fp_names[i+j] != b->fp_names[j]) goto step; } /* 'b' is a proper subset */ return 1; step: ; } return 0; }
void db_append_full_path(struct db_full_path *dest, const struct db_full_path *src) { unsigned int i = 0; RT_CK_FULL_PATH(dest); RT_CK_FULL_PATH(src); db_extend_full_path(dest, src->fp_len); memcpy((char *)&dest->fp_names[dest->fp_len], (char *)&src->fp_names[0], src->fp_len * sizeof(struct directory *)); memcpy((char *)&dest->fp_bool[dest->fp_len], (char *)&src->fp_bool[0], src->fp_len * sizeof(int)); for (i = 0; i < src->fp_len; i++) { if (src->fp_mat[i]) { dest->fp_mat[dest->fp_len + i] = (matp_t)bu_calloc(1, sizeof(mat_t), "transformation matrix"); MAT_COPY(dest->fp_mat[dest->fp_len + i], src->fp_mat[i]); } } dest->fp_len += src->fp_len; }
int db_full_path_search(const struct db_full_path *a, const struct directory *dp) { long i; RT_CK_FULL_PATH(a); RT_CK_DIR(dp); BU_ASSERT_SIZE_T(a->fp_len, <, LONG_MAX); for (i = a->fp_len-1; i >= 0; i--) { if (a->fp_names[i] == dp) return 1; } return 0; }
void db_dup_path_tail(struct db_full_path *newp, const struct db_full_path *oldp, off_t start) { unsigned int i = 0; RT_CK_FULL_PATH(newp); RT_CK_FULL_PATH(oldp); if (start < 0 || (size_t)start > oldp->fp_len-1) bu_bomb("db_dup_path_tail: start offset out of range\n"); newp->fp_maxlen = newp->fp_len = oldp->fp_len - start; if (newp->fp_len <= 0) { newp->fp_names = (struct directory **)0; newp->fp_bool = (int *)0; newp->fp_mat = (matp_t *)0; return; } newp->fp_names = (struct directory **)bu_malloc( newp->fp_maxlen * sizeof(struct directory *), "db_full_path array (duplicate)"); memcpy((char *)newp->fp_names, (char *)&oldp->fp_names[start], newp->fp_len * sizeof(struct directory *)); newp->fp_bool = (int *)bu_malloc( newp->fp_maxlen * sizeof(int), "db_full_path bool array (duplicate)"); memcpy((char *)newp->fp_bool, (char *)&oldp->fp_bool[start], newp->fp_len * sizeof(int)); newp->fp_mat = (matp_t *)bu_calloc(newp->fp_maxlen, sizeof(matp_t), "db_full_path mat array (duplicate)"); for (i = start; i < newp->fp_len; i++) { if (oldp->fp_mat[i]) { newp->fp_mat[i] = (matp_t)bu_calloc(1, sizeof(mat_t), "transformation matrix"); MAT_COPY(newp->fp_mat[i], oldp->fp_mat[i]); } } }
void db_path_to_vls(struct bu_vls *str, const struct db_full_path *pp) { size_t i; BU_CK_VLS(str); RT_CK_FULL_PATH(pp); for (i = 0; i < pp->fp_len; i++) { bu_vls_putc(str, '/'); if (pp->fp_names[i]) bu_vls_strcat(str, pp->fp_names[i]->d_namep); else bu_vls_strcat(str, "**NULL**"); } }
/** * This routine must be prepared to run in parallel. */ HIDDEN int _rt_gettree_region_start(struct db_tree_state *tsp, const struct db_full_path *pathp, const struct rt_comb_internal *combp, void *UNUSED(client_data)) { if (tsp) { RT_CK_RTI(tsp->ts_rtip); RT_CK_RESOURCE(tsp->ts_resp); if (pathp) RT_CK_FULL_PATH(pathp); if (combp) RT_CHECK_COMB(combp); /* Ignore "air" regions unless wanted */ if (tsp->ts_rtip->useair == 0 && tsp->ts_aircode != 0) { tsp->ts_rtip->rti_air_discards++; return -1; /* drop this region */ } } return 0; }
/** * This routine will be called by db_walk_tree() once all the solids * in this region have been visited. * * This routine must be prepared to run in parallel. As a result, * note that the details of the solids pointed to by the soltab * pointers in the tree may not be filled in when this routine is * called (due to the way multiple instances of solids are handled). * Therefore, everything which referred to the tree has been moved out * into the serial section. (_rt_tree_region_assign, rt_bound_tree) */ HIDDEN union tree * _rt_gettree_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { struct region *rp; struct directory *dp = NULL; size_t shader_len=0; struct rt_i *rtip; Tcl_HashTable *tbl = (Tcl_HashTable *)client_data; Tcl_HashEntry *entry; matp_t inv_mat; struct bu_attribute_value_set avs; struct bu_attribute_value_pair *avpp; RT_CK_DBI(tsp->ts_dbip); RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); rtip = tsp->ts_rtip; RT_CK_RTI(rtip); RT_CK_RESOURCE(tsp->ts_resp); if (curtree->tr_op == OP_NOP) { /* Ignore empty regions */ return curtree; } BU_ALLOC(rp, struct region); rp->l.magic = RT_REGION_MAGIC; rp->reg_regionid = tsp->ts_regionid; rp->reg_is_fastgen = tsp->ts_is_fastgen; rp->reg_aircode = tsp->ts_aircode; rp->reg_gmater = tsp->ts_gmater; rp->reg_los = tsp->ts_los; dp = (struct directory *)DB_FULL_PATH_CUR_DIR(pathp); if (!dp) return TREE_NULL; bu_avs_init_empty(&avs); if (db5_get_attributes(tsp->ts_dbip, &avs, dp) == 0) { /* copy avs */ bu_avs_init_empty(&(rp->attr_values)); for (BU_AVS_FOR(avpp, &(tsp->ts_attrs))) { bu_avs_add(&(rp->attr_values), avpp->name, bu_avs_get(&avs, avpp->name)); } }
static int select_lights(struct db_tree_state *UNUSED(tsp), const struct db_full_path *pathp, const struct rt_comb_internal *UNUSED(combp), void *UNUSED(client_data)) { struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; RT_CK_FULL_PATH( pathp ); dp = DB_FULL_PATH_CUR_DIR( pathp ); if ( !(dp->d_flags & RT_DIR_COMB) ) return -1; id = rt_db_get_internal( &intern, dp, dbip, (matp_t)NULL, &rt_uniresource ); if ( id < 0 ) { bu_log( "Cannot internal form of %s\n", dp->d_namep ); return -1; } if ( id != ID_COMBINATION ) { bu_log( "Directory/database mismatch!\n\t is '%s' a combination or not?\n", dp->d_namep ); return -1; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB( comb ); if ( BU_STR_EQUAL( bu_vls_addr( &comb->shader ), "light" ) ) { rt_db_free_internal(&intern); return 0; } else { rt_db_free_internal(&intern); return -1; } }
char * db_path_to_string(const struct db_full_path *pp) { char *cp; char *buf; size_t len; size_t rem; size_t i; long j; RT_CK_FULL_PATH(pp); BU_ASSERT_SIZE_T(pp->fp_len, <, LONG_MAX); len = 3; /* leading slash, trailing null, spare */ for (j=pp->fp_len-1; j >= 0; j--) { if (pp->fp_names[j]) len += strlen(pp->fp_names[j]->d_namep) + 1; else len += 16; } buf = (char *)bu_malloc(len, "pathname string"); cp = buf; rem = len; for (i = 0; i < pp->fp_len; i++) { *cp++ = '/'; rem--; if (pp->fp_names[i]) { bu_strlcpy(cp, pp->fp_names[i]->d_namep, rem); rem -= strlen(pp->fp_names[i]->d_namep); } else { bu_strlcpy(cp, "**NULL**", rem); rem -= 8; } cp += strlen(cp); } *cp++ = '\0'; return buf; }
/** * R T _ F R E E _ S O L T A B * * Decrement use count on soltab structure. If no longer needed, * release associated storage, and free the structure. * * This routine semaphore protects against other copies of itself * running in parallel, and against other routines (such as * rt_find_identical_solid()) which might also be modifying the linked * list heads. * * Called by - * db_free_tree() * rt_clean() * rt_gettrees() * rt_kill_deal_solid_refs() */ void rt_free_soltab(struct soltab *stp) { int hash; RT_CK_SOLTAB(stp); if ( stp->st_id < 0 ) bu_bomb("rt_free_soltab: bad st_id"); hash = db_dirhash(stp->st_dp->d_namep); ACQUIRE_SEMAPHORE_TREE(hash); /* start critical section */ if ( --(stp->st_uses) > 0 ) { RELEASE_SEMAPHORE_TREE(hash); return; } BU_LIST_DEQUEUE( &(stp->l2) ); /* remove from st_dp->d_use_hd list */ BU_LIST_DEQUEUE( &(stp->l) ); /* uses rti_solidheads[] */ RELEASE_SEMAPHORE_TREE(hash); /* end critical section */ if ( stp->st_aradius > 0 ) { stp->st_meth->ft_free( stp ); stp->st_aradius = 0; } if ( stp->st_matp ) bu_free( (char *)stp->st_matp, "st_matp"); stp->st_matp = (matp_t)0; /* Sanity */ bu_ptbl_free(&stp->st_regions); stp->st_dp = DIR_NULL; /* Sanity */ if ( stp->st_path.magic ) { RT_CK_FULL_PATH( &stp->st_path ); db_free_full_path( &stp->st_path ); } bu_free( (char *)stp, "struct soltab" ); }
void db_free_full_path(struct db_full_path *pp) { unsigned int i = 0; RT_CK_FULL_PATH(pp); if (pp->fp_maxlen > 0) { bu_free((char *)pp->fp_names, "db_full_path array"); bu_free((char *)pp->fp_bool, "db_full_path bool array"); for (i = 0; i < pp->fp_len; i++) { if (pp->fp_mat[i]) { bu_free((char *)pp->fp_mat[i], "free matrix"); pp->fp_mat[i] = NULL; } } bu_free((char *)pp->fp_mat, "db_full_path matrix array"); pp->fp_maxlen = pp->fp_len = 0; pp->fp_names = (struct directory **)0; pp->fp_bool = (int *)0; pp->fp_mat = (matp_t *)0; } }
void db_extend_full_path(struct db_full_path *pathp, size_t incr) { size_t newlen; RT_CK_FULL_PATH(pathp); if (pathp->fp_maxlen <= 0) { pathp->fp_len = 0; pathp->fp_maxlen = incr; pathp->fp_names = (struct directory **)bu_malloc( pathp->fp_maxlen * sizeof(struct directory *), "empty fp_names extension"); pathp->fp_bool = (int *)bu_calloc(pathp->fp_maxlen, sizeof(int), "empty fp_bool bool extension"); pathp->fp_mat = (matp_t *)bu_calloc(pathp->fp_maxlen, sizeof(matp_t), "db_full_path matrices array"); return; } newlen = pathp->fp_len + incr; if (pathp->fp_maxlen < newlen) { pathp->fp_maxlen = newlen+1; pathp->fp_names = (struct directory **)bu_realloc( (char *)pathp->fp_names, pathp->fp_maxlen * sizeof(struct directory *), "fp_names extension"); pathp->fp_bool = (int *)bu_realloc( (char *)pathp->fp_bool, pathp->fp_maxlen * sizeof(int), "fp_names bool extension"); pathp->fp_mat = (matp_t *)bu_realloc( (char *)pathp->fp_mat, pathp->fp_maxlen * sizeof(matp_t), "enlarged db_full_path matrices array"); } }
/* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree *do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { union tree *ret_tree; struct bu_list vhead; struct nmgregion *r; RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); { char *sofar = db_path_to_string(pathp); bu_log("\ndo_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; if (verbose) bu_log("Attempting to process region %s\n", db_path_to_string(pathp)); ret_tree= process_boolean(curtree, tsp, pathp); if (ret_tree) r = ret_tree->tr_d.td_r; else { if (verbose) bu_log("\tNothing left of this region after Boolean evaluation\n"); regions_written++; /* don't count as a failure */ r = (struct nmgregion *)NULL; } regions_converted++; if (r != (struct nmgregion *)NULL) { struct shell *s; int empty_region=0; int empty_model=0; /* Kill cracks */ s = BU_LIST_FIRST(shell, &r->s_hd); while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } s = next_s; } /* kill zero length edgeuses */ if (!empty_region) { empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); } if (!empty_region && !empty_model) { process_triangulation(r, pathp, tsp); regions_written++; } if (!empty_model) nmg_kr(r); } /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * and there is no point to adding _another_ message to our output, * so we need to cons up an OP_NOP node to return. */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ BU_ALLOC(curtree, union tree); RT_TREE_INIT(curtree); curtree->tr_op = OP_NOP; return curtree; }
/* routine to output the faceted NMG representation of a BRL-CAD region */ static void output_nmg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id)) { struct model *m; struct shell *s; struct vertex *v; char *region_name; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &tol); /* Output triangles */ if (verbose) { printf("Convert these triangles to your format for region %s\n", region_name); } else { printf("Converted %s\n", region_name); } for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; /* vect_t facet_normal; */ NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; /* Grab the face normal if needed */ /* NMG_GET_FU_NORMAL(facet_normal, fu); */ for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* loop through the edges in this loop (facet) */ if (verbose) printf("\tfacet:\n"); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); if (verbose) printf("\t\t(%g %g %g)\n", V3ARGS(v->vg_p->coord)); } tot_polygons++; } } } bu_free(region_name, "region name"); }
void nmg_2_vrml(struct db_tree_state *tsp, const struct db_full_path *pathp, struct model *m) { struct mater_info *mater = &tsp->ts_mater; const struct bn_tol *tol2 = tsp->ts_tol; struct nmgregion *reg; struct bu_ptbl verts; struct vrml_mat mat; struct bu_vls vls = BU_VLS_INIT_ZERO; char *tok; int i; int first = 1; int is_light = 0; point_t ave_pt = VINIT_ZERO; struct bu_vls shape_name = BU_VLS_INIT_ZERO; char *full_path; /* There may be a better way to capture the region_id, than * getting the rt_comb_internal structure, (and may be a better * way to capture the rt_comb_internal struct), but for now I just * copied the method used in select_lights/select_non_lights above, * could have used a global variable but I noticed none other were * used, so I didn't want to be the first */ struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; /* static due to libbu exception handling */ static float r, g, b; NMG_CK_MODEL(m); full_path = db_path_to_string(pathp); RT_CK_FULL_PATH(pathp); dp = DB_FULL_PATH_CUR_DIR(pathp); if (!(dp->d_flags & RT_DIR_COMB)) { return; } id = rt_db_get_internal(&intern, dp, dbip, (matp_t)NULL, &rt_uniresource); if (id < 0) { bu_log("Cannot internal form of %s\n", dp->d_namep); return; } if (id != ID_COMBINATION) { bu_log("Directory/database mismatch!\n\t is '%s' a combination or not?\n", dp->d_namep); return; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); if (mater->ma_color_valid) { r = mater->ma_color[0]; g = mater->ma_color[1]; b = mater->ma_color[2]; } else { r = g = b = 0.5; } if (mater->ma_shader) { tok = strtok(mater->ma_shader, tok_sep); bu_strlcpy(mat.shader, tok, TXT_NAME_SIZE); } else { mat.shader[0] = '\0'; } mat.shininess = -1; mat.transparency = -1.0; mat.lt_fraction = -1.0; VSETALL(mat.lt_dir, 0.0); mat.lt_angle = -1.0; mat.tx_file[0] = '\0'; mat.tx_w = -1; mat.tx_n = -1; bu_vls_strcpy(&vls, &mater->ma_shader[strlen(mat.shader)]); (void)bu_struct_parse(&vls, vrml_mat_parse, (char *)&mat, NULL); if (bu_strncmp("light", mat.shader, 5) == 0) { /* this is a light source */ is_light = 1; } else { path_2_vrml_id(&shape_name, full_path); fprintf(fp_out, "\t\tDEF %s Shape {\n", bu_vls_addr(&shape_name)); fprintf(fp_out, "\t\t\t# Component_ID: %ld %s\n", comb->region_id, full_path); fprintf(fp_out, "\t\t\tappearance Appearance {\n"); if (bu_strncmp("plastic", mat.shader, 7) == 0) { if (mat.shininess < 0) { mat.shininess = 10; } if (mat.transparency < SMALL_FASTF) { mat.transparency = 0.0; } fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b); fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0)); if (mat.transparency > SMALL_FASTF) { fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency); } fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0); } else if (bu_strncmp("glass", mat.shader, 5) == 0) { if (mat.shininess < 0) { mat.shininess = 4; } if (mat.transparency < SMALL_FASTF) { mat.transparency = 0.8; } fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b); fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0)); if (mat.transparency > SMALL_FASTF) { fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency); } fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0); } else if (bu_strncmp("texture", mat.shader, 7) == 0) { if (mat.tx_w < 0) { mat.tx_w = 512; } if (mat.tx_n < 0) { mat.tx_n = 512; } if (strlen(mat.tx_file)) { int tex_fd; unsigned char tex_buf[TXT_BUF_LEN * 3]; if ((tex_fd = open(mat.tx_file, O_RDONLY | O_BINARY)) == (-1)) { bu_log("Cannot open texture file (%s)\n", mat.tx_file); perror("g-vrml: "); } else { long tex_len; long bytes_read = 0; long bytes_to_go = 0; /* Johns note - need to check (test) the texture stuff */ fprintf(fp_out, "\t\t\t\ttextureTransform TextureTransform {\n"); fprintf(fp_out, "\t\t\t\t\tscale 1.33333 1.33333\n\t\t\t\t}\n"); fprintf(fp_out, "\t\t\t\ttexture PixelTexture {\n"); fprintf(fp_out, "\t\t\t\t\trepeatS TRUE\n"); fprintf(fp_out, "\t\t\t\t\trepeatT TRUE\n"); fprintf(fp_out, "\t\t\t\t\timage %d %d %d\n", mat.tx_w, mat.tx_n, 3); tex_len = mat.tx_w*mat.tx_n * 3; while (bytes_read < tex_len) { int nbytes; long readval; bytes_to_go = tex_len - bytes_read; CLAMP(bytes_to_go, 0, TXT_BUF_LEN * 3); nbytes = 0; while (nbytes < bytes_to_go) { readval = read(tex_fd, &tex_buf[nbytes], bytes_to_go-nbytes); if (readval < 0) { perror("READ ERROR"); break; } else { nbytes += readval; } } bytes_read += nbytes; for (i = 0; i < nbytes; i += 3) { fprintf(fp_out, "\t\t\t0x%02x%02x%02x\n", tex_buf[i], tex_buf[i+1], tex_buf[i+2]); } } fprintf(fp_out, "\t\t\t\t}\n"); close(tex_fd); } } } else if (mater->ma_color_valid) { /* no shader specified, but a color is assigned */ fprintf(fp_out, "\t\t\t\tmaterial Material {\n"); fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g }\n", r, g, b); } else { /* If no color was defined set the colors according to the thousands groups */ int thou = comb->region_id / 1000; thou == 0 ? fprintf(fp_out, "\t\t\tmaterial USE Material_999\n") : thou == 1 ? fprintf(fp_out, "\t\t\tmaterial USE Material_1999\n") : thou == 2 ? fprintf(fp_out, "\t\t\tmaterial USE Material_2999\n") : thou == 3 ? fprintf(fp_out, "\t\t\tmaterial USE Material_3999\n") : thou == 4 ? fprintf(fp_out, "\t\t\tmaterial USE Material_4999\n") : thou == 5 ? fprintf(fp_out, "\t\t\tmaterial USE Material_5999\n") : thou == 6 ? fprintf(fp_out, "\t\t\tmaterial USE Material_6999\n") : thou == 7 ? fprintf(fp_out, "\t\t\tmaterial USE Material_7999\n") : thou == 8 ? fprintf(fp_out, "\t\t\tmaterial USE Material_8999\n") : fprintf(fp_out, "\t\t\tmaterial USE Material_9999\n"); } } if (!is_light) { nmg_triangulate_model(m, tol2); fprintf(fp_out, "\t\t\t}\n"); fprintf(fp_out, "\t\t\tgeometry IndexedFaceSet {\n"); fprintf(fp_out, "\t\t\t\tcoord Coordinate {\n"); } /* get list of vertices */ nmg_vertex_tabulate(&verts, &m->magic); if (!is_light) { fprintf(fp_out, "\t\t\t\t\tpoint ["); } else { VSETALL(ave_pt, 0.0); } for (i = 0; i < BU_PTBL_END(&verts); i++) { struct vertex *v; struct vertex_g *vg; point_t pt_meters; v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); vg = v->vg_p; NMG_CK_VERTEX_G(vg); /* convert to desired units */ VSCALE(pt_meters, vg->coord, scale_factor); if (is_light) { VADD2(ave_pt, ave_pt, pt_meters); } if (first) { if (!is_light) { fprintf(fp_out, " %10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i); } first = 0; } else if (!is_light) { fprintf(fp_out, "\t\t\t\t\t%10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i); } } if (!is_light) { fprintf(fp_out, "\t\t\t\t\t]\n\t\t\t\t}\n"); } else { fastf_t one_over_count; one_over_count = 1.0/(fastf_t)BU_PTBL_END(&verts); VSCALE(ave_pt, ave_pt, one_over_count); } first = 1; if (!is_light) { fprintf(fp_out, "\t\t\t\tcoordIndex [\n"); for (BU_LIST_FOR(reg, nmgregion, &m->r_hd)) { struct shell *s; NMG_CK_REGION(reg); for (BU_LIST_FOR(s, shell, ®->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) { continue; } for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) { continue; } if (!first) { fprintf(fp_out, ",\n"); } else { first = 0; } fprintf(fp_out, "\t\t\t\t\t"); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { struct vertex *v; NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(fp_out, " %d,", bu_ptbl_locate(&verts, (long *)v)); } fprintf(fp_out, "-1"); } } } } fprintf(fp_out, "\n\t\t\t\t]\n\t\t\t\tnormalPerVertex FALSE\n"); fprintf(fp_out, "\t\t\t\tconvex FALSE\n"); fprintf(fp_out, "\t\t\t\tcreaseAngle 0.5\n"); fprintf(fp_out, "\t\t\t}\n\t\t}\n"); } else {
/* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree * do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { union tree *ret_tree = NULL; struct bu_list vhead; /* static due to longjmp */ static struct nmgregion *r = NULL; RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) { char *sofar = db_path_to_string(pathp); bu_log("\ndo_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; /* do the deed */ ret_tree = process_region(pathp, curtree, tsp); if (ret_tree) r = ret_tree->tr_d.td_r; else { if (verbose) { printf("\tNothing left of this region after Boolean evaluation\n"); fprintf(fpe, "WARNING: Nothing left after Boolean evaluation: %s\n", db_path_to_string(pathp)); fflush(fpe); } regions_written++; /* don't count as a failure */ r = (struct nmgregion *)NULL; } regions_converted++; if (r != (struct nmgregion *)NULL) { struct shell *s; int empty_region=0; int empty_model=0; /* Kill cracks */ s = BU_LIST_FIRST(shell, &r->s_hd); while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } s = next_s; } /* kill zero length edgeuses */ if (!empty_region) { empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); } if (!empty_region && !empty_model) { if (!BU_SETJUMP) { /* try */ /* Write the region to the TANKILL file */ nmg_to_acad(r, pathp, tsp->ts_regionid); regions_written++; } else { /* catch */ char *sofar; BU_UNSETJUMP; sofar = db_path_to_string(pathp); bu_free((char *)sofar, "sofar"); /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before bombing out. */ RTG.NMG_debug = NMG_debug; /* restore mode */ /* Release any intersector 2d tables */ nmg_isect2d_final_cleanup(); /* Get rid of (m)any other intermediate structures */ if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC) { nmg_km(*tsp->ts_m); } else { bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n"); } /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); /* FIXME: leaking memory with curtree */ return TREE_NULL; } BU_UNSETJUMP; } if (!empty_model) nmg_kr(r); } /* * Dispose of original tree, so that all associated dynamic * memory is released now, not at the end of all regions. * A return of TREE_NULL from this routine signals an error, * and there is no point to adding _another_ message to our output, * so we need to cons up an OP_NOP node to return. */ if (regions_tried>0) { float npercent, tpercent; npercent = (float)(regions_converted * 100) / regions_tried; tpercent = (float)(regions_written * 100) / regions_tried; printf("Tried %d regions, %d conv. to NMG's %d conv. to tri. nmgper = %.2f%% triper = %.2f%% \n", regions_tried, regions_converted, regions_written, npercent, tpercent); } BU_ALLOC(curtree, union tree); RT_TREE_INIT(curtree); curtree->tr_op = OP_NOP; return curtree; }
static void nmg_to_obj(struct nmgregion *r, struct db_full_path *pathp, int region_id, int aircode, int los, int material_id) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; struct bu_ptbl norms; char *region_name; int numverts = 0; /* Number of vertices to output */ int numtri = 0; /* Number of triangles to output */ int i; NMG_CK_REGION( r ); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string( pathp ); #if 0 printf("Attempting to process region %s\n", region_name); fflush(stdout); #endif m = r->m_p; NMG_CK_MODEL( m ); /* triangulate model */ nmg_triangulate_model( m, &tol ); /* list all vertices in result */ nmg_vertex_tabulate( &verts, &r->l.magic ); /* Get number of vertices */ numverts = BU_PTBL_END (&verts); /* get list of vertexuse normals */ if ( do_normals ) nmg_vertexuse_normal_tabulate( &norms, &r->l.magic ); /* XXX Check vertices, shells faces first? Do not want to punt mid-stream */ /* BEGIN CHECK SECTION */ /* Check vertices */ for ( i=0; i<numverts; i++ ) { v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); } /* Check triangles */ for ( BU_LIST_FOR( s, shell, &r->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; /* check vertex numbers for each triangle */ for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); vert_count++; i = bu_ptbl_locate( &verts, (long *)v ); if ( i < 0 ) { /*XXX*/ bu_ptbl_free( &verts); /*XXX*/ bu_free( region_name, "region name" ); bu_log( "Vertex from eu x%x is not in nmgregion x%x\n", eu, r ); bu_exit(1, "ERROR: Can't find vertex in list!"); } } if ( vert_count > 3 ) { /*XXX*/ bu_ptbl_free( &verts); /*XXX*/ bu_free( region_name, "region name" ); bu_log( "lu x%x has %d vertices!\n", lu, vert_count ); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if ( vert_count < 3 ) continue; numtri++; } } } /* END CHECK SECTION */ /* Write pertinent info for this region */ if ( usemtl ) fprintf( fp, "usemtl %d_%d_%d\n", aircode, los, material_id ); fprintf( fp, "g %s", pathp->fp_names[0]->d_namep ); for ( i=1; i<pathp->fp_len; i++ ) fprintf( fp, "/%s", pathp->fp_names[i]->d_namep ); fprintf( fp, "\n" ); /* Write vertices */ for ( i=0; i<numverts; i++ ) { v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); if (inches) fprintf( fp, "v %f %f %f\n", V3ARGSIN( v->vg_p->coord )); else fprintf( fp, "v %f %f %f\n", V3ARGS( v->vg_p->coord )); } /* Write vertexuse normals */ if ( do_normals ) { for ( i=0; i<BU_PTBL_END( &norms ); i++ ) { struct vertexuse_a_plane *va; va = (struct vertexuse_a_plane *)BU_PTBL_GET( &norms, i ); NMG_CK_VERTEXUSE_A_PLANE( va ); if (inches) fprintf( fp, "vn %f %f %f\n", V3ARGSIN( va->N )); else fprintf( fp, "vn %f %f %f\n", V3ARGS( va->N )); } } /* output triangles */ for ( BU_LIST_FOR( s, shell, &r->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; int vert_count=0; int use_normals=1; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; /* Each vertexuse of the face must have a normal in order * to use the normals in Wavefront */ if ( do_normals ) { for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); if ( !eu->vu_p->a.magic_p ) { use_normals = 0; break; } if ( *eu->vu_p->a.magic_p != NMG_VERTEXUSE_A_PLANE_MAGIC ) { use_normals = 0; break; } } } else use_normals = 0; fprintf( fp, "f" ); /* list vertex numbers for each triangle */ for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); vert_count++; i = bu_ptbl_locate( &verts, (long *)v ); if ( i < 0 ) { bu_ptbl_free( &verts); bu_log( "Vertex from eu x%x is not in nmgregion x%x\n", eu, r ); /*XXX*/ bu_free( region_name, "region name" ); /*XXX*/ bu_exit(1, "Can't find vertex in list!\n"); } if ( use_normals ) { int j; j = bu_ptbl_locate( &norms, (long *)eu->vu_p->a.magic_p ); fprintf( fp, " %ld//%ld", i+1+vert_offset, j+1+norm_offset ); } else fprintf( fp, " %ld", i+1+vert_offset ); } fprintf( fp, "\n" ); if ( vert_count > 3 ) { bu_ptbl_free( &verts); bu_free( region_name, "region name" ); bu_log( "lu x%x has %d vertices!\n", lu, vert_count ); bu_exit(1, "ERROR: LU is not a triangle\n" ); } } } }
static void nmg_to_acad(struct nmgregion *r, const struct db_full_path *pathp, int region_id) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; char *region_name; int numverts = 0; /* Number of vertices to output */ int numtri = 0; /* Number of triangles to output */ int tricount = 0; /* Triangle number */ int i; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &tol); /* list all vertices in result */ nmg_vertex_tabulate(&verts, &r->l.magic); /* Get number of vertices */ numverts = BU_PTBL_END (&verts); /* BEGIN CHECK SECTION */ /* Check vertices */ for (i=0; i<numverts; i++) { v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); } /* Check triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* check vertex numbers for each triangle */ for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); vert_count++; i = bu_ptbl_locate(&verts, (long *)v); if (i < 0) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("Vertex from eu %p is not in nmgregion %p\n", (void *)eu, (void *)r); bu_exit(1, "ERROR: Triangle vertex was not located\n"); } } if (vert_count > 3) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("lu %p has too many (%d) vertices!\n", (void *)lu, vert_count); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if (vert_count < 3) continue; numtri++; } } } /* END CHECK SECTION */ /* Write pertinent info for this region */ fprintf(fp, "%s\n", (region_name+1)); /* No mirror plane */ fprintf(fp, "%d\n", 0); /* Number of vertices */ fprintf(fp, "%d\n", numverts); /* Write numverts, then vertices */ for (i=0; i<numverts; i++) { v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); if (inches) fprintf(fp, "%f %f %f\n", V3ARGSIN(v->vg_p->coord)); else fprintf(fp, "%f %f %f\n", V3ARGS(v->vg_p->coord)); } /* Number of sub-parts (always 1 with BRL-CAD) */ fprintf(fp, "%d\n", 1); /* Write out name again */ fprintf(fp, "%s\n", (region_name+1)); /* Number of triangles, number of vert/tri (3) */ fprintf(fp, "%d %d\n", numtri, 3); /* output triangles */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; int vert_count=0; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* list vertex numbers for each triangle */ for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); vert_count++; i = bu_ptbl_locate(&verts, (long *)v); if (i < 0) { bu_ptbl_free(&verts); bu_log("Vertex from eu %p is not in nmgregion %p\n", (void *)eu, (void *)r); bu_free(region_name, "region name"); bu_exit(1, "ERROR: Can't find vertex in list!\n"); } fprintf(fp, " %d", i+1); } /* Output other info. for triangle ICOAT, component#, facet# */ /* Map Icoat from material table later */ /* fprintf(fp, "%s icomp=%d material=%d:\n", (region_name+1), region_id);*/ fprintf(fp, " %d %d %d\n", 0, region_id, ++tricount); if (vert_count > 3) { bu_ptbl_free(&verts); bu_free(region_name, "region name"); bu_log("lu %p has %d vertices!\n", (void *)lu, vert_count); bu_exit(1, "ERROR: LU is not a triangle\n"); } else if (vert_count < 3) continue; tot_polygons++; } } } /* regions_converted++; printf("Processed region %s\n", region_name); printf("Regions attempted = %d Regions done = %d\n", regions_tried, regions_converted); fflush(stdout); */ bu_ptbl_free(&verts); bu_free(region_name, "region name"); }
union tree * gcv_region_end_mc(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { union tree *tp = NULL; struct model *m = NULL; struct nmgregion *r = NULL; struct shell *s = NULL; struct bu_list vhead; int empty_region = 0; int empty_model = 0; int NMG_debug_state = 0; int count = 0; void (*write_region)(struct nmgregion *, const struct db_full_path *, int, int, float [3]); if (!tsp || !pathp || !client_data) { bu_log("INTERNAL ERROR: gcv_region_end_mc missing parameters\n"); return TREE_NULL; } write_region = ((struct gcv_data *)client_data)->func; if (!write_region) { bu_log("INTERNAL ERROR: gcv_region_end missing conversion callback function\n"); return TREE_NULL; } RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); /* if (curtree->tr_op == OP_NOP) return 0; */ /* get a copy to play with as the parameters might get clobbered * by a longjmp. FIXME: db_dup_subtree() doesn't create real copies */ tp = db_dup_subtree(curtree, &rt_uniresource); /* FIXME: we can't free curtree until we get a "real" copy form * db_dup_subtree(). right now we get a fake copy just so we can * keep the compiler quiet about clobbering curtree during longjmp */ /* db_free_tree(curtree, &rt_uniresource); */ /* Sometimes the NMG library adds debugging bits when it detects * an internal error, before bombing. Stash. */ NMG_debug_state = RTG.NMG_debug; m = nmg_mmr(); r = nmg_mrsv(m); s = BU_LIST_FIRST(shell, &r->s_hd); if (tsp->ts_rtip == NULL) tsp->ts_rtip = rt_new_rti(tsp->ts_dbip); count += nmg_mc_evaluate (s, tsp->ts_rtip, pathp, tsp->ts_ttol, tsp->ts_tol); /* empty region? */ if (count == 0) { bu_log("Region %s appears to be empty.\n", db_path_to_string(pathp)); return TREE_NULL; } /* bu_log("Target is shot, %d triangles seen.\n", count); bu_log("Fusing\n"); fflush(stdout); nmg_model_fuse(m, tsp->ts_tol); bu_log("Done\n"); fflush(stdout); */ /* Kill cracks */ while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } /* nmg_shell_coplanar_face_merge(s, tsp->ts_tol, 42); */ s = next_s; } if (empty_region) return _gcv_cleanup(NMG_debug_state, tp); /* kill zero length edgeuses */ empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); if (empty_model) return _gcv_cleanup(NMG_debug_state, tp); if (BU_SETJUMP) { /* Error, bail out */ char *sofar; /* Relinquish bomb protection */ BU_UNSETJUMP; sofar = db_path_to_string(pathp); bu_log("FAILED in triangulator: %s\n", sofar); bu_free((char *)sofar, "sofar"); /* Release any intersector 2d tables */ nmg_isect2d_final_cleanup(); /* Get rid of (m)any other intermediate structures */ if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC) nmg_km(*tsp->ts_m); else bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n"); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); nmg_kr(r); return _gcv_cleanup(NMG_debug_state, tp); } else { /* Write the region out */ write_region(r, pathp, tsp->ts_regionid, tsp->ts_gmater, tsp->ts_mater.ma_color); } BU_UNSETJUMP; /* Relinquish bomb protection */ nmg_kr(r); return _gcv_cleanup(NMG_debug_state, tp); }
static void nmg_to_egg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id), float UNUSED(color[3]), void *client_data) { struct model *m; struct shell *s; struct vertex *v; char *region_name; int region_polys=0; int vert_count=0; struct egg_conv_data *conv_data = (struct egg_conv_data *)client_data; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* triangulate model */ nmg_triangulate_model(m, &conv_data->tol); /* Write pertinent info for this region */ fprintf(conv_data->fp, " <VertexPool> %s {\n", (region_name+1)); /* Build the VertexPool */ for (BU_LIST_FOR (s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) { struct loopuse *lu; vect_t facet_normal; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; /* Grab the face normal and save it for all the vertex loops */ NMG_GET_FU_NORMAL(facet_normal, fu); for (BU_LIST_FOR (lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; /* check vertex numbers for each triangle */ for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); vert_count++; v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(conv_data->fp, " <Vertex> %d {\n %f %f %f\n <Normal> { %f %f %f }\n }\n", vert_count, V3ARGS(v->vg_p->coord), V3ARGS(facet_normal)); } } } } fprintf(conv_data->fp, " }\n"); vert_count = 0; for (BU_LIST_FOR (s, shell, &r->s_hd)) { struct faceuse *fu; NMG_CK_SHELL(s); for (BU_LIST_FOR (fu, faceuse, &s->fu_hd)) { struct loopuse *lu; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR (lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; fprintf(conv_data->fp, " <Polygon> { \n <RGBA> { 1 1 1 1 } \n <VertexRef> { "); /* check vertex numbers for each triangle */ for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) { NMG_CK_EDGEUSE(eu); vert_count++; v = eu->vu_p->v_p; NMG_CK_VERTEX(v); fprintf(conv_data->fp, " %d", vert_count); } fprintf(conv_data->fp, " <Ref> { \"%s\" } }\n }\n", region_name+1); region_polys++; } } } conv_data->tot_polygons += region_polys; bu_free(region_name, "region name"); }
void nmg_2_vrml(FILE *fp, const struct db_full_path *pathp, struct model *m, struct mater_info *mater) { struct nmgregion *reg; struct bu_ptbl verts; struct vrml_mat mat; struct bu_vls vls = BU_VLS_INIT_ZERO; char *tok; int i; int first=1; int is_light=0; float r, g, b; point_t ave_pt; char *full_path; /*There may be a better way to capture the region_id, than getting the rt_comb_internal structure, * (and may be a better way to capture the rt_comb_internal struct), but for now I just copied the * method used in select_lights/select_non_lights above, could have used a global variable but I noticed * none other were used, so I didn't want to be the first */ struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; NMG_CK_MODEL( m ); BARRIER_CHECK; full_path = db_path_to_string( pathp ); /* replace all occurrences of '.' with '_' */ char_replace(full_path, '.', '_'); RT_CK_FULL_PATH( pathp ); dp = DB_FULL_PATH_CUR_DIR( pathp ); if ( !(dp->d_flags & RT_DIR_COMB) ) return; id = rt_db_get_internal( &intern, dp, dbip, (matp_t)NULL, &rt_uniresource ); if ( id < 0 ) { bu_log( "Cannot internal form of %s\n", dp->d_namep ); return; } if ( id != ID_COMBINATION ) { bu_log( "Directory/database mismatch!\n\t is '%s' a combination or not?\n", dp->d_namep ); return; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB( comb ); if ( mater->ma_color_valid ) { r = mater->ma_color[0]; g = mater->ma_color[1]; b = mater->ma_color[2]; } else { r = g = b = 0.5; } if ( mater->ma_shader ) { tok = strtok( mater->ma_shader, tok_sep ); bu_strlcpy( mat.shader, tok, TXT_NAME_SIZE ); } else mat.shader[0] = '\0'; mat.shininess = -1; mat.transparency = -1.0; mat.lt_fraction = -1.0; VSETALL( mat.lt_dir, 0.0 ); mat.lt_angle = -1.0; mat.tx_file[0] = '\0'; mat.tx_w = -1; mat.tx_n = -1; bu_vls_strcpy( &vls, &mater->ma_shader[strlen(mat.shader)] ); (void)bu_struct_parse( &vls, vrml_mat_parse, (char *)&mat, NULL); if ( bu_strncmp( "light", mat.shader, 5 ) == 0 ) { /* this is a light source */ is_light = 1; } else { fprintf( fp, "\t<Shape DEF=\"%s\">\n", full_path); fprintf( fp, "\t\t<Appearance>\n"); if ( bu_strncmp( "plastic", mat.shader, 7 ) == 0 ) { if ( mat.shininess < 0 ) mat.shininess = 10; V_MAX(mat.transparency, 0.0); fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0); } else if ( bu_strncmp( "glass", mat.shader, 5 ) == 0 ) { if ( mat.shininess < 0 ) mat.shininess = 4; if ( mat.transparency < 0.0 ) mat.transparency = 0.8; fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0); } else if ( mater->ma_color_valid ) { fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\"/>\n", r, g, b); } else { /* If no color was defined set the colors according to the thousands groups */ int thou = comb->region_id/1000; thou == 0 ? fprintf( fp, "\t\t\t<Material USE=\"Material_999\"/>\n") : thou == 1 ? fprintf( fp, "\t\t\t<Material USE=\"Material_1999\"/>\n") : thou == 2 ? fprintf( fp, "\t\t\t<Material USE=\"Material_2999\"/>\n") : thou == 3 ? fprintf( fp, "\t\t\t<Material USE=\"Material_3999\"/>\n") : thou == 4 ? fprintf( fp, "\t\t\t<Material USE=\"Material_4999\"/>\n") : thou == 5 ? fprintf( fp, "\t\t\t<Material USE=\"Material_5999\"/>\n") : thou == 6 ? fprintf( fp, "\t\t\t<Material USE=\"Material_6999\"/>\n") : thou == 7 ? fprintf( fp, "\t\t\t<Material USE=\"Material_7999\"/>\n") : thou == 8 ? fprintf( fp, "\t\t\t<Material USE=\"Material_8999\"/>\n") : fprintf( fp, "\t\t\t<Material USE=\"Material_9999\"/>\n"); } } if ( !is_light ) { process_non_light(m); fprintf( fp, "\t\t</Appearance>\n"); } /* FIXME: need code to handle light */ /* get list of vertices */ nmg_vertex_tabulate( &verts, &m->magic ); fprintf( fp, "\t\t<IndexedFaceSet coordIndex=\"\n"); first = 1; if ( !is_light ) { for ( BU_LIST_FOR( reg, nmgregion, &m->r_hd ) ) { struct shell *s; NMG_CK_REGION( reg ); for ( BU_LIST_FOR( s, shell, ®->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; if ( !first ) fprintf( fp, ",\n" ); else first = 0; fprintf( fp, "\t\t\t\t" ); for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { struct vertex *v; NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); fprintf( fp, " %d,", bu_ptbl_locate( &verts, (long *)v ) ); } fprintf( fp, "-1" ); } } } } /* close coordIndex */ fprintf( fp, "\" "); fprintf( fp, "normalPerVertex=\"false\" "); fprintf( fp, "convex=\"false\" "); fprintf( fp, "creaseAngle=\"0.5\" "); /* close IndexedFaceSet open tag */ fprintf( fp, ">\n"); } fprintf( fp, "\t\t\t<Coordinate point=\""); for ( i=0; i<BU_PTBL_END( &verts ); i++ ) { struct vertex *v; struct vertex_g *vg; point_t pt_meters; v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); vg = v->vg_p; NMG_CK_VERTEX_G( vg ); /* convert to desired units */ VSCALE( pt_meters, vg->coord, scale_factor ); if ( is_light ) VADD2( ave_pt, ave_pt, pt_meters ); if ( first ) { if ( !is_light ) fprintf( fp, " %10.10e %10.10e %10.10e, ", V3ARGS(pt_meters)); first = 0; } else if ( !is_light ) fprintf( fp, "%10.10e %10.10e %10.10e, ", V3ARGS( pt_meters )); } /* close point */ fprintf(fp, "\""); /* close Coordinate */ fprintf(fp, "/>\n"); /* IndexedFaceSet end tag */ fprintf( fp, "\t\t</IndexedFaceSet>\n"); /* Shape end tag */ fprintf( fp, "\t</Shape>\n"); BARRIER_CHECK; }
void db_fullpath_to_vls(struct bu_vls *vls, const struct db_full_path *full_path, const struct db_i *dbip, int fp_flags) { size_t i; int type; const struct bn_tol tol = {BN_TOL_MAGIC, BN_TOL_DIST, BN_TOL_DIST * BN_TOL_DIST, 1e-6, 1.0 - 1e-6 }; BU_CK_VLS(vls); RT_CK_FULL_PATH(full_path); if (!full_path->fp_names[0]) { bu_vls_strcat(vls, "**NULL**"); return; } if ((fp_flags & DB_FP_PRINT_TYPE) && !dbip) { bu_log("Warning - requested object type printing, but dbip is NULL - object types will not be printed!"); } for (i = 0; i < full_path->fp_len; i++) { bu_vls_putc(vls, '/'); if (fp_flags & DB_FP_PRINT_BOOL) { switch (full_path->fp_bool[i]) { case 2: bu_vls_strcat(vls, "u "); break; case 3: bu_vls_strcat(vls, "+ "); break; case 4: bu_vls_strcat(vls, "- "); break; } } if (fp_flags & DB_FP_PRINT_MATRIX) { if (full_path->fp_mat[i]) { bu_vls_strcat(vls, "(M)"); } } bu_vls_strcat(vls, full_path->fp_names[i]->d_namep); if ((fp_flags & DB_FP_PRINT_TYPE) && dbip) { struct rt_db_internal intern; if (!(rt_db_get_internal(&intern, full_path->fp_names[i], dbip, NULL, &rt_uniresource) < 0)) { if (intern.idb_meth->ft_label) { bu_vls_putc(vls, '('); switch (intern.idb_minor_type) { case DB5_MINORTYPE_BRLCAD_ARB8: type = rt_arb_std_type(&intern, &tol); switch (type) { case 4: bu_vls_strcat(vls, "arb4"); break; case 5: bu_vls_strcat(vls, "arb5"); break; case 6: bu_vls_strcat(vls, "arb6"); break; case 7: bu_vls_strcat(vls, "arb7"); break; case 8: bu_vls_strcat(vls, "arb8"); break; default: break; } break; case DB5_MINORTYPE_BRLCAD_COMBINATION: if (full_path->fp_names[i]->d_flags & RT_DIR_REGION) { bu_vls_putc(vls, 'r'); } else { bu_vls_putc(vls, 'c'); } break; default: bu_vls_strcat(vls, intern.idb_meth->ft_label); break; } } bu_vls_putc(vls, ')'); rt_db_free_internal(&intern); } } } }