/* =========================================================================== Copyright (C) 1997-2006 Id Software, Inc. This file is part of Quake 2 Tools source code. Quake 2 Tools source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake 2 Tools source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Quake 2 Tools source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "texpaint.h" #define CAMERA_WINDOW_CLASS "TPCamera" HDC camdc; HGLRC baseRC; float pitch, yaw, roll; qboolean model_lines = false; float cam_x, cam_y=-64, cam_z=32; int cam_width, cam_height; BINDTEXFUNCPTR BindTextureEXT; void InitIndexTexture (void) { int i; BindTextureEXT (GL_TEXTURE_2D, TEXTURE_INDEX); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); for (i=0 ; i= width2*height2) return; if (index == cam_last_index) return; // in same pixel cam_last_index = index; if (shift) { Pal_SetIndex (pic[index]); return; } SetSkin (index, selected_rgb); UpdateWindow (camerawindow); } void Cam_DrawSetup (void) { glViewport (0,0,cam_width, cam_height); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective (90, (float)cam_width/cam_height, 2, 1024); gluLookAt (cam_x, cam_y, cam_z, cam_x, cam_y+1, cam_z, 0, 0, 1); glRotated (-roll*0.3, 0, 1, 0); glRotated (-pitch*0.3, 1, 0, 0); glRotated (yaw*0.3, 0, 0, 1); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable (GL_DEPTH_TEST); glEnable (GL_CULL_FACE); glEnable (GL_TEXTURE_2D); glCullFace (GL_FRONT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } void Cam_Draw (void) { if (!cam_width || !cam_height) return; glClearColor (0.3,0.3,0.3,1); Cam_DrawSetup (); BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN); DrawModel (); if (model_lines) { glDisable (GL_TEXTURE_2D); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glDepthFunc (GL_LEQUAL); glDepthRange (0, 0.999); // nudge depth to avoid dropouts DrawModel (); glDepthRange (0, 1); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_TEXTURE_2D); } SwapBuffers(camdc); // now fill the back buffer with the index texture glClearColor (0,0,0,0); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); BindTextureEXT (GL_TEXTURE_2D, TEXTURE_INDEX); DrawModel (); BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN); } /* ============ CameraWndProc ============ */ LONG WINAPI WCam_WndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LONG lRet = 1; int fwKeys, xPos, yPos; RECT rect; static int oldx, oldy; POINT pt; GetClientRect(hWnd, &rect); cam_width = rect.right-rect.left; cam_height = rect.bottom-rect.top; switch (uMsg) { case WM_CREATE: camdc = GetDC(hWnd); bSetupPixelFormat(camdc); baseRC = wglCreateContext( camdc ); if (!baseRC) Sys_Error ("wglCreateContext failed"); if (!wglMakeCurrent( camdc, baseRC )) Sys_Error ("wglMakeCurrent failed"); BindTextureEXT = (void *)wglGetProcAddress((LPCSTR) "glBindTextureEXT"); if (!BindTextureEXT) Sys_Error ("GetProcAddress for BindTextureEXT failed"); break; case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); if (!wglMakeCurrent( camdc, baseRC )) Sys_Error ("wglMakeCurrent failed"); Cam_Draw (); EndPaint(hWnd, &ps); } break; case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: if (GetTopWindow(mainwindow) != hWnd) BringWindowToTop(hWnd); SetFocus (camerawindow); SetCapture (camerawindow); GetCursorPos (&pt); xPos = pt.x; yPos = pt.y; oldx = xPos; oldy = yPos; break; case WM_LBUTTONDOWN: cam_last_index = -1; draw: if (GetTopWindow(mainwindow) != hWnd) BringWindowToTop(hWnd); SetFocus (camerawindow); SetCapture (camerawindow); fwKeys = wParam; // key flags xPos = (short)LOWORD(lParam); // horizontal position of cursor yPos = (short)HIWORD(lParam); // vertical position of cursor yPos = (int)rect.bottom - 1 - yPos; if (!wglMakeCurrent( camdc, baseRC )) Sys_Error ("wglMakeCurrent failed"); Cam_Click (xPos, yPos, !!(wParam&(MK_SHIFT|MK_CONTROL)) ); // Cam_MouseDown (xPos, yPos, fwKeys); break; case WM_MBUTTONUP: case WM_RBUTTONUP: case WM_LBUTTONUP: if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON))) ReleaseCapture (); break; case WM_MOUSEMOVE: { int dx, dy; if (wParam & MK_LBUTTON) goto draw; GetCursorPos (&pt); xPos = pt.x; yPos = pt.y; if (!(wParam & (MK_RBUTTON|MK_MBUTTON))) { oldx = xPos; oldy = yPos; break; } dx = xPos-oldx; dy = oldy-yPos; if (!dx && !dy) break; SetCursorPos (oldx, oldy); if (wParam == (MK_RBUTTON|MK_CONTROL) ) { if (abs(dx) > abs(dy)) cam_y -= 0.1*dx; else cam_y -= 0.1*dy; InvalidateRect (camerawindow, NULL, false); } if (wParam == MK_RBUTTON) { cam_x -= 0.1*dx; cam_z -= 0.1*dy; InvalidateRect (camerawindow, NULL, false); } if (wParam == (MK_MBUTTON|MK_CONTROL) ) { if (abs(dx) > abs(dy)) roll -= dx; else roll -= dy; InvalidateRect (camerawindow, NULL, false); } if (wParam == MK_MBUTTON) { yaw += dx; pitch += dy; InvalidateRect (camerawindow, NULL, false); } } break; case WM_SIZE: // camera.width = rect.right; // camera.height = rect.bottom; InvalidateRect(camerawindow, NULL, false); break; case WM_NCCALCSIZE:// don't let windows copy pixels lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); return WVR_REDRAW; case WM_CLOSE: /* call destroy window to cleanup and go away */ DestroyWindow (hWnd); break; case WM_DESTROY: { HGLRC hRC; HDC hDC; /* release and free the device context and rendering context */ hRC = wglGetCurrentContext(); hDC = wglGetCurrentDC(); wglMakeCurrent(NULL, NULL); if (hRC) wglDeleteContext(hRC); if (hDC) ReleaseDC(hWnd, hDC); } break; default: /* pass all unhandled messages to DefWindowProc */ lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); break; } /* return 1 if handled message, 0 if not */ return lRet; } /* ============== WCam_Register ============== */ void WCam_Register (HINSTANCE hInstance) { WNDCLASS wc; /* Register the camera class */ memset (&wc, 0, sizeof(wc)); wc.style = 0; wc.lpfnWndProc = (WNDPROC)WCam_WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = 0; wc.hCursor = LoadCursor (NULL,IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = 0; wc.lpszClassName = CAMERA_WINDOW_CLASS; if (!RegisterClass (&wc) ) Sys_Error ("WCam_Register: failed"); } void WCam_Create (HINSTANCE hInstance) { WCam_Register (hInstance); camerawindow = CreateWindow (CAMERA_WINDOW_CLASS , "Camera View", QE3_STYLE, 0, 0, (int)(screen_width*0.5), (int)(screen_height-20), // size mainwindow, // parent window 0, // no menu hInstance, 0); if (!camerawindow) Sys_Error ("Couldn't create camerawindow"); RestoreWindowState(camerawindow, "camerawindow"); ShowWindow (camerawindow, SW_SHOWDEFAULT); }