/* * Copyright (c) 1986, 1987, 1988, 1989 by Sun Microsystems, Inc. * Permission to use, copy, modify, and distribute this software for any * purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both that copyright * notice and this permission notice are retained, and that the name * of Sun Microsystems, Inc., not be used in advertising or publicity * pertaining to this software without specific, written prior permission. * Sun Microsystems, Inc., makes no representations about the suitability * of this software or the interface defined in this software for any * purpose. It is provided "as is" without express or implied warranty. */ #ifndef lint static char sccsid[] = "@(#)xformattrib.c 1.1 94/10/31 Copyr 1986 Sun Micro"; #endif /* * Copyright (c) 1986 by Sun Microsystems, Inc. */ /* Operation: These routines maintain the transformation stack, viewport attributes. Included are routines for concatenating matrices, transforming points, taking vector crossproducts, computing unit vectors, obtaining the length of a vector, finding vector dotproducts and popping and pushing transformations on the transform stack. The stack currently will hold only 10 transforms. Usage: typedef struct{ float x,y,z,w; } pt_type; ' homogeneous point type --- Transform utility operations --- _core_push( m) float *m; ' push 4x4 matrix onto stack _core_pop( m) float *m; ' pop 4x4 matrix from stack _core_matcon(); ' concatenate top matrix times next ' matrix, pop both, push the result ' on the stack. crossprod( p1,p2,p3) pt_type *p1, *p2, *p3; ' 3-D vector cross product, ' p3 = p1 X p2. float dotprod( p1,p2) pt_type *p1, *p2; ' 3-D vector dot product _core_unitvec( p1) pt_type *p1; ' Convert 3-D vector to unit vector. float vecleng( x,y,z) float x,y,z; ' Return length of vector. _core_make_mat(); ' Build transform from view attributes ' and push it on the stack. --- Viewing attribute operations --- set_viewing_parameters(viewparm)' Set all viewing parameters set_view_reference_point(x,y,z) ' Set view reference in world coords. set_view_plane_normal( dx,dy,dz)' Set view plane normal. set_view_plane_distance(vwdist) ' Set view distance. set_view_up_3( dxup, dyup, dzup)' Set up direction for viewing window. set_window(umin,umax,vmin,vmax) ' Set view window size in world coords. set_viewport_2(xmin,xmax,ymin,ymax) ' Set view port in display coords. set_view_depth( near,far) ' Set near and far clipping planes. set_projection( type,dx,dy,dz); ' Specify perspective or parallel. ' set direction of projection. ' set center of projection. */ #include "coretypes.h" #include "corevars.h" #include #include static char *funcname; static int errnum; _core_push(m) float *m; /* push 4x4 transform onto stack */ { int i; if (_core_TSp >= TSlim) (void) fprintf(stderr, "Transform stack overflow!\n"); else { _core_TSp += 1; for (i = 0; i < TSize; i++) _core_TStack[_core_TSp][i] = *m++; } _core_ddxformset = FALSE; } _core_pop(m) float *m; /* pop transform, return it to caller */ { int i; if (_core_TSp < 0) (void) fprintf(stderr, "Transform stack empty!\n"); else { for (i = 0; i < TSize; i++) *m++ = _core_TStack[_core_TSp][i]; _core_TSp -= 1; } _core_ddxformset = FALSE; } _core_copytop(m) float *m; { int i; if (_core_TSp < 0) (void) fprintf(stderr, "Transform stack empty!\n"); else for (i = 0; i < TSize; i++) *m++ = _core_TStack[_core_TSp][i]; } _core_matcon() { /* concatenate top 2 transforms on *//* stack */ int j, l; /* row col */ float m3[4][4]; /* m3(j, l) = Sum(m1(j,k)*m2(k,l) */ float sum, *m1, *m2, *r; /* k */ float *p, *q; register short k; ddargtype ddstruct; if (_core_TSp < 1) { (void) fprintf(stderr, "Transform stack empty!\n"); return (-1); } m1 = &_core_TStack[_core_TSp][0]; m2 = &_core_TStack[_core_TSp - 1][0]; if (_core_xformvs) { _core_critflag++; /* critical section since slight chance of * view surface termination via SIGCHILD * during the call to the dd */ ddstruct.opcode = MATMULT; /* matrix mult */ ddstruct.instance = _core_xformvs->instance; ddstruct.ptr1 = (char *) m1; ddstruct.ptr2 = (char *) m2; ddstruct.ptr3 = (char *) m3; (*_core_xformvs->dd) (&ddstruct); if (--_core_critflag == 0 && _core_updatewin && _core_sighandle) (*_core_sighandle) (); } else { for (j = 0; j < 4; j++) { /* for all output matrix rows */ r = m1 + j * 4; for (l = 0; l < 4; l++) { /* for all output matrix cols */ q = m2 + l; p = r; sum = 0.0; for (k = 0; k < 4; k++) { /* sum over k */ sum += *p++ * *q; q += 4; } m3[j][l] = sum; } } } _core_TSp -= 2; _core_push(&m3[0][0]); return (0); } static crossprod(p1, p2, p3) pt_type *p1, *p2, *p3; { /* vector cross product p3=p1xp2 */ p3->x = (p1->y * p2->z) - (p1->z * p2->y); p3->y = (p1->z * p2->x) - (p1->x * p2->z); p3->z = (p1->x * p2->y) - (p1->y * p2->x); } static float dotprod(p1, p2) pt_type *p1, *p2; { /* vector dot product val=p1.p2 */ return (p1->x * p2->x + p1->y * p2->y + p1->z * p2->z); } static float vecleng(x1, y1, z1) float x1, y1, z1; { /* compute length of vector */ return (sqrt(x1 * x1 + y1 * y1 + z1 * z1)); } _core_unitvec(p1) pt_type *p1; { /* convert p1 to unit vector */ float len; len = vecleng(p1->x, p1->y, p1->z); if (len == 0.0) len = 1.0; p1->x /= len; p1->y /= len; p1->z /= len; } set_ndc_space_2(width, height) float width, height; { char *funcname; viewsurf *surfp; ddargtype ddstruct; funcname = "set_ndc_space_2"; if (_core_ndcset) { if (_core_ndcset & 2) { _core_errhand(funcname, 97); return (503); } _core_errhand(funcname, 98); return (504); } if (width < 0.0 || width > 1.0 || height < 0.0 || height > 1.0) { _core_errhand(funcname, 99); return (505); } if (width != 1.0 && height != 1.0) { _core_errhand(funcname, 100); return (506); } if (width == 0.0 || height == 0.0) { _core_errhand(funcname, 101); return (507); } _core_ndcset |= 2; _core_ndc.width = width; _core_ndc.height = height; _core_ndc.depth = 0.0; _core_ndcspace[0] = (int) (width * (float) MAX_NDC_COORD); _core_ndcspace[1] = (int) (height * (float) MAX_NDC_COORD); _core_ndcspace[2] = 0; ddstruct.opcode = SETNDC; ddstruct.float1 = width; ddstruct.float2 = height; ddstruct.float3 = 0.0; for (surfp = &_core_surface[0]; surfp < &_core_surface[MAXVSURF]; surfp++) if (surfp->vinit) { ddstruct.instance = surfp->vsurf.instance; (*surfp->vsurf.dd) (&ddstruct); } return (0); } set_ndc_space_3(width, height, depth) float width, height, depth; { char *funcname; viewsurf *surfp; ddargtype ddstruct; funcname = "set_ndc_space_3"; if (_core_ndcset) { if (_core_ndcset & 2) { _core_errhand(funcname, 97); return (503); } _core_errhand(funcname, 98); return (504); } if (width < 0.0 || width > 1.0 || height < 0.0 || height > 1.0 || depth < 0.0 || depth > 1.0) { _core_errhand(funcname, 99); return (505); } if (width != 1.0 && height != 1.0) { _core_errhand(funcname, 100); return (506); } if (width == 0.0 || height == 0.0) { _core_errhand(funcname, 101); return (507); } _core_ndcset |= 2; _core_ndc.width = width; _core_ndc.height = height; _core_ndc.depth = depth; _core_ndcspace[0] = (int) (width * (float) MAX_NDC_COORD); _core_ndcspace[1] = (int) (height * (float) MAX_NDC_COORD); _core_ndcspace[2] = (int) (depth * (float) MAX_NDC_COORD); ddstruct.opcode = SETNDC; ddstruct.float1 = width; ddstruct.float2 = height; ddstruct.float3 = depth; for (surfp = &_core_surface[0]; surfp < &_core_surface[MAXVSURF]; surfp++) if (surfp->vinit) { ddstruct.instance = surfp->vsurf.instance; (*surfp->vsurf.dd) (&ddstruct); } return (0); } set_viewing_parameters(viewparm) struct { float vwrefpt[3]; float vwplnorm[3]; float viewdis; float frontdis; float backdis; int projtype; float projdir[3]; windtype window; float vwupdir[3]; float viewport[6]; } *viewparm; { int err; vwprmtype savevwp; int savevfinvokd, savevtchang, savendcset; if (_core_osexists) { _core_errhand("set_viewing_parameters", 8); return (6); } savevwp = _core_vwstate; savevfinvokd = _core_vfinvokd; savevtchang = _core_vtchang; savendcset = _core_ndcset; err = 0; do { if (set_view_reference_point(viewparm->vwrefpt[0], viewparm->vwrefpt[1], viewparm->vwrefpt[2])) { err = 1; break; } if (set_view_plane_normal(viewparm->vwplnorm[0], viewparm->vwplnorm[1], viewparm->vwplnorm[2])) { err = 2; break; } if (set_view_plane_distance(viewparm->viewdis)) { err = 3; break; } if (set_view_depth(viewparm->frontdis, viewparm->backdis)) { err = 4; break; } if (set_projection(viewparm->projtype, viewparm->projdir[0], viewparm->projdir[1], viewparm->projdir[2])) { err = 5; break; } if (set_window(viewparm->window.xmin, viewparm->window.xmax, viewparm->window.ymin, viewparm->window.ymax)) { err = 6; break; } if (set_view_up_3(viewparm->vwupdir[0], viewparm->vwupdir[1], viewparm->vwupdir[2])) { err = 7; break; } if (set_viewport_3(viewparm->viewport[0], viewparm->viewport[1], viewparm->viewport[2], viewparm->viewport[3], viewparm->viewport[4], viewparm->viewport[5])) { err = 8; break; } } while (FALSE); if (err) { _core_errhand("set_viewing_parameters", 88 + err); _core_vwstate = savevwp; _core_vfinvokd = savevfinvokd; _core_vtchang = savevtchang; _core_ndcset = savendcset; return (err); } return (0); } set_view_reference_point(x, y, z) float x, y, z; { /* set look at point, world coords */ _core_vwstate.vwrefpt[0] = x; _core_vwstate.vwrefpt[1] = y; _core_vwstate.vwrefpt[2] = z; _core_vtchang = TRUE; _core_vfinvokd = TRUE; return (0); } set_view_plane_normal(dx, dy, dz) float dx, dy, dz; { /* set view plane normal, world */ funcname = "set_view_plane_normal"; if ((dx == 0.0) && (dy == 0.0) && (dz == 0.0)) { errnum = 39; _core_errhand(funcname, errnum); return (2); } _core_vwstate.vwplnorm[0] = dx; _core_vwstate.vwplnorm[1] = dy; _core_vwstate.vwplnorm[2] = dz; _core_vtchang = TRUE; _core_vfinvokd = TRUE; return (0); } set_view_plane_distance(dist) float dist; { /* set viewing distance */ _core_vwstate.viewdis = dist; _core_vtchang = TRUE; _core_vfinvokd = TRUE; return (0); } set_view_up_2(dx, dy) float dx, dy; { /* set direction of 'up' */ funcname = "set_view_up_2"; if ((dx == 0.0) && (dy == 0.0)) { _core_errhand(funcname, 39); return (2); } _core_vwstate.vwupdir[0] = dx; _core_vwstate.vwupdir[1] = dy; _core_vwstate.vwupdir[2] = 0.0; _core_vfinvokd = TRUE; _core_vtchang = TRUE; return (0); } set_view_up_3(dx, dy, dz) float dx, dy, dz; { /* set direction of 'up' */ funcname = "set_view_up_3"; if ((dx == 0.0) && (dy == 0.0) && (dz == 0.0)) { errnum = 39; _core_errhand(funcname, errnum); return (2); } _core_vwstate.vwupdir[0] = dx; _core_vwstate.vwupdir[1] = dy; _core_vwstate.vwupdir[2] = dz; _core_vfinvokd = TRUE; _core_vtchang = TRUE; return (0); } set_window(umin, umax, vmin, vmax) float umin, umax, vmin, vmax; { /* set view window in world coords */ funcname = "set_window"; if ((umin >= umax) || (vmin >= vmax)) { errnum = 40; _core_errhand(funcname, errnum); return (2); } _core_vwstate.window.xmin = umin; _core_vwstate.window.xmax = umax; _core_vwstate.window.ymin = vmin; _core_vwstate.window.ymax = vmax; _core_vtchang = TRUE; _core_vfinvokd = TRUE; return (0); } set_viewport_2(xmin, xmax, ymin, ymax) float xmin, xmax, ymin, ymax; { /* set view port in NDC coords */ float f; funcname = "set_viewport_2"; if (_core_osexists) { _core_errhand(funcname, 8); return (1); } f = (float) MAX_NDC_COORD; xmin *= f; xmax *= f; ymin *= f; ymax *= f; if (((int) xmax > _core_ndcspace[0]) || ((int) ymax > _core_ndcspace[1]) || (xmin < 0.0) || (ymin < 0.0)) { errnum = 46; _core_errhand(funcname, errnum); return (1); } if ((xmin >= xmax) || (ymin >= ymax)) { errnum = 47; _core_errhand(funcname, errnum); return (3); } _core_vwstate.viewport.xmin = (int) xmin; _core_vwstate.viewport.xmax = (int) xmax; _core_vwstate.viewport.ymin = (int) ymin; _core_vwstate.viewport.ymax = (int) ymax; /* compute scale params */ _core_scalex = (int) ((xmax - xmin) / 2.0); _core_scaley = (int) ((ymax - ymin) / 2.0);; /* and offset params */ _core_poffx = (int) ((xmax + xmin) / 2.0); _core_poffy = (int) ((ymax + ymin) / 2.0);; _core_vfinvokd = TRUE; _core_ndcset |= 1; _core_vtchang = TRUE; return (0); } set_viewport_3(xmin, xmax, ymin, ymax, zmin, zmax) float xmin, xmax, ymin, ymax, zmin, zmax; { /* set view port in NDC coords */ float f; funcname = "set_viewport_3"; if (_core_osexists) { _core_errhand(funcname, 8); return (1); } f = (float) MAX_NDC_COORD; xmin *= f; xmax *= f; ymin *= f; ymax *= f; zmin *= f; zmax *= f; if (((int) xmax > _core_ndcspace[0]) || ((int) ymax > _core_ndcspace[1]) || ((int) zmax > _core_ndcspace[2]) || (xmin < 0.0) || (ymin < 0.0) || (zmin < 0.0)) { errnum = 46; _core_errhand(funcname, errnum); return (1); } if ((xmin >= xmax) || (ymin >= ymax) || (zmin >= zmax)) { errnum = 47; _core_errhand(funcname, errnum); return (3); } _core_vwstate.viewport.xmin = (int) xmin; _core_vwstate.viewport.xmax = (int) xmax; _core_vwstate.viewport.ymin = (int) ymin; _core_vwstate.viewport.ymax = (int) ymax; _core_vwstate.viewport.zmin = (int) zmin; _core_vwstate.viewport.zmax = (int) zmax; /* compute scale params */ _core_scalex = (int) ((xmax - xmin) / 2.0); _core_scaley = (int) ((ymax - ymin) / 2.0); _core_scalez = (int) (zmax - zmin); /* and offset params */ _core_poffx = (int) ((xmax + xmin) / 2.0); _core_poffy = (int) ((ymax + ymin) / 2.0); _core_poffz = (int) zmin; _core_vfinvokd = TRUE; _core_ndcset |= 1; _core_vtchang = TRUE; return (0); } set_view_depth(near, far) float near, far; { /* set clipping plane distances */ funcname = "set_view_depth"; if (near > far) { errnum = 41; _core_errhand(funcname, errnum); return (1); } else { _core_vwstate.frontdis = near; _core_vwstate.backdis = far; } _core_vtchang = TRUE; _core_vfinvokd = TRUE; return (0); } set_projection(projtype, dx, dy, dz) int projtype; float dx, dy, dz; { funcname = "set_projection"; if (projtype == PARALLEL) { if ((dx == 0.0) && (dy == 0.0) && (dz == 0.0)) { errnum = 39; _core_errhand(funcname, errnum); return (1); } _core_vwstate.projtype = PARALLEL; /* specify parallel * projection */ _core_vwstate.projdir[0] = dx; _core_vwstate.projdir[1] = dy; _core_vwstate.projdir[2] = dz; } else { _core_vwstate.projtype = PERSPECTIVE; _core_vwstate.projdir[0] = dx; _core_vwstate.projdir[1] = dy; _core_vwstate.projdir[2] = dz; } _core_vtchang = TRUE; _core_vfinvokd = TRUE; return (0); } int _core_make_mat() { /* build matrix from view attrib */ int i, err; float cp[3]; register float *ptr1, *ptr2; _core_TSp = -1; crossprod((pt_type *) _core_vwstate.vwplnorm, (pt_type *) _core_vwstate.vwupdir, (pt_type *) cp); if (vecleng(cp[0], cp[1], cp[2]) < 1.0e-15) err = 1; /* vwplnorm || vwupdir */ else if ((_core_vwstate.frontdis == _core_vwstate.backdis) && (_core_vwstate.viewport.zmin != _core_vwstate.viewport.zmax)) err = 1; /* Condition only legal if 3-D viewport zmin * == zmax. */ else if (_core_vwstate.projtype == PERSPECTIVE) err = make_perspective_mat(); else err = make_parallel_mat(); if (err) { _core_errhand("_core_make_mat", 82); _core_TSp = -1; _core_push(&_core_vwxform1[0][0]); return (1); } else { /* Always called once in initialization */ /* with valid view parameters */ _core_copytop(&_core_vwxform1[0][0]); ptr1 = &_core_vwxform1[0][0]; ptr2 = &_core_vwxform32k[0][0]; for (i = 0; i < 16; i++) *ptr2++ = *ptr1++ * (float) MAX_CLIP_COORD; return (0); } } static int make_perspective_mat() { /* Terminology from Foley & van Dam Sect. * 8.4.2 */ float amat[4][4], bmat[4][4]; float d1, d2; float pt1[4], pt2[4]; float tvwplnz, tvrpz, tfplnz, tbplnz; float zvmin, twr; if (_core_coordsys == RIGHT)/* twr used to transform world */ twr = 1.0; /* coordinates to a RHS if necessary */ else twr = -1.0; _core_identity(&amat[0][0]); d1 = vecleng(_core_vwstate.vwplnorm[0], _core_vwstate.vwplnorm[2], 0.0); d2 = vecleng(d1, _core_vwstate.vwplnorm[1], 0.0); amat[2][2] = amat[1][1] = d1 / d2; amat[2][1] = _core_vwstate.vwplnorm[1] / d2; amat[1][2] = -amat[2][1]; _core_push(&amat[0][0]); /* Rx */ _core_identity(&amat[0][0]); if (d1 != 0.0) { amat[0][0] = amat[2][2] = (twr * -_core_vwstate.vwplnorm[2]) / d1; amat[2][0] = _core_vwstate.vwplnorm[0] / d1; amat[0][2] = -amat[2][0]; } _core_push(&amat[0][0]); /* Ry */ (void) _core_matcon(); /* Ry*Rx */ pt1[0] = _core_vwstate.vwupdir[0]; pt1[1] = _core_vwstate.vwupdir[1]; pt1[2] = twr * _core_vwstate.vwupdir[2]; pt1[3] = 1.0; _core_tranpt(pt1, pt2); /* pt2 used below to compute Rz */ _core_pop(&bmat[0][0]); /* bmat = RyRx */ _core_identity(&amat[0][0]); amat[2][2] = -1.0; _core_push(&amat[0][0]); /* Trl */ _core_identity(&amat[0][0]); d1 = vecleng(pt2[0], pt2[1], 0.0); amat[0][0] = amat[1][1] = pt2[1] / d1; amat[0][1] = pt2[0] / d1; amat[1][0] = -amat[0][1]; _core_push(&amat[0][0]); /* Rz */ (void) _core_matcon(); /* Rz*Trl */ _core_push(&bmat[0][0]); (void) _core_matcon(); /* Ry*Rx*Rz*Trl */ _core_identity(&amat[0][0]); amat[3][0] = -_core_vwstate.vwrefpt[0] - _core_vwstate.projdir[0]; amat[3][1] = -_core_vwstate.vwrefpt[1] - _core_vwstate.projdir[1]; amat[3][2] = twr * (-_core_vwstate.vwrefpt[2] - _core_vwstate.projdir[2]); _core_push(&amat[0][0]); /* Tper */ _core_identity(&amat[0][0]); amat[2][2] = twr; _core_push(&amat[0][0]); /* Twr: Transform world coords to RHS */ (void) _core_matcon(); /* Twr * Tper */ (void) _core_matcon(); /* Twr*Tper*Ry*Rx*Rz*Trl */ pt1[0] = _core_vwstate.vwrefpt[0]; pt1[1] = _core_vwstate.vwrefpt[1]; pt1[2] = _core_vwstate.vwrefpt[2]; /* * Since we now have Twr in the transform on the stack, we no longer need * to premultiply by twr */ pt1[3] = 1.0; _core_tranpt(pt1, pt2); /* pt2 = VRP' = VRP*Twr Tper R Trl */ _core_pop(&bmat[0][0]); tvrpz = pt2[2]; tvwplnz = tvrpz + _core_vwstate.viewdis; tfplnz = tvrpz + _core_vwstate.frontdis; tbplnz = tvrpz + _core_vwstate.backdis; if ((tvwplnz <= 0.0) || (tfplnz <= 0.0) || (tbplnz < tfplnz)) return (1); if (tbplnz == tfplnz) if (_core_vwstate.viewport.zmin != _core_vwstate.viewport.zmax) return (1); _core_identity(&amat[0][0]); amat[0][0] = ((float) 2.0 * tvwplnz) / ((_core_vwstate.window.xmax - _core_vwstate.window.xmin) * tbplnz); amat[1][1] = ((float) 2.0 * tvwplnz) / ((_core_vwstate.window.ymax - _core_vwstate.window.ymin) * tbplnz); amat[2][2] = (float) 1.0 / tbplnz; _core_push(&amat[0][0]); /* Sper */ _core_identity(&amat[0][0]); amat[2][0] = -(pt2[0] + 0.5 * (_core_vwstate.window.xmin + _core_vwstate.window.xmax)) / tvwplnz; amat[2][1] = -(pt2[1] + 0.5 * (_core_vwstate.window.ymin + _core_vwstate.window.ymax)) / tvwplnz; _core_push(&amat[0][0]); /* SHper */ (void) _core_matcon(); /* SHper*Sper */ _core_push(&bmat[0][0]); (void) _core_matcon(); /* Twr*Tper*Ry*Rx*Rz*Trl*SHper*Sper */ _core_pop(&bmat[0][0]); _core_identity(&amat[0][0]); zvmin = tfplnz / tbplnz; amat[3][3] = 0.0; amat[2][3] = 1.0; if (zvmin != (float) 1.0) { amat[2][2] = (float) 1.0 / ((float) 1.0 - zvmin); amat[3][2] = -zvmin * amat[2][2]; } else { /* if F=B map z to zvmin */ amat[2][2] = zvmin; amat[3][2] = 0.0; } _core_push(&amat[0][0]); /* M */ _core_push(&bmat[0][0]); (void) _core_matcon(); /* Twr*Tper*Ry*Rx*Rz*Trl*SHper*Sper*M */ return (0); } static int make_parallel_mat() { /* Terminology from Foley & van Dam Sect. * 8.4.1 */ float amat[4][4], bmat[4][4]; float d1, d2; float pt1[4], pt2[4]; float twr; if (fabs(dotprod((pt_type *) & _core_vwstate.vwplnorm[0], (pt_type *) & _core_vwstate.projdir[0])) < 1.0e-15) return (1); /* DOP perpendicular to VPN */ if (_core_coordsys == RIGHT) twr = 1.0; else twr = -1.0; _core_identity(&amat[0][0]); d1 = vecleng(_core_vwstate.vwplnorm[0], _core_vwstate.vwplnorm[2], 0.0); d2 = vecleng(d1, _core_vwstate.vwplnorm[1], 0.0); amat[2][2] = amat[1][1] = d1 / d2; amat[2][1] = _core_vwstate.vwplnorm[1] / d2; amat[1][2] = -amat[2][1]; _core_push(&amat[0][0]); /* Rx */ _core_identity(&amat[0][0]); if (d1 != 0.0) { amat[0][0] = amat[2][2] = (twr * -_core_vwstate.vwplnorm[2]) / d1; amat[2][0] = _core_vwstate.vwplnorm[0] / d1; amat[0][2] = -amat[2][0]; } _core_push(&amat[0][0]); /* Ry */ (void) _core_matcon(); /* Ry*Rx */ pt1[0] = _core_vwstate.vwupdir[0]; pt1[1] = _core_vwstate.vwupdir[1]; pt1[2] = twr * _core_vwstate.vwupdir[2]; pt1[3] = 1.0; _core_tranpt(pt1, pt2); /* pt2 used below to compute Rz */ _core_pop(&bmat[0][0]); /* bmat = RyRx */ _core_identity(&amat[0][0]); amat[2][2] = -1.0; _core_push(&amat[0][0]); /* Trl */ _core_identity(&amat[0][0]); d1 = vecleng(pt2[0], pt2[1], 0.0); amat[0][0] = amat[1][1] = pt2[1] / d1; amat[0][1] = pt2[0] / d1; amat[1][0] = -amat[0][1]; _core_push(&amat[0][0]); /* Rz */ (void) _core_matcon(); /* Rz*Trl */ _core_push(&bmat[0][0]); (void) _core_matcon(); /* Ry*Rx*Rz*Trl */ pt1[0] = _core_vwstate.projdir[0]; pt1[1] = _core_vwstate.projdir[1]; pt1[2] = twr * _core_vwstate.projdir[2]; pt1[3] = 1.0; _core_tranpt(pt1, pt2); /* DOP' = DOP*R*Trl */ /* pt2 used below to compute SHpar */ _core_identity(&amat[0][0]); amat[3][0] = -_core_vwstate.vwrefpt[0]; amat[3][1] = -_core_vwstate.vwrefpt[1]; amat[3][2] = twr * -_core_vwstate.vwrefpt[2]; _core_push(&amat[0][0]); /* T */ _core_identity(&amat[0][0]); amat[2][2] = twr; _core_push(&amat[0][0]); /* Twr */ (void) _core_matcon(); /* Twr*T */ (void) _core_matcon(); /* Twr*T*Ry*Rx*Rz*Trl */ _core_pop(&bmat[0][0]); _core_identity(&amat[0][0]); amat[0][0] = (float) 2.0 / (_core_vwstate.window.xmax - _core_vwstate.window.xmin); amat[1][1] = (float) 2.0 / (_core_vwstate.window.ymax - _core_vwstate.window.ymin); if (_core_vwstate.backdis == _core_vwstate.frontdis) { amat[2][2] = 0.0; } else { amat[2][2] = (float) 1.0 / (_core_vwstate.backdis - _core_vwstate.frontdis); } amat[3][3] = (float) 1.0; _core_push(&amat[0][0]); /* Spar */ _core_identity(&amat[0][0]); amat[3][0] = -(_core_vwstate.window.xmax + _core_vwstate.window.xmin) / 2; amat[3][1] = -(_core_vwstate.window.ymax + _core_vwstate.window.ymin) / 2; amat[3][2] = -_core_vwstate.frontdis; _core_push(&amat[0][0]); /* Tpar */ (void) _core_matcon(); /* Tpar*Spar */ _core_identity(&amat[0][0]); amat[2][0] = -(pt2[0]) / (pt2[2]); amat[2][1] = -(pt2[1]) / (pt2[2]); _core_push(&amat[0][0]); /* SHpar */ (void) _core_matcon(); /* SHpar*Tpar*Spar */ _core_push(&bmat[0][0]); (void) _core_matcon(); /* Twr*T*Ry*Rx*Rz*Trl*SHpar*Tpar*Spar */ return (0); } _core_moveword(a, b, c) short *a, *b, c; { /* move a word array, 16 bit words */ int i; for (i = 0; i < c; i++) *b++ = *a++; }