/* PROJECT: GDI3D DLL PROGRAMMER(S): Pasi Paavola COMPILER: Microsoft C/C++ 7.0 ENVIRONMENT: Windows 3.1 running on 386/33/SuperVGA/no 80x87 386 enhanced mode ROUTINES: General services and G3 management */ #include #include #include "3d\gdi3d.h" #include "3d\intern.h" // Allocate storage for globals //#define GLOBALS #include "3d\globals.h" #define GLOB #define INI(x) = x #define INIT(x) x GLOB int GiVersion INI(0x0009); // Version 0xabnm means version ab.nm GLOB HWND GhWnd INI(NULL); // Handle of the current window GLOB HINSTANCE GhInst INI(NULL); // Instance handle of this module GLOB BOOL GbClRegistered INI(FALSE); // Is our window class registered? GLOB NPG3PARAMS GpParams INI(NULL); // Pointer to the current params block GLOB HDC GhDC INI(NULL); // Current device context handle GLOB char GszScratch[INIT(MAXSCR)]; // Scratch string niche // #include "3d\helpers.h" #include "3d\compatib.h" //////////////////////////////////////////////////////////////////////////// // Window callback function //////////////////////////////////////////////////////////////////////////// LONG WINAPI __export G3WndProcGDI(HWND hWnd, UINT msg, UINT wParam, LONG lParam) { //HDC hDC; PAINTSTRUCT ps; LOCALHANDLE hwData; NPG3PARAMS pParams; G3POINT gP; switch (msg) { case WM_CREATE: hwData = (LOCALHANDLE)LocalAlloc(LHND, sizeof(G3PARAMS)); if (!hwData) return -1; // Delete window, not enough local memory SetWindowWord(hWnd, IERRPOS, 0); SetWindowWord(hWnd, HPARPOS, (WORD) hwData); // Initialize the parameter block GpParams = (NPG3PARAMS) LocalLock(hwData); #define iX 120. #define iY 80. #define iZ 120. #define iS1 10. #define iS2 10. #define iD 40. #define iCX 0 #define iCY 0 #define iHW 0 #define iHH 0 gP.x = iX; gP.y = iY; gP.z = iZ; G3SetViewpoint(&gP); G3SetPicturePlaneParams(iD, iS1, iS2); GpParams->cx = iCX; GpParams->cy = iCY; GpParams->hw = iHW; GpParams->hh = iHH; GpParams->M11 = 1.0; GpParams->M22 = 1.0; GpParams->M33 = 1.0; GpParams->M12 = 0.0; GpParams->M13 = 0.0; GpParams->M14 = 0.0; GpParams->M21 = 0.0; GpParams->M23 = 0.0; GpParams->M24 = 0.0; GpParams->M31 = 0.0; GpParams->M32 = 0.0; GpParams->M34 = 0.0; GpParams->iTrFlag = 0; // If it is a metafile window hide the window if (GetWindowWord(hWnd, GWL_STYLE) & GS_METAFILE) SetWindowPos(hWnd, HWND_BOTTOM, 0, 0 , 0, 0, SWP_HIDEWINDOW); LocalUnlock(hwData); return 0; case WM_SIZE: // Suspects MM_TEXT hwData = (LOCALHANDLE)GetWindowWord(hWnd, HPARPOS); if (hwData) pParams = (NPG3PARAMS) LocalLock(hwData); /* if ((pParams->cx == 0 && pParams->cy == 0 && pParams->hw == 0 && pParams->hh == 0) || (pParams->cx + pParams->hw > (int) LOWORD(lParam)) || (pParams->cy + pParams->hh > (int) HIWORD(lParam))) {*/ pParams->cx = pParams->hw = LOWORD(lParam)/2; pParams->cy = HIWORD(lParam)/2; pParams->hh = - (int) HIWORD(lParam)/2; //} LocalUnlock(hwData); return 0; case WM_PAINT: // hDC = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); return 0; case WM_CLOSE: DestroyWindow(hWnd); return 0; case WM_DESTROY: hwData = (LOCALHANDLE) GetWindowWord(hWnd, HPARPOS); if (hwData) LocalFree(hwData); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } //////////////////////////////////////////////////////////////////////////// /* */ //////////////////////////////////////////////////////////////////////////// int WINAPI_LIB G3GetLastError(HWND hWnd) { if (IsG3Window(hWnd)) return (int) GetWindowWord(hWnd, IERRPOS); else return G3ERR_ERROR; } //////////////////////////////////////////////////////////////////////////// /* */ //////////////////////////////////////////////////////////////////////////// int WINAPI_LIB G3GetVersion() { return GiVersion; } //////////////////////////////////////////////////////////////////////////// /* G3GetDC() gets a device context for G3 drawing. Parameter Description hWnd Handle of the output window. Only handles related to the windows with class G3WND are accepted. Returns Handle of the G3 device context if successful, otherwise NULL. The device context handle returned is a metafile device context handle if the style GS_METAFILE is specified for the window identified by hWnd. Comments After using the device context it has be released by calling G3ReleaseDC(). The call pair G3GetDC() -- G3ReleaseDC() should be called during the handling of the same message. G3 parameters are retained between G3GetDC() calls. Even though G3GetDC() returns the device context handle, the G3 functions don't need it. However, if the client application uses the usual GDI functions it can then utilize the returned device context handle. */ //////////////////////////////////////////////////////////////////////////// HDC WINAPI_LIB G3GetDC(HWND hWnd) { HDC hDC; int iErr; if (!IsG3Window(hWnd)) return NULL; if (GetWindowLong(hWnd, GWL_STYLE) & GS_METAFILE) { hDC = CreateMetaFile(NULL); iErr = G3ERR_CREATEMETA; } else {// usual window hDC = GetDC(hWnd); iErr = G3ERR_GETDC; } if (hDC) { GpParams = (NPG3PARAMS) LocalLock((LOCALHANDLE) GetWindowWord(hWnd, HPARPOS)); GhWnd = hWnd; GhDC = hDC; } else SetWindowWord(hWnd, IERRPOS, (WORD) iErr); return hDC; } //////////////////////////////////////////////////////////////////////////// /* G3ReleaseDC() releases the G3 device context. Parameter Description hWnd Handle of the G3 window hDC Handle of the G3 device context Returns The return value is the handle of the G3 window, if the current G3 window is a usual screen window. Else if the window is a "pseudo" metafile window the returned value is the handle of the metafile. If an error occurs, then NULL is returned. Comments If the to be released device context is a metafile device context it is closed in G3ReleaseDC(). It shouldn't be closed using CloseMetaFile(). However, the created metafile (identified by the returned handle) should be deleted later using DeleteMetafile() (if the metafile is copied to the clipboard then the application doesn't need to delete it). */ //////////////////////////////////////////////////////////////////////////// HANDLE WINAPI_LIB G3ReleaseDC(HWND hWnd, HDC hDC) { HANDLE handle; if (!IsG3Window(hWnd) || !hDC) return NULL; LocalUnlock((LOCALHANDLE)GetWindowWord(hWnd, HPARPOS)); GhDC = NULL; if (GetWindowLong(hWnd, GWL_STYLE) & GS_METAFILE) { handle = CloseMetaFile(hDC); if (!handle) { SetWindowWord(GhWnd, IERRPOS, (WORD) G3ERR_CLOSEMETA); return NULL; } return handle; } else { // usual window if (!ReleaseDC(hWnd, hDC)) { SetWindowWord(GhWnd, IERRPOS, (WORD) G3ERR_RELDC); return NULL; } return hWnd; } } //////////////////////////////////////////////////////////////////////////// /* SetViewpoint() generates the spherical coordinates from the given 3D point, that represents the new viewpoint. Note that only sines and cosines of the angle data (and some combinated terms) are saved. The result is put into the global current parameter block. Parameter Description pPt Pointer to a 3D point structure containing the cartesian coordinates of the viewpoint Returns Nonzero, if OK; zero if given point in origo */ //////////////////////////////////////////////////////////////////////////// int WINAPI_LIB G3SetViewpoint(LPG3POINT pPt) { double thetaD; double fiD; //double r1,r2,r3,r4; #define EPS (1.e-2) GpParams->VPx = pPt->x; GpParams->VPy = pPt->y; GpParams->VPz = pPt->z; #if 0 r1 = pPt->x*pPt->x; r2 = pPt->y*pPt->y; r3 = pPt->z*pPt->z; r4 = (r1 + r2 + r3); r4 = sqrt(r4); GpParams->r = r4; #else GpParams->r = sqrt(pPt->x*pPt->x + pPt->y*pPt->y + pPt->z*pPt->z); #endif if (GpParams->r < EPS) { SetWindowWord(GhWnd, IERRPOS, (WORD) G3ERR_INVPOINT); return 0; } thetaD = atan2(pPt->y, pPt->x); GpParams->CosTheta = cos(thetaD); GpParams->SinTheta = sin(thetaD); GpParams->CosFi = pPt->z / GpParams->r; fiD = acos(GpParams->CosFi); GpParams->SinFi = sin(fiD); GpParams->CtCf = GpParams->CosTheta * GpParams->CosFi; GpParams->CtSf = GpParams->CosTheta * GpParams->SinFi; GpParams->StSf = GpParams->SinTheta * GpParams->SinFi; GpParams->StCf = GpParams->SinTheta * GpParams->CosFi; return 1; } //////////////////////////////////////////////////////////////////////////// /* G3GetViewpoint returns the current viewpoint Parameter Description lpG3Point Pointer to a G3 point structure to receive the viewpoint coordinates Returns Nothing Comments */ //////////////////////////////////////////////////////////////////////////// VOID WINAPI_LIB G3GetViewpoint(LPG3POINT pPt) { pPt->x = GpParams->VPx; pPt->y = GpParams->VPy; pPt->z = GpParams->VPz; } //////////////////////////////////////////////////////////////////////////// /* G3ToViewport() converts given 3D points to 2D viewport points. Parameter Description lpG3Points Pointer to the array containing the 3D points lpVPPoints Pointer to the array that will receive the resulting viewport points nPoints Number of points to be converted Returns Nonzero, if OK, 0 if an error occurs or invalid arguments are encountered. Comments The arrays should have enough space to provide space for the required amount of points. If the array are cross-segmented, they should be allocated by using GlobalAlloc() family of functions (?). */ //////////////////////////////////////////////////////////////////////////// int WINAPI_LIB G3G3ToViewport(LPG3POINT lpG3Points, LPPOINT lpVPPoints, int nPoints) { register int i; G3POINT HUGE * pG3; POINT HUGE * pP; POINT p; if (lpG3Points == NULL || lpVPPoints == NULL || nPoints <= 0) { SetWindowWord(GhWnd, IERRPOS, (WORD) G3ERR_INVPAR); return 0; } pG3 = lpG3Points; pP = lpVPPoints; for (i = 0; i < nPoints; i++, pG3++, pP++) { p = G3ToViewport(pG3->x, pG3->y, pG3->z); pP->x = p.x; pP->y = p.y; } return 0; } //////////////////////////////////////////////////////////////////////////// /* G3SetViewport() sets the current output viewport parameters. Parameter Description iCenterX x-coordinate of the center of the viewport iCenterY y-coordinate of the center of the viewport iHalfWidth Half width of the viewport iHalfHeight Half height of the viewport. This parameter should be negative if in the current mapping mode y-axis go downwards. Returns Nonzero, if successful, 0 otherwise Comments The parameters should reflect the current mapping mode selected to the output device context. */ //////////////////////////////////////////////////////////////////////////// int WINAPI_LIB G3SetViewport(int iCenterX, int iCenterY, int iHalfWidth, int iHalfHeight) { GpParams->cx = iCenterX; GpParams->cy = iCenterY; GpParams->hw = iHalfWidth; GpParams->hh = iHalfHeight; return 1; } //////////////////////////////////////////////////////////////////////////// /* G3SetPicturePlaneParams() sets the current picture plane parameters. Parameter Description dDist Distance from the origin to the center of picture plane. The center of the picture plane is situated on the line beginning from the origin and ending to the viewpoint. Parameter dDist has to be larger than 0.0 and smaller than the distance between the viewpoint and the origin of the world coordinate system origin. dHalfWidth Half width of the picture plane (has to be > 0) dHalfHeight Half height of the picture plane (has to be > 0) Returns Nonzero, if OK, 0, if illegal parameters Comments See Also G3SetViewpoint, G3GetPicturePlaneParams */ //////////////////////////////////////////////////////////////////////////// int WINAPI_LIB G3SetPicturePlaneParams(double dDist, double dHalfWidth, double dHalfHeight) { #define EPSH (1.e-1) if (dDist <= 0.0 || dDist >= GpParams->r || dHalfWidth <= EPSH || dHalfHeight <= EPSH) { SetWindowWord(GhWnd, IERRPOS, (WORD) G3ERR_INVPAR); return 0; } GpParams->d = dDist; GpParams->S1 = dHalfWidth; GpParams->S2 = dHalfHeight; GpParams->dS1 = dDist / dHalfWidth; GpParams->dS2 = dDist / dHalfHeight; return 1; } //////////////////////////////////////////////////////////////////////////// /* G3GetPicturePlaneParams() gets the current picture plane parameters. Parameter Description LPdDist Pointer to a double that will receive the current distance from the origin to the center of picture plane. The center of the picture plane is situated on the line beginning from the origin and ending to the viewpoint. LPdHalfWidth Pointer to a double that will receive the half width of the picture plane LPdHalfHeight Pointer to a double that will receive the half height of the picture plane Comments See Also G3SetViewpoint, G3SetPicturePlaneParams */ //////////////////////////////////////////////////////////////////////////// VOID WINAPI_LIB G3GetPicturePlaneParams(double FAR * LPdDist, double FAR * LPdHalfWidth, double FAR * LPdHalfHeight) { *LPdDist = GpParams->d; *LPdHalfWidth = GpParams->S1; *LPdHalfHeight = GpParams->S2; } //////////////////////////////////////////////////////////////////////////// /* G3VectorLength() returns the length of the vector pointed by lpG3Vector. Parameter Description lpG3Vector Pointer to the vector the length of which is to be determined Returns The length of the vector */ //////////////////////////////////////////////////////////////////////////// double WINAPI_LIB G3VectorLength(LPG3VECTOR lpG3Vector) { return sqrt(lpG3Vector->x * lpG3Vector->x + lpG3Vector->y * lpG3Vector->y + lpG3Vector->z * lpG3Vector->z); } //////////////////////////////////////////////////////////////////////////// /* G3Normalize() normalizes the 3D vector pointed by lpG3Vector. Parameter Description lpG3Vector A pointer to a 3D vector Returns Pointer to the modified vector Comments If the length of the vector to be normalized is zero, then the vector is retained the same. */ //////////////////////////////////////////////////////////////////////////// LPG3VECTOR WINAPI_LIB G3Normalize(LPG3VECTOR lpG3Vector) { double dLength; dLength = G3VectorLength(lpG3Vector); if (dLength != 0.0) { lpG3Vector->x /= dLength; lpG3Vector->y /= dLength; lpG3Vector->z /= dLength; } return lpG3Vector; } //////////////////////////////////////////////////////////////////////////// /* */ //////////////////////////////////////////////////////////////////////////// int WINAPI Init3DWndClass(HINSTANCE hInst) { WNDCLASS wc; if ( GbClRegistered == TRUE ) return 0; GhInst = hInst; // Register our class wc.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_DBLCLKS; wc.lpfnWndProc = G3WndProcGDI; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(G3WND); wc.hInstance = hInst; wc.hIcon = NULL; wc.lpszMenuName = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); // wc.hbrBackground = COLOR_WINDOW + 1; wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszClassName = G3CLASSNAME; if (RegisterClass(&wc)) GbClRegistered = TRUE; return GbClRegistered != TRUE; } //////////////////////////////////////////////////////////////////////////// /* LibMain() is the entry point for the GDI3D DLL. */ //////////////////////////////////////////////////////////////////////////// int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine) { (void)wDataSeg; (void)lpszCmdLine; if (cbHeapSize > 0) UnlockData(0); Init3DWndClass(hInst); return 1; } int WINAPI _WEP(int nExitType) { // Unregister our class (void)nExitType; if (GbClRegistered) UnregisterClass(G3CLASSNAME, GhInst); return 1; }