Example #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;
}
Example #2
0
File: pr.c Project: kanzure/brlcad
void
rt_pr_partitions(const struct rt_i *rtip, register const struct partition *phead, const char *title)
{
    register const struct partition *pp;
    struct bu_vls v = BU_VLS_INIT_ZERO;

    RT_CHECK_RTI(rtip);

    bu_log_indent_vls(&v);
    bu_vls_strcat(&v, "------");
    bu_vls_strcat(&v, title);
    bu_vls_strcat(&v, "\n");
    bu_log_indent_delta(2);

    for (pp = phead->pt_forw; pp != phead; pp = pp->pt_forw) {
	RT_CHECK_PT(pp);
	rt_pr_pt_vls(&v, rtip, pp);
    }
    bu_log_indent_delta(-2);
    bu_log_indent_vls(&v);
    bu_vls_strcat(&v, "------\n");

    bu_log("%s", bu_vls_addr(&v));
    bu_vls_free(&v);
}
Example #3
0
File: pr.c Project: kanzure/brlcad
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);
    }
}
Example #4
0
File: pr.c Project: kanzure/brlcad
void
rt_pr_pt(const struct rt_i *rtip, register const struct partition *pp)
{
    struct bu_vls v = BU_VLS_INIT_ZERO;

    RT_CHECK_RTI(rtip);
    RT_CHECK_PT(pp);
    rt_pr_pt_vls(&v, rtip, pp);
    bu_log("%s", bu_vls_addr(&v));
    bu_vls_free(&v);
}
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 */
int
toon_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    int i;
    struct toon_specific *toon_sp = (struct toon_specific *)dp;
    struct light_specific *lp;
    fastf_t cosi, scale;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_TOON_SP(toon_sp);

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

    /* if surface normal is nearly orthogonal to the ray, make a black line */
    if (VDOT(swp->sw_hit.hit_normal, ap->a_inv_dir) >= 0.8) {
	VSETALL(swp->sw_color, 0);
	return 1;
    }

    /* probably need to set some swp values here to avoid the infinite recursion
     * if specified lights exist. */
    light_obs(ap, swp, MFI_HIT);

    /* Consider effects of each light source */
    for (i=ap->a_rt_i->rti_nlights-1; i>=0; i--) {
	if ((lp = (struct light_specific *)swp->sw_visible[i]) == LIGHT_NULL)
	    continue;

	cosi = VDOT(swp->sw_hit.hit_normal, swp->sw_tolight);
	if (cosi <= 0.0) scale = 0.0;
	else if (cosi <= 0.5) scale = 0.5;
	else if (cosi <= 0.8) scale = 0.8;
	else scale = 1.0;
	VSCALE(swp->sw_color, swp->sw_color, scale);
	return 1;
    }

    /* no paths to light source, so just paint it black */
    VSETALL(swp->sw_color, 0);

    if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	(void)rr_render(ap, pp, swp);
    return 1;
}
Example #6
0
/*
 *	N U L L _ R E N D E R
 *
 *	This is called (from viewshade() in shade.c) once for each hit point
 *	to be shaded.  The purpose here is to fill in values in the shadework
 *	structure.  This is, of course, not necessary when setup returns 0.
 *
 *  The null shader actually does "something", though it is not called.
 *  It has to at least pass the ray through so that it can actually
 *  raytrace what is visible behind the invisible object.  Otherwise,
 *  an empty black void would be rendered.  this is not really important
 *  though, since it shouldn't normally be called.
 */
HIDDEN int
sh_null_render( struct application *ap, struct partition *pp, struct shadework *swp, char *dp ) {

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    /* shadework structures do not have magic numbers or other means to test
     * their validity
     */

    bu_log("Who called sh_null_render explicitly?");

    /* here is what actually makes the object invisible/null instead of being a
     * black void (if render ever is called).
     */
    (void)rr_render(ap, pp, swp);

    return(1);
}
Example #7
0
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 *
 * The flat shader is probably the second most simple shader (second to
 * the null/invisible shader -- it does nothing).  It shades an object
 * a constant color.  The only complexity comes into play when a
 * transparency value is set.  Then we get the color value behind the
 * one we are shading and blend accordingly with the flat color.
 */
int
flat_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{

    register struct flat_specific *flat_sp = (struct flat_specific *)dp;
    const point_t unit = {1.0, 1.0, 1.0};
    point_t intensity;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_FLAT_SP(flat_sp);

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

    /* do the actual flat color shading for the flat object. if the object is
     * not transparent, just put the color.  if the object is transparent, do
     * a little more work determining the background pixel, and then blend with
     * the flat foreground object.
     */
    if (VNEAR_ZERO(flat_sp->transparency, SMALL_FASTF)) {

	/* just put the flat value */
	VMOVE(swp->sw_color, flat_sp->color);
    } else {

	/* this gets the background pixel value, if the transparency is not 0 */
	swp->sw_transmit = 1.0; /*!!! try to remove */
	VMOVE(swp->sw_basecolor, flat_sp->transparency);
	(void)rr_render(ap, pp, swp);

	/* now blend with the foreground object being shaded */
	VSUB2(intensity, unit, flat_sp->transparency);  /* inverse transparency is how much we want */
	VELMUL(intensity, intensity, flat_sp->color); /* ??? is there a way to merge this mul->add step? */
	VADD2(swp->sw_color, swp->sw_color, intensity);
    }

    return 1;
}
Example #8
0
/*
 * Given a u, v coordinate within the texture (0 <= u, v <= 1.0),
 * return a pointer to the relevant pixel.
 *
 * Note that .pix files are stored left-to-right, bottom-to-top,
 * which works out very naturally for the indexing scheme.
 */
HIDDEN int
txt_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct txt_specific *tp =
	(struct txt_specific *)dp;
    fastf_t xmin, xmax, ymin, ymax;
    int dx, dy;
    register fastf_t r, g, b;
    struct uvcoord uvc;
    long tmp;

    RT_CK_AP(ap);
    RT_CHECK_PT(pp);

    uvc = swp->sw_uv;

    if (rdebug & RDEBUG_SHADE)
	bu_log("in txt_render(): du=%g, dv=%g\n",
	       uvc.uv_du, uvc.uv_dv);

    /* take care of scaling U, V coordinates to get the desired amount
     * of replication of the texture
     */
    uvc.uv_u *= tp->tx_scale[X];
    tmp = uvc.uv_u;
    uvc.uv_u -= tmp;
    if (tp->tx_mirror && (tmp & 1))
	uvc.uv_u = 1.0 - uvc.uv_u;

    uvc.uv_v *= tp->tx_scale[Y];
    tmp = uvc.uv_v;
    uvc.uv_v -= tmp;
    if (tp->tx_mirror && (tmp & 1))
	uvc.uv_v = 1.0 - uvc.uv_v;

    uvc.uv_du /= tp->tx_scale[X];
    uvc.uv_dv /= tp->tx_scale[Y];

    /*
     * If no texture file present, or if
     * texture isn't and can't be read, give debug colors
     */

    if ((bu_vls_strlen(&tp->tx_name) <= 0) || (!tp->tx_mp && !tp->tx_binunifp)) {
	bu_log("WARNING: texture [%s] could not be read\n", bu_vls_addr(&tp->tx_name));
	VSET(swp->sw_color, uvc.uv_u, 0, uvc.uv_v);
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	    (void)rr_render(ap, pp, swp);
	return 1;
    }

    /* u is left->right index, v is line number bottom->top */
    /* Don't filter more than 1/8 of the texture for 1 pixel! */
    if (uvc.uv_du > 0.125) uvc.uv_du = 0.125;
    if (uvc.uv_dv > 0.125) uvc.uv_dv = 0.125;

    if (uvc.uv_du < 0 || uvc.uv_dv < 0) {
	bu_log("txt_render uv=%g, %g, du dv=%g %g seg=%s\n",
	       uvc.uv_u, uvc.uv_v, uvc.uv_du, uvc.uv_dv,
	       pp->pt_inseg->seg_stp->st_name);
	uvc.uv_du = uvc.uv_dv = 0;
    }

    xmin = uvc.uv_u - uvc.uv_du;
    xmax = uvc.uv_u + uvc.uv_du;
    ymin = uvc.uv_v - uvc.uv_dv;
    ymax = uvc.uv_v + uvc.uv_dv;
    if (xmin < 0) xmin = 0;
    if (ymin < 0) ymin = 0;
    if (xmax > 1) xmax = 1;
    if (ymax > 1) ymax = 1;

    if (rdebug & RDEBUG_SHADE)
	bu_log("footprint in texture space is (%g %g) <-> (%g %g)\n",
	       xmin * (tp->tx_w-1), ymin * (tp->tx_n-1),
	       xmax * (tp->tx_w-1), ymax * (tp->tx_n-1));

    dx = (int)(xmax * (tp->tx_w-1)) - (int)(xmin * (tp->tx_w-1));
    dy = (int)(ymax * (tp->tx_n-1)) - (int)(ymin * (tp->tx_n-1));

    if (rdebug & RDEBUG_SHADE)
	bu_log("\tdx = %d, dy = %d\n", dx, dy);

    if (dx == 0 && dy == 0) {
	/* No averaging necessary */

	register unsigned char *cp=NULL;

	if (tp->tx_mp) {
	    cp = ((unsigned char *)(tp->tx_mp->buf)) +
		(int)(ymin * (tp->tx_n-1)) * tp->tx_w * 3 +
		(int)(xmin * (tp->tx_w-1)) * 3;
	} else if (tp->tx_binunifp) {
	    cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) +
		(int)(ymin * (tp->tx_n-1)) * tp->tx_w * 3 +
		(int)(xmin * (tp->tx_w-1)) * 3;
	} else {
	    bu_bomb("sh_text.c -- No texture data found\n");
	}
	r = *cp++;
	g = *cp++;
	b = *cp;
    } else {
	/* Calculate weighted average of cells in footprint */

	fastf_t tot_area = 0.0;
	fastf_t cell_area;
	int start_line, stop_line, line;
	int start_col, stop_col, col;
	fastf_t xstart, xstop, ystart, ystop;

	xstart = xmin * (tp->tx_w-1);
	xstop = xmax * (tp->tx_w-1);
	ystart = ymin * (tp->tx_n-1);
	ystop = ymax * (tp->tx_n-1);

	start_line = ystart;
	stop_line = ystop;
	start_col = xstart;
	stop_col = xstop;

	r = g = b = 0.0;

	if (rdebug & RDEBUG_SHADE) {
	    bu_log("\thit in texture space = (%g %g)\n", uvc.uv_u * (tp->tx_w-1), uvc.uv_v * (tp->tx_n-1));
	    bu_log("\t averaging from  (%g %g) to (%g %g)\n", xstart, ystart, xstop, ystop);
	    bu_log("\tcontributions to average:\n");
	}

	for (line = start_line; line <= stop_line; line++) {
	    register unsigned char *cp=NULL;
	    fastf_t line_factor;
	    fastf_t line_upper, line_lower;

	    line_upper = line + 1.0;
	    if (line_upper > ystop)
		line_upper = ystop;
	    line_lower = line;
	    if (line_lower < ystart)
		line_lower = ystart;
	    line_factor = line_upper - line_lower;

	    if (tp->tx_mp) {
		cp = ((unsigned char *)(tp->tx_mp->buf)) +
		    line * tp->tx_w * 3 + (int)(xstart) * 3;
	    } else if (tp->tx_binunifp) {
		cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) +
		    line * tp->tx_w * 3 + (int)(xstart) * 3;
	    } else {
		/* not reachable */
		bu_bomb("sh_text.c -- Unable to read datasource\n");
	    }

	    for (col = start_col; col <= stop_col; col++) {
		fastf_t col_upper, col_lower;

		col_upper = col + 1.0;
		if (col_upper > xstop) col_upper = xstop;
		col_lower = col;
		if (col_lower < xstart) col_lower = xstart;

		cell_area = line_factor * (col_upper - col_lower);
		tot_area += cell_area;

		if (rdebug & RDEBUG_SHADE)
		    bu_log("\t %d %d %d weight=%g (from col=%d line=%d)\n", *cp, *(cp+1), *(cp+2), cell_area, col, line);

		r += (*cp++) * cell_area;
		g += (*cp++) * cell_area;
		b += (*cp++) * cell_area;
	    }

	}
	r /= tot_area;
	g /= tot_area;
	b /= tot_area;
    }

    if (rdebug & RDEBUG_SHADE)
	bu_log(" average: %g %g %g\n", r, g, b);

    if (!tp->tx_trans_valid) {
    opaque:
	VSET(swp->sw_color,
	     r / 255.0,
	     g / 255.0,
	     b / 255.0);

	if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	    (void)rr_render(ap, pp, swp);
	return 1;
    }
    /* This circumlocution needed to keep expression simple for Cray,
     * and others
     */
    if (!EQUAL(r, ((long)tp->tx_transp[0]))) goto opaque;
    if (!EQUAL(g, ((long)tp->tx_transp[1]))) goto opaque;
    if (!EQUAL(b, ((long)tp->tx_transp[2]))) goto opaque;

    /*
     * Transparency mapping is enabled, and we hit a transparent spot.
     * Let higher level handle it in reflect/refract code.
     */
    swp->sw_transmit = 1.0;
    swp->sw_reflect = 0.0;

    bu_log("leaving txt_render()\n");

    if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	(void)rr_render(ap, pp, swp);
    return 1;
}
Example #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;
}
Example #10
0
/*
 *	F I R E _ R E N D E R
 *
 *	This is called (from viewshade() in shade.c) once for each hit point
 *	to be shaded.  The purpose here is to fill in values in the shadework
 *	structure.
 */
int
fire_render(struct application *ap, struct partition *pp, struct shadework *swp, char *dp)


    /* defined in material.h */
    /* ptr to the shader-specific struct */
{
#define DEBUG_SPACE_PRINT(str, i_pt, o_pt) \
	if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) { \
		bu_log("fire_render() %s space \n", str); \
		bu_log("fire_render() i_pt(%g %g %g)\n", V3ARGS(i_pt) ); \
		bu_log("fire_render() o_pt(%g %g %g)\n", V3ARGS(o_pt) ); \
	}

#define	SHADER_TO_NOISE(n_pt, sh_pt, fire_sp, zdelta) { \
	point_t tmp_pt; \
	tmp_pt[X] = sh_pt[X]; \
	tmp_pt[Y] = sh_pt[Y]; \
	if ( ! NEAR_ZERO(fire_sp->fire_stretch, SQRT_SMALL_FASTF) ) \
		tmp_pt[Z] = exp( (sh_pt[Z]+0.125) * -fire_sp->fire_stretch ); \
	else \
		tmp_pt[Z] = sh_pt[Z]; \
	MAT4X3PNT(n_pt, fire_sp->fire_sh_to_noise, tmp_pt); \
	n_pt[Z] += zdelta; \
}

    register struct fire_specific *fire_sp =
	(struct fire_specific *)dp;
    point_t	m_i_pt, m_o_pt;	/* model space in/out points */
    point_t sh_i_pt, sh_o_pt;	/* shader space in/out points */
    point_t noise_i_pt, noise_o_pt;	/* shader space in/out points */
    point_t noise_pt;
    point_t	color;
    vect_t	noise_r_dir;
    double	noise_r_thick;
    int	i;
    double	samples_per_unit_noise;
    double	noise_dist_per_sample;
    point_t	shader_pt;
    vect_t	shader_r_dir;
    double	shader_r_thick;
    double	shader_dist_per_sample;
    double	noise_zdelta;

    int	samples;
    double	dist;
    double	noise_val;
    double	lumens;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_fire_SP(fire_sp);

    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) {
/*		bu_struct_print( "fire_render Parameters:", fire_print_tab, (char *)fire_sp ); */
	bu_log("fire_render()\n");
    }
    /* If we are performing the shading in "region" space, we must
     * transform the hit point from "model" space to "region" space.
     * See the call to db_region_mat in fire_setup().
     */

    /*
     * Compute the ray/solid in and out points,
     */
    VMOVE(m_i_pt, swp->sw_hit.hit_point);
    VJOIN1(m_o_pt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir);
    DEBUG_SPACE_PRINT("model", m_i_pt, m_o_pt);

    /* map points into shader space */
    MAT4X3PNT(sh_i_pt, fire_sp->fire_m_to_sh, m_i_pt);
    MAT4X3PNT(sh_o_pt, fire_sp->fire_m_to_sh, m_o_pt);
    DEBUG_SPACE_PRINT("shader", sh_i_pt, sh_o_pt);

    noise_zdelta = fire_sp->fire_flicker * swp->sw_frametime;

    SHADER_TO_NOISE(noise_i_pt, sh_i_pt, fire_sp, noise_zdelta);
    SHADER_TO_NOISE(noise_o_pt, sh_o_pt, fire_sp, noise_zdelta);

    VSUB2(noise_r_dir, noise_o_pt, noise_i_pt);

    noise_r_thick = MAGNITUDE(noise_r_dir);

    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) {
	bu_log("fire_render() noise_r_dir (%g %g %g)\n",
	       V3ARGS(noise_r_dir) );
	bu_log("fire_render() noise_r_thick %g\n", noise_r_thick);
    }


    /* compute number of samples per unit length in noise space.
     *
     * 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, nyquist
     * tells us we need at least 4 samples/cycle at the highest octave
     * rate.
     */

    samples_per_unit_noise =
	pow(fire_sp->noise_lacunarity, fire_sp->noise_octaves-1) * 4.0;

    noise_dist_per_sample = 1.0 / samples_per_unit_noise;

    samples = samples_per_unit_noise * noise_r_thick;

    if (samples < 1) samples = 1;

    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) {
	bu_log("samples:%d\n", samples);
	bu_log("samples_per_unit_noise %g\n", samples_per_unit_noise);
	bu_log("noise_dist_per_sample %g\n", noise_dist_per_sample);
    }

    /* To do the exponential stretch and decay properly we need to
     * do the computations in shader space, and convert the points
     * to noise space.  Performance pig.
     */

    VSUB2(shader_r_dir, sh_o_pt, sh_i_pt);
    shader_r_thick = MAGNITUDE(shader_r_dir);
    VUNITIZE(shader_r_dir);

    shader_dist_per_sample = shader_r_thick / samples;

    lumens = 0.0;
    for (i = 0; i < samples; i++) {
	dist = (double)i * shader_dist_per_sample;
	VJOIN1(shader_pt, sh_i_pt, dist, shader_r_dir);

	SHADER_TO_NOISE(noise_pt, shader_pt, fire_sp, noise_zdelta);

	noise_val = bn_noise_turb(noise_pt, fire_sp->noise_h_val,
				  fire_sp->noise_lacunarity, fire_sp->noise_octaves);

	if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug )
	    bu_log("bn_noise_turb(%g %g %g) = %g\n",
		   V3ARGS(noise_pt),
		   noise_val);

	/* XXX
	 * When doing the exponential stretch, we scale the noise
	 * value by the height in shader space
	 */

	if ( NEAR_ZERO(fire_sp->fire_stretch, SQRT_SMALL_FASTF) )
	    lumens += noise_val * 0.025;
	else {
	    register double t;
	    t = lumens;
	    lumens += noise_val * 0.025 *  (1.0 -shader_pt[Z]);
	    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug )
		bu_log("lumens:%g = %g + %g * %g\n",
		       lumens, t, noise_val,
		       0.025 * (1.0 - shader_pt[Z]) );

	}
	if (lumens >= 1.0) {
	    lumens = 1.0;
	    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug )
		bu_log("early exit from lumens loop\n");
	    break;
	}

    }

    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug )
	bu_log("lumens = %g\n", lumens);

    if (lumens < 0.0) lumens = 0.0;
    else if (lumens > 1.0) lumens = 1.0;


    rt_dspline_n(color, fire_sp->fire_colorspline_mat, (double *)flame_colors,
		 18, 3, lumens);

    VMOVE(swp->sw_color, color);
/*	VSETALL(swp->sw_basecolor, 1.0);*/

    swp->sw_transmit = 1.0 - (lumens * 4.);
    if (swp->sw_reflect > 0 || swp->sw_transmit > 0 )
	(void)rr_render( ap, pp, swp );

    return(1);
}
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 */
HIDDEN int osl_render(struct application *ap, const struct partition *pp,
		      struct shadework *swp, void *dp)
/* defined in ../h/shadework.h */
/* ptr to the shader-specific struct */
{
    register struct osl_specific *osl_sp =
	(struct osl_specific *)dp;

    void * thread_info;

    int nsamples; /* Number of samples */

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_OSL_SP(osl_sp);

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

    bu_semaphore_acquire(BU_SEM_SYSCALL);

    /* Check if it is the first time this thread is calling this function */
    bool visited = false;
    for (size_t i = 0; i < visited_addrs.size(); i++) {
	if (ap->a_resource == visited_addrs[i]) {
	    visited = true;
	    thread_info = thread_infos[i];
	    break;
	}
    }
    if (!visited) {
	visited_addrs.push_back(ap->a_resource);
	/* Get thread specific information from OSLRender system */
	thread_info = oslr->CreateThreadInfo();
	thread_infos.push_back(thread_info);
    }

    if (ap->a_level == 0) {
	default_a_hit = ap->a_hit; /* save the default hit callback (colorview @ rt) */
	default_a_miss = ap->a_miss;
    }
    bu_semaphore_release(BU_SEM_SYSCALL);

    Color3 acc_color(0.0f);

    /* -----------------------------------
     * Fill in all necessary information for the OSL renderer
     * -----------------------------------
     */
    RenderInfo info;
    /* Set hit point */
    VMOVE(info.P, swp->sw_hit.hit_point);

    /* Set normal at the point */
    VMOVE(info.N, swp->sw_hit.hit_normal);

    /* Set incidence ray direction */
    VMOVE(info.I, ap->a_ray.r_dir);

    /* U-V mapping stuff */
    info.u = swp->sw_uv.uv_u;
    info.v = swp->sw_uv.uv_v;
    VSETALL(info.dPdu, 0.0f);
    VSETALL(info.dPdv, 0.0f);

    /* x and y pixel coordinates */
    info.screen_x = ap->a_x;
    info.screen_y = ap->a_y;

    info.depth = ap->a_level;
    info.surfacearea = 1.0f;

    info.shader_ref = osl_sp->shader_ref;

    /* We assume that the only information that will be written is thread_info,
       so that oslr->QueryColor is thread safe */
    info.thread_info = thread_info;


// Ray-tracing (local illumination)

    /* We only perform reflection if application decides to */
    info.doreflection = 0;
    info.out_ray_type = 0;

    Color3 weight = oslr->QueryColor(&info);

    /* Fire another ray */
    if ((info.out_ray_type & RAY_REFLECT) || (info.out_ray_type & RAY_TRANSMIT)) {

	struct application new_ap;
	RT_APPLICATION_INIT(&new_ap);

	new_ap = *ap;                     /* struct copy */
	new_ap.a_onehit = 1;
	new_ap.a_hit = default_a_hit;
	new_ap.a_level = info.depth + 1;
	new_ap.a_flag = 0;

	VMOVE(new_ap.a_ray.r_dir, info.out_ray.dir);
	VMOVE(new_ap.a_ray.r_pt, info.out_ray.origin);

	/* This next ray represents refraction */
	if (info.out_ray_type & RAY_TRANSMIT) {

	    /* Displace the hit point a little bit in the direction
	       of the next ray */
	    Vec3 tmp;
	    VSCALE(tmp, info.out_ray.dir, 1e-4);
	    VADD2(new_ap.a_ray.r_pt, new_ap.a_ray.r_pt, tmp);

	    new_ap.a_onehit = 1;
	    new_ap.a_refrac_index = 1.5;
	    new_ap.a_flag = 2; /* mark as refraction */
	    new_ap.a_hit = osl_refraction_hit;
	}

	(void)rt_shootray(&new_ap);

	Color3 rec;
	VMOVE(rec, new_ap.a_color);

	Color3 res = rec*weight;

	VMOVE(swp->sw_color, res);
    }
    else {
	/* Final color */
	VMOVE(swp->sw_color, weight);
    }

    return 1;
}
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 */
int
gauss_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)


/* defined in material.h */
/* ptr to the shader-specific struct */
{
    register struct gauss_specific *gauss_sp =
	(struct gauss_specific *)dp;
    struct seg *seg_p;
    struct reg_db_internals *dbint_p;
    double optical_density = 0.0;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_gauss_SP(gauss_sp);

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print("gauss_render Parameters:", gauss_print_tab, (char *)gauss_sp);

	bu_log("r_pt(%g %g %g) r_dir(%g %g %g)\n",
	       V3ARGS(ap->a_ray.r_pt),
	       V3ARGS(ap->a_ray.r_dir));
    }

    BU_CK_LIST_HEAD(&swp->sw_segs->l);
    BU_CK_LIST_HEAD(&gauss_sp->dbil);


    /* look at each segment that participated in the ray partition(s) */
    for (BU_LIST_FOR(seg_p, seg, &swp->sw_segs->l)) {

	if (rdebug&RDEBUG_SHADE) {
	    bu_log("seg %g -> %g\n",
		   seg_p->seg_in.hit_dist,
		   seg_p->seg_out.hit_dist);
	}
	RT_CK_SEG(seg_p);
	RT_CK_SOLTAB(seg_p->seg_stp);

	/* check to see if the seg/solid is in this partition */
	if (bu_ptbl_locate(&pp->pt_seglist, (long *)seg_p) != -1) {

	    /* XXX You might use a bu_ptbl list of the solid pointers... */
	    /* check to see if the solid is from this region */
	    for (BU_LIST_FOR(dbint_p, reg_db_internals,
			     &gauss_sp->dbil)) {

		CK_DBINT(dbint_p);

		if (dbint_p->st_p == seg_p->seg_stp) {
		    /* The solid from the region is
		     * the solid from the segment
		     * from the partition
		     */
		    optical_density +=
			eval_seg(ap, dbint_p, seg_p);
		    break;
		}
	    }
	} else {
	    if (rdebug&RDEBUG_SHADE)
		bu_log("gauss_render() bittest failed\n");
	}
    }
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 *
 * dp is a pointer to the shader-specific struct
 */
int
bbd_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct bbd_specific *bbd_sp = (struct bbd_specific *)dp;
    union tree *tp;
    struct bbd_img *bi;
    struct imgdist id[MAX_IMAGES];
    size_t i;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_bbd_SP(bbd_sp);

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print("bbd_render Parameters:",
			bbd_print_tab, (char *)bbd_sp);
	bu_log("pixel %d %d\n", ap->a_x, ap->a_y);
	bu_log("bbd region: %s\n", pp->pt_regionp->reg_name);
    }
    tp = pp->pt_regionp->reg_treetop;
    if (tp->tr_a.tu_op != OP_SOLID) {
	bu_log("%s:%d region %s rendering bbd should have found OP_SOLID, not %d\n",
	       __FILE__, __LINE__, pp->pt_regionp->reg_name, tp->tr_a.tu_op);
	bu_bomb("\n");
    }


    swp->sw_transmit = 1.0;
    VSETALL(swp->sw_color, 0.0);
    VSETALL(swp->sw_basecolor, 1.0);

    i = 0;
    for (BU_LIST_FOR(bi, bbd_img, &bbd_sp->imgs)) {
	/* find out if the ray hits the plane */
	id[i].index = i;
	id[i].bi = bi;
	id[i].status = bn_isect_line3_plane(&id[i].dist,
					    ap->a_ray.r_pt, ap->a_ray.r_dir,
					    bi->img_plane, &ap->a_rt_i->rti_tol);
	i++;
    }

    bu_sort(id, bbd_sp->img_count, sizeof(id[0]), &imgdist_compare, NULL);

    for (i = 0; i < bbd_sp->img_count && swp->sw_transmit > 0.0; i++) {
	if (id[i].status > 0) do_ray_image(ap, pp, swp, bbd_sp, id[i].bi, id[i].dist);
    }
    if (rdebug&RDEBUG_SHADE) {
	bu_log("color %g %g %g\n", V3ARGS(swp->sw_color));
    }
    /* shader must perform transmission/reflection calculations
     *
     * 0 < swp->sw_transmit <= 1 causes transmission computations
     * 0 < swp->sw_reflect <= 1 causes reflection computations
     */
    if (swp->sw_reflect > 0 || swp->sw_transmit > 0) {
	int level = ap->a_level;
	ap->a_level = 0; /* Bogus hack to keep rr_render from giving up */
	(void)rr_render(ap, pp, swp);
	ap->a_level = level;
    }
    if (rdebug&RDEBUG_SHADE) {
	bu_log("color %g %g %g\n", V3ARGS(swp->sw_color));
    }
    return 1;
}
Example #14
0
/*
 * T R E E T H E R M _ R E N D E R
 *
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 */
int
tthrm_render(struct application *ap, const struct partition *pp, struct shadework *swp, genptr_t dp)


/* defined in material.h */
/* ptr to the shader-specific struct */
{
    register struct tthrm_specific *tthrm_sp =
	(struct tthrm_specific *)dp;
    struct rt_part_internal *part_p;

    point_t pt;
    vect_t pt_v;
    vect_t v;
    int solid_number;
    struct thrm_seg *thrm_seg;
    int best_idx;
    double best_val;
    double Vdot;
    int node;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_tthrm_SP(tthrm_sp);

    /* We are performing the shading in "region" space.  We must
     * transform the hit point from "model" space to "region" space.
     * See the call to db_region_mat in tthrm_setup().
     */
    MAT4X3PNT(pt, tthrm_sp->tthrm_m_to_sh, swp->sw_hit.hit_point);

    if (rdebug&RDEBUG_SHADE)
	bu_log("tthrm_render(%s, %g %g %g)\n", tthrm_sp->tt_name,
	       V3ARGS(pt));


    solid_number = get_solid_number(pp);

    if (solid_number > tthrm_sp->tt_max_seg) {
	bu_log("%s:%d solid name %s has solid number higher than %ld\n",
	       __FILE__, __LINE__, tthrm_sp->tt_max_seg);
	bu_bomb("Choke! ack! gasp! wheeeeeeze.\n");
    }

    thrm_seg = &tthrm_sp->tt_segs[solid_number];
    CK_THRM_SEG(thrm_seg);


    /* Extract the solid parameters for the particle we hit,
     * Compare them to the values for the node extracted.  If they
     * don't match, then we probably have a mis-match between the
     * geometry and the treetherm output files.
     */
    if (pp->pt_inseg->seg_stp->st_id != ID_PARTICLE) {
	bu_log("%d != ID_PART\n", pp->pt_inseg->seg_stp->st_id);
	bu_bomb("");
    }
    part_p = (struct rt_part_internal *)pp->pt_inseg->seg_stp->st_specific;
    RT_PART_CK_MAGIC(part_p);
    VSUB2(v, part_p->part_V, thrm_seg->pt);
    if (MAGSQ(v) > 100.0) {
	double dist;
	dist = MAGNITUDE(v);
	/* Distance between particle origin and centroid of thermal
	 * segment nodes is > 10.0mm (1cm).  This suggests that
	 * they aren't related.
	 */
	bu_log(
	    "----------------------------- W A R N I N G -----------------------------\n\
%s:%d distance %g between origin of particle and thermal node centroid is\n\
too large.  Probable mis-match between geometry and thermal data\n",
	    __FILE__, __LINE__, dist);
	bu_bomb("");
    }