2025-04-27 07:49:33 -04:00

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);
}