]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/extra/qe4/camera.c
Merge remote-tracking branch 'ttimo/master'
[xonotic/netradiant.git] / tools / quake2 / extra / qe4 / camera.c
diff --git a/tools/quake2/extra/qe4/camera.c b/tools/quake2/extra/qe4/camera.c
new file mode 100644 (file)
index 0000000..8dd7d5f
--- /dev/null
@@ -0,0 +1,594 @@
+/*
+===========================================================================
+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<g_qeglobals.d_numpoints ; i++)
+                       glVertex3fv (g_qeglobals.d_points[i]);
+               glEnd ();
+               glPointSize (1);
+       }
+       else if (g_qeglobals.d_select_mode == sel_edge)
+       {
+               float   *v1, *v2;
+
+               glPointSize (4);
+               glColor3f (0,0,1);
+               glBegin (GL_POINTS);
+               for (i=0 ; i<g_qeglobals.d_numedges ; i++)
+               {
+                       v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
+                       v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
+                       glVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
+               }
+               glEnd ();
+               glPointSize (1);
+       }
+
+       //
+       // draw pointfile
+       //
+       glEnable(GL_DEPTH_TEST);
+
+       DrawPathLines ();
+
+       if (g_qeglobals.d_pointfile_display_list)
+       {
+               Pointfile_Draw();
+//             glCallList (g_qeglobals.d_pointfile_display_list);
+       }
+
+       // bind back to the default texture so that we don't have problems
+       // elsewhere using/modifying texture maps between contexts
+       glBindTexture( GL_TEXTURE_2D, 0 );
+
+    glFinish();
+       QE_CheckOpenGLForErrors();
+//     Sys_EndWait();
+       if (camera.timing)
+       {
+               end = Sys_DoubleTime ();
+               Sys_Printf ("Camera: %i ms\n", (int)(1000*(end-start)));
+       }
+}
+