779 lines
19 KiB
C
779 lines
19 KiB
C
|
/******************************Module*Header*******************************\
|
||
|
* Module Name: glwindow.c
|
||
|
*
|
||
|
* OpenGL window maintenance.
|
||
|
*
|
||
|
* Created: 09-Mar-1995 15:10:10
|
||
|
* Author: Gilman Wong [gilmanw]
|
||
|
*
|
||
|
* Copyright (c) 1995 Microsoft Corporation
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#include "global.h"
|
||
|
#include "glwindow.h"
|
||
|
#include "nff.h"
|
||
|
#include "trackbal.h"
|
||
|
|
||
|
// Move global stuff into SCENE struct.
|
||
|
|
||
|
HGLRC ghrc = (HGLRC) 0;
|
||
|
HPALETTE ghpalOld, ghPalette = (HPALETTE) 0;
|
||
|
BOOL bUseStatic = FALSE;
|
||
|
UINT uiSysPalUse = SYSPAL_STATIC;
|
||
|
|
||
|
extern void DoGlStuff(HWND, HDC);
|
||
|
extern HGLRC hrcInitGL(HWND, HDC);
|
||
|
extern void stateInit(HWND, HDC);
|
||
|
extern void vCleanupGL(HGLRC, HDC);
|
||
|
extern BOOL bSetupPixelFormat(HDC);
|
||
|
extern void CreateRGBPalette(HDC);
|
||
|
extern VOID vSetSize(HWND);
|
||
|
extern void ForceRedraw(HWND);
|
||
|
extern SCENE *OpenScene(LPSTR lpstrFile);
|
||
|
|
||
|
CHAR lpstrFile[256];
|
||
|
|
||
|
// Global ambient lights.
|
||
|
|
||
|
static GLfloat lightAmbient[4] = {0.4f, 0.4f, 0.4f, 1.0f};
|
||
|
static GLfloat lightAmbientLow[4] = {0.2f, 0.2f, 0.2f, 1.0f};
|
||
|
|
||
|
//!!!move to SCENE structure
|
||
|
// Trackball stuff
|
||
|
|
||
|
POINT gptWindow;
|
||
|
SIZE gszWindow; // already in SCENE
|
||
|
float curquat[4], lastquat[4];
|
||
|
LONG glMouseDownX, glMouseDownY;
|
||
|
BOOL gbLeftMouse = FALSE;
|
||
|
BOOL gbSpinning = FALSE;
|
||
|
|
||
|
float zoom = 1.0f;
|
||
|
|
||
|
//!!!move to SCENE structure
|
||
|
typedef enum enumPOLYDRAW {
|
||
|
POLYDRAW_FILLED = 0,
|
||
|
POLYDRAW_LINES = 1,
|
||
|
POLYDRAW_POINTS = 2
|
||
|
} POLYDRAW;
|
||
|
typedef enum enumSHADE {
|
||
|
SHADE_SMOOTH = 0,
|
||
|
SHADE_FLAT = 1
|
||
|
} SHADE;
|
||
|
typedef enum enumLIGHT {
|
||
|
LIGHT_OFF = 0,
|
||
|
LIGHT_INFINITE = 1,
|
||
|
LIGHT_LOCAL = 2
|
||
|
} LIGHT;
|
||
|
SHADE gShadeMode = SHADE_SMOOTH;
|
||
|
POLYDRAW gPolyDrawMode = POLYDRAW_FILLED;
|
||
|
LIGHT gLightMode = LIGHT_INFINITE;
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* MyCreateGLWindow
|
||
|
*
|
||
|
* Setup the windows.
|
||
|
*
|
||
|
* History:
|
||
|
* 15-Dec-1994 -by- Gilman Wong [gilmanw]
|
||
|
* Wrote it.
|
||
|
\**************************************************************************/
|
||
|
|
||
|
HWND MyCreateGLWindow(HINSTANCE hInstance, LPTSTR lpstr)
|
||
|
{
|
||
|
WNDCLASS wc;
|
||
|
RECT rcl;
|
||
|
HWND hwnd;
|
||
|
|
||
|
lstrcpy(lpstrFile, lpstr);
|
||
|
|
||
|
// Create the OpenGL window.
|
||
|
|
||
|
wc.style = CS_OWNDC;
|
||
|
wc.lpfnWndProc = GLWndProc;
|
||
|
wc.cbClsExtra = 0;
|
||
|
wc.cbWndExtra = 0;
|
||
|
wc.hInstance = hInstance;
|
||
|
wc.hIcon = NULL;
|
||
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||
|
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||
|
wc.lpszMenuName = NULL;
|
||
|
wc.lpszClassName = "GLWClass";
|
||
|
RegisterClass(&wc);
|
||
|
|
||
|
hwnd = CreateWindow(
|
||
|
"GLWClass",
|
||
|
"OpenGL stuff",
|
||
|
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
||
|
//CW_USEDEFAULT,
|
||
|
//CW_USEDEFAULT,
|
||
|
300,
|
||
|
0,
|
||
|
100,
|
||
|
100,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
hInstance,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
//!!!hack -- not really the right coordinates
|
||
|
gptWindow.x = 0;
|
||
|
gptWindow.y = 300;
|
||
|
gszWindow.cx = 100;
|
||
|
gszWindow.cy = 100;
|
||
|
|
||
|
if (hwnd)
|
||
|
{
|
||
|
ShowWindow(hwnd, SW_NORMAL);
|
||
|
UpdateWindow(hwnd);
|
||
|
}
|
||
|
|
||
|
SetTimer(hwnd, 1, 1, NULL);
|
||
|
|
||
|
return hwnd;
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* GLWndProc
|
||
|
*
|
||
|
* WndProc for the OpenGL window.
|
||
|
*
|
||
|
* History:
|
||
|
* 15-Dec-1994 -by- Gilman Wong [gilmanw]
|
||
|
* Wrote it.
|
||
|
\**************************************************************************/
|
||
|
|
||
|
long FAR PASCAL GLWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
long lRet = 0;
|
||
|
RECT rcl;
|
||
|
HDC hdc;
|
||
|
PAINTSTRUCT ps;
|
||
|
SCENE *scene;
|
||
|
|
||
|
if (message != WM_CREATE)
|
||
|
scene = (SCENE *) GetWindowLong(hwnd, GWL_USERDATA);
|
||
|
|
||
|
// Process window message.
|
||
|
|
||
|
switch (message)
|
||
|
{
|
||
|
case WM_CREATE:
|
||
|
//LBprintf("WM_CREATE");
|
||
|
|
||
|
if(hdc = GetDC(hwnd))
|
||
|
{
|
||
|
if (ghrc == (HGLRC) 0)
|
||
|
ghrc = hrcInitGL(hwnd, hdc);
|
||
|
|
||
|
scene = OpenScene(lpstrFile);
|
||
|
if (scene)
|
||
|
{
|
||
|
SetWindowLong(hwnd, GWL_USERDATA, (LONG) scene);
|
||
|
rcl.left = 0;
|
||
|
rcl.top = 0;
|
||
|
rcl.right = scene->szWindow.cx;
|
||
|
rcl.bottom = scene->szWindow.cy;
|
||
|
AdjustWindowRect(&rcl, WS_OVERLAPPEDWINDOW, 0);
|
||
|
SetWindowPos(hwnd, NULL, 0, 0,
|
||
|
rcl.right, rcl.bottom,
|
||
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS);
|
||
|
|
||
|
stateInit(hwnd, hdc);
|
||
|
}
|
||
|
else
|
||
|
lRet = -1;
|
||
|
|
||
|
ReleaseDC(hwnd,hdc);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_MOVE:
|
||
|
gptWindow.x = (int) LOWORD(lParam);
|
||
|
gptWindow.y = (int) HIWORD(lParam);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_SIZE:
|
||
|
gszWindow.cx = LOWORD(lParam);
|
||
|
gszWindow.cy = HIWORD(lParam);
|
||
|
scene->szWindow.cx = LOWORD(lParam);
|
||
|
scene->szWindow.cy = HIWORD(lParam);
|
||
|
vSetSize(hwnd);
|
||
|
ForceRedraw(hwnd);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_PAINT:
|
||
|
//LBprintf("WM_PAINT");
|
||
|
|
||
|
hdc = BeginPaint( hwnd, &ps );
|
||
|
|
||
|
DoGlStuff( hwnd, hdc );
|
||
|
|
||
|
EndPaint( hwnd, &ps );
|
||
|
break;
|
||
|
|
||
|
case WM_PALETTECHANGED:
|
||
|
//LBprintf("WM_PALETTECHANGED");
|
||
|
|
||
|
if (hwnd != (HWND) wParam)
|
||
|
{
|
||
|
if (hdc = GetDC(hwnd))
|
||
|
{
|
||
|
UnrealizeObject(ghPalette);
|
||
|
SelectPalette(hdc, ghPalette, TRUE);
|
||
|
if (RealizePalette(hdc) != GDI_ERROR)
|
||
|
lRet = 1;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_QUERYNEWPALETTE:
|
||
|
//LBprintf("WM_QUERYNEWPALETTE");
|
||
|
|
||
|
if (hdc = GetDC(hwnd))
|
||
|
{
|
||
|
UnrealizeObject(ghPalette);
|
||
|
SelectPalette(hdc, ghPalette, FALSE);
|
||
|
if (RealizePalette(hdc) != GDI_ERROR)
|
||
|
lRet = 1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_KEYDOWN:
|
||
|
switch (wParam)
|
||
|
{
|
||
|
case VK_ESCAPE: // <ESC> is quick exit
|
||
|
|
||
|
PostMessage(hwnd, WM_DESTROY, 0, 0);
|
||
|
break;
|
||
|
|
||
|
case VK_UP:
|
||
|
zoom *= .8f;
|
||
|
if (zoom < 1.0f && zoom > .8f)
|
||
|
zoom = 1.0f;
|
||
|
LBprintf("Zoom = %f", zoom);
|
||
|
vSetSize(hwnd);
|
||
|
break;
|
||
|
|
||
|
case VK_DOWN:
|
||
|
zoom *= 1.25f;
|
||
|
if (zoom > 1.0f && zoom < 1.25f)
|
||
|
zoom = 1.0f;
|
||
|
LBprintf("Zoom = %f", zoom);
|
||
|
vSetSize(hwnd);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_CHAR:
|
||
|
switch(wParam)
|
||
|
{
|
||
|
case 's':
|
||
|
case 'S':
|
||
|
gShadeMode = (gShadeMode + 1) % 2;
|
||
|
glShadeModel( gShadeMode == SHADE_FLAT ? GL_FLAT : GL_SMOOTH );
|
||
|
LBprintf("glShadeModel(%s)", gShadeMode == SHADE_FLAT ? "GL_FLAT" :
|
||
|
"GL_SMOOTH");
|
||
|
break;
|
||
|
|
||
|
case 'p':
|
||
|
case 'P':
|
||
|
gPolyDrawMode = (gPolyDrawMode + 1) % 3;
|
||
|
switch (gPolyDrawMode)
|
||
|
{
|
||
|
case POLYDRAW_POINTS:
|
||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
||
|
break;
|
||
|
case POLYDRAW_LINES:
|
||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||
|
break;
|
||
|
case POLYDRAW_FILLED:
|
||
|
default:
|
||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||
|
break;
|
||
|
}
|
||
|
LBprintf("glPolygonMode(%s)", gPolyDrawMode == POLYDRAW_POINTS ? "GL_POINT" :
|
||
|
gPolyDrawMode == POLYDRAW_LINES ? "GL_LINE" :
|
||
|
"GL_FILL");
|
||
|
break;
|
||
|
|
||
|
case 'l':
|
||
|
case 'L':
|
||
|
gLightMode = (gLightMode + 1) % 3;
|
||
|
if ( gLightMode != LIGHT_OFF )
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
glEnable(GL_NORMALIZE);
|
||
|
glEnable(GL_LIGHTING);
|
||
|
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
||
|
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,
|
||
|
gLightMode == LIGHT_LOCAL ? GL_TRUE : GL_FALSE);
|
||
|
for (i = 0; i < scene->Lights.count; i++)
|
||
|
{
|
||
|
glCallList(scene->Lights.listBase + i);
|
||
|
glEnable(GL_LIGHT0 + i);
|
||
|
}
|
||
|
|
||
|
/* If no other lights, turn on ambient on higher */
|
||
|
|
||
|
if (!scene->Lights.count)
|
||
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &lightAmbient);
|
||
|
else
|
||
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &lightAmbientLow);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
glDisable(GL_NORMALIZE);
|
||
|
glDisable(GL_LIGHTING);
|
||
|
}
|
||
|
LBprintf("Light = %s", gLightMode == LIGHT_OFF ? "disabled" :
|
||
|
gLightMode == LIGHT_INFINITE ? "infinite" :
|
||
|
"local");
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ForceRedraw(hwnd);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONDOWN:
|
||
|
|
||
|
SetCapture(hwnd);
|
||
|
|
||
|
glMouseDownX = LOWORD(lParam);
|
||
|
glMouseDownY = HIWORD(lParam);
|
||
|
gbLeftMouse = TRUE;
|
||
|
|
||
|
ForceRedraw(hwnd);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONUP:
|
||
|
|
||
|
ReleaseCapture();
|
||
|
|
||
|
gbLeftMouse = FALSE;
|
||
|
|
||
|
ForceRedraw(hwnd);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_TIMER:
|
||
|
hdc = GetDC(hwnd);
|
||
|
DoGlStuff( hwnd, hdc );
|
||
|
ReleaseDC(hwnd, hdc);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
KillTimer(hwnd, 1);
|
||
|
hdc = GetDC(hwnd);
|
||
|
vCleanupGL(ghrc, hdc);
|
||
|
ReleaseDC(hwnd, hdc);
|
||
|
PostQuitMessage( 0 );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
lRet = DefWindowProc(hwnd, message, wParam, lParam);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return lRet;
|
||
|
}
|
||
|
|
||
|
unsigned char threeto8[8] = {
|
||
|
0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
|
||
|
};
|
||
|
|
||
|
unsigned char twoto8[4] = {
|
||
|
0, 0x55, 0xaa, 0xff
|
||
|
};
|
||
|
|
||
|
unsigned char oneto8[2] = {
|
||
|
0, 255
|
||
|
};
|
||
|
|
||
|
unsigned char
|
||
|
ComponentFromIndex(i, nbits, shift)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = i >> shift;
|
||
|
switch (nbits) {
|
||
|
|
||
|
case 1:
|
||
|
val &= 0x1;
|
||
|
return oneto8[val];
|
||
|
|
||
|
case 2:
|
||
|
val &= 0x3;
|
||
|
return twoto8[val];
|
||
|
|
||
|
case 3:
|
||
|
val &= 0x7;
|
||
|
return threeto8[val];
|
||
|
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CreateRGBPalette(HDC hdc)
|
||
|
{
|
||
|
PIXELFORMATDESCRIPTOR pfd, *ppfd;
|
||
|
LOGPALETTE *pPal;
|
||
|
int n, i;
|
||
|
|
||
|
ppfd = &pfd;
|
||
|
n = GetPixelFormat(hdc);
|
||
|
DescribePixelFormat(hdc, n, sizeof(PIXELFORMATDESCRIPTOR), ppfd);
|
||
|
|
||
|
if (ppfd->dwFlags & PFD_NEED_PALETTE) {
|
||
|
n = 1 << ppfd->cColorBits;
|
||
|
pPal = (PLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
|
||
|
n * sizeof(PALETTEENTRY));
|
||
|
pPal->palVersion = 0x300;
|
||
|
pPal->palNumEntries = n;
|
||
|
for (i=0; i<n; i++) {
|
||
|
pPal->palPalEntry[i].peRed =
|
||
|
ComponentFromIndex(i, ppfd->cRedBits, ppfd->cRedShift);
|
||
|
pPal->palPalEntry[i].peGreen =
|
||
|
ComponentFromIndex(i, ppfd->cGreenBits, ppfd->cGreenShift);
|
||
|
pPal->palPalEntry[i].peBlue =
|
||
|
ComponentFromIndex(i, ppfd->cBlueBits, ppfd->cBlueShift);
|
||
|
pPal->palPalEntry[i].peFlags = (i == 0 || i == 255) ? 0 : PC_NOCOLLAPSE;
|
||
|
}
|
||
|
ghPalette = CreatePalette(pPal);
|
||
|
LocalFree(pPal);
|
||
|
|
||
|
if (ppfd->dwFlags & PFD_NEED_SYSTEM_PALETTE)
|
||
|
{
|
||
|
uiSysPalUse = SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
|
||
|
bUseStatic = TRUE;
|
||
|
}
|
||
|
|
||
|
ghpalOld = SelectPalette(hdc, ghPalette, FALSE);
|
||
|
n = RealizePalette(hdc);
|
||
|
UnrealizeObject(ghPalette);
|
||
|
n = RealizePalette(hdc);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL bSetupPixelFormat(HDC hdc)
|
||
|
{
|
||
|
PIXELFORMATDESCRIPTOR pfd, *ppfd;
|
||
|
int pixelformat;
|
||
|
|
||
|
ppfd = &pfd;
|
||
|
|
||
|
memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
||
|
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||
|
ppfd->nVersion = 1;
|
||
|
ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||
|
ppfd->dwLayerMask = PFD_MAIN_PLANE;
|
||
|
|
||
|
ppfd->iPixelType = PFD_TYPE_RGBA;
|
||
|
ppfd->cColorBits = 24;
|
||
|
|
||
|
ppfd->cDepthBits = 16;
|
||
|
ppfd->cAccumBits = 0;
|
||
|
ppfd->cStencilBits = 0;
|
||
|
|
||
|
pixelformat = ChoosePixelFormat(hdc, ppfd);
|
||
|
|
||
|
if ( (pixelformat = ChoosePixelFormat(hdc, ppfd)) == 0 )
|
||
|
{
|
||
|
MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (SetPixelFormat(hdc, pixelformat, ppfd) == FALSE)
|
||
|
{
|
||
|
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
CreateRGBPalette(hdc);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
HGLRC hrcInitGL(HWND hwnd, HDC hdc)
|
||
|
{
|
||
|
HGLRC hrc;
|
||
|
|
||
|
/* Create a Rendering Context */
|
||
|
|
||
|
bSetupPixelFormat( hdc );
|
||
|
hrc = wglCreateContext( hdc );
|
||
|
|
||
|
/* Make it Current */
|
||
|
|
||
|
wglMakeCurrent( hdc, hrc );
|
||
|
|
||
|
return hrc;
|
||
|
}
|
||
|
|
||
|
void stateInit(HWND hwnd, HDC hdc)
|
||
|
{
|
||
|
GLint i;
|
||
|
SCENE *scene = (SCENE *) GetWindowLong(hwnd, GWL_USERDATA); //!!! pass instead
|
||
|
|
||
|
glDrawBuffer(GL_BACK);
|
||
|
|
||
|
/* Set the clear color */
|
||
|
|
||
|
glClearColor( scene->rgbaClear.r, scene->rgbaClear.g,
|
||
|
scene->rgbaClear.b, scene->rgbaClear.a );
|
||
|
|
||
|
/* Turn on z-buffer */
|
||
|
|
||
|
glEnable(GL_DEPTH_TEST);
|
||
|
|
||
|
/* Turn on backface culling */
|
||
|
|
||
|
glFrontFace(GL_CCW);
|
||
|
//glEnable(GL_CULL_FACE);
|
||
|
|
||
|
/* Shading */
|
||
|
|
||
|
glShadeModel( gShadeMode == SHADE_FLAT ? GL_FLAT : GL_SMOOTH );
|
||
|
|
||
|
/* Polygon draw mode */
|
||
|
|
||
|
switch (gPolyDrawMode)
|
||
|
{
|
||
|
case POLYDRAW_POINTS:
|
||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
||
|
break;
|
||
|
case POLYDRAW_LINES:
|
||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||
|
break;
|
||
|
case POLYDRAW_FILLED:
|
||
|
default:
|
||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Turn on the lights */
|
||
|
|
||
|
if ( gLightMode != LIGHT_OFF )
|
||
|
{
|
||
|
glEnable(GL_NORMALIZE);
|
||
|
glEnable(GL_LIGHTING);
|
||
|
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
||
|
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,
|
||
|
gLightMode == LIGHT_LOCAL ? GL_TRUE : GL_FALSE);
|
||
|
for (i = 0; i < scene->Lights.count; i++)
|
||
|
{
|
||
|
glCallList(scene->Lights.listBase + i);
|
||
|
glEnable(GL_LIGHT0 + i);
|
||
|
}
|
||
|
|
||
|
/* If no other lights, turn on ambient on higher */
|
||
|
|
||
|
if (!scene->Lights.count)
|
||
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &lightAmbient);
|
||
|
else
|
||
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &lightAmbientLow);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
glDisable(GL_NORMALIZE);
|
||
|
glDisable(GL_LIGHTING);
|
||
|
}
|
||
|
|
||
|
/* Setup viewport */
|
||
|
|
||
|
vSetSize(hwnd);
|
||
|
|
||
|
/* Initialize trackball */
|
||
|
|
||
|
trackball(curquat, 0.0, 0.0, 0.0, 0.0);
|
||
|
}
|
||
|
|
||
|
VOID vSetSize(HWND hwnd)
|
||
|
{
|
||
|
SCENE *scene = (SCENE *) GetWindowLong(hwnd, GWL_USERDATA); //!!! pass instead
|
||
|
MyXYZ xyzZoomFrom;
|
||
|
GLfloat localPerspective = scene->AspectRatio;
|
||
|
|
||
|
/* Adjust aspect ratio to window size */
|
||
|
|
||
|
localPerspective *= ((GLfloat) scene->szWindow.cx / (GLfloat) scene->szWindow.cy);
|
||
|
|
||
|
/* Compute the vector from xyzAt to xyzFrom */
|
||
|
|
||
|
xyzZoomFrom.x = scene->xyzFrom.x - scene->xyzAt.x;
|
||
|
xyzZoomFrom.y = scene->xyzFrom.y - scene->xyzAt.y;
|
||
|
xyzZoomFrom.z = scene->xyzFrom.z - scene->xyzAt.z;
|
||
|
|
||
|
/* Scale by the zoom factor */
|
||
|
|
||
|
xyzZoomFrom.x *= zoom;
|
||
|
xyzZoomFrom.y *= zoom;
|
||
|
xyzZoomFrom.z *= zoom;
|
||
|
|
||
|
/* Compute new xyzFrom */
|
||
|
|
||
|
xyzZoomFrom.x += scene->xyzAt.x;
|
||
|
xyzZoomFrom.y += scene->xyzAt.y;
|
||
|
xyzZoomFrom.z += scene->xyzAt.x;
|
||
|
|
||
|
/* Set up viewport extents */
|
||
|
|
||
|
glViewport(0, 0, scene->szWindow.cx, scene->szWindow.cy);
|
||
|
|
||
|
/* Set up the projection matrix */
|
||
|
|
||
|
glMatrixMode(GL_PROJECTION);
|
||
|
glLoadIdentity();
|
||
|
//gluPerspective(scene->ViewAngle, scene->AspectRatio,
|
||
|
// scene->Hither, scene->Yon);
|
||
|
gluPerspective(scene->ViewAngle, localPerspective,
|
||
|
scene->Hither, scene->Yon * zoom);
|
||
|
|
||
|
/* Set up the model matrix */
|
||
|
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
glLoadIdentity();
|
||
|
//gluLookAt(scene->xyzFrom.x,scene->xyzFrom.y,scene->xyzFrom.z,
|
||
|
// scene->xyzAt.x,scene->xyzAt.y,scene->xyzAt.z,
|
||
|
// scene->xyzUp.x,scene->xyzUp.y,scene->xyzUp.z);
|
||
|
gluLookAt(xyzZoomFrom.x,xyzZoomFrom.y,xyzZoomFrom.z,
|
||
|
scene->xyzAt.x,scene->xyzAt.y,scene->xyzAt.z,
|
||
|
scene->xyzUp.x,scene->xyzUp.y,scene->xyzUp.z);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
vCleanupGL(HGLRC hrc, HDC hdc)
|
||
|
{
|
||
|
//if (ghPalette)
|
||
|
// DeleteObject(SelectObject(ghdcMem, ghpalOld));
|
||
|
|
||
|
/* Destroy our context */
|
||
|
|
||
|
wglDeleteContext( hrc );
|
||
|
|
||
|
if (bUseStatic)
|
||
|
SetSystemPaletteUse(hdc, uiSysPalUse);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ForceRedraw(HWND hwnd)
|
||
|
{
|
||
|
MSG msg;
|
||
|
|
||
|
if (!PeekMessage(&msg, hwnd, WM_PAINT, WM_PAINT, PM_NOREMOVE) )
|
||
|
{
|
||
|
InvalidateRect(hwnd, NULL, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
DoGlStuff( HWND hwnd, HDC hdc )
|
||
|
{
|
||
|
SCENE *scene = (SCENE *) GetWindowLong(hwnd, GWL_USERDATA); //!!! pass instead
|
||
|
USHORT usMouseCurX, usMouseCurY;
|
||
|
POINT pt;
|
||
|
float matRot[4][4];
|
||
|
|
||
|
if (gbLeftMouse)
|
||
|
{
|
||
|
if (GetCursorPos(&pt))
|
||
|
{
|
||
|
// Subtract current window origin to convert to window coordinates.
|
||
|
|
||
|
pt.x -= gptWindow.x;
|
||
|
pt.y -= gptWindow.y;
|
||
|
|
||
|
// If mouse has moved since button was pressed, change quaternion.
|
||
|
|
||
|
if (pt.x != glMouseDownX || pt.y != glMouseDownY)
|
||
|
{
|
||
|
//trackball(lastquat,
|
||
|
// 2.0*(gszWindow.cx-glMouseDownX)/gszWindow.cx-1.0,
|
||
|
// 2.0*glMouseDownY/gszWindow.cy-1.0,
|
||
|
// 2.0*(gszWindow.cx-pt.x)/gszWindow.cx-1.0,
|
||
|
// 2.0*pt.y/gszWindow.cy-1.0);
|
||
|
trackball(lastquat,
|
||
|
2.0*(glMouseDownX)/gszWindow.cx-1.0,
|
||
|
2.0*(gszWindow.cy-glMouseDownY)/gszWindow.cy-1.0,
|
||
|
2.0*(pt.x)/gszWindow.cx-1.0,
|
||
|
2.0*(gszWindow.cy-pt.y)/gszWindow.cy-1.0);
|
||
|
|
||
|
gbSpinning = TRUE;
|
||
|
}
|
||
|
else
|
||
|
gbSpinning = FALSE;
|
||
|
|
||
|
glMouseDownX = pt.x;
|
||
|
glMouseDownY = pt.y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||
|
|
||
|
glPushMatrix();
|
||
|
|
||
|
if (gbSpinning)
|
||
|
add_quats(lastquat, curquat, curquat);
|
||
|
|
||
|
build_rotmatrix(matRot, curquat);
|
||
|
glMultMatrixf(&(matRot[0][0]));
|
||
|
|
||
|
if (scene->Objects.count)
|
||
|
{
|
||
|
//LBprintf("call display list");
|
||
|
|
||
|
glCallList(scene->Objects.listBase);
|
||
|
}
|
||
|
|
||
|
glPopMatrix();
|
||
|
|
||
|
SwapBuffers(hdc);
|
||
|
}
|
||
|
|
||
|
SCENE *OpenScene(LPSTR lpstrFile)
|
||
|
{
|
||
|
SCENE *scene = (SCENE *) NULL;
|
||
|
CHAR *pchExt;
|
||
|
|
||
|
// Find the extension.
|
||
|
|
||
|
pchExt = lpstrFile;
|
||
|
while ((*pchExt != '.') && (*pchExt != '\0'))
|
||
|
pchExt++;
|
||
|
|
||
|
if (*pchExt == '.')
|
||
|
{
|
||
|
// Use extension as the key to call appropriate parser.
|
||
|
|
||
|
if (!lstrcmpi(pchExt, ".nff"))
|
||
|
scene = NffOpenScene(lpstrFile);
|
||
|
else if (!lstrcmpi(pchExt, ".obj"))
|
||
|
scene = ObjOpenScene(lpstrFile);
|
||
|
else
|
||
|
LBprintf("Unknown extension: %s", pchExt);
|
||
|
}
|
||
|
|
||
|
return scene;
|
||
|
}
|