Beispiel #1
0
/*
 * Sort of a surface spot transparency shader.  Picks transparency
 * based upon noise value of surface spot.
 */
int
tsplat_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct scloud_specific *scloud_sp =
        (struct scloud_specific *)dp;
    point_t in_pt;	/* point where ray enters scloud solid */
    double val;

    RT_CHECK_PT(pp);
    RT_AP_CHECK(ap);
    RT_CK_REGION(pp->pt_regionp);


    /* just shade the surface with a transparency */
    MAT4X3PNT(in_pt, scloud_sp->mtos, swp->sw_hit.hit_point);
    val = bn_noise_fbm(in_pt, scloud_sp->h_val,
                       scloud_sp->lacunarity, scloud_sp->octaves);
    CLAMP(val, 0.0, 1.0);
    swp->sw_transmit = 1.0 - val;


    if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
        (void)rr_render(ap, pp, swp);

    return 1;
}
HIDDEN void
_rt_tree_region_assign(union tree *tp, const struct region *regionp)
{
    RT_CK_TREE(tp);
    RT_CK_REGION(regionp);
    switch (tp->tr_op) {
	case OP_NOP:
	    return;

	case OP_SOLID:
	    tp->tr_a.tu_regionp = (struct region *)regionp;
	    return;

	case OP_NOT:
	case OP_GUARD:
	case OP_XNOP:
	    tp->tr_b.tb_regionp = (struct region *)regionp;
	    _rt_tree_region_assign(tp->tr_b.tb_left, regionp);
	    return;

	case OP_UNION:
	case OP_INTERSECT:
	case OP_SUBTRACT:
	case OP_XOR:
	    tp->tr_b.tb_regionp = (struct region *)regionp;
	    _rt_tree_region_assign(tp->tr_b.tb_left, regionp);
	    _rt_tree_region_assign(tp->tr_b.tb_right, regionp);
	    return;

	default:
	    bu_bomb("_rt_tree_region_assign: bad op\n");
    }
}
/*
 * This routine is called (at prep time)
 * once for each region which uses this shader.
 * Any shader-specific initialization should be done here.
 *
 * Returns:
 * 1 success
 * 0 success, but delete region
 * -1 failure
 */
HIDDEN int
toon_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)


/* pointer to reg_udata in *rp */

/* New since 4.4 release */
{
    register struct toon_specific *toon_sp;

    /* check the arguments */
    RT_CHECK_RTI(rtip);
    BU_CK_VLS(matparm);
    RT_CK_REGION(rp);

    if (rdebug&RDEBUG_SHADE)
	bu_log("toon_setup(%s)\n", rp->reg_name);

    /* Get memory for the shader parameters and shader-specific data */
    BU_GET(toon_sp, struct toon_specific);
    *dpp = toon_sp;

    /* initialize the default values for the shader */
    memcpy(toon_sp, &toon_defaults, sizeof(struct toon_specific));

    /* parse the user's arguments for this use of the shader. */
    if (bu_struct_parse(matparm, toon_parse_tab, (char *)toon_sp, NULL) < 0)
	return -1;

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print(" Parameters:", toon_print_tab, (char *)toon_sp);
    }

    return 1;
}
Beispiel #4
0
void
rt_pr_region(register const struct region *rp)
{
    struct bu_vls v = BU_VLS_INIT_ZERO;

    RT_CK_REGION(rp);

    bu_log("REGION %s (bit %d)\n", rp->reg_name, rp->reg_bit);
    bu_log("instnum=%ld, id=%d, air=%d, gift_material=%d, los=%d\n",
	   rp->reg_instnum,
	   rp->reg_regionid, rp->reg_aircode,
	   rp->reg_gmater, rp->reg_los);
    if (rp->reg_is_fastgen != REGION_NON_FASTGEN) {
	bu_log("reg_is_fastgen = %s mode\n",
	       rp->reg_is_fastgen == REGION_FASTGEN_PLATE ?
	       "plate" : "volume");
    }
    if (rp->reg_mater.ma_color_valid)
	bu_log("Color %d %d %d\n",
	       (int)rp->reg_mater.ma_color[0]*255,
	       (int)rp->reg_mater.ma_color[1]*255,
	       (int)rp->reg_mater.ma_color[2]*255);
    if (rp->reg_mater.ma_temperature > 0)
	bu_log("Temperature %g degrees K\n", INTCLAMP(rp->reg_mater.ma_temperature));
    if (rp->reg_mater.ma_shader && rp->reg_mater.ma_shader[0] != '\0')
	bu_log("Shader '%s'\n", rp->reg_mater.ma_shader);

    rt_pr_tree_vls(&v, rp->reg_treetop);
    bu_log("%s %ld %s\n", rp->reg_name,
	   rp->reg_instnum, bu_vls_addr(&v));
    bu_vls_free(&v);
}
Beispiel #5
0
void
rt_pr_pt_vls(struct bu_vls *v, const struct rt_i *rtip, register const struct partition *pp)
{
    register const struct soltab *stp;
    register struct seg **segpp;

    RT_CHECK_RTI(rtip);
    RT_CHECK_PT(pp);
    BU_CK_VLS(v);

    bu_log_indent_vls(v);
    bu_vls_printf(v, "%p: PT ", (void *)pp);

    stp = pp->pt_inseg->seg_stp;
    bu_vls_printf(v, "%s (%s#%ld) ",
		  stp->st_dp->d_namep,
		  OBJ[stp->st_id].ft_name+3,
		  stp->st_bit);

    stp = pp->pt_outseg->seg_stp;
    bu_vls_printf(v, "%s (%s#%ld) ",
		  stp->st_dp->d_namep,
		  OBJ[stp->st_id].ft_name+3,
		  stp->st_bit);

    bu_vls_printf(v, "(%g, %g)",
		  pp->pt_inhit->hit_dist, pp->pt_outhit->hit_dist);
    if (pp->pt_inflip) bu_vls_strcat(v, " Iflip");
    if (pp->pt_outflip) bu_vls_strcat(v, " Oflip");
    bu_vls_strcat(v, "\n");

    rt_pr_hit_vls(v, "  In", pp->pt_inhit);
    rt_pr_hit_vls(v, " Out", pp->pt_outhit);
    bu_log_indent_vls(v);
    bu_vls_strcat(v, "  Primitives: ");
    for (BU_PTBL_FOR(segpp, (struct seg **), &pp->pt_seglist)) {
	stp = (*segpp)->seg_stp;
	RT_CK_SOLTAB(stp);
	bu_vls_strcat(v, stp->st_dp->d_namep);
	bu_vls_strcat(v, ", ");
    }
    bu_vls_strcat(v, "\n");

    bu_log_indent_vls(v);
    bu_vls_strcat(v, "  Untrimmed Segments spanning this interval:\n");
    bu_log_indent_delta(4);
    for (BU_PTBL_FOR(segpp, (struct seg **), &pp->pt_seglist)) {
	RT_CK_SEG(*segpp);
	rt_pr_seg_vls(v, *segpp);
    }
    bu_log_indent_delta(-4);

    if (pp->pt_regionp) {
	RT_CK_REGION(pp->pt_regionp);
	bu_log_indent_vls(v);
	bu_vls_printf(v, "  Region: %s\n", pp->pt_regionp->reg_name);
    }
}
HIDDEN int osl_setup(register struct region *rp, struct bu_vls *matparm,
		     void **dpp, const struct mfuncs *mfp,
		     struct rt_i *rtip)
{
    register struct osl_specific *osl_sp;

    /* check the arguments */
    RT_CHECK_RTI(rtip);
    BU_CK_VLS(matparm);
    RT_CK_REGION(rp);

    if (rdebug&RDEBUG_SHADE)
	bu_log("osl_setup(%s)\n", rp->reg_name);

    /* Get memory for the shader parameters and shader-specific data */
    BU_GET(osl_sp, struct osl_specific);
    *dpp = (char *)osl_sp;

    /* -----------------------------------
     * Initialize the osl specific values
     * -----------------------------------
     */

    osl_sp->magic = OSL_MAGIC;

    /* Parse the user's arguments to fill osl specifics */
    ShaderGroupInfo group_info;
    if (osl_parse(matparm, group_info) < 0) {
	return -1;
    }

    /* -----------------------------------
     * Initialize osl render system
     * -----------------------------------
     */
    /* If OSL system was not initialized yet, do it */
    if (oslr == NULL) {
	oslr = new OSLRenderer();
    }
    /* Add this shader to OSL system */
    osl_sp->shader_ref = oslr->AddShader(group_info);

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print(" Parameters:", osl_print_tab, (char *)osl_sp);
    }

    return 1;
}
Beispiel #7
0
/*
 * This routine is called (at prep time) once for each region which uses this
 * shader.  The shader specific flat_specific structure is allocated and
 * default values are set.  Then any user-given values override.
 */
HIDDEN int
flat_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)
{

    register struct flat_specific *flat_sp;

    /* check the arguments */
    RT_CHECK_RTI(rtip);
    BU_CK_VLS(matparm);
    RT_CK_REGION(rp);

    if (rdebug&RDEBUG_SHADE)
	bu_log("flat_setup(%s)\n", rp->reg_name);

    /* Get memory for the shader parameters and shader-specific data */
    BU_GET(flat_sp, struct flat_specific);
    *dpp = flat_sp;

    /* color priority:
     *
     * priority goes first to the flat shader's color parameter
     * second priority is to the material color value
     * third priority is to the flat shader's default color (white)
     */

    /* initialize the default values for the shader */
    memcpy(flat_sp, &flat_defaults, sizeof(struct flat_specific));

    /* load the material color if it was set */
    if (rp->reg_mater.ma_color_valid) {
	VMOVE(flat_sp->color, rp->reg_mater.ma_color);
    }

    /* parse the user's arguments for this use of the shader. */
    if (bu_struct_parse(matparm, flat_parse_tab, (char *)flat_sp) < 0)
	return -1;

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print(" Parameters:", flat_parse_tab, (char *)flat_sp);
    }

    return 1;
}
Beispiel #8
0
/*
 *			E X T _ S E T U P
 *
 *  Returns 0 on failure, 1 on success.
 */
HIDDEN int
ext_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 */


{
    struct bu_mapped_file	*parameter_file;
    struct bu_vls		parameter_data;
    char			*filename;
    int			status;

    RT_CHECK_RTI(rtip);
    BU_CK_VLS( matparm );
    RT_CK_REGION(rp);

    filename = bu_vls_addr(matparm);
    parameter_file = bu_open_mapped_file( filename, (char *)NULL );
    if (!parameter_file) {
	bu_log("cannot open external shader file \"%s\"\n", filename);
	bu_bomb("ext_setup()\n");
    }

    bu_vls_init(&parameter_data);
    bu_vls_strncpy( &parameter_data, (char *)parameter_file->buf,
		    parameter_file->buflen );

    if (rdebug&RDEBUG_SHADE ) {
	bu_log("ext_setup(%s): {%s}\n",
	       filename, bu_vls_addr(&parameter_data));
    }

    bu_close_mapped_file( parameter_file );

    status = sh_stk_setup(rp, &parameter_data, dpp, mf_p, rtip, headp);

    bu_vls_free( &parameter_data );

    return status;
}
Beispiel #9
0
int
scloud_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct scloud_specific *scloud_sp =
        (struct scloud_specific *)dp;
    point_t in_pt;	/* point where ray enters scloud solid */
    point_t out_pt; /* point where ray leaves scloud solid */
    point_t pt;
    vect_t v_cloud;/* vector representing ray/solid intersection */
    double thickness; /* magnitude of v_cloud (distance through solid) */
    int steps;	   /* # of samples along ray/solid intersection */
    double step_delta;/* distance between sample points, texture space */
    int i;
    double val;
    double trans;
    point_t incident_light = VINIT_ZERO;
    double delta_dpmm;
    double density;
    struct shadework sub_sw;
    struct light_specific *lp;

    RT_CHECK_PT(pp);
    RT_AP_CHECK(ap);
    RT_CK_REGION(pp->pt_regionp);

    /* compute the ray/solid in and out points,
     * and transform them into "shader space" coordinates
     */
    VJOIN1(pt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir);
    MAT4X3PNT(in_pt, scloud_sp->mtos, pt);

    VJOIN1(pt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir);
    MAT4X3PNT(out_pt, scloud_sp->mtos, pt);


    /* get ray/solid intersection vector (in noise space)
     * and compute thickness of solid (in noise space) along ray path
     */
    VSUB2(v_cloud, out_pt, in_pt);
    thickness = MAGNITUDE(v_cloud);

    /* The noise field used by the bn_noise_turb and bn_noise_fbm routines
     * has a maximum frequency of about 1 cycle per integer step in
     * noise space.  Each octave increases this frequency by the
     * "lacunarity" factor.  To sample this space adequately we need
     *
     * 4 samples per integer step for the first octave,
     * lacunarity * 4 samples/step for the second octave,
     * lacunarity^2 * 4 samples/step for the third octave,
     * lacunarity^3 * 4 samples/step for the forth octave,
     *
     * so for a computation with 4 octaves we need something on the
     * order of lacunarity^3 * 4 samples per integer step in noise space.
     */

    steps = pow(scloud_sp->lacunarity, scloud_sp->octaves-1) * 4;
    step_delta = thickness / (double)steps;

    if (rdebug&RDEBUG_SHADE)
        bu_log("steps=%d  delta=%g  thickness=%g\n",
               steps, step_delta, thickness);

    VUNITIZE(v_cloud);
    VMOVE(pt, in_pt);
    trans = 1.0;

    delta_dpmm = scloud_sp->max_d_p_mm - scloud_sp->min_d_p_mm;

    sub_sw = *swp; /* struct copy */
    sub_sw.sw_inputs = MFI_HIT;

    for (i=0; i < steps; i++) {
        /* compute the next point in the cloud space */
        VJOIN1(pt, in_pt, i*step_delta, v_cloud);

        /* get turbulence value (0 .. 1) */
        val = bn_noise_turb(pt, scloud_sp->h_val,
                            scloud_sp->lacunarity, scloud_sp->octaves);

        density = scloud_sp->min_d_p_mm + val * delta_dpmm;

        val = exp(- density * step_delta);
        trans *= val;

        if (swp->sw_xmitonly) continue;

        /* need to set the hit in our fake shadework structure */
        MAT4X3PNT(sub_sw.sw_hit.hit_point, scloud_sp->stom, pt);
        sub_sw.sw_transmit = trans;

        sub_sw.sw_inputs = MFI_HIT;

        light_obs(ap, &sub_sw, swp->sw_inputs);
        /* now we know how much light has arrived from each
         * light source to this point
         */
        for (i=ap->a_rt_i->rti_nlights-1; i >= 0; i--) {
            lp = (struct light_specific *)swp->sw_visible[i];
            if (lp == LIGHT_NULL) continue;

            /* compute how much light has arrived at
             * this location
             */
            incident_light[0] += sub_sw.sw_intensity[3*i+0] *
                                 lp->lt_color[0] * sub_sw.sw_lightfract[i];
            incident_light[1] += sub_sw.sw_intensity[3*i+1] *
                                 lp->lt_color[1] * sub_sw.sw_lightfract[i];
            incident_light[2] += sub_sw.sw_intensity[3*i+2] *
                                 lp->lt_color[2] * sub_sw.sw_lightfract[i];
        }

        VSCALE(incident_light, incident_light, trans);


    }

    /* scloud is basically a white object with partial transparency */
    swp->sw_transmit = trans;
    if (swp->sw_xmitonly) return 1;


    /*
     * At the point of maximum opacity, check light visibility
     * for light color and cloud shadowing.
     * OOPS:  Don't use an interior point, or light_visibility()
     * will see an attenuated light source.
     */
    swp->sw_hit.hit_dist = pp->pt_inhit->hit_dist;
    VJOIN1(swp->sw_hit.hit_point, ap->a_ray.r_pt, swp->sw_hit.hit_dist,
           ap->a_ray.r_dir);
    VREVERSE(swp->sw_hit.hit_normal, ap->a_ray.r_dir);
    swp->sw_inputs |= MFI_HIT | MFI_NORMAL;
    light_obs(ap, swp, swp->sw_inputs);
    VSETALL(incident_light, 0);
    for (i=ap->a_rt_i->rti_nlights-1; i>=0; i--) {
        struct light_specific *lp2;
        if ((lp2 = (struct light_specific *)swp->sw_visible[i]) == LIGHT_NULL)
            continue;
        /* XXX don't have a macro for this */
        incident_light[0] += swp->sw_intensity[3*i+0] * lp2->lt_color[0];
        incident_light[1] += swp->sw_intensity[3*i+1] * lp2->lt_color[1];
        incident_light[2] += swp->sw_intensity[3*i+2] * lp2->lt_color[2];
    }
    VELMUL(swp->sw_color, swp->sw_color, incident_light);


    if (rdebug&RDEBUG_SHADE) {
        pr_shadework("scloud: after light vis, before rr_render", swp);
    }

    if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
        (void)rr_render(ap, pp, swp);

    return 1;
}
Beispiel #10
0
/*	F I R E _ S E T U P
 *
 *	This routine is called (at prep time)
 *	once for each region which uses this shader.
 *	Any shader-specific initialization should be done here.
 */
HIDDEN int
fire_setup(register struct region *rp, struct bu_vls *matparm, char **dpp, struct mfuncs *mfp, struct rt_i *rtip)


    /* pointer to reg_udata in *rp */

    /* New since 4.4 release */
{
    register struct fire_specific	*fire_sp;

    /* check the arguments */
    RT_CHECK_RTI(rtip);
    BU_CK_VLS( matparm );
    RT_CK_REGION(rp);


    if (rdebug&RDEBUG_SHADE)
	bu_log("fire_setup(%s)\n", rp->reg_name);

    /* Get memory for the shader parameters and shader-specific data */
    BU_GETSTRUCT( fire_sp, fire_specific );
    *dpp = (char *)fire_sp;

    /* initialize the default values for the shader */
    memcpy(fire_sp, &fire_defaults, sizeof(struct fire_specific));

    /* parse the user's arguments for this use of the shader. */
    if (bu_struct_parse( matparm, fire_parse_tab, (char *)fire_sp ) < 0 )
	return(-1);

    if (fire_sp->noise_size != -1.0) {
	VSETALL(fire_sp->noise_vscale, fire_sp->noise_size);
    }

    /*
     * The shader needs to operate in a coordinate system which stays
     * fixed on the region when the region is moved (as in animation).
     * We need to get a matrix to perform the appropriate transform(s).
     */

    db_shader_mat(fire_sp->fire_m_to_sh, rtip, rp, fire_sp->fire_min,
		  fire_sp->fire_max, &rt_uniresource);

    /* Build matrix to map shader space to noise space.
     * XXX If only we could get the frametime at this point
     * we could factor the flicker of flames into this matrix
     * rather than having to recompute it on a pixel-by-pixel basis.
     */
    MAT_IDN(fire_sp->fire_sh_to_noise);
    MAT_DELTAS_VEC(fire_sp->fire_sh_to_noise, fire_sp->noise_delta);
    MAT_SCALE_VEC(fire_sp->fire_sh_to_noise, fire_sp->noise_vscale);

    /* get matrix for performing spline of fire colors */
    rt_dspline_matrix(fire_sp->fire_colorspline_mat, "Catmull", 0.5, 0.0);


    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) {
	bu_struct_print( " FIRE Parameters:", fire_print_tab, (char *)fire_sp );
	bn_mat_print( "m_to_sh", fire_sp->fire_m_to_sh );
	bn_mat_print( "sh_to_noise", fire_sp->fire_sh_to_noise );
	bn_mat_print( "colorspline", fire_sp->fire_colorspline_mat );
    }

    return(1);
}
Beispiel #11
0
int
make_hole_in_prepped_regions(struct rt_wdb *wdbp,	/* database to be modified */
			     struct rt_i *rtip,		/* rt_i pointer for the same database */
			     point_t hole_start,	/* center of start of hole */
			     vect_t hole_depth,		/* depth and direction of hole */
			     fastf_t radius,		/* radius of hole */
			     struct bu_ptbl *regions)	/* list of region structures to which this hole
							 * is to be applied
							 */
{
    struct bu_vls tmp_name = BU_VLS_INIT_ZERO;
    size_t i, base_len, count=0;
    struct directory *dp;
    struct rt_db_internal intern;
    struct soltab *stp;

    RT_CHECK_WDB(wdbp);

    /* make a unique name for the RCC we will use (of the form "make_hole_%d") */
    bu_vls_strcat(&tmp_name, "make_hole_");
    base_len = bu_vls_strlen(&tmp_name);
    bu_vls_strcat(&tmp_name, "0");
    while ((db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET)) != RT_DIR_NULL) {
	count++;
	bu_vls_trunc(&tmp_name, base_len);
	bu_vls_printf(&tmp_name, "%zu", count);
    }

    /* build the RCC based on parameters passed in */
    if (mk_rcc(wdbp, bu_vls_addr(&tmp_name), hole_start, hole_depth, radius)) {
	bu_log("Failed to create hole cylinder!!!\n");
	bu_vls_free(&tmp_name);
	return 2;
    }

    /* lookup the newly created RCC */
    dp=db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET);
    if (dp == RT_DIR_NULL) {
      bu_log("Failed to lookup RCC (%s) just made by make_hole_in_prepped_regions()!!!\n",
	       bu_vls_addr(&tmp_name));
	bu_bomb("Failed to lookup RCC just made by make_hole_in_prepped_regions()!!!\n");
    }

    /* get the internal form of the new RCC */
    if (rt_db_get_internal(&intern, dp, wdbp->dbip, NULL, wdbp->wdb_resp) < 0) {
	bu_log("Failed to get internal form of RCC (%s) just made by make_hole_in_prepped_regions()!!!\n",
	       bu_vls_addr(&tmp_name));
	bu_bomb("Failed to get internal form of RCC just made by make_hole_in_prepped_regions()!!!\n");
    }

    /* Build a soltab structure for the new RCC */
    BU_ALLOC(stp, struct soltab);
    stp->l.magic = RT_SOLTAB_MAGIC;
    stp->l2.magic = RT_SOLTAB2_MAGIC;
    stp->st_uses = 1;
    stp->st_dp = dp;
    stp->st_bit = rtip->nsolids++;

    /* Add the new soltab structure to the rt_i structure */
    rtip->rti_Solids = (struct soltab **)bu_realloc(rtip->rti_Solids,
						    rtip->nsolids * sizeof(struct soltab *),
						    "new rti_Solids");
    rtip->rti_Solids[stp->st_bit] = stp;

    /* actually prep the new RCC */
    if (intern.idb_meth->ft_prep(stp, &intern, rtip)) {
	bu_log("Failed to prep RCC (%s) just made by make_hole_in_prepped_regions()!!!\n",
	       bu_vls_addr(&tmp_name));
	bu_bomb("Failed to prep RCC just made by make_hole_in_prepped_regions()!!!\n");
    }

    /* initialize the soltabs list of containing regions */
    bu_ptbl_init(&stp->st_regions, BU_PTBL_LEN(regions), "stp->st_regions");

    /* Subtract the new RCC from each region structure in the list provided */
    for (i=0; i<BU_PTBL_LEN(regions); i++) {
	struct region *rp;
	union tree *treep;

	/* get the next region structure */
	rp = (struct region *)BU_PTBL_GET(regions, i);

	RT_CK_REGION(rp);

	/* create a tree node for the subtraction operation, this will be the new tree root */
	BU_ALLOC(treep, union tree);
	RT_TREE_INIT(treep);
	treep->tr_b.tb_op = OP_SUBTRACT;
	treep->tr_b.tb_left = rp->reg_treetop;	/* subtract from the old treetop */
	treep->tr_b.tb_regionp = rp;

	/* make the new node the new treetop */
	rp->reg_treetop = treep;

	/* create a tree node for the new RCC */
	BU_ALLOC(treep, union tree);
	RT_TREE_INIT(treep);
	treep->tr_a.tu_op = OP_SOLID;
	treep->tr_a.tu_stp = stp;
	treep->tr_a.tu_regionp = rp;

	/* the new RCC gets hung on the right of the subtract node */
	rp->reg_treetop->tr_b.tb_right = treep;

	/* make sure the "all unions" flag is not set on this region */
	rp->reg_all_unions = 0;

	/* Add this region to the list of containing regions for the new RCC */
	bu_ptbl_ins(&stp->st_regions, (long *)rp);
    }

    /* insert the new RCC soltab structure into the already existing space partitioning tree */
    insert_in_bsp(stp, &rtip->rti_CutHead);

    return 0;
}
/*
 * This routine is called (at prep time)
 * once for each region which uses this shader.
 * Any shader-specific initialization should be done here.
 */
HIDDEN int
gauss_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)


/* pointer to reg_udata in *rp */

/* New since 4.4 release */
{
    register struct gauss_specific *gauss_sp;
    struct tree_bark tb;

    /* check the arguments */
    RT_CHECK_RTI(rtip);
    BU_CK_VLS(matparm);
    RT_CK_REGION(rp);


    if (rdebug&RDEBUG_SHADE)
	bu_log("gauss_setup(%s)\n", rp->reg_name);

    if (! rtip->useair)
	bu_bomb("gauss shader used and useair not set\n");


    /* Get memory for the shader parameters and shader-specific data */
    BU_GET(gauss_sp, struct gauss_specific);
    *dpp = gauss_sp;

    /* initialize the default values for the shader */
    memcpy(gauss_sp, &gauss_defaults, sizeof(struct gauss_specific));

    /* parse the user's arguments for this use of the shader. */
    if (bu_struct_parse(matparm, gauss_parse_tab, (char *)gauss_sp, NULL) < 0)
	return -1;

    /* We have to pick up the parameters for the gaussian puff now.
     * They won't be available later.  So what we do is sneak a peak
     * inside the region, make sure the first item in it is an ellipsoid
     * solid, and if it is go steal a peek at its balls ... er ... make
     * that definition/parameters.
     */

    BU_LIST_INIT(&gauss_sp->dbil);
    tb.l = &gauss_sp->dbil;

    tb.dbip = rtip->rti_dbip;
    tb.name = rp->reg_name;
    tb.gs = gauss_sp;

    tree_solids (rp->reg_treetop, &tb, OP_UNION, &rt_uniresource);


    /* XXX If this puppy isn't axis-aligned, we should come up with a
     * matrix to rotate it into alignment.  We're going to have to do
     * computation in the space defined by this ellipsoid.
     */

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print(" Parameters:", gauss_print_tab, (char *)gauss_sp);
	bn_mat_print("m_to_sh", gauss_sp->gauss_m_to_sh);
    }

    return 1;
}
/*
 * This routine is called (at prep time)
 * once for each region which uses this shader.
 * Any shader-specific initialization should be done here.
 *
 * Returns:
 * 1 success
 * 0 success, but delete region
 * -1 failure
 */
HIDDEN int
bbd_setup(struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip)
{
    register struct bbd_specific *bbd_sp;
    struct rt_db_internal intern;
    struct rt_tgc_internal *tgc;
    int s;
    mat_t mat;
    struct bbd_img *bi;
    double angle;
    vect_t vtmp;
    int img_num;
    vect_t vv;

    /* check the arguments */
    RT_CHECK_RTI(rtip);
    BU_CK_VLS(matparm);
    RT_CK_REGION(rp);


    if (rdebug&RDEBUG_SHADE) bu_log("bbd_setup(%s)\n", rp->reg_name);

    RT_CK_TREE(rp->reg_treetop);

    if (rp->reg_treetop->tr_a.tu_op != OP_SOLID) {
	bu_log("--- Warning: Region %s shader %s", rp->reg_name, mfp->mf_name);
	bu_bomb("Shader should be used on region of single (rec/rcc) primitive\n");
    }

    RT_CK_SOLTAB(rp->reg_treetop->tr_a.tu_stp);
    if (rp->reg_treetop->tr_a.tu_stp->st_id != ID_REC) {
	bu_log("--- Warning: Region %s shader %s", rp->reg_name, mfp->mf_name);
	bu_log("Shader should be used on region of single REC/RCC primitive %d\n",
	       rp->reg_treetop->tr_a.tu_stp->st_id);
	bu_bomb("oops\n");
    }


    /* Get memory for the shader parameters and shader-specific data */
    BU_GET(bbd_sp, struct bbd_specific);
    *dpp = bbd_sp;

    /* initialize the default values for the shader */
    memcpy(bbd_sp, &bbd_defaults, sizeof(struct bbd_specific));
    bu_vls_init(&bbd_sp->img_filename);
    BU_LIST_INIT(&bbd_sp->imgs);
    bbd_sp->rtip = rtip; /* because new_image() needs this */
    bbd_sp->img_count = 0;

    /* parse the user's arguments for this use of the shader. */
    if (bu_struct_parse(matparm, bbd_parse_tab, (char *)bbd_sp, NULL) < 0)
	return -1;

    if (bbd_sp->img_count > MAX_IMAGES) {
	bu_log("too many images (%zu) in shader for %s sb < %d\n",
	       bbd_sp->img_count, rp->reg_name, MAX_IMAGES);
	bu_bomb("excessive image count\n");
    }


    MAT_IDN(mat);
    RT_DB_INTERNAL_INIT(&intern);
    s = rt_db_get_internal(&intern, rp->reg_treetop->tr_a.tu_stp->st_dp, rtip->rti_dbip,
			   mat, &rt_uniresource);

    if (intern.idb_minor_type != ID_TGC &&
	intern.idb_minor_type != ID_REC) {
	bu_log("What did I get? %d\n", intern.idb_minor_type);
    }

    if (s < 0) {
	bu_log("%s:%d didn't get internal", __FILE__, __LINE__);
	bu_bomb("");
    }
    tgc = (struct rt_tgc_internal *)intern.idb_ptr;
    RT_TGC_CK_MAGIC(tgc);

    angle = M_PI / (double)bbd_sp->img_count;
    img_num = 0;
    VMOVE(vv, tgc->h);
    VUNITIZE(vv);
    for (BU_LIST_FOR(bi, bbd_img, &bbd_sp->imgs)) {
	static const point_t o = VINIT_ZERO;
	bn_mat_arb_rot(mat, o, vv, angle*img_num);

	/* compute plane equation */
	MAT4X3VEC(bi->img_plane, mat, tgc->a);
	VUNITIZE(bi->img_plane);
	bi->img_plane[H] = VDOT(tgc->v, bi->img_plane);

	MAT4X3VEC(vtmp, mat, tgc->b);
	VADD2(bi->img_origin, tgc->v, vtmp); /* image origin in 3d space */
	/* calculate image u vector */
	VREVERSE(bi->img_x, vtmp);
	VUNITIZE(bi->img_x);
	bi->img_xlen = MAGNITUDE(vtmp) * 2;

	/* calculate image v vector */
	VMOVE(bi->img_y, tgc->h);
	VUNITIZE(bi->img_y);
	bi->img_ylen = MAGNITUDE(tgc->h);

	if (rdebug&RDEBUG_SHADE) {
	    HPRINT("\nimg_plane", bi->img_plane);
	    VPRINT("vtmp", vtmp);
	    VPRINT("img_origin", bi->img_origin);
	    bu_log("img_xlen:%g  ", bi->img_xlen);
	    VPRINT("img_x", bi->img_x);
	    bu_log("img_ylen:%g  ", bi->img_ylen);
	    VPRINT("img_y", bi->img_y);
	}

	img_num++;
    }

    rt_db_free_internal(&intern);

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print(" Parameters:", bbd_print_tab, (char *)bbd_sp);
    }

    return 1;
}
Beispiel #14
0
/* T R E E T H E R M _ S E T U P
 *
 * This routine is called (at prep time)
 * once for each region which uses this shader.
 * Any shader-specific initialization should be done here.
 */
HIDDEN int
tthrm_setup(register struct region *rp, struct bu_vls *matparm, genptr_t *dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip)


/* pointer to reg_udata in *rp */

/* New since 4.4 release */
{
    register struct tthrm_specific *tthrm_sp;
    struct bu_mapped_file *tt_file;
    char *tt_data;
    long cyl_tot = 0;
    long tseg;
    float *fp;
    float fv[4];
    double min_temp;
    double max_temp;
    point_t center;
    point_t pt;
    vect_t dir;
    static const double inv_nodes = 1.0/8.0;
    int node;
    int i;
    int long_size = 0;
    size_t file_size_long;
    size_t file_size_int;

    /* check the arguments */
    RT_CHECK_RTI(rtip);
    BU_CK_VLS(matparm);
    RT_CK_REGION(rp);

    if (rdebug&RDEBUG_SHADE)
	bu_log("tthrm_setup(Region:\"%s\", tthrm(%s))\n",
	       rp->reg_name, bu_vls_addr(matparm));

    /* Get memory for the shader parameters and shader-specific data */
    BU_GET(tthrm_sp, struct tthrm_specific);
    *dpp = tthrm_sp;
    tthrm_sp->magic = tthrm_MAGIC;

    tthrm_sp->tt_name[0] = '\0';
    tthrm_sp->tt_min_temp = tthrm_sp->tt_max_temp = 0.0;

    if (rdebug&RDEBUG_SHADE)
	bu_log("Parsing: (%s)\n", bu_vls_addr(matparm));

    if (bu_struct_parse(matparm, tthrm_parse, (char *)tthrm_sp) < 0) {
	bu_bomb(__FILE__);
    }
    if (tthrm_sp->tt_name[0] == '\0') {
	bu_log("Must specify file for tthrm shader on %s (got \"%s\"\n",
	       rp->reg_name, bu_vls_addr(matparm));
	bu_bomb(__FILE__);
    }

    tt_file = bu_open_mapped_file(tthrm_sp->tt_name, (char *)NULL);
    if (!tt_file) {
	bu_log("Error mapping \"%s\"\n",  tthrm_sp->tt_name);
	bu_bomb("shader tthrm: can't get thermal data");
    }
    tt_data = tt_file->buf;


    if (rdebug&RDEBUG_SHADE)
	bu_log("tthrm_setup() data: %p total\n",
	       (void *)tt_data);

    /* Compute how big the file should be, so that we can guess
     * at the size of the integer at the front of the file
     */
    file_size_int = sizeof(int) + *((int *)tt_data) *
	(sizeof(short) + sizeof(float) * 4 * NUM_NODES);

    file_size_long = sizeof(long) + *((long *)tt_data) *
	(sizeof(short) + sizeof(float) * 4 * NUM_NODES);

    switch (sizeof(long)) {
	case 8:
	    if (tt_file->buflen == file_size_long) {
		/* 64bit data on 64bit host */
		long_size = sizeof(long);
		tthrm_sp->tt_max_seg = cyl_tot = *((long *)tt_data);
	    } else if (tt_file->buflen == file_size_int) {
		/* 32bit data on 32bit host */
		long_size = sizeof(int);
		tthrm_sp->tt_max_seg = cyl_tot = *((int *)tt_data);
	    }
	    break;
	case 4:
	    if (tt_file->buflen == file_size_long) {
		/* 32bit data on 32bit host */
		long_size = sizeof(long);
		tthrm_sp->tt_max_seg = cyl_tot = *((long *)tt_data);
	    } else if (tt_file->buflen == (file_size_long+4)) {
		/* 64bit data on 32bit host */

		cyl_tot = *((int *)tt_data);
		if (cyl_tot != 0) {
		    bu_log("%s:%d thermal data written on 64bit machine with more that 2^32 segs\n", __FILE__, __LINE__);
		    bu_bomb("");
		}

		long_size = sizeof(long) + 4;
		tthrm_sp->tt_max_seg = cyl_tot =
		    ((int *)tt_data)[1];
	    }
	    break;
	default:
	    bu_log("a long int is %d bytes on this machine\n", sizeof(long));
	    bu_bomb("I can only handle 4 or 8 byte longs\n");
	    break;
    }

    if (rdebug&RDEBUG_SHADE)
	bu_log("cyl_tot = %ld\n", cyl_tot);

    tthrm_sp->tt_segs = (struct thrm_seg *)
	bu_calloc(cyl_tot, sizeof(struct thrm_seg), "thermal segs");

    min_temp = MAX_FASTF;
    max_temp = -MAX_FASTF;

#define CYL_DATA(_n) ((float *) (&tt_data[				\
				     long_size +			\
				     (_n) * (sizeof(short) + sizeof(float) * 4 * NUM_NODES) + \
				     sizeof(short)			\
				     ]))

    for (tseg = 0; tseg < cyl_tot; tseg++) {

	/* compute centerpoint, min/max temperature values */
	fp = CYL_DATA(tseg);
	VSETALL(center, 0.0);
	for (node=0; node < NUM_NODES; node++, fp+=4) {
	    /* this is necessary to assure that all float
	     * values are aligned on 4-byte boundaries
	     */
	    memcpy(fv, fp, sizeof(float)*4);

	    if (rdebug&RDEBUG_SHADE)
		bu_log("tthrm_setup() node %d (%g %g %g) %g\n",
		       node, fv[0], fv[1], fv[2], fv[3]);

	    /* make sure we don't have any "infinity" values */
	    for (i=0; i < 4; i++) {
		if (fv[i] > MAX_FASTF || fv[i] < -MAX_FASTF) {
		    bu_log("%s:%d seg %ld node %d coord %d out of bounds: %g\n",
			   __FILE__, __LINE__, tseg, node, i, fv[i]);
		    bu_bomb("choke, gasp, *croak*\n");
		}
	    }

	    /* copy the values to the segment list, converting
	     * from Meters to Millimeters in the process
	     */
	    VSCALE(tthrm_sp->tt_segs[tseg].node[node], fv, 1000.0);
	    tthrm_sp->tt_segs[tseg].temperature[node] = fv[3];

	    VADD2(center, center, fv);

	    if (fv[3] > max_temp) max_temp = fv[3];
	    if (fv[3] < min_temp) min_temp = fv[3];
	}

	VSCALE(center, center, 1000.0);
	VSCALE(tthrm_sp->tt_segs[tseg].pt, center, inv_nodes);

	if (rdebug&RDEBUG_SHADE) {
	    bu_log("Center: (%g %g %g) (now in mm, not m)\n",
		   V3ARGS(tthrm_sp->tt_segs[tseg].pt));
	}

	/* compute vectors from center pt for each node */
	fp = CYL_DATA(tseg);
	for (node=0; node < NUM_NODES; node++, fp+=4) {
	    /* this is necessary to assure that all float
	     * values are aligned on 4-byte boundaries
	     */
	    memcpy(fv, fp, sizeof(float)*4);

	    VSCALE(pt, fv, 1000.0);
	    VSUB2(tthrm_sp->tt_segs[tseg].vect[node],
		  pt,
		  tthrm_sp->tt_segs[tseg].pt
		);
	}

	/* compute a direction vector for the thermal segment */
	VCROSS(dir, tthrm_sp->tt_segs[tseg].vect[0],
	       tthrm_sp->tt_segs[tseg].vect[2]);
	VUNITIZE(dir);
	VMOVE(tthrm_sp->tt_segs[tseg].dir, dir);
	tthrm_sp->tt_segs[tseg].magic = THRM_SEG_MAGIC;
    }

    bu_close_mapped_file(tt_file);

    if (ZERO(tthrm_sp->tt_min_temp) && EQUAL(tthrm_sp->tt_max_temp, SMALL_FASTF)) {
	tthrm_sp->tt_min_temp = min_temp;
	tthrm_sp->tt_max_temp = max_temp;
	bu_log("computed temp min/max on %s: %g/%g\n", rp->reg_name, min_temp, max_temp);
    } else {
	min_temp =tthrm_sp->tt_min_temp;
	max_temp = tthrm_sp->tt_max_temp;
	bu_log("taking user specified on %s: min/max %g/%g\n", rp->reg_name, min_temp, max_temp);
    }

    if (!EQUAL(max_temp, min_temp)) {
	tthrm_sp->tt_temp_scale = 1.0 / (max_temp - min_temp);
    } else {
	/* min and max are equal, maybe zero */
	if (ZERO(max_temp))
	    tthrm_sp->tt_temp_scale = 0.0;
	else
	    tthrm_sp->tt_temp_scale = 255.0/max_temp;
    }
    /* The shader needs to operate in a coordinate system which stays
     * fixed on the region when the region is moved (as in animation)
     * we need to get a matrix to perform the appropriate transform(s).
     *
     * Shading is done in "region coordinates":
     */
    db_region_mat(tthrm_sp->tthrm_m_to_sh, rtip->rti_dbip, rp->reg_name, &rt_uniresource);

    if (rdebug&RDEBUG_SHADE) {
	bu_log("min_temp: %17.14e  max_temp %17.14e temp_scale: %17.14e\n",
	       tthrm_sp->tt_min_temp,
	       tthrm_sp->tt_max_temp,
	       tthrm_sp->tt_temp_scale);

	bu_log("tthrm_setup(%s, %s)done\n",
	       rp->reg_name, bu_vls_addr(matparm));
	tthrm_print(rp, *dpp);
    }

    return 1;
}
Beispiel #15
0
/**
 * R T _ G E T T R E E S _ M U V E S
 *
 * User-called function to add a set of tree hierarchies to the active
 * set. Includes getting the indicated list of attributes and a
 * Tcl_HashTable for use with the ORCA man regions. (stashed in the
 * rt_i structure).
 *
 * This function may run in parallel, but is not multiply re-entrant
 * itself, because db_walk_tree() isn't multiply re-entrant.
 *
 * Semaphores used for critical sections in parallel mode:
 *	RT_SEM_TREE*	protects rti_solidheads[] lists, d_uses(solids)
 *	RT_SEM_RESULTS	protects HeadRegion, mdl_min/max, d_uses(reg), nregions
 *	RT_SEM_WORKER	(db_walk_dispatcher, from db_walk_tree)
 *	RT_SEM_STATS	nsolids
 *
 * INPUTS
 *	rtip	- RT instance pointer
 *	attrs	- array of pointers (NULL terminated) to strings (attribute names). A corresponding
 *		  array of "bu_mro" objects containing the attribute values will be attached to region
 *		  structures ("attr_values")
 *	argc	- number of trees to get
 *	argv	- array of char pointers to the names of the tree tops
 *	ncpus	- number of cpus to use
 *
 * Returns -
 *  	0	Ordinarily
 *	-1	On major error
 */
int
rt_gettrees_muves(struct rt_i *rtip, const char **attrs, int argc, const char **argv, int ncpus)
{
    register struct soltab	*stp;
    register struct region	*regp;
    Tcl_HashTable		*tbl;
    int			prev_sol_count;
    int			i;
    int			num_attrs=0;
    point_t			region_min, region_max;

    RT_CHECK_RTI(rtip);
    RT_CK_DBI(rtip->rti_dbip);

    if (!rtip->needprep)  {
	bu_log("ERROR: rt_gettree() called again after rt_prep!\n");
	return(-1);		/* FAIL */
    }

    if ( argc <= 0 )  return(-1);	/* FAIL */

    tbl = (Tcl_HashTable *)bu_malloc( sizeof( Tcl_HashTable ), "rtip->Orca_hash_tbl" );
    Tcl_InitHashTable( tbl, TCL_ONE_WORD_KEYS );
    rtip->Orca_hash_tbl = (genptr_t)tbl;

    prev_sol_count = rtip->nsolids;

    {
	struct db_tree_state	tree_state;

	tree_state = rt_initial_tree_state;	/* struct copy */
	tree_state.ts_dbip = rtip->rti_dbip;
	tree_state.ts_rtip = rtip;
	tree_state.ts_resp = NULL;	/* sanity.  Needs to be updated */

	if ( attrs ) {
	    if ( rtip->rti_dbip->dbi_version < 5 ) {
		bu_log( "WARNING: requesting attributes from an old database version (ignored)\n" );
		bu_avs_init_empty( &tree_state.ts_attrs );
	    } else {
		while ( attrs[num_attrs] ) {
		    num_attrs++;
		}
		if ( num_attrs ) {
		    bu_avs_init( &tree_state.ts_attrs,
				 num_attrs,
				 "avs in tree_state" );
		    num_attrs = 0;
		    while ( attrs[num_attrs] ) {
			bu_avs_add( &tree_state.ts_attrs,
				    attrs[num_attrs],
				    NULL );
			num_attrs++;
		    }
		} else {
		    bu_avs_init_empty( &tree_state.ts_attrs );
		}
	    }
	} else {
	    bu_avs_init_empty( &tree_state.ts_attrs );
	}

	/* ifdef this out for now, it is only using memory.  perhaps a
	 * better way of initiating ORCA stuff can be found.
	 */
#if 0
	bu_avs_add( &tree_state.ts_attrs, "ORCA_Comp", (char *)NULL );
#endif
	i = db_walk_tree( rtip->rti_dbip, argc, argv, ncpus,
			  &tree_state,
			  rt_gettree_region_start,
			  rt_gettree_region_end,
			  rt_gettree_leaf, (genptr_t)tbl );
	bu_avs_free( &tree_state.ts_attrs );
    }

    /* DEBUG:  Ensure that all region trees are valid */
    for ( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) )  {
	RT_CK_REGION(regp);
	db_ck_tree(regp->reg_treetop);
    }

    /*
     * Eliminate any "dead" solids that parallel code couldn't change.
     * First remove any references from the region tree, then remove
     * actual soltab structs from the soltab list.
     */
    for ( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) )  {
	RT_CK_REGION(regp);
	rt_tree_kill_dead_solid_refs( regp->reg_treetop );
	(void)rt_tree_elim_nops( regp->reg_treetop, &rt_uniresource );
    }
 again:
    RT_VISIT_ALL_SOLTABS_START( stp, rtip )  {
	RT_CK_SOLTAB(stp);
	if ( stp->st_aradius <= 0 )  {
	    bu_log("rt_gettrees() cleaning up dead solid '%s'\n",
		   stp->st_dp->d_namep );
	    rt_free_soltab(stp);
	    /* Can't do rtip->nsolids--, that doubles as max bit number! */
	    /* The macro makes it hard to regain place, punt */
	    goto again;
	}
    } RT_VISIT_ALL_SOLTABS_END