Пример #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
/**
 * R T _ D S P _ M I R R O R
 *
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_dsp_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_dsp_internal *dsp;

    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);

    dsp = (struct rt_dsp_internal *)ip->idb_ptr;
    RT_EBM_CK_MAGIC(dsp);

    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];

    bn_mat_mul(temp, mirmat, dsp->dsp_mtos);
    MAT_COPY(dsp->dsp_mtos, temp);

    return 0;
}
Пример #3
0
void
db_dup_full_path(struct db_full_path *newp, const struct db_full_path *oldp)
{
    unsigned int i = 0;
    RT_CK_FULL_PATH(newp);
    RT_CK_FULL_PATH(oldp);

    newp->fp_maxlen = oldp->fp_maxlen;
    newp->fp_len = oldp->fp_len;
    if (oldp->fp_len <= 0) {
	newp->fp_names = (struct directory **)0;
	newp->fp_bool = (int *)0;
	return;
    }
    newp->fp_names = (struct directory **)bu_malloc(newp->fp_maxlen * sizeof(struct directory *),
	    "db_full_path array (duplicate)");
    memcpy((char *)newp->fp_names, (char *)oldp->fp_names, newp->fp_len * sizeof(struct directory *));

    newp->fp_bool = (int *)bu_malloc(newp->fp_maxlen * sizeof(int),
	    "db_full_path bool array (duplicate)");
    memcpy((char *)newp->fp_bool, (char *)oldp->fp_bool, newp->fp_len * sizeof(int));

    newp->fp_mat = (matp_t *)bu_calloc(newp->fp_maxlen, sizeof(matp_t),
	    "db_full_path mat array (duplicate)");
    for (i = 0; i < newp->fp_len; i++) {
	if (oldp->fp_mat[i]) {
	    newp->fp_mat[i] = (matp_t)bu_calloc(1, sizeof(mat_t), "transformation matrix");
	    MAT_COPY(newp->fp_mat[i], oldp->fp_mat[i]);
	}
    }
}
Пример #4
0
/**
 * P L O T _ L O A D M A T R I X
 *
 * Load a new transformation matrix.  This will be followed by
 * many calls to plot_draw().
 */
HIDDEN int
plot_loadMatrix(struct dm *dmp, fastf_t *mat, int which_eye)
{
    Tcl_Obj *obj;

    if (!dmp)
	return TCL_ERROR;

    obj = Tcl_GetObjResult(dmp->dm_interp);
    if (Tcl_IsShared(obj))
	obj = Tcl_DuplicateObj(obj);

    if (((struct plot_vars *)dmp->dm_vars.priv_vars)->debug) {
	struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;

	Tcl_AppendStringsToObj(obj, "plot_loadMatrix()\n", (char *)NULL);

	bu_vls_printf(&tmp_vls, "which eye = %d\t", which_eye);
	bu_vls_printf(&tmp_vls, "transformation matrix = \n");
	bu_vls_printf(&tmp_vls, "%g %g %g %g\n", mat[0], mat[4], mat[8], mat[12]);
	bu_vls_printf(&tmp_vls, "%g %g %g %g\n", mat[1], mat[5], mat[9], mat[13]);
	bu_vls_printf(&tmp_vls, "%g %g %g %g\n", mat[2], mat[6], mat[10], mat[14]);
	bu_vls_printf(&tmp_vls, "%g %g %g %g\n", mat[3], mat[7], mat[11], mat[15]);

	Tcl_AppendStringsToObj(obj, bu_vls_addr(&tmp_vls), (char *)NULL);
	bu_vls_free(&tmp_vls);
    }

    MAT_COPY(plotmat, mat);
    Tcl_SetObjResult(dmp->dm_interp, obj);
    return TCL_OK;
}
Пример #5
0
static int orient_find_neighbor(int *utag, int ublk1 ,int ublk2, int mat[3][3]) 
{
   int ublk_match;
   int ibnd;
   int ibnd_match;
   int mat_temp1[3][3];
   int mat_temp2[3][3];
   BndMapping_t *ubnd;
   ubnd = umap[ublk1].bnd;
   ublk_match = -1;
   ibnd_match = -1;
   for (ibnd = 0; ibnd < umap[ublk1].nbnd; ibnd++) {
      if ((ubnd[ibnd].orientation[0] != 0) && (utag[ubnd[ibnd].iblk] == 0)) {
         ublk_match = ubnd[ibnd].iblk;
         ibnd_match = ibnd;
         if (ublk_match == ublk2) break;
      }
   }
   if (ublk_match >= 0) {
      utag[ublk_match] = 1;
      MAT_ZERO(mat_temp1);
      MAT_ZERO(mat_temp2);
      MAT_EXPAND(mat_temp1,ubnd[ibnd_match].orientation);
      MAT_X_MAT(mat_temp2,mat_temp1,mat);
      MAT_COPY(mat,mat_temp2);
   } 
   return(ublk_match);
} 
Пример #6
0
void
bn_mat_mul2(register const mat_t i, register mat_t o)
{
    mat_t temp;

    bn_mat_mul(temp, i, o);
    MAT_COPY(o, temp);
}
Пример #7
0
matp_t
bn_mat_dup(const mat_t in)
{
    mat_t *out;

    BU_ALLOC(out, mat_t);
    MAT_COPY(*out, in);

    return (matp_t)out;
}
Пример #8
0
/*
 *			V I E W _ 2 I N I T
 *
 *  View_2init is called by do_frame(), which in turn is called by
 *  main() in rt.c.  It writes the view-specific COVART header.
 *
 */
void
view_2init(struct application *ap)
{
    if ( outfp == NULL )
	bu_exit(EXIT_FAILURE, "outfp is NULL\n");

    /*
     *  Overall header, to be read by COVART format:
     *  9220 FORMAT( BZ, I5, 10A4 )
     *	number of views, title
     *  Initially, do only one view per run of RTG3.
     */
    fprintf(outfp, "%5d %s %s\n", 1, save_file, save_obj);

    /*
     *  Header for each view, to be read by COVART format:
     *  9230 FORMAT( BZ, 2( 5X, E15.8), 30X, E10.3 )
     *	azimuth, elevation, grid_spacing
     * NOTE that GIFT provides several other numbers that are not used
     * by COVART;  this should be investigated.
     * NOTE that grid_spacing is assumed to be square (by COVART),
     * and that the units have been converted from MM to IN.
     * COVART, given the appropriate code, will take, IN, M,
     * FT, MM, and CM.  However, GIFT  output is expected to be IN.
     * NOTE that variables "azimuth and elevation" are not valid
     * when the -M flag is used.
     * NOTE:  %10g was changed to %10f so that a decimal point is generated
     * even when the number is an integer.  Otherwise the client codes
     * get confused get confused and are unable to convert the number to
     * scientific notation.
     */
    fprintf(outfp,
	    "     %-15.8f     %-15.8f                              %10f\n",
	    azimuth, elevation, cell_width*MM2IN );

    /*
     *  GIFT uses an H, V coordinate system that is anchored at the
     *  model origin, but rotated according to the view.
     *  For convenience later, build a matrix that will take
     *  a point in model space (with units of mm), and convert it
     *  to a point in HV space, with units of inches.
     */
    MAT_COPY( model2hv, Viewrotscale );
    model2hv[15] = 1/MM2IN;

    line_num += 2;
}
Пример #9
0
int
mat_build(fastf_t *mat1, fastf_t *mat2, fastf_t *regismat)
{

    vect_t	adelta, bdelta;		/* deltas for mod1 and mod2 */
    vect_t	delta;			/* difference bet. mod1 and mod2 deltas */
    fastf_t	scale;

    /* At this point it is important to check that the rotation part
     * of the matices is within a certain tolerance: ie. that the
     * two images were raytraced from the same angle.  No overlays will
     * be possible if they are not at the same rotation.
     */

    /* Now record the deltas: the translation part of the matrix. */
    VSET(adelta, mat1[MDX], mat1[MDY], mat1[MDZ]);
    VSET(bdelta, mat2[MDX], mat2[MDY], mat2[MDZ]);

    /* Take the difference between the deltas. Also scale the size
     * of the model (scale).  These will be used to register two
     * pixel files later on.
     */

    VSUB2(delta, adelta, bdelta);
    scale = mat1[15]/mat2[15];

    VPRINT("delta", delta);
    fprintf(stderr, "scale: %.6f\n", scale);

    /* If the first log corresponds to a UNIX-Plot file, following
     * applies.  Since UNIX-Plot files are in model coordinates, the
     * mod2view2 ("model2pix") is also the registration matrix.  In
     * this case, pl-fb needs to learn that the UNIX-Plot file's space
     * runs from -1 -> 1 in x and y.  This can be done by adding an
     * alternate space command in that program. Therefore the below
     * applies.
     * What if the first log corresponds to a hi-res pixel file to be
     * registered with a lo-res pixel file?  Then the above calculated
     * deltas are used.   This will be implemented later.
     */

    MAT_COPY( regismat, mat2);
    bn_mat_print("regismat", regismat);
    return(1);				/* OK */
}
Пример #10
0
int
ged_perspective(struct ged *gedp, int argc, const char *argv[])
{
    /* intentionally double for scan */
    double perspective;
    static const char *usage = "[angle]";

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_VIEW(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* get the perspective angle */
    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "%g", gedp->ged_gvp->gv_perspective);
	return GED_OK;
    }

    /* set perspective angle */
    if (argc == 2) {
	if (sscanf(argv[1], "%lf", &perspective) != 1) {
	    bu_vls_printf(gedp->ged_result_str, "bad perspective angle - %s", argv[1]);
	    return GED_ERROR;
	}

	gedp->ged_gvp->gv_perspective = perspective;

	if (SMALL_FASTF < gedp->ged_gvp->gv_perspective) {
	    ged_persp_mat(gedp->ged_gvp->gv_pmat, gedp->ged_gvp->gv_perspective,
			  (fastf_t)1.0f, (fastf_t)0.01f, (fastf_t)1.0e10f, (fastf_t)1.0f);
	} else {
	    MAT_COPY(gedp->ged_gvp->gv_pmat, bn_mat_identity);
	}

	ged_view_update(gedp->ged_gvp);

	return GED_OK;
    }

    bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
    return GED_ERROR;
}
Пример #11
0
int
mk_dsp(struct rt_wdb *fp, const char *name, const char *file, size_t xdim, size_t ydim, const matp_t mat)
    /* name of file containing elevation data */
    /* X dimension of file (w cells) */
    /* Y dimension of file (n cells) */
    /* convert solid coords to model space */
{
    struct rt_dsp_internal *dsp;

    BU_ALLOC(dsp, struct rt_dsp_internal);
    dsp->magic = RT_DSP_INTERNAL_MAGIC;

    bu_vls_init(&dsp->dsp_name);
    bu_vls_strcat(&dsp->dsp_name, file);

    dsp->dsp_xcnt = xdim;
    dsp->dsp_ycnt = ydim;
    MAT_COPY(dsp->dsp_stom, mat);

    return wdb_export(fp, name, (void *)dsp, ID_DSP, mk_conv2mm);
}
Пример #12
0
void
db_append_full_path(struct db_full_path *dest, const struct db_full_path *src)
{
    unsigned int i = 0;
    RT_CK_FULL_PATH(dest);
    RT_CK_FULL_PATH(src);

    db_extend_full_path(dest, src->fp_len);
    memcpy((char *)&dest->fp_names[dest->fp_len],
	   (char *)&src->fp_names[0],
	   src->fp_len * sizeof(struct directory *));
    memcpy((char *)&dest->fp_bool[dest->fp_len],
	   (char *)&src->fp_bool[0],
	   src->fp_len * sizeof(int));
    for (i = 0; i < src->fp_len; i++) {
	if (src->fp_mat[i]) {
	    dest->fp_mat[dest->fp_len + i] = (matp_t)bu_calloc(1, sizeof(mat_t), "transformation matrix");
	    MAT_COPY(dest->fp_mat[dest->fp_len + i], src->fp_mat[i]);
	}
    }
    dest->fp_len += src->fp_len;
}
Пример #13
0
void
db_dup_path_tail(struct db_full_path *newp, const struct db_full_path *oldp, off_t start)
{
    unsigned int i = 0;
    RT_CK_FULL_PATH(newp);
    RT_CK_FULL_PATH(oldp);

    if (start < 0 || (size_t)start > oldp->fp_len-1)
	bu_bomb("db_dup_path_tail: start offset out of range\n");

    newp->fp_maxlen = newp->fp_len = oldp->fp_len - start;
    if (newp->fp_len <= 0) {
	newp->fp_names = (struct directory **)0;
	newp->fp_bool = (int *)0;
	newp->fp_mat = (matp_t *)0;
	return;
    }
    newp->fp_names = (struct directory **)bu_malloc(
	newp->fp_maxlen * sizeof(struct directory *),
	"db_full_path array (duplicate)");
    memcpy((char *)newp->fp_names, (char *)&oldp->fp_names[start], newp->fp_len * sizeof(struct directory *));

    newp->fp_bool = (int *)bu_malloc(
	newp->fp_maxlen * sizeof(int),
	"db_full_path bool array (duplicate)");
    memcpy((char *)newp->fp_bool, (char *)&oldp->fp_bool[start], newp->fp_len * sizeof(int));

    newp->fp_mat = (matp_t *)bu_calloc(newp->fp_maxlen, sizeof(matp_t),
	    "db_full_path mat array (duplicate)");
    for (i = start; i < newp->fp_len; i++) {
	if (oldp->fp_mat[i]) {
	    newp->fp_mat[i] = (matp_t)bu_calloc(1, sizeof(mat_t), "transformation matrix");
	    MAT_COPY(newp->fp_mat[i], oldp->fp_mat[i]);
	}
    }
}
Пример #14
0
/**
 * 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;
}
Пример #15
0
/*
 * Process a space command.
 * Behavior depends on setting of several flags.
 *
 * Implicit Returns -
 * In all cases, sets space_min and space_max.
 */
int
model_rpp(const fastf_t *min, const fastf_t *max)
{

    if (space_set) {
	bu_log("plot3rot:  additional SPACE command ignored\n");
	bu_log("got: space (%g, %g, %g) (%g, %g, %g)\n",
	       V3ARGS(min), V3ARGS(max));
	bu_log("still using: space (%g, %g, %g) (%g, %g, %g)\n",
	       V3ARGS(space_min), V3ARGS(space_max));
	return 0;
    }

    if (rpp) {
	point_t rot_center;		/* center of rotation */
	mat_t xlate;
	mat_t resize;
	mat_t t1, t2;

	VADD2SCALE(rot_center, min, max, 0.5);

	/* Create the matrix which encodes this */
	MAT_IDN(xlate);
	MAT_DELTAS_VEC_NEG(xlate, rot_center);
	MAT_IDN(resize);
	resize[15] = 1/scale;
	bn_mat_mul(t1, resize, xlate);
	bn_mat_mul(t2, rmat, t1);
	MAT_COPY(rmat, t2);
	if (verbose) {
	    bn_mat_print("rmat", rmat);
	}

	if (Mflag) {
	    /* Don't rebound, just expand size of space
	     * around center point.
	     * Has advantage of the output space() not being
	     * affected by changes in rotation,
	     * which may be significant for animation scripts.
	     */
	    vect_t diag;
	    double v;

	    VSUB2(diag, max, min);
	    v = MAGNITUDE(diag)*0.5 + 0.5;
	    VSET(space_min, -v, -v, -v);
	    VSET(space_max,  v,  v,  v);
	} else {
	    /* re-bound the space() rpp with a tighter one
	     * after rotating & scaling it.
	     */
	    bn_rotate_bbox(space_min, space_max, rmat, min, max);
	}
	space_set = 1;
    } else {
	VMOVE(space_min, min);
	VMOVE(space_max, max);
	space_set = 1;
    }

    if (forced_space) {
	/* Put forced space back */
	VMOVE(space_min, forced_space_min);
	VMOVE(space_max, forced_space_max);
	space_set = 1;
    }

    if (verbose) {
	bu_log("got: space (%g, %g, %g) (%g, %g, %g)\n",
	       V3ARGS(min), V3ARGS(max));
	bu_log("put: space (%g, %g, %g) (%g, %g, %g)\n",
	       V3ARGS(space_min), V3ARGS(space_max));
    }

    return 1;
}
Пример #16
0
/**
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_nurb_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_nurb_internal *nurb;

    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;

    int i;
    int j;

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

    RT_CK_DB_INTERNAL(ip);

    nurb = (struct rt_nurb_internal *)ip->idb_ptr;
    RT_PG_CK_MAGIC(nurb);

    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<nurb->nsrf; i++) {
	fastf_t *ptr;
	int tmp;
	int orig_size[2];
	int ncoords;
	int m;
	int l;

	/* swap knot vectors between u and v */
	ptr = nurb->srfs[i]->u.knots;
	tmp = nurb->srfs[i]->u.k_size;

	nurb->srfs[i]->u.knots = nurb->srfs[i]->v.knots;
	nurb->srfs[i]->u.k_size = nurb->srfs[i]->v.k_size;
	nurb->srfs[i]->v.knots = ptr;
	nurb->srfs[i]->v.k_size = tmp;

	/* swap order */
	tmp = nurb->srfs[i]->order[0];
	nurb->srfs[i]->order[0] = nurb->srfs[i]->order[1];
	nurb->srfs[i]->order[1] = tmp;

	/* swap mesh size */
	orig_size[0] = nurb->srfs[i]->s_size[0];
	orig_size[1] = nurb->srfs[i]->s_size[1];

	nurb->srfs[i]->s_size[0] = orig_size[1];
	nurb->srfs[i]->s_size[1] = orig_size[0];

	/* allocate memory for a new control mesh */
	ncoords = RT_NURB_EXTRACT_COORDS(nurb->srfs[i]->pt_type);
	ptr = (fastf_t *)bu_calloc(orig_size[0]*orig_size[1]*ncoords, sizeof(fastf_t), "rt_mirror: ctl mesh ptr");

	/* mirror each control point */
	for (j=0; j<orig_size[0]*orig_size[1]; j++) {
	    point_t pt;

	    VMOVE(pt, &nurb->srfs[i]->ctl_points[j*ncoords]);
	    MAT4X3PNT(&nurb->srfs[i]->ctl_points[j*ncoords], mirmat, pt);
	}

	/* copy mirrored control points into new mesh
	 * while swapping u and v */
	m = 0;
	for (j=0; j<orig_size[0]; j++) {
	    for (l=0; l<orig_size[1]; l++) {
		VMOVEN(&ptr[(l*orig_size[0]+j)*ncoords], &nurb->srfs[i]->ctl_points[m*ncoords], ncoords);
		m++;
	    }
	}

	/* free old mesh */
	bu_free((char *)nurb->srfs[i]->ctl_points, "rt_mirror: ctl points");

	/* put new mesh in place */
	nurb->srfs[i]->ctl_points = ptr;
    }

    return 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;
}
Пример #18
0
   -x# -y# -z#    Rotation about axis in degrees\n\
   -X# -Y# -Z#    Translation along axis\n\
   -s#            Scale factor\n\
   -a# -e#        Azimuth/Elevation from front view\n\
		  (usually first, in this order, implies -M)\n\
   -g             MGED front view to display coordinates (usually last)\n\
   -M             Autoscale space command like RT model RPP\n\
   -m#            Takes a 4X4 matrix as an argument\n\
   -v             Verbose\n\
   -S#            Space: takes a quoted string of six floats\n";

/*
 *			M O D E L _ R P P
 *
 *  Process a space command.
 *  Behavior depends on setting of several flags.
 *
 *  Implicit Returns -
 *	In all cases, sets space_min and space_max.
 */
int
model_rpp(const fastf_t *min, const fastf_t *max)
{

    if ( space_set )  {
	fprintf(stderr, "plrot:  additional SPACE command ignored\n");
	fprintf(stderr, "got: space (%g, %g, %g) (%g, %g, %g)\n",
		V3ARGS(min), V3ARGS(max) );
	fprintf(stderr, "still using: space (%g, %g, %g) (%g, %g, %g)\n",
		V3ARGS(space_min), V3ARGS(space_max) );
	return 0;
    }

    if ( rpp )  {
	point_t	rot_center;		/* center of rotation */
	mat_t	xlate;
	mat_t	resize;
	mat_t	t1, t2;

	VADD2SCALE( rot_center, min, max, 0.5 );

	/* Create the matrix which encodes this */
	MAT_IDN( xlate );
	MAT_DELTAS_VEC_NEG( xlate, rot_center);
	MAT_IDN( resize );
	resize[15] = 1/scale;
	bn_mat_mul( t1, resize, xlate );
	bn_mat_mul( t2, rmat, t1 );
	MAT_COPY( rmat, t2 );
	if ( verbose )  {
	    bn_mat_print("rmat", rmat);
	}

	if ( Mflag )  {
	    /*  Don't rebound, just expand size of space
	     *  around center point.
	     *  Has advantage of the output space() not being
	     *  affected by changes in rotation,
	     *  which may be significant for animation scripts.
	     */
	    vect_t	diag;
	    double	v;

	    VSUB2( diag, max, min );
	    v = MAGNITUDE(diag)*0.5 + 0.5;
	    VSET( space_min, -v, -v, -v );
	    VSET( space_max,  v,  v,  v );
	} else {
	    /* re-bound the space() rpp with a tighter one
	     * after rotating & scaling it.
	     */
	    bn_rotate_bbox( space_min, space_max, rmat, min, max );
	}
	space_set = 1;
    } else {
	VMOVE( space_min, min );
	VMOVE( space_max, max );
	space_set = 1;
    }

    if ( forced_space )  {
	/* Put forced space back */
	VMOVE( space_min, forced_space_min );
	VMOVE( space_max, forced_space_max );
	space_set = 1;
    }

    if ( verbose )  {
	fprintf(stderr, "got: space (%g, %g, %g) (%g, %g, %g)\n",
		V3ARGS(min), V3ARGS(max) );
	fprintf(stderr, "put: space (%g, %g, %g) (%g, %g, %g)\n",
		V3ARGS(space_min), V3ARGS(space_max) );
    }

    return( 1 );
}
Пример #19
0
/**
 * R E A D _ M A T
 */
void read_mat (struct rt_i *rtip)
{
    double scan[16] = MAT_INIT_ZERO;
    char	*buf;
    int		status = 0x0;
    mat_t	m;
    mat_t       q;

    while ((buf = rt_read_cmd(stdin)) != (char *) 0) {
	if (bu_strncmp(buf, "eye_pt", 6) == 0) {
	    if (sscanf(buf + 6, "%lf%lf%lf", &scan[X], &scan[Y], &scan[Z]) != 3) {
		bu_exit(1, "nirt: read_mat(): Failed to read eye_pt\n");
	    }
	    target(X) = scan[X];
	    target(Y) = scan[Y];
	    target(Z) = scan[Z];
	    status |= RMAT_SAW_EYE;
	} else if (bu_strncmp(buf, "orientation", 11) == 0) {
	    if (sscanf(buf + 11,
		       "%lf%lf%lf%lf",
		       &scan[X], &scan[Y], &scan[Z], &scan[W]) != 4) {
		bu_exit(1, "nirt: read_mat(): Failed to read orientation\n");
	    }
	    MAT_COPY(q, scan);
	    quat_quat2mat(m, q);
	    if (nirt_debug & DEBUG_MAT)
		bn_mat_print("view matrix", m);
	    azimuth() = atan2(-m[0], m[1]) / DEG2RAD;
	    elevation() = atan2(m[10], m[6]) / DEG2RAD;
	    status |= RMAT_SAW_ORI;
	} else if (bu_strncmp(buf, "viewrot", 7) == 0) {
	    if (sscanf(buf + 7,
		       "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
		       &scan[0], &scan[1], &scan[2], &scan[3],
		       &scan[4], &scan[5], &scan[6], &scan[7],
		       &scan[8], &scan[9], &scan[10], &scan[11],
		       &scan[12], &scan[13], &scan[14], &scan[15]) != 16) {
		bu_exit(1, "nirt: read_mat(): Failed to read viewrot\n");
	    }
	    MAT_COPY(m, scan);
	    if (nirt_debug & DEBUG_MAT)
		bn_mat_print("view matrix", m);
	    azimuth() = atan2(-m[0], m[1]) / DEG2RAD;
	    elevation() = atan2(m[10], m[6]) / DEG2RAD;
	    status |= RMAT_SAW_VR;
	}
    }

    if ((status & RMAT_SAW_EYE) == 0) {
	bu_exit(1, "nirt: read_mat(): Was given no eye_pt\n");
    }
    if ((status & (RMAT_SAW_ORI | RMAT_SAW_VR)) == 0) {
	bu_exit(1, "nirt: read_mat(): Was given no orientation or viewrot\n");
    }

    direct(X) = -m[8];
    direct(Y) = -m[9];
    direct(Z) = -m[10];

    dir2ae();

    targ2grid();
    shoot("", 0, rtip);
}
/**
 * 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;
}
static void
tree_solids(union tree *tp, struct tree_bark *tb, int op, struct resource *resp)
{
    RT_CK_TREE(tp);

    switch (tp->tr_op) {
	case OP_NOP:
	    return;

	case OP_SOLID: {
	    struct reg_db_internals *dbint;
	    matp_t mp;
	    long sol_id = 0;
	    struct rt_ell_internal *ell_p;
	    vect_t v;
	    int ret;

	    BU_ALLOC(dbint, struct reg_db_internals);
	    BU_LIST_INIT_MAGIC(&(dbint->l), DBINT_MAGIC);

	    if (tp->tr_a.tu_stp->st_matp)
		mp = tp->tr_a.tu_stp->st_matp;
	    else
		mp = (matp_t)bn_mat_identity;

	    /* Get the internal form of this solid & add it to the list */
	    ret = rt_db_get_internal(&dbint->ip, tp->tr_a.tu_stp->st_dp, tb->dbip, mp, resp);
	    if (ret < 0) {
		bu_log("Failure reading %s object from database.\n", OBJ[sol_id].ft_name);
		return;
	    }

	    RT_CK_DB_INTERNAL(&dbint->ip);
	    dbint->st_p = tp->tr_a.tu_stp;

	    sol_id = dbint->ip.idb_type;

	    if (sol_id < 0) {
		bu_log("Primitive ID %ld out of bounds\n", sol_id);
		bu_bomb("");
	    }


	    if (sol_id != ID_ELL) {

		if (op == OP_UNION)
		    bu_log("Non-ellipse \"union\" primitive of \"%s\" being ignored\n",
			   tb->name);

		if (rdebug&RDEBUG_SHADE)
		    bu_log(" got a primitive type %ld \"%s\".  This primitive ain't no ellipse bucko!\n",
			   sol_id, OBJ[sol_id].ft_name);

		break;
	    }


	    ell_p = (struct rt_ell_internal *)dbint->ip.idb_ptr;

	    if (rdebug&RDEBUG_SHADE)
		bu_log(" got a primitive type %ld \"%s\"\n",
		       sol_id,
		       OBJ[sol_id].ft_name);

	    RT_ELL_CK_MAGIC(ell_p);

	    if (rdebug&RDEBUG_SHADE) {
		VPRINT("point", ell_p->v);
		VPRINT("a", ell_p->a);
		VPRINT("b", ell_p->b);
		VPRINT("c", ell_p->c);
	    }

	    /* create the matrix that maps the coordinate system defined
	     * by the ellipse into model space, and get inverse for use
	     * in the _render() proc
	     */
	    MAT_IDN(mp);
	    VMOVE(v, ell_p->a);	VUNITIZE(v);
	    mp[0] = v[0];	mp[4] = v[1];	mp[8] = v[2];

	    VMOVE(v, ell_p->b);	VUNITIZE(v);
	    mp[1] = v[0];	mp[5] = v[1];	mp[9] = v[2];

	    VMOVE(v, ell_p->c);	VUNITIZE(v);
	    mp[2] = v[0];	mp[6] = v[1];	mp[10] = v[2];

	    MAT_DELTAS_VEC(mp, ell_p->v);

	    MAT_COPY(dbint->ell2model, mp);
	    bn_mat_inv(dbint->model2ell, mp);


	    /* find scaling of gaussian puff in ellipsoid space */
	    VSET(dbint->one_sigma,
		 MAGNITUDE(ell_p->a) / tb->gs->gauss_sigma,
		 MAGNITUDE(ell_p->b) / tb->gs->gauss_sigma,
		 MAGNITUDE(ell_p->c) / tb->gs->gauss_sigma);


	    if (rdebug&RDEBUG_SHADE) {
		VPRINT("sigma", dbint->one_sigma);
	    }
	    BU_LIST_APPEND(tb->l, &(dbint->l));

	    break;
	}
	case OP_UNION:
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    tree_solids(tp->tr_b.tb_right, tb, tp->tr_op, resp);
	    break;

	case OP_NOT: bu_log("Warning: 'Not' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;
	case OP_GUARD:bu_log("Warning: 'Guard' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;
	case OP_XNOP:bu_log("Warning: 'XNOP' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;

	case OP_INTERSECT:
	case OP_SUBTRACT:
	case OP_XOR:
	    /* XXX this can get us in trouble if 1 solid is subtracted
	     * from less than all the "union" solids of the region.
	     */
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    tree_solids(tp->tr_b.tb_right, tb, tp->tr_op, resp);
	    return;

	default:
	    bu_bomb("rt_tree_region_assign: bad op\n");
    }
}
Пример #22
0
/**
 * 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;
}
Пример #23
0
int
bn_mat_inverse(register mat_t output, const mat_t input)
{
    register int i, j;	/* Indices */
    int k;		/* Indices */
    int z[4];		/* Temporary */
    fastf_t b[4];	/* Temporary */
    fastf_t c[4];	/* Temporary */

    MAT_COPY(output, input);	/* Duplicate */

    /* Initialization */
    for (j = 0; j < 4; j++) {
	z[j] = j;
    }

    /* Main Loop */
    for (i = 0; i < 4; i++) {
	register fastf_t y;		/* local temporary */

	k = i;
	y = output[i * 4 + i];
	for (j = i + 1; j < 4; j++) {
	    register fastf_t w;		/* local temporary */

	    w = output[i * 4 + j];
	    if (fabs(w) > fabs(y)) {
		k = j;
		y = w;
	    }
	}

	if (ZERO(y)) {
	    /* SINGULAR */
	    return 0;
	}
	y = 1.0 / y;

	for (j = 0; j < 4; j++) {
	    register fastf_t temp;	/* Local */

	    c[j] = output[j * 4 + k];
	    output[j * 4 + k] = output[j * 4 + i];
	    output[j * 4 + i] = - c[j] * y;
	    temp = output[i * 4 + j] * y;
	    b[j] = temp;
	    output[i * 4 + j] = temp;
	}

	output[i * 4 + i] = y;
	j = z[i];
	z[i] = z[k];
	z[k] = j;
	for (k = 0; k < 4; k++) {
	    if (k == i) {
		continue;
	    }
	    for (j = 0; j < 4; j++) {
		if (j == i) {
		    continue;
		}
		output[k * 4 + j] = output[k * 4 + j] - b[j] * c[k];
	    }
	}
    }

    /* Second Loop */
    for (i = 0; i < 4; i++) {
	while ((k = z[i]) != i) {
	    int p;			/* Local temp */

	    for (j = 0; j < 4; j++) {
		register fastf_t w;	/* Local temp */

		w = output[i * 4 + j];
		output[i * 4 + j] = output[k * 4 + j];
		output[k * 4 + j] = w;
	    }
	    p = z[i];
	    z[i] = z[k];
	    z[k] = p;
	}
    }

    return 1;
}
Пример #24
0
/**
 * make a copy of a v5 solid by adding it to our book-keeping list,
 * adding it to the db directory, and writing it out to disk.
 */
static void
copy_v5_solid(struct db_i *_dbip, struct directory *proto, struct clone_state *state, int idx)
{
    size_t i;
    mat_t matrix;

    MAT_IDN(matrix);

    /* mirror */
    if (state->miraxis != W) {
	matrix[state->miraxis*5] = -1.0;
	matrix[3 + state->miraxis*4] -= 2 * (matrix[3 + state->miraxis*4] - state->mirpos);
    }

    /* translate */
    if (state->trans[W] > SMALL_FASTF)
	MAT_DELTAS_ADD_VEC(matrix, state->trans);

    /* rotation */
    if (state->rot[W] > SMALL_FASTF) {
	mat_t m2, t;

	bn_mat_angles(m2, state->rot[X], state->rot[Y], state->rot[Z]);
	if (state->rpnt[W] > SMALL_FASTF) {
	    mat_t m3;

	    bn_mat_xform_about_pt(m3, m2, state->rpnt);
	    bn_mat_mul(t, matrix, m3);
	} else
	    bn_mat_mul(t, matrix, m2);

	MAT_COPY(matrix, t);
    }

    /* make n copies */
    for (i = 0; i < state->n_copies; i++) {
	char *argv[6] = {"wdb_copy", (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
	struct bu_vls *name;
	int ret;
	struct directory *dp = (struct directory *)NULL;
	struct rt_db_internal intern;

	if (i==0)
	    dp = proto;
	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); /* get new name */
	bu_vls_strcpy(&obj_list.names[idx].dest[i], bu_vls_addr(name));

	/* actually copy the primitive to the new name */
	argv[1] = proto->d_namep;
	argv[2] = bu_vls_addr(name);
	ret = wdb_copy_cmd(_dbip->dbi_wdbp, 3, (const char **)argv);
	if (ret != TCL_OK)
	    bu_log("WARNING: failure cloning \"%s\" to \"%s\"\n", proto->d_namep, bu_vls_addr(name));

	/* get the original objects matrix */
	if (rt_db_get_internal(&intern, dp, _dbip, matrix, &rt_uniresource) < 0) {
	    bu_log("ERROR: clone internal error copying %s\n", proto->d_namep);
	    bu_vls_free(name);
	    return;
	}
	RT_CK_DB_INTERNAL(&intern);
	/* pull the new name */
	dp = db_lookup(_dbip, bu_vls_addr(name), LOOKUP_QUIET);
	bu_vls_free(name);
	if (!dp) {
	    bu_vls_free(name);
	    continue;
	}

	/* write the new matrix to the new object */
	if (rt_db_put_internal(dp, wdbp->dbip, &intern, &rt_uniresource) < 0)
	    bu_log("ERROR: clone internal error copying %s\n", proto->d_namep);
	rt_db_free_internal(&intern);
    } /* end iteration over each copy */

    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
/**
 * R T _ A R S _ M I R R O R
 *
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_ars_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_ars_internal *ars;

    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;
    size_t j;
    fastf_t *tmp_curve;

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

    RT_CK_DB_INTERNAL(ip);

    ars = (struct rt_ars_internal *)ip->idb_ptr;
    RT_ARS_CK_MAGIC(ars);

    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<ars->ncurves; i++) {
	for (j=0; j<ars->pts_per_curve; j++) {
	    point_t pt;

	    VMOVE(pt, &ars->curves[i][j*3]);
	    MAT4X3PNT(&ars->curves[i][j*3], mirmat, pt);
	}
    }

    /* now reverse order of vertices in each curve */
    tmp_curve = (fastf_t *)bu_calloc(3*ars->pts_per_curve, sizeof(fastf_t), "rt_mirror: tmp_curve");
    for (i=0; i<ars->ncurves; i++) {
	/* reverse vertex order */
	for (j=0; j<ars->pts_per_curve; j++) {
	    VMOVE(&tmp_curve[(ars->pts_per_curve-j-1)*3], &ars->curves[i][j*3]);
	}

	/* now copy back */
	memcpy(ars->curves[i], tmp_curve, ars->pts_per_curve*3*sizeof(fastf_t));
    }

    bu_free((char *)tmp_curve, "rt_mirror: tmp_curve");

    return 0;
}
Пример #27
0
int
get_args(int argc, register char **argv)
{
    register int c;
    mat_t	tmp, m;
    int	i, num;
    double	mtmp[16];

    MAT_IDN( rmat );
    scale = 1.0;

    while ( (c = bu_getopt( argc, argv, "S:m:vMga:e:x:y:z:X:Y:Z:s:" )) != EOF )  {
	switch ( c )  {
	    case 'M':
		/* take model RPP from space() command */
		rpp++;
		Mflag = 1;		/* don't rebound */
		break;
	    case 'g':
		bn_mat_angles( tmp, -90.0, 0.0, -90.0 );
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		break;
	    case 'a':
		bn_mat_angles( tmp, 0.0, 0.0, -atof(bu_optarg) );
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		rpp++;
		break;
	    case 'e':
		bn_mat_angles( tmp, 0.0, -atof(bu_optarg), 0.0 );
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		rpp++;
		break;
	    case 'x':
		bn_mat_angles( tmp, atof(bu_optarg), 0.0, 0.0 );
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		break;
	    case 'y':
		bn_mat_angles( tmp, 0.0, atof(bu_optarg), 0.0 );
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		break;
	    case 'z':
		bn_mat_angles( tmp, 0.0, 0.0, atof(bu_optarg) );
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		break;
	    case 'm':
		num = sscanf(&bu_optarg[0], "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
			     &mtmp[0], &mtmp[1], &mtmp[2], &mtmp[3],
			     &mtmp[4], &mtmp[5], &mtmp[6], &mtmp[7],
			     &mtmp[8], &mtmp[9], &mtmp[10], &mtmp[11],
			     &mtmp[12], &mtmp[13], &mtmp[14], &mtmp[15]);

		if ( num != 16)  {
		    fprintf(stderr, "Num of arguments to -m only %d, should be 16\n", num);
		    bu_exit (1, NULL);
		}

		/* Now copy the array of doubles into mat. */
		for (i=0; i < 16; i++ )  {
		    rmat[i] = mtmp[i];
		}
		break;
	    case 'X':
		MAT_IDN( tmp );
		tmp[MDX] = atof(bu_optarg);
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		break;
	    case 'Y':
		MAT_IDN( tmp );
		tmp[MDY] = atof(bu_optarg);
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		break;
	    case 'Z':
		MAT_IDN( tmp );
		tmp[MDZ] = atof(bu_optarg);
		MAT_COPY( m, rmat );
		bn_mat_mul( rmat, tmp, m );
		break;
	    case 's':
		scale *= atof(bu_optarg);
		/*
		 *  If rpp flag has already been set, defer
		 *  application of scale until after the
		 *  xlate to space-center, in model_rpp().
		 *  Otherwise, do it here, in the sequence
		 *  seen in the arg list.
		 */
		if ( !rpp )  {
		    MAT_IDN( tmp );
		    tmp[15] = 1/scale;
		    MAT_COPY( m, rmat );
		    bn_mat_mul( rmat, tmp, m );
		    scale = 1.0;
		}
		break;
	    case 'v':
		verbose++;
		break;
	    case 'S':
		num = sscanf(bu_optarg, "%lf %lf %lf %lf %lf %lf",
			     &mtmp[0], &mtmp[1], &mtmp[2],
			     &mtmp[3], &mtmp[4], &mtmp[5]);
		VSET(forced_space_min, mtmp[0], mtmp[1], mtmp[2]);
		VSET(forced_space_max, mtmp[3], mtmp[4], mtmp[5]);

		/* Write it now, in case input does not have one */
		pdv_3space( stdout, forced_space_min, forced_space_max );
		forced_space = 1;
		break;
	    default:		/* '?' */
		return(0);	/* Bad */
	}
    }


    if ( isatty(fileno(stdout))
	 || (isatty(fileno(stdin)) && (bu_optind >= argc)) )  {
	return(0);	/* Bad */
    }

    return(1);		/* OK */
}
Пример #28
0
/**
 * R T _ F I N D _ I D E N T I C A L _ S O L I D
 *
 * See if solid "dp" as transformed by "mat" already exists in the
 * soltab list.  If it does, return the matching stp, otherwise,
 * create a new soltab structure, enrole it in the list, and return a
 * pointer to that.
 *
 * "mat" will be a null pointer when an identity matrix is signified.
 * This greatly speeds the comparison process.
 *
 * The two cases can be distinguished by the fact that stp->st_id will
 * be 0 for a new soltab structure, and non-zero for an existing one.
 *
 * This routine will run in parallel.
 *
 * In order to avoid a race between searching the soltab list and
 * adding new solids to it, the new solid to be added *must* be
 * enrolled in the list before exiting the critical section.
 *
 * To limit the size of the list to be searched, there are many lists.
 * The selection of which list is determined by the hash value
 * computed from the solid's name.  This is the same optimization used
 * in searching the directory lists.
 *
 * This subroutine is the critical bottleneck in parallel tree walking.
 *
 * It is safe, and much faster, to use several different critical
 * sections when searching different lists.
 *
 * There are only 4 dedicated semaphores defined, TREE0 through TREE3.
 * This unfortunately limits the code to having only 4 CPUs doing list
 * searching at any one time.  Hopefully, this is enough parallelism
 * to keep the rest of the CPUs doing I/O and actual solid prepping.
 *
 * Since the algorithm has been reduced from an O((nsolid/128)**2)
 * search on the entire rti_solidheads[hash] list to an O(ninstance)
 * search on the dp->d_use_head list for this one solid, the critical
 * section should be relatively short-lived.  Having the 3-way split
 * should provide ample opportunity for parallelism through here,
 * while still ensuring that the necessary variables are protected.
 *
 * There are two critical variables which *both* need to be protected:
 * the specific rti_solidhead[hash] list head, and the specific
 * dp->d_use_hd list head.  Fortunately, since the selection of
 * critical section is based upon db_dirhash(dp->d_namep), any other
 * processor that wants to search this same 'dp' will get the same
 * hash as the current thread, and will thus wait for the appropriate
 * semaphore to be released.  Similarly, any other thread that wants
 * to search the same rti_solidhead[hash] list as the current thread
 * will be using the same hash, and will thus wait for the proper
 * semaphore.
 */
HIDDEN struct soltab *rt_find_identical_solid(register const matp_t mat, register struct directory *dp, struct rt_i *rtip)
{
    register struct soltab	*stp = RT_SOLTAB_NULL;
    int			hash;

    RT_CK_DIR(dp);
    RT_CK_RTI(rtip);

    hash = db_dirhash( dp->d_namep );

    /* Enter the appropriate dual critical-section */
    ACQUIRE_SEMAPHORE_TREE(hash);

    /*
     * If solid has not been referenced yet, the search can be
     * skipped.  If solid is being referenced a _lot_, it certainly
     * isn't all going to be in the same place, so don't bother
     * searching.  Consider the case of a million instances of the
     * same tree submodel solid.
     */
    if ( dp->d_uses > 0 && dp->d_uses < 100 &&
	 rtip->rti_dont_instance == 0
	)  {
	struct bu_list	*mid;

	/* Search dp->d_use_hd list for other instances */
	for ( BU_LIST_FOR( mid, bu_list, &dp->d_use_hd ) )  {

	    stp = BU_LIST_MAIN_PTR( soltab, mid, l2 );
	    RT_CK_SOLTAB(stp);

	    if ( stp->st_matp == (matp_t)0 )  {
		if ( mat == (matp_t)0 )  {
		    /* Both have identity matrix */
		    goto more_checks;
		}
		continue;
	    }
	    if ( mat == (matp_t)0 )  continue;	/* doesn't match */

	    if ( !bn_mat_is_equal(mat, stp->st_matp, &rtip->rti_tol))
		continue;

	more_checks:
	    /* Don't instance this solid from some other model
	     * instance.  As this is nearly always equal, check it
	     * last
	     */
	    if ( stp->st_rtip != rtip )  continue;

	    /*
	     * stp now points to re-referenced solid.  stp->st_id is
	     * non-zero, indicating pre-existing solid.
	     */
	    RT_CK_SOLTAB(stp);		/* sanity */

	    /* Only increment use counter for non-dead solids. */
	    if ( !(stp->st_aradius <= -1) )
		stp->st_uses++;
	    /* dp->d_uses is NOT incremented, because number of
	     * soltab's using it has not gone up.
	     */
	    if ( RT_G_DEBUG & DEBUG_SOLIDS )  {
		bu_log( mat ?
			"rt_find_identical_solid:  %s re-referenced %d\n" :
			"rt_find_identical_solid:  %s re-referenced %d (identity mat)\n",
			dp->d_namep, stp->st_uses );
	    }

	    /* Leave the appropriate dual critical-section */
	    RELEASE_SEMAPHORE_TREE(hash);
	    return stp;
	}
    }

    /*
     * Create and link a new solid into the list.
     *
     * Ensure the search keys "dp", "st_mat" and "st_rtip" are stored
     * now, while still inside the critical section, because they are
     * searched on, above.
     */
    BU_GETSTRUCT(stp, soltab);
    stp->l.magic = RT_SOLTAB_MAGIC;
    stp->l2.magic = RT_SOLTAB2_MAGIC;
    stp->st_rtip = rtip;
    stp->st_dp = dp;
    dp->d_uses++;
    stp->st_uses = 1;
    /* stp->st_id is intentionally left zero here, as a flag */

    if ( mat )  {
	stp->st_matp = (matp_t)bu_malloc( sizeof(mat_t), "st_matp" );
	MAT_COPY( stp->st_matp, mat );
    } else {
	stp->st_matp = (matp_t)0;
    }

    /* Add to the appropriate soltab list head */
    /* PARALLEL NOTE:  Uses critical section on rt_solidheads element */
    BU_LIST_INSERT( &(rtip->rti_solidheads[hash]), &(stp->l) );

    /* Also add to the directory structure list head */
    /* PARALLEL NOTE:  Uses critical section on this 'dp' */
    BU_LIST_INSERT( &dp->d_use_hd, &(stp->l2) );

    /*
     * Leave the 4-way critical-section protecting dp and [hash]
     */
    RELEASE_SEMAPHORE_TREE(hash);

    /* Enter an exclusive critical section to protect nsolids.
     * nsolids++ needs to be locked to a SINGLE thread
     */
    bu_semaphore_acquire(RT_SEM_STATS);
    stp->st_bit = rtip->nsolids++;
    bu_semaphore_release(RT_SEM_STATS);

    /*
     * Fill in the last little bit of the structure in full parallel
     * mode, outside of any critical section.
     */

    /* Init tables of regions using this solid.  Usually small. */
    bu_ptbl_init( &stp->st_regions, 7, "st_regions ptbl" );

    return stp;
}