コード例 #1
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));
    }
}
コード例 #2
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;
    }
}
コード例 #3
0
ファイル: BrepHandler.cpp プロジェクト: cciechad/brlcad
  int
  BrepHandler::extractCircularArc(const DirectoryEntry* de, const ParameterData& params) {
    point_t center, start, end;
    double offset_z = params.getReal(1);
    center[X] = params.getReal(2);
    center[Y] = params.getReal(3);
    center[Z] = offset_z;
    start[X]  = params.getReal(4);
    start[Y]  = params.getReal(5);
    start[Z]  = offset_z;
    end[X]    = params.getReal(6);
    end[Y]    = params.getReal(7);
    end[Z]    = offset_z;

    mat_t xform;
    MAT_IDN(xform);
    _iges->getTransformation(de->xform(), xform);

    // choose the circle/interval representation
    // so, calculate the circle params, and then the angle the arc subtends
    double dx = start[X] - center[X];
    double dy = start[Y] - center[Y];
    double radius = sqrt(dx*dx + dy*dy);

    point_t tcenter, tstart, tend;
    MAT4X3PNT(tcenter, xform, center);
    MAT4X3PNT(tstart, xform, start);
    MAT4X3PNT(tend, xform, end);
    vect_t normal = {0,0,1};
    vect_t tnormal;
    MAT4X3VEC(tnormal, xform, normal);

    return handleCircularArc(radius, tcenter, tnormal, tstart, tend);
  }
コード例 #4
0
ファイル: superell.c プロジェクト: kanzure/brlcad
/**
 * Import an superellipsoid/sphere from the database format to the
 * internal structure.  Apply modeling transformations as wsuperell.
 */
int
rt_superell_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
{
    struct rt_superell_internal *eip;
    union record *rp;
    fastf_t vec[3*4 + 2];

    if (dbip) RT_CK_DBI(dbip);

    BU_CK_EXTERNAL(ep);
    rp = (union record *)ep->ext_buf;
    /* Check record type */
    if (rp->u_id != ID_SOLID) {
        bu_log("rt_superell_import4():  defective record\n");
        return -1;
    }

    RT_CK_DB_INTERNAL(ip);
    ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
    ip->idb_type = ID_SUPERELL;
    ip->idb_meth = &OBJ[ID_SUPERELL];
    BU_ALLOC(ip->idb_ptr, struct rt_superell_internal);

    eip = (struct rt_superell_internal *)ip->idb_ptr;
    eip->magic = RT_SUPERELL_INTERNAL_MAGIC;

    /* Convert from database to internal format */
    flip_fastf_float(vec, rp->s.s_values, 4, dbip->dbi_version < 0 ? 1 : 0);

    /* Apply modeling transformations */
    if (mat == NULL) mat = bn_mat_identity;
    MAT4X3PNT(eip->v, mat, &vec[0*3]);
    MAT4X3VEC(eip->a, mat, &vec[1*3]);
    MAT4X3VEC(eip->b, mat, &vec[2*3]);
    MAT4X3VEC(eip->c, mat, &vec[3*3]);

    if (dbip->dbi_version < 0) {
        eip->n = flip_dbfloat(rp->s.s_values[12]);
        eip->e = flip_dbfloat(rp->s.s_values[13]);
    } else {
        eip->n = rp->s.s_values[12];
        eip->e = rp->s.s_values[13];
    }

    return 0;		/* OK */
}
コード例 #5
0
ファイル: vutil.c プロジェクト: kanzure/brlcad
void
ged_view_update(struct ged_view *gvp)
{
    vect_t work, work1;
    vect_t temp, temp1;

    if (!gvp)
        return;

    bn_mat_mul(gvp->gv_model2view,
               gvp->gv_rotation,
               gvp->gv_center);
    gvp->gv_model2view[15] = gvp->gv_scale;
    bn_mat_inv(gvp->gv_view2model, gvp->gv_model2view);

    /* Find current azimuth, elevation, and twist angles */
    VSET(work, 0.0, 0.0, 1.0);       /* view z-direction */
    MAT4X3VEC(temp, gvp->gv_view2model, work);
    VSET(work1, 1.0, 0.0, 0.0);      /* view x-direction */
    MAT4X3VEC(temp1, gvp->gv_view2model, work1);

    /* calculate angles using accuracy of 0.005, since display
     * shows 2 digits right of decimal point */
    bn_aet_vec(&gvp->gv_aet[0],
               &gvp->gv_aet[1],
               &gvp->gv_aet[2],
               temp, temp1, (fastf_t)0.005);

    /* Force azimuth range to be [0, 360] */
    if ((NEAR_EQUAL(gvp->gv_aet[1], 90.0, (fastf_t)0.005) ||
            NEAR_EQUAL(gvp->gv_aet[1], -90.0, (fastf_t)0.005)) &&
            gvp->gv_aet[0] < 0 &&
            !NEAR_ZERO(gvp->gv_aet[0], (fastf_t)0.005))
        gvp->gv_aet[0] += 360.0;
    else if (NEAR_ZERO(gvp->gv_aet[0], (fastf_t)0.005))
        gvp->gv_aet[0] = 0.0;

    /* apply the perspective angle to model2view */
    bn_mat_mul(gvp->gv_pmodel2view, gvp->gv_pmat, gvp->gv_model2view);

    if (gvp->gv_callback)
        (*gvp->gv_callback)(gvp, gvp->gv_clientData);
}
コード例 #6
0
ファイル: rotate_tgc.c プロジェクト: kanzure/brlcad
int
_ged_rotate_tgc(struct ged *gedp, struct rt_tgc_internal *tgc, const char *attribute, matp_t rmat)
{
    RT_TGC_CK_MAGIC(tgc);

    switch (attribute[0]) {
    case 'h':
    case 'H':
        switch (attribute[1]) {
        case '\0':
            MAT4X3VEC(tgc->h, rmat, tgc->h);
            break;
        case 'a':
        case 'A':
            if ((attribute[2] == 'b' || attribute[2] == 'B') &&
                    attribute[3] == '\0') {
                MAT4X3VEC(tgc->a, rmat, tgc->a);
                MAT4X3VEC(tgc->b, rmat, tgc->b);
                MAT4X3VEC(tgc->c, rmat, tgc->c);
                MAT4X3VEC(tgc->d, rmat, tgc->d);
            } else {
                bu_vls_printf(gedp->ged_result_str, "bad tgc attribute - %s", attribute);
                return GED_ERROR;
            }

            break;
        default:
            bu_vls_printf(gedp->ged_result_str, "bad tgc attribute - %s", attribute);
            return GED_ERROR;
        }

        break;
    default:
        bu_vls_printf(gedp->ged_result_str, "bad tgc attribute - %s", attribute);
        return GED_ERROR;
    }

    return GED_OK;
}
コード例 #7
0
ファイル: superell.c プロジェクト: kanzure/brlcad
/**
 * Import an superellipsoid/sphere from the database format to the
 * internal structure.  Apply modeling transformations as wsuperell.
 */
int
rt_superell_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
{
    struct rt_superell_internal *eip;

    /* must be double for import and export */
    double vec[ELEMENTS_PER_VECT*4 + 2];

    if (dbip) RT_CK_DBI(dbip);

    RT_CK_DB_INTERNAL(ip);
    BU_CK_EXTERNAL(ep);

    BU_ASSERT_LONG(ep->ext_nbytes, ==, SIZEOF_NETWORK_DOUBLE * (ELEMENTS_PER_VECT*4 + 2));

    ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
    ip->idb_type = ID_SUPERELL;
    ip->idb_meth = &OBJ[ID_SUPERELL];
    BU_ALLOC(ip->idb_ptr, struct rt_superell_internal);

    eip = (struct rt_superell_internal *)ip->idb_ptr;
    eip->magic = RT_SUPERELL_INTERNAL_MAGIC;

    /* Convert from database (network) to internal (host) format */
    bu_cv_ntohd((unsigned char *)vec, ep->ext_buf, ELEMENTS_PER_VECT*4 + 2);

    /* Apply modeling transformations */
    if (mat == NULL) mat = bn_mat_identity;
    MAT4X3PNT(eip->v, mat, &vec[0*ELEMENTS_PER_VECT]);
    MAT4X3VEC(eip->a, mat, &vec[1*ELEMENTS_PER_VECT]);
    MAT4X3VEC(eip->b, mat, &vec[2*ELEMENTS_PER_VECT]);
    MAT4X3VEC(eip->c, mat, &vec[3*ELEMENTS_PER_VECT]);
    eip->n = vec[4*ELEMENTS_PER_VECT];
    eip->e = vec[4*ELEMENTS_PER_VECT + 1];

    return 0;		/* OK */
}
コード例 #8
0
ファイル: vutil.c プロジェクト: kanzure/brlcad
/**
 * Create a perspective matrix that transforms the +/1 viewing cube,
 * with the actual eye position (not at Z=+1) specified in viewing
 * coords, into a related space where the eye has been sheared onto
 * the Z axis and repositioned at Z=(0, 0, 1), with the same
 * perspective field of view as before.
 *
 * The Zbuffer clips off stuff with negative Z values.
 *
 * pmat = persp * xlate * shear
 */
void
ged_mike_persp_mat(mat_t pmat,
                   const point_t eye)
{
    mat_t shear;
    mat_t persp;
    mat_t xlate;
    mat_t t1, t2;
    point_t sheared_eye;

    if (eye[Z] <= SMALL) {
        VPRINT("mike_persp_mat(): ERROR, z<0, eye", eye);
        return;
    }

    /* Shear "eye" to +Z axis */
    MAT_IDN(shear);
    shear[2] = -eye[X]/eye[Z];
    shear[6] = -eye[Y]/eye[Z];

    MAT4X3VEC(sheared_eye, shear, eye);
    if (!NEAR_ZERO(sheared_eye[X], .01) || !NEAR_ZERO(sheared_eye[Y], .01)) {
        VPRINT("ERROR sheared_eye", sheared_eye);
        return;
    }

    /* Translate along +Z axis to put sheared_eye at (0, 0, 1). */
    MAT_IDN(xlate);
    /* XXX should I use MAT_DELTAS_VEC_NEG()?  X and Y should be 0 now */
    MAT_DELTAS(xlate, 0, 0, 1-sheared_eye[Z]);

    /* Build perspective matrix inline, substituting fov=2*atan(1, Z) */
    MAT_IDN(persp);
    /* From page 492 of Graphics Gems */
    persp[0] = sheared_eye[Z];	/* scaling: fov aspect term */
    persp[5] = sheared_eye[Z];	/* scaling: determines fov */

    /* From page 158 of Rogers Mathematical Elements */
    /* Z center of projection at Z=+1, r=-1/1 */
    persp[14] = -1;

    bn_mat_mul(t1, xlate, shear);
    bn_mat_mul(t2, persp, t1);

    /* Now, move eye from Z=1 to Z=0, for clipping purposes */
    MAT_DELTAS(xlate, 0, 0, -1);

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

    vect_t xlated;
    fastf_t scale;

    VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
    VSUB2(xlated, hitp->hit_point, superell->superell_V);
    MAT4X3VEC(hitp->hit_normal, superell->superell_invRSSR, xlated);
    scale = 1.0 / MAGNITUDE(hitp->hit_normal);
    VSCALE(hitp->hit_normal, hitp->hit_normal, scale);

    return;
}
コード例 #10
0
ファイル: arbn.c プロジェクト: kanzure/brlcad
/**
 * Convert from "network" doubles to machine specific.
 * Transform
 */
int
rt_arbn_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
{
    union record *rp;
    struct rt_arbn_internal *aip;
    size_t i;

    /* must be double for import and export */
    double *scan;

    if (dbip) RT_CK_DBI(dbip);

    BU_CK_EXTERNAL(ep);
    rp = (union record *)ep->ext_buf;
    if (rp->u_id != DBID_ARBN) {
	bu_log("rt_arbn_import4: defective record, id=x%x\n", rp->u_id);
	return -1;
    }

    RT_CK_DB_INTERNAL(ip);
    ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
    ip->idb_type = ID_ARBN;
    ip->idb_meth = &OBJ[ID_ARBN];
    BU_ALLOC(ip->idb_ptr, struct rt_arbn_internal);

    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    aip->magic = RT_ARBN_INTERNAL_MAGIC;
    aip->neqn = ntohl(*(uint32_t *)rp->n.n_neqn);
    if (aip->neqn <= 0) return -1;

    aip->eqn = (plane_t *)bu_malloc(aip->neqn*sizeof(plane_t), "arbn plane eqn[]");
    scan = (double *)bu_malloc(aip->neqn*sizeof(double)*ELEMENTS_PER_PLANE, "scan array");

    bu_cv_ntohd((unsigned char *)scan, (unsigned char *)(&rp[1]), aip->neqn*ELEMENTS_PER_PLANE);
    for (i = 0; i < aip->neqn; i++) {
	aip->eqn[i][X] = scan[(i*ELEMENTS_PER_PLANE)+0]; /* convert double to fastf_t */
	aip->eqn[i][Y] = scan[(i*ELEMENTS_PER_PLANE)+1]; /* convert double to fastf_t */
	aip->eqn[i][Z] = scan[(i*ELEMENTS_PER_PLANE)+2]; /* convert double to fastf_t */
	aip->eqn[i][W] = scan[(i*ELEMENTS_PER_PLANE)+3]; /* convert double to fastf_t */
    }
    bu_free(scan, "scan array");

    /* Transform by the matrix */
    if (mat == NULL) mat = bn_mat_identity;
    for (i = 0; i < aip->neqn; i++) {
	point_t orig_pt;
	point_t pt;
	vect_t norm;
	fastf_t factor;

	/* unitize the plane equation first */
	factor = 1.0 / MAGNITUDE(aip->eqn[i]);
	VSCALE(aip->eqn[i], aip->eqn[i], factor);
	aip->eqn[i][W] = aip->eqn[i][W] * factor;


	/* Pick a point on the original halfspace */
	VSCALE(orig_pt, aip->eqn[i], aip->eqn[i][W]);

	/* Transform the point, and the normal */
	MAT4X3VEC(norm, mat, aip->eqn[i]);
	MAT4X3PNT(pt, mat, orig_pt);

	/* Measure new distance from origin to new point */
	VUNITIZE(norm);
	VMOVE(aip->eqn[i], norm);
	aip->eqn[i][W] = VDOT(pt, norm);
    }

    return 0;
}
コード例 #11
0
ファイル: superell.c プロジェクト: kanzure/brlcad
/**
 * Intersect a ray with an superellipsoid, where all constant terms
 * have been precomputed by rt_superell_prep().  If an intersection
 * occurs, a struct seg will be acquired and filled in.
 *
 * Returns -
 * 0 MISS
 * >0 HIT
 */
int
rt_superell_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
{
    static int counter=10;

    struct superell_specific *superell = (struct superell_specific *)stp->st_specific;
    bn_poly_t equation; /* equation of superell to be solved */
    vect_t translated;  /* translated shot vector */
    vect_t newShotPoint; /* P' */
    vect_t newShotDir; /* D' */
    vect_t normalizedShotPoint; /* P' with normalized dist from superell */
    bn_complex_t complexRoot[4]; /* roots returned from poly solver */
    double realRoot[4];  /* real ray distance values */
    int i, j;
    struct seg *segp;

    /* translate ray point */
    /* VSUB2(translated, rp->r_pt, superell->superell_V); */
    (translated)[X] = (rp->r_pt)[X] - (superell->superell_V)[X];
    (translated)[Y] = (rp->r_pt)[Y] - (superell->superell_V)[Y];
    (translated)[Z] = (rp->r_pt)[Z] - (superell->superell_V)[Z];

    /* scale and rotate point to get P' */

    /* MAT4X3VEC(newShotPoint, superell->superell_SoR, translated); */
    newShotPoint[X] = (superell->superell_SoR[0]*translated[X] + superell->superell_SoR[1]*translated[Y] + superell->superell_SoR[ 2]*translated[Z]) * 1.0/(superell->superell_SoR[15]);
    newShotPoint[Y] = (superell->superell_SoR[4]*translated[X] + superell->superell_SoR[5]*translated[Y] + superell->superell_SoR[ 6]*translated[Z]) * 1.0/(superell->superell_SoR[15]);
    newShotPoint[Z] = (superell->superell_SoR[8]*translated[X] + superell->superell_SoR[9]*translated[Y] + superell->superell_SoR[10]*translated[Z]) * 1.0/(superell->superell_SoR[15]);

    /* translate ray direction vector */
    MAT4X3VEC(newShotDir, superell->superell_SoR, rp->r_dir);
    VUNITIZE(newShotDir);

    /* normalize distance from the superell.  substitutes a corrected ray
     * point, which contains a translation along the ray direction to the
     * closest approach to vertex of the superell.  Translating the ray
     * along the direction of the ray to the closest point near the
     * primitive's center vertex.  New ray origin is hence, normalized.
     */
    VSCALE(normalizedShotPoint, newShotDir,
           VDOT(newShotPoint, newShotDir));
    VSUB2(normalizedShotPoint, newShotPoint, normalizedShotPoint);

    /* Now generate the polynomial equation for passing to the root finder */

    equation.dgr = 2;

    /* (x^2 / A) + (y^2 / B) + (z^2 / C) - 1 */
    equation.cf[0] = newShotPoint[X] * newShotPoint[X] * superell->superell_invmsAu + newShotPoint[Y] * newShotPoint[Y] * superell->superell_invmsBu + newShotPoint[Z] * newShotPoint[Z] * superell->superell_invmsCu - 1;
    /* (2xX / A) + (2yY / B) + (2zZ / C) */
    equation.cf[1] = 2 * newShotDir[X] * newShotPoint[X] * superell->superell_invmsAu + 2 * newShotDir[Y] * newShotPoint[Y] * superell->superell_invmsBu + 2 * newShotDir[Z] * newShotPoint[Z] * superell->superell_invmsCu;
    /* (X^2 / A) + (Y^2 / B) + (Z^2 / C) */
    equation.cf[2] = newShotDir[X] * newShotDir[X] * superell->superell_invmsAu + newShotDir[Y] * newShotDir[Y] * superell->superell_invmsBu + newShotDir[Z] * newShotDir[Z] * superell->superell_invmsCu;

    if ((i = rt_poly_roots(&equation, complexRoot, stp->st_dp->d_namep)) != 2) {
        if (i > 0) {
            bu_log("rt_superell_shot():  poly roots %d != 2\n", i);
            bn_pr_roots(stp->st_name, complexRoot, i);
        } else if (i < 0) {
            static int reported=0;
            bu_log("rt_superell_shot():  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("rt_superell_shot():  Additional superellipsoid convergence failure details will be suppressed.\n");
                reported=1;
            }
        }
        return 0; /* MISS */
    }

    /* XXX BEGIN CUT */
    /* Only real roots indicate an intersection in real space.
     *
     * Look at each root returned; if the imaginary part is zero
     * or sufficiently close, then use the real part as one value
     * of 't' for the intersections
     */
    for (j=0, i=0; j < 2; j++) {
        if (NEAR_ZERO(complexRoot[j].im, 0.001))
            realRoot[i++] = complexRoot[j].re;
    }

    /* reverse above translation by adding distance to all 'k' values. */
    /* for (j = 0; j < i; ++j)
       realRoot[j] -= VDOT(newShotPoint, newShotDir);
    */

    /* Here, 'i' is number of points found */
    switch (i) {
    case 0:
        return 0;		/* No hit */

    default:
        bu_log("rt_superell_shot():  reduced 4 to %d roots\n", i);
        bn_pr_roots(stp->st_name, complexRoot, 4);
        return 0;		/* No hit */

    case 2:
    {
        /* Sort most distant to least distant. */
        fastf_t u;
        if ((u=realRoot[0]) < realRoot[1]) {
            /* bubble larger towards [0] */
            realRoot[0] = realRoot[1];
            realRoot[1] = u;
        }
    }
    break;
    case 4:
    {
        short n;
        short lim;

        /* Inline rt_pt_sort().  Sorts realRoot[] into descending order. */
        for (lim = i-1; lim > 0; lim--) {
            for (n = 0; n < lim; n++) {
                fastf_t u;
                if ((u=realRoot[n]) < realRoot[n+1]) {
                    /* bubble larger towards [0] */
                    realRoot[n] = realRoot[n+1];
                    realRoot[n+1] = u;
                }
            }
        }
    }
    break;
    }

    if (counter > 0) {
        bu_log("rt_superell_shot():  realroot in %f out %f\n", realRoot[1], realRoot[0]);
        counter--;
    }


    /* Now, t[0] > t[npts-1] */
    /* realRoot[1] is entry point, and realRoot[0] is farthest exit point */
    RT_GET_SEG(segp, ap->a_resource);
    segp->seg_stp = stp;
    segp->seg_in.hit_dist = realRoot[1];
    segp->seg_out.hit_dist = realRoot[0];
    /* segp->seg_in.hit_surfno = segp->seg_out.hit_surfno = 0; */
    /* Set aside vector for rt_superell_norm() later */
    /* VJOIN1(segp->seg_in.hit_vpriv, newShotPoint, realRoot[1], newShotDir); */
    /* VJOIN1(segp->seg_out.hit_vpriv, newShotPoint, realRoot[0], newShotDir); */
    BU_LIST_INSERT(&(seghead->l), &(segp->l));

    if (i == 2) {
        return 2;			/* HIT */
    }

    /* 4 points */
    /* realRoot[3] is entry point, and realRoot[2] is exit point */
    RT_GET_SEG(segp, ap->a_resource);
    segp->seg_stp = stp;
    segp->seg_in.hit_dist = realRoot[3]*superell->superell_e;
    segp->seg_out.hit_dist = realRoot[2]*superell->superell_e;
    segp->seg_in.hit_surfno = segp->seg_out.hit_surfno = 1;
    VJOIN1(segp->seg_in.hit_vpriv, newShotPoint, realRoot[3], newShotDir);
    VJOIN1(segp->seg_out.hit_vpriv, newShotPoint, realRoot[2], newShotDir);
    BU_LIST_INSERT(&(seghead->l), &(segp->l));
    return 4;			/* HIT */
    /* XXX END CUT */

}
コード例 #12
0
ファイル: bn_tcl.c プロジェクト: cciechad/brlcad
static void
bn_mat4x3vec(fastf_t *o, mat_t m, vect_t i)
{
    MAT4X3VEC(o, m, i);
}
コード例 #13
0
ファイル: revolve.c プロジェクト: kanzure/brlcad
/**
 * Apply a transformation matrix to the specified 'ip' input revolve
 * object, storing the results in the specified 'op' out pointer or
 * creating a copy if NULL.
 */
int
rt_revolve_xform(
    struct rt_db_internal *op,
    const mat_t mat,
    struct rt_db_internal *ip,
    int release,
    struct db_i *dbip,
    struct resource *resp)
{
    struct rt_revolve_internal *rip, *rop;
    point_t tmp_vec;

    if (dbip) RT_CK_DBI(dbip);
    RT_CK_DB_INTERNAL(ip);
    RT_CK_RESOURCE(resp);
    rip = (struct rt_revolve_internal *)ip->idb_ptr;
    RT_REVOLVE_CK_MAGIC(rip);

    if (bu_debug&BU_DEBUG_MEM_CHECK) {
	bu_log("Barrier check at start of revolve_xform():\n");
	bu_mem_barriercheck();
    }

    if (op != ip) {
	RT_DB_INTERNAL_INIT(op);
	BU_ALLOC(rop, struct rt_revolve_internal);
	rop->magic = RT_REVOLVE_INTERNAL_MAGIC;
	bu_vls_init(&rop->sketch_name);
	bu_vls_vlscat(&rop->sketch_name, &rip->sketch_name);
	op->idb_ptr = (void *)rop;
	op->idb_meth = &OBJ[ID_REVOLVE];
	op->idb_major_type = DB5_MAJORTYPE_BRLCAD;
	op->idb_type = ID_REVOLVE;
	if (ip->idb_avs.magic == BU_AVS_MAGIC) {
	    bu_avs_init(&op->idb_avs, ip->idb_avs.count, "avs");
	    bu_avs_merge(&op->idb_avs, &ip->idb_avs);
	}
    } else {
	rop = (struct rt_revolve_internal *)ip->idb_ptr;
    }
    MAT4X3PNT(tmp_vec, mat, rip->v3d);
    VMOVE(rop->v3d, tmp_vec);
    MAT4X3VEC(tmp_vec, mat, rip->axis3d);
    VMOVE(rop->axis3d, tmp_vec);
    V2MOVE(rop->v2d, rip->v2d);
    V2MOVE(rop->axis2d, rip->axis2d);

    if (release && ip != op) {
	rop->skt = rip->skt;
	rip->skt = (struct rt_sketch_internal *)NULL;
	rt_db_free_internal(ip);
    } else if (rip->skt) {
	rop->skt = rt_copy_sketch(rip->skt);
    } else {
	rop->skt = (struct rt_sketch_internal *)NULL;
    }

    if (bu_debug&BU_DEBUG_MEM_CHECK) {
	bu_log("Barrier check at end of revolve_xform():\n");
	bu_mem_barriercheck();
    }

    return 0;
}
コード例 #14
0
ファイル: poly.c プロジェクト: cogitokat/brlcad
/**
 * R T _ P G _ I M P O R T
 *
 * Read all the polygons in as a complex dynamic structure.
 * The caller is responsible for freeing the dynamic memory.
 * (vid rt_pg_ifree).
 */
int
rt_pg_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
{
    struct rt_pg_internal *pgp;
    union record *rp;
    size_t i;
    size_t rno;		/* current record number */
    size_t p;		/* current polygon index */

    if (dbip) RT_CK_DBI(dbip);

    BU_CK_EXTERNAL(ep);
    rp = (union record *)ep->ext_buf;
    if (rp->u_id != ID_P_HEAD) {
	bu_log("rt_pg_import4: defective header record\n");
	return -1;
    }

    RT_CK_DB_INTERNAL(ip);
    ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
    ip->idb_type = ID_POLY;
    ip->idb_meth = &rt_functab[ID_POLY];
    BU_ALLOC(ip->idb_ptr, struct rt_pg_internal);

    pgp = (struct rt_pg_internal *)ip->idb_ptr;
    pgp->magic = RT_PG_INTERNAL_MAGIC;

    pgp->npoly = (ep->ext_nbytes - sizeof(union record)) /
	sizeof(union record);
    if (pgp->npoly <= 0) {
	bu_log("rt_pg_import4: polysolid with no polygons!\n");
	return -1;
    }
    if (pgp->npoly)
	pgp->poly = (struct rt_pg_face_internal *)bu_malloc(
	    pgp->npoly * sizeof(struct rt_pg_face_internal), "rt_pg_face_internal");
    pgp->max_npts = 0;

    if (mat == NULL) mat = bn_mat_identity;
    for (p=0; p < pgp->npoly; p++) {
	struct rt_pg_face_internal *pp;

	pp = &pgp->poly[p];
	rno = p+1;
	if (rp[rno].q.q_id != ID_P_DATA) {
	    bu_log("rt_pg_import4: defective data record\n");
	    return -1;
	}
	pp->npts = rp[rno].q.q_count;
	pp->verts = (fastf_t *)bu_malloc(pp->npts * 3 * sizeof(fastf_t), "pg verts[]");
	pp->norms = (fastf_t *)bu_malloc(pp->npts * 3 * sizeof(fastf_t), "pg norms[]");
	for (i=0; i < pp->npts; i++) {
	    point_t pnt;
	    vect_t vec;

	    if (dbip->dbi_version < 0) {
		flip_fastf_float(pnt, rp[rno].q.q_verts[i], 1, 1);
		flip_fastf_float(vec, rp[rno].q.q_norms[i], 1, 1);
	    } else {
		VMOVE(pnt, rp[rno].q.q_verts[i]);
		VMOVE(vec, rp[rno].q.q_norms[i]);
	    }

	    /* Note:  side effect of importing dbfloat_t */
	    MAT4X3PNT(&pp->verts[i*3], mat, pnt);
	    MAT4X3VEC(&pp->norms[i*3], mat, vec);
	}
	if (pp->npts > pgp->max_npts) pgp->max_npts = pp->npts;
    }
    if (pgp->max_npts < 3) {
	bu_log("rt_pg_import4: polysolid with all polygons of less than %zu vertices!\n", pgp->max_npts);
	/* XXX free storage */
	return -1;
    }
    return 0;
}
コード例 #15
0
ファイル: hideline.c プロジェクト: cciechad/brlcad
/*
 *			F _ H I D E L I N E
 */
int
f_hideline(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
{
    FILE 	*plotfp;
    char 	visible;
    int 	i, numobjs;
    char 	*objname[MAXOBJECTS], title[1];
    fastf_t 	len, u, step;
    float 	ratio;
    vect_t	last_move;
    struct rt_i	*rtip;
    struct resource resource;
    struct application a;
    vect_t temp;
    vect_t last, dir;
    register struct bn_vlist	*vp;

    CHECK_DBI_NULL;

    if (argc < 2 || 4 < argc) {
	struct bu_vls vls;

	bu_vls_init(&vls);
	bu_vls_printf(&vls, "help H");
	Tcl_Eval(interp, bu_vls_addr(&vls));
	bu_vls_free(&vls);
	return TCL_ERROR;
    }

    if ((plotfp = fopen(argv[1], "w")) == NULL) {
	Tcl_AppendResult(interp, "f_hideline: unable to open \"", argv[1],
			 "\" for writing.\n", (char *)NULL);
	return TCL_ERROR;
    }
    pl_space(plotfp, (int)GED_MIN, (int)GED_MIN, (int)GED_MAX, (int)GED_MAX);

    /*  Build list of objects being viewed */
    numobjs = 0;
    FOR_ALL_SOLIDS(sp) {
	for (i = 0; i < numobjs; i++)  {
	    if ( objname[i] == FIRST_SOLID(sp)->d_namep )
		break;
	}
	if (i == numobjs)
	    objname[numobjs++] = FIRST_SOLID(sp)->d_namep;
    }

    Tcl_AppendResult(interp, "Generating hidden-line drawing of the following regions:\n",
		     (char *)NULL);
    for (i = 0; i < numobjs; i++)
	Tcl_AppendResult(interp, "\t", objname[i], "\n", (char *)NULL);

    /* Initialization for librt */
    if ((rtip = rt_dirbuild(dbip->dbi_filename, title, 0)) == RTI_NULL) {
	Tcl_AppendResult(interp, "f_hideline: unable to open model file \"",
			 dbip->dbi_filename, "\"\n", (char *)NULL);
	return TCL_ERROR;
    }
    a.a_hit = hit_headon;
    a.a_miss = hit_tangent;
    a.a_overlap = hit_overlap;
    a.a_rt_i = rtip;
    a.a_resource = &resource;
    a.a_level = 0;
    a.a_onehit = 1;
    a.a_diverge = 0;
    a.a_rbeam = 0;

    if (argc > 2) {
	sscanf(argv[2], "%f", &step);
	step = view_state->vs_Viewscale/step;
	sscanf(argv[3], "%f", &epsilon);
	epsilon *= view_state->vs_Viewscale/100;
    } else {
	step = view_state->vs_Viewscale/256;
	epsilon = 0.1*view_state->vs_Viewscale;
    }

    for (i = 0; i < numobjs; i++)
	if (rt_gettree(rtip, objname[i]) == -1)
	    Tcl_AppendResult(interp, "f_hideline: rt_gettree failed on \"",
			     objname[i], "\"\n", (char *)NULL);

    /* Crawl along the vectors raytracing as we go */
    VSET(temp, 0.0, 0.0, -1.0);				/* looking at model */
    MAT4X3VEC(a.a_ray.r_dir, view_state->vs_view2model, temp);
    VUNITIZE(a.a_ray.r_dir);

    FOR_ALL_SOLIDS(sp) {

	ratio = sp->s_size / VIEWSIZE;		/* ignore if small or big */
	if (ratio >= dmp->dmr_bound || ratio < 0.001)
	    continue;

	Tcl_AppendResult(interp, "Primitive\n", (char *)NULL);
	for ( BU_LIST_FOR( vp, bn_vlist, &(sp->s_vlist) ) )  {
	    register int	i;
	    register int	nused = vp->nused;
	    register int	*cmd = vp->cmd;
	    register point_t *pt = vp->pt;
	    for ( i = 0; i < nused; i++, cmd++, pt++ )  {
		Tcl_AppendResult(interp, "\tVector\n", (char *)NULL);
		switch ( *cmd )  {
		    case BN_VLIST_POLY_START:
		    case BN_VLIST_POLY_VERTNORM:
			break;
		    case BN_VLIST_POLY_MOVE:
		    case BN_VLIST_LINE_MOVE:
			/* move */
			VMOVE(last, *pt);
			MOVE(last);
			break;
		    case BN_VLIST_POLY_DRAW:
		    case BN_VLIST_POLY_END:
		    case BN_VLIST_LINE_DRAW:
			/* setup direction && length */
			VSUB2(dir, *pt, last);
			len = MAGNITUDE(dir);
			VUNITIZE(dir);
			visible = FALSE;
			{
			    struct bu_vls tmp_vls;

			    bu_vls_init(&tmp_vls);
			    bu_vls_printf(&tmp_vls, "\t\tDraw 0 -> %g, step %g\n", len, step);
			    Tcl_AppendResult(interp, bu_vls_addr(&tmp_vls), (char *)NULL);
			    bu_vls_free(&tmp_vls);
			}
			for (u = 0; u <= len; u += step) {
			    VJOIN1(aim_point, last, u, dir);
			    MAT4X3PNT(temp, view_state->vs_model2view, aim_point);
			    temp[Z] = 100;			/* parallel project */
			    MAT4X3PNT(a.a_ray.r_pt, view_state->vs_view2model, temp);
			    if (rt_shootray(&a)) {
				if (!visible) {
				    visible = TRUE;
				    MOVE(aim_point);
				}
			    } else {
				if (visible) {
				    visible = FALSE;
				    DRAW(aim_point);
				}
			    }
			}
			if (visible)
			    DRAW(aim_point);
			VMOVE(last, *pt); /* new last vertex */
		}
	    }
	}
    }
    fclose(plotfp);
    return TCL_OK;
}
コード例 #16
0
/**
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_bot_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_bot_internal *bot;

    mat_t mirmat;
    mat_t rmat;
    mat_t temp;
    vect_t nvec;
    vect_t xvec;
    vect_t mirror_dir;
    point_t mirror_pt;
    fastf_t ang;

    size_t i;

    static point_t origin = {0.0, 0.0, 0.0};

    RT_CK_DB_INTERNAL(ip);

    bot = (struct rt_bot_internal *)ip->idb_ptr;
    RT_BOT_CK_MAGIC(bot);

    MAT_IDN(mirmat);

    VMOVE(mirror_dir, plane);
    VSCALE(mirror_pt, plane, plane[W]);

    /* Build mirror transform matrix, for those who need it. */
    /* First, perform a mirror down the X axis */
    mirmat[0] = -1.0;

    /* Create the rotation matrix */
    VSET(xvec, 1, 0, 0);
    VCROSS(nvec, xvec, mirror_dir);
    VUNITIZE(nvec);
    ang = -acos(VDOT(xvec, mirror_dir));
    bn_mat_arb_rot(rmat, origin, nvec, ang*2.0);

    /* Add the rotation to mirmat */
    MAT_COPY(temp, mirmat);
    bn_mat_mul(mirmat, temp, rmat);

    /* Add the translation to mirmat */
    mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X];
    mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y];
    mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z];

    /* mirror each vertex */
    for (i=0; i<bot->num_vertices; i++) {
	point_t pt;

	VMOVE(pt, &bot->vertices[i*3]);
	MAT4X3PNT(&bot->vertices[i*3], mirmat, pt);
    }

    /* Reverse each faces' order */
    for (i=0; i<bot->num_faces; i++) {
	int save_face = bot->faces[i*3];

	bot->faces[i*3] = bot->faces[i*3 + Z];
	bot->faces[i*3 + Z] = save_face;
    }

    /* fix normals */
    for (i=0; i<bot->num_normals; i++) {
	vectp_t np = &bot->normals[i*3];
	vect_t n1;
	vect_t n2;
	mat_t mat;

	VMOVE(n1, np);
	VCROSS(n2, mirror_dir, n1);
	VUNITIZE(n2);
	ang = M_PI_2 - acos(VDOT(n1, mirror_dir));
	bn_mat_arb_rot(mat, origin, n2, ang*2);
	MAT4X3VEC(np, mat, n1);
    }

    return 0;
}
コード例 #17
0
ファイル: rec.c プロジェクト: cogitokat/brlcad
/**
 * R E C _ U V
 *
 * For a hit on the surface of an REC, return the (u, v) coordinates
 * of the hit point, 0 <= u, v <= 1.
 *
 * u is the rotation around the cylinder, and
 * v is the displacement along H.
 */
void
rt_rec_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
{
    struct rec_specific *rec =
	(struct rec_specific *)stp->st_specific;

    vect_t work;
    vect_t pprime;
    fastf_t len;
    fastf_t ratio;

    if (ap) RT_CK_APPLICATION(ap);

    /* hit_point is on surface;  project back to unit cylinder,
     * creating a vector from vertex to hit point.
     */
    VSUB2(work, hitp->hit_point, rec->rec_V);
    MAT4X3VEC(pprime, rec->rec_SoR, work);

    switch (hitp->hit_surfno) {
	case REC_NORM_BODY:
	    /* Skin.  x, y coordinates define rotation.  radius = 1 */
	    ratio = pprime[Y];
	    if (ratio > 1.0)
		ratio = 1.0;
	    if (ratio < -1.0)
		ratio = -1.0;
	    uvp->uv_u = acos(ratio) * bn_inv2pi;
	    uvp->uv_v = pprime[Z];		/* height */
	    break;
	case REC_NORM_TOP:
	    /* top plate */
	    len = sqrt(pprime[X]*pprime[X]+pprime[Y]*pprime[Y]);
	    ratio = pprime[Y]/len;
	    if (ratio > 1.0)
		ratio = 1.0;
	    if (ratio < -1.0)
		ratio = -1.0;
	    uvp->uv_u = acos(ratio) * bn_inv2pi;
	    uvp->uv_v = len;		/* rim v = 1 */
	    break;
	case REC_NORM_BOT:
	    /* bottom plate */
	    len = sqrt(pprime[X]*pprime[X]+pprime[Y]*pprime[Y]);
	    ratio = pprime[Y]/len;
	    if (ratio > 1.0)
		ratio = 1.0;
	    if (ratio < -1.0)
		ratio = -1.0;
	    uvp->uv_u = acos(ratio) * bn_inv2pi;
	    uvp->uv_v = 1 - len;	/* rim v = 0 */
	    break;
    }
    /* Handle other half of acos() domain */
    if (pprime[X] < 0)
	uvp->uv_u = 1.0 - uvp->uv_u;

    if (uvp->uv_u < 0) uvp->uv_u = 0;
    else if (uvp->uv_u > 1) uvp->uv_u = 1;
    if (uvp->uv_v < 0) uvp->uv_v = 0;
    else if (uvp->uv_v > 1) uvp->uv_v = 1;

    /* XXX uv_du should be relative to rotation, uv_dv relative to height */
    uvp->uv_du = uvp->uv_dv = 0;
}
コード例 #18
0
ファイル: rec.c プロジェクト: cogitokat/brlcad
/**
 * R E C _ V S H O T
 *
 * This is the Becker vector version
 */
void
rt_rec_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
    /* An array of solid pointers */
    /* An array of ray pointers */
    /* array of segs (results returned) */
    /* Number of ray/object pairs */

{
    int i;
    struct rec_specific *rec;
    vect_t dprime;		/* D' */
    vect_t pprime;		/* P' */
    fastf_t k1, k2;		/* distance constants of solution */
    vect_t xlated;		/* translated vector */
    struct hit hits[3];	/* 4 potential hit points */
    struct hit *hitp;	/* pointer to hit point */
    fastf_t b;		/* coeff of polynomial */
    fastf_t root;		/* root of radical */
    fastf_t dx2dy2;

    if (ap) RT_CK_APPLICATION(ap);

    /* for each ray/right_elliptical_cylinder pair */
    for (i = 0; i < n; i++) {
	if (stp[i] == 0) continue; /* stp[i] == 0 signals skip ray */

	rec = (struct rec_specific *)stp[i]->st_specific;
	hitp = &hits[0];

	/* out, Mat, vect */
	MAT4X3VEC(dprime, rec->rec_SoR, rp[i]->r_dir);
	VSUB2(xlated, rp[i]->r_pt, rec->rec_V);
	MAT4X3VEC(pprime, rec->rec_SoR, xlated);

	if (ZERO(dprime[X]) && ZERO(dprime[Y]))
	    goto check_plates;

	/* Find roots of eqn, using formula for quadratic w/ a=1 */
	b = 2 * (dprime[X]*pprime[X] + dprime[Y]*pprime[Y]) *
	    (dx2dy2 = 1 / (dprime[X]*dprime[X] + dprime[Y]*dprime[Y]));
	if ((root = b*b - 4 * dx2dy2 *
	     (pprime[X]*pprime[X] + pprime[Y]*pprime[Y] - 1)) <= 0)
	    goto check_plates;

	root = sqrt(root);
	k1 = (root-b) * 0.5;
	k2 = (root+b) * (-0.5);

	/*
	 * k1 and k2 are potential solutions to intersection with side.
	 * See if they fall in range.
	 */
	VJOIN1(hitp->hit_vpriv, pprime, k1, dprime);	/* hit' */
	if (hitp->hit_vpriv[Z] >= 0.0 && hitp->hit_vpriv[Z] <= 1.0) {
	    hitp->hit_dist = k1;
	    hitp->hit_surfno = REC_NORM_BODY;	/* compute N */
	    hitp++;
	}

	VJOIN1(hitp->hit_vpriv, pprime, k2, dprime);		/* hit' */
	if (hitp->hit_vpriv[Z] >= 0.0 && hitp->hit_vpriv[Z] <= 1.0) {
	    hitp->hit_dist = k2;
	    hitp->hit_surfno = REC_NORM_BODY;	/* compute N */
	    hitp++;
	}

	/*
	 * Check for hitting the end plates.
	 */
    check_plates:
	if (hitp < &hits[2]  &&  !ZERO(dprime[Z])) {
	    /* 0 or 1 hits so far, this is worthwhile */
	    k1 = -pprime[Z] / dprime[Z];	/* bottom plate */
	    k2 = (1.0 - pprime[Z]) / dprime[Z];	/* top plate */

	    VJOIN1(hitp->hit_vpriv, pprime, k1, dprime);/* hit' */
	    if (hitp->hit_vpriv[X] * hitp->hit_vpriv[X] +
		hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y] <= 1.0) {
		hitp->hit_dist = k1;
		hitp->hit_surfno = REC_NORM_BOT;	/* -H */
		hitp++;
	    }

	    VJOIN1(hitp->hit_vpriv, pprime, k2, dprime);/* hit' */
	    if (hitp->hit_vpriv[X] * hitp->hit_vpriv[X] +
		hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y] <= 1.0) {
		hitp->hit_dist = k2;
		hitp->hit_surfno = REC_NORM_TOP;	/* +H */
		hitp++;
	    }
	}

	if (hitp != &hits[2]) {
	    RT_REC_SEG_MISS(segp[i]);		/* MISS */
	} else {
	    segp[i].seg_stp = stp[i];

	    if (hits[0].hit_dist < hits[1].hit_dist) {
		/* entry is [0], exit is [1] */
		VMOVE(segp[i].seg_in.hit_vpriv, hits[0].hit_vpriv);
		segp[i].seg_in.hit_dist = hits[0].hit_dist;
		segp[i].seg_in.hit_surfno = hits[0].hit_surfno;
		VMOVE(segp[i].seg_out.hit_vpriv, hits[1].hit_vpriv);
		segp[i].seg_out.hit_dist = hits[1].hit_dist;
		segp[i].seg_out.hit_surfno = hits[1].hit_surfno;
	    } else {
		/* entry is [1], exit is [0] */
		VMOVE(segp[i].seg_in.hit_vpriv, hits[1].hit_vpriv);
		segp[i].seg_in.hit_dist = hits[1].hit_dist;
		segp[i].seg_in.hit_surfno = hits[1].hit_surfno;
		VMOVE(segp[i].seg_out.hit_vpriv, hits[0].hit_vpriv);
		segp[i].seg_out.hit_dist = hits[0].hit_dist;
		segp[i].seg_out.hit_surfno = hits[0].hit_surfno;
	    }
	}
    }
}
コード例 #19
0
ファイル: rec.c プロジェクト: cogitokat/brlcad
/**
 * R E C _ S H O T
 *
 * Intersect a ray with a right elliptical cylinder,
 * where all constant terms have
 * been precomputed by rt_rec_prep().  If an intersection occurs,
 * a struct seg will be acquired and filled in.
 *
 * Returns -
 * 0 MISS
 * >0 HIT
 */
int
rt_rec_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
{
    struct rec_specific *rec =
	(struct rec_specific *)stp->st_specific;
    vect_t dprime;		/* D' */
    vect_t pprime;		/* P' */
    fastf_t k1, k2;		/* distance constants of solution */
    vect_t xlated;		/* translated vector */
    struct hit hits[4];	/* 4 potential hit points */
    struct hit *hitp;	/* pointer to hit point */
    int nhits = 0;	/* Number of hit points */

    memset(hits, 0, 4 * sizeof(struct hit));

    hitp = &hits[0];

    /* out, Mat, vect */
    MAT4X3VEC(dprime, rec->rec_SoR, rp->r_dir);
    VSUB2(xlated, rp->r_pt, rec->rec_V);
    MAT4X3VEC(pprime, rec->rec_SoR, xlated);

    if (ZERO(dprime[X]) && ZERO(dprime[Y]))
	goto check_plates;

    /* Find roots of the equation, using formula for quadratic w/ a=1 */
    {
	fastf_t b;		/* coeff of polynomial */
	fastf_t root;		/* root of radical */
	fastf_t dx2dy2;

	b = 2 * (dprime[X]*pprime[X] + dprime[Y]*pprime[Y]) *
	    (dx2dy2 = 1 / (dprime[X]*dprime[X] + dprime[Y]*dprime[Y]));
	if ((root = b*b - 4 * dx2dy2 *
	     (pprime[X]*pprime[X] + pprime[Y]*pprime[Y] - 1)) <= 0)
	    goto check_plates;
	root = sqrt(root);

	k1 = (root-b) * 0.5;
	k2 = (root+b) * (-0.5);
    }

    /*
     * k1 and k2 are potential solutions to intersection with side.
     * See if they fall in range.
     */
    VJOIN1(hitp->hit_vpriv, pprime, k1, dprime);		/* hit' */
    if (hitp->hit_vpriv[Z] >= 0.0 && hitp->hit_vpriv[Z] <= 1.0) {
	hitp->hit_magic = RT_HIT_MAGIC;
	hitp->hit_dist = k1;
	hitp->hit_surfno = REC_NORM_BODY;	/* compute N */
	hitp++; nhits++;
    }

    VJOIN1(hitp->hit_vpriv, pprime, k2, dprime);		/* hit' */
    if (hitp->hit_vpriv[Z] >= 0.0 && hitp->hit_vpriv[Z] <= 1.0) {
	hitp->hit_magic = RT_HIT_MAGIC;
	hitp->hit_dist = k2;
	hitp->hit_surfno = REC_NORM_BODY;	/* compute N */
	hitp++; nhits++;
    }

    /*
     * Check for hitting the end plates.
     */
 check_plates:
    if (nhits < 2  &&  !ZERO(dprime[Z])) {
	/* 0 or 1 hits so far, this is worthwhile */
	k1 = -pprime[Z] / dprime[Z];		/* bottom plate */
	k2 = (1.0 - pprime[Z]) / dprime[Z];	/* top plate */

	VJOIN1(hitp->hit_vpriv, pprime, k1, dprime);	/* hit' */
	if (hitp->hit_vpriv[X] * hitp->hit_vpriv[X] +
	    hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y] <= 1.0) {
	    hitp->hit_magic = RT_HIT_MAGIC;
	    hitp->hit_dist = k1;
	    hitp->hit_surfno = REC_NORM_BOT;	/* -H */
	    hitp++; nhits++;
	}

	VJOIN1(hitp->hit_vpriv, pprime, k2, dprime);	/* hit' */
	if (hitp->hit_vpriv[X] * hitp->hit_vpriv[X] +
	    hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y] <= 1.0) {
	    hitp->hit_magic = RT_HIT_MAGIC;
	    hitp->hit_dist = k2;
	    hitp->hit_surfno = REC_NORM_TOP;	/* +H */
	    hitp++; nhits++;
	}
    }
    if (nhits == 0) return 0;	/* MISS */
    if (nhits == 2) {
    hit:
	if (hits[0].hit_dist < hits[1].hit_dist) {
	    /* entry is [0], exit is [1] */
	    struct seg *segp;

	    RT_GET_SEG(segp, ap->a_resource);
	    segp->seg_stp = stp;
	    segp->seg_in = hits[0];		/* struct copy */
	    segp->seg_out = hits[1];	/* struct copy */
	    BU_LIST_INSERT(&(seghead->l), &(segp->l));
	} else {
	    /* entry is [1], exit is [0] */
	    struct seg *segp;

	    RT_GET_SEG(segp, ap->a_resource);
	    segp->seg_stp = stp;
	    segp->seg_in = hits[1];		/* struct copy */
	    segp->seg_out = hits[0];	/* struct copy */
	    BU_LIST_INSERT(&(seghead->l), &(segp->l));
	}
	return 2;			/* HIT */
    }
    if (nhits == 1) {
	if (hits[0].hit_surfno != REC_NORM_BODY)
	    bu_log("rt_rec_shot(%s): 1 intersection with end plate?\n", stp->st_name);
	/*
	 * Ray is tangent to body of cylinder,
	 * or a single hit on on an end plate (??)
	 * This could be considered a MISS,
	 * but to signal the condition, return 0-thickness hit.
	 */
	hits[1] = hits[0];	/* struct copy */
	nhits++;
	goto hit;
    }
    if (nhits == 3) {
	fastf_t tol_dist = ap->a_rt_i->rti_tol.dist;
	/*
	 * Check for case where two of the three hits
	 * have the same distance, e.g. hitting at the rim.
	 */
	k1 = hits[0].hit_dist - hits[1].hit_dist;
	if (NEAR_ZERO(k1, tol_dist)) {
	    if (RT_G_DEBUG&DEBUG_ARB8)bu_log("rt_rec_shot(%s): 3 hits, collapsing 0&1\n", stp->st_name);
	    hits[1] = hits[2];	/* struct copy */
	    nhits--;
	    goto hit;
	}
	k1 = hits[1].hit_dist - hits[2].hit_dist;
	if (NEAR_ZERO(k1, tol_dist)) {
	    if (RT_G_DEBUG&DEBUG_ARB8)bu_log("rt_rec_shot(%s): 3 hits, collapsing 1&2\n", stp->st_name);
	    nhits--;
	    goto hit;
	}
	k1 = hits[0].hit_dist - hits[2].hit_dist;
	if (NEAR_ZERO(k1, tol_dist)) {
	    if (RT_G_DEBUG&DEBUG_ARB8)bu_log("rt_rec_shot(%s): 3 hits, collapsing 1&2\n", stp->st_name);
	    nhits--;
	    goto hit;
	}
    }
    /* nhits >= 3 */
    bu_log("rt_rec_shot(%s): %d unique hits?!?  %g, %g, %g, %g\n",
	   stp->st_name, nhits,
	   hits[0].hit_dist,
	   hits[1].hit_dist,
	   hits[2].hit_dist,
	   hits[3].hit_dist);

    /* count just the first two, to have something */
    goto hit;
}
コード例 #20
0
ファイル: arbn_mirror.c プロジェクト: kanzure/brlcad
/**
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_arbn_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_arbn_internal *arbn;

    size_t i;
    mat_t mirmat;
    mat_t rmat;
    mat_t temp;
    vect_t nvec;
    vect_t xvec;
    vect_t mirror_dir;
    point_t mirror_pt;
    fastf_t ang;

    static point_t origin = {0.0, 0.0, 0.0};

    RT_CK_DB_INTERNAL(ip);

    arbn = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(arbn);

    MAT_IDN(mirmat);

    VMOVE(mirror_dir, plane);
    VSCALE(mirror_pt, plane, plane[W]);

    /* Build mirror transform matrix, for those who need it. */
    /* First, perform a mirror down the X axis */
    mirmat[0] = -1.0;

    /* Create the rotation matrix */
    VSET(xvec, 1, 0, 0);
    VCROSS(nvec, xvec, mirror_dir);
    VUNITIZE(nvec);
    ang = -acos(VDOT(xvec, mirror_dir));
    bn_mat_arb_rot(rmat, origin, nvec, ang*2.0);

    /* Add the rotation to mirmat */
    MAT_COPY(temp, mirmat);
    bn_mat_mul(mirmat, temp, rmat);

    /* Add the translation to mirmat */
    mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X];
    mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y];
    mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z];

    for (i=0; i<arbn->neqn; i++) {
	point_t orig_pt;
	point_t pt;
	vect_t norm;
	fastf_t factor;

	/* unitize the plane equation first */
	factor = 1.0 / MAGNITUDE(arbn->eqn[i]);
	VSCALE(arbn->eqn[i], arbn->eqn[i], factor);
	arbn->eqn[i][W] = arbn->eqn[i][W] * factor;

	/* Pick a point on the original halfspace */
	VSCALE(orig_pt, arbn->eqn[i], arbn->eqn[i][W]);

	/* Transform the point, and the normal */
	MAT4X3VEC(norm, mirmat, arbn->eqn[i]);
	MAT4X3PNT(pt, mirmat, orig_pt);

	/* Measure new distance from origin to new point */
	VUNITIZE(norm);
	VMOVE(arbn->eqn[i], norm);
	arbn->eqn[i][W] = VDOT(pt, norm);
    }

    return 0;
}
コード例 #21
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);
}
コード例 #22
0
ファイル: arbn.c プロジェクト: kanzure/brlcad
/**
 * Convert from "network" doubles to machine specific.
 * Transform
 */
int
rt_arbn_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
{
    struct rt_arbn_internal *aip;
    size_t i;
    unsigned long neqn;
    int double_count;
    size_t byte_count;

    /* must be double for import and export */
    double *eqn;

    RT_CK_DB_INTERNAL(ip);
    BU_CK_EXTERNAL(ep);
    if (dbip) RT_CK_DBI(dbip);

    neqn = ntohl(*(uint32_t *)ep->ext_buf);
    double_count = neqn * ELEMENTS_PER_PLANE;
    byte_count = double_count * SIZEOF_NETWORK_DOUBLE;

    BU_ASSERT_LONG(ep->ext_nbytes, ==, 4+ byte_count);

    ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
    ip->idb_type = ID_ARBN;
    ip->idb_meth = &OBJ[ID_ARBN];
    BU_ALLOC(ip->idb_ptr, struct rt_arbn_internal);

    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    aip->magic = RT_ARBN_INTERNAL_MAGIC;
    aip->neqn = neqn;
    if (aip->neqn <= 0) return -1;

    eqn = (double *)bu_malloc(byte_count, "arbn plane eqn[] temp buf");
    bu_cv_ntohd((unsigned char *)eqn, (unsigned char *)ep->ext_buf + ELEMENTS_PER_PLANE, double_count);
    aip->eqn = (plane_t *)bu_malloc(double_count * sizeof(fastf_t), "arbn plane eqn[]");
    for (i = 0; i < aip->neqn; i++) {
	HMOVE(aip->eqn[i], &eqn[i*ELEMENTS_PER_PLANE]);
    }
    bu_free(eqn, "arbn plane eqn[] temp buf");

    /* Transform by the matrix, if we have one that is not the identity */
    if (mat && !bn_mat_is_identity(mat)) {
	for (i = 0; i < aip->neqn; i++) {
	    point_t orig_pt;
	    point_t pt;
	    vect_t norm;
	    fastf_t factor;

	    /* unitize the plane equation first */
	    factor = 1.0 / MAGNITUDE(aip->eqn[i]);
	    VSCALE(aip->eqn[i], aip->eqn[i], factor);
	    aip->eqn[i][W] = aip->eqn[i][W] * factor;

	    /* Pick a point on the original halfspace */
	    VSCALE(orig_pt, aip->eqn[i], aip->eqn[i][W]);

	    /* Transform the point, and the normal */
	    MAT4X3VEC(norm, mat, aip->eqn[i]);
	    MAT4X3PNT(pt, mat, orig_pt);

	    /* Measure new distance from origin to new point */
	    VUNITIZE(norm);
	    VMOVE(aip->eqn[i], norm);
	    aip->eqn[i][W] = VDOT(pt, norm);
	}
    }

    return 0;
}
コード例 #23
0
ファイル: ell_mirror.c プロジェクト: kanzure/brlcad
/**
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_ell_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_ell_internal *ell;

    mat_t mirmat;
    mat_t rmat;
    mat_t temp;
    vect_t nvec;
    vect_t xvec;
    vect_t mirror_dir;
    point_t mirror_pt;
    fastf_t ang;

    mat_t mat;
    point_t pt;
    vect_t a, b, c;
    vect_t n;

    static point_t origin = {0.0, 0.0, 0.0};

    RT_CK_DB_INTERNAL(ip);

    ell = (struct rt_ell_internal *)ip->idb_ptr;
    RT_ELL_CK_MAGIC(ell);

    MAT_IDN(mirmat);

    VMOVE(mirror_dir, plane);
    VSCALE(mirror_pt, plane, plane[W]);

    /* Build mirror transform matrix, for those who need it. */
    /* First, perform a mirror down the X axis */
    mirmat[0] = -1.0;

    /* Create the rotation matrix */
    VSET(xvec, 1, 0, 0);
    VCROSS(nvec, xvec, mirror_dir);
    VUNITIZE(nvec);
    ang = -acos(VDOT(xvec, mirror_dir));
    bn_mat_arb_rot(rmat, origin, nvec, ang*2.0);

    /* Add the rotation to mirmat */
    MAT_COPY(temp, mirmat);
    bn_mat_mul(mirmat, temp, rmat);

    /* Add the translation to mirmat */
    mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X];
    mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y];
    mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z];

    VMOVE(pt, ell->v);
    MAT4X3PNT(ell->v, mirmat, pt);

    VMOVE(a, ell->a);
    VUNITIZE(a);
    VCROSS(n, mirror_dir, ell->a);
    VUNITIZE(n);
    ang = M_PI_2 - acos(VDOT(a, mirror_dir));
    bn_mat_arb_rot(mat, origin, n, ang*2);
    VMOVE(a, ell->a);
    MAT4X3VEC(ell->a, mat, a);

    VMOVE(b, ell->b);
    VUNITIZE(b);
    VCROSS(n, mirror_dir, ell->b);
    VUNITIZE(n);
    ang = M_PI_2 - acos(VDOT(b, mirror_dir));
    bn_mat_arb_rot(mat, origin, n, ang*2);
    VMOVE(b, ell->b);
    MAT4X3VEC(ell->b, mat, b);

    VMOVE(c, ell->c);
    VUNITIZE(c);
    VCROSS(n, mirror_dir, ell->c);
    VUNITIZE(n);
    ang = M_PI_2 - acos(VDOT(c, mirror_dir));
    bn_mat_arb_rot(mat, origin, n, ang*2);
    VMOVE(c, ell->c);
    MAT4X3VEC(ell->c, mat, c);

    return 0;
}
コード例 #24
0
ファイル: clone.c プロジェクト: cogitokat/brlcad
/**
 * make a copy of a v4 solid by adding it to our book-keeping list,
 * adding it to the db directory, and writing it out to disk.
 */
static void
copy_v4_solid(struct db_i *_dbip, struct directory *proto, struct clone_state *state, int idx)
{
    struct directory *dp = (struct directory *)NULL;
    union record *rp = (union record *)NULL;
    size_t i, j;

    /* make n copies */
    for (i = 0; i < state->n_copies; i++) {
	struct bu_vls *name;

	if (i==0)
	    name = get_name(_dbip, proto, state, i);
	else {
	    dp = db_lookup(_dbip, bu_vls_addr(&obj_list.names[idx].dest[i-1]), LOOKUP_QUIET);
	    if (!dp) {
		continue;
	    }
	    name = get_name(_dbip, dp, state, i);
	}

	/* XXX: this can probably be optimized. */
	bu_vls_strcpy(&obj_list.names[idx].dest[i], bu_vls_addr(name));
	bu_vls_free(name);

	/* add the object to the directory */
	dp = db_diradd(_dbip, bu_vls_addr(&obj_list.names[idx].dest[i]), RT_DIR_PHONY_ADDR, proto->d_len, proto->d_flags, &proto->d_minor_type);
	if ((dp == RT_DIR_NULL) || (db_alloc(_dbip, dp, proto->d_len) < 0)) {
	    TCL_ALLOC_ERR;
	    return;
	}

	/* get an in-memory reference to the object being copied */
	if ((rp = db_getmrec(_dbip, proto)) == (union record *)0) {
	    TCL_READ_ERR;
	    return;
	}

	if (rp->u_id == ID_SOLID) {
	    bu_strlcpy(rp->s.s_name, dp->d_namep, NAMESIZE);

	    /* mirror */
	    if (state->miraxis != W) {
		/* XXX er, this seems rather wrong .. but it's v4 so punt */
		rp->s.s_values[state->miraxis] += 2 * (state->mirpos - rp->s.s_values[state->miraxis]);
		for (j = 3+state->miraxis; j < 24; j++)
		    rp->s.s_values[j] = -rp->s.s_values[j];
	    }
	    /* translate */
	    if (state->trans[W] > SMALL_FASTF)
		/* assumes primitive's first parameter is its position */
		VADD2(rp->s.s_values, rp->s.s_values, state->trans);
	    /* rotate */
	    if (state->rot[W] > SMALL_FASTF) {
		mat_t r;
		vect_t vec, ovec;

		if (state->rpnt[W] > SMALL_FASTF)
		    VSUB2(rp->s.s_values, rp->s.s_values, state->rpnt);
		MAT_IDN(r);
		bn_mat_angles(r, state->rot[X], state->rot[Y], state->rot[Z]);
		for (j = 0; j < 24; j+=3) {
		    VMOVE(vec, rp->s.s_values+j);
		    MAT4X3VEC(ovec, r, vec);
		    VMOVE(rp->s.s_values+j, ovec);
		}
		if (state->rpnt[W] > SMALL_FASTF)
		    VADD2(rp->s.s_values, rp->s.s_values, state->rpnt);
	    }
	} else
	    bu_log("mods not available on %s\n", proto->d_namep);

	/* write the object to disk */
	if (db_put(_dbip, dp, rp, 0, dp->d_len) < 0) {
	    bu_log("ERROR: clone internal error writing to the database\n");
	    return;
	}
    }
    if (rp)
	bu_free((char *)rp, "copy_solid record[]");

    return;
}
コード例 #25
0
/**
 * In theory, the grid can be specified by providing any two of
 * these sets of parameters:
 *
 * number of pixels (width, height)
 * viewsize (in model units, mm)
 * number of grid cells (cell_width, cell_height)
 *
 * however, for now, it is required that the view size always be
 * specified, and one or the other parameter be provided.
 */
void
grid_setup(void)
{
    vect_t temp;
    mat_t toEye;

    if (viewsize <= 0.0)
	bu_exit(EXIT_FAILURE, "viewsize <= 0");
    /* model2view takes us to eye_model location & orientation */
    MAT_IDN(toEye);
    MAT_DELTAS_VEC_NEG(toEye, eye_model);
    Viewrotscale[15] = 0.5*viewsize;	/* Viewscale */
    bn_mat_mul(model2view, Viewrotscale, toEye);
    bn_mat_inv(view2model, model2view);

    /* Determine grid cell size and number of pixels */
    if (cell_newsize) {
	if (cell_width <= 0.0) cell_width = cell_height;
	if (cell_height <= 0.0) cell_height = cell_width;
	width = (viewsize / cell_width) + 0.99;
	height = (viewsize / (cell_height*aspect)) + 0.99;
	cell_newsize = 0;
    } else {
	/* Chop -1.0..+1.0 range into parts */
	cell_width = viewsize / width;
	cell_height = viewsize / (height*aspect);
    }

    /*
     * Optional GIFT compatibility, mostly for RTG3.  Round coordinates
     * of lower left corner to fall on integer- valued coordinates, in
     * "gift_grid_rounding" units.
     */
    if (gift_grid_rounding > 0.0) {
	point_t v_ll;		/* view, lower left */
	point_t m_ll;		/* model, lower left */
	point_t hv_ll;		/* hv, lower left*/
	point_t hv_wanted;
	vect_t hv_delta;
	vect_t m_delta;
	mat_t model2hv;
	mat_t hv2model;

	/* Build model2hv matrix, including mm2inches conversion */
	MAT_COPY(model2hv, Viewrotscale);
	model2hv[15] = gift_grid_rounding;
	bn_mat_inv(hv2model, model2hv);

	VSET(v_ll, -1, -1, 0);
	MAT4X3PNT(m_ll, view2model, v_ll);
	MAT4X3PNT(hv_ll, model2hv, m_ll);
	VSET(hv_wanted, floor(hv_ll[X]), floor(hv_ll[Y]), floor(hv_ll[Z]));
	VSUB2(hv_delta, hv_ll, hv_wanted);

	MAT4X3PNT(m_delta, hv2model, hv_delta);
	VSUB2(eye_model, eye_model, m_delta);
	MAT_DELTAS_VEC_NEG(toEye, eye_model);
	bn_mat_mul(model2view, Viewrotscale, toEye);
	bn_mat_inv(view2model, model2view);
    }

    /* Create basis vectors dx and dy for emanation plane (grid) */
    VSET(temp, 1, 0, 0);
    MAT3X3VEC(dx_unit, view2model, temp);	/* rotate only */
    VSCALE(dx_model, dx_unit, cell_width);

    VSET(temp, 0, 1, 0);
    MAT3X3VEC(dy_unit, view2model, temp);	/* rotate only */
    VSCALE(dy_model, dy_unit, cell_height);

    if (stereo) {
	/* Move left 2.5 inches (63.5mm) */
	VSET(temp, -63.5*2.0/viewsize, 0, 0);
	bu_log("red eye: moving %f relative screen (left)\n", temp[X]);
	MAT4X3VEC(left_eye_delta, view2model, temp);
	VPRINT("left_eye_delta", left_eye_delta);
    }

    /* "Lower left" corner of viewing plane */
    if (rt_perspective > 0.0) {
	fastf_t zoomout;
	zoomout = 1.0 / tan(DEG2RAD * rt_perspective / 2.0);
	VSET(temp, -1, -1/aspect, -zoomout);	/* viewing plane */

	/*
	 * divergence is perspective angle divided by the number of
	 * pixels in that angle. Extra factor of 0.5 is because
	 * perspective is a full angle while divergence is the tangent
	 * (slope) of a half angle.
	 */
	APP.a_diverge = tan(DEG2RAD * rt_perspective * 0.5 / width);
	APP.a_rbeam = 0;
    } else {
	/* all rays go this direction */
	VSET(temp, 0, 0, -1);
	MAT4X3VEC(APP.a_ray.r_dir, view2model, temp);
	VUNITIZE(APP.a_ray.r_dir);

	VSET(temp, -1, -1/aspect, 0);	/* eye plane */
	APP.a_rbeam = 0.5 * viewsize / width;
	APP.a_diverge = 0;
    }
    if (ZERO(APP.a_rbeam) && ZERO(APP.a_diverge))
	bu_exit(EXIT_FAILURE, "zero-radius beam");
    MAT4X3PNT(viewbase_model, view2model, temp);

    if (jitter & JITTER_FRAME) {
	/* Move the frame in a smooth circular rotation in the plane */
	fastf_t ang;	/* radians */
	fastf_t dx, dy;

	ang = curframe * frame_delta_t * M_2PI / 10;	/* 10 sec period */
	dx = cos(ang) * 0.5;	/* +/- 1/4 pixel width in amplitude */
	dy = sin(ang) * 0.5;
	VJOIN2(viewbase_model, viewbase_model,
	       dx, dx_model,
	       dy, dy_model);
    }

    if (cell_width <= 0 || cell_width >= INFINITY ||
	cell_height <= 0 || cell_height >= INFINITY) {
	bu_log("grid_setup: cell size ERROR (%g, %g) mm\n",
	       cell_width, cell_height);
	bu_exit(EXIT_FAILURE, "cell size");
    }
    if (width <= 0 || height <= 0) {
	bu_log("grid_setup: ERROR bad image size (%zu, %zu)\n",
	       width, height);
	bu_exit(EXIT_FAILURE, "bad size");
    }
}
コード例 #26
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;
}
コード例 #27
0
/**
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_half_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_half_internal *half;

    mat_t mirmat;
    mat_t rmat;
    mat_t temp;
    vect_t nvec;
    vect_t xvec;
    vect_t mirror_dir;
    point_t mirror_pt;
    fastf_t ang;

    vect_t n1;
    vect_t n2;

    static fastf_t tol_dist_sq = 0.0005 * 0.0005;
    static point_t origin = {0.0, 0.0, 0.0};

    RT_CK_DB_INTERNAL(ip);

    half = (struct rt_half_internal *)ip->idb_ptr;
    RT_HALF_CK_MAGIC(half);

    MAT_IDN(mirmat);

    VMOVE(mirror_dir, plane);
    VSCALE(mirror_pt, plane, plane[W]);

    /* Build mirror transform matrix, for those who need it. */
    /* First, perform a mirror down the X axis */
    mirmat[0] = -1.0;

    /* Create the rotation matrix */
    VSET(xvec, 1, 0, 0);
    VCROSS(nvec, xvec, mirror_dir);
    VUNITIZE(nvec);
    ang = -acos(VDOT(xvec, mirror_dir));
    bn_mat_arb_rot(rmat, origin, nvec, ang*2.0);

    /* Add the rotation to mirmat */
    MAT_COPY(temp, mirmat);
    bn_mat_mul(mirmat, temp, rmat);

    /* Add the translation to mirmat */
    mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X];
    mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y];
    mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z];

    /* FIXME: this is not using the mirmat we just computed, not clear
     * it's even right given it's only taking the mirror direction
     * into account and not the mirror point.
     */

    VMOVE(n1, half->eqn);
    VCROSS(n2, mirror_dir, n1);
    VUNITIZE(n2);
    ang = M_PI_2 - acos(VDOT(n1, mirror_dir));
    bn_mat_arb_rot(rmat, origin, n2, ang*2);
    MAT4X3VEC(half->eqn, rmat, n1);

    if (!NEAR_EQUAL(VDOT(n1, half->eqn), 1.0, tol_dist_sq)) {
	point_t ptA;
	point_t ptB;
	point_t ptC;
	vect_t h;
	fastf_t mag;
	fastf_t cosa;

	VSCALE(ptA, n1, half->eqn[H]);
	VADD2(ptB, ptA, mirror_dir);
	VSUB2(h, ptB, ptA);
	mag = MAGNITUDE(h);
	VUNITIZE(h);

	cosa = VDOT(h, mirror_dir);

	VSCALE(ptC, half->eqn, -mag * cosa);
	VADD2(ptC, ptC, ptA);
	half->eqn[H] = VDOT(half->eqn, ptC);
    }

    return 0;
}
コード例 #28
0
/*
 *  Returns -
 *	-2	unknown keyword
 *	-1	error in processing keyword
 *	 0	OK
 */
int
multi_words( char *words[], int	nwords )
{

    if ( strcmp( words[0], "rot" ) == 0 )  {
	mat_t	mat;

	/* Expects rotations rx, ry, rz, in degrees */
	if ( nwords < 4 )  return(-1);
	MAT_IDN( mat );
	bn_mat_angles( mat,
		       atof( words[1] ),
		       atof( words[2] ),
		       atof( words[3] ) );
	out_mat( mat, stdout );
	return(0);
    }
    if ( strcmp( words[0], "xlate" ) == 0 )  {
	mat_t	mat;

	if ( nwords < 4 )  return(-1);
	/* Expects translations tx, ty, tz */
	MAT_IDN( mat );
	MAT_DELTAS( mat,
		    atof( words[1] ),
		    atof( words[2] ),
		    atof( words[3] ) );
	out_mat( mat, stdout );
	return(0);
    }
    if ( strcmp( words[0], "rot_at" ) == 0 )  {
	mat_t	mat;
	mat_t	mat1;
	mat_t	mat2;
	mat_t	mat3;

	/* JG - Expects x, y, z, rx, ry, rz               */
	/* Translation back to the origin by (-x, -y, -z)   */
	/* is done first, then the rotation, and finally  */
	/* back into the original position by (+x, +y, +z). */

	if ( nwords < 7 )  return(-1);

	MAT_IDN( mat1 );
	MAT_IDN( mat2 );
	MAT_IDN( mat3 );

	MAT_DELTAS( mat1,
		    -atof( words[1] ),
		    -atof( words[2] ),
		    -atof( words[3] ) );

	bn_mat_angles( mat2,
		       atof( words[4] ),
		       atof( words[5] ),
		       atof( words[6] ) );

	MAT_DELTAS( mat3,
		    atof( words[1] ),
		    atof( words[2] ),
		    atof( words[3] ) );

	bn_mat_mul( mat, mat2, mat1 );
	bn_mat_mul2( mat3, mat );

	out_mat( mat, stdout );
	return(0);
    }
    if ( strcmp( words[0], "orient" ) == 0 )  {
	register int i;
	mat_t	mat;
	double	args[8];

	/* Expects tx, ty, tz, rx, ry, rz, [scale]. */
	/* All rotation is done first, then translation */
	/* Note: word[0] and args[0] are the keyword */
	if ( nwords < 6+1 )  return(-1);
	for ( i=1; i<6+1; i++ )
	    args[i] = 0;
	args[7] = 1.0;	/* optional arg, default to 1 */
	for ( i=1; i<nwords; i++ )
	    args[i] = atof( words[i] );
	MAT_IDN( mat );
	bn_mat_angles( mat, args[4], args[5], args[6] );
	MAT_DELTAS( mat, args[1], args[2], args[3] );
	if ( NEAR_ZERO( args[7], VDIVIDE_TOL ) )  {
	    /* Nearly zero, signal error */
	    fprintf(stderr, "Orient scale arg is near zero ('%s')\n",
		    words[7] );
	    return(-1);
	} else {
	    mat[15] = 1 / args[7];
	}
	out_mat( mat, stdout );
	return(0);
    }
    if ( strcmp( words[0], "ae" ) == 0 )  {
	mat_t	mat;
	fastf_t	az, el;

	if ( nwords < 3 )  return(-1);
	/* Expects azimuth, elev, optional twist */
	az = atof(words[1]);
	el = atof(words[2]);
#if 0
	if ( nwords == 3 )
	    twist = 0.0;
	else
	    twist = atof(words[3]);
#endif
	MAT_IDN( mat );
	/* XXX does not take twist, for now XXX */
	bn_mat_ae( mat, az, el );
	out_mat( mat, stdout );
	return(0);
    }
    if ( strcmp( words[0], "arb_rot_pt" ) == 0 )  {
	mat_t	mat;
	point_t	pt1, pt2;
	vect_t	dir;
	fastf_t	ang;

	if ( nwords < 1+3+3+1 )  return(-1);
	/* Expects point1, point2, angle */
	VSET( pt1, atof(words[1]), atof(words[2]), atof(words[3]) );
	VSET( pt2, atof(words[4]), atof(words[5]), atof(words[6]) );
	ang = atof(words[7]) * bn_degtorad;
	VSUB2( dir, pt2, pt2 );
	VUNITIZE(dir);
	MAT_IDN( mat );
	bn_mat_arb_rot( mat, pt1, dir, ang );
	out_mat( mat, stdout );
	return(0);
    }
    if ( strcmp( words[0], "arb_rot_dir" ) == 0 )  {
	mat_t	mat;
	point_t	pt1;
	vect_t	dir;
	fastf_t	ang;

	if ( nwords < 1+3+3+1 )  return(-1);
	/* Expects point1, dir, angle */
	VSET( pt1, atof(words[1]), atof(words[2]), atof(words[3]) );
	VSET( dir, atof(words[4]), atof(words[5]), atof(words[6]) );
	ang = atof(words[7]) * bn_degtorad;
	VUNITIZE(dir);
	MAT_IDN( mat );
	bn_mat_arb_rot( mat, pt1, dir, ang );
	out_mat( mat, stdout );
	return(0);
    }
    if ( strcmp( words[0], "quat" ) == 0 )  {
	mat_t	mat;
	quat_t	quat;

	/* Usage: quat x, y, z, w */
	if ( nwords < 5 ) return -1;
	QSET( quat, atof(words[1]), atof(words[2]),
	      atof(words[3]), atof(words[4]) );

	quat_quat2mat( mat, quat );
	out_mat( mat, stdout);
	return 0;
    }
    if ( strcmp( words[0], "fromto" ) == 0 )  {
	mat_t	mat;
	point_t	cur;
	point_t	next;
	vect_t	from;
	vect_t	to;

	/* Usage: fromto +Z cur_xyz next_xyz */
	if ( nwords < 8 )  return -1;
	if ( strcmp( words[1], "+X" ) == 0 )  {
	    VSET( from, 1, 0, 0 );
	} else if ( strcmp( words[1], "-X" ) == 0 )  {
	    VSET( from, -1, 0, 0 );
	} else if ( strcmp( words[1], "+Y" ) == 0 )  {
	    VSET( from, 0, 1, 0 );
	} else if ( strcmp( words[1], "-Y" ) == 0 )  {
	    VSET( from, 0, -1, 0 );
	} else if ( strcmp( words[1], "+Z" ) == 0 )  {
	    VSET( from, 0, 0, 1 );
	} else if ( strcmp( words[1], "-Z" ) == 0 )  {
	    VSET( from, 0, 0, -1 );
	} else {
	    fprintf(stderr, "fromto '%s' is not +/-XYZ\n", words[1]);
	    return -1;
	}
	VSET( cur, atof(words[2]), atof(words[3]), atof(words[4]) );
	VSET( next, atof(words[5]), atof(words[6]), atof(words[7]) );
	VSUB2( to, next, cur );
	VUNITIZE(to);
	bn_mat_fromto( mat, from, to );
	/* Check to see if it worked. */
	{
	    vect_t	got;

	    MAT4X3VEC( got, mat, from );
	    if ( VDOT( got, to ) < 0.9 )  {
		bu_log("\ntabsub ERROR: At t=%s, bn_mat_fromto failed!\n", chanwords[0] );
		VPRINT("\tfrom", from);
		VPRINT("\tto", to);
		VPRINT("\tgot", got);
	    }
	}
	out_mat( mat, stdout );
	return 0;
    }
    return(-2);		/* Unknown keyword */
}
コード例 #29
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);
}
コード例 #30
0
void
bn_mat_fromto(
    mat_t m,
    const fastf_t *from,
    const fastf_t *to,
    const struct bn_tol *tol)
{
    vect_t test_to;
    vect_t unit_from, unit_to;
    fastf_t dot;
    point_t origin = VINIT_ZERO;

    /**
     * The method used here is from Graphics Gems, A. Glassner, ed.
     * page 531, "The Use of Coordinate Frames in Computer Graphics",
     * by Ken Turkowski, Example 6.
     */
    mat_t Q, Qt;
    mat_t R;
    mat_t A;
    mat_t temp;
    vect_t N, M;
    vect_t w_prime;		/* image of "to" ("w") in Qt */

    VMOVE(unit_from, from);
    VUNITIZE(unit_from);		/* aka "v" */
    VMOVE(unit_to, to);
    VUNITIZE(unit_to);		/* aka "w" */

    /* If from and to are the same or opposite, special handling is
     * needed, because the cross product isn't defined.  asin(0.00001)
     * = 0.0005729 degrees (1/2000 degree)
     */
    if (bn_lseg3_lseg3_parallel(origin, from, origin, to, tol)) {
	dot = VDOT(from, to);
	if (dot > SMALL_FASTF) {
	    MAT_IDN(m);
	    return;
	} else {
	    bn_vec_perp(N, unit_from);
	}
    } else {
	VCROSS(N, unit_from, unit_to);
	VUNITIZE(N);			/* should be unnecessary */
    }
    VCROSS(M, N, unit_from);
    VUNITIZE(M);			/* should be unnecessary */

    /* Almost everything here is done with pre-multiplys:  vector * mat */
    MAT_IDN(Q);
    VMOVE(&Q[0], unit_from);
    VMOVE(&Q[4], M);
    VMOVE(&Q[8], N);
    bn_mat_trn(Qt, Q);

    /* w_prime = w * Qt */
    MAT4X3VEC(w_prime, Q, unit_to);	/* post-multiply by transpose */

    MAT_IDN(R);
    VMOVE(&R[0], w_prime);
    VSET(&R[4], -w_prime[Y], w_prime[X], w_prime[Z]);
    VSET(&R[8], 0, 0, 1);		/* is unnecessary */

    bn_mat_mul(temp, R, Q);
    bn_mat_mul(A, Qt, temp);
    bn_mat_trn(m, A);		/* back to post-multiply style */

    /* Verify that it worked */
    MAT4X3VEC(test_to, m, unit_from);
    if (UNLIKELY(!bn_lseg3_lseg3_parallel(origin, unit_to, origin, test_to, tol))) {
	dot = VDOT(unit_to, test_to);
	bu_log("bn_mat_fromto() ERROR!  from (%g, %g, %g) to (%g, %g, %g) went to (%g, %g, %g), dot=%g?\n",
	       V3ARGS(from), V3ARGS(to), V3ARGS(test_to), dot);
    }
}