/* =========================================================================== Copyright (C) 1997-2006 Id Software, Inc. This file is part of Quake 2 Tools source code. Quake 2 Tools source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake 2 Tools source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Quake 2 Tools source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "qe3.h" #define PAGEFLIPS 2 void DrawPathLines (void); camera_t camera; /* ============ Cam_Init ============ */ void Cam_Init (void) { // camera.draw_mode = cd_texture; // camera.draw_mode = cd_solid; // camera.draw_mode = cd_wire; camera.timing = false; camera.origin[0] = 0; camera.origin[1] = 20; camera.origin[2] = 46; camera.color[0] = 0.3; camera.color[1] = 0.3; camera.color[2] = 0.3; } //============================================================================ void Cam_BuildMatrix (void) { float xa, ya; float matrix[4][4]; int i; xa = camera.angles[0]/180*Q_PI; ya = camera.angles[1]/180*Q_PI; // the movement matrix is kept 2d camera.forward[0] = cos(ya); camera.forward[1] = sin(ya); camera.right[0] = camera.forward[1]; camera.right[1] = -camera.forward[0]; glGetFloatv (GL_PROJECTION_MATRIX, &matrix[0][0]); for (i=0 ; i<3 ; i++) { camera.vright[i] = matrix[i][0]; camera.vup[i] = matrix[i][1]; camera.vpn[i] = matrix[i][2]; } VectorNormalize (camera.vright); VectorNormalize (camera.vup); VectorNormalize (camera.vpn); } //=============================================== /* =============== Cam_ChangeFloor =============== */ void Cam_ChangeFloor (qboolean up) { brush_t *b; float d, bestd, current; vec3_t start, dir; start[0] = camera.origin[0]; start[1] = camera.origin[1]; start[2] = 8192; dir[0] = dir[1] = 0; dir[2] = -1; current = 8192 - (camera.origin[2] - 48); if (up) bestd = 0; else bestd = 16384; for (b=active_brushes.next ; b != &active_brushes ; b=b->next) { if (!Brush_Ray (start, dir, b, &d)) continue; if (up && d < current && d > bestd) bestd = d; if (!up && d > current && d < bestd) bestd = d; } if (bestd == 0 || bestd == 16384) return; camera.origin[2] += current - bestd; Sys_UpdateWindows (W_CAMERA|W_Z_OVERLAY); } //=============================================== int cambuttonstate; static int buttonx, buttony; static int cursorx, cursory; face_t *side_select; #define ANGLE_SPEED 300 #define MOVE_SPEED 400 /* ================ Cam_PositionDrag ================ */ void Cam_PositionDrag (void) { int x, y; Sys_GetCursorPos (&x, &y); if (x != cursorx || y != cursory) { x -= cursorx; VectorMA (camera.origin, x, camera.vright, camera.origin); y -= cursory; camera.origin[2] -= y; Sys_SetCursorPos (cursorx, cursory); Sys_UpdateWindows (W_CAMERA | W_XY_OVERLAY); } } /* =============== Cam_MouseControl =============== */ void Cam_MouseControl (float dtime) { int xl, xh; int yl, yh; float xf, yf; if (cambuttonstate != MK_RBUTTON) return; xf = (float)(buttonx - camera.width/2) / (camera.width/2); yf = (float)(buttony - camera.height/2) / (camera.height/2); xl = camera.width/3; xh = xl*2; yl = camera.height/3; yh = yl*2; #if 0 // strafe if (buttony < yl && (buttonx < xl || buttonx > xh)) VectorMA (camera.origin, xf*dtime*MOVE_SPEED, camera.right, camera.origin); else #endif { xf *= 1.0 - fabs(yf); if (xf < 0) { xf += 0.1; if (xf > 0) xf = 0; } else { xf -= 0.1; if (xf < 0) xf = 0; } VectorMA (camera.origin, yf*dtime*MOVE_SPEED, camera.forward, camera.origin); camera.angles[YAW] += xf*-dtime*ANGLE_SPEED; } Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); } /* ============== Cam_MouseDown ============== */ void Cam_MouseDown (int x, int y, int buttons) { vec3_t dir; float f, r, u; int i; // // calc ray direction // u = (float)(y - camera.height/2) / (camera.width/2); r = (float)(x - camera.width/2) / (camera.width/2); f = 1; for (i=0 ; i<3 ; i++) dir[i] = camera.vpn[i] * f + camera.vright[i] * r + camera.vup[i] * u; VectorNormalize (dir); Sys_GetCursorPos (&cursorx, &cursory); cambuttonstate = buttons; buttonx = x; buttony = y; // LBUTTON = manipulate selection // shift-LBUTTON = select // middle button = grab texture // ctrl-middle button = set entire brush to texture // ctrl-shift-middle button = set single face to texture if ( (buttons == MK_LBUTTON) || (buttons == (MK_LBUTTON | MK_SHIFT)) || (buttons == (MK_LBUTTON | MK_CONTROL)) || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) || (buttons == MK_MBUTTON) || (buttons == (MK_MBUTTON|MK_CONTROL)) || (buttons == (MK_MBUTTON|MK_SHIFT|MK_CONTROL)) ) { Drag_Begin (x, y, buttons, camera.vright, camera.vup, camera.origin, dir); return; } if (buttons == MK_RBUTTON) { Cam_MouseControl (0.1); return; } } /* ============== Cam_MouseUp ============== */ void Cam_MouseUp (int x, int y, int buttons) { cambuttonstate = 0; Drag_MouseUp (); } /* ============== Cam_MouseMoved ============== */ void Cam_MouseMoved (int x, int y, int buttons) { cambuttonstate = buttons; if (!buttons) return; buttonx = x; buttony = y; if (buttons == (MK_RBUTTON|MK_CONTROL) ) { Cam_PositionDrag (); Sys_UpdateWindows (W_XY|W_CAMERA|W_Z); return; } Sys_GetCursorPos (&cursorx, &cursory); if (buttons & (MK_LBUTTON | MK_MBUTTON) ) { Drag_MouseMoved (x, y, buttons); Sys_UpdateWindows (W_XY|W_CAMERA|W_Z); } } vec3_t cull1, cull2; int cullv1[3], cullv2[3]; void InitCull (void) { int i; VectorSubtract (camera.vpn, camera.vright, cull1); VectorAdd (camera.vpn, camera.vright, cull2); for (i=0 ; i<3 ; i++) { if (cull1[i] > 0) cullv1[i] = 3+i; else cullv1[i] = i; if (cull2[i] > 0) cullv2[i] = 3+i; else cullv2[i] = i; } } qboolean CullBrush (brush_t *b) { int i; vec3_t point; float d; for (i=0 ; i<3 ; i++) point[i] = b->mins[cullv1[i]] - camera.origin[i]; d = DotProduct (point, cull1); if (d < -1) return true; for (i=0 ; i<3 ; i++) point[i] = b->mins[cullv2[i]] - camera.origin[i]; d = DotProduct (point, cull2); if (d < -1) return true; return false; } /* ============== Cam_Draw ============== */ void Cam_Draw (void) { brush_t *brush; face_t *face; float screenaspect; float yfov; double start, end; int i; if (!active_brushes.next) return; // not valid yet if (camera.timing) start = Sys_DoubleTime (); // // clear // QE_CheckOpenGLForErrors(); glViewport(0, 0, camera.width, camera.height); glScissor(0, 0, camera.width, camera.height); glClearColor ( 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); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // // set up viewpoint // glMatrixMode(GL_PROJECTION); glLoadIdentity (); screenaspect = (float)camera.width/camera.height; yfov = 2*atan((float)camera.height/camera.width)*180/Q_PI; gluPerspective (yfov, screenaspect, 2, 8192); glRotatef (-90, 1, 0, 0); // put Z going up glRotatef (90, 0, 0, 1); // put Z going up glRotatef (camera.angles[0], 0, 1, 0); glRotatef (-camera.angles[1], 0, 0, 1); glTranslatef (-camera.origin[0], -camera.origin[1], -camera.origin[2]); Cam_BuildMatrix (); InitCull (); // // draw stuff // switch (camera.draw_mode) { case cd_wire: glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_1D); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glColor3f(1.0, 1.0, 1.0); // glEnable (GL_LINE_SMOOTH); break; case cd_solid: glCullFace(GL_FRONT); glEnable(GL_CULL_FACE); glShadeModel (GL_FLAT); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthFunc (GL_LEQUAL); break; case cd_texture: glCullFace(GL_FRONT); glEnable(GL_CULL_FACE); glShadeModel (GL_FLAT); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthFunc (GL_LEQUAL); #if 0 { GLfloat fogColor[4] = {0.0, 1.0, 0.0, 0.25}; glFogi (GL_FOG_MODE, GL_LINEAR); glHint (GL_FOG_HINT, GL_NICEST); /* per pixel */ glFogf (GL_FOG_START, -8192); glFogf (GL_FOG_END, 65536); glFogfv (GL_FOG_COLOR, fogColor); } #endif break; case cd_blend: glCullFace(GL_FRONT); glEnable(GL_CULL_FACE); glShadeModel (GL_FLAT); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glDisable(GL_DEPTH_TEST); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; } glMatrixMode(GL_TEXTURE); for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next) { if (CullBrush (brush)) continue; if (FilterBrush (brush)) continue; Brush_Draw( brush ); } glMatrixMode(GL_PROJECTION); // // now draw selected brushes // glTranslatef (g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]); glMatrixMode(GL_TEXTURE); // draw normally for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) { Brush_Draw( brush ); } // blend on top glMatrixMode(GL_PROJECTION); glColor4f(1.0, 0.0, 0.0, 0.3); glEnable (GL_BLEND); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable (GL_TEXTURE_2D); for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) for (face=brush->brush_faces ; face ; face=face->next) Face_Draw( face ); if (selected_face) Face_Draw(selected_face); // non-zbuffered outline glDisable (GL_BLEND); glDisable (GL_DEPTH_TEST); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glColor3f (1, 1, 1); for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) for (face=brush->brush_faces ; face ; face=face->next) Face_Draw( face ); // edge / vertex flags if (g_qeglobals.d_select_mode == sel_vertex) { glPointSize (4); glColor3f (0,1,0); glBegin (GL_POINTS); for (i=0 ; i