/* return 0 when IS a light or an error occurred. regions are skipped
 * when this function returns 0.
 */
static int
select_non_lights(struct db_tree_state *UNUSED(tsp), const struct db_full_path *pathp, const struct rt_comb_internal *UNUSED(combp), void *UNUSED(client_data))
{
    struct directory *dp;
    struct rt_db_internal intern;
    struct rt_comb_internal *comb;
    int id;

    RT_CK_FULL_PATH(pathp);
    dp = DB_FULL_PATH_CUR_DIR(pathp);

    id = rt_db_get_internal(&intern, dp, dbip, (matp_t)NULL, &rt_uniresource);
    if (id < 0) {
	/* error occurred retrieving object */
	bu_log("Warning: Can not load internal form of %s\n", dp->d_namep);
	return 0;
    }

    if ((dp->d_flags & RT_DIR_COMB) && (id == ID_COMBINATION)) {
	comb = (struct rt_comb_internal *)intern.idb_ptr;
	RT_CK_COMB(comb);
	if (BU_STR_EQUAL(bu_vls_addr(&comb->shader), "light")) {
	    rt_db_free_internal(&intern);
	    return 0;
	}
    }

    return 1;
}
Пример #2
0
static union tree *
    leaf_stub(struct db_tree_state *tsp, struct db_full_path *pathp, struct rt_db_internal *ip, genptr_t client_data)
{
    struct directory *fp_name;	/* name from pathp */

    fp_name = DB_FULL_PATH_CUR_DIR( pathp );
    bu_log( "Only regions may be converted to TANKILL format\n\t%s is not a region and will be ignored\n", fp_name->d_namep );
    return( (union tree *)NULL );
}
Пример #3
0
/* stubs to warn of the unexpected */
static union tree *
    region_stub(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data)
{
    struct directory *fp_name;	/* name from pathp */

    fp_name = DB_FULL_PATH_CUR_DIR( pathp );
    bu_log( "region stub called (for object %s), this shouldn't happen\n", fp_name->d_namep );
    return( (union tree *)NULL );
}
Пример #4
0
/**
 * This routine will be called by db_walk_tree() once all the solids
 * in this region have been visited.
 *
 * This routine must be prepared to run in parallel.  As a result,
 * note that the details of the solids pointed to by the soltab
 * pointers in the tree may not be filled in when this routine is
 * called (due to the way multiple instances of solids are handled).
 * Therefore, everything which referred to the tree has been moved out
 * into the serial section.  (_rt_tree_region_assign, rt_bound_tree)
 */
HIDDEN union tree *
_rt_gettree_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data)
{
    struct region *rp;
    struct directory *dp = NULL;
    size_t shader_len=0;
    struct rt_i *rtip;
    Tcl_HashTable *tbl = (Tcl_HashTable *)client_data;
    Tcl_HashEntry *entry;
    matp_t inv_mat;
    struct bu_attribute_value_set avs;
    struct bu_attribute_value_pair *avpp;

    RT_CK_DBI(tsp->ts_dbip);
    RT_CK_FULL_PATH(pathp);
    RT_CK_TREE(curtree);
    rtip =  tsp->ts_rtip;
    RT_CK_RTI(rtip);
    RT_CK_RESOURCE(tsp->ts_resp);

    if (curtree->tr_op == OP_NOP) {
	/* Ignore empty regions */
	return curtree;
    }

    BU_ALLOC(rp, struct region);
    rp->l.magic = RT_REGION_MAGIC;
    rp->reg_regionid = tsp->ts_regionid;
    rp->reg_is_fastgen = tsp->ts_is_fastgen;
    rp->reg_aircode = tsp->ts_aircode;
    rp->reg_gmater = tsp->ts_gmater;
    rp->reg_los = tsp->ts_los;

    dp = (struct directory *)DB_FULL_PATH_CUR_DIR(pathp);
    if (!dp)
	return TREE_NULL;

    bu_avs_init_empty(&avs);
    if (db5_get_attributes(tsp->ts_dbip, &avs, dp) == 0) {
	/* copy avs */
	bu_avs_init_empty(&(rp->attr_values));
	for (BU_AVS_FOR(avpp, &(tsp->ts_attrs))) {
	    bu_avs_add(&(rp->attr_values), avpp->name, bu_avs_get(&avs, avpp->name));
	}
    }
Пример #5
0
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;
    }
}
Пример #6
0
int cyclic_path(const struct db_full_path *fp, const char *name)
{
    /* skip the last one added since it is currently being tested. */
    long int depth = fp->fp_len - 1;
    const char *test_name;

    if (name && !name[0] == '\0') {
	test_name = name;
    } else {
	test_name = DB_FULL_PATH_CUR_DIR(fp)->d_namep;
    }

    /* check the path to see if it is groundhog day */
    while (--depth >= 0) {
	if (BU_STR_EQUAL(test_name, fp->fp_names[depth]->d_namep)) {
	    return 1;
	}
    }

    /* not cyclic */
    return 0;
}
Пример #7
0
/**
 * @brief This routine is called when a region is first encountered in the
 * hierarchy when processing a tree
 *
 *      @param tsp tree state (for parsing the tree)
 *      @param pathp A listing of all the nodes traversed to get to this node in the database
 *      @param combp the combination record for this region
 */
int
region_start(struct db_tree_state *tsp,
	     const struct db_full_path *pathp,
	     const struct rt_comb_internal *combp,
	     void *client_data)
{
    char *name;
    struct directory *dp;
    struct bu_vls str = BU_VLS_INIT_ZERO;
    struct user_data *your_stuff = (struct user_data *)client_data;

    RT_CK_DBTS(tsp);

    name = db_path_to_string(pathp);
    bu_log("region_start %s\n", name);
    bu_free(name, "reg_start name");

    bu_log("data = %ld\n", your_stuff->data);
    rt_pr_tol(&your_stuff->tol);

    dp = DB_FULL_PATH_CUR_DIR(pathp);

    /* here is where the conversion should be done */
    if (combp->region_flag)
	printf("Write this region (name=%s) as a part in your format:\n", dp->d_namep);
    else
	printf("Write this combination (name=%s) as an assembly in your format:\n", dp->d_namep);

    describe_tree(combp->tree, &str);

    printf("\t%s\n\n", bu_vls_addr(&str));

    bu_vls_free(&str);

    return 0;
}
Пример #8
0
/*
 *			D O _ R E G I O N _ E N D
 *
 *  Called from db_walk_tree().
 *
 *  This routine must be prepared to run in parallel.
 */
union tree *do_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data)
{
    union tree		*ret_tree;
    struct nmgregion	*r;
    struct bu_list		vhead;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char	*sofar = db_path_to_string(pathp);
	bu_log("\ndo_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_done * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return  curtree;

    regions_tried++;

    /* Begin bomb protection */
    if ( ncpu == 1 ) {
	if ( BU_SETJUMP )  {
	    /* Error, bail out */
	    BU_UNSETJUMP;		/* Relinquish the protection */

	    /* Sometimes the NMG library adds debugging bits when
	     * it detects an internal error, before bombing out.
	     */
	    rt_g.NMG_debug = NMG_debug;	/* restore mode */

	    /* Release the tree memory & input regions */
	    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

	    /* Get rid of (m)any other intermediate structures */
	    if ( (*tsp->ts_m)->magic != -1L )
		nmg_km(*tsp->ts_m);

	    /* Now, make a new, clean model structure for next pass. */
	    *tsp->ts_m = nmg_mm();
	    goto out;
	}
    }
    (void)nmg_model_fuse(*tsp->ts_m, tsp->ts_tol);
    ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource);	/* librt/nmg_bool.c */
    BU_UNSETJUMP;		/* Relinquish the protection */
    if ( ret_tree )
	r = ret_tree->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;
    regions_done++;
    if (r != 0) {
	FILE	*fp_psurf;
	int	i;
	struct bu_vls	file_base;
	struct bu_vls	file;

	bu_vls_init(&file_base);
	bu_vls_init(&file);
	bu_vls_strcpy(&file_base, prefix);
	bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
	/* Dots confuse Jack's Peabody language.  Change to '_'. */
	for (i = 0; i < file_base.vls_len; i++)
	    if (file_base.vls_str[i] == '.')
		file_base.vls_str[i] = '_';

	/* Write color attribute to .fig figure file. */
	if (tsp->ts_mater.ma_color_valid != 0) {
	    fprintf(fp_fig, "\tattribute %s {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n",
		    V3ARGS(tsp->ts_mater.ma_color));
	    fprintf(fp_fig, "\t\tambient = 0.18;\n");
	    fprintf(fp_fig, "\t\tdiffuse = 0.72;\n");
	    fprintf(fp_fig, "\t}\n");
	}

	/* Write segment attributes to .fig figure file. */
	fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base));
	if (tsp->ts_mater.ma_color_valid != 0)
	    fprintf(fp_fig,
		    "\t\tattribute=%s;\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n");
	fprintf(fp_fig, "\t}\n");

	if ( bu_vls_strlen(&base_seg) <= 0 )  {
	    bu_vls_vlscat( &base_seg, &file_base );
	} else {
	    fprintf(fp_fig, "\tjoint %s_jt {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig,
		    "\t\tconnect %s_seg.base to %s_seg.base;\n",
		    bu_vls_addr(&file_base),
		    bu_vls_addr(&base_seg) );
	    fprintf(fp_fig, "\t}\n");
	}

	bu_vls_vlscat(&file, &file_base);
	bu_vls_strcat(&file, ".pss");	/* Required Jack suffix. */

	/* Write psurf to .pss file. */
	if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL)
	    perror(bu_vls_addr(&file));
	else {
	    nmg_to_psurf(r, fp_psurf);
	    fclose(fp_psurf);
	    if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	}
	bu_vls_free(&file);

	/* Also write as UNIX-plot file, if desired */
	if ( debug_plots )  {
	    FILE	*fp;
	    bu_vls_vlscat(&file, &file_base);
	    bu_vls_strcat(&file, ".pl");

	    if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL)
		perror(bu_vls_addr(&file));
	    else {
		struct bu_list	vhead;
		pl_color( fp,
			  (int)(tsp->ts_mater.ma_color[0] * 255),
			  (int)(tsp->ts_mater.ma_color[1] * 255),
			  (int)(tsp->ts_mater.ma_color[2] * 255) );
		/* nmg_pl_r( fp, r ); */
		BU_LIST_INIT( &vhead );
		nmg_r_to_vlist( &vhead, r, 0 );
		rt_vlist_to_uplot( fp, &vhead );
		fclose(fp);
		if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	    }
	    bu_vls_free(&file);
	}

	/* NMG region is no longer necessary */
	nmg_kr(r);
    }

    /*
     *  Dispose of original tree, so that all associated dynamic
     *  memory is released now, not at the end of all regions.
     *  A return of TREE_NULL from this routine signals an error,
     *  so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

 out:
    BU_GETUNION(curtree, tree);
    curtree->magic = RT_TREE_MAGIC;
    curtree->tr_op = OP_NOP;
    return(curtree);
}
Пример #9
0
/*
 *			D O _ R E G I O N _ E N D
 *
 *  Called from db_walk_tree().
 *
 *  This routine must be prepared to run in parallel.
 */
union tree *do_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, genptr_t UNUSED(client_data))
{
    union tree		*ret_tree;
    struct nmgregion	*r;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char	*sofar = db_path_to_string(pathp);
	bu_log("\ndo_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_done * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return curtree;

    regions_tried++;

    ret_tree = process_boolean(curtree, tsp, pathp);

    if ( ret_tree )
	r = ret_tree->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;

    regions_done++;

    if (r != 0) {
	FILE	*fp_psurf;
	size_t	i;
	struct bu_vls	file_base = BU_VLS_INIT_ZERO;
	struct bu_vls	file = BU_VLS_INIT_ZERO;

	bu_vls_strcpy(&file_base, prefix);
	bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
	/* Dots confuse Jack's Peabody language.  Change to '_'. */
	for (i = 0; i < file_base.vls_len; i++)
	    if (file_base.vls_str[i] == '.')
		file_base.vls_str[i] = '_';

	/* Write color attribute to .fig figure file. */
	if (tsp->ts_mater.ma_color_valid != 0) {
	    fprintf(fp_fig, "\tattribute %s {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n",
		    V3ARGS(tsp->ts_mater.ma_color));
	    fprintf(fp_fig, "\t\tambient = 0.18;\n");
	    fprintf(fp_fig, "\t\tdiffuse = 0.72;\n");
	    fprintf(fp_fig, "\t}\n");
	}

	/* Write segment attributes to .fig figure file. */
	fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base));
	if (tsp->ts_mater.ma_color_valid != 0)
	    fprintf(fp_fig,
		    "\t\tattribute=%s;\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n");
	fprintf(fp_fig, "\t}\n");

	if ( bu_vls_strlen(&base_seg) <= 0 )  {
	    bu_vls_vlscat( &base_seg, &file_base );
	} else {
	    fprintf(fp_fig, "\tjoint %s_jt {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig,
		    "\t\tconnect %s_seg.base to %s_seg.base;\n",
		    bu_vls_addr(&file_base),
		    bu_vls_addr(&base_seg) );
	    fprintf(fp_fig, "\t}\n");
	}

	bu_vls_vlscat(&file, &file_base);
	bu_vls_strcat(&file, ".pss");	/* Required Jack suffix. */

	/* Write psurf to .pss file. */
	if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL)
	    perror(bu_vls_addr(&file));
	else {
	    nmg_to_psurf(r, fp_psurf);
	    fclose(fp_psurf);
	    if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	}
	bu_vls_free(&file);

	/* Also write as UNIX-plot file, if desired */
	if ( debug_plots )  {
	    FILE	*fp;
	    bu_vls_vlscat(&file, &file_base);
	    bu_vls_strcat(&file, ".pl");

	    if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL)
		perror(bu_vls_addr(&file));
	    else {
		struct bu_list	vhead;
		pl_color( fp,
			  (int)(tsp->ts_mater.ma_color[0] * 255),
			  (int)(tsp->ts_mater.ma_color[1] * 255),
			  (int)(tsp->ts_mater.ma_color[2] * 255) );
		/* nmg_pl_r( fp, r ); */
		BU_LIST_INIT( &vhead );
		nmg_r_to_vlist( &vhead, r, 0 );
		rt_vlist_to_uplot( fp, &vhead );
		fclose(fp);
		if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	    }
	    bu_vls_free(&file);
	}

	/* NMG region is no longer necessary */
	nmg_kr(r);
    }

    /*
     *  Dispose of original tree, so that all associated dynamic
     *  memory is released now, not at the end of all regions.
     *  A return of TREE_NULL from this routine signals an error,
     *  so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

    BU_ALLOC(curtree, union tree);
    RT_TREE_INIT(curtree);
    curtree->tr_op = OP_NOP;
    return curtree;
}
Пример #10
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, &reg->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;
}
Пример #11
0
/**
 * R T _ G E T T R E E _ L E A F
 *
 * This routine must be prepared to run in parallel.
 */
HIDDEN union tree *rt_gettree_leaf(struct db_tree_state *tsp, struct db_full_path *pathp, struct rt_db_internal *ip, genptr_t client_data)
    /*const*/

    /*const*/

{
    register struct soltab	*stp;
    union tree		*curtree;
    struct directory	*dp;
    register matp_t		mat;
    int			i;
    struct rt_i		*rtip;

    RT_CK_DBTS(tsp);
    RT_CK_DBI(tsp->ts_dbip);
    RT_CK_FULL_PATH(pathp);
    RT_CK_DB_INTERNAL(ip);
    rtip = tsp->ts_rtip;
    RT_CK_RTI(rtip);
    RT_CK_RESOURCE(tsp->ts_resp);
    dp = DB_FULL_PATH_CUR_DIR(pathp);

    /* Determine if this matrix is an identity matrix */

    if ( !bn_mat_is_equal(tsp->ts_mat, bn_mat_identity, &rtip->rti_tol)) {
	/* Not identity matrix */
	mat = (matp_t)tsp->ts_mat;
    } else {
	/* Identity matrix */
	mat = (matp_t)0;
    }

    /*
     * Check to see if this exact solid has already been processed.
     * Match on leaf name and matrix.  Note that there is a race here
     * between having st_id filled in a few lines below (which is
     * necessary for calling ft_prep), and ft_prep filling in
     * st_aradius.  Fortunately, st_aradius starts out as zero, and
     * will never go down to -1 unless this soltab structure has
     * become a dead solid, so by testing against -1 (instead of <= 0,
     * like before, oops), it isn't a problem.
     */
    stp = rt_find_identical_solid( mat, dp, rtip );
    if ( stp->st_id != 0 )  {
	/* stp is an instance of a pre-existing solid */
	if ( stp->st_aradius <= -1 )  {
	    /* It's dead, Jim.  st_uses was not incremented. */
	    return( TREE_NULL );	/* BAD: instance of dead solid */
	}
	goto found_it;
    }

    if ( rtip->rti_add_to_new_solids_list ) {
	bu_ptbl_ins( &rtip->rti_new_solids, (long *)stp );
    }

    stp->st_id = ip->idb_type;
    stp->st_meth = &rt_functab[ip->idb_type];
    if ( mat )  {
	mat = stp->st_matp;
    } else {
	mat = (matp_t)bn_mat_identity;
    }

    RT_CK_DB_INTERNAL( ip );

    /* init solid's maxima and minima */
    VSETALL( stp->st_max, -INFINITY );
    VSETALL( stp->st_min,  INFINITY );

    /*
     * If the ft_prep routine wants to keep the internal structure,
     * that is OK, as long as idb_ptr is set to null.  Note that the
     * prep routine may have changed st_id.
     */
    if ( stp->st_meth->ft_prep( stp, ip, rtip ) )  {
	int	hash;
	/* Error, solid no good */
	bu_log("rt_gettree_leaf(%s):  prep failure\n", dp->d_namep );
	/* Too late to delete soltab entry; mark it as "dead" */
	hash = db_dirhash( dp->d_namep );
	ACQUIRE_SEMAPHORE_TREE(hash);
	stp->st_aradius = -1;
	stp->st_uses--;
	RELEASE_SEMAPHORE_TREE(hash);
	return( TREE_NULL );		/* BAD */
    }

    if ( rtip->rti_dont_instance )  {
	/*
	 * If instanced solid refs are not being compressed, then
	 * memory isn't an issue, and the application (such as
	 * solids_on_ray) probably cares about the full path of this
	 * solid, from root to leaf.  So make it available here.
	 * (stp->st_dp->d_uses could be the way to discriminate
	 * references uniquely, if the path isn't enough.  To locate
	 * given dp and d_uses, search dp->d_use_hd list.  Question
	 * is, where to stash current val of d_uses?)
	 */
	db_full_path_init( &stp->st_path );
	db_dup_full_path( &stp->st_path, pathp );
    } else {
	/*
	 * If there is more than just a direct reference to this leaf
	 * from it's containing region, copy that below-region path
	 * into st_path.  Otherwise, leave st_path's magic number 0.
	 *
	 * XXX nothing depends on this behavior yet, and this whole
	 * XXX 'else' clause might well be deleted. -Mike
	 */
	i = pathp->fp_len-1;
	if ( i > 0 && !(pathp->fp_names[i-1]->d_flags & DIR_REGION) )  {
	    /* Search backwards for region.  If no region, use whole path */
	    for ( --i; i > 0; i-- )  {
		if ( pathp->fp_names[i-1]->d_flags & DIR_REGION ) break;
	    }
	    if ( i < 0 )  i = 0;
	    db_full_path_init( &stp->st_path );
	    db_dup_path_tail( &stp->st_path, pathp, i );
	}
    }
    if (RT_G_DEBUG&DEBUG_TREEWALK && stp->st_path.magic == DB_FULL_PATH_MAGIC)  {
	char	*sofar = db_path_to_string(&stp->st_path);
	bu_log("rt_gettree_leaf() st_path=%s\n", sofar );
	bu_free(sofar, "path string");
    }

    if (RT_G_DEBUG&DEBUG_SOLIDS)  {
	struct bu_vls	str;
	bu_log("\n---Primitive %d: %s\n", stp->st_bit, dp->d_namep);
	bu_vls_init( &str );
	/* verbose=1, mm2local=1.0 */
	if ( stp->st_meth->ft_describe( &str, ip, 1, 1.0, tsp->ts_resp, tsp->ts_dbip ) < 0 )  {
	    bu_log("rt_gettree_leaf(%s):  solid describe failure\n",
		   dp->d_namep );
	}
	bu_log( "%s:  %s", dp->d_namep, bu_vls_addr( &str ) );
	bu_vls_free( &str );
    }

 found_it:
    RT_GET_TREE( curtree, tsp->ts_resp );
    curtree->magic = RT_TREE_MAGIC;
    curtree->tr_op = OP_SOLID;
    curtree->tr_a.tu_stp = stp;
    /* regionp will be filled in later by rt_tree_region_assign() */
    curtree->tr_a.tu_regionp = (struct region *)0;

    if (RT_G_DEBUG&DEBUG_TREEWALK)  {
	char	*sofar = db_path_to_string(pathp);
	bu_log("rt_gettree_leaf() %s\n", sofar );
	bu_free(sofar, "path string");
    }

    return(curtree);
}
Пример #12
0
/*
 * Called from db_walk_tree().
 *
 * This routine must be prepared to run in parallel.
 */
union tree *
do_nmg_region_end(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *UNUSED(client_data))
{
    union tree *result;
    struct nmgregion *r;
    struct bu_list vhead;
    struct directory *dp;
    int dependent;
    size_t i;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char *sofar = db_path_to_string(pathp);
	bu_log("\ndo_nmg_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_done * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return curtree;

    regions_tried++;

    if (verbose)
	bu_log("\ndoing boolean tree evaluate...\n");

    /* evaluate the boolean */
    result = process_boolean(tsp, curtree, pathp);

    if (result)
	r = result->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;

    if (verbose)
	bu_log("\nfinished boolean tree evaluate...\n");

    regions_done++;
    if (r != NULL) {

	dp = DB_FULL_PATH_CUR_DIR(pathp);

	if (multi_file) {
	    /* Open the output file */
	    if (output_file == NULL)
		fp_dir = stdout;
	    else {
		char *multi_name;
		size_t len;
		int unique = 0;
		char suffix[SUFFIX_LEN+1];

		/* construct a unique file name */
		len = strlen(output_file) + strlen(dp->d_namep) + 6 + SUFFIX_LEN;
		multi_name = (char *)bu_malloc(sizeof(char)*len, "multi_name");
		snprintf(multi_name, len, "%s/%s.igs", output_file, dp->d_namep);
		bu_strlcpy(suffix, "a", sizeof(suffix));
		suffix[0]--;
		while (!unique) {
		    if (bu_file_readable(multi_name)) {
			unique = 1;
			break;
		    }

		    /* not unique, try adding a suffix */
		    len = strlen(suffix);
		    i = len - 1;
		    suffix[i]++;
		    while (suffix[i] > 'z' && i > 0) {
			suffix[i] = 'a';
			i--;
			suffix[i]++;
		    }

		    if (suffix[0] > 'z' && len < SUFFIX_LEN) {
			for (i = 0; i <= len; i++)
			    suffix[i] = 'a';
		    } else if (suffix[0] > 'z' && len >= SUFFIX_LEN) {
			bu_log("too many files with the same name (%s)\n", dp->d_namep);
			bu_exit(1, "Cannot create a unique filename, \n");
		    }
		    snprintf(multi_name, len, "%s/%s%s.igs", output_file, dp->d_namep, suffix);
		}
		if ((fp_dir = fopen(multi_name, "wb")) == NULL) {
		    perror("g-iges");
		    bu_exit(1, "Cannot open output file: %s\n", multi_name);
		}
	    }

	    /* Open the temporary file for the parameter section */
	    if ((fp_param = bu_temp_file(NULL, 0)) == NULL) {
		perror("g-iges");
		bu_exit(1, "Cannot open temporary file\n");
	    }

	    /* let the IGES routines know the selected tolerances and the database pointer */
	    iges_init(&tol, &ttol, verbose, DBIP);

	    /* Write start and global sections of the IGES file */
	    w_start_global(fp_dir, fp_param, db_name, prog_name, output_file, __DATE__, brlcad_version());
	}

	if (mode == FACET_MODE) {
	    dependent = 1;
	    for (i = 0; i < no_of_indeps; i++) {
		if (!bu_strncmp(dp->d_namep, independent[i], NAMESIZE+1)) {
		    dependent = 0;
		    break;
		}
	    }

	    dp->d_uses = (-nmgregion_to_iges(dp->d_namep, r, dependent, fp_dir, fp_param));
	} else if (mode == TRIMMED_SURF_MODE)
	    dp->d_uses = (-nmgregion_to_tsurf(dp->d_namep, r, fp_dir, fp_param));

	/* NMG region is no longer necessary */
	nmg_kr(r);

	if (multi_file) {
	    char copy_buffer[CP_BUF_SIZE] = {0};

	    /* Copy the parameter section from the temporary file to the output file */
	    if ((bu_fseek(fp_param, 0, 0))) {
		perror("g-iges");
		bu_exit(1, "Cannot seek to start of temporary file\n");
	    }

	    while ((i = fread(copy_buffer, 1, CP_BUF_SIZE, fp_param)))
		if (fwrite(copy_buffer, 1, i, fp_dir) != i) {
		    perror("g-iges");
		    bu_exit(1, "Error in copying parameter data to %s\n", output_file);
		}

	    /* Write the terminate section */
	    w_terminate(fp_dir);
	    fclose(fp_dir);
	    fclose(fp_param);
	}
    }

    /*
     * Dispose of original tree, so that all associated dynamic
     * memory is released now, not at the end of all regions.
     * A return of TREE_NULL from this routine signals an error,
     * so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

    BU_ALLOC(curtree, union tree);
    RT_TREE_INIT(curtree);
    curtree->tr_op = OP_NOP;
    return curtree;
}
Пример #13
0
/* This routine is called by the tree walker (db_walk_tree)
 * for every primitive encountered in the trees specified on the command line */
union tree *
primitive_func(struct db_tree_state *tsp,
	       const struct db_full_path *pathp,
	       struct rt_db_internal *ip,
	       void *UNUSED(client_data))
{
    struct directory *dp;
    char *name;
    dp = DB_FULL_PATH_CUR_DIR(pathp);

    RT_CK_DBTS(tsp);

    name = db_path_to_string(pathp);
    bu_log("leaf_func    %s\n", name);
    bu_free(name, "region_end name");

    /* handle each type of primitive (see h/rtgeom.h) */
    if (ip->idb_major_type == DB5_MAJORTYPE_BRLCAD) {
	switch (ip->idb_type) {
	    /* most commonly used primitives */
	    case ID_TOR:	/* torus */
		{
		    struct rt_tor_internal *tor = (struct rt_tor_internal *)ip->idb_ptr;

		    printf("Write this torus (name=%s) in your format:\n", dp->d_namep);
		    printf("\tV=(%g %g %g)\n", V3ARGS(tor->v));
		    printf("\tnormal=(%g %g %g)\n", V3ARGS(tor->h));
		    printf("\tradius1 = %g\n", tor->r_a);
		    printf("\tradius2 = %g\n", tor->r_h);
		    break;
		}
	    case ID_TGC: /* truncated general cone frustum */
	    case ID_REC: /* right elliptical cylinder */
		{
		    /* This primitive includes circular cross-section
		     * cones and cylinders
		     */
		    struct rt_tgc_internal *tgc = (struct rt_tgc_internal *)ip->idb_ptr;

		    printf("Write this TGC (name=%s) in your format:\n", dp->d_namep);
		    printf("\tV=(%g %g %g)\n", V3ARGS(tgc->v));
		    printf("\tH=(%g %g %g)\n", V3ARGS(tgc->h));
		    printf("\tA=(%g %g %g)\n", V3ARGS(tgc->a));
		    printf("\tB=(%g %g %g)\n", V3ARGS(tgc->b));
		    printf("\tC=(%g %g %g)\n", V3ARGS(tgc->c));
		    printf("\tD=(%g %g %g)\n", V3ARGS(tgc->d));
		    break;
		}
	    case ID_ELL:
	    case ID_SPH:
		{
		    /* spheres and ellipsoids */
		    struct rt_ell_internal *ell = (struct rt_ell_internal *)ip->idb_ptr;

		    printf("Write this ellipsoid (name=%s) in your format:\n", dp->d_namep);
		    printf("\tV=(%g %g %g)\n", V3ARGS(ell->v));
		    printf("\tA=(%g %g %g)\n", V3ARGS(ell->a));
		    printf("\tB=(%g %g %g)\n", V3ARGS(ell->b));
		    printf("\tC=(%g %g %g)\n", V3ARGS(ell->c));
		    break;
		}
	    case ID_ARB8:	/* convex primitive with from four to six faces */
		{
		    int i;

		    /* this primitive may have degenerate faces
		     * faces are: 0123, 7654, 0347, 1562, 0451, 3267
		     * (points listed above in counter-clockwise order)
		     */
		    struct rt_arb_internal *arb = (struct rt_arb_internal *)ip->idb_ptr;

		    printf("Write this ARB (name=%s) in your format:\n", dp->d_namep);
		    for (i=0; i<8; i++)
			printf("\tpoint #%d: (%g %g %g)\n", i, V3ARGS(arb->pt[i]));
		    break;
		}

		/* other primitives, left as an exercise to the reader */

	    case ID_BOT:	/* Bag O' Triangles */
	    case ID_ARS:
		    /* series of curves
		     * each with the same number of points
		     */
	    case ID_HALF:
		    /* half universe defined by a plane */
	    case ID_POLY:
		    /* polygons (up to 5 vertices per) */
	    case ID_BSPLINE:
		    /* NURB surfaces */
	    case ID_NMG:
		    /* N-manifold geometry */
	    case ID_ARBN:
	    case ID_DSP:
		    /* Displacement map (terrain primitive) */
		    /* the DSP primitive may reference an external file or binunif object */
	    case ID_HF:
		    /* height field (terrain primitive) */
		    /* the HF primitive references an external file */
	    case ID_EBM:
		    /* extruded bit-map */
		    /* the EBM primitive references an external file */
	    case ID_VOL:
		    /* the VOL primitive references an external file */
	    case ID_PIPE:
	    case ID_PARTICLE:
	    case ID_RPC:
	    case ID_RHC:
	    case ID_EPA:
	    case ID_EHY:
	    case ID_ETO:
	    case ID_GRIP:
	    case ID_SKETCH:
	    case ID_EXTRUDE:
		    /* note that an extrusion references a sketch, make sure you convert
		     * the sketch also
		     */
	    default:
		bu_log("Primitive %s is an unsupported or unrecognized type (%d)\n", dp->d_namep, ip->idb_type);
		break;
	}
    } else {
	switch (ip->idb_major_type) {
	    case DB5_MAJORTYPE_BINARY_UNIF:
		{
		    /* not actually a primitive, just a block of storage for data
		     * a uniform array of chars, ints, floats, doubles, ...
		     */
		    struct rt_binunif_internal *bin = (struct rt_binunif_internal *)ip->idb_ptr;

		    if (bin)
			printf("Found a binary object (%s)\n\n", dp->d_namep);
		    break;
		}
	    default:
		bu_log("Major type of %s is unrecognized type (%d)\n", dp->d_namep, ip->idb_major_type);
		break;
	}
    }

    return (union tree *) NULL;
}
Пример #14
0
static int
plot_shaded_eval(
    struct ged *gedp,
    const char *path_name,
    struct _ged_client_data *dgcdp)
{
    int ret;
    const char *av[3];
    const char *tmp_basename = "tmp_shaded_eval_obj";
    char *brep_name;

    /* make a name for the temp brep */
    av[0] = "make_name";
    av[1] = tmp_basename;

    ged_make_name(gedp, 2, (const char **)av);

    brep_name = bu_vls_strdup(gedp->ged_result_str);
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* create temp evaluated brep from named object */
    av[0] = "brep";
    av[1] = path_name;
    av[2] = brep_name;
    ret = ged_brep(gedp, 3, av);

    if (ret == GED_OK) {
	int brep_made = 0;
	struct db_tree_state ts;
	struct rt_db_internal brep_intern;
	struct db_full_path input_path, brep_path;

	RT_DB_INTERNAL_INIT(&brep_intern);
	db_full_path_init(&input_path);
	db_full_path_init(&brep_path);

	/* get brep internal */
	ret = get_path_and_state(&ts, &brep_path, brep_name, gedp);
	if (ret == GED_OK) {
	    struct directory *dp = DB_FULL_PATH_CUR_DIR(&brep_path);

	    if (dp->d_flags & RT_DIR_COMB) {
		ret = rt_db_get_internal(&brep_intern, dp, ts.ts_dbip, NULL,
			ts.ts_resp);
	    } else {
		ret = rt_db_get_internal(&brep_intern, dp, ts.ts_dbip, ts.ts_mat,
			ts.ts_resp);
	    }
	    if (ret >= 0) {
		brep_made = 1;
	    }
	    db_free_full_path(&brep_path);
	}

	/* plot brep, but use the path and state of the input object */
	if (brep_made) {
	    ret = get_path_and_state(&ts, &input_path, path_name, gedp);
	    if (ret == GED_OK) {
		plot_shaded(&ts, &input_path, &brep_intern, dgcdp);

		rt_db_free_internal(&brep_intern);
		db_free_full_path(&input_path);
	    }
	}

	/* kill temp brep */
	av[0] = "kill";
	av[1] = brep_name;
	ged_kill(gedp, 2, av);
    }
    bu_free((char *)brep_name, "vls_strdup");

    return ret;
}
void
nmg_2_vrml(struct db_tree_state *tsp, const struct db_full_path *pathp, struct model *m)
{
    struct mater_info *mater = &tsp->ts_mater;
    const struct bn_tol *tol2 = tsp->ts_tol;
    struct nmgregion *reg;
    struct bu_ptbl verts;
    struct vrml_mat mat;
    struct bu_vls vls = BU_VLS_INIT_ZERO;
    char *tok;
    int i;
    int first = 1;
    int is_light = 0;
    point_t ave_pt = VINIT_ZERO;
    struct bu_vls shape_name = BU_VLS_INIT_ZERO;
    char *full_path;
    /* There may be a better way to capture the region_id, than
     * getting the rt_comb_internal structure, (and may be a better
     * way to capture the rt_comb_internal struct), but for now I just
     * copied the method used in select_lights/select_non_lights above,
     * could have used a global variable but I noticed none other were
     * used, so I didn't want to be the first
     */
    struct directory *dp;
    struct rt_db_internal intern;
    struct rt_comb_internal *comb;
    int id;

    /* static due to libbu exception handling */
    static float r, g, b;

    NMG_CK_MODEL(m);

    full_path = db_path_to_string(pathp);

    RT_CK_FULL_PATH(pathp);
    dp = DB_FULL_PATH_CUR_DIR(pathp);

    if (!(dp->d_flags & RT_DIR_COMB)) {
	return;
    }

    id = rt_db_get_internal(&intern, dp, dbip, (matp_t)NULL, &rt_uniresource);
    if (id < 0) {
	bu_log("Cannot internal form of %s\n", dp->d_namep);
	return;
    }

    if (id != ID_COMBINATION) {
	bu_log("Directory/database mismatch!\n\t is '%s' a combination or not?\n",
		dp->d_namep);
	return;
    }

    comb = (struct rt_comb_internal *)intern.idb_ptr;
    RT_CK_COMB(comb);

    if (mater->ma_color_valid) {
	r = mater->ma_color[0];
	g = mater->ma_color[1];
	b = mater->ma_color[2];
    } else {
	r = g = b = 0.5;
    }

    if (mater->ma_shader) {
	tok = strtok(mater->ma_shader, tok_sep);
	bu_strlcpy(mat.shader, tok, TXT_NAME_SIZE);
    } else {
	mat.shader[0] = '\0';
    }

    mat.shininess = -1;
    mat.transparency = -1.0;
    mat.lt_fraction = -1.0;
    VSETALL(mat.lt_dir, 0.0);
    mat.lt_angle = -1.0;
    mat.tx_file[0] = '\0';
    mat.tx_w = -1;
    mat.tx_n = -1;
    bu_vls_strcpy(&vls, &mater->ma_shader[strlen(mat.shader)]);
    (void)bu_struct_parse(&vls, vrml_mat_parse, (char *)&mat, NULL);

    if (bu_strncmp("light", mat.shader, 5) == 0) {
	/* this is a light source */
	is_light = 1;
    } else {
	path_2_vrml_id(&shape_name, full_path);
	fprintf(fp_out, "\t\tDEF %s Shape {\n", bu_vls_addr(&shape_name));

	fprintf(fp_out, "\t\t\t# Component_ID: %ld   %s\n", comb->region_id, full_path);
	fprintf(fp_out, "\t\t\tappearance Appearance {\n");

	if (bu_strncmp("plastic", mat.shader, 7) == 0) {
	    if (mat.shininess < 0) {
		mat.shininess = 10;
	    }
	    if (mat.transparency < SMALL_FASTF) {
		mat.transparency = 0.0;
	    }

	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b);
	    fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0));
	    if (mat.transparency > SMALL_FASTF) {
		fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency);
	    }
	    fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0);
	} else if (bu_strncmp("glass", mat.shader, 5) == 0) {
	    if (mat.shininess < 0) {
		mat.shininess = 4;
	    }
	    if (mat.transparency < SMALL_FASTF) {
		mat.transparency = 0.8;
	    }

	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b);
	    fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0));
	    if (mat.transparency > SMALL_FASTF) {
		fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency);
	    }
	    fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0);
	} else if (bu_strncmp("texture", mat.shader, 7) == 0) {
	    if (mat.tx_w < 0) {
		mat.tx_w = 512;
	    }
	    if (mat.tx_n < 0) {
		mat.tx_n = 512;
	    }
	    if (strlen(mat.tx_file)) {
		int tex_fd;
		unsigned char tex_buf[TXT_BUF_LEN * 3];

		if ((tex_fd = open(mat.tx_file, O_RDONLY | O_BINARY)) == (-1)) {
		    bu_log("Cannot open texture file (%s)\n", mat.tx_file);
		    perror("g-vrml: ");
		} else {
		    long tex_len;
		    long bytes_read = 0;
		    long bytes_to_go = 0;

		    /* Johns note - need to check (test) the texture stuff */
		    fprintf(fp_out, "\t\t\t\ttextureTransform TextureTransform {\n");
		    fprintf(fp_out, "\t\t\t\t\tscale 1.33333 1.33333\n\t\t\t\t}\n");
		    fprintf(fp_out, "\t\t\t\ttexture PixelTexture {\n");
		    fprintf(fp_out, "\t\t\t\t\trepeatS TRUE\n");
		    fprintf(fp_out, "\t\t\t\t\trepeatT TRUE\n");
		    fprintf(fp_out, "\t\t\t\t\timage %d %d %d\n", mat.tx_w, mat.tx_n, 3);
		    tex_len = mat.tx_w*mat.tx_n * 3;
		    while (bytes_read < tex_len) {
			int nbytes;
			long readval;

			bytes_to_go = tex_len - bytes_read;
			CLAMP(bytes_to_go, 0, TXT_BUF_LEN * 3);

			nbytes = 0;
			while (nbytes < bytes_to_go) {
			    readval = read(tex_fd, &tex_buf[nbytes], bytes_to_go-nbytes);
			    if (readval < 0) {
				perror("READ ERROR");
				break;
			    } else {
				nbytes += readval;
			    }
			}
			bytes_read += nbytes;
			for (i = 0; i < nbytes; i += 3) {
			    fprintf(fp_out, "\t\t\t0x%02x%02x%02x\n",
				    tex_buf[i], tex_buf[i+1], tex_buf[i+2]);
			}
		    }
		    fprintf(fp_out, "\t\t\t\t}\n");

		    close(tex_fd);
		}
	    }
	} else if (mater->ma_color_valid) {
	    /* no shader specified, but a color is assigned */
	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g }\n", r, g, b);
	} else {
	    /* If no color was defined set the colors according to the thousands groups */
	    int thou = comb->region_id / 1000;
	    thou == 0 ? fprintf(fp_out, "\t\t\tmaterial USE Material_999\n")
		: thou == 1 ? fprintf(fp_out, "\t\t\tmaterial USE Material_1999\n")
		: thou == 2 ? fprintf(fp_out, "\t\t\tmaterial USE Material_2999\n")
		: thou == 3 ? fprintf(fp_out, "\t\t\tmaterial USE Material_3999\n")
		: thou == 4 ? fprintf(fp_out, "\t\t\tmaterial USE Material_4999\n")
		: thou == 5 ? fprintf(fp_out, "\t\t\tmaterial USE Material_5999\n")
		: thou == 6 ? fprintf(fp_out, "\t\t\tmaterial USE Material_6999\n")
		: thou == 7 ? fprintf(fp_out, "\t\t\tmaterial USE Material_7999\n")
		: thou == 8 ? fprintf(fp_out, "\t\t\tmaterial USE Material_8999\n")
		: fprintf(fp_out, "\t\t\tmaterial USE Material_9999\n");
	}
    }

    if (!is_light) {
	nmg_triangulate_model(m, tol2);
	fprintf(fp_out, "\t\t\t}\n");
	fprintf(fp_out, "\t\t\tgeometry IndexedFaceSet {\n");
	fprintf(fp_out, "\t\t\t\tcoord Coordinate {\n");
    }

    /* get list of vertices */
    nmg_vertex_tabulate(&verts, &m->magic);
    if (!is_light) {
	fprintf(fp_out, "\t\t\t\t\tpoint [");
    } else {
	VSETALL(ave_pt, 0.0);
    }

    for (i = 0; i < BU_PTBL_END(&verts); i++) {
	struct vertex *v;
	struct vertex_g *vg;
	point_t pt_meters;

	v = (struct vertex *)BU_PTBL_GET(&verts, i);
	NMG_CK_VERTEX(v);
	vg = v->vg_p;
	NMG_CK_VERTEX_G(vg);

	/* convert to desired units */
	VSCALE(pt_meters, vg->coord, scale_factor);

	if (is_light) {
	    VADD2(ave_pt, ave_pt, pt_meters);
	}

	if (first) {
	    if (!is_light) {
		fprintf(fp_out, " %10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i);
	    }
	    first = 0;
	} else if (!is_light) {
	    fprintf(fp_out, "\t\t\t\t\t%10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i);
	}
    }

    if (!is_light) {
	fprintf(fp_out, "\t\t\t\t\t]\n\t\t\t\t}\n");
    } else {
	fastf_t one_over_count;
	one_over_count = 1.0/(fastf_t)BU_PTBL_END(&verts);
	VSCALE(ave_pt, ave_pt, one_over_count);
    }

    first = 1;
    if (!is_light) {
	fprintf(fp_out, "\t\t\t\tcoordIndex [\n");
	for (BU_LIST_FOR(reg, nmgregion, &m->r_hd)) {
	    struct shell *s;

	    NMG_CK_REGION(reg);
	    for (BU_LIST_FOR(s, shell, &reg->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 {
Пример #16
0
int
ged_lc(struct ged *gedp, int argc, const char *argv[])
{
    char *file_name = NULL;
    int file_name_flag_cnt = 0;
    int sort_column = 1;
    int sort_column_flag_cnt = 0;
    int find_duplicates_flag = 0;
    int skip_special_duplicates_flag = 0;
    int skip_subtracted_regions_flag = 0;
    int descending_sort_flag = 0;
    int unrecognized_flag_cnt = 0;

    int orig_argc;
    const char **orig_argv;

    static const char *usage = "[-d|-s] [-r] [-z] [-0|-1|-2|-3|-4|-5] [-f {FileName}] {GroupName}";

    int c;
    int error_cnt = 0;

    FILE *outfile = NULL;
    struct bu_vls *output;

    const char *group_name;

    size_t i,j;
    struct bu_ptbl results1 = BU_PTBL_INIT_ZERO;
    struct bu_ptbl results2 = BU_PTBL_INIT_ZERO;
    char *path;
    char *plan;
    struct db_full_path root;
    int matches;
    struct region_record *regions;
    size_t ignored_cnt = 0;

    /* The defaults are the minimum widths to accommodate column headers */
    size_t region_id_len_max = 2;
    size_t material_id_len_max = 3;
    size_t los_len_max = 3;
    size_t obj_len_max = 6;

    /* For the output at the end */
    size_t start, end, incr;

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s\n", usage);
	return GED_HELP;
    }

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    bu_optind = 1; /* re-init bu_getopt() */
    while ((c = bu_getopt(argc, (char * const *)argv, "dsrz012345f:")) != -1) {
	switch (c) {
	    case '0':
	    case '1':
	    case '2':
	    case '3':
	    case '4':
	    case '5':
		sort_column_flag_cnt++;
		sort_column = c - '0';
		break;
	    case 'f':
		file_name_flag_cnt++;
		file_name = bu_optarg;
		break;
	    case 's':
		skip_special_duplicates_flag = 1;
		/* FALLTHROUGH */
	    case 'd':
		find_duplicates_flag = 1;
		break;
	    case 'r':
		skip_subtracted_regions_flag = 1;
		break;
	    case 'z':
		descending_sort_flag = 1;
		break;
	    default:
		unrecognized_flag_cnt++;
	}
    }
    orig_argc = argc;
    orig_argv = argv;
    argc -= (bu_optind - 1);
    argv += (bu_optind - 1);

    /* Attempt to recreate the exact error messages from the original lc.tcl */

    if (file_name_flag_cnt > 1) {
	bu_vls_printf(gedp->ged_result_str, "Error: '-f' used more than once.\n");
	error_cnt++;
    }

    if (sort_column_flag_cnt > 1) {
	bu_vls_printf(gedp->ged_result_str, "Error: Sort column defined more than once.\n");
	error_cnt++;
    }

    if (file_name_flag_cnt + argc + unrecognized_flag_cnt > 3) {
	bu_vls_printf(gedp->ged_result_str, "Error: More than one group name and/or file name was specified.\n");
	error_cnt++;
    } else if (argc < 2) {
	if (file_name_flag_cnt && !file_name) {
	    bu_vls_printf(gedp->ged_result_str, "Error: Group name and file name not specified\n");
	} else {
	    bu_vls_printf(gedp->ged_result_str, "Error: Group name not specified.\n");
	}
        error_cnt++;
    } else if (argc + unrecognized_flag_cnt > 2) {
	bu_vls_printf(gedp->ged_result_str, "Error: More than one group name was specified.\n");
	error_cnt++;
    } else if (file_name_flag_cnt && !file_name) {
	bu_vls_printf(gedp->ged_result_str, "Error: File name not specified.\n");
	error_cnt++;
    }

    if (file_name) {
	char *norm_name;
	norm_name = bu_realpath(file_name, NULL);
	if (file_name[0] == '-') {
	    bu_vls_printf(gedp->ged_result_str, "Error: File name can not start with '-'.\n");
	    error_cnt++;
	} else if (bu_file_exists(file_name, NULL)) {
	    bu_vls_printf(gedp->ged_result_str, "Error: Output file %s already exists.\n",norm_name);
	    error_cnt++;
	} else {
	    outfile = fopen(file_name, "w");
	    if (!outfile) {
		bu_vls_printf(gedp->ged_result_str, "Error: %d\n", errno);
		error_cnt++;
	    }
	}
	bu_vls_printf(gedp->ged_result_str, "Output filename: %s\n", norm_name);
	bu_free(norm_name, "ged_lc");
	output = bu_vls_vlsinit();
    } else {
	output = gedp->ged_result_str;
    }

    if (error_cnt > 0) { return GED_ERROR; }

    group_name = argv[1];

    /* The 7 is for the "-name" and '\0' */
    plan = (char *) bu_malloc(sizeof(char) * (strlen(group_name) + 7), "ged_lc");
    sprintf(plan, "-name %s", group_name);
    matches = db_search(&results1, DB_SEARCH_TREE, plan, 0, NULL, gedp->ged_wdbp->dbip);
    if (matches < 1) {
	bu_vls_printf(gedp->ged_result_str, "Error: Group '%s' does not exist.\n", group_name);
	return GED_ERROR;
    }
    bu_free(plan, "ged_lc");
    db_search_free(&results1);

    if (skip_subtracted_regions_flag) {
	plan = "-type region ! -bool -";
    } else {
	plan = "-type region";
    }
    path = (char *) bu_malloc(sizeof(char) * (strlen(group_name) + 2), "ged_lc");
    sprintf(path, "/%s", group_name);
    db_string_to_path(&root, gedp->ged_wdbp->dbip, path);
    matches = db_search(&results2, DB_SEARCH_TREE, plan, root.fp_len, root.fp_names, gedp->ged_wdbp->dbip);
    bu_free(path, "ged_lc");
    if (matches < 1) { return GED_ERROR; }
    regions = (struct region_record *) bu_malloc(sizeof(struct region_record) * BU_PTBL_LEN(&results2), "ged_lc");
    for (i = 0; i < BU_PTBL_LEN(&results2); i++) {
	struct db_full_path *entry = (struct db_full_path *)BU_PTBL_GET(&results2, i);
	struct directory *dp_curr_dir = DB_FULL_PATH_CUR_DIR(entry);
	struct bu_attribute_value_set avs;

    	j = BU_PTBL_LEN(&results2) - i - 1 ;
	regions[j].ignore = 0;

	bu_avs_init_empty(&avs);
	db5_get_attributes(gedp->ged_wdbp->dbip, &avs, dp_curr_dir);

	regions[j].region_id = get_attr(&avs, "region_id");
	V_MAX(region_id_len_max, strlen(regions[j].region_id));
	regions[j].material_id = get_attr(&avs, "material_id");
	V_MAX(material_id_len_max, strlen(regions[j].material_id));
	regions[j].los = get_attr(&avs, "los");
	V_MAX(los_len_max, strlen(regions[j].los));
	regions[j].obj_name = dp_curr_dir->d_namep;
	V_MAX(obj_len_max, strlen(regions[j].obj_name));

	if (entry->fp_len > 1) {
	    struct directory *dp_parent = DB_FULL_PATH_GET(entry, entry->fp_len - 2);
	    regions[j].obj_parent = dp_parent->d_namep;
	} else {
	    regions[j].obj_parent = "--";
	}
    }

    if (find_duplicates_flag) {

	bu_sort((void *) regions, BU_PTBL_LEN(&results2), sizeof(struct region_record), cmp_regions, NULL);

	for (i = 1;  i < BU_PTBL_LEN(&results2); i++) {
	    int same;
	    if (skip_special_duplicates_flag) {
		same = !cmp_regions((void *)&(regions[i - 1]), (void *)&(regions[i]), NULL);
	    } else {
		same = !bu_strcmp(regions[i - 1].region_id, regions[i].region_id);
	    }
	    if (same) {
		regions[i].ignore = 1;
		ignored_cnt++;
	    }
	}

	if (ignored_cnt == BU_PTBL_LEN(&results2)) {
	    if (file_name) {
		print_cmd_args(output, orig_argc, orig_argv);
		bu_vls_printf(output, "No duplicate region_id\n");
		bu_vls_fwrite(outfile, output);
		fclose(outfile);
	    }
	    bu_vls_printf(gedp->ged_result_str, "No duplicate region_id\n");
	    bu_vls_printf(gedp->ged_result_str, "Done.\n");
	    bu_free(regions, "ged_lc");
	    return GED_ERROR;
	}
    }

    if (sort_column > 0) {
	bu_sort((void *) regions, BU_PTBL_LEN(&results2), sizeof(struct region_record), sort_regions, (void *)&sort_column);
    }

    if (file_name) {
	print_cmd_args(output, orig_argc, orig_argv);
    }

    bu_vls_printf(output, "List length: %d\n", BU_PTBL_LEN(&results2) - ignored_cnt);
    bu_vls_printf(output, "%-*s %-*s %-*s %-*s %s\n",
		  region_id_len_max + 1, "ID",
		  material_id_len_max + 1, "MAT",
		  los_len_max, "LOS",
		  obj_len_max,  "REGION",
		  "PARENT");
    end = BU_PTBL_LEN(&results2);
    if (descending_sort_flag) {
	start = end - 1; end = -1; incr = -1;
    } else {
	start = 0; incr = 1;
    }
    for (i = start; i != end; i += incr) {
	if (regions[i].ignore) { continue; }
	bu_vls_printf(output, "%-*s %-*s %-*s %-*s %s\n",
		      region_id_len_max + 1, regions[i].region_id,
		      material_id_len_max + 1, regions[i].material_id,
		      los_len_max, regions[i].los,
		      obj_len_max, regions[i].obj_name,
		      regions[i].obj_parent);
    }
    bu_vls_printf(gedp->ged_result_str, "Done.\n");

    if (file_name) {
	bu_vls_fwrite(outfile, output);
	fclose(outfile);
    }

    bu_free(regions, "ged_lc");

    return GED_OK;
}
Пример #17
0
/**
 * R T _ G E T T R E E _ R E G I O N _ E N D
 *
 * This routine will be called by db_walk_tree() once all the solids
 * in this region have been visited.
 *
 * This routine must be prepared to run in parallel.  As a result,
 * note that the details of the solids pointed to by the soltab
 * pointers in the tree may not be filled in when this routine is
 * called (due to the way multiple instances of solids are handled).
 * Therefore, everything which referred to the tree has been moved out
 * into the serial section.  (rt_tree_region_assign, rt_bound_tree)
 */
HIDDEN union tree *rt_gettree_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data)
{
    struct region		*rp;
    struct directory	*dp;
    int			shader_len=0;
    struct rt_i		*rtip;
    int			i;
    Tcl_HashTable		*tbl = (Tcl_HashTable *)client_data;
    Tcl_HashEntry		*entry;
    matp_t			inv_mat;

    RT_CK_DBI(tsp->ts_dbip);
    RT_CK_FULL_PATH(pathp);
    RT_CK_TREE(curtree);
    rtip =  tsp->ts_rtip;
    RT_CK_RTI(rtip);
    RT_CK_RESOURCE(tsp->ts_resp);

    if ( curtree->tr_op == OP_NOP )  {
	/* Ignore empty regions */
	return  curtree;
    }

    BU_GETSTRUCT( rp, region );
    rp->l.magic = RT_REGION_MAGIC;
    rp->reg_regionid = tsp->ts_regionid;
    rp->reg_is_fastgen = tsp->ts_is_fastgen;
    rp->reg_aircode = tsp->ts_aircode;
    rp->reg_gmater = tsp->ts_gmater;
    rp->reg_los = tsp->ts_los;

    if ( tsp->ts_attrs.count && tsp->ts_attrs.avp ) {
	rp->attr_values = (struct bu_mro **)bu_calloc( tsp->ts_attrs.count+1,
						       sizeof( struct bu_mro *), "regp->attr_values" );
	for ( i=0; i<tsp->ts_attrs.count; i++ ) {
	    rp->attr_values[i] = bu_malloc( sizeof( struct bu_mro ),
					    "rp->attr_values[i]" );
	    bu_mro_init_with_string( rp->attr_values[i], tsp->ts_attrs.avp[i].value );
	}
    } else {
	rp->attr_values = (struct bu_mro **)NULL;
    }

    rp->reg_mater = tsp->ts_mater; /* struct copy */
    if ( tsp->ts_mater.ma_shader )
	shader_len = strlen( tsp->ts_mater.ma_shader );
    if ( shader_len )
    {
	rp->reg_mater.ma_shader = bu_strdup( tsp->ts_mater.ma_shader );
    }
    else
	rp->reg_mater.ma_shader = (char *)NULL;

    rp->reg_name = db_path_to_string( pathp );

    dp = (struct directory *)DB_FULL_PATH_CUR_DIR(pathp);

    if (RT_G_DEBUG&DEBUG_TREEWALK)  {
	bu_log("rt_gettree_region_end() %s\n", rp->reg_name );
	rt_pr_tree( curtree, 0 );
    }

    rp->reg_treetop = curtree;
    rp->reg_all_unions = db_is_tree_all_unions( curtree );

    /* Determine material properties */
    rp->reg_mfuncs = (char *)0;
    rp->reg_udata = (char *)0;
    if ( rp->reg_mater.ma_color_valid == 0 )
	rt_region_color_map(rp);

    /* enter critical section */
    bu_semaphore_acquire( RT_SEM_RESULTS );

    rp->reg_instnum = dp->d_uses++;

    /*
     * Add the region to the linked list of regions.
     * Positions in the region bit vector are established at this time.
     */
    BU_LIST_INSERT( &(rtip->HeadRegion), &rp->l );

    /* Assign bit vector pos. */
    rp->reg_bit = rtip->nregions++;

    /* leave critical section */
    bu_semaphore_release( RT_SEM_RESULTS );

    if ( tbl && bu_avs_get( &tsp->ts_attrs, "ORCA_Comp" ) ) {
	int newentry;
	long int reg_bit = rp->reg_bit;

	inv_mat = (matp_t)bu_calloc( 16, sizeof( fastf_t ), "inv_mat" );
	if ( tsp->ts_mat )
	    bn_mat_inv( inv_mat, tsp->ts_mat );
	else
	    MAT_IDN( inv_mat );

	/* enter critical section */
	bu_semaphore_acquire( RT_SEM_RESULTS );

	entry = Tcl_CreateHashEntry(tbl, (char *)reg_bit, &newentry);
	Tcl_SetHashValue( entry, (ClientData)inv_mat );

	/* leave critical section */
	bu_semaphore_release( RT_SEM_RESULTS );
    }

    if ( RT_G_DEBUG & DEBUG_REGIONS )  {
	bu_log("Add Region %s instnum %d\n",
	       rp->reg_name, rp->reg_instnum);
    }

    /* Indicate that we have swiped 'curtree' */
    return(TREE_NULL);
}