/* viewer3d.c * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information (NCBI) * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government do not place any restriction on its use or reproduction. * We would, however, appreciate having the NCBI and the author cited in * any work or product based on this material * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * =========================================================================== * * File Name: viewer3d.c * * Author: Alex Smirnov, Denis Vakatov * * Version Creation Date: 04/03/95 * * $Revision: 6.6 $ * * File Description: * * Modifications: * -------------------------------------------------------------------------- * $Log: viewer3d.c,v $ * Revision 6.6 2007/05/01 22:01:30 kans * changes in preparation for supporing Quartz on Macintosh * * Revision 6.5 2000/01/11 01:16:45 lewisg * fix color selection in Cn3D, other misc. bugs * * Revision 6.4 1998/08/12 23:04:06 vakatov * [64-bit platforms] Made "idBuffer" be VoidPtr[] rather than Int4[]; * Fixed bugs mostly caused by casting between Int4 vars and 8-byte pointers * * Revision 6.3 1998/08/07 22:27:00 vakatov * +FitZ() -- makes sure that picture does not outrun the "Z=0" plane * +GetSphere3D() -- to keep in-sync the viewer and static Nlm_stCon * * Revision 6.2 1998/04/20 18:30:36 lewisg * moved typedef for _Nlm_Viewer3D to include file * * Revision 6.1 1997/11/26 21:30:56 vakatov * Fixed errors and warnings issued by C and C++ (GNU and Sun) compilers * * Revision 5.17 1997/06/12 20:56:57 vakatov * Nlm_SetPosition3D() -- don't fail if the drawing area gets too small * ScreenToWorld() -- fixed memory leak * * Revision 5.16 1997/06/11 17:07:36 vakatov * DrawViewer3D(): redraw if p_version has changed * * Revision 5.15 1997/05/29 17:54:13 vakatov * Provided unconditional redraw of highlighted primitives * * Revision 5.14 1997/05/20 15:15:08 vakatov * Rotate(): on Z-rotation, now rotate around the center of currently * visible area(instead of the picture center); added ScreenToWorld() * function to map screen coordinates to the world ones * * Revision 5.13 1997/03/31 16:52:37 vakatov * Z-rotation implemented and added to alternative standard mouse * groups(-ZX and -YZ). Added Z-rotation scrollbar. * Moved all picture-rotation code from rotateXY(), QRotate() and * RotateViewer() to the new universal Rotate(). * * Revision 1.25 1997/03/31 16:18:12 vakatov * Fixed scrollbar updating (using ResetClip) in ViewerRotate. Other * minor fixes. * * Revision 1.24 1997/03/25 22:59:41 vakatov * All coord-rotation code from rotateXY(), QRotate() and RotateVierer() * moved to the new universal Rotate() * Z-rotation added to alternative standard mouse groups(-ZX and -YZ) * * Revision 1.23 1997/03/25 19:40:38 vakatov * Z-rotation works; wanna revise the former rotateXY() function to let * it rotate around an arbitrary point * * Revision 5.12 1997/03/21 16:17:05 vakatov * For SunOS compiler, casted most of the MemCpy() #1,#2 arguments to VoidPtr * * Revision 5.11 1997/03/20 19:03:16 vakatov * Heavily redesigned the 3D-Viewer code and internal data structures to work * with the new panel-mouse management. * Incapsulated code&data of the 3D-Viewer controls. * Added code for the "soft viewer resize". General code cleaning. * * Revision 5.10 1996/11/22 19:47:29 vakatov * Nlm_CreateViewer3D(): set image-dependent background color; * + extensive type casting * * Revision 5.9 1996/09/20 13:54:47 vakatov * Nlm_AttachPicture3D(): assign new picture *at first*; then do anyth. else * * Revision 5.8 1996/09/19 18:54:18 vakatov * Replace Reset() by CorrectBarValue() to avoid undesirable call to * the scrollbar callbacks * * Revision 5.7 1996/07/25 14:52:34 epstein * BigScalar change for OSF1 portability * * Revision 5.6 1996/07/24 16:59:59 vakatov * Trapped crashes caused by attempts to rotate and zoom blank 3D-pictures * * Revision 5.5 1996/07/23 21:51:29 vakatov * [WIN_MOTIF] Reserve 32th(instead of 0th) color for the background * color; it lets CN3D do not confuse other parts of the program and allows * to save the background color to GIF metafile * * Revision 5.3 1996/06/14 20:16:38 vakatov * [WIN_MSWIN] Slight modification in the bg-color setting * * Revision 5.2 1996/06/14 14:33:04 vakatov * Added a set of functions to control the 3D-Viewer background color * [WIN_MOTIF] Special precautions made to avoid Motif/3D-Viewer color conflict * * Revision 5.1 1996/06/07 15:19:39 hogue * Removed the PlayLayer button and sundry stuff from MAC. * * Revision 5.0 1996/05/28 13:45:08 ostell * Set to revision 5.0 * * Revision 1.23 1996/05/23 14:36:35 hogue * Fixed PrintViewer/PasteViewer discrepancy in .h file, added * IsPlaying3D, StopPlaying3D, StartPlaying3D for more * external control of the animation * * Revision 1.22 1996/05/21 22:00:40 vakatov * The viewer scrollbar width/height are now treated more carefully. * Do not store viewer width and height in the camera position storage as * it caused a coredump when resizing the viewer. * Viewer rotation flag is ON(was OFF) in the very begining. * * Revision 1.21 1996/05/14 15:29:08 hogue * Made the Horizontal viewer controls more compact. * * Revision 1.20 1996/05/13 15:04:21 hogue * Save button in Viewer Controls now optional * * Revision 1.19 1996/05/09 18:45:35 vakatov * There was a bug resulting the program crash while switching between * pictures with different number of layers(and then restoring the * camera position) -- fixed. * * Revision 1.18 1996/05/07 18:30:03 vakatov * Nlm_CreateViewer3D() -- slightly changed; * Nlm_AllLayerSetStates3D() function -- added; * Nlm_AllLayerSet3D() -- modified, "state" parameter added * Nlm_RewindLayer3D() -- prototype and content modified; * + a lot of variable casting and code simplifying * * Revision 1.17 1996/04/23 16:30:47 vakatov * Nlm_PlayLayer3D() -- fixed an extra(some cycles) delay responding to * the V3D_bPLAY("Go") toggle button release event * * Revision 1.16 1996/04/17 21:31:58 vakatov * Implemented "Nlm_SaveViewer3D()" function which allows one to save * presently visible part of the 3D-viewer picture into a GIF metafile. * Added "Copy" button to the 3D-viewer controls. * Fixed a bug caused by "the asynchroneous commenting" of "Print" and "Copy" * controls. * Added "Nlm_GetViewerImage3D()" function returning image of the 3D-viewer. * * Revision 1.15 1996/04/09 15:24:49 vakatov * Most of the basic, commonly used colors (0 - 15, eventually including * white and black) are not to be overwritten by the 3D-viewer image * drawing routine now. * The initial brightness level has been increased from 3 to 4 (43% to 57%). * * Revision 1.14 1996/04/07 20:04:56 kans * getlayertop3d needed (void) as prototype * * Revision 1.13 1996/04/04 18:58:39 vakatov * Slight corrections to the camera storing/restoring algorithm and * the relevant data to avoid the object/camera position mismatching -- * while setting the camera attributes stored during the work with another * picture. * * Revision 1.12 1996/04/03 16:03:33 vakatov * Now ZoomAll() can keep the camera angle (ZOOM_KEEP_ANGLE method) * * Revision 1.11 1996/04/02 22:30:02 vakatov * AttachZoomPic3D() removed; now previously stored camera position * is to be restored within AttachPicture3D automatically, as soon as * valid (non-NULL and initialized) "camera" argument is provided * * Revision 1.10 1996/04/01 23:07:03 vakatov * Now one can use prevously stored camera position * in the "AttachZoomPic3D(...,TRUE)" * * Revision 1.8 1996/03/30 23:48:02 hogue * removed unused variables, fixed a return value. * * Revision 1.7 1996/03/30 23:24:47 hogue * Cast MemCpy and Memset, changed camera to Int4, fixed nonportable uses of MemCpy, Added an AttachZoomPic . Cameras are still not always saved and restored correctly... * * ========================================================================== */ #include #ifndef _VIBRANT_ #include #endif #ifndef _VIEWER3D_ #include #endif #ifndef _PPICT3D_ #include #endif #include /***************************************************************************** * * DEFINES * *****************************************************************************/ #define CAMERA_KEY 8071967 #define FIND_BLOCK_SIZE 8 /***************************************************************************** * * TYPEDEFS and DECLARATIONS * *****************************************************************************/ typedef struct _Nlm_Viewer3D structViewer3D; typedef struct { Uint1 perspectN; Uint1 brighN; Uint1 colorPicN; Uint1 colorHLR, colorHLG, colorHLB; Uint1 colorFon; Uint1 adjust; Int4 scale; Uint1 colorFonR, colorFonG, colorFonB, dummy_align; } PCamera3DUnion; struct _Nlm_Controls3D { GrouP group; ButtoN zoomAll; ButtoN Move3D; ButtoN Zoom3D; GrouP adjustButtons; ButtoN plusButton; ButtoN minusButton; /* layer - animation controls */ ButtoN allButton; ButtoN rewindButton; ButtoN prevButton; ButtoN nextButton; ButtoN playButton; } structControls3D; typedef enum { ZOOM_ALL, ZOOM_KEEP_ANGLE, ZOOM_KEEP_ALL } enumZoom3D; typedef enum { ROTATE_X, ROTATE_Y, ROTATE_Z } enumRotate3D; /***************************************************************************** * * GLOBAL VARIABLES * *****************************************************************************/ Uint1 Nlm_Isqrt[129*129]; extern Nlm_Context3D Nlm_stCon; /***************************************************************************** * * STATIC VARIABLES * *****************************************************************************/ static CharPtr viewerClass = "Viewer3D"; static Boolean isqrtInit = FALSE; static Uint1 perspectAll[6] = { 8,6,4,3,2,1 }; static Int2 brighAll[7] = { -150,-100,-50,0,50,100,150 }; static Uint1 colorPicAll[6] = { 2,3,4,6,8,255 }; static Uint1 currlayer = 0; static ButtoN V3D_bPLAY = NULL; static Uint1 toplayer = 0; /***************************************************************************** * * STATIC FUNCTIONS * *****************************************************************************/ static void SetUpContext(Viewer3D vvv) { Nlm_stCon.xmin = (Int4)0; Nlm_stCon.xmax = (Int4)vvv->width - 1; Nlm_stCon.ymin = (Int4)0; Nlm_stCon.ymax = (Int4)vvv->height - 1; Nlm_stCon.zmax = vvv->zmax; Nlm_stCon.pic = vvv->pic; Nlm_stCon.width = (Int4)vvv->width; Nlm_stCon.height = (Int4)vvv->height; MemCpy(Nlm_stCon.layerTable, vvv->layerTable, sizeof(Nlm_stCon.layerTable)); MemCpy((VoidPtr)Nlm_stCon.a, (VoidPtr)vvv->a, sizeof(Nlm_stCon.a )); MemCpy((VoidPtr)Nlm_stCon.c, (VoidPtr)vvv->c, sizeof(Nlm_stCon.c )); Nlm_stCon.scale = vvv->scale; Nlm_stCon.colorOffset = vvv->colorOffset; Nlm_stCon.colorStep = vvv->colorStep; Nlm_stCon.colorScale = vvv->colorScale; Nlm_stCon.perspect = vvv->perspect; Nlm_stCon.zmaxPersp = Nlm_stCon.perspect * Nlm_stCon.zmax; Nlm_stCon.zmaxPersp1 = Nlm_stCon.zmaxPersp + Nlm_stCon.zmax; if ( vvv->pic ) Nlm_stCon.colorHL = (Uint1)((Nlm_PPict3DPtr)vvv->pic)->totalColors; } static Boolean GetSphere3D(Viewer3D vvv, Spher3D *sph) { SetUpContext(vvv); return Nlm_GetSegSphere3D(vvv->pic, NULL, sph); } static void MakeIntMat(Viewer3D vvv) { Int2 i; double PNTR dPtr = &vvv->dAOrt[0][0]; Int4 PNTR iPtr = &vvv->a[0][0]; for (i = 0; i < 9; i++) { double tmpDoub = *dPtr; if (tmpDoub < 1.0e-100 && tmpDoub > -1.0e-100) *iPtr = INT4_MAX; else { tmpDoub = vvv->dscale / tmpDoub; if (tmpDoub > (double)INT4_MAX) *iPtr = INT4_MAX; else if (tmpDoub < (double)INT4_MIN) *iPtr = INT4_MIN; else *iPtr = (Int4)tmpDoub; } dPtr++; iPtr++; } dPtr = vvv->dC; iPtr = vvv->c; for (i = 0; i < 3; i++) *iPtr++ = (Int4)(*dPtr++); vvv->scale = (Int4)vvv->dscale; } /* Adjust viewer along the Z axis */ static Boolean FitZ(Viewer3D vvv) { Spher3D sph; Int4 z_max; double z_offset; if ( !GetSphere3D(vvv, &sph) ) return FALSE; /* empty viewer picture */ z_max = (Int4)((double)sph.radius * 2.0 / vvv->dscale) + 1; z_offset = (double)((z_max>>1) + 1) - ((double)sph.x * vvv->dAOrt[2][0] + (double)sph.y * vvv->dAOrt[2][1] + (double)sph.z * vvv->dAOrt[2][2]) / vvv->dscale; if ((Int4)z_offset <= (Int4)vvv->dC[2]) return TRUE; /* picture fits the viewer(does not run out of Z=0 plane) */ /* adjust */ vvv->zmax = z_max; vvv->dC[2] = z_offset; vvv->colorScale = (vvv->zmax<<8) / vvv->colorStep; MakeIntMat(vvv); SetUpContext(vvv); return TRUE; } static void DrawViewer3D(Viewer3D vvv) { register Viewer3D VVV = vvv; register Nlm_PPict3DPtr PPP = (Nlm_PPict3DPtr)(VVV ? VVV->pic : NULL); if (PPP == NULL) return; Nlm_stCon.image = LockPixMapImage ( VVV->image ); if ( Nlm_stCon.image == NULL ) { Nlm_DiagPutRecord(DA_ERROR, viewerClass, "DrawViewer3D", "Cannot lock memory block"); return; } if (PPP->version != VVV->p_version || VVV->c_version != VVV->c_versionPrev) { Uint1 i, k, colorStep; Uint2 j; Int4 red, green, blue; Int4 colorPic; Int4 brigh, kbrigh; VVV->colorOffset = 33; colorStep = (Uint1)((256 - VVV->colorOffset) / (PPP->totalColors + 1)); if (colorStep > 32) colorStep = 32; VVV->colorStep = colorStep; i = (Uint1)VVV->colorOffset; colorPic = (Int4)colorPicAll[VVV->colorPicN]; brigh = (Int4)brighAll[VVV->brighN]; for (j = 0; j <= PPP->totalColors; j++) { if (j != PPP->totalColors) { red = PPP->colorR[j]; green = PPP->colorG[j]; blue = PPP->colorB[j]; } else { red = VVV->colorHLR; green = VVV->colorHLG; blue = VVV->colorHLB; } red = red + 2 * (255 - red ) / colorPic; green = green + 2 * (255 - green) / colorPic; blue = blue + 2 * (255 - blue ) / colorPic; for (k = 1; k <= colorStep; k++) { if (brigh >= 0) kbrigh = (256 - brigh) * k + brigh * colorStep; else kbrigh = (256 + brigh) * k; kbrigh /= (Int4)colorStep; SetColorImage(VVV->image, i++, (Uint1)((red * kbrigh)>>8), (Uint1)((green * kbrigh)>>8), (Uint1)((blue * kbrigh)>>8)); } } SetColorImage(VVV->image, VVV->colorFon, VVV->colorFonR, VVV->colorFonG, VVV->colorFonB); ImageSetPalette(VVV->image, VVV->parentWindow); VVV->c_versionPrev = VVV->c_version; if (VVV->p_version != PPP->version) { VVV->p_version = PPP->version; VVV->g_version++; } } if (VVV->g_version != VVV->g_versionPrev) { Uint2 iwidth, iheight; Nlm_stCon.zBuffer = (Uint2Ptr) HandLock( VVV->zBuffer ); if ( Nlm_stCon.zBuffer == NULL ) { Nlm_DiagPutRecord(DA_ERROR, viewerClass, "DrawViewer3D", "Can not lock memory block"); return; } VVV->colorScale = (VVV->zmax<<8) / VVV->colorStep; GetImageSize(VVV->image, &iwidth, &iheight); MemSet((void*)Nlm_stCon.image, VVV->colorFon, iwidth*iheight ); MemSet((void*)Nlm_stCon.zBuffer, 0, sizeof(Int2)*iwidth*iheight ); if ( FitZ(VVV) ) { PPP->seg.base.fTable->draw( &PPP->seg ); } ImageModified( VVV->image ); VVV->g_versionPrev = VVV->g_version; HandUnlock( VVV->zBuffer ); } {{ RecT r; PoinT p; ObjectRect(vvv->panel, &r); #ifdef WIN_MOTIF p.x = 2; p.y = 2; #else p.x = (Int2)(r.left + 2); p.y = (Int2)(r.top + 2); #endif ImageShow(VVV->image, p); }} UnlockPixMapImage( VVV->image ); } static void DrawViewer3D_CB(PaneL panel) { DrawViewer3D( PanelToViewer3D( panel ) ); } static void WorldToScreen(Viewer3D vvv, double x, double y, double z, double *xS, double *yS, double *zS) { register Viewer3D VVV = vvv; *xS = VVV->dC[0] + (x * VVV->dAOrt[0][0] + y * VVV->dAOrt[0][1] + z * VVV->dAOrt[0][2]) / VVV->dscale; *yS = VVV->dC[1] + (x * VVV->dAOrt[1][0] + y * VVV->dAOrt[1][1] + z * VVV->dAOrt[1][2]) / VVV->dscale; *zS = VVV->dC[2] + (x * VVV->dAOrt[2][0] + y * VVV->dAOrt[2][1] + z * VVV->dAOrt[2][2]) / VVV->dscale; } static void ScreenToWorld(Viewer3D vvv, double xS, double yS, double zS, double *x, double *y, double *z) { Uint4 i,j; Nlm_Matrix A = Nlm_MatrixNew(3, 3); Nlm_Matrix sV = Nlm_MatrixNew(3, 1); Nlm_Matrix wV; Nlm_MatrixSetNode(sV, 0, 0, (xS - vvv->dC[0]) * vvv->dscale); Nlm_MatrixSetNode(sV, 1, 0, (yS - vvv->dC[1]) * vvv->dscale); Nlm_MatrixSetNode(sV, 2, 0, (zS - vvv->dC[2]) * vvv->dscale); for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) Nlm_MatrixSetNode(A, i, j, vvv->dAOrt[i][j]); wV = Nlm_MatrixSolve(A, sV); *x = Nlm_MatrixNode(wV, 0, 0); *y = Nlm_MatrixNode(wV, 1, 0); *z = Nlm_MatrixNode(wV, 2, 0); Nlm_MatrixDelete( wV ); Nlm_MatrixDelete( sV ); Nlm_MatrixDelete( A ); } static void MakeOffsets(Viewer3D vvv, double xWorld, double yWorld, double zWorld, double xScreen, double yScreen, double zScreen) { vvv->dC[0] = xScreen - (xWorld * vvv->dAOrt[0][0] + yWorld * vvv->dAOrt[0][1] + zWorld * vvv->dAOrt[0][2]) / vvv->dscale; vvv->dC[1] = yScreen - (xWorld * vvv->dAOrt[1][0] + yWorld * vvv->dAOrt[1][1] + zWorld * vvv->dAOrt[1][2]) / vvv->dscale; vvv->dC[2] = zScreen - (xWorld * vvv->dAOrt[2][0] + yWorld * vvv->dAOrt[2][1] + zWorld * vvv->dAOrt[2][2]) / vvv->dscale; vvv->g_version++; } static void MakeFloatMat(Viewer3D vvv) { Int2 i; double PNTR dPtr = &vvv->dAOrt[0][0]; Int4 PNTR iPtr = &vvv->a[0][0]; vvv->dscale = (double)vvv->scale; for (i = 0; i < 9; i++, dPtr++, iPtr++) *dPtr = (iPtr != 0) ? (vvv->dscale / (double)*iPtr) : (vvv->dscale * 4); dPtr = vvv->dC; iPtr = vvv->c; for (i = 0; i < 3; i++) *dPtr++ = (double)(*iPtr++); } static void ZoomAll(Viewer3D vvv, enumZoom3D method) { Spher3D sph; Int4 diametr; if ( !GetSphere3D(vvv, &sph) ) return; diametr = sph.radius << 1; if (method == ZOOM_ALL) { vvv->dAOrt[0][0] = vvv->dAOrt[1][1] = vvv->dAOrt[2][2] = (double)1; vvv->dAOrt[0][1] = vvv->dAOrt[0][2] = vvv->dAOrt[1][0] = vvv->dAOrt[1][2] = vvv->dAOrt[2][0] = vvv->dAOrt[2][1] = (double)0; } if (method == ZOOM_KEEP_ALL && !vvv->is_zoomed) method = ZOOM_KEEP_ANGLE; if (method != ZOOM_KEEP_ALL) { double scale = (double)diametr / (double)MIN(vvv->width, vvv->height); if (scale < 10000.0) scale = 10000.0; vvv->dscale = (double)scale * (double)vvv->perspect / ((double)vvv->perspect + 0.5); vvv->is_zoomed = FALSE; } vvv->zmax = (Int4)((double)diametr / vvv->dscale) + 1; if (method != ZOOM_KEEP_ALL) { MakeOffsets(vvv, (double)sph.x, (double)sph.y, (double)sph.z, (double)(vvv->width>>1), (double)(vvv->height>>1), (double)((vvv->zmax>>1) + 1)); } else { vvv->dC[2] = (double)((vvv->zmax>>1) + 1) - ((double)sph.x * vvv->dAOrt[2][0] + (double)sph.y * vvv->dAOrt[2][1] + (double)sph.z * vvv->dAOrt[2][2]) / vvv->dscale; vvv->g_version++; } MakeIntMat( vvv ); } static void Move3D(Viewer3D vvv, Int2 dx, Int2 dy) { vvv->dC[0] += (double)dx; vvv->dC[1] -= (double)dy; MakeIntMat( vvv ); vvv->g_version++; } static void Zoom3D(Viewer3D vvv, Int2 x1, Int2 y1, Int2 x2, Int2 y2) { Spher3D sph; double scale; int width, height; if ( !GetSphere3D(vvv, &sph) ) return; {{ RecT r; ObjectRect(vvv->panel, &r); x1 -= r.left; x2 -= r.left; y1 -= r.top; y2 -= r.top; width = x2 - x1; if (width < 0) { width = -width; x1 = x2; } y1 = (Int2)(vvv->height - y1); y2 = (Int2)(vvv->height - y2); height = y2 - y1; if (height < 0) { height = -height; y1 = y2; } }} {{ double minscale = (double)sph.radius / 32000.0 / vvv->dscale; double d = (double)height / (double)vvv->height; scale = (double)width / (double)vvv->width; if (d > scale) scale = d; if (scale < minscale) scale = minscale; }} vvv->dC[0] = (vvv->dC[0] - (double)(x1+width /2)) / scale + vvv->width / 2; vvv->dC[1] = (vvv->dC[1] - (double)(y1+height/2)) / scale + vvv->height/ 2; vvv->dscale *= scale; vvv->zmax = (Int4)((double)sph.radius * 2.0 / vvv->dscale) + 1; vvv->dC[2] = (double)((vvv->zmax>>1) + 1) - ((double)sph.x * vvv->dAOrt[2][0] + (double)sph.y * vvv->dAOrt[2][1] + (double)sph.z * vvv->dAOrt[2][2]) / vvv->dscale; MakeIntMat( vvv ); vvv->g_version++; vvv->is_zoomed = TRUE; } /*********************************************************************** * Generic ROTATION functions */ static void Rotate(Viewer3D vvv, Int4 dAngle, enumRotate3D pivot) { double dx, dy, dz; double xx, yy, zz; double d; double ssin; double ccos; double a[3][3]; Spher3D sph; Int2 i,j; if ( !dAngle ) return; /* store viewport position */ if ( !GetSphere3D(vvv, &sph) ) return; WorldToScreen(vvv, (double)sph.x, (double)sph.y, (double)sph.z, &dx, &dy, &dz); if (pivot == ROTATE_Z) { /* rotate around the center of the visible area */ dx = vvv->width / 2; dy = vvv->height / 2; } ScreenToWorld(vvv, dx, dy, dz, &xx, &yy, &zz); /* compose rotation matrix */ d = (double)dAngle * NCBIMATH_PI / 180.0; ssin = sin( d ); ccos = cos( d ); for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) a[i][j] = 0.0; switch ( pivot ) { case ROTATE_X: a[0][0] = 1.0; a[1][1] = ccos; a[1][2] = ssin; a[2][1] = -ssin; a[2][2] = ccos; break; case ROTATE_Y: a[0][0] = ccos; a[0][2] = ssin; a[1][1] = 1.0; a[2][0] = -ssin; a[2][2] = ccos; break; case ROTATE_Z: a[0][0] = ccos; a[0][1] = ssin; a[1][0] = -ssin; a[1][1] = ccos; a[2][2] = 1.0; break; } {{ /* rotate */ double b[3][3]; for (j = 0; j < 3; j++) for (i = 0; i < 3; i++) { b[i][j] = a[i][0] * vvv->dAOrt[0][j] + a[i][1] * vvv->dAOrt[1][j] + a[i][2] * vvv->dAOrt[2][j]; } MemCpy((VoidPtr)vvv->dAOrt, (VoidPtr)b, sizeof(vvv->dAOrt)); }} /* restore viewport position */ MakeOffsets(vvv, xx, yy, zz, dx, dy, dz); MakeIntMat( vvv ); vvv->g_version++; } static void ViewerRotate(SlatE panel, Int4 delta, enumRotate3D pivot, Boolean adjust_scrollbar, Boolean redraw) { Viewer3D vvv; if (panel == NULL || !Visible(panel) || !AllParentsVisible(panel)) return; vvv = PanelToViewer3D( (PaneL)panel ); if ( adjust_scrollbar ) { /* adjust the relevant rotation scrollbar, if any */ BaR sbar = NULL; switch ( pivot ) { case ROTATE_X: sbar = GetSlateVScrollBar( panel ); break; case ROTATE_Y: sbar = GetSlateHScrollBar( panel ); break; case ROTATE_Z: sbar = vvv->z_rotate; break; } if ( sbar ) { ResetClip(); CorrectBarValue(sbar, (GetValue(sbar) + delta + 360) % 360); } } /* the coordination transformation (rotation) */ if (pivot == ROTATE_X) delta = -delta; Rotate(vvv, delta, pivot); if ( redraw ) { /* Draw the viewer */ WindoW tempPort = CurrentWindow(); UseWindow( ParentWindow(panel) ); Select( panel ); DrawViewer3D( vvv ); UseWindow( tempPort ); } Nlm_DiagReset(); } static void ResetViewerProc_CB(PaneL panel) { Viewer3D vvv = PanelToViewer3D( panel ); if ( !vvv ) return; vvv->panel = NULL; DeleteViewer3D( PanelToViewer3D( panel ) ); } static void ResetImage3D(Viewer3D vvv) { vvv->width = vvv->height = 0; if ( vvv->image ) { DeleteImage( vvv->image ); vvv->image = NULL; } if ( vvv->zBuffer ) { HandFree( vvv->zBuffer ); vvv->zBuffer = NULL; } } /*********************************************************************** * SCROLLBARS */ static void ViewerVScrollProc(BaR sb, SlatE viewer, Int2 newval, Int2 oldval) { ViewerRotate(viewer, newval - oldval, ROTATE_X, FALSE, TRUE); } static void ViewerHScrollProc(BaR sb, SlatE viewer, Int2 newval, Int2 oldval) { ViewerRotate(viewer, newval - oldval, ROTATE_Y, FALSE, TRUE); } static void ViewerZScrollProc(BaR sb, GraphiC group, Int2 newval, Int2 oldval) { SlatE viewer = (SlatE)GetObjectExtra( sb ); ViewerRotate(viewer, newval - oldval, ROTATE_Z, FALSE, TRUE); } /*********************************************************************** * PRIMITIVEs */ static Boolean Nlm_AddFoundPrim(Viewer3D vvv, Prim3D primId) { Uint2 i; if (primId == 0) return TRUE; for (i = 0; i < vvv->nPrimFound; i++) if (vvv->foundPrim[i] == primId) return TRUE; if (vvv->nPrimFound >= MAX_FOUND_PRIM) return FALSE; vvv->foundPrim[vvv->nPrimFound++] = primId; return TRUE; } static void Nlm_RedrawPrim3D(Viewer3D vvv, Nlm_Base3DPtr pBase) { if (vvv->pic == NULL) return; Nlm_stCon.image = LockPixMapImage( vvv->image ); if (Nlm_stCon.image == NULL) { Nlm_DiagPutRecord(DA_ERROR, viewerClass, "RedrawPrim3D", "Cannot lock image memory block"); return; } Nlm_stCon.zBuffer = (Uint2Ptr) HandLock( vvv->zBuffer ); if (Nlm_stCon.zBuffer == NULL) { UnlockPixMapImage( vvv->image ); Nlm_DiagPutRecord(DA_ERROR, viewerClass, "RedrawPrim3D", "Cannot lock Z-buffer memory block" ); return; } vvv->colorScale = (vvv->zmax<<8) / vvv->colorStep; SetUpContext( vvv ); if (pBase->status & HL_MASK) { Uint1 color = pBase->color; pBase->color = Nlm_stCon.colorHL; pBase->fTable->draw( (Nlm_VoidPtr)pBase ); pBase->color = color; } else { pBase->fTable->draw( (Nlm_VoidPtr)pBase ); } ImageModified( vvv->image ); HandUnlock( vvv->zBuffer ); UnlockPixMapImage( vvv->image ); } static void Nlm_ResetHLSeg3D(Segment3D segment) { register Nlm_Base3DPtr prim = (Nlm_Base3DPtr)segment; prim->status &= ~HL_MASK; for (prim = ((Nlm_PSeg3DPtr)prim)->first; prim; prim = prim->next) { if (prim->fTable->code == 0) Nlm_ResetHLSeg3D((Segment3D)prim); else prim->status &= ~HL_MASK; } } /*********************************************************************** * LAYERing */ static void Nlm_AllLayerSetStates3D(Viewer3D vvv, Nlm_Boolean state) { register Uint1 level = 0; do { SetLayer3D(vvv->pic, level, state); vvv->layerTable[level] = state; } while (level++ != 255); } NLM_EXTERN void Nlm_AllLayerSet3D(Viewer3D vvv, Nlm_Boolean state) { Spher3D sph; double dx, dy, dz; if (vvv == NULL || vvv->pic == NULL) return; Nlm_AllLayerSetStates3D(vvv, state); if ( GetSphere3D(vvv, &sph) ) { WorldToScreen (vvv, (double)sph.x, (double)sph.y, (double)sph.z, &dx, &dy, &dz ); MakeOffsets (vvv, (double)sph.x, (double)sph.y, (double)sph.z, dx, dy, dz ); MakeIntMat( vvv ); } RedrawViewer3D( vvv ); } static void Nlm_RewindLayer3D(Viewer3D vvv) { if (vvv == NULL || vvv->pic == NULL) return; Nlm_AllLayerSetStates3D(vvv, FALSE); SetLayer3D(vvv->pic, 1, TRUE); vvv->layerTable[0] = TRUE; currlayer = 0; RedrawViewer3D( vvv ); } extern void Nlm_PrevLayer3D (Viewer3D vvv) { if (vvv == NULL || vvv->pic == NULL) return; Nlm_AllLayerSetStates3D(vvv, FALSE); currlayer = (Uint1)((currlayer != 0) ? (currlayer - 1) : toplayer); SetLayer3D(vvv->pic, currlayer, TRUE); vvv->layerTable[currlayer] = TRUE; RedrawViewer3D( vvv ); } extern void Nlm_NextLayer3D(Viewer3D vvv) { if (vvv == NULL || vvv->pic == NULL) return; Nlm_AllLayerSetStates3D(vvv, FALSE); currlayer = (Uint1)((currlayer != toplayer) ? (currlayer + 1) : 0); SetLayer3D(vvv->pic, currlayer, TRUE); vvv->layerTable[currlayer] = TRUE; RedrawViewer3D( vvv ); } extern Boolean Nlm_IsPlaying3D(void) { #ifdef WIN_MAC return FALSE; #else return (Boolean)(V3D_bPLAY && GetStatus( V3D_bPLAY )); #endif } extern void Nlm_StopPlaying3D(void) { if ( V3D_bPLAY ) SetStatus(V3D_bPLAY, FALSE); } extern void Nlm_StartPlaying3D(Viewer3D vvv) { #ifndef WIN_MAC if ( V3D_bPLAY ) { SetStatus(V3D_bPLAY, TRUE); Nlm_PlayLayer3D( vvv ); } #endif } extern void Nlm_PlayLayer3D(Viewer3D vvv) { #ifndef WIN_MAC if (vvv == NULL || vvv->pic == NULL) return; Nlm_AllLayerSetStates3D(vvv, FALSE); SetLayer3D(vvv->pic, currlayer, TRUE); vvv->layerTable[currlayer] = TRUE; while (!QuittingProgram() && IsPlaying3D()) { SetLayer3D(vvv->pic, currlayer, FALSE); vvv->layerTable[currlayer] = FALSE; currlayer = (Uint1)((currlayer != toplayer) ? (currlayer + 1) : 0); SetLayer3D(vvv->pic, currlayer, TRUE); vvv->layerTable[currlayer] = TRUE; RedrawViewer3D( vvv ); while ( Nlm_EventAvail() ) Nlm_ProcessAnEvent(); } #endif } extern void Nlm_SetLayerTop3D(Uint1 top) { toplayer = top; } extern Uint1 Nlm_GetLayerTop3D(void) { return toplayer; } /*********************************************************************** * VIEWER CONTROLS ***********************************************************************/ /* Callbacks */ /* Animation callbacks */ static void AllLayerOnProc( ButtoN b ) { Nlm_AllLayerSet3D((Viewer3D)GetObjectExtra(b), TRUE); } static void RewindLayerProc(ButtoN b) { Nlm_RewindLayer3D( (Viewer3D)GetObjectExtra( b ) ); } static void PrevLayerProc(ButtoN b) { Nlm_PrevLayer3D( (Viewer3D)GetObjectExtra( b ) ); } static void NextLayerProc(ButtoN b) { Nlm_PrevLayer3D( (Viewer3D)GetObjectExtra( b ) ); } #ifndef WIN_MAC static void PlayLayerProc(ButtoN b) { Nlm_PlayLayer3D( (Viewer3D)GetObjectExtra( b ) ); } #endif /* Navigation callbacks */ static void UnzoomProc(ButtoN b) { Nlm_ZoomAll3D( (Viewer3D)GetObjectExtra( b ) ); } static void MoveProc(ButtoN b) { SetStdMouse3D((Viewer3D)GetObjectExtra( b ), Mouse3D_Move); MsgAlert(KEY_OK, SEV_INFO, "Cn3D Online Manual", "Use the [Shift] modifier key to move with mouse"); } static void ZoomProc(ButtoN b) { SetStdMouse3D((Viewer3D)GetObjectExtra( b ), Mouse3D_Zoom); MsgAlert(KEY_OK, SEV_INFO, "Cn3D Online Manual", "Use the [Control] modifier key to zoom with mouse"); } /* Adjustment callbacks */ static void AdjustProc(GrouP g) { Nlm_SetAdjust3D((Viewer3D)GetObjectExtra(g), (Uint1)GetValue(g)); } static void PlusProc(ButtoN b) { Nlm_Adjust3D((Viewer3D)GetObjectExtra( b ), TRUE); } static void MinusProc(ButtoN b) { Nlm_Adjust3D((Viewer3D)GetObjectExtra( b ), FALSE); } /* Create and place the viewer controls */ static GrouP BasicControls3D(GrouP prnt, Boolean vertical, Controls3D controls) { GrouP mGroup; GrouP tmpGroup; GrouP tmptmpGroup; Nlm_DiagReset(); if ( vertical ) { mGroup = HiddenGroup(prnt, 1, 0, NULL); #ifdef WIN_MOTIF SetGroupMargins(mGroup, 0, 0); #else SetGroupMargins(mGroup, 1, 1); #endif SetGroupSpacing(mGroup, 0, 0); StaticPrompt(mGroup, "Zoom:", 0, 0, Nlm_systemFont, 'c'); controls->zoomAll = PushButton(mGroup, "All", UnzoomProc); controls->Move3D = PushButton(mGroup, "Move", MoveProc ); controls->Zoom3D = PushButton(mGroup, "Zoom", ZoomProc ); StaticPrompt(mGroup, "------", 0, 0, Nlm_systemFont, 'c'); controls->adjustButtons = tmpGroup = HiddenGroup(mGroup, 1, 3, AdjustProc); RadioButton(tmpGroup, "Persp"); RadioButton(tmpGroup, "Brigh"); RadioButton(tmpGroup, "Color"); SetValue(tmpGroup, 1); tmpGroup = HiddenGroup(mGroup, 2, 1, NULL); controls->minusButton = PushButton(tmpGroup, "-", MinusProc); controls->plusButton = PushButton(tmpGroup, "+", PlusProc ); StaticPrompt(mGroup, "------", 0, 0, Nlm_systemFont, 'c'); } else { /* horizontal*/ /* rearranged to use a single horizontal group */ mGroup = HiddenGroup(prnt, 0, 1, NULL); SetGroupSpacing(mGroup, 6, 1); tmpGroup = HiddenGroup(mGroup, 3, 0, NULL); SetGroupSpacing(tmpGroup, 1, 0); controls->minusButton = PushButton(tmpGroup, "-", MinusProc); controls->adjustButtons = tmptmpGroup = HiddenGroup(tmpGroup, 3, 0, AdjustProc); RadioButton(tmptmpGroup, "p"); RadioButton(tmptmpGroup, "b"); RadioButton(tmptmpGroup, "c"); SetValue(tmptmpGroup, 1); controls->plusButton = PushButton(tmpGroup, "+", PlusProc); tmpGroup = HiddenGroup(mGroup, 4, 0, NULL); controls->zoomAll = PushButton(tmpGroup, "All", UnzoomProc); controls->Move3D = PushButton(tmpGroup, "Move", MoveProc ); controls->Zoom3D = PushButton(tmpGroup, "Zoom", ZoomProc ); } return mGroup; } static void FreeControls(GraphiC group, VoidPtr controls) { MemFree( controls ); } extern Controls3D Nlm_CreateControls3D(GrouP prnt, Boolean vertical, Boolean anim_ctrl, GrouP *ctrl_group) { Controls3D controls = (Controls3D)MemNew( sizeof(structControls3D) ); GrouP mGroup = BasicControls3D(prnt, vertical, controls); controls->group = mGroup; SetObjectExtra(controls->group, controls, FreeControls); if ( anim_ctrl ) { GrouP tmpGroup = mGroup; if ( vertical ) { StaticPrompt(mGroup, "Animate:", 0, 0, Nlm_systemFont, 'r'); tmpGroup = HiddenGroup(mGroup, 4, 1, NULL); } controls->allButton = PushButton(tmpGroup, "*", AllLayerOnProc); controls->rewindButton = PushButton(tmpGroup, "|<", RewindLayerProc); controls->prevButton = PushButton(tmpGroup, "<", PrevLayerProc); controls->nextButton = PushButton(tmpGroup, ">", NextLayerProc); #ifndef WIN_MAC V3D_bPLAY = controls->playButton = CheckBox(mGroup, "Go", PlayLayerProc); #endif } if ( ctrl_group ) *ctrl_group = mGroup; return controls; } extern void Nlm_DeleteControls3D(Controls3D controls) { Remove( controls->group ); } /* Link the viewer controls to a viewer */ static void Nlm_LinkBasicControls3D(Controls3D controls, Viewer3D vvv) { SetObjectExtra(controls->zoomAll, vvv, NULL); SetObjectExtra(controls->Move3D, vvv, NULL); SetObjectExtra(controls->Zoom3D, vvv, NULL); SetObjectExtra(controls->adjustButtons, vvv, NULL); SetObjectExtra(controls->plusButton, vvv, NULL); SetObjectExtra(controls->minusButton, vvv, NULL); } #ifndef WIN_MAC static void Cleanup_V3D_bPLAY(GraphiC playButton, VoidPtr vvv) { if ((ButtoN)playButton == V3D_bPLAY) V3D_bPLAY = NULL; } #endif extern void Nlm_LinkControls3D(Controls3D controls, Viewer3D vvv) { if (controls == NULL) return; Nlm_LinkBasicControls3D(controls, vvv); if ( !controls->allButton ) return; SetObjectExtra(controls->allButton, vvv, NULL); SetObjectExtra(controls->rewindButton, vvv, NULL); SetObjectExtra(controls->prevButton, vvv, NULL); SetObjectExtra(controls->nextButton, vvv, NULL); #ifndef WIN_MAC SetObjectExtra(controls->playButton, vvv, Cleanup_V3D_bPLAY); #endif } /* ADJUSTMENT (color, brightness, perspective) */ extern void Nlm_Adjust3D(Viewer3D vvv, Boolean plus) { Boolean needRedraw = FALSE; switch ( vvv->adjust ) { case ADJUST3D_PERSPECT: if ( plus ) { if (vvv->perspectN < 5) { vvv->perspectN++; needRedraw = TRUE; } } else { if (vvv->perspectN > 0) { vvv->perspectN--; needRedraw = TRUE; } } if ( needRedraw ) { Spher3D sph; double dx,dy,dz; vvv->g_version++; if ( !GetSphere3D(vvv, &sph) ) break; WorldToScreen(vvv, (double)sph.x, (double)sph.y, (double)sph.z, &dx, &dy, &dz); vvv->dscale = (vvv->dscale * (2.0 * (double)vvv->perspect + 1.0)) / (2.0 * (double)vvv->perspect); vvv->perspect = perspectAll[vvv->perspectN]; vvv->dscale = (vvv->dscale * 2.0 * (double)vvv->perspect) / (2.0 * (double)vvv->perspect + 1.0); vvv->zmax = (Int4)((double)(sph.radius<<1) / vvv->dscale) + 1; MakeOffsets(vvv, (double)sph.x, (double)sph.y, (double)sph.z, dx, dy, (double)((vvv->zmax>>1) + 1)); MakeIntMat( vvv ); } break; case ADJUST3D_BRIGH: if ( plus ) { if ( vvv->brighN < 6 ) { vvv->brighN++; vvv->c_version++; needRedraw = TRUE; } } else { if ( vvv->brighN > 0 ) { vvv->brighN--; vvv->c_version++; needRedraw = TRUE; } } break; case ADJUST3D_COLOR: if ( plus ) { if ( vvv->colorPicN < 5 ) { vvv->colorPicN++; vvv->c_version++; needRedraw = TRUE; } } else { if ( vvv->colorPicN > 0 ) { vvv->colorPicN--; vvv->c_version++; needRedraw = TRUE; } } } if ( needRedraw ) { WindoW tmpPort = SavePort( vvv->panel ); Select( vvv->panel ); DrawViewer3D ( vvv ); RestorePort( tmpPort ); Nlm_DiagReset(); } } /*********************************************************************** * MOUSE EVENT HANDLERS ***********************************************************************/ /* MOVE */ static void Move_DrawTrace(MA_TracePtr trace) { if ( EqualPt(trace->start, trace->end) ) return; #ifdef WIN_MOTIF SetColor( 0xf1 ); #endif InvertMode(); DrawLine(trace->start, trace->end); CopyMode(); } static void Move_PressMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { trace->start = trace->end = point; } static void Move_DragMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { Move_DrawTrace( trace ); trace->end = point; Move_DrawTrace( trace ); } static void Move_ReleaseMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { Move_DrawTrace( trace ); trace->end = point; if ( EqualPt(trace->start, trace->end) ) return; {{ Viewer3D vvv = MAToViewer3D( ma ); Move3D(vvv, (Int2)(trace->end.x - trace->start.x), (Int2)(trace->end.y - trace->start.y)); DrawViewer3D( vvv ); }} trace->start = trace->end; } static void Move_CancelMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { Move_DrawTrace( trace ); } /* ZOOM */ static void Zoom_DrawTrace(MA_TracePtr trace) { RecT rubber_box; if ( EqualPt(trace->start, trace->end) ) return; #ifdef WIN_MOTIF SetColor( 0xf1 ); #endif InvertMode(); LoadRect(&rubber_box, trace->start.x, trace->start.y, trace->end.x, trace->end.y); FrameRect( &rubber_box ); CopyMode(); } static void Zoom_PressMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { trace->start = trace->end = point; } static void Zoom_DragMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { Zoom_DrawTrace( trace ); trace->end = point; Zoom_DrawTrace( trace ); } static void Zoom_ReleaseMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { Zoom_DrawTrace( trace ); trace->end = point; if ( EqualPt(trace->start, trace->end) ) return; {{ Viewer3D vvv = MAToViewer3D( ma ); Zoom3D(vvv, trace->start.x, trace->start.y, trace->end.x, trace->end.y); DrawViewer3D( vvv ); }} } static void Zoom_CancelMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { Zoom_DrawTrace( trace ); } /* ROTATE */ typedef struct { enumRotate3D H; /* horizontal dragging */ enumRotate3D V; /* vertical dragging */ } RotatePivots3D, PNTR RotatePivots3DPtr; static void Rotate_PressMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { trace->start = point; } static void Rotate_DragMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { Viewer3D vvv = MAToViewer3D( ma ); RotatePivots3DPtr pivot = (RotatePivots3DPtr)extra; if ( EqualPt(trace->start, point) ) return; ViewerRotate((SlatE)vvv->panel, (Int4)((180.0 * (point.x - trace->start.x)) / vvv->width), pivot->H, TRUE, FALSE); ViewerRotate((SlatE)vvv->panel, (Int4)((180.0 * (point.y - trace->start.y)) / vvv->height), pivot->V, TRUE, TRUE); trace->start = point; } /* MISC */ static void Bg_HL_DClickMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { Viewer3D vvv = MAToViewer3D( ma ); Uint2 n_prim = FindPrim3D(vvv, point); if ( n_prim ) { /* Highlight primitive */ Prim3D prim = GetFoundPrim3D(vvv, 0); SetHLColor3D(vvv, 0, 255, 0); HighlightPrim3D(vvv, prim, (Boolean)(!IsPrim3DHlighted(vvv, prim))); RedrawViewer3D( vvv ); } else { /* Choose and change viewer background color */ if ( ChooseColorDialog(&vvv->colorFonR, &vvv->colorFonG, &vvv->colorFonB, 0) ) Nlm_SetBackground3D(vvv, vvv->colorFonR, vvv->colorFonG, vvv->colorFonB); } } /* RESET */ static void ResetMA(MAPtr ma, MA_TracePtr trace, PoinT point, VoidPtr extra) { VERIFY ( MA_UnsetAll( ma ) ); } /* Initialize MA for the viewer */ static Boolean InitializeMA(Viewer3D vvv) { MAPtr ma = vvv->ma; /* rotate */ MActionPtr rotate_press = MA_AddAction(ma, MK_Normal, MA_Press, Rotate_PressMA, NULL, NULL); static RotatePivots3D RotateDrag_YX = { ROTATE_Y, ROTATE_X }; MActionPtr rotate_drag_YX = MA_AddAction(ma, MK_Normal, MA_Drag, Rotate_DragMA, &RotateDrag_YX, NULL); MA_GroupPtr rotate_group_YX = MA_AddGroup(ma, "Rotate_YX", rotate_press, MA_ONLY, rotate_drag_YX, MA_ONLY, NULL); static RotatePivots3D RotateDrag_ZX = { ROTATE_Z, ROTATE_X }; MActionPtr rotate_drag_ZX = MA_AddAction(ma, MK_Normal, MA_Drag, Rotate_DragMA, &RotateDrag_ZX, NULL); MA_GroupPtr rotate_group_ZX = MA_AddGroup(ma, "Rotate_ZX", rotate_press, MA_ONLY, rotate_drag_ZX, MA_ONLY, NULL); static RotatePivots3D RotateDrag_YZ = { ROTATE_Y, ROTATE_Z }; MActionPtr rotate_drag_YZ = MA_AddAction(ma, MK_Normal, MA_Drag, Rotate_DragMA, &RotateDrag_YZ, NULL); MA_GroupPtr rotate_group_YZ = MA_AddGroup(ma, "Rotate_YZ", rotate_press, MA_ONLY, rotate_drag_YZ, MA_ONLY, NULL); /* move */ MActionPtr move_press = MA_AddAction(ma, MK_Shift, MA_Press, Move_PressMA, NULL, NULL); MActionPtr move_drag = MA_AddAction(ma, MK_Shift, MA_Drag, Move_DragMA, NULL, NULL); MActionPtr move_release = MA_AddAction(ma, MK_Shift, MA_Release, Move_ReleaseMA, NULL, NULL); MActionPtr move_cancel = MA_AddAction(ma, MK_Shift, MA_Cancel, Move_CancelMA, NULL, NULL); MA_GroupPtr move_group = MA_AddGroup(ma, "Move", move_press, MA_ONLY, move_drag, MA_ONLY, move_release, MA_ONLY, move_cancel, MA_ONLY, NULL); /* zoom */ MActionPtr zoom_press = MA_AddAction(ma, MK_Ctrl, MA_Press, Zoom_PressMA, NULL, NULL); MActionPtr zoom_drag = MA_AddAction(ma, MK_Ctrl, MA_Drag, Zoom_DragMA, NULL, NULL); MActionPtr zoom_release = MA_AddAction(ma, MK_Ctrl, MA_Release, Zoom_ReleaseMA, NULL, NULL); MActionPtr zoom_cancel = MA_AddAction(ma, MK_Ctrl, MA_Cancel, Zoom_CancelMA, NULL, NULL); MA_GroupPtr zoom_group = MA_AddGroup(ma, "Zoom", zoom_press, MA_ONLY, zoom_drag, MA_ONLY, zoom_release, MA_ONLY, zoom_cancel, MA_ONLY, NULL); /* miscellaneous actions */ MActionPtr bg_hl_dclick = MA_AddAction(ma, MK_Normal, MA_DClick, Bg_HL_DClickMA, NULL, "Highlight-Prim or Background"); /* this group disables all mouse actions when set */ MActionPtr reset_init = MA_AddAction(ma, MK_Normal, MA_Init, ResetMA, NULL, NULL); MA_GroupPtr reset_group = MA_AddGroup(ma, "No Action", reset_init, MA_SHARED, NULL); {{ /* "No-Action"s */ int i, j; for (i = 0; i < MK_Default; i++) for (j = 0; j < MA_Init; j++) { VERIFY ( MA_AddAction(ma, (enumMKey)i, (enumMAction)j, DoNothingMA, NULL, "No Action") ); } }} /* register the set of standard 3D-viewer groups */ vvv->ma_std_group[Mouse3D_DoNothing] = reset_group; vvv->ma_std_group[Mouse3D_RotateYX ] = rotate_group_YX; vvv->ma_std_group[Mouse3D_RotateZX ] = rotate_group_ZX; vvv->ma_std_group[Mouse3D_RotateYZ ] = rotate_group_YZ; vvv->ma_std_group[Mouse3D_Move ] = move_group; vvv->ma_std_group[Mouse3D_Zoom ] = zoom_group; /* Test, Setup defaults and Link viewer panel to MA */ if (!rotate_press || !rotate_drag_YX || !rotate_group_YX || !rotate_drag_ZX || !rotate_group_ZX || !rotate_drag_YZ || !rotate_group_YZ || !move_press || !move_drag || !move_release || !move_cancel || !move_group || !zoom_press || !zoom_drag || !zoom_release || !zoom_cancel || !zoom_group || !bg_hl_dclick || !reset_group || !SetStdMouse3D(vvv, Mouse3D_RotateYX) || !SetStdMouse3D(vvv, Mouse3D_Move ) || !SetStdMouse3D(vvv, Mouse3D_Zoom ) || !MA_SetAction(bg_hl_dclick, FALSE) || !MA_LinkPanel(ma, vvv->panel)) { MA_Reset( ma ); return FALSE; } return TRUE; } /***************************************************************************** * * EXTERNAL FUNCTIONS * *****************************************************************************/ /* * Viewer data access */ extern Viewer3D MAToViewer3D(MAPtr ma) { return (Viewer3D)MA_GetExtra( ma ); } extern Viewer3D PanelToViewer3D(PaneL panel) { MAPtr ma; GetPanelExtra(panel, &ma); return MAToViewer3D( ma ); } extern void Nlm_SetAdjust3D(Viewer3D vvv, Uint1 ajust) { if ( vvv ) vvv->adjust = ajust; } extern void Nlm_SetHLColor3D(Viewer3D vvv, Uint1 red, Uint1 green, Uint1 blue ) { Nlm_DiagReset(); if (vvv == NULL) return; vvv->colorHLR = red; vvv->colorHLG = green; vvv->colorHLB = blue; vvv->c_version++; } extern Nlm_Image Nlm_GetViewerImage3D(Viewer3D vvv) { return vvv->image; } extern void Nlm_GetViewerInfo3D(Viewer3D vvv, Picture3D PNTR pic, Nlm_Camera3DPtr camera, RectPtr rectangle) { PCamera3DUnion camUnn; Nlm_DiagReset(); if (pic != NULL) *pic = NULL; if (vvv == NULL) return; if (pic != NULL) *pic = vvv->pic; if (camera != NULL && vvv->pic != NULL) { camera->dummy[0] = CAMERA_KEY; MemCpy((VoidPtr)&camera->dummy[1], (VoidPtr)vvv->a, sizeof(vvv->a)); MemCpy((VoidPtr)&camera->dummy[10], (VoidPtr)vvv->c, sizeof(vvv->c)); camUnn.colorHLR = vvv->colorHLR; camUnn.colorHLG = vvv->colorHLG; camUnn.colorHLB = vvv->colorHLB; camUnn.perspectN = vvv->perspectN; camUnn.brighN = vvv->brighN; camUnn.colorPicN = vvv->colorPicN; camUnn.colorFon = vvv->colorFon; camUnn.colorFonR = vvv->colorFonR; camUnn.colorFonG = vvv->colorFonG; camUnn.colorFonB = vvv->colorFonB; camUnn.adjust = vvv->adjust; camUnn.scale = vvv->scale; MemCpy((VoidPtr)&camera->dummy[13], (VoidPtr)&camUnn, sizeof(camUnn)); } if (rectangle != NULL) ObjectRect(vvv->panel, rectangle); } extern Prim3D Nlm_GetFoundPrim3D(Viewer3D vvv, Uint2 primIndex) { Nlm_DiagReset(); if (vvv == NULL || primIndex >= vvv->nPrimFound) return NULL; return vvv->foundPrim[primIndex]; } extern Boolean Nlm_IsSeg3DHlighted(Viewer3D vvv, Segment3D segment) { Nlm_DiagReset(); return (Boolean)(segment != NULL && (((Nlm_Base3DPtr)segment)->status & HL_SEGMENT)); } extern Boolean Nlm_IsPrim3DHlighted(Viewer3D vvv, Prim3D prim) { Nlm_DiagReset(); return (Boolean) (prim != NULL && (((Nlm_Base3DPtr)prim)->status & HL_PRIMITIVE)); } extern void Nlm_SetBackground3D(Nlm_Viewer3D vvv, Nlm_Uint1 red, Nlm_Uint1 green, Nlm_Uint1 blue) { if (vvv == NULL) return; SetColorCell((Nlm_GraphiC)vvv->panel, vvv->colorFon, (vvv->colorFonR = red), (vvv->colorFonG = green), (vvv->colorFonB = blue)); vvv->c_version++; } /* * Viewer auxiliary routines */ extern void BgColorDlg3D(Viewer3D vvv) { /* Choose and change the viewer background color */ if ( ChooseColorDialog(&vvv->colorFonR, &vvv->colorFonG, &vvv->colorFonB, 0) ) Nlm_SetBackground3D(vvv, vvv->colorFonR, vvv->colorFonG, vvv->colorFonB); } extern void Nlm_ZoomAll3D(Viewer3D vvv) { WindoW tmpPort; if (!Visible(vvv->panel) || !AllParentsVisible(vvv->panel)) return; ZoomAll(vvv, ZOOM_KEEP_ANGLE); tmpPort = SavePort( vvv->panel ); Select( vvv->panel ); DrawViewer3D( vvv ); RestorePort( tmpPort ); Nlm_DiagReset(); } #ifndef WIN_MOTIF extern void Nlm_CopyViewer3D(Viewer3D vvv) { SaveImageClip( vvv->image ); } extern void Nlm_PrintViewer3D(Viewer3D vvv) { PrintImage( vvv->image ); } #endif extern void Nlm_SaveViewer3D(Viewer3D vvv) { Char fname[PATH_MAX]; if ( !GetOutputFileName(fname, sizeof(fname), "*.gif") ) return; SaveImageGIF(vvv->image, fname); } extern Uint2 Nlm_FindPrim3D(Viewer3D vvv, PoinT pt) { Nlm_PPict3DPtr PPP; RecT r; int i,j,k; int x, y; Nlm_DiagReset(); if (vvv == NULL) return 0; ObjectRect(vvv->panel, &r); Nlm_stCon.zBuffer = (Uint2Ptr)MemNew((2*FIND_BLOCK_SIZE+1) * (2*FIND_BLOCK_SIZE+1) * sizeof(Uint2)); Nlm_stCon.idBuffer = (VoidPtr*)MemNew((2*FIND_BLOCK_SIZE+1) * (2*FIND_BLOCK_SIZE+1) * sizeof(VoidPtr)); if (!Nlm_stCon.zBuffer || !Nlm_stCon.idBuffer) { Nlm_DiagPutRecord(DA_ERROR, viewerClass, "FindPrim3D", "Cannot lock memory block"); Nlm_stCon.zBuffer = (Uint2Ptr)MemFree(Nlm_stCon.zBuffer); Nlm_stCon.idBuffer = (VoidPtr*)MemFree(Nlm_stCon.idBuffer); return 0; } PPP = (Nlm_PPict3DPtr)vvv->pic; pt.x -= r.left + 2; pt.y -= r.top + 4; #ifdef NEGYSCREEN pt.y = (Int2)(vvv->height - pt.y); #endif SetUpContext( vvv ); Nlm_stCon.widthCur = Nlm_stCon.heightCur = FIND_BLOCK_SIZE * 2 + 1; Nlm_UpdateGver( PPP ); Nlm_stCon.xmin = pt.x - FIND_BLOCK_SIZE; Nlm_stCon.xmax = pt.x + FIND_BLOCK_SIZE; Nlm_stCon.ymin = pt.y - FIND_BLOCK_SIZE; Nlm_stCon.ymax = pt.y + FIND_BLOCK_SIZE; PPP->seg.base.fTable->hittest( (Nlm_VoidPtr)&PPP->seg ); vvv->nPrimFound = 0; for (i = 0; i <= (FIND_BLOCK_SIZE - 1); i++) for (j = -i; j <= i; j++) for (k = 0; k < 4; k++) { switch ( k ) { case 0: x = -j; y = -i; break; case 1: x = j; y = i; break; case 2: x = -i; y = j; break; default: x = i; y = -j; } x += FIND_BLOCK_SIZE; y += FIND_BLOCK_SIZE; Nlm_AddFoundPrim(vvv, (Prim3D)Nlm_stCon.idBuffer[y * (FIND_BLOCK_SIZE+1) + x]); } Nlm_stCon.zBuffer = (Uint2Ptr) MemFree( Nlm_stCon.zBuffer ); Nlm_stCon.idBuffer = (VoidPtr*) MemFree( Nlm_stCon.idBuffer ); return vvv->nPrimFound; } extern void Nlm_HighlightSeg3D(Viewer3D vvv, Segment3D segment, Boolean highlight) { register Nlm_Base3DPtr prim = (Nlm_Base3DPtr)segment; Nlm_DiagReset(); if (vvv == NULL || prim == 0) return; if ( highlight ) prim->status |= HL_SEGMENT; else prim->status &= ~HL_MASK; for (prim = ((Nlm_PSeg3DPtr)prim)->first; prim; prim = prim->next) { if (prim->fTable->code == 0) Nlm_HighlightSeg3D(vvv, (Segment3D)prim, highlight); else if ( highlight ) prim->status |= HL_SEGMENT; else prim->status &= ~HL_SEGMENT; } {{ register Nlm_PPict3DPtr PPP = (Nlm_PPict3DPtr)vvv->pic; if (PPP->version == vvv->p_version) { Nlm_RedrawPrim3D(vvv, (Nlm_Base3DPtr)segment); vvv->p_version++; } PPP->version++; }} } extern void Nlm_HighlightPrim3D(Viewer3D vvv, Prim3D prim, Boolean highlight) { Nlm_DiagReset(); if (vvv == NULL || prim == NULL) return; if ( highlight ) ((Nlm_Base3DPtr)prim)->status |= HL_PRIMITIVE; else ((Nlm_Base3DPtr)prim)->status &= ~HL_PRIMITIVE; {{ register Nlm_PPict3DPtr PPP = (Nlm_PPict3DPtr)vvv->pic; if (PPP->version == vvv->p_version) { Nlm_RedrawPrim3D(vvv, (Nlm_Base3DPtr)prim); vvv->p_version++; } PPP->version++; }} } extern Boolean Nlm_ResetHighlight3D(Viewer3D vvv) { Nlm_DiagReset(); if (vvv != NULL && vvv->pic != NULL) { register Nlm_PPict3DPtr PPP = (Nlm_PPict3DPtr)vvv->pic; Nlm_ResetHLSeg3D( (Segment3D)&PPP->seg ); PPP->version++; } return TRUE; } extern Boolean Nlm_MapWorldToViewer3D(Viewer3D vvv, Int4 x, Int4 y, Int4 z, PoinT PNTR vPoint) { register Viewer3D VVV = vvv; Int4 xs, ys, zs; Int4 t4, zmaxPersp, zmaxPersp1; Nlm_DiagReset(); if (VVV == NULL) return FALSE; zmaxPersp = VVV->perspect * VVV->zmax; zmaxPersp1 = zmaxPersp + VVV->zmax; xs = x/VVV->a[0][0] + y/VVV->a[0][1] + z/VVV->a[0][2] + VVV->c[0]; ys = x/VVV->a[1][0] + y/VVV->a[1][1] + z/VVV->a[1][2] + VVV->c[1]; zs = x/VVV->a[2][0] + y/VVV->a[2][1] + z/VVV->a[2][2] + VVV->c[2]; t4 = xs - (VVV->width >>1); xs = (VVV->width >>1) + (t4 * zmaxPersp) / (zmaxPersp1 - zs); t4 = ys - (VVV->height>>1); ys = (VVV->height>>1) - (t4 * zmaxPersp) / (zmaxPersp1 - zs); vPoint->x = (Int2)xs; vPoint->y = (Int2)ys; return TRUE; } extern Boolean Nlm_SetStdMouse3D(Viewer3D vvv, enumStdMA3D action) { return MA_SetGroup( vvv->ma_std_group[action] ); } /* * Viewer general management */ extern Viewer3D Nlm_CreateViewer3D(GrouP prnt, Uint2Ptr width, Uint2 height, Int4 flags, MenU ma_group_menu, MenU ma_action_menu, Nlm_MAInit3DFunc ma_init_func, VoidPtr ma_init_data) { Viewer3D vvv = NULL; CharPtr err_msg = NULL; while ( TRUE ) {{{ /* TRY! */ Int4 i; Uint2 x_width; Nlm_DiagReset(); if ( !isqrtInit ) { Int4 j, k = 0; for (i = 0; i < 128; i++) for (j = -i; j <= i; j++) Nlm_Isqrt[k++] = (Uint1)(sqrt( (double)(i*i - j*j) )); isqrtInit = TRUE; } vvv = (Viewer3D)MemNew( sizeof(structViewer3D) ); if (vvv == NULL) { err_msg = "Cannot allocate memory block for the viewer"; break; } vvv->parentWindow = ParentWindow( (Handle)prnt ); vvv->panel = AutonomousPanel(prnt, (Int2)*width, (Int2)height, DrawViewer3D_CB, ((flags & Y_ROTATE_SBAR) ? ViewerVScrollProc : NULL), ((flags & X_ROTATE_SBAR) ? ViewerHScrollProc : NULL), sizeof(MAPtr), ResetViewerProc_CB, NULL); if ( !vvv->panel ) { err_msg = "Cannot create panel"; break; } if (flags & Z_ROTATE_SBAR) { vvv->z_rotate = ScrollBar(prnt, 1, 0, ViewerZScrollProc); if ( !vvv->z_rotate ) { err_msg = "Cannot create Z-rotation scrollbar"; break; } SetObjectExtra(vvv->z_rotate, vvv->panel, NULL); } {{ RecT rect; GetPosition(vvv->panel, &rect); rect.right = (Int2)(rect.left + *width); rect.bottom = (Int2)(rect.top + height); if ( !SetPosition3D(vvv, &rect) ) { err_msg = "Cannot allocate memory for the viewer image & zBuffer"; break; } x_width = (Uint2)(rect.right - rect.left); }} vvv->colorHLR = vvv->colorHLG = vvv->colorHLB = (Uint1)255; vvv->colorFon = ImageGetBlack( vvv->image ); vvv->colorFonR = vvv->colorFonG = vvv->colorFonB = (Uint1)0; for ( i=0; i<256; i++ ) vvv->layerTable[i] = TRUE; if (flags & X_ROTATE_SBAR) { BaR sb = GetSlateHScrollBar( (SlatE)vvv->panel ); CorrectBarValue(sb, 0); SetRange(sb, 10, 10, 360); } if (flags & Y_ROTATE_SBAR) { BaR sb = GetSlateVScrollBar( (SlatE)vvv->panel ); CorrectBarValue(sb, 0); SetRange(sb, 10, 10, 360); } if (flags & Z_ROTATE_SBAR) { SetRange(vvv->z_rotate, 10, 10, 360); CorrectBarValue(vvv->z_rotate, 180); } vvv->adjust = ADJUST3D_PERSPECT; vvv->ma = MA_Create(ma_group_menu, ma_action_menu); MA_SetExtra(vvv->ma, vvv); if ( !InitializeMA( vvv ) ) { err_msg = "Cannot create/initialize standard mouse controls"; break; } if (ma_init_func && !(*ma_init_func)(vvv->ma, ma_init_data)) { err_msg = "Cannot create/initialize user-specified mouse controls"; break; } *width = x_width; return vvv; }}} /* End of TRY; below is the CATCH block(post-error cleaning code): */ ASSERT ( err_msg ); Nlm_DiagPutRecord(DA_ERROR, viewerClass, "CreateViewer3D", err_msg); if ( vvv ) { if ( vvv->panel ) Remove( vvv->panel ); if ( vvv->z_rotate ) Remove( vvv->z_rotate ); ResetImage3D( vvv ); MemFree( vvv ); } return NULL; } extern Boolean Nlm_SetPosition3D(Viewer3D vvv, RectPtr rect) { Int4 width = rect->right - rect->left; Int4 height = rect->bottom - rect->top; Nlm_DiagReset(); ResetImage3D( vvv ); if ( vvv->z_rotate ) { rect->top += Nlm_hScrollBarHeight; height -= Nlm_hScrollBarHeight; } if ( GetSlateVScrollBar((SlatE)vvv->panel) ) width -= Nlm_vScrollBarWidth + 3; if ( GetSlateHScrollBar((SlatE)vvv->panel) ) height -= Nlm_hScrollBarHeight + 3; if (width < 16 || height < 16 #ifdef WIN16 || width * height > (Int4)0x7FFF #endif ) return FALSE; vvv->image = CreateImage(); if (vvv->image == NULL) return FALSE; {{ Uint2 x_width = (Uint2)width; if ( !AllocateImage(vvv->image, &x_width, (Uint2)height, 32, 256) ) { ResetImage3D( vvv ); return FALSE; } width = x_width; }} vvv->width = (Int2)width; vvv->height = (Int2)height; vvv->zBuffer = HandNew(sizeof(Int2) * vvv->width * vvv->height); if (vvv->zBuffer == NULL) { ResetImage3D( vvv ); return FALSE; } vvv->g_version++; vvv->c_version++; ZoomAll(vvv, ZOOM_KEEP_ALL); rect->right = (Int2)(rect->left + vvv->width + 3); rect->bottom = (Int2)(rect->top + vvv->height + 3); if ( GetSlateVScrollBar((SlatE)vvv->panel) ) rect->right += Nlm_vScrollBarWidth; if ( GetSlateHScrollBar((SlatE)vvv->panel) ) rect->bottom += Nlm_hScrollBarHeight; SetPosition(vvv->panel, rect); ProcessUpdatesFirst( FALSE ); AdjustPrnt(vvv->panel, rect, FALSE); if ( vvv->z_rotate ) { rect->bottom = rect->top; rect->top -= Nlm_hScrollBarHeight; SetPosition(vvv->z_rotate, rect); } return TRUE; } extern Boolean Nlm_AttachPicture3D(Viewer3D vvv, Picture3D picture, Nlm_Camera3DPtr camera) { Nlm_PPict3DPtr PPP = (Nlm_PPict3DPtr)picture; Nlm_DiagReset(); if (vvv == NULL) return FALSE; vvv->pic = NULL; {{ BaR sb; sb = GetSlateHScrollBar( (SlatE)vvv->panel ); if ( sb ) { CorrectBarValue(sb, 0); SetRange(sb, 10, 10, 360); } sb = GetSlateVScrollBar( (SlatE)vvv->panel ); if ( sb ) { CorrectBarValue(sb, 0); SetRange(sb, 10, 10, 360); } if ( vvv->z_rotate ) { CorrectBarValue(vvv->z_rotate, 180); SetRange(vvv->z_rotate, 10, 10, 360); } }} vvv->pic = picture; ASSERT ( sizeof(vvv->layerTable) == sizeof(PPP->layerTable) ); MemCpy(vvv->layerTable, PPP->layerTable, sizeof(vvv->layerTable)); SetLayer3D(picture, 1, TRUE); vvv->layerTable[0] = TRUE; currlayer = 0; ASSERT ( CAMERA_SIZE_I4 * sizeof(Int4) == sizeof(camera->dummy) ); if (camera != NULL && camera->dummy[0] == CAMERA_KEY) { PCamera3DUnion camUnn; ASSERT ( sizeof(vvv->a) <= sizeof(camera->dummy) - 1*sizeof(camera->dummy[0]) ); MemCpy((VoidPtr)vvv->a, (VoidPtr)&camera->dummy[1], sizeof(vvv->a)); ASSERT ( sizeof(vvv->c) <= sizeof(camera->dummy) - 10*sizeof(camera->dummy[0]) ); MemCpy((VoidPtr)vvv->c, (VoidPtr)&camera->dummy[10], sizeof(vvv->c)); ASSERT ( sizeof(camUnn) <= sizeof(camera->dummy) - 13*sizeof(camera->dummy[0]) ); MemCpy((VoidPtr)&camUnn, (VoidPtr)&camera->dummy[13], sizeof(camUnn)); vvv->perspectN = camUnn.perspectN; vvv->perspect = perspectAll[vvv->perspectN]; vvv->brighN = camUnn.brighN; vvv->colorPicN = camUnn.colorPicN; vvv->colorHLR = camUnn.colorHLR; vvv->colorHLG = camUnn.colorHLG; vvv->colorHLB = camUnn.colorHLB; vvv->colorFon = camUnn.colorFon; vvv->colorFonR = camUnn.colorFonR; vvv->colorFonG = camUnn.colorFonG; vvv->colorFonB = camUnn.colorFonB; vvv->adjust = camUnn.adjust; vvv->scale = camUnn.scale; MakeFloatMat( vvv ); ZoomAll(vvv, ZOOM_KEEP_ALL); } else { vvv->perspectN = 2; vvv->perspect = perspectAll[vvv->perspectN]; vvv->brighN = 5; vvv->colorPicN = 5; ZoomAll(vvv, ZOOM_ALL); } vvv->c_version++; vvv->g_version++; SetUpContext( vvv ); if (Visible(vvv->panel) && AllParentsVisible(vvv->panel)) { RecT r; WindoW tempPort = SavePort( vvv->panel ); Select( vvv->panel ); ObjectRect(vvv->panel, &r); InvalRect( &r ); RestorePort( tempPort ); } return DiagHasErrorRec(); } extern Boolean Nlm_RedrawViewer3D(Viewer3D vvv) { Nlm_DiagReset(); if (!Visible( vvv->panel ) || !AllParentsVisible( vvv->panel )) return FALSE; {{ WindoW tempPort = SavePort( vvv->panel ); Select( vvv->panel ); DrawViewer3D( vvv ); RestorePort( tempPort ); }} return DiagHasErrorRec(); } extern void Nlm_DeleteViewer3D(Nlm_Viewer3D vvv) { if (vvv == NULL) return; Nlm_DiagReset(); MA_Destroy( vvv->ma ); ResetImage3D( vvv ); if ( vvv->panel ) Remove( vvv->panel ); MemFree( vvv ); }