2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 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.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 // Leonardo Zide (leo@lokigames.com)
32 extern void DrawPathLines();
33 extern void Select_ShiftTexture( int x, int y );
34 extern void Select_RotateTexture( int amt );
35 extern void DrawAlternatePoint( vec3_t v, float scale );
36 //extern void Select_ScaleTexture(int x, int y);
38 extern int g_nPatchClickedView;
40 brush_t* g_pSplitList = NULL;
42 // =============================================================================
46 : GLWindow( TRUE ), m_XORRectangle( m_pWidget ){
47 m_nNumTransBrushes = 0;
48 memset( &m_Camera, 0, sizeof( camera_t ) );
49 m_pSide_select = NULL;
58 void CamWnd::OnCreate(){
59 if ( !MakeCurrent() ) {
60 Error( "glMakeCurrent failed" );
63 // report OpenGL information
64 Sys_Printf( "GL_VENDOR: %s\n", qglGetString( GL_VENDOR ) );
65 Sys_Printf( "GL_RENDERER: %s\n", qglGetString( GL_RENDERER ) );
66 Sys_Printf( "GL_VERSION: %s\n", qglGetString( GL_VERSION ) );
67 Sys_Printf( "GL_EXTENSIONS: %s\n", qglGetString( GL_EXTENSIONS ) );
69 // Set off texture compression supported
70 g_qeglobals.bTextureCompressionSupported = 0;
72 // finalize OpenGL init
74 // why is this here? well .. the Gtk objects get constructed when you enter gtk_main
75 // and I wanted to have the extensions information in the editor startup console (avoid looking that up in the early console)
77 // I Split this up so as to add support for extension and user-friendly
78 // compression format selection.
79 // ADD new globals for your new format so as to minimise
80 // calls to Sys_QGL_ExtensionSupported
81 // NOTE TTimo: I don't really like this approach with globals. Frequent calls to Sys_QGL_ExtensionSupported don't sound like
82 // a problem to me. If there is some caching to be done, then I think it should be inside Sys_QGL_ExtensionSupported
83 ///////////////////////////////////////////
84 // Check for default OpenGL
85 if ( Sys_QGL_ExtensionSupported( "GL_ARB_texture_compression" ) ) {
86 g_qeglobals.bTextureCompressionSupported = 1;
87 g_qeglobals.m_bOpenGLCompressionSupported = 1;
90 // INSERT PROPRIETARY EXTENSIONS HERE
91 // Check for S3 extensions
92 // create a bool global for extension supported
93 if ( Sys_QGL_ExtensionSupported( "GL_EXT_texture_compression_s3tc" ) ) {
94 g_qeglobals.bTextureCompressionSupported = 1;
95 g_qeglobals.m_bS3CompressionSupported = 1;
98 g_qeglobals.m_bOpenGLReady = true;
100 g_PrefsDlg.UpdateTextureCompression();
103 g_PrefsDlg.UpdateATIHack();
106 g_qeglobals_gui.d_camera = m_pWidget;
109 void CamWnd::Cam_Init(){
110 m_Camera.timing = false;
111 m_Camera.origin[0] = 0.f;
112 m_Camera.origin[1] = 20.f;
113 m_Camera.origin[2] = 46.f;
114 m_Camera.color[0] = 0.3f;
115 m_Camera.color[1] = 0.3f;
116 m_Camera.color[2] = 0.3f;
117 m_nCambuttonstate = 0;
120 void CamWnd::OnSize( int cx, int cy ){
122 m_Camera.height = cy;
123 gtk_widget_queue_draw( m_pWidget );
126 rectangle_t rectangle_from_area_cam(){
127 const float left = MIN( g_qeglobals.d_vAreaTL[0], g_qeglobals.d_vAreaBR[0] );
128 const float top = MAX( g_qeglobals.d_vAreaTL[1], g_qeglobals.d_vAreaBR[1] );
129 const float right = MAX( g_qeglobals.d_vAreaTL[0], g_qeglobals.d_vAreaBR[0] );
130 const float bottom = MIN( g_qeglobals.d_vAreaTL[1], g_qeglobals.d_vAreaBR[1] );
131 return rectangle_t( left, bottom, right - left, top - bottom );
134 void update_xor_rectangle( XORRectangle& xor_rectangle ){
135 rectangle_t rectangle;
136 if ( ( g_qeglobals.d_select_mode == sel_area ) ) {
137 rectangle = rectangle_from_area_cam();
139 xor_rectangle.set( rectangle );
142 void CamWnd::OnMouseMove( guint32 flags, int pointx, int pointy ){
143 int height = m_pWidget->allocation.height;
144 // NOTE RR2DO2 this hasn't got any use anymore really. It is an old qeradiant feature
145 // that can be re-enabled by removing the checks for HasCapture and not shift/ctrl down
146 // but the scaling/rotating (unless done with the steps set in the surface inspector
147 // dialog) is way too sensitive to be of any use
148 if ( HasCapture() && Sys_AltDown() &&
149 !( ( flags & MK_SHIFT ) || ( flags & MK_CONTROL ) ) ) {
150 if ( flags & MK_CONTROL ) {
151 Select_RotateTexture( pointy - m_ptLastCursorY );
154 if ( flags & MK_SHIFT ) {
155 Select_ScaleTexture( pointx - m_ptLastCursorX, m_ptLastCursorY - pointy );
158 Select_ShiftTexture( pointx - m_ptLastCursorX, m_ptLastCursorY - pointy );
163 Cam_MouseMoved( pointx, height - 1 - pointy, flags );
165 m_ptLastCursorX = pointx;
166 m_ptLastCursorY = pointy;
168 update_xor_rectangle( m_XORRectangle );
171 void CamWnd::OnMouseWheel( bool bUp ){
173 VectorMA( m_Camera.origin, g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, m_Camera.origin );
176 VectorMA( m_Camera.origin, -g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, m_Camera.origin );
179 int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
180 Sys_UpdateWindows( nUpdate );
181 g_pParentWnd->OnTimer();
184 void CamWnd::OnLButtonDown( guint32 nFlags, int pointx, int pointy ){
185 m_ptLastCursorX = pointx;
186 m_ptLastCursorY = pointy;
187 OriginalMouseDown( nFlags, pointx, pointy );
190 void CamWnd::OnLButtonUp( guint32 nFlags, int pointx, int pointy ){
191 OriginalMouseUp( nFlags, pointx, pointy );
194 void CamWnd::OnMButtonDown( guint32 nFlags, int pointx, int pointy ){
195 OriginalMouseDown( nFlags, pointx, pointy );
198 void CamWnd::OnMButtonUp( guint32 nFlags, int pointx, int pointy ){
199 OriginalMouseUp( nFlags, pointx, pointy );
202 void CamWnd::OnRButtonDown( guint32 nFlags, int pointx, int pointy ){
203 OriginalMouseDown( nFlags, pointx, pointy );
206 void CamWnd::OnRButtonUp( guint32 nFlags, int pointx, int pointy ){
207 OriginalMouseUp( nFlags, pointx, pointy );
210 void CamWnd::OriginalMouseUp( guint32 nFlags, int pointx, int pointy ){
211 int height = m_pWidget->allocation.height;
213 if ( g_qeglobals.d_select_mode == sel_facets_on || g_qeglobals.d_select_mode == sel_facets_off ) {
214 g_qeglobals.d_select_mode = sel_brush;
217 Cam_MouseUp( pointx, height - 1 - pointy, nFlags );
220 update_xor_rectangle( m_XORRectangle );
223 void CamWnd::OriginalMouseDown( guint32 nFlags, int pointx, int pointy ){
224 int height = m_pWidget->allocation.height;
228 Cam_MouseDown( pointx, height - 1 - pointy, nFlags );
230 update_xor_rectangle( m_XORRectangle );
233 void CamWnd::Cam_BuildMatrix(){
238 if ( !m_bFreeMove ) {
239 ya = m_Camera.angles[1] / 180 * Q_PI;
241 // the movement matrix is kept 2d
242 m_Camera.forward[0] = cos( ya );
243 m_Camera.forward[1] = sin( ya );
244 m_Camera.forward[2] = 0;
245 m_Camera.right[0] = m_Camera.forward[1];
246 m_Camera.right[1] = -m_Camera.forward[0];
250 AngleVectors( m_Camera.angles, m_Camera.forward, m_Camera.right, NULL );
251 m_Camera.forward[2] = -m_Camera.forward[2];
254 memcpy( matrix, m_Camera.projection, sizeof( m4x4_t ) );
255 m4x4_multiply_by_m4x4( &matrix[0][0], &m_Camera.modelview[0][0] );
257 //qglGetFloatv (GL_PROJECTION_MATRIX, &matrix[0][0]);
259 for ( i = 0 ; i < 3 ; i++ )
261 m_Camera.vright[i] = matrix[i][0];
262 m_Camera.vup[i] = matrix[i][1];
263 m_Camera.vpn[i] = matrix[i][2];
266 VectorNormalize( m_Camera.vright, m_Camera.vright );
267 VectorNormalize( m_Camera.vup, m_Camera.vup );
268 VectorNormalize( m_Camera.vpn, m_Camera.vpn );
271 void CamWnd::Cam_ChangeFloor( qboolean up ){
273 float d, bestd, current;
276 start[0] = m_Camera.origin[0];
277 start[1] = m_Camera.origin[1];
278 start[2] = g_MaxWorldCoord;
282 current = g_MaxWorldCoord - ( m_Camera.origin[2] - 48 );
287 bestd = 2 * g_MaxWorldCoord;
290 for ( b = active_brushes.next ; b != &active_brushes ; b = b->next )
292 if ( !Brush_Ray( start, dir, b, &d ) ) {
295 if ( up && d < current && d > bestd ) {
298 if ( !up && d > current && d < bestd ) {
303 if ( bestd == 0 || bestd == 2 * g_MaxWorldCoord ) {
307 m_Camera.origin[2] += current - bestd;
308 Sys_UpdateWindows( W_CAMERA | W_Z_OVERLAY );
311 void CamWnd::Cam_PositionDrag(){
314 Sys_GetCursorPos( &x, &y );
315 if ( x != m_ptCursorX || y != m_ptCursorY ) {
317 VectorMA( m_Camera.origin, x, m_Camera.vright, m_Camera.origin );
319 m_Camera.origin[2] -= y;
320 Sys_SetCursorPos( m_ptCursorX, m_ptCursorY );
321 Sys_UpdateWindows( W_CAMERA | W_XY_OVERLAY );
325 void CamWnd::Cam_MouseControl( float dtime ){
326 Cam_KeyControl( dtime );
328 if ( g_PrefsDlg.m_bCamFreeLook ) {
332 if ( !m_bFreeMove || m_nCambuttonstate == MK_CONTROL ) {
337 Sys_GetCursorPos( &m_ptCursorX, &m_ptCursorY );
339 dx = m_ptLastCamCursorX - m_ptCursorX;
340 dy = m_ptLastCamCursorY - m_ptCursorY;
342 gdk_window_get_origin( m_pWidget->window, &x, &y );
344 m_ptLastCamCursorX = x + ( m_Camera.width / 2 );
345 m_ptLastCamCursorY = y + ( m_Camera.height / 2 );
347 Sys_SetCursorPos( m_ptLastCamCursorX, m_ptLastCamCursorY );
350 if ( !g_PrefsDlg.m_bCamFreeLookStrafe ) {
351 if ( g_PrefsDlg.m_bCamInverseMouse ) {
352 m_Camera.angles[PITCH] -= dy * dtime * g_PrefsDlg.m_nAngleSpeed;
355 m_Camera.angles[PITCH] += dy * dtime * g_PrefsDlg.m_nAngleSpeed;
359 VectorMA( m_Camera.origin, dy * (float) ( g_PrefsDlg.m_nMoveSpeed / 6.0f ), m_Camera.forward, m_Camera.origin );
362 m_Camera.angles[YAW] += dx * dtime * g_PrefsDlg.m_nAngleSpeed;
364 if ( m_Camera.angles[PITCH] > 90 ) {
365 m_Camera.angles[PITCH] = 90;
367 else if ( m_Camera.angles[PITCH] < -90 ) {
368 m_Camera.angles[PITCH] = -90;
371 if ( m_Camera.angles[YAW] >= 360 ) {
372 m_Camera.angles[YAW] = 0;
374 else if ( m_Camera.angles[YAW] <= -360 ) {
375 m_Camera.angles[YAW] = 0;
378 if ( dx || dy || m_Camera.movementflags ) {
379 int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
380 Sys_UpdateWindows( nUpdate );
381 g_pParentWnd->OnTimer();
390 if ( g_PrefsDlg.m_nMouseButtons == 2 ) {
391 if ( m_nCambuttonstate != ( MK_RBUTTON | MK_SHIFT ) ) {
397 if ( m_nCambuttonstate != MK_RBUTTON ) {
402 xf = (float)( m_ptButtonX - m_Camera.width / 2 ) / ( m_Camera.width / 2 );
403 yf = (float)( m_ptButtonY - m_Camera.height / 2 ) / ( m_Camera.height / 2 );
405 xl = m_Camera.width / 3;
407 yl = m_Camera.height / 3;
410 xf *= 1.0 - fabs( yf );
425 VectorMA( m_Camera.origin, yf * dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, m_Camera.origin );
426 m_Camera.angles[YAW] += xf * -dtime * g_PrefsDlg.m_nAngleSpeed;
428 int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
429 Sys_UpdateWindows( nUpdate );
430 g_pParentWnd->OnTimer();
434 void CamWnd::Cam_KeyControl( float dtime ) {
437 if ( m_Camera.movementflags & MOVE_ROTLEFT ) {
438 m_Camera.angles[YAW] += 15 * dtime * g_PrefsDlg.m_nAngleSpeed;
440 if ( m_Camera.movementflags & MOVE_ROTRIGHT ) {
441 m_Camera.angles[YAW] -= 15 * dtime * g_PrefsDlg.m_nAngleSpeed;
445 if ( m_Camera.movementflags & MOVE_FORWARD ) {
446 VectorMA( m_Camera.origin, dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, m_Camera.origin );
448 if ( m_Camera.movementflags & MOVE_BACK ) {
449 VectorMA( m_Camera.origin, -dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, m_Camera.origin );
451 if ( m_Camera.movementflags & MOVE_STRAFELEFT ) {
452 VectorMA( m_Camera.origin, -dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.right, m_Camera.origin );
454 if ( m_Camera.movementflags & MOVE_STRAFERIGHT ) {
455 VectorMA( m_Camera.origin, dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.right, m_Camera.origin );
458 // Save a screen update (when m_bFreeMove is enabled, mousecontrol does the update)
459 if ( !m_bFreeMove && m_Camera.movementflags ) {
460 int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
461 Sys_UpdateWindows( nUpdate );
462 g_pParentWnd->OnTimer();
466 // NOTE TTimo if there's an OS-level focus out of the application
467 // then we can release the camera cursor grab
468 static gint camwindow_focusout( GtkWidget* widget, GdkEventKey* event, gpointer data ){
469 g_pParentWnd->GetCamWnd()->ToggleFreeMove();
473 void CamWnd::ToggleFreeMove(){
477 m_bFreeMove = !m_bFreeMove;
478 Camera()->movementflags = 0;
479 m_ptLastCamCursorX = m_ptCursorX;
480 m_ptLastCamCursorY = m_ptCursorY;
482 if ( g_pParentWnd->CurrentStyle() == MainFrame::eFloating ) {
483 widget = g_pParentWnd->GetCamWnd()->m_pParent;
484 window = widget->window;
488 widget = g_pParentWnd->m_pWidget;
489 window = widget->window;
500 char buffer [( 32 * 32 ) / 8];
501 memset( buffer, 0, ( 32 * 32 ) / 8 );
502 GdkColor white = {0, 0xffff, 0xffff, 0xffff};
503 GdkColor black = {0, 0x0000, 0x0000, 0x0000};
504 pixmap = gdk_bitmap_create_from_data( NULL, buffer, 32, 32 );
505 mask = gdk_bitmap_create_from_data( NULL, buffer, 32, 32 );
506 GdkCursor *cursor = gdk_cursor_new_from_pixmap( pixmap, mask, &white, &black, 1, 1 );
508 gdk_window_set_cursor( window, cursor );
509 gdk_cursor_unref( cursor );
510 gdk_drawable_unref( pixmap );
511 gdk_drawable_unref( mask );
514 // RR2DO2: FIXME why does this only work the 2nd and
515 // further times the event is called? (floating windows
516 // mode seems to work fine though...)
517 m_FocusOutHandler_id = gtk_signal_connect( GTK_OBJECT( widget ), "focus_out_event",
518 GTK_SIGNAL_FUNC( camwindow_focusout ), g_pParentWnd );
521 GdkEventMask mask = (GdkEventMask)( GDK_POINTER_MOTION_MASK
522 | GDK_POINTER_MOTION_HINT_MASK
523 | GDK_BUTTON_MOTION_MASK
524 | GDK_BUTTON1_MOTION_MASK
525 | GDK_BUTTON2_MOTION_MASK
526 | GDK_BUTTON3_MOTION_MASK
527 | GDK_BUTTON_PRESS_MASK
528 | GDK_BUTTON_RELEASE_MASK );
530 gdk_pointer_grab( widget->window, TRUE, mask, widget->window, NULL, GDK_CURRENT_TIME );
535 gdk_pointer_ungrab( GDK_CURRENT_TIME );
537 gtk_signal_disconnect( GTK_OBJECT( widget ), m_FocusOutHandler_id );
539 GdkCursor *cursor = gdk_cursor_new( GDK_LEFT_PTR );
540 gdk_window_set_cursor( window, cursor );
541 gdk_cursor_unref( cursor );
546 int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
547 Sys_UpdateWindows( nUpdate );
548 g_pParentWnd->OnTimer();
551 void CamWnd::Cam_MouseDown( int x, int y, int buttons ){
558 // calc ray direction
560 u = (float)( y - ( m_Camera.height * .5f ) ) / ( m_Camera.width * .5f );
561 r = (float)( x - ( m_Camera.width * .5f ) ) / ( m_Camera.width * .5f );
564 for ( i = 0 ; i < 3 ; i++ )
565 dir[i] = m_Camera.vpn[i] * f + m_Camera.vright[i] * r + m_Camera.vup[i] * u;
566 VectorNormalize( dir, dir );
568 Sys_GetCursorPos( &m_ptCursorX, &m_ptCursorY );
570 m_nCambuttonstate = buttons;
574 // LBUTTON = manipulate selection
575 // shift-LBUTTON = select
576 // middle button = grab texture
577 // ctrl-middle button = set entire brush to texture
578 // ctrl-shift-middle button = set single face to texture
579 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
580 if ( ( buttons == MK_LBUTTON )
581 || ( buttons == ( MK_LBUTTON | MK_SHIFT ) )
582 || ( buttons == ( MK_LBUTTON | MK_CONTROL ) )
583 || ( buttons == ( MK_LBUTTON | MK_CONTROL | MK_SHIFT ) )
584 || ( buttons == nMouseButton )
585 || ( buttons == ( nMouseButton | MK_SHIFT ) )
586 || ( buttons == ( nMouseButton | MK_CONTROL ) )
587 || ( buttons == ( nMouseButton | MK_SHIFT | MK_CONTROL ) ) ) {
588 if ( g_PrefsDlg.m_nMouseButtons == 2 && ( buttons == ( MK_RBUTTON | MK_SHIFT ) ) ) {
589 if ( g_PrefsDlg.m_bCamFreeLook ) {
593 Cam_MouseControl( 0.1f );
598 // something global needs to track which window is responsible for stuff
599 Patch_SetView( W_CAMERA );
600 Drag_Begin( x, y, buttons, m_Camera.vright, m_Camera.vup, m_Camera.origin, dir, true );
605 if ( buttons == MK_RBUTTON ) {
606 if ( g_PrefsDlg.m_bCamFreeLook ) {
610 Cam_MouseControl( 0.1f );
616 void CamWnd::Cam_MouseUp( int x, int y, int buttons ){
617 m_nCambuttonstate = 0;
618 Drag_MouseUp( buttons );
621 void CamWnd::Cam_MouseMoved( int x, int y, int buttons ){
622 m_nCambuttonstate = buttons;
627 if ( g_PrefsDlg.m_nCamDragMultiSelect ) {
628 if ( g_qeglobals.d_select_mode == sel_brush_on || g_qeglobals.d_select_mode == sel_brush_off ) {
629 bool bDoDragMultiSelect = FALSE;
631 if ( g_PrefsDlg.m_nCamDragMultiSelect == 1 && buttons == ( MK_LBUTTON | MK_SHIFT ) ) {
632 bDoDragMultiSelect = TRUE;
634 else if ( g_PrefsDlg.m_nCamDragMultiSelect == 2 && buttons == ( MK_LBUTTON | MK_CONTROL ) && Sys_AltDown() ) {
635 bDoDragMultiSelect = TRUE;
638 if ( bDoDragMultiSelect ) {
644 // calc ray direction
646 u = (float)( y - ( m_Camera.height * .5f ) ) / ( m_Camera.width * .5f );
647 r = (float)( x - ( m_Camera.width * .5f ) ) / ( m_Camera.width * .5f );
650 for ( i = 0 ; i < 3 ; i++ )
651 dir[i] = m_Camera.vpn[i] * f + m_Camera.vright[i] * r + m_Camera.vup[i] * u;
652 VectorNormalize( dir,dir );
654 switch ( g_qeglobals.d_select_mode )
657 Select_Ray( m_Camera.origin, dir, ( SF_DRAG_ON | SF_CAMERA ) );
661 Select_Ray( m_Camera.origin, dir, ( SF_DRAG_OFF | SF_CAMERA ) );
670 else if ( g_qeglobals.d_select_mode == sel_facets_on || g_qeglobals.d_select_mode == sel_facets_off ) {
671 if ( buttons == ( MK_LBUTTON | MK_CONTROL | MK_SHIFT ) ) {
677 // calc ray direction
679 u = (float)( y - ( m_Camera.height * .5f ) ) / ( m_Camera.width * .5f );
680 r = (float)( x - ( m_Camera.width * .5f ) ) / ( m_Camera.width * .5f );
683 for ( i = 0 ; i < 3 ; i++ )
684 dir[i] = m_Camera.vpn[i] * f + m_Camera.vright[i] * r + m_Camera.vup[i] * u;
685 VectorNormalize( dir,dir );
687 switch ( g_qeglobals.d_select_mode )
690 Select_Ray( m_Camera.origin, dir, ( SF_SINGLEFACE | SF_DRAG_ON | SF_CAMERA ) );
694 Select_Ray( m_Camera.origin, dir, ( SF_SINGLEFACE | SF_DRAG_OFF | SF_CAMERA ) );
708 if ( ( m_bFreeMove && ( buttons & MK_CONTROL ) && !( buttons & MK_SHIFT ) ) || ( !m_bFreeMove && ( buttons == ( MK_RBUTTON | MK_CONTROL ) ) ) ) {
710 Sys_UpdateWindows( W_XY | W_CAMERA | W_Z );
714 Sys_GetCursorPos( &m_ptCursorX, &m_ptCursorY );
716 if ( buttons & ( MK_LBUTTON | MK_MBUTTON ) ) {
717 Drag_MouseMoved( x, y, buttons );
718 if ( g_qeglobals.d_select_mode != sel_area ) {
719 Sys_UpdateWindows( W_XY | W_CAMERA | W_Z );
724 void CamWnd::InitCull(){
727 VectorSubtract( m_Camera.vpn, m_Camera.vright, m_vCull1 );
728 VectorAdd( m_Camera.vpn, m_Camera.vright, m_vCull2 );
730 for ( i = 0 ; i < 3 ; i++ )
732 if ( m_vCull1[i] > 0 ) {
733 m_nCullv1[i] = 3 + i;
738 if ( m_vCull2[i] > 0 ) {
739 m_nCullv2[i] = 3 + i;
747 qboolean CamWnd::CullBrush( brush_t *b ){
752 if ( g_PrefsDlg.m_bCubicClipping ) {
753 float fLevel = g_PrefsDlg.m_nCubicScale * 64;
755 point[0] = m_Camera.origin[0] - fLevel;
756 point[1] = m_Camera.origin[1] - fLevel;
757 point[2] = m_Camera.origin[2] - fLevel;
759 for ( i = 0; i < 3; i++ )
760 if ( b->mins[i] < point[i] && b->maxs[i] < point[i] ) {
764 point[0] = m_Camera.origin[0] + fLevel;
765 point[1] = m_Camera.origin[1] + fLevel;
766 point[2] = m_Camera.origin[2] + fLevel;
768 for ( i = 0; i < 3; i++ )
769 if ( b->mins[i] > point[i] && b->maxs[i] > point[i] ) {
774 for ( i = 0 ; i < 3 ; i++ )
775 point[i] = b->mins[m_nCullv1[i]] - m_Camera.origin[i];
777 d = DotProduct( point, m_vCull1 );
782 for ( i = 0 ; i < 3 ; i++ )
783 point[i] = b->mins[m_nCullv2[i]] - m_Camera.origin[i];
785 d = DotProduct( point, m_vCull2 );
793 // project a 3D point onto the camera space
794 // we use the GL viewing matrixes
795 // this is the implementation of a glu function (I realized that afterwards): gluProject
796 void CamWnd::ProjectCamera( const vec3_t A, vec_t B[2] ){
798 vec_t P1[4],P2[4],P3[4];
799 VectorCopy( A,P1 ); P1[3] = 1;
801 GLMatMul( m_Camera.modelview, P1, P2 );
802 GLMatMul( m_Camera.projection, P2, P3 );
804 // we ASSUME that the view port is 0 0 m_Camera.width m_Camera.height (you can check in Cam_Draw)
805 B[0] = (float)m_Camera.width * ( P3[0] + 1.0 ) / 2.0;
806 B[1] = (float)m_Camera.height * ( P3[1] + 1.0 ) / 2.0;
810 // vec defines a direction in geometric space and P an origin point
811 // the user is interacting from the camera view
812 // (for example with texture adjustment shortcuts)
813 // and intuitively if he hits left / right / up / down
814 // what happens in geometric space should match the left/right/up/down move in camera space
815 // axis = 0: vec is along left/right
816 // axis = 1: vec is along up/down
817 // sgn = +1: same directions
818 // sgn = -1: opposite directions
820 // typical use case is giving a face center and a normalized vector
821 // 1) compute start and endpoint, project them in camera view, get the direction
822 // depending on the situation, we might bump into precision issues with that
823 // 2) possible to compute the projected direction independently?
824 // this solution would be better but right now I don't see how to do it..
825 void CamWnd::MatchViewAxes( const vec3_t P, const vec3_t vec, int &axis, float &sgn ){
827 vec_t A[2],B[2],V[2];
828 ProjectCamera( P,A );
830 VectorAdd( P,vec,Q );
831 ProjectCamera( Q,B );
832 // V is the vector projected in camera space
835 if ( fabs( V[0] ) > fabs( V[1] ) ) {
836 // best match is against right
847 // best match is against up
859 void CamWnd::DrawLightRadius( brush_t* pBrush ){
861 int nRadius = Brush_LightRadius( pBrush );
863 Brush_SetLightColor( pBrush );
864 qglEnable( GL_BLEND );
865 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
866 qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
867 qglDisable( GL_TEXTURE_2D );
869 qglEnable( GL_TEXTURE_2D );
870 qglDisable( GL_BLEND );
871 qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
876 extern void DrawPatchMesh( patchMesh_t *pm );
877 extern void DrawPatchControls( patchMesh_t *pm );
878 extern void Brush_DrawFacingAngle( brush_t *b, entity_t *e );
879 extern void Brush_DrawModel( brush_t *b, bool bTextured = false );
880 extern void DrawModelOrigin( brush_t *b );
881 extern void DrawModelBBox( brush_t *b );
883 void CamWnd::Cam_DrawBrush( brush_t *b, int mode ){
884 int nGLState = m_Camera.draw_glstate;
885 int nModelMode = g_PrefsDlg.m_nEntityShowState;
887 GLfloat material[4], identity[4];
888 VectorSet( identity, 0.8f, 0.8f, 0.8f );
892 if ( b->owner->eclass->fixedsize && b->owner->eclass->nShowFlags & ECLASS_LIGHT && g_PrefsDlg.m_bNewLightDraw ) {
896 VectorCopy( b->owner->color, material );
897 VectorScale( material, 0.8f, material );
900 qglColor4fv( material );
902 if ( g_PrefsDlg.m_bNewLightDraw ) {
903 DrawLight( b->owner, nGLState, ( IsBrushSelected( b ) ) ? g_PrefsDlg.m_nLightRadiuses : 0, 0 );
911 else if ( b->owner->eclass->fixedsize && b->owner->model.pRender
912 && !( !IsBrushSelected( b ) && ( nModelMode & ENTITY_SELECTED_ONLY ) ) ) {
916 if ( !( nModelMode & ENTITY_WIREFRAME ) && nModelMode != ENTITY_BOX ) {
917 VectorCopy( b->owner->eclass->color, material );
918 material[3] = identity[3] = 1.0f;
920 qglEnable( GL_CULL_FACE );
922 if ( !( nGLState & DRAW_GL_TEXTURE_2D ) ) {
923 qglColor4fv( material );
925 else{ qglColor4fv( identity ); }
926 if ( nGLState & DRAW_GL_LIGHTING ) {
927 qglShadeModel( GL_SMOOTH );
930 b->owner->model.pRender->Draw( nGLState, DRAW_RF_CAM );
934 VectorCopy( b->owner->eclass->color, material );
936 qglColor4fv( material );
938 // model view mode "wireframe" or "selected wire"
939 if ( nModelMode & ENTITY_WIREFRAME ) {
940 b->owner->model.pRender->Draw( nGLState, DRAW_RF_CAM );
943 // model view mode "skinned and boxed"
944 if ( !( b->owner->eclass->nShowFlags & ECLASS_MISCMODEL ) ) {
945 qglColor4fv( material );
946 aabb_draw( b->owner->model.pRender->GetAABB(), DRAW_GL_WIRE );
948 else if ( nModelMode & ENTITY_BOXED ) {
949 aabb_draw( b->owner->model.pRender->GetAABB(), DRAW_GL_WIRE );
952 if(!(nModelMode & ENTITY_BOXED) && b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
959 else if ( b->patchBrush ) {
960 bool bTrans = ( b->pPatch->pShader->getTrans() < 1.0f );
964 if ( !g_bPatchWireFrame && ( ( nGLState & DRAW_GL_BLEND && bTrans ) || ( !( nGLState & DRAW_GL_BLEND ) && !bTrans ) ) ) {
965 qglDisable( GL_CULL_FACE );
967 pShader = b->pPatch->pShader;
968 VectorCopy( pShader->getTexture()->color, material );
969 material[3] = identity[3] = pShader->getTrans();
971 if ( nGLState & DRAW_GL_TEXTURE_2D ) {
972 qglColor4fv( identity );
973 qglBindTexture( GL_TEXTURE_2D, pShader->getTexture()->texture_number );
976 qglColor4fv( material );
978 if ( nGLState & DRAW_GL_LIGHTING ) {
979 qglShadeModel( GL_SMOOTH );
982 DrawPatchMesh( b->pPatch );
986 if ( g_bPatchWireFrame ) {
987 VectorCopy( b->pPatch->pShader->getTexture()->color, material );
989 qglColor4fv( material );
990 DrawPatchMesh( b->pPatch );
992 if ( b->pPatch->bSelected && ( g_qeglobals.d_select_mode == sel_curvepoint
993 || g_qeglobals.d_select_mode == sel_area
994 || g_bPatchBendMode ) ) {
995 DrawPatchControls( b->pPatch );
1001 else if ( b->owner->eclass->fixedsize ) {
1005 VectorCopy( b->owner->eclass->color, material );
1006 VectorScale( material, 0.8f, material );
1008 qglColor4fv( material );
1010 qglEnable( GL_CULL_FACE );
1011 qglShadeModel( GL_FLAT );
1015 if ( ( g_qeglobals.d_savedinfo.include & INCLUDE_ANGLES )
1016 && ( b->owner->eclass->nShowFlags & ECLASS_ANGLE ) ) {
1017 Brush_DrawFacingAngle( b, b->owner );
1028 qglEnable( GL_CULL_FACE );
1029 qglShadeModel( GL_FLAT );
1035 void CamWnd::Cam_DrawBrushes( int mode ){
1037 brush_t *pList = ( g_bClipMode && g_pSplitList ) ? g_pSplitList : &selected_brushes;
1039 for ( b = active_brushes.next; b != &active_brushes; b = b->next )
1040 if ( !b->bFiltered && !b->bCamCulled ) {
1041 Cam_DrawBrush( b, mode );
1043 for ( b = pList->next; b != pList; b = b->next )
1044 if ( !b->bFiltered && !b->bCamCulled ) {
1045 Cam_DrawBrush( b, mode );
1049 void CamWnd::Cam_DrawStuff(){
1050 GLfloat identity[4];
1051 VectorSet( identity, 0.8f, 0.8f, 0.8f );
1054 for ( b = active_brushes.next; b != &active_brushes; b = b->next )
1055 b->bCamCulled = CullBrush( b );
1057 for ( b = selected_brushes.next; b != &selected_brushes; b = b->next )
1058 b->bCamCulled = CullBrush( b );
1060 switch ( m_Camera.draw_mode )
1063 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1064 qglDisable( GL_TEXTURE_2D );
1065 qglDisable( GL_TEXTURE_1D );
1066 qglDisable( GL_BLEND );
1067 qglEnable( GL_DEPTH_TEST );
1068 qglEnableClientState( GL_VERTEX_ARRAY );
1069 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1070 qglShadeModel( GL_FLAT );
1071 if ( g_PrefsDlg.m_bGLLighting ) {
1072 qglDisable( GL_LIGHTING );
1073 qglDisable( GL_COLOR_MATERIAL );
1074 qglDisableClientState( GL_NORMAL_ARRAY );
1076 m_Camera.draw_glstate = DRAW_GL_WIRE;
1080 qglCullFace( GL_FRONT );
1081 qglEnable( GL_CULL_FACE );
1082 qglShadeModel( GL_FLAT );
1083 qglPolygonMode( GL_FRONT, GL_LINE );
1084 qglPolygonMode( GL_BACK, GL_FILL );
1085 qglDisable( GL_TEXTURE_2D );
1086 qglDisable( GL_BLEND );
1087 qglEnable( GL_DEPTH_TEST );
1088 qglEnableClientState( GL_VERTEX_ARRAY );
1089 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1090 qglPolygonOffset( -1.0, 2 );
1091 if ( g_PrefsDlg.m_bGLLighting ) {
1092 qglEnable( GL_LIGHTING );
1093 qglEnable( GL_COLOR_MATERIAL );
1094 // qglEnable(GL_RESCALE_NORMAL);
1095 qglEnableClientState( GL_NORMAL_ARRAY );
1097 m_Camera.draw_glstate = DRAW_GL_SOLID;
1101 qglCullFace( GL_FRONT );
1102 qglEnable( GL_CULL_FACE );
1103 qglShadeModel( GL_FLAT );
1104 qglPolygonMode( GL_FRONT, GL_LINE );
1105 qglPolygonMode( GL_BACK, GL_FILL );
1106 qglEnable( GL_TEXTURE_2D );
1107 qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
1108 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1109 qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1110 qglDisable( GL_BLEND );
1111 qglEnable( GL_DEPTH_TEST );
1112 qglEnableClientState( GL_VERTEX_ARRAY );
1113 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1114 if ( g_PrefsDlg.m_bGLLighting ) {
1115 qglEnable( GL_LIGHTING );
1116 qglDisable( GL_COLOR_MATERIAL );
1117 qglMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, identity );
1118 qglEnableClientState( GL_NORMAL_ARRAY );
1119 // qglEnable(GL_RESCALE_NORMAL);
1121 qglPolygonOffset( -1.0, 2 );
1122 m_Camera.draw_glstate = DRAW_GL_TEXTURED;
1125 default: Sys_Printf( "CamWnd::Cam_DrawStuff:invalid render mode\n" );
1128 Cam_DrawBrushes( DRAW_TEXTURED );
1130 // setup for solid stuff
1131 switch ( m_Camera.draw_mode )
1134 qglDisable( GL_TEXTURE_2D );
1135 m_Camera.draw_glstate &= ~DRAW_GL_TEXTURE_2D;
1136 if ( g_PrefsDlg.m_bGLLighting ) {
1137 qglEnable( GL_COLOR_MATERIAL );
1139 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1145 default: Sys_Printf( "CamWnd::Cam_DrawStuff:invalid render mode\n" );
1148 qglEnable( GL_CULL_FACE );
1149 qglShadeModel( GL_FLAT );
1150 Cam_DrawBrushes( DRAW_SOLID );
1152 // setup for wireframe stuff
1153 switch ( m_Camera.draw_mode )
1156 if ( g_PrefsDlg.m_bGLLighting ) {
1157 qglDisable( GL_LIGHTING );
1158 qglDisable( GL_COLOR_MATERIAL );
1159 qglDisableClientState( GL_NORMAL_ARRAY );
1160 // qglDisable(GL_RESCALE_NORMAL);
1162 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1165 if ( g_PrefsDlg.m_bGLLighting ) {
1166 qglDisable( GL_LIGHTING );
1167 qglDisable( GL_COLOR_MATERIAL );
1168 qglDisableClientState( GL_NORMAL_ARRAY );
1169 // qglDisable(GL_RESCALE_NORMAL);
1171 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1175 default: Sys_Printf( "CamWnd::Cam_DrawStuff:invalid render mode\n" );
1178 qglDisable( GL_CULL_FACE );
1179 Cam_DrawBrushes( DRAW_WIRE );
1181 // setup for transparent texture stuff
1182 switch ( m_Camera.draw_mode )
1185 qglPolygonMode( GL_FRONT, GL_LINE );
1186 qglPolygonMode( GL_BACK, GL_FILL );
1187 if ( g_PrefsDlg.m_bGLLighting ) {
1188 qglEnable( GL_COLOR_MATERIAL );
1189 qglEnableClientState( GL_NORMAL_ARRAY );
1190 qglMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, identity );
1192 qglEnable( GL_TEXTURE_2D );
1193 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1194 m_Camera.draw_glstate = DRAW_GL_TEXTURED;
1197 qglPolygonMode( GL_FRONT, GL_LINE );
1198 qglPolygonMode( GL_BACK, GL_FILL );
1199 if ( g_PrefsDlg.m_bGLLighting ) {
1200 qglEnable( GL_LIGHTING );
1201 qglEnable( GL_COLOR_MATERIAL );
1202 qglEnableClientState( GL_NORMAL_ARRAY );
1203 // qglEnable(GL_RESCALE_NORMAL);
1205 m_Camera.draw_glstate = DRAW_GL_SOLID;
1208 m_Camera.draw_glstate = DRAW_GL_WIRE;
1210 default: Sys_Printf( "CamWnd::Cam_DrawStuff:invalid render mode\n" );
1214 qglEnable( GL_BLEND );
1215 m_Camera.draw_glstate |= DRAW_GL_BLEND;
1216 qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1217 // FIXME: some .TGA are buggy, have a completely empty alpha channel
1218 // if such brushes are rendered in this loop they would be totally transparent with GL_MODULATE
1219 // so I decided using GL_DECAL instead
1220 // if an empty-alpha-channel or nearly-empty texture is used. It will be blank-transparent.
1221 // this could get better if you can get qglTexEnviv (GL_TEXTURE_ENV, to work .. patches are welcome
1222 // Arnout: empty alpha channels are now always filled with data. Don't set this anymore (would cause problems with qer_alphafunc too)
1223 // qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1225 Cam_DrawBrushes( DRAW_TEXTURED );
1227 // qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1228 qglDisable( GL_BLEND );
1230 // setup for wireframe stuff
1231 switch ( m_Camera.draw_mode )
1234 if ( g_PrefsDlg.m_bGLLighting ) {
1235 qglDisable( GL_COLOR_MATERIAL );
1236 qglDisable( GL_LIGHTING );
1237 // qglDisable(GL_RESCALE_NORMAL);
1241 if ( g_PrefsDlg.m_bGLLighting ) {
1242 qglDisable( GL_COLOR_MATERIAL );
1243 qglDisable( GL_LIGHTING );
1244 // qglDisable(GL_RESCALE_NORMAL);
1249 default: Sys_Printf( "CamWnd::Cam_DrawStuff:invalid render mode\n" );
1263 void CamWnd::Cam_Draw(){
1268 double start = 0.0, end;
1271 if ( !active_brushes.next ) {
1272 return; // not valid yet
1275 if ( m_Camera.timing ) {
1276 start = Sys_DoubleTime();
1282 QE_CheckOpenGLForErrors();
1284 qglViewport( 0, 0, m_Camera.width, m_Camera.height );
1285 qglClearColor( g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][0],
1286 g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][1],
1287 g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][2], 0 );
1288 qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1295 qglMatrixMode( GL_PROJECTION );
1298 screenaspect = (float)m_Camera.width / m_Camera.height;
1299 yfov = 2 * atan( (float)m_Camera.height / m_Camera.width ) * 180 / Q_PI;
1300 qgluPerspective( yfov, screenaspect, 8, 32768 );
1302 // we're too lazy to calc projection matrix ourselves!!!
1303 qglGetFloatv( GL_PROJECTION_MATRIX, &m_Camera.projection[0][0] );
1307 m4x4_identity( &m_Camera.modelview[0][0] );
1308 VectorSet( vec, -90, 0, 0 );
1309 m4x4_rotate_by_vec3( &m_Camera.modelview[0][0], vec, eXYZ );
1310 VectorSet( vec, 0, 0, 90 );
1311 m4x4_rotate_by_vec3( &m_Camera.modelview[0][0], vec, eXYZ );
1312 VectorSet( vec, 0, m_Camera.angles[0], 0 );
1313 m4x4_rotate_by_vec3( &m_Camera.modelview[0][0], vec, eXYZ );
1314 VectorSet( vec, 0, 0, -m_Camera.angles[1] );
1315 m4x4_rotate_by_vec3( &m_Camera.modelview[0][0], vec, eXYZ );
1316 VectorSet( vec, -m_Camera.origin[0], -m_Camera.origin[1], -m_Camera.origin[2] );
1317 m4x4_translate_by_vec3( &m_Camera.modelview[0][0], vec );
1321 qglMatrixMode( GL_MODELVIEW );
1324 qglMultMatrixf( &m_Camera.modelview[0][0] );
1326 // grab the GL_PROJECTION and GL_MODELVIEW matrixes
1327 // used in GetRelativeAxes
1328 //qglGetFloatv (GL_PROJECTION_MATRIX, &m_Camera.projection[0][0]);
1329 //qglGetFloatv (GL_MODELVIEW_MATRIX, &m_Camera.modelview[0][0]);
1332 // TTimo: this is not used, just for verification (0, 0, m_Camera.width, m_Camera.height)
1334 qglGetIntegerv( GL_VIEWPORT, viewprt );
1337 if ( g_PrefsDlg.m_bGLLighting ) {
1338 GLfloat inverse_cam_dir[4], ambient[4], diffuse[4]; //, material[4];
1340 ambient[0] = ambient[1] = ambient[2] = 0.6f;
1342 diffuse[0] = diffuse[1] = diffuse[2] = 0.4f;
1344 //material[0] = material[1] = material[2] = 0.8f;
1345 //material[3] = 1.0f;
1347 vec3_t vCam, vRotate;
1348 VectorSet( vCam, -1, 0, 0 ); //default cam pos
1349 VectorSet( vRotate, 0, -m_Camera.angles[0], 0 );
1350 VectorRotate( vCam, vRotate, vCam );
1351 VectorSet( vRotate, 0, 0, m_Camera.angles[1] );
1352 VectorRotate( vCam, vRotate, vCam );
1354 inverse_cam_dir[0] = vCam[0];
1355 inverse_cam_dir[1] = vCam[1];
1356 inverse_cam_dir[2] = vCam[2];
1357 inverse_cam_dir[3] = 0;
1359 qglColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
1361 qglLightfv( GL_LIGHT0, GL_POSITION, inverse_cam_dir );
1363 qglLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
1364 qglLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
1366 qglEnable( GL_LIGHT0 );
1377 qglEnableClientState( GL_VERTEX_ARRAY );
1378 qglDisableClientState( GL_NORMAL_ARRAY );
1379 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1380 qglDisable( GL_TEXTURE_2D );
1381 qglDisable( GL_LIGHTING );
1382 qglDisable( GL_COLOR_MATERIAL );
1384 qglEnable( GL_CULL_FACE );
1386 brush_t* pList = ( g_bClipMode && g_pSplitList ) ? g_pSplitList : &selected_brushes;
1388 if ( g_qeglobals.d_savedinfo.iSelectedOutlinesStyle & OUTLINE_BSEL ) {
1389 qglColor4f( g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES3D][0], g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES3D][1], g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES3D][2], 0.3f );
1390 qglEnable( GL_BLEND );
1391 qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1392 qglDepthFunc( GL_LEQUAL );
1393 for ( brush = pList->next ; brush != pList ; brush = brush->next )
1395 if ( brush->bCamCulled ) { // draw selected faces of filtered brushes to remind that there is a selection
1399 if ( brush->patchBrush && ( g_qeglobals.d_select_mode == sel_curvepoint || g_qeglobals.d_select_mode == sel_area ) ) {
1403 if ( !g_PrefsDlg.m_bPatchBBoxSelect && brush->patchBrush ) {
1404 DrawPatchMesh( brush->pPatch );
1406 else if ( brush->owner->model.pRender && g_PrefsDlg.m_nEntityShowState != ENTITY_BOX ) {
1407 brush->owner->model.pRender->Draw( DRAW_GL_FLAT, ( DRAW_RF_SEL_OUTLINE | DRAW_RF_CAM ) );
1411 for ( face = brush->brush_faces ; face ; face = face->next )
1412 Brush_FaceDraw( face, DRAW_GL_FLAT );
1417 int nCount = g_ptrSelectedFaces.GetSize();
1419 for ( int i = 0; i < nCount; i++ )
1421 face_t *selFace = reinterpret_cast<face_t*>( g_ptrSelectedFaces.GetAt( i ) );
1422 Brush_FaceDraw( selFace, DRAW_GL_FLAT );
1426 qglDisableClientState( GL_NORMAL_ARRAY );
1427 qglDepthFunc( GL_LESS );
1430 if ( g_qeglobals.d_savedinfo.iSelectedOutlinesStyle & OUTLINE_ZBUF ) {
1431 // non-zbuffered outline
1432 qglDisable( GL_BLEND );
1433 qglDisable( GL_DEPTH_TEST );
1434 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1435 qglColor3f( 1, 1, 1 );
1436 for ( brush = pList->next ; brush != pList ; brush = brush->next )
1438 if ( ( brush->patchBrush && ( g_qeglobals.d_select_mode == sel_curvepoint || g_qeglobals.d_select_mode == sel_area ) ) ) {
1442 if ( !g_PrefsDlg.m_bPatchBBoxSelect && brush->patchBrush ) {
1443 DrawPatchMesh( brush->pPatch );
1445 else if ( brush->owner->model.pRender && g_PrefsDlg.m_nEntityShowState != ENTITY_BOX ) {
1446 brush->owner->model.pRender->Draw( DRAW_GL_WIRE, ( DRAW_RF_SEL_FILL | DRAW_RF_CAM ) );
1448 // Hydra : always draw bbox outline!
1449 aabb_draw( brush->owner->model.pRender->GetAABB(), DRAW_GL_WIRE );
1453 for ( face = brush->brush_faces ; face ; face = face->next )
1454 Brush_FaceDraw( face, DRAW_GL_WIRE );
1459 // edge / vertex flags
1460 if ( g_qeglobals.d_select_mode == sel_vertex ) {
1461 // GL_POINTS on Kyro Workaround
1462 if ( !g_PrefsDlg.m_bGlPtWorkaround ) {
1465 qglColor3f( 0,1,0 );
1466 qglBegin( GL_POINTS );
1467 for ( i = 0 ; i < g_qeglobals.d_numpoints ; i++ )
1468 qglVertex3fv( g_qeglobals.d_points[i] );
1471 if ( g_qeglobals.d_num_move_points ) {
1472 // selected brush verts
1474 qglColor3f( 0,0,1 );
1475 qglBegin( GL_POINTS );
1476 for ( i = 0; i < g_qeglobals.d_num_move_points; i++ )
1477 qglVertex3fv( g_qeglobals.d_move_points[i] );
1486 qglColor3f( 0,1,0 );
1487 qglLineWidth( 2.0 );
1488 qglBegin( GL_LINES );
1489 for ( i = 0; i < g_qeglobals.d_numpoints; i++ )
1490 DrawAlternatePoint( g_qeglobals.d_points[i], 1.5 );
1493 if ( g_qeglobals.d_num_move_points ) {
1494 // selected brush verts
1495 qglColor3f( 0,0,1 );
1496 qglLineWidth( 3.0 );
1497 qglBegin( GL_LINES );
1498 for ( i = 0; i < g_qeglobals.d_num_move_points; i++ )
1499 qglVertex3fv( g_qeglobals.d_move_points[i] );
1502 qglLineWidth( 1.0 );
1505 else if ( g_qeglobals.d_select_mode == sel_edge ) {
1507 // GL_POINTS on Kyro Workaround
1508 if ( !g_PrefsDlg.m_bGlPtWorkaround ) {
1510 qglColor3f( 0,0,1 );
1511 qglBegin( GL_POINTS );
1512 for ( i = 0 ; i < g_qeglobals.d_numedges ; i++ )
1514 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
1515 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
1516 qglVertex3f( ( v1[0] + v2[0] ) * 0.5,( v1[1] + v2[1] ) * 0.5,( v1[2] + v2[2] ) * 0.5 );
1522 qglColor3f( 0,0,1 );
1523 qglLineWidth( 2.0 );
1524 qglBegin( GL_LINES );
1525 for ( i = 0; i < g_qeglobals.d_numedges; i++ )
1527 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
1528 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
1530 v3[0] = ( v1[0] + v2[0] ) * 0.5;
1531 v3[1] = ( v1[1] + v2[1] ) * 0.5;
1532 v3[2] = ( v1[2] + v2[2] ) * 0.5;
1533 DrawAlternatePoint( v3, 1.5 );
1536 qglLineWidth( 1.0 );
1543 qglEnable( GL_DEPTH_TEST );
1546 if ( g_qeglobals.d_pointfile_display_list ) {
1550 // call the drawing routine of plugin entities
1551 //++timo FIXME: we might need to hook in other places as well for transparency etc.
1552 //++timo FIXME: also needs a way to get some parameters about the view
1553 //++timo FIXME: maybe provide some culling API on Radiant side?
1554 Draw3DPluginEntities();
1556 // draw the crosshair
1557 if ( m_bFreeMove ) {
1558 // setup orthographic projection mode
1559 qglMatrixMode( GL_PROJECTION );
1562 qglDisable( GL_DEPTH_TEST );
1563 qglOrtho( 0, (float)m_Camera.width, 0, (float)m_Camera.height, -100, 100 );
1564 qglScalef( 1, -1, 1 );
1565 qglTranslatef( 0, -(float)m_Camera.height, 0 );
1566 qglMatrixMode( GL_MODELVIEW );
1571 qglColor3f( 1.f, 1.f, 1.f );
1572 qglBegin( GL_LINES );
1573 qglVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f + 6 );
1574 qglVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f + 2 );
1575 qglVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f - 6 );
1576 qglVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f - 2 );
1577 qglVertex2f( (float)m_Camera.width / 2.f + 6, (float)m_Camera.height / 2.f );
1578 qglVertex2f( (float)m_Camera.width / 2.f + 2, (float)m_Camera.height / 2.f );
1579 qglVertex2f( (float)m_Camera.width / 2.f - 6, (float)m_Camera.height / 2.f );
1580 qglVertex2f( (float)m_Camera.width / 2.f - 2, (float)m_Camera.height / 2.f );
1584 // reset perspective projection
1585 //qglMatrixMode(GL_PROJECTION);
1587 //qglMatrixMode(GL_MODELVIEW);
1591 if ( ( g_qeglobals.d_select_mode == sel_area ) && ( g_nPatchClickedView == W_CAMERA ) ) {
1592 // setup orthographic projection mode
1593 qglMatrixMode( GL_PROJECTION );
1596 qglDisable( GL_DEPTH_TEST );
1597 qglOrtho( 0, (float)m_Camera.width, 0, (float)m_Camera.height, -100, 100 );
1598 //qglScalef(1, -1, 1);
1599 //qglTranslatef(0, -(float)m_Camera.height, 0);
1600 qglMatrixMode( GL_MODELVIEW );
1602 // area selection hack
1604 qglDisable( GL_CULL_FACE );
1605 qglEnable( GL_BLEND );
1606 qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
1607 qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1608 qglColor4f( 0.0, 0.0, 1.0, 0.25 );
1609 qglRectf( g_qeglobals.d_vAreaTL[0], g_qeglobals.d_vAreaTL[1], g_qeglobals.d_vAreaBR[0], g_qeglobals.d_vAreaBR[1] );
1610 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1611 qglDisable( GL_BLEND );
1612 qglEnable( GL_CULL_FACE );
1616 // bind back to the default texture so that we don't have problems
1617 // elsewhere using/modifying texture maps between contexts
1618 qglBindTexture( GL_TEXTURE_2D, 0 );
1621 QE_CheckOpenGLForErrors();
1623 if ( m_Camera.timing ) {
1624 end = Sys_DoubleTime();
1625 Sys_Printf( "Camera: %i ms\n", (int)( 1000 * ( end - start ) ) );
1628 for ( brush = active_brushes.next ; brush != &active_brushes ; brush = brush->next )
1629 brush->bCamCulled = false;
1631 for ( brush = pList->next ; brush != pList ; brush = brush->next )
1632 brush->bCamCulled = false;
1635 void CamWnd::OnExpose(){
1636 if ( !MakeCurrent() ) {
1637 Sys_Printf( "ERROR: glXMakeCurrent failed..\n " );
1638 Sys_Printf( "Please restart Radiant if the camera view is not working\n" );
1642 QE_CheckOpenGLForErrors();
1643 g_pSplitList = NULL;
1644 if ( g_bClipMode ) {
1645 if ( g_Clip1.Set() && g_Clip2.Set() ) {
1646 g_pSplitList = ( g_bSwitch ) ?
1647 &g_brBackSplits : &g_brFrontSplits;
1651 Patch_LODMatchAll(); // spog
1654 QE_CheckOpenGLForErrors();
1656 m_XORRectangle.set( rectangle_t() );
1661 void CamWnd::BenchMark(){
1662 if ( !MakeCurrent() ) {
1663 Error( "glXMakeCurrent failed in Benchmark" );
1666 qglDrawBuffer( GL_FRONT );
1667 double dStart = Sys_DoubleTime();
1668 for ( int i = 0 ; i < 100 ; i++ )
1670 m_Camera.angles[YAW] = i * 4;
1674 qglDrawBuffer( GL_BACK );
1675 double dEnd = Sys_DoubleTime();
1676 Sys_Printf( "%5.2f seconds\n", dEnd - dStart );