1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "tools/edit_gui_common.h"
30
31
32 #include "qe3.h"
33 #include "Radiant.h"
34 #include "XYWnd.h"
35 #include "CamWnd.h"
36 #include "splines.h"
37 #include <GL/glu.h>
38
39 #include "../../renderer/tr_local.h"
40 #include "../../renderer/model_local.h" // for idRenderModelMD5
41
42
43 // TODO: DG: could merge SteelStorm2 "new 3D view navigation" improvements
44
45 #ifdef _DEBUG
46 #define new DEBUG_NEW
47 #undef THIS_FILE
48 static char THIS_FILE[] = __FILE__;
49 #endif
50 extern void DrawPathLines();
51
52 int g_axialAnchor = -1;
53 int g_axialDest = -1;
54 bool g_bAxialMode = false;
55
ValidateAxialPoints()56 void ValidateAxialPoints() {
57 int faceCount = g_ptrSelectedFaces.GetSize();
58 if (faceCount > 0) {
59 face_t *selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(0));
60 if (g_axialAnchor >= selFace->face_winding->GetNumPoints()) {
61 g_axialAnchor = 0;
62 }
63 if (g_axialDest >= selFace->face_winding->GetNumPoints()) {
64 g_axialDest = 0;
65 }
66 } else {
67 g_axialDest = 0;
68 g_axialAnchor = 0;
69 }
70 }
71
72 // CCamWnd
73 IMPLEMENT_DYNCREATE(CCamWnd, CWnd);
74
75 /*
76 =======================================================================================================================
77 =======================================================================================================================
78 */
CCamWnd()79 CCamWnd::CCamWnd() {
80 m_pXYFriend = NULL;
81 memset(&m_Camera, 0, sizeof(camera_t));
82 m_pSide_select = NULL;
83 m_bClipMode = false;
84 worldDirty = true;
85 worldModel = NULL;
86 renderMode = false;
87 rebuildMode = false;
88 entityMode = false;
89 animationMode = false;
90 selectMode = false;
91 soundMode = false;
92 saveValid = false;
93 Cam_Init();
94 }
95
96 /*
97 =======================================================================================================================
98 =======================================================================================================================
99 */
~CCamWnd()100 CCamWnd::~CCamWnd() {
101 }
102
BEGIN_MESSAGE_MAP(CCamWnd,CWnd)103 BEGIN_MESSAGE_MAP(CCamWnd, CWnd)
104 //{{AFX_MSG_MAP(CCamWnd)
105 ON_WM_KEYDOWN()
106 ON_WM_PAINT()
107 ON_WM_DESTROY()
108 ON_WM_CLOSE()
109 ON_WM_MOUSEMOVE()
110 ON_WM_LBUTTONDOWN()
111 ON_WM_LBUTTONUP()
112 ON_WM_MBUTTONDOWN()
113 ON_WM_MBUTTONUP()
114 ON_WM_RBUTTONDOWN()
115 ON_WM_RBUTTONUP()
116 ON_WM_CREATE()
117 ON_WM_SIZE()
118 ON_WM_KEYUP()
119 ON_WM_NCCALCSIZE()
120 ON_WM_KILLFOCUS()
121 ON_WM_SETFOCUS()
122 ON_WM_TIMER()
123 //}}AFX_MSG_MAP
124 END_MESSAGE_MAP()
125 /*
126 =======================================================================================================================
127 =======================================================================================================================
128 */
129 LONG WINAPI CamWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
130 RECT rect;
131
132 GetClientRect(hWnd, &rect);
133
134 switch (uMsg)
135 {
136 case WM_KILLFOCUS:
137 case WM_SETFOCUS:
138 SendMessage(hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0);
139 return 0;
140
141 case WM_NCCALCSIZE: // don't let windows copy pixels
142 DefWindowProc(hWnd, uMsg, wParam, lParam);
143 return WVR_REDRAW;
144 }
145
146 return DefWindowProc(hWnd, uMsg, wParam, lParam);
147 }
148
149 //
150 // =======================================================================================================================
151 // CCamWnd message handlers
152 // =======================================================================================================================
153 //
PreCreateWindow(CREATESTRUCT & cs)154 BOOL CCamWnd::PreCreateWindow(CREATESTRUCT &cs) {
155 WNDCLASS wc;
156 HINSTANCE hInstance = AfxGetInstanceHandle();
157 if (::GetClassInfo(hInstance, CAMERA_WINDOW_CLASS, &wc) == FALSE) {
158 // Register a new class
159 memset(&wc, 0, sizeof(wc));
160
161 // wc.style = CS_NOCLOSE | CS_OWNDC;
162 wc.style = CS_NOCLOSE;
163 wc.lpszClassName = CAMERA_WINDOW_CLASS;
164 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
165 wc.lpfnWndProc = CamWndProc;
166 if (AfxRegisterClass(&wc) == FALSE) {
167 Error("CCamWnd RegisterClass: failed");
168 }
169 }
170
171 cs.lpszClass = CAMERA_WINDOW_CLASS;
172 cs.lpszName = "CAM";
173 if (cs.style != QE3_CHILDSTYLE) {
174 cs.style = QE3_SPLITTER_STYLE;
175 }
176
177 BOOL bResult = CWnd::PreCreateWindow(cs);
178
179 //
180 // See if the class already exists and if not then we need to register our new
181 // window class.
182 //
183 return bResult;
184 }
185
186 /*
187 =======================================================================================================================
188 =======================================================================================================================
189 */
OnKeyDown(UINT nChar,UINT nRepCnt,UINT nFlags)190 void CCamWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
191 g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
192 }
193
194 brush_t *g_pSplitList = NULL;
195
196 /*
197 =======================================================================================================================
198 =======================================================================================================================
199 */
OnPaint()200 void CCamWnd::OnPaint() {
201 CPaintDC dc(this); // device context for painting
202 bool bPaint = true;
203
204 if (!qwglMakeCurrent(dc.m_hDC, win32.hGLRC)) {
205 common->Printf("ERROR: wglMakeCurrent failed..\n ");
206 common->Printf("Please restart " EDITOR_WINDOWTEXT " if the camera view is not working\n");
207 }
208 else {
209 QE_CheckOpenGLForErrors();
210 g_pSplitList = NULL;
211 if (g_bClipMode) {
212 if (g_Clip1.Set() && g_Clip2.Set()) {
213 g_pSplitList = ((g_pParentWnd->ActiveXY()->GetViewType() == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
214 }
215 }
216
217 Cam_Draw();
218 QE_CheckOpenGLForErrors();
219 qwglSwapBuffers(dc.m_hDC);
220 }
221 }
222
223 /*
224 =======================================================================================================================
225 =======================================================================================================================
226 */
SetXYFriend(CXYWnd * pWnd)227 void CCamWnd::SetXYFriend(CXYWnd *pWnd) {
228 m_pXYFriend = pWnd;
229 }
230
231 /*
232 =======================================================================================================================
233 =======================================================================================================================
234 */
OnDestroy()235 void CCamWnd::OnDestroy() {
236 CWnd::OnDestroy();
237 }
238
239 /*
240 =======================================================================================================================
241 =======================================================================================================================
242 */
OnClose()243 void CCamWnd::OnClose() {
244 CWnd::OnClose();
245 }
246
247 extern void Select_RotateTexture(float amt, bool absolute);
248
249 /*
250 =======================================================================================================================
251 =======================================================================================================================
252 */
OnMouseMove(UINT nFlags,CPoint point)253 void CCamWnd::OnMouseMove(UINT nFlags, CPoint point) {
254 CRect r;
255 GetClientRect(r);
256 if (GetCapture() == this && (GetAsyncKeyState(VK_MENU) & 0x8000) && !((GetAsyncKeyState(VK_SHIFT) & 0x8000) || (GetAsyncKeyState(VK_CONTROL) & 0x8000))) {
257 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) {
258 Select_RotateTexture((float)point.y - m_ptLastCursor.y);
259 }
260 else if (GetAsyncKeyState(VK_SHIFT) & 0x8000) {
261 Select_ScaleTexture((float)point.x - m_ptLastCursor.x, (float)m_ptLastCursor.y - point.y);
262 }
263 else {
264 Select_ShiftTexture((float)point.x - m_ptLastCursor.x, (float)m_ptLastCursor.y - point.y);
265 }
266 }
267 else {
268 Cam_MouseMoved(point.x, r.bottom - 1 - point.y, nFlags);
269 }
270
271 m_ptLastCursor = point;
272 }
273
274 /*
275 =======================================================================================================================
276 =======================================================================================================================
277 */
OnLButtonDown(UINT nFlags,CPoint point)278 void CCamWnd::OnLButtonDown(UINT nFlags, CPoint point) {
279 m_ptLastCursor = point;
280 OriginalMouseDown(nFlags, point);
281 }
282
283 /*
284 =======================================================================================================================
285 =======================================================================================================================
286 */
OnLButtonUp(UINT nFlags,CPoint point)287 void CCamWnd::OnLButtonUp(UINT nFlags, CPoint point) {
288 OriginalMouseUp(nFlags, point);
289 }
290
291 /*
292 =======================================================================================================================
293 =======================================================================================================================
294 */
OnMButtonDown(UINT nFlags,CPoint point)295 void CCamWnd::OnMButtonDown(UINT nFlags, CPoint point) {
296 OriginalMouseDown(nFlags, point);
297 }
298
299 /*
300 =======================================================================================================================
301 =======================================================================================================================
302 */
OnMButtonUp(UINT nFlags,CPoint point)303 void CCamWnd::OnMButtonUp(UINT nFlags, CPoint point) {
304 OriginalMouseUp(nFlags, point);
305 }
306
307 /*
308 =======================================================================================================================
309 =======================================================================================================================
310 */
OnRButtonDown(UINT nFlags,CPoint point)311 void CCamWnd::OnRButtonDown(UINT nFlags, CPoint point) {
312 OriginalMouseDown(nFlags, point);
313 }
314
315 /*
316 =======================================================================================================================
317 =======================================================================================================================
318 */
OnRButtonUp(UINT nFlags,CPoint point)319 void CCamWnd::OnRButtonUp(UINT nFlags, CPoint point) {
320 OriginalMouseUp(nFlags, point);
321 }
322
323 /*
324 =======================================================================================================================
325 =======================================================================================================================
326 */
OnCreate(LPCREATESTRUCT lpCreateStruct)327 int CCamWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
328 if (CWnd::OnCreate(lpCreateStruct) == -1) {
329 return -1;
330 }
331
332 CDC *pDC = GetDC();
333 HDC hDC = pDC->GetSafeHdc();
334
335 QEW_SetupPixelFormat(hDC, true);
336
337 HFONT hfont = CreateFont(
338 12, // logical height of font
339 0, // logical average character width
340 0, // angle of escapement
341 0, // base-line orientation angle
342 0, // font weight
343 0, // italic attribute flag
344 0, // underline attribute flag
345 0, // strikeout attribute flag
346 0, // character set identifier
347 0, // output precision
348 0, // clipping precision
349 0, // output quality
350 FIXED_PITCH | FF_MODERN, // pitch and family
351 "Lucida Console" // pointer to typeface name string
352 );
353
354 if (!hfont) {
355 Error("couldn't create font");
356 }
357
358 HFONT hOldFont = (HFONT)SelectObject(hDC, hfont);
359
360 //qwglMakeCurrent (hDC, win32.hGLRC);
361 if( qwglMakeCurrent ( hDC, win32.hGLRC ) == FALSE ) {
362 common->Warning("wglMakeCurrent failed: %d", ::GetLastError());
363 if ( r_multiSamples.GetInteger() > 0 ) {
364 common->Warning("\n!!! Remember to set r_multiSamples 0 when using the editor !!!\n");
365 }
366 }
367
368 if ((g_qeglobals.d_font_list = qglGenLists(256)) == 0) {
369 common->Warning( "couldn't create font dlists" );
370 }
371
372 // create the bitmap display lists we're making images of glyphs 0 thru 255
373 if ( !qwglUseFontBitmaps(hDC, 0, 255, g_qeglobals.d_font_list) ) {
374 common->Warning( "wglUseFontBitmaps failed (%d). Trying again.", GetLastError() );
375
376 // FIXME: This is really wacky, sometimes the first call fails, but calling it again makes it work
377 // This probably indicates there's something wrong somewhere else in the code, but I'm not sure what
378 if ( !qwglUseFontBitmaps(hDC, 0, 255, g_qeglobals.d_font_list) ) {
379 common->Warning( "wglUseFontBitmaps failed again (%d). Trying outlines.", GetLastError() );
380
381 if (!qwglUseFontOutlines(hDC, 0, 255, g_qeglobals.d_font_list, 0.0f, 0.1f, WGL_FONT_LINES, NULL)) {
382 common->Warning( "wglUseFontOutlines also failed (%d), no coordinate text will be visible.", GetLastError() );
383 }
384 }
385 }
386
387 SelectObject(hDC, hOldFont);
388 ReleaseDC(pDC);
389
390 // indicate start of glyph display lists
391 qglListBase(g_qeglobals.d_font_list);
392
393 // report OpenGL information
394 common->Printf("GL_VENDOR: %s\n", qglGetString(GL_VENDOR));
395 common->Printf("GL_RENDERER: %s\n", qglGetString(GL_RENDERER));
396 common->Printf("GL_VERSION: %s\n", qglGetString(GL_VERSION));
397 common->Printf("GL_EXTENSIONS: %s\n", qglGetString(GL_EXTENSIONS));
398
399 return 0;
400 }
401
402 /*
403 =======================================================================================================================
404 =======================================================================================================================
405 */
OriginalMouseUp(UINT nFlags,CPoint point)406 void CCamWnd::OriginalMouseUp(UINT nFlags, CPoint point) {
407 CRect r;
408 GetClientRect(r);
409 Cam_MouseUp(point.x, r.bottom - 1 - point.y, nFlags);
410 if (!(nFlags & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON))) {
411 ReleaseCapture();
412 }
413 }
414
415 /*
416 =======================================================================================================================
417 =======================================================================================================================
418 */
OriginalMouseDown(UINT nFlags,CPoint point)419 void CCamWnd::OriginalMouseDown(UINT nFlags, CPoint point) {
420 // if (GetTopWindow()->GetSafeHwnd() != GetSafeHwnd()) BringWindowToTop();
421 CRect r;
422 GetClientRect(r);
423 SetFocus();
424 SetCapture();
425
426 // if (!(GetAsyncKeyState(VK_MENU) & 0x8000))
427 Cam_MouseDown(point.x, r.bottom - 1 - point.y, nFlags);
428 }
429
430 /*
431 =======================================================================================================================
432 =======================================================================================================================
433 */
Cam_Init()434 void CCamWnd::Cam_Init() {
435 // m_Camera.draw_mode = cd_texture;
436 m_Camera.origin[0] = 0.0f;
437 m_Camera.origin[1] = 20.0f;
438 m_Camera.origin[2] = 72.0f;
439 m_Camera.color[0] = 0.3f;
440 m_Camera.color[1] = 0.3f;
441 m_Camera.color[2] = 0.3f;
442 }
443
444 /*
445 =======================================================================================================================
446 =======================================================================================================================
447 */
Cam_BuildMatrix()448 void CCamWnd::Cam_BuildMatrix() {
449 float xa, ya;
450 float matrix[4][4];
451 int i;
452
453 xa = ((renderMode) ? -m_Camera.angles[PITCH] : m_Camera.angles[PITCH]) * idMath::M_DEG2RAD;
454 ya = m_Camera.angles[YAW] * idMath::M_DEG2RAD;
455
456 // the movement matrix is kept 2d
457 m_Camera.forward[0] = cos(ya);
458 m_Camera.forward[1] = sin(ya);
459 m_Camera.right[0] = m_Camera.forward[1];
460 m_Camera.right[1] = -m_Camera.forward[0];
461
462 qglGetFloatv(GL_PROJECTION_MATRIX, &matrix[0][0]);
463
464 for (i = 0; i < 3; i++) {
465 m_Camera.vright[i] = matrix[i][0];
466 m_Camera.vup[i] = matrix[i][1];
467 m_Camera.vpn[i] = matrix[i][2];
468 }
469
470 m_Camera.vright.Normalize();
471 m_Camera.vup.Normalize();
472 m_Camera.vpn.Normalize();
473 InitCull();
474 }
475
476 /*
477 =======================================================================================================================
478 =======================================================================================================================
479 */
480
Cam_ChangeFloor(bool up)481 void CCamWnd::Cam_ChangeFloor(bool up) {
482 brush_t *b;
483 float d, bestd, current;
484 idVec3 start, dir;
485
486 start[0] = m_Camera.origin[0];
487 start[1] = m_Camera.origin[1];
488 start[2] = HUGE_DISTANCE;
489 dir[0] = dir[1] = 0;
490 dir[2] = -1;
491
492 current = HUGE_DISTANCE - (m_Camera.origin[2] - 72);
493 if (up) {
494 bestd = 0;
495 }
496 else {
497 bestd = HUGE_DISTANCE*2;
498 }
499
500 for (b = active_brushes.next; b != &active_brushes; b = b->next) {
501 if (!Brush_Ray(start, dir, b, &d)) {
502 continue;
503 }
504
505 if (up && d < current && d > bestd) {
506 bestd = d;
507 }
508
509 if (!up && d > current && d < bestd) {
510 bestd = d;
511 }
512 }
513
514 if (bestd == 0 || bestd == HUGE_DISTANCE*2) {
515 return;
516 }
517
518 m_Camera.origin[2] += current - bestd;
519 Sys_UpdateWindows(W_CAMERA | W_Z_OVERLAY);
520 }
521
522 /*
523 =======================================================================================================================
524 =======================================================================================================================
525 */
Cam_PositionDrag()526 void CCamWnd::Cam_PositionDrag() {
527 int x, y;
528 Sys_GetCursorPos(&x, &y);
529 if (x != m_ptCursor.x || y != m_ptCursor.y) {
530 x -= m_ptCursor.x;
531 VectorMA(m_Camera.origin, x, m_Camera.vright, m_Camera.origin);
532 y -= m_ptCursor.y;
533 m_Camera.origin[2] -= y;
534 SetCursorPos(m_ptCursor.x, m_ptCursor.y);
535 Sys_UpdateWindows(W_CAMERA | W_XY_OVERLAY);
536 }
537 }
538
Cam_MouseLook()539 void CCamWnd::Cam_MouseLook() {
540 CPoint current;
541
542 GetCursorPos(¤t);
543 if (current.x != m_ptCursor.x || current.y != m_ptCursor.y) {
544
545 current.x -= m_ptCursor.x;
546 current.y -= m_ptCursor.y;
547
548 m_Camera.angles[PITCH] -= (float)((float)current.y * 0.25f);
549 m_Camera.angles[YAW] -= (float)((float)current.x * 0.25f);
550
551 SetCursorPos(m_ptCursor.x, m_ptCursor.y);
552
553 Cam_BuildMatrix();
554 }
555 }
556
557 /*
558 =======================================================================================================================
559 =======================================================================================================================
560 */
Cam_MouseControl(float dtime)561 void CCamWnd::Cam_MouseControl(float dtime) {
562 int xl, xh;
563 int yl, yh;
564 float xf, yf;
565 if (g_PrefsDlg.m_nMouseButtons == 2) {
566 if (m_nCambuttonstate != (MK_RBUTTON | MK_SHIFT)) {
567 return;
568 }
569 }
570 else {
571 if (m_nCambuttonstate != MK_RBUTTON) {
572 return;
573 }
574 }
575
576 xf = (float)(m_ptButton.x - m_Camera.width / 2) / (m_Camera.width / 2);
577 yf = (float)(m_ptButton.y - m_Camera.height / 2) / (m_Camera.height / 2);
578
579 xl = m_Camera.width / 3;
580 xh = xl * 2;
581 yl = m_Camera.height / 3;
582 yh = yl * 2;
583
584 // common->Printf("xf-%f yf-%f xl-%i xh-i% yl-i% yh-i%\n",xf,yf,xl,xh,yl,yh);
585 #if 0
586
587 // strafe
588 if (buttony < yl && (buttonx < xl || buttonx > xh)) {
589 VectorMA(camera.origin, xf * dtime * g_nMoveSpeed, camera.right, camera.origin);
590 }
591 else
592 #endif
593 {
594 xf *= 1.0f - idMath::Fabs(yf);
595 if ( xf < 0.0f ) {
596 xf += 0.1f;
597 if ( xf > 0.0f ) {
598 xf = 0.0f;
599 }
600 }
601 else {
602 xf -= 0.1f;
603 if ( xf < 0.0f ) {
604 xf = 0.0f;
605 }
606 }
607
608 VectorMA(m_Camera.origin, yf * dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, m_Camera.origin);
609 m_Camera.angles[YAW] += xf * -dtime * g_PrefsDlg.m_nAngleSpeed;
610 }
611
612 Cam_BuildMatrix();
613 int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
614 Sys_UpdateWindows(nUpdate);
615 g_pParentWnd->PostMessage(WM_TIMER, 0, 0);
616 }
617
618 /*
619 =======================================================================================================================
620 =======================================================================================================================
621 */
Cam_MouseDown(int x,int y,int buttons)622 void CCamWnd::Cam_MouseDown(int x, int y, int buttons) {
623 idVec3 dir;
624 float f, r, u;
625 int i;
626
627 // calc ray direction
628 u = (float)(y - m_Camera.height / 2) / (m_Camera.width / 2);
629 r = (float)(x - m_Camera.width / 2) / (m_Camera.width / 2);
630 f = 1;
631
632 for (i = 0; i < 3; i++) {
633 dir[i] = m_Camera.vpn[i] * f + m_Camera.vright[i] * r + m_Camera.vup[i] * u;
634 }
635
636 dir.Normalize();
637
638 GetCursorPos(&m_ptCursor);
639
640 m_nCambuttonstate = buttons;
641 m_ptButton.x = x;
642 m_ptButton.y = y;
643
644 //
645 // LBUTTON = manipulate selection shift-LBUTTON = select middle button = grab
646 // texture ctrl-middle button = set entire brush to texture ctrl-shift-middle
647 // button = set single face to texture
648 //
649 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
650 if
651 (
652 (buttons == MK_LBUTTON) ||
653 (buttons == (MK_LBUTTON | MK_SHIFT)) ||
654 (buttons == (MK_LBUTTON | MK_CONTROL)) ||
655 (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) ||
656 (buttons == nMouseButton) ||
657 (buttons == (nMouseButton | MK_SHIFT)) ||
658 (buttons == (nMouseButton | MK_CONTROL)) ||
659 (buttons == (nMouseButton | MK_SHIFT | MK_CONTROL))
660 ) {
661 if (g_PrefsDlg.m_nMouseButtons == 2 && (buttons == (MK_RBUTTON | MK_SHIFT))) {
662 Cam_MouseControl( 0.1f );
663 }
664 else {
665 // something global needs to track which window is responsible for stuff
666 Patch_SetView(W_CAMERA);
667 Drag_Begin(x, y, buttons, m_Camera.vright, m_Camera.vup, m_Camera.origin, dir);
668 }
669
670 return;
671 }
672
673 if ( buttons == MK_RBUTTON ) {
674 Cam_MouseControl( 0.1f );
675 return;
676 }
677 }
678
679 /*
680 =======================================================================================================================
681 =======================================================================================================================
682 */
Cam_MouseUp(int x,int y,int buttons)683 void CCamWnd::Cam_MouseUp(int x, int y, int buttons) {
684 m_nCambuttonstate = 0;
685 Drag_MouseUp(buttons);
686 }
687
688 /*
689 =======================================================================================================================
690 =======================================================================================================================
691 */
Cam_MouseMoved(int x,int y,int buttons)692 void CCamWnd::Cam_MouseMoved(int x, int y, int buttons) {
693 m_nCambuttonstate = buttons;
694 if (!buttons) {
695 return;
696 }
697
698 m_ptButton.x = x;
699 m_ptButton.y = y;
700
701 if (buttons == (MK_RBUTTON | MK_CONTROL)) {
702 Cam_PositionDrag();
703 Sys_UpdateWindows(W_XY | W_CAMERA | W_Z);
704 return;
705 }
706 else if ( buttons == (MK_RBUTTON | MK_CONTROL | MK_SHIFT) ) {
707 Cam_MouseLook();
708 Sys_UpdateWindows(W_XY | W_CAMERA | W_Z);
709 return;
710 }
711
712 GetCursorPos(&m_ptCursor);
713
714 if (buttons & (MK_LBUTTON | MK_MBUTTON)) {
715 Drag_MouseMoved(x, y, buttons);
716 Sys_UpdateWindows(W_XY | W_CAMERA | W_Z);
717 }
718 }
719
720 /*
721 =======================================================================================================================
722 =======================================================================================================================
723 */
InitCull()724 void CCamWnd::InitCull() {
725 int i;
726
727 VectorSubtract(m_Camera.vpn, m_Camera.vright, m_vCull1);
728 VectorAdd(m_Camera.vpn, m_Camera.vright, m_vCull2);
729
730 for (i = 0; i < 3; i++) {
731 if (m_vCull1[i] > 0) {
732 m_nCullv1[i] = 3 + i;
733 }
734 else {
735 m_nCullv1[i] = i;
736 }
737
738 if (m_vCull2[i] > 0) {
739 m_nCullv2[i] = 3 + i;
740 }
741 else {
742 m_nCullv2[i] = i;
743 }
744 }
745 }
746
747 /*
748 =======================================================================================================================
749 =======================================================================================================================
750 */
CullBrush(brush_t * b,bool cubicOnly)751 bool CCamWnd::CullBrush(brush_t *b, bool cubicOnly) {
752 int i;
753 idVec3 point;
754 float d;
755
756 if ( b->forceVisibile ) {
757 return false;
758 }
759
760 if (g_PrefsDlg.m_bCubicClipping) {
761
762 float distance = g_PrefsDlg.m_nCubicScale * 64;
763
764 idVec3 mid;
765 for (int i = 0; i < 3; i++) {
766 mid[i] = (b->mins[i] + ((b->maxs[i] - b->mins[i]) / 2));
767 }
768
769 point = mid - m_Camera.origin;
770 if (point.Length() > distance) {
771 return true;
772 }
773
774 }
775
776 if (cubicOnly) {
777 return false;
778 }
779
780 for (i = 0; i < 3; i++) {
781 point[i] = b->mins[m_nCullv1[i]] - m_Camera.origin[i];
782 }
783
784 d = DotProduct(point, m_vCull1);
785 if (d < -1) {
786 return true;
787 }
788
789 for (i = 0; i < 3; i++) {
790 point[i] = b->mins[m_nCullv2[i]] - m_Camera.origin[i];
791 }
792
793 d = DotProduct(point, m_vCull2);
794 if (d < -1) {
795 return true;
796 }
797
798 return false;
799 }
800
801 #if 0
802
803 /*
804 =======================================================================================================================
805 =======================================================================================================================
806 */
807 void CCamWnd::DrawLightRadius(brush_t *pBrush) {
808 // if lighting
809 int nRadius = Brush_LightRadius(pBrush);
810 if (nRadius > 0) {
811 Brush_SetLightColor(pBrush);
812 qglEnable(GL_BLEND);
813 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
814 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
815 qglDisable(GL_BLEND);
816 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
817 }
818 }
819 #endif
820
821 /*
822 =======================================================================================================================
823 =======================================================================================================================
824 */
setGLMode(int mode)825 void setGLMode(int mode) {
826 switch (mode)
827 {
828 case cd_wire:
829 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
830 globalImages->BindNull();
831 qglDisable(GL_BLEND);
832 qglDisable(GL_DEPTH_TEST);
833 qglColor3f( 1.0f, 1.0f, 1.0f );
834 break;
835
836 case cd_solid:
837 qglCullFace(GL_FRONT);
838 qglEnable(GL_CULL_FACE);
839 qglShadeModel(GL_FLAT);
840 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
841 globalImages->BindNull();
842 qglDisable(GL_BLEND);
843 qglEnable(GL_DEPTH_TEST);
844 qglDepthFunc(GL_LEQUAL);
845 break;
846
847 case cd_texture:
848 qglCullFace(GL_FRONT);
849 qglEnable(GL_CULL_FACE);
850 qglShadeModel(GL_FLAT);
851 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
852 qglDisable(GL_BLEND);
853 qglEnable(GL_DEPTH_TEST);
854 qglDepthFunc(GL_LEQUAL);
855 break;
856
857 case cd_blend:
858 qglCullFace(GL_FRONT);
859 qglEnable(GL_CULL_FACE);
860 qglShadeModel(GL_FLAT);
861 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
862 qglDisable(GL_DEPTH_TEST);
863 qglEnable(GL_BLEND);
864 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
865 break;
866 }
867 }
868
869
870 extern void glLabeledPoint(idVec4 &color, idVec3 &point, float size, const char *label);
DrawAxial(face_t * selFace)871 void DrawAxial(face_t *selFace) {
872 if (g_bAxialMode) {
873 idVec3 points[4];
874
875 for (int j = 0; j < selFace->face_winding->GetNumPoints(); j++) {
876 glLabeledPoint(idVec4(1, 1, 1, 1), (*selFace->face_winding)[j].ToVec3(), 3, va("%i", j));
877 }
878
879 ValidateAxialPoints();
880 points[0] = (*selFace->face_winding)[g_axialAnchor].ToVec3();
881 VectorMA (points[0], 1, selFace->plane, points[0]);
882 VectorMA (points[0], 4, selFace->plane, points[1]);
883 points[3] = (*selFace->face_winding)[g_axialDest].ToVec3();
884 VectorMA (points[3], 1, selFace->plane, points[3]);
885 VectorMA (points[3], 4, selFace->plane, points[2]);
886 glLabeledPoint(idVec4(1, 0, 0, 1), points[1], 3, "Anchor");
887 glLabeledPoint(idVec4(1, 1, 0, 1), points[2], 3, "Dest");
888 qglBegin (GL_LINE_STRIP);
889 qglVertex3fv( points[0].ToFloatPtr() );
890 qglVertex3fv( points[1].ToFloatPtr() );
891 qglVertex3fv( points[2].ToFloatPtr() );
892 qglVertex3fv( points[3].ToFloatPtr() );
893 qglEnd();
894 }
895 }
896
897
898 /*
899 =======================================================================================================================
900 Cam_Draw
901 =======================================================================================================================
902 */
SetProjectionMatrix()903 void CCamWnd::SetProjectionMatrix() {
904 float xfov = 90;
905 float yfov = 2 * atan((float)m_Camera.height / m_Camera.width) * idMath::M_RAD2DEG;
906 #if 0
907 float screenaspect = (float)m_Camera.width / m_Camera.height;
908 qglLoadIdentity();
909 gluPerspective(yfov, screenaspect, 2, 8192);
910 #else
911 float xmin, xmax, ymin, ymax;
912 float width, height;
913 float zNear;
914 float projectionMatrix[16];
915
916 //
917 // set up projection matrix
918 //
919 zNear = r_znear.GetFloat();
920
921 ymax = zNear * tan( yfov * idMath::PI / 360.0f );
922 ymin = -ymax;
923
924 xmax = zNear * tan( xfov * idMath::PI / 360.0f );
925 xmin = -xmax;
926
927 width = xmax - xmin;
928 height = ymax - ymin;
929
930 projectionMatrix[0] = 2 * zNear / width;
931 projectionMatrix[4] = 0;
932 projectionMatrix[8] = ( xmax + xmin ) / width; // normally 0
933 projectionMatrix[12] = 0;
934
935 projectionMatrix[1] = 0;
936 projectionMatrix[5] = 2 * zNear / height;
937 projectionMatrix[9] = ( ymax + ymin ) / height; // normally 0
938 projectionMatrix[13] = 0;
939
940 // this is the far-plane-at-infinity formulation
941 projectionMatrix[2] = 0;
942 projectionMatrix[6] = 0;
943 projectionMatrix[10] = -1;
944 projectionMatrix[14] = -2 * zNear;
945
946 projectionMatrix[3] = 0;
947 projectionMatrix[7] = 0;
948 projectionMatrix[11] = -1;
949 projectionMatrix[15] = 0;
950
951 qglLoadMatrixf( projectionMatrix );
952 #endif
953 }
954
Cam_Draw()955 void CCamWnd::Cam_Draw() {
956 brush_t *brush;
957 face_t *face;
958
959 // float yfov;
960 int i;
961
962 if (!active_brushes.next) {
963 return; // not valid yet
964 }
965
966 // set the sound origin for both simple draw and rendered mode
967 // the editor uses opposite pitch convention
968 idMat3 axis = idAngles( -m_Camera.angles.pitch, m_Camera.angles.yaw, m_Camera.angles.roll ).ToMat3();
969 g_qeglobals.sw->PlaceListener( m_Camera.origin, axis, 0, Sys_Milliseconds(), "Undefined" );
970
971 if (renderMode) {
972 Cam_Render();
973 }
974
975 qglViewport(0, 0, m_Camera.width, m_Camera.height);
976 qglScissor(0, 0, m_Camera.width, m_Camera.height);
977 qglClearColor(g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][0], g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][1], g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][2], 0);
978
979 if (!renderMode) {
980 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
981 }
982
983 qglDisable(GL_LIGHTING);
984 qglMatrixMode(GL_PROJECTION);
985
986 SetProjectionMatrix();
987
988 qglRotatef(-90, 1, 0, 0); // put Z going up
989 qglRotatef(90, 0, 0, 1); // put Z going up
990 qglRotatef(m_Camera.angles[0], 0, 1, 0);
991 qglRotatef(-m_Camera.angles[1], 0, 0, 1);
992 qglTranslatef(-m_Camera.origin[0], -m_Camera.origin[1], -m_Camera.origin[2]);
993
994 Cam_BuildMatrix();
995
996 for (brush = active_brushes.next; brush != &active_brushes; brush = brush->next) {
997
998 if ( CullBrush(brush, false) ) {
999 continue;
1000 }
1001
1002 if ( FilterBrush(brush) ) {
1003 continue;
1004 }
1005
1006 if (renderMode) {
1007 if (!(entityMode && brush->owner->eclass->fixedsize)) {
1008 continue;
1009 }
1010 }
1011
1012 setGLMode(m_Camera.draw_mode);
1013 Brush_Draw(brush);
1014 }
1015
1016
1017 //qglDepthMask ( 1 ); // Ok, write now
1018 qglMatrixMode(GL_PROJECTION);
1019
1020 qglTranslatef(g_qeglobals.d_select_translate[0],g_qeglobals.d_select_translate[1],g_qeglobals.d_select_translate[2]);
1021
1022 brush_t *pList = (g_bClipMode && g_pSplitList) ? g_pSplitList : &selected_brushes;
1023
1024 if (!renderMode) {
1025 // draw normally
1026 for (brush = pList->next; brush != pList; brush = brush->next) {
1027 if (brush->pPatch) {
1028 continue;
1029 }
1030 setGLMode(m_Camera.draw_mode);
1031 Brush_Draw(brush, true);
1032 }
1033 }
1034
1035 // blend on top
1036
1037 setGLMode(m_Camera.draw_mode);
1038 qglDisable(GL_LIGHTING);
1039 qglColor4f( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0],g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1],g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2], 0.25f );
1040 qglEnable(GL_BLEND);
1041 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1042 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1043 globalImages->BindNull();
1044 for (brush = pList->next; brush != pList; brush = brush->next) {
1045 if (brush->pPatch || brush->modelHandle > 0) {
1046 Brush_Draw(brush, true);
1047
1048 // DHM - Nerve:: patch display lists/models mess with the state
1049 qglEnable(GL_BLEND);
1050 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1051 qglColor4f( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0],g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1],g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2], 0.25f );
1052 globalImages->BindNull();
1053 continue;
1054 }
1055
1056 if ( brush->owner->eclass->entityModel ) {
1057 continue;
1058 }
1059
1060 for (face = brush->brush_faces; face; face = face->next) {
1061 Face_Draw(face);
1062 }
1063 }
1064
1065 int nCount = g_ptrSelectedFaces.GetSize();
1066
1067 if (!renderMode) {
1068 for (int i = 0; i < nCount; i++) {
1069 face_t *selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
1070 Face_Draw(selFace);
1071 DrawAxial(selFace);
1072 }
1073 }
1074
1075 // non-zbuffered outline
1076 qglDisable(GL_BLEND);
1077 qglDisable(GL_DEPTH_TEST);
1078 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1079
1080 if (renderMode) {
1081 qglColor3f(1, 0, 0);
1082 for (int i = 0; i < nCount; i++) {
1083 face_t *selFace = reinterpret_cast < face_t * > (g_ptrSelectedFaces.GetAt(i));
1084 Face_Draw(selFace);
1085 }
1086 }
1087
1088 qglColor3f(1, 1, 1);
1089 for (brush = pList->next; brush != pList; brush = brush->next) {
1090 if (brush->pPatch || brush->modelHandle > 0) {
1091 continue;
1092 }
1093
1094 for (face = brush->brush_faces; face; face = face->next) {
1095 Face_Draw(face);
1096 }
1097 }
1098 // edge / vertex flags
1099 if (g_qeglobals.d_select_mode == sel_vertex) {
1100 qglPointSize(4);
1101 qglColor3f(0, 1, 0);
1102 qglBegin(GL_POINTS);
1103 for (i = 0; i < g_qeglobals.d_numpoints; i++) {
1104 qglVertex3fv( g_qeglobals.d_points[i].ToFloatPtr() );
1105 }
1106
1107 qglEnd();
1108 qglPointSize(1);
1109 }
1110 else if (g_qeglobals.d_select_mode == sel_edge) {
1111 float *v1, *v2;
1112
1113 qglPointSize(4);
1114 qglColor3f(0, 0, 1);
1115 qglBegin(GL_POINTS);
1116 for (i = 0; i < g_qeglobals.d_numedges; i++) {
1117 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1].ToFloatPtr();
1118 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2].ToFloatPtr();
1119 qglVertex3f( (v1[0] + v2[0]) * 0.5f, (v1[1] + v2[1]) * 0.5f, (v1[2] + v2[2]) * 0.5f );
1120 }
1121
1122 qglEnd();
1123 qglPointSize(1);
1124 }
1125
1126 g_splineList->draw (static_cast<bool>(g_qeglobals.d_select_mode == sel_addpoint || g_qeglobals.d_select_mode == sel_editpoint));
1127
1128 if ( g_qeglobals.selectObject && (g_qeglobals.d_select_mode == sel_addpoint || g_qeglobals.d_select_mode == sel_editpoint) ) {
1129 g_qeglobals.selectObject->drawSelection();
1130 }
1131
1132 // draw pointfile
1133 qglEnable(GL_DEPTH_TEST);
1134
1135 DrawPathLines();
1136
1137 if (g_qeglobals.d_pointfile_display_list) {
1138 Pointfile_Draw();
1139 }
1140
1141 //
1142 // bind back to the default texture so that we don't have problems elsewhere
1143 // using/modifying texture maps between contexts
1144 //
1145 globalImages->BindNull();
1146
1147 qglFinish();
1148 QE_CheckOpenGLForErrors();
1149
1150 if (!renderMode) {
1151 // clean up any deffered tri's
1152 R_ToggleSmpFrame();
1153 }
1154 }
1155
1156 /*
1157 =======================================================================================================================
1158 =======================================================================================================================
1159 */
OnSize(UINT nType,int cx,int cy)1160 void CCamWnd::OnSize(UINT nType, int cx, int cy) {
1161 CWnd::OnSize(nType, cx, cy);
1162
1163 CRect rect;
1164 GetClientRect(rect);
1165 m_Camera.width = rect.right;
1166 m_Camera.height = rect.bottom;
1167 InvalidateRect(NULL, false);
1168 }
1169
1170
1171 /*
1172 =======================================================================================================================
1173 =======================================================================================================================
1174 */
OnKeyUp(UINT nChar,UINT nRepCnt,UINT nFlags)1175 void CCamWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {
1176 g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
1177 }
1178
1179 //
1180 // =======================================================================================================================
1181 // Timo brush primitive texture shifting, using camera view to select translations::
1182 // =======================================================================================================================
1183 //
ShiftTexture_BrushPrimit(face_t * f,int x,int y)1184 void CCamWnd::ShiftTexture_BrushPrimit(face_t *f, int x, int y) {
1185 /*
1186 idVec3 texS, texT;
1187 idVec3 viewX, viewY;
1188 int XS, XT, YS, YT;
1189 int outS, outT;
1190 #ifdef _DEBUG
1191 if (!g_qeglobals.m_bBrushPrimitMode) {
1192 common->Printf("Warning : unexpected call to CCamWnd::ShiftTexture_BrushPrimit with brush primitive mode disbaled\n");
1193 return;
1194 }
1195 #endif
1196 // compute face axis base
1197 //ComputeAxisBase(f->plane.Normal(), texS, texT);
1198
1199 // compute camera view vectors
1200 VectorCopy(m_Camera.vup, viewY);
1201 VectorCopy(m_Camera.vright, viewX);
1202
1203 // compute best vectors
1204 //ComputeBest2DVector(viewX, texS, texT, XS, XT);
1205 //ComputeBest2DVector(viewY, texS, texT, YS, YT);
1206
1207 // check this is not a degenerate case
1208 if ((XS == YS) && (XT == YT))
1209 {
1210 #ifdef _DEBUG
1211 common->Printf("Warning : degenerate best vectors axis base in CCamWnd::ShiftTexture_BrushPrimit\n");
1212 #endif
1213 // forget it
1214 Select_ShiftTexture_BrushPrimit(f, x, y, false);
1215 return;
1216 }
1217
1218 // compute best fitted translation in face axis base
1219 outS = XS * x + YS * y;
1220 outT = XT * x + YT * y;
1221
1222 // call actual texture shifting code
1223 Select_ShiftTexture_BrushPrimit(f, outS, outT, false);
1224 */
1225 }
1226
1227
IsBModel(brush_t * b)1228 bool IsBModel(brush_t *b) {
1229 const char *v = ValueForKey( b->owner, "model" );
1230 if (v && *v) {
1231 const char *n = ValueForKey( b->owner, "name");
1232 return (stricmp( n, v ) == 0);
1233 }
1234 return false;
1235 }
1236
1237 /*
1238 ================
1239 BuildEntityRenderState
1240
1241 Creates or updates modelDef and lightDef for an entity
1242 ================
1243 */
1244 int Brush_ToTris(brush_t *brush, idTriList *tris, idMatList *mats, bool models, bool bmodel);
1245
BuildEntityRenderState(entity_t * ent,bool update)1246 void CCamWnd::BuildEntityRenderState( entity_t *ent, bool update) {
1247 const char *v;
1248 idDict spawnArgs;
1249 const char *name = NULL;
1250
1251 Entity_UpdateSoundEmitter( ent );
1252
1253 // delete the existing def if we aren't creating a brand new world
1254 if ( !update ) {
1255 if ( ent->lightDef >= 0 ) {
1256 g_qeglobals.rw->FreeLightDef( ent->lightDef );
1257 ent->lightDef = -1;
1258 }
1259
1260 if ( ent->modelDef >= 0 ) {
1261 g_qeglobals.rw->FreeEntityDef( ent->modelDef );
1262 ent->modelDef = -1;
1263 }
1264 }
1265
1266 // if an entity doesn't have any brushes at all, don't do anything
1267 if ( ent->brushes.onext == &ent->brushes ) {
1268 return;
1269 }
1270
1271 // if the brush isn't displayed (filtered or culled), don't do anything
1272 if (FilterBrush(ent->brushes.onext)) {
1273 return;
1274 }
1275
1276 spawnArgs = ent->epairs;
1277 if (ent->eclass->defArgs.FindKey("model")) {
1278 spawnArgs.Set("model", ent->eclass->defArgs.GetString("model"));
1279 }
1280
1281 // any entity can have a model
1282 name = ValueForKey( ent, "name" );
1283 v = spawnArgs.GetString("model");
1284 if ( v && *v ) {
1285 renderEntity_t refent;
1286
1287 refent.referenceSound = ent->soundEmitter;
1288
1289 if ( !stricmp( name, v ) ) {
1290 // build the model from brushes
1291 idTriList tris(1024);
1292 idMatList mats(1024);
1293
1294 for (brush_t *b = ent->brushes.onext; b != &ent->brushes; b = b->onext) {
1295 Brush_ToTris( b, &tris, &mats, false, true);
1296 }
1297
1298 if ( ent->modelDef >= 0 ) {
1299 g_qeglobals.rw->FreeEntityDef( ent->modelDef );
1300 ent->modelDef = -1;
1301 }
1302
1303 idRenderModel *bmodel = renderModelManager->FindModel( name );
1304
1305 if ( bmodel ) {
1306 renderModelManager->RemoveModel( bmodel );
1307 renderModelManager->FreeModel( bmodel );
1308 }
1309
1310 bmodel = renderModelManager->AllocModel();
1311
1312 bmodel->InitEmpty( name );
1313
1314 // add the surfaces to the renderModel
1315 modelSurface_t surf;
1316 for ( int i = 0 ; i < tris.Num() ; i++ ) {
1317 surf.geometry = tris[i];
1318 surf.shader = mats[i];
1319 bmodel->AddSurface( surf );
1320 }
1321
1322 bmodel->FinishSurfaces();
1323
1324 renderModelManager->AddModel( bmodel );
1325
1326 // FIXME: brush entities
1327 gameEdit->ParseSpawnArgsToRenderEntity( &spawnArgs, &refent );
1328
1329 ent->modelDef = g_qeglobals.rw->AddEntityDef( &refent );
1330
1331 } else {
1332 // use the game's epair parsing code so
1333 // we can use the same renderEntity generation
1334 gameEdit->ParseSpawnArgsToRenderEntity( &spawnArgs, &refent );
1335 idRenderModelMD5 *md5 = dynamic_cast<idRenderModelMD5 *>( refent.hModel );
1336 if (md5) {
1337 idStr str;
1338 spawnArgs.GetString("anim", "idle", str);
1339 refent.numJoints = md5->NumJoints();
1340 if ( update && refent.joints ) {
1341 Mem_Free16( refent.joints );
1342 }
1343 refent.joints = ( idJointMat * )Mem_Alloc16( refent.numJoints * sizeof( *refent.joints ) );
1344 const idMD5Anim *anim = gameEdit->ANIM_GetAnimFromEntityDef(spawnArgs.GetString("classname"), str);
1345 int frame = spawnArgs.GetInt("frame") + 1;
1346 if ( frame < 1 ) {
1347 frame = 1;
1348 }
1349 const idVec3 &offset = gameEdit->ANIM_GetModelOffsetFromEntityDef( spawnArgs.GetString("classname") );
1350 gameEdit->ANIM_CreateAnimFrame( md5, anim, refent.numJoints, refent.joints, ( frame * 1000 ) / 24, offset, false );
1351 }
1352 if (ent->modelDef >= 0) {
1353 g_qeglobals.rw->FreeEntityDef( ent->modelDef );
1354 }
1355 ent->modelDef = g_qeglobals.rw->AddEntityDef( &refent );
1356 }
1357 }
1358
1359 // check for lightdefs
1360 if (!(ent->eclass->nShowFlags & ECLASS_LIGHT)) {
1361 return;
1362 }
1363
1364 if ( spawnArgs.GetBool( "start_off" ) ) {
1365 return;
1366 }
1367 // use the game's epair parsing code so
1368 // we can use the same renderLight generation
1369
1370 renderLight_t lightParms;
1371
1372 gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &lightParms );
1373 lightParms.referenceSound = ent->soundEmitter;
1374
1375 if (update && ent->lightDef >= 0) {
1376 g_qeglobals.rw->UpdateLightDef( ent->lightDef, &lightParms );
1377 } else {
1378 if (ent->lightDef >= 0) {
1379 g_qeglobals.rw->FreeLightDef(ent->lightDef);
1380 }
1381 ent->lightDef = g_qeglobals.rw->AddLightDef( &lightParms );
1382 }
1383
1384 }
1385
Tris_ToOBJ(const char * outFile,idTriList * tris,idMatList * mats)1386 void Tris_ToOBJ(const char *outFile, idTriList *tris, idMatList *mats) {
1387 idFile *f = fileSystem->OpenExplicitFileWrite( outFile );
1388 if ( f ) {
1389 char out[1024];
1390 strcpy(out, outFile);
1391 StripExtension(out);
1392
1393 idList<idStr*> matNames;
1394 int i, j, k;
1395 int indexBase = 1;
1396 idStr lastMaterial("");
1397 int matCount = 0;
1398 //idStr basePath = cvarSystem->GetCVarString( "fs_savepath" );
1399 f->Printf( "mtllib %s.mtl\n", out );
1400 for (i = 0; i < tris->Num(); i++) {
1401 srfTriangles_t *tri = (*tris)[i];
1402 for (j = 0; j < tri->numVerts; j++) {
1403 f->Printf( "v %f %f %f\n", tri->verts[j].xyz.x, tri->verts[j].xyz.z, -tri->verts[j].xyz.y );
1404 }
1405 for (j = 0; j < tri->numVerts; j++) {
1406 f->Printf( "vt %f %f\n", tri->verts[j].st.x, 1.0f - tri->verts[j].st.y );
1407 }
1408 for (j = 0; j < tri->numVerts; j++) {
1409 f->Printf( "vn %f %f %f\n", tri->verts[j].normal.x, tri->verts[j].normal.y, tri->verts[j].normal.z );
1410 }
1411
1412 if (stricmp( (*mats)[i]->GetName(), lastMaterial)) {
1413 lastMaterial = (*mats)[i]->GetName();
1414
1415 bool found = false;
1416 for (k = 0; k < matNames.Num(); k++) {
1417 if ( idStr::Icmp(matNames[k]->c_str(), lastMaterial.c_str()) == 0 ) {
1418 found = true;
1419 // f->Printf( "usemtl m%i\n", k );
1420 f->Printf( "usemtl %s\n", lastMaterial.c_str() );
1421 break;
1422 }
1423 }
1424
1425 if (!found) {
1426 // f->Printf( "usemtl m%i\n", matCount++ );
1427 f->Printf( "usemtl %s\n", lastMaterial.c_str() );
1428 matNames.Append(new idStr(lastMaterial));
1429 }
1430 }
1431
1432 for (int j = 0; j < tri->numIndexes; j += 3) {
1433 int i1, i2, i3;
1434 i1 = tri->indexes[j+2] + indexBase;
1435 i2 = tri->indexes[j+1] + indexBase;
1436 i3 = tri->indexes[j] + indexBase;
1437 f->Printf( "f %i/%i/%i %i/%i/%i %i/%i/%i\n", i1,i1,i1, i2,i2,i2, i3,i3,i3 );
1438 }
1439
1440 indexBase += tri->numVerts;
1441
1442 }
1443 fileSystem->CloseFile( f );
1444
1445 strcat(out, ".mtl");
1446 f = fileSystem->OpenExplicitFileWrite( out );
1447 if (f) {
1448 for (k = 0; k < matNames.Num(); k++) {
1449 // This presumes the diffuse tga name matches the material name
1450 f->Printf( "newmtl %s\n\tNs 0\n\td 1\n\tillum 2\n\tKd 0 0 0 \n\tKs 0.22 0.22 0.22 \n\tKa 0 0 0 \n\tmap_Kd %s/base/%s.tga\n\n\n", matNames[k]->c_str(), "z:/d3xp", matNames[k]->c_str() );
1451 }
1452 fileSystem->CloseFile( f );
1453 }
1454
1455 }
1456 }
1457
Brush_TransformModel(brush_t * brush,idTriList * tris,idMatList * mats)1458 int Brush_TransformModel(brush_t *brush, idTriList *tris, idMatList *mats) {
1459 int ret = 0;
1460 if (brush->modelHandle > 0 ) {
1461 idRenderModel *model = brush->modelHandle;
1462 if (model) {
1463 float a = FloatForKey(brush->owner, "angle");
1464 float s, c;
1465 //FIXME: support full rotation matrix
1466 bool matrix = false;
1467 if (a) {
1468 s = sin( DEG2RAD(a) );
1469 c = cos( DEG2RAD(a) );
1470 }
1471 idMat3 mat;
1472 if (GetMatrixForKey(brush->owner, "rotation", mat)) {
1473 matrix = true;
1474 }
1475
1476
1477 for (int i = 0; i < model->NumSurfaces() ; i++) {
1478 const modelSurface_t *surf = model->Surface( i );
1479 srfTriangles_t *tri = surf->geometry;
1480 srfTriangles_t *tri2 = R_CopyStaticTriSurf(tri);
1481 for (int j = 0; j < tri2->numVerts; j++) {
1482 idVec3 v;
1483 if (matrix) {
1484 v = tri2->verts[j].xyz * brush->owner->rotation + brush->owner->origin;
1485 } else {
1486 v = tri2->verts[j].xyz;
1487 VectorAdd(v, brush->owner->origin, v);
1488 float x = v[0];
1489 float y = v[1];
1490 if (a) {
1491 float x2 = (((x - brush->owner->origin[0]) * c) - ((y - brush->owner->origin[1]) * s)) + brush->owner->origin[0];
1492 float y2 = (((x - brush->owner->origin[0]) * s) + ((y - brush->owner->origin[1]) * c)) + brush->owner->origin[1];
1493 x = x2;
1494 y = y2;
1495 }
1496 v[0] = x;
1497 v[1] = y;
1498 }
1499 tri2->verts[j].xyz = v;
1500 }
1501 tris->Append(tri2);
1502 mats->Append( surf->shader );
1503 }
1504 return model->NumSurfaces();
1505 }
1506 }
1507 return ret;
1508 }
1509
1510
1511 #define MAX_TRI_SURFACES 16384
Brush_ToTris(brush_t * brush,idTriList * tris,idMatList * mats,bool models,bool bmodel)1512 int Brush_ToTris(brush_t *brush, idTriList *tris, idMatList *mats, bool models, bool bmodel) {
1513 int i, j;
1514 srfTriangles_t *tri;
1515 //
1516 // patches
1517 //
1518 if (brush->modelHandle > 0 ) {
1519 if (!models) {
1520 return 0;
1521 } else {
1522 return Brush_TransformModel(brush, tris, mats);
1523 }
1524 }
1525
1526 int numSurfaces = 0;
1527
1528 if ( brush->owner->eclass->fixedsize && !brush->entityModel) {
1529 return NULL;
1530 }
1531
1532 if ( brush->pPatch ) {
1533 patchMesh_t *pm;
1534 int width, height;
1535
1536 pm = brush->pPatch;
1537
1538 // build a patch mesh
1539 idSurface_Patch *cp = new idSurface_Patch( pm->width * 6, pm->height * 6 );
1540 cp->SetSize( pm->width, pm->height );
1541 for ( i = 0; i < pm->width; i++ ) {
1542 for ( j = 0; j < pm->height; j++ ) {
1543 (*cp)[j*cp->GetWidth()+i].xyz = pm->ctrl(i, j).xyz;
1544 (*cp)[j*cp->GetWidth()+i].st = pm->ctrl(i, j).st;
1545 }
1546 }
1547
1548 // subdivide it
1549 if ( pm->explicitSubdivisions ) {
1550 cp->SubdivideExplicit( pm->horzSubdivisions, pm->vertSubdivisions, true );
1551 } else {
1552 cp->Subdivide( DEFAULT_CURVE_MAX_ERROR, DEFAULT_CURVE_MAX_ERROR, DEFAULT_CURVE_MAX_LENGTH, true );
1553 }
1554 width = cp->GetWidth();
1555 height = cp->GetHeight();
1556
1557 // convert to srfTriangles
1558 tri = R_AllocStaticTriSurf();
1559 tri->numVerts = width * height;
1560 tri->numIndexes = 6 * ( width - 1 ) * ( height - 1 );
1561 R_AllocStaticTriSurfVerts( tri, tri->numVerts );
1562 R_AllocStaticTriSurfIndexes( tri, tri->numIndexes );
1563 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1564 tri->verts[i] = (*cp)[i];
1565 if (bmodel) {
1566 tri->verts[i].xyz -= brush->owner->origin;
1567 }
1568 }
1569
1570 tri->numIndexes = 0;
1571 for ( i = 1 ; i < width ; i++ ) {
1572 for ( j = 1 ; j < height ; j++ ) {
1573 tri->indexes[tri->numIndexes++] = ( j - 1 ) * width + i;
1574 tri->indexes[tri->numIndexes++] = ( j - 1 ) * width + i - 1;
1575 tri->indexes[tri->numIndexes++] = j * width + i - 1;
1576
1577 tri->indexes[tri->numIndexes++] = j * width + i;
1578 tri->indexes[tri->numIndexes++] = ( j - 1 ) * width + i;
1579 tri->indexes[tri->numIndexes++] = j * width + i - 1;
1580 }
1581 }
1582
1583 delete cp;
1584
1585 tris->Append(tri);
1586 mats->Append(pm->d_texture);
1587 //surfaces[numSurfaces] = tri;
1588 //materials[numSurfaces] = pm->d_texture;
1589 return 1;
1590 }
1591
1592 //
1593 // normal brush
1594 //
1595 for ( face_t *face = brush->brush_faces ; face; face = face->next ) {
1596 idWinding *w;
1597
1598 w = face->face_winding;
1599 if (!w) {
1600 continue; // freed or degenerate face
1601 }
1602
1603 tri = R_AllocStaticTriSurf();
1604 tri->numVerts = w->GetNumPoints();
1605 tri->numIndexes = ( w->GetNumPoints() - 2 ) * 3;
1606 R_AllocStaticTriSurfVerts( tri, tri->numVerts );
1607 R_AllocStaticTriSurfIndexes( tri, tri->numIndexes );
1608
1609 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1610
1611 tri->verts[i].Clear();
1612
1613 tri->verts[i].xyz[0] = (*w)[i][0];
1614 tri->verts[i].xyz[1] = (*w)[i][1];
1615 tri->verts[i].xyz[2] = (*w)[i][2];
1616
1617 if ( bmodel ) {
1618 tri->verts[i].xyz -= brush->owner->origin;
1619 }
1620
1621 tri->verts[i].st[0] = (*w)[i][3];
1622 tri->verts[i].st[1] = (*w)[i][4];
1623
1624 tri->verts[i].normal = face->plane.Normal();
1625 }
1626
1627 tri->numIndexes = 0;
1628 for ( i = 2 ; i < w->GetNumPoints() ; i++ ) {
1629 tri->indexes[tri->numIndexes++] = 0;
1630 tri->indexes[tri->numIndexes++] = i-1;
1631 tri->indexes[tri->numIndexes++] = i;
1632 }
1633
1634 tris->Append(tri);
1635 mats->Append(face->d_texture);
1636 numSurfaces++;
1637 }
1638
1639 return numSurfaces;
1640 }
1641
Select_ToOBJ()1642 void Select_ToOBJ() {
1643 int i;
1644 CFileDialog dlgFile(FALSE, "obj", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Wavefront object files (*.obj)|*.obj||", g_pParentWnd);
1645 if (dlgFile.DoModal() == IDOK) {
1646 idTriList tris(1024);
1647 idMatList mats(1024);
1648
1649 for (brush_t *b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1650
1651 if ( b->hiddenBrush ) {
1652 continue;
1653 }
1654
1655 if (FilterBrush(b)) {
1656 continue;
1657 }
1658
1659 Brush_ToTris(b, &tris, &mats, true, false);
1660 }
1661
1662 Tris_ToOBJ(dlgFile.GetPathName().GetBuffer(0), &tris, &mats);
1663
1664 for( i = 0; i < tris.Num(); i++ ) {
1665 R_FreeStaticTriSurf( tris[i] );
1666 }
1667 tris.Clear();
1668 }
1669 }
1670
Select_ToCM()1671 void Select_ToCM() {
1672 CFileDialog dlgFile( FALSE, "lwo, ase", NULL, 0, "(*.lwo)|*.lwo|(*.ase)|*.ase|(*.ma)|*.ma||", g_pParentWnd );
1673
1674 if ( dlgFile.DoModal() == IDOK ) {
1675 idMapEntity *mapEnt;
1676 idMapPrimitive *p;
1677 idStr name;
1678
1679 name = fileSystem->OSPathToRelativePath( dlgFile.GetPathName() );
1680 name.BackSlashesToSlashes();
1681
1682 mapEnt = new idMapEntity();
1683 mapEnt->epairs.Set( "name", name.c_str() );
1684
1685 for ( brush_t *b = selected_brushes.next; b != &selected_brushes; b = b->next ) {
1686
1687 if ( b->hiddenBrush ) {
1688 continue;
1689 }
1690
1691 if ( FilterBrush( b ) ) {
1692 continue;
1693 }
1694
1695 p = BrushToMapPrimitive( b, b->owner->origin );
1696 if ( p ) {
1697 mapEnt->AddPrimitive( p );
1698 }
1699 }
1700
1701 collisionModelManager->WriteCollisionModelForMapEntity( mapEnt, name.c_str() );
1702
1703 delete mapEnt;
1704 }
1705 }
1706
1707
1708 /*
1709 =================
1710 BuildRendererState
1711
1712 Builds models, lightdefs, and modeldefs for the current editor data
1713 so it can be rendered by the game renderSystem
1714 =================
1715 */
BuildRendererState()1716 void CCamWnd::BuildRendererState() {
1717 renderEntity_t worldEntity;
1718 entity_t *ent;
1719 brush_t *brush;
1720
1721 FreeRendererState();
1722
1723 // the renderWorld holds all the references and defs
1724 g_qeglobals.rw->InitFromMap( NULL );
1725
1726 // create the raw model for all the brushes
1727 int numBrushes = 0;
1728 int numSurfaces = 0;
1729
1730 // the renderModel for the world holds all the geometry that isn't in an entity
1731 worldModel = renderModelManager->AllocModel();
1732 worldModel->InitEmpty( "EditorWorldModel" );
1733
1734 for ( brush_t *brushList = &active_brushes ; brushList ;
1735 brushList = (brushList == &active_brushes) ? &selected_brushes : NULL ) {
1736
1737 for (brush = brushList->next; brush != brushList; brush = brush->next) {
1738
1739 if ( brush->hiddenBrush ) {
1740 continue;
1741 }
1742
1743 if (FilterBrush(brush)) {
1744 continue;
1745 }
1746
1747 if (CullBrush(brush, true)) {
1748 continue;
1749 }
1750
1751 idTriList tris(1024);
1752 idMatList mats(1024);
1753
1754 if (!IsBModel(brush)) {
1755 numSurfaces += Brush_ToTris( brush, &tris, &mats, false, false );
1756 }
1757
1758 // add the surfaces to the renderModel
1759 modelSurface_t surf;
1760 for ( int i = 0 ; i < tris.Num() ; i++ ) {
1761 surf.geometry = tris[i];
1762 surf.shader = mats[i];
1763 worldModel->AddSurface( surf );
1764 }
1765
1766 numBrushes++;
1767 }
1768 }
1769
1770 // bound and clean the triangles
1771 worldModel->FinishSurfaces();
1772
1773 // the worldEntity just has the handle for the worldModel
1774 memset( &worldEntity, 0, sizeof( worldEntity ) );
1775 worldEntity.hModel = worldModel;
1776 worldEntity.axis = mat3_default;
1777 worldEntity.shaderParms[0] = 1;
1778 worldEntity.shaderParms[1] = 1;
1779 worldEntity.shaderParms[2] = 1;
1780 worldEntity.shaderParms[3] = 1;
1781
1782 worldModelDef = g_qeglobals.rw->AddEntityDef( &worldEntity );
1783
1784 // create the light and model entities exactly the way the game code would
1785 for ( ent = entities.next ; ent != &entities ; ent = ent->next ) {
1786 if ( ent->brushes.onext == &ent->brushes ) {
1787 continue;
1788 }
1789
1790 if (CullBrush(ent->brushes.onext, true)) {
1791 continue;
1792 }
1793
1794 if (Map_IsBrushFiltered(ent->brushes.onext)) {
1795 continue;
1796 }
1797
1798 BuildEntityRenderState( ent, false );
1799 }
1800
1801 //common->Printf("Render data used %d brushes\n", numBrushes);
1802 worldDirty = false;
1803 UpdateCaption();
1804 }
1805
1806 /*
1807 ===============================
1808 CCamWnd::UpdateRenderEntities
1809
1810 Creates a new entity state list
1811 returns true if a repaint is needed
1812 ===============================
1813 */
UpdateRenderEntities()1814 bool CCamWnd::UpdateRenderEntities() {
1815
1816 if (rebuildMode) {
1817 return false;
1818 }
1819
1820 bool ret = false;
1821 for ( entity_t *ent = entities.next ; ent != &entities ; ent = ent->next ) {
1822 BuildEntityRenderState( ent, (ent->lightDef != -1 || ent->modelDef != -1 || ent->soundEmitter ) ? true : false );
1823 if (ret == false && ent->modelDef || ent->lightDef) {
1824 ret = true;
1825 }
1826 }
1827 return ret;
1828 }
1829
1830 /*
1831 ============================
1832 CCamWnd::FreeRendererState
1833
1834 Frees the render state data
1835 ============================
1836 */
FreeRendererState()1837 void CCamWnd::FreeRendererState() {
1838
1839 for ( entity_t *ent = entities.next ; ent != &entities ; ent = ent->next ) {
1840 if (ent->lightDef >= 0) {
1841 g_qeglobals.rw->FreeLightDef( ent->lightDef );
1842 ent->lightDef = -1;
1843 }
1844
1845 if (ent->modelDef >= 0) {
1846 renderEntity_t *refent = const_cast<renderEntity_t *>(g_qeglobals.rw->GetRenderEntity( ent->modelDef ));
1847 if ( refent ) {
1848 if ( refent->callbackData ) {
1849 Mem_Free( refent->callbackData );
1850 refent->callbackData = NULL;
1851 }
1852 if ( refent->joints ) {
1853 Mem_Free16(refent->joints);
1854 refent->joints = NULL;
1855 }
1856 }
1857 g_qeglobals.rw->FreeEntityDef( ent->modelDef );
1858 ent->modelDef = -1;
1859 }
1860 }
1861
1862 if ( worldModel ) {
1863 renderModelManager->FreeModel( worldModel );
1864 worldModel = NULL;
1865 }
1866
1867 }
1868
1869
1870 /*
1871 ========================
1872 CCamWnd::UpdateCaption
1873
1874 updates the caption based on rendermode and whether the render mode needs updated
1875 ========================
1876 */
UpdateCaption()1877 void CCamWnd::UpdateCaption() {
1878
1879 idStr strCaption;
1880
1881 if (worldDirty) {
1882 strCaption = "*";
1883 }
1884 // FIXME:
1885 strCaption += (renderMode) ? "RENDER" : "CAM";
1886 if (renderMode) {
1887 strCaption += (rebuildMode) ? " (Realtime)" : "";
1888 strCaption += (entityMode) ? " +lights" : "";
1889 strCaption += (selectMode) ? " +selected" : "";
1890 strCaption += (animationMode) ? " +anim" : "";
1891 }
1892 strCaption += (soundMode) ? " +snd" : "";
1893 SetWindowText(strCaption);
1894 }
1895
1896 /*
1897 ===========================
1898 CCamWnd::ToggleRenderMode
1899
1900 Toggles the render mode
1901 ===========================
1902 */
ToggleRenderMode()1903 void CCamWnd::ToggleRenderMode() {
1904 renderMode ^= 1;
1905 UpdateCaption();
1906 }
1907
1908 /*
1909 ===========================
1910 CCamWnd::ToggleRebuildMode
1911
1912 Toggles the rebuild mode
1913 ===========================
1914 */
ToggleRebuildMode()1915 void CCamWnd::ToggleRebuildMode() {
1916 rebuildMode ^= 1;
1917 UpdateCaption();
1918 }
1919
1920 /*
1921 ===========================
1922 CCamWnd::ToggleEntityMode
1923
1924 Toggles the entity mode
1925 ===========================
1926 */
ToggleEntityMode()1927 void CCamWnd::ToggleEntityMode() {
1928 entityMode ^= 1;
1929 UpdateCaption();
1930 }
1931
1932
1933 /*
1934 ===========================
1935 CCamWnd::ToggleRenderMode
1936
1937 Toggles the render mode
1938 ===========================
1939 */
ToggleAnimationMode()1940 void CCamWnd::ToggleAnimationMode() {
1941 animationMode ^= 1;
1942 if (animationMode) {
1943 SetTimer(0, 10, NULL);
1944 } else {
1945 KillTimer(0);
1946 }
1947 UpdateCaption();
1948 }
1949
1950 /*
1951 ===========================
1952 CCamWnd::ToggleSoundMode
1953
1954 Toggles the sound mode
1955 ===========================
1956 */
ToggleSoundMode()1957 void CCamWnd::ToggleSoundMode() {
1958 soundMode ^= 1;
1959
1960 UpdateCaption();
1961
1962 for ( entity_t *ent = entities.next ; ent != &entities ; ent = ent->next ) {
1963 Entity_UpdateSoundEmitter( ent );
1964 }
1965 }
1966
1967 /*
1968 ===========================
1969 CCamWnd::ToggleRenderMode
1970
1971 Toggles the render mode
1972 ===========================
1973 */
ToggleSelectMode()1974 void CCamWnd::ToggleSelectMode() {
1975 selectMode ^= 1;
1976 UpdateCaption();
1977 }
1978
1979 /*
1980 =========================
1981 CCamWnd::MarkWorldDirty
1982
1983 marks the render world as dirty
1984 =========================
1985 */
MarkWorldDirty()1986 void CCamWnd::MarkWorldDirty() {
1987 worldDirty = true;
1988 UpdateCaption();
1989 }
1990
1991
1992 /*
1993 =========================
1994 CCamWnd::DrawEntityData
1995
1996 Draws entity data ( experimental )
1997 =========================
1998 */
1999 extern void glBox(idVec4 &color, idVec3 &point, float size);
2000
DrawEntityData()2001 void CCamWnd::DrawEntityData() {
2002
2003 qglMatrixMode( GL_MODELVIEW );
2004 qglLoadIdentity();
2005 qglMatrixMode( GL_PROJECTION );
2006 qglLoadIdentity();
2007
2008 SetProjectionMatrix();
2009
2010 qglRotatef(-90, 1, 0, 0); // put Z going up
2011 qglRotatef(90, 0, 0, 1); // put Z going up
2012 qglRotatef(m_Camera.angles[0], 0, 1, 0);
2013 qglRotatef(-m_Camera.angles[1], 0, 0, 1);
2014 qglTranslatef(-m_Camera.origin[0], -m_Camera.origin[1], -m_Camera.origin[2]);
2015
2016 Cam_BuildMatrix();
2017
2018 if (!(entityMode || selectMode)) {
2019 return;
2020 }
2021
2022 qglDisable(GL_BLEND);
2023 qglDisable(GL_DEPTH_TEST);
2024 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2025 globalImages->BindNull();
2026 idVec3 color(0, 1, 0);
2027 qglColor3fv( color.ToFloatPtr() );
2028
2029 brush_t *brushList = &active_brushes;
2030 int pass = 0;
2031 while (brushList) {
2032 for (brush_t *brush = brushList->next; brush != brushList; brush = brush->next) {
2033
2034 if (CullBrush(brush, true)) {
2035 continue;
2036 }
2037
2038 if (FilterBrush(brush)) {
2039 continue;
2040 }
2041
2042 if ((pass == 1 && selectMode) || (entityMode && pass == 0 && brush->owner->lightDef >= 0)) {
2043 Brush_DrawXY(brush, 0, true, true);
2044 }
2045
2046 }
2047 brushList = (brushList == &active_brushes) ? &selected_brushes : NULL;
2048 color.x = 1;
2049 color.y = 0;
2050 pass++;
2051 qglColor3fv( color.ToFloatPtr() );
2052 }
2053
2054 }
2055
2056
2057 /*
2058 =======================================================================================================================
2059 Cam_Render
2060
2061 This used the renderSystem to draw a fully lit view of the world
2062 =======================================================================================================================
2063 */
Cam_Render()2064 void CCamWnd::Cam_Render() {
2065
2066 renderView_t refdef;
2067 CPaintDC dc(this); // device context for painting
2068
2069
2070 if (!active_brushes.next) {
2071 return; // not valid yet
2072 }
2073
2074 // DG: from SteelStorm2
2075 // Jmarshal23 recommended to disable this to fix lighting render in the Cam window
2076 /* if (!qwglMakeCurrent(dc.m_hDC, win32.hGLRC)) {
2077 common->Printf("ERROR: wglMakeCurrent failed..\n ");
2078 common->Printf("Please restart " EDITOR_WINDOWTEXT " if the camera view is not working\n");
2079 return;
2080 } */
2081
2082 // save the editor state
2083 //qglPushAttrib( GL_ALL_ATTRIB_BITS );
2084 qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
2085 qglScissor( 0, 0, m_Camera.width, m_Camera.height );
2086 qglClear( GL_COLOR_BUFFER_BIT );
2087
2088 // qwglSwapBuffers(dc.m_hDC);
2089
2090 // create the model, using explicit normals
2091 if ( rebuildMode && worldDirty ) {
2092 BuildRendererState();
2093 }
2094
2095 // render it
2096 renderSystem->BeginFrame( m_Camera.width, m_Camera.height );
2097
2098 memset( &refdef, 0, sizeof( refdef ) );
2099 refdef.vieworg = m_Camera.origin;
2100
2101 // the editor uses opposite pitch convention
2102 refdef.viewaxis = idAngles( -m_Camera.angles.pitch, m_Camera.angles.yaw, m_Camera.angles.roll ).ToMat3();
2103
2104 refdef.width = SCREEN_WIDTH;
2105 refdef.height = SCREEN_HEIGHT;
2106 refdef.fov_x = 90;
2107 refdef.fov_y = 2 * atan((float)m_Camera.height / m_Camera.width) * idMath::M_RAD2DEG;
2108
2109 // only set in animation mode to give a consistent look
2110 if (animationMode) {
2111 refdef.time = eventLoop->Milliseconds();
2112 }
2113
2114 g_qeglobals.rw->RenderScene( &refdef );
2115
2116 int frontEnd, backEnd;
2117
2118 renderSystem->EndFrame( &frontEnd, &backEnd );
2119 //common->Printf( "front:%i back:%i\n", frontEnd, backEnd );
2120
2121 //qglPopAttrib();
2122 //DrawEntityData();
2123
2124 //qwglSwapBuffers(dc.m_hDC);
2125 // get back to the editor state
2126 qglMatrixMode( GL_MODELVIEW );
2127 qglLoadIdentity();
2128 Cam_BuildMatrix();
2129 }
2130
2131
OnTimer(UINT nIDEvent)2132 void CCamWnd::OnTimer(UINT nIDEvent)
2133 {
2134 if (animationMode || nIDEvent == 1) {
2135 Sys_UpdateWindows(W_CAMERA);
2136 }
2137 if (nIDEvent == 1) {
2138 KillTimer(1);
2139 }
2140
2141 if (!animationMode ) {
2142 KillTimer(0);
2143 }
2144 }
2145
2146
UpdateCameraView()2147 void CCamWnd::UpdateCameraView() {
2148 if (QE_SingleBrush(true, true)) {
2149 brush_t *b = selected_brushes.next;
2150 if (b->owner->eclass->nShowFlags & ECLASS_CAMERAVIEW) {
2151 // find the entity that targets this
2152 const char *name = ValueForKey(b->owner, "name");
2153 entity_t *ent = FindEntity("target", name);
2154 if (ent) {
2155 if (!saveValid) {
2156 saveOrg = m_Camera.origin;
2157 saveAng = m_Camera.angles;
2158 saveValid = true;
2159 }
2160 idVec3 v = b->owner->origin - ent->origin;
2161 v.Normalize();
2162 idAngles ang = v.ToMat3().ToAngles();
2163 ang.pitch = -ang.pitch;
2164 ang.roll = 0.0f;
2165 SetView( ent->origin, ang );
2166 Cam_BuildMatrix();
2167 Sys_UpdateWindows( W_CAMERA );
2168 return;
2169 }
2170 }
2171 }
2172 if (saveValid) {
2173 SetView(saveOrg, saveAng);
2174 Cam_BuildMatrix();
2175 Sys_UpdateWindows(W_CAMERA);
2176 saveValid = false;
2177 }
2178 }
2179