Exemplo n.º 1
0
void
prepare(void)
{
    struct rt_i *rtip = APP.a_rt_i;

    RT_CK_RTI(rtip);

    if (debug)  fprintf(stderr, "prepare()\n");

    /*
     * initialize application -- it will allocate 1 line and
     * set buf_mode=1, as well as do mlib_init().
     */
    (void)view_init(&APP, title_file, title_obj, 0, 0);

    do_prep(rtip);

    if (rtip->nsolids <= 0)
	bu_exit(3, "ph_matrix: No solids remain after prep.\n");

    grid_setup();

    /* initialize lighting */
    view_2init(&APP, NULL);

    rtip->nshots = 0;
    rtip->nmiss_model = 0;
    rtip->nmiss_tree = 0;
    rtip->nmiss_solid = 0;
    rtip->nmiss = 0;
    rtip->nhits = 0;
    rtip->rti_nrays = 0;

}
Exemplo n.º 2
0
HIDDEN int
envmap_setup(register struct region *rp, struct bu_vls *matparm, void **UNUSED(dpp), const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)
{
    struct mfuncs *shaders = MF_NULL;

    BU_CK_VLS(matparm);
    RT_CK_RTI(rtip);

    if (env_region.reg_mfuncs) {
	bu_log("envmap_setup:  second environment map ignored\n");
	return 0;		/* drop region */
    }

    env_region = *rp;		/* struct copy */
    /* Get copies of, or eliminate, references to dynamic structures */
    env_region.reg_name = bu_strdup(rp->reg_name);
    env_region.reg_treetop = TREE_NULL;
    env_region.l.forw = BU_LIST_NULL;
    env_region.l.back = BU_LIST_NULL;
    env_region.reg_mfuncs = (char *)0;
    env_region.reg_mater.ma_shader = bu_vls_strdup(matparm);

    /* get list of available shaders */
    if (!shaders) {
	optical_shader_init(&shaders);
    }
    if (mlib_setup(&shaders, &env_region, rtip) < 0)
	bu_log("envmap_setup() material '%s' failed\n",
	       env_region.reg_mater.ma_shader);


    return 0;		/* This region should be dropped */
}
Exemplo n.º 3
0
void
ph_matrix(struct pkg_conn *UNUSED(pc), char *buf)
{
#ifndef NO_MAGIC_CHECKING
    struct rt_i *rtip = APP.a_rt_i;

    RT_CK_RTI(rtip);
#endif

    if (debug)  fprintf(stderr, "ph_matrix: %s\n", buf);

    /* Start options in a known state */
    AmbientIntensity = 0.4;
    hypersample = 0;
    jitter = 0;
    rt_perspective = 0;
    eye_backoff = M_SQRT2;
    aspect = 1;
    stereo = 0;
    use_air = 0;
    width = height = 0;
    cell_width = cell_height = 0;
    lightmodel = 0;
    incr_mode = 0;
    rt_dist_tol = 0;
    rt_perp_tol = 0;

    process_cmd(buf);
    free(buf);

    seen_matrix = 1;
}
Exemplo n.º 4
0
int
rt_obj_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    int id;
    const struct rt_functab *ft;

    if (!stp || !ip)
	return -1;

    RT_CK_SOLTAB(stp);
    RT_CK_DB_INTERNAL(ip);
    if (rtip) RT_CK_RTI(rtip);

    id = stp->st_id;
    if (id < 0)
	return -2;

    ft = &OBJ[id];
    if (!ft)
	return -3;
    if (!ft->ft_prep)
	return -4;

    return ft->ft_prep(stp, ip, rtip);
}
Exemplo n.º 5
0
/*
 *  Go poke the rgb values of a region, on the fly.
 *  This does not update the inmemory database,
 *  so any changes will vanish on next re-prep unless other measures
 *  are taken.
 */
int
sh_directchange_shader(ClientData UNUSED(clientData), Tcl_Interp *interp, int argc, const char *argv[])
{
    long int rtip_val;
    struct rt_i	*rtip;
    struct region *regp;
    struct directory *dp;
    struct bu_vls shader = BU_VLS_INIT_ZERO;

    if ( argc < 4 )  {
	Tcl_AppendResult(interp, "Usage: sh_directchange_shader $rtip comb shader_arg(s)\n", NULL);
	return TCL_ERROR;
    }

    rtip_val = atol(argv[1]);
    rtip = (struct rt_i *)rtip_val;
    RT_CK_RTI(rtip);

    if ( rtip->needprep )  {
	Tcl_AppendResult(interp, "rt_prep() hasn't been called yet, error.\n", NULL);
	return TCL_ERROR;
    }

    if ( (dp = db_lookup( rtip->rti_dbip, argv[2], LOOKUP_NOISY)) == RT_DIR_NULL )  {
	Tcl_AppendResult(interp, argv[2], ": not found\n", NULL);
	return TCL_ERROR;
    }

    bu_vls_from_argv(&shader, argc-3, argv+3);
    bu_vls_trimspace(&shader);

    /* Find all region names which match /comb/ pattern */
    for ( BU_LIST_FOR( regp, region, &rtip->HeadRegion ) )  {
/*	if ( dp->d_flags & RT_DIR_REGION )  {	*/
	    /* name will occur at end of region string w/leading slash */
/*	} else {	*/
	    /* name will occur anywhere, bracketed by slashes */
/*	}	*/

	/* XXX quick hack */
	if ( strstr( regp->reg_name, argv[2] ) == NULL )  continue;

	/* Modify the region's shader string */
	bu_log("sh_directchange_shader() changing %s\n", regp->reg_name);
	if ( regp->reg_mater.ma_shader )
	    bu_free( (void *)regp->reg_mater.ma_shader, "reg_mater.ma_shader");
	regp->reg_mater.ma_shader = bu_vls_strdup(&shader);

	/* Update the shader */
	mlib_free(regp);
	if ( mlib_setup( &mfHead, regp, rtip ) != 1 )  {
	    Tcl_AppendResult(interp, regp->reg_name, ": mlib_setup() failure\n", NULL);
	}
    }

    bu_vls_free(&shader);
    return TCL_OK;
}
Exemplo n.º 6
0
/*
 *  Process pixels from 'a' to 'b' inclusive.
 *  The results are sent back all at once.
 *  Limitation:  may not do more than 'width' pixels at once,
 *  because that is the size of the buffer (for now).
 */
void
ph_lines(struct pkg_conn *UNUSED(pc), char *buf)
{
    int		a, b, fr;
    struct line_info	info;
    struct rt_i	*rtip = APP.a_rt_i;
    struct	bu_external	ext;

    RT_CK_RTI(rtip);

    if (debug > 1)  fprintf(stderr, "ph_lines: %s\n", buf);
    if (!seen_gettrees)  {
	bu_log("ph_lines:  no MSG_GETTREES yet\n");
	return;
    }
    if (!seen_matrix)  {
	bu_log("ph_lines:  no MSG_MATRIX yet\n");
	return;
    }

    a=0;
    b=0;
    fr=0;
    if (sscanf(buf, "%d %d %d", &a, &b, &fr) != 3)
	bu_exit(2, "ph_lines:  %s conversion error\n", buf);

    srv_startpix = a;		/* buffer un-offset for view_pixel */
    if (b-a+1 > srv_scanlen)  b = a + srv_scanlen - 1;

    rtip->rti_nrays = 0;
    info.li_startpix = a;
    info.li_endpix = b;
    info.li_frame = fr;

    rt_prep_timer();
    do_run(a, b);
    info.li_nrays = rtip->rti_nrays;
    info.li_cpusec = rt_read_timer((char *)0, 0);
    info.li_percent = 42.0;	/* for now */

    if (!bu_struct_export(&ext, (void *)&info, desc_line_info))
	bu_exit(98, "ph_lines: bu_struct_export failure\n");

    if (debug)  {
	fprintf(stderr, "PIXELS fr=%d pix=%d..%d, rays=%d, cpu=%g\n",
		info.li_frame,
		info.li_startpix, info.li_endpix,
		info.li_nrays, info.li_cpusec);
    }
    if (pkg_2send(MSG_PIXELS, (const char *)ext.ext_buf, ext.ext_nbytes, (const char *)scanbuf, (b-a+1)*3, pcsrv) < 0)  {
	fprintf(stderr, "MSG_PIXELS send error\n");
	bu_free_external(&ext);
    }

    bu_free_external(&ext);
}
Exemplo n.º 7
0
/*
 *  Go poke the rgb values of a region, on the fly.
 *  This does not update the inmemory database,
 *  so any changes will vanish on next re-prep unless other measures
 *  are taken.
 */
int
sh_directchange_rgb(ClientData UNUSED(clientData), Tcl_Interp *interp, int argc, const char *argv[])
{
    long int rtip_val;
    struct rt_i	*rtip;
    struct region	*regp;
    struct directory *dp;
    float		r, g, b;

    if ( argc != 6 )  {
	Tcl_AppendResult(interp, "Usage: sh_directchange_rgb $rtip comb r g b\n", NULL);
	return TCL_ERROR;
    }

    r = atoi(argv[3+0]) / 255.0;
    g = atoi(argv[3+1]) / 255.0;
    b = atoi(argv[3+2]) / 255.0;

    rtip_val = atol(argv[1]);
    rtip = (struct rt_i *)rtip_val;
    RT_CK_RTI(rtip);

    if ( rtip->needprep )  {
	Tcl_AppendResult(interp, "rt_prep() hasn't been called yet, error.\n", NULL);
	return TCL_ERROR;
    }

    if ( (dp = db_lookup( rtip->rti_dbip, argv[2], LOOKUP_NOISY)) == RT_DIR_NULL )  {
	Tcl_AppendResult(interp, argv[2], ": not found\n", NULL);
	return TCL_ERROR;
    }

    /* Find all region names which match /comb/ pattern */
    for ( BU_LIST_FOR( regp, region, &rtip->HeadRegion ) )  {
/*	if ( dp->d_flags & RT_DIR_REGION )  {	*/
	    /* name will occur at end of region string w/leading slash */
/*	} else {	*/
	    /* name will occur anywhere, bracketed by slashes */
/*	}	*/

	/* XXX quick hack */
	if ( strstr( regp->reg_name, argv[2] ) == NULL )  continue;

	/* Modify the region's color */
	bu_log("sh_directchange_rgb() changing %s\n", regp->reg_name);
	VSET( regp->reg_mater.ma_color, r, g, b );

	/* Update the shader */
	mlib_free(regp);
	if ( mlib_setup( &mfHead, regp, rtip ) != 1 )  {
	    Tcl_AppendResult(interp, regp->reg_name, ": mlib_setup() failure\n", NULL);
	}
    }

    return TCL_OK;
}
Exemplo n.º 8
0
Arquivo: xxx.c Projeto: kanzure/brlcad
/**
 * Given a pointer to a GED database record, and a transformation
 * matrix, determine if this is a valid XXX, and if so, precompute
 * various terms of the formula.
 *
 * Returns -
 * 0 XXX is OK
 * !0 Error in description
 *
 * Implicit return -
 * A struct xxx_specific is created, and its address is stored in
 * stp->st_specific for use by xxx_shot().
 */
int
rt_xxx_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_xxx_internal *xxx_ip;

    if (stp) RT_CK_SOLTAB(stp);
    RT_CK_DB_INTERNAL(ip);
    if (rtip) RT_CK_RTI(rtip);

    xxx_ip = (struct rt_xxx_internal *)ip->idb_ptr;
    RT_XXX_CK_MAGIC(xxx_ip);

    return 0;
}
/**
 * prep and build bounding volumes... unfortunately, generating the
 * bounding sphere is too 'loose' (I think) and O(n^2).
 */
int
rt_metaball_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_metaball_internal *mb, *nmb;
    struct wdb_metaballpt *mbpt, *nmbpt;
    fastf_t minfstr = +INFINITY;

    if (rtip) RT_CK_RTI(rtip);

    mb = (struct rt_metaball_internal *)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);

    /* generate a copy of the metaball */
    BU_ALLOC(nmb, struct rt_metaball_internal);
    nmb->magic = RT_METABALL_INTERNAL_MAGIC;
    BU_LIST_INIT(&nmb->metaball_ctrl_head);
    nmb->threshold = mb->threshold;
    nmb->method = mb->method;

    /* and copy the list of control points */
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) {
	BU_ALLOC(nmbpt, struct wdb_metaballpt);
	nmbpt->fldstr = mbpt->fldstr;
	if (mbpt->fldstr < minfstr)
	    minfstr = mbpt->fldstr;
	nmbpt->sweat = mbpt->sweat;
	VMOVE(nmbpt->coord, mbpt->coord);
	BU_LIST_INSERT(&nmb->metaball_ctrl_head, &nmbpt->l);
    }

    /* find the bounding sphere */
    stp->st_aradius = rt_metaball_get_bounding_sphere(&stp->st_center, mb->threshold, mb);
    stp->st_bradius = stp->st_aradius * 1.01;

    /* XXX magic numbers, increase if scalloping is observed. :(*/
    nmb->initstep = minfstr / 2.0;
    if (nmb->initstep < (stp->st_aradius / 200.0))
	nmb->initstep = (stp->st_aradius / 200.0);
    else if (nmb->initstep > (stp->st_aradius / 10.0))
	nmb->initstep = (stp->st_aradius / 10.0);
    nmb->finalstep = /*stp->st_aradius * */minfstr / 1e5;

    /* generate a bounding box around the sphere...
     * XXX this can be optimized greatly to reduce the BSP presence... */
    if (rt_metaball_bbox(ip, &(stp->st_min), &(stp->st_max), &rtip->rti_tol)) return 1;
    stp->st_specific = (void *)nmb;
    return 0;
}
Exemplo n.º 10
0
/* ARGSUSED */
HIDDEN int rt_gettree_region_start(struct db_tree_state *tsp, struct db_full_path *pathp, const struct rt_comb_internal *combp, genptr_t client_data)
    /*const*/
    /*const*/


{
    RT_CK_RTI(tsp->ts_rtip);
    RT_CK_RESOURCE(tsp->ts_resp);

    /* Ignore "air" regions unless wanted */
    if ( tsp->ts_rtip->useair == 0 &&  tsp->ts_aircode != 0 )  {
	tsp->ts_rtip->rti_air_discards++;
	return(-1);	/* drop this region */
    }
    return(0);
}
Exemplo n.º 11
0
/**
 * This routine must be prepared to run in parallel.
 */
HIDDEN int
_rt_gettree_region_start(struct db_tree_state *tsp, const struct db_full_path *pathp, const struct rt_comb_internal *combp, void *UNUSED(client_data))
{
  if (tsp) {
    RT_CK_RTI(tsp->ts_rtip);
    RT_CK_RESOURCE(tsp->ts_resp);
    if (pathp) RT_CK_FULL_PATH(pathp);
    if (combp) RT_CHECK_COMB(combp);

    /* Ignore "air" regions unless wanted */
    if (tsp->ts_rtip->useair == 0 &&  tsp->ts_aircode != 0) {
      tsp->ts_rtip->rti_air_discards++;
      return -1;	/* drop this region */
    }
  }
  return 0;
}
Exemplo n.º 12
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));
	}
    }
Exemplo n.º 13
0
/*
 *  Each word in the command buffer is the name of a treetop.
 */
void
ph_gettrees(struct pkg_conn *UNUSED(pc), char *buf)
{
    size_t n = 0;
    long max_argc = 0;
    char **argv = NULL;
    int	argc = 0;
    struct rt_i *rtip = APP.a_rt_i;

    RT_CK_RTI(rtip);

    if (debug)  fprintf(stderr, "ph_gettrees: %s\n", buf);

    /* Copy values from command line options into rtip */
    rtip->useair = use_air;
    if (rt_dist_tol > 0)  {
	rtip->rti_tol.dist = rt_dist_tol;
	rtip->rti_tol.dist_sq = rt_dist_tol * rt_dist_tol;
    }
    if (rt_perp_tol > 0)  {
	rtip->rti_tol.perp = rt_perp_tol;
	rtip->rti_tol.para = 1 - rt_perp_tol;
    }

    for (n = 0; n < strlen(buf); n++) {
	if (isspace((int)buf[n]))
	    max_argc++;
    }
    argv = (char **)bu_calloc(max_argc+1, sizeof(char *), "alloc argv");

    if ((argc = bu_argv_from_string(argv, max_argc, buf)) <= 0)  {
	/* No words in input */
	(void)free(buf);
	bu_free(argv, "free argv");
	return;
    }
    title_obj = bu_strdup(argv[0]);

    if (rtip->needprep == 0)  {
	/* First clean up after the end of the previous frame */
	if (debug)bu_log("Cleaning previous model\n");
	view_end(&APP);
	view_cleanup(rtip);
	rt_clean(rtip);
	if (rdebug&RDEBUG_RTMEM_END)
	    bu_prmem("After rt_clean");
    }

    /* Load the desired portion of the model */
    if (rt_gettrees(rtip, argc, (const char **)argv, npsw) < 0)
	fprintf(stderr, "rt_gettrees(%s) FAILED\n", argv[0]);
    bu_free(argv, "free argv");

    /* In case it changed from startup time via an OPT command */
    if (npsw > 1)  {
	RTG.rtg_parallel = 1;
    } else
	RTG.rtg_parallel = 0;

    seen_gettrees = 1;
    (void)free(buf);

    prepare();

    /* Acknowledge that we are ready */
    if (pkg_send(MSG_GETTREES_REPLY,
		   title_obj, strlen(title_obj)+1, pcsrv) < 0)
	fprintf(stderr, "MSG_START error\n");
}
Exemplo n.º 14
0
/**
 * Given a pointer to a GED database record, and a transformation
 * matrix, determine if this is a valid REVOLVE, and if so, precompute
 * various terms of the formula.
 *
 * Returns -
 * 0 REVOLVE is OK
 * !0 Error in description
 *
 * Implicit return -
 * A struct revolve_specific is created, and its address is stored
 * in stp->st_specific for use by revolve_shot().
 */
int
rt_revolve_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_revolve_internal *rip;
    struct revolve_specific *rev;

    vect_t xEnd, yEnd;

    int *endcount = NULL;
    size_t nseg, i, j, k;

    if (rtip) RT_CK_RTI(rtip);

    RT_CK_DB_INTERNAL(ip);
    rip = (struct rt_revolve_internal *)ip->idb_ptr;
    RT_REVOLVE_CK_MAGIC(rip);

    /* if there's no sketch, there's nothing to do */
    if (!rip->skt || rip->skt->vert_count < 1) {
	return -1;
    }

    stp->st_id = ID_REVOLVE;
    stp->st_meth = &OBJ[ID_REVOLVE];

    BU_GET(rev, struct revolve_specific);
    stp->st_specific = (void *)rev;

    VMOVE(rev->v3d, rip->v3d);
    VMOVE(rev->zUnit, rip->axis3d);
    VMOVE(rev->xUnit, rip->r);
    VCROSS(rev->yUnit, rev->zUnit, rev->xUnit);

    VUNITIZE(rev->xUnit);
    VUNITIZE(rev->yUnit);
    VUNITIZE(rev->zUnit);

    rev->ang = rip->ang;
    rev->sketch_name = bu_vls_addr(&rip->sketch_name);
    rev->skt = rip->skt;

    /* calculate end plane */
    VSCALE(xEnd, rev->xUnit, cos(rev->ang));
    VSCALE(yEnd, rev->yUnit, sin(rev->ang));
    VADD2(rev->rEnd, xEnd, yEnd);
    VUNITIZE(rev->rEnd);

    /* check the sketch - degree & closed/open */

    /* count the number of times an endpoint is used:
     * if even, the point is ok
     * if odd, the point is at the end of a path
     */
    endcount = (int *)bu_calloc(rev->skt->vert_count, sizeof(int), "endcount");
    nseg = rev->skt->curve.count;

    for (i=0; i<nseg; i++) {
	uint32_t *lng;
	struct line_seg *lsg;
	struct carc_seg *csg;
	struct nurb_seg *nsg;
	struct bezier_seg *bsg;

	lng = (uint32_t *)rev->skt->curve.segment[i];

	switch (*lng) {
	    case CURVE_LSEG_MAGIC:
		lsg = (struct line_seg *)lng;
		endcount[lsg->start]++;
		endcount[lsg->end]++;
		break;
	    case CURVE_CARC_MAGIC:
		csg = (struct carc_seg *)lng;
		if (csg->radius <= 0.0) break;
		endcount[csg->start]++;
		endcount[csg->end]++;
		break;
	    case CURVE_BEZIER_MAGIC:
		bsg = (struct bezier_seg *)lng;
		endcount[bsg->ctl_points[0]]++;
		endcount[bsg->ctl_points[bsg->degree]]++;
		break;
	    case CURVE_NURB_MAGIC:
		nsg = (struct nurb_seg *)lng;
		endcount[nsg->ctl_points[0]]++;
		endcount[nsg->ctl_points[nsg->c_size-1]]++;
		break;
	    default:
		bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
		break;
	}
    }

    /* convert endcounts to store which endpoints are odd */
    for (i=0, j=0; i<rip->skt->vert_count; i++) {
	if (endcount[i] % 2 != 0) {
	    /* add 'i' to list, insertion sort by vert[i][Y] */
	    for (k=j; k>0; k--) {
		if ((ZERO(rip->skt->verts[i][Y] - rip->skt->verts[endcount[k-1]][Y])
		     && rip->skt->verts[i][X] > rip->skt->verts[endcount[k-1]][X])
		    || (!ZERO(rip->skt->verts[i][Y] - rip->skt->verts[endcount[k-1]][Y])
			&& rip->skt->verts[i][Y] < rip->skt->verts[endcount[k-1]][Y])) {
		    endcount[k] = endcount[k-1];
		} else {
		    break;
		}
	    }
	    endcount[k] = i;
	    j++;
	}
    }
    while (j < rev->skt->vert_count)
	endcount[j++] = -1;

    rev->ends = endcount;

    /* bounding volume */
    rt_sketch_bounds(rev->skt, rev->bounds);
    if (endcount[0] != -1 && rev->bounds[0] > 0) rev->bounds[0] = 0;
    VJOIN1(stp->st_center, rev->v3d, 0.5*(rev->bounds[2]+rev->bounds[3]), rev->zUnit);
    stp->st_aradius = sqrt(0.25*(rev->bounds[3]-rev->bounds[2])*(rev->bounds[3]-rev->bounds[2]) + FMAX(rev->bounds[0]*rev->bounds[0], rev->bounds[1]*rev->bounds[1]));
    stp->st_bradius = stp->st_aradius;

    /* cheat, make bounding RPP by enclosing bounding sphere (copied from g_ehy.c) */
    stp->st_min[X] = stp->st_center[X] - stp->st_bradius;
    stp->st_max[X] = stp->st_center[X] + stp->st_bradius;
    stp->st_min[Y] = stp->st_center[Y] - stp->st_bradius;
    stp->st_max[Y] = stp->st_center[Y] + stp->st_bradius;
    stp->st_min[Z] = stp->st_center[Z] - stp->st_bradius;
    stp->st_max[Z] = stp->st_center[Z] + stp->st_bradius;

    return 0;			/* OK */
}
Exemplo n.º 15
0
/*
 *			S T K _ S E T U P
 *
 *  Returns 0 on failure, 1 on success.
 */
HIDDEN int
sh_stk_setup(register struct region *rp, struct bu_vls *matparm, char **dpp, struct mfuncs *mf_p, struct rt_i *rtip, struct mfuncs **headp)

    /* parameter string */
    /* pointer to user data pointer */


{
    register struct stk_specific *sp;
    char	*cp, *start;
    int	i;
    int	inputs = 0;
    struct mfuncs *mfp;

    BU_CK_VLS( matparm );
    RT_CK_RTI(rtip);

    BU_GETSTRUCT( sp, stk_specific );
    *dpp = (char *)sp;

    /*bu_struct_parse( matparm, sh_stk_parse, (char *)sp );*/

    if (rdebug&RDEBUG_MATERIAL || rdebug&RDEBUG_SHADE)
	bu_log( "sh_stk_setup called with \"%s\"\n", bu_vls_addr(matparm) );

    i = 0;
    start = cp = bu_vls_addr(matparm);
    while ( *cp != '\0' ) {
	if (*cp == ';' ) {
	    *cp = '\0';
	    if (i >= 16 ) {
		bu_log( "sh_stk_setup: max levels exceeded\n" );
		return( 0 );
	    }
	    /* add one */
	    if (sh_stk_dosetup(start, rp, &sp->udata[i],
			       (char **)&sp->mfuncs[i], rtip, headp) == 0 )  {
		inputs |= sp->mfuncs[i]->mf_inputs;
		i++;
	    } else {
		/* XXX else clear entry? */
		bu_log("Problem in stack shader setup\n");
	    }
	    start = ++cp;
	} else {
	    cp++;
	}
    }
    if (start != cp ) {
	if (i >= 16 ) {
	    bu_log( "sh_stk_setup: max levels exceeded\n" );
	    return( 0 );
	}
	/* add one */
	if (sh_stk_dosetup(start, rp, &sp->udata[i], (char **)&sp->mfuncs[i],
			   rtip, headp ) == 0 )  {
	    inputs |= sp->mfuncs[i]->mf_inputs;
	    i++;
	} else {
	    /* XXX else clear entry? */
	}
    }

    /* Request only those input bits needed by subordinate shaders */
    BU_GETSTRUCT( mfp, mfuncs );
    memcpy((char *)mfp, (char *)rp->reg_mfuncs, sizeof(*mfp));
    mfp->mf_inputs = inputs;
    rp->reg_mfuncs = (genptr_t)mfp;
    return( 1 );
}
Exemplo n.º 16
0
/*
 *			S T K _ D O S E T U P
 */
static int sh_stk_dosetup(char *cp, struct region *rp, char **dpp, char **mpp, struct rt_i *rtip, struct mfuncs **headp)


    /* udata pointer address */
    /* mfuncs pointer address */


{
    register struct mfuncs *mfp;
#ifdef HAVE_DLOPEN
    register struct mfuncs *mfp_new;
#endif
    struct bu_vls	arg;
    char	matname[32];
    int	ret;
    int	i;

    RT_CK_RTI(rtip);

    if (rdebug&RDEBUG_MATERIAL)
	bu_log( "...starting \"%s\"\n", cp );

    /* skip leading white space */
    while ( *cp == ' ' || *cp == '\t' )
	cp++;

    for ( i = 0; i < 31 && *cp != '\0'; i++, cp++ ) {
	if (*cp == ' ' || *cp == '\t' ) {
	    matname[i++] = '\0';
	    break;
	} else
	    matname[i] = *cp;
    }
    matname[i] = '\0';	/* ensure null termination */

#ifdef HAVE_DLOPEN
 retry:
#endif
    for ( mfp = *headp; mfp != MF_NULL; mfp = mfp->mf_forw )  {
	if (matname[0] != mfp->mf_name[0]  ||
	    strcmp( matname, mfp->mf_name ) != 0 )
	    continue;
	goto found;
    }
#ifdef HAVE_DLOPEN
    /* If we get here, then the shader wasn't found in the list of
     * compiled-in (or previously loaded) shaders.  See if we can
     * dynamically load it.
     */

    bu_log("Shader \"%s\"... ", matname);

    if ((mfp_new = load_dynamic_shader(matname, strlen(matname)))) {
	mlib_add_shader(headp, mfp_new);
	goto retry;
    }
#else
    bu_log("****** dynamic shader loading not available ******\n");
#endif


    bu_log("stack_setup(%s):  material not known\n",
	   matname );
    ret = -1;
    goto out;

 found:
    *mpp = (char *)mfp;
    *dpp = (char *)0;
    bu_vls_init( &arg );
    if (*cp != '\0' )
	bu_vls_strcat( &arg, ++cp );
    if (rdebug&RDEBUG_MATERIAL)
	bu_log("calling %s with %s\n", mfp->mf_name, bu_vls_addr(&arg));
    if (mfp->mf_setup( rp, &arg, dpp, mfp, rtip, headp ) < 0 )  {
	/* Setup has failed */
	bu_vls_free( &arg );
	ret = -1;		/* BAD */
	goto out;
    }
    bu_vls_free( &arg );
    ret = 0;			/* OK */
 out:
    if (rdebug&RDEBUG_MATERIAL)
	bu_log( "...finished \"%s\", ret=%d\n", matname, ret );
    return ret;
}
HIDDEN int
sh_stk_dosetup(char *cp, struct region *rp, void **dpp, struct mfuncs **mpp, struct rt_i *rtip)


/* udata pointer address */
/* mfuncs pointer address */


{
    register struct mfuncs *mfp;
    register struct mfuncs *mfp_new;
    struct bu_vls arg = BU_VLS_INIT_ZERO;
    char matname[32];
    int ret;
    int i;
    struct mfuncs *shaders = MF_NULL;

    RT_CK_RTI(rtip);

    if (rdebug&RDEBUG_MATERIAL)
	bu_log("...starting \"%s\"\n", cp);

    /* skip leading white space */
    while (*cp == ' ' || *cp == '\t')
	cp++;

    for (i = 0; i < 31 && *cp != '\0'; i++, cp++) {
	if (*cp == ' ' || *cp == '\t') {
	    matname[i++] = '\0';
	    break;
	} else
	    matname[i] = *cp;
    }
    matname[i] = '\0';	/* ensure null termination */

retry:
    /* get list of available shaders */
    if (!shaders) {
	optical_shader_init(&shaders);
    }

    for (mfp = shaders; mfp && mfp->mf_name != NULL; mfp = mfp->mf_forw) {
	if (matname[0] != mfp->mf_name[0]  ||
	    !BU_STR_EQUAL(matname, mfp->mf_name))
	    continue;
	goto found;
    }

    /* If we get here, then the shader wasn't found in the list of
     * compiled-in (or previously loaded) shaders.  See if we can
     * dynamically load it.
     */

    bu_log("Shader \"%s\"... ", matname);

    if ((mfp_new = load_dynamic_shader(matname))) {
	mlib_add_shader(&shaders, mfp_new);
	goto retry;
    }

    bu_log("stack_setup(%s):  material not known\n",
	   matname);
    ret = -1;
    goto out;

found:
    *mpp = mfp;
    *dpp = (char *)0;
    if (*cp != '\0')
	bu_vls_strcat(&arg, ++cp);
    if (rdebug&RDEBUG_MATERIAL)
	bu_log("calling %s with %s\n", mfp->mf_name, bu_vls_addr(&arg));
    if (!mfp || !mfp->mf_setup || mfp->mf_setup(rp, &arg, dpp, mfp, rtip) < 0) {
	/* Setup has failed */
	bu_vls_free(&arg);
	ret = -1;		/* BAD */
	goto out;
    }
    bu_vls_free(&arg);
    ret = 0;			/* OK */
out:
    if (rdebug&RDEBUG_MATERIAL)
	bu_log("...finished \"%s\", ret=%d\n", matname, ret);
    return ret;
}
Exemplo n.º 18
0
/**
 * R T _ F I N D _ I D E N T I C A L _ S O L I D
 *
 * See if solid "dp" as transformed by "mat" already exists in the
 * soltab list.  If it does, return the matching stp, otherwise,
 * create a new soltab structure, enrole it in the list, and return a
 * pointer to that.
 *
 * "mat" will be a null pointer when an identity matrix is signified.
 * This greatly speeds the comparison process.
 *
 * The two cases can be distinguished by the fact that stp->st_id will
 * be 0 for a new soltab structure, and non-zero for an existing one.
 *
 * This routine will run in parallel.
 *
 * In order to avoid a race between searching the soltab list and
 * adding new solids to it, the new solid to be added *must* be
 * enrolled in the list before exiting the critical section.
 *
 * To limit the size of the list to be searched, there are many lists.
 * The selection of which list is determined by the hash value
 * computed from the solid's name.  This is the same optimization used
 * in searching the directory lists.
 *
 * This subroutine is the critical bottleneck in parallel tree walking.
 *
 * It is safe, and much faster, to use several different critical
 * sections when searching different lists.
 *
 * There are only 4 dedicated semaphores defined, TREE0 through TREE3.
 * This unfortunately limits the code to having only 4 CPUs doing list
 * searching at any one time.  Hopefully, this is enough parallelism
 * to keep the rest of the CPUs doing I/O and actual solid prepping.
 *
 * Since the algorithm has been reduced from an O((nsolid/128)**2)
 * search on the entire rti_solidheads[hash] list to an O(ninstance)
 * search on the dp->d_use_head list for this one solid, the critical
 * section should be relatively short-lived.  Having the 3-way split
 * should provide ample opportunity for parallelism through here,
 * while still ensuring that the necessary variables are protected.
 *
 * There are two critical variables which *both* need to be protected:
 * the specific rti_solidhead[hash] list head, and the specific
 * dp->d_use_hd list head.  Fortunately, since the selection of
 * critical section is based upon db_dirhash(dp->d_namep), any other
 * processor that wants to search this same 'dp' will get the same
 * hash as the current thread, and will thus wait for the appropriate
 * semaphore to be released.  Similarly, any other thread that wants
 * to search the same rti_solidhead[hash] list as the current thread
 * will be using the same hash, and will thus wait for the proper
 * semaphore.
 */
HIDDEN struct soltab *rt_find_identical_solid(register const matp_t mat, register struct directory *dp, struct rt_i *rtip)
{
    register struct soltab	*stp = RT_SOLTAB_NULL;
    int			hash;

    RT_CK_DIR(dp);
    RT_CK_RTI(rtip);

    hash = db_dirhash( dp->d_namep );

    /* Enter the appropriate dual critical-section */
    ACQUIRE_SEMAPHORE_TREE(hash);

    /*
     * If solid has not been referenced yet, the search can be
     * skipped.  If solid is being referenced a _lot_, it certainly
     * isn't all going to be in the same place, so don't bother
     * searching.  Consider the case of a million instances of the
     * same tree submodel solid.
     */
    if ( dp->d_uses > 0 && dp->d_uses < 100 &&
	 rtip->rti_dont_instance == 0
	)  {
	struct bu_list	*mid;

	/* Search dp->d_use_hd list for other instances */
	for ( BU_LIST_FOR( mid, bu_list, &dp->d_use_hd ) )  {

	    stp = BU_LIST_MAIN_PTR( soltab, mid, l2 );
	    RT_CK_SOLTAB(stp);

	    if ( stp->st_matp == (matp_t)0 )  {
		if ( mat == (matp_t)0 )  {
		    /* Both have identity matrix */
		    goto more_checks;
		}
		continue;
	    }
	    if ( mat == (matp_t)0 )  continue;	/* doesn't match */

	    if ( !bn_mat_is_equal(mat, stp->st_matp, &rtip->rti_tol))
		continue;

	more_checks:
	    /* Don't instance this solid from some other model
	     * instance.  As this is nearly always equal, check it
	     * last
	     */
	    if ( stp->st_rtip != rtip )  continue;

	    /*
	     * stp now points to re-referenced solid.  stp->st_id is
	     * non-zero, indicating pre-existing solid.
	     */
	    RT_CK_SOLTAB(stp);		/* sanity */

	    /* Only increment use counter for non-dead solids. */
	    if ( !(stp->st_aradius <= -1) )
		stp->st_uses++;
	    /* dp->d_uses is NOT incremented, because number of
	     * soltab's using it has not gone up.
	     */
	    if ( RT_G_DEBUG & DEBUG_SOLIDS )  {
		bu_log( mat ?
			"rt_find_identical_solid:  %s re-referenced %d\n" :
			"rt_find_identical_solid:  %s re-referenced %d (identity mat)\n",
			dp->d_namep, stp->st_uses );
	    }

	    /* Leave the appropriate dual critical-section */
	    RELEASE_SEMAPHORE_TREE(hash);
	    return stp;
	}
    }

    /*
     * Create and link a new solid into the list.
     *
     * Ensure the search keys "dp", "st_mat" and "st_rtip" are stored
     * now, while still inside the critical section, because they are
     * searched on, above.
     */
    BU_GETSTRUCT(stp, soltab);
    stp->l.magic = RT_SOLTAB_MAGIC;
    stp->l2.magic = RT_SOLTAB2_MAGIC;
    stp->st_rtip = rtip;
    stp->st_dp = dp;
    dp->d_uses++;
    stp->st_uses = 1;
    /* stp->st_id is intentionally left zero here, as a flag */

    if ( mat )  {
	stp->st_matp = (matp_t)bu_malloc( sizeof(mat_t), "st_matp" );
	MAT_COPY( stp->st_matp, mat );
    } else {
	stp->st_matp = (matp_t)0;
    }

    /* Add to the appropriate soltab list head */
    /* PARALLEL NOTE:  Uses critical section on rt_solidheads element */
    BU_LIST_INSERT( &(rtip->rti_solidheads[hash]), &(stp->l) );

    /* Also add to the directory structure list head */
    /* PARALLEL NOTE:  Uses critical section on this 'dp' */
    BU_LIST_INSERT( &dp->d_use_hd, &(stp->l2) );

    /*
     * Leave the 4-way critical-section protecting dp and [hash]
     */
    RELEASE_SEMAPHORE_TREE(hash);

    /* Enter an exclusive critical section to protect nsolids.
     * nsolids++ needs to be locked to a SINGLE thread
     */
    bu_semaphore_acquire(RT_SEM_STATS);
    stp->st_bit = rtip->nsolids++;
    bu_semaphore_release(RT_SEM_STATS);

    /*
     * Fill in the last little bit of the structure in full parallel
     * mode, outside of any critical section.
     */

    /* Init tables of regions using this solid.  Usually small. */
    bu_ptbl_init( &stp->st_regions, 7, "st_regions ptbl" );

    return stp;
}
Exemplo n.º 19
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);
}
Exemplo n.º 20
0
/**
 * R E C _ P R E P
 *
 * Given a pointer to a GED database record, and a transformation matrix,
 * determine if this is a valid REC,
 * and if so, precompute various terms of the formulas.
 *
 * Returns -
 * 0 REC is OK
 * !0 Error in description
 *
 * Implicit return - A struct rec_specific is created, and its
 * address is stored in stp->st_specific for use by rt_rec_shot().  If
 * the TGC is really an REC, stp->st_id is modified to ID_REC.
 */
int
rt_rec_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_tgc_internal *tip;
    struct rec_specific *rec;
    double magsq_h, magsq_a, magsq_b;
    double mag_h, mag_a, mag_b;
    mat_t R;
    mat_t Rinv;
    mat_t S;
    vect_t invsq;	/* [ 1/(|A|**2), 1/(|B|**2), 1/(|Hv|**2) ] */
    vect_t work;
    fastf_t f;

    if (!stp || !ip)
	return -1;
    RT_CK_SOLTAB(stp);
    RT_CK_DB_INTERNAL(ip);
    if (rtip) RT_CK_RTI(rtip);

    tip = (struct rt_tgc_internal *)ip->idb_ptr;
    RT_TGC_CK_MAGIC(tip);

    /* Validate that |H| > 0, compute |A| |B| |C| |D| */
    mag_h = sqrt(magsq_h = MAGSQ(tip->h));
    mag_a = sqrt(magsq_a = MAGSQ(tip->a));
    mag_b = sqrt(magsq_b = MAGSQ(tip->b));

    /* Check for |H| > 0, |A| > 0, |B| > 0 */
    if (NEAR_ZERO(mag_h, RT_LEN_TOL) || NEAR_ZERO(mag_a, RT_LEN_TOL)
	|| NEAR_ZERO(mag_b, RT_LEN_TOL)) {
	return 1;		/* BAD, too small */
    }

    /* Make sure that A == C, B == D */
    VSUB2(work, tip->a, tip->c);
    f = MAGNITUDE(work);
    if (! NEAR_ZERO(f, RT_LEN_TOL)) {
	return 1;		/* BAD, !cylinder */
    }
    VSUB2(work, tip->b, tip->d);
    f = MAGNITUDE(work);
    if (! NEAR_ZERO(f, RT_LEN_TOL)) {
	return 1;		/* BAD, !cylinder */
    }

    /* Check for A.B == 0, H.A == 0 and H.B == 0 */
    f = VDOT(tip->a, tip->b) / (mag_a * mag_b);
    if (! NEAR_ZERO(f, RT_DOT_TOL)) {
	return 1;		/* BAD */
    }
    f = VDOT(tip->h, tip->a) / (mag_h * mag_a);
    if (! NEAR_ZERO(f, RT_DOT_TOL)) {
	return 1;		/* BAD */
    }
    f = VDOT(tip->h, tip->b) / (mag_h * mag_b);
    if (! NEAR_ZERO(f, RT_DOT_TOL)) {
	return 1;		/* BAD */
    }

    /*
     * This TGC is really an REC
     */
    stp->st_id = ID_REC;		/* "fix" soltab ID */
    stp->st_meth = &rt_functab[ID_REC];

    BU_GET(rec, struct rec_specific);
    stp->st_specific = (genptr_t)rec;

    VMOVE(rec->rec_Hunit, tip->h);
    VUNITIZE(rec->rec_Hunit);

    VMOVE(rec->rec_V, tip->v);
    VMOVE(rec->rec_A, tip->a);
    VMOVE(rec->rec_B, tip->b);
    rec->rec_iAsq = 1.0/magsq_a;
    rec->rec_iBsq = 1.0/magsq_b;

    VSET(invsq, 1.0/magsq_a, 1.0/magsq_b, 1.0/magsq_h);

    /* Compute R and Rinv matrices */
    MAT_IDN(R);
    f = 1.0/mag_a;
    VSCALE(&R[0], tip->a, f);
    f = 1.0/mag_b;
    VSCALE(&R[4], tip->b, f);
    f = 1.0/mag_h;
    VSCALE(&R[8], tip->h, f);
    bn_mat_trn(Rinv, R);			/* inv of rot mat is trn */

    /* Compute S */
    MAT_IDN(S);
    S[ 0] = sqrt(invsq[0]);
    S[ 5] = sqrt(invsq[1]);
    S[10] = sqrt(invsq[2]);

    /* Compute SoR and invRoS */
    bn_mat_mul(rec->rec_SoR, S, R);
    bn_mat_mul(rec->rec_invRoS, Rinv, S);

    /* Compute bounding sphere and RPP */
    {
	fastf_t dx, dy, dz;	/* For bounding sphere */

	if (stp->st_meth->ft_bbox(ip, &(stp->st_min), &(stp->st_max), &(rtip->rti_tol))) return 1;

	VSET(stp->st_center,
	     (stp->st_max[X] + stp->st_min[X])/2,
	     (stp->st_max[Y] + stp->st_min[Y])/2,
	     (stp->st_max[Z] + stp->st_min[Z])/2);

	dx = (stp->st_max[X] - stp->st_min[X])/2;
	f = dx;
	dy = (stp->st_max[Y] - stp->st_min[Y])/2;
	if (dy > f) f = dy;
	dz = (stp->st_max[Z] - stp->st_min[Z])/2;
	if (dz > f) f = dz;
	stp->st_aradius = f;
	stp->st_bradius = sqrt(dx*dx + dy*dy + dz*dz);
    }
    return 0;			/* OK */
}
Exemplo n.º 21
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);
}