コード例 #1
0
void
Normals(void)
{
    struct points *ptr;


    if ( root == NULL )
	return;

    ptr = root->next;
    if ( ptr == NULL )
	return;

    VSUB2( root->nnext, ptr->p, root->p );
    VUNITIZE( root->nnext );

    while ( ptr->next != NULL )
    {
	VREVERSE( ptr->nprev, ptr->prev->nnext );
	VSUB2( ptr->nnext, ptr->next->p, ptr->p );
	VUNITIZE( ptr->nnext );
	VCROSS( ptr->norm, ptr->nprev, ptr->nnext );
	VUNITIZE( ptr->norm );
	VADD2( ptr->nmitre, ptr->nprev, ptr->nnext );
	VUNITIZE( ptr->nmitre );
	VCROSS( ptr->mnorm, ptr->norm, ptr->nmitre );
	VUNITIZE( ptr->mnorm );
	if ( VDOT( ptr->mnorm, ptr->nnext ) > 0.0 )
	    VREVERSE( ptr->mnorm, ptr->mnorm );
	ptr->alpha = acos( VDOT( ptr->nnext, ptr->nprev ) );
	ptr = ptr->next;
    }
}
コード例 #2
0
ファイル: hyp.c プロジェクト: kanzure/brlcad
/**
 * Create a bounding RPP for an hyp
 */
int
rt_hyp_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) {
    struct rt_hyp_internal *xip;
    vect_t hyp_Au, hyp_B, hyp_An, hyp_Bn, hyp_H;
    vect_t pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8;
    RT_CK_DB_INTERNAL(ip);
    xip = (struct rt_hyp_internal *)ip->idb_ptr;
    RT_HYP_CK_MAGIC(xip);

    VMOVE(hyp_H, xip->hyp_Hi);
    VUNITIZE(hyp_H);
    VMOVE(hyp_Au, xip->hyp_A);
    VUNITIZE(hyp_Au);
    VCROSS(hyp_B, hyp_Au, hyp_H);

    VSETALL((*min), INFINITY);
    VSETALL((*max), -INFINITY);

    VSCALE(hyp_B, hyp_B, xip->hyp_b);
    VREVERSE(hyp_An, xip->hyp_A);
    VREVERSE(hyp_Bn, hyp_B);

    VADD3(pt1, xip->hyp_Vi, xip->hyp_A, hyp_B);
    VADD3(pt2, xip->hyp_Vi, xip->hyp_A, hyp_Bn);
    VADD3(pt3, xip->hyp_Vi, hyp_An, hyp_B);
    VADD3(pt4, xip->hyp_Vi, hyp_An, hyp_Bn);
    VADD4(pt5, xip->hyp_Vi, xip->hyp_A, hyp_B, xip->hyp_Hi);
    VADD4(pt6, xip->hyp_Vi, xip->hyp_A, hyp_Bn, xip->hyp_Hi);
    VADD4(pt7, xip->hyp_Vi, hyp_An, hyp_B, xip->hyp_Hi);
    VADD4(pt8, xip->hyp_Vi, hyp_An, hyp_Bn, xip->hyp_Hi);

    /* Find the RPP of the rotated axis-aligned hyp bbox - that is,
     * the bounding box the given hyp would have if its height
     * vector were in the positive Z direction. This does not give
     * us an optimal bbox except in the case where the hyp is
     * actually axis aligned to start with, but it's usually
     * at least a bit better than the bounding sphere RPP. */
    VMINMAX((*min), (*max), pt1);
    VMINMAX((*min), (*max), pt2);
    VMINMAX((*min), (*max), pt3);
    VMINMAX((*min), (*max), pt4);
    VMINMAX((*min), (*max), pt5);
    VMINMAX((*min), (*max), pt6);
    VMINMAX((*min), (*max), pt7);
    VMINMAX((*min), (*max), pt8);

    return 0;
}
コード例 #3
0
ファイル: rec.c プロジェクト: cogitokat/brlcad
/**
 * R E C _ N O R M
 *
 * Given ONE ray distance, return the normal and entry/exit point.
 * hit_surfno is a flag indicating if normal needs to be computed or not.
 */
void
rt_rec_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
{
    struct rec_specific *rec =
	(struct rec_specific *)stp->st_specific;

    VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
    switch (hitp->hit_surfno) {
	case REC_NORM_BODY:
	    /* compute it */
	    hitp->hit_vpriv[Z] = 0.0;
	    MAT4X3VEC(hitp->hit_normal, rec->rec_invRoS,
		      hitp->hit_vpriv);
	    VUNITIZE(hitp->hit_normal);
	    break;
	case REC_NORM_TOP:
	    VMOVE(hitp->hit_normal, rec->rec_Hunit);
	    break;
	case REC_NORM_BOT:
	    VREVERSE(hitp->hit_normal, rec->rec_Hunit);
	    break;
	default:
	    bu_log("rt_rec_norm: surfno=%d bad\n", hitp->hit_surfno);
	    break;
    }
}
コード例 #4
0
ファイル: refract.c プロジェクト: cogitokat/brlcad
/*
 * R E F R A C T
 *
 * Compute the refracted ray 'v_2' from the incident ray 'v_1' with
 * the refractive indices 'ri_2' and 'ri_1' respectively.
 * Using Schnell's Law:
 *
 * theta_1 = angle of v_1 with surface normal
 * theta_2 = angle of v_2 with reversed surface normal
 * ri_1 * sin(theta_1) = ri_2 * sin(theta_2)
 *
 * sin(theta_2) = ri_1/ri_2 * sin(theta_1)
 *
 * The above condition is undefined for ri_1/ri_2 * sin(theta_1)
 * being greater than 1, and this represents the condition for total
 * reflection, the 'critical angle' is the angle theta_1 for which
 * ri_1/ri_2 * sin(theta_1) equals 1.
 *
 * Returns TRUE if refracted, FALSE if reflected.
 *
 * Note:  output (v_2) can be same storage as an input.
 */
HIDDEN int
rr_refract(vect_t v_1, vect_t norml, double ri_1, double ri_2, vect_t v_2)
{
    vect_t w, u;
    fastf_t beta;

    if (NEAR_ZERO(ri_1, 0.0001) || NEAR_ZERO(ri_2, 0.0001)) {
	bu_log("rr_refract:ri1=%g, ri2=%g\n", ri_1, ri_2);
	beta = 1;
    } else {
	beta = ri_1/ri_2;		/* temp */
	if (beta > 10000) {
	    bu_log("rr_refract:  beta=%g\n", beta);
	    beta = 1000;
	}
    }
    VSCALE(w, v_1, beta);
    VCROSS(u, w, norml);

    /*
     *	|w X norml| = |w||norml| * sin(theta_1)
     *	        |u| = ri_1/ri_2 * sin(theta_1) = sin(theta_2)
     */
    if ((beta = VDOT(u, u)) > 1.0) {
	/* Past critical angle, total reflection.
	 * Calculate reflected (bounced) incident ray.
	 */
	if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_refract: reflected.  ri1=%g ri2=%g beta=%g\n",
					   ri_1, ri_2, beta);
	VREVERSE(u, v_1);
	beta = 2 * VDOT(u, norml);
	VSCALE(w, norml, beta);
	VSUB2(v_2, w, u);
	return 0;		/* reflected */
    } else {
	/*
	 * 1 - beta = 1 - sin(theta_2)^^2
	 *	    = cos(theta_2)^^2.
	 * beta = -1.0 * cos(theta_2) - Dot(w, norml).
	 */
	if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_refract: refracted.  ri1=%g ri2=%g beta=%g\n",
					   ri_1, ri_2, beta);
	beta = -sqrt(1.0 - beta) - VDOT(w, norml);
	VSCALE(u, norml, beta);
	VADD2(v_2, w, u);
	return 1;		/* refracted */
    }
    /* NOTREACHED */
}
コード例 #5
0
static void
plot_ray_img(struct application *ap,
	     const struct partition *pp,
	     double dist,
	     struct bbd_img *bi)
{
    static int plot_num;
    FILE *pfd;
    char name[256];
    point_t pt;

    sprintf(name, "bbd_%d.plot3", plot_num++);
    bu_log("plotting %s\n", name);
    if ((pfd = fopen(name, "wb")) == (FILE *)NULL) {
	bu_bomb("can't open plot3 file\n");
    }

    /* red line from ray origin to hit point */
    VJOIN1(pp->pt_inhit->hit_point, ap->a_ray.r_pt, pp->pt_inhit->hit_dist,
	   ap->a_ray.r_dir);
    if (VNEAR_EQUAL(ap->a_ray.r_pt, pp->pt_inhit->hit_point, 0.125)) {
	/* start and hit point identical, make special allowance */
	vect_t vtmp;

	pl_color(pfd, 255, 0, 128);
	VREVERSE(vtmp, ap->a_ray.r_dir);
	VJOIN1(vtmp, ap->a_ray.r_pt, 5.0, vtmp);
	pdv_3line(pfd, vtmp, pp->pt_inhit->hit_point);
    } else {
	pl_color(pfd, 255, 0, 0);
	pdv_3line(pfd, ap->a_ray.r_pt, pp->pt_inhit->hit_point);
    }

    /* yellow line from hit point to plane point */
    VJOIN1(pt, ap->a_ray.r_pt, dist, ap->a_ray.r_dir); /* point on plane */
    pl_color(pfd, 255, 255, 0);
    pdv_3line(pfd, pp->pt_inhit->hit_point, pt);

    /* green line from image origin to plane point */
    pl_color(pfd, 0, 255, 0);
    pdv_3line(pfd, pt, bi->img_origin);

    fclose(pfd);


}
コード例 #6
0
ファイル: hyp.c プロジェクト: kanzure/brlcad
/**
 * Given ONE ray distance, return the normal and entry/exit point.
 */
void
rt_hyp_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
{
    struct hyp_specific *hyp =
	(struct hyp_specific *)stp->st_specific;

    /* normal from basic hyperboloid and transformed normal */
    vect_t n, nT;

    VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
    switch (hitp->hit_surfno) {
	case HYP_NORM_TOP:
	    VMOVE(hitp->hit_normal, hyp->hyp_Hunit);
	    break;
	case HYP_NORM_BOTTOM:
	    VREVERSE(hitp->hit_normal, hyp->hyp_Hunit);
	    break;
	case HYP_NORM_BODY:
	    /* normal vector is VUNITIZE(z * dz/dx, z * dz/dy, -z) */
	    /* z = +- (c/a) * sqrt(x^2/a^2 + y^2/b^2 -1) */
	    VSET(n, hyp->hyp_rx * hitp->hit_vpriv[X],
		 hyp->hyp_ry * hitp->hit_vpriv[Y],
		 -hyp->hyp_rz * hitp->hit_vpriv[Z]);

	    nT[X] = (hyp->hyp_Aunit[X] * n[X])
		+ (hyp->hyp_Bunit[X] * n[Y])
		+ (hyp->hyp_Hunit[X] * n[Z]);
	    nT[Y] = (hyp->hyp_Aunit[Y] * n[X])
		+ (hyp->hyp_Bunit[Y] * n[Y])
		+ (hyp->hyp_Hunit[Y] * n[Z]);
	    nT[Z] = (hyp->hyp_Aunit[Z] * n[X])
		+ (hyp->hyp_Bunit[Z] * n[Y])
		+ (hyp->hyp_Hunit[Z] * n[Z]);

	    VUNITIZE(nT);
	    VMOVE(hitp->hit_normal, nT);
	    break;
	default:
	    bu_log("rt_hyp_norm: surfno=%d bad\n", hitp->hit_surfno);
	    break;
    }
}
コード例 #7
0
ファイル: wray.c プロジェクト: cogitokat/brlcad
/*
 * W R A Y P T S
 *
 * Write a VLD-standard ray for a section of a ray specified
 * by the "in" and "out" distances along the ray.  This is usually
 * used for logging passage through "air" (i.e., no solid).
 * The "inorm" flag holds an inward pointing normal (typ. a r_dir value)
 * that will be flipped on output, so that the "air solid"
 * has a proper outward pointing normal.
 */
void
wraypts(vect_t in, vect_t inorm, vect_t out, int id, struct application *ap, FILE *fp)
{
    struct vldray vldray;
    vect_t norm;
    size_t ret;

    VMOVE(&(vldray.ox), in);
    VSUB2(&(vldray.rx), out, in);

    VREVERSE(norm, inorm);
    WRAY_NORMAL(vldray, norm);

    vldray.pa = vldray.pe = vldray.pc = vldray.sc = 0;	/* no curv */

    vldray.ob = id;

    WRAY_TAG(vldray, ap);

    ret = fwrite(&vldray, sizeof(struct vldray), 1, fp);
    if (ret != 1)
	bu_log("Unable to write ray\n");
}
コード例 #8
0
ファイル: pyramid.c プロジェクト: cogitokat/brlcad
/*
 * Find the single outward pointing normal for a facet.
 * Assumes all points are coplanar (they better be!).
 */
void
pnorms(fastf_t (*norms)[3], fastf_t (*verts)[3], fastf_t *centroid, int npts)
{
    int i;
    vect_t ab, ac;
    vect_t n;
    vect_t out;		/* hopefully points outwards */

    VSUB2(ab, verts[1], verts[0]);
    VSUB2(ac, verts[2], verts[0]);
    VCROSS(n, ab, ac);
    VUNITIZE(n);

    /* If normal points inwards (towards centroid), flip it */
    VSUB2(out, verts[0], centroid);
    if (VDOT(n, out) < 0) {
	VREVERSE(n, n);
    }

    /* Use same normal for all vertices (flat shading) */
    for (i=0; i<npts; i++) {
	VMOVE(norms[i], n);
    }
}
コード例 #9
0
ファイル: anim_hardtrack.c プロジェクト: cciechad/brlcad
int
main(int argc, char **argv)
{
    void anim_dir2mat(fastf_t *, const fastf_t *, const fastf_t *), anim_y_p_r2mat(fastf_t *, double, double, double), anim_add_trans(fastf_t *, const fastf_t *, const fastf_t *), anim_mat_print(FILE *, const fastf_t *, int);
    int get_args(int argc, char **argv), track_prep(void), val, frame, go, i, count;
    fastf_t y_rot, distance, yaw, pitch, roll;
    vect_t p1, p2, p3, dir, dir2, wheel_now, wheel_prev;
    vect_t zero, position, vdelta, temp, to_track, to_front;
    mat_t mat_v, wmat, mat_x;
    FILE *stream;
    int last_frame;

    VSETALL(zero, 0.0);
    VSETALL(to_track, 0.0);
    VSETALL(centroid, 0.0);
    VSETALL(rcentroid, 0.0);
    init_dist = y_rot = radius= 0.0;
    first_frame = num_wheels = steer = axes = cent = links_placed=0;
    num_wheels = num_links = last_frame = 0;
    MAT_IDN(mat_v);
    MAT_IDN(mat_x);
    MAT_IDN(wmat);
    MAT_IDN(m_axes);
    MAT_IDN(m_rev_axes);

    if (!get_args(argc, argv)) {
	fprintf(stderr, "anim_hardtrack: argument error.");
	return(-1);
    }

    if (axes || cent ) {
	/* vehicle has own reference frame */
	anim_add_trans(m_axes, centroid, zero);
	anim_add_trans(m_rev_axes, zero, rcentroid);
    }

    /* get track information from specified file */

    if (!(stream = fopen(*(argv+bu_optind), "rb"))) {
	fprintf(stderr, "Anim_hardtrack: Could not open file %s.\n", *(argv+bu_optind));
	return(0);
    }
    num_wheels = -1;
    if (radius) {
	while (!feof(stream)) {
	    fscanf(stream, "%*f %*f %*f");
	    num_wheels++;
	}
    } else {
	while (!feof(stream)) {
	    fscanf(stream, "%*f %*f %*f %*f");
	    num_wheels++;
	}
    }
    rewind(stream);

    /*allocate memory for track information*/
    x = (struct all *) bu_calloc(num_wheels, sizeof(struct all), "struct all");
    /*read rest of track info */
    for (i=0;i<NW;i++) {
	fscanf(stream, "%lf %lf %lf", temp, temp+1, temp+2);
	if (radius)
	    x[i].w.rad = radius;
	else
	    fscanf(stream, "%lf", & x[i].w.rad);
	MAT4X3PNT(x[i].w.pos, m_rev_axes, temp);
	if (i==0)
	    track_y = x[0].w.pos[1];
	else
	    x[i].w.pos[1] = track_y;
    }
    (void) fclose(stream);

    (void) track_prep();

    if (get_circumf) {
	printf("%.10g\n", tracklen);
	return(0);
    }

    /* initialize to_track */
    VSET(to_track, 0.0, track_y, 0.0);
    VSET(to_front, 1.0, 0.0, 0.0);

    if ((!print_link)&&(!print_wheel)) {
	fprintf(stderr, "anim_hardtrack: no ouput requested. Use -l or -w.\n");
	bu_exit(0, NULL);
    }
    /* main loop */
    distance = 0.0;
    if (!steer)
	frame = first_frame;
    else
	frame = first_frame-1;
    for (val = 3; val > 2; frame++) {
	go = 1;
	/*p2 is current position. p3 is next;p1 is previous*/
	VMOVE(p1, p2);
	VMOVE(p2, p3);
	scanf("%*f");/*time stamp*/
	val = scanf("%lf %lf %lf", p3, p3+1, p3 + 2);
	if (!steer) {
	    scanf("%lf %lf %lf", &yaw, &pitch, &roll);
	    anim_dy_p_r2mat(mat_v, yaw, pitch, roll);
	    anim_add_trans(mat_v, p3, rcentroid);
	}
	else {
	    /* analyze positions for steering */
	    /*get useful direction unit vectors*/
	    if (frame == first_frame) {
		/* first frame*/
		VSUBUNIT(dir, p3, p2);
		VMOVE(dir2, dir);
	    }
	    else if (val < 3) {
		/*last frame*/
		VSUBUNIT(dir, p2, p1);
		VMOVE(dir2, dir);
	    }
	    else if (frame > first_frame) {
		/*normal*/
		VSUBUNIT(dir, p3, p1);
		VSUBUNIT(dir2, p2, p1);/*needed for vertical case*/
	    }
	    else go = 0;/*first time through loop;no p2*/

			/*create matrix which would move vehicle*/
	    anim_dir2mat(mat_v, dir, dir2);
	    anim_add_trans(mat_v, p2, rcentroid);
	}

	/*determine distance traveled*/
	VMOVE(wheel_prev, wheel_now);
	MAT4X3PNT(wheel_now, mat_v, to_track);
	if (frame > first_frame) {
	    /* increment distance by distance moved */
	    VSUB2(vdelta, wheel_now, wheel_prev);
	    MAT3X3VEC(temp, mat_v, to_front);/*new front of vehicle*/
	    distance += VDOT(temp, vdelta);/*portion of vdelta in line with track*/
	}

	if (go) {
	    if (print_mode==TRACK_ANIM) {
		printf("start %d;\nclean;\n", frame);
	    } else if (print_mode==TRACK_ARCED) {
		if (frame != arced_frame) continue;
		last_frame = 1;
	    }
	    if (print_link) {
		for (count=0;count<num_links;count++) {
		    (void) get_link(position, &y_rot, distance+tracklen*count/num_links+init_dist);
		    anim_y_p_r2mat(wmat, 0.0, y_rot+r[count].ang, 0.0);
		    anim_add_trans(wmat, position, r[count].pos);
		    if ((axes || cent) && links_placed) {
			/* link moved from vehicle coords */
			bn_mat_mul(mat_x, wmat, m_rev_axes);
			bn_mat_mul(wmat, m_axes, mat_x);
		    }
		    else if (axes || cent) {
			/* link moved to vehicle coords */
			MAT_MOVE(mat_x, wmat);
			bn_mat_mul(wmat, m_axes, mat_x);
		    }
		    if (print_mode==TRACK_ANIM) {
			printf("anim %s.%d matrix %s\n", *(argv+link_nindex), count, link_cmd);
			anim_mat_printf(stdout, wmat, "%.10g ", "\n", ";\n");
		    } else if (print_mode==TRACK_ARCED) {
			printf("arced %s.%d matrix %s ", *(argv+link_nindex), count, link_cmd);
			anim_mat_printf(stdout, wmat, "%.10g ", "", "\n");
		    }
		}
	    }
	    if (print_wheel) {
		for (count = 0;count<num_wheels;count++) {
		    anim_y_p_r2mat(wmat, 0.0, -distance/x[count].w.rad, 0.0);
		    VREVERSE(temp, x[count].w.pos);
		    anim_add_trans(wmat, x[count].w.pos, temp);
		    if (axes || cent) {
			bn_mat_mul(mat_x, wmat, m_rev_axes);
			bn_mat_mul(wmat, m_axes, mat_x);
		    }
		    if (print_mode==TRACK_ANIM) {
			printf("anim %s.%d matrix %s\n", *(argv+wheel_nindex), count, wheel_cmd);
			anim_mat_printf(stdout, wmat, "%.10g ", "\n", ";\n");
		    } else if (print_mode==TRACK_ARCED) {
			printf("arced %s.%d matrix %s ", *(argv+wheel_nindex), count, wheel_cmd);
			anim_mat_printf(stdout, wmat, "%.10g ", "", "\n");
		    }
		}
	    }
	    if (print_mode==TRACK_ANIM)
		printf("end;\n");
	}
	if (last_frame) break;
    }

    if (x) {
	bu_free(x, "struct all");
    }
    if (r) {
	bu_free(r, "struct rlink");
    }
    return( 0 );
}
コード例 #10
0
ファイル: revolve.c プロジェクト: kanzure/brlcad
int
rt_revolve_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    struct rt_revolve_internal *rip;

    size_t nvert, narc, nadd, nseg, i, j, k;
    point2d_t *verts;
    struct rt_curve *crv;

    vect_t ell[16], cir[16], ucir[16], height, xdir, ydir, ux, uy, uz, rEnd, xEnd, yEnd;
    fastf_t cos22_5 = 0.9238795325112867385;
    fastf_t cos67_5 = 0.3826834323650898373;
    int *endcount = NULL;
    point_t add, add2, add3;

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

    nvert = rip->skt->vert_count;
    verts = rip->skt->verts;
    crv = &rip->skt->curve;

    if (rip->ang < M_2PI) {
	narc = ceil(rip->ang * 8 * M_1_PI);
    } else {
	narc = 16;
    }
    VSCALE(xEnd, rip->r, cos(rip->ang));
    VCROSS(rEnd, rip->axis3d, rip->r);	/* using rEnd for temp storage */
    VSCALE(yEnd, rEnd, sin(rip->ang));
    VADD2(rEnd, xEnd, yEnd);

    VMOVE(uz, rip->axis3d);
    VMOVE(ux, rip->r);
    VCROSS(uy, uz, ux);

    VUNITIZE(ux);
    VUNITIZE(uy);
    VUNITIZE(uz);

    /* setup unit circle to be scaled */
    VMOVE(ucir[ 0], ux);
    VREVERSE(ucir[ 8], ucir[0]);

    VSCALE(xdir, ux, cos22_5);
    VSCALE(ydir, uy, cos67_5);
    VADD2(ucir[ 1], xdir, ydir);
    VREVERSE(ucir[ 9], ucir[1]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 7], xdir, ydir);
    VREVERSE(ucir[15], ucir[7]);

    VSCALE(xdir, ux, M_SQRT1_2);
    VSCALE(ydir, uy, M_SQRT1_2);
    VADD2(ucir[ 2], xdir, ydir);
    VREVERSE(ucir[10], ucir[2]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 6], xdir, ydir);
    VREVERSE(ucir[14], ucir[6]);


    VSCALE(xdir, ux, cos67_5);
    VSCALE(ydir, uy, cos22_5);
    VADD2(ucir[ 3], xdir, ydir);
    VREVERSE(ucir[11], ucir[3]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 5], xdir, ydir);
    VREVERSE(ucir[13], ucir[5]);

    VMOVE(ucir[ 4], uy);
    VREVERSE(ucir[12], ucir[4]);

    /* find open endpoints, and determine which points are used */
    if (nvert)
	endcount = (int *)bu_calloc(nvert, sizeof(int), "endcount");

    nseg = rip->skt->curve.count;

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

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

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

    /* draw circles */
    for (i=0; i<nvert; i++) {
	if (endcount[i] == 0) continue;
	VSCALE(height, uz, verts[i][Y]);
	for (j=0; j<narc; j++) {
	    VSCALE(cir[j], ucir[j], verts[i][X]);
	    VADD3(ell[j], rip->v3d, cir[j], height);
	}
	RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_MOVE);
	for (j=1; j<narc; j++) {
	    RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
	}
	if (narc < 16) {
	    VSCALE(cir[narc], rEnd, verts[i][X]);
	    VADD3(ell[narc], rip->v3d, cir[narc], height);
	    RT_ADD_VLIST(vhead, ell[narc], BN_VLIST_LINE_DRAW);
	} else {
	    RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_DRAW);
	}
    }

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

    /* draw sketch outlines */
    for (i=0; i<narc; i++) {
	curve_to_vlist(vhead, ttol, rip->v3d, ucir[i], uz, rip->skt, crv);
	for (j=0; j<nadd; j++) {
	    if (j+1 < nadd &&
		ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]);
		VJOIN1(add3, add, verts[endcount[j+1]][X], ucir[i]);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW);
		j++;
	    } else {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
    }
    if (narc < 16) {
	curve_to_vlist(vhead, ttol, rip->v3d, rEnd, uz, rip->skt, crv);
	for (j=0; j<nadd; j++) {
	    if (j+1 < nadd &&
		ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], rEnd);
		VJOIN1(add3, add, verts[endcount[j+1]][X], rEnd);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW);
		j++;
	    } else {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], rEnd);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
	for (j=0; j<nadd; j+=2) {
	    if (!ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, rip->v3d, verts[endcount[j+1]][Y], rip->axis3d);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
    }

    if (nvert)
	bu_free(endcount, "endcount");
    return 0;
}
コード例 #11
0
ファイル: revolve.c プロジェクト: kanzure/brlcad
/**
 * Intersect a ray with a revolve.  If an intersection occurs, a struct
 * seg will be acquired and filled in.
 *
 * Returns -
 * 0 MISS
 * >0 HIT
 */
int
rt_revolve_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
{
    struct revolve_specific *rev =
	(struct revolve_specific *)stp->st_specific;
    struct seg *segp;

    struct hit *hitp;
    struct hit *hits[MAX_HITS], hit[MAX_HITS];

    size_t i, j, nseg, nhits;
    int in, out;

    fastf_t k, m, h, aa, bb;
    point_t dp, pr, xlated;
    vect_t vr, ur, norm, normS, normE;

    fastf_t start, end, angle;

    vect_t dir;
    point_t hit1, hit2;
    point2d_t hit2d, pt1, pt2;
    fastf_t a, b, c, disc, k1, k2, t1, t2;
    uint32_t *lng;
    struct line_seg *lsg;
    struct carc_seg *csg;

    nhits = 0;

    for (i=0; i<MAX_HITS; i++) hits[i] = &hit[i];

    vr[X] = VDOT(rev->xUnit, rp->r_dir);
    vr[Y] = VDOT(rev->yUnit, rp->r_dir);
    vr[Z] = VDOT(rev->zUnit, rp->r_dir);

    VSUB2(xlated, rp->r_pt, rev->v3d);
    pr[X] = VDOT(rev->xUnit, xlated);
    pr[Y] = VDOT(rev->yUnit, xlated);
    pr[Z] = VDOT(rev->zUnit, xlated);

    VMOVE(ur, vr);
    VUNITIZE(ur);

    if (rev->ang < M_2PI) {
	VREVERSE(normS, rev->yUnit);	/* start normal */
	start = (VDOT(normS, rev->v3d) - VDOT(normS, rp->r_pt)) / VDOT(normS, rp->r_dir);

	VCROSS(normE, rev->zUnit, rev->rEnd);	/* end normal */
	end = (VDOT(normE, rev->v3d) - VDOT(normE, rp->r_pt)) / VDOT(normE, rp->r_dir);

	VJOIN1(hit1, pr, start, vr);
	hit2d[Y] = hit1[Z];
	hit2d[X] = sqrt(hit1[X]*hit1[X] + hit1[Y]*hit1[Y]);

	VJOIN1(hit2, xlated, start, rp->r_dir);
	if (VDOT(rev->xUnit, hit2) < 0) {
	    /* set the sign of the 2D point's x coord */
	    hit2d[X] = -hit2d[X];
	}

	if (rt_sketch_contains(rev->skt, hit2d)) {
	    hit2d[X] = -hit2d[X];
	    if (rev->ang > M_PI && rt_sketch_contains(rev->skt, hit2d)) {
		/* skip it */
	    } else {
		hitp = hits[nhits++];
		hitp->hit_magic = RT_HIT_MAGIC;
		hitp->hit_dist = start;
		hitp->hit_surfno = (hit2d[X]>0) ? START_FACE_NEG : START_FACE_POS;
		VSET(hitp->hit_vpriv, -hit2d[X], hit2d[Y], 0);
	    }
	}

	VJOIN1(hit1, pr, end, vr);
	hit2d[Y] = hit1[Z];
	hit2d[X] = sqrt(hit1[X]*hit1[X] + hit1[Y]*hit1[Y]);

	VJOIN1(hit2, xlated, end, rp->r_dir);
	if (VDOT(rev->rEnd, hit2) < 0) {
	    /* set the sign of the 2D point's x coord */
	    hit2d[X] = -hit2d[X];
	}

	if (rt_sketch_contains(rev->skt, hit2d)) {
	    hit2d[X] = -hit2d[X];
	    if (rev->ang > M_PI && rt_sketch_contains(rev->skt, hit2d)) {
		/* skip it */
	    } else {
		if (nhits >= MAX_HITS) return -1; /* too many hits */
		hitp = hits[nhits++];
		hitp->hit_magic = RT_HIT_MAGIC;
		hitp->hit_dist = end;
		hitp->hit_surfno = (hit2d[X]>0) ? END_FACE_NEG : END_FACE_POS;
		VSET(hitp->hit_vpriv, -hit2d[X], hit2d[Y], 0);
	    }
	}
    }

    /**
     * calculate hyperbola parameters
     *
     * [ (x*x) / aa^2 ] - [ (y-h)^2 / bb^2 ] = 1
     *
     * x = aa cosh(t - k);
     * y = h + bb sinh(t - k);
     */

    VREVERSE(dp, pr);
    VSET(norm, ur[X], ur[Y], 0);

    k = VDOT(dp, norm) / VDOT(ur, norm);
    h = pr[Z] + k*vr[Z];

    if (NEAR_EQUAL(fabs(ur[Z]), 1.0, RT_DOT_TOL)) {
	aa = sqrt(pr[X]*pr[X] + pr[Y]*pr[Y]);
	bb = MAX_FASTF;
    } else {
	aa = sqrt((pr[X] + k*vr[X])*(pr[X] + k*vr[X]) + (pr[Y] + k*vr[Y])*(pr[Y] + k*vr[Y]));
	bb = sqrt(aa*aa * (1.0/(1 - ur[Z]*ur[Z]) - 1.0));
    }

    /**
     * if (ur[Z] == 1) {
     *	    bb = inf;
     *	    // ray becomes a line parallel to sketch's y-axis instead of a hyberbola
     * }
     * if (ur[Z] == 0) {
     *	    bb = 0;
     *	    // ray becomes a line parallel to sketch's x-axis instead of a hyperbola
     *	    // all hits must have x > aa
     * }
     */

    /* handle open sketches */
    if (!NEAR_ZERO(ur[Z], RT_DOT_TOL)) {
	for (i=0; i<rev->skt->vert_count && rev->ends[i] != -1; i++) {
	    V2MOVE(pt1, rev->skt->verts[rev->ends[i]]);
	    hit2d[Y] = pt1[Y];
	    if (NEAR_EQUAL(fabs(ur[Z]), 1.0, RT_DOT_TOL)) {
		/* ur[Z] == 1 */
		hit2d[X] = aa;
	    } else {
		hit2d[X] = aa*sqrt((hit2d[Y]-h)*(hit2d[Y]-h)/(bb*bb) + 1);
	    }
	    if (pt1[X] < 0) hit2d[X] = -fabs(hit2d[X]);
	    if (fabs(hit2d[X]) < fabs(pt1[X])) {
		/* valid hit */
		if (nhits >= MAX_HITS) return -1; /* too many hits */
		hitp = hits[nhits++];
		hitp->hit_magic = RT_HIT_MAGIC;
		hitp->hit_dist = (hit2d[Y] - pr[Z]) / vr[Z];
		hitp->hit_surfno = HORIZ_SURF;
		VJOIN1(hitp->hit_vpriv, pr, hitp->hit_dist, vr);
		hitp->hit_point[X] = hit2d[X];
		hitp->hit_point[Y] = hit2d[Y];
		hitp->hit_point[Z] = 0;

		angle = atan2(hitp->hit_vpriv[Y], hitp->hit_vpriv[X]);
		if (pt1[X] < 0) {
		    angle += M_PI;
		} else if (angle < 0) {
		    angle += M_2PI;
		}
		hit2d[X] = -hit2d[X];
		if (angle > rev->ang) {
		    nhits--;
		    continue;
		} else if ((angle + M_PI < rev->ang || angle - M_PI > 0)
			   && rt_sketch_contains(rev->skt, hit2d)
			   && hit2d[X] > 0) {
		    nhits--;
		    continue;
		}
		/* X and Y are used for uv(), Z is used for norm() */
		hitp->hit_vpriv[X] = pt1[X];
		hitp->hit_vpriv[Y] = angle;
		if (i+1 < rev->skt->vert_count && rev->ends[i+1] != -1 &&
		    NEAR_EQUAL(rev->skt->verts[rev->ends[i]][Y],
			       rev->skt->verts[rev->ends[i+1]][Y], SMALL)) {
		    hitp->hit_vpriv[Z] = rev->skt->verts[rev->ends[i+1]][X];
		    i++;
		    if (fabs(hit2d[X]) < fabs(hitp->hit_vpriv[Z])) {
			nhits--;
		    }
		} else {
		    hitp->hit_vpriv[Z] = 0;
		}
	    }
	}
    }

    /* find hyperbola intersection with each sketch segment */
    nseg = rev->skt->curve.count;
    for (i=0; i<nseg; i++) {
	lng = (uint32_t *)rev->skt->curve.segment[i];

	switch (*lng) {
	    case CURVE_LSEG_MAGIC:
		lsg = (struct line_seg *)lng;
		V2MOVE(pt1, rev->skt->verts[lsg->start]);
		V2MOVE(pt2, rev->skt->verts[lsg->end]);
		V2SUB2(dir, pt2, pt1);
		if (ZERO(dir[X])) {
		    m = 1.0;
		} else {
		    m = dir[Y] / dir[X];
		}

		if (NEAR_EQUAL(fabs(ur[Z]), 1.0, RT_DOT_TOL)) {
		    /* ray is vertical line at x=aa */
		    if (FMIN(pt1[X], pt2[X]) < aa && aa < FMAX(pt1[X], pt2[X])) {
			/* check the positive side of the sketch (x > 0) */
			k1 = (m * (aa - pt1[X]) + pt1[Y] - pr[Z]) / vr[Z];
			VJOIN1(hit1, pr, k1, vr);
			angle = atan2(hit1[Y], hit1[X]);
			hit2d[X] = -aa;		/* use neg to check for overlap in contains() */
			hit2d[Y] = hit1[Z];
			if (angle < 0) {
			    angle += M_2PI;
			}
			if (angle < rev->ang &&
			    !((angle + M_PI < rev->ang || angle - M_PI > 0)
			      && rt_sketch_contains(rev->skt, hit2d))) {
			    if (nhits >= MAX_HITS) return -1; /* too many hits */
			    hitp = hits[nhits++];
			    hitp->hit_point[X] = -hit2d[X];
			    hitp->hit_point[Y] = hit2d[Y];
			    hitp->hit_point[Z] = 0;
			    VMOVE(hitp->hit_vpriv, hit1);
			    if (ZERO(m)) {
				hitp->hit_vpriv[Z] = 0.0;
			    } else {
				hitp->hit_vpriv[Z] = -1.0/m;
			    }
			    hitp->hit_magic = RT_HIT_MAGIC;
			    hitp->hit_dist = k1;
			    hitp->hit_surfno = i;
			}
		    }
		    if (FMIN(pt1[X], pt2[X]) < -aa && -aa < FMAX(pt1[X], pt2[X])) {
			/* check negative side of the sketch (x < 0) */
			k1 = (m * (-aa - pt1[X]) + pt1[Y] - pr[Z]) / vr[Z];
			VJOIN1(hit1, pr, k1, vr);
			angle = atan2(hit1[Y], hit1[X]);
			hit2d[X] = aa;		/* use neg to check for overlap in contains() */
			hit2d[Y] = hit1[Z];
			if (angle < 0) {
			    angle += M_PI;
			}
			if (angle < rev->ang &&
			    !((angle + M_PI < rev->ang || angle - M_PI > 0)
			      && rt_sketch_contains(rev->skt, hit2d))) {
			    if (nhits >= MAX_HITS) return -1; /* too many hits */
			    hitp = hits[nhits++];
			    hitp->hit_point[X] = -hit2d[X];
			    hitp->hit_point[Y] = hit2d[Y];
			    hitp->hit_point[Z] = 0;
			    VMOVE(hitp->hit_vpriv, hit1);
			    if (ZERO(m)) {
				hitp->hit_vpriv[Z] = 0.0;
			    } else {
				hitp->hit_vpriv[Z] = 1.0/m;
			    }
			    hitp->hit_magic = RT_HIT_MAGIC;
			    hitp->hit_dist = k1;
			    hitp->hit_surfno = i;
			}
		    }
		} else if (NEAR_ZERO(ur[Z], RT_DOT_TOL)) {
		    /* ray is horizontal line at y = h; hit2d[X] > aa */
		    if (FMIN(pt1[Y], pt2[Y]) < h && h < FMAX(pt1[Y], pt2[Y])) {
			if (ZERO(m)) {
			    hit2d[X] = pt1[X];
			} else {
			    hit2d[X] = pt1[X] + (h-pt1[Y])/m;
			}
			hit2d[Y] = h;
			if (fabs(hit2d[X]) > aa) {
			    k1 = k + sqrt(hit2d[X]*hit2d[X] - aa*aa);
			    k2 = k - sqrt(hit2d[X]*hit2d[X] - aa*aa);

			    VJOIN1(hit1, pr, k1, vr);
			    angle = atan2(hit1[Y], hit1[X]);
			    if (hit2d[X] < 0) {
				angle += M_PI;
			    } else if (angle < 0) {
				angle += M_2PI;
			    }
			    hit2d[X] = -hit2d[X];
			    if (angle < rev->ang &&
				!((angle + M_PI < rev->ang || angle - M_PI > 0)
				  && rt_sketch_contains(rev->skt, hit2d))) {
				if (nhits >= MAX_HITS) return -1; /* too many hits */
				hitp = hits[nhits++];
				hitp->hit_point[X] = -hit2d[X];
				hitp->hit_point[Y] = hit2d[Y];
				hitp->hit_point[Z] = 0;
				VMOVE(hitp->hit_vpriv, hit1);
				if (ZERO(m)) {
				    hitp->hit_vpriv[Z] = 0.0;
				} else {
				    hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
				}
				hitp->hit_magic = RT_HIT_MAGIC;
				hitp->hit_dist = k1;
				hitp->hit_surfno = i;
			    }

			    VJOIN1(hit2, pr, k2, vr);
			    angle = atan2(hit2[Y], hit2[X]);
			    if (-hit2d[X] < 0) {
				angle += M_PI;
			    } else if (angle < 0) {
				angle += M_2PI;
			    }
			    if (angle < rev->ang &&
				!((angle + M_PI < rev->ang || angle - M_PI > 0)
				  && rt_sketch_contains(rev->skt, hit2d))) {
				if (nhits >= MAX_HITS) return -1; /* too many hits */
				hitp = hits[nhits++];
				hitp->hit_point[X] = -hit2d[X];
				hitp->hit_point[Y] = hit2d[Y];
				hitp->hit_point[Z] = 0;
				VMOVE(hitp->hit_vpriv, hit2);
				if (ZERO(m)) {
				    hitp->hit_vpriv[Z] = 0.0;
				} else {
				    hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
				}
				hitp->hit_magic = RT_HIT_MAGIC;
				hitp->hit_dist = k2;
				hitp->hit_surfno = i;
			    }
			}
		    }
		} else {

		    a = dir[X]*dir[X]/(aa*aa) - dir[Y]*dir[Y]/(bb*bb);
		    b = 2*(dir[X]*pt1[X]/(aa*aa) - dir[Y]*(pt1[Y]-h)/(bb*bb));
		    c = pt1[X]*pt1[X]/(aa*aa) - (pt1[Y]-h)*(pt1[Y]-h)/(bb*bb) - 1;
		    disc = b*b - (4.0 * a * c);
		    if (!NEAR_ZERO(a, RT_PCOEF_TOL)) {
			if (disc > 0) {
			    disc = sqrt(disc);
			    t1 =  (-b + disc) / (2.0 * a);
			    t2 =  (-b - disc) / (2.0 * a);
			    k1 = (pt1[Y]-pr[Z] + t1*dir[Y])/vr[Z];
			    k2 = (pt1[Y]-pr[Z] + t2*dir[Y])/vr[Z];

			    if (t1 > 0 && t1 < 1) {
				if (nhits >= MAX_HITS) return -1; /* too many hits */
				VJOIN1(hit1, pr, k1, vr);
				angle = atan2(hit1[Y], hit1[X]);
				V2JOIN1(hit2d, pt1, t1, dir);
				if (hit2d[X] < 0) {
				    angle += M_PI;
				} else if (angle < 0) {
				    angle += M_2PI;
				}
				hit2d[X] = -hit2d[X];
				if (angle < rev->ang) {
				    if ((angle + M_PI < rev->ang || angle - M_PI > 0)
					&& rt_sketch_contains(rev->skt, hit2d)) {
					/* overlap, so ignore it */
				    } else {
					hitp = hits[nhits++];
					hitp->hit_point[X] = -hit2d[X];
					hitp->hit_point[Y] = hit2d[Y];
					hitp->hit_point[Z] = 0;
					VMOVE(hitp->hit_vpriv, hit1);
					if (ZERO(m)) {
					    hitp->hit_vpriv[Z] = 0.0;
					} else {
					    hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
					}
					hitp->hit_magic = RT_HIT_MAGIC;
					hitp->hit_dist = k1;
					hitp->hit_surfno = i;
				    }
				}
			    }
			    if (t2 > 0 && t2 < 1) {
				if (nhits >= MAX_HITS) return -1; /* too many hits */
				VJOIN1(hit2, pr, k2, vr);
				angle = atan2(hit2[Y], hit2[X]);
				V2JOIN1(hit2d, pt1, t2, dir);
				if (hit2d[X] < 0) {
				    angle += M_PI;
				} else if (angle < 0) {
				    angle += M_2PI;
				}
				hit2d[X] = -hit2d[X];
				if (angle < rev->ang) {
				    if ((angle + M_PI < rev->ang || angle - M_PI > 0)
					&& rt_sketch_contains(rev->skt, hit2d)) {
					/* overlap, so ignore it */
				    } else {
					hitp = hits[nhits++];
					hitp->hit_point[X] = -hit2d[X];
					hitp->hit_point[Y] = hit2d[Y];
					hitp->hit_point[Z] = 0;
					VMOVE(hitp->hit_vpriv, hit2);
					if (ZERO(m)) {
					    hitp->hit_vpriv[Z] = 0.0;
					} else {
					    hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
					}
					hitp->hit_magic = RT_HIT_MAGIC;
					hitp->hit_dist = k2;
					hitp->hit_surfno = i;
				    }
				}
			    }
			}
		    } else if (!NEAR_ZERO(b, RT_PCOEF_TOL)) {
			t1 = -c / b;
			k1 = (pt1[Y]-pr[Z] + t1*dir[Y])/vr[Z];
			if (t1 > 0 && t1 < 1) {
			    if (nhits >= MAX_HITS) return -1; /* too many hits */

			    VJOIN1(hit1, pr, k1, vr);
			    angle = atan2(hit1[Y], hit1[X]);
			    V2JOIN1(hit2d, pt1, t1, dir);
			    if (hit2d[X] < 0) {
				angle += M_PI;
			    } else if (angle < 0) {
				angle += M_2PI;
			    }
			    hit2d[X] = -hit2d[X];
			    if (angle < rev->ang) {
				if ((angle + M_PI < rev->ang || angle - M_PI > 0)
				    && rt_sketch_contains(rev->skt, hit2d)) {
				    /* overlap, so ignore it */
				} else {
				    hitp = hits[nhits++];
				    hitp->hit_point[X] = -hit2d[X];
				    hitp->hit_point[Y] = hit2d[Y];
				    hitp->hit_point[Z] = 0;
				    VMOVE(hitp->hit_vpriv, hit1);
				    if (ZERO(m)) {
					hitp->hit_vpriv[Z] = 0.0;
				    } else {
					hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
				    }
				    hitp->hit_magic = RT_HIT_MAGIC;
				    hitp->hit_dist = k1;
				    hitp->hit_surfno = i;
				}
			    }
			}
		    }
		}
		break;
	    case CURVE_CARC_MAGIC:
		/*
		  circle: (x-cx)^2 + (y-cy)^2 = cr^2
		  x = (1/2cx)y^2 + (-cy/cx)y + (1/2cx)(cy^2 + cx^2 - cr^2) + (1/2cx)(x^2)
		  x = f(y) + (1/2cx)x^2

		  hyperbola:
		  [(x-hx)/a]^2 - [(y-hy)/b]^2 = 1
		  x^2 = (a^2/b^2)y^2 + (-2*hy*a^2/b^2)y + (hy^2 * a^2/b^2) + a^2
		  x^2 = g(y)

		  plug the second equation into the first to get:
		  x = f(y) + (1/2cx)g(y)
		  then square that to get:
		  x^2 = {f(y) + (1/2cx)g(y)}^2 = g(y)
		  move all to one side to get:
		  0 = {f(y) + (1/2cx)g(y)}^2 - g(y)
		  this is a fourth order polynomial in y.
		*/
		{
		    bn_poly_t circleX;	/* f(y) */
		    bn_poly_t hypXsq;		/* g(y) */
		    bn_poly_t hypXsq_scaled;	/* g(y) / (2*cx) */
		    bn_poly_t sum;		/* f(y) + g(y)/(2cx) */
		    bn_poly_t sum_sq;		/* {f(y) + g(y)/(2cx)}^2 */
		    bn_poly_t answer;		/* {f(y) + g(y)/(2cx)}^2 - g(y) */
		    bn_complex_t roots[4];
		    int rootcnt;

		    fastf_t cx, cy, crsq = 0;	/* carc's (x, y) coords and radius^2 */
		    point2d_t center, radius;

		    /* calculate circle parameters */
		    csg = (struct carc_seg *)lng;

		    if (csg->radius <= 0.0) {
			/* full circle, "end" is center and "start" is on the circle */
			V2MOVE(center, rev->skt->verts[csg->end]);
			V2SUB2(radius, rev->skt->verts[csg->start], center);
			crsq = MAG2SQ(radius);
		    } else {
			point_t startpt, endpt, midpt;
			vect_t s_to_m;
			vect_t bisector;
			vect_t vertical;
			fastf_t distance;
			fastf_t magsq_s2m;

			VSET(vertical, 0, 0, 1);
			V2MOVE(startpt, rev->skt->verts[csg->start]);
			startpt[Z] = 0.0;
			V2MOVE(endpt, rev->skt->verts[csg->end]);
			endpt[Z] = 0.0;

			VBLEND2(midpt, 0.5, startpt, 0.5, endpt);
			VSUB2(s_to_m, midpt, startpt);
			VCROSS(bisector, vertical, s_to_m);
			VUNITIZE(bisector);
			magsq_s2m = MAGSQ(s_to_m);
			if (magsq_s2m > csg->radius*csg->radius) {
			    fastf_t max_radius;

			    max_radius = sqrt(magsq_s2m);
			    if (NEAR_EQUAL(max_radius, csg->radius, RT_LEN_TOL)) {
				csg->radius = max_radius;
			    } else {
				bu_log("Impossible radius for circular arc in extrusion (%s), is %g, cannot be more than %g!\n",
				       stp->st_dp->d_namep, csg->radius, sqrt(magsq_s2m));
				bu_log("Difference is %g\n", max_radius - csg->radius);
				return -1;
			    }
			}
			distance = sqrt(csg->radius*csg->radius - magsq_s2m);

			/* save arc center */
			if (csg->center_is_left) {
			    V2JOIN1(center, midpt, distance, bisector);
			} else {
			    V2JOIN1(center, midpt, -distance, bisector);
			}
		    }

		    cx = center[X];
		    cy = center[Y];

		    circleX.dgr = 2;
		    hypXsq.dgr = 2;
		    hypXsq_scaled.dgr = 2;
		    sum.dgr = 2;
		    sum_sq.dgr = 4;
		    answer.dgr = 4;

		    circleX.cf[0] = (cy*cy + cx*cx - crsq)/(2.0*cx);
		    circleX.cf[1] = -cy/cx;
		    circleX.cf[2] = 1/(2.0*cx);

		    hypXsq_scaled.cf[0] = hypXsq.cf[0] = aa*aa + h*h*aa*aa/(bb*bb);
		    hypXsq_scaled.cf[1] = hypXsq.cf[1] = -2.0*h*aa*aa/(bb*bb);
		    hypXsq_scaled.cf[2] = hypXsq.cf[2] = (aa*aa)/(bb*bb);

		    bn_poly_scale(&hypXsq_scaled, 1.0 / (2.0 * cx));
		    bn_poly_add(&sum, &hypXsq_scaled, &circleX);
		    bn_poly_mul(&sum_sq, &sum, &sum);
		    bn_poly_sub(&answer, &sum_sq, &hypXsq);

		    /* It is known that the equation is 4th order.  Therefore, if the
		     * root finder returns other than 4 roots, error.
		     */
		    rootcnt = rt_poly_roots(&answer, roots, stp->st_dp->d_namep);
		    if (rootcnt != 4) {
			if (rootcnt > 0) {
			    bu_log("tor:  rt_poly_roots() 4!=%d\n", rootcnt);
			    bn_pr_roots(stp->st_name, roots, rootcnt);
			} else if (rootcnt < 0) {
			    static int reported=0;
			    bu_log("The root solver failed to converge on a solution for %s\n", stp->st_dp->d_namep);
			    if (!reported) {
				VPRINT("while shooting from:\t", rp->r_pt);
				VPRINT("while shooting at:\t", rp->r_dir);
				bu_log("Additional torus convergence failure details will be suppressed.\n");
				reported=1;
			    }
			}
		    }

		    break;
		}
	    case CURVE_BEZIER_MAGIC:
		break;
	    case CURVE_NURB_MAGIC:
		break;
	    default:
		bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
		break;
	}

    }

    if (nhits%2 != 0) {
	bu_log("odd number of hits: %zu\n", nhits);
	for (i=0; i<nhits; i++) {
	    bu_log("\t(%6.2f, %6.2f)\t%6.2f\t%2d\n",
		   hits[i]->hit_point[X], hits[i]->hit_point[Y], hits[i]->hit_dist, hits[i]->hit_surfno);
	}
	return -1;
    }

    /* sort hitpoints (an arbitrary number of hits depending on sketch) */
    for (i=0; i<nhits; i+=2) {
	in = out = -1;
	for (j=0; j<nhits; j++) {
	    if (hits[j] == NULL) continue;
	    if (in == -1) {
		in = j;
		continue;
	    }
	    /* store shortest dist as 'in', second shortest as 'out' */
	    if (hits[j]->hit_dist <= hits[in]->hit_dist) {
		out = in;
		in = j;
	    } else if (out == -1 || hits[j]->hit_dist <= hits[out]->hit_dist) {
		out = j;
	    }
	}
	if (in == -1 || out == -1) {
	    bu_log("failed to find valid segment. nhits: %zu\n", nhits);
	    break;
	}

	if (ZERO(hits[in]->hit_dist - hits[out]->hit_dist)) {
	    hits[in] = NULL;
	    hits[out] = NULL;
	    continue;
	}

	RT_GET_SEG(segp, ap->a_resource);
	segp->seg_stp = stp;

	segp->seg_in = *hits[in];
	hits[in] = NULL;
	segp->seg_out = *hits[out];
	hits[out] = NULL;
	BU_LIST_INSERT(&(seghead->l), &(segp->l));
    }

    return nhits;
}
コード例 #12
0
static int
radhit(register struct application *ap, struct partition *PartHeadp, struct seg *segHeadp)
{
    register struct partition *pp;
    register struct hit *hitp;
    struct application sub_ap;
    fastf_t	f;
    vect_t	to_eye, work;
    int	depth;

    for ( pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw )
	if ( pp->pt_outhit->hit_dist >= 0.0 )  break;
    if ( pp == PartHeadp )  {
	bu_log("radhit:  no hit out front?\n");
	return(0);
    }

    if (R_DEBUG&RDEBUG_HITS)  {
	rt_pr_pt( ap->a_rt_i, pp );
    }

    hitp = pp->pt_inhit;
    if ( hitp->hit_dist >= INFINITY )  {
	bu_log("radhit:  entry beyond infinity\n");
	return(1);
    }
    /* Check to see if eye is "inside" the solid */
    if ( hitp->hit_dist < 0 )  {
	/* XXX */
	bu_log("radhit:  GAK, eye inside solid (%g)\n", hitp->hit_dist );
	for ( pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw )
	    rt_pr_pt( ap->a_rt_i, pp );
	return(0);
    }

    rayp = &rayinfo[ ap->a_level ];

    RT_HIT_NORMAL( rayp->norm, hitp, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip );

    if (R_DEBUG&RDEBUG_HITS)  {
	rt_pr_hit( " In", hitp );
    }

    rayp->dist = hitp->hit_dist;
    rayp->reg = pp->pt_regionp->reg_regionid;
    rayp->sol = pp->pt_inseg->seg_stp->st_id;
    rayp->surf = hitp->hit_surfno;
    RT_CURVATURE( &(rayp->curvature), hitp, pp->pt_inflip, pp->pt_inseg->seg_stp );
    if ( VDOT( rayp->norm, ap->a_ray.r_dir ) < 0 ) {
	bu_log(" debug: flipping curvature\n");
	rayp->curvature.crv_c1 = - rayp->curvature.crv_c1;
	rayp->curvature.crv_c2 = - rayp->curvature.crv_c2;
    }
    VMOVE( rayp->ip, hitp->hit_point );

    /* Compute the specular direction */
    VREVERSE( to_eye, ap->a_ray.r_dir );
    f = 2 * VDOT( to_eye, rayp->norm );
    VSCALE( work, rayp->norm, f );
    /* I have been told this has unit length */
    VSUB2( rayp->spec, work, to_eye );

    /* Save info for 1st ray */
    if ( ap->a_level == 0 ) {
	firstray = ap->a_ray;	/* struct copy */
	rayp->sight = 1;	/* the 1st intersect is always visible */
    } else {
	/* Check for visibility */
	rayp->sight = isvisible( ap, hitp, rayp->norm );
    }

    /*
     * Shoot another ray in the specular direction.
     */
    if ( ap->a_level < numreflect-1 ) {
	sub_ap = *ap;	/* struct copy */
	sub_ap.a_level = ap->a_level+1;
	VMOVE( sub_ap.a_ray.r_pt, hitp->hit_point );
	VMOVE( sub_ap.a_ray.r_dir, rayp->spec );
	depth = rt_shootray( &sub_ap );
    } else {
	bu_log( "radhit:  max reflections exceeded [%d %d]\n",
		ap->a_x, ap->a_y );
	depth = 0;
    }

    if ( ap->a_level == 0 ) {
	/* We're the 1st ray, output the raylist */
	dumpall( ap, depth+1 );
    }
    return(depth+1);	/* report hit to main routine */
}
コード例 #13
0
ファイル: revolve.c プロジェクト: kanzure/brlcad
/**
 * Given ONE ray distance, return the normal and entry/exit point.
 */
void
rt_revolve_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
{
    struct revolve_specific *rev =
	(struct revolve_specific *)stp->st_specific;
    vect_t n, nT;

    VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);

/*
  XXX debug printing
  VPRINT("hitp", hitp->hit_point);
  VPRINT("vpriv", hitp->hit_vpriv);
*/

    switch (hitp->hit_surfno) {
	case START_FACE_POS:
	    VREVERSE(hitp->hit_normal, rev->yUnit);
	    break;
	case START_FACE_NEG:
	    VMOVE(hitp->hit_normal, rev->yUnit);
	    break;
	case END_FACE_POS:
	    VCROSS(hitp->hit_normal, rev->zUnit, rev->rEnd);
	    VUNITIZE(hitp->hit_normal);
	    break;
	case END_FACE_NEG:
	    VCROSS(hitp->hit_normal, rev->rEnd, rev->zUnit);
	    VUNITIZE(hitp->hit_normal);
	    break;
	default:
	    VMOVE(n, hitp->hit_vpriv);
	    n[Z] *= sqrt((hitp->hit_vpriv[X] * hitp->hit_vpriv[X]) + (hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y]));

	    if (hitp->hit_surfno == HORIZ_SURF) {
		VSET(n, 0, 0, 1);
	    }

	    nT[X] = (rev->xUnit[X] * n[X])
		+ (rev->yUnit[X] * n[Y])
		+ (rev->zUnit[X] * n[Z]);
	    nT[Y] = (rev->xUnit[Y] * n[X])
		+ (rev->yUnit[Y] * n[Y])
		+ (rev->zUnit[Y] * n[Z]);
	    nT[Z] = (rev->xUnit[Z] * n[X])
		+ (rev->yUnit[Z] * n[Y])
		+ (rev->zUnit[Z] * n[Z]);

	    VUNITIZE(nT);

/* XXX Debug printing
   VPRINT("xUnit", rev->xUnit);
   VPRINT("yUnit", rev->yUnit);
   VPRINT("zUnit", rev->zUnit);
   VPRINT("n", n);
   VPRINT("nT", nT);
*/

	    if (VDOT(nT, rp->r_dir) < 0) {
		VMOVE(hitp->hit_normal, nT);
	    } else {
		VREVERSE(hitp->hit_normal, nT);
	    }
	    break;
    }
}
コード例 #14
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;
}
コード例 #15
0
ファイル: hyp.c プロジェクト: kanzure/brlcad
int
rt_hyp_plot(struct bu_list *vhead, struct rt_db_internal *incoming, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    int i, j;		/* loop indices */
    struct rt_hyp_internal *hyp_in;
    struct hyp_specific *hyp;
    vect_t majorAxis[8],	/* vector offsets along major axis */
	minorAxis[8],		/* vector offsets along minor axis */
	heightAxis[7],		/* vector offsets for layers */
	Bunit;			/* unit vector along semi-minor axis */
    vect_t ell[16];		/* stores 16 points to draw ellipses */
    vect_t ribs[16][7];		/* assume 7 layers for now */
    fastf_t scale;		/* used to calculate semi-major/minor axes for top/bottom */
    fastf_t cos22_5 = 0.9238795325112867385;
    fastf_t cos67_5 = 0.3826834323650898373;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(incoming);
    hyp_in = (struct rt_hyp_internal *)incoming->idb_ptr;
    RT_HYP_CK_MAGIC(hyp_in);

    hyp = hyp_internal_to_specific(hyp_in);

    VCROSS(Bunit, hyp->hyp_H, hyp->hyp_Au);
    VUNITIZE(Bunit);

    VMOVE(heightAxis[0], hyp->hyp_H);
    VSCALE(heightAxis[1], heightAxis[0], 0.5);
    VSCALE(heightAxis[2], heightAxis[0], 0.25);
    VSETALL(heightAxis[3], 0);
    VREVERSE(heightAxis[4], heightAxis[2]);
    VREVERSE(heightAxis[5], heightAxis[1]);
    VREVERSE(heightAxis[6], heightAxis[0]);

    for (i = 0; i < 7; i++) {
	/* determine Z height depending on i */
	scale = sqrt(MAGSQ(heightAxis[i])*(hyp->hyp_c * hyp->hyp_c)/(hyp->hyp_r1 * hyp->hyp_r1) + 1);

	/* calculate vectors for offset */
	VSCALE(majorAxis[0], hyp->hyp_Au, hyp->hyp_r1 * scale);
	VSCALE(majorAxis[1], majorAxis[0], cos22_5);
	VSCALE(majorAxis[2], majorAxis[0], M_SQRT1_2);
	VSCALE(majorAxis[3], majorAxis[0], cos67_5);
	VREVERSE(majorAxis[4], majorAxis[3]);
	VREVERSE(majorAxis[5], majorAxis[2]);
	VREVERSE(majorAxis[6], majorAxis[1]);
	VREVERSE(majorAxis[7], majorAxis[0]);

	VSCALE(minorAxis[0], Bunit, hyp->hyp_r2 * scale);
	VSCALE(minorAxis[1], minorAxis[0], cos22_5);
	VSCALE(minorAxis[2], minorAxis[0], M_SQRT1_2);
	VSCALE(minorAxis[3], minorAxis[0], cos67_5);
	VREVERSE(minorAxis[4], minorAxis[3]);
	VREVERSE(minorAxis[5], minorAxis[2]);
	VREVERSE(minorAxis[6], minorAxis[1]);
	VREVERSE(minorAxis[7], minorAxis[0]);

	/* calculate ellipse */
	VADD3(ell[ 0], hyp->hyp_V, heightAxis[i], majorAxis[0]);
	VADD4(ell[ 1], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[3]);
	VADD4(ell[ 2], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[2]);
	VADD4(ell[ 3], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[1]);
	VADD3(ell[ 4], hyp->hyp_V, heightAxis[i], minorAxis[0]);
	VADD4(ell[ 5], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[1]);
	VADD4(ell[ 6], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[2]);
	VADD4(ell[ 7], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[3]);
	VADD3(ell[ 8], hyp->hyp_V, heightAxis[i], majorAxis[7]);
	VADD4(ell[ 9], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[4]);
	VADD4(ell[10], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[5]);
	VADD4(ell[11], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[6]);
	VADD3(ell[12], hyp->hyp_V, heightAxis[i], minorAxis[7]);
	VADD4(ell[13], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[6]);
	VADD4(ell[14], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[5]);
	VADD4(ell[15], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[4]);

	/* draw ellipse */
	RT_ADD_VLIST(vhead, ell[15], BN_VLIST_LINE_MOVE);
	for (j = 0; j < 16; j++) {
	    RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
	}

	/* add ellipse's points to ribs */
	for (j = 0; j < 16; j++) {
	    VMOVE(ribs[j][i], ell[j]);
	}
    }

    /* draw ribs */
    for (i = 0; i < 16; i++) {
	RT_ADD_VLIST(vhead, ribs[i][0], BN_VLIST_LINE_MOVE);
	for (j = 1; j < 7; j++) {
	    RT_ADD_VLIST(vhead, ribs[i][j], BN_VLIST_LINE_DRAW);
	}

    }

    BU_PUT(hyp, struct hyp_specific);

    return 0;
}
コード例 #16
0
ファイル: poly.c プロジェクト: cogitokat/brlcad
/**
 * R T _ P G _ S H O T
 *
 * Function -
 * Shoot a ray at a polygonal object.
 *
 * Returns -
 * 0 MISS
 * >0 HIT
 */
int
rt_pg_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
{
    struct tri_specific *trip =
	(struct tri_specific *)stp->st_specific;
#define MAXHITS 128		/* # surfaces hit, must be even */
    struct hit hits[MAXHITS];
    struct hit *hp;
    size_t nhits;

    nhits = 0;
    hp = &hits[0];

    /* consider each face */
    for (; trip; trip = trip->tri_forw) {
	fastf_t dn;		/* Direction dot Normal */
	fastf_t abs_dn;
	fastf_t k;
	fastf_t alpha, beta;
	vect_t wxb;		/* vertex - ray_start */
	vect_t xp;		/* wxb cross ray_dir */

	/*
	 * Ray Direction dot N.  (N is outward-pointing normal)
	 * wn points inwards, and is not unit length.
	 */
	dn = VDOT(trip->tri_wn, rp->r_dir);

	/*
	 * If ray lies directly along the face, (i.e., dot product
	 * is zero), drop this face.
	 */
	abs_dn = dn >= 0.0 ? dn : (-dn);
	if (abs_dn < SQRT_SMALL_FASTF)
	    continue;
	VSUB2(wxb, trip->tri_A, rp->r_pt);
	VCROSS(xp, wxb, rp->r_dir);

	/* Check for exceeding along the one side */
	alpha = VDOT(trip->tri_CA, xp);
	if (dn < 0.0) alpha = -alpha;
	if (alpha < 0.0 || alpha > abs_dn)
	    continue;

	/* Check for exceeding along the other side */
	beta = VDOT(trip->tri_BA, xp);
	if (dn > 0.0) beta = -beta;
	if (beta < 0.0 || beta > abs_dn)
	    continue;
	if (alpha+beta > abs_dn)
	    continue;
	k = VDOT(wxb, trip->tri_wn) / dn;

	/* For hits other than the first one, might check
	 * to see it this is approx. equal to previous one */

	/* If dn < 0, we should be entering the solid.
	 * However, we just assume in/out sorting later will work.
	 * Really should mark and check this!
	 */
	VJOIN1(hp->hit_point, rp->r_pt, k, rp->r_dir);

	/* HIT is within planar face */
	hp->hit_magic = RT_HIT_MAGIC;
	hp->hit_dist = k;
	VMOVE(hp->hit_normal, trip->tri_N);
	hp->hit_surfno = trip->tri_surfno;
	if (++nhits >= MAXHITS) {
	    bu_log("rt_pg_shot(%s): too many hits (%zu)\n", stp->st_name, nhits);
	    break;
	}
	hp++;
    }
    if (nhits == 0)
	return 0;		/* MISS */

    /* Sort hits, Near to Far */
    rt_hitsort(hits, nhits);

    /* Remove duplicate hits.
       We remove one of a pair of hits when they are
       1) close together, and
       2) both "entry" or both "exit" occurrences.
       Two immediate "entry" or two immediate "exit" hits suggest
       that we hit both of two joined faces, while we want to hit only
       one.  An "entry" followed by an "exit" (or vice versa) suggests
       that we grazed an edge, and thus we should leave both
       in the hit list. */

    {
	size_t i, j;

	for (i=0; i<nhits-1; i++) {
	    fastf_t dist;

	    dist = hits[i].hit_dist - hits[i+1].hit_dist;
	    if (NEAR_ZERO(dist, ap->a_rt_i->rti_tol.dist) &&
		VDOT(hits[i].hit_normal, rp->r_dir) *
		VDOT(hits[i+1].hit_normal, rp->r_dir) > 0)
	    {
		for (j=i; j<nhits-1; j++)
		    hits[j] = hits[j+1];
		nhits--;
		i--;
	    }
	}
    }


    if (nhits == 1)
	nhits = 0;

    if (nhits&1) {
	size_t i;
	static int nerrors = 0;		/* message counter */
	/*
	 * If this condition exists, it is almost certainly due to
	 * the dn==0 check above.  Thus, we will make the last
	 * surface rather thin.
	 * This at least makes the
	 * presence of this solid known.  There may be something
	 * better we can do.
	 */

	if (nerrors++ < 6) {
	    bu_log("rt_pg_shot(%s): WARNING %zu hits:\n", stp->st_name, nhits);
	    bu_log("\tray start = (%g %g %g) ray dir = (%g %g %g)\n",
		   V3ARGS(rp->r_pt), V3ARGS(rp->r_dir));
	    for (i=0; i < nhits; i++) {
		point_t tmp_pt;

		VJOIN1(tmp_pt, rp->r_pt, hits[i].hit_dist, rp->r_dir);
		if (VDOT(rp->r_dir, hits[i].hit_normal) < 0.0)
		    bu_log("\tentrance at dist=%f (%g %g %g)\n", hits[i].hit_dist, V3ARGS(tmp_pt));
		else
		    bu_log("\texit at dist=%f (%g %g %g)\n", hits[i].hit_dist, V3ARGS(tmp_pt));
	    }
	}

	if (nhits > 2) {
	    fastf_t dot1, dot2;
	    size_t j;

	    /* likely an extra hit,
	     * look for consecutive entrances or exits */

	    dot2 = 1.0;
	    i = 0;
	    while (i<nhits) {
		dot1 = dot2;
		dot2 = VDOT(rp->r_dir, hits[i].hit_normal);
		if (dot1 > 0.0 && dot2 > 0.0) {
		    /* two consecutive exits,
		     * manufacture an entrance at same distance
		     * as second exit.
		     */
		    for (j=nhits; j>i; j--)
			hits[j] = hits[j-1];	/* struct copy */

		    VREVERSE(hits[i].hit_normal, hits[i].hit_normal);
		    dot2 = VDOT(rp->r_dir, hits[i].hit_normal);
		    nhits++;
		    bu_log("\t\tadding fictitious entry at %f (%s)\n", hits[i].hit_dist, stp->st_name);
		} else if (dot1 < 0.0 && dot2 < 0.0) {
		    /* two consecutive entrances,
		     * manufacture an exit between them.
		     */

		    for (j=nhits; j>i; j--)
			hits[j] = hits[j-1];	/* struct copy */

		    hits[i] = hits[i-1];	/* struct copy */
		    VREVERSE(hits[i].hit_normal, hits[i-1].hit_normal);
		    dot2 = VDOT(rp->r_dir, hits[i].hit_normal);
		    nhits++;
		    bu_log("\t\tadding fictitious exit at %f (%s)\n", hits[i].hit_dist, stp->st_name);
		}
		i++;
	    }

	} else {
	    hits[nhits] = hits[nhits-1];	/* struct copy */
	    VREVERSE(hits[nhits].hit_normal, hits[nhits-1].hit_normal);
	    bu_log("\t\tadding fictitious hit at %f (%s)\n", hits[nhits].hit_dist, stp->st_name);
	    nhits++;
	}
    }

    if (nhits&1) {
	if (nhits < MAXHITS) {
	    hits[nhits] = hits[nhits-1];	/* struct copy */
	    VREVERSE(hits[nhits].hit_normal, hits[nhits-1].hit_normal);
	    bu_log("\t\tadding fictitious hit at %f (%s)\n", hits[nhits].hit_dist, stp->st_name);
	    nhits++;
	} else
	    nhits--;
    }

    /* nhits is even, build segments */
    {
	struct seg *segp;
	size_t i;
	for (i=0; i < nhits; i += 2) {
	    RT_GET_SEG(segp, ap->a_resource);
	    segp->seg_stp = stp;
	    segp->seg_in = hits[i];		/* struct copy */
	    segp->seg_out = hits[i+1];	/* struct copy */
	    BU_LIST_INSERT(&(seghead->l), &(segp->l));
	}
    }
    return nhits;			/* HIT */
}
コード例 #17
0
ファイル: shapefact.c プロジェクト: cciechad/brlcad
/*  User supplied hit function.  */
int
hit(register struct application *ap_p, struct partition *PartHeadp, struct seg *segp)
{
    /*  START # 0H  */
    extern struct table info[];	/*  Structure is external.  */
    register struct partition *pp;
    register struct hit *hitp;
    register struct soltab *stp;
    int icur=0;			/*  Current region hit.  */
    int iprev;			/*  Previous region hit.  */
    int iair;			/*  Type of air or region came from,  */
				/*  0=>region, 1=>exterior air, 2=>crew  */
				/*  air, 5=>engine air, 6=>closed  */
				/*  compartment air, 7=>exhaust air,  */
				/*  8=>generic air 1, 9=>generic air 2.  */

    /*
     * (void)printf("In hit function.\n");
     * (void)fflush(stdout);
     */

    /*  Set beginning parameters.  */
    iprev = -1;
    iair = 1;		/*  Comes from exterior air.  */

    /*
     * (void)printf("Beginning loop again.\n");
     * (void)fflush(stdout);
     */

    pp = PartHeadp->pt_forw;
    for (; pp != PartHeadp;  pp = pp->pt_forw)
    {
	/*  START # 1H  */
	/*
	 *	(void)printf("Region %d - %s - %d - %d - %d - \n",
	 *		pp->pt_regionp->reg_bit,
	 *		info[(int)pp->pt_regionp->reg_bit].name,
	 *		pp->pt_regionp->reg_gmater,
	 *		pp->pt_regionp->reg_aircode,
	 *		pp->pt_regionp->reg_regionid);
	 *	(void)fflush(stdout);
	 */

	if (iair == 1)	/*  Ray comes from nothing (exterior air).  */
	{
	    /*  START # 2H  */
	    /*
	     *	   (void)printf("Ray comes from exterior air (1).\n");
	     *	   (void)fflush(stdout);
	     */

	    if (pp->pt_regionp->reg_regionid > (short)0)	/*  Hit region.  */
	    {
		/*  START # 3H  */
		/*  Region number hit.  */
		icur = (int)(pp->pt_regionp->reg_bit);

		/*  Find leaving point.  */
		hitp = pp->pt_outhit;
		stp = pp->pt_outseg->seg_stp;
		RT_HIT_NORM(hitp, stp, &(ap_p->a_ray));
		/*  Flip normal if needed.  */
		if (pp->pt_outflip)
		{
		    VREVERSE(hitp->hit_normal, hitp->hit_normal);
		    pp->pt_outflip = 0;
		}
		iprev = icur;
		iair = 0;	/*  A region was just hit.  */
	    }					/*  END # 3H  */

	    else	/*  Hit air.  */
	    {
		/*  START # 4H  */
		iair = pp->pt_regionp->reg_aircode;
	    }					/*  END # 4H  */
	}					/*  END # 2H  */

	else if (iair == 5)	/*  Ray comes from engine air.  */
	{
	    /*  START # 5H  */
	    /*
	     *	   (void)printf("Ray comes from engine air (5).\n");
	     *	   (void)fflush(stdout);
	     */

	    if (pp->pt_regionp->reg_regionid > (short)0)	/*  Hit region.  */
	    {
		/*  START # 6H  */
		/*  Region number hit.  */
		icur = (int)(pp->pt_regionp->reg_bit);

		/*  Only execute the following two statements if iprev >= 0.  */
		if (iprev < (-1))
		{
		    (void)fprintf(stderr, "ERROR -- iprev = %d\n", iprev);
		    (void)fflush(stderr);
		}
		if (iprev == (-1))
		{
		    (void)fprintf(stderr, "iprev = %d - entered ", iprev);
		    (void)fprintf(stderr, "through engine air\n");
		    (void)fflush(stderr);
		}
		if (iprev > (-1))
		{
		    /*  Add one to number of rays leaving previous region.  */
		    info[iprev].lvrays++;

		    /*  Add one to the number of rays leaving current region  */
		    /*  for the backward ray.  */
		    info[icur].lvrays++;

		    /*  Add one to number of rays leaving previous region and  */
		    /*  intercepted by current region.  */
		    info[iprev].intrays[icur]++;

		    /*  Add one to the number of rays leaving the current  */
		    /*  region and intersecting the previous region for the  */
		    /*  backward ray.  */
		    info[icur].intrays[iprev]++;

		}

		/*  Find leave point.  */
		hitp = pp->pt_outhit;
		stp = pp->pt_outseg->seg_stp;
		RT_HIT_NORM(hitp, stp, &(ap_p->a_ray));
		/*  Flip normal if needed.  */
		if (pp->pt_outflip)
		{
		    VREVERSE(hitp->hit_normal, hitp->hit_normal);
		    pp->pt_outflip = 0;
		}
		iprev = icur;
		iair = 0;	/*  Hit a region.  */
	    }					/*  END # 6H  */

	    else	/*  Hit air.  */
	    {
		iair = 5;	/*  Since coming through engine air  */
		/*  assume should still be engine air.  */
	    }
	}					/*  END # 5H  */

	else if (iair == 0)	/*  Ray comes from a region.  */
	{
	    /*  START # 7H  */
	    /*
	     *	   (void)printf("Ray comes from region (0).\n");
	     *	   (void)fflush(stdout);
	     */

	    if (pp->pt_regionp->reg_regionid > (short)0)	/*  Hit a region.  */
	    {
		/*  START # 8H  */
		/*  Region number hit.  */
		icur = (int)(pp->pt_regionp->reg_bit);

		/*  Find leaving point.  */
		hitp = pp->pt_outhit;
		stp = pp->pt_outseg->seg_stp;
		RT_HIT_NORM(hitp, stp, &(ap_p->a_ray));
		/*  Flip normal if needed.  */
		if (pp->pt_outflip)
		{
		    VREVERSE(hitp->hit_normal, hitp->hit_normal);
		    pp->pt_outflip = 0;
		}
		iprev = icur;
		iair = 0;	/*  Hit a region.  */
	    }					/*  END # 8H  */

	    else	/*  Hit air.  */
	    {
		/*  START # 9H  */
		/*  Increment allvrays if the ray is leaving through  */
		/*  engine air.  Make sure this is only done once.  */
		if ( (iair != 5) && (pp->pt_regionp->reg_aircode == 5) )
		    info[icur].allvrays++;

		if (iair != 5) iair = pp->pt_regionp->reg_aircode;
	    }					/*  END # 9H  */
	}					/*  END # 7H  */

	else	/*  Ray comes from any interior air.  */
	{
	    /*  START # 10H  */
	    /*
	     *	   (void)printf("Ray comes from interior air (not 0, 1, 5).\n");
	     *	   (void)fflush(stdout);
	     */

	    if (pp->pt_regionp->reg_regionid > (short)0)	/*  Hits region.  */
	    {
		/*  START # 11H  */
		/*  Region number hit.  */
		icur = (int)(pp->pt_regionp->reg_bit);

		/*  Find leaving point.  */
		hitp = pp->pt_outhit;
		stp = pp->pt_outseg->seg_stp;
		RT_HIT_NORM(hitp, stp, &(ap_p->a_ray));
		/*  Flip normal if needed.  */
		if (pp->pt_outflip)
		{
		    VREVERSE(hitp->hit_normal, hitp->hit_normal);
		    pp->pt_outflip = 0;
		}
		iprev = icur;
		iair = 0;	/*  Hit region.  */
	    }					/*  END # 11H  */

	    else	/*  Hits air.  */
	    {
		iair = pp->pt_regionp->reg_aircode;
	    }
	}					/*  END # 10H  */
    }						/*  END # 1H  */

    if (iprev == (-1) )		/*  Went through air only.  */
    {
	return(1);		/*  Indicates miss.  */
    }

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

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


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

    RT_CK_TREE(rp->reg_treetop);

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

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


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

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

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

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


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

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

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

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

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

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

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

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

	img_num++;
    }

    rt_db_free_internal(&intern);

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

    return 1;
}
コード例 #19
0
ファイル: anim_hardtrack.c プロジェクト: cciechad/brlcad
int track_prep(void)/*run once at the beginning to establish important track info*/
{
    int i;
    fastf_t phi, costheta, link_angle, arc_angle;
    vect_t difference, link_cent;

    /* first loop - get inter axle slopes and start/end angles */
    for (i=0;i<NW;i++) {
	/*calculate current slope vector*/
	VSUB2(x[i].s.dir, x[i].w.pos, x[PREV(i)].w.pos);
	x[i].s.len = MAGNITUDE(x[i].s.dir);
	/*calculate end angle of previous wheel - atan2(y, x)*/
	phi = atan2(x[i].s.dir[2], x[i].s.dir[0]);/*absolute angle of slope*/
	costheta = (x[PREV(i)].w.rad - x[i].w.rad)/x[i].s.len;/*cosine of special angle*/
	x[PREV(i)].w.ang1 = phi +  acos(costheta);
	while (x[PREV(i)].w.ang1 < 0.0)
	    x[PREV(i)].w.ang1 += 2.0*M_PI;
	x[i].w.ang0 = x[PREV(i)].w.ang1;
    }

    /* second loop - handle concavities */
    for (i=0;i<NW;i++) {
	arc_angle = x[i].w.ang0 - x[i].w.ang1;
	while (arc_angle < 0.0)
	    arc_angle += 2.0*M_PI;
	if (arc_angle > M_PI) {
	    /* concave */
	    x[i].w.ang0 = 0.5*(x[i].w.ang0 + x[i].w.ang1);
	    x[i].w.ang1 = x[i].w.ang0;
	    x[i].w.arc = 0.0;
	}
	else {
	    /* convex - angles are already correct */
	    x[i].w.arc = arc_angle;
	}
    }

    /* third loop - calculate geometry of track segments */
    tracklen = 0.0;
    for (i=0;i<NW;i++) {
	/*calculate endpoints of track segment*/
	x[i].t.pos1[0] = x[i].w.pos[0] + x[i].w.rad*cos(x[i].w.ang0);
	x[i].t.pos1[1] = x[i].w.pos[1];
	x[i].t.pos1[2] = x[i].w.pos[2] + x[i].w.rad*sin(x[i].w.ang0);
	x[i].t.pos0[0] = x[PREV(i)].w.pos[0] + x[PREV(i)].w.rad*cos(x[PREV(i)].w.ang1);
	x[i].t.pos0[1] = x[PREV(i)].w.pos[1];
	x[i].t.pos0[2] = x[PREV(i)].w.pos[2] + x[PREV(i)].w.rad*sin(x[PREV(i)].w.ang1);
	/*calculate length and direction*/
	VSUB2(difference, x[i].t.pos1, x[i].t.pos0);
	x[i].t.len = MAGNITUDE(difference);
	VSCALE((x[i].t.dir), difference, (1.0/x[i].t.len));

	/*calculate arclength and total track length*/
	tracklen += x[i].t.len;
	tracklen += x[i].w.arc*x[i].w.rad;
    }

    /* for a track with links already placed, get initial positions*/
    r = (struct rlink *) bu_calloc(num_links, sizeof(struct rlink), "struct rlink");
    if (links_placed)
	for (i=0;i<num_links;i++) {
	    get_link(link_cent, &link_angle, init_dist + tracklen*i/num_links);
	    VREVERSE(r[i].pos, link_cent);
	    r[i].ang = -link_angle;
	}
    return(0);
}
コード例 #20
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);
}
コード例 #21
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);
}
コード例 #22
0
ファイル: all_sf.c プロジェクト: cciechad/brlcad
/*  User supplied hit function.  */
int
hit(register struct application *ap_p, struct partition *PartHeadp, struct seg *segp)
{
    /*  START # 1000  */
    register struct partition *pp;
    register struct hit *hitp;
    register struct soltab *stp;

    int rh1;		/*  1st region hit (leaving region).  */
    int rh2;		/*  2nd region hit (entering region).  */
    double lvpt[3];	/*  Leaving point of 1st region.  */
    double entpt[3];	/*  Entering point of 2nd region.  */
    double tol[3];	/*  Used to check tolerance of equal numbers.  */

    /*
     * (void)fprintf(fpw1, "In function hit.\n");
     * (void)fflush(fpw1);
     */

    /*  Set regions hit to -1 to show no regions hit yet.  */
    rh1 = (-1);
    rh2 = (-1);

    /*  Set leave & enter points to show no hits yet.  */
    lvpt[X] = (-999.);
    lvpt[Y] = (-999.);
    lvpt[Z] = (-999.);
    entpt[X] = (-999.);
    entpt[Y] = (-999.);
    entpt[Z] = (-999.);

    /*  Set for first region.  */
    pp = PartHeadp->pt_forw;

    for (; pp != PartHeadp; pp=pp->pt_forw)
    {
        /*  START # 1010  */
        if ( (rh1 == (-1)) && (rh2 == (-1)) )
        {
            /*  START # 1020  */
            /*  First time through; therefore, find the region hit for  */
            /*  the first region.  */

            rh1 = (int)pp->pt_regionp->reg_bit;

            /*  Find the leave point of the first region.  */
            hitp = pp->pt_outhit;
            stp = pp->pt_outseg->seg_stp;
            RT_HIT_NORM(hitp, stp, &(ap_p->a_ray));
            /*  Flip normal if needed.  */
            if (pp->pt_outflip)
            {
                VREVERSE(hitp->hit_normal, hitp->hit_normal);
                pp->pt_outflip = 0;
            }
            lvpt[X] = hitp->hit_point[X];
            lvpt[Y] = hitp->hit_point[Y];
            lvpt[Z] = hitp->hit_point[Z];

            /*  Increment backwards for hitting ray.  */
            info[rh1].lvrays += 1.;

        }						/*  END # 1020  */

        else
        {
            /*  START # 1030  */
            /*  Any time but the first time through.  Find the region hit  */
            /*  for the second region.  */
            rh2 = (int)pp->pt_regionp->reg_bit;

            /*  Find the enter point for the second region.  */
            hitp = pp->pt_inhit;
            stp = pp->pt_inseg->seg_stp;
            RT_HIT_NORM(hitp, stp, &(ap_p->a_ray));
            /*  Flip normal if needed.  */
            if (pp->pt_inflip)
            {
                VREVERSE(hitp->hit_normal, hitp->hit_normal);
                pp->pt_inflip = 0;
            }
            entpt[X] = hitp->hit_point[X];
            entpt[Y] = hitp->hit_point[Y];
            entpt[Z] = hitp->hit_point[Z];

            /*  Check if the leave & enter point are the same.  */
            tol[X] = lvpt[X] - entpt[X];
            tol[Y] = lvpt[Y] - entpt[Y];
            tol[Z] = lvpt[Z] - entpt[Z];
            if (tol[X] < 0.) tol[X] = (-tol[X]);
            if (tol[Y] < 0.) tol[Y] = (-tol[Y]);
            if (tol[Z] < 0.) tol[Z] = (-tol[Z]);

            if ( (tol[X] < VDIVIDE_TOL) && (tol[Y] < VDIVIDE_TOL) && (tol[Z] < VDIVIDE_TOL) )
            {
                /*  Nothing happens since the points are the same.  */
            }

            else
            {
                /*  START # 1040  */
                /*  The points are not the same; therefore, increment  */
                /*  appropriately.  */
                info[rh1].lvrays += 1.;
                info[rh1].intrays[rh2] += 1.;

                /*  Increment backwards also.  */
                info[rh2].lvrays += 1.;
                info[rh2].intrays[rh1] += 1.;
            }						/*  END # 1040  */

            /*  Find info for 1st region.  */
            rh1 = rh2;
            /*  Find leaving point.  */
            hitp = pp->pt_outhit;
            stp = pp->pt_outseg->seg_stp;
            RT_HIT_NORM(hitp, stp, &(ap_p->a_ray));
            /*  Flip normal if needed.  */
            if (pp->pt_outflip)
            {
                VREVERSE(hitp->hit_normal, hitp->hit_normal);
                pp->pt_outflip = 0;
            }
            lvpt[X] = hitp->hit_point[X];
            lvpt[Y] = hitp->hit_point[Y];
            lvpt[Z] = hitp->hit_point[Z];

        }						/*  END # 1030  */
    }							/*  END # 1010  */

    /*  Increment the leaving ray since it leaves & doesn't hit anything.  */
    info[rh1].lvrays += 1.;

    return(0);
}							/*  END # 1000  */
コード例 #23
0
ファイル: anim_hardtrack.c プロジェクト: cciechad/brlcad
int get_args(int argc, char **argv)
{
    fastf_t yaw, pch, rll;
    void anim_dx_y_z2mat(fastf_t *, double, double, double), anim_dz_y_x2mat(fastf_t *, double, double, double);
    int c, i;
    axes = cent = links_placed = print_wheel = print_link = 0;
    get_circumf = 0;
    print_mode = TRACK_ANIM;
    bu_strlcpy(link_cmd, "rarc", sizeof(link_cmd));
    bu_strlcpy(wheel_cmd, "lmul", sizeof(wheel_cmd));
    while ( (c=bu_getopt(argc, argv, OPT_STR)) != EOF) {
	i=0;
	switch (c) {
	    case 'b':
		bu_optind -= 1;
		sscanf(argv[bu_optind+(i++)], "%lf", &yaw );
		sscanf(argv[bu_optind+(i++)], "%lf", &pch );
		sscanf(argv[bu_optind+(i++)], "%lf", &rll );
		bu_optind += 3;
		anim_dx_y_z2mat(m_axes, rll, -pch, yaw);
		anim_dz_y_x2mat(m_rev_axes, -rll, pch, -yaw);
		axes = 1;
		break;
	    case 'd':
		bu_optind -= 1;
		sscanf(argv[bu_optind+(i++)], "%lf", centroid);
		sscanf(argv[bu_optind+(i++)], "%lf", centroid+1);
		sscanf(argv[bu_optind+(i++)], "%lf", centroid+2);
		bu_optind += 3;
		VREVERSE(rcentroid, centroid);
		cent = 1;
		break;
	    case 'f':
		sscanf(bu_optarg, "%d", &first_frame);
		break;
	    case 'i':
		sscanf(bu_optarg, "%lf", &init_dist);
		break;
	    case 'p':
		links_placed = 1;
		break;
	    case 'r':
		sscanf(bu_optarg, "%lf", &radius);
		break;
	    case 'w':
		wheel_nindex = bu_optind - 1;
		/*sscanf(bu_optarg, "%s", wheel_name);*/
		print_wheel = 1;
		break;
	    case 'l':
		sscanf(bu_optarg, "%d", &num_links);
		link_nindex = bu_optind;
		bu_optind += 1;
		print_link = 1;
		break;
	    case 's':
		steer = 1;
		break;
	    case 'g':
		sscanf(bu_optarg, "%d", &arced_frame);
		print_mode = TRACK_ARCED;
		break;
	    case 'm':
		switch (*bu_optarg) {
		    case 'l':
			bu_strlcpy(link_cmd, argv[bu_optind], sizeof(link_cmd));
			break;
		    case 'w':
			bu_strlcpy(wheel_cmd, argv[bu_optind], sizeof(wheel_cmd));
			break;
		    default:
			fprintf(stderr, "Unknown option: -m%c\n", *bu_optarg);
			return(0);
		}
		bu_optind += 1;
		break;
	    case 'c':
		get_circumf = 1;
		break;
	    default:
		fprintf(stderr, "Unknown option: -%c\n", c);
		return(0);
	}
    }
    return(1);
}
コード例 #24
0
void writeRingModeBox
(
    rt_wdb* wdbp,
    Form&   form,
    bool    translate
) {
    char name[NAMELEN + 1];

    // get the transformed outer points
    vect_t outer[MAX_NPTS];

    if (translate) {
	for (size_t i = 0; i < form.npts; ++i)
	  VADD2(outer[i], form.data.pt[i], form.tr_vec);
    } else {
      for (size_t i = 0; i < form.npts; ++i) {
	  VMOVE(outer[i], form.data.pt[i]);
      }
    }

    for (size_t i1 = 0; i1 < form.npts; ++i1) {
      VSCALE(outer[i1], outer[i1], IntavalUnitInMm);
    }

    // compute inner points
    vect_t inner[MAX_NPTS];

    for (size_t i2 = 0; i2 < form.npts; ++i2) {
	vect_t a, b, c;

	VMOVE(a, outer[i2]);
	if (i2 == 0) {
	  VMOVE(b, outer[i2 + 1]);
	  VMOVE(c, outer[form.npts-1]);
	} else if (i2 == form.npts-1) {
	  VMOVE(b, outer[0]);
	  VMOVE(c, outer[i2 - 1]);
	} else {
	  VMOVE(b, outer[i2 + 1]);
	  VMOVE(c, outer[i2 - 1]);
	}

	vect_t b_v, c_v;
	VSUB2(b_v, b, a);
	VSUB2(c_v, c, a);

	vect_t n_v;
	VCROSS(n_v, b_v, c_v);

	// with on b_v
	vect_t width_b_v;
	VCROSS(width_b_v, b_v, n_v);

	if (VDOT(width_b_v, c_v) < 0)
	  VREVERSE(width_b_v, width_b_v);

	VUNITIZE(width_b_v);
	VSCALE(width_b_v, width_b_v, form.width * IntavalUnitInMm);

	// with on c_v
	vect_t width_c_v;
	VCROSS(width_c_v, c_v, n_v);

	if (VDOT(width_c_v, b_v) < 0)
	  VREVERSE(width_c_v, width_c_v);

	VUNITIZE(width_c_v);
	VSCALE(width_c_v, width_c_v, form.width * IntavalUnitInMm);

	// intersection
	VUNITIZE(b_v);
	VUNITIZE(c_v);

	vect_t cb_v;
	VSUB2(cb_v, b_v, c_v);
	fastf_t l_cb_v = MAGNITUDE(cb_v);

	if (!NEAR_ZERO(l_cb_v, VUNITIZE_TOL)) {
	    vect_t width_cb_v;
	    VSUB2(width_cb_v, width_b_v, width_c_v);

	    vect_t s_b_v;
	    VSCALE(s_b_v, b_v, MAGNITUDE(width_cb_v) / l_cb_v);

	    vect_t res;
	    VADD2(res, a, width_c_v);
	    VADD2(res, res, s_b_v);

	    VMOVE(inner[i2], res);
	} else {
	  VMOVE(inner[i2], outer[i2]);
	}
    }

    // bot parameters
    // vertices
    size_t num_vertices = 0;
    size_t outer_i[MAX_NPTS];
    size_t inner_i[MAX_NPTS];
    fastf_t vertices[MAX_NPTS * 3];

    for (size_t i3 = 0; i3 < form.npts; ++i3) {
	size_t i = 0;

	// outer
	// search for duplicate vertex
	for (; i < num_vertices; ++i) {
	  if (NEAR_EQUAL(outer[i3][0], vertices[3 * i], VUNITIZE_TOL) &&
	      NEAR_EQUAL(outer[i3][1], vertices[3 * i + 1], VUNITIZE_TOL) &&
	      NEAR_EQUAL(outer[i3][2], vertices[3 * i + 2], VUNITIZE_TOL)) {
		outer_i[i3] = i;
		break;
	    }
	}

	if (i == num_vertices) {
	    // add a new vertex
	    vertices[num_vertices * 3]     = outer[i3][0];
	    vertices[num_vertices * 3 + 1] = outer[i3][1];
	    vertices[num_vertices * 3 + 2] = outer[i3][2];

	    outer_i[i3] = num_vertices;
	    ++num_vertices;
	}

	// inner
	// search for duplicate vertex
	for (i = 0; i < num_vertices; ++i) {
	    if (NEAR_EQUAL(inner[i3][0], vertices[3 * i], VUNITIZE_TOL) &&
		NEAR_EQUAL(inner[i3][1], vertices[3 * i + 1], VUNITIZE_TOL) &&
		NEAR_EQUAL(inner[i3][2], vertices[3 * i + 2], VUNITIZE_TOL)) {
		inner_i[i3] = i;
		break;
	    }
	}

	if (i == num_vertices) {
	    // add a new vertex
	    vertices[num_vertices * 3]     = inner[i3][0];
	    vertices[num_vertices * 3 + 1] = inner[i3][1];
	    vertices[num_vertices * 3 + 2] = inner[i3][2];

	    inner_i[i3] = num_vertices;
	    ++num_vertices;
	}
    }

    // faces
    size_t num_faces = 0;
    int faces[MAX_TRIANGLES * 3];

    for (size_t i4 = 0; i4 < form.npts; ++i4) {
	size_t nextIndex = (i4 + 1) % form.npts;

	addTriangle(faces, num_faces, outer_i[i4], outer_i[nextIndex], inner_i[i4]);
	addTriangle(faces, num_faces, inner_i[i4], outer_i[nextIndex], inner_i[nextIndex]);
    }

    fastf_t thickness[MAX_TRIANGLES];

    for (size_t i5 = 0; i5 < num_faces; ++i5)
	thickness[i5] = form.thickness * IntavalUnitInMm;

    bu_bitv* faceMode = bu_bitv_new(num_faces);

    sprintf(name, "s%lu.pbot", (long unsigned)++bot_counter);

    mk_bot(wdbp,
	   name,
	   RT_BOT_PLATE,
	   RT_BOT_UNORIENTED,
	   0,
	   num_vertices,
	   num_faces,
	   vertices,
	   faces,
	   thickness,
	   faceMode);

    addToRegion(form.compnr, name);

    if (form.s_compnr >= 1000)
	excludeFromRegion(form.s_compnr, name);

    bu_bitv_free(faceMode);
}
コード例 #25
0
ファイル: sh_scloud.c プロジェクト: kanzure/brlcad
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;
}
コード例 #26
0
ファイル: hyp_brep.cpp プロジェクト: kanzure/brlcad
extern "C" void
rt_hyp_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *)
{
    struct rt_hyp_internal *eip;

    RT_CK_DB_INTERNAL(ip);
    eip = (struct rt_hyp_internal *)ip->idb_ptr;
    RT_HYP_CK_MAGIC(eip);

    point_t p1_origin, p2_origin;
    ON_3dPoint plane1_origin, plane2_origin;
    ON_3dVector plane_x_dir, plane_y_dir;

    //  First, find planes corresponding to the top and bottom faces - initially

    vect_t x_dir, y_dir;
    VMOVE(x_dir, eip->hyp_A);
    VCROSS(y_dir, eip->hyp_A, eip->hyp_Hi);
    VREVERSE(y_dir, y_dir);

    VMOVE(p1_origin, eip->hyp_Vi);
    plane1_origin = ON_3dPoint(p1_origin);
    plane_x_dir = ON_3dVector(x_dir);
    plane_y_dir = ON_3dVector(y_dir);
    const ON_Plane hyp_bottom_plane(plane1_origin, plane_x_dir, plane_y_dir);

    VADD2(p2_origin, eip->hyp_Vi, eip->hyp_Hi);
    plane2_origin = ON_3dPoint(p2_origin);
    const ON_Plane hyp_top_plane(plane2_origin, plane_x_dir, plane_y_dir);

    // Next, create ellipses in the planes corresponding to the edges of the hyp

    ON_Ellipse b_ell(hyp_bottom_plane, MAGNITUDE(eip->hyp_A), eip->hyp_b);
    ON_NurbsCurve* bcurve = ON_NurbsCurve::New();
    b_ell.GetNurbForm((*bcurve));
    bcurve->SetDomain(0.0, 1.0);

    ON_Ellipse t_ell(hyp_top_plane, MAGNITUDE(eip->hyp_A), eip->hyp_b);
    ON_NurbsCurve* tcurve = ON_NurbsCurve::New();
    t_ell.GetNurbForm((*tcurve));
    tcurve->SetDomain(0.0, 1.0);

    // Generate the bottom cap
    ON_SimpleArray<ON_Curve*> boundary;
    boundary.Append(ON_Curve::Cast(bcurve));
    ON_PlaneSurface* bp = new ON_PlaneSurface();
    bp->m_plane = hyp_bottom_plane;
    bp->SetDomain(0, -100.0, 100.0);
    bp->SetDomain(1, -100.0, 100.0);
    bp->SetExtents(0, bp->Domain(0));
    bp->SetExtents(1, bp->Domain(1));
    (*b)->m_S.Append(bp);
    const int bsi = (*b)->m_S.Count() - 1;
    ON_BrepFace& bface = (*b)->NewFace(bsi);
    (*b)->NewPlanarFaceLoop(bface.m_face_index, ON_BrepLoop::outer, boundary, true);
    const ON_BrepLoop* bloop = (*b)->m_L.Last();
    bp->SetDomain(0, bloop->m_pbox.m_min.x, bloop->m_pbox.m_max.x);
    bp->SetDomain(1, bloop->m_pbox.m_min.y, bloop->m_pbox.m_max.y);
    bp->SetExtents(0, bp->Domain(0));
    bp->SetExtents(1, bp->Domain(1));
    (*b)->FlipFace(bface);
    (*b)->SetTrimIsoFlags(bface);
    boundary.Empty();
    delete bcurve;

    // Generate the top cap
    boundary.Append(ON_Curve::Cast(tcurve));
    ON_PlaneSurface* tp = new ON_PlaneSurface();
    tp->m_plane = hyp_top_plane;
    tp->SetDomain(0, -100.0, 100.0);
    tp->SetDomain(1, -100.0, 100.0);
    tp->SetExtents(0, bp->Domain(0));
    tp->SetExtents(1, bp->Domain(1));
    (*b)->m_S.Append(tp);
    int tsi = (*b)->m_S.Count() - 1;
    ON_BrepFace& tface = (*b)->NewFace(tsi);
    (*b)->NewPlanarFaceLoop(tface.m_face_index, ON_BrepLoop::outer, boundary, true);
    ON_BrepLoop* tloop = (*b)->m_L.Last();
    tp->SetDomain(0, tloop->m_pbox.m_min.x, tloop->m_pbox.m_max.x);
    tp->SetDomain(1, tloop->m_pbox.m_min.y, tloop->m_pbox.m_max.y);
    tp->SetExtents(0, bp->Domain(0));
    tp->SetExtents(1, bp->Domain(1));
    (*b)->SetTrimIsoFlags(tface);
    delete tcurve;

    //  Now, the hard part.  Need an elliptical hyperbolic NURBS surface.
    //  First step is to create a nurbs curve.

    double MX = eip->hyp_b * eip->hyp_bnr;
    point_t ep1, ep2, ep3;
    VSET(ep1, -eip->hyp_b, 0, 0.5*MAGNITUDE(eip->hyp_Hi));
    VSET(ep2, -MX*eip->hyp_bnr, 0, 0);
    VSET(ep3, -eip->hyp_b, 0, -0.5*MAGNITUDE(eip->hyp_Hi));

    ON_3dPoint onp1 = ON_3dPoint(ep1);
    ON_3dPoint onp2 = ON_3dPoint(ep2);
    ON_3dPoint onp3 = ON_3dPoint(ep3);

    ON_3dPointArray cpts(3);
    cpts.Append(onp1);
    cpts.Append(onp2);
    cpts.Append(onp3);
    ON_BezierCurve *bezcurve = new ON_BezierCurve(cpts);
    bezcurve->MakeRational();
    bezcurve->SetWeight(1, bezcurve->Weight(0)/eip->hyp_bnr);

    ON_NurbsCurve* tnurbscurve = ON_NurbsCurve::New();
    bezcurve->GetNurbForm(*tnurbscurve);
    delete bezcurve;

    ON_3dPoint revpnt1 = ON_3dPoint(0, 0, -0.5*MAGNITUDE(eip->hyp_Hi));
    ON_3dPoint revpnt2 = ON_3dPoint(0, 0, 0.5*MAGNITUDE(eip->hyp_Hi));

    ON_Line revaxis = ON_Line(revpnt1, revpnt2);
    ON_RevSurface* hyp_surf = ON_RevSurface::New();
    hyp_surf->m_curve = tnurbscurve;
    hyp_surf->m_axis = revaxis;
    hyp_surf->m_angle = ON_Interval(0, 2*ON_PI);

    // Get the NURBS form of the surface
    ON_NurbsSurface *hypcurvedsurf = ON_NurbsSurface::New();
    hyp_surf->GetNurbForm(*hypcurvedsurf, 0.0);
    delete hyp_surf;

    for (int i = 0; i < hypcurvedsurf->CVCount(0); i++) {
	for (int j = 0; j < hypcurvedsurf->CVCount(1); j++) {
	    point_t cvpt;
	    ON_4dPoint ctrlpt;
	    hypcurvedsurf->GetCV(i, j, ctrlpt);

	    // Scale and shear
	    vect_t proj_ah;
	    vect_t proj_ax;
	    fastf_t factor;

	    VPROJECT(eip->hyp_A, eip->hyp_Hi, proj_ah, proj_ax);
	    VSET(cvpt, ctrlpt.x * MAGNITUDE(proj_ax)/eip->hyp_b, ctrlpt.y, ctrlpt.z);
	    factor = VDOT(eip->hyp_A, eip->hyp_Hi)>0 ? 1.0 : -1.0;
	    cvpt[2] += factor*cvpt[0]/MAGNITUDE(proj_ax)*MAGNITUDE(proj_ah) + 0.5*MAGNITUDE(eip->hyp_Hi)*ctrlpt.w;

	    // Rotate
	    vect_t Au, Bu, Hu;
	    mat_t R;
	    point_t new_cvpt;

	    VSCALE(Bu, y_dir, 1/MAGNITUDE(y_dir));
	    VSCALE(Hu, eip->hyp_Hi, 1/MAGNITUDE(eip->hyp_Hi));
	    VCROSS(Au, Bu, Hu);
	    VUNITIZE(Au);
	    MAT_IDN(R);
	    VMOVE(&R[0], Au);
	    VMOVE(&R[4], Bu);
	    VMOVE(&R[8], Hu);
	    VEC3X3MAT(new_cvpt, cvpt, R);
	    VMOVE(cvpt, new_cvpt);

	    // Translate
	    vect_t scale_v;
	    VSCALE(scale_v, eip->hyp_Vi, ctrlpt.w);
	    VADD2(cvpt, cvpt, scale_v);
	    ON_4dPoint newpt = ON_4dPoint(cvpt[0], cvpt[1], cvpt[2], ctrlpt.w);
	    hypcurvedsurf->SetCV(i, j, newpt);
	}
    }

    (*b)->m_S.Append(hypcurvedsurf);
    int surfindex = (*b)->m_S.Count();
    ON_BrepFace& face = (*b)->NewFace(surfindex - 1);
    (*b)->FlipFace(face);
    int faceindex = (*b)->m_F.Count();
    (*b)->NewOuterLoop(faceindex-1);

}
コード例 #27
0
ファイル: nmg_brep.cpp プロジェクト: cogitokat/brlcad
extern "C" void
rt_nmg_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol)
{
    struct model *m;
    struct nmgregion *r;
    struct shell *s;
    struct faceuse *fu;
    struct loopuse *lu;
    struct edgeuse *eu;

    int edge_index;
    long* brepi;

    RT_CK_DB_INTERNAL(ip);
    m = (struct model *)ip->idb_ptr;
    NMG_CK_MODEL(m);

    brepi = static_cast<long*>(bu_malloc(m->maxindex * sizeof(long), "rt_nmg_brep: brepi[]"));
    for (int i = 0; i < m->maxindex; i++) brepi[i] = -INT_MAX;

    for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
	for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	    for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) {
		NMG_CK_FACEUSE(fu);
		if (fu->orientation != OT_SAME) continue;

		// Need to create ON_NurbsSurface based on plane of
		// face in order to have UV space in which to define
		// trimming loops.  Bounding points are NOT on the
		// face plane, so another approach must be used.
		//
		// General approach: For all loops in the faceuse,
		// collect all the vertices.  Find the center point of
		// all the vertices, and search for the point with the
		// greatest distance from that center point.  Once
		// found, cross the vector between the center point
		// and furthest point with the normal of the face and
		// scale the resulting vector to have the same length
		// as the vector to the furthest point.  Add the two
		// resulting vectors to find the first corner point.
		// Mirror the first corner point across the center to
		// find the second corner point.  Cross the two
		// vectors created by the first two corner points with
		// the face normal to get the vectors of the other two
		// corners, and scale the resulting vectors to the
		// same magnitude as the first two.  These four points
		// bound all vertices on the plane and form a suitable
		// staring point for a UV space, since all points on
		// all the edges are equal to or further than the
		// distance between the furthest vertex and the center
		// point.

		// ............. .............
		// .           .* .          .
		// .         .  .    .       .
		// .        .   .      .     .
		// .       .    .       *    .
		// .      .     .       .    .
		// .     .      .       .    .
		// .    .       .       .    .
		// .   *        *       .    .
		// .   .                .    .
		// .   .                .    .
		// .   .                .    .
		// .   *.               .    .
		// .     ...        ...*     .
		// .       .... ....         .
		// .           *             .
		// ...........................
		//


		const struct face_g_plane *fg = fu->f_p->g.plane_p;
		struct bu_ptbl vert_table;
		nmg_tabulate_face_g_verts(&vert_table, fg);
		point_t tmppt, center, max_pt;
		struct vertex **pt;

		VSET(tmppt, 0, 0, 0);
		VSET(max_pt, 0, 0, 0);

		int ptcnt = 0;
		for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) {
		    tmppt[0] += (*pt)->vg_p->coord[0];
		    tmppt[1] += (*pt)->vg_p->coord[1];
		    tmppt[2] += (*pt)->vg_p->coord[2];
		    ptcnt++;
		    if (brepi[(*pt)->vg_p->index] == -INT_MAX) {
			ON_BrepVertex& vert = (*b)->NewVertex((*pt)->vg_p->coord, SMALL_FASTF);
			brepi[(*pt)->vg_p->index] = vert.m_vertex_index;
		    }
		}
		VSET(center, tmppt[0]/ptcnt, tmppt[1]/ptcnt, tmppt[2]/ptcnt);
		fastf_t max_dist = 0.0;
		fastf_t curr_dist;
		for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) {
		    tmppt[0] = (*pt)->vg_p->coord[0];
		    tmppt[1] = (*pt)->vg_p->coord[1];
		    tmppt[2] = (*pt)->vg_p->coord[2];
		    curr_dist = DIST_PT_PT(center, tmppt);
		    if (curr_dist > max_dist) {
			max_dist = curr_dist;
			VMOVE(max_pt, tmppt);
		    }
		}
		bu_ptbl_free(&vert_table);
		int ccw = 0;
		vect_t vtmp, uv1, uv2, uv3, uv4, vnormal;
		// If an outer loop is found in the nmg with a cw
		// orientation, use a flipped normal to form the NURBS
		// surface
		for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		    if (lu->orientation == OT_SAME && nmg_loop_is_ccw(lu, fg->N, tol) == -1) ccw = -1;
		}
		if (ccw != -1) {
		    VSET(vnormal, fg->N[0], fg->N[1], fg->N[2]);
		} else {
		    VSET(vnormal, -fg->N[0], -fg->N[1], -fg->N[2]);
		}
		VSUB2(uv1, max_pt, center);
		VCROSS(vtmp, uv1, vnormal);
		VADD2(uv1, uv1, vtmp);
		VCROSS(uv2, uv1, vnormal);
		VREVERSE(uv3, uv1);
		VCROSS(uv4, uv3, vnormal);
		VADD2(uv1, uv1, center);
		VADD2(uv2, uv2, center);
		VADD2(uv3, uv3, center);
		VADD2(uv4, uv4, center);

		ON_3dPoint p1 = ON_3dPoint(uv1);
		ON_3dPoint p2 = ON_3dPoint(uv2);
		ON_3dPoint p3 = ON_3dPoint(uv3);
		ON_3dPoint p4 = ON_3dPoint(uv4);

		(*b)->m_S.Append(sideSurface(p1, p4, p3, p2));
		ON_Surface *surf = (*(*b)->m_S.Last());
		int surfindex = (*b)->m_S.Count();

		// Now that we have the surface, define the face
		ON_BrepFace& face = (*b)->NewFace(surfindex - 1);

		// With the surface and the face defined, make
		// trimming loops and create faces.  To generate UV
		// coordinates for each from and to for the
		// edgecurves, the UV origin is defined to be v1,
		// v1->v2 is defined as the U domain, and v1->v4 is
		// defined as the V domain.
		vect_t u_axis, v_axis;
		VSUB2(u_axis, uv2, uv1);
		VSUB2(v_axis, uv4, uv1);
		fastf_t u_axis_dist = MAGNITUDE(u_axis);
		fastf_t v_axis_dist = MAGNITUDE(v_axis);

		// Now that the surface context is set up, add the loops.
		for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
		    int edges=0;
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex
		    ON_BrepLoop::TYPE looptype;
		    // Check if this is an inner or outer loop
		    if (lu->orientation == OT_SAME) {
			looptype = ON_BrepLoop::outer;
		    } else {
			looptype = ON_BrepLoop::inner;
		    }
		    ON_BrepLoop& loop = (*b)->NewLoop(looptype, face);
		    for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
			++edges;
			vect_t ev1, ev2;
			struct vertex_g *vg1, *vg2;
			vg1 = eu->vu_p->v_p->vg_p;
			NMG_CK_VERTEX_G(vg1);
			int vert1 = brepi[vg1->index];
			VMOVE(ev1, vg1->coord);
			vg2 = eu->eumate_p->vu_p->v_p->vg_p;
			NMG_CK_VERTEX_G(vg2);
			int vert2 = brepi[vg2->index];
			VMOVE(ev2, vg2->coord);
			// Add edge if not already added
			if (brepi[eu->e_p->index] == -INT_MAX) {
			    /* always add edges with the small vertex index as from */
			    if (vg1->index > vg2->index) {
				int tmpvert = vert1;
				vert1 = vert2;
				vert2 = tmpvert;
			    }
			    // Create and add 3D curve
			    ON_Curve* c3d = new ON_LineCurve((*b)->m_V[vert1].Point(), (*b)->m_V[vert2].Point());
			    c3d->SetDomain(0.0, 1.0);
			    (*b)->m_C3.Append(c3d);
			    // Create and add 3D edge
			    ON_BrepEdge& e = (*b)->NewEdge((*b)->m_V[vert1], (*b)->m_V[vert2] , (*b)->m_C3.Count() - 1);
			    e.m_tolerance = 0.0;
			    brepi[eu->e_p->index] = e.m_edge_index;
			}
			// Regardless of whether the edge existed as
			// an object, it needs to be added to the
			// trimming loop
			vect_t u_component, v_component;
			ON_3dPoint vg1pt(vg1->coord);
			int orientation = 0;
			edge_index = brepi[eu->e_p->index];
			if (vg1pt !=  (*b)->m_V[(*b)->m_E[edge_index].m_vi[0]].Point()) {
			    orientation = 1;
			}
			// Now, make 2d trimming curves
			vect_t vect1, vect2;
			VSUB2(vect1, ev1, uv1);
			VSUB2(vect2, ev2, uv1);
			ON_2dPoint from_uv, to_uv;
			double u0, u1, v0, v1;
			surf->GetDomain(0, &u0, &u1);
			surf->GetDomain(1, &v0, &v1);

			VPROJECT(vect1, u_axis, u_component, v_component);
			from_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0);
			from_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0);
			VPROJECT(vect2, u_axis, u_component, v_component);
			to_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0);
			to_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0);
			ON_3dPoint S1, S2;
			ON_3dVector Su, Sv;
			surf->Ev1Der(from_uv.x, from_uv.y, S1, Su, Sv);
			surf->Ev1Der(to_uv.x, to_uv.y, S2, Su, Sv);
			ON_Curve* c2d =  new ON_LineCurve(from_uv, to_uv);
			c2d->SetDomain(0.0, 1.0);
			int c2i = (*b)->m_C2.Count();
			(*b)->m_C2.Append(c2d);
			edge_index = brepi[eu->e_p->index];
			ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[edge_index], orientation, loop, c2i);
			trim.m_type = ON_BrepTrim::mated;
			trim.m_tolerance[0] = 0.0;
			trim.m_tolerance[1] = 0.0;
		    }
		}
	    }
	    (*b)->SetTrimIsoFlags();
	}
    }

    bu_free(brepi, "rt_nmg_brep: brepi[]");
}
コード例 #28
0
static int
radhit( struct application *ap, struct partition *PartHeadp )
{
    register struct partition *pp;
    register struct hit *hitp;
    struct application sub_ap;
    struct rayinfo *rayp;
    fastf_t	f;
    vect_t	to_eye, work;
    int	depth;
    int	cpu_num;


    for ( pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw )
	if ( pp->pt_outhit->hit_dist >= 0.0 )  break;
    if ( pp == PartHeadp )  {
	bu_log("radhit:  no hit out front?\n");
	return 0;
    }

    if (R_DEBUG&RDEBUG_HITS)  {
	rt_pr_pt( ap->a_rt_i, pp );
    }

    hitp = pp->pt_inhit;
    if ( hitp->hit_dist >= INFINITY )  {
	bu_log("radhit:  entry beyond infinity\n");
	return 1;
    }
    /* Check to see if eye is "inside" the solid */
    if ( hitp->hit_dist < 0 )  {
	/* XXX */
	return 0;
    }

    if (R_DEBUG&RDEBUG_HITS)  {
	rt_pr_hit( " In", hitp );
    }

    if ( ap->a_resource == RESOURCE_NULL)
	cpu_num = 0;
    else
	cpu_num = ap->a_resource->re_cpu;

    rayp = &rayinfo[cpu_num][ ap->a_level +1 ];
    rayp->x = ap->a_x;
    rayp->y = ap->a_y;
    rayp->dist = hitp->hit_dist;
    rayp->reg = pp->pt_regionp->reg_regionid;
    rayp->sol = pp->pt_inseg->seg_stp->st_id;
    rayp->surf = hitp->hit_surfno;
    RT_HIT_NORMAL( rayp->norm, hitp, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip );
    RT_CURVATURE( &(rayp->curvature), hitp, pp->pt_inflip, pp->pt_inseg->seg_stp );
    if ( VDOT( hitp->hit_normal, ap->a_ray.r_dir ) < 0 ) {
	bu_log(" debug: curvature flip\n");
	rayp->curvature.crv_c1 = - rayp->curvature.crv_c1;
	rayp->curvature.crv_c2 = - rayp->curvature.crv_c2;
    }
    VMOVE( rayp->ip, hitp->hit_point );
    VMOVE( rayp->dir, ap->a_ray.r_dir);

    /* Compute the specular direction */
    VREVERSE( to_eye, ap->a_ray.r_dir );
    f = 2 * VDOT( to_eye, rayp->norm );
    VSCALE( work, rayp->norm, f );
    /* I have been told this has unit length */
    VSUB2( rayp->spec, work, to_eye );
    VUNITIZE( rayp->spec );

    /* Save info for 1st ray */
    if ( ap->a_level == 0 ) {
	firstray[cpu_num] = ap->a_ray;	/* struct copy */
	rayp->sight = 1;	/* the 1st intersect is always visible */
    } else {
	/* Check for visibility */
	rayp->sight = isvisible( ap, hitp, rayp->norm );
    }

    /*
     * Shoot another ray in the specular direction.
     */
    if ( ap->a_level < numreflect-1 ) {
	sub_ap = *ap;	/* struct copy */
	sub_ap.a_level = ap->a_level+1;
	sub_ap.a_purpose = "secondary ray";
	VMOVE( sub_ap.a_ray.r_pt, hitp->hit_point );
	VMOVE( sub_ap.a_ray.r_dir, rayp->spec );
	depth = rt_shootray( &sub_ap );
    } else {
	depth = 0;
    }

    if ( ap->a_level == 0 ) {
	rayinfo[cpu_num][0].x = ap->a_x;
	rayinfo[cpu_num][0].y = ap->a_y;
	rayinfo[cpu_num][0].surf = depth+1;
	rayinfo[cpu_num][0].ip[0] = ap->a_ray.r_pt[0];
	rayinfo[cpu_num][0].ip[1] = ap->a_ray.r_pt[1];
	rayinfo[cpu_num][0].ip[2] = ap->a_ray.r_pt[2];
	radar_physics( cpu_num, depth + 1 );
#ifdef SAR
	dumpall( ap, cpu_num, depth + 1);
#endif
    }

    return depth+1;	/* report hit to main routine */
}