On 17 August 2015 at 09:03, Daniel Roßberg <danielmrossb...@gmail.com> wrote: > Konrad, > > What does the standard say about the unit used in X3D?
According to X3D Unit Specification Updates <http://www.web3d.org/sites/default/files/presentations/X3D%20Unit%20Specification%20Updates/%284%29UnitsUpdate%28myeong%29.pdf> the standard unit for length is meters. > You could send us your g-x3d.c file, e.g. via this mailing list. > Maybe someone has an idea how to fix the export. Attached to this mail is the g-x3d.c file which I found in src/conv/ of the BRL-CAD source code. I have an idea of how to rewrite the code, as modification of g-stl.c but I would have to get a better understanding of the code first to see if there is a chance of fixing whatever the problem is without rewriting the whole code. Thanks Konrad
/* G - X 3 D . C * BRL-CAD * * Copyright (c) 2004-2014 United States Government as represented by * the U.S. Army Research Laboratory. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this file; see the file named COPYING for more * information. * */ /** @file conv/g-x3d.c * * Program to convert a BRL-CAD model (in a .g file) to a X3D faceted * model by calling on the NMG booleans. This program is a modified * version of g-vrml (authored by John R. Anderson). * */ #include "common.h" /* system headers */ #include <stdlib.h> #include <stddef.h> #include <sys/types.h> #include <sys/stat.h> #include <math.h> #include <string.h> #include "bio.h" /* interface headers */ #include "vmath.h" #include "bu/getopt.h" #include "bu/units.h" #include "nmg.h" #include "rt/geom.h" #include "raytrace.h" #include "wdb.h" /* #define MEMORY_LEAK_CHECKING 1 */ #ifdef MEMORY_LEAK_CHECKING #define BARRIER_CHECK { \ if ( bu_mem_barriercheck() ) { \ bu_log( "memory is corrupted at line %d in file %d\n", __LINE__, __FILE__ ); \ } \ } #else #define BARRIER_CHECK /* */ #endif #define TXT_BUF_LEN 512 #define TXT_NAME_SIZE 128 struct plate_mode { int num_bots; int num_nonbots; int array_size; struct rt_bot_internal **bots; }; struct vrml_mat { /* typical shader parameters */ char shader[TXT_NAME_SIZE]; int shininess; double transparency; /* light parameters */ fastf_t lt_fraction; vect_t lt_dir; fastf_t lt_angle; /* texture parameters */ char tx_file[TXT_NAME_SIZE]; int tx_w; int tx_n; }; #define PL_O(_m) bu_offsetof(struct vrml_mat, _m) struct bu_structparse vrml_mat_parse[]={ {"%s", TXT_NAME_SIZE, "ma_shader", PL_O(shader), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%d", 1, "shine", PL_O(shininess), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%d", 1, "sh", PL_O(shininess), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%g", 1, "transmit", PL_O(transparency), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%g", 1, "tr", PL_O(transparency), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%f", 1, "angle", PL_O(lt_angle), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%f", 1, "fract", PL_O(lt_fraction), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%f", 3, "aim", PL_O(lt_dir), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%d", 1, "w", PL_O(tx_w), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%d", 1, "n", PL_O(tx_n), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"%s", TXT_NAME_SIZE, "file", PL_O(tx_file), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }, {"", 0, (char *)0, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL } }; extern union tree *do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data); extern union tree *nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data); static const char *usage = "[-v] [-xX lvl] [-d tolerance_distance] [-a abs_tol] [-r rel_tol] [-n norm_tol] [-P #_of_cpus] [-o out_file] [-u units] brlcad_db.g object(s)\n" "(units default to mm)\n"; static char *tok_sep = " \t"; static int NMG_debug; /* saved arg of -X, for longjmp handling */ static int verbose=0; static int ncpu = 1; /* Number of processors */ static char *out_file = NULL; /* Output filename */ static FILE *outfp; /* Output file pointer */ static struct db_i *dbip; static struct rt_tess_tol ttol; static struct bn_tol tol; static struct model *the_model; static char* units="mm"; static fastf_t scale_factor=1.0; static struct db_tree_state tree_state; /* includes tol & model */ static int regions_tried = 0; static int regions_converted = 0; static void print_usage(const char *progname) { bu_exit(1, "Usage: %s %s", progname, usage); } /* * Replace all occurrences of "old" with "new" in str. */ static void char_replace(char *str, char oldc, char newc) { if (str == (char *)0) return; while (*str != '\0') { if (*str == oldc) *str = newc; ++str; } } static void clean_pmp( struct plate_mode *pmp ) { int i; BARRIER_CHECK; pmp->num_bots = 0; pmp->num_nonbots = 0; for ( i=0; i<pmp->array_size; i++ ) { if ( pmp->bots[i] ) { struct rt_db_internal intern; intern.idb_ptr = (void *) pmp->bots[i]; intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_BOT; intern.idb_meth = &OBJ[ID_BOT]; intern.idb_magic = RT_DB_INTERNAL_MAGIC; intern.idb_meth->ft_ifree( &intern ); pmp->bots[i] = NULL; } } BARRIER_CHECK; } struct rt_bot_internal * dup_bot( struct rt_bot_internal *bot_in ) { struct rt_bot_internal *bot; size_t i; RT_BOT_CK_MAGIC( bot_in ); BU_ALLOC(bot, struct rt_bot_internal); *bot = *bot_in; /* struct copy */ bot->faces = (int *)bu_calloc( bot_in->num_faces*3, sizeof( int ), "bot faces" ); for ( i=0; i<bot_in->num_faces*3; i++ ) bot->faces[i] = bot_in->faces[i]; bot->vertices = (fastf_t *)bu_calloc( bot_in->num_vertices*3, sizeof( fastf_t ), "bot verts" ); for ( i=0; i<bot_in->num_vertices*3; i++ ) bot->vertices[i] = bot_in->vertices[i]; if ( bot_in->thickness ) { bot->thickness = (fastf_t *)bu_calloc( bot_in->num_faces, sizeof( fastf_t ), "bot thickness" ); for ( i=0; i<bot_in->num_faces; i++ ) bot->thickness[i] = bot_in->thickness[i]; } if ( bot_in->face_mode ) { bot->face_mode = bu_bitv_dup( bot_in->face_mode ); } return bot; } 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; } } static int select_non_lights(struct db_tree_state *tsp, const struct db_full_path *pathp, const struct rt_comb_internal *combp, void *client_data) { int ret; ret = select_lights( tsp, pathp, combp, client_data ); if ( ret == 0 ) return -1; else return 0; } union tree * leaf_tess(struct db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal *ip, void *client_data) { struct rt_bot_internal *bot; struct plate_mode *pmp = (struct plate_mode *)client_data; BARRIER_CHECK; if ( ip->idb_type != ID_BOT ) { pmp->num_nonbots++; return nmg_booltree_leaf_tess(tsp, pathp, ip, client_data); } bot = (struct rt_bot_internal *)ip->idb_ptr; RT_BOT_CK_MAGIC( bot ); if ( bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_SURFACE ) { if ( pmp->array_size <= pmp->num_bots ) { pmp->array_size += 5; pmp->bots = (struct rt_bot_internal **)bu_realloc( (char *)pmp->bots, pmp->array_size * sizeof( struct rt_bot_internal *), "pmp->bots" ); } /* walk tree will free the BOT, so we need a copy */ pmp->bots[pmp->num_bots] = dup_bot( bot ); BARRIER_CHECK; pmp->num_bots++; return (union tree *)NULL; } pmp->num_nonbots++; BARRIER_CHECK; return nmg_booltree_leaf_tess(tsp, pathp, ip, client_data); } void writeX3dHeader(FILE *fp_out, char *x3dFileName) { fprintf(fp_out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fprintf(fp_out, "<!DOCTYPE X3D PUBLIC \"http://www.web3D.org/TaskGroups/x3d/translation/x3d-compact.dtd\"\n\"/www.web3D.org/TaskGroups/x3d/translation/x3d-compact.dtd\">\n"); fprintf(fp_out, "<X3D>\n"); fprintf(fp_out, " <head>\n"); fprintf(fp_out, " <meta name=\"filename\" content=\"%s\"/>\n", x3dFileName); fprintf(fp_out, " <meta name=\"description\" content=\"*enter description here, short-sentence summaries preferred*\"/>\n"); fprintf(fp_out, " <meta name=\"author\" content=\"*enter name of original author here*\"/>\n"); fprintf(fp_out, " <meta name=\"translator\" content=\"*if manually translating VRML-to-X3D, enter name of person translating here*\"/>\n"); fprintf(fp_out, " <meta name=\"created\" content=\"*enter date of initial version here*\"/>\n"); fprintf(fp_out, " <meta name=\"revised\" content=\"*enter date of latest revision here*\"/>\n"); fprintf(fp_out, " <meta name=\"version\" content=\"*enter version here*\"/>\n"); fprintf(fp_out, " <meta name=\"reference\" content=\"*enter reference citation or relative/online url here*\"/>\n"); fprintf(fp_out, " <meta name=\"reference\" content=\"*enter additional url/bibliographic reference information here*\"/>\n"); fprintf(fp_out, " <meta name=\"copyright\" content=\"*enter copyright information here* Example: Copyright (c) Web3D Consortium Inc. 2001\"/>\n"); fprintf(fp_out, " <meta name=\"drawing\" content=\"*enter drawing filename/url here*\"/>\n"); fprintf(fp_out, " <meta name=\"image\" content=\"*enter image filename/url here*\"/>\n"); fprintf(fp_out, " <meta name=\"movie\" content=\"*enter movie filename/url here*\"/>\n"); fprintf(fp_out, " <meta name=\"photo\" content=\"*enter photo filename/url here*\"/>\n"); fprintf(fp_out, " <meta name=\"keywords\" content=\"*enter keywords here*\"/>\n"); fprintf(fp_out, " <meta name=\"url\" content=\"*enter online url address for this file here*\"/>\n"); fprintf(fp_out, " </head>\n"); fprintf(fp_out, " <Scene>\n"); /* Note we may want to inquire about bounding boxes for the various groups and add Viewpoints nodes that * point the camera to the center and orient for Top, Side, etc. Views * * We will add some default Material Color definitions (for thousands groups) before we start defining the geometry */ fprintf( fp_out, "\t<Material DEF=\"Material_999\" diffuseColor=\"0.78 0.78 0.78\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_1999\" diffuseColor=\"0.88 0.29 0.29\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_2999\" diffuseColor=\"0.82 0.53 0.54\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_3999\" diffuseColor=\"0.39 0.89 0.00\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_4999\" diffuseColor=\"1.00 0.00 0.00\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_5999\" diffuseColor=\"0.82 0.00 0.82\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_6999\" diffuseColor=\"0.62 0.62 0.62\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_7999\" diffuseColor=\"0.49 0.49 0.49\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_8999\" diffuseColor=\"0.18 0.31 0.31\"/>\n"); fprintf( fp_out, "\t<Material DEF=\"Material_9999\" diffuseColor=\"0.00 0.41 0.82\"/>\n"); } void writeX3dEnd(FILE *fp_out) { fprintf(fp_out, " </Scene>\n\n"); fprintf(fp_out, "</X3D>\n"); } int main(int argc, char **argv) { int i; int c; struct plate_mode pm; bu_setprogname(argv[0]); bu_setlinebuf( stderr ); the_model = nmg_mm(); tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_tol = &tol; tree_state.ts_ttol = &ttol; tree_state.ts_m = &the_model; ttol.magic = RT_TESS_TOL_MAGIC; /* Defaults, updated by command line options. */ ttol.abs = 0.0; ttol.rel = 0.01; ttol.norm = 0.0; /* FIXME: These need to be improved */ tol.magic = BN_TOL_MAGIC; tol.dist = BN_TOL_DIST; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; /* NOTE: For visualization purposes, in the debug plot files */ { /* WTF: This value is specific to the Bradley */ nmg_eue_dist = 2.0; } BU_LIST_INIT( &RTG.rtg_vlfree ); /* for vlist macros */ BARRIER_CHECK; /* Get command line arguments. */ while ((c = bu_getopt(argc, argv, "d:a:n:o:r:vx:P:X:u:h?")) != -1) { switch (c) { case 'a': /* Absolute tolerance. */ ttol.abs = atof(bu_optarg); ttol.rel = 0.0; break; case 'd': /* calculational tolerance */ tol.dist = atof( bu_optarg ); tol.dist_sq = tol.dist * tol.dist; break; case 'n': /* Surface normal tolerance. */ ttol.norm = atof(bu_optarg)*DEG2RAD; ttol.rel = 0.0; break; case 'o': /* Output file name */ out_file = bu_optarg; break; case 'r': /* Relative tolerance. */ ttol.rel = atof(bu_optarg); break; case 'v': verbose++; break; case 'P': ncpu = atoi(bu_optarg); break; case 'x': sscanf( bu_optarg, "%x", (unsigned int *)&RTG.debug ); break; case 'X': sscanf( bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug ); NMG_debug = RTG.NMG_debug; break; case 'u': units = bu_strdup( bu_optarg ); scale_factor = bu_units_conversion( units ); if ( ZERO(scale_factor) ) bu_exit(1, "Unrecognized units (%s)\n", units ); scale_factor = 1.0 / scale_factor; break; default: print_usage(argv[0]); } } if (bu_optind+1 >= argc) print_usage(argv[0]); /* Open BRL-CAD database */ if ((dbip = db_open( argv[bu_optind], DB_OPEN_READONLY)) == DBI_NULL) { perror(argv[0]); bu_exit(1, "Cannot open geometry database file %s\n", argv[bu_optind] ); } if ( db_dirbuild( dbip ) ) bu_exit(1, "db_dirbuild() failed!\n" ); if (out_file == NULL) { outfp = stdout; setmode(fileno(outfp), O_BINARY); } else { if ((outfp = fopen( out_file, "wb")) == NULL) { perror( argv[0] ); bu_exit(2, "Cannot open %s\n", out_file ); } } writeX3dHeader(outfp, out_file); bu_optind++; BARRIER_CHECK; pm.num_bots = 0; pm.num_nonbots = 0; pm.array_size = 5; pm.bots = (struct rt_bot_internal **)bu_calloc( pm.array_size, sizeof( struct rt_bot_internal *), "pm.bots" ); for ( i=bu_optind; i<argc; i++ ) { struct directory *dp; dp = db_lookup( dbip, argv[i], LOOKUP_QUIET ); if ( dp == RT_DIR_NULL ) { bu_log( "Cannot find %s\n", argv[i] ); continue; } /* light source must be a combination */ if ( !(dp->d_flags & RT_DIR_COMB) ) continue; /* walk trees selecting only light source regions */ (void)db_walk_tree(dbip, 1, (const char **)(&argv[i]), ncpu, &tree_state, select_lights, do_region_end, leaf_tess, (void *)&pm); /* in librt/nmg_bool.c */ } BARRIER_CHECK; /* Walk indicated tree(s). Each non-light-source region will be output separately */ (void)db_walk_tree(dbip, argc-bu_optind, (const char **)(&argv[bu_optind]), ncpu, &tree_state, select_non_lights, do_region_end, leaf_tess, (void *)&pm); /* in librt/nmg_bool.c */ BARRIER_CHECK; /* Release dynamic storage */ nmg_km(the_model); db_close(dbip); /* Now we need to close each group set */ writeX3dEnd(outfp); if ( verbose ) bu_log( "Total of %d regions converted of %d regions attempted\n", regions_converted, regions_tried ); return 0; } 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; } } } void nmg_2_vrml(FILE *fp, const struct db_full_path *pathp, struct model *m, struct mater_info *mater) { struct nmgregion *reg; struct bu_ptbl verts; struct vrml_mat mat; struct bu_vls vls = BU_VLS_INIT_ZERO; char *tok; int i; int first=1; int is_light=0; float r, g, b; point_t ave_pt; char *full_path; /*There may be a better way to capture the region_id, than getting the rt_comb_internal structure, * (and may be a better way to capture the rt_comb_internal struct), but for now I just copied the * method used in select_lights/select_non_lights above, could have used a global variable but I noticed * none other were used, so I didn't want to be the first */ struct directory *dp; struct rt_db_internal intern; struct rt_comb_internal *comb; int id; NMG_CK_MODEL( m ); BARRIER_CHECK; full_path = db_path_to_string( pathp ); /* replace all occurrences of '.' with '_' */ char_replace(full_path, '.', '_'); RT_CK_FULL_PATH( pathp ); dp = DB_FULL_PATH_CUR_DIR( pathp ); if ( !(dp->d_flags & RT_DIR_COMB) ) return; id = rt_db_get_internal( &intern, dp, dbip, (matp_t)NULL, &rt_uniresource ); if ( id < 0 ) { bu_log( "Cannot internal form of %s\n", dp->d_namep ); return; } if ( id != ID_COMBINATION ) { bu_log( "Directory/database mismatch!\n\t is '%s' a combination or not?\n", dp->d_namep ); return; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB( comb ); if ( mater->ma_color_valid ) { r = mater->ma_color[0]; g = mater->ma_color[1]; b = mater->ma_color[2]; } else { r = g = b = 0.5; } if ( mater->ma_shader ) { tok = strtok( mater->ma_shader, tok_sep ); bu_strlcpy( mat.shader, tok, TXT_NAME_SIZE ); } else mat.shader[0] = '\0'; mat.shininess = -1; mat.transparency = -1.0; mat.lt_fraction = -1.0; VSETALL( mat.lt_dir, 0.0 ); mat.lt_angle = -1.0; mat.tx_file[0] = '\0'; mat.tx_w = -1; mat.tx_n = -1; bu_vls_strcpy( &vls, &mater->ma_shader[strlen(mat.shader)] ); (void)bu_struct_parse( &vls, vrml_mat_parse, (char *)&mat, NULL); if ( bu_strncmp( "light", mat.shader, 5 ) == 0 ) { /* this is a light source */ is_light = 1; } else { fprintf( fp, "\t<Shape DEF=\"%s\">\n", full_path); fprintf( fp, "\t\t<Appearance>\n"); if ( bu_strncmp( "plastic", mat.shader, 7 ) == 0 ) { if ( mat.shininess < 0 ) mat.shininess = 10; V_MAX(mat.transparency, 0.0); fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0); } else if ( bu_strncmp( "glass", mat.shader, 5 ) == 0 ) { if ( mat.shininess < 0 ) mat.shininess = 4; if ( mat.transparency < 0.0 ) mat.transparency = 0.8; fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0); } else if ( mater->ma_color_valid ) { fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\"/>\n", r, g, b); } else { /* If no color was defined set the colors according to the thousands groups */ int thou = comb->region_id/1000; thou == 0 ? fprintf( fp, "\t\t\t<Material USE=\"Material_999\"/>\n") : thou == 1 ? fprintf( fp, "\t\t\t<Material USE=\"Material_1999\"/>\n") : thou == 2 ? fprintf( fp, "\t\t\t<Material USE=\"Material_2999\"/>\n") : thou == 3 ? fprintf( fp, "\t\t\t<Material USE=\"Material_3999\"/>\n") : thou == 4 ? fprintf( fp, "\t\t\t<Material USE=\"Material_4999\"/>\n") : thou == 5 ? fprintf( fp, "\t\t\t<Material USE=\"Material_5999\"/>\n") : thou == 6 ? fprintf( fp, "\t\t\t<Material USE=\"Material_6999\"/>\n") : thou == 7 ? fprintf( fp, "\t\t\t<Material USE=\"Material_7999\"/>\n") : thou == 8 ? fprintf( fp, "\t\t\t<Material USE=\"Material_8999\"/>\n") : fprintf( fp, "\t\t\t<Material USE=\"Material_9999\"/>\n"); } } if ( !is_light ) { process_non_light(m); fprintf( fp, "\t\t</Appearance>\n"); } /* FIXME: need code to handle light */ /* get list of vertices */ nmg_vertex_tabulate( &verts, &m->magic ); fprintf( fp, "\t\t<IndexedFaceSet coordIndex=\"\n"); first = 1; if ( !is_light ) { for ( BU_LIST_FOR( reg, nmgregion, &m->r_hd ) ) { struct shell *s; NMG_CK_REGION( reg ); for ( BU_LIST_FOR( s, shell, ®->s_hd ) ) { struct faceuse *fu; NMG_CK_SHELL( s ); for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) ) { struct loopuse *lu; NMG_CK_FACEUSE( fu ); if ( fu->orientation != OT_SAME ) continue; for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) ) { struct edgeuse *eu; NMG_CK_LOOPUSE( lu ); if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC ) continue; if ( !first ) fprintf( fp, ",\n" ); else first = 0; fprintf( fp, "\t\t\t\t" ); for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) ) { struct vertex *v; NMG_CK_EDGEUSE( eu ); v = eu->vu_p->v_p; NMG_CK_VERTEX( v ); fprintf( fp, " %d,", bu_ptbl_locate( &verts, (long *)v ) ); } fprintf( fp, "-1" ); } } } } /* close coordIndex */ fprintf( fp, "\" "); fprintf( fp, "normalPerVertex=\"false\" "); fprintf( fp, "convex=\"false\" "); fprintf( fp, "creaseAngle=\"0.5\" "); /* close IndexedFaceSet open tag */ fprintf( fp, ">\n"); } fprintf( fp, "\t\t\t<Coordinate point=\""); for ( i=0; i<BU_PTBL_END( &verts ); i++ ) { struct vertex *v; struct vertex_g *vg; point_t pt_meters; v = (struct vertex *)BU_PTBL_GET( &verts, i ); NMG_CK_VERTEX( v ); vg = v->vg_p; NMG_CK_VERTEX_G( vg ); /* convert to desired units */ VSCALE( pt_meters, vg->coord, scale_factor ); if ( is_light ) VADD2( ave_pt, ave_pt, pt_meters ); if ( first ) { if ( !is_light ) fprintf( fp, " %10.10e %10.10e %10.10e, ", V3ARGS(pt_meters)); first = 0; } else if ( !is_light ) fprintf( fp, "%10.10e %10.10e %10.10e, ", V3ARGS( pt_meters )); } /* close point */ fprintf(fp, "\""); /* close Coordinate */ fprintf(fp, "/>\n"); /* IndexedFaceSet end tag */ fprintf( fp, "\t\t</IndexedFaceSet>\n"); /* Shape end tag */ fprintf( fp, "\t</Shape>\n"); BARRIER_CHECK; } void bot2vrml( struct plate_mode *pmp, const struct db_full_path *pathp, int region_id ) { char *path_str; int appearance; struct rt_bot_internal *bot; int bot_num; size_t i; size_t vert_count=0; BARRIER_CHECK; path_str = db_path_to_string( pathp ); /* replace all occurrences of '.' with '_' */ char_replace(path_str, '.', '_'); fprintf( outfp, "\t<Shape DEF=\"%s\">\n", path_str); bu_free( path_str, "result of db_path_to_string" ); appearance = region_id / 1000; appearance = appearance * 1000 + 999; fprintf( outfp, "\t\t<Appearance USE=\"Material_%d\">\n", appearance); fprintf( outfp, "\t\t<IndexedFaceSet coordIndex=\"\n"); vert_count = 0; for ( bot_num = 0; bot_num < pmp->num_bots; bot_num++ ) { bot = pmp->bots[bot_num]; RT_BOT_CK_MAGIC( bot ); for ( i=0; i<bot->num_faces; i++ ) fprintf( outfp, "\t\t\t\t%lu, %lu, %lu, -1,\n", (long unsigned int)vert_count+bot->faces[i*3], (long unsigned int)vert_count+bot->faces[i*3+1], (long unsigned int)vert_count+bot->faces[i*3+2]); vert_count += bot->num_vertices; } /* close coordIndex */ fprintf( outfp, "\" "); fprintf( outfp, "normalPerVertex=\"false\" "); fprintf( outfp, "convex=\"true\" "); fprintf( outfp, "creaseAngle=\"0.5\" "); fprintf( outfp, "solid=\"false\" "); /* close IndexedFaceSet open tag */ fprintf( outfp, ">\n"); fprintf( outfp, "\t\t<Coordinate point=\""); for ( bot_num = 0; bot_num < pmp->num_bots; bot_num++ ) { bot = pmp->bots[bot_num]; RT_BOT_CK_MAGIC( bot ); for ( i=0; i<bot->num_vertices; i++ ) { point_t pt; VSCALE( pt, &bot->vertices[i*3], scale_factor ); fprintf( outfp, "%10.10e %10.10e %10.10e, ", V3ARGS( pt )); vert_count++; } } /* close point */ fprintf(outfp, "\""); /* close Coordinate */ fprintf(outfp, "/>\n"); /* IndexedFaceSet end tag */ fprintf( outfp, "\t\t</IndexedFaceSet>\n"); /* Shape end tag */ fprintf( outfp, "\t</Shape>\n"); BARRIER_CHECK; } /* * Called from db_walk_tree(). * * This routine must be prepared to run in parallel. */ union tree * do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { struct plate_mode *pmp = (struct plate_mode *)client_data; char *name; BARRIER_CHECK; if ( tsp->ts_is_fastgen != REGION_FASTGEN_PLATE ) { clean_pmp( pmp ); return nmg_region_end(tsp, pathp, curtree, client_data); } /* FASTGEN plate mode region, just spew the bot triangles */ if ( pmp->num_bots < 1 || pmp->num_nonbots > 0 ) { clean_pmp( pmp ); BARRIER_CHECK; return nmg_region_end(tsp, pathp, curtree, client_data); } if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) { bu_log("\nConverted %d%% so far (%d of %d)\n", regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, regions_converted, regions_tried ); } regions_tried++; name = db_path_to_string( pathp ); bu_log( "Attempting %s\n", name ); bu_free( name, "db_path_to_string" ); bot2vrml( pmp, pathp, tsp->ts_regionid ); clean_pmp( pmp ); regions_converted++; BARRIER_CHECK; return (union tree *)NULL; } static union tree * process_boolean(union tree *curtree, struct db_tree_state *tsp, const struct db_full_path *pathp) { union tree *ret_tree = TREE_NULL; /* Begin bomb protection */ if ( !BU_SETJUMP ) { /* try */ ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource); } else { /* catch */ char *name = db_path_to_string( pathp ); /* Error, bail out */ bu_log( "conversion of %s FAILED!\n", name ); /* Sometimes the NMG library adds debugging bits when * it detects an internal error, before before bombing out. */ RTG.NMG_debug = NMG_debug; /* restore mode */ /* Release any intersector 2d tables */ nmg_isect2d_final_cleanup(); /* 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 == NMG_MODEL_MAGIC ) { nmg_km(*tsp->ts_m); } else { bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n"); } bu_free( name, "db_path_to_string" ); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); } BU_UNSETJUMP; /* Relinquish the protection */ return ret_tree; } union tree * nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data)) { struct nmgregion *r; struct bu_list vhead; union tree *ret_tree; char *name; RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BARRIER_CHECK; BU_LIST_INIT(&vhead); if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) { bu_log("\nConverted %d%% so far (%d of %d)\n", regions_tried>0 ? (regions_converted * 100) / regions_tried : 0, regions_converted, regions_tried ); } if (curtree->tr_op == OP_NOP) return curtree; name = db_path_to_string( pathp ); bu_log( "Attempting %s\n", name ); regions_tried++; ret_tree = process_boolean(curtree, tsp, pathp); if ( ret_tree ) r = ret_tree->tr_d.td_r; else r = (struct nmgregion *)NULL; bu_free( name, "db_path_to_string" ); regions_converted++; if (r != (struct nmgregion *)NULL) { struct shell *s; int empty_region=0; int empty_model=0; /* Kill cracks */ s = BU_LIST_FIRST( shell, &r->s_hd ); while ( BU_LIST_NOT_HEAD( &s->l, &r->s_hd ) ) { struct shell *next_s; next_s = BU_LIST_PNEXT( shell, &s->l ); if ( nmg_kill_cracks( s ) ) { if ( nmg_ks( s ) ) { empty_region = 1; break; } } s = next_s; } /* kill zero length edgeuses */ if ( !empty_region ) { empty_model = nmg_kill_zero_length_edgeuses( *tsp->ts_m ); } if ( !empty_region && !empty_model ) { /* Write the nmgregion to the output file */ nmg_2_vrml( outfp, pathp, r->m_p, &tsp->ts_mater ); } /* NMG region is no longer necessary */ if ( !empty_model ) nmg_kr(r); } else bu_log( "WARNING: Nothing left after Boolean evaluation of %s\n", db_path_to_string( pathp ) ); /* * 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; BARRIER_CHECK; return curtree; } /* * Local Variables: * mode: C * tab-width: 8 * indent-tabs-mode: t * c-file-style: "stroustrup" * End: * ex: shiftwidth=4 tabstop=8 */
------------------------------------------------------------------------------
_______________________________________________ BRL-CAD Developer mailing list brlcad-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/brlcad-devel