view_obj.c

Go to the documentation of this file.
00001 /*                      V I E W _ O B J . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1997-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup librt */
00023 /*@{*/
00024 /** @file view_obj.c
00025  * A view object contains the attributes and methods for
00026  * controlling viewing transformations. Much of this code
00027  * was extracted from MGED and modified to work herein.
00028  *
00029  * Source -
00030  *      SLAD CAD Team
00031  *      The U. S. Army Research Laboratory
00032  *      Aberdeen Proving Ground, Maryland  21005
00033  *
00034  * Author -
00035  *      Robert G. Parker
00036  *
00037  *  Source -
00038  *      The U. S. Army Research Laboratory
00039  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00040  */
00041 /*@}*/
00042 
00043 #include "common.h"
00044 
00045 
00046 #ifdef HAVE_STRING_H
00047 #include <string.h>
00048 #else
00049 #include <strings.h>
00050 #endif
00051 #include <math.h>
00052 #include "tcl.h"
00053 #include "machine.h"
00054 #include "cmd.h"                /* includes bu.h */
00055 #include "vmath.h"
00056 #include "bn.h"
00057 #include "raytrace.h"
00058 
00059 
00060 int Vo_Init(Tcl_Interp *interp);
00061 
00062 static int vo_open_tcl(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv);
00063 static int vo_size_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00064 static int vo_invSize_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00065 static int vo_aet_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00066 static int vo_rmat_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00067 static int vo_center_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00068 static int vo_model2view_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00069 static int vo_pmodel2view_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00070 static int vo_view2model_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00071 static int vo_perspective_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00072 static int vo_pmat_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00073 static int vo_rot_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00074 static int vo_tra_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00075 static int vo_sca_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00076 static int vo_slew_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00077 
00078 static int vo_eye_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00079 static int vo_eye_pos_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00080 static int vo_lookat_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00081 static int vo_orientation_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00082 static int vo_pov_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00083 static int vo_units_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00084 static int vo_zoom_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00085 static int vo_local2base_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00086 static int vo_base2local_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00087 static int vo_observer_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00088 static int vo_coord_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00089 static int vo_rotate_about_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00090 static int vo_keypoint_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00091 static int vo_setview_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00092 static int vo_arot_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00093 static int vo_vrot_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00094 static int vo_mrot_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00095 static int vo_mrotPoint_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00096 static int vo_m2vPoint_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00097 static int vo_v2mPoint_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00098 static int vo_viewDir_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00099 
00100 static int vo_cmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
00101 void vo_update(struct view_obj *vop, Tcl_Interp *interp, int oflag);
00102 void vo_mat_aet(struct view_obj *vop);
00103 static void vo_persp_mat(fastf_t *m, fastf_t fovy, fastf_t aspect, fastf_t near1, fastf_t far1, fastf_t backoff);
00104 static void vo_mike_persp_mat(fastf_t *pmat, const fastf_t *eye);
00105 
00106 struct view_obj HeadViewObj;            /* head of view object list */
00107 
00108 static struct bu_cmdtab vo_cmds[] =
00109 {
00110         {"ae",                  vo_aet_tcl},
00111         {"arot",                vo_arot_tcl},
00112         {"base2local",          vo_base2local_tcl},
00113         {"center",              vo_center_tcl},
00114         {"coord",               vo_coord_tcl},
00115         {"viewDir",             vo_viewDir_tcl},
00116         {"eye",                 vo_eye_tcl},
00117         {"eye_pos",             vo_eye_pos_tcl},
00118         {"invSize",             vo_invSize_tcl},
00119         {"keypoint",            vo_keypoint_tcl},
00120         {"local2base",          vo_local2base_tcl},
00121         {"lookat",              vo_lookat_tcl},
00122         {"m2vPoint",            vo_m2vPoint_tcl},
00123         {"model2view",          vo_model2view_tcl},
00124         {"mrot",                vo_mrot_tcl},
00125         {"mrotPoint",           vo_mrotPoint_tcl},
00126         {"observer",            vo_observer_tcl},
00127         {"orientation",         vo_orientation_tcl},
00128         {"perspective",         vo_perspective_tcl},
00129         {"pmat",                vo_pmat_tcl},
00130         {"pmodel2view",         vo_pmodel2view_tcl},
00131         {"pov",                 vo_pov_tcl},
00132         {"rmat",                vo_rmat_tcl},
00133         {"rot",                 vo_rot_tcl},
00134         {"rotate_about",        vo_rotate_about_tcl},
00135         {"sca",                 vo_sca_tcl},
00136         {"setview",             vo_setview_tcl},
00137         {"size",                vo_size_tcl},
00138         {"slew",                vo_slew_tcl},
00139         {"tra",                 vo_tra_tcl},
00140         {"units",               vo_units_tcl},
00141         {"view2model",          vo_view2model_tcl},
00142         {"v2mPoint",            vo_v2mPoint_tcl},
00143         {"vrot",                vo_vrot_tcl},
00144         {"zoom",                vo_zoom_tcl},
00145 #if 0
00146         {"knob",                vo_knob_tcl},
00147         {"qorot",               vo_qorot_tcl},
00148         {"qvrot",               vo_qvrot_tcl},
00149         {"status",              vo_status_tcl},
00150         {"",            vo__tcl},
00151 #endif
00152         {(char *)0,             (int (*)())0}
00153 };
00154 
00155 static int
00156 vo_cmd(ClientData       clientData,
00157        Tcl_Interp       *interp,
00158        int              argc,
00159        char             **argv)
00160 {
00161         return bu_cmd(clientData, interp, argc, argv, vo_cmds, 1);
00162 }
00163 
00164 int
00165 Vo_Init(Tcl_Interp *interp)
00166 {
00167         BU_LIST_INIT(&HeadViewObj.l);
00168         (void)Tcl_CreateCommand(interp, "v_open", vo_open_tcl,
00169                                 (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
00170 
00171         return TCL_OK;
00172 }
00173 
00174 static void
00175 vo_deleteProc(ClientData clientData)
00176 {
00177         struct view_obj *vop = (struct view_obj *)clientData;
00178 
00179         /* free observers */
00180         bu_observer_free(&vop->vo_observers);
00181 
00182         bu_vls_free(&vop->vo_name);
00183         BU_LIST_DEQUEUE(&vop->l);
00184         bu_free((genptr_t)vop, "vo_deleteProc: vop");
00185 }
00186 
00187 /*
00188  * Create an command/object named "oname" in "interp".
00189  */
00190 struct view_obj *
00191 vo_open_cmd(const char  *oname)
00192 {
00193         Tcl_Interp      *interp = (Tcl_Interp *)NULL;
00194         struct view_obj *vop;
00195 
00196         BU_GETSTRUCT(vop,view_obj);
00197 
00198         /* initialize view_obj */
00199         bu_vls_init(&vop->vo_name);
00200         bu_vls_strcpy(&vop->vo_name, oname);
00201         vop->vo_scale = 1.0;
00202         vop->vo_size = 2.0 * vop->vo_scale;
00203         vop->vo_invSize = 1.0 / vop->vo_size;
00204         vop->vo_local2base = 1.0;               /* default units - mm */
00205         vop->vo_base2local = 1.0;               /* default units - mm */
00206         VSET(vop->vo_eye_pos, 0.0, 0.0, 1.0);
00207         MAT_IDN(vop->vo_rotation);
00208         MAT_IDN(vop->vo_center);
00209         VSETALL(vop->vo_keypoint, 0.0);
00210         vop->vo_coord = 'v';
00211         vop->vo_rotate_about = 'v';
00212         vo_update(vop, interp, 0);
00213         BU_LIST_INIT(&vop->vo_observers.l);
00214         vop->vo_callback = (void (*)())0;
00215 
00216         /* append to list of view_obj's */
00217         BU_LIST_APPEND(&HeadViewObj.l,&vop->l);
00218 
00219         return vop;
00220 }
00221 
00222 /*
00223  * Open a view object.
00224  *
00225  * USAGE: v_open [name]
00226  */
00227 static int
00228 vo_open_tcl(ClientData  clientData,
00229             Tcl_Interp  *interp,
00230             int         argc,
00231             const char  **argv)
00232 {
00233         struct view_obj *vop;
00234 
00235         if (argc == 1) {
00236                 /* get list of view objects */
00237                 for (BU_LIST_FOR(vop, view_obj, &HeadViewObj.l))
00238                         Tcl_AppendResult(interp, bu_vls_addr(&vop->vo_name), " ", (char *)NULL);
00239 
00240                 return TCL_OK;
00241         }
00242 
00243         /* first, delete any commands by this name */
00244         (void)Tcl_DeleteCommand(interp, argv[1]);
00245 
00246         vop = vo_open_cmd(argv[1]);
00247         (void)Tcl_CreateCommand(interp,
00248                                 bu_vls_addr(&vop->vo_name),
00249                                 (Tcl_CmdProc *)vo_cmd,
00250                                 (ClientData)vop,
00251                                 vo_deleteProc);
00252 
00253         /* Return new function name as result */
00254         Tcl_ResetResult(interp);
00255         Tcl_AppendResult(interp, bu_vls_addr(&vop->vo_name), (char *)NULL);
00256 
00257         return TCL_OK;
00258 }
00259 
00260 /****************** View Object Methods ********************/
00261 
00262 #if 0
00263 /* skeleton functions for view_obj methods */
00264 int
00265 vo__cmd(struct view_obj *vop,
00266          Tcl_Interp     *interp,
00267          int            argc,
00268          char           **argv)
00269 {
00270 }
00271 
00272 /*
00273  * Usage:
00274  *        procname
00275  */
00276 static int
00277 vo__tcl(ClientData      clientData,
00278          Tcl_Interp     *interp,
00279          int            argc,
00280          char           **argv)
00281 {
00282         struct view_obj *vop = (struct view_obj *)clientData;
00283 
00284         return vo__cmd(vop, interp, argc-1, argv+1);
00285 }
00286 #endif
00287 
00288 void
00289 vo_size(struct view_obj *vop,
00290         Tcl_Interp      *interp,
00291         fastf_t         size)
00292 {
00293         vop->vo_size = vop->vo_local2base * size;
00294         if (vop->vo_size < RT_MINVIEWSIZE)
00295                 vop->vo_size = RT_MINVIEWSIZE;
00296         vop->vo_invSize = 1.0 / vop->vo_size;
00297         vop->vo_scale = 0.5 * vop->vo_size;
00298         vo_update(vop, interp, 1);
00299 }
00300 
00301 int
00302 vo_size_cmd(struct view_obj     *vop,
00303             Tcl_Interp          *interp,
00304             int                 argc,
00305             char                **argv)
00306 {
00307         struct bu_vls vls;
00308         fastf_t size;
00309 
00310         /* get view size */
00311         if (argc == 1) {
00312                 bu_vls_init(&vls);
00313                 bu_vls_printf(&vls, "%g", vop->vo_size * vop->vo_base2local);
00314                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00315                 bu_vls_free(&vls);
00316 
00317                 return TCL_OK;
00318         }
00319 
00320         /* set view size */
00321         if (argc == 2) {
00322                 if (sscanf(argv[1], "%lf", &size) != 1 ||
00323                     size <= 0 ||
00324                     NEAR_ZERO(size, SMALL_FASTF)) {
00325                         Tcl_AppendResult(interp, "bad size - ",
00326                                          argv[1], (char *)NULL);
00327                         return TCL_ERROR;
00328                 }
00329 
00330                 vo_size(vop, interp, size);
00331                 return TCL_OK;
00332         }
00333 
00334         /* compose error message */
00335         bu_vls_init(&vls);
00336         bu_vls_printf(&vls, "helplib_alias vo_size %s", argv[0]);
00337         Tcl_Eval(interp, bu_vls_addr(&vls));
00338         bu_vls_free(&vls);
00339 
00340         return TCL_ERROR;
00341 }
00342 
00343 /*
00344  * Get or set the view size.
00345  *
00346  * Usage:
00347  *        procname size [s]
00348  */
00349 static int
00350 vo_size_tcl(ClientData  clientData,
00351              Tcl_Interp *interp,
00352              int        argc,
00353              char       **argv)
00354 {
00355         struct view_obj *vop = (struct view_obj *)clientData;
00356 
00357         return vo_size_cmd(vop, interp, argc-1, argv+1);
00358 }
00359 
00360 int
00361 vo_invSize_cmd(struct view_obj  *vop,
00362                Tcl_Interp       *interp,
00363                int              argc,
00364                char             **argv)
00365 {
00366         struct bu_vls vls;
00367 
00368         if (argc == 1) {
00369                 bu_vls_init(&vls);
00370                 bu_vls_printf(&vls, "%g", vop->vo_invSize * vop->vo_base2local);
00371                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00372                 bu_vls_free(&vls);
00373 
00374                 return TCL_OK;
00375         }
00376 
00377         /* compose error message */
00378         bu_vls_init(&vls);
00379         bu_vls_printf(&vls, "helplib_alias vo_invSize %s", argv[0]);
00380         Tcl_Eval(interp, bu_vls_addr(&vls));
00381         bu_vls_free(&vls);
00382 
00383         return TCL_ERROR;
00384 }
00385 
00386 /*
00387  * Get the inverse view size.
00388  *
00389  * Usage:
00390  *        procname
00391  */
00392 static int
00393 vo_invSize_tcl(ClientData       clientData,
00394                 Tcl_Interp      *interp,
00395                 int             argc,
00396                 char            **argv)
00397 {
00398         struct view_obj *vop = (struct view_obj *)clientData;
00399 
00400         return vo_invSize_cmd(vop, interp, argc-1, argv+1);
00401 }
00402 
00403 int
00404 vo_aet_cmd(struct view_obj      *vop,
00405            Tcl_Interp           *interp,
00406            int                  argc,
00407            char                 **argv)
00408 {
00409         struct bu_vls   vls;
00410         vect_t          aet;
00411         int             iflag = 0;
00412 
00413         if (argc == 1) { /* get aet */
00414                 bu_vls_init(&vls);
00415                 bn_encode_vect(&vls, vop->vo_aet);
00416                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00417                 bu_vls_free(&vls);
00418 
00419                 return TCL_OK;
00420         }
00421 
00422         /* Check for -i option */
00423         if (argv[1][0] == '-' && argv[1][1] == 'i') {
00424                 iflag = 1;  /* treat arguments as incremental values */
00425                 ++argv;
00426                 --argc;
00427         }
00428 
00429         if (argc == 2) {  /* set aet */
00430                 int n;
00431 
00432                 if ((n = bn_decode_vect(aet, argv[1])) == 2)
00433                         aet[2] = 0;
00434                 else if (n != 3)
00435                         goto bad;
00436 
00437                 if (iflag) {
00438                         VADD2(vop->vo_aet, vop->vo_aet, aet);
00439                 } else {
00440                         VMOVE(vop->vo_aet, aet);
00441                 }
00442                 vo_mat_aet(vop);
00443                 vo_update(vop, interp, 1);
00444 
00445                 return TCL_OK;
00446         }
00447 
00448         if (argc == 3 || argc == 4) {
00449                 if (sscanf(argv[1], "%lf", &aet[X]) != 1) {
00450                         Tcl_AppendResult(interp, "vo_aet: bad azimuth - ", argv[1], "\n", (char *)0);
00451                         return TCL_ERROR;
00452                 }
00453 
00454                 if (sscanf(argv[2], "%lf", &aet[Y]) != 1) {
00455                         Tcl_AppendResult(interp, "vo_aet: bad elevation - ", argv[2], "\n", (char *)0);
00456                         return TCL_ERROR;
00457                 }
00458 
00459                 if (argc == 4) {
00460                         if (sscanf(argv[3], "%lf", &aet[Z]) != 1) {
00461                                 Tcl_AppendResult(interp, "vo_aet: bad twist - ", argv[3], "\n", (char *)0);
00462                                 return TCL_ERROR;
00463                         }
00464                 } else
00465                         aet[Z] = 0.0;
00466 
00467                 if (iflag) {
00468                         VADD2(vop->vo_aet, vop->vo_aet, aet);
00469                 } else {
00470                         VMOVE(vop->vo_aet, aet);
00471                 }
00472                 vo_mat_aet(vop);
00473                 vo_update(vop, interp, 1);
00474 
00475                 return TCL_OK;
00476         }
00477 
00478  bad:
00479         /* compose error message */
00480         bu_vls_init(&vls);
00481         bu_vls_printf(&vls, "helplib_alias vo_aet %s", argv[0]);
00482         Tcl_Eval(interp, bu_vls_addr(&vls));
00483         bu_vls_free(&vls);
00484 
00485         return TCL_ERROR;
00486 }
00487 
00488 /*
00489  * Get or set the azimuth, elevation and twist.
00490  *
00491  * Usage:
00492  *        procname ae [[-i] az el [tw]]
00493  */
00494 static int
00495 vo_aet_tcl(ClientData   clientData,
00496          Tcl_Interp     *interp,
00497          int            argc,
00498          char           **argv)
00499 {
00500         struct view_obj *vop = (struct view_obj *)clientData;
00501 
00502         return vo_aet_cmd(vop, interp, argc-1, argv+1);
00503 }
00504 
00505 int
00506 vo_rmat_cmd(struct view_obj     *vop,
00507             Tcl_Interp          *interp,
00508             int                 argc,
00509             char                **argv)
00510 {
00511         struct bu_vls vls;
00512         mat_t rotation;
00513 
00514         if (argc == 1) { /* get rotation matrix */
00515                 bu_vls_init(&vls);
00516                 bn_encode_mat(&vls, vop->vo_rotation);
00517                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00518                 bu_vls_free(&vls);
00519 
00520                 return TCL_OK;
00521         } else if (argc == 2) {  /* set rotation matrix */
00522                 if (bn_decode_mat(rotation, argv[1]) != 16)
00523                         return TCL_ERROR;
00524 
00525                 MAT_COPY(vop->vo_rotation, rotation);
00526                 vo_update(vop, interp , 1);
00527 
00528                 return TCL_OK;
00529         }
00530 
00531         /* compose error message */
00532         bu_vls_init(&vls);
00533         bu_vls_printf(&vls, "helplib_alias vo_rmat %s", argv[0]);
00534         Tcl_Eval(interp, bu_vls_addr(&vls));
00535         bu_vls_free(&vls);
00536 
00537         return TCL_ERROR;
00538 }
00539 
00540 /*
00541  * Get or set the rotation matrix.
00542  *
00543  * Usage:
00544  *        procname
00545  */
00546 static int
00547 vo_rmat_tcl(ClientData  clientData,
00548             Tcl_Interp  *interp,
00549             int         argc,
00550             char        **argv)
00551 {
00552         struct view_obj *vop = (struct view_obj *)clientData;
00553 
00554         return vo_rmat_cmd(vop, interp, argc-1, argv+1);
00555 }
00556 
00557 void
00558 vo_center(struct view_obj       *vop,
00559           Tcl_Interp            *interp,
00560           point_t               center)
00561 {
00562         VSCALE(center, center, vop->vo_local2base);
00563         MAT_DELTAS_VEC_NEG(vop->vo_center, center);
00564         vo_update(vop, interp, 1);
00565 }
00566 
00567 int
00568 vo_center_cmd(struct view_obj   *vop,
00569               Tcl_Interp        *interp,
00570               int               argc,
00571               char              **argv)
00572 {
00573         point_t         center;
00574         struct bu_vls   vls;
00575 
00576 
00577         /* get view center */
00578         if (argc == 1) {
00579                 MAT_DELTAS_GET_NEG(center, vop->vo_center);
00580                 VSCALE(center, center, vop->vo_base2local);
00581                 bu_vls_init(&vls);
00582                 bn_encode_vect(&vls, center);
00583                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00584                 bu_vls_free(&vls);
00585 
00586                 return TCL_OK;
00587         }
00588 
00589         /* set view center */
00590         if (argc == 2 || argc == 4) {
00591                 if (argc == 2) {
00592                         if (bn_decode_vect(center, argv[1]) != 3)
00593                                 goto bad;
00594                 } else {
00595                         if (sscanf(argv[1], "%lf", &center[X]) != 1) {
00596                                 Tcl_AppendResult(interp, "vo_center: bad X value - ", argv[1], "\n", (char *)0);
00597                                 return TCL_ERROR;
00598                         }
00599 
00600                         if (sscanf(argv[2], "%lf", &center[Y]) != 1) {
00601                                 Tcl_AppendResult(interp, "vo_center: bad Y value - ", argv[2], "\n", (char *)0);
00602                                 return TCL_ERROR;
00603                         }
00604 
00605                         if (sscanf(argv[3], "%lf", &center[Z]) != 1) {
00606                                 Tcl_AppendResult(interp, "vo_center: bad Z value - ", argv[3], "\n", (char *)0);
00607                                 return TCL_ERROR;
00608                         }
00609                 }
00610 
00611                 vo_center(vop, interp, center);
00612                 return TCL_OK;
00613         }
00614 
00615  bad:
00616         /* compose error message */
00617         bu_vls_init(&vls);
00618         bu_vls_printf(&vls, "helplib_alias vo_center %s", argv[0]);
00619         Tcl_Eval(interp, bu_vls_addr(&vls));
00620         bu_vls_free(&vls);
00621 
00622         return TCL_ERROR;
00623 }
00624 
00625 /*
00626  * Get or set the view center.
00627  *
00628  * Usage:
00629  *        procname
00630  */
00631 static int
00632 vo_center_tcl(ClientData        clientData,
00633               Tcl_Interp        *interp,
00634               int               argc,
00635               char              **argv)
00636 {
00637         struct view_obj *vop = (struct view_obj *)clientData;
00638 
00639         return vo_center_cmd(vop, interp, argc-1, argv+1);
00640 }
00641 
00642 int
00643 vo_model2view_cmd(struct view_obj       *vop,
00644                   Tcl_Interp            *interp,
00645                   int                   argc,
00646                   char                  **argv)
00647 {
00648         struct bu_vls vls;
00649 
00650         if (argc == 1) {
00651                 bu_vls_init(&vls);
00652                 bn_encode_mat(&vls, vop->vo_model2view);
00653                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00654                 bu_vls_free(&vls);
00655 
00656                 return TCL_OK;
00657         }
00658 
00659         /* compose error message */
00660         bu_vls_init(&vls);
00661         bu_vls_printf(&vls, "helplib_alias vo_model2view %s", argv[0]);
00662         Tcl_Eval(interp, bu_vls_addr(&vls));
00663         bu_vls_free(&vls);
00664 
00665         return TCL_ERROR;
00666 }
00667 
00668 /*
00669  * Get the model2view matrix.
00670  *
00671  * Usage:
00672  *        procname
00673  */
00674 static int
00675 vo_model2view_tcl(ClientData    clientData,
00676                   Tcl_Interp    *interp,
00677                   int           argc,
00678                   char          **argv)
00679 {
00680         struct view_obj *vop = (struct view_obj *)clientData;
00681 
00682         return vo_model2view_cmd(vop, interp, argc-1, argv+1);
00683 }
00684 
00685 int
00686 vo_pmodel2view_cmd(struct view_obj      *vop,
00687                    Tcl_Interp           *interp,
00688                    int                  argc,
00689                    char                 **argv)
00690 {
00691         struct bu_vls vls;
00692 
00693         if (argc == 1) {
00694                 bu_vls_init(&vls);
00695                 bn_encode_mat(&vls, vop->vo_pmodel2view);
00696                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00697                 bu_vls_free(&vls);
00698 
00699                 return TCL_OK;
00700         }
00701 
00702         /* compose error message */
00703         bu_vls_init(&vls);
00704         bu_vls_printf(&vls, "helplib_alias vo_pmodel2view %s", argv[0]);
00705         Tcl_Eval(interp, bu_vls_addr(&vls));
00706         bu_vls_free(&vls);
00707 
00708         return TCL_ERROR;
00709 }
00710 
00711 /*
00712  * Get the pmodel2view matrix.
00713  *
00714  * Usage:
00715  *        procname pmodel2view
00716  */
00717 static int
00718 vo_pmodel2view_tcl(ClientData   clientData,
00719                    Tcl_Interp   *interp,
00720                    int          argc,
00721                    char         **argv)
00722 {
00723         struct view_obj *vop = (struct view_obj *)clientData;
00724 
00725         return vo_pmodel2view_cmd(vop, interp, argc-1, argv+1);
00726 }
00727 
00728 int
00729 vo_view2model_cmd(struct view_obj       *vop,
00730                   Tcl_Interp            *interp,
00731                   int                   argc,
00732                   char                  **argv)
00733 {
00734         struct bu_vls vls;
00735 
00736         if (argc == 1) {
00737                 bu_vls_init(&vls);
00738                 bn_encode_mat(&vls, vop->vo_view2model);
00739                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00740                 bu_vls_free(&vls);
00741 
00742                 return TCL_OK;
00743         }
00744 
00745         /* compose error message */
00746         bu_vls_init(&vls);
00747         bu_vls_printf(&vls, "helplib_alias vo_view2model %s", argv[0]);
00748         Tcl_Eval(interp, bu_vls_addr(&vls));
00749         bu_vls_free(&vls);
00750 
00751         return TCL_ERROR;
00752 }
00753 
00754 /*
00755  * Usage:
00756  *        procname view2model
00757  */
00758 static int
00759 vo_view2model_tcl(ClientData    clientData,
00760                   Tcl_Interp    *interp,
00761                   int           argc,
00762                   char          **argv)
00763 {
00764         struct view_obj *vop = (struct view_obj *)clientData;
00765 
00766         return vo_view2model_cmd(vop, interp, argc-1, argv+1);
00767 }
00768 
00769 int
00770 vo_perspective_cmd(struct view_obj      *vop,
00771                    Tcl_Interp           *interp,
00772                    int                  argc,
00773                    char                 **argv)
00774 {
00775         struct bu_vls vls;
00776         fastf_t perspective;
00777 
00778         /* get the perspective angle */
00779         if (argc == 1) {
00780                 bu_vls_init(&vls);
00781                 bu_vls_printf(&vls, "%g", vop->vo_perspective);
00782                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00783                 bu_vls_free(&vls);
00784 
00785                 return TCL_OK;
00786         }
00787 
00788         /* set the perspective angle */
00789         if (argc == 2) {
00790                 if (sscanf(argv[1], "%lf", &perspective) != 1) {
00791                         Tcl_AppendResult(interp, "bad perspective angle - ",
00792                                          argv[1], (char *)NULL);
00793                         return TCL_ERROR;
00794                 }
00795 
00796                 vop->vo_perspective = perspective;
00797 
00798 #if 1
00799                 /* This way works, with reasonable Z-clipping */
00800                 vo_persp_mat(vop->vo_pmat, vop->vo_perspective,
00801                              1.0, 0.01, 1.0e10, 1.0);
00802 #else
00803                 vo_mike_persp_mat(vop->vo_pmat, vop->vo_eye_pos);
00804 #endif
00805                 vo_update(vop, interp, 1);
00806 
00807                 return TCL_OK;
00808         }
00809 
00810         /* Compose error message */
00811         bu_vls_init(&vls);
00812         bu_vls_printf(&vls, "helplib_alias vo_perspective %s", argv[0]);
00813         Tcl_Eval(interp, bu_vls_addr(&vls));
00814         bu_vls_free(&vls);
00815 
00816         return TCL_ERROR;
00817 }
00818 
00819 /*
00820  * Get/set the perspective angle.
00821  *
00822  * Usage:
00823  *        procname perspective [angle]
00824  */
00825 static int
00826 vo_perspective_tcl(ClientData   clientData,
00827                    Tcl_Interp   *interp,
00828                    int          argc,
00829                    char         **argv)
00830 {
00831         struct view_obj *vop = (struct view_obj *)clientData;
00832 
00833         return vo_perspective_cmd(vop, interp, argc-1, argv+1);
00834 }
00835 
00836 int
00837 vo_pmat_cmd(struct view_obj     *vop,
00838             Tcl_Interp          *interp,
00839             int                 argc,
00840             char                **argv)
00841 {
00842         struct bu_vls vls;
00843 
00844         if (argc == 1) {
00845                 bu_vls_init(&vls);
00846                 bn_encode_mat(&vls, vop->vo_pmat);
00847                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00848                 bu_vls_free(&vls);
00849 
00850                 return TCL_OK;
00851         }
00852 
00853         /* compose error message */
00854         bu_vls_init(&vls);
00855         bu_vls_printf(&vls, "helplib_alias vo_pmat %s", argv[0]);
00856         Tcl_Eval(interp, bu_vls_addr(&vls));
00857         bu_vls_free(&vls);
00858 
00859         return TCL_ERROR;
00860 }
00861 
00862 /*
00863  * Get the perspective matrix.
00864  *
00865  * Usage:
00866  *        procname pmat
00867  */
00868 static int
00869 vo_pmat_tcl(ClientData  clientData,
00870             Tcl_Interp  *interp,
00871             int         argc,
00872             char        **argv)
00873 {
00874         struct view_obj *vop = (struct view_obj *)clientData;
00875 
00876         return vo_pmat_cmd(vop, interp, argc-1, argv+1);
00877 }
00878 
00879 int
00880 vo_eye_cmd(struct view_obj      *vop,
00881            Tcl_Interp           *interp,
00882            int                  argc,
00883            char                 **argv)
00884 {
00885         point_t         eye_model;
00886         vect_t          xlate;
00887         vect_t          new_cent;
00888         struct bu_vls   vls;
00889 
00890         /* get eye */
00891         if (argc == 1) {
00892           point_t eye;
00893 
00894           /* calculate eye point */
00895           VSET(xlate, 0.0, 0.0, 1.0);
00896           MAT4X3PNT(eye, vop->vo_view2model, xlate);
00897           VSCALE(eye, eye, vop->vo_base2local);
00898 
00899           bu_vls_init(&vls);
00900           bn_encode_vect(&vls, eye);
00901           Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
00902           bu_vls_free(&vls);
00903 
00904           return TCL_OK;
00905         }
00906 
00907         if (argc != 2 && argc != 4)
00908                 goto bad;
00909 
00910         if (argc == 2) {
00911                 if (bn_decode_vect(eye_model, argv[1]) != 3)
00912                         goto bad;
00913         } else {
00914                 if (sscanf(argv[1], "%lf", &eye_model[X]) != 1) {
00915                         Tcl_AppendResult(interp, "vo_eye: bad X value - ", argv[1], "\n", (char *)0);
00916                         return TCL_ERROR;
00917                 }
00918 
00919                 if (sscanf(argv[2], "%lf", &eye_model[Y]) != 1) {
00920                         Tcl_AppendResult(interp, "vo_eye: bad Y value - ", argv[2], "\n", (char *)0);
00921                         return TCL_ERROR;
00922                 }
00923 
00924                 if (sscanf(argv[3], "%lf", &eye_model[Z]) != 1) {
00925                         Tcl_AppendResult(interp, "vo_eye: bad Z value - ", argv[3], "\n", (char *)0);
00926                         return TCL_ERROR;
00927                 }
00928         }
00929 
00930         VSCALE(eye_model, eye_model, vop->vo_local2base);
00931 
00932         /* First step:  put eye at view center (view 0,0,0) */
00933         MAT_DELTAS_VEC_NEG(vop->vo_center, eye_model);
00934         vo_update(vop, interp, 0);
00935 
00936         /*  Second step:  put eye at view 0,0,1.
00937          *  For eye to be at 0,0,1, the old 0,0,-1 needs to become 0,0,0.
00938          */
00939         VSET(xlate, 0.0, 0.0, -1.0);    /* correction factor */
00940         MAT4X3PNT(new_cent, vop->vo_view2model, xlate);
00941         MAT_DELTAS_VEC_NEG(vop->vo_center, new_cent);
00942         vo_update(vop, interp, 1);
00943 
00944         return TCL_OK;
00945 
00946  bad:
00947         bu_vls_init(&vls);
00948         bu_vls_printf(&vls, "helplib_alias vo_eye %s", argv[0]);
00949         Tcl_Eval(interp, bu_vls_addr(&vls));
00950         bu_vls_free(&vls);
00951         return TCL_ERROR;
00952 }
00953 
00954 /*
00955  * Get/set the eye point.
00956  *
00957  * Usage:
00958  *      procname eye [eye_point]
00959  */
00960 static int
00961 vo_eye_tcl(ClientData   clientData,
00962          Tcl_Interp     *interp,
00963          int            argc,
00964          char           **argv)
00965 {
00966         struct view_obj *vop = (struct view_obj *)clientData;
00967 
00968         return vo_eye_cmd(vop, interp, argc-1, argv+1);
00969 }
00970 
00971 int
00972 vo_eye_pos_cmd(struct view_obj  *vop,
00973                Tcl_Interp       *interp,
00974                int              argc,
00975                char             **argv)
00976 {
00977         vect_t          eye_pos;
00978         struct bu_vls   vls;
00979 
00980         if (argc != 2 && argc != 4)
00981                 goto bad;
00982 
00983         if (argc == 2) {
00984                 if (bn_decode_vect(eye_pos, argv[1]) != 3)
00985                         goto bad;
00986         } else {
00987                 if (sscanf(argv[1], "%lf", &eye_pos[X]) != 1) {
00988                         Tcl_AppendResult(interp, "vo_eye_pos: bad X value - ", argv[1], "\n", (char *)0);
00989                         return TCL_ERROR;
00990                 }
00991 
00992                 if (sscanf(argv[2], "%lf", &eye_pos[Y]) != 1) {
00993                         Tcl_AppendResult(interp, "vo_eye_pos: bad Y value - ", argv[2], "\n", (char *)0);
00994                         return TCL_ERROR;
00995                 }
00996 
00997                 if (sscanf(argv[3], "%lf", &eye_pos[Z]) != 1) {
00998                         Tcl_AppendResult(interp, "vo_eye_pos: bad Z value - ", argv[3], "\n", (char *)0);
00999                         return TCL_ERROR;
01000                 }
01001         }
01002 
01003         VSCALE(eye_pos, eye_pos, vop->vo_local2base);
01004         VMOVE(vop->vo_eye_pos, eye_pos);
01005 
01006         /* update perspective matrix */
01007         vo_mike_persp_mat(vop->vo_pmat, vop->vo_eye_pos);
01008 
01009         /* update all other view related matrices */
01010         vo_update(vop, interp, 1);
01011 
01012         return TCL_OK;
01013 
01014  bad:
01015         bu_vls_init(&vls);
01016         bu_vls_printf(&vls, "helplib_alias vo_eye_pos %s", argv[0]);
01017         Tcl_Eval(interp, bu_vls_addr(&vls));
01018         bu_vls_free(&vls);
01019         return TCL_ERROR;
01020 }
01021 
01022 /*
01023  * Set the eye position.
01024  *
01025  * Usage:
01026  *      procname eye_pos pos
01027  */
01028 static int
01029 vo_eye_pos_tcl(ClientData       clientData,
01030                Tcl_Interp       *interp,
01031                int              argc,
01032                char             **argv)
01033 {
01034         struct view_obj *vop = (struct view_obj *)clientData;
01035 
01036         return vo_eye_pos_cmd(vop, interp, argc-1, argv+1);
01037 }
01038 
01039 int
01040 vo_lookat_cmd(struct view_obj   *vop,
01041               Tcl_Interp        *interp,
01042               int               argc,
01043               char              **argv)
01044 {
01045         point_t look;
01046         point_t eye;
01047         point_t tmp;
01048         point_t new_center;
01049         vect_t dir;
01050         fastf_t new_az, new_el;
01051         struct bu_vls vls;
01052 
01053         if (argc != 2 && argc != 4)
01054                 goto bad;
01055 
01056         if (argc == 2) {
01057                 if (bn_decode_vect(look, argv[1]) != 3)
01058                         goto bad;
01059         } else {
01060                 if (sscanf(argv[1], "%lf", &look[X]) != 1) {
01061                         Tcl_AppendResult(interp, "vo_lookat: bad X value - ", argv[1], "\n", (char *)0);
01062                         return TCL_ERROR;
01063                 }
01064 
01065                 if (sscanf(argv[2], "%lf", &look[Y]) != 1) {
01066                         Tcl_AppendResult(interp, "vo_lookat: bad Y value - ", argv[2], "\n", (char *)0);
01067                         return TCL_ERROR;
01068                 }
01069 
01070                 if (sscanf(argv[3], "%lf", &look[Z]) != 1) {
01071                         Tcl_AppendResult(interp, "vo_lookat: bad Z value - ", argv[3], "\n", (char *)0);
01072                         return TCL_ERROR;
01073                 }
01074         }
01075 
01076         VSCALE(look, look, vop->vo_local2base);
01077 
01078         VSET(tmp, 0.0, 0.0, 1.0);
01079         MAT4X3PNT(eye, vop->vo_view2model, tmp);
01080 
01081         VSUB2(dir, eye, look);
01082         VUNITIZE(dir);
01083         bn_ae_vec(&new_az, &new_el, dir);
01084 
01085         VSET(vop->vo_aet, new_az, new_el, vop->vo_aet[Z]);
01086         vo_mat_aet(vop);
01087 
01088         VJOIN1(new_center, eye, -vop->vo_scale, dir);
01089         MAT_DELTAS_VEC_NEG(vop->vo_center, new_center);
01090 
01091         vo_update(vop, interp, 1);
01092 
01093         return TCL_OK;
01094 
01095  bad:
01096         bu_vls_init(&vls);
01097         bu_vls_printf(&vls, "helplib_alias vo_lookat %s", argv[0]);
01098         Tcl_Eval(interp, bu_vls_addr(&vls));
01099         bu_vls_free(&vls);
01100         return TCL_ERROR;
01101 }
01102 
01103 /*
01104  * Set look-at point.
01105  *
01106  * Usage:
01107  *      procname lookat lookat_point
01108  */
01109 static int
01110 vo_lookat_tcl(ClientData        clientData,
01111               Tcl_Interp        *interp,
01112               int               argc,
01113               char              **argv)
01114 {
01115         struct view_obj *vop = (struct view_obj *)clientData;
01116 
01117         return vo_lookat_cmd(vop, interp, argc-1, argv+1);
01118 }
01119 
01120 int
01121 vo_orientation_cmd(struct view_obj      *vop,
01122                    Tcl_Interp           *interp,
01123                    int                  argc,
01124                    char                 **argv)
01125 {
01126         quat_t          quat;
01127         struct bu_vls   vls;
01128 
01129         if (argc != 2 && argc != 5)
01130                 goto bad;
01131 
01132         if (argc == 2) {
01133                 if (bn_decode_quat(quat, argv[1]) != 4)
01134                         goto bad;
01135         } else {
01136                 int     i;
01137 
01138                 for (i = 1; i < 5; ++i)
01139                         if (sscanf(argv[i], "%lf", &quat[i-1]) != 1)
01140                                 goto bad;
01141         }
01142 
01143         quat_quat2mat(vop->vo_rotation, quat);
01144         vo_update(vop, interp, 1);
01145 
01146         return TCL_OK;
01147 
01148  bad:
01149         bu_vls_init(&vls);
01150         bu_vls_printf(&vls, "helplib_alias vo_orient %s", argv[0]);
01151         Tcl_Eval(interp, bu_vls_addr(&vls));
01152         bu_vls_free(&vls);
01153         return TCL_ERROR;
01154 }
01155 
01156 /*
01157  * Usage:
01158  *      procname orient quat
01159  */
01160 static int
01161 vo_orientation_tcl(ClientData   clientData,
01162                    Tcl_Interp   *interp,
01163                    int          argc,
01164                    char         **argv)
01165 {
01166         struct view_obj *vop = (struct view_obj *)clientData;
01167 
01168         return vo_orientation_cmd(vop, interp, argc-1, argv+1);
01169 }
01170 
01171 int
01172 vo_pov_cmd(struct view_obj      *vop,
01173            Tcl_Interp           *interp,
01174            int                  argc,
01175            char                 **argv)
01176 {
01177         vect_t          center;
01178         quat_t          quat;
01179         vect_t          eye_pos;
01180         fastf_t         scale;
01181         fastf_t         perspective;
01182 
01183         if (argc != 6) {
01184                 struct bu_vls   vls;
01185 
01186                 bu_vls_init(&vls);
01187                 bu_vls_printf(&vls, "helplib_alias vo_pov %s", argv[0]);
01188                 Tcl_Eval(interp, bu_vls_addr(&vls));
01189                 bu_vls_free(&vls);
01190                 return TCL_ERROR;
01191         }
01192 
01193         /***************** Get the arguments *******************/
01194 
01195         if (bn_decode_vect(center, argv[1]) != 3) {
01196                 Tcl_AppendResult(interp, "vo_pov: bad center - ", argv[1], "\n", (char *)0);
01197                 return TCL_ERROR;
01198         }
01199 
01200         if (bn_decode_quat(quat, argv[2]) != 4) {
01201                 Tcl_AppendResult(interp, "vo_pov: bad quat - ", argv[2], "\n", (char *)0);
01202                 return TCL_ERROR;
01203         }
01204 
01205         if (sscanf(argv[3], "%lf", &scale) != 1) {
01206                 Tcl_AppendResult(interp, "vo_pov: bad scale - ", argv[3], "\n", (char *)0);
01207                 return TCL_ERROR;
01208         }
01209 
01210         if (bn_decode_vect(eye_pos, argv[4]) != 3) {
01211                 Tcl_AppendResult(interp, "vo_pov: bad eye position - ", argv[4], "\n", (char *)0);
01212                 return TCL_ERROR;
01213         }
01214 
01215         if (sscanf(argv[5], "%lf", &perspective) != 1) {
01216                 Tcl_AppendResult(interp, "vo_pov: bad perspective - ", argv[5], "\n", (char *)0);
01217                 return TCL_ERROR;
01218         }
01219 
01220         /***************** Use the arguments *******************/
01221 
01222         VSCALE(center, center, vop->vo_local2base);
01223         MAT_DELTAS_VEC_NEG(vop->vo_center, center);
01224         quat_quat2mat(vop->vo_rotation, quat);
01225         vop->vo_scale = vop->vo_local2base * scale;
01226         VSCALE(eye_pos, eye_pos, vop->vo_local2base);
01227         VMOVE(vop->vo_eye_pos, eye_pos);
01228         vop->vo_perspective = perspective;
01229 
01230         vo_update(vop, interp, 1);
01231 
01232         return TCL_OK;
01233 }
01234 
01235 /*
01236  * Usage:
01237  *      procname pov center quat scale eye_pos perspective
01238  */
01239 static int
01240 vo_pov_tcl(ClientData   clientData,
01241          Tcl_Interp     *interp,
01242          int            argc,
01243          char           **argv)
01244 {
01245         struct view_obj *vop = (struct view_obj *)clientData;
01246 
01247         return vo_pov_cmd(vop, interp, argc-1, argv+1);
01248 }
01249 
01250 int
01251 vo_zoom(struct view_obj *vop,
01252         Tcl_Interp      *interp,
01253         fastf_t         sf)
01254 {
01255         if (sf < SMALL_FASTF || INFINITY < sf) {
01256                 Tcl_AppendResult(interp, "vo_zoom - scale factor out of range\n", (char *)0);
01257                 return TCL_ERROR;
01258         }
01259 
01260         vop->vo_scale /= sf;
01261         if (vop->vo_scale < RT_MINVIEWSCALE)
01262                 vop->vo_scale = RT_MINVIEWSCALE;
01263         vop->vo_size = 2.0 * vop->vo_scale;
01264         vop->vo_invSize = 1.0 / vop->vo_size;
01265         vo_update(vop, interp, 1);
01266 
01267         return TCL_OK;
01268 }
01269 
01270 int
01271 vo_zoom_cmd(struct view_obj     *vop,
01272             Tcl_Interp          *interp,
01273             int                 argc,
01274             char                **argv)
01275 {
01276         fastf_t sf;
01277 
01278         if (argc != 2) {
01279                 struct bu_vls vls;
01280 
01281                 bu_vls_init(&vls);
01282                 bu_vls_printf(&vls, "helplib_alias vo_zoom %s", argv[0]);
01283                 Tcl_Eval(interp, bu_vls_addr(&vls));
01284                 bu_vls_free(&vls);
01285 
01286                 return TCL_ERROR;
01287         }
01288 
01289         if (sscanf(argv[1], "%lf", &sf) != 1) {
01290                 Tcl_AppendResult(interp, "bad zoom value - ", argv[1], "\n", (char *)0);
01291                 return TCL_ERROR;
01292         }
01293 
01294         return vo_zoom(vop, interp, sf);
01295 }
01296 
01297 /*
01298  * Usage:
01299  *      procname zoom scale_factor
01300  */
01301 static int
01302 vo_zoom_tcl(ClientData  clientData,
01303             Tcl_Interp  *interp,
01304             int         argc,
01305             char        **argv)
01306 {
01307         struct view_obj *vop = (struct view_obj *)clientData;
01308 
01309         return vo_zoom_cmd(vop, interp, argc-1, argv+1);
01310 }
01311 
01312 int
01313 vo_units_cmd(struct view_obj    *vop,
01314              Tcl_Interp         *interp,
01315              int                argc,
01316              char               **argv)
01317 {
01318         struct bu_vls vls;
01319 
01320         /* get units */
01321         if (argc == 1) {
01322                 bu_vls_init(&vls);
01323                 bu_vls_printf(&vls, "%s", bu_units_string(vop->vo_local2base));
01324                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
01325                 bu_vls_free(&vls);
01326 
01327                 return TCL_OK;
01328         }
01329 
01330         /* set units */
01331         if (argc == 2) {
01332                 double uval;
01333 
01334                 if ((uval = bu_units_conversion(argv[1])) == 0) {
01335                         bu_vls_init(&vls);
01336                         bu_vls_printf(&vls, "unrecognized unit type - %s\n", argv[1]);
01337                         Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
01338                         bu_vls_free(&vls);
01339 
01340                         return TCL_ERROR;
01341                 }
01342 
01343                 vop->vo_local2base = uval;
01344                 vop->vo_base2local = 1.0 / vop->vo_local2base;
01345 
01346                 return TCL_OK;
01347         }
01348 
01349         bu_vls_init(&vls);
01350         bu_vls_printf(&vls, "helplib_alias vo_units %s", argv[0]);
01351         Tcl_Eval(interp, bu_vls_addr(&vls));
01352         bu_vls_free(&vls);
01353 
01354         return TCL_ERROR;
01355 }
01356 
01357 /*
01358  * Set/get local units.
01359  *
01360  * Usage:
01361  *      procname units [unit_spec]
01362  */
01363 static int
01364 vo_units_tcl(ClientData clientData,
01365              Tcl_Interp *interp,
01366              int        argc,
01367              char       **argv)
01368 {
01369         struct view_obj *vop = (struct view_obj *)clientData;
01370 
01371         return vo_units_cmd(vop, interp, argc-1, argv+1);
01372 }
01373 
01374 int
01375 vo_base2local_cmd(struct view_obj       *vop,
01376                   Tcl_Interp            *interp,
01377                   int                   argc,
01378                   char                  **argv)
01379 {
01380         struct bu_vls vls;
01381 
01382         bu_vls_init(&vls);
01383 
01384         if (argc != 1) {
01385                 bu_vls_printf(&vls, "helplib_alias vo_base2local %s", argv[0]);
01386                 Tcl_Eval(interp, bu_vls_addr(&vls));
01387                 bu_vls_free(&vls);
01388 
01389                 return TCL_ERROR;
01390         }
01391 
01392         bu_vls_printf(&vls, "%g", vop->vo_base2local);
01393         Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
01394         bu_vls_free(&vls);
01395 
01396         return TCL_OK;
01397 }
01398 
01399 /*
01400  * Get base2local conversion factor.
01401  *
01402  * Usage:
01403  *      procname base2local
01404  */
01405 static int
01406 vo_base2local_tcl(ClientData    clientData,
01407                   Tcl_Interp    *interp,
01408                   int           argc,
01409                   char          **argv)
01410 {
01411         struct view_obj *vop = (struct view_obj *)clientData;
01412 
01413         return vo_base2local_cmd(vop, interp, argc-1, argv+1);
01414 }
01415 
01416 int
01417 vo_local2base_cmd(struct view_obj       *vop,
01418                   Tcl_Interp            *interp,
01419                   int                   argc,
01420                   char                  **argv)
01421 {
01422         struct bu_vls vls;
01423 
01424         bu_vls_init(&vls);
01425 
01426         if (argc != 1) {
01427                 bu_vls_printf(&vls, "helplib_alias vo_local2base %s", argv[0]);
01428                 Tcl_Eval(interp, bu_vls_addr(&vls));
01429                 bu_vls_free(&vls);
01430 
01431                 return TCL_ERROR;
01432         }
01433 
01434         bu_vls_printf(&vls, "%g", vop->vo_local2base);
01435         Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
01436         bu_vls_free(&vls);
01437 
01438         return TCL_OK;
01439 }
01440 
01441 /*
01442  * Get local2base conversion factor.
01443  *
01444  * Usage:
01445  *      procname local2base
01446  */
01447 static int
01448 vo_local2base_tcl(ClientData    clientData,
01449                   Tcl_Interp    *interp,
01450                   int           argc,
01451                   char          **argv)
01452 {
01453         struct view_obj *vop = (struct view_obj *)clientData;
01454 
01455         return vo_local2base_cmd(vop, interp, argc-1, argv+1);
01456 }
01457 
01458 int
01459 vo_rot(struct view_obj  *vop,
01460        Tcl_Interp       *interp,
01461        char             coord,
01462        char             rotate_about,
01463        mat_t            rmat,
01464        int              (*func)())
01465 {
01466         mat_t temp1, temp2;
01467 
01468         if (func != (int (*)())0)
01469                 return (*func)(vop, interp, coord, rotate_about, rmat);
01470 
01471         switch (coord) {
01472         case 'm':
01473                 /* transform model rotations into view rotations */
01474                 bn_mat_inv(temp1, vop->vo_rotation);
01475                 bn_mat_mul(temp2, vop->vo_rotation, rmat);
01476                 bn_mat_mul(rmat, temp2, temp1);
01477                 break;
01478         case 'v':
01479         default:
01480                 break;
01481         }
01482 
01483         /* Calculate new view center */
01484         if (rotate_about != 'v') {
01485                 point_t         rot_pt;
01486                 point_t         new_origin;
01487                 mat_t           viewchg, viewchginv;
01488                 point_t         new_cent_view;
01489                 point_t         new_cent_model;
01490 
01491                 switch (rotate_about) {
01492                 case 'e':
01493                         VSET(rot_pt, 0.0, 0.0, 1.0);
01494                         break;
01495                 case 'k':
01496                         MAT4X3PNT(rot_pt, vop->vo_model2view, vop->vo_keypoint);
01497                         break;
01498                 case 'm':
01499                         /* rotate around model center (0,0,0) */
01500                         VSET(new_origin, 0.0, 0.0, 0.0);
01501                         MAT4X3PNT(rot_pt, vop->vo_model2view, new_origin);
01502                         break;
01503                 default:
01504                         {
01505                                 struct bu_vls vls;
01506 
01507                                 bu_vls_init(&vls);
01508                                 bu_vls_printf(&vls, "vo_rot_tcl: bad rotate_about - %c\n", rotate_about);
01509                                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)0);
01510                                 bu_vls_free(&vls);
01511                                 return TCL_ERROR;
01512                         }
01513                 }
01514 
01515                 bn_mat_xform_about_pt(viewchg, rmat, rot_pt);
01516                 bn_mat_inv(viewchginv, viewchg);
01517 
01518                 /* Convert origin in new (viewchg) coords back to old view coords */
01519                 VSET(new_origin, 0.0, 0.0, 0.0);
01520                 MAT4X3PNT(new_cent_view, viewchginv, new_origin);
01521                 MAT4X3PNT(new_cent_model, vop->vo_view2model, new_cent_view);
01522                 MAT_DELTAS_VEC_NEG(vop->vo_center, new_cent_model);
01523         }
01524 
01525         /* pure rotation */
01526         bn_mat_mul2(rmat, vop->vo_rotation);
01527         vo_update(vop, interp, 1);
01528 
01529         return TCL_OK;
01530 }
01531 
01532 int
01533 vo_rot_cmd(struct view_obj      *vop,
01534            Tcl_Interp           *interp,
01535            int                  argc,
01536            char                 **argv,
01537            int                  (*func)())
01538 {
01539         vect_t          rvec;
01540         mat_t           rmat;
01541         char            coord = vop->vo_coord;
01542         struct bu_vls   vls;
01543 
01544         if (argc < 2 || 5 < argc)
01545                 goto bad;
01546 
01547         /* process coord flag */
01548         if (argv[1][0] == '-' && (argv[1][1] == 'v' || argv[1][1] == 'm') && argv[1][2] == '\0') {
01549                 coord = argv[1][1];
01550                 --argc;
01551                 ++argv;
01552         }
01553 
01554         if (argc != 2 && argc != 4)
01555                 goto bad;
01556 
01557         if (argc == 2) {
01558                 if (bn_decode_vect(rvec, argv[1]) != 3)
01559                         goto bad;
01560         } else {
01561                 if (sscanf(argv[1], "%lf", &rvec[X]) != 1) {
01562                         Tcl_AppendResult(interp, "vo_rot: bad X value - ", argv[1], "\n", (char *)0);
01563                         return TCL_ERROR;
01564                 }
01565 
01566                 if (sscanf(argv[2], "%lf", &rvec[Y]) != 1) {
01567                         Tcl_AppendResult(interp, "vo_rot: bad Y value - ", argv[2], "\n", (char *)0);
01568                         return TCL_ERROR;
01569                 }
01570 
01571                 if (sscanf(argv[3], "%lf", &rvec[Z]) != 1) {
01572                         Tcl_AppendResult(interp, "vo_rot: bad Z value - ", argv[3], "\n", (char *)0);
01573                         return TCL_ERROR;
01574                 }
01575         }
01576 
01577         VSCALE(rvec, rvec, -1.0);
01578         bn_mat_angles(rmat, rvec[X], rvec[Y], rvec[Z]);
01579 
01580         return vo_rot(vop, interp, coord, vop->vo_rotate_about, rmat, func);
01581 
01582  bad:
01583         bu_vls_init(&vls);
01584         bu_vls_printf(&vls, "helplib_alias vo_rot %s", argv[0]);
01585         Tcl_Eval(interp, bu_vls_addr(&vls));
01586         bu_vls_free(&vls);
01587 
01588         return TCL_ERROR;
01589 }
01590 
01591 /*
01592  * Rotate the view according to xyz.
01593  *
01594  * Usage:
01595  *      procname rot [-v|-m] xyz
01596  */
01597 static int
01598 vo_rot_tcl(ClientData   clientData,
01599            Tcl_Interp   *interp,
01600            int          argc,
01601            char         **argv)
01602 {
01603         struct view_obj *vop = (struct view_obj *)clientData;
01604 
01605         return vo_rot_cmd(vop, interp, argc-1, argv+1, (int (*)())0);
01606 }
01607 
01608 int
01609 vo_tra(struct view_obj  *vop,
01610        Tcl_Interp       *interp,
01611        char             coord,
01612        vect_t           tvec,
01613        int              (*func)())
01614 {
01615         point_t delta;
01616         point_t work;
01617         point_t vc, nvc;
01618 
01619         if (func != (int (*)())0)
01620                 return (*func)(vop, interp, coord, tvec);
01621 
01622         switch (coord) {
01623         case 'm':
01624                 VSCALE(delta, tvec, vop->vo_local2base);
01625                 MAT_DELTAS_GET_NEG(vc, vop->vo_center);
01626                 break;
01627         case 'v':
01628         default:
01629                 VSCALE(tvec, tvec, -2.0*vop->vo_local2base*vop->vo_invSize);
01630                 MAT4X3PNT(work, vop->vo_view2model, tvec);
01631                 MAT_DELTAS_GET_NEG(vc, vop->vo_center);
01632                 VSUB2(delta, work, vc);
01633                 break;
01634         }
01635 
01636         VSUB2(nvc, vc, delta);
01637         MAT_DELTAS_VEC_NEG(vop->vo_center, nvc);
01638         vo_update(vop, interp, 1);
01639 
01640         return TCL_OK;
01641 }
01642 
01643 int
01644 vo_tra_cmd(struct view_obj      *vop,
01645            Tcl_Interp           *interp,
01646            int                  argc,
01647            char                 **argv,
01648            int                  (*func)())
01649 {
01650         vect_t          tvec;
01651         char            coord = vop->vo_coord;
01652         struct bu_vls   vls;
01653 
01654         if (argc < 2 || 5 < argc)
01655                 goto bad;
01656 
01657         /* process coord flag */
01658         if (argv[1][0] == '-' && (argv[1][1] == 'v' || argv[1][1] == 'm') && argv[1][2] == '\0') {
01659                 coord = argv[1][1];
01660                 --argc;
01661                 ++argv;
01662         }
01663 
01664         if (argc != 2 && argc != 4)
01665                 goto bad;
01666 
01667         if (argc == 2) {
01668                 if (bn_decode_vect(tvec, argv[1]) != 3)
01669                         goto bad;
01670         } else {
01671                 if (sscanf(argv[1], "%lf", &tvec[X]) != 1) {
01672                         Tcl_AppendResult(interp, "vo_tra: bad X value - ", argv[1], "\n", (char *)0);
01673                         return TCL_ERROR;
01674                 }
01675 
01676                 if (sscanf(argv[2], "%lf", &tvec[Y]) != 1) {
01677                         Tcl_AppendResult(interp, "vo_tra: bad Y value - ", argv[2], "\n", (char *)0);
01678                         return TCL_ERROR;
01679                 }
01680 
01681                 if (sscanf(argv[3], "%lf", &tvec[Z]) != 1) {
01682                         Tcl_AppendResult(interp, "vo_tra: bad Z value - ", argv[3], "\n", (char *)0);
01683                         return TCL_ERROR;
01684                 }
01685         }
01686 
01687         return vo_tra(vop, interp, coord, tvec, func);
01688 
01689  bad:
01690         bu_vls_init(&vls);
01691         bu_vls_printf(&vls, "helplib_alias vo_tra %s", argv[0]);
01692         Tcl_Eval(interp, bu_vls_addr(&vls));
01693         bu_vls_free(&vls);
01694 
01695         return TCL_ERROR;
01696 }
01697 
01698 /*
01699  * Translate the view according to xyz.
01700  *
01701  * Usage:
01702  *      procname tra [-v|-m] xyz
01703  */
01704 static int
01705 vo_tra_tcl(ClientData   clientData,
01706          Tcl_Interp     *interp,
01707          int            argc,
01708          char           **argv)
01709 {
01710         struct view_obj *vop = (struct view_obj *)clientData;
01711 
01712         return vo_tra_cmd(vop, interp, argc-1, argv+1, (int (*)())0);
01713 }
01714 
01715 int
01716 vo_slew(struct view_obj *vop,
01717         Tcl_Interp      *interp,
01718         vect_t          svec)
01719 {
01720         point_t model_center;
01721 
01722         MAT4X3PNT(model_center, vop->vo_view2model, svec);
01723         MAT_DELTAS_VEC_NEG(vop->vo_center, model_center);
01724         vo_update(vop, interp, 1);
01725 
01726         return TCL_OK;
01727 }
01728 
01729 int
01730 vo_slew_cmd(struct view_obj     *vop,
01731             Tcl_Interp          *interp,
01732             int                 argc,
01733             char                **argv)
01734 {
01735         struct bu_vls   vls;
01736         vect_t          svec;
01737 
01738         if (argc == 2) {
01739                 int     n;
01740 
01741                 if ((n = bn_decode_vect(svec, argv[1])) != 3) {
01742                         if (n != 2)
01743                                 goto bad;
01744 
01745                         svec[Z] = 0.0;
01746                 }
01747 
01748                 return vo_slew(vop, interp, svec);
01749         }
01750 
01751         if (argc == 3 || argc == 4) {
01752                 if (sscanf(argv[1], "%lf", &svec[X]) != 1) {
01753                         Tcl_AppendResult(interp, "vo_slew: bad X value - ", argv[1], "\n", (char *)0);
01754                         return TCL_ERROR;
01755                 }
01756 
01757                 if (sscanf(argv[2], "%lf", &svec[Y]) != 1) {
01758                         Tcl_AppendResult(interp, "vo_slew: bad Y value - ", argv[2], "\n", (char *)0);
01759                         return TCL_ERROR;
01760                 }
01761 
01762                 if (argc == 4) {
01763                         if (sscanf(argv[3], "%lf", &svec[Z]) != 1) {
01764                                 Tcl_AppendResult(interp, "vo_slew: bad Z value - ", argv[3], "\n", (char *)0);
01765                                 return TCL_ERROR;
01766                         }
01767                 } else
01768                         svec[Z] = 0.0;
01769 
01770                 return vo_slew(vop, interp, svec);
01771         }
01772 
01773  bad:
01774         bu_vls_init(&vls);
01775         bu_vls_printf(&vls, "helplib_alias vo_slew %s", argv[0]);
01776         Tcl_Eval(interp, bu_vls_addr(&vls));
01777         bu_vls_free(&vls);
01778 
01779         return TCL_ERROR;
01780 }
01781 
01782 /*
01783  * Make xyz the new view center.
01784  *
01785  * Usage:
01786  *      procname slew xy
01787  */
01788 static int
01789 vo_slew_tcl(ClientData  clientData,
01790          Tcl_Interp     *interp,
01791          int            argc,
01792          char           **argv)
01793 {
01794         struct view_obj *vop = (struct view_obj *)clientData;
01795 
01796         return vo_slew_cmd(vop, interp, argc-1, argv+1);
01797 }
01798 
01799 int
01800 vo_observer_cmd(struct view_obj *vop,
01801                 Tcl_Interp      *interp,
01802                 int             argc,
01803                 char            **argv)
01804 {
01805         if (argc < 2) {
01806                 struct bu_vls vls;
01807 
01808                 /* return help message */
01809                 bu_vls_init(&vls);
01810                 bu_vls_printf(&vls, "helplib_alias vo_observer %s", argv[0]);
01811                 Tcl_Eval(interp, bu_vls_addr(&vls));
01812                 bu_vls_free(&vls);
01813                 return TCL_ERROR;
01814         }
01815 
01816         return bu_cmd((ClientData)&vop->vo_observers,
01817                       interp, argc - 1, argv + 1, bu_observer_cmds, 0);
01818 }
01819 
01820 /*
01821  * Attach/detach observers to/from list.
01822  *
01823  * Usage:
01824  *        procname observer cmd [args]
01825  */
01826 static int
01827 vo_observer_tcl(ClientData      clientData,
01828                 Tcl_Interp      *interp,
01829                 int             argc,
01830                 char            **argv)
01831 {
01832         struct view_obj *vop = (struct view_obj *)clientData;
01833 
01834         return vo_observer_cmd(vop, interp, argc-1, argv+1);
01835 }
01836 
01837 int
01838 vo_coord_cmd(struct view_obj    *vop,
01839              Tcl_Interp         *interp,
01840              int                argc,
01841              char               **argv)
01842 {
01843         struct bu_vls vls;
01844 
01845         /* Get coord */
01846         if (argc == 1) {
01847                 bu_vls_init(&vls);
01848                 bu_vls_printf(&vls, "%c", vop->vo_coord);
01849                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)0);
01850                 bu_vls_free(&vls);
01851                 return TCL_OK;
01852         }
01853 
01854         /* Set coord */
01855         if (argc == 2) {
01856                 switch (argv[1][0]) {
01857                 case 'm':
01858                 case 'v':
01859                         vop->vo_coord = argv[1][0];
01860                         return TCL_OK;
01861                 }
01862         }
01863 
01864         /* return help message */
01865         bu_vls_init(&vls);
01866         bu_vls_printf(&vls, "helplib_alias vo_coord %s", argv[0]);
01867         Tcl_Eval(interp, bu_vls_addr(&vls));
01868         bu_vls_free(&vls);
01869         return TCL_ERROR;
01870 }
01871 
01872 /*
01873  * Get/set the coordinate system.
01874  *
01875  * Usage:
01876  *        procname coord [v|m]
01877  */
01878 static int
01879 vo_coord_tcl(ClientData clientData,
01880              Tcl_Interp *interp,
01881              int        argc,
01882              char       **argv)
01883 {
01884         struct view_obj *vop = (struct view_obj *)clientData;
01885 
01886         return vo_coord_cmd(vop, interp, argc-1, argv+1);
01887 }
01888 
01889 int
01890 vo_rotate_about_cmd(struct view_obj     *vop,
01891                     Tcl_Interp          *interp,
01892                     int                 argc,
01893                     char                **argv)
01894 {
01895         struct bu_vls vls;
01896 
01897         /* Get rotate_about */
01898         if (argc == 1) {
01899                 bu_vls_init(&vls);
01900                 bu_vls_printf(&vls, "%c", vop->vo_rotate_about);
01901                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)0);
01902                 bu_vls_free(&vls);
01903                 return TCL_OK;
01904         }
01905 
01906         /* Set rotate_about */
01907         if (argc == 2 && argv[1][1] == '\0') {
01908                 switch (argv[1][0]) {
01909                 case 'e':
01910                 case 'k':
01911                 case 'm':
01912                 case 'v':
01913                         vop->vo_rotate_about = argv[1][0];
01914                         return TCL_OK;
01915                 }
01916         }
01917 
01918         /* return help message */
01919         bu_vls_init(&vls);
01920         bu_vls_printf(&vls, "helplib_alias vo_rotate_about %s", argv[0]);
01921         Tcl_Eval(interp, bu_vls_addr(&vls));
01922         bu_vls_free(&vls);
01923         return TCL_ERROR;
01924 }
01925 
01926 /*
01927  * Get/set the rotate about point.
01928  *
01929  * Usage:
01930  *        procname rotate_about [e|k|m|v]
01931  */
01932 static int
01933 vo_rotate_about_tcl(ClientData  clientData,
01934          Tcl_Interp     *interp,
01935          int            argc,
01936          char           **argv)
01937 {
01938         struct view_obj *vop = (struct view_obj *)clientData;
01939 
01940         return vo_rotate_about_cmd(vop, interp, argc-1, argv+1);
01941 }
01942 
01943 int
01944 vo_keypoint_cmd(struct view_obj *vop,
01945                 Tcl_Interp      *interp,
01946                 int             argc,
01947                 char            **argv)
01948 {
01949         struct bu_vls   vls;
01950         vect_t          tvec;
01951 
01952         /* Get the keypoint */
01953         if (argc == 1) {
01954                 bu_vls_init(&vls);
01955                 VSCALE(tvec, vop->vo_keypoint, vop->vo_base2local);
01956                 bn_encode_vect(&vls, tvec);
01957                 Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)0);
01958                 bu_vls_free(&vls);
01959                 return TCL_OK;
01960         }
01961 
01962         /* Set the keypoint */
01963         if (argc == 2) {
01964                 if (bn_decode_vect(tvec, argv[1]) != 3)
01965                         goto bad;
01966         } else if (argc == 4) {
01967                 if (sscanf(argv[1], "%lf", &tvec[X]) != 1) {
01968                         Tcl_AppendResult(interp, "vo_keypoint: bad X value - ", argv[1], "\n", (char *)0);
01969                         return TCL_ERROR;
01970                 }
01971 
01972                 if (sscanf(argv[2], "%lf", &tvec[Y]) != 1) {
01973                         Tcl_AppendResult(interp, "vo_keypoint: bad Y value - ", argv[2], "\n", (char *)0);
01974                         return TCL_ERROR;
01975                 }
01976 
01977                 if (sscanf(argv[3], "%lf", &tvec[Z]) != 1) {
01978                         Tcl_AppendResult(interp, "vo_keypoint: bad Z value - ", argv[3], "\n", (char *)0);
01979                         return TCL_ERROR;
01980                 }
01981         }
01982 
01983         VSCALE(vop->vo_keypoint, tvec, vop->vo_local2base);
01984         return TCL_OK;
01985 
01986  bad:
01987         bu_vls_init(&vls);
01988         bu_vls_printf(&vls, "helplib_alias vo_keypoint %s", argv[0]);
01989         Tcl_Eval(interp, bu_vls_addr(&vls));
01990         bu_vls_free(&vls);
01991         return TCL_ERROR;
01992 }
01993 
01994 /*
01995  * Get/set the keypoint.
01996  *
01997  * Usage:
01998  *        procname keypoint [point]
01999  */
02000 static int
02001 vo_keypoint_tcl(ClientData      clientData,
02002                 Tcl_Interp      *interp,
02003                 int             argc,
02004                 char            **argv)
02005 {
02006         struct view_obj *vop = (struct view_obj *)clientData;
02007 
02008         return vo_keypoint_cmd(vop, interp, argc-1, argv+1);
02009 }
02010 
02011 /*
02012  *                      V O _ S E T V I E W
02013  *
02014  * Set the view.  Angles are DOUBLES, in degrees.
02015  *
02016  * Given that viewvec = scale . rotate . (xlate to view center) . modelvec,
02017  * we just replace the rotation matrix.
02018  * (This assumes rotation around the view center).
02019  */
02020 void
02021 vo_setview(struct view_obj      *vop,
02022            Tcl_Interp           *interp,
02023            vect_t               rvec)           /* DOUBLE angles, in degrees */
02024 {
02025         bn_mat_angles(vop->vo_rotation, rvec[X], rvec[Y], rvec[Z]);
02026         vo_update(vop, interp, 1);
02027 }
02028 
02029 int
02030 vo_setview_cmd(struct view_obj  *vop,
02031                Tcl_Interp       *interp,
02032                int              argc,
02033                char             **argv)
02034 {
02035         vect_t          rvec;
02036         struct bu_vls   vls;
02037 
02038         if (argc != 2 && argc != 4)
02039                 goto bad;
02040 
02041         if (argc == 2) {
02042                 if (bn_decode_vect(rvec, argv[1]) != 3)
02043                         goto bad;
02044         } else {
02045                 if (sscanf(argv[1], "%lf", &rvec[X]) != 1) {
02046                         Tcl_AppendResult(interp, "vo_setview_cmd: bad X value - ", argv[1], "\n", (char *)0);
02047                         return TCL_ERROR;
02048                 }
02049 
02050                 if (sscanf(argv[2], "%lf", &rvec[Y]) != 1) {
02051                         Tcl_AppendResult(interp, "vo_setview_cmd: bad Y value - ", argv[2], "\n", (char *)0);
02052                         return TCL_ERROR;
02053                 }
02054 
02055                 if (sscanf(argv[3], "%lf", &rvec[Z]) != 1) {
02056                         Tcl_AppendResult(interp, "vo_setview_cmd: bad Z value - ", argv[3], "\n", (char *)0);
02057                         return TCL_ERROR;
02058                 }
02059         }
02060 
02061         vo_setview(vop, interp, rvec);
02062         return TCL_OK;
02063 
02064  bad:
02065         bu_vls_init(&vls);
02066         bu_vls_printf(&vls, "helplib_alias vo_setview %s", argv[0]);
02067         Tcl_Eval(interp, bu_vls_addr(&vls));
02068         bu_vls_free(&vls);
02069         return TCL_ERROR;
02070 }
02071 
02072 /*
02073  * Usage:
02074  *        procname setview x y z
02075  */
02076 static int
02077 vo_setview_tcl(ClientData       clientData,
02078                Tcl_Interp       *interp,
02079                int              argc,
02080                char             **argv)
02081 {
02082         struct view_obj *vop = (struct view_obj *)clientData;
02083 
02084         return vo_setview_cmd(vop, interp, argc-1, argv+1);
02085 }
02086 
02087 int
02088 vo_arot_cmd(struct view_obj     *vop,
02089             Tcl_Interp          *interp,
02090             int                 argc,
02091             char                **argv,
02092             int                 (*func)())
02093 {
02094         mat_t newrot;
02095         point_t pt;
02096         vect_t axis;
02097         fastf_t angle;
02098 
02099         if (argc != 5) {
02100                 struct bu_vls vls;
02101 
02102                 bu_vls_init(&vls);
02103                 bu_vls_printf(&vls, "helplib_alias vo_arot %s", argv[0]);
02104                 Tcl_Eval(interp, bu_vls_addr(&vls));
02105                 bu_vls_free(&vls);
02106                 return TCL_ERROR;
02107         }
02108 
02109         if (sscanf(argv[1], "%lf", &axis[X]) != 1) {
02110                 Tcl_AppendResult(interp, "vo_arot: bad X value - ", argv[1], "\n", (char *)0);
02111                 return TCL_ERROR;
02112         }
02113 
02114         if (sscanf(argv[2], "%lf", &axis[Y]) != 1) {
02115                 Tcl_AppendResult(interp, "vo_arot: bad Y value - ", argv[2], "\n", (char *)0);
02116                 return TCL_ERROR;
02117         }
02118 
02119         if (sscanf(argv[3], "%lf", &axis[Z]) != 1) {
02120                 Tcl_AppendResult(interp, "vo_arot: bad Z value - ", argv[3], "\n", (char *)0);
02121                 return TCL_ERROR;
02122         }
02123 
02124         if (sscanf(argv[4], "%lf", &angle) != 1) {
02125                 Tcl_AppendResult(interp, "vo_arot: bad angle - ", argv[4], "\n", (char *)0);
02126                 return TCL_ERROR;
02127         }
02128 
02129         VSETALL(pt, 0.0);
02130         VUNITIZE(axis);
02131 
02132         bn_mat_arb_rot(newrot, pt, axis, angle*bn_degtorad);
02133 
02134         return vo_rot(vop, interp, vop->vo_coord, vop->vo_rotate_about, newrot, func);
02135 }
02136 
02137 /*
02138  * Usage:
02139  *        procname arot x y z angle
02140  */
02141 static int
02142 vo_arot_tcl(ClientData  clientData,
02143             Tcl_Interp  *interp,
02144             int         argc,
02145             char        **argv)
02146 {
02147         struct view_obj *vop = (struct view_obj *)clientData;
02148 
02149         return vo_arot_cmd(vop, interp, argc-1, argv+1, (int (*)())0);
02150 }
02151 
02152 int
02153 vo_vrot_cmd(struct view_obj     *vop,
02154             Tcl_Interp          *interp,
02155             int                 argc,
02156             char                **argv)
02157 {
02158         vect_t          rvec;
02159         mat_t           rmat;
02160         struct bu_vls   vls;
02161 
02162         if (argc != 2 && argc != 4)
02163                 goto bad;
02164 
02165         if (argc == 2) {
02166                 if (bn_decode_vect(rvec, argv[1]) != 3)
02167                         goto bad;
02168         } else {
02169                 if (sscanf(argv[1], "%lf", &rvec[X]) < 1) {
02170                         Tcl_AppendResult(interp, "vo_vrot: bad X value - ", argv[1], "\n", (char *)0);
02171                         return TCL_ERROR;
02172                 }
02173 
02174                 if (sscanf(argv[2], "%lf", &rvec[Y]) < 1) {
02175                         Tcl_AppendResult(interp, "vo_vrot: bad Y value - ", argv[2], "\n", (char *)0);
02176                         return TCL_ERROR;
02177                 }
02178 
02179                 if (sscanf(argv[3], "%lf", &rvec[Z]) < 1) {
02180                         Tcl_AppendResult(interp, "vo_vrot: bad Z value - ", argv[3], "\n", (char *)0);
02181                         return TCL_ERROR;
02182                 }
02183         }
02184 
02185         VSCALE(rvec, rvec, -1.0);
02186         bn_mat_angles(rmat, rvec[X], rvec[Y], rvec[Z]);
02187 
02188         return vo_rot(vop, interp, 'v', vop->vo_rotate_about, rmat, (int (*)())0);
02189 
02190 bad:
02191         bu_vls_init(&vls);
02192         bu_vls_printf(&vls, "helplib_alias vo_vrot %s", argv[0]);
02193         Tcl_Eval(interp, bu_vls_addr(&vls));
02194         bu_vls_free(&vls);
02195         return TCL_ERROR;
02196 }
02197 
02198 /*
02199  * Usage:
02200  *        procname vrot x y z
02201  */
02202 static int
02203 vo_vrot_tcl(ClientData  clientData,
02204             Tcl_Interp  *interp,
02205             int         argc,
02206             char        **argv)
02207 {
02208         struct view_obj *vop = (struct view_obj *)clientData;
02209 
02210         return vo_vrot_cmd(vop, interp, argc-1, argv+1);
02211 }
02212 
02213 int
02214 vo_mrot_cmd(struct view_obj     *vop,
02215             Tcl_Interp          *interp,
02216             int                 argc,
02217             char                **argv,
02218             int                 (*func)())
02219 {
02220         vect_t          rvec;
02221         mat_t           rmat;
02222         struct bu_vls   vls;
02223 
02224         if (argc != 2 && argc != 4)
02225                 goto bad;
02226 
02227         if (argc == 2) {
02228                 if (bn_decode_vect(rvec, argv[1]) != 3)
02229                         goto bad;
02230         } else {
02231                 if (sscanf(argv[1], "%lf", &rvec[X]) < 1) {
02232                         Tcl_AppendResult(interp, "vo_mrot: bad X value - ", argv[1], "\n", (char *)0);
02233                         return TCL_ERROR;
02234                 }
02235 
02236                 if (sscanf(argv[2], "%lf", &rvec[Y]) < 1) {
02237                         Tcl_AppendResult(interp, "vo_mrot: bad Y value - ", argv[2], "\n", (char *)0);
02238                         return TCL_ERROR;
02239                 }
02240 
02241                 if (sscanf(argv[3], "%lf", &rvec[Z]) < 1) {
02242                         Tcl_AppendResult(interp, "vo_mrot: bad Z value - ", argv[3], "\n", (char *)0);
02243                         return TCL_ERROR;
02244                 }
02245         }
02246 
02247         VSCALE(rvec, rvec, -1.0);
02248         bn_mat_angles(rmat, rvec[X], rvec[Y], rvec[Z]);
02249 
02250         return vo_rot(vop, interp, 'm', vop->vo_rotate_about, rmat, func);
02251 
02252  bad:
02253         bu_vls_init(&vls);
02254         bu_vls_printf(&vls, "helplib_alias vo_mrot %s", argv[0]);
02255         Tcl_Eval(interp, bu_vls_addr(&vls));
02256         bu_vls_free(&vls);
02257         return TCL_ERROR;
02258 }
02259 
02260 /*
02261  * Usage:
02262  *        procname mrot x y z
02263  */
02264 static int
02265 vo_mrot_tcl(ClientData  clientData,
02266             Tcl_Interp  *interp,
02267             int         argc,
02268             char        **argv)
02269 {
02270         struct view_obj *vop = (struct view_obj *)clientData;
02271 
02272         return vo_mrot_cmd(vop, interp, argc-1, argv+1, (int (*)())0);
02273 }
02274 
02275 int
02276 vo_mrotPoint_cmd(struct view_obj        *vop,
02277                        Tcl_Interp       *interp,
02278                        int              argc,
02279                        char             **argv)
02280 {
02281     struct bu_vls       vls;
02282 
02283     /* Parse the incoming point */
02284     if (argc == 2 || argc == 4) {
02285         point_t viewPt;
02286         point_t modelPt;
02287         mat_t invRot;
02288 
02289         if (argc == 2) {
02290             if (bn_decode_vect(viewPt, argv[1]) != 3)
02291                 goto bad;
02292         } else {
02293             if (sscanf(argv[1], "%lf", &viewPt[X]) != 1) {
02294                 Tcl_AppendResult(interp,
02295                                  "vo_mrotPoint: bad X value - ",
02296                                  argv[1],
02297                                  "\n",
02298                                  (char *)0);
02299                 return TCL_ERROR;
02300             }
02301 
02302             if (sscanf(argv[2], "%lf", &viewPt[Y]) != 1) {
02303                 Tcl_AppendResult(interp,
02304                                  "vo_mrotPoint: bad Y value - ",
02305                                  argv[2],
02306                                  "\n",
02307                                  (char *)0);
02308                 return TCL_ERROR;
02309             }
02310 
02311             if (sscanf(argv[3], "%lf", &viewPt[Z]) != 1) {
02312                 Tcl_AppendResult(interp,
02313                                  "vo_mrotPoint: bad Z value - ",
02314                                  argv[3],
02315                                  "\n",
02316                                  (char *)0);
02317                 return TCL_ERROR;
02318             }
02319         }
02320 
02321         bu_vls_init(&vls);
02322         bn_mat_inv(invRot, vop->vo_rotation);
02323         MAT4X3PNT(modelPt, invRot, viewPt);
02324         bn_encode_vect(&vls, modelPt);
02325         Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
02326         bu_vls_free(&vls);
02327 
02328         return TCL_OK;
02329     }
02330 
02331  bad:
02332     /* compose error message */
02333     bu_vls_init(&vls);
02334     bu_vls_printf(&vls, "helplib_alias vo_mrotPoint %s", argv[0]);
02335     Tcl_Eval(interp, bu_vls_addr(&vls));
02336     bu_vls_free(&vls);
02337 
02338     return TCL_ERROR;
02339 }
02340 
02341 /*
02342  * Convert view point to a model point (rotation only).
02343  *
02344  * Usage:
02345  *        procname mrotPoint vx vy vz
02346  */
02347 static int
02348 vo_mrotPoint_tcl(ClientData     clientData,
02349                      Tcl_Interp *interp,
02350                      int        argc,
02351                      char       **argv)
02352 {
02353     struct view_obj *vop = (struct view_obj *)clientData;
02354 
02355     return vo_mrotPoint_cmd(vop, interp, argc-1, argv+1);
02356 }
02357 
02358 int
02359 vo_m2vPoint_cmd(struct view_obj *vop,
02360                 Tcl_Interp      *interp,
02361                 int             argc,
02362                 char            **argv)
02363 {
02364     struct bu_vls       vls;
02365 
02366     /* Parse the incoming point */
02367     if (argc == 2 || argc == 4) {
02368         point_t viewPt;
02369         point_t modelPt;
02370 
02371         if (argc == 2) {
02372             if (bn_decode_vect(viewPt, argv[1]) != 3)
02373                 goto bad;
02374         } else {
02375             if (sscanf(argv[1], "%lf", &modelPt[X]) != 1) {
02376                 Tcl_AppendResult(interp,
02377                                  "vo_m2vPoint: bad X value - ",
02378                                  argv[1],
02379                                  "\n",
02380                                  (char *)0);
02381                 return TCL_ERROR;
02382             }
02383 
02384             if (sscanf(argv[2], "%lf", &modelPt[Y]) != 1) {
02385                 Tcl_AppendResult(interp,
02386                                  "vo_m2vPoint: bad Y value - ",
02387                                  argv[2],
02388                                  "\n",
02389                                  (char *)0);
02390                 return TCL_ERROR;
02391             }
02392 
02393             if (sscanf(argv[3], "%lf", &modelPt[Z]) != 1) {
02394                 Tcl_AppendResult(interp,
02395                                  "vo_m2vPoint: bad Z value - ",
02396                                  argv[3],
02397                                  "\n",
02398                                  (char *)0);
02399                 return TCL_ERROR;
02400             }
02401         }
02402 
02403         bu_vls_init(&vls);
02404         MAT4X3PNT(viewPt, vop->vo_model2view, modelPt);
02405         bn_encode_vect(&vls, viewPt);
02406         Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
02407         bu_vls_free(&vls);
02408 
02409         return TCL_OK;
02410     }
02411 
02412  bad:
02413     /* compose error message */
02414     bu_vls_init(&vls);
02415     bu_vls_printf(&vls, "helplib_alias vo_m2vPoint %s", argv[0]);
02416     Tcl_Eval(interp, bu_vls_addr(&vls));
02417     bu_vls_free(&vls);
02418 
02419     return TCL_ERROR;
02420 }
02421 
02422 /*
02423  * Convert model point to a view point.
02424  *
02425  * Usage:
02426  *        procname m2vPoint vx vy vz
02427  */
02428 static int
02429 vo_m2vPoint_tcl(ClientData      clientData,
02430                 Tcl_Interp      *interp,
02431                 int             argc,
02432                 char            **argv)
02433 {
02434     struct view_obj *vop = (struct view_obj *)clientData;
02435 
02436     return vo_m2vPoint_cmd(vop, interp, argc-1, argv+1);
02437 }
02438 
02439 int
02440 vo_v2mPoint_cmd(struct view_obj *vop,
02441                 Tcl_Interp      *interp,
02442                 int             argc,
02443                 char            **argv)
02444 {
02445     struct bu_vls       vls;
02446 
02447     /* Parse the incoming point */
02448     if (argc == 2 || argc == 4) {
02449         point_t viewPt;
02450         point_t modelPt;
02451 
02452         if (argc == 2) {
02453             if (bn_decode_vect(viewPt, argv[1]) != 3)
02454                 goto bad;
02455         } else {
02456             if (sscanf(argv[1], "%lf", &viewPt[X]) != 1) {
02457                 Tcl_AppendResult(interp,
02458                                  "vo_v2mPoint: bad X value - ",
02459                                  argv[1],
02460                                  "\n",
02461                                  (char *)0);
02462                 return TCL_ERROR;
02463             }
02464 
02465             if (sscanf(argv[2], "%lf", &viewPt[Y]) != 1) {
02466                 Tcl_AppendResult(interp,
02467                                  "vo_v2mPoint: bad Y value - ",
02468                                  argv[2],
02469                                  "\n",
02470                                  (char *)0);
02471                 return TCL_ERROR;
02472             }
02473 
02474             if (sscanf(argv[3], "%lf", &viewPt[Z]) != 1) {
02475                 Tcl_AppendResult(interp,
02476                                  "vo_v2mPoint: bad Z value - ",
02477                                  argv[3],
02478                                  "\n",
02479                                  (char *)0);
02480                 return TCL_ERROR;
02481             }
02482         }
02483 
02484         bu_vls_init(&vls);
02485         MAT4X3PNT(modelPt, vop->vo_view2model, viewPt);
02486         bn_encode_vect(&vls, modelPt);
02487         Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
02488         bu_vls_free(&vls);
02489 
02490         return TCL_OK;
02491     }
02492 
02493  bad:
02494     /* compose error message */
02495     bu_vls_init(&vls);
02496     bu_vls_printf(&vls, "helplib_alias vo_v2mPoint %s", argv[0]);
02497     Tcl_Eval(interp, bu_vls_addr(&vls));
02498     bu_vls_free(&vls);
02499 
02500     return TCL_ERROR;
02501 }
02502 
02503 /*
02504  * Convert view point to a model point.
02505  *
02506  * Usage:
02507  *        procname v2mPoint vx vy vz
02508  */
02509 static int
02510 vo_v2mPoint_tcl(ClientData      clientData,
02511                 Tcl_Interp      *interp,
02512                 int             argc,
02513                 char            **argv)
02514 {
02515     struct view_obj *vop = (struct view_obj *)clientData;
02516 
02517     return vo_v2mPoint_cmd(vop, interp, argc-1, argv+1);
02518 }
02519 
02520 int
02521 vo_sca(struct view_obj  *vop,
02522        Tcl_Interp       *interp,
02523        fastf_t          sf,
02524        int              (*func)())
02525 {
02526         if (func != (int (*)())0)
02527                 return (*func)(vop, interp, sf);
02528 
02529         if (sf < SMALL_FASTF || INFINITY < sf)
02530                 return TCL_OK;
02531 
02532         vop->vo_scale *= sf;
02533         if (vop->vo_scale < RT_MINVIEWSIZE)
02534                 vop->vo_scale = RT_MINVIEWSIZE;
02535         vop->vo_size = 2.0 * vop->vo_scale;
02536         vop->vo_invSize = 1.0 / vop->vo_size;
02537         vo_update(vop, interp, 1);
02538         return TCL_OK;
02539 }
02540 
02541 int
02542 vo_sca_cmd(struct view_obj      *vop,
02543            Tcl_Interp           *interp,
02544            int                  argc,
02545            char                 **argv,
02546            int                  (*func)())
02547 {
02548         fastf_t sf;
02549 
02550         if (argc != 2) {
02551                 struct bu_vls vls;
02552 
02553                 bu_vls_init(&vls);
02554                 bu_vls_printf(&vls, "helplib_alias vo_sca %s", argv[0]);
02555                 Tcl_Eval(interp, bu_vls_addr(&vls));
02556                 bu_vls_free(&vls);
02557                 return TCL_ERROR;
02558         }
02559 
02560         if (sscanf(argv[1], "%lf", &sf) != 1) {
02561                 Tcl_AppendResult(interp, "vo_sca: bad scale factor - ", argv[1], "\n", (char *)0);
02562                 return TCL_ERROR;
02563         }
02564 
02565         return vo_sca(vop, interp, sf, func);
02566 }
02567 
02568 /*
02569  * Usage:
02570  *        procname sca [sf]
02571  */
02572 static int
02573 vo_sca_tcl(ClientData   clientData,
02574            Tcl_Interp   *interp,
02575            int          argc,
02576            char         **argv)
02577 {
02578         struct view_obj *vop = (struct view_obj *)clientData;
02579 
02580         return vo_sca_cmd(vop, interp, argc-1, argv+1, (int (*)())0);
02581 }
02582 
02583 int
02584 vo_viewDir_cmd(struct view_obj  *vop,
02585               Tcl_Interp        *interp,
02586               int               argc,
02587               char              **argv)
02588 {
02589     vect_t view;
02590     vect_t model;
02591     mat_t invRot;
02592     struct bu_vls vls;
02593     int iflag = 0;
02594 
02595     if (2 < argc) {
02596         struct bu_vls vls;
02597 
02598         bu_vls_init(&vls);
02599         bu_vls_printf(&vls, "helplib_alias vo_viewDir %s", argv[0]);
02600         Tcl_Eval(interp, bu_vls_addr(&vls));
02601         bu_vls_free(&vls);
02602         return TCL_ERROR;
02603     }
02604 
02605     /* Look for -i option */
02606     if (argc == 2 &&
02607         argv[1][0] == '-' &&
02608         argv[1][1] == 'i' &&
02609         argv[1][2] == '\0')
02610         iflag = 1;
02611 
02612     if (iflag) {
02613         VSET(view, 0.0, 0.0, -1.0);
02614     } else {
02615         VSET(view, 0.0, 0.0, 1.0);
02616     }
02617 
02618     bn_mat_inv(invRot, vop->vo_rotation);
02619     MAT4X3PNT(model, invRot, view);
02620     
02621     bu_vls_init(&vls);
02622     bn_encode_vect(&vls, model);
02623     Tcl_AppendResult(interp, bu_vls_addr(&vls), (char *)NULL);
02624     bu_vls_free(&vls);
02625 
02626     return TCL_OK;
02627 }
02628 
02629 /*
02630  * Usage:
02631  *        procname viewDir
02632  */
02633 static int
02634 vo_viewDir_tcl(ClientData       clientData,
02635               Tcl_Interp        *interp,
02636               int               argc,
02637               char              **argv)
02638 {
02639         struct view_obj *vop = (struct view_obj *)clientData;
02640 
02641         return vo_viewDir_cmd(vop, interp, argc-1, argv+1);
02642 }
02643 
02644 #if 0
02645 /* skeleton functions for view_obj methods */
02646 int
02647 vo__cmd(struct view_obj *vop,
02648          Tcl_Interp     *interp,
02649          int            argc,
02650          char           **argv)
02651 {
02652 }
02653 
02654 /*
02655  * Usage:
02656  *        procname
02657  */
02658 static int
02659 vo__tcl(ClientData      clientData,
02660          Tcl_Interp     *interp,
02661          int            argc,
02662          char           **argv)
02663 {
02664         struct view_obj *vop = (struct view_obj *)clientData;
02665 
02666         return vo__cmd(vop, interp, argc-1, argv+1);
02667 }
02668 #endif
02669 
02670 /****************** Utility Routines ********************/
02671 void
02672 vo_update(struct view_obj       *vop,
02673           Tcl_Interp            *interp,
02674           int                   oflag)
02675 {
02676         vect_t work, work1;
02677         vect_t temp, temp1;
02678 
02679         bn_mat_mul(vop->vo_model2view,
02680                    vop->vo_rotation,
02681                    vop->vo_center);
02682         vop->vo_model2view[15] = vop->vo_scale;
02683         bn_mat_inv(vop->vo_view2model, vop->vo_model2view);
02684 
02685         /* Find current azimuth, elevation, and twist angles */
02686         VSET(work, 0.0, 0.0, 1.0);       /* view z-direction */
02687         MAT4X3VEC(temp , vop->vo_view2model , work);
02688         VSET(work1 , 1.0, 0.0, 0.0);      /* view x-direction */
02689         MAT4X3VEC(temp1 , vop->vo_view2model , work1);
02690 
02691         /* calculate angles using accuracy of 0.005, since display
02692          * shows 2 digits right of decimal point */
02693         bn_aet_vec(&vop->vo_aet[0],
02694                    &vop->vo_aet[1],
02695                    &vop->vo_aet[2],
02696                    temp, temp1, (fastf_t)0.005);
02697 
02698         /* Force azimuth range to be [0,360] */
02699         if ((NEAR_ZERO(vop->vo_aet[1] - 90.0,(fastf_t)0.005) ||
02700              NEAR_ZERO(vop->vo_aet[1] + 90.0,(fastf_t)0.005)) &&
02701             vop->vo_aet[0] < 0 &&
02702             !NEAR_ZERO(vop->vo_aet[0],(fastf_t)0.005))
02703                 vop->vo_aet[0] += 360.0;
02704         else if (NEAR_ZERO(vop->vo_aet[0],(fastf_t)0.005))
02705                 vop->vo_aet[0] = 0.0;
02706 
02707         /* apply the perspective angle to model2view */
02708         bn_mat_mul(vop->vo_pmodel2view, vop->vo_pmat, vop->vo_model2view);
02709 
02710         if (vop->vo_callback)
02711                 (*vop->vo_callback)(vop->vo_clientData, vop);
02712         else if (oflag && interp != (Tcl_Interp *)NULL)
02713                 bu_observer_notify(interp, &vop->vo_observers, bu_vls_addr(&vop->vo_name));
02714 }
02715 
02716 void
02717 vo_mat_aet(struct view_obj *vop)
02718 {
02719         mat_t tmat;
02720         fastf_t twist;
02721         fastf_t c_twist;
02722         fastf_t s_twist;
02723 
02724         bn_mat_angles(vop->vo_rotation,
02725                       270.0 + vop->vo_aet[1],
02726                       0.0,
02727                       270.0 - vop->vo_aet[0]);
02728 
02729         twist = -vop->vo_aet[2] * bn_degtorad;
02730         c_twist = cos(twist);
02731         s_twist = sin(twist);
02732         bn_mat_zrot(tmat, s_twist, c_twist);
02733         bn_mat_mul2(tmat, vop->vo_rotation);
02734 }
02735 
02736 /*
02737  *                      P E R S P _ M A T
02738  *
02739  *  This code came from mged/dozoom.c.
02740  *  Compute a perspective matrix for a right-handed coordinate system.
02741  *  Reference: SGI Graphics Reference Appendix C
02742  *  (Note:  SGI is left-handed, but the fix is done in the Display Manger).
02743  */
02744 static void
02745 vo_persp_mat(mat_t      m,
02746              fastf_t    fovy,
02747              fastf_t    aspect,
02748              fastf_t    near1,
02749              fastf_t    far1,
02750              fastf_t    backoff)
02751 {
02752         mat_t   m2, tran;
02753 
02754         fovy *= 3.1415926535/180.0;
02755 
02756         MAT_IDN(m2);
02757         m2[5] = cos(fovy/2.0) / sin(fovy/2.0);
02758         m2[0] = m2[5]/aspect;
02759         m2[10] = (far1+near1) / (far1-near1);
02760         m2[11] = 2*far1*near1 / (far1-near1);   /* This should be negative */
02761 
02762         m2[14] = -1;            /* XXX This should be positive */
02763         m2[15] = 0;
02764 
02765         /* Move eye to origin, then apply perspective */
02766         MAT_IDN(tran);
02767         tran[11] = -backoff;
02768         bn_mat_mul(m, m2, tran);
02769 }
02770 
02771 /*
02772  *  This code came from mged/dozoom.c.
02773  *  Create a perspective matrix that transforms the +/1 viewing cube,
02774  *  with the acutal eye position (not at Z=+1) specified in viewing coords,
02775  *  into a related space where the eye has been sheared onto the Z axis
02776  *  and repositioned at Z=(0,0,1), with the same perspective field of view
02777  *  as before.
02778  *
02779  *  The Zbuffer clips off stuff with negative Z values.
02780  *
02781  *  pmat = persp * xlate * shear
02782  */
02783 static void
02784 vo_mike_persp_mat(mat_t         pmat,
02785                   const point_t eye)
02786 {
02787         mat_t   shear;
02788         mat_t   persp;
02789         mat_t   xlate;
02790         mat_t   t1, t2;
02791         point_t sheared_eye;
02792 
02793         if( eye[Z] < SMALL )  {
02794                 VPRINT("mike_persp_mat(): ERROR, z<0, eye", eye);
02795                 return;
02796         }
02797 
02798         /* Shear "eye" to +Z axis */
02799         MAT_IDN(shear);
02800         shear[2] = -eye[X]/eye[Z];
02801         shear[6] = -eye[Y]/eye[Z];
02802 
02803         MAT4X3VEC( sheared_eye, shear, eye );
02804         if( !NEAR_ZERO(sheared_eye[X], .01) || !NEAR_ZERO(sheared_eye[Y], .01) )  {
02805                 VPRINT("ERROR sheared_eye", sheared_eye);
02806                 return;
02807         }
02808 
02809         /* Translate along +Z axis to put sheared_eye at (0,0,1). */
02810         MAT_IDN(xlate);
02811         /* XXX should I use MAT_DELTAS_VEC_NEG()?  X and Y should be 0 now */
02812         MAT_DELTAS( xlate, 0, 0, 1-sheared_eye[Z] );
02813 
02814         /* Build perspective matrix inline, substituting fov=2*atan(1,Z) */
02815         MAT_IDN( persp );
02816         /* From page 492 of Graphics Gems */
02817         persp[0] = sheared_eye[Z];      /* scaling: fov aspect term */
02818         persp[5] = sheared_eye[Z];      /* scaling: determines fov */
02819 
02820         /* From page 158 of Rogers Mathematical Elements */
02821         /* Z center of projection at Z=+1, r=-1/1 */
02822         persp[14] = -1;
02823 
02824         bn_mat_mul( t1, xlate, shear );
02825         bn_mat_mul( t2, persp, t1 );
02826 
02827         /* Now, move eye from Z=1 to Z=0, for clipping purposes */
02828         MAT_DELTAS( xlate, 0, 0, -1 );
02829 
02830         bn_mat_mul( pmat, xlate, t2 );
02831 }
02832 
02833 
02834 
02835 /*
02836  * Local Variables:
02837  * mode: C
02838  * tab-width: 8
02839  * c-basic-offset: 4
02840  * indent-tabs-mode: t
02841  * End:
02842  * ex: shiftwidth=4 tabstop=8
02843  */

Generated on Mon Sep 18 01:24:57 2006 for BRL-CAD by  doxygen 1.4.6