/* 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; }
static union tree * leaf_stub(struct db_tree_state *tsp, struct db_full_path *pathp, struct rt_db_internal *ip, genptr_t client_data) { struct directory *fp_name; /* name from pathp */ fp_name = DB_FULL_PATH_CUR_DIR( pathp ); bu_log( "Only regions may be converted to TANKILL format\n\t%s is not a region and will be ignored\n", fp_name->d_namep ); return( (union tree *)NULL ); }
/* stubs to warn of the unexpected */ static union tree * region_stub(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data) { struct directory *fp_name; /* name from pathp */ fp_name = DB_FULL_PATH_CUR_DIR( pathp ); bu_log( "region stub called (for object %s), this shouldn't happen\n", fp_name->d_namep ); return( (union tree *)NULL ); }
/** * 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; } }
int cyclic_path(const struct db_full_path *fp, const char *name) { /* skip the last one added since it is currently being tested. */ long int depth = fp->fp_len - 1; const char *test_name; if (name && !name[0] == '\0') { test_name = name; } else { test_name = DB_FULL_PATH_CUR_DIR(fp)->d_namep; } /* check the path to see if it is groundhog day */ while (--depth >= 0) { if (BU_STR_EQUAL(test_name, fp->fp_names[depth]->d_namep)) { return 1; } } /* not cyclic */ return 0; }
/** * @brief This routine is called when a region is first encountered in the * hierarchy when processing a tree * * @param tsp tree state (for parsing the tree) * @param pathp A listing of all the nodes traversed to get to this node in the database * @param combp the combination record for this region */ int region_start(struct db_tree_state *tsp, const struct db_full_path *pathp, const struct rt_comb_internal *combp, void *client_data) { char *name; struct directory *dp; struct bu_vls str = BU_VLS_INIT_ZERO; struct user_data *your_stuff = (struct user_data *)client_data; RT_CK_DBTS(tsp); name = db_path_to_string(pathp); bu_log("region_start %s\n", name); bu_free(name, "reg_start name"); bu_log("data = %ld\n", your_stuff->data); rt_pr_tol(&your_stuff->tol); dp = DB_FULL_PATH_CUR_DIR(pathp); /* here is where the conversion should be done */ if (combp->region_flag) printf("Write this region (name=%s) as a part in your format:\n", dp->d_namep); else printf("Write this combination (name=%s) as an assembly in your format:\n", dp->d_namep); describe_tree(combp->tree, &str); printf("\t%s\n\n", bu_vls_addr(&str)); bu_vls_free(&str); return 0; }
/* * D O _ R E G I O N _ E N D * * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree *do_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data) { union tree *ret_tree; struct nmgregion *r; struct bu_list vhead; 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_done * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; /* Begin bomb protection */ if ( ncpu == 1 ) { if ( BU_SETJUMP ) { /* Error, bail out */ BU_UNSETJUMP; /* Relinquish the protection */ /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before bombing out. */ rt_g.NMG_debug = NMG_debug; /* restore mode */ /* Release the tree memory & input regions */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ /* Get rid of (m)any other intermediate structures */ if ( (*tsp->ts_m)->magic != -1L ) nmg_km(*tsp->ts_m); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); goto out; } } (void)nmg_model_fuse(*tsp->ts_m, tsp->ts_tol); ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource); /* librt/nmg_bool.c */ BU_UNSETJUMP; /* Relinquish the protection */ if ( ret_tree ) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; regions_done++; if (r != 0) { FILE *fp_psurf; int i; struct bu_vls file_base; struct bu_vls file; bu_vls_init(&file_base); bu_vls_init(&file); bu_vls_strcpy(&file_base, prefix); bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep); /* Dots confuse Jack's Peabody language. Change to '_'. */ for (i = 0; i < file_base.vls_len; i++) if (file_base.vls_str[i] == '.') file_base.vls_str[i] = '_'; /* Write color attribute to .fig figure file. */ if (tsp->ts_mater.ma_color_valid != 0) { fprintf(fp_fig, "\tattribute %s {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n", V3ARGS(tsp->ts_mater.ma_color)); fprintf(fp_fig, "\t\tambient = 0.18;\n"); fprintf(fp_fig, "\t\tdiffuse = 0.72;\n"); fprintf(fp_fig, "\t}\n"); } /* Write segment attributes to .fig figure file. */ fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base)); if (tsp->ts_mater.ma_color_valid != 0) fprintf(fp_fig, "\t\tattribute=%s;\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n"); fprintf(fp_fig, "\t}\n"); if ( bu_vls_strlen(&base_seg) <= 0 ) { bu_vls_vlscat( &base_seg, &file_base ); } else { fprintf(fp_fig, "\tjoint %s_jt {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tconnect %s_seg.base to %s_seg.base;\n", bu_vls_addr(&file_base), bu_vls_addr(&base_seg) ); fprintf(fp_fig, "\t}\n"); } bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pss"); /* Required Jack suffix. */ /* Write psurf to .pss file. */ if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { nmg_to_psurf(r, fp_psurf); fclose(fp_psurf); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); /* Also write as UNIX-plot file, if desired */ if ( debug_plots ) { FILE *fp; bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pl"); if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { struct bu_list vhead; pl_color( fp, (int)(tsp->ts_mater.ma_color[0] * 255), (int)(tsp->ts_mater.ma_color[1] * 255), (int)(tsp->ts_mater.ma_color[2] * 255) ); /* nmg_pl_r( fp, r ); */ BU_LIST_INIT( &vhead ); nmg_r_to_vlist( &vhead, r, 0 ); rt_vlist_to_uplot( fp, &vhead ); fclose(fp); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); } /* NMG region is no longer necessary */ 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, * so we need to cons up an OP_NOP node to return. */ db_free_tree(curtree, &rt_uniresource); /* Does an nmg_kr() */ out: BU_GETUNION(curtree, tree); curtree->magic = RT_TREE_MAGIC; curtree->tr_op = OP_NOP; return(curtree); }
/* * D O _ R E G I O N _ E N D * * 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, genptr_t UNUSED(client_data)) { union tree *ret_tree; struct nmgregion *r; RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); 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_done * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; ret_tree = process_boolean(curtree, tsp, pathp); if ( ret_tree ) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; regions_done++; if (r != 0) { FILE *fp_psurf; size_t i; struct bu_vls file_base = BU_VLS_INIT_ZERO; struct bu_vls file = BU_VLS_INIT_ZERO; bu_vls_strcpy(&file_base, prefix); bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep); /* Dots confuse Jack's Peabody language. Change to '_'. */ for (i = 0; i < file_base.vls_len; i++) if (file_base.vls_str[i] == '.') file_base.vls_str[i] = '_'; /* Write color attribute to .fig figure file. */ if (tsp->ts_mater.ma_color_valid != 0) { fprintf(fp_fig, "\tattribute %s {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n", V3ARGS(tsp->ts_mater.ma_color)); fprintf(fp_fig, "\t\tambient = 0.18;\n"); fprintf(fp_fig, "\t\tdiffuse = 0.72;\n"); fprintf(fp_fig, "\t}\n"); } /* Write segment attributes to .fig figure file. */ fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base)); if (tsp->ts_mater.ma_color_valid != 0) fprintf(fp_fig, "\t\tattribute=%s;\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n"); fprintf(fp_fig, "\t}\n"); if ( bu_vls_strlen(&base_seg) <= 0 ) { bu_vls_vlscat( &base_seg, &file_base ); } else { fprintf(fp_fig, "\tjoint %s_jt {\n", bu_vls_addr(&file_base)); fprintf(fp_fig, "\t\tconnect %s_seg.base to %s_seg.base;\n", bu_vls_addr(&file_base), bu_vls_addr(&base_seg) ); fprintf(fp_fig, "\t}\n"); } bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pss"); /* Required Jack suffix. */ /* Write psurf to .pss file. */ if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { nmg_to_psurf(r, fp_psurf); fclose(fp_psurf); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); /* Also write as UNIX-plot file, if desired */ if ( debug_plots ) { FILE *fp; bu_vls_vlscat(&file, &file_base); bu_vls_strcat(&file, ".pl"); if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL) perror(bu_vls_addr(&file)); else { struct bu_list vhead; pl_color( fp, (int)(tsp->ts_mater.ma_color[0] * 255), (int)(tsp->ts_mater.ma_color[1] * 255), (int)(tsp->ts_mater.ma_color[2] * 255) ); /* nmg_pl_r( fp, r ); */ BU_LIST_INIT( &vhead ); nmg_r_to_vlist( &vhead, r, 0 ); rt_vlist_to_uplot( fp, &vhead ); fclose(fp); if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file)); } bu_vls_free(&file); } /* NMG region is no longer necessary */ 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, * 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; }
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; }
/** * R T _ G E T T R E E _ L E A F * * This routine must be prepared to run in parallel. */ HIDDEN union tree *rt_gettree_leaf(struct db_tree_state *tsp, struct db_full_path *pathp, struct rt_db_internal *ip, genptr_t client_data) /*const*/ /*const*/ { register struct soltab *stp; union tree *curtree; struct directory *dp; register matp_t mat; int i; struct rt_i *rtip; RT_CK_DBTS(tsp); RT_CK_DBI(tsp->ts_dbip); RT_CK_FULL_PATH(pathp); RT_CK_DB_INTERNAL(ip); rtip = tsp->ts_rtip; RT_CK_RTI(rtip); RT_CK_RESOURCE(tsp->ts_resp); dp = DB_FULL_PATH_CUR_DIR(pathp); /* Determine if this matrix is an identity matrix */ if ( !bn_mat_is_equal(tsp->ts_mat, bn_mat_identity, &rtip->rti_tol)) { /* Not identity matrix */ mat = (matp_t)tsp->ts_mat; } else { /* Identity matrix */ mat = (matp_t)0; } /* * Check to see if this exact solid has already been processed. * Match on leaf name and matrix. Note that there is a race here * between having st_id filled in a few lines below (which is * necessary for calling ft_prep), and ft_prep filling in * st_aradius. Fortunately, st_aradius starts out as zero, and * will never go down to -1 unless this soltab structure has * become a dead solid, so by testing against -1 (instead of <= 0, * like before, oops), it isn't a problem. */ stp = rt_find_identical_solid( mat, dp, rtip ); if ( stp->st_id != 0 ) { /* stp is an instance of a pre-existing solid */ if ( stp->st_aradius <= -1 ) { /* It's dead, Jim. st_uses was not incremented. */ return( TREE_NULL ); /* BAD: instance of dead solid */ } goto found_it; } if ( rtip->rti_add_to_new_solids_list ) { bu_ptbl_ins( &rtip->rti_new_solids, (long *)stp ); } stp->st_id = ip->idb_type; stp->st_meth = &rt_functab[ip->idb_type]; if ( mat ) { mat = stp->st_matp; } else { mat = (matp_t)bn_mat_identity; } RT_CK_DB_INTERNAL( ip ); /* init solid's maxima and minima */ VSETALL( stp->st_max, -INFINITY ); VSETALL( stp->st_min, INFINITY ); /* * If the ft_prep routine wants to keep the internal structure, * that is OK, as long as idb_ptr is set to null. Note that the * prep routine may have changed st_id. */ if ( stp->st_meth->ft_prep( stp, ip, rtip ) ) { int hash; /* Error, solid no good */ bu_log("rt_gettree_leaf(%s): prep failure\n", dp->d_namep ); /* Too late to delete soltab entry; mark it as "dead" */ hash = db_dirhash( dp->d_namep ); ACQUIRE_SEMAPHORE_TREE(hash); stp->st_aradius = -1; stp->st_uses--; RELEASE_SEMAPHORE_TREE(hash); return( TREE_NULL ); /* BAD */ } if ( rtip->rti_dont_instance ) { /* * If instanced solid refs are not being compressed, then * memory isn't an issue, and the application (such as * solids_on_ray) probably cares about the full path of this * solid, from root to leaf. So make it available here. * (stp->st_dp->d_uses could be the way to discriminate * references uniquely, if the path isn't enough. To locate * given dp and d_uses, search dp->d_use_hd list. Question * is, where to stash current val of d_uses?) */ db_full_path_init( &stp->st_path ); db_dup_full_path( &stp->st_path, pathp ); } else { /* * If there is more than just a direct reference to this leaf * from it's containing region, copy that below-region path * into st_path. Otherwise, leave st_path's magic number 0. * * XXX nothing depends on this behavior yet, and this whole * XXX 'else' clause might well be deleted. -Mike */ i = pathp->fp_len-1; if ( i > 0 && !(pathp->fp_names[i-1]->d_flags & DIR_REGION) ) { /* Search backwards for region. If no region, use whole path */ for ( --i; i > 0; i-- ) { if ( pathp->fp_names[i-1]->d_flags & DIR_REGION ) break; } if ( i < 0 ) i = 0; db_full_path_init( &stp->st_path ); db_dup_path_tail( &stp->st_path, pathp, i ); } } if (RT_G_DEBUG&DEBUG_TREEWALK && stp->st_path.magic == DB_FULL_PATH_MAGIC) { char *sofar = db_path_to_string(&stp->st_path); bu_log("rt_gettree_leaf() st_path=%s\n", sofar ); bu_free(sofar, "path string"); } if (RT_G_DEBUG&DEBUG_SOLIDS) { struct bu_vls str; bu_log("\n---Primitive %d: %s\n", stp->st_bit, dp->d_namep); bu_vls_init( &str ); /* verbose=1, mm2local=1.0 */ if ( stp->st_meth->ft_describe( &str, ip, 1, 1.0, tsp->ts_resp, tsp->ts_dbip ) < 0 ) { bu_log("rt_gettree_leaf(%s): solid describe failure\n", dp->d_namep ); } bu_log( "%s: %s", dp->d_namep, bu_vls_addr( &str ) ); bu_vls_free( &str ); } found_it: RT_GET_TREE( curtree, tsp->ts_resp ); curtree->magic = RT_TREE_MAGIC; curtree->tr_op = OP_SOLID; curtree->tr_a.tu_stp = stp; /* regionp will be filled in later by rt_tree_region_assign() */ curtree->tr_a.tu_regionp = (struct region *)0; if (RT_G_DEBUG&DEBUG_TREEWALK) { char *sofar = db_path_to_string(pathp); bu_log("rt_gettree_leaf() %s\n", sofar ); bu_free(sofar, "path string"); } return(curtree); }
/* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree * do_nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { union tree *result; struct nmgregion *r; struct bu_list vhead; struct directory *dp; int dependent; size_t i; 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_nmg_region_end(%d %d%%) %s\n", regions_tried, regions_tried>0 ? (regions_done * 100) / regions_tried : 0, sofar); bu_free(sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; regions_tried++; if (verbose) bu_log("\ndoing boolean tree evaluate...\n"); /* evaluate the boolean */ result = process_boolean(tsp, curtree, pathp); if (result) r = result->tr_d.td_r; else r = (struct nmgregion *)NULL; if (verbose) bu_log("\nfinished boolean tree evaluate...\n"); regions_done++; if (r != NULL) { dp = DB_FULL_PATH_CUR_DIR(pathp); if (multi_file) { /* Open the output file */ if (output_file == NULL) fp_dir = stdout; else { char *multi_name; size_t len; int unique = 0; char suffix[SUFFIX_LEN+1]; /* construct a unique file name */ len = strlen(output_file) + strlen(dp->d_namep) + 6 + SUFFIX_LEN; multi_name = (char *)bu_malloc(sizeof(char)*len, "multi_name"); snprintf(multi_name, len, "%s/%s.igs", output_file, dp->d_namep); bu_strlcpy(suffix, "a", sizeof(suffix)); suffix[0]--; while (!unique) { if (bu_file_readable(multi_name)) { unique = 1; break; } /* not unique, try adding a suffix */ len = strlen(suffix); i = len - 1; suffix[i]++; while (suffix[i] > 'z' && i > 0) { suffix[i] = 'a'; i--; suffix[i]++; } if (suffix[0] > 'z' && len < SUFFIX_LEN) { for (i = 0; i <= len; i++) suffix[i] = 'a'; } else if (suffix[0] > 'z' && len >= SUFFIX_LEN) { bu_log("too many files with the same name (%s)\n", dp->d_namep); bu_exit(1, "Cannot create a unique filename, \n"); } snprintf(multi_name, len, "%s/%s%s.igs", output_file, dp->d_namep, suffix); } if ((fp_dir = fopen(multi_name, "wb")) == NULL) { perror("g-iges"); bu_exit(1, "Cannot open output file: %s\n", multi_name); } } /* Open the temporary file for the parameter section */ if ((fp_param = bu_temp_file(NULL, 0)) == NULL) { perror("g-iges"); bu_exit(1, "Cannot open temporary file\n"); } /* let the IGES routines know the selected tolerances and the database pointer */ iges_init(&tol, &ttol, verbose, DBIP); /* Write start and global sections of the IGES file */ w_start_global(fp_dir, fp_param, db_name, prog_name, output_file, __DATE__, brlcad_version()); } if (mode == FACET_MODE) { dependent = 1; for (i = 0; i < no_of_indeps; i++) { if (!bu_strncmp(dp->d_namep, independent[i], NAMESIZE+1)) { dependent = 0; break; } } dp->d_uses = (-nmgregion_to_iges(dp->d_namep, r, dependent, fp_dir, fp_param)); } else if (mode == TRIMMED_SURF_MODE) dp->d_uses = (-nmgregion_to_tsurf(dp->d_namep, r, fp_dir, fp_param)); /* NMG region is no longer necessary */ nmg_kr(r); if (multi_file) { char copy_buffer[CP_BUF_SIZE] = {0}; /* Copy the parameter section from the temporary file to the output file */ if ((bu_fseek(fp_param, 0, 0))) { perror("g-iges"); bu_exit(1, "Cannot seek to start of temporary file\n"); } while ((i = fread(copy_buffer, 1, CP_BUF_SIZE, fp_param))) if (fwrite(copy_buffer, 1, i, fp_dir) != i) { perror("g-iges"); bu_exit(1, "Error in copying parameter data to %s\n", output_file); } /* Write the terminate section */ w_terminate(fp_dir); fclose(fp_dir); fclose(fp_param); } } /* * 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, * 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; }
/* This routine is called by the tree walker (db_walk_tree) * for every primitive encountered in the trees specified on the command line */ union tree * primitive_func(struct db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal *ip, void *UNUSED(client_data)) { struct directory *dp; char *name; dp = DB_FULL_PATH_CUR_DIR(pathp); RT_CK_DBTS(tsp); name = db_path_to_string(pathp); bu_log("leaf_func %s\n", name); bu_free(name, "region_end name"); /* handle each type of primitive (see h/rtgeom.h) */ if (ip->idb_major_type == DB5_MAJORTYPE_BRLCAD) { switch (ip->idb_type) { /* most commonly used primitives */ case ID_TOR: /* torus */ { struct rt_tor_internal *tor = (struct rt_tor_internal *)ip->idb_ptr; printf("Write this torus (name=%s) in your format:\n", dp->d_namep); printf("\tV=(%g %g %g)\n", V3ARGS(tor->v)); printf("\tnormal=(%g %g %g)\n", V3ARGS(tor->h)); printf("\tradius1 = %g\n", tor->r_a); printf("\tradius2 = %g\n", tor->r_h); break; } case ID_TGC: /* truncated general cone frustum */ case ID_REC: /* right elliptical cylinder */ { /* This primitive includes circular cross-section * cones and cylinders */ struct rt_tgc_internal *tgc = (struct rt_tgc_internal *)ip->idb_ptr; printf("Write this TGC (name=%s) in your format:\n", dp->d_namep); printf("\tV=(%g %g %g)\n", V3ARGS(tgc->v)); printf("\tH=(%g %g %g)\n", V3ARGS(tgc->h)); printf("\tA=(%g %g %g)\n", V3ARGS(tgc->a)); printf("\tB=(%g %g %g)\n", V3ARGS(tgc->b)); printf("\tC=(%g %g %g)\n", V3ARGS(tgc->c)); printf("\tD=(%g %g %g)\n", V3ARGS(tgc->d)); break; } case ID_ELL: case ID_SPH: { /* spheres and ellipsoids */ struct rt_ell_internal *ell = (struct rt_ell_internal *)ip->idb_ptr; printf("Write this ellipsoid (name=%s) in your format:\n", dp->d_namep); printf("\tV=(%g %g %g)\n", V3ARGS(ell->v)); printf("\tA=(%g %g %g)\n", V3ARGS(ell->a)); printf("\tB=(%g %g %g)\n", V3ARGS(ell->b)); printf("\tC=(%g %g %g)\n", V3ARGS(ell->c)); break; } case ID_ARB8: /* convex primitive with from four to six faces */ { int i; /* this primitive may have degenerate faces * faces are: 0123, 7654, 0347, 1562, 0451, 3267 * (points listed above in counter-clockwise order) */ struct rt_arb_internal *arb = (struct rt_arb_internal *)ip->idb_ptr; printf("Write this ARB (name=%s) in your format:\n", dp->d_namep); for (i=0; i<8; i++) printf("\tpoint #%d: (%g %g %g)\n", i, V3ARGS(arb->pt[i])); break; } /* other primitives, left as an exercise to the reader */ case ID_BOT: /* Bag O' Triangles */ case ID_ARS: /* series of curves * each with the same number of points */ case ID_HALF: /* half universe defined by a plane */ case ID_POLY: /* polygons (up to 5 vertices per) */ case ID_BSPLINE: /* NURB surfaces */ case ID_NMG: /* N-manifold geometry */ case ID_ARBN: case ID_DSP: /* Displacement map (terrain primitive) */ /* the DSP primitive may reference an external file or binunif object */ case ID_HF: /* height field (terrain primitive) */ /* the HF primitive references an external file */ case ID_EBM: /* extruded bit-map */ /* the EBM primitive references an external file */ case ID_VOL: /* the VOL primitive references an external file */ case ID_PIPE: case ID_PARTICLE: case ID_RPC: case ID_RHC: case ID_EPA: case ID_EHY: case ID_ETO: case ID_GRIP: case ID_SKETCH: case ID_EXTRUDE: /* note that an extrusion references a sketch, make sure you convert * the sketch also */ default: bu_log("Primitive %s is an unsupported or unrecognized type (%d)\n", dp->d_namep, ip->idb_type); break; } } else { switch (ip->idb_major_type) { case DB5_MAJORTYPE_BINARY_UNIF: { /* not actually a primitive, just a block of storage for data * a uniform array of chars, ints, floats, doubles, ... */ struct rt_binunif_internal *bin = (struct rt_binunif_internal *)ip->idb_ptr; if (bin) printf("Found a binary object (%s)\n\n", dp->d_namep); break; } default: bu_log("Major type of %s is unrecognized type (%d)\n", dp->d_namep, ip->idb_major_type); break; } } return (union tree *) NULL; }
static int plot_shaded_eval( struct ged *gedp, const char *path_name, struct _ged_client_data *dgcdp) { int ret; const char *av[3]; const char *tmp_basename = "tmp_shaded_eval_obj"; char *brep_name; /* make a name for the temp brep */ av[0] = "make_name"; av[1] = tmp_basename; ged_make_name(gedp, 2, (const char **)av); brep_name = bu_vls_strdup(gedp->ged_result_str); bu_vls_trunc(gedp->ged_result_str, 0); /* create temp evaluated brep from named object */ av[0] = "brep"; av[1] = path_name; av[2] = brep_name; ret = ged_brep(gedp, 3, av); if (ret == GED_OK) { int brep_made = 0; struct db_tree_state ts; struct rt_db_internal brep_intern; struct db_full_path input_path, brep_path; RT_DB_INTERNAL_INIT(&brep_intern); db_full_path_init(&input_path); db_full_path_init(&brep_path); /* get brep internal */ ret = get_path_and_state(&ts, &brep_path, brep_name, gedp); if (ret == GED_OK) { struct directory *dp = DB_FULL_PATH_CUR_DIR(&brep_path); if (dp->d_flags & RT_DIR_COMB) { ret = rt_db_get_internal(&brep_intern, dp, ts.ts_dbip, NULL, ts.ts_resp); } else { ret = rt_db_get_internal(&brep_intern, dp, ts.ts_dbip, ts.ts_mat, ts.ts_resp); } if (ret >= 0) { brep_made = 1; } db_free_full_path(&brep_path); } /* plot brep, but use the path and state of the input object */ if (brep_made) { ret = get_path_and_state(&ts, &input_path, path_name, gedp); if (ret == GED_OK) { plot_shaded(&ts, &input_path, &brep_intern, dgcdp); rt_db_free_internal(&brep_intern); db_free_full_path(&input_path); } } /* kill temp brep */ av[0] = "kill"; av[1] = brep_name; ged_kill(gedp, 2, av); } bu_free((char *)brep_name, "vls_strdup"); return ret; }
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 {
int ged_lc(struct ged *gedp, int argc, const char *argv[]) { char *file_name = NULL; int file_name_flag_cnt = 0; int sort_column = 1; int sort_column_flag_cnt = 0; int find_duplicates_flag = 0; int skip_special_duplicates_flag = 0; int skip_subtracted_regions_flag = 0; int descending_sort_flag = 0; int unrecognized_flag_cnt = 0; int orig_argc; const char **orig_argv; static const char *usage = "[-d|-s] [-r] [-z] [-0|-1|-2|-3|-4|-5] [-f {FileName}] {GroupName}"; int c; int error_cnt = 0; FILE *outfile = NULL; struct bu_vls *output; const char *group_name; size_t i,j; struct bu_ptbl results1 = BU_PTBL_INIT_ZERO; struct bu_ptbl results2 = BU_PTBL_INIT_ZERO; char *path; char *plan; struct db_full_path root; int matches; struct region_record *regions; size_t ignored_cnt = 0; /* The defaults are the minimum widths to accommodate column headers */ size_t region_id_len_max = 2; size_t material_id_len_max = 3; size_t los_len_max = 3; size_t obj_len_max = 6; /* For the output at the end */ size_t start, end, incr; /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s\n", usage); return GED_HELP; } GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); bu_optind = 1; /* re-init bu_getopt() */ while ((c = bu_getopt(argc, (char * const *)argv, "dsrz012345f:")) != -1) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': sort_column_flag_cnt++; sort_column = c - '0'; break; case 'f': file_name_flag_cnt++; file_name = bu_optarg; break; case 's': skip_special_duplicates_flag = 1; /* FALLTHROUGH */ case 'd': find_duplicates_flag = 1; break; case 'r': skip_subtracted_regions_flag = 1; break; case 'z': descending_sort_flag = 1; break; default: unrecognized_flag_cnt++; } } orig_argc = argc; orig_argv = argv; argc -= (bu_optind - 1); argv += (bu_optind - 1); /* Attempt to recreate the exact error messages from the original lc.tcl */ if (file_name_flag_cnt > 1) { bu_vls_printf(gedp->ged_result_str, "Error: '-f' used more than once.\n"); error_cnt++; } if (sort_column_flag_cnt > 1) { bu_vls_printf(gedp->ged_result_str, "Error: Sort column defined more than once.\n"); error_cnt++; } if (file_name_flag_cnt + argc + unrecognized_flag_cnt > 3) { bu_vls_printf(gedp->ged_result_str, "Error: More than one group name and/or file name was specified.\n"); error_cnt++; } else if (argc < 2) { if (file_name_flag_cnt && !file_name) { bu_vls_printf(gedp->ged_result_str, "Error: Group name and file name not specified\n"); } else { bu_vls_printf(gedp->ged_result_str, "Error: Group name not specified.\n"); } error_cnt++; } else if (argc + unrecognized_flag_cnt > 2) { bu_vls_printf(gedp->ged_result_str, "Error: More than one group name was specified.\n"); error_cnt++; } else if (file_name_flag_cnt && !file_name) { bu_vls_printf(gedp->ged_result_str, "Error: File name not specified.\n"); error_cnt++; } if (file_name) { char *norm_name; norm_name = bu_realpath(file_name, NULL); if (file_name[0] == '-') { bu_vls_printf(gedp->ged_result_str, "Error: File name can not start with '-'.\n"); error_cnt++; } else if (bu_file_exists(file_name, NULL)) { bu_vls_printf(gedp->ged_result_str, "Error: Output file %s already exists.\n",norm_name); error_cnt++; } else { outfile = fopen(file_name, "w"); if (!outfile) { bu_vls_printf(gedp->ged_result_str, "Error: %d\n", errno); error_cnt++; } } bu_vls_printf(gedp->ged_result_str, "Output filename: %s\n", norm_name); bu_free(norm_name, "ged_lc"); output = bu_vls_vlsinit(); } else { output = gedp->ged_result_str; } if (error_cnt > 0) { return GED_ERROR; } group_name = argv[1]; /* The 7 is for the "-name" and '\0' */ plan = (char *) bu_malloc(sizeof(char) * (strlen(group_name) + 7), "ged_lc"); sprintf(plan, "-name %s", group_name); matches = db_search(&results1, DB_SEARCH_TREE, plan, 0, NULL, gedp->ged_wdbp->dbip); if (matches < 1) { bu_vls_printf(gedp->ged_result_str, "Error: Group '%s' does not exist.\n", group_name); return GED_ERROR; } bu_free(plan, "ged_lc"); db_search_free(&results1); if (skip_subtracted_regions_flag) { plan = "-type region ! -bool -"; } else { plan = "-type region"; } path = (char *) bu_malloc(sizeof(char) * (strlen(group_name) + 2), "ged_lc"); sprintf(path, "/%s", group_name); db_string_to_path(&root, gedp->ged_wdbp->dbip, path); matches = db_search(&results2, DB_SEARCH_TREE, plan, root.fp_len, root.fp_names, gedp->ged_wdbp->dbip); bu_free(path, "ged_lc"); if (matches < 1) { return GED_ERROR; } regions = (struct region_record *) bu_malloc(sizeof(struct region_record) * BU_PTBL_LEN(&results2), "ged_lc"); for (i = 0; i < BU_PTBL_LEN(&results2); i++) { struct db_full_path *entry = (struct db_full_path *)BU_PTBL_GET(&results2, i); struct directory *dp_curr_dir = DB_FULL_PATH_CUR_DIR(entry); struct bu_attribute_value_set avs; j = BU_PTBL_LEN(&results2) - i - 1 ; regions[j].ignore = 0; bu_avs_init_empty(&avs); db5_get_attributes(gedp->ged_wdbp->dbip, &avs, dp_curr_dir); regions[j].region_id = get_attr(&avs, "region_id"); V_MAX(region_id_len_max, strlen(regions[j].region_id)); regions[j].material_id = get_attr(&avs, "material_id"); V_MAX(material_id_len_max, strlen(regions[j].material_id)); regions[j].los = get_attr(&avs, "los"); V_MAX(los_len_max, strlen(regions[j].los)); regions[j].obj_name = dp_curr_dir->d_namep; V_MAX(obj_len_max, strlen(regions[j].obj_name)); if (entry->fp_len > 1) { struct directory *dp_parent = DB_FULL_PATH_GET(entry, entry->fp_len - 2); regions[j].obj_parent = dp_parent->d_namep; } else { regions[j].obj_parent = "--"; } } if (find_duplicates_flag) { bu_sort((void *) regions, BU_PTBL_LEN(&results2), sizeof(struct region_record), cmp_regions, NULL); for (i = 1; i < BU_PTBL_LEN(&results2); i++) { int same; if (skip_special_duplicates_flag) { same = !cmp_regions((void *)&(regions[i - 1]), (void *)&(regions[i]), NULL); } else { same = !bu_strcmp(regions[i - 1].region_id, regions[i].region_id); } if (same) { regions[i].ignore = 1; ignored_cnt++; } } if (ignored_cnt == BU_PTBL_LEN(&results2)) { if (file_name) { print_cmd_args(output, orig_argc, orig_argv); bu_vls_printf(output, "No duplicate region_id\n"); bu_vls_fwrite(outfile, output); fclose(outfile); } bu_vls_printf(gedp->ged_result_str, "No duplicate region_id\n"); bu_vls_printf(gedp->ged_result_str, "Done.\n"); bu_free(regions, "ged_lc"); return GED_ERROR; } } if (sort_column > 0) { bu_sort((void *) regions, BU_PTBL_LEN(&results2), sizeof(struct region_record), sort_regions, (void *)&sort_column); } if (file_name) { print_cmd_args(output, orig_argc, orig_argv); } bu_vls_printf(output, "List length: %d\n", BU_PTBL_LEN(&results2) - ignored_cnt); bu_vls_printf(output, "%-*s %-*s %-*s %-*s %s\n", region_id_len_max + 1, "ID", material_id_len_max + 1, "MAT", los_len_max, "LOS", obj_len_max, "REGION", "PARENT"); end = BU_PTBL_LEN(&results2); if (descending_sort_flag) { start = end - 1; end = -1; incr = -1; } else { start = 0; incr = 1; } for (i = start; i != end; i += incr) { if (regions[i].ignore) { continue; } bu_vls_printf(output, "%-*s %-*s %-*s %-*s %s\n", region_id_len_max + 1, regions[i].region_id, material_id_len_max + 1, regions[i].material_id, los_len_max, regions[i].los, obj_len_max, regions[i].obj_name, regions[i].obj_parent); } bu_vls_printf(gedp->ged_result_str, "Done.\n"); if (file_name) { bu_vls_fwrite(outfile, output); fclose(outfile); } bu_free(regions, "ged_lc"); return GED_OK; }
/** * R T _ G E T T R E E _ R E G I O N _ E N D * * 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(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data) { struct region *rp; struct directory *dp; int shader_len=0; struct rt_i *rtip; int i; Tcl_HashTable *tbl = (Tcl_HashTable *)client_data; Tcl_HashEntry *entry; matp_t inv_mat; 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_GETSTRUCT( rp, 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; if ( tsp->ts_attrs.count && tsp->ts_attrs.avp ) { rp->attr_values = (struct bu_mro **)bu_calloc( tsp->ts_attrs.count+1, sizeof( struct bu_mro *), "regp->attr_values" ); for ( i=0; i<tsp->ts_attrs.count; i++ ) { rp->attr_values[i] = bu_malloc( sizeof( struct bu_mro ), "rp->attr_values[i]" ); bu_mro_init_with_string( rp->attr_values[i], tsp->ts_attrs.avp[i].value ); } } else { rp->attr_values = (struct bu_mro **)NULL; } rp->reg_mater = tsp->ts_mater; /* struct copy */ if ( tsp->ts_mater.ma_shader ) shader_len = strlen( tsp->ts_mater.ma_shader ); if ( shader_len ) { rp->reg_mater.ma_shader = bu_strdup( tsp->ts_mater.ma_shader ); } else rp->reg_mater.ma_shader = (char *)NULL; rp->reg_name = db_path_to_string( pathp ); dp = (struct directory *)DB_FULL_PATH_CUR_DIR(pathp); if (RT_G_DEBUG&DEBUG_TREEWALK) { bu_log("rt_gettree_region_end() %s\n", rp->reg_name ); rt_pr_tree( curtree, 0 ); } rp->reg_treetop = curtree; rp->reg_all_unions = db_is_tree_all_unions( curtree ); /* Determine material properties */ rp->reg_mfuncs = (char *)0; rp->reg_udata = (char *)0; if ( rp->reg_mater.ma_color_valid == 0 ) rt_region_color_map(rp); /* enter critical section */ bu_semaphore_acquire( RT_SEM_RESULTS ); rp->reg_instnum = dp->d_uses++; /* * Add the region to the linked list of regions. * Positions in the region bit vector are established at this time. */ BU_LIST_INSERT( &(rtip->HeadRegion), &rp->l ); /* Assign bit vector pos. */ rp->reg_bit = rtip->nregions++; /* leave critical section */ bu_semaphore_release( RT_SEM_RESULTS ); if ( tbl && bu_avs_get( &tsp->ts_attrs, "ORCA_Comp" ) ) { int newentry; long int reg_bit = rp->reg_bit; inv_mat = (matp_t)bu_calloc( 16, sizeof( fastf_t ), "inv_mat" ); if ( tsp->ts_mat ) bn_mat_inv( inv_mat, tsp->ts_mat ); else MAT_IDN( inv_mat ); /* enter critical section */ bu_semaphore_acquire( RT_SEM_RESULTS ); entry = Tcl_CreateHashEntry(tbl, (char *)reg_bit, &newentry); Tcl_SetHashValue( entry, (ClientData)inv_mat ); /* leave critical section */ bu_semaphore_release( RT_SEM_RESULTS ); } if ( RT_G_DEBUG & DEBUG_REGIONS ) { bu_log("Add Region %s instnum %d\n", rp->reg_name, rp->reg_instnum); } /* Indicate that we have swiped 'curtree' */ return(TREE_NULL); }