home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_11_03
/
1103054a
< prev
next >
Wrap
Text File
|
1993-01-06
|
17KB
|
452 lines
#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;
}