441 lines
13 KiB
C
441 lines
13 KiB
C
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <GL\gl.h>
|
|
#include <GL\glu.h>
|
|
|
|
#include "math.h"
|
|
#include "mesh.h"
|
|
#include "globals.h"
|
|
|
|
typedef enum enumINPUTSTATE { IS_EMPTY, IS_INPUT, IS_REALIZED } INPUTSTATE;
|
|
INPUTSTATE gInputState = IS_EMPTY;
|
|
|
|
#define MAX_CURVE_POINTS 128
|
|
|
|
typedef struct _INPUT_CURVE {
|
|
ULONG cPoints;
|
|
POINTL pptl[MAX_CURVE_POINTS];
|
|
} INPUT_CURVE;
|
|
|
|
INPUT_CURVE gInputCurve;
|
|
POINT3D *gppt3d = (POINT3D *) NULL;
|
|
|
|
HWND ghwndInput = NULL;
|
|
HPEN ghpenCurve = NULL, ghpenAxis = NULL, ghpenGrid = NULL;
|
|
HCURSOR ghcurCross = NULL, ghcurArrow = NULL;
|
|
SHORT gsMouseX, gsMouseY;
|
|
|
|
RECT grcClient;
|
|
|
|
void DrawCurve(HWND, HDC, BOOL);
|
|
void InitCurve(void);
|
|
void DeleteCurve(void);
|
|
void AddPointToCurve(POINTL *);
|
|
void RealizeCurve(HWND);
|
|
void SnapPointToGrid(POINTL *, int);
|
|
|
|
#define GRID_SIZE 5
|
|
|
|
void CreateInputWindow( HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow
|
|
)
|
|
{
|
|
static char szInputWindow[] = "Input curve";
|
|
static char szIniFile[] = "lathe.ini";
|
|
RECT Rect;
|
|
WNDCLASS wndclass;
|
|
|
|
if ( !hPrevInstance )
|
|
{
|
|
wndclass.style = CS_OWNDC;
|
|
wndclass.lpfnWndProc = (WNDPROC)InputProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = 0;
|
|
wndclass.hInstance = hInstance;
|
|
//wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wndclass.hCursor = NULL;
|
|
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
|
|
wndclass.lpszMenuName = NULL;
|
|
wndclass.lpszClassName = szInputWindow;
|
|
|
|
// With a NULL icon handle, app will paint into the icon window.
|
|
wndclass.hIcon = NULL;
|
|
//wndclass.hIcon = LoadIcon(hInstance, "CubeIcon");
|
|
|
|
RegisterClass(&wndclass);
|
|
}
|
|
|
|
ghcurArrow = LoadCursor(NULL, IDC_ARROW);
|
|
ghcurCross = LoadCursor(hInstance, "WhiteCross");
|
|
|
|
Rect.left = GetPrivateProfileInt("InputWindow", "left", 50, szIniFile);
|
|
Rect.top = GetPrivateProfileInt("InputWindow", "top", 50, szIniFile);
|
|
Rect.right = GetPrivateProfileInt("InputWindow", "right", 450, szIniFile);
|
|
Rect.bottom = GetPrivateProfileInt("InputWindow", "bottom", 450, szIniFile);
|
|
|
|
AdjustWindowRect( &Rect, WS_OVERLAPPEDWINDOW, FALSE );
|
|
|
|
ghwndInput = CreateWindow(szInputWindow, // window class name
|
|
"Input Curve", // window caption
|
|
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
|
Rect.left, // initial x position
|
|
Rect.top, // initial y position
|
|
WINDSIZEX(Rect), // initial x size
|
|
WINDSIZEY(Rect), // initial y size
|
|
NULL, // parent window handle
|
|
NULL, // window menu handle
|
|
hInstance, // program instance handle
|
|
NULL // creation parameter
|
|
);
|
|
|
|
ShowWindow( ghwndInput, nCmdShow );
|
|
UpdateWindow( ghwndInput );
|
|
}
|
|
|
|
|
|
long
|
|
InputProc ( HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
POINTL ptl, *pptlCur;
|
|
|
|
switch ( message )
|
|
{
|
|
case WM_CREATE:
|
|
GetClientRect(hwnd, &grcClient);
|
|
ghpenGrid = CreatePen(PS_SOLID, 1, PALETTERGB(0x7F, 0x7F, 0x7F));
|
|
ghpenAxis = CreatePen(PS_SOLID, 1, PALETTERGB(0x00, 0xFF, 0x00));
|
|
ghpenCurve = CreatePen(PS_SOLID, 1, PALETTERGB(0xFF, 0x00, 0x00));
|
|
|
|
InitCurve();
|
|
if(hdc = GetDC(hwnd))
|
|
{
|
|
DrawCurve(hwnd, hdc, TRUE);
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
return(0);
|
|
|
|
case WM_PAINT:
|
|
hdc = BeginPaint( hwnd, &ps );
|
|
DrawCurve(hwnd, hdc, TRUE);
|
|
EndPaint( hwnd, &ps );
|
|
return(0);
|
|
|
|
case WM_SIZE:
|
|
GetClientRect(hwnd, &grcClient);
|
|
return(0);
|
|
|
|
case WM_ACTIVATE:
|
|
if ( gInputState == IS_INPUT )
|
|
{
|
|
if ( LOWORD(wParam) & WA_INACTIVE )
|
|
{
|
|
SetCursor(ghcurArrow);
|
|
ReleaseCapture();
|
|
}
|
|
else
|
|
{
|
|
SetCursor(ghcurCross);
|
|
SetCapture(hwnd);
|
|
}
|
|
}
|
|
return(0);
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
switch (gInputState)
|
|
{
|
|
case IS_EMPTY:
|
|
gInputState = IS_INPUT;
|
|
SetCursor(ghcurCross);
|
|
|
|
// Fall into code below.
|
|
|
|
case IS_INPUT:
|
|
SetCapture(hwnd);
|
|
|
|
ptl.x = LOWORD(lParam);
|
|
ptl.y = HIWORD(lParam);
|
|
SnapPointToGrid(&ptl, GRID_SIZE);
|
|
AddPointToCurve(&ptl);
|
|
gsMouseX = ptl.x;
|
|
gsMouseY = ptl.y;
|
|
|
|
if(hdc = GetDC(hwnd))
|
|
{
|
|
DrawCurve(hwnd, hdc, FALSE);
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
|
|
break;
|
|
|
|
case IS_REALIZED:
|
|
default:
|
|
break;
|
|
}
|
|
return (0);
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
if ( gInputState == IS_INPUT )
|
|
{
|
|
ptl.x = LOWORD(lParam);
|
|
ptl.y = HIWORD(lParam);
|
|
|
|
if ( ptl.x < grcClient.right && ptl.y < grcClient.bottom )
|
|
{
|
|
SnapPointToGrid(&ptl, GRID_SIZE);
|
|
|
|
SetCursor(ghcurCross);
|
|
|
|
if (hdc = GetDC(hwnd))
|
|
{
|
|
pptlCur = &gInputCurve.pptl[gInputCurve.cPoints-1];
|
|
|
|
SetROP2(hdc, R2_NOT);
|
|
SelectObject(hdc, ghpenCurve);
|
|
MoveToEx(hdc, pptlCur->x, pptlCur->y, NULL);
|
|
LineTo(hdc, gsMouseX, gsMouseY);
|
|
|
|
gsMouseX = ptl.x;
|
|
gsMouseY = ptl.y;
|
|
|
|
MoveToEx(hdc, pptlCur->x, pptlCur->y, NULL);
|
|
LineTo(hdc, gsMouseX, gsMouseY);
|
|
SetROP2(hdc, R2_COPYPEN);
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (hdc = GetDC(hwnd))
|
|
{
|
|
pptlCur = &gInputCurve.pptl[gInputCurve.cPoints-1];
|
|
|
|
SetROP2(hdc, R2_NOT);
|
|
SelectObject(hdc, ghpenCurve);
|
|
MoveToEx(hdc, pptlCur->x, pptlCur->y, NULL);
|
|
LineTo(hdc, gsMouseX, gsMouseY);
|
|
SetROP2(hdc, R2_COPYPEN);
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
SetCursor(ghcurArrow);
|
|
ReleaseCapture();
|
|
}
|
|
}
|
|
return (0);
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
switch (gInputState)
|
|
{
|
|
case IS_INPUT:
|
|
RealizeCurve(hwnd);
|
|
if (hdc = GetDC(hwnd))
|
|
{
|
|
pptlCur = &gInputCurve.pptl[gInputCurve.cPoints-1];
|
|
|
|
SetROP2(hdc, R2_NOT);
|
|
SelectObject(hdc, ghpenCurve);
|
|
MoveToEx(hdc, pptlCur->x, pptlCur->y, NULL);
|
|
LineTo(hdc, gsMouseX, gsMouseY);
|
|
SetROP2(hdc, R2_COPYPEN);
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
gInputState = IS_REALIZED;
|
|
SetCursor(ghcurArrow);
|
|
ReleaseCapture();
|
|
break;
|
|
|
|
case IS_REALIZED:
|
|
DeleteCurve();
|
|
gInputState = IS_EMPTY;
|
|
|
|
if(hdc = GetDC(hwnd))
|
|
{
|
|
DrawCurve(hwnd, hdc, TRUE);
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
SetCursor(ghcurArrow);
|
|
ReleaseCapture();
|
|
break;
|
|
}
|
|
return (0);
|
|
|
|
case WM_KEYDOWN:
|
|
switch (wParam)
|
|
{
|
|
case VK_ESCAPE:
|
|
PostMessage(hwnd, WM_DESTROY, 0, 0);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return(0);
|
|
|
|
case WM_CHAR:
|
|
switch(wParam)
|
|
{
|
|
case 'w':
|
|
case 'W':
|
|
DestroyWindow(ghwndObject);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage( 0 );
|
|
PostMessage(ghwndObject, WM_QUIT, 0, 0); // quit object thread too
|
|
return(0);
|
|
|
|
}
|
|
return( DefWindowProc( hwnd, message, wParam, lParam ) );
|
|
}
|
|
|
|
void InitCurve()
|
|
{
|
|
gInputCurve.cPoints = 0;
|
|
}
|
|
|
|
void DeleteCurve()
|
|
{
|
|
gInputCurve.cPoints = 0;
|
|
}
|
|
|
|
void AddPointToCurve(POINTL *pptl)
|
|
{
|
|
if (gInputCurve.cPoints < MAX_CURVE_POINTS)
|
|
{
|
|
gInputCurve.pptl[gInputCurve.cPoints] = *pptl;
|
|
gInputCurve.cPoints++;
|
|
}
|
|
else
|
|
MessageBox(NULL, "Too many points", "Temp hack warning", MB_OK);
|
|
}
|
|
|
|
void DrawCurve(HWND hwnd, HDC hdc, BOOL bClear)
|
|
{
|
|
POINTL *pptl, *pptlEnd;
|
|
|
|
if (bClear)
|
|
{
|
|
BitBlt(hdc, grcClient.left, grcClient.top,
|
|
WINDSIZEX(grcClient), WINDSIZEY(grcClient),
|
|
NULL, 0, 0, BLACKNESS);
|
|
|
|
SelectObject(hdc, ghpenAxis);
|
|
MoveToEx(hdc, grcClient.right/2, 0, NULL);
|
|
LineTo(hdc, grcClient.right/2, grcClient.bottom);
|
|
MoveToEx(hdc, 0, grcClient.bottom/2, NULL);
|
|
LineTo(hdc, grcClient.right, grcClient.bottom/2);
|
|
|
|
}
|
|
|
|
#if 0
|
|
if (gInputCurve.cPoints)
|
|
{
|
|
SelectObject(hdc, ghpen);
|
|
|
|
pptl = gInputCurve.pptl;
|
|
pptlEnd = pptl + gInputCurve.cPoints;
|
|
|
|
MoveToEx(hdc, pptl->x, pptl->y, NULL);
|
|
pptl += 1;
|
|
|
|
while (pptl < pptlEnd)
|
|
{
|
|
LineTo(hdc, pptl->x, pptl->y);
|
|
pptl += 1;
|
|
}
|
|
}
|
|
#else
|
|
if ( gInputCurve.cPoints )
|
|
{
|
|
SelectObject(hdc, ghpenCurve);
|
|
Polyline(hdc, gInputCurve.pptl, gInputCurve.cPoints);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void RealizeCurve(HWND hwnd)
|
|
{
|
|
POINTL *pptl, *pptlEnd;
|
|
POINT3D *ppt3dNew;
|
|
GLfloat w, h;
|
|
|
|
if (!gInputCurve.cPoints)
|
|
return;
|
|
|
|
w = (GLfloat) (WINDSIZEX(grcClient) / 2);
|
|
h = (GLfloat) (WINDSIZEY(grcClient) / 2);
|
|
|
|
pptl = gInputCurve.pptl;
|
|
pptlEnd = pptl + gInputCurve.cPoints;
|
|
|
|
// Allocate new 3d curve data array.
|
|
|
|
if (gppt3d)
|
|
LocalFree(gppt3d);
|
|
|
|
gppt3d = (POINT3D *) LocalAlloc(LMEM_FIXED,
|
|
gInputCurve.cPoints * sizeof(POINT3D));
|
|
if (!gppt3d)
|
|
{
|
|
MessageBox(NULL, "Out of memory.", "Error", MB_OK);
|
|
return;
|
|
}
|
|
|
|
for (ppt3dNew = gppt3d; pptl < pptlEnd; pptl+=1, ppt3dNew += 1)
|
|
{
|
|
ppt3dNew->x = ((GLfloat) pptl->x - w) / w;
|
|
ppt3dNew->y = (h - (GLfloat) pptl->y) / h;
|
|
ppt3dNew->z = 0.0f;
|
|
}
|
|
|
|
// Stick it into the 3D curve structure.
|
|
|
|
curve.pts = gppt3d;
|
|
curve.numPoints = gInputCurve.cPoints;
|
|
|
|
vInputThreadMakeObject();
|
|
}
|
|
|
|
|
|
void SnapPointToGrid(POINTL *pptl, int iGridSize)
|
|
{
|
|
int xOrg = WINDSIZEX(grcClient), yOrg = WINDSIZEY(grcClient);
|
|
int xRel = pptl->x - xOrg;
|
|
int yRel = pptl->y - yOrg;
|
|
int xDelt, yDelt;
|
|
|
|
xDelt = abs(xRel) % iGridSize;
|
|
yDelt = abs(yRel) % iGridSize;
|
|
|
|
if ( xDelt <= (iGridSize / 2) )
|
|
pptl->x -= xDelt * (xRel >= 0 ? 1 : -1);
|
|
else
|
|
pptl->x += (iGridSize - xDelt) * (xRel >= 0 ? 1 : -1);
|
|
|
|
if ( yDelt <= (iGridSize / 2) )
|
|
pptl->y -= yDelt * (yRel >= 0 ? 1 : -1);
|
|
else
|
|
pptl->y += (iGridSize - yDelt) * (yRel >= 0 ? 1 : -1);
|
|
}
|