home *** CD-ROM | disk | FTP | other *** search
- #include "windows.h"
- #include <math.h>
- #include <stdlib.h>
-
- //******************************************************************
- //Title: 3D.C
- //Author: Thomas W. Olsen
- //Version: 1.0
- //Compiler: Microsoft C/C++ 7.0
- // rc /r 3d.rc
- // cl /c /AL /Gsw /W3 /Oas /Zpe /Zi /FPi 3d.c
- // link /CO /NOD 3d,,, libw llibcew win87em, 3d.def
- // rc 3d.exe
- //******************************************************************
-
- //*********************** Various Constants ************************
-
- #define CENTER 0
- #define PI 3.141593
- #define RADIANS(a) (a * (PI / 180.0))
- #define DEGREES(a) (a * (180.0 / PI))
- #define NO_OF_VERTICES 66
- #define NO_OF_SURFACES 45
- #define NO_OF_SURFACE_VERTICES 220
- #define VIEW_RATIO (40 / 10)
- #define MIN_DEGREES 0
- #define MAX_DEGREES 359
- #define ROTATE_DEGREES 5
-
- //********************* Structure Definitions **********************
-
- typedef struct tagPOINT3D
- {
- double x;
- double y;
- double z;
- } POINT3D;
-
- typedef struct tagVERTEX
- {
- POINT3D world; // World Coordinates
- POINT3D eye; // Eye Coordinates
- POINT screen; // Screen Coordinates
- } VERTEX;
-
- typedef struct tagSURFACE
- {
- int mapIndex; // Index Into the Surface Map Array
- int noOfVertices; // No of Vertices Forming the Surface
- int depthIndex; // Used in Determining Depth of Surface
- int brushColor;
- } SURFACE;
-
- typedef struct tagOBJECT
- {
- VERTEX vertex[NO_OF_VERTICES];
- SURFACE info[NO_OF_SURFACES];
- int map[NO_OF_SURFACE_VERTICES];
- } OBJECT;
-
- //************************** Static Data ***************************
-
- OBJECT f16 =
- {
- { // Vertex Array
- { 0.00, 0.00, 0.00 }, //Center
- { 0.00, -17.00, 9.00 }, { 0.00, -13.00, 9.00 }, //Tail
- { 0.00, -14.50, 3.00 }, { 0.00, -8.00, 3.00 },
- { 0.00, -14.50, 2.00 }, { 0.00, -5.00, 2.00 },
- { -0.50, -16.00, 1.00 }, { -1.00, -16.00, 0.00 }, //Exhaust
- { -0.50, -16.00, -0.50 }, { 0.00, -16.00, -1.00 },
- { 0.50, -16.00, -0.50 }, { 1.00, -16.00, 0.00 },
- { 0.50, -16.00, 1.00 },
- { -1.00, -13.00, 2.00 }, { -2.00, -13.00, 0.00 }, //Fuse
- { -1.50, -13.00, -1.50 }, { 0.00, -13.00, -2.00 },
- { 1.50, -13.00, -1.50 }, { 2.00, -13.00, 0.00 },
- { 1.00, -13.00, 2.00 }, { -1.00, 7.00, 2.00 },
- { -2.00, 7.00, 0.00 }, { -1.50, 7.00, -1.50 },
- { 0.00, 7.00, -2.00 }, { 1.50, 7.00, -1.50 },
- { 2.00, 7.00, 0.00 }, { 1.00, 7.00, 2.00 },
- { 2.00, -8.00, 0.00 }, { 11.00, -8.00, 0.00 }, //Wings
- { 11.00, -5.00, 0.00 }, { 5.00, 0.00, 0.00 },
- { 2.00, 7.00, 0.00 }, { -2.00, -8.00, 0.00 },
- { -11.00, -8.00, 0.00 }, { -11.00, -5.00, 0.00 },
- { -5.00, 0.00, 0.00 }, { -2.00, 7.00, 0.00 },
- { 0.50, 2.00, 2.00 }, { -0.50, 2.00, 2.00 }, //Cockpit
- { 1.00, 5.00, 2.00 }, { 0.50, 5.00, 3.50 },
- { -0.50, 5.00, 3.50 }, { -1.00, 5.00, 2.00 },
- { 1.00, 8.00, 2.00 }, { 0.50, 8.00, 3.50 },
- { -0.50, 8.00, 3.50 }, { -1.00, 8.00, 2.00 },
- { 0.50, 11.00, 2.00 }, { -0.50, 11.00, 2.00 },
- { 0.00, 7.00, -1.00 }, { -1.00, 11.00, 2.00 }, //Subfuse
- { -2.00, 11.00, 0.00 }, { 0.00, 11.00, -1.00 },
- { 2.00, 11.00, 0.00 }, { 1.00, 11.00, 2.00 },
- { 0.00, 11.00, -1.00 }, { 0.00, 17.00, 0.00 }, //Nose
- { -2.00, -16.00, 0.00 }, { -8.00, -16.00, 0.00 }, //Elevators
- { -8.00, -14.00, 0.00 }, { -2.00, -10.00, 0.00 },
- { 2.00, -16.00, 0.00 }, { 8.00, -16.00, 0.00 },
- { 8.00, -14.00, 0.00 }, { 2.00, -10.00, 0.00 }
- },
- { // Surface Info ... (Points to Surface Map)
- { 0, 5, 60, DKGRAY_BRUSH }, { 5, 5, 64, DKGRAY_BRUSH }, //Elevators
- { 10, 5, 60, DKGRAY_BRUSH }, { 15, 5, 64, DKGRAY_BRUSH },
- { 20, 5, 1, GRAY_BRUSH }, { 25, 5, 4, LTGRAY_BRUSH }, //Tail
- { 30, 5, 1, GRAY_BRUSH }, { 35, 5, 4, LTGRAY_BRUSH },
- { 40, 5, 14, BLACK_BRUSH }, { 45, 5, 15, DKGRAY_BRUSH }, //Exhaust
- { 50, 5, 16, BLACK_BRUSH }, { 55, 5, 17, BLACK_BRUSH },
- { 60, 5, 18, DKGRAY_BRUSH }, { 65, 5, 19, BLACK_BRUSH },
- { 70, 5, 20, DKGRAY_BRUSH },
- { 75, 5, 22, DKGRAY_BRUSH }, { 80, 5, 23, GRAY_BRUSH }, //Fuse
- { 85, 5, 24, DKGRAY_BRUSH }, { 90, 5, 25, DKGRAY_BRUSH },
- { 95, 5, 26, GRAY_BRUSH }, { 100, 5, 27, DKGRAY_BRUSH },
- { 105, 5, 20, GRAY_BRUSH, },
- { 110, 6, 30, DKGRAY_BRUSH }, { 116, 6, 35, DKGRAY_BRUSH }, //Wings
- { 122, 6, 30, DKGRAY_BRUSH }, { 128, 6, 35, DKGRAY_BRUSH },
- { 134, 5, 21, LTGRAY_BRUSH }, { 139, 5, 22, LTGRAY_BRUSH }, //Subfuse
- { 144, 5, 50, LTGRAY_BRUSH }, { 149, 5, 26, LTGRAY_BRUSH },
- { 154, 5, 27, LTGRAY_BRUSH },
- { 159, 4, 55, GRAY_BRUSH }, { 163, 4, 54, GRAY_BRUSH }, //Nose
- { 167, 4, 56, GRAY_BRUSH }, { 171, 4, 52, GRAY_BRUSH },
- { 175, 4, 51, LTGRAY_BRUSH },
- { 179, 5, 41, WHITE_BRUSH }, { 184, 5, 45, WHITE_BRUSH }, //Cockpit
- { 189, 5, 46, WHITE_BRUSH }, { 194, 4, 41, WHITE_BRUSH },
- { 198, 4, 42, WHITE_BRUSH }, { 202, 5, 41, WHITE_BRUSH },
- { 207, 5, 46, WHITE_BRUSH }, { 212, 4, 45, WHITE_BRUSH },
- { 216, 4, 46, WHITE_BRUSH }
- },
- { // Surface Map ... (Points to Vertex Array)
- 58, 61, 60, 59, 58, 62, 63, 64, 65, 62, 58, 59, 60, 61, 58, // Elevators
- 62, 65, 64, 63, 62,
- 1, 3, 4, 2, 1, 3, 5, 6, 4, 3, 1, 2, 4, 3, 1, // Tail
- 3, 4, 6, 5, 3,
- 14, 15, 8, 7, 14, 15, 16, 9, 8, 15, 16, 17, 10, 9, 16, // Exhaust
- 17, 18, 11, 10, 17, 18, 19, 12, 11, 18, 19, 20, 13, 12, 19,
- 20, 14, 7, 13, 20,
- 14, 21, 22, 15, 14, 15, 22, 23, 16, 15, 16, 23, 24, 17, 16, // Fuse
- 17, 24, 25, 18, 17, 18, 25, 26, 19, 18, 19, 26, 27, 20, 19,
- 20, 27, 21, 14, 20,
- 28, 29, 30, 31, 32, 28, 33, 37, 36, 35, 34, 33, 28, 32, 31, // Wings
- 30, 29, 28, 33, 34, 35, 36, 37, 33,
- 21, 51, 52, 22, 21, 22, 52, 53, 50, 22, 50, 53, 54, 26, 50, // Subfuse
- 26, 54, 55, 27, 26, 27, 55, 51, 21, 27,
- 55, 54, 57, 55, 54, 56, 57, 54, 56, 52, 57, 56, 52, 51, 57, 52, // Nose
- 51, 55, 57, 51,
- 41, 42, 39, 38, 41, 45, 46, 42, 41, 45, 48, 49, 46, 45, 48, // Cockpit
- 40, 41, 38, 40, 42, 43, 39, 42, 44, 45, 41, 40, 44,
- 46, 47, 43, 42, 46, 48, 45, 44, 48, 49, 47, 46, 49
- }
- };
-
- BOOL wireFrame = FALSE;
- double distance = 75, thetaDegrees = 90, phiDegrees = 60;
-
- //************************** Static Data ***************************
-
- LONG FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
- void DrawObject(HWND hWnd, HDC hDC, OBJECT *object );
- int __cdecl compareProc( const void *elem1, const void *elem2 );
-
- //************************** Program Begin *************************
-
- int PASCAL WinMain(HANDLE hInst, HANDLE hPrevInst, LPSTR lpCmdLine, int numCmdShow )
- {
- MSG msg;
- HWND hWnd;
- WNDCLASS wc;
-
- //************************* Setup Window ************************
-
- wc.style = (UINT) NULL;
- wc.lpfnWndProc = WindowProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInst;
- wc.hIcon = LoadIcon( NULL, IDI_APPLICATION);
- wc.hCursor = LoadCursor( NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(BLACK_BRUSH);
- wc.lpszMenuName = (LPSTR) "Menu";
- wc.lpszClassName = (LPSTR) "3DClass";
-
- if (!RegisterClass(&wc))
- return(FALSE);
-
- hWnd = CreateWindow( "3DClass", "3D Modeling Example",
- WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, NULL, NULL, hInst, NULL );
- if (!hWnd)
- return (FALSE);
-
- SetScrollRange( hWnd, SB_HORZ, MIN_DEGREES, MAX_DEGREES, TRUE );
- SetScrollRange( hWnd, SB_VERT, MIN_DEGREES, MAX_DEGREES, TRUE );
- SetScrollPos( hWnd, SB_HORZ, (int) thetaDegrees, TRUE );
- SetScrollPos( hWnd, SB_VERT, (int) phiDegrees, TRUE );
-
- ShowWindow( hWnd, numCmdShow );
-
- while (GetMessage(&msg, NULL, NULL, NULL)) /* Typical Message Loop */
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- return (msg.wParam);
- }
-
-
- LONG FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- PAINTSTRUCT paint;
- HDC hDC;
- HMENU hMenu;
- int vPos, hPos;
-
- switch (message)
- {
- case WM_COMMAND:
- hMenu = GetMenu( hWnd );
- CheckMenuItem( hMenu, wParam, MF_CHECKED);
-
- if (wParam == 1)
- {
- CheckMenuItem( hMenu, 2, MF_UNCHECKED);
- wireFrame = TRUE;
- }
- else
- {
- CheckMenuItem( hMenu, 1, MF_UNCHECKED);
- wireFrame = FALSE;
- }
-
- InvalidateRect( hWnd, NULL, TRUE );
- break;
-
- case WM_DESTROY:
- PostQuitMessage( NULL );
- break;
-
- case WM_HSCROLL:
- if (wParam == SB_THUMBTRACK)
- break;
-
- hPos = GetScrollPos( hWnd, SB_HORZ);
-
- switch( wParam )
- {
- case SB_TOP:
- hPos = MIN_DEGREES;
- break;
- case SB_BOTTOM:
- hPos = MAX_DEGREES;
- break;
- case SB_LINEUP:
- case SB_PAGEUP:
- hPos -= ROTATE_DEGREES;
- break;
- case SB_PAGEDOWN:
- case SB_LINEDOWN:
- hPos += ROTATE_DEGREES;
- break;
- case SB_THUMBPOSITION:
- hPos = LOWORD(lParam);
- break;
- }
-
- if (hPos < MIN_DEGREES)
- hPos = MAX_DEGREES;
- else
- if (hPos > MAX_DEGREES)
- hPos = MIN_DEGREES;
-
- SetScrollPos( hWnd, SB_HORZ, hPos, TRUE );
- thetaDegrees = (double) hPos;
- InvalidateRect( hWnd, NULL, TRUE );
- break;
-
- case WM_VSCROLL:
- if (wParam == SB_THUMBTRACK)
- break;
-
- vPos = GetScrollPos( hWnd, SB_VERT );
-
- switch( wParam )
- {
- case SB_TOP:
- vPos = MIN_DEGREES;
- break;
- case SB_BOTTOM:
- vPos = MAX_DEGREES;
- break;
- case SB_LINEUP:
- case SB_PAGEUP:
- vPos -= ROTATE_DEGREES;
- break;
- case SB_PAGEDOWN:
- case SB_LINEDOWN:
- vPos += ROTATE_DEGREES;
- break;
- case SB_THUMBPOSITION:
- vPos = LOWORD(lParam);
- break;
- }
-
- if (vPos < MIN_DEGREES)
- vPos = MAX_DEGREES;
- else
- if (vPos > MAX_DEGREES)
- vPos = MIN_DEGREES;
-
- SetScrollPos( hWnd, SB_VERT, vPos, TRUE );
- phiDegrees = (double) vPos;
- InvalidateRect( hWnd, NULL, TRUE );
- break;
-
- case WM_SIZE:
- InvalidateRect( hWnd, NULL, TRUE );
- break;
-
-
- case WM_PAINT:
- hDC = BeginPaint( hWnd, &paint );
- DrawObject(hWnd, hDC, &f16);
- ReleaseDC( hWnd, hDC );
- EndPaint( hWnd, &paint );
- break;
-
- default:
- return (DefWindowProc(hWnd, message, wParam, lParam));
- }
- }
-
-
- void DrawObject(HWND hWnd, HDC hDC, OBJECT *object)
- {
- double sinTheta, cosTheta, sinPhi, cosPhi;
- double s1, s2, s3;
- POINT3D *v1, *v2, *v3;
- POINT center;
- RECT rect;
- POINT points[10];
- HBITMAP hBitmap, hOldBitmap;
- HRGN hRgn;
- HDC hMemDC;
- int surface, vertex, mapIndex, vertexIndex, loop;
-
- GetClientRect( hWnd, &rect); // Determine Size of Client Area
- center.x = (rect.right / 2); // Calculate X-Centerpoint
- center.y = (rect.bottom / 2); // Calculate Y-Centerpoint
-
- hRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom );
- hMemDC = CreateCompatibleDC( hDC );
- hBitmap = CreateCompatibleBitmap( hDC, rect.right, rect.bottom);
- hOldBitmap = SelectObject( hMemDC, hBitmap );
-
- //**********************************************************************
- //* Precalculate SIN(x) and COS(x) *
- //**********************************************************************
-
- cosTheta = cos( RADIANS(thetaDegrees) );
- sinTheta = sin( RADIANS(thetaDegrees) );
- cosPhi = cos( RADIANS(phiDegrees) );
- sinPhi = sin( RADIANS(phiDegrees) );
-
- //******************************************************************
- //* Calculate Eye and Screen Coordinates *
- //******************************************************************
-
- for (loop = 1; loop < NO_OF_VERTICES; loop++)
- {
- object->vertex[loop].eye.x =
- (-object->vertex[loop].world.x * sinTheta) +
- (object->vertex[loop].world.y * cosTheta);
- object->vertex[loop].eye.y =
- (-object->vertex[loop].world.x * cosTheta * cosPhi) -
- (object->vertex[loop].world.y * sinTheta * cosPhi) +
- (object->vertex[loop].world.z * sinPhi);
- object->vertex[loop].eye.z =
- (-object->vertex[loop].world.x * sinPhi * cosTheta) -
- (object->vertex[loop].world.y * sinTheta * sinPhi) -
- (object->vertex[loop].world.z * cosPhi) + distance;
-
- object->vertex[loop].screen.x = (int)
- (VIEW_RATIO * (object->vertex[loop].eye.x / object->vertex[loop].eye.z) * center.y + center.x);
- object->vertex[loop].screen.y = (int)
- (-VIEW_RATIO * (object->vertex[loop].eye.y / object->vertex[loop].eye.z) * center.y + center.y);
- }
-
- //******************************************************************
- //* Draw Object *
- //******************************************************************
-
- FillRgn( hMemDC, hRgn, GetStockObject(BLACK_BRUSH));
- SelectObject( hMemDC, GetStockObject(wireFrame == TRUE ? WHITE_PEN:BLACK_PEN) );
-
- if (wireFrame == FALSE)
- qsort( object->info, NO_OF_SURFACES, sizeof(SURFACE), compareProc );
-
- for (surface = 0; surface < NO_OF_SURFACES; surface++)
- {
- mapIndex = object->info[surface].mapIndex;
-
- if (wireFrame == FALSE) // No Hidden Surface Removal For Wire Frame
- {
- v1 = &object->vertex[ object->map[ mapIndex ] ].eye; // Setup pointers to three
- v2 = &object->vertex[ object->map[ mapIndex+1 ] ].eye; // surface vertices
- v3 = &object->vertex[ object->map[ mapIndex+2 ] ].eye;
-
- s1 = v1->x * (v2->y * v3->z - v3->y * v2->z); s1 = (-1) * s1;
- s2 = v2->x * (v3->y * v1->z - v1->y * v3->z); // Perform dot product on surface
- s3 = v3->x * (v1->y * v2->z - v2->y * v1->z); // vectors to find normal vector
- }
-
- if (wireFrame == TRUE || s1 - s2 - s3 <= 0.0)
- {
- for (vertex = 0; vertex < object->info[surface].noOfVertices; vertex++, mapIndex++)
- {
- vertexIndex = object->map[mapIndex];
- points[vertex].x = object->vertex[vertexIndex].screen.x;
- points[vertex].y = object->vertex[vertexIndex].screen.y;
- }
-
- if (wireFrame == TRUE)
- Polyline( hMemDC, &points[0], vertex);
- else
- {
- SelectObject( hMemDC, GetStockObject(object->info[surface].brushColor) );
- Polygon( hMemDC, &points[0], vertex);
- }
- }
- }
- BitBlt( hDC, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY);
-
- SelectObject( hMemDC, hOldBitmap );
- DeleteObject( hBitmap );
- DeleteObject( hRgn );
- DeleteDC( hMemDC );
- }
-
-
- int __cdecl compareProc( const void *elem1, const void *elem2 )
- {
- if( f16.vertex[((SURFACE *) elem1)->depthIndex].eye.z >
- f16.vertex[((SURFACE *) elem2)->depthIndex].eye.z )
- return -1;
- if( f16.vertex[((SURFACE *) elem1)->depthIndex].eye.z <
- f16.vertex[((SURFACE *) elem2)->depthIndex].eye.z )
- return 1;
- else
- return 0;
- }
-