void bn_wrt_point_direc(mat_t out, const mat_t change, const mat_t in, const point_t point, const vect_t direc, const struct bn_tol *tol) { static mat_t t1; static mat_t pt_to_origin, origin_to_pt; static mat_t d_to_zaxis, zaxis_to_d; static vect_t zaxis; /* build "point to origin" matrix */ MAT_IDN(pt_to_origin); MAT_DELTAS_VEC_NEG(pt_to_origin, point); /* build "origin to point" matrix */ MAT_IDN(origin_to_pt); MAT_DELTAS_VEC_NEG(origin_to_pt, point); /* build "direc to zaxis" matrix */ VSET(zaxis, 0.0, 0.0, 1.0); bn_mat_fromto(d_to_zaxis, direc, zaxis, tol); /* build "zaxis to direc" matrix */ bn_mat_inv(zaxis_to_d, d_to_zaxis); /* apply change matrix... * t1 = change * d_to_zaxis * pt_to_origin * in */ bn_mat_mul4(t1, change, d_to_zaxis, pt_to_origin, in); /* apply origin_to_pt matrix: * out = origin_to_pt * zaxis_to_d * * change * d_to_zaxis * pt_to_origin * in */ bn_mat_mul3(out, origin_to_pt, zaxis_to_d, t1); }
int _ged_do_tra(struct ged *gedp, char coord, vect_t tvec, int (*func)()) { point_t delta; point_t work; point_t vc, nvc; if (func != (int (*)())0) return (*func)(gedp, coord, tvec); switch (coord) { case 'm': VSCALE(delta, tvec, -gedp->ged_wdbp->dbip->dbi_base2local); MAT_DELTAS_GET_NEG(vc, gedp->ged_gvp->gv_center); break; case 'v': default: VSCALE(tvec, tvec, -2.0*gedp->ged_wdbp->dbip->dbi_base2local*gedp->ged_gvp->gv_isize); MAT4X3PNT(work, gedp->ged_gvp->gv_view2model, tvec); MAT_DELTAS_GET_NEG(vc, gedp->ged_gvp->gv_center); VSUB2(delta, work, vc); break; } VSUB2(nvc, vc, delta); MAT_DELTAS_VEC_NEG(gedp->ged_gvp->gv_center, nvc); ged_view_update(gedp->ged_gvp); return GED_OK; }
int _ged_do_slew(struct ged *gedp, vect_t svec) { point_t model_center; MAT4X3PNT(model_center, gedp->ged_gvp->gv_view2model, svec); MAT_DELTAS_VEC_NEG(gedp->ged_gvp->gv_center, model_center); ged_view_update(gedp->ged_gvp); return GED_OK; }
void bn_mat_xform_about_pt(mat_t mat, const mat_t xform, const point_t pt) { mat_t xlate; mat_t tmp; MAT_IDN(xlate); MAT_DELTAS_VEC_NEG(xlate, pt); bn_mat_mul(tmp, xform, xlate); MAT_DELTAS_VEC(xlate, pt); bn_mat_mul(mat, xlate, tmp); }
int bn_mat_scale_about_pt(mat_t mat, const point_t pt, const double scale) { mat_t xlate; mat_t s; mat_t tmp; MAT_IDN(xlate); MAT_DELTAS_VEC_NEG(xlate, pt); MAT_IDN(s); if (ZERO(scale)) { MAT_ZERO(mat); return -1; /* ERROR */ } s[15] = 1 / scale; bn_mat_mul(tmp, s, xlate); MAT_DELTAS_VEC(xlate, pt); bn_mat_mul(mat, xlate, tmp); return 0; /* OK */ }
-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 ); }
int ged_pov(struct ged *gedp, int argc, const char *argv[]) { vect_t center; quat_t quat; vect_t eye_pos; /* intentionally double for scan */ double scale; double perspective; static const char *usage = "center quat scale eye_pos perspective"; 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); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc != 6) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } /***************** Get the arguments *******************/ if (bn_decode_vect(center, argv[1]) != 3) { bu_vls_printf(gedp->ged_result_str, "ged_pov: bad center - %s\n", argv[1]); return TCL_ERROR; } if (bn_decode_quat(quat, argv[2]) != 4) { bu_vls_printf(gedp->ged_result_str, "ged_pov: bad quat - %s\n", argv[2]); return TCL_ERROR; } if (sscanf(argv[3], "%lf", &scale) != 1) { bu_vls_printf(gedp->ged_result_str, "ged_pov: bad scale - %s\n", argv[3]); return TCL_ERROR; } if (bn_decode_vect(eye_pos, argv[4]) != 3) { bu_vls_printf(gedp->ged_result_str, "ged_pov: bad eye position - %s\n", argv[4]); return TCL_ERROR; } if (sscanf(argv[5], "%lf", &perspective) != 1) { bu_vls_printf(gedp->ged_result_str, "ged_pov: bad perspective - %s\n", argv[5]); return TCL_ERROR; } /***************** Use the arguments *******************/ VSCALE(center, center, gedp->ged_wdbp->dbip->dbi_local2base); MAT_DELTAS_VEC_NEG(gedp->ged_gvp->gv_center, center); quat_quat2mat(gedp->ged_gvp->gv_rotation, quat); gedp->ged_gvp->gv_scale = gedp->ged_wdbp->dbip->dbi_local2base * scale; VSCALE(eye_pos, eye_pos, gedp->ged_wdbp->dbip->dbi_local2base); VMOVE(gedp->ged_gvp->gv_eye_pos, eye_pos); gedp->ged_gvp->gv_perspective = perspective; ged_view_update(gedp->ged_gvp); return GED_OK; }
/** * 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"); } }
int _ged_do_rot(struct ged *gedp, char coord, mat_t rmat, int (*func)()) { mat_t temp1, temp2; if (func != (int (*)())0) return (*func)(gedp, coord, gedp->ged_gvp->gv_rotate_about, rmat); switch (coord) { case 'm': /* transform model rotations into view rotations */ bn_mat_inv(temp1, gedp->ged_gvp->gv_rotation); bn_mat_mul(temp2, gedp->ged_gvp->gv_rotation, rmat); bn_mat_mul(rmat, temp2, temp1); break; case 'v': default: break; } /* Calculate new view center */ if (gedp->ged_gvp->gv_rotate_about != 'v') { point_t rot_pt; point_t new_origin; mat_t viewchg, viewchginv; point_t new_cent_view; point_t new_cent_model; switch (gedp->ged_gvp->gv_rotate_about) { case 'e': VSET(rot_pt, 0.0, 0.0, 1.0); break; case 'k': MAT4X3PNT(rot_pt, gedp->ged_gvp->gv_model2view, gedp->ged_gvp->gv_keypoint); break; case 'm': /* rotate around model center (0, 0, 0) */ VSET(new_origin, 0.0, 0.0, 0.0); MAT4X3PNT(rot_pt, gedp->ged_gvp->gv_model2view, new_origin); break; default: return GED_ERROR; } bn_mat_xform_about_pt(viewchg, rmat, rot_pt); bn_mat_inv(viewchginv, viewchg); /* Convert origin in new (viewchg) coords back to old view coords */ VSET(new_origin, 0.0, 0.0, 0.0); MAT4X3PNT(new_cent_view, viewchginv, new_origin); MAT4X3PNT(new_cent_model, gedp->ged_gvp->gv_view2model, new_cent_view); MAT_DELTAS_VEC_NEG(gedp->ged_gvp->gv_center, new_cent_model); } /* pure rotation */ bn_mat_mul2(rmat, gedp->ged_gvp->gv_rotation); ged_view_update(gedp->ged_gvp); return GED_OK; }
/* * 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; }