/** * Tesssuperellate an superellipsoid. * * The strategy is based upon the approach of Jon Leech 3/24/89, from * program "sphere", which generates a polygon mesh approximating a * sphere by recursive subdivision. First approximation is an * octahedron; each level of refinement increases the number of * polygons by a factor of 4. Level 3 (128 polygons) is a good * tradeoff if gouraud shading is used to render the database. * * At the start, points ABC lie on surface of the unit sphere. Pick * DEF as the midpoints of the three edges of ABC. Normalize the new * points to lie on surface of the unit sphere. * * 1 * B * /\ * 3 / \ 4 * D /____\ E * /\ /\ * / \ / \ * /____\/____\ * A F C * 0 5 2 * * Returns - * -1 failure * 0 OK. *r points to nmgregion that holds this tesssuperellation. */ int rt_superell_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol)) { if (r) NMG_CK_REGION(*r); if (m) NMG_CK_MODEL(m); if (ip) RT_CK_DB_INTERNAL(ip); bu_log("called rt_superell_tess()\n"); return -1; }
/** * Returns - * -1 failure * 0 OK. *r points to nmgregion that holds this tessellation. */ int rt_xxx_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol)) { struct rt_xxx_internal *xxx_ip; if (r) NMG_CK_REGION(*r); if (m) NMG_CK_MODEL(m); RT_CK_DB_INTERNAL(ip); xxx_ip = (struct rt_xxx_internal *)ip->idb_ptr; RT_XXX_CK_MAGIC(xxx_ip); return -1; }
void nmg_visit_region(struct nmgregion *r, const struct nmg_visit_handlers *htab, void *state) /* Handler's private state */ { struct shell *s; NMG_CK_REGION(r); if (htab->bef_region) htab->bef_region((uint32_t *)r, state, 0); for (BU_LIST_FOR(s, shell, &r->s_hd)) { nmg_visit_shell(s, htab, state); } if (htab->vis_region_a && r->ra_p) htab->vis_region_a((uint32_t *)r->ra_p, state, 0); if (htab->aft_region) htab->aft_region((uint32_t *)r, state, 1); }
int ged_bev(struct ged *gedp, int argc, const char *argv[]) { static const char *usage = "[P|t] new_obj obj1 op obj2 op obj3 ..."; int i; int c; int ncpu; char *cmdname; char *newname; struct rt_db_internal intern; struct directory *dp; char op; int failed; /* static due to longjmp */ static int triangulate = 0; static union tree *tmp_tree = NULL; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } cmdname = (char *)argv[0]; /* Establish tolerances */ gedp->ged_wdbp->wdb_initial_tree_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol; gedp->ged_wdbp->wdb_initial_tree_state.ts_tol = &gedp->ged_wdbp->wdb_tol; gedp->ged_wdbp->wdb_ttol.magic = RT_TESS_TOL_MAGIC; /* Initial values for options, must be reset each time */ ncpu = 1; triangulate = 0; /* Parse options. */ bu_optind = 1; /* re-init bu_getopt() */ while ((c=bu_getopt(argc, (char * const *)argv, "tP:")) != -1) { switch (c) { case 'P': #if 0 /* not yet supported */ ncpu = atoi(bu_optarg); #endif break; case 't': triangulate = 1; break; default: { bu_vls_printf(gedp->ged_result_str, "%s: option '%c' unknown\n", cmdname, c); } break; } } argc -= bu_optind; argv += bu_optind; newname = (char *)argv[0]; argv++; argc--; if (argc < 1) { bu_vls_printf(gedp->ged_result_str, "%s: Nothing to evaluate!!!\n", cmdname); return GED_ERROR; } GED_CHECK_EXISTS(gedp, newname, LOOKUP_QUIET, GED_ERROR); bu_vls_printf(gedp->ged_result_str, "%s: tessellating primitives with tolerances a=%g, r=%g, n=%g\n", argv[0], gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm); bev_facetize_tree = (union tree *)0; bev_nmg_model = nmg_mm(); gedp->ged_wdbp->wdb_initial_tree_state.ts_m = &bev_nmg_model; op = ' '; tmp_tree = (union tree *)NULL; while (argc) { i = db_walk_tree(gedp->ged_wdbp->dbip, 1, (const char **)argv, ncpu, &gedp->ged_wdbp->wdb_initial_tree_state, 0, /* take all regions */ bev_facetize_region_end, nmg_booltree_leaf_tess, (genptr_t)gedp); if (i < 0) { bu_vls_printf(gedp->ged_result_str, "%s: error in db_walk_tree()\n", cmdname); /* Destroy NMG */ nmg_km(bev_nmg_model); return GED_ERROR; } argc--; argv++; if (tmp_tree && op != ' ') { union tree *new_tree; BU_ALLOC(new_tree, union tree); RT_TREE_INIT(new_tree); new_tree->tr_b.tb_regionp = REGION_NULL; new_tree->tr_b.tb_left = tmp_tree; new_tree->tr_b.tb_right = bev_facetize_tree; switch (op) { case 'u': case 'U': new_tree->tr_op = OP_UNION; break; case '-': new_tree->tr_op = OP_SUBTRACT; break; case '+': new_tree->tr_op = OP_INTERSECT; break; default: { bu_vls_printf(gedp->ged_result_str, "%s: Unrecognized operator: (%c)\nAborting\n", argv[0], op); db_free_tree(bev_facetize_tree, &rt_uniresource); nmg_km(bev_nmg_model); return GED_ERROR; } } tmp_tree = new_tree; bev_facetize_tree = (union tree *)NULL; } else if (!tmp_tree && op == ' ') { /* just starting out */ tmp_tree = bev_facetize_tree; bev_facetize_tree = (union tree *)NULL; } if (argc) { op = *argv[0]; argc--; argv++; } else op = ' '; } if (tmp_tree) { /* Now, evaluate the boolean tree into ONE region */ bu_vls_printf(gedp->ged_result_str, "%s: evaluating boolean expressions\n", cmdname); if (BU_SETJUMP) { BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "%s: WARNING: Boolean evaluation failed!!!\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } failed = nmg_boolean(tmp_tree, bev_nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource); BU_UNSETJUMP; } else failed = 1; if (failed) { bu_vls_printf(gedp->ged_result_str, "%s: no resulting region, aborting\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } /* New region remains part of this nmg "model" */ NMG_CK_REGION(tmp_tree->tr_d.td_r); bu_vls_printf(gedp->ged_result_str, "%s: facetize %s\n", cmdname, tmp_tree->tr_d.td_name); nmg_vmodel(bev_nmg_model); /* Triangulate model, if requested */ if (triangulate) { bu_vls_printf(gedp->ged_result_str, "%s: triangulating resulting object\n", cmdname); if (BU_SETJUMP) { BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "%s: WARNING: Triangulation failed!!!\n", cmdname); if (tmp_tree) db_free_tree(tmp_tree, &rt_uniresource); tmp_tree = (union tree *)NULL; nmg_km(bev_nmg_model); bev_nmg_model = (struct model *)NULL; return GED_ERROR; } nmg_triangulate_model(bev_nmg_model, &gedp->ged_wdbp->wdb_tol); BU_UNSETJUMP; } bu_vls_printf(gedp->ged_result_str, "%s: converting NMG to database format\n", cmdname); /* Export NMG as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_NMG; intern.idb_meth = &rt_functab[ID_NMG]; intern.idb_ptr = (genptr_t)bev_nmg_model; bev_nmg_model = (struct model *)NULL; GED_DB_DIRADD(gedp, dp, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (genptr_t)&intern.idb_type, GED_ERROR); GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); tmp_tree->tr_d.td_r = (struct nmgregion *)NULL; /* Free boolean tree, and the regions in it. */ db_free_tree(tmp_tree, &rt_uniresource); return GED_OK; }
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 {
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" ); } } } }
int main(int argc, char **argv) /* really has no arguments */ { struct nmgregion *r; char * id_name = "BRL-CAD t-NURBS NMG Example"; char * tea_name = "UtahTeapot"; char * uplot_name = "teapot.pl"; struct bu_list vhead; FILE *fp; int i; tol.magic = BN_TOL_MAGIC; tol.dist = 0.005; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; BU_LIST_INIT( &rt_g.rtg_vlfree ); outfp = wdb_fopen( "tea_nmg.g" ); rt_g.debug |= DEBUG_ALLRAYS; /* Cause core dumps on bu_bomb(), but no extra messages */ while ((i=bu_getopt(argc, argv, "d")) != EOF) { switch (i) { case 'd' : rt_g.debug |= DEBUG_MEM | DEBUG_MEM_FULL; break; default : (void)fprintf(stderr, "Usage: %s [-d] > database.g\n", *argv); return(-1); } } mk_id( outfp, id_name); m = nmg_mm(); NMG_CK_MODEL( m ); r = nmg_mrsv( m ); NMG_CK_REGION( r ); s = BU_LIST_FIRST( shell, &r->s_hd ); NMG_CK_SHELL( s ); /* Step through each patch and create a NMG TNURB face * representing the patch then dump them out. */ for ( i = 0; i < PATCH_COUNT; i++) { dump_patch( patches[i] ); } /* Connect up the coincident vertexuses and edges */ (void)nmg_model_fuse( m, &tol ); /* write NMG to output file */ (void)mk_nmg( outfp, tea_name, m ); wdb_close(outfp); /* Make a vlist drawing of the model */ BU_LIST_INIT( &vhead ); nmg_m_to_vlist( &vhead, m, 0 ); /* Make a UNIX plot file from this vlist */ if ( (fp=fopen( uplot_name, "w" )) == NULL ) { bu_log( "Cannot open plot file: %s\n", uplot_name ); perror( "teapot_nmg" ); } else rt_vlist_to_uplot( fp, &vhead ); return(0); }
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; }
static void nmg_to_dxf(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id), float color[3]) { struct model *m; struct shell *s; struct vertex *v; struct bu_ptbl verts; char *region_name; int region_polys=0; int tri_count=0; int color_num; int do_triangulate=0; NMG_CK_REGION(r); RT_CK_FULL_PATH(pathp); region_name = db_path_to_string(pathp); m = r->m_p; NMG_CK_MODEL(m); /* Count 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; int vert_count=0; NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { struct edgeuse *eu; if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { vert_count++; } if (vert_count > 3) { do_triangulate = 1; goto triangulate; } tri_count++; } } } triangulate: if (do_triangulate) { /* triangulate model */ nmg_triangulate_model(m, &tol); /* Count triangles */ tri_count = 0; for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; if (fu->orientation != OT_SAME) continue; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; tri_count++; } } } } nmg_vertex_tabulate(&verts, &r->l.magic); color_num = find_closest_color(color); if (polyface_mesh) { size_t i; fprintf(fp, "0\nPOLYLINE\n8\n%s\n62\n%d\n70\n64\n71\n%lu\n72\n%d\n", region_name, color_num, (unsigned long)BU_PTBL_LEN(&verts), tri_count); for (i = 0; i < BU_PTBL_LEN(&verts); i++) { fprintf(fp, "0\nVERTEX\n8\n%s\n", region_name); v = (struct vertex *)BU_PTBL_GET(&verts, i); NMG_CK_VERTEX(v); if (inches) { fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n70\n192\n", V3ARGSIN(v->vg_p->coord)); } else { fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n70\n192\n", V3ARGS(v->vg_p->coord)); } } } /* 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; if (polyface_mesh) { fprintf(fp, "0\nVERTEX\n8\n%s\n70\n128\n10\n0.0\n20\n0.0\n30\n0.0\n", region_name); } else { fprintf(fp, "0\n3DFACE\n8\n%s\n62\n%d\n", region_name, color_num); } /* 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); if (polyface_mesh) { fprintf(fp, "%d\n%d\n", vert_count+70, bu_ptbl_locate(&verts, (long *)v) + 1); } else { if (inches) { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X] / 25.4, 20 + vert_count - 1, v->vg_p->coord[Y] / 25.4, 30 + vert_count -1, v->vg_p->coord[Z] / 25.4); } else { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X], 20 + vert_count - 1, v->vg_p->coord[Y], 30 + vert_count -1, v->vg_p->coord[Z]); } } } if (vert_count > 3) { 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; } else { /* repeat the last vertex for the benefit of codes * that interpret the dxf specification for * 3DFACES as requiring a fourth vertex even when * only three are input. */ if (!polyface_mesh) { vert_count++; if (inches) { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X] / 25.4, 20 + vert_count - 1, v->vg_p->coord[Y] / 25.4, 30 + vert_count -1, v->vg_p->coord[Z] / 25.4); } else { fprintf(fp, "%d\n%f\n%d\n%f\n%d\n%f\n", 10 + vert_count - 1, v->vg_p->coord[X], 20 + vert_count - 1, v->vg_p->coord[Y], 30 + vert_count -1, v->vg_p->coord[Z]); } } } tot_polygons++; region_polys++; } } } bu_ptbl_free(&verts); bu_free(region_name, "region name"); if (polyface_mesh) { fprintf(fp, "0\nSEQEND\n"); } }
/* Routine to write an nmgregion in the Euclid "decoded" format */ static void Write_euclid_region(struct nmgregion *r, struct db_tree_state *tsp) { struct shell *s; struct facets *faces=NULL; int i, j; NMG_CK_REGION(r); if (verbose) bu_log("Write_euclid_region: r=%p\n", (void *)r); /* if bounds haven't been calculated, do it now */ if (r->ra_p == NULL) nmg_region_a(r, &tol); /* Check if region extents are beyond the limitations of the format */ for (i=X; i<ELEMENTS_PER_POINT; i++) { if (r->ra_p->min_pt[i] < (-999999.0)) { bu_log("g-euclid: Coordinates too large (%g) for Euclid format\n", r->ra_p->min_pt[i]); return; } if (r->ra_p->max_pt[i] > 9999999.0) { bu_log("g-euclid: Coordinates too large (%g) for Euclid format\n", r->ra_p->max_pt[i]); return; } } /* write out each face in the region */ for (BU_LIST_FOR(s, shell, &r->s_hd)) { struct faceuse *fu; for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { struct loopuse *lu; int no_of_loops = 0; int no_of_holes = 0; if (fu->orientation != OT_SAME) continue; /* count the loops in this face */ for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; no_of_loops++; } if (!no_of_loops) continue; faces = (struct facets *)bu_calloc(no_of_loops, sizeof(struct facets), "g-euclid: faces"); i = 0; for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; faces[i].lu = lu; if (lu->orientation == OT_OPPOSITE) faces[i].facet_type = 1; /* this is a hole */ else faces[i].facet_type = (-1); /* TBD */ faces[i].outer_loop = NULL; i++; } /* determine type of face * 0 -> simple facet (no holes) * 1 -> a hole * 2 -> a facet that will have holes */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type == 1) no_of_holes++; } if (!no_of_holes) { /* no holes, so each loop is a simple face (type 0) */ for (i = 0; i < no_of_loops; i++) faces[i].facet_type = 0; } else if (no_of_loops == no_of_holes + 1) { struct loopuse *outer_lu = (struct loopuse *)NULL; /* only one outer loop, so find it */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type == (-1)) { outer_lu = faces[i].lu; faces[i].facet_type = 2; break; } } /* every hole must have this same outer_loop */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type == 1) faces[i].outer_loop = outer_lu; } } else { int loop1, loop2; int outer_loop_count; /* must determine which holes go with which outer loops */ for (loop1 = 0; loop1 < no_of_loops; loop1++) { if (faces[loop1].facet_type != 1) continue; /* loop1 is a hole look for loops containing loop1 */ outer_loop_count = 0; for (loop2 = 0; loop2 < no_of_loops; loop2++) { int nmg_class; if (faces[loop2].facet_type == 1) continue; nmg_class = nmg_classify_lu_lu(faces[loop1].lu, faces[loop2].lu, &tol); if (nmg_class != NMG_CLASS_AinB) continue; /* loop1 is inside loop2, possible outer loop */ faces[loop2].facet_type = (-2); outer_loop_count++; } if (outer_loop_count > 1) { /* must choose outer loop from a list of candidates * if any of these candidates contain one of the * other candidates, the outer one can be eliminated * as a possible choice */ for (loop2 = 0; loop2 < no_of_loops; loop2++) { if (faces[loop2].facet_type != (-2)) continue; for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type != (-2)) continue; if (nmg_classify_lu_lu(faces[i].lu, faces[loop2].lu, &tol)) { if (faces[i].facet_type != (-2)) continue; faces[loop2].facet_type = (-1); outer_loop_count--; } } } } if (outer_loop_count != 1) { bu_log("Failed to find outer loop for hole in component %d\n", tsp->ts_regionid); goto outt; } for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type == (-2)) { faces[i].facet_type = 2; faces[loop1].outer_loop = faces[i].lu; } } } /* Check */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type < 0) { /* all holes have been placed * so these must be simple faces */ faces[i].facet_type = 0; } if (faces[i].facet_type == 1 && faces[i].outer_loop == NULL) { bu_log("Failed to find outer loop for hole in component %d\n", tsp->ts_regionid); goto outt; } } } /* output faces with holes first */ for (i = 0; i < no_of_loops; i++) { struct loopuse *outer_loop; if (faces[i].facet_type != 2) continue; outer_loop = faces[i].lu; Write_euclid_face(outer_loop, 2, tsp->ts_regionid, ++face_count); /* output holes for this face */ for (j = 0; j < no_of_loops; j++) { if (j == i) continue; if (faces[j].outer_loop == outer_loop) Write_euclid_face(faces[j].lu, 1, tsp->ts_regionid, ++face_count); } } /* output simple faces */ for (i = 0; i < no_of_loops; i++) { if (faces[i].facet_type != 0) continue; Write_euclid_face(faces[i].lu, 0, tsp->ts_regionid, ++face_count); } bu_free((char *)faces, "g-euclid: faces"); faces = (struct facets*)NULL; } } regions_written++; outt: if (faces) bu_free((char *)faces, "g-euclid: faces"); return; }
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"); }
/** * This routine must be prepared to run in parallel. */ static union tree * draw_nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { struct nmgregion *r; struct bu_list vhead; int failed; struct _ged_client_data *dgcdp = (struct _ged_client_data *)client_data; RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); RT_CK_RESOURCE(tsp->ts_resp); BU_LIST_INIT(&vhead); if (RT_G_DEBUG&DEBUG_TREEWALK) { char *sofar = db_path_to_string(pathp); bu_vls_printf(dgcdp->gedp->ged_result_str, "nmg_region_end() path='%s'\n", sofar); bu_free((void *)sofar, "path string"); } else { char *sofar = db_path_to_string(pathp); bu_vls_printf(dgcdp->gedp->ged_result_str, "%s:\n", sofar); bu_free((void *)sofar, "path string"); } if (curtree->tr_op == OP_NOP) return curtree; failed = 1; if (!dgcdp->draw_nmg_only) { failed = process_boolean(curtree, tsp, pathp, dgcdp); if (failed) { db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } } else if (curtree->tr_op != OP_NMG_TESS) { bu_vls_printf(dgcdp->gedp->ged_result_str, "Cannot use '-d' option when Boolean evaluation is required\n"); db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } r = curtree->tr_d.td_r; NMG_CK_REGION(r); if (dgcdp->do_not_draw_nmg_solids_during_debugging && r) { db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } if (dgcdp->nmg_triangulate) { failed = process_triangulation(tsp, pathp, dgcdp); if (failed) { db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } } if (r != 0) { int style; /* Convert NMG to vlist */ NMG_CK_REGION(r); if (dgcdp->draw_wireframes) { /* Draw in vector form */ style = NMG_VLIST_STYLE_VECTOR; } else { /* Default -- draw polygons */ style = NMG_VLIST_STYLE_POLYGON; } if (dgcdp->draw_normals) { style |= NMG_VLIST_STYLE_VISUALIZE_NORMALS; } if (dgcdp->shade_per_vertex_normals) { style |= NMG_VLIST_STYLE_USE_VU_NORMALS; } if (dgcdp->draw_no_surfaces) { style |= NMG_VLIST_STYLE_NO_SURFACES; } nmg_r_to_vlist(&vhead, r, style); _ged_drawH_part2(0, &vhead, pathp, tsp, dgcdp); if (dgcdp->draw_edge_uses) { nmg_vlblock_r(dgcdp->draw_edge_uses_vbp, r, 1); } /* NMG region is no longer necessary, only vlist remains */ db_free_tree(curtree, tsp->ts_resp); return (union tree *)NULL; } /* Return tree -- it needs to be freed (by caller) */ return curtree; }
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"); }
/* 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 process_non_light(struct model *m) { /* static due to bu exception handling */ static struct shell *s; static struct shell *next_s; static struct faceuse *fu; static struct faceuse *next_fu; static struct loopuse *lu; static struct nmgregion *reg; /* triangulate any faceuses with holes */ for ( BU_LIST_FOR( reg, nmgregion, &m->r_hd ) ) { NMG_CK_REGION( reg ); s = BU_LIST_FIRST( shell, ®->s_hd ); while ( BU_LIST_NOT_HEAD( s, ®->s_hd ) ) { NMG_CK_SHELL( s ); next_s = BU_LIST_PNEXT( shell, &s->l ); fu = BU_LIST_FIRST( faceuse, &s->fu_hd ); while ( BU_LIST_NOT_HEAD( &fu->l, &s->fu_hd ) ) { int shell_is_dead=0; NMG_CK_FACEUSE( fu ); next_fu = BU_LIST_PNEXT( faceuse, &fu->l ); if ( fu->orientation != OT_SAME ) { fu = next_fu; continue; } if ( fu->fumate_p == next_fu ) { /* make sure next_fu is not the mate of fu */ next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l ); } /* check if this faceuse has any holes */ for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { NMG_CK_LOOPUSE( lu ); if ( lu->orientation == OT_OPPOSITE ) { /* this is a hole, so * triangulate the faceuse */ if ( !BU_SETJUMP ) { /* try */ if ( nmg_triangulate_fu( fu, &tol ) ) { if ( nmg_kfu( fu ) ) { (void) nmg_ks( s ); shell_is_dead = 1; } } } else { /* catch */ bu_log( "A face has failed triangulation!\n" ); if ( next_fu == fu->fumate_p ) next_fu = BU_LIST_PNEXT( faceuse, &next_fu->l ); if ( nmg_kfu( fu ) ) { (void) nmg_ks( s ); shell_is_dead = 1; } } BU_UNSETJUMP; break; } } if ( shell_is_dead ) break; fu = next_fu; } s = next_s; } } }
/* * Default keypoint in model space is established in "pt". Returns * GED_ERROR if unable to determine a keypoint, otherwise returns * GED_OK. */ int _ged_get_solid_keypoint(struct ged *const gedp, fastf_t *const pt, const struct rt_db_internal *const ip, const fastf_t *const mat) { point_t mpt; RT_CK_DB_INTERNAL(ip); switch (ip->idb_type) { case ID_CLINE: { struct rt_cline_internal *cli = (struct rt_cline_internal *)ip->idb_ptr; RT_CLINE_CK_MAGIC(cli); VMOVE(mpt, cli->v); break; } case ID_PARTICLE: { struct rt_part_internal *part = (struct rt_part_internal *)ip->idb_ptr; RT_PART_CK_MAGIC(part); VMOVE(mpt, part->part_V); break; } case ID_PIPE: { struct rt_pipe_internal *pipeip; struct wdb_pipept *pipe_seg; pipeip = (struct rt_pipe_internal *)ip->idb_ptr; RT_PIPE_CK_MAGIC(pipeip); pipe_seg = BU_LIST_FIRST(wdb_pipept, &pipeip->pipe_segs_head); VMOVE(mpt, pipe_seg->pp_coord); break; } case ID_METABALL: { struct rt_metaball_internal *metaball = (struct rt_metaball_internal *)ip->idb_ptr; struct wdb_metaballpt *metaballpt; RT_METABALL_CK_MAGIC(metaball); VSETALL(mpt, 0.0); metaballpt = BU_LIST_FIRST(wdb_metaballpt, &metaball->metaball_ctrl_head); VMOVE(mpt, metaballpt->coord); break; } case ID_ARBN: { struct rt_arbn_internal *arbn = (struct rt_arbn_internal *)ip->idb_ptr; size_t i, j, k; int good_vert = 0; RT_ARBN_CK_MAGIC(arbn); for (i = 0; i < arbn->neqn; i++) { for (j = i + 1; j < arbn->neqn; j++) { for (k = j + 1; k < arbn->neqn; k++) { if (!bn_mkpoint_3planes(mpt, arbn->eqn[i], arbn->eqn[j], arbn->eqn[k])) { size_t l; good_vert = 1; for (l = 0; l < arbn->neqn; l++) { if (l == i || l == j || l == k) continue; if (DIST_PT_PLANE(mpt, arbn->eqn[l]) > gedp->ged_wdbp->wdb_tol.dist) { good_vert = 0; break; } } if (good_vert) break; } } if (good_vert) break; } if (good_vert) break; } break; } case ID_EBM: { struct rt_ebm_internal *ebm = (struct rt_ebm_internal *)ip->idb_ptr; point_t pnt; RT_EBM_CK_MAGIC(ebm); VSETALL(pnt, 0.0); MAT4X3PNT(mpt, ebm->mat, pnt); break; } case ID_BOT: { struct rt_bot_internal *bot = (struct rt_bot_internal *)ip->idb_ptr; VMOVE(mpt, bot->vertices); break; } case ID_DSP: { struct rt_dsp_internal *dsp = (struct rt_dsp_internal *)ip->idb_ptr; point_t pnt; RT_DSP_CK_MAGIC(dsp); VSETALL(pnt, 0.0); MAT4X3PNT(mpt, dsp->dsp_stom, pnt); break; } case ID_HF: { struct rt_hf_internal *hf = (struct rt_hf_internal *)ip->idb_ptr; RT_HF_CK_MAGIC(hf); VMOVE(mpt, hf->v); break; } case ID_VOL: { struct rt_vol_internal *vol = (struct rt_vol_internal *)ip->idb_ptr; point_t pnt; RT_VOL_CK_MAGIC(vol); VSETALL(pnt, 0.0); MAT4X3PNT(mpt, vol->mat, pnt); break; } case ID_HALF: { struct rt_half_internal *haf = (struct rt_half_internal *)ip->idb_ptr; RT_HALF_CK_MAGIC(haf); VSCALE(mpt, haf->eqn, haf->eqn[H]); break; } case ID_ARB8: { struct rt_arb_internal *arb = (struct rt_arb_internal *)ip->idb_ptr; RT_ARB_CK_MAGIC(arb); VMOVE(mpt, arb->pt[0]); break; } case ID_ELL: case ID_SPH: { struct rt_ell_internal *ell = (struct rt_ell_internal *)ip->idb_ptr; RT_ELL_CK_MAGIC(ell); VMOVE(mpt, ell->v); break; } case ID_SUPERELL: { struct rt_superell_internal *superell = (struct rt_superell_internal *)ip->idb_ptr; RT_SUPERELL_CK_MAGIC(superell); VMOVE(mpt, superell->v); break; } case ID_TOR: { struct rt_tor_internal *tor = (struct rt_tor_internal *)ip->idb_ptr; RT_TOR_CK_MAGIC(tor); VMOVE(mpt, tor->v); break; } case ID_TGC: case ID_REC: { struct rt_tgc_internal *tgc = (struct rt_tgc_internal *)ip->idb_ptr; RT_TGC_CK_MAGIC(tgc); VMOVE(mpt, tgc->v); break; } case ID_GRIP: { struct rt_grip_internal *gip = (struct rt_grip_internal *)ip->idb_ptr; RT_GRIP_CK_MAGIC(gip); VMOVE(mpt, gip->center); break; } case ID_ARS: { struct rt_ars_internal *ars = (struct rt_ars_internal *)ip->idb_ptr; RT_ARS_CK_MAGIC(ars); VMOVE(mpt, &ars->curves[0][0]); break; } case ID_RPC: { struct rt_rpc_internal *rpc = (struct rt_rpc_internal *)ip->idb_ptr; RT_RPC_CK_MAGIC(rpc); VMOVE(mpt, rpc->rpc_V); break; } case ID_RHC: { struct rt_rhc_internal *rhc = (struct rt_rhc_internal *)ip->idb_ptr; RT_RHC_CK_MAGIC(rhc); VMOVE(mpt, rhc->rhc_V); break; } case ID_EPA: { struct rt_epa_internal *epa = (struct rt_epa_internal *)ip->idb_ptr; RT_EPA_CK_MAGIC(epa); VMOVE(mpt, epa->epa_V); break; } case ID_EHY: { struct rt_ehy_internal *ehy = (struct rt_ehy_internal *)ip->idb_ptr; RT_EHY_CK_MAGIC(ehy); VMOVE(mpt, ehy->ehy_V); break; } case ID_HYP: { struct rt_hyp_internal *hyp = (struct rt_hyp_internal *)ip->idb_ptr; RT_HYP_CK_MAGIC(hyp); VMOVE(mpt, hyp->hyp_Vi); break; } case ID_ETO: { struct rt_eto_internal *eto = (struct rt_eto_internal *)ip->idb_ptr; RT_ETO_CK_MAGIC(eto); VMOVE(mpt, eto->eto_V); break; } case ID_POLY: { struct rt_pg_face_internal *_poly; struct rt_pg_internal *pg = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(pg); _poly = pg->poly; VMOVE(mpt, _poly->verts); break; } case ID_SKETCH: { struct rt_sketch_internal *skt = (struct rt_sketch_internal *)ip->idb_ptr; RT_SKETCH_CK_MAGIC(skt); VMOVE(mpt, skt->V); break; } case ID_EXTRUDE: { struct rt_extrude_internal *extr = (struct rt_extrude_internal *)ip->idb_ptr; RT_EXTRUDE_CK_MAGIC(extr); if (extr->skt && extr->skt->verts) { VJOIN2(mpt, extr->V, extr->skt->verts[0][0], extr->u_vec, extr->skt->verts[0][1], extr->v_vec); } else { VMOVE(mpt, extr->V); } break; } case ID_NMG: { struct vertex *v; struct vertexuse *vu; struct edgeuse *eu; struct loopuse *lu; struct faceuse *fu; struct shell *s; struct nmgregion *r; struct model *m = (struct model *) ip->idb_ptr; NMG_CK_MODEL(m); /* set default first */ VSETALL(mpt, 0.0); if (BU_LIST_IS_EMPTY(&m->r_hd)) break; r = BU_LIST_FIRST(nmgregion, &m->r_hd); if (!r) break; NMG_CK_REGION(r); if (BU_LIST_IS_EMPTY(&r->s_hd)) break; s = BU_LIST_FIRST(shell, &r->s_hd); if (!s) break; NMG_CK_SHELL(s); if (BU_LIST_IS_EMPTY(&s->fu_hd)) fu = (struct faceuse *)NULL; else fu = BU_LIST_FIRST(faceuse, &s->fu_hd); if (fu) { NMG_CK_FACEUSE(fu); lu = BU_LIST_FIRST(loopuse, &fu->lu_hd); NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) { eu = BU_LIST_FIRST(edgeuse, &lu->down_hd); NMG_CK_EDGEUSE(eu); NMG_CK_VERTEXUSE(eu->vu_p); v = eu->vu_p->v_p; } else { vu = BU_LIST_FIRST(vertexuse, &lu->down_hd); NMG_CK_VERTEXUSE(vu); v = vu->v_p; } NMG_CK_VERTEX(v); if (!v->vg_p) break; VMOVE(mpt, v->vg_p->coord); break; } if (BU_LIST_IS_EMPTY(&s->lu_hd)) lu = (struct loopuse *)NULL; else lu = BU_LIST_FIRST(loopuse, &s->lu_hd); if (lu) { NMG_CK_LOOPUSE(lu); if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) { eu = BU_LIST_FIRST(edgeuse, &lu->down_hd); NMG_CK_EDGEUSE(eu); NMG_CK_VERTEXUSE(eu->vu_p); v = eu->vu_p->v_p; } else { vu = BU_LIST_FIRST(vertexuse, &lu->down_hd); NMG_CK_VERTEXUSE(vu); v = vu->v_p; } NMG_CK_VERTEX(v); if (!v->vg_p) break; VMOVE(mpt, v->vg_p->coord); break; } if (BU_LIST_IS_EMPTY(&s->eu_hd)) eu = (struct edgeuse *)NULL; else eu = BU_LIST_FIRST(edgeuse, &s->eu_hd); if (eu) { NMG_CK_EDGEUSE(eu); NMG_CK_VERTEXUSE(eu->vu_p); v = eu->vu_p->v_p; NMG_CK_VERTEX(v); if (!v->vg_p) break; VMOVE(mpt, v->vg_p->coord); break; } vu = s->vu_p; if (vu) { NMG_CK_VERTEXUSE(vu); v = vu->v_p; NMG_CK_VERTEX(v); if (!v->vg_p) break; VMOVE(mpt, v->vg_p->coord); break; } } default: VSETALL(mpt, 0.0); bu_vls_printf(gedp->ged_result_str, "get_solid_keypoint: unrecognized solid type"); return GED_ERROR; } MAT4X3PNT(pt, mat, mpt); return GED_OK; }
int ged_facetize(struct ged *gedp, int argc, const char *argv[]) { int i; int c; char *newname; struct rt_db_internal intern; struct directory *dp; int failed; int nmg_use_tnurbs = 0; struct db_tree_state init_state; struct db_i *dbip; union tree *facetize_tree; struct model *nmg_model; static const char *usage = "[ [-P] | [-n] [-t] [-T] ] new_obj old_obj [old_obj2 old_obj3 ...]"; /* static due to jumping */ static int triangulate; static int make_bot; static int marching_cube; static int screened_poisson; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } dbip = gedp->ged_wdbp->dbip; RT_CHECK_DBI(dbip); db_init_db_tree_state(&init_state, dbip, gedp->ged_wdbp->wdb_resp); /* Establish tolerances */ init_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol; init_state.ts_tol = &gedp->ged_wdbp->wdb_tol; /* Initial values for options, must be reset each time */ marching_cube = 0; screened_poisson = 0; triangulate = 0; make_bot = 1; /* Parse options. */ bu_optind = 1; /* re-init bu_getopt() */ while ((c=bu_getopt(argc, (char * const *)argv, "mntTP")) != -1) { switch (c) { case 'm': marching_cube = triangulate = 1; /* no break, marching cubes assumes nmg for now */ case 'n': make_bot = 0; break; case 'P': screened_poisson = 1; triangulate = 1; make_bot = 1; break; case 'T': triangulate = 1; break; case 't': nmg_use_tnurbs = 1; break; default: { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } } } argc -= bu_optind; argv += bu_optind; if (argc < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n"); return GED_ERROR; } if (screened_poisson && (marching_cube || !make_bot || nmg_use_tnurbs)) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } newname = (char *)argv[0]; argv++; argc--; if (argc < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n"); return GED_ERROR; } if (db_lookup(dbip, newname, LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "error: solid '%s' already exists, aborting\n", newname); return GED_ERROR; } if (screened_poisson) { struct rt_bot_internal *bot; BU_ALLOC(bot, struct rt_bot_internal); bot->magic = RT_BOT_INTERNAL_MAGIC; bot->mode = RT_BOT_SOLID; bot->orientation = RT_BOT_UNORIENTED; bot->thickness = (fastf_t *)NULL; bot->face_mode = (struct bu_bitv *)NULL; /* TODO - generate point cloud, then mesh - need to see the input points for debugging */ (void)rt_generate_mesh(&(bot->faces), (int *)&(bot->num_faces), (point_t **)&(bot->vertices), (int *)&(bot->num_vertices), dbip, argv[0], 15); /* Export BOT as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_BOT; intern.idb_meth = &OBJ[ID_BOT]; intern.idb_ptr = (void *) bot; } else { bu_vls_printf(gedp->ged_result_str, "facetize: tessellating primitives with tolerances a=%g, r=%g, n=%g\n", gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm); facetize_tree = (union tree *)0; nmg_model = nmg_mm(); init_state.ts_m = &nmg_model; i = db_walk_tree(dbip, argc, (const char **)argv, 1, &init_state, 0, /* take all regions */ facetize_region_end, nmg_use_tnurbs ? nmg_booltree_leaf_tnurb : nmg_booltree_leaf_tess, (void *)&facetize_tree ); if (i < 0) { bu_vls_printf(gedp->ged_result_str, "facetize: error in db_walk_tree()\n"); /* Destroy NMG */ nmg_km(nmg_model); return GED_ERROR; } if (facetize_tree) { /* Now, evaluate the boolean tree into ONE region */ bu_vls_printf(gedp->ged_result_str, "facetize: evaluating boolean expressions\n"); if (!BU_SETJUMP) { /* try */ failed = nmg_boolean(facetize_tree, nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: facetization failed!!!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; } else failed = 1; if (failed) { bu_vls_printf(gedp->ged_result_str, "facetize: no resulting region, aborting\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } /* New region remains part of this nmg "model" */ NMG_CK_REGION(facetize_tree->tr_d.td_r); bu_vls_printf(gedp->ged_result_str, "facetize: %s\n", facetize_tree->tr_d.td_name); /* Triangulate model, if requested */ if (triangulate && !make_bot) { bu_vls_printf(gedp->ged_result_str, "facetize: triangulating resulting object\n"); if (!BU_SETJUMP) { /* try */ if (marching_cube == 1) nmg_triangulate_model_mc(nmg_model, &gedp->ged_wdbp->wdb_tol); else nmg_triangulate_model(nmg_model, &gedp->ged_wdbp->wdb_tol); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: triangulation failed!!!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; } if (make_bot) { struct rt_bot_internal *bot; struct nmgregion *r; struct shell *s; bu_vls_printf(gedp->ged_result_str, "facetize: converting to BOT format\n"); /* WTF, FIXME: this is only dumping the first shell of the first region */ r = BU_LIST_FIRST(nmgregion, &nmg_model->r_hd); if (r && BU_LIST_NEXT(nmgregion, &r->l) != (struct nmgregion *)&nmg_model->r_hd) bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one region, only facetizing the first\n"); s = BU_LIST_FIRST(shell, &r->s_hd); if (s && BU_LIST_NEXT(shell, &s->l) != (struct shell *)&r->s_hd) bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one shell, only facetizing the first\n"); if (!BU_SETJUMP) { /* try */ bot = (struct rt_bot_internal *)nmg_bot(s, &gedp->ged_wdbp->wdb_tol); } else { /* catch */ BU_UNSETJUMP; bu_vls_printf(gedp->ged_result_str, "WARNING: conversion to BOT failed!\n"); db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; nmg_km(nmg_model); nmg_model = (struct model *)NULL; return GED_ERROR; } BU_UNSETJUMP; nmg_km(nmg_model); nmg_model = (struct model *)NULL; /* Export BOT as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_BOT; intern.idb_meth = &OBJ[ID_BOT]; intern.idb_ptr = (void *) bot; } else { bu_vls_printf(gedp->ged_result_str, "facetize: converting NMG to database format\n"); /* Export NMG as a new solid */ RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_NMG; intern.idb_meth = &OBJ[ID_NMG]; intern.idb_ptr = (void *)nmg_model; nmg_model = (struct model *)NULL; } } dp=db_diradd(dbip, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type); if (dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", newname); return GED_ERROR; } if (rt_db_put_internal(dp, dbip, &intern, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Failed to write %s to database\n", newname); rt_db_free_internal(&intern); return GED_ERROR; } if (!screened_poisson) { facetize_tree->tr_d.td_r = (struct nmgregion *)NULL; /* Free boolean tree, and the regions in it */ db_free_tree(facetize_tree, &rt_uniresource); facetize_tree = (union tree *)NULL; } return GED_OK; }