home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hall of Fame
/
HallofFameCDROM.cdr
/
window
/
wcrane3d.lzh
/
CRANE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-30
|
53KB
|
2,083 lines
/******************************************************************************
Module Name: crane
Description: 3D Origami Crane Animator
Version: v1.00
Authors: Mike Robert
Date: 3/30/90
For Jennifer Lee.
Revision History:
Bugs:
Enhancements:
******************************************************************************/
/* INCLUDE FILES
*/
#define NOCOMM
#include <Windows.h>
#include <math.h>
#include <process.h>
#include "WinUnDoc.h"
#include "crane.h"
#include "dialogs.h"
/* SYMBOLIC CONSTANTS
*/
/* Miscellaneous. */
#define PI 3.14159265 /* The value of π */
#define CNT_ANIMATE 4 /* Animate count */
#define MAX_MOVE 100. /* Maximum movement */
#define MAX_POINTS 56 /* Maximum points */
#define MAX_SHAPES 11 /* Maximum shapes */
/* Crane Point Flags. */
#define CPF_NORMAL 0x0000 /* Normal point */
#define CPF_START 0x0001 /* New line sequence start */
#define CPF_MOVE 0x0002 /* Movement point */
#define CPF_EOL 0x8000 /* End of point list */
/* ROTation. */
#define ROT_INC ( PI / 18. ) /* Rotation degree increment */
#define ROT_MIN ( 0. ) /* Rotation minimum */
#define ROT_MAX ( PI * 2. ) /* Rotation maximum */
/* Z-SiZing. */
#define ZSZ_ATMINSIZ -5000.
#define ZSZ_ATMAXSIZ 5000.
#define ZSZ_WINORG -1500
#define ZSZ_WINEXT 3000
/* MACROS
*/
#define WITHIN(a,b,c) ( (a) >= (b) && (a) <= (c) )
/* TYPEDEFS
*/
typedef struct _POINT3D
{
double x, y, z; /* XYZ coordinates (floating) */
}
POINT3D; /* 3-dimensional point */
typedef POINT3D FAR *LPPOINT3D;
typedef struct _ANIMATEPT
{
WORD unPtIndex; /* Point index */
double dfMinRot, /* Minimum rotation */
dfMaxRot, /* Maximum rotation */
dfCurRot, /* Current rotation */
dfIncRot, /* Rotation increment */
dfDst; /* Distance */
}
ANIMATEPT; /* Animate point structure */
typedef ANIMATEPT FAR *LPANIMATEPT;
typedef struct _SHAPE
{
WORD unIndex, /* Index */
unCnt; /* Point count */
}
SHAPE; /* Shape structure */
typedef SHAPE FAR *LPSHAPE;
typedef struct _CRANEPT
{
WORD unFlags; /* Flags */
POINT3D pt3dOrg, /* Original point */
pt3dNew; /* New point */
}
CRANEPT; /* Crane point structure */
typedef CRANEPT FAR *LPCRANEPT;
/* GLOBAL VARIABLES
*/
static HANDLE hModule; /* Module instance handle */
static HWND hClientWnd; /* Client window handle */
static HDC hClientDC; /* Client display context handle */
static FARPROC lpfnXYZDataDlgProc; /* XYZ data dialog function pointer */
static HWND hXYZDataDlg = NULL; /* Data dialog window handle */
static BOOL bAnimate = FALSE; /* Animation flag */
static BOOL bRecording = FALSE; /* Recording flag */
static WORD unRecordCnt = 0; /* Record count */
static int fhRecordFile; /* Record file handle */
static RECT rErase, /* Erase rectangle */
rOldErase, /* Old erase rectangle */
rUpdate; /* Update rectangle */
static POINT aptList[ MAX_POINTS ];
/* Point list */
static POINT3D pt3dRot; /* Rotation amounts */
static POINT3D pt3dLoc; /* Current location */
static CRANEPT cptMove = /* Movement crane point */
{
CPF_MOVE,
{ 0., 0., MAX_MOVE },
{ 0., 0., 0. }
};
static ANIMATEPT aaptList[ CNT_ANIMATE ] =
/* Animate point list */
{
{
33,
PI * 3. / 4. + PI / 40.,
PI * 5. / 4. - PI / 40.,
PI,
-PI / 20.,
1050.
},
{
37,
PI * 3. / 4. + PI / 40.,
PI * 5. / 4. - PI / 40.,
PI,
-PI / 20.,
1050.
},
{
41,
-PI / 4. + PI / 40.,
PI / 4. - PI / 40.,
0.,
PI / 20.,
1050.
},
{
45,
-PI / 4. + PI / 40.,
PI / 4. - PI / 40.,
0.,
PI / 20.,
1050.
}
};
static POINT3D pt3dMin = /* Coordinate minimums */
{ -1050., -405., -810. },
pt3dMax = /* Coordinate maximums */
{ 1050., 405., 810. };
static SHAPE ashpList[ ] = /* Shape list */
{
{ 0, 4 },
{ 4, 7 },
{ 11, 5 },
{ 16, 5 },
{ 21, 5 },
{ 26, 5 },
{ 31, 4 },
{ 35, 4 },
{ 39, 4 },
{ 43, 4 },
{ 47, 9 }
};
static CRANEPT acptList[ ] = /* Crane points */
{
{ /* 0 */
CPF_START,
{ 0., -405., -810. },
{ 0., 0., 0. }
},
{ /* 1 */
CPF_NORMAL,
{ 0., 405., -180. },
{ 0., 0., 0. }
},
{ /* 2 */
CPF_NORMAL,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 3 */
CPF_NORMAL,
{ 0., -405., -810. },
{ 0., 0., 0. }
},
{ /* 4 */
CPF_START,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 5 */
CPF_NORMAL,
{ 0., 405., 300. },
{ 0., 0., 0. }
},
{ /* 6 */
CPF_NORMAL,
{ 0., -135., 720. },
{ 0., 0., 0. }
},
{ /* 7 */
CPF_NORMAL,
{ 0., 135., 810. },
{ 0., 0., 0. }
},
{ /* 8 */
CPF_NORMAL,
{ 0., -195., 780. },
{ 0., 0., 0. }
},
{ /* 9 */
CPF_NORMAL,
{ 0., -225., 690. },
{ 0., 0., 0. }
},
{ /* 10 */
CPF_NORMAL,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 11 */
CPF_START,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 12 */
CPF_NORMAL,
{ 0., 405., -180. },
{ 0., 0., 0. }
},
{ /* 13 */
CPF_NORMAL,
{ -450., 75., -270. },
{ 0., 0., 0. }
},
{ /* 14 */
CPF_NORMAL,
{ -90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 15 */
CPF_NORMAL,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 16 */
CPF_START,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 17 */
CPF_NORMAL,
{ 0., 405., 300. },
{ 0., 0., 0. }
},
{ /* 18 */
CPF_NORMAL,
{ -450., 75., 390. },
{ 0., 0., 0. }
},
{ /* 19 */
CPF_NORMAL,
{ -90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 20 */
CPF_NORMAL,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 21 */
CPF_START,
{ 450., 75., -270. },
{ 0., 0., 0. }
},
{ /* 22 */
CPF_NORMAL,
{ 90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 23 */
CPF_NORMAL,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 24 */
CPF_NORMAL,
{ 0., 405., -180. },
{ 0., 0., 0. }
},
{ /* 25 */
CPF_NORMAL,
{ 450., 75., -270. },
{ 0., 0., 0. }
},
{ /* 26 */
CPF_START,
{ 90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 27 */
CPF_NORMAL,
{ 450., 75., 390. },
{ 0., 0., 0. }
},
{ /* 28 */
CPF_NORMAL,
{ 0., 405., 300. },
{ 0., 0., 0. }
},
{ /* 29 */
CPF_NORMAL,
{ 0., 255., 60. },
{ 0., 0., 0. }
},
{ /* 30 */
CPF_NORMAL,
{ 90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 31 */
CPF_START,
{ -90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 32 */
CPF_NORMAL,
{ -450., 75., -270. },
{ 0., 0., 0. }
},
{ /* 33 */
CPF_NORMAL,
{ -1050., 0., 60. },
{ 0., 0., 0. }
},
{ /* 34 */
CPF_NORMAL,
{ -90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 35 */
CPF_START,
{ -90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 36 */
CPF_NORMAL,
{ -450., 75., 390. },
{ 0., 0., 0. }
},
{ /* 37 */
CPF_NORMAL,
{ -1050., 0., 60. },
{ 0., 0., 0. }
},
{ /* 38 */
CPF_NORMAL,
{ -90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 39 */
CPF_START,
{ 90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 40 */
CPF_NORMAL,
{ 450., 75., -270. },
{ 0., 0., 0. }
},
{ /* 41 */
CPF_NORMAL,
{ 1050., 0., 60. },
{ 0., 0., 0. }
},
{ /* 42 */
CPF_NORMAL,
{ 90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 43 */
CPF_START,
{ 90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 44 */
CPF_NORMAL,
{ 450., 75., 390. },
{ 0., 0., 0. }
},
{ /* 45 */
CPF_NORMAL,
{ 1050., 0., 60. },
{ 0., 0., 0. }
},
{ /* 46 */
CPF_NORMAL,
{ 90., 195., 60. },
{ 0., 0., 0. }
},
{ /* 47 */
CPF_START,
{ -270., 135., 390. },
{ 0., 0., 0. }
},
{ /* 48 */
CPF_NORMAL,
{ 0., -15., 330. },
{ 0., 0., 0. }
},
{ /* 49 */
CPF_NORMAL,
{ 270., 135., 390. },
{ 0., 0., 0. }
},
{ /* 50 */
CPF_NORMAL,
{ 270., 45., 60. },
{ 0., 0., 0. }
},
{ /* 51 */
CPF_NORMAL,
{ 270., 135., -270. },
{ 0., 0., 0. }
},
{ /* 52 */
CPF_NORMAL,
{ 0., -45., -210. },
{ 0., 0., 0. }
},
{ /* 53 */
CPF_NORMAL,
{ -270., 135., -270. },
{ 0., 0., 0. }
},
{ /* 54 */
CPF_NORMAL,
{ -270., 45., 60. },
{ 0., 0., 0. }
},
{ /* 55 */
CPF_NORMAL,
{ -270., 135., 390. },
{ 0., 0., 0. }
},
{ /* 56 */
CPF_EOL,
{ 0., 0., 0. },
{ 0., 0., 0. }
}
};
#define MAX_POINTS 56 /* Maximum points */
#define MAX_SHAPES 11 /* Maximum shapes */
/* FUNCTION PROTOYPES
*/
void PASCAL WinMain(
HANDLE hInstance, /* Instance handle.
*/
HANDLE hPrevInstance,
/* Previous instance handle.
*/
LPSTR lpszCmdLine, /* Command line string pointer.
*/
int nCmdShow /* Show command parameter.
*/
);
long FAR PASCAL WindowProc(
HWND hWnd, /* Window handle.
*/
unsigned nMsg, /* Message type.
*/
WORD wParam, /* 16-bit parameter.
*/
LONG lParam /* 32-bit parameter.
*/
);
BOOL NEAR PASCAL Init(
HANDLE hInstance, /* Instance handle.
*/
HANDLE hPrevInstance,
/* Previous instance handle.
*/
LPSTR lpszCmdLine, /* Command line string pointer.
*/
int nCmdShow /* Show command parameter.
*/
);
void NEAR PASCAL Menu(
HWND hWnd, /* Window handle.
*/
WORD wID /* Command ID.
*/
);
void NEAR PASCAL InitMenu(
HWND hWnd, /* Window handle.
*/
HMENU hMenu /* Menu handle.
*/
);
BOOL FAR PASCAL XYZDataDlgProc(
HWND hDlg, /* Dialog window handle.
*/
unsigned nMsg, /* Message to dialog.
*/
WORD wParam, /* Word parameter.
*/
LONG lParam /* Long parameter.
*/
);
void NEAR PASCAL UpdateXYZDataDlg( void );
BOOL FAR PASCAL AboutDlgProc(
HWND hDlg, /* Dialog window handle.
*/
unsigned nMsg, /* Message type.
*/
WORD wParam, /* 16-bit parameter.
*/
LONG lParam /* 32-bit parameter.
*/
);
void NEAR PASCAL AnimateCranePts(
HWND hWnd /* Window handle.
*/
);
void NEAR PASCAL RecordPlayback(
HWND hWnd /* Window handle.
*/
);
void NEAR PASCAL RecordRead( void );
void NEAR PASCAL RecordWrite( void );
void NEAR PASCAL Key(
HWND hWnd, /* Window handle.
*/
WORD wId /* Key ID.
*/
);
void NEAR PASCAL CalcNewCranePts( void );
void NEAR PASCAL CalcNewPt(
LPCRANEPT lpcpt /* Crane point pointer.
*/
);
void NEAR PASCAL Size(
HWND hWnd, /* Window handle.
*/
LONG lParam /* 32-bit parameter.
*/
);
void NEAR PASCAL Paint(
HWND hWnd /* Window handle.
*/
);
void NEAR PASCAL ResetCranePts( void );
void NEAR PASCAL myYield( void );
/******************************************************************************
Function Name: WinMain
Description:
Top level procedure called by windows on application startup.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void PASCAL WinMain(
HANDLE hInstance, /* Instance handle.
*/
HANDLE hPrevInstance,
/* Previous instance handle.
*/
LPSTR lpszCmdLine, /* Command line string pointer.
*/
int nCmdShow /* Show command parameter.
*/
)
{
/* Variable definition. */
MSG stMsg; /* Message structure */
/* Initialize ourselves. */
if ( !Init( hInstance, hPrevInstance, lpszCmdLine, nCmdShow ) )
exit( 1 );
/* Process messages until exit. */
while ( GetMessage( &stMsg, NULL, 0, 0 ) )
{
/* Translate and dispatch the message. */
TranslateMessage( &stMsg );
DispatchMessage( &stMsg );
}
exit( stMsg.wParam );
}
/******************************************************************************
Function Name: Init
Description:
Provides initialization for the first instance and every following
instance.
Control Flow:
Return Values:
Failure: FALSE
Success: TRUE
Notes:
******************************************************************************/
BOOL NEAR PASCAL Init(
HANDLE hInstance, /* Instance handle.
*/
HANDLE hPrevInstance,
/* Previous instance handle.
*/
LPSTR lpszCmdLine, /* Command line string pointer.
*/
int nCmdShow /* Show command parameter.
*/
)
{
/* Variable definition. */
WNDCLASS wcClass; /* Class information storage */
OFSTRUCT ofRecord; /* Record open file structure */
/* Perform the appropiate initialization. */
if ( !hPrevInstance )
{
wcClass.lpszClassName = "Crane";
wcClass.hInstance = hInstance;
wcClass.lpfnWndProc = WindowProc;
wcClass.hCursor = LoadCursor( NULL, IDC_ARROW );
wcClass.hIcon = LoadIcon( hInstance, "CraneIcon" );
wcClass.lpszMenuName = "CraneMenu";
wcClass.hbrBackground = GetStockObject( WHITE_BRUSH );
wcClass.style = CS_OWNDC;
wcClass.cbClsExtra = 0;
wcClass.cbWndExtra = 0;
RegisterClass( &wcClass );
}
/* Store this instance so window procedures can use it. */
hModule = hInstance;
/* Create the window. */
hClientWnd = CreateWindow( "Crane",
" Crane ",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
SW_SHOWNORMAL,
CW_USEDEFAULT,
0,
NULL,
NULL,
hInstance,
NULL
);
/* Get our display context and initialize it. */
hClientDC = GetDC( hClientWnd );
SetMapMode( hClientDC, MM_ANISOTROPIC );
SetWindowOrg( hClientDC, ZSZ_WINORG, ZSZ_WINORG );
SetWindowExt( hClientDC, ZSZ_WINEXT, ZSZ_WINEXT );
SelectObject( hClientDC, GetStockObject( BLACK_PEN ) );
/* Initialize the crane data. */
ResetCranePts( );
/* Create the dialog procedure pointer. */
lpfnXYZDataDlgProc = MakeProcInstance( XYZDataDlgProc, hModule );
/* Open the record file. */
fhRecordFile = OpenFile( "RECORD.DAT", &ofRecord, OF_CREATE | OF_READWRITE );
if ( !fhRecordFile )
MessageBox( hClientWnd,
"Unable to open record file",
"Error",
MB_ICONEXCLAMATION | MB_OK
);
unRecordCnt = 0;
/* Display this window on the screen. */
ShowWindow( hClientWnd, nCmdShow );
/* Force immediate paint of the client area. */
UpdateWindow( hClientWnd );
return ( TRUE );
}
/******************************************************************************
Function Name: WindowProc
Description:
Processes the messages for the Crane window.
Control Flow:
Return Values:
DefWindowProc specific return values if message not processed
else 0L signalling message was processed.
Notes:
******************************************************************************/
long FAR PASCAL WindowProc(
HWND hWnd, /* Window handle.
*/
unsigned nMsg, /* Message type.
*/
WORD wParam, /* 16-bit parameter.
*/
LONG lParam /* 32-bit parameter.
*/
)
{
/* Process the message. */
switch ( nMsg )
{
case WM_INITMENU:
InitMenu( hWnd, wParam );
break;
case WM_COMMAND:
Menu( hWnd, wParam );
break;
case WM_KEYUP:
Key( hWnd, wParam );
break;
case WM_SIZE:
Size( hWnd, lParam );
break;
case WM_PAINT:
Paint( hWnd );
break;
case WM_CLOSE:
if ( bAnimate )
{
bAnimate = FALSE;
PostMessage( hWnd, nMsg, wParam, lParam );
break;
}
DestroyWindow( hWnd );
break;
case WM_DESTROY:
_lclose( fhRecordFile );
FreeProcInstance( lpfnXYZDataDlgProc );
ReleaseDC( hWnd, hClientDC );
PostQuitMessage( 0 );
break;
default:
return ( DefWindowProc( hWnd, nMsg, wParam, lParam ) );
break;
}
return ( 0L );
}
/******************************************************************************
Function Name: Menu
Description:
Provides processing for menu commands.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL Menu(
HWND hWnd, /* Window handle.
*/
WORD wId /* Command ID.
*/
)
{
/* Variable definition. */
FARPROC lpfnProc; /* Procedure pointer */
/* Check for a Control command. */
if ( WITHIN( wId, MI_CONTROL_MIN, MI_CONTROL_MAX ) )
{
switch ( wId )
{
/* Check for the Reset command. */
case MI_CONTROL_RESET:
ResetCranePts( );
InvalidateRect( hWnd, NULL, TRUE );
break;
/* Check for the About... command. */
case MI_CONTROL_DATA:
hXYZDataDlg = CreateDialog( hModule,
"DATABOX",
hWnd,
lpfnXYZDataDlgProc
);
break;
/* Check for the About... command. */
case MI_CONTROL_ABOUT:
lpfnProc = MakeProcInstance( AboutDlgProc, hModule );
DialogBox( hModule, "ABOUTBOX", hWnd, lpfnProc );
FreeProcInstance( lpfnProc );
break;
}
}
/* Check for an Animate command. */
else if ( WITHIN( wId, MI_ANIMATE_MIN, MI_ANIMATE_MAX ) )
{
switch ( wId )
{
/* Check for the Start command. */
case MI_ANIMATE_START:
bAnimate = TRUE;
rOldErase.left = ZSZ_WINORG;
rOldErase.top = ZSZ_WINORG;
rOldErase.right = ZSZ_WINORG + ZSZ_WINEXT + 1;
rOldErase.bottom = ZSZ_WINORG + ZSZ_WINEXT + 1;
AnimateCranePts( hWnd );
break;
/* Check for the Stop command. */
case MI_ANIMATE_STOP:
bAnimate = FALSE;
break;
}
}
/* Check for a Record command. */
else if ( WITHIN( wId, MI_RECORD_MIN, MI_RECORD_MAX ) )
{
switch ( wId )
{
/* Check for the Start command. */
case MI_RECORD_START:
bRecording = TRUE;
break;
/* Check for the Stop command. */
case MI_RECORD_STOP:
bRecording = FALSE;
break;
/* Check for the Playback command. */
case MI_RECORD_PLAYBACK:
RecordPlayback( hWnd );
break;
/* Check for the Reset command. */
case MI_RECORD_RESET:
unRecordCnt = 0;
_llseek( fhRecordFile, 0L, 0 );
break;
}
}
return;
}
/******************************************************************************
Function Name: InitMenu
Description:
Changes the status of any of the menuitems that require moment to
moment changes.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL InitMenu(
HWND hWnd, /* Window handle.
*/
HMENU hMenu /* Menu handle.
*/
)
{
/* Update the apropiate menu items. */
if ( !hXYZDataDlg )
EnableMenuItem( hMenu, MI_CONTROL_DATA, MF_ENABLED );
else
EnableMenuItem( hMenu, MI_CONTROL_DATA, MF_DISABLED | MF_GRAYED );
if ( !bAnimate )
{
EnableMenuItem( hMenu, MI_ANIMATE_START, MF_ENABLED );
EnableMenuItem( hMenu, MI_ANIMATE_STOP, MF_DISABLED | MF_GRAYED );
}
else
{
EnableMenuItem( hMenu, MI_ANIMATE_START, MF_DISABLED | MF_GRAYED );
EnableMenuItem( hMenu, MI_ANIMATE_STOP, MF_ENABLED );
}
if ( !bRecording )
EnableMenuItem( hMenu, MI_RECORD_START, MF_ENABLED );
else
EnableMenuItem( hMenu, MI_RECORD_START, MF_DISABLED | MF_GRAYED );
if ( bRecording )
EnableMenuItem( hMenu, MI_RECORD_STOP, MF_ENABLED );
else
EnableMenuItem( hMenu, MI_RECORD_STOP, MF_DISABLED | MF_GRAYED );
if ( !bRecording && !bAnimate && unRecordCnt != 0 )
EnableMenuItem( hMenu, MI_RECORD_PLAYBACK, MF_ENABLED );
else
EnableMenuItem( hMenu, MI_RECORD_PLAYBACK, MF_DISABLED | MF_GRAYED );
return;
}
/******************************************************************************
Function Name: XYZDataDlgProc
Description:
This routine will process the XYZ data dialog box.
Control Flow:
Return Values:
Success: TRUE
Failure: FALSE
Notes:
******************************************************************************/
BOOL FAR PASCAL XYZDataDlgProc(
HWND hDlg, /* Dialog window handle.
*/
unsigned nMsg, /* Message to dialog.
*/
WORD wParam, /* Word parameter.
*/
LONG lParam /* Long parameter.
*/
)
{
/* Process the message. */
switch ( nMsg )
{
/* Process the init dialog message. */
case WM_INITDIALOG:
/* Update the data fields. */
UpdateXYZDataDlg( );
SetFocus( GetDlgItem( hDlg, IDOK ) );
return ( FALSE );
break;
/* Process the command message. */
case WM_COMMAND:
/* Parse the control ID. */
switch ( wParam )
{
/* Process the Ok button. */
case IDOK:
DestroyWindow( hDlg );
break;
/* Default processing. */
default:
return ( FALSE );
break;
}
break;
/* Process the destroy message. */
case WM_DESTROY:
hXYZDataDlg = NULL;
break;
/* Default processing. */
default:
return ( FALSE );
break;
}
return ( TRUE );
}
/******************************************************************************
Function Name: UpdateXYZDataDlg
Description:
Updates the controls in the XYZ data dialog.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL UpdateXYZDataDlg( void )
{
/* Update the controls. */
SetDlgItemInt( hXYZDataDlg, ID_XROT, (int) ( pt3dRot.x / PI * 180. ), TRUE );
SetDlgItemInt( hXYZDataDlg, ID_YROT, (int) ( pt3dRot.y / PI * 180. ), TRUE );
SetDlgItemInt( hXYZDataDlg, ID_ZROT, (int) ( pt3dRot.z / PI * 180. ), TRUE );
SetDlgItemInt( hXYZDataDlg, ID_XLOC, (int) ( pt3dLoc.x ), TRUE );
SetDlgItemInt( hXYZDataDlg, ID_YLOC, (int) ( pt3dLoc.y ), TRUE );
SetDlgItemInt( hXYZDataDlg, ID_ZLOC, (int) ( pt3dLoc.z ), TRUE );
SetDlgItemInt( hXYZDataDlg, ID_XMOV, (int) ( cptMove.pt3dNew.x ), TRUE );
SetDlgItemInt( hXYZDataDlg, ID_YMOV, (int) ( cptMove.pt3dNew.y ), TRUE );
SetDlgItemInt( hXYZDataDlg, ID_ZMOV, (int) ( cptMove.pt3dNew.z ), TRUE );
return;
}
/******************************************************************************
Function Name: AboutDlgProc
Description:
Processes the messages for the About dialog window.
Control Flow:
Return Values:
Dialog function dependent.
Notes:
******************************************************************************/
BOOL FAR PASCAL AboutDlgProc(
HWND hDlg, /* Dialog window handle.
*/
unsigned nMsg, /* Message type.
*/
WORD wParam, /* 16-bit parameter.
*/
LONG lParam /* 32-bit parameter.
*/
)
{
/* Process the message. */
switch ( nMsg )
{
/* Process the command message. */
case WM_COMMAND:
/* Parse the control ID. */
switch ( wParam )
{
/* Process the OK button. */
case IDOK:
EndDialog( hDlg, TRUE );
break;
/* Default processing. */
default:
return ( FALSE );
break;
}
break;
/* Default processing. */
default:
return ( FALSE );
break;
}
return ( TRUE );
}
/******************************************************************************
Function Name: AnimateCranePts
Description:
Performs animation on the specific crane points.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL AnimateCranePts(
HWND hWnd /* Window handle.
*/
)
{
/* Variable definition. */
WORD unI, /* Indexing variable */
unIndex; /* Index */
/* Animate the points while animation is requested. */
while ( bAnimate )
{
/* Initialize the erase rectangle. */
rErase.left = 32767;
rErase.top = 32767;
rErase.right = -32767;
rErase.bottom = -32767;
/* Loop and animate the points. */
for ( unI = 0; unI < CNT_ANIMATE; ++unI )
{
aaptList[ unI ].dfCurRot += aaptList[ unI ].dfIncRot;
if ( aaptList[ unI ].dfCurRot <= aaptList[ unI ].dfMinRot ||
aaptList[ unI ].dfCurRot >= aaptList[ unI ].dfMaxRot
)
aaptList[ unI ].dfIncRot = -aaptList[ unI ].dfIncRot;
unIndex = aaptList[ unI ].unPtIndex;
acptList[ unIndex ].pt3dOrg.x = cos( aaptList[ unI ].dfCurRot ) *
aaptList[ unI ].dfDst;
acptList[ unIndex ].pt3dOrg.y = sin( aaptList[ unI ].dfCurRot ) *
aaptList[ unI ].dfDst;
}
/* Compute the location offset. */
CalcNewPt( &cptMove );
pt3dLoc.x += cptMove.pt3dNew.x;
pt3dLoc.y += cptMove.pt3dNew.y;
pt3dLoc.z += cptMove.pt3dNew.z;
/* Calculate the new points. */
CalcNewCranePts( );
/* Compute and erase the update rectangle. */
UnionRect( &rUpdate, &rErase, &rOldErase );
rOldErase = rErase;
/* Convert the update rectangle to device units. */
LPtoDP( hClientDC, (LPPOINT) &rUpdate, 2 );
rUpdate.left -= 2;
rUpdate.top -= 2;
rUpdate.right += 2;
rUpdate.bottom += 2;
InvalidateRect( hWnd, &rUpdate, TRUE );
/* Convert back to logical units. */
DPtoLP( hClientDC, (LPPOINT) &rUpdate, 2 );
/* If recording then write the data. */
if ( bRecording )
RecordWrite( );
/* Update the dialog. */
if ( hXYZDataDlg )
UpdateXYZDataDlg( );
/* Yield. */
myYield( );
}
return;
}
/******************************************************************************
Function Name: CalcNewCranePts
Description:
Calculate the new crane points.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL CalcNewCranePts( void )
{
/* Variable definition. */
WORD unI; /* Indexing variable */
/* Recalculate the points. */
for ( unI = 0; acptList[ unI ].unFlags != CPF_EOL; ++unI )
{
CalcNewPt( &acptList[ unI ] );
aptList[ unI ].x = (int) acptList[ unI ].pt3dNew.x;
aptList[ unI ].y = (int) acptList[ unI ].pt3dNew.y;
if ( aptList[ unI ].x < rErase.left )
rErase.left = aptList[ unI ].x;
if ( aptList[ unI ].y < rErase.top )
rErase.top = aptList[ unI ].y;
if ( aptList[ unI ].x > rErase.right )
rErase.right = aptList[ unI ].x;
if ( aptList[ unI ].y > rErase.bottom )
rErase.bottom = aptList[ unI ].y;
}
return;
}
/******************************************************************************
Function Name: CalcNewPt
Description:
Calculates the new point.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL CalcNewPt(
LPCRANEPT lpcpt /* Crane point pointer.
*/
)
{
/* Variable definition. */
double dfRot, /* Rotation */
dfDst; /* Distance */
/* Reset the point. */
lpcpt->pt3dNew = lpcpt->pt3dOrg;
/* Perform Z rotation. */
if ( lpcpt->pt3dNew.x != 0. || lpcpt->pt3dNew.y != 0. )
{
dfRot = atan2( lpcpt->pt3dNew.y, lpcpt->pt3dNew.x ) + pt3dRot.z;
dfDst = sqrt( lpcpt->pt3dNew.x * lpcpt->pt3dNew.x +
lpcpt->pt3dNew.y * lpcpt->pt3dNew.y
);
lpcpt->pt3dNew.x = ( cos( dfRot ) * dfDst );
lpcpt->pt3dNew.y = ( sin( dfRot ) * dfDst );
}
/* Perform X rotation. */
if ( lpcpt->pt3dNew.z != 0. || lpcpt->pt3dNew.y != 0. )
{
dfRot = atan2( lpcpt->pt3dNew.y, lpcpt->pt3dNew.z ) + pt3dRot.x;
dfDst = sqrt( lpcpt->pt3dNew.z * lpcpt->pt3dNew.z +
lpcpt->pt3dNew.y * lpcpt->pt3dNew.y
);
lpcpt->pt3dNew.z = ( cos( dfRot ) * dfDst );
lpcpt->pt3dNew.y = ( sin( dfRot ) * dfDst );
}
/* Perform Y rotation. */
if ( lpcpt->pt3dNew.x != 0. || lpcpt->pt3dNew.z != 0. )
{
dfRot = atan2( lpcpt->pt3dNew.z, lpcpt->pt3dNew.x ) + pt3dRot.y;
dfDst = sqrt( lpcpt->pt3dNew.x * lpcpt->pt3dNew.x +
lpcpt->pt3dNew.z * lpcpt->pt3dNew.z
);
lpcpt->pt3dNew.x = ( cos( dfRot ) * dfDst );
lpcpt->pt3dNew.z = ( sin( dfRot ) * dfDst );
}
/* Exit if move point. */
if ( lpcpt->unFlags == CPF_MOVE )
return;
/* Adjust relative location and size in space. */
lpcpt->pt3dNew.x += pt3dLoc.x;
lpcpt->pt3dNew.y += pt3dLoc.y;
lpcpt->pt3dNew.z += pt3dLoc.z;
if ( lpcpt->pt3dNew.x != 0. || lpcpt->pt3dNew.y != 0. )
{
dfRot = atan2( lpcpt->pt3dNew.y, lpcpt->pt3dNew.x );
dfDst = sqrt( lpcpt->pt3dNew.x * lpcpt->pt3dNew.x +
lpcpt->pt3dNew.y * lpcpt->pt3dNew.y
);
dfDst *= ( lpcpt->pt3dNew.z - ZSZ_ATMINSIZ ) / ZSZ_ATMAXSIZ;
if ( dfDst < 0. )
dfDst = 0.;
lpcpt->pt3dNew.x = ( cos( dfRot ) * dfDst );
lpcpt->pt3dNew.y = ( sin( dfRot ) * dfDst );
}
return;
}
/******************************************************************************
Function Name: RecordPlayback
Description:
Plays back the recording.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL RecordPlayback(
HWND hWnd /* Window handle.
*/
)
{
/* Variable definition. */
RECT rClient; /* Client rectangle */
HBRUSH hEraseBrush; /* Brush handle */
WORD unC, /* Counting variable */
unI; /* Indexing variable */
/* Erase the background. */
hEraseBrush = GetStockObject( WHITE_BRUSH );
GetClientRect( hWnd, &rClient );
DPtoLP( hClientDC, (LPPOINT) &rClient, 2 );
FillRect( hClientDC, &rClient, hEraseBrush );
/* Playback the records. */
_llseek( fhRecordFile, 0L, 0 );
for ( unC = 0; unC < unRecordCnt; ++unC )
{
/* Read the next set of points. */
RecordRead( );
/* Perform our painting. */
FillRect( hClientDC, &rUpdate, hEraseBrush );
for ( unI = 0; unI < MAX_SHAPES; ++unI )
Polyline( hClientDC,
&aptList[ ashpList[ unI ].unIndex ],
ashpList[ unI ].unCnt
);
}
return;
}
/******************************************************************************
Function Name: RecordRead
Description:
Reads one set of points from the file.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL RecordRead( void )
{
/* Read the points in. */
_lread( fhRecordFile, (LPSTR) &rUpdate, sizeof ( RECT ) );
_lread( fhRecordFile, (LPSTR) aptList, sizeof ( POINT ) * MAX_POINTS );
return;
}
/******************************************************************************
Function Name: RecordWrite
Description:
Writes one set of points to the file.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL RecordWrite( void )
{
/* Read the points in. */
_lwrite( fhRecordFile, (LPSTR) &rUpdate, sizeof ( RECT ) );
_lwrite( fhRecordFile, (LPSTR) aptList, sizeof ( POINT ) * MAX_POINTS );
++unRecordCnt;
return;
}
/******************************************************************************
Function Name: Key
Description:
Provides processing for key events.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL Key(
HWND hWnd, /* Window handle.
*/
WORD wId /* Key ID.
*/
)
{
/* Parse the key pressed and adjust the appropiate rotation amount. */
switch ( wId )
{
case VK_NUMPAD2:
pt3dRot.x -= ROT_INC;
if ( pt3dRot.x <= ROT_MIN )
pt3dRot.x = ROT_MAX;
break;
case VK_NUMPAD8:
pt3dRot.x += ROT_INC;
if ( pt3dRot.x >= ROT_MAX )
pt3dRot.x = ROT_MIN;
break;
case VK_NUMPAD4:
pt3dRot.y -= ROT_INC;
if ( pt3dRot.y <= ROT_MIN )
pt3dRot.y = ROT_MAX;
break;
case VK_NUMPAD6:
pt3dRot.y += ROT_INC;
if ( pt3dRot.y >= ROT_MAX )
pt3dRot.y = ROT_MIN;
break;
case VK_NUMPAD1:
pt3dRot.z -= ROT_INC;
if ( pt3dRot.z <= ROT_MIN )
pt3dRot.z = ROT_MAX;
break;
case VK_NUMPAD9:
pt3dRot.z += ROT_INC;
if ( pt3dRot.z >= ROT_MAX )
pt3dRot.z = ROT_MIN;
break;
default:
return;
break;
}
/* If not animating then calculate the new points and paint them. */
if ( !bAnimate )
{
CalcNewCranePts( );
InvalidateRect( hWnd, NULL, TRUE );
}
return;
}
/******************************************************************************
Function Name: Size
Description:
Performs processing for re-sizing of the client window.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL Size(
HWND hWnd, /* Window handle.
*/
LONG lParam /* 32-bit parameter.
*/
)
{
/* Variable definition. */
POINT ptExt, /* Extents */
ptOrg; /* Origin */
/* Get the new size and update the mapping. */
ptExt = MAKEPOINT( lParam );
if ( ptExt.x < ptExt.y )
{
ptOrg.x = 0;
ptOrg.y = ( ptExt.y - ptExt.x ) / 2;
ptExt.y = ptExt.x;
}
else
{
ptOrg.x = ( ptExt.x - ptExt.y ) / 2;
ptOrg.y = 0;
ptExt.x = ptExt.y;
}
SetViewportOrg( hClientDC, ptOrg.x, ptOrg.y );
SetViewportExt( hClientDC, ptExt.x, ptExt.y );
InvalidateRect( hWnd, NULL, TRUE );
return;
}
/******************************************************************************
Function Name: Paint
Description:
Performs updates on the client area as requested by window messages.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL Paint(
HWND hWnd /* Window handle.
*/
)
{
/* Variable definition. */
PAINTSTRUCT stPS; /* Painting structure */
WORD unI; /* Indexing variable */
/* Prepare the client area for painting. */
BeginPaint( hWnd, &stPS );
/* Perform our painting. */
for ( unI = 0; unI < MAX_SHAPES; ++unI )
Polyline( hClientDC,
&aptList[ ashpList[ unI ].unIndex ],
ashpList[ unI ].unCnt
);
/* We're done so exit. */
EndPaint( hWnd, &stPS );
return;
}
/******************************************************************************
Function Name: ResetCranePts
Description:
Resets the crane points back to the origin.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL ResetCranePts( void )
{
/* Reset the points. */
pt3dRot.x = 0.;
pt3dRot.y = 0.;
pt3dRot.z = 0.;
pt3dLoc.x = 0.;
pt3dLoc.y = 0.;
pt3dLoc.z = 0.;
CalcNewCranePts( );
return;
}
/******************************************************************************
Function Name: myYield
Description:
Uses PeekMessage to yield control.
Control Flow:
Return Values:
None.
Notes:
******************************************************************************/
void NEAR PASCAL myYield( void )
{
/* Variable definition. */
MSG stMsg; /* Buffer to hold message */
/* Process messages until exit. */
while ( PeekMessage( &stMsg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &stMsg );
DispatchMessage( &stMsg );
}
return;
}