예제 #1
0
파일: sh_fbm.c 프로젝트: cciechad/brlcad
/*
 *	F B M _ R E N D E R
 */
int
fbm_render(struct application *ap, struct partition *pp, struct shadework *swp, char *dp)
{
    register struct fbm_specific *fbm_sp =
	(struct fbm_specific *)dp;
    vect_t v_noise;
    point_t pt;

    if (rdebug&RDEBUG_SHADE)
	bu_struct_print( "foo", fbm_parse, (char *)fbm_sp );

    pt[0] = swp->sw_hit.hit_point[0] * fbm_sp->scale[0];
    pt[1] = swp->sw_hit.hit_point[1] * fbm_sp->scale[1];
    pt[2] = swp->sw_hit.hit_point[2] * fbm_sp->scale[2];

    bn_noise_vec(pt, v_noise);

    VSCALE(v_noise, v_noise, fbm_sp->distortion);

    if (rdebug&RDEBUG_SHADE)
	bu_log("fbm_render: point (%g %g %g) becomes (%g %g %g)\n\tv_noise (%g %g %g)\n",
	       V3ARGS(swp->sw_hit.hit_point),
	       V3ARGS(pt),
	       V3ARGS(v_noise));

    VADD2(swp->sw_hit.hit_normal, swp->sw_hit.hit_normal, v_noise);
    VUNITIZE(swp->sw_hit.hit_normal);

    return(1);
}
예제 #2
0
void
btRTCollisionAlgorithm::processCollision(btCollisionObject* col0,
					 btCollisionObject* col1,
					 const btDispatcherInfo& dispatchInfo,
					 btManifoldResult* resultOut)
{
    if (!m_manifoldPtr)
	return;

    //quellage
    // unquell: otherwise get unused param dispatchInfo warning
    bu_log("%d", dispatchInfo.m_stepCount);

    /// report a contact. internally this will be kept persistent, and contact reduction is done
    resultOut->setPersistentManifold(m_manifoldPtr);
#ifndef USE_PERSISTENT_CONTACTS
    m_manifoldPtr->clearManifold();
#endif //USE_PERSISTENT_CONTACTS


    //------------------- DEBUG ---------------------------

    int i;

    //Get the user pointers to struct rigid_body, for printing the body name
    struct rigid_body *rbA = (struct rigid_body *)col0->getUserPointer();
    struct rigid_body *rbB = (struct rigid_body *)col1->getUserPointer();

    if (rbA != NULL && rbB != NULL) {

	   struct sim_manifold *rt_mf = &(rbB->rt_manifold);

	   // Now add the RT contact pairs
	   for (i = 0; i < rt_mf->num_contacts; i++) {

		   btVector3 ptA, ptB, normalWorldOnB;

		   VMOVE(ptA, rt_mf->contacts[i].ptA);
		   VMOVE(ptB, rt_mf->contacts[i].ptB);
		   VMOVE(normalWorldOnB, rt_mf->contacts[i].normalWorldOnB);

		   //Negative depth for penetration
		   resultOut->addContactPoint(normalWorldOnB, ptB, rt_mf->contacts[i].depth);

		   bu_log("processCollision: Added RT contact %d, A(ignore): %s(%f, %f, %f) , \
				   B: %s(%f, %f, %f), n(%f, %f, %f), depth=%f\n",
					   i+1,
					rt_mf->rbA->rb_namep, V3ARGS(ptA),
					rt_mf->rbB->rb_namep, V3ARGS(ptB),
					V3ARGS(normalWorldOnB),
					rt_mf->contacts[i].depth);
	   }

    } //end- if (rbA != NULL && rbB...

}
예제 #3
0
파일: plot3.c 프로젝트: cciechad/brlcad
/* Double 3-D, both in vector and enumerated versions */
void
pdv_3space(register FILE *plotfp, const fastf_t *min, const fastf_t *max)
{
    unsigned char	out[6*8+1];

    if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
	htond( &out[1], (unsigned char *)min, 3 );
	htond( &out[3*8+1], (unsigned char *)max, 3 );

	out[0] = 'W';
	fwrite( out, 1, 6*8+1, plotfp );
    } else {
	fprintf(plotfp, "W %g %g %g %g %g %g\n", V3ARGS(min), V3ARGS(max));
    }
}
예제 #4
0
파일: plot3.c 프로젝트: cciechad/brlcad
void
pdv_3line(register FILE *plotfp, const fastf_t *a, const fastf_t *b)
{
    unsigned char	out[6*8+1];

    if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
	htond( &out[1], (unsigned char *)a, 3 );
	htond( &out[3*8+1], (unsigned char *)b, 3 );

	out[0] = 'V';
	fwrite( out, 1, 6*8+1, plotfp );
    } else {
	fprintf(plotfp, "V %g %g %g %g %g %g\n", V3ARGS(a), V3ARGS(b));
    }
}
예제 #5
0
/**
 * Creates one metaball object that includes all points from an
 * existing list (in 'av') of named metaballs.  This routine creates
 * an rt_metaball_internal object directly via LIBRT given it requires
 * reading existing metaballs from the database.
 */
static void
mix_balls(struct db_i *dbip, const char *name, int ac, const char *av[])
{
    int i;
    struct directory *dp;
    struct rt_metaball_internal *newmp;

    RT_CK_DBI(dbip);

    /* allocate a struct rt_metaball_internal object that we'll
     * manually fill in with points from the other metaballs being
     * joined together.
     */
    BU_ALLOC(newmp, struct rt_metaball_internal);
    newmp->magic = RT_METABALL_INTERNAL_MAGIC;
    newmp->threshold = 1.0;
    newmp->method = 1;
    BU_LIST_INIT(&newmp->metaball_ctrl_head);

    bu_log("Combining together the following metaballs:\n");

    for (i = 0; i < ac; i++) {
	struct rt_db_internal dir;
	struct rt_metaball_internal *mp;
	struct wdb_metaballpt *mpt;

	/* get a handle on the existing database object */
	bu_log("\t%s\n", av[i]);
	dp = db_lookup(dbip, av[i], 1);
	if (!dp) {
	    bu_log("Unable to find %s\n", av[i]);
	    continue;
	}

	/* load the existing database object */
	if (rt_db_get_internal(&dir, dp, dbip, NULL, &rt_uniresource) < 0) {
	    bu_log("Unable to load %s\n", av[i]);
	    continue;
	}

	/* access the metaball-specific internal structure */
	mp = (struct rt_metaball_internal *)dir.idb_ptr;
	RT_METABALL_CK_MAGIC(mp);

	/* iterate over each point in that database object and add it
	 * to our new metaball.
	 */
	for (BU_LIST_FOR(mpt, wdb_metaballpt, &mp->metaball_ctrl_head)) {
	    bu_log("Adding point (%lf %lf %lf)\n", V3ARGS(mpt->coord));
	    rt_metaball_add_point(newmp, (const point_t *)&mpt->coord, mpt->fldstr, mpt->sweat);
	}
    }

    bu_log("Joining balls together and creating [%s] object\n", name);

    /* write out new "mega metaball" out to disk */
    dbip->dbi_wdbp = wdb_dbopen(dbip, RT_WDB_TYPE_DB_DISK);
    wdb_export(dbip->dbi_wdbp, name, newmp, ID_METABALL, 1.0);
}
예제 #6
0
void
print_thrm_seg(struct thrm_seg *ts)
{
    int i;
    CK_THRM_SEG(ts);

    bu_log("Thermal cylinder\n");
    bu_log("Center: (%g %g %g)\n", V3ARGS(ts->pt));
    bu_log("   dir: (%g %g %g)\n", V3ARGS(ts->dir));
    bu_log(" Nodes:\n");
    for (i=0; i < NUM_NODES; i++) {

	bu_log("\t(%g %g %g) %17.14e  (%g %g %g)\n",
	       V3ARGS(ts->node[i]),
	       ts->temperature[i],
	       V3ARGS(ts->vect[i])
	    );
    }
}
int
rt_gen_conic(struct xrays *rays, const struct xray *center_ray,
	     fastf_t theta, vect_t up_vector, int rays_per_radius)
{
    int count = 0;

    point_t start;
    vect_t orig_dir;

    fastf_t x, y;

    /* Setting radius to tan(theta) works because, as shown in the
     * following diagram, the ray that starts at the given point and
     * passes through orig_dir + (radius in any orthogonal direction)
     * has an angle of theta with the original ray; when the
     * resulting vector is normalized, the angle is preserved.
     */
    fastf_t radius = tan(theta);
    fastf_t rsq = radius * radius; /* radius-squared, for use in the loop */

    fastf_t gridsize = 2 * radius / (rays_per_radius - 1);

    vect_t a_dir, b_dir;

    register struct xrays *xrayp;

    VMOVE(start, center_ray->r_pt);
    VMOVE(orig_dir, center_ray->r_dir);

    /* Create vectors a_dir, b_dir that are orthogonal to orig_dir. */
    VMOVE(b_dir, up_vector);
    VUNITIZE(b_dir);

    VCROSS(a_dir, orig_dir, up_vector);
    VUNITIZE(a_dir);

    for (y = -radius; y <= radius; y += gridsize) {
	vect_t tmp;
	printf("y:%f\n", y);
	VSCALE(tmp, b_dir, y);
	printf("y_partofit: %f,%f,%f\n", V3ARGS(tmp));
	for (x = -radius; x <= radius; x += gridsize) {
	    if (((x*x)/rsq + (y*y)/rsq) <= 1) {
		BU_ALLOC(xrayp, struct xrays);
		VMOVE(xrayp->ray.r_pt, start);
		VJOIN2(xrayp->ray.r_dir, orig_dir, x, a_dir, y, b_dir);
		VUNITIZE(xrayp->ray.r_dir);
		xrayp->ray.index = count++;
		xrayp->ray.magic = RT_RAY_MAGIC;
		BU_LIST_APPEND(&rays->l, &xrayp->l);
	    }
	}
    }
    return count;
}
/**
 * used for db put/asc2g
 */
int
rt_metaball_adjust(struct bu_vls *logstr, struct rt_db_internal *intern, int argc, const char **argv)
{
    struct rt_metaball_internal *mb;
    const char *pts;
    const char *pend;
    double thresh;

    if (argc != 3)  {
	bu_vls_printf(logstr, "Invalid number of arguments: %d\n", argc);
	return BRLCAD_ERROR;
    }

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

    if ( strlen(*argv) != 1 || (**argv < '0' || **argv > '2') ) {
	bu_vls_printf(logstr, "Invalid method type, must be one of 0, 1, or 2.");
	return BRLCAD_ERROR;
    }
    mb->method = *argv[0] - '0';
    sscanf(argv[1], "%lG", &thresh);
    mb->threshold = thresh;
    BU_LIST_INIT(&mb->metaball_ctrl_head);

    pts = argv[2];
    pend = pts + strlen(pts);

    while (1) {
	int len;
	double xyz[3];
	double fldstr, goo;
	point_t loc;
	const point_t *locp = (const point_t *)&loc;

	while ( pts < pend && *pts != '{' ) ++pts;
	if (pts >= pend) break;
	len = sscanf(pts, "{%lG %lG %lG %lG %lG}", &xyz[0], &xyz[1], &xyz[2], &fldstr, &goo);
	VMOVE(loc, xyz);

	if (len == EOF) break;
	if (len != 5) {
	    bu_vls_printf(logstr, "Failed to parse point information: \"%s\"", pts);
	    return BRLCAD_ERROR;
	}
	pts++;
	if (rt_metaball_add_point (mb, locp, fldstr, goo)) {
	    bu_vls_printf(logstr, "Failure adding point: {%f %f %f %f %f}", V3ARGS(loc), fldstr, goo);
	    return BRLCAD_ERROR;
	}
    }

    return BRLCAD_OK;
}
예제 #9
0
void
bn_vec_ortho(register vect_t out, register const vect_t in)
{
    register int j, k;
    register fastf_t f;
    register int i;

    if (UNLIKELY(NEAR_ZERO(MAGSQ(in), SQRT_SMALL_FASTF))) {
	bu_log("bn_vec_ortho(): zero magnitude input vector %g %g %g\n", V3ARGS(in));
	VSETALL(out, 0);
	return;
    }

    /* Find component closest to zero */
    f = fabs(in[X]);
    i = X;
    j = Y;
    k = Z;
    if (fabs(in[Y]) < f) {
	f = fabs(in[Y]);
	i = Y;
	j = Z;
	k = X;
    }
    if (fabs(in[Z]) < f) {
	i = Z;
	j = X;
	k = Y;
    }
    f = hypot(in[j], in[k]);
    if (UNLIKELY(ZERO(f))) {
	bu_log("bn_vec_ortho(): zero hypot on %g %g %g\n", V3ARGS(in));
	VSETALL(out, 0);
	return;
    }
    f = 1.0 / f;
    out[i] = 0.0;
    out[j] = -in[k] * f;
    out[k] =  in[j] * f;

    return;
}
void
rt_metaballpt_print(const struct wdb_metaballpt *metaball, double mm2local)
{
    point_t p1;

    bu_log("Metaball Point:\n");
    VSCALE(p1, metaball->coord, mm2local);
    bu_log("\tat (%g %g %g)\n", V3ARGS(p1));
    bu_log("\tfield strength = %g\n", metaball->fldstr*mm2local);
    return;
}
예제 #11
0
void
bn_mat_lookat(mat_t rot, const vect_t dir, int yflip)
{
    mat_t first;
    mat_t second;
    mat_t prod12;
    mat_t third;
    vect_t x;
    vect_t z;
    vect_t t1;
    fastf_t hypot_xy;
    vect_t xproj;
    vect_t zproj;

    /* First, rotate D around Z axis to match +X axis (azimuth) */
    hypot_xy = hypot(dir[X], dir[Y]);
    bn_mat_zrot(first, -dir[Y] / hypot_xy, dir[X] / hypot_xy);

    /* Next, rotate D around Y axis to match -Z axis (elevation) */
    bn_mat_yrot(second, -hypot_xy, -dir[Z]);
    bn_mat_mul(prod12, second, first);

    /* Produce twist correction, by re-orienting projection of X axis */
    VSET(x, 1, 0, 0);
    MAT4X3VEC(xproj, prod12, x);
    hypot_xy = hypot(xproj[X], xproj[Y]);
    if (hypot_xy < 1.0e-10) {
	bu_log("Warning: bn_mat_lookat:  unable to twist correct, hypot=%g\n", hypot_xy);
	VPRINT("xproj", xproj);
	MAT_COPY(rot, prod12);
	return;
    }
    bn_mat_zrot(third, -xproj[Y] / hypot_xy, xproj[X] / hypot_xy);
    bn_mat_mul(rot, third, prod12);

    if (yflip) {
	VSET(z, 0, 0, 1);
	MAT4X3VEC(zproj, rot, z);
	/* If original Z inverts sign, flip sign on resulting Y */
	if (zproj[Y] < 0.0) {
	    MAT_COPY(prod12, rot);
	    MAT_IDN(third);
	    third[5] = -1;
	    bn_mat_mul(rot, third, prod12);
	}
    }

    /* Check the final results */
    MAT4X3VEC(t1, rot, dir);
    if (t1[Z] > -0.98) {
	bu_log("Error:  bn_mat_lookat final= (%g, %g, %g)\n", V3ARGS(t1));
    }
}
/**
 * Make human-readable formatted presentation of this solid. First
 * line describes type of solid. Additional lines are indented one
 * tab, and give parameter values.
 */
int
rt_metaball_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double UNUSED(mm2local))
{
    int metaball_count = 0;
    char buf[BUFSIZ];
    struct rt_metaball_internal *mb;
    struct wdb_metaballpt *mbpt;

    RT_CK_DB_INTERNAL(ip);
    mb = (struct rt_metaball_internal *)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) metaball_count++;

    snprintf(buf, BUFSIZ, "Metaball with %d points and a threshold of %g (%s rendering)\n", metaball_count, mb->threshold, rt_metaball_lookup_type_name(mb->method));
    bu_vls_strcat(str, buf);

    if (!verbose)
	return 0;

    metaball_count = 0;
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) {
	switch (mb->method) {
	    case METABALL_ISOPOTENTIAL:
		snprintf(buf, BUFSIZ, "\t%d: %g field strength at (%g, %g, %g)\n",
			 ++metaball_count, mbpt->fldstr, V3ARGS(mbpt->coord));
		break;
	    case METABALL_METABALL:
	    case METABALL_BLOB:
		snprintf(buf, BUFSIZ, "\t%d: %g field strength at (%g, %g, %g) and blobbiness factor of %g\n",
			 ++metaball_count, mbpt->fldstr, V3ARGS(mbpt->coord), mbpt->sweat);
		break;
	    default:
		bu_bomb("Bad metaball method");	/* asplode */
	}
	bu_vls_strcat(str, buf);
    }
    return 0;
}
/**
 * db get/g2asc
 */
int
rt_metaball_get(struct bu_vls *logstr, const struct rt_db_internal *intern, const char *UNUSED(attr))
{
    struct rt_metaball_internal *mb = (struct rt_metaball_internal *)intern->idb_ptr;
    struct wdb_metaballpt *mbpt = NULL;
    int first = 1;

    RT_METABALL_CK_MAGIC(mb);

    /* write crap in */
    bu_vls_printf(logstr, "metaball %d %.25G {", mb->method, mb->threshold);
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head))
	if (first) {
	    first = 0;
	    bu_vls_printf(logstr, "{%.25G %.25G %.25G %.25G %.25G}",
			    V3ARGS(mbpt->coord), mbpt->fldstr, mbpt->sweat);
	} else
	    bu_vls_printf(logstr, " {%.25G %.25G %.25G %.25G %.25G}",
			    V3ARGS(mbpt->coord), mbpt->fldstr, mbpt->sweat);
    bu_vls_printf(logstr, "}");

    return 0;
}
예제 #14
0
파일: plot3.c 프로젝트: cciechad/brlcad
void
pdv_3cont(register FILE *plotfp, const fastf_t *pt)
{
    unsigned char	out[3*8+1];

    if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
	htond( &out[1], (unsigned char *)pt, 3 );

	out[0] = 'Q';
	fwrite( out, 1, 3*8+1, plotfp );
    } else {
	fprintf(plotfp, "Q %g %g %g\n", V3ARGS(pt));
    }
}
예제 #15
0
파일: sh_wood.c 프로젝트: kanzure/brlcad
/*
 * Phase 2 setup routine
 */
HIDDEN void
wood_setup_2(struct wood_specific *wd)
{
    mat_t xlate;
    int i;
    vect_t a_vertex, a_dir;

    register struct resource *resp = &rt_uniresource;

    /*
     * See if the user specified absolute coordinates for the vertex and
     * direction.  If so, use those instead of the RPP.
     */

    bn_mat_angles(xlate, V3ARGS(wd->rot));

    if (wd->flags & EXPLICIT_VERTEX) {
	MAT4X3PNT(wd->vertex, xlate, wd->V);
	MAT4X3PNT(wd->dir, xlate, wd->D);
    } else {
	if (wd->dz > 0.0) {
	    for (i = 0; i < 2; i++) {
		a_vertex[i] = wd->b_min[i];
		a_dir[i] = wd->b_max[i];
	    }
	    /* Z component is [2] */
	    a_vertex[2] = ((wd->b_max[2] - wd->b_min[2]) *
			   (bn_rand0to1(resp->re_randptr) * wd->dz)) + wd->b_min[2];
	    a_dir[2]    = ((wd->b_max[2] - wd->b_min[2]) *
			   (bn_rand0to1(resp->re_randptr) * wd->dz)) + wd->b_min[2];
	} else {
	    for (i = 0; i < 3; i++) {
		a_vertex[i] = ((wd->b_max[i] - wd->b_min[i]) *
			       (bn_rand0to1(resp->re_randptr) * wd->dd)) + wd->b_min[i];
		a_dir[i]    = ((wd->b_max[i] - wd->b_min[i]) *
			       (bn_rand0to1(resp->re_randptr) * wd->dd)) + wd->b_max[i];
	    }
	}
	MAT4X3PNT(wd->vertex, xlate, a_vertex);
	MAT4X3PNT(wd->dir, xlate, a_dir);
    }

    VSUB2(wd->dir, wd->dir, wd->vertex);
    VUNITIZE(wd->dir);
}
예제 #16
0
파일: vlist.c 프로젝트: cogitokat/brlcad
int
rt_ck_vlist(const struct bu_list *vhead)
{
    register struct bn_vlist *vp;
    int npts = 0;

    for (BU_LIST_FOR(vp, bn_vlist, vhead)) {
	register int i;
	register int nused = vp->nused;
	register int *cmd = vp->cmd;
	register point_t *pt = vp->pt;

	BN_CK_VLIST(vp);
	npts += nused;

	for (i = 0; i < nused; i++, cmd++, pt++) {
	    register int j;

	    for (j=0; j < 3; j++) {
		/*
		 * If (*pt)[j] is an IEEE NaN, then all comparisons
		 * between it and any genuine number will return
		 * FALSE.  This test is formulated so that NaN values
		 * will activate the "else" clause.
		 */
		if ((*pt)[j] > -INFINITY && (*pt)[j] < INFINITY) {
		    /* Number is good */
		} else {
		    bu_log("  %s (%g, %g, %g)\n",
			   rt_vlist_cmd_descriptions[*cmd],
			   V3ARGS(*pt));
		    bu_bomb("rt_ck_vlist() bad coordinate value\n");
		}
		/* XXX Need a define for largest command number */
		if (*cmd < 0 || *cmd > BN_VLIST_CMD_MAX) {
		    bu_log("cmd = x%x (%d.)\n", *cmd, *cmd);
		    bu_bomb("rt_ck_vlist() bad vlist command\n");
		}
	    }
	}
    }
    return npts;
}
예제 #17
0
/*
 * The output occurs here.
 *
 * framenumber, viewsize, eye x y z, orientation x y z w
 */
int
cm_end(const int UNUSED(argc), const char **UNUSED(argv))
{
    quat_t orient;

    /* If no matrix or az/el specified yet, use params from cmd line */
    if (Viewrotscale[15] <= 0.0)
	bu_exit(EXIT_FAILURE, "cm_end:  matrix not specified\n");

    quat_mat2quat(orient, Viewrotscale);

    /* Output information about this frame */
    printf("%d %.15e %.15e %.15e %.15e %.15e %.15e %.15e %.15e\n",
	   curframe,
	   viewsize,
	   V3ARGS(eye_model),
	   V4ARGS(orient));

    return 0;
}
예제 #18
0
파일: bottess.c 프로젝트: kanzure/brlcad
union tree *
compose(union tree *left_tree, union tree *right_tree, unsigned long int UNUSED(face_status1), unsigned long int UNUSED(face_status2), unsigned long int UNUSED(face_status3))
{
    struct soup_s *l, *r;
    int i;

    RT_CK_TREE(left_tree);
    RT_CK_TREE(right_tree);
    l = (struct soup_s *)left_tree->tr_d.td_r->m_p;
    r = (struct soup_s *)right_tree->tr_d.td_r->m_p;
    printf("Composing! %lu %lu\n", l->nfaces, r->nfaces);

    bu_log("solid /left\n");
    for (i=0; i < (int)l->nfaces; i++) {
	bu_log("  facet normal %f %f %f\n", V3ARGS(l->faces[i].plane));
	bu_log("    outer loop\n");
	bu_log("      vertex %f %f %f\n", V3ARGS(l->faces[i].vert[0]));
	bu_log("      vertex %f %f %f\n", V3ARGS(l->faces[i].vert[1]));
	bu_log("      vertex %f %f %f\n", V3ARGS(l->faces[i].vert[2]));
	bu_log("    endloop\n");
	bu_log("  endfacet\n");
    }
    bu_log("endsolid /left\n");

    bu_log("solid /right\n");
    for (i=0; i < (int)r->nfaces; i++) {
	bu_log("  facet normal %f %f %f\n", V3ARGS(r->faces[i].plane));
	bu_log("    outer loop\n");
	bu_log("      vertex %f %f %f\n", V3ARGS(r->faces[i].vert[0]));
	bu_log("      vertex %f %f %f\n", V3ARGS(r->faces[i].vert[1]));
	bu_log("      vertex %f %f %f\n", V3ARGS(r->faces[i].vert[2]));
	bu_log("    endloop\n");
	bu_log("  endfacet\n");
    }
    bu_log("endsolid /right\n");
    return left_tree;

}
/*
 *
 * Evaluate the 3-D gaussian "puff" function:
 *
 * 1.0 / ((2*PI)^(3/2) * sigmaX*sigmaY*sigmaZ)) *
 * exp(-0.5 * ((x-ux)^2/sigmaX + (y-uy)^2/sigmaY + (z-uz)^2/sigmaZ))
 *
 * for a given point "pt" where the center of the puff is at {ux, uy, uz} and
 * the size of 1 standard deviation is {sigmaX, sigmaY, sigmaZ}
 */
static double
gauss_eval(fastf_t *pt, fastf_t *ell_center, fastf_t *sigma)
{
    double term2;
    point_t p;
    double val;

    VSUB2(p, pt, ell_center);
    p[X] *= p[X];
    p[Y] *= p[Y];
    p[Z] *= p[Z];

    term2 = (p[X]/sigma[X]) + (p[Y]/sigma[Y]) + (p[Z]/sigma[Z]);
    term2 *= term2;

    val = exp(-0.5 * term2);

    if (rdebug&RDEBUG_SHADE)
	bu_log("pt(%g %g %g) term2:%g val:%g\n",
	       V3ARGS(pt), term2, val);

    return val;
}
예제 #20
0
/*
 *		H S V _ T O _ R G B ( )
 */
int hsv_to_rgb (fastf_t *hsv, unsigned char *rgb)
{
    fastf_t	float_rgb[3];
    fastf_t	hue, sat, val;
    fastf_t	hue_frac;
    fastf_t	p, q, t;
    int		hue_int;

    hue = hsv[HUE];
    sat = hsv[SAT];
    val = hsv[VAL];

    if (sat == 0.0)
	if (hue == ACHROMATIC)
	    VSETALL(float_rgb, val)
		else
		{
		    (void) fprintf(stderr, "Illegal HSV (%g, %g, %g)\n",
				   V3ARGS(hsv));
		    return (0);
		}
    else
    {
	if (hue == 360.0)
예제 #21
0
/*
 *			R A Y H I T
 *
 *  Rayhit() is called by rt_shootray() when the ray hits one or more objects.
 *  A per-shotline header record is written, followed by information about
 *  each object hit.
 *
 *  Note that the GIFT-3 format uses a different convention for the "zero"
 *  distance along the ray.  RT has zero at the ray origin (emanation plain),
 *  while GIFT has zero at the screen plain translated so that it contains
 *  the model origin.  This difference is compensated for by adding the
 *  'dcorrection' distance correction factor.
 *
 *  Also note that the GIFT-3 format requires information about the start
 *  point of the ray in two formats.  First, the h, v coordinates of the
 *  grid cell CENTERS (in screen space coordinates) are needed.
 *  Second, the ACTUAL h, v coordinates fired from are needed.
 *
 *  An optional rtg3.pl UnixPlot file is written, permitting a
 *  color vector display of ray-model intersections.
 */
int
rayhit(struct application *ap, register struct partition *PartHeadp, struct seg *segp)
{
    register struct partition *pp = PartHeadp->pt_forw;
    int 			comp_count;	/* component count */
    fastf_t			dfirst, dlast;	/* ray distances */
    static fastf_t		dcorrection = 0; /* RT to GIFT dist corr */
    int			card_count;	/* # comp. on this card */
    const char		*fmt;		/* printf() format string */
    struct bu_vls		str;
    char			buf[128];	/* temp. sprintf() buffer */
    point_t			hv;		/* GIFT h, v coords, in inches */
    point_t			hvcen;
    int			prev_id=-1;
    point_t			first_hit;
    int			first;

    if ( pp == PartHeadp )
	return(0);		/* nothing was actually hit?? */

    if ( ap->a_rt_i->rti_save_overlaps )
	rt_rebuild_overlaps( PartHeadp, ap, 1 );

    part_compact(ap, PartHeadp, TOL);

    /* count components in partitions */
    comp_count = 0;
    for ( pp=PartHeadp->pt_forw; pp!=PartHeadp; pp=pp->pt_forw )  {
	if ( pp->pt_regionp->reg_regionid > 0 ) {
	    prev_id = pp->pt_regionp->reg_regionid;
	    comp_count++;
	} else if ( prev_id <= 0 ) {
	    /* normally air would be output along with a solid partition, but this will require a '111' partition */
	    prev_id = pp->pt_regionp->reg_regionid;
	    comp_count++;
	} else
	    prev_id = pp->pt_regionp->reg_regionid;
    }
    pp = PartHeadp->pt_back;
    if ( pp!=PartHeadp && pp->pt_regionp->reg_regionid <= 0 )
	comp_count++;  /* a trailing '111' ident */
    if ( comp_count == 0 )
	return( 0 );

    /* Set up variable length string, to buffer this shotline in.
     * Note that there is one component per card, and that each card
     * (line) is 80 characters long.  Hence the parameters given to
     * rt-vls-extend().
     */

    bu_vls_init( &str );
    bu_vls_extend( &str, 80 * (comp_count+1) );

    /*
     *  Find the H, V coordinates of the grid cell center.
     *  RT uses the lower left corner of each cell.
     */
    {
	point_t		center;
	fastf_t		dx;
	fastf_t		dy;

	dx = ap->a_x + 0.5;
	dy = ap->a_y + 0.5;
	VJOIN2( center, viewbase_model, dx, dx_model, dy, dy_model );
	MAT4X3PNT( hvcen, model2hv, center );
    }

    /*
     *  Find exact h, v coordinates of actual ray start by
     *  projecting start point into GIFT h, v coordinates.
     */
    MAT4X3PNT( hv, model2hv, ap->a_ray.r_pt );

    /*
     *  In RT, rays are launched from the plane of the screen,
     *  and ray distances are relative to the start point.
     *  In GIFT-3 output files, ray distances are relative to
     *  the (H, V) plane translated so that it contains the origin.
     *  A distance correction is required to convert between the two.
     *  Since this really should be computed only once, not every time,
     *  the trip_count flag was added.
     */
    {

	static int  trip_count;
	vect_t	tmp;
	vect_t	viewZdir;

	if ( trip_count == 0) {

	    VSET( tmp, 0, 0, -1 );		/* viewing direction */
	    MAT4X3VEC( viewZdir, view2model, tmp );
	    VUNITIZE( viewZdir );
	    /* dcorrection will typically be negative */
	    dcorrection = VDOT( ap->a_ray.r_pt, viewZdir );
	    trip_count = 1;
	}
    }

    /* This code is for diagnostics.
     * bu_log("dcorrection=%g\n", dcorrection);
     */

    /* dfirst and dlast have been made negative to account for GIFT looking
     * in the opposite direction of RT.
     */

    dfirst = -(PartHeadp->pt_forw->pt_inhit->hit_dist + dcorrection);
    dlast = -(PartHeadp->pt_back->pt_outhit->hit_dist + dcorrection);
#if 0
    /* This code is to note any occurances of negative distances. */
    if ( PartHeadp->pt_forw->pt_inhit->hit_dist < 0)  {
	bu_log("ERROR: dfirst=%g at partition x%x\n", dfirst, PartHeadp->pt_forw );
	bu_log("\tdcorrection = %f\n", dcorrection );
	bu_log("\tray start point is ( %f %f %f ) in direction ( %f %f %f )\n", V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ) );
	VJOIN1( PartHeadp->pt_forw->pt_inhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_inhit->hit_dist, ap->a_ray.r_dir );
	VJOIN1( PartHeadp->pt_back->pt_outhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_outhit->hit_dist, ap->a_ray.r_dir );
	rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
    }
    /* End of bug trap. */
#endif
    /*
     *  Output the ray header.  The GIFT statements that
     *  would have generated this are:
     *  410	write(1, 411) hcen, vcen, h, v, ncomp, dfirst, dlast, a, e
     *  411	format(2f7.1, 2f9.3, i3, 2f8.2,' A', f6.1,' E', f6.1)
     */

#define	SHOT_FMT	"%7.1f%7.1f%9.3f%9.3f%3d%8.2f%8.2f A%6.1f E%6.1f"

    if ( rt_perspective > 0 )  {
	bn_ae_vec( &azimuth, &elevation, ap->a_ray.r_dir );
    }

    bu_vls_printf( &str, SHOT_FMT,
		   hvcen[0], hvcen[1],
		   hv[0], hv[1],
		   comp_count,
		   dfirst * MM2IN, dlast * MM2IN,
		   azimuth, elevation );

    /*
     *  As an aid to debugging, take advantage of the fact that
     *  there are more than 80 columns on UNIX "cards", and
     *  add debugging information to the end of the line to
     *  allow this shotline to be reproduced offline.
     *   -b gives the shotline x, y coordinates when re-running RTG3,
     *   -p and -d are used with RTSHOT
     *  The easy way to activate this is with the harmless -!1 option
     *  when running RTG3.
     */
    if ( R_DEBUG || bu_debug || RT_G_DEBUG )  {
	bu_vls_printf( &str, "   -b%d,%d -p %26.20e %26.20e %26.20e -d %26.20e %26.20e %26.20e\n",
		       ap->a_x, ap->a_y,
		       V3ARGS(ap->a_ray.r_pt),
		       V3ARGS(ap->a_ray.r_dir) );
    } else {
	bu_vls_putc( &str, '\n' );
    }

    /* loop here to deal with individual components */
    card_count = 0;
    prev_id = -1;
    first = 1;
    for ( pp=PartHeadp->pt_forw; pp!=PartHeadp; pp=pp->pt_forw )  {
	/*
	 *  The GIFT statements that would have produced
	 *  this output are:
	 *	do 632 i=icomp, iend
	 *	if (clos(icomp).gt.999.99.or.slos(i).gt.999.9) goto 635
	 * 632	continue
	 * 	write(1, 633)(item(i), clos(i), cangi(i), cango(i),
	 * &			kspac(i), slos(i), i=icomp, iend)
	 * 633	format(1x, 3(i4, f6.2, 2f5.1, i1, f5.1))
	 *	goto 670
	 * 635	write(1, 636)(item(i), clos(i), cangi(i), cango(i),
	 * &			kspac(i), slos(i), i=icomp, iend)
	 * 636	format(1x, 3(i4, f6.1, 2f5.1, i1, f5.0))
	 */
	fastf_t	comp_thickness;	/* component line of sight thickness */
	fastf_t	in_obliq;	/* in obliquity angle */
	fastf_t	out_obliq;	/* out obliquity angle */
	int	region_id;	/* solid region's id */
	int	air_id;		/* air id */
	fastf_t	dot_prod;	/* dot product of normal and ray dir */
	fastf_t	air_thickness;	/* air line of sight thickness */
	vect_t	normal;		/* surface normal */
	register struct partition	*nextpp = pp->pt_forw;

	region_id = pp->pt_regionp->reg_regionid;

	if ( region_id <= 0 && prev_id > 0 )
	{
	    /* air region output with previous partition */
	    prev_id = region_id;
	    continue;
	}
	comp_thickness = pp->pt_outhit->hit_dist -
	    pp->pt_inhit->hit_dist;

	/* The below code is meant to catch components with zero or
	 * negative thicknesses.  This is not supposed to be possible,
	 * but the condition has been seen.
	 */
#if 0
	if ( comp_thickness <= 0 )  {
	    VJOIN1( pp->pt_inhit->hit_point, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir );
	    VJOIN1( pp->pt_outhit->hit_point, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir );
	    bu_log("ERROR: comp_thickness=%g for region id = %d at h=%g, v=%g (x=%d, y=%d), partition at x%x\n",
		   comp_thickness, region_id, hv[0], hv[1], ap->a_x, ap->a_y, pp );
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	    bu_log("Send this output to the BRL-CAD Developers ([email protected])\n");
	    if ( ! (RT_G_DEBUG & DEBUG_ARB8)) {
		rt_g.debug |= DEBUG_ARB8;
		rt_shootray(ap);
		rt_g.debug &= ~DEBUG_ARB8;
	    }
	}
#endif

	if ( nextpp == PartHeadp )  {
	    if ( region_id <= 0 ) {
		/* last partition is air, need a 111 'phantom armor' before AND after */
		bu_log( "WARNING: adding 'phantom armor' (id=111) with zero thickness before and after air region %s\n",
			pp->pt_regionp->reg_name );
		region_id = 111;
		air_id = pp->pt_regionp->reg_aircode;
		air_thickness = comp_thickness;
		comp_thickness = 0.0;
	    } else {
		/* Last partition, no air follows, use code 9 */
		air_id = 9;
		air_thickness = 0.0;
	    }
	} else if ( region_id <= 0 ) {
	    /* air region, need a 111 'phantom armor' */
	    bu_log( "WARNING: adding 'phantom armor' (id=111) with zero thickness before air region %s\n",
		    pp->pt_regionp->reg_name );
	    prev_id = region_id;
	    region_id = 111;
	    air_id = pp->pt_regionp->reg_aircode;
	    air_thickness = comp_thickness;
	    comp_thickness = 0.0;
	} else if ( nextpp->pt_regionp->reg_regionid <= 0 &&
		    nextpp->pt_regionp->reg_aircode != 0 )  {
	    /* Next partition is air region */
	    air_id = nextpp->pt_regionp->reg_aircode;
	    air_thickness = nextpp->pt_outhit->hit_dist -
		nextpp->pt_inhit->hit_dist;
	    prev_id = air_id;
	} else {
	    /* 2 solid regions, maybe with gap */
	    air_id = 0;
	    air_thickness = nextpp->pt_inhit->hit_dist -
		pp->pt_outhit->hit_dist;
	    if ( air_thickness < 0.0 )
		air_thickness = 0.0;
	    if ( !NEAR_ZERO( air_thickness, 0.1 ) )  {
		air_id = 1;	/* air gap */
		if ( R_DEBUG & RDEBUG_HITS )
		    bu_log("air gap added\n");
	    } else {
		air_thickness = 0.0;
	    }
	    prev_id = region_id;
	}

	/*
	 *  Compute the obliquity angles in degrees, ie,
	 *  the "declension" angle down off the normal vector.
	 *  RT normals always point outwards;
	 *  the "inhit" normal points opposite the ray direction,
	 *  the "outhit" normal points along the ray direction.
	 *  Hence the one sign change.
	 *  XXX this should probably be done with atan2()
	 */

	if ( first ) {
	    first = 0;
	    VJOIN1( first_hit, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir );
	}
    out:
	RT_HIT_NORMAL( normal, pp->pt_inhit, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip );
	dot_prod = VDOT( ap->a_ray.r_dir, normal );
	if ( dot_prod > 1.0 )
	    dot_prod = 1.0;
	if ( dot_prod < -1.0 )
	    dot_prod = (-1.0);

	in_obliq = acos( -dot_prod ) *
	    bn_radtodeg;
	RT_HIT_NORMAL( normal, pp->pt_outhit, pp->pt_outseg->seg_stp, &(ap->a_ray), pp->pt_outflip );
	dot_prod = VDOT( ap->a_ray.r_dir, normal );
	if ( dot_prod > 1.0 )
	    dot_prod = 1.0;
	if ( dot_prod < -1.0 )
	    dot_prod = (-1.0);

	out_obliq = acos( dot_prod ) *
	    bn_radtodeg;

	/* Check for exit obliquties greater than 90 degrees. */
#if 0
	if ( in_obliq > 90 || in_obliq < 0 )  {
	    bu_log("ERROR: in_obliquity=%g\n", in_obliq);
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	}
	if ( out_obliq > 90 || out_obliq < 0 )  {
	    bu_log("ERROR: out_obliquity=%g\n", out_obliq);
	    VPRINT(" r_dir", ap->a_ray.r_dir);
	    VPRINT("normal", normal);
	    bu_log("dot=%g, acos(dot)=%g\n",
		   VDOT( ap->a_ray.r_dir, normal ),
		   acos( VDOT( ap->a_ray.r_dir, normal ) ) );
	    /* Print the defective one */
	    rt_pr_pt( ap->a_rt_i, pp );
	    /* Print the whole ray's partition list */
	    rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:");
	}
#endif

	if ( in_obliq > 90.0 )
	    in_obliq = 90.0;
	if ( in_obliq < 0.0 )
	    in_obliq = 0.0;
	if ( out_obliq > 90.0 )
	    out_obliq = 90.0;
	if ( out_obliq < 0.0 )
	    out_obliq = 0.0;

	/*
	 *  Handle 3-components per card output format, with
	 *  a leading space in front of the first component.
	 */
	if ( card_count == 0 )  {
	    bu_vls_strcat( &str, " " );
	}
	comp_thickness *= MM2IN;
	/* Check thickness fields for format overflow */
	if ( comp_thickness > 999.99 || air_thickness*MM2IN > 999.9 )
	    fmt = "%4d%6.1f%5.1f%5.1f%1d%5.0f";
	else
	    fmt = "%4d%6.2f%5.1f%5.1f%1d%5.1f";
#ifdef SPRINTF_NOT_PARALLEL
	bu_semaphore_acquire( BU_SEM_SYSCALL );
#endif
	snprintf(buf, 128, fmt,
		 region_id,
		 comp_thickness,
		 in_obliq, out_obliq,
		 air_id, air_thickness*MM2IN );
#ifdef SPRINTF_NOT_PARALLEL
	bu_semaphore_release( BU_SEM_SYSCALL );
#endif
	bu_vls_strcat( &str, buf );
	card_count++;
	if ( card_count >= 3 )  {
	    bu_vls_strcat( &str, "\n" );
	    card_count = 0;
	}

	/* A color rtg3.pl UnixPlot file of output commands
	 * is generated.  This is processed by plot(1)
	 * plotting filters such as pl-fb or pl-sgi.
	 * Portions of a ray passing through air within the
	 * model are represented in blue, while portions
	 * passing through a solid are assigned green.
	 * This will always be done single CPU,
	 * to prevent output garbling.  (See view_init).
	 */
	if (R_DEBUG & RDEBUG_RAYPLOT) {
	    vect_t     inpt;
	    vect_t     outpt;
	    VJOIN1(inpt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist,
		   ap->a_ray.r_dir);
	    VJOIN1(outpt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist,
		   ap->a_ray.r_dir);
	    pl_color(plotfp, 0, 255, 0);	/* green */
	    pdv_3line(plotfp, inpt, outpt);

	    if (air_thickness > 0) {
		vect_t     air_end;
		VJOIN1(air_end, ap->a_ray.r_pt,
		       pp->pt_outhit->hit_dist + air_thickness,
		       ap->a_ray.r_dir);
		pl_color(plotfp, 0, 0, 255);	/* blue */
		pdv_3cont(plotfp, air_end);
	    }
	}
	if ( nextpp == PartHeadp && air_id != 9 ) {
	    /* need to output a 111 'phantom armor' at end of shotline */
	    air_id = 9;
	    air_thickness = 0.0;
	    region_id = 111;
	    comp_thickness = 0.0;
	    goto out;
	}
    }

    /* If partway through building the line, add a newline */
    if ( card_count > 0 )  {
	/*
	 *  Note that GIFT zero-fills the unused component slots,
	 *  but neither COVART II nor COVART III require it,
	 *  so just end the line here.
	 */
	bu_vls_strcat( &str, "\n" );
    }

    /* Single-thread through file output.
     * COVART will accept non-sequential ray data provided the
     * ray header and its associated data are not separated.  CAVEAT:
     * COVART will not accept headers out of sequence.
     */
    bu_semaphore_acquire( BU_SEM_SYSCALL );

    fputs( bu_vls_addr( &str ), outfp );

    if ( shot_fp )
    {
	fprintf( shot_fp, "%.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %ld %.5f %.5f %.5f\n",
		 azimuth, elevation, V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ),
		 line_num, V3ARGS( first_hit) );

	line_num +=  1 + (comp_count / 3 );
	if ( comp_count % 3 )
	    line_num++;
    }

    /* End of single-thread region */
    bu_semaphore_release( BU_SEM_SYSCALL );

    /* Release vls storage */
    bu_vls_free( &str );

    return(0);
}
예제 #22
0
int hit(register struct application *ap, struct partition *PartHeadp, struct seg *segp)
{
    register struct partition *pp;
    register struct soltab *stp;
    struct curvature cur;
    fastf_t out;
    point_t inpt, outpt;
    vect_t	inormal, onormal;

    if ( (pp=PartHeadp->pt_forw) == PartHeadp )
	return(0);		/* Nothing hit?? */

    if ( overlap_claimant_handling == 1 )
	rt_rebuild_overlaps( PartHeadp, ap, 1 );
    else if ( overlap_claimant_handling == 2 )
	rt_rebuild_overlaps( PartHeadp, ap, 0 );

    /* First, plot ray start to inhit */
    if ( R_DEBUG&RDEBUG_RAYPLOT )  {
	if ( pp->pt_inhit->hit_dist > 0.0001 )  {
	    VJOIN1( inpt, ap->a_ray.r_pt,
		    pp->pt_inhit->hit_dist, ap->a_ray.r_dir );
	    pl_color( plotfp, 0, 0, 255 );
	    pdv_3line( plotfp, ap->a_ray.r_pt, inpt );
	}
    }
    for (; pp != PartHeadp; pp = pp->pt_forw )  {
	matp_t inv_mat;
	Tcl_HashEntry *entry;

	bu_log("\n--- Hit region %s (in %s, out %s) reg_bit = %d\n",
	       pp->pt_regionp->reg_name,
	       pp->pt_inseg->seg_stp->st_name,
	       pp->pt_outseg->seg_stp->st_name,
	       pp->pt_regionp->reg_bit);

	entry = Tcl_FindHashEntry( (Tcl_HashTable *)ap->a_rt_i->Orca_hash_tbl,
				   (const char *)(size_t)pp->pt_regionp->reg_bit );
	if ( !entry ) {
	    inv_mat = (matp_t)NULL;
	}
	else {
	    inv_mat = (matp_t)Tcl_GetHashValue( entry );
	    bn_mat_print( "inv_mat", inv_mat );
	}

	if ( pp->pt_overlap_reg )
	{
	    struct region *pp_reg;
	    int j=-1;

	    bu_log( "    Claiming regions:\n" );
	    while ( (pp_reg=pp->pt_overlap_reg[++j]) )
		bu_log( "        %s\n", pp_reg->reg_name );
	}

	/* inhit info */
	stp = pp->pt_inseg->seg_stp;
	VJOIN1( inpt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir );
	RT_HIT_NORMAL( inormal, pp->pt_inhit, stp, &(ap->a_ray), pp->pt_inflip );
	RT_CURVATURE( &cur, pp->pt_inhit, pp->pt_inflip, stp );

	rt_pr_hit( "  In", pp->pt_inhit );
	VPRINT(    "  Ipoint", inpt );
	VPRINT(    "  Inormal", inormal );
	bu_log(    "   PDir (%g, %g, %g) c1=%g, c2=%g\n",
		   V3ARGS(cur.crv_pdir), cur.crv_c1, cur.crv_c2);

	if ( inv_mat ) {
	    point_t in_trans;

	    MAT4X3PNT( in_trans, inv_mat, inpt );
	    bu_log( "\ttransformed ORCA inhit = (%g %g %g)\n", V3ARGS( in_trans ) );
	}

	/* outhit info */
	stp = pp->pt_outseg->seg_stp;
	VJOIN1( outpt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir );
	RT_HIT_NORMAL( onormal, pp->pt_outhit, stp, &(ap->a_ray), pp->pt_outflip );
	RT_CURVATURE( &cur, pp->pt_outhit, pp->pt_outflip, stp );

	rt_pr_hit( "  Out", pp->pt_outhit );
	VPRINT(    "  Opoint", outpt );
	VPRINT(    "  Onormal", onormal );
	bu_log(    "   PDir (%g, %g, %g) c1=%g, c2=%g\n",
		   V3ARGS(cur.crv_pdir), cur.crv_c1, cur.crv_c2);

	if ( inv_mat ) {
	    point_t out_trans;
	    vect_t dir_trans;

	    MAT4X3PNT( out_trans, inv_mat, outpt );
	    MAT4X3VEC( dir_trans, inv_mat, ap->a_ray.r_dir );
	    VUNITIZE( dir_trans );
	    bu_log( "\ttranformed ORCA outhit = (%g %g %g)\n", V3ARGS( out_trans ) );
	    bu_log( "\ttransformed ORCA ray direction = (%g %g %g)\n", V3ARGS( dir_trans ) );
	}

	/* Plot inhit to outhit */
	if ( R_DEBUG&RDEBUG_RAYPLOT )  {
	    if ( (out = pp->pt_outhit->hit_dist) >= INFINITY )
		out = 10000;	/* to imply the direction */

	    VJOIN1( outpt,
		    ap->a_ray.r_pt, out,
		    ap->a_ray.r_dir );
	    pl_color( plotfp, 0, 255, 255 );
	    pdv_3line( plotfp, inpt, outpt );
	}

	{
	    struct region *regp = pp->pt_regionp;
	    int i;

	    if ( ap->attrs ) {
		bu_log( "\tattribute values:\n" );
		i = 0;
		while ( ap->attrs[i] && regp->attr_values[i] ) {
		    bu_log( "\t\t%s:\n", ap->attrs[i] );
		    bu_log( "\t\t\tstring rep = %s\n",
			    BU_MRO_GETSTRING(regp->attr_values[i]));
		    bu_log( "\t\t\tlong rep = %d\n",
			    BU_MRO_GETLONG(regp->attr_values[i]));
		    bu_log( "\t\t\tdouble rep = %f\n",
			    BU_MRO_GETDOUBLE(regp->attr_values[i]));
		    i++;
		}
	    }
	}
    }
    return(1);
}
예제 #23
0
/* routine to output the faceted NMG representation of a BRL-CAD region */
static void
output_nmg(struct nmgregion *r, const struct db_full_path *pathp, int UNUSED(region_id), int UNUSED(material_id))
{
    struct model *m;
    struct shell *s;
    struct vertex *v;
    char *region_name;

    NMG_CK_REGION(r);
    RT_CK_FULL_PATH(pathp);

    region_name = db_path_to_string(pathp);

    m = r->m_p;
    NMG_CK_MODEL(m);

    /* triangulate model */
    nmg_triangulate_model(m, &tol);

    /* Output triangles */
    if (verbose) {
	printf("Convert these triangles to your format for region %s\n", region_name);
    } else {
	printf("Converted %s\n", region_name);
    }
    for (BU_LIST_FOR(s, shell, &r->s_hd))
    {
	struct faceuse *fu;

	NMG_CK_SHELL(s);

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

	    NMG_CK_FACEUSE(fu);

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

	    /* Grab the face normal if needed */
	    /* NMG_GET_FU_NORMAL(facet_normal, fu); */

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

		NMG_CK_LOOPUSE(lu);

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

		/* loop through the edges in this loop (facet) */
		if (verbose)
		    printf("\tfacet:\n");
		for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd))
		{
		    NMG_CK_EDGEUSE(eu);

		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);
		    if (verbose)
			printf("\t\t(%g %g %g)\n", V3ARGS(v->vg_p->coord));
		}
		tot_polygons++;
	    }
	}
    }

    bu_free(region_name, "region name");
}
예제 #24
0
파일: nurb_ray.c 프로젝트: kanzure/brlcad
struct rt_nurb_uv_hit *
rt_nurb_intersect(const struct face_g_snurb *srf, fastf_t *plane1, fastf_t *plane2, double uv_tol, struct resource *res, struct bu_list *plist)
{
    struct rt_nurb_uv_hit * h;
    struct face_g_snurb * psrf,
	* osrf;
    int dir,
	sub;

    point_t vmin,
	vmax;
    fastf_t u[2],
	v[2];
    struct bu_list rni_plist;

    NMG_CK_SNURB(srf);

    h = (struct rt_nurb_uv_hit *) 0;
    if (plist == NULL) {
	plist = &rni_plist;
	BU_LIST_INIT(plist);
    }

    /* project the surface to a 2 dimensional problem */
    /* NOTE that this gives a single snurb back, NOT a list */
    psrf = rt_nurb_project_srf(srf, plane2, plane1, res);
    psrf->dir = 1;
    BU_LIST_APPEND(plist, &psrf->l);

    if (RT_G_DEBUG & DEBUG_SPLINE)
	rt_nurb_s_print("srf", psrf);

    /* This list starts out with only a single snurb, but more may be
     * added on as work progresses.
     */
    while (BU_LIST_WHILE(psrf, face_g_snurb, plist)) {
	int flat;

	BU_LIST_DEQUEUE(&psrf->l);
	NMG_CK_SNURB(psrf);
	sub = 0;
	flat = 0;
	dir = psrf->dir;

	while (!flat) {
	    fastf_t smin = 0.0, smax = 0.0;

	    sub++;
	    dir = (dir == 0)?1:0;	/* change direction */

	    if (RT_G_DEBUG & DEBUG_SPLINE)
		rt_nurb_s_print("psrf", psrf);

	    rt_nurb_pbound(psrf, vmin, vmax);

	    /* Check for origin to be included in the bounding box */
	    if (!(vmin[0] <= 0.0 && vmin[1] <= 0.0 &&
		  vmax[0] >= 0.0 && vmax[1] >= 0.0)) {
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("this srf doesn't include the origin\n");
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
		continue;
	    }

	    rt_nurb_clip_srf(psrf, dir, &smin, &smax);

	    if ((smax - smin) > .8) {
		struct rt_nurb_uv_hit *hp;

		/* Split surf, requeue both sub-surfs at head */
		/* New surfs will have same dir as arg, here */
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("splitting this surface\n");
		rt_nurb_s_split(plist, psrf, dir, res);
		rt_nurb_free_snurb(psrf, res);

		hp = rt_nurb_intersect(srf, plane1, plane2, uv_tol, res, plist);
		return hp;
	    }
	    if (smin > 1.0 || smax < 0.0) {
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("eliminating this surface (smin=%g, smax=%g)\n", smin, smax);
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
		continue;
	    }
	    if (dir == RT_NURB_SPLIT_ROW) {
		smin = (1.0 - smin) * psrf->u.knots[0] +
		    smin * psrf->u.knots[
			psrf->u.k_size -1];
		smax = (1.0 - smax) * psrf->u.knots[0] +
		    smax * psrf->u.knots[
			psrf->u.k_size -1];
	    } else {
		smin = (1.0 - smin) * psrf->v.knots[0] +
		    smin * psrf->v.knots[
			psrf->v.k_size -1];
		smax = (1.0 - smax) * psrf->v.knots[0] +
		    smax * psrf->v.knots[
			psrf->v.k_size -1];
	    }

	    osrf = psrf;
	    psrf = (struct face_g_snurb *) rt_nurb_region_from_srf(
		osrf, dir, smin, smax, res);

	    psrf->dir = dir;
	    rt_nurb_free_snurb(osrf, res);

	    if (RT_G_DEBUG & DEBUG_SPLINE) {
		bu_log("After call to rt_nurb_region_from_srf() (smin=%g, smax=%g)\n", smin, smax);
		rt_nurb_s_print("psrf", psrf);
	    }

	    u[0] = psrf->u.knots[0];
	    u[1] = psrf->u.knots[psrf->u.k_size -1];

	    v[0] = psrf->v.knots[0];
	    v[1] = psrf->v.knots[psrf->v.k_size -1];

	    if ((u[1] - u[0]) < uv_tol && (v[1] - v[0]) < uv_tol) {
		struct rt_nurb_uv_hit * hit;

		if (RT_G_DEBUG & DEBUG_SPLINE) {
		    fastf_t p1[4], p2[4];
		    int coords;
		    vect_t diff;

		    coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
		    rt_nurb_s_eval(srf, u[0], v[0], p1);
		    rt_nurb_s_eval(srf, u[1], v[1], p2);

		    if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
			fastf_t inv_w;

			inv_w = 1.0 / p1[coords-1];
			VSCALE(p1, p1, inv_w);

			inv_w = 1.0 / p2[coords-1];
			VSCALE(p2, p2, inv_w);
		    }

		    VSUB2(diff, p1, p2);
		    bu_log("Precision of hit point = %g (%f %f %f) <-> (%f %f %f)\n",
			   MAGNITUDE(diff), V3ARGS(p1), V3ARGS(p2));
		}

		hit = (struct rt_nurb_uv_hit *) bu_malloc(
		    sizeof(struct rt_nurb_uv_hit),  "hit");

		hit->next = (struct rt_nurb_uv_hit *)0;
		hit->sub = sub;
		hit->u = (u[0] + u[1])/2.0;
		hit->v = (v[0] + v[1])/2.0;

		if (h == (struct rt_nurb_uv_hit *)0)
		    h = hit;
		else {
		    hit->next = h;
		    h = hit;
		}
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
	    }
	    if ((u[1] - u[0]) > (v[1] - v[0]))
		dir = 1;
	    else dir = 0;
	}
    }

    return (struct rt_nurb_uv_hit *)h;
}
예제 #25
0
파일: g-off.c 프로젝트: cciechad/brlcad
/*
 *			D O _ R E G I O N _ E N D
 *
 *  Called from db_walk_tree().
 *
 *  This routine must be prepared to run in parallel.
 */
union tree *do_region_end(register struct db_tree_state *tsp, struct db_full_path *pathp, union tree *curtree, genptr_t client_data)
{
    union tree		*ret_tree;
    struct nmgregion	*r;
    struct bu_list		vhead;

    RT_CK_TESS_TOL(tsp->ts_ttol);
    BN_CK_TOL(tsp->ts_tol);
    NMG_CK_MODEL(*tsp->ts_m);

    BU_LIST_INIT(&vhead);

    if (RT_G_DEBUG&DEBUG_TREEWALK || verbose) {
	char	*sofar = db_path_to_string(pathp);
	bu_log("\ndo_region_end(%d %d%%) %s\n",
	       regions_tried,
	       regions_tried>0 ? (regions_done * 100) / regions_tried : 0,
	       sofar);
	bu_free(sofar, "path string");
    }

    if (curtree->tr_op == OP_NOP)
	return  curtree;

    regions_tried++;

    /* Begin bomb protection */
    if ( ncpu == 1 ) {
	if ( BU_SETJUMP )  {
	    /* Error, bail out */
	    BU_UNSETJUMP;		/* Relinquish the protection */

	    /* Sometimes the NMG library adds debugging bits when
	     * it detects an internal error, before bombing out.
	     */
	    rt_g.NMG_debug = NMG_debug;	/* restore mode */

	    /* Release the tree memory & input regions */
	    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

	    /* Get rid of (m)any other intermediate structures */
	    if ( (*tsp->ts_m)->magic != -1L )
		nmg_km(*tsp->ts_m);

	    /* Now, make a new, clean model structure for next pass. */
	    *tsp->ts_m = nmg_mm();
	    goto out;
	}
    }
    (void)nmg_model_fuse(*tsp->ts_m, tsp->ts_tol);
    ret_tree = nmg_booltree_evaluate(curtree, tsp->ts_tol, &rt_uniresource);	/* librt/nmg_bool.c */
    BU_UNSETJUMP;		/* Relinquish the protection */
    if ( ret_tree )
	r = ret_tree->tr_d.td_r;
    else
	r = (struct nmgregion *)NULL;
    regions_done++;
    if (r != 0) {
	FILE	*fp_psurf;
	int	i;
	struct bu_vls	file_base;
	struct bu_vls	file;

	bu_vls_init(&file_base);
	bu_vls_init(&file);
	bu_vls_strcpy(&file_base, prefix);
	bu_vls_strcat(&file_base, DB_FULL_PATH_CUR_DIR(pathp)->d_namep);
	/* Dots confuse Jack's Peabody language.  Change to '_'. */
	for (i = 0; i < file_base.vls_len; i++)
	    if (file_base.vls_str[i] == '.')
		file_base.vls_str[i] = '_';

	/* Write color attribute to .fig figure file. */
	if (tsp->ts_mater.ma_color_valid != 0) {
	    fprintf(fp_fig, "\tattribute %s {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig, "\t\trgb = (%f, %f, %f);\n",
		    V3ARGS(tsp->ts_mater.ma_color));
	    fprintf(fp_fig, "\t\tambient = 0.18;\n");
	    fprintf(fp_fig, "\t\tdiffuse = 0.72;\n");
	    fprintf(fp_fig, "\t}\n");
	}

	/* Write segment attributes to .fig figure file. */
	fprintf(fp_fig, "\tsegment %s_seg {\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tpsurf=\"%s.pss\";\n", bu_vls_addr(&file_base));
	if (tsp->ts_mater.ma_color_valid != 0)
	    fprintf(fp_fig,
		    "\t\tattribute=%s;\n", bu_vls_addr(&file_base));
	fprintf(fp_fig, "\t\tsite base->location=trans(0, 0, 0);\n");
	fprintf(fp_fig, "\t}\n");

	if ( bu_vls_strlen(&base_seg) <= 0 )  {
	    bu_vls_vlscat( &base_seg, &file_base );
	} else {
	    fprintf(fp_fig, "\tjoint %s_jt {\n",
		    bu_vls_addr(&file_base));
	    fprintf(fp_fig,
		    "\t\tconnect %s_seg.base to %s_seg.base;\n",
		    bu_vls_addr(&file_base),
		    bu_vls_addr(&base_seg) );
	    fprintf(fp_fig, "\t}\n");
	}

	bu_vls_vlscat(&file, &file_base);
	bu_vls_strcat(&file, ".pss");	/* Required Jack suffix. */

	/* Write psurf to .pss file. */
	if ((fp_psurf = fopen(bu_vls_addr(&file), "wb")) == NULL)
	    perror(bu_vls_addr(&file));
	else {
	    nmg_to_psurf(r, fp_psurf);
	    fclose(fp_psurf);
	    if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	}
	bu_vls_free(&file);

	/* Also write as UNIX-plot file, if desired */
	if ( debug_plots )  {
	    FILE	*fp;
	    bu_vls_vlscat(&file, &file_base);
	    bu_vls_strcat(&file, ".pl");

	    if ((fp = fopen(bu_vls_addr(&file), "wb")) == NULL)
		perror(bu_vls_addr(&file));
	    else {
		struct bu_list	vhead;
		pl_color( fp,
			  (int)(tsp->ts_mater.ma_color[0] * 255),
			  (int)(tsp->ts_mater.ma_color[1] * 255),
			  (int)(tsp->ts_mater.ma_color[2] * 255) );
		/* nmg_pl_r( fp, r ); */
		BU_LIST_INIT( &vhead );
		nmg_r_to_vlist( &vhead, r, 0 );
		rt_vlist_to_uplot( fp, &vhead );
		fclose(fp);
		if (verbose) bu_log("*** Wrote %s\n", bu_vls_addr(&file));
	    }
	    bu_vls_free(&file);
	}

	/* NMG region is no longer necessary */
	nmg_kr(r);
    }

    /*
     *  Dispose of original tree, so that all associated dynamic
     *  memory is released now, not at the end of all regions.
     *  A return of TREE_NULL from this routine signals an error,
     *  so we need to cons up an OP_NOP node to return.
     */
    db_free_tree(curtree, &rt_uniresource);		/* Does an nmg_kr() */

 out:
    BU_GETUNION(curtree, tree);
    curtree->magic = RT_TREE_MAGIC;
    curtree->tr_op = OP_NOP;
    return(curtree);
}
static void
log_Run(void)
{
    time_t clock_time;
    mat_t model2hv;		/* model to h, v matrix */
    mat_t hv2model;		/* h, v tp model matrix */
    quat_t orient;			/* orientation */
    point_t hv_eye;			/* eye position in h, v coords */
    point_t m_eye;			/* eye position in model coords */
    fastf_t hv_viewsize;		/* size of view in h, v coords */
    fastf_t m_viewsize;		/* size of view in model coords. */

    /* Current date and time get printed in header comment */
    (void) time(&clock_time);

    (void) printf("# Log information produced by cell-fb %s\n",
		  ctime(&clock_time));
    (void) printf("az_el: %f %f\n", az, el);
    (void) printf("view_extrema: %f %f %f %f\n",
		  SCRX2H(0), SCRX2H(fb_width), SCRY2V(0), SCRY2V(fb_height));
    (void) printf("fb_size: %d %d\n", fb_width, fb_height);

    /* Produce the orientation, the model eye_pos, and the model
     * view size for input into rtregis.
     * First use the azimuth and elevation to produce the model2hv
     * matrix and use that to find the orientation.
     */

    MAT_IDN(model2hv);
    MAT_IDN(hv2model);

    /* Print out the "view" just to keep rtregis from belly-aching */

    printf("View: %g azimuth, %g elevation\n", az, el);

    /** mat_ae(model2hv, az, el); **/
    /* Formula from rt/do.c */
    bn_mat_angles(model2hv, 270.0+el, 0.0, 270.0-az);
    model2hv[15] = 25.4;		/* input is in inches */
    bn_mat_inv(hv2model, model2hv);

    quat_mat2quat(orient, model2hv);

    printf("Orientation: %.6f, %.6f, %.6f, %.6f\n", V4ARGS(orient));

    /* Now find the eye position in h, v space.  Note that the eye
     * is located at the center of the image; in this case, the center
     * of the screen space, i.e., the framebuffer.)
     * Also find the hv_viewsize at this time.
     */
    hv_viewsize = SCRX2H((double)fb_width) - SCRX2H(0.0);
    hv_eye[0] = SCRX2H((double)fb_width/2);
    hv_eye[1] = SCRY2V((double)fb_height/2);
    hv_eye[2] = hv_viewsize/2;

    /* Debugging */
    printf("hv_viewsize= %g\n", hv_viewsize);
    printf("hv_eye= %.6f, %.6f, %.6f\n", V3ARGS(hv_eye));

    /* Now find the model eye_position and report on that */
    MAT4X3PNT(m_eye, hv2model, hv_eye);
    printf("Eye_pos: %.6f, %.6f, %.6f\n", V3ARGS(m_eye));

    /*
     * Find the view size in model coordinates and print that as well.
     * Important:  Don't use %g format, it may round to nearest integer!
     */
    m_viewsize = hv_viewsize/hv2model[15];
    printf("Size: %.6f\n", m_viewsize);
}
예제 #27
0
파일: nurb_ray.c 프로젝트: kanzure/brlcad
struct face_g_snurb *
rt_nurb_project_srf(const struct face_g_snurb *srf, fastf_t *plane1, fastf_t *plane2, struct resource *res)
{

    register struct face_g_snurb *psrf;
    register fastf_t *mp1, *mp2;
    int n_pt_type;
    int rational;
    int i;

    if (RTG.NMG_debug & DEBUG_RT_ISECT)
	bu_log("rt_nurb_project_srf: projecting surface, planes = (%g %g %g %g) (%g %g %g %g)\n",
	       V4ARGS(plane1), V4ARGS(plane2));

    rational = RT_NURB_IS_PT_RATIONAL(srf->pt_type);

    n_pt_type = RT_NURB_MAKE_PT_TYPE(2, RT_NURB_PT_PROJ, 0);

    psrf = (struct face_g_snurb *) rt_nurb_new_snurb(srf->order[0], srf->order[1],
						     srf->u.k_size, srf->v.k_size,
						     srf->s_size[0], srf->s_size[1], n_pt_type, res);

    psrf->dir = RT_NURB_SPLIT_COL;

    for (i = 0; i < srf->u.k_size; i++) {
	psrf->u.knots[i] = srf->u.knots[i];
    }

    for (i = 0; i < srf->v.k_size; i++) {
	psrf->v.knots[i] = srf->v.knots[i];
    }

    mp1 = srf->ctl_points;
    mp2 = psrf->ctl_points;

    for (i = 0; i < srf->s_size[0] * srf->s_size[1]; i++) {

	if (rational) {
	    mp2[0] = (mp1[0] / mp1[3] * plane1[0] +
		      mp1[1] / mp1[3] * plane1[1] +
		      mp1[2] / mp1[3] * plane1[2] - plane1[3]) *
		mp1[3];
	    mp2[1] = (mp1[0] / mp1[3] * plane2[0] +
		      mp1[1] / mp1[3] * plane2[1] +
		      mp1[2] / mp1[3] * plane2[2] - plane2[3]) *
		mp1[3];
	} else {
	    mp2[0] = mp1[0] * plane1[0] + mp1[1] * plane1[1] +
		mp1[2] * plane1[2] - plane1[3];
	    mp2[1] = mp1[0] * plane2[0] + mp1[1] * plane2[1] +
		mp1[2] * plane2[2] - plane2[3];
	}

	if (RTG.NMG_debug & DEBUG_RT_ISECT) {
	    if (rational)
		bu_log("\tmesh pt (%g %g %g %g), becomes (%g %g)\n", V4ARGS(mp1), mp2[0], mp2[1]);
	    else
		bu_log("\tmesh pt (%g %g %g), becomes (%g %g)\n", V3ARGS(mp1), mp2[0], mp2[1]);
	}

	mp1 += RT_NURB_EXTRACT_COORDS(srf->pt_type);
	mp2 += RT_NURB_EXTRACT_COORDS(psrf->pt_type);
    }

    return (struct face_g_snurb *) psrf;
}
예제 #28
0
파일: enf-g.c 프로젝트: kanzure/brlcad
struct obj_info *
Part_import( int id_start )
{
    char line[MAX_LINE_SIZE];
    struct obj_info *part;
    struct wmember reg_head;
    unsigned char rgb[3];
    int surf_count=0;
    int id_end;
    int last_surf=0;
    int i;
    int tri[3];
    int corner_index=-1;

    clean_vert_tree( tree_root );

    VSETALL( rgb, 128 );

    BU_ALLOC(part, struct obj_info);
    part->obj_type = PART_TYPE;
    part->obj_id = id_start;
    while ( bu_fgets( line, MAX_LINE_SIZE, fd_in ) ) {
	if ( !bu_strncmp( line, "PartName", 8 ) ) {
	    line[strlen( line ) - 1] = '\0';
	    part->obj_name = bu_strdup( &line[9] );
	    lower_case( part->obj_name );
	    Make_brlcad_names( part );
	} else if ( !bu_strncmp( line, "FaceCount", 9 ) ) {
	    surf_count = atoi( &line[10] );
	    if ( surf_count == 0 ) {
		last_surf = 1;
	    }
	} else if ( !bu_strncmp( line, "EndPartId", 9 ) ) {
	    /* found end of part, check id */
	    id_end = atoi( &line[10] );
	    if ( id_end != id_start )
		bu_exit( 1, "%s: ERROR: found end of part id %d while processing part %d\n", progname,id_end, id_start );
	    if ( last_surf ) {
		break;
	    }
	} else if ( !bu_strncmp( line, "FaceRGB", 7 ) ) {
	    /* get face color */
	    char *ptr;

	    i = 8;
	    ptr = strtok( &line[i], " \t" );
	    for ( i=0; i<3 && ptr; i++ ) {
		rgb[i] = atof( ptr );
		ptr = strtok( (char *)NULL, " \t" );
	    }
	} else if ( !bu_strncmp( line, "Facet", 5 ) ) {
	    /* read a triangle */
	    VSETALL( tri, -1 );
	    corner_index = -1;
	} else if ( !bu_strncmp( line, "Face", 4 ) ) {
	    /* start of a surface */
	    int surf_no;

	    surf_no = atoi( &line[5] );
	    if ( surf_no == surf_count ) {
		last_surf = 1;
	    }
	} else if ( !bu_strncmp( line, "TriangleCount", 13 ) ) {
	    /* get number of triangles for this surface */
	} else if ( !bu_strncmp( line, "Vertices", 9 ) ) {
	    /* get vertex list for this triangle */
	} else if ( !bu_strncmp( line, "Vertex", 6 ) ) {
	    /* get a vertex */
	    char *ptr = NULL;
	    vect_t v = VINIT_ZERO;

	    i = 7;
	    while ( !isspace( (int)line[i] ) && line[i] != '\0' )
		i++;
	    ptr = strtok( &line[i], " \t" );
	    for ( i=0; i<3 && ptr; i++ ) {
		v[i] = atof( ptr );
		ptr = strtok( (char *)NULL, " \t" );
	    }
	    tri[++corner_index] = Add_vert( V3ARGS( v ), tree_root, local_tol_sq );
	    if ( corner_index == 2 ) {
		if ( !bad_triangle( tri, tree_root->the_array ) ) {
		    add_triangle( tri );
		}
	    }
	} else if ( !bu_strncmp( line, "Normal", 6 ) ) {
	    /* get a vertex normal */
	} else if ( !bu_strncmp( line, "PointCount", 10 ) ) {
	    /* get number of vertices for this surface */
	} else
	    bu_exit( 1, "%s: ERROR: unrecognized line encountered while processing part id %d:\n%s\n", progname,id_start, line );
    }

    if ( curr_tri == 0 ) {
	/* no facets in this part, so ignore it */
	bu_free( (char *)part, "part" );
	part = (struct obj_info *)NULL;
    } else {

	/* write this part to database, first make a primitive solid */
	if ( mk_bot( fd_out, part->brlcad_solid, RT_BOT_SOLID, RT_BOT_UNORIENTED, 0,
		     tree_root->curr_vert, curr_tri, tree_root->the_array, part_tris, NULL, NULL ) )
	    bu_exit( 1, "%s: Failed to write primitive %s (%s) to database\n", progname,part->brlcad_solid, part->obj_name );
	if ( verbose ) {
	    DO_INDENT;
	    bu_log( "Wrote BOT %s\n", part->brlcad_solid );
	}

	/* then a region */
	BU_LIST_INIT( &reg_head.l );
	if ( mk_addmember( part->brlcad_solid, &reg_head.l, NULL, WMOP_UNION ) == WMEMBER_NULL )
	    bu_exit( 1, "%s: ERROR: Failed to add solid (%s), to region (%s)\n", progname,part->brlcad_solid, part->brlcad_comb );
	if ( mk_comb( fd_out, part->brlcad_comb, &reg_head.l, 1, NULL, NULL, rgb, ident++,
		      0, 1, 100, 0, 0, 0 ) )
	    bu_exit( 1, "%s: Failed to write region %s (%s) to database\n", progname,part->brlcad_comb, part->obj_name );
	if ( verbose ) {
	    DO_INDENT;
	    bu_log( "Wrote region %s\n", part->brlcad_comb );
	}

	if ( use_part_name_hash ) {
	    if ( db5_update_attribute( part->brlcad_comb, "Part_No",
				       part->obj_name, fd_out->dbip ) ) {
		bu_log( "Failed to assign Part_no attribute to %s\n",
			part->brlcad_comb );
	    }
	}
    }

    /* free some memory */
    if ( part_tris ) {
	bu_free( (char *)part_tris, "part_tris" );
    }
    max_tri = 0;
    curr_tri = 0;
    part_tris = NULL;

    return part;
}
예제 #29
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 */
}
void
nmg_2_vrml(struct db_tree_state *tsp, const struct db_full_path *pathp, struct model *m)
{
    struct mater_info *mater = &tsp->ts_mater;
    const struct bn_tol *tol2 = tsp->ts_tol;
    struct nmgregion *reg;
    struct bu_ptbl verts;
    struct vrml_mat mat;
    struct bu_vls vls = BU_VLS_INIT_ZERO;
    char *tok;
    int i;
    int first = 1;
    int is_light = 0;
    point_t ave_pt = VINIT_ZERO;
    struct bu_vls shape_name = BU_VLS_INIT_ZERO;
    char *full_path;
    /* There may be a better way to capture the region_id, than
     * getting the rt_comb_internal structure, (and may be a better
     * way to capture the rt_comb_internal struct), but for now I just
     * copied the method used in select_lights/select_non_lights above,
     * could have used a global variable but I noticed none other were
     * used, so I didn't want to be the first
     */
    struct directory *dp;
    struct rt_db_internal intern;
    struct rt_comb_internal *comb;
    int id;

    /* static due to libbu exception handling */
    static float r, g, b;

    NMG_CK_MODEL(m);

    full_path = db_path_to_string(pathp);

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

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

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

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

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

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

    if (mater->ma_shader) {
	tok = strtok(mater->ma_shader, tok_sep);
	bu_strlcpy(mat.shader, tok, TXT_NAME_SIZE);
    } else {
	mat.shader[0] = '\0';
    }

    mat.shininess = -1;
    mat.transparency = -1.0;
    mat.lt_fraction = -1.0;
    VSETALL(mat.lt_dir, 0.0);
    mat.lt_angle = -1.0;
    mat.tx_file[0] = '\0';
    mat.tx_w = -1;
    mat.tx_n = -1;
    bu_vls_strcpy(&vls, &mater->ma_shader[strlen(mat.shader)]);
    (void)bu_struct_parse(&vls, vrml_mat_parse, (char *)&mat, NULL);

    if (bu_strncmp("light", mat.shader, 5) == 0) {
	/* this is a light source */
	is_light = 1;
    } else {
	path_2_vrml_id(&shape_name, full_path);
	fprintf(fp_out, "\t\tDEF %s Shape {\n", bu_vls_addr(&shape_name));

	fprintf(fp_out, "\t\t\t# Component_ID: %ld   %s\n", comb->region_id, full_path);
	fprintf(fp_out, "\t\t\tappearance Appearance {\n");

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

	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b);
	    fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0));
	    if (mat.transparency > SMALL_FASTF) {
		fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency);
	    }
	    fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0);
	} else if (bu_strncmp("glass", mat.shader, 5) == 0) {
	    if (mat.shininess < 0) {
		mat.shininess = 4;
	    }
	    if (mat.transparency < SMALL_FASTF) {
		mat.transparency = 0.8;
	    }

	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g \n", r, g, b);
	    fprintf(fp_out, "\t\t\t\t\tshininess %g\n", 1.0-exp(-(double)mat.shininess/20.0));
	    if (mat.transparency > SMALL_FASTF) {
		fprintf(fp_out, "\t\t\t\t\ttransparency %g\n", mat.transparency);
	    }
	    fprintf(fp_out, "\t\t\t\t\tspecularColor %g %g %g \n\t\t\t\t}\n", 1.0, 1.0, 1.0);
	} else if (bu_strncmp("texture", mat.shader, 7) == 0) {
	    if (mat.tx_w < 0) {
		mat.tx_w = 512;
	    }
	    if (mat.tx_n < 0) {
		mat.tx_n = 512;
	    }
	    if (strlen(mat.tx_file)) {
		int tex_fd;
		unsigned char tex_buf[TXT_BUF_LEN * 3];

		if ((tex_fd = open(mat.tx_file, O_RDONLY | O_BINARY)) == (-1)) {
		    bu_log("Cannot open texture file (%s)\n", mat.tx_file);
		    perror("g-vrml: ");
		} else {
		    long tex_len;
		    long bytes_read = 0;
		    long bytes_to_go = 0;

		    /* Johns note - need to check (test) the texture stuff */
		    fprintf(fp_out, "\t\t\t\ttextureTransform TextureTransform {\n");
		    fprintf(fp_out, "\t\t\t\t\tscale 1.33333 1.33333\n\t\t\t\t}\n");
		    fprintf(fp_out, "\t\t\t\ttexture PixelTexture {\n");
		    fprintf(fp_out, "\t\t\t\t\trepeatS TRUE\n");
		    fprintf(fp_out, "\t\t\t\t\trepeatT TRUE\n");
		    fprintf(fp_out, "\t\t\t\t\timage %d %d %d\n", mat.tx_w, mat.tx_n, 3);
		    tex_len = mat.tx_w*mat.tx_n * 3;
		    while (bytes_read < tex_len) {
			int nbytes;
			long readval;

			bytes_to_go = tex_len - bytes_read;
			CLAMP(bytes_to_go, 0, TXT_BUF_LEN * 3);

			nbytes = 0;
			while (nbytes < bytes_to_go) {
			    readval = read(tex_fd, &tex_buf[nbytes], bytes_to_go-nbytes);
			    if (readval < 0) {
				perror("READ ERROR");
				break;
			    } else {
				nbytes += readval;
			    }
			}
			bytes_read += nbytes;
			for (i = 0; i < nbytes; i += 3) {
			    fprintf(fp_out, "\t\t\t0x%02x%02x%02x\n",
				    tex_buf[i], tex_buf[i+1], tex_buf[i+2]);
			}
		    }
		    fprintf(fp_out, "\t\t\t\t}\n");

		    close(tex_fd);
		}
	    }
	} else if (mater->ma_color_valid) {
	    /* no shader specified, but a color is assigned */
	    fprintf(fp_out, "\t\t\t\tmaterial Material {\n");
	    fprintf(fp_out, "\t\t\t\t\tdiffuseColor %g %g %g }\n", r, g, b);
	} else {
	    /* If no color was defined set the colors according to the thousands groups */
	    int thou = comb->region_id / 1000;
	    thou == 0 ? fprintf(fp_out, "\t\t\tmaterial USE Material_999\n")
		: thou == 1 ? fprintf(fp_out, "\t\t\tmaterial USE Material_1999\n")
		: thou == 2 ? fprintf(fp_out, "\t\t\tmaterial USE Material_2999\n")
		: thou == 3 ? fprintf(fp_out, "\t\t\tmaterial USE Material_3999\n")
		: thou == 4 ? fprintf(fp_out, "\t\t\tmaterial USE Material_4999\n")
		: thou == 5 ? fprintf(fp_out, "\t\t\tmaterial USE Material_5999\n")
		: thou == 6 ? fprintf(fp_out, "\t\t\tmaterial USE Material_6999\n")
		: thou == 7 ? fprintf(fp_out, "\t\t\tmaterial USE Material_7999\n")
		: thou == 8 ? fprintf(fp_out, "\t\t\tmaterial USE Material_8999\n")
		: fprintf(fp_out, "\t\t\tmaterial USE Material_9999\n");
	}
    }

    if (!is_light) {
	nmg_triangulate_model(m, tol2);
	fprintf(fp_out, "\t\t\t}\n");
	fprintf(fp_out, "\t\t\tgeometry IndexedFaceSet {\n");
	fprintf(fp_out, "\t\t\t\tcoord Coordinate {\n");
    }

    /* get list of vertices */
    nmg_vertex_tabulate(&verts, &m->magic);
    if (!is_light) {
	fprintf(fp_out, "\t\t\t\t\tpoint [");
    } else {
	VSETALL(ave_pt, 0.0);
    }

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

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

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

	if (is_light) {
	    VADD2(ave_pt, ave_pt, pt_meters);
	}

	if (first) {
	    if (!is_light) {
		fprintf(fp_out, " %10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i);
	    }
	    first = 0;
	} else if (!is_light) {
	    fprintf(fp_out, "\t\t\t\t\t%10.10e %10.10e %10.10e, # point %d\n", V3ARGS(pt_meters), i);
	}
    }

    if (!is_light) {
	fprintf(fp_out, "\t\t\t\t\t]\n\t\t\t\t}\n");
    } else {
	fastf_t one_over_count;
	one_over_count = 1.0/(fastf_t)BU_PTBL_END(&verts);
	VSCALE(ave_pt, ave_pt, one_over_count);
    }

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

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

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

		    NMG_CK_FACEUSE(fu);

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

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

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

			if (!first) {
			    fprintf(fp_out, ",\n");
			} else {
			    first = 0;
			}

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

			    NMG_CK_EDGEUSE(eu);
			    v = eu->vu_p->v_p;
			    NMG_CK_VERTEX(v);
			    fprintf(fp_out, " %d,", bu_ptbl_locate(&verts, (long *)v));
			}
			fprintf(fp_out, "-1");
		    }
		}
	    }
	}
	fprintf(fp_out, "\n\t\t\t\t]\n\t\t\t\tnormalPerVertex FALSE\n");
	fprintf(fp_out, "\t\t\t\tconvex FALSE\n");
	fprintf(fp_out, "\t\t\t\tcreaseAngle 0.5\n");
	fprintf(fp_out, "\t\t\t}\n\t\t}\n");
    } else {