mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2024-11-10 07:11:54 +00:00
594 lines
12 KiB
C
594 lines
12 KiB
C
/*
|
|
===========================================================================
|
|
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)));
|
|
}
|
|
}
|
|
|