예제 #1
0
파일: sh_brdf.c 프로젝트: cciechad/brlcad
/*
 *			B R D F _ R E N D E R
 *
 Color pixel based on the energy of a point light source (Eps)
 plus some diffuse illumination (Epd) reflected from the point
 <x, y> :

 E = Epd + Eps		(1)

 The energy reflected from diffuse illumination is the product
 of the reflectance coefficient at point P (Rp) and the diffuse
 illumination (Id) :

 Epd = Rp * Id		(2)

 The energy reflected from the point light source is calculated
 by the sum of the diffuse reflectance (Rd) and the specular
 reflectance (Rs), multiplied by the intensity of the light
 source (Ips) :

 Eps = (Rd + Rs) * Ips	(3)

 The diffuse reflectance is calculated by the product of the
 reflectance coefficient (Rp) and the cosine of the angle of
 incidence (I) and normalized by PI :

 Rd = Rp * cos(I) / PI	(4)

 The specular reflectance is calculated by the product of the
 specular reflectance coeffient and a term dependent on the
 surface roughness :

 Rs = W(I, O) * R(I, O, r)	(5)

 Where,
 I is the angle of incidence.
 O is the angle to the observer.
 r is the standard deviation (RMS) of the surface slope.
 W returns the specular reflection coefficient as a function
 of the angle of incidence, and the viewer angle.
 R is a surface roughness term.

*/
HIDDEN int
brdf_render(register struct application *ap, struct partition *pp, struct shadework *swp, char *dp)
{
    register struct light_specific *lp;
    register fastf_t *intensity, *to_light;
    register int	i;
    register fastf_t cosi, cosr;
    register fastf_t refl;
    vect_t h_dir;
    vect_t to_eye;
    vect_t	work;
    vect_t	cprod;			/* color product */
    point_t	matcolor;		/* Material color */
    struct brdf_specific *ps =
	(struct brdf_specific *)dp;

    if (ps->magic != BRDF_MAGIC )  bu_log("brdf_render: bad magic\n");

    if (rdebug&RDEBUG_SHADE)
	bu_struct_print( "brdf_render", brdf_parse, (char *)ps );

    swp->sw_transmit = ps->transmit;
    swp->sw_reflect = ps->reflect;
    swp->sw_refrac_index = ps->refrac_index;
    swp->sw_extinction = ps->extinction;
    if (swp->sw_xmitonly ) {
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0 )
	    (void)rr_render( ap, pp, swp );
	return(1);	/* done */
    }

    VMOVE( matcolor, swp->sw_color );

    /* Diffuse reflectance from "Ambient" light source (at eye) */
    if ((cosr = -VDOT( swp->sw_hit.hit_normal, ap->a_ray.r_dir )) > 0.0 )  {
	if (cosr > 1.00001 )  {
	    bu_log("cosAmb=1+%g (x%d, y%d, lvl%d)\n", cosr-1,
		   ap->a_x, ap->a_y, ap->a_level);
	    cosr = 1;
	}
	refl = cosr * AmbientIntensity;
	VSCALE( swp->sw_color, matcolor, refl );
    } else {
	VSETALL( swp->sw_color, 0 );
    }

    VREVERSE( to_eye, ap->a_ray.r_dir );

    /* Consider effects of each light source */
    for ( i=ap->a_rt_i->rti_nlights-1; i>=0; i-- )  {
	fastf_t cos_tmp;
	fastf_t tan_sq;
	double exponent;

	if ((lp = (struct light_specific *)swp->sw_visible[i]) == LIGHT_NULL )
	    continue;

	/* Light is not shadowed -- add this contribution */
	intensity = swp->sw_intensity+3*i;
	to_light = swp->sw_tolight+3*i;

	if ((cosi = VDOT( swp->sw_hit.hit_normal, to_light )) > 0.0 )  {
	    if (cosi > 1.00001 )  {
		bu_log("cosI=1+%g (x%d, y%d, lvl%d)\n", cosi-1,
		       ap->a_x, ap->a_y, ap->a_level);
		cosi = 1;
	    }

	    /* Diffuse reflectance from this light source. */
	    refl = cosi * lp->lt_fraction * ps->diffuse_refl;
	    VELMUL( work, lp->lt_color,
		    intensity );
	    VELMUL( cprod, matcolor, work );
	    VJOIN1( swp->sw_color, swp->sw_color,
		    refl, cprod );

	    /* Calculate specular reflectance. */
	    if (NEAR_ZERO( ps->rms_sq, SMALL_FASTF ) )
		continue;
	    VADD2( h_dir, to_eye, to_light )
		VUNITIZE( h_dir );
	    cos_tmp = VDOT( h_dir, swp->sw_hit.hit_normal );
	    if (cos_tmp <= 0.0 )
		continue;
	    cos_tmp *= cos_tmp;
	    if (NEAR_ZERO( cos_tmp, SMALL_FASTF ) )
		continue;

	    tan_sq = (1.0-cos_tmp)/cos_tmp;
	    exponent = (-tan_sq/ps->rms_sq );
	    refl = ps->specular_refl * lp->lt_fraction * exp( exponent ) /
		sqrt( cosi * cosr ) / ps->denom;
	    if (refl > 1.0 )
		refl = 1.0;

	    VELMUL( work, lp->lt_color, intensity );
	    VJOIN1( swp->sw_color, swp->sw_color, refl, work );

	}
    }

    if (swp->sw_reflect > 0 || swp->sw_transmit > 0 )
	(void)rr_render( ap, pp, swp );
    return(1);
}
예제 #2
0
파일: solid.c 프로젝트: cciechad/brlcad
int
read_arbn(char *name)
{
    int	npt;			/* # vertex pts to be read in */
    int	npe;			/* # planes from 3 vertex points */
    int	neq;			/* # planes from equation */
    int	nae;			/* # planes from az, el & vertex index */
    int	nface;			/* total number of faces */
    double	*input_points = (double *)0;
    double	*vertex = (double *)0;	/* vertex list of final solid */
    int	last_vertex;		/* index of first unused vertex */
    int	max_vertex;		/* size of vertex array */
    int	*used = (int *)0;	/* plane eqn use count */
    plane_t	*eqn = (plane_t *)0;	/* plane equations */
    int	cur_eq = 0;		/* current (free) equation number */
    int	symm = 0;		/* symmetry about Y used */
    register int	i;
    int	j;
    int	k;
    register int	m;
    point_t	cent;			/* centroid of arbn */
    struct bn_tol	tol;

    /* XXX The tolerance here is sheer guesswork */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.005;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    npt = getint( scard, 10+0*10, 10 );
    npe = getint( scard, 10+1*10, 10 );
    neq = getint( scard, 10+2*10, 10 );
    nae = getint( scard, 10+3*10, 10 );

    nface = npe + neq + nae;
    if ( npt < 1 )  {
        /* Having one point is necessary to compute centroid */
        printf("arbn defined without at least one point\n");
bad:
        if (npt>0) eat( (npt+1)/2 );	/* vertex input_points */
        if (npe>0) eat( (npe+5)/6 );	/* vertex pt index numbers */
        if (neq>0) eat( neq );		/* plane eqns? */
        if (nae>0) eat( (nae+1)/2 );	/* az el & vertex index? */
        return(-1);
    }

    /* Allocate storage for plane equations */
    eqn = (plane_t *)bu_malloc(nface*sizeof(plane_t), "eqn");

    /* Allocate storage for per-plane use count */
    used = (int *)bu_malloc(nface*sizeof(int), "used");

    if ( npt >= 1 )  {
        /* Obtain vertex input_points */
        input_points = (double *)bu_malloc(npt*3*sizeof(double), "input_points");

        if ( getxsoldata( input_points, npt*3, sol_work ) < 0 )
            goto bad;
    }

    /* Get planes defined by three points, 6 per card */
    for ( i=0; i<npe; i += 6 )  {
        if ( get_line( scard, sizeof(scard), "arbn vertex point indices" ) == EOF )  {
            printf("too few cards for arbn %d\n",
                   sol_work);
            return(-1);
        }
        for ( j=0; j<6; j++ )  {
            int	q, r, s;
            point_t	a, b, c;

            q = getint( scard, 10+j*10+0, 4 );
            r = getint( scard, 10+j*10+4, 3 );
            s = getint( scard, 10+j*10+7, 3 );

            if ( q == 0 || r == 0 || s == 0 ) continue;

            if ( q < 0 )  {
                VMOVE( a, &input_points[((-q)-1)*3] );
                a[Y] = -a[Y];
                symm = 1;
            } else {
                VMOVE( a, &input_points[((q)-1)*3] );
            }

            if ( r < 0 )  {
                VMOVE( b, &input_points[((-r)-1)*3] );
                b[Y] = -b[Y];
                symm = 1;
            } else {
                VMOVE( b, &input_points[((r)-1)*3] );
            }

            if ( s < 0 )  {
                VMOVE( c, &input_points[((-s)-1)*3] );
                c[Y] = -c[Y];
                symm = 1;
            } else {
                VMOVE( c, &input_points[((s)-1)*3] );
            }
            if ( bn_mk_plane_3pts( eqn[cur_eq], a, b, c, &tol ) < 0 )  {
                printf("arbn degenerate plane\n");
                VPRINT("a", a);
                VPRINT("b", b);
                VPRINT("c", c);
                continue;
            }
            cur_eq++;
        }
    }

    /* Get planes defined by their equation */
    for ( i=0; i < neq; i++ )  {
        register double	scale;
        if ( get_line( scard, sizeof(scard), "arbn plane equation card" ) == EOF )  {
            printf("too few cards for arbn %d\n",
                   sol_work);
            return(-1);
        }
        eqn[cur_eq][0] = getdouble( scard, 10+0*10, 10 );
        eqn[cur_eq][1] = getdouble( scard, 10+1*10, 10 );
        eqn[cur_eq][2] = getdouble( scard, 10+2*10, 10 );
        eqn[cur_eq][3] = getdouble( scard, 10+3*10, 10 );
        scale = MAGNITUDE(eqn[cur_eq]);
        if ( scale < SMALL )  {
            printf("arbn plane normal too small\n");
            continue;
        }
        scale = 1/scale;
        VSCALE( eqn[cur_eq], eqn[cur_eq], scale );
        eqn[cur_eq][3] *= scale;
        cur_eq++;
    }

    /* Get planes defined by azimuth, elevation, and pt, 2 per card */
    for ( i=0; i < nae;  i += 2 )  {
        if ( get_line( scard, sizeof(scard), "arbn az/el card" ) == EOF )  {
            printf("too few cards for arbn %d\n",
                   sol_work);
            return(-1);
        }
        for ( j=0; j<2; j++ )  {
            double	az, el;
            int	vert_no;
            double	cos_el;
            point_t	pt;

            az = getdouble( scard, 10+j*30+0*10, 10 ) * bn_degtorad;
            el = getdouble( scard, 10+j*30+1*10, 10 ) * bn_degtorad;
            vert_no = getint( scard, 10+j*30+2*10, 10 );
            if ( vert_no == 0 )  break;
            cos_el = cos(el);
            eqn[cur_eq][X] = cos(az)*cos_el;
            eqn[cur_eq][Y] = sin(az)*cos_el;
            eqn[cur_eq][Z] = sin(el);

            if ( vert_no < 0 )  {
                VMOVE( pt, &input_points[((-vert_no)-1)*3] );
                pt[Y] = -pt[Y];
            } else {
                VMOVE( pt, &input_points[((vert_no)-1)*3] );
            }
            eqn[cur_eq][3] = VDOT(pt, eqn[cur_eq]);
            cur_eq++;
        }
    }
    if ( nface != cur_eq )  {
        printf("arbn expected %d faces, got %d\n", nface, cur_eq);
        return(-1);
    }

    /* Average all given points together to find centroid */
    /* This is why there must be at least one (two?) point given */
    VSETALL(cent, 0);
    for ( i=0; i<npt; i++ )  {
        VADD2( cent, cent, &input_points[i*3] );
    }
    VSCALE( cent, cent, 1.0/npt );
    if ( symm )  cent[Y] = 0;

    /* Point normals away from centroid */
    for ( i=0; i<nface; i++ )  {
        double	dist;

        dist = VDOT( eqn[i], cent ) - eqn[i][3];
        /* If dist is negative, 'cent' is inside halfspace */
#define DIST_TOL	(1.0e-8)
#define DIST_TOL_SQ	(1.0e-10)
        if ( dist < -DIST_TOL )  continue;
        if ( dist > DIST_TOL )  {
            /* Flip halfspace over */
            VREVERSE( eqn[i], eqn[i] );
            eqn[i][3] = -eqn[i][3];
        } else {
            /* Centroid lies on this face */
            printf("arbn centroid lies on face\n");
            return(-1);
        }

    }

    /* Release storage for input points */
    bu_free( (char *)input_points, "input_points" );
    input_points = (double *)0;


    /*
     *  ARBN must be convex.  Test for concavity.
     *  Byproduct is an enumeration of all the verticies.
     */
    last_vertex = max_vertex = 0;

    /* Zero face use counts */
    for ( i=0; i<nface; i++ )  {
        used[i] = 0;
    }
    for ( i=0; i<nface-2; i++ )  {
        for ( j=i+1; j<nface-1; j++ )  {
            double	dot;
            int	point_count;	/* # points on this line */

            /* If normals are parallel, no intersection */
            dot = VDOT( eqn[i], eqn[j] );
            if ( !NEAR_ZERO( dot, 0.999999 ) )  continue;

            point_count = 0;
            for ( k=j+1; k<nface; k++ )  {
                point_t	pt;

                if ( bn_mkpoint_3planes( pt, eqn[i], eqn[j], eqn[k] ) < 0 )  continue;

                /* See if point is outside arb */
                for ( m=0; m<nface; m++ )  {
                    if ( i==m || j==m || k==m )  continue;
                    if ( VDOT(pt, eqn[m])-eqn[m][3] > DIST_TOL )
                        goto next_k;
                }
                /* See if vertex already was found */
                for ( m=0; m<last_vertex; m++ )  {
                    vect_t	dist;
                    VSUB2( dist, pt, &vertex[m*3] );
                    if ( MAGSQ(dist) < DIST_TOL_SQ )
                        goto next_k;
                }

                /*
                 *  Add point to vertex array.
                 *  If more room needed, realloc.
                 */
                if ( last_vertex >= max_vertex )  {
                    if ( max_vertex == 0 )   {
                        max_vertex = 3;
                        vertex = (double *)bu_malloc( max_vertex*3*sizeof(double), "vertex" );
                    } else {
                        max_vertex *= 10;
                        vertex = (double *)bu_realloc( (char *)vertex, max_vertex*3*sizeof(double), "vertex" );
                    }
                }

                VMOVE( &vertex[last_vertex*3], pt );
                last_vertex++;
                point_count++;

                /* Increment "face used" counts */
                used[i]++;
                used[j]++;
                used[k]++;
next_k:
                ;
            }
            if ( point_count > 2 )  {
                printf("arbn: warning, point_count on line=%d\n", point_count);
            }
        }
    }

    /* If any planes were not used, then arbn is not convex */
    for ( i=0; i<nface; i++ )  {
        if ( used[i] != 0 )  continue;	/* face was used */
        printf("arbn face %d unused, solid is not convex\n", i);
        return(-1);
    }

    /* Write out the solid ! */
    i = mk_arbn( outfp, name, nface, eqn );

    if ( input_points )  bu_free( (char *)input_points, "input_points" );
    if ( vertex )  bu_free( (char *)vertex, "vertex" );
    if ( eqn )  bu_free( (char *)eqn, "eqn" );
    if ( used )  bu_free( (char *)used, "used" );

    return(i);
}
/*
 * 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;
}
예제 #4
0
파일: metaball.c 프로젝트: cogitokat/brlcad
/* compute the bounding sphere for a metaball cluster. center is
 * filled, and the radius is returned.
 */
fastf_t
rt_metaball_get_bounding_sphere(point_t *center, fastf_t threshold, struct rt_metaball_internal *mb)
{
    struct wdb_metaballpt *mbpt, *mbpt2;
    point_t min, max, d;
    fastf_t r = 0.0, dist, mag;
    int i;
    struct bu_list *points;

    points = &mb->metaball_ctrl_head;

    /* find a bounding box for the POINTS (NOT the surface) */
    VSETALL(min, +INFINITY);
    VSETALL(max, -INFINITY);
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, points))
	for (i=0;i<3;i++) {
	    if (mbpt->coord[i] < min[i])
		min[i] = mbpt->coord[i];
	    if (mbpt->coord[i] > max[i])
		max[i] = mbpt->coord[i];
	}
    /* return -1 if no points are defined. */
    if (ZERO(min[X] - INFINITY) || min[X] > INFINITY)
	return -1;

    /* compute the center of the generated box, call that the center */
    VADD2(*center, min, max);
    VSCALE(*center, *center, 0.5);

    /* start looking for the radius... */
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, points)) {
	VSUB2(d, mbpt->coord, *center);
	/* since the surface is where threshold=fldstr/mag,
	   mag=fldstr/threshold, so make that the initial value */
	dist = MAGNITUDE(d) + mbpt->fldstr/threshold;
	/* and add all the contribution */
	for (BU_LIST_FOR(mbpt2, wdb_metaballpt, points))
	    if (mbpt2 != mbpt) {
		fastf_t additive = 0.0;
		VSUB2(d, mbpt2->coord, mbpt->coord);
		mag = MAGNITUDE(d) + dist;

		switch(mb->method) {
		    case METABALL_METABALL:
			break;
		    case METABALL_ISOPOTENTIAL:
			additive = fabs(mbpt2->fldstr) * mbpt2->fldstr / mag;
			break;
		    case METABALL_BLOB:
			additive = 1.0/exp((mbpt2->sweat / (mbpt2->fldstr * mbpt2->fldstr)) * mag * mag - mbpt2->sweat);
			break;
		}

		dist += additive;
	    }
	/* then see if this is a 'defining' point */
	if (dist > r)
	    r = dist;
    }
    return r;
}
예제 #5
0
파일: refract.c 프로젝트: cogitokat/brlcad
/*
 * R R _ H I T
 *
 * This routine is called when an internal reflection ray hits something
 * (which is ordinarily the case).
 *
 * Generally, there will be one or two partitions on the hit list.
 * The values for pt_outhit for the second partition should not be used,
 * as a_onehit was set to 3, getting a maximum of 3 valid hit points.
 *
 * Explicit Returns -
 * 0 dreadful internal error
 * 1 treat as escaping ray & reshoot
 * 2 Proper exit point determined, with Implicit Returns:
 *	a_uvec		exit Point
 *	a_vvec		exit Normal (inward pointing)
 *	a_refrac_index	RI of *next* material
 */
HIDDEN int
rr_hit(struct application *ap, struct partition *PartHeadp, struct seg *UNUSED(segp))
{
    register struct partition *pp;
    register struct hit *hitp;
    register struct soltab *stp;
    struct partition *psave = (struct partition *)NULL;
    struct shadework sw;
    struct application appl;
    int ret;

    RT_AP_CHECK(ap);

    RT_APPLICATION_INIT(&appl);

    for (pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw)
	if (pp->pt_outhit->hit_dist > 0.0) break;
    if (pp == PartHeadp) {
	if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) {
	    bu_log("rr_hit:  %d, %d no hit out front?\n",
		   ap->a_x, ap->a_y);
	    ret = 0;	/* error */
	    goto out;
	}
	ret = 1;		/* treat as escaping ray */
	goto out;
    }

    /*
     * Ensure that the partition we are given is part of the same
     * region that we started in.  When the internal reflection
     * is happening very near an edge or corner, this is not always
     * the case, and either (a) a small sliver of some other region
     * is found to be in the way, or (b) the ray completely misses the
     * region that it started in, although not by much.
     */
    psave = pp;
    if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_hit(%s)\n", psave->pt_regionp->reg_name);
    for (; pp != PartHeadp; pp = pp->pt_forw)
	if (pp->pt_regionp == (struct region *)(ap->a_uptr)) break;
    if (pp == PartHeadp) {
	if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) {
	    bu_log("rr_hit:  %d, %d Ray internal to %s landed unexpectedly in %s\n",
		   ap->a_x, ap->a_y,
		   ((struct region *)(ap->a_uptr))->reg_name,
		   psave->pt_regionp->reg_name);
	    ret = 0;	/* error */
	    goto out;
	}
	ret = 1;		/* treat as escaping ray */
	goto out;
    }

    /*
     * At one time, this was a check for pp->pt_inhit->hit_dist
     * being NEAR zero.  That was a mistake, because we may have
     * been at the edge of a subtracted out center piece when
     * internal reflection happened, except that floating point
     * error (being right on the surface of the interior solid)
     * prevented us from "seeing" that solid on the next ray,
     * causing our ray endpoints to be quite far from the starting
     * point, yet with the ray still validly inside the glass region.
     *
     * There is a major problem if the entry point
     * is further ahead than the firing point, i.e., >0.
     *
     * Because this error has not yet been encountered, it is
     * considered dreadful.  Some recovery may be possible.
     *
     * For now, this seems to happen when a reflected ray starts outside
     * the glass and doesn't even intersect the glass, so treat it as
     * an escaping ray.
     */

    if (pp->pt_inhit->hit_dist > 10) {
	stp = pp->pt_inseg->seg_stp;
	if (R_DEBUG&RDEBUG_REFRACT)
	    bu_log("rr_hit: %d, %d %s inhit %g > 10.0! (treating as escaping ray)\n",
		   ap->a_x, ap->a_y,
		   pp->pt_regionp->reg_name,
		   pp->pt_inhit->hit_dist);
	ret = 1;	/* treat as escaping ray */
	goto out;
    }

    /*
     * If there is a very small crack in the glass, perhaps formed
     * by a small error when taking the Union of two solids,
     * attempt to find the real exit point.
     * NOTE that this is usually taken care of inside librt
     * in the bool_weave code, but it is inexpensive to check for it
     * here.  If this case is detected, push on, and log it.
     * This code is not expected to be needed.
     */
    while (pp->pt_forw != PartHeadp) {
	register fastf_t d;
	d = pp->pt_forw->pt_inhit->hit_dist - pp->pt_outhit->hit_dist;
	if (!NEAR_ZERO(d, AIR_GAP_TOL))
	    break;
	if (pp->pt_forw->pt_regionp != pp->pt_regionp)
	    break;
	if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) bu_log(
	    "rr_hit: %d, %d fusing small crack in glass %s\n",
	    ap->a_x, ap->a_y,
	    pp->pt_regionp->reg_name);
	pp = pp->pt_forw;
    }

    hitp = pp->pt_outhit;
    stp = pp->pt_outseg->seg_stp;
    if (hitp->hit_dist >= INFINITY) {
	bu_log("rr_hit: %d, %d infinite glass (%g, %g) %s\n",
	       ap->a_x, ap->a_y,
	       pp->pt_inhit->hit_dist, hitp->hit_dist,
	       pp->pt_regionp->reg_name);
	ret = 0;		/* dreadful error */
	goto out;
    }
    VJOIN1(hitp->hit_point, ap->a_ray.r_pt,
	   hitp->hit_dist, ap->a_ray.r_dir);
    RT_HIT_NORMAL(ap->a_vvec, hitp, stp, &(ap->a_ray), pp->pt_outflip);

    /* For refraction, want exit normal to point inward. */
    VREVERSE(ap->a_vvec, ap->a_vvec);
    VMOVE(ap->a_uvec, hitp->hit_point);
    ap->a_cumlen += (hitp->hit_dist - pp->pt_inhit->hit_dist);

    ap->a_refrac_index = RI_AIR;			/* Default medium: air */

    /*
     * Look ahead, and see if there is more glass to come.
     * If so, obtain its refractive index, to enable correct
     * calculation of the departing refraction angle.
     */
    if (pp->pt_forw != PartHeadp) {
	register fastf_t d;
	d = pp->pt_forw->pt_inhit->hit_dist - hitp->hit_dist;
	if (NEAR_ZERO(d, AIR_GAP_TOL)) {
	    /*
	     * Make a private copy of the application struct,
	     * because viewshade() may change various fields.
	     */
	    appl = *ap;			/* struct copy */

	    memset((char *)&sw, 0, sizeof(sw));
	    sw.sw_transmit = sw.sw_reflect = 0.0;

	    /* Set default in case shader doesn't fill this in. */
	    sw.sw_refrac_index = RI_AIR;

	    /* Set special flag so that we get only shader
	     * parameters (refractive index, in this case).
	     * We don't even care about transmitted energy.
	     */
	    sw.sw_xmitonly = 2;
	    sw.sw_inputs = 0;		/* no fields filled yet */
#ifdef RT_MULTISPECTRAL
	    sw.msw_color = bn_tabdata_get_constval(1.0, spectrum);
	    sw.msw_basecolor = bn_tabdata_get_constval(1.0, spectrum);
#else
	    VSETALL(sw.sw_color, 1);
	    VSETALL(sw.sw_basecolor, 1);
#endif

	    if (R_DEBUG&(RDEBUG_SHADE|RDEBUG_REFRACT))
		bu_log("rr_hit calling viewshade to discover refractive index\n");

	    (void)viewshade(&appl, pp->pt_forw, &sw);

#ifdef RT_MULTISPECTRAL
	    bu_free(sw.msw_color, "sw.msw_color");
	    bu_free(sw.msw_basecolor, "sw.msw_basecolor");
#endif

	    if (R_DEBUG&(RDEBUG_SHADE|RDEBUG_REFRACT))
		bu_log("rr_hit refractive index = %g\n", sw.sw_refrac_index);

	    if (sw.sw_transmit > 0) {
		ap->a_refrac_index = sw.sw_refrac_index;
		if (R_DEBUG&RDEBUG_SHADE) {
		    bu_log("rr_hit a_refrac_index=%g (trans=%g)\n",
			   ap->a_refrac_index,
			   sw.sw_transmit);
		}
		ret= 3;	/* OK -- more glass follows */
		goto out;
	    }
	}
    }
    ret = 2;				/* OK -- no more glass */
out:
    if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_hit(%s) return=%d\n",
				       psave ? psave->pt_regionp->reg_name : "",
				       ret);
    return ret;
}
/*
 * Handle ray interaction with 1 image
 */
static void
do_ray_image(struct application *ap,
	     const struct partition *pp,
	     struct shadework *swp,	/* defined in ../h/shadework.h */
	     struct bbd_specific *bbd_sp,
	     struct bbd_img *bi,
	     double dist)
{
    double x, y, dx, dy, xlo, xhi, ylo, yhi;
    int u, v, ulo, uhi, vlo, vhi;
    unsigned char *pixels, *color;
    int val;
    static const double rgb255 = 1.0 / 256.0;
    vect_t cum_color;
    point_t pt;
    vect_t vpt;
    double radius;
    int tot;
    int color_count;
    double t, opacity;

    if (rdebug&RDEBUG_SHADE) {
	bu_log("do_ray_image\n");
	plot_ray_img(ap, pp, dist, bi);
    }

    VJOIN1(pt, ap->a_ray.r_pt, dist, ap->a_ray.r_dir); /* point on plane */
    VSUB2(vpt, pt, bi->img_origin);	/* vect: origin to pt */
    x = VDOT(vpt, bi->img_x);
    y = VDOT(vpt, bi->img_y);

    if (x < 0.0 || x > bi->img_xlen ||
	y < 0.0 || y > bi->img_ylen) {
	if (rdebug&RDEBUG_SHADE) {
	    bu_log("hit outside bounds, leaving color %g %g %g\n",
		   V3ARGS(swp->sw_color));
	}
	return;
    }


    /* get the radius of the beam at the image plane */
    radius = ap->a_rbeam + dist * ap->a_diverge;

    /*
      dx = radius * VDOT(ap->a_ray.r_dir, bi->img_x);
      dy = radius * VDOT(ap->a_ray.r_dir, bi->img_y);
    */
    dx = radius;
    dy = radius;


    xlo = x - dx;
    xhi = x + dx;

    ylo = y - dy;
    yhi = y + dy;

    CLAMP(xlo, 0.0, bi->img_xlen);
    CLAMP(xhi, 0.0, bi->img_xlen);

    CLAMP(ylo, 0.0, bi->img_ylen);
    CLAMP(yhi, 0.0, bi->img_ylen);

    vlo = (ylo / bi->img_ylen) * (bi->img_height -1);
    vhi = (yhi / bi->img_ylen) * (bi->img_height -1);

    ulo = (xlo / bi->img_xlen) * (bi->img_width -1);
    uhi = (xhi / bi->img_xlen) * (bi->img_width -1);

    if (ulo > uhi) { int i = ulo; ulo = uhi; uhi = i; }
    if (vlo > vhi) { int i = vlo; vlo = vhi; vhi = i; }

    pixels = (unsigned char*)bi->img_mf->buf;

    if (rdebug&RDEBUG_SHADE) {
	bu_log("u:%d..%d  v:%d..%d\n", ulo, uhi, vlo, vhi);
    }

    tot = (uhi - ulo + 1) * (vhi - vlo + 1); /* total # of pixels */
    color_count = 0; /* */
    VSETALL(cum_color, 0.0);
    for (v = vlo; v <= vhi; v++) {
	for (u = ulo; u <= uhi; u++) {
	    color = &pixels[v*bi->img_width*3 + u*3];
	    val = color[0]+color[1]+color[2];
	    if (val > bbd_sp->img_threshold) {
		color_count++;
		VJOIN1(cum_color, cum_color, rgb255, color);
		if (rdebug&RDEBUG_SHADE) {
		    bu_log("%d %d %d\n", V3ARGS(color));
		    VPRINT("cum_color", cum_color);
		}
	    }
	}
    }
    if (rdebug&RDEBUG_SHADE)
	bu_log("tot:%d color_count: %d\n", tot, color_count);

    if (color_count == 0) {
	if (rdebug&RDEBUG_SHADE)
	    bu_log("no color contribution, leaving color as %g %g %g\n",
		   V3ARGS(swp->sw_color));
	return;
    }
    /* get average color: scale color by the # of contributions */
    t = 1.0 / (double)color_count;
    VSCALE(cum_color, cum_color, t);
    if (rdebug&RDEBUG_SHADE) {
	int c[3];

	VSCALE(c, cum_color, 256);
	bu_log("average color: %d %d %d\n", V3ARGS(c));
    }

    /* compute residual transmission */
    opacity = ((double)color_count / tot); /* opacity */

    t = swp->sw_transmit*opacity;
    VJOIN1(swp->sw_color, swp->sw_color, t, cum_color);

    swp->sw_transmit -= opacity;
    if (swp->sw_transmit < 0.0) swp->sw_transmit = 0.0;


}
예제 #7
0
파일: g-x3d.c 프로젝트: kanzure/brlcad
void
nmg_2_vrml(FILE *fp, const struct db_full_path *pathp, struct model *m, struct mater_info *mater)
{
    struct nmgregion *reg;
    struct bu_ptbl verts;
    struct vrml_mat mat;
    struct bu_vls vls = BU_VLS_INIT_ZERO;
    char *tok;
    int i;
    int first=1;
    int is_light=0;
    float r, g, b;
    point_t ave_pt;
    char *full_path;
    /*There may be a better way to capture the region_id, than getting the rt_comb_internal structure,
     * (and may be a better way to capture the rt_comb_internal struct), but for now I just copied the
     * method used in select_lights/select_non_lights above, could have used a global variable but I noticed
     * none other were used, so I didn't want to be the first
     */
    struct directory *dp;
    struct rt_db_internal intern;
    struct rt_comb_internal *comb;
    int id;

    NMG_CK_MODEL( m );

    BARRIER_CHECK;

    full_path = db_path_to_string( pathp );

    /* replace all occurrences of '.' with '_' */
    char_replace(full_path, '.', '_');

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

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

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

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

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

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

    if ( mater->ma_shader )
    {
	tok = strtok( mater->ma_shader, tok_sep );
	bu_strlcpy( mat.shader, tok, TXT_NAME_SIZE );
    }
    else
	mat.shader[0] = '\0';
    mat.shininess = -1;
    mat.transparency = -1.0;
    mat.lt_fraction = -1.0;
    VSETALL( mat.lt_dir, 0.0 );
    mat.lt_angle = -1.0;
    mat.tx_file[0] = '\0';
    mat.tx_w = -1;
    mat.tx_n = -1;

    bu_vls_strcpy( &vls, &mater->ma_shader[strlen(mat.shader)] );
    (void)bu_struct_parse( &vls, vrml_mat_parse, (char *)&mat );

    if ( bu_strncmp( "light", mat.shader, 5 ) == 0 )
    {
	/* this is a light source */
	is_light = 1;
    }
    else
    {
	fprintf( fp, "\t<Shape DEF=\"%s\">\n", full_path);
	fprintf( fp, "\t\t<Appearance>\n");

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

	    fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0);
	}
	else if ( bu_strncmp( "glass", mat.shader, 5 ) == 0 )
	{
	    if ( mat.shininess < 0 )
		mat.shininess = 4;
	    if ( mat.transparency < 0.0 )
		mat.transparency = 0.8;

	    fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\" shininess=\"%g\" transparency=\"%g\" specularColor=\"%g %g %g\"/>\n", r, g, b, 1.0-exp(-(double)mat.shininess/20.0), mat.transparency, 1.0, 1.0, 1.0);
	}
	else if ( mater->ma_color_valid )
	{
	    fprintf( fp, "\t\t\t<Material diffuseColor=\"%g %g %g\"/>\n", r, g, b);
	}
	else
	{
	    /* If no color was defined set the colors according to the thousands groups */
	    int thou = comb->region_id/1000;
	    thou == 0 ? fprintf( fp, "\t\t\t<Material USE=\"Material_999\"/>\n")
		: thou == 1 ? fprintf( fp, "\t\t\t<Material USE=\"Material_1999\"/>\n")
		: thou == 2 ? fprintf( fp, "\t\t\t<Material USE=\"Material_2999\"/>\n")
		: thou == 3 ? fprintf( fp, "\t\t\t<Material USE=\"Material_3999\"/>\n")
		: thou == 4 ? fprintf( fp, "\t\t\t<Material USE=\"Material_4999\"/>\n")
		: thou == 5 ? fprintf( fp, "\t\t\t<Material USE=\"Material_5999\"/>\n")
		: thou == 6 ? fprintf( fp, "\t\t\t<Material USE=\"Material_6999\"/>\n")
		: thou == 7 ? fprintf( fp, "\t\t\t<Material USE=\"Material_7999\"/>\n")
		: thou == 8 ? fprintf( fp, "\t\t\t<Material USE=\"Material_8999\"/>\n")
		: fprintf( fp, "\t\t\t<Material USE=\"Material_9999\"/>\n");
	}
    }

    if ( !is_light )
    {
	process_non_light(m);
	fprintf( fp, "\t\t</Appearance>\n");
    }

    /* FIXME: need code to handle light */

    /* get list of vertices */
    nmg_vertex_tabulate( &verts, &m->magic );

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

	    NMG_CK_REGION( reg );
	    for ( BU_LIST_FOR( s, shell, &reg->s_hd ) )
	    {
		struct faceuse *fu;

		NMG_CK_SHELL( s );
		for ( BU_LIST_FOR( fu, faceuse, &s->fu_hd ) )
		{
		    struct loopuse *lu;

		    NMG_CK_FACEUSE( fu );

		    if ( fu->orientation != OT_SAME )
			continue;

		    for ( BU_LIST_FOR( lu, loopuse, &fu->lu_hd ) )
		    {
			struct edgeuse *eu;

			NMG_CK_LOOPUSE( lu );

			if ( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
			    continue;

			if ( !first )
			    fprintf( fp, ",\n" );
			else
			    first = 0;

			fprintf( fp, "\t\t\t\t" );
			for ( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
			{
			    struct vertex *v;

			    NMG_CK_EDGEUSE( eu );

			    v = eu->vu_p->v_p;
			    NMG_CK_VERTEX( v );
			    fprintf( fp, " %d,", bu_ptbl_locate( &verts, (long *)v ) );
			}
			fprintf( fp, "-1" );
		    }
		}
	    }
	}
	/* close coordIndex */
	fprintf( fp, "\" ");
	fprintf( fp, "normalPerVertex=\"false\" ");
	fprintf( fp, "convex=\"false\" ");
	fprintf( fp, "creaseAngle=\"0.5\" ");
	/* close IndexedFaceSet open tag */
	fprintf( fp, ">\n");
    }

    fprintf( fp, "\t\t\t<Coordinate point=\"");

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

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

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

	if ( is_light )
	    VADD2( ave_pt, ave_pt, pt_meters );
	if ( first )
	{
	    if ( !is_light )
		fprintf( fp, " %10.10e %10.10e %10.10e, ", V3ARGS(pt_meters));
	    first = 0;
	}
	else
	    if ( !is_light )
		fprintf( fp, "%10.10e %10.10e %10.10e, ", V3ARGS( pt_meters ));
    }

    /* close point */
    fprintf(fp, "\"");
    /* close Coordinate */
    fprintf(fp, "/>\n");
    /* IndexedFaceSet end tag */
    fprintf( fp, "\t\t</IndexedFaceSet>\n");
    /* Shape end tag */
    fprintf( fp, "\t</Shape>\n");

    BARRIER_CHECK;
}
예제 #8
0
파일: refract.c 프로젝트: cogitokat/brlcad
/*
 * R R _ R E N D E R
 */
int
rr_render(register struct application *ap,
	  const struct partition *pp,
	  struct shadework *swp)
{
    struct application sub_ap;
    vect_t work;
    vect_t incident_dir;
    fastf_t shader_fract;
    fastf_t reflect;
    fastf_t transmit;

#ifdef RT_MULTISPECTRAL
    struct bn_tabdata *ms_filter_color = BN_TABDATA_NULL;
    struct bn_tabdata *ms_shader_color = BN_TABDATA_NULL;
    struct bn_tabdata *ms_reflect_color = BN_TABDATA_NULL;
    struct bn_tabdata *ms_transmit_color = BN_TABDATA_NULL;
#else
    vect_t filter_color;
    vect_t shader_color;
    vect_t reflect_color;
    vect_t transmit_color;
#endif

    fastf_t attenuation;
    vect_t to_eye;
    int code;

    RT_AP_CHECK(ap);

    RT_APPLICATION_INIT(&sub_ap);

#ifdef RT_MULTISPECTRAL
    sub_ap.a_spectrum = BN_TABDATA_NULL;
    ms_reflect_color = bn_tabdata_get_constval(0.0, spectrum);
#endif

    /*
     * sw_xmitonly is set primarily for light visibility rays.
     * Need to compute (partial) transmission through to the light,
     * or procedural shaders won't be able to cast shadows
     * and light won't be able to get through glass
     * (including "stained glass" and "filter glass").
     *
     * On the other hand, light visibility rays shouldn't be refracted,
     * it is pointless to shoot at where the light isn't.
     */
    if (swp->sw_xmitonly) {
	/* Caller wants transmission term only, don't fire reflected rays */
	transmit = swp->sw_transmit + swp->sw_reflect;	/* Don't loose energy */
	reflect = 0;
    } else {
	reflect = swp->sw_reflect;
	transmit = swp->sw_transmit;
    }
    if (R_DEBUG&RDEBUG_REFRACT) {
	bu_log("rr_render(%s) START: lvl=%d reflect=%g, transmit=%g, xmitonly=%d\n",
	       pp->pt_regionp->reg_name,
	       ap->a_level,
	       reflect, transmit,
	       swp->sw_xmitonly);
    }
    if (reflect <= 0 && transmit <= 0)
	goto out;

    if (ap->a_level > max_bounces) {
	/* Nothing more to do for this ray */
	static long count = 0;		/* Not PARALLEL, should be OK */

	if ((R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) && (
		count++ < MSG_PROLOGUE ||
		(count%MSG_INTERVAL) == 3
		)) {
	    bu_log("rr_render: %d, %d MAX BOUNCES=%d: %s\n",
		   ap->a_x, ap->a_y,
		   ap->a_level,
		   pp->pt_regionp->reg_name);
	}

	/*
	 * Return the basic color of the object, ignoring the
	 * the fact that it is supposed to be
	 * filtering or reflecting light here.
	 * This is much better than returning just black,
	 * but something better might be done.
	 */
#ifdef RT_MULTISPECTRAL
	BN_CK_TABDATA(swp->msw_color);
	BN_CK_TABDATA(swp->msw_basecolor);
	bn_tabdata_copy(swp->msw_color, swp->msw_basecolor);
#else
	VMOVE(swp->sw_color, swp->sw_basecolor);
#endif
	ap->a_cumlen += pp->pt_inhit->hit_dist;
	goto out;
    }
#ifdef RT_MULTISPECTRAL
    BN_CK_TABDATA(swp->msw_basecolor);
    ms_filter_color = bn_tabdata_dup(swp->msw_basecolor);

#else
    VMOVE(filter_color, swp->sw_basecolor);
#endif

    if ((swp->sw_inputs & (MFI_HIT|MFI_NORMAL)) != (MFI_HIT|MFI_NORMAL))
	shade_inputs(ap, pp, swp, MFI_HIT|MFI_NORMAL);

    /*
     * If this ray is being fired from the exit point of
     * an object, and is directly entering another object,
     * (i.e., there is no intervening air-gap), and
     * the two refractive indices match, then do not fire a
     * reflected ray -- just take the transmission contribution.
     * This is important, e.g., for glass gun tubes projecting
     * through a glass armor plate. :-)
     */
    if (NEAR_ZERO(pp->pt_inhit->hit_dist, AIR_GAP_TOL)
	&& ZERO(ap->a_refrac_index - swp->sw_refrac_index))
    {
	transmit += reflect;
	reflect = 0;
    }

    /*
     * Diminish base color appropriately, and add in
     * contributions from mirror reflection & transparency
     */
    shader_fract = 1 - (reflect + transmit);
    if (shader_fract < 0) {
	shader_fract = 0;
    } else if (shader_fract >= 1) {
	goto out;
    }
    if (R_DEBUG&RDEBUG_REFRACT) {
	bu_log("rr_render: lvl=%d start shader=%g, reflect=%g, transmit=%g %s\n",
	       ap->a_level,
	       shader_fract, reflect, transmit,
	       pp->pt_regionp->reg_name);
    }
#ifdef RT_MULTISPECTRAL
    BN_GET_TABDATA(ms_shader_color, swp->msw_color->table);
    bn_tabdata_scale(ms_shader_color, swp->msw_color, shader_fract);
#else
    VSCALE(shader_color, swp->sw_color, shader_fract);
#endif

    /*
     * Compute transmission through an object.
     * There may be a mirror reflection, which will be handled
     * by the reflection code later
     */
    if (transmit > 0) {
	if (R_DEBUG&RDEBUG_REFRACT) {
	    bu_log("rr_render: lvl=%d transmit=%g.  Calculate refraction at entrance to %s.\n",
		   ap->a_level, transmit,
		   pp->pt_regionp->reg_name);
	}
	/*
	 * Calculate refraction at entrance.
	 */
	sub_ap = *ap;		/* struct copy */
#ifdef RT_MULTISPECTRAL
	sub_ap.a_spectrum = bn_tabdata_dup((struct bn_tabdata *)ap->a_spectrum);
#endif
	sub_ap.a_level = 0;	/* # of internal reflections */
	sub_ap.a_cumlen = 0;	/* distance through the glass */
	sub_ap.a_user = -1;	/* sanity */
	sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge;
	sub_ap.a_diverge = 0.0;
	sub_ap.a_uptr = (genptr_t)(pp->pt_regionp);
	VMOVE(sub_ap.a_ray.r_pt, swp->sw_hit.hit_point);
	VMOVE(incident_dir, ap->a_ray.r_dir);

	/* If there is an air gap, reset ray's RI to air */
	if (pp->pt_inhit->hit_dist > AIR_GAP_TOL)
	    sub_ap.a_refrac_index = RI_AIR;

	if (!ZERO(sub_ap.a_refrac_index - swp->sw_refrac_index)
	    && !rr_refract(incident_dir,		/* input direction */
			   swp->sw_hit.hit_normal,	/* exit normal */
			   sub_ap.a_refrac_index,	/* current RI */
			   swp->sw_refrac_index,	/* next RI */
			   sub_ap.a_ray.r_dir		/* output direction */
		))
	{
	    /*
	     * Ray was mirror reflected back outside solid.
	     * Just add contribution to reflection,
	     * and quit.
	     */
	    reflect += transmit;
	    transmit = 0;
#ifdef RT_MULTISPECTRAL
	    ms_transmit_color = bn_tabdata_get_constval(0.0, spectrum);
#else
	    VSETALL(transmit_color, 0);
#endif
	    if (R_DEBUG&RDEBUG_REFRACT) {
		bu_log("rr_render: lvl=%d change xmit into reflection %s\n",
		       ap->a_level,
		       pp->pt_regionp->reg_name);
	    }
	    goto do_reflection;
	}
	if (R_DEBUG&RDEBUG_REFRACT) {
	    bu_log("rr_render: lvl=%d begin transmission through %s.\n",
		   ap->a_level,
		   pp->pt_regionp->reg_name);
	}

	/*
	 * Find new exit point from the inside.
	 * We will iterate, but not recurse, due to the special
	 * (non-recursing) hit and miss routines used here for
	 * internal reflection.
	 *
	 * a_onehit is set to 3, so that where possible,
	 * rr_hit() will be given three accurate hit points:
	 * the entry and exit points of this glass region,
	 * and the entry point into the next region.
	 * This permits calculation of the departing
	 * refraction angle based on the RI of the current and
	 * *next* regions along the ray.
	 */
	sub_ap.a_purpose = "rr first glass transmission ray";
	sub_ap.a_flag = 0;
    do_inside:
	sub_ap.a_hit =  rr_hit;
	sub_ap.a_miss = rr_miss;
	sub_ap.a_logoverlap = ap->a_logoverlap;
	sub_ap.a_onehit = 3;
	sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge;
	sub_ap.a_diverge = 0.0;
	switch (code = rt_shootray(&sub_ap)) {
	    case 3:
		/* More glass to come.
		 * uvec=exit_pt, vvec=N, a_refrac_index = next RI.
		 */
		break;
	    case 2:
		/* No more glass to come.
		 * uvec=exit_pt, vvec=N, a_refrac_index = next RI.
		 */
		break;
	    case 1:
		/* Treat as escaping ray */
		if (R_DEBUG&RDEBUG_REFRACT)
		    bu_log("rr_refract: Treating as escaping ray\n");
		goto do_exit;
	    case 0:
	    default:
		/* Dreadful error */
#ifdef RT_MULTISPECTRAL
		bu_bomb("rr_refract: Stuck in glass. Very green pixel, unsupported in multi-spectral mode\n");
#else
		VSET(swp->sw_color, 0, 99, 0); /* very green */
#endif
		goto out;			/* abandon hope */
	}

	if (R_DEBUG&RDEBUG_REFRACT) {
	    bu_log("rr_render: calculating refraction @ exit from %s (green)\n", pp->pt_regionp->reg_name);
	    bu_log("Start point to exit point:\n\
vdraw open rr;vdraw params c 00ff00; vdraw write n 0 %g %g %g; vdraw wwrite n 1 %g %g %g; vdraw send\n",
		   V3ARGS(sub_ap.a_ray.r_pt),
		   V3ARGS(sub_ap.a_uvec));
	}
	/* NOTE: rr_hit returns EXIT Point in sub_ap.a_uvec,
	 * and returns EXIT Normal in sub_ap.a_vvec,
	 * and returns next RI in sub_ap.a_refrac_index
	 */
	if (R_DEBUG&RDEBUG_RAYWRITE) {
	    wraypts(sub_ap.a_ray.r_pt,
		    sub_ap.a_ray.r_dir,
		    sub_ap.a_uvec,
		    2, ap, stdout);	/* 2 = ?? */
	}
	if (R_DEBUG&RDEBUG_RAYPLOT) {
	    /* plotfp */
	    bu_semaphore_acquire(BU_SEM_SYSCALL);
	    pl_color(stdout, 0, 255, 0);
	    pdv_3line(stdout,
		      sub_ap.a_ray.r_pt,
		      sub_ap.a_uvec);
	    bu_semaphore_release(BU_SEM_SYSCALL);
	}
	/* Advance.  Exit point becomes new start point */
	VMOVE(sub_ap.a_ray.r_pt, sub_ap.a_uvec);
	VMOVE(incident_dir, sub_ap.a_ray.r_dir);

	/*
	 * Calculate refraction at exit point.
	 * Use "look ahead" RI value from rr_hit.
	 */
	if (!ZERO(sub_ap.a_refrac_index - swp->sw_refrac_index)
	    && !rr_refract(incident_dir,		/* input direction */
			   sub_ap.a_vvec,		/* exit normal */
			   swp->sw_refrac_index,	/* current RI */
			   sub_ap.a_refrac_index,	/* next RI */
			   sub_ap.a_ray.r_dir		/* output direction */
		))
	{
	    static long count = 0;		/* not PARALLEL, should be OK */

	    /* Reflected internally -- keep going */
	    if ((++sub_ap.a_level) <= max_ireflect) {
		sub_ap.a_purpose = "rr reflected internal ray, probing for glass exit point";
		sub_ap.a_flag = 0;
		goto do_inside;
	    }

	    /*
	     * Internal Reflection limit exceeded -- just let
	     * the ray escape, continuing on current course.
	     * This will cause some energy from somewhere in the
	     * scene to be received through this glass,
	     * which is much better than just returning
	     * grey or black, as before.
	     */
	    if ((R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) && (
		    count++ < MSG_PROLOGUE ||
		    (count%MSG_INTERVAL) == 3
		    )) {
		bu_log("rr_render: %d, %d Int.reflect=%d: %s lvl=%d\n",
		       sub_ap.a_x, sub_ap.a_y,
		       sub_ap.a_level,
		       pp->pt_regionp->reg_name,
		       ap->a_level);
	    }
	    VMOVE(sub_ap.a_ray.r_dir, incident_dir);
	    goto do_exit;
	}
    do_exit:
	/*
	 * Compute internal spectral transmittance.
	 * Bouger's law.  pg 30 of "color science"
	 *
	 * Apply attenuation factor due to thickness of the glass.
	 * sw_extinction is in terms of fraction of light absorbed
	 * per linear meter of glass.  a_cumlen is in mm.
	 */
/* XXX extinction should be a spectral curve, not scalor */
	if (swp->sw_extinction > 0 && sub_ap.a_cumlen > 0) {
	    attenuation = pow(10.0, -1.0e-3 * sub_ap.a_cumlen *
			      swp->sw_extinction);
	} else {
	    attenuation = 1;
	}

	/*
	 * Process the escaping refracted ray.
	 * This is the only place we might recurse dangerously,
	 * so we are careful to use our caller's recursion level+1.
	 * NOTE: point & direction already filled in
	 */
	sub_ap.a_hit =  ap->a_hit;
	sub_ap.a_miss = ap->a_miss;
	sub_ap.a_logoverlap = ap->a_logoverlap;
	sub_ap.a_onehit = ap->a_onehit;
	sub_ap.a_level = ap->a_level+1;
	sub_ap.a_uptr = ap->a_uptr;
	sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge;
	sub_ap.a_diverge = 0.0;
	if (code == 3) {
	    sub_ap.a_purpose = "rr recurse on next glass";
	    sub_ap.a_flag = 0;
	} else {
	    sub_ap.a_purpose = "rr recurse on escaping internal ray";
	    sub_ap.a_flag = 1;
	    sub_ap.a_onehit = sub_ap.a_onehit > -3 ? -3 : sub_ap.a_onehit;
	}
	/* sub_ap.a_refrac_index was set to RI of next material by rr_hit().
	 */
	sub_ap.a_cumlen = 0;
	(void) rt_shootray(&sub_ap);

	/* a_user has hit/miss flag! */
	if (sub_ap.a_user == 0) {
#ifdef RT_MULTISPECTRAL
	    ms_transmit_color = bn_tabdata_dup(background);
#else
	    VMOVE(transmit_color, background);
#endif
	    sub_ap.a_cumlen = 0;
	} else {
#ifdef RT_MULTISPECTRAL
	    ms_transmit_color = bn_tabdata_dup(sub_ap.a_spectrum);
#else
	    VMOVE(transmit_color, sub_ap.a_color);
#endif
	}
	transmit *= attenuation;
#ifdef RT_MULTISPECTRAL
	bn_tabdata_mul(ms_transmit_color, ms_filter_color, ms_transmit_color);
#else
	VELMUL(transmit_color, filter_color, transmit_color);
#endif
	if (R_DEBUG&RDEBUG_REFRACT) {
	    bu_log("rr_render: lvl=%d end of xmit through %s\n",
		   ap->a_level,
		   pp->pt_regionp->reg_name);
	}
    } else {
예제 #9
0
파일: sh_fire.c 프로젝트: kanzure/brlcad
/*
 * 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, void **dpp, const struct mfuncs *UNUSED(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_GET(fire_sp, struct fire_specific);
    *dpp = 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 (!EQUAL(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).
     */

    rt_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;
}
예제 #10
0
파일: arbn.c 프로젝트: kanzure/brlcad
/**
 * Brute force through all possible plane intersections.
 * Generate all edge lines, then intersect the line with all
 * the other faces to find the vertices on that line.
 * If the geometry is correct, there will be no more than two.
 * While not the fastest strategy, this will produce an accurate
 * plot without requiring extra bookkeeping.
 * Note that the vectors will be drawn in no special order.
 */
int
rt_arbn_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol, const struct rt_view_info *UNUSED(info))
{
    struct rt_arbn_internal *aip;
    size_t i;
    size_t j;
    size_t k;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    for (i = 0; i < aip->neqn - 1; i++) {
	for (j = i + 1; j < aip->neqn; j++) {
	    double dot;
	    int point_count;	/* # points on this line */
	    point_t a, b;		/* start and end points */
	    vect_t dist;

	    VSETALL(a, 0);
	    VSETALL(b, 0);

	    /* If normals are parallel, no intersection */
	    dot = VDOT(aip->eqn[i], aip->eqn[j]);
	    if (BN_VECT_ARE_PARALLEL(dot, tol)) continue;

	    /* Have an edge line, isect with all other planes */
	    point_count = 0;
	    for (k = 0; k < aip->neqn; k++) {
		size_t m;
		point_t pt;
		size_t next_k;

		next_k = 0;

		if (k == i || k == j) continue;
		if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue;

		/* See if point is outside arb */
		for (m = 0; m < aip->neqn; m++) {
		    if (i == m || j == m || k == m) continue;
		    if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) {
			next_k = 1;
			break;
		    }
		}

		if (next_k != 0) continue;

		if (point_count <= 0) {
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE);
		    VMOVE(a, pt);
		} else if (point_count == 1) {
		    VSUB2(dist, pt, a);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
		    VMOVE(b, pt);
		} else {
		    VSUB2(dist, pt, a);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    VSUB2(dist, pt, b);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    bu_log("rt_arbn_plot() error, point_count=%d (>2) on edge %zu/%zu, non-convex\n",
			   point_count+1,
			   i, j);
		    VPRINT(" a", a);
		    VPRINT(" b", b);
		    VPRINT("pt", pt);
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);	/* draw it */
		}
		point_count++;
	    }
	    /* Point counts of 1 are (generally) not harmful,
	     * occurring on pyramid peaks and the like.
	     */
	}
    }
    return 0;
}
예제 #11
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;
}
예제 #12
0
파일: tree.c 프로젝트: cciechad/brlcad
/**
 * 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);
}
예제 #13
0
파일: sh_wood.c 프로젝트: kanzure/brlcad
HIDDEN int
wood_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *UNUSED(rtip))
/* New since 4.4 release */
{
    register int i;
    register struct wood_specific *wd;

    register struct resource *resp = &rt_uniresource;

    /*
     * Get the impure storage for the control block
     */

    BU_CK_VLS(matparm);
    BU_GET(wd, struct wood_specific);
    *dpp = wd;

    /*
     * Load the default values
     */

    if (rp->reg_mater.ma_color_valid) {
	VSCALE(wd->lt_rgb, rp->reg_mater.ma_color, 255);
    } else {
	wd->lt_rgb[0] = 255;	/* Light yellow */
	wd->lt_rgb[1] = 255;
	wd->lt_rgb[2] = 224;
    }

    wd->dk_rgb[0] = 191;		/* Brownish-red */
    wd->dk_rgb[1] =  97;
    wd->dk_rgb[2] =   0;

    wd->ident     = 0;
    wd->forw      = WOOD_NULL;
    wd->rp	      = rp;
    wd->flags     = 0;
    wd->overlay   = 0;		/* Draw only one ring */
    wd->ns	      = 10;
    wd->jitter    = 0.0;
    wd->scale     = 1.0;
    wd->spacing   = 5;		/* 5mm space between rings */
    wd->dd        = 0.0;		/* no dither of vertex */
    wd->dz        = 0.0;		/* nor of Z-axis */
    wd->qd        = 0;
    wd->qp        = 0;
    wd->phase     = 5;
    wd->depth     = 0;

    wd->dither[0] = bn_rand0to1(resp->re_randptr);
    wd->dither[1] = bn_rand0to1(resp->re_randptr);
    wd->dither[2] = bn_rand0to1(resp->re_randptr);

    VSETALL(wd->rot, 0);
    VSETALL(wd->vertex, 0);
    VSETALL(wd->D, 0);
    VSETALL(wd->V, 0);

    /*
     * Parse the MATPARM field
     */

    if (bu_struct_parse(matparm, wood_parse, (char *)wd) < 0) {
	BU_PUT(wd, struct wood_specific);
	return -1;
    }

    /*
     * Do some sundry range and misc. checking
     */

    for (i = 0; i < 3; i++) {
	if (wd->dither[i] < 0 || wd->dither[i] > 1.0) {
	    bu_log("wood_setup(%s):  dither is out of range.\n",
		    rp->reg_name);
	    return -1;
	}
    }

    if (wd->flags == EXPLICIT_VERTEX) {
	bu_log("wood_setup(%s):  Explicit vertex specified without direction\n", rp->reg_name);
	return -1;
    }

    if (wd->flags == EXPLICIT_DIRECTION) {
	bu_log("wood_setup(%s):  Explicit direction specified without vertex\n", rp->reg_name);
	return -1;
    }

    /*
     * Get the bounding RPP
     */

    if (rt_bound_tree(rp->reg_treetop, wd->b_min, wd->b_max) < 0) return -1;

    /*
     * Add it to the wood chain
     */

    wd->forw   = Wood_Chain;
    Wood_Chain = wd;

    /*
     * See if the user has flagged this region as a member of a larger
     * combination.  If so, go ahead and process it
     */

    if (wd->ident == 0)
	wood_setup_2(wd);

    else {
	register struct wood_specific *wc;
	vect_t c_min, c_max;

	/*
	 * First, process the accumulated chain of wood regions and
	 * process all regions which have the specified ident field.
	 */

	VSETALL(c_min, 0);
	VSETALL(c_max, 0);

	for (wc = Wood_Chain; wc != WOOD_NULL; wc = wc->forw) {
	    if (wc->ident == wd->ident) {
		VMIN(c_min, wc->b_min);
		VMAX(c_max, wc->b_max);
	    }
	}

	/*
	 * Now, loop through the chain again this time updating the
	 * regions' min/max fields with the new values
	 */

	for (wc = Wood_Chain; wc != WOOD_NULL; wc = wc->forw) {
	    if (wc->ident == wd->ident) {
		VMOVE(wc->b_min, c_min);
		VMOVE(wc->b_max, c_max);
		wood_setup_2(wc);
	    }
	}

	/*
	 * End of multi-region processing loop
	 */

    }

    /*
     * Normalize the RGB colors
     */

    for (i = 0; i < 3; i++) {
	wd->lt_rgb[i] /= 255.0;
	wd->dk_rgb[i] /= 255.0;
    }

    /*
     * Return to the caller
     */

    return 1;
}