Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

CamWnd.cpp (27714B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 // CamWnd.cpp : implementation file
     23 //
     24 
     25 #include "stdafx.h"
     26 #include "Radiant.h"
     27 #include "XYWnd.h"
     28 #include "CamWnd.h"
     29 #include "qe3.h"
     30 #include "splines/splines.h"
     31 
     32 #ifdef _DEBUG
     33 #define new DEBUG_NEW
     34 #undef THIS_FILE
     35 static char THIS_FILE[] = __FILE__;
     36 #endif
     37 
     38 extern void DrawPathLines();
     39 
     40 int g_nAngleSpeed = 300;
     41 int g_nMoveSpeed = 400;
     42 
     43 
     44 /////////////////////////////////////////////////////////////////////////////
     45 // CCamWnd
     46 IMPLEMENT_DYNCREATE(CCamWnd, CWnd);
     47 
     48 CCamWnd::CCamWnd()
     49 {
     50   m_pXYFriend = NULL;
     51   m_nNumTransBrushes = 0;
     52   memset(&m_Camera, 0, sizeof(camera_t));
     53   m_pSide_select = NULL;
     54   m_bClipMode = false;
     55   Cam_Init();
     56 }
     57 
     58 CCamWnd::~CCamWnd()
     59 {
     60 }
     61 
     62 
     63 BEGIN_MESSAGE_MAP(CCamWnd, CWnd)
     64 	//{{AFX_MSG_MAP(CCamWnd)
     65 	ON_WM_KEYDOWN()
     66 	ON_WM_PAINT()
     67 	ON_WM_DESTROY()
     68 	ON_WM_CLOSE()
     69 	ON_WM_MOUSEMOVE()
     70 	ON_WM_LBUTTONDOWN()
     71 	ON_WM_LBUTTONUP()
     72 	ON_WM_MBUTTONDOWN()
     73 	ON_WM_MBUTTONUP()
     74 	ON_WM_RBUTTONDOWN()
     75 	ON_WM_RBUTTONUP()
     76 	ON_WM_CREATE()
     77 	ON_WM_SIZE()
     78 	ON_WM_NCCALCSIZE()
     79 	ON_WM_KILLFOCUS()
     80 	ON_WM_SETFOCUS()
     81 	ON_WM_KEYUP()
     82 	//}}AFX_MSG_MAP
     83 END_MESSAGE_MAP()
     84 
     85 
     86 LONG WINAPI CamWndProc (
     87     HWND    hWnd,
     88     UINT    uMsg,
     89     WPARAM  wParam,
     90     LPARAM  lParam)
     91 {
     92     RECT	rect;
     93 
     94     GetClientRect(hWnd, &rect);
     95 
     96     switch (uMsg)
     97     {
     98 	case WM_KILLFOCUS:
     99 	case WM_SETFOCUS:
    100 		SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 );
    101 		return 0;
    102 
    103 	case WM_NCCALCSIZE:// don't let windows copy pixels
    104 		DefWindowProc (hWnd, uMsg, wParam, lParam);
    105 		return WVR_REDRAW;
    106 
    107     }
    108 
    109 	return DefWindowProc( hWnd, uMsg, wParam, lParam );
    110 }
    111 
    112 
    113 /////////////////////////////////////////////////////////////////////////////
    114 // CCamWnd message handlers
    115 
    116 BOOL CCamWnd::PreCreateWindow(CREATESTRUCT& cs) 
    117 {
    118   WNDCLASS wc;
    119   HINSTANCE hInstance = AfxGetInstanceHandle();
    120   if (::GetClassInfo(hInstance, CAMERA_WINDOW_CLASS, &wc) == FALSE)
    121   {
    122     // Register a new class
    123   	memset (&wc, 0, sizeof(wc));
    124     wc.style         = CS_NOCLOSE | CS_OWNDC;
    125     wc.lpszClassName = CAMERA_WINDOW_CLASS;
    126     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
    127     wc.lpfnWndProc   = CamWndProc;
    128     if (AfxRegisterClass(&wc) == FALSE)
    129       Error ("CCamWnd RegisterClass: failed");
    130   }
    131 
    132   cs.lpszClass = CAMERA_WINDOW_CLASS;
    133   cs.lpszName = "CAM";
    134   if (cs.style != QE3_CHILDSTYLE)
    135     cs.style = QE3_SPLITTER_STYLE;
    136 
    137 	BOOL bResult = CWnd::PreCreateWindow(cs);
    138 
    139   // See if the class already exists and if not then we need
    140   // to register our new window class.
    141   return bResult;
    142 	
    143 }
    144 
    145 
    146 void CCamWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
    147 {
    148   g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
    149 }
    150 
    151 
    152 brush_t* g_pSplitList = NULL;
    153 
    154 void CCamWnd::OnPaint() 
    155 {
    156 	CPaintDC dc(this); // device context for painting
    157   bool bPaint = true;
    158   if (!qwglMakeCurrent( dc.m_hDC, g_qeglobals.d_hglrcBase ))
    159   {
    160     Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
    161     Sys_Printf("Please restart Q3Radiant if the camera view is not working\n");
    162   }
    163   else
    164   {
    165     QE_CheckOpenGLForErrors();
    166     g_pSplitList = NULL;
    167     if (g_bClipMode)
    168     {
    169       if (g_Clip1.Set() && g_Clip2.Set())
    170       {
    171         g_pSplitList = ( (g_pParentWnd->ActiveXY()->GetViewType() == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
    172       }
    173     }
    174 		Cam_Draw ();
    175 		QE_CheckOpenGLForErrors();
    176 		qwglSwapBuffers(dc.m_hDC);
    177   }
    178 }
    179 
    180 
    181 void CCamWnd::SetXYFriend(CXYWnd * pWnd)
    182 {
    183   m_pXYFriend = pWnd;
    184 }
    185 
    186 void CCamWnd::OnDestroy() 
    187 {
    188 	QEW_StopGL(GetSafeHwnd(), g_qeglobals.d_hglrcBase, g_qeglobals.d_hdcBase );
    189 	CWnd::OnDestroy();
    190 }
    191 
    192 void CCamWnd::OnClose() 
    193 {
    194 	CWnd::OnClose();
    195 }
    196 
    197 extern void Select_ShiftTexture(int x, int y);
    198 extern void Select_RotateTexture(int amt);
    199 extern void Select_ScaleTexture(int x, int y);
    200 void CCamWnd::OnMouseMove(UINT nFlags, CPoint point) 
    201 {
    202   CRect r;
    203   GetClientRect(r);
    204   if (GetCapture() == this && (GetKeyState(VK_MENU) & 0x8000) && !((GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_CONTROL) & 0x8000)))
    205   {
    206     if (GetKeyState(VK_CONTROL) & 0x8000)
    207       Select_RotateTexture(point.y - m_ptLastCursor.y);
    208     else
    209     if (GetKeyState(VK_SHIFT) & 0x8000)
    210       Select_ScaleTexture(point.x - m_ptLastCursor.x, m_ptLastCursor.y - point.y);
    211     else
    212       Select_ShiftTexture(point.x - m_ptLastCursor.x, m_ptLastCursor.y - point.y);
    213   }
    214   else
    215   {
    216     Cam_MouseMoved(point.x, r.bottom - 1 - point.y, nFlags);
    217   }
    218   m_ptLastCursor = point;
    219 }
    220 
    221 void CCamWnd::OnLButtonDown(UINT nFlags, CPoint point) 
    222 {
    223   m_ptLastCursor = point;
    224   OriginalMouseDown(nFlags, point);
    225 }
    226 
    227 void CCamWnd::OnLButtonUp(UINT nFlags, CPoint point) 
    228 {
    229   OriginalMouseUp(nFlags, point);
    230 }
    231 
    232 void CCamWnd::OnMButtonDown(UINT nFlags, CPoint point) 
    233 {
    234   OriginalMouseDown(nFlags, point);
    235 }
    236 
    237 void CCamWnd::OnMButtonUp(UINT nFlags, CPoint point) 
    238 {
    239   OriginalMouseUp(nFlags, point);
    240 }
    241 
    242 void CCamWnd::OnRButtonDown(UINT nFlags, CPoint point) 
    243 {
    244   OriginalMouseDown(nFlags, point);
    245 }
    246 
    247 void CCamWnd::OnRButtonUp(UINT nFlags, CPoint point) 
    248 {
    249   OriginalMouseUp(nFlags, point);
    250 }
    251 
    252 int CCamWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    253 {
    254   if (CWnd::OnCreate(lpCreateStruct) == -1)
    255 		return -1;
    256 
    257 	g_qeglobals.d_hdcBase = GetDC()->m_hDC;
    258 	QEW_SetupPixelFormat(g_qeglobals.d_hdcBase, true);
    259 
    260   if ((g_qeglobals.d_hglrcBase = qwglCreateContext(g_qeglobals.d_hdcBase)) == 0)
    261 	  Error("wglCreateContext failed");
    262   
    263   if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
    264 	  Error ("wglMakeCurrent failed");
    265 
    266 
    267 	//
    268 	// create GL font
    269 	//
    270   HFONT hfont = ::CreateFont(
    271 	  12,	// logical height of font 
    272 		 6,	// logical average character width 
    273 		 0,	// angle of escapement 
    274 		 0,	// base-line orientation angle 
    275 		 0,	// font weight 
    276 		 0,	// italic attribute flag 
    277 		 0,	// underline attribute flag 
    278 		 0,	// strikeout attribute flag 
    279 		 0,	// character set identifier 
    280 		 0,	// output precision 
    281 		 0,	// clipping precision 
    282 		 0,	// output quality 
    283 		 0,	// pitch and family 
    284 		 "system font" // pointer to typeface name string 
    285 		 	);
    286 
    287 	if (!hfont)
    288 	  Error( "couldn't create font" );
    289 
    290   ::SelectObject(g_qeglobals.d_hdcBase, hfont);
    291 
    292 	if ((g_qeglobals.d_font_list = qglGenLists (256)) == 0)
    293 	  Error( "couldn't create font dlists" );
    294 			
    295 	// create the bitmap display lists
    296 	// we're making images of glyphs 0 thru 255
    297   
    298   if (g_PrefsDlg.m_bBuggyICD)
    299   {
    300 	  if ( !qwglUseFontBitmaps (g_qeglobals.d_hdcBase, 1, 255, g_qeglobals.d_font_list-1) )
    301 	    Error( "wglUseFontBitmaps faileD" );
    302   }
    303   else
    304   {
    305 	  if ( !qwglUseFontBitmaps (g_qeglobals.d_hdcBase, 1, 255, g_qeglobals.d_font_list) )
    306 	    Error( "wglUseFontBitmaps faileD" );
    307   }
    308 	
    309 	// indicate start of glyph display lists
    310 	qglListBase (g_qeglobals.d_font_list);
    311 
    312 	// report OpenGL information
    313 	Sys_Printf ("GL_VENDOR: %s\n", qglGetString (GL_VENDOR));
    314 	Sys_Printf ("GL_RENDERER: %s\n", qglGetString (GL_RENDERER));
    315 	Sys_Printf ("GL_VERSION: %s\n", qglGetString (GL_VERSION));
    316 	Sys_Printf ("GL_EXTENSIONS: %s\n", qglGetString (GL_EXTENSIONS));
    317 
    318   g_qeglobals.d_hwndCamera = GetSafeHwnd();
    319 
    320 	return 0;
    321 }
    322 
    323 void CCamWnd::OriginalMouseUp(UINT nFlags, CPoint point)
    324 {
    325   CRect r;
    326   GetClientRect(r);
    327   Cam_MouseUp(point.x, r.bottom - 1 - point.y, nFlags);
    328 	if (!(nFlags & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
    329   	ReleaseCapture ();
    330 }
    331 
    332 void CCamWnd::OriginalMouseDown(UINT nFlags, CPoint point)
    333 {
    334   //if (GetTopWindow()->GetSafeHwnd() != GetSafeHwnd())
    335   //  BringWindowToTop();
    336   CRect r;
    337   GetClientRect(r);
    338   SetFocus();
    339 	SetCapture();
    340   //if (!(GetKeyState(VK_MENU) & 0x8000))
    341 	  Cam_MouseDown (point.x, r.bottom - 1 - point.y, nFlags);
    342 }
    343 
    344 void CCamWnd::Cam_Init()
    345 {
    346 	//m_Camera.draw_mode = cd_texture;
    347 	m_Camera.timing = false;
    348 	m_Camera.origin[0] = 0;
    349 	m_Camera.origin[1] = 20;
    350 	m_Camera.origin[2] = 46;
    351 	m_Camera.color[0] = 0.3;
    352 	m_Camera.color[1] = 0.3;
    353 	m_Camera.color[2] = 0.3;
    354 }
    355 
    356 void CCamWnd::Cam_BuildMatrix()
    357 {
    358 	float	xa, ya;
    359 	float	matrix[4][4];
    360 	int		i;
    361 
    362 	xa = m_Camera.angles[0]/180*Q_PI;
    363 	ya = m_Camera.angles[1]/180*Q_PI;
    364 
    365 	// the movement matrix is kept 2d
    366 
    367   m_Camera.forward[0] = cos(ya);
    368   m_Camera.forward[1] = sin(ya);
    369   m_Camera.right[0] = m_Camera.forward[1];
    370   m_Camera.right[1] = -m_Camera.forward[0];
    371 
    372 	qglGetFloatv (GL_PROJECTION_MATRIX, &matrix[0][0]);
    373 
    374 	for (i=0 ; i<3 ; i++)
    375 	{
    376 		m_Camera.vright[i] = matrix[i][0];
    377 		m_Camera.vup[i] = matrix[i][1];
    378 		m_Camera.vpn[i] = matrix[i][2];
    379 	}
    380 
    381 	VectorNormalize (m_Camera.vright);
    382 	VectorNormalize (m_Camera.vup);
    383 	VectorNormalize (m_Camera.vpn);
    384 }
    385 
    386 
    387 
    388 void CCamWnd::Cam_ChangeFloor (qboolean up)
    389 {
    390 	brush_t	*b;
    391 	float	d, bestd, current;
    392 	vec3_t	start, dir;
    393 
    394 	start[0] = m_Camera.origin[0];
    395 	start[1] = m_Camera.origin[1];
    396 	start[2] = 8192;
    397 	dir[0] = dir[1] = 0;
    398 	dir[2] = -1;
    399 
    400 	current = 8192 - (m_Camera.origin[2] - 48);
    401 	if (up)
    402 		bestd = 0;
    403 	else
    404 		bestd = 16384;
    405 
    406 	for (b=active_brushes.next ; b != &active_brushes ; b=b->next)
    407 	{
    408 		if ( b->pTerrain && !Terrain_Ray( start, dir, b, &d ) )
    409 			continue;
    410 		if ( !b->pTerrain && !Brush_Ray (start, dir, b, &d) )
    411 			continue;
    412 		if (up && d < current && d > bestd)
    413 			bestd = d;
    414 		if (!up && d > current && d < bestd)
    415 			bestd = d;
    416 	}
    417 
    418 	if (bestd == 0 || bestd == 16384)
    419 		return;
    420 
    421 	m_Camera.origin[2] += current - bestd;
    422 	Sys_UpdateWindows (W_CAMERA|W_Z_OVERLAY);
    423 }
    424 
    425 
    426 void CCamWnd::Cam_PositionDrag()
    427 {
    428 	int	x, y;
    429 	Sys_GetCursorPos (&x, &y);
    430 	if (x != m_ptCursor.x || y != m_ptCursor.y)
    431 	{
    432 		x -= m_ptCursor.x;
    433 		VectorMA (m_Camera.origin, x, m_Camera.vright, m_Camera.origin);
    434 		y -= m_ptCursor.y;
    435 		m_Camera.origin[2] -= y;
    436     SetCursorPos(m_ptCursor.x, m_ptCursor.y);
    437 		Sys_UpdateWindows (W_CAMERA | W_XY_OVERLAY);
    438 	}
    439 }
    440 
    441 
    442 void CCamWnd::Cam_MouseControl (float dtime)
    443 {
    444 	int		xl, xh;
    445 	int		yl, yh;
    446 	float	xf, yf;
    447   if (g_PrefsDlg.m_nMouseButtons == 2)
    448   {
    449     if (m_nCambuttonstate != (MK_RBUTTON | MK_SHIFT))
    450       return;
    451   }
    452   else
    453   {
    454 	  if (m_nCambuttonstate != MK_RBUTTON)
    455       return;
    456   }
    457 
    458 	xf = (float)(m_ptButton.x - m_Camera.width/2) / (m_Camera.width/2);
    459 	yf = (float)(m_ptButton.y - m_Camera.height/2) / (m_Camera.height/2);
    460 
    461 
    462 	xl = m_Camera.width/3;
    463 	xh = xl*2;
    464 	yl = m_Camera.height/3;
    465 	yh = yl*2;
    466 
    467   //Sys_Printf("xf-%f  yf-%f  xl-%i  xh-i%  yl-i%  yh-i%\n",xf,yf,xl,xh,yl,yh);
    468 #if 0
    469 	// strafe
    470 	if (buttony < yl && (buttonx < xl || buttonx > xh))
    471 		VectorMA (camera.origin, xf*dtime*g_nMoveSpeed, camera.right, camera.origin);
    472 	else
    473 #endif
    474 	{
    475 		xf *= 1.0 - fabs(yf);
    476 		if (xf < 0)
    477 		{
    478 			xf += 0.1;
    479 			if (xf > 0)
    480 				xf = 0;
    481 		}
    482 		else
    483 		{
    484 			xf -= 0.1;
    485 			if (xf < 0)
    486 				xf = 0;
    487 		}
    488 		
    489 		VectorMA (m_Camera.origin, yf*dtime*g_nMoveSpeed, m_Camera.forward, m_Camera.origin);
    490 		m_Camera.angles[YAW] += xf*-dtime*g_nAngleSpeed;
    491 	}
    492 
    493 #if 0
    494   if (g_PrefsDlg.m_bQE4Painting)
    495   {
    496     MSG msg;
    497     if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 
    498     { 
    499       TranslateMessage(&msg);
    500       DispatchMessage(&msg);
    501     }
    502   }
    503 #endif
    504 
    505   int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
    506 	Sys_UpdateWindows (nUpdate);
    507   g_pParentWnd->PostMessage(WM_TIMER, 0, 0);
    508 
    509 }
    510 
    511 
    512 
    513 void CCamWnd::Cam_MouseDown(int x, int y, int buttons)
    514 {
    515 	vec3_t		dir;
    516 	float		f, r, u;
    517 	int			i;
    518 
    519 	//
    520 	// calc ray direction
    521 	//
    522 	u = (float)(y - m_Camera.height/2) / (m_Camera.width/2);
    523 	r = (float)(x - m_Camera.width/2) / (m_Camera.width/2);
    524 	f = 1;
    525 
    526 	for (i=0 ; i<3 ; i++)
    527 		dir[i] = m_Camera.vpn[i] * f + m_Camera.vright[i] * r + m_Camera.vup[i] * u;
    528 	VectorNormalize (dir);
    529 
    530 	GetCursorPos(&m_ptCursor);
    531 
    532 	m_nCambuttonstate = buttons;
    533 	m_ptButton.x = x;
    534 	m_ptButton.y = y;
    535 
    536 	// LBUTTON = manipulate selection
    537 	// shift-LBUTTON = select
    538 	// middle button = grab texture
    539 	// ctrl-middle button = set entire brush to texture
    540 	// ctrl-shift-middle button = set single face to texture
    541 	int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
    542 	if ((buttons == MK_LBUTTON)
    543 		        || (buttons == (MK_LBUTTON | MK_SHIFT))
    544 		        || (buttons == (MK_LBUTTON | MK_CONTROL))
    545 		        || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT))
    546 		        || (buttons == nMouseButton)
    547 		        || (buttons == (nMouseButton|MK_SHIFT))
    548 		        || (buttons == (nMouseButton|MK_CONTROL))
    549 		        || (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL)))
    550 	{
    551 
    552     if (g_PrefsDlg.m_nMouseButtons == 2 && (buttons == (MK_RBUTTON | MK_SHIFT)))
    553 		  Cam_MouseControl (0.1);
    554     else
    555     {
    556       // something global needs to track which window is responsible for stuff
    557       Patch_SetView(W_CAMERA);
    558 		  Drag_Begin (x, y, buttons, m_Camera.vright, m_Camera.vup,	m_Camera.origin, dir);
    559     }
    560     return;
    561 	}
    562 
    563 	if (buttons == MK_RBUTTON)
    564 	{
    565 		Cam_MouseControl (0.1);
    566 		return;
    567 	}
    568 }
    569 
    570 
    571 void CCamWnd::Cam_MouseUp (int x, int y, int buttons)
    572 {
    573 	m_nCambuttonstate = 0;
    574 	Drag_MouseUp (buttons);
    575 }
    576 
    577 
    578 void CCamWnd::Cam_MouseMoved (int x, int y, int buttons)
    579 {
    580 	m_nCambuttonstate = buttons;
    581 	if (!buttons) {
    582 		if ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) || ( g_qeglobals.d_select_mode == sel_terraintexture ) ) {
    583 			vec3_t		dir;
    584 			float		f, r, u;
    585 			int			i;
    586 
    587 			//
    588 			// calc ray direction
    589 			//
    590 			u = (float)(y - m_Camera.height/2) / (m_Camera.width/2);
    591 			r = (float)(x - m_Camera.width/2) / (m_Camera.width/2);
    592 			f = 1;
    593 
    594 			for (i=0 ; i<3 ; i++)
    595 				dir[i] = m_Camera.vpn[i] * f + m_Camera.vright[i] * r + m_Camera.vup[i] * u;
    596 			VectorNormalize (dir);
    597 
    598 			m_ptButton.x = x;
    599 			m_ptButton.y = y;
    600 
    601 			Terrain_SelectPointByRay( m_Camera.origin, dir, buttons );
    602 
    603 			Sys_UpdateWindows(W_CAMERA);
    604 		}
    605 
    606 		return;
    607 	}
    608 	m_ptButton.x = x;
    609 	m_ptButton.y = y;
    610 
    611 	if (buttons == (MK_RBUTTON|MK_CONTROL) )
    612 	{
    613 		Cam_PositionDrag ();
    614 		Sys_UpdateWindows (W_XY|W_CAMERA|W_Z);
    615 		return;
    616 	}
    617 
    618 	GetCursorPos(&m_ptCursor);
    619 
    620 	if (buttons & (MK_LBUTTON | MK_MBUTTON) )
    621 	{
    622 		Drag_MouseMoved (x, y, buttons);
    623 		Sys_UpdateWindows (W_XY|W_CAMERA|W_Z);
    624 	}
    625 }
    626 
    627 
    628 void CCamWnd::InitCull()
    629 {
    630 	int		i;
    631 
    632 	VectorSubtract (m_Camera.vpn, m_Camera.vright, m_vCull1);
    633 	VectorAdd (m_Camera.vpn, m_Camera.vright, m_vCull2);
    634 
    635 	for (i=0 ; i<3 ; i++)
    636 	{
    637 		if (m_vCull1[i] > 0)
    638 			m_nCullv1[i] = 3+i;
    639 		else
    640 			m_nCullv1[i] = i;
    641 		if (m_vCull2[i] > 0)
    642 			m_nCullv2[i] = 3+i;
    643 		else
    644 			m_nCullv2[i] = i;
    645 	}
    646 }
    647 
    648 qboolean CCamWnd::CullBrush (brush_t *b)
    649 {
    650 	int		i;
    651 	vec3_t	point;
    652 	float	d;
    653 
    654 	if (g_PrefsDlg.m_bCubicClipping)
    655 	{
    656 		float fLevel = g_PrefsDlg.m_nCubicScale * 64;
    657 
    658 		point[0] = m_Camera.origin[0] - fLevel;
    659 		point[1] = m_Camera.origin[1] - fLevel;
    660 		point[2] = m_Camera.origin[2] - fLevel;
    661 
    662 		for (i=0; i<3; i++)
    663 			if (b->mins[i] < point[i] && b->maxs[i] < point[i])
    664 				return true;
    665 
    666 		point[0] = m_Camera.origin[0] + fLevel;
    667 		point[1] = m_Camera.origin[1] + fLevel;
    668 		point[2] = m_Camera.origin[2] + fLevel;
    669 	
    670 		for (i=0; i<3; i++)
    671 			if (b->mins[i] > point[i] && b->maxs[i] > point[i])
    672 				return true;
    673 	}
    674 
    675 
    676 	for (i=0 ; i<3 ; i++)
    677 		point[i] = b->mins[m_nCullv1[i]] - m_Camera.origin[i];
    678 
    679 	d = DotProduct (point, m_vCull1);
    680 	if (d < -1)
    681 		return true;
    682 
    683 	for (i=0 ; i<3 ; i++)
    684 		point[i] = b->mins[m_nCullv2[i]] - m_Camera.origin[i];
    685 
    686 	d = DotProduct (point, m_vCull2);
    687 	if (d < -1)
    688 		return true;
    689 
    690 	return false;
    691 }
    692 
    693 #if 0
    694 void CCamWnd::DrawLightRadius(brush_t* pBrush)
    695 {
    696   // if lighting
    697   int nRadius = Brush_LightRadius(pBrush);
    698   if (nRadius > 0)
    699   {
    700     Brush_SetLightColor(pBrush);
    701 	  qglEnable (GL_BLEND);
    702 	  qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
    703 	  qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    704 	  qglDisable (GL_TEXTURE_2D);
    705 
    706     qglEnable(GL_TEXTURE_2D);
    707     qglDisable(GL_BLEND);
    708     qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
    709   }
    710 }
    711 #endif
    712 
    713 /*
    714 ==============
    715 Cam_Draw
    716 ==============
    717 */
    718 
    719 void CCamWnd::Cam_Draw()
    720 {
    721 	brush_t	*brush;
    722 	face_t	*face;
    723 	float	screenaspect;
    724 	float	yfov;
    725 	double	start, end;
    726 	int		i;
    727 
    728 	/*
    729   FILE *f = fopen("g:/nardo/raduffy/editorhack.dat", "w");
    730   if (f != NULL) {
    731     fwrite(&m_Camera.origin[0], sizeof(float), 1, f);
    732     fwrite(&m_Camera.origin[1], sizeof(float), 1, f);
    733     fwrite(&m_Camera.origin[2], sizeof(float), 1, f);
    734 		fwrite(&m_Camera.angles[PITCH], sizeof(float), 1, f);
    735 		fwrite(&m_Camera.angles[YAW], sizeof(float), 1, f);
    736     fclose(f);
    737   }
    738 	*/
    739 	
    740 	if (!active_brushes.next)
    741 		return;	// not valid yet
    742 	
    743 	if (m_Camera.timing)
    744 		start = Sys_DoubleTime ();
    745 	
    746 	//
    747 	// clear
    748 	//
    749 	QE_CheckOpenGLForErrors();
    750 	
    751 	qglViewport(0, 0, m_Camera.width, m_Camera.height);
    752 	qglScissor(0, 0, m_Camera.width, m_Camera.height);
    753 	qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][0],
    754 		g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][1],
    755 		g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][2], 0);
    756 	qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    757 	
    758 	//
    759 	// set up viewpoint
    760 	//
    761 	vec5_t lightPos;
    762 	
    763 	if (g_PrefsDlg.m_bGLLighting)
    764 	{
    765 		qglEnable(GL_LIGHTING);
    766 		//qglEnable(GL_LIGHT0);
    767 		
    768 		lightPos[0] = lightPos[1] = lightPos[2] = 3.5;
    769 		lightPos[3] = 1.0;
    770 		qglLightModelfv(GL_LIGHT_MODEL_AMBIENT, lightPos);
    771 		//qglLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
    772 		//lightPos[0] = lightPos[1] = lightPos[2] = 3.5;
    773     //qglLightfv(GL_LIGHT0, GL_AMBIENT, lightPos);
    774 	}
    775 	else
    776 	{
    777 		qglDisable(GL_LIGHTING);
    778 	}
    779 	
    780 	qglMatrixMode(GL_PROJECTION);
    781 	qglLoadIdentity ();
    782 	
    783 	screenaspect = (float)m_Camera.width / m_Camera.height;
    784 	yfov = 2*atan((float)m_Camera.height / m_Camera.width)*180/Q_PI;
    785 	qgluPerspective (yfov,  screenaspect,  2,  8192);
    786 	
    787 	qglRotatef (-90,  1, 0, 0);	    // put Z going up
    788 	qglRotatef (90,  0, 0, 1);	    // put Z going up
    789 	qglRotatef (m_Camera.angles[0],  0, 1, 0);
    790 	qglRotatef (-m_Camera.angles[1],  0, 0, 1);
    791 	qglTranslatef (-m_Camera.origin[0],  -m_Camera.origin[1],  -m_Camera.origin[2]);
    792 	
    793 	Cam_BuildMatrix ();
    794 	
    795 	
    796 	//if (m_Camera.draw_mode == cd_light)
    797 	//{
    798 //	if (g_PrefsDlg.m_bGLLighting)
    799 //	{
    800 //		VectorCopy(m_Camera.origin, lightPos);
    801 //		lightPos[3] = 1;
    802 //		qglLightfv(GL_LIGHT0, GL_POSITION, lightPos);
    803 //	}
    804 	//}
    805 	
    806 	InitCull ();
    807 	
    808 	//
    809 	// draw stuff
    810 	//
    811 	GLfloat lAmbient[] = {1.0, 1.0, 1.0, 1.0};
    812 	
    813 	switch (m_Camera.draw_mode)
    814 	{
    815 	case cd_wire:
    816 		qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
    817 		qglDisable(GL_TEXTURE_2D);
    818 		qglDisable(GL_TEXTURE_1D);
    819 		qglDisable(GL_BLEND);
    820 		qglDisable(GL_DEPTH_TEST);
    821 		qglColor3f(1.0, 1.0, 1.0);
    822 		//		qglEnable (GL_LINE_SMOOTH);
    823 		break;
    824 		
    825 	case cd_solid:
    826 		qglCullFace(GL_FRONT);
    827 		qglEnable(GL_CULL_FACE);
    828 		qglShadeModel (GL_FLAT);
    829 		qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
    830 		qglDisable(GL_TEXTURE_2D);
    831 		qglDisable(GL_BLEND);
    832 		qglEnable(GL_DEPTH_TEST);
    833 		qglDepthFunc (GL_LEQUAL);
    834 		break;
    835 		
    836 	case cd_texture:
    837 		qglCullFace(GL_FRONT);
    838 		qglEnable(GL_CULL_FACE);
    839 		qglShadeModel (GL_FLAT);
    840 		qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
    841 		qglEnable(GL_TEXTURE_2D);
    842 		qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    843 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    844 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    845 		qglDisable(GL_BLEND);
    846 		qglEnable(GL_DEPTH_TEST);
    847 		qglDepthFunc (GL_LEQUAL);
    848 		break;
    849 		
    850 	case cd_blend:
    851 		qglCullFace(GL_FRONT);
    852 		qglEnable(GL_CULL_FACE);
    853 		qglShadeModel (GL_FLAT);
    854 		qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
    855 		qglEnable(GL_TEXTURE_2D);
    856 		qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    857 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    858 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    859 		qglDisable(GL_DEPTH_TEST);
    860 		qglEnable (GL_BLEND);
    861 		qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    862 		break;
    863 	}
    864 	
    865 	qglMatrixMode(GL_TEXTURE);
    866 	
    867 	m_nNumTransBrushes = 0;
    868 	
    869 	for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
    870 	{
    871 		//DrawLightRadius(brush);
    872 		
    873 		if (CullBrush (brush))
    874 			continue;
    875 		
    876 		if (FilterBrush (brush))
    877 			continue;
    878 		
    879 		if ((brush->brush_faces->texdef.flags & (SURF_TRANS33 | SURF_TRANS66)) || (brush->brush_faces->d_texture->bFromShader && brush->brush_faces->d_texture->fTrans != 1.0))
    880 		{
    881 			m_TransBrushes [ m_nNumTransBrushes++ ] = brush;
    882 		} 
    883 		else 
    884 		{
    885 			//--      if (brush->patchBrush)
    886 			//--			  m_TransBrushes [ m_nNumTransBrushes++ ] = brush;
    887 			//--      else
    888 			Brush_Draw(brush);
    889 		}
    890 		
    891 		
    892 	}
    893 	
    894 	if (g_PrefsDlg.m_bGLLighting)
    895 	{
    896 		qglDisable (GL_LIGHTING);
    897 	}
    898 	
    899 	//
    900 	//qglDepthMask ( 0 ); // Don't write to depth buffer
    901 	qglEnable ( GL_BLEND );
    902 	qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    903 	for ( i = 0; i < m_nNumTransBrushes; i++ ) 
    904 		Brush_Draw (m_TransBrushes[i]);
    905 	
    906 	//qglDepthMask ( 1 ); // Ok, write now
    907 	
    908 	qglMatrixMode(GL_PROJECTION);
    909 	
    910 	//
    911 	// now draw selected brushes
    912 	//
    913 	
    914 	if (g_PrefsDlg.m_bGLLighting)
    915 	{
    916 		qglEnable (GL_LIGHTING);
    917 	}
    918 	
    919 	qglTranslatef (g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]);
    920 	qglMatrixMode(GL_TEXTURE);
    921 	
    922 	brush_t* pList = (g_bClipMode && g_pSplitList) ? g_pSplitList : &selected_brushes;
    923 	// draw normally
    924 	for (brush = pList->next ; brush != pList ; brush=brush->next)
    925 	{
    926 		//DrawLightRadius(brush);
    927 		//if (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint)
    928 		//  continue;
    929 		
    930 		Brush_Draw(brush);
    931 	}
    932 	
    933 	// blend on top
    934 	qglMatrixMode(GL_PROJECTION);
    935 	
    936 	
    937 	qglDisable (GL_LIGHTING);
    938 	qglColor4f(1.0, 0.0, 0.0, 0.3);
    939 	qglEnable (GL_BLEND);
    940 	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
    941 	qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    942 	qglDisable (GL_TEXTURE_2D);
    943 	for (brush = pList->next ; brush != pList ; brush=brush->next)
    944 	{
    945 		if ( (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint) || 
    946 			(brush->terrainBrush && g_qeglobals.d_select_mode == sel_terrainpoint) )
    947 			continue;
    948 		
    949 		for (face=brush->brush_faces ; face ; face=face->next)
    950 			Face_Draw( face );
    951 	}
    952 	
    953  
    954   int nCount = g_ptrSelectedFaces.GetSize();
    955 	if (nCount > 0)
    956   {
    957     for (int i = 0; i < nCount; i++)
    958     {
    959       face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
    960 		  Face_Draw(selFace);
    961     }
    962   }
    963 		
    964 	// non-zbuffered outline
    965 	
    966 	qglDisable (GL_BLEND);
    967 	qglDisable (GL_DEPTH_TEST);
    968 	qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
    969 	qglColor3f (1, 1, 1);
    970 	for (brush = pList->next ; brush != pList ; brush=brush->next)
    971 	{
    972 		if (g_qeglobals.dontDrawSelectedOutlines || (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint) ||
    973 			(brush->terrainBrush && g_qeglobals.d_select_mode == sel_terrainpoint))
    974 			continue;
    975 		
    976 		for (face=brush->brush_faces ; face ; face=face->next)
    977 			Face_Draw( face );
    978 	}
    979 	
    980 	
    981 	// edge / vertex flags
    982 	
    983 	if (g_qeglobals.d_select_mode == sel_vertex)
    984 	{
    985 		qglPointSize (4);
    986 		qglColor3f (0,1,0);
    987 		qglBegin (GL_POINTS);
    988 		for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
    989 			qglVertex3fv (g_qeglobals.d_points[i]);
    990 		qglEnd ();
    991 		qglPointSize (1);
    992 	}
    993 	else if (g_qeglobals.d_select_mode == sel_edge)
    994 	{
    995 		float	*v1, *v2;
    996 		
    997 		qglPointSize (4);
    998 		qglColor3f (0,0,1);
    999 		qglBegin (GL_POINTS);
   1000 		for (i=0 ; i<g_qeglobals.d_numedges ; i++)
   1001 		{
   1002 			v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
   1003 			v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
   1004 			qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
   1005 		}
   1006 		qglEnd ();
   1007 		qglPointSize (1);
   1008 	}
   1009 	
   1010 	
   1011 	g_splineList->draw(static_cast<qboolean>(g_qeglobals.d_select_mode == sel_addpoint || g_qeglobals.d_select_mode == sel_editpoint));
   1012 	if (g_qeglobals.selectObject && (g_qeglobals.d_select_mode == sel_addpoint || g_qeglobals.d_select_mode == sel_editpoint)) {
   1013 		g_qeglobals.selectObject->drawSelection();
   1014 	}
   1015 
   1016 	//
   1017 	// draw pointfile
   1018 	//
   1019 
   1020 	qglEnable(GL_DEPTH_TEST);
   1021 	
   1022 
   1023 	DrawPathLines ();
   1024 	
   1025 	
   1026 	
   1027 	if (g_qeglobals.d_pointfile_display_list)
   1028 	{
   1029 		Pointfile_Draw();
   1030 		//		glCallList (g_qeglobals.d_pointfile_display_list);
   1031 	}
   1032 	
   1033 	// bind back to the default texture so that we don't have problems
   1034 	// elsewhere using/modifying texture maps between contexts
   1035 	qglBindTexture( GL_TEXTURE_2D, 0 );
   1036 	
   1037 #if 0
   1038 	// area selection hack
   1039 	if (g_qeglobals.d_select_mode == sel_area)
   1040 	{
   1041 		qglEnable (GL_BLEND);
   1042 		qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   1043 		qglColor4f(0.0, 0.0, 1.0, 0.25);
   1044 		qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
   1045 		qglRectfv(g_qeglobals.d_vAreaTL, g_qeglobals.d_vAreaBR);
   1046 		qglDisable (GL_BLEND);
   1047 	}
   1048 #endif
   1049 	
   1050 	qglFinish();
   1051 	QE_CheckOpenGLForErrors();
   1052 	//	Sys_EndWait();
   1053 	if (m_Camera.timing)
   1054 	{
   1055 		end = Sys_DoubleTime ();
   1056 		Sys_Printf ("Camera: %i ms\n", (int)(1000*(end-start)));
   1057 	}
   1058 }
   1059 
   1060 
   1061 void CCamWnd::OnSize(UINT nType, int cx, int cy) 
   1062 {
   1063 	CWnd::OnSize(nType, cx, cy);
   1064   CRect rect;
   1065   GetClientRect(rect);
   1066 	m_Camera.width = rect.right;
   1067 	m_Camera.height = rect.bottom;
   1068 	InvalidateRect(NULL, false);
   1069 }
   1070 
   1071 void CCamWnd::BenchMark()
   1072 {
   1073 	PAINTSTRUCT	ps;
   1074   CRect rct;
   1075   GetWindowRect(rct);
   1076   long lStyle = ::GetWindowLong(GetSafeHwnd(), GWL_STYLE);
   1077   ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, QE3_CHILDSTYLE);
   1078   CWnd* pParent = GetParent();
   1079   SetParent(g_pParentWnd);
   1080   MoveWindow(CRect(30, 30, 400, 400), TRUE);
   1081 
   1082   BeginPaint(&ps);
   1083   if (!qwglMakeCurrent(ps.hdc, g_qeglobals.d_hglrcBase))
   1084 		Error ("wglMakeCurrent failed in Benchmark");
   1085   
   1086 	qglDrawBuffer (GL_FRONT);
   1087 	double dStart = Sys_DoubleTime ();
   1088 	for (int i=0 ; i < 100 ; i++)
   1089 	{
   1090 		m_Camera.angles[YAW] = i*4;
   1091 		Cam_Draw();
   1092 	}
   1093 	qwglSwapBuffers(ps.hdc);
   1094 	qglDrawBuffer (GL_BACK);
   1095 	double dEnd = Sys_DoubleTime ();
   1096 	EndPaint(&ps);
   1097 	Sys_Printf ("%5.2f seconds\n", dEnd - dStart);
   1098   ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, lStyle);
   1099   SetParent(pParent);
   1100   MoveWindow(rct, TRUE);
   1101 }
   1102 
   1103 void CCamWnd::ReInitGL()
   1104 {
   1105 
   1106   qwglMakeCurrent(0,0);
   1107 	QEW_SetupPixelFormat(GetDC()->m_hDC, true);
   1108   if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
   1109 	  Error ("wglMakeCurrent failed");
   1110 
   1111   return;
   1112 
   1113   long lStyle = ::GetWindowLong(GetSafeHwnd(), GWL_STYLE);
   1114   int nID = ::GetWindowLong(GetSafeHwnd(), GWL_ID);
   1115   CWnd* pParent = GetParent();
   1116   CRect rctClient;
   1117   GetClientRect(rctClient);
   1118   DestroyWindow();
   1119   Create(CAMERA_WINDOW_CLASS, "", lStyle, rctClient, pParent, nID);
   1120 }
   1121 
   1122 void CCamWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
   1123 {
   1124   g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
   1125 }
   1126 
   1127 // Timo
   1128 // brush primitive texture shifting, using camera view to select translations :
   1129 void CCamWnd::ShiftTexture_BrushPrimit(face_t *f, int x, int y)
   1130 {
   1131 	vec3_t texS,texT;
   1132 	vec3_t viewX,viewY;
   1133 	int XS,XT,YS,YT;
   1134 	int outS,outT;
   1135 #ifdef _DEBUG
   1136 	if (!g_qeglobals.m_bBrushPrimitMode)
   1137 	{
   1138 		Sys_Printf("Warning : unexpected call to CCamWnd::ShiftTexture_BrushPrimit with brush primitive mode disbaled\n");
   1139 		return;
   1140 	}
   1141 #endif
   1142 	// compute face axis base
   1143 	ComputeAxisBase( f->plane.normal, texS, texT );
   1144 	// compute camera view vectors
   1145 	VectorCopy( m_Camera.vup, viewY );
   1146 	VectorCopy( m_Camera.vright, viewX );
   1147 	// compute best vectors
   1148 	ComputeBest2DVector( viewX, texS, texT, XS, XT );
   1149 	ComputeBest2DVector( viewY, texS, texT, YS, YT );
   1150 	// check this is not a degenerate case
   1151 	if ( ( XS == YS ) && ( XT == YT ) )
   1152 	{
   1153 #ifdef _DEBUG
   1154 		Sys_Printf("Warning : degenerate best vectors axis base in CCamWnd::ShiftTexture_BrushPrimit\n");
   1155 #endif
   1156 		// forget it
   1157 		Select_ShiftTexture_BrushPrimit( f, x, y );
   1158 		return;
   1159 	}
   1160 	// compute best fitted translation in face axis base
   1161 	outS = XS*x + YS*y;
   1162 	outT = XT*x + YT*y;
   1163 	// call actual texture shifting code
   1164 	Select_ShiftTexture_BrushPrimit( f, outS, outT );
   1165 }