Alliteration Annoys Always

This commit is contained in:
Ragnvald Maartmann-Moe IV 2001-05-11 01:01:27 +00:00
parent bcfd870550
commit 28c809d27e
19 changed files with 2685 additions and 1730 deletions

View file

@ -73,7 +73,8 @@ client_POST_LIBS= $(top_builddir)/libs/video/targets/libQFjs.la
client_SOURCES= cl_cam.c cl_cmd.c cl_demo.c cl_input.c cl_main.c cl_parse.c \
cl_tent.c console.c keys.c sbar.c r_part.c r_view.c \
nonintel.c gib.c gib_instructions.c gib_vars.c \
gib_interpret.c gib_modules.c gib_parse.c gib_stack.c
gib_interpret.c gib_modules.c gib_parse.c gib_stack.c \
pcx.c tga.c
server_SOURCES= host.c host_cmd.c pr_cmds.c sv_cvar.c sv_main.c \
sv_move.c sv_phys.c sv_progs.c sv_user.c
@ -122,7 +123,7 @@ nq_x11_DEPENDENCIES=$(client_LIB_DEPS)
ogl_SOURCES= noisetextures.c gl_textures.c gl_draw.c gl_dyn_fires.c \
gl_dyn_part.c gl_dyn_textures.c gl_mesh.c \
gl_refrag.c gl_rlight.c gl_rmain.c gl_rmisc.c gl_rsurf.c \
gl_screen.c gl_view.c gl_warp.c
gl_screen.c gl_sky.c gl_view.c gl_warp.c
# ... 3Dfx Voodoo 1 and 2 SVGAlib-based console GL
nq_3dfx_SOURCES= $(combined_SOURCES) $(ogl_SOURCES)

View file

@ -176,12 +176,10 @@ CL_ClearState (void)
/*
=====================
CL_Disconnect
CL_Disconnect
Sends a disconnect message to the server
This is also called on Host_Error, so it shouldn't cause any errors
=====================
Sends a disconnect message to the server
This is also called on Host_Error, so it shouldn't cause any errors
*/
void
CL_Disconnect (void)
@ -215,6 +213,7 @@ CL_Disconnect (void)
cls.signon = 0;
}
void
CL_Disconnect_f (void)
{
@ -225,11 +224,9 @@ CL_Disconnect_f (void)
/*
=====================
CL_EstablishConnection
CL_EstablishConnection
Host should be either "local" or a net address to be passed on
=====================
Host should be either "local" or a net address to be passed on
*/
void
CL_EstablishConnection (char *host)
@ -255,11 +252,9 @@ CL_EstablishConnection (char *host)
/*
=====================
CL_SignonReply
CL_SignonReply
An svc_signonnum has been received, perform a client side setup
=====================
An svc_signonnum has been received, perform a client side setup
*/
void
CL_SignonReply (void)
@ -295,18 +290,16 @@ CL_SignonReply (void)
break;
case 4:
SCR_EndLoadingPlaque (); // allow normal screen updates
// SCR_EndLoadingPlaque (); // allow normal screen updates
break;
}
}
/*
=====================
CL_NextDemo
CL_NextDemo
Called to play the next demo in the demo loop
=====================
Called to play the next demo in the demo loop
*/
void
CL_NextDemo (void)
@ -316,8 +309,6 @@ CL_NextDemo (void)
if (cls.demonum == -1)
return; // don't play demos
SCR_BeginLoadingPlaque ();
if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) {
cls.demonum = 0;
if (!cls.demos[cls.demonum][0]) {

View file

@ -1,7 +1,7 @@
/*
d_sky.c
@description@
(description)
Copyright (C) 1996-1997 Id Software, Inc.
@ -39,9 +39,7 @@
/*
=================
D_Sky_uv_To_st
=================
D_Sky_uv_To_st
*/
void
D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
@ -64,16 +62,14 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
VectorNormalize (end);
temp = skytime * skyspeed; // TODO: add D_SetupFrame & set this
// there
// there
*s = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[0]) * 0x10000);
*t = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[1]) * 0x10000);
}
/*
=================
D_DrawSkyScans8
=================
D_DrawSkyScans8
*/
void
D_DrawSkyScans8 (espan_t *pspan)

View file

@ -1,7 +1,7 @@
/*
draw.c
@description@
this is the only file outside the refresh that touches the vid buffer
Copyright (C) 1996-1997 Id Software, Inc.
@ -29,14 +29,20 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/console.h"
#include "QF/draw.h"
#include "QF/quakefs.h"
#include "QF/sound.h"
#include "QF/sys.h"
#include "QF/vid.h"
#include "QF/zone.h"
#include "client.h"
#include "d_iface.h"
typedef struct {
@ -53,6 +59,8 @@ byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_disc;
qpic_t *draw_backtile;
cvar_t *cl_verstring;
//=============================================================================
/* Support Routines */
@ -73,6 +81,17 @@ Draw_PicFromWad (char *name)
}
/*
Draw_ClearCache
This is a no-op in software targets
*/
void
Draw_ClearCache (void)
{
}
qpic_t *
Draw_CachePic (char *path, qboolean alpha)
{
@ -112,12 +131,59 @@ Draw_CachePic (char *path, qboolean alpha)
}
void
Draw_TextBox (int x, int y, int width, int lines)
{
qpic_t *p;
int cx, cy;
int n;
// draw left side
cx = x;
cy = y;
p = Draw_CachePic ("gfx/box_tl.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_ml.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bl.lmp", true);
Draw_Pic (cx, cy + 8, p);
// draw middle
cx += 8;
while (width > 0) {
cy = y;
p = Draw_CachePic ("gfx/box_tm.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mm.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
if (n == 1)
p = Draw_CachePic ("gfx/box_mm2.lmp", true);
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_bm.lmp", true);
Draw_Pic (cx, cy + 8, p);
width -= 2;
cx += 16;
}
// draw right side
cy = y;
p = Draw_CachePic ("gfx/box_tr.lmp", true);
Draw_Pic (cx, cy, p);
p = Draw_CachePic ("gfx/box_mr.lmp", true);
for (n = 0; n < lines; n++) {
cy += 8;
Draw_Pic (cx, cy, p);
}
p = Draw_CachePic ("gfx/box_br.lmp", true);
Draw_Pic (cx, cy + 8, p);
}
/*
===============
Draw_Init
===============
*/
void
Draw_Init (void)
{
@ -129,21 +195,25 @@ Draw_Init (void)
r_rectdesc.height = draw_backtile->height;
r_rectdesc.ptexbytes = draw_backtile->data;
r_rectdesc.rowbytes = draw_backtile->width;
cl_verstring =
Cvar_Get ("cl_verstring", PROGRAM " " VERSION, CVAR_NONE, NULL,
"Client version string");
}
void
Draw_Init_Cvars (void)
{
}
/*
================
Draw_Character8
Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
================
/*
Draw_Character8
Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
*/
void
Draw_Character8 (int x, int y, int num)
@ -159,12 +229,10 @@ Draw_Character8 (int x, int y, int num)
if (y <= -8)
return; // totally off screen
#ifdef PARANOID
if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
Sys_Error ("Con_DrawCharacter: (%i, %i)", x, y);
return;
if (num < 0 || num > 255)
Sys_Error ("Con_DrawCharacter: char %i", num);
#endif
return;
row = num >> 4;
col = num & 15;
@ -230,11 +298,7 @@ Draw_Character8 (int x, int y, int num)
}
}
/*
================
Draw_String8
================
*/
void
Draw_String8 (int x, int y, char *str)
{
@ -245,155 +309,73 @@ Draw_String8 (int x, int y, char *str)
}
}
/*
================
Draw_DebugChar
Draws a single character directly to the upper right corner of the screen.
This is for debugging lockups by drawing different chars in different parts
of the code.
================
*/
void
Draw_DebugChar (char num)
Draw_AltString8 (int x, int y, char *str)
{
while (*str) {
Draw_Character8 (x, y, (*str) | 0x80);
str++;
x += 8;
}
}
void
Draw_Pixel (int x, int y, byte color)
{
byte *dest;
byte *source;
int drawline;
extern byte *draw_chars;
int row, col;
unsigned short *pusdest;
if (!vid.direct)
return; // don't have direct FB access, so no
//
//
// debugchars...
drawline = 8;
row = num >> 4;
col = num & 15;
source = draw_chars + (row << 10) + (col << 3);
dest = vid.direct + 312;
while (drawline--) {
dest[0] = source[0];
dest[1] = source[1];
dest[2] = source[2];
dest[3] = source[3];
dest[4] = source[4];
dest[5] = source[5];
dest[6] = source[6];
dest[7] = source[7];
source += 128;
dest += 320;
if (r_pixbytes == 1) {
dest = vid.conbuffer + y * vid.conrowbytes + x;
*dest = color;
} else {
// FIXME: pre-expand to native format?
pusdest = (unsigned short *)
((byte *) vid.conbuffer + y * vid.conrowbytes + (x << 1));
*pusdest = d_8to16table[color];
}
}
/*
=============
Draw_Pic
=============
*/
void
Draw_Crosshair (void)
{
int x, y;
extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor;
extern vrect_t scr_vrect;
byte c = crosshaircolor->int_val;
if (crosshair->int_val == 2) {
x = scr_vrect.x + scr_vrect.width / 2 + cl_crossx->int_val;
y = scr_vrect.y + scr_vrect.height / 2 + cl_crossy->int_val;
Draw_Pixel (x - 1, y, c);
Draw_Pixel (x - 3, y, c);
Draw_Pixel (x + 1, y, c);
Draw_Pixel (x + 3, y, c);
Draw_Pixel (x, y - 1, c);
Draw_Pixel (x, y - 3, c);
Draw_Pixel (x, y + 1, c);
Draw_Pixel (x, y + 3, c);
} else if (crosshair->int_val)
Draw_Character8 (scr_vrect.x + scr_vrect.width / 2 - 4 +
cl_crossx->int_val,
scr_vrect.y + scr_vrect.height / 2 - 4 +
cl_crossy->int_val, '+');
}
void
Draw_Pic (int x, int y, qpic_t *pic)
{
byte *dest, *source;
unsigned short *pusdest;
int v, u;
if ((x < 0) ||
(x + pic->width > vid.width) ||
(y < 0) || (y + pic->height > vid.height)) {
Sys_Error ("Draw_Pic: bad coordinates");
}
source = pic->data;
if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x;
for (v = 0; v < pic->height; v++) {
memcpy (dest, source, pic->width);
dest += vid.rowbytes;
source += pic->width;
}
} else {
// FIXME: pretranslate at load time?
pusdest = (unsigned short *) vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v = 0; v < pic->height; v++) {
for (u = 0; u < pic->width; u++) {
pusdest[u] = d_8to16table[source[u]];
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
/*
=============
Draw_SubPic
=============
*/
void
Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
int height)
{
byte *dest, *source;
unsigned short *pusdest;
int v, u;
if ((x < 0) ||
(x + width > vid.width) || (y < 0) || (y + height > vid.height)) {
Sys_Error ("Draw_SubPic: bad coordinates");
}
source = pic->data + srcy * pic->width + srcx;
if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x;
for (v = 0; v < height; v++) {
memcpy (dest, source, width);
dest += vid.rowbytes;
source += pic->width;
}
} else {
// FIXME: pretranslate at load time?
pusdest = (unsigned short *) vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v = 0; v < height; v++) {
for (u = srcx; u < (srcx + width); u++) {
pusdest[u] = d_8to16table[source[u]];
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
/*
=============
Draw_TransPic
=============
*/
void
Draw_TransPic (int x, int y, qpic_t *pic)
{
byte *dest, *source, tbyte;
unsigned short *pusdest;
int v, u;
if (x < 0 || (unsigned) (x + pic->width) > vid.width || y < 0 ||
(unsigned) (y + pic->height) > vid.height) {
Sys_Error ("Draw_TransPic: bad coordinates");
if (x < 0 || (unsigned int) (x + pic->width) > vid.width || y < 0 ||
(unsigned int) (y + pic->height) > vid.height) {
Sys_Error ("Draw_Pic: bad coordinates");
}
source = pic->data;
@ -454,11 +436,45 @@ Draw_TransPic (int x, int y, qpic_t *pic)
}
/*
=============
Draw_TransPicTranslate
=============
*/
void
Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
int height)
{
byte *dest, *source;
unsigned short *pusdest;
int v, u;
if ((x < 0) ||
(x + width > vid.width) || (y < 0) || (y + height > vid.height)) {
Sys_Error ("Draw_Pic: bad coordinates");
}
source = pic->data + srcy * pic->width + srcx;
if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x;
for (v = 0; v < height; v++) {
memcpy (dest, source, width);
dest += vid.rowbytes;
source += pic->width;
}
} else {
// FIXME: pretranslate at load time?
pusdest = (unsigned short *) vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v = 0; v < height; v++) {
for (u = srcx; u < (srcx + width); u++) {
pusdest[u] = d_8to16table[source[u]];
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
void
Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte * translation)
{
@ -466,8 +482,8 @@ Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte * translation)
unsigned short *pusdest;
int v, u;
if (x < 0 || (unsigned) (x + pic->width) > vid.width || y < 0 ||
(unsigned) (y + pic->height) > vid.height) {
if (x < 0 || (unsigned int) (x + pic->width) > vid.width || y < 0 ||
(unsigned int) (y + pic->height) > vid.height) {
Sys_Error ("Draw_TransPic: bad coordinates");
}
@ -529,33 +545,6 @@ Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte * translation)
}
void
Draw_CharToConback (int num, byte * dest)
{
int row, col;
byte *source;
int drawline;
int x;
row = num >> 4;
col = num & 15;
source = draw_chars + (row << 10) + (col << 3);
drawline = 8;
while (drawline--) {
for (x = 0; x < 8; x++)
if (source[x])
dest[x] = 0x60 + source[x];
source += 128;
dest += 320;
}
}
/*
Draw_ConsoleBackground
*/
void
Draw_ConsoleBackground (int lines)
{
@ -565,9 +554,9 @@ Draw_ConsoleBackground (int lines)
int f, fstep;
qpic_t *conback;
conback = Draw_CachePic ("gfx/conback.lmp", true);
conback = Draw_CachePic ("gfx/conback.lmp", false);
// draw the pic
// draw the pic
if (r_pixbytes == 1) {
dest = vid.conbuffer;
@ -613,14 +602,12 @@ Draw_ConsoleBackground (int lines)
}
}
}
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string)
* 8 - 11, lines - 14, cl_verstring->string);
}
/*
==============
R_DrawRect8
==============
*/
void
R_DrawRect8 (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
{
@ -658,11 +645,6 @@ R_DrawRect8 (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
}
/*
==============
R_DrawRect16
==============
*/
void
R_DrawRect16 (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
{
@ -709,12 +691,10 @@ R_DrawRect16 (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
/*
=============
Draw_TileClear
Draw_TileClear
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
*/
void
Draw_TileClear (int x, int y, int w, int h)
@ -768,32 +748,35 @@ Draw_TileClear (int x, int y, int w, int h)
vr.x += vr.width;
width -= vr.width;
tileoffsetx = 0; // only the left tile can be
// left-clipped
// left-clipped
}
vr.y += vr.height;
height -= vr.height;
tileoffsety = 0; // only the top tile can be
// top-clipped
// top-clipped
}
}
/*
=============
Draw_Fill
Draw_Fill
Fills a box of pixels with a single color
=============
Fills a box of pixels with a single color
*/
void
Draw_Fill (int x, int y, int w, int h, int c)
{
byte *dest;
unsigned short *pusdest;
unsigned uc;
unsigned int uc;
int u, v;
if (x < 0 || x + w > vid.width || y < 0 || y + h > vid.height) {
Con_Printf ("Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c);
return;
}
if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x;
for (v = 0; v < h; v++, dest += vid.rowbytes)
@ -808,14 +791,11 @@ Draw_Fill (int x, int y, int w, int h, int c)
pusdest[u] = uc;
}
}
//=============================================================================
/*
================
Draw_FadeScreen
================
*/
void
Draw_FadeScreen (void)
{
@ -843,15 +823,15 @@ Draw_FadeScreen (void)
VID_LockBuffer ();
}
//=============================================================================
/*
================
Draw_BeginDisc
Draws the little blue disc in the corner of the screen.
Call before beginning any disc IO.
================
/*
Draw_BeginDisc
Draws the little blue disc in the corner of the screen.
Call before beginning any disc IO.
*/
void
Draw_BeginDisc (void)
@ -862,12 +842,10 @@ Draw_BeginDisc (void)
/*
================
Draw_EndDisc
Draw_EndDisc
Erases the disc icon.
Call after completing any disc IO
================
Erases the disc icon.
Call after completing any disc IO
*/
void
Draw_EndDisc (void)
@ -875,42 +853,3 @@ Draw_EndDisc (void)
D_EndDirectRect (vid.width - 24, 0, 24, 24);
}
void
Draw_Crosshair (void)
{
int x, y;
extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor;
extern vrect_t scr_vrect;
byte c = (byte) crosshaircolor->value;
if (crosshair->value == 2) {
byte *dest;
x = scr_vrect.x + scr_vrect.width / 2 + cl_crossx->value;
y = scr_vrect.y + scr_vrect.height / 2 + cl_crossy->value;
dest = vid.conbuffer + y * vid.conrowbytes + x;
dest[-3] = dest[-1] = dest[1] = dest[3] = c;
dest[-3 * vid.conrowbytes] = dest[-1 * vid.conrowbytes] =
dest[1 * vid.conrowbytes] = dest[3 * vid.conrowbytes] = c;
// FIXME: Find a better way to do this...
#if 0
Draw_Pixel (x - 1, y, c);
Draw_Pixel (x - 3, y, c);
Draw_Pixel (x + 1, y, c);
Draw_Pixel (x + 3, y, c);
Draw_Pixel (x, y - 1, c);
Draw_Pixel (x, y - 3, c);
Draw_Pixel (x, y + 1, c);
Draw_Pixel (x, y + 3, c);
#endif
} else if (crosshair->value) {
Draw_Character8 (scr_vrect.x + scr_vrect.width / 2 - 4 +
cl_crossx->value,
scr_vrect.y + scr_vrect.height / 2 - 4 +
cl_crossy->value, '+');
}
}

View file

@ -267,6 +267,7 @@ gl_lightmode_callback (cvar_t *cvar)
R_ForceLightUpdate ();
}
void
Draw_Init (void)
{
@ -315,6 +316,7 @@ Draw_Init (void)
glrsurf_init ();
}
void
Draw_Init_Cvars (void)
{
@ -506,8 +508,6 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
}
extern int gl_filter_min, gl_filter_max;
/*
Draw_TransPicTranslate
@ -603,7 +603,7 @@ Draw_ConsoleBackground (int lines)
else
ofs = (vid.conheight - lines) / (float) vid.conheight;
y = vid.height * 0.5; // 0.5 was scr_consize->value
y = vid.height * scr_consize->value;
if (cls.state != ca_active || lines > y) {
alpha = 1.0;
} else {
@ -642,7 +642,7 @@ Draw_ConsoleBackground (int lines)
glMatrixMode (GL_MODELVIEW);
glPopMatrix ();
}
// draw version string if not downloading
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string) * 8 - 11,
lines - 14, cl_verstring->string);
glColor3ubv (lighthalf_v);
@ -705,11 +705,10 @@ Draw_Fill (int x, int y, int w, int h, int c)
glEnable (GL_TEXTURE_2D);
}
//=============================================================================
/*
Draw_FadeScreen
*/
void
Draw_FadeScreen (void)
{
@ -729,8 +728,10 @@ Draw_FadeScreen (void)
Sbar_Changed ();
}
//=============================================================================
/*
Draw_BeginDisc

View file

@ -54,9 +54,9 @@
#include "net.h"
#include "protocol.h"
#include "sbar.h"
#include "render.h"
#include "r_dynamic.h"
#include "r_local.h"
#include "render.h"
extern entity_t r_worldentity;
extern void GDT_Init ();

File diff suppressed because it is too large Load diff

343
nq/source/gl_sky.c Normal file
View file

@ -0,0 +1,343 @@
/*
gl_sky.c
sky polygons
Copyright (C) 1996-1997 Id Software, Inc.
This program 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.
This program 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 this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/compat.h"
#include "QF/console.h"
#include "QF/quakefs.h"
#include "QF/tga.h"
#include "QF/vid.h"
#include "glquake.h"
#include "render.h"
#include "view.h"
extern double realtime;
extern model_t *loadmodel;
extern int skytexturenum;
extern qboolean lighthalf;
int solidskytexture;
int alphaskytexture;
float speedscale; // for top sky and bottom sky
// Set to true if a valid skybox is loaded --KB
qboolean skyloaded = false;
/*
R_LoadSkys
*/
char *suf[6] = { "rt", "bk", "lf", "ft", "up", "dn" };
void
R_LoadSkys (const char *skyname)
{
int i;
QFile *f;
char name[64];
if (strcasecmp (skyname, "none") == 0) {
skyloaded = false;
return;
}
skyloaded = true;
for (i = 0; i < 6; i++) {
byte *targa_rgba;
glBindTexture (GL_TEXTURE_2D, SKY_TEX + i);
snprintf (name, sizeof (name), "env/%s%s.tga", skyname, suf[i]);
COM_FOpenFile (name, &f);
if (!f) {
Con_DPrintf ("Couldn't load %s\n", name);
skyloaded = false;
continue;
}
targa_rgba = LoadTGA (f);
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA,
GL_UNSIGNED_BYTE, targa_rgba);
free (targa_rgba);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (!skyloaded)
Con_Printf ("Unable to load skybox %s, using normal sky\n", skyname);
}
void
R_SkyBoxPolyVec (vec5_t v)
{
// avoid interpolation seams
// s = s * (254.0/256.0) + (1.0/256.0);
// t = t * (254.0/256.0) + (1.0/256.0);
glTexCoord2fv (v);
glVertex3f (r_refdef.vieworg[0] + v[2],
r_refdef.vieworg[1] + v[3], r_refdef.vieworg[2] + v[4]);
}
#define ftc(x) (x * (254.0/256.0) + (1.0/256.0))
vec5_t skyvec[6][4] = {
{
// right +y
{ftc (1), ftc (0), 1024, 1024, 1024},
{ftc (1), ftc (1), 1024, 1024, -1024},
{ftc (0), ftc (1), -1024, 1024, -1024},
{ftc (0), ftc (0), -1024, 1024, 1024}
},
{
// back -x
{ftc (1), ftc (0), -1024, 1024, 1024},
{ftc (1), ftc (1), -1024, 1024, -1024},
{ftc (0), ftc (1), -1024, -1024, -1024},
{ftc (0), ftc (0), -1024, -1024, 1024}
},
{
// left -y
{ftc (1), ftc (0), -1024, -1024, 1024},
{ftc (1), ftc (1), -1024, -1024, -1024},
{ftc (0), ftc (1), 1024, -1024, -1024},
{ftc (0), ftc (0), 1024, -1024, 1024}
},
{
// front +x
{ftc (1), ftc (0), 1024, -1024, 1024},
{ftc (1), ftc (1), 1024, -1024, -1024},
{ftc (0), ftc (1), 1024, 1024, -1024},
{ftc (0), ftc (0), 1024, 1024, 1024}
},
{
// up +z
{ftc (1), ftc (0), 1024, -1024, 1024},
{ftc (1), ftc (1), 1024, 1024, 1024},
{ftc (0), ftc (1), -1024, 1024, 1024},
{ftc (0), ftc (0), -1024, -1024, 1024}
},
{
// down -z
{ftc (1), ftc (0), 1024, 1024, -1024},
{ftc (1), ftc (1), 1024, -1024, -1024},
{ftc (0), ftc (1), -1024, -1024, -1024},
{ftc (0), ftc (0), -1024, 1024, -1024}
}
};
#undef ftc
void
R_DrawSkyBox (void)
{
int i, j;
glDisable (GL_DEPTH_TEST);
glDepthRange (gldepthmax, gldepthmax);
for (i = 0; i < 6; i++) {
glBindTexture (GL_TEXTURE_2D, SKY_TEX + i);
glBegin (GL_QUADS);
for (j = 0; j < 4; j++)
R_SkyBoxPolyVec (skyvec[i][j]);
glEnd ();
}
glEnable (GL_DEPTH_TEST);
glDepthRange (gldepthmin, gldepthmax);
}
vec3_t domescale;
void
R_DrawSkyLayer (float s)
{
int a, b;
float x, y, a1x, a1y, a2x, a2y;
vec3_t v;
for (a = 0; a < 16; a++) {
a1x = bubble_costable[a * 2] * domescale[0];
a1y = -bubble_sintable[a * 2] * domescale[1];
a2x = bubble_costable[(a + 1) * 2] * domescale[0];
a2y = -bubble_sintable[(a + 1) * 2] * domescale[1];
glBegin (GL_TRIANGLE_STRIP);
glTexCoord2f (0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f (r_refdef.vieworg[0],
r_refdef.vieworg[1], r_refdef.vieworg[2] + domescale[2]);
for (b = 1; b < 8; b++) {
x = bubble_costable[b * 2 + 16];
y = -bubble_sintable[b * 2 + 16];
v[0] = a1x * x;
v[1] = a1y * x;
v[2] = y * domescale[2];
glTexCoord2f ((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f (v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1], v[2] + r_refdef.vieworg[2]);
v[0] = a2x * x;
v[1] = a2y * x;
v[2] = y * domescale[2];
glTexCoord2f ((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f (v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1], v[2] + r_refdef.vieworg[2]);
}
glTexCoord2f (0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f (r_refdef.vieworg[0],
r_refdef.vieworg[1], r_refdef.vieworg[2] - domescale[2]);
glEnd ();
}
}
void
R_DrawSkyDome (void)
{
glDisable (GL_DEPTH_TEST);
glDepthRange (gldepthmax, gldepthmax);
glDisable (GL_BLEND);
// base sky
glBindTexture (GL_TEXTURE_2D, solidskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime * 8;
speedscale -= (int) speedscale & ~127;
R_DrawSkyLayer (speedscale);
glEnable (GL_BLEND);
// clouds
if (gl_skymultipass->int_val) {
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime * 16;
speedscale -= (int) speedscale & ~127;
R_DrawSkyLayer (speedscale);
}
glEnable (GL_DEPTH_TEST);
glDepthRange (gldepthmin, gldepthmax);
}
void
R_DrawSky (void)
{
float l = 1 / (256 * brightness->value);
glColor3f (lighthalf_v[0] * l, lighthalf_v[1] * l, lighthalf_v[2] * l);
if (skyloaded)
R_DrawSkyBox ();
else
R_DrawSkyDome ();
glColor3ubv (lighthalf_v);
}
//===============================================================
/*
R_InitSky
A sky texture is 256*128, with the right side being a masked overlay
*/
void
R_InitSky (texture_t *mt)
{
int i, j, p;
byte *src;
unsigned int trans[128 * 128];
unsigned int transpix;
int r, g, b;
unsigned int *rgba;
src = (byte *) mt + mt->offsets[0];
// make an average value for the back to avoid
// a fringe on the top level
r = g = b = 0;
for (i = 0; i < 128; i++)
for (j = 0; j < 128; j++) {
p = src[i * 256 + j + 128];
rgba = &d_8to24table[p];
trans[(i * 128) + j] = *rgba;
r += ((byte *) rgba)[0];
g += ((byte *) rgba)[1];
b += ((byte *) rgba)[2];
}
((byte *) & transpix)[0] = r / (128 * 128);
((byte *) & transpix)[1] = g / (128 * 128);
((byte *) & transpix)[2] = b / (128 * 128);
((byte *) & transpix)[3] = 0;
if (!solidskytexture)
solidskytexture = texture_extension_number++;
glBindTexture (GL_TEXTURE_2D, solidskytexture);
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA,
GL_UNSIGNED_BYTE, trans);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
for (i = 0; i < 128; i++)
for (j = 0; j < 128; j++) {
p = src[i * 256 + j];
if (p == 0)
trans[(i * 128) + j] = transpix;
else
trans[(i * 128) + j] = d_8to24table[p];
}
if (!alphaskytexture)
alphaskytexture = texture_extension_number++;
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA,
GL_UNSIGNED_BYTE, trans);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

776
nq/source/gl_sky_clip.c Normal file
View file

@ -0,0 +1,776 @@
/*
gl_sky_clip.c
sky polygons
Copyright (C) 1996-1997 Id Software, Inc.
This program 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.
This program 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 this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdarg.h>
#include "QF/console.h"
#include "QF/sys.h"
#include "client.h"
#include "glquake.h"
#include "view.h"
extern qboolean skyloaded;
extern vec5_t skyvec[6][4];
#define BOX_WIDTH 2056
/* cube face to sky texture offset conversion */
static const int skytex_offs[] = { 3, 0, 4, 1, 2, 5 };
/* clockwise loop through the cube faces adjoining the current face */
static const int face_loop[6][5] = {
{1, 2, 4, 5, 1},
{0, 5, 3, 2, 0},
{0, 1, 3, 4, 0},
{1, 5, 4, 2, 1},
{0, 2, 3, 5, 0},
{0, 4, 3, 1, 0},
};
/* convert axis and face distance into face */
static const int faces_table[3][6] = {
{-1, 0, 0, -1, 3, 3},
{-1, 4, 4, -1, 1, 1},
{-1, 2, 2, -1, 5, 5},
};
/* convert face magic bit mask to index into visit array */
static const int faces_bit_magic[] = { 2, 1, -1, 0, 3, -1, 4, -1 };
/* axis the cube face cuts (also index into vec3_t and n % 3 for 0 <= n < 6) */
static const int face_axis[] = { 0, 1, 2, 0, 1, 2 };
/* offset on the axis the cube face cuts */
static const vec_t face_offset[] = { 1024, 1024, 1024, -1024, -1024, -1024 };
/* cube face */
struct face_def {
int tex; // texture to bind to
glpoly_t poly; // describe the polygon of this face
float verts[32][VERTEXSIZE];
};
struct visit_def {
int face; // face being visited
int leave; // vertex departed through
};
/* our cube */
struct box_def {
/* keep track of which cube faces we visit and in what order */
struct visit_def visited_faces[9];
int face_visits[6];
int face_count;
/* the cube faces */
struct face_def face[6];
};
/*
determine_face
return the face of the cube which v hits first
0 +x
1 +y
2 +z
3 -x
4 -y
5 -z
Also scales v so it touches that face.
*/
static int
determine_face (vec3_t v)
{
float a[3];
float m;
int i = 0;
m = a[0] = fabs (v[0]);
a[1] = fabs (v[1]);
a[2] = fabs (v[2]);
if (a[1] > m) {
m = a[1];
i = 1;
}
if (a[2] > m) {
m = a[2];
i = 2;
}
if (!m) {
Sys_Error ("%s speared by sky poly edge\n", name->string);
}
if (v[i] < 0)
i += 3;
VectorScale (v, 1024 / m, v);
return i;
}
/*
find_intersect (for want of a better name)
finds the point of intersection of the plane formed by the eye and the two
points on the cube and the edge of the cube defined by the two faces.
Currently, this will break if the two points are not on adjoining cube
faces (ie either on opposing faces or the same face).
The equation for the point of intersection of a line and a plane is:
(x - p).n
y = x - _________ v
v.n
where n is the normal to the plane, p is a point on the plane, x is a
point on the line, and v is the direction vector of the line. n is found
by (x1 - e) cross (x2 - e) and p is taken to be e (e = eye coords) for
simplicity. However, because e is at 0,0,0, this simplifies to n = x1
cross x2 and p = 0,0,0, so the equation above simplifies to:
x.n
y = x - ___ v
v.n
*/
static int
find_intersect (int face1, vec3_t x1, int face2, vec3_t x2, vec3_t y)
{
vec3_t n; // normal to the plane formed by the
// eye and the two points on the cube.
vec3_t x = { 0, 0, 0 }; // point on cube edge of adjoining
// faces. always on an axis plane.
vec3_t v = { 0, 0, 0 }; // direction vector of cube edge.
// always +ve
vec_t x_n, v_n; // x.n and v.n
int axis;
vec3_t t;
x[face_axis[face1]] = face_offset[face1];
x[face_axis[face2]] = face_offset[face2];
axis = 3 - ((face_axis[face1]) + (face_axis[face2]));
v[axis] = 1;
CrossProduct (x1, x2, n);
x_n = DotProduct (x, n);
v_n = DotProduct (v, n);
VectorScale (v, x_n / v_n, t);
VectorSubtract (x, t, y);
return axis;
}
/*
find_cube_vertex
get the coords of the vertex common to the three specified faces of the
cube. NOTE: this WILL break if the three faces do not share a common
vertex. ie works = ((face1 % 3 != face2 % 3)
&& (face2 % 3 != face3 % 3)
&& (face1 % 3 != face3 % 3))
*/
static void
find_cube_vertex (int face1, int face2, int face3, vec3_t v)
{
v[face_axis[face1]] = face_offset[face1];
v[face_axis[face2]] = face_offset[face2];
v[face_axis[face3]] = face_offset[face3];
}
/*
set_vertex
add the vertex to the polygon describing the face of the cube. Offsets
the vertex relative to r_refdef.vieworg so the cube is always centered
on the player and also calculates the texture coordinates of the vertex
(wish I could find a cleaner way of calculating s and t).
*/
static void
set_vertex (struct box_def *box, int face, int ind, vec3_t v)
{
VectorCopy (v, box->face[face].poly.verts[ind]);
VectorAdd (v, r_refdef.vieworg, box->face[face].poly.verts[ind]);
switch (face) {
case 0:
box->face[face].poly.verts[ind][3] = (1024 - v[1] + 4) / BOX_WIDTH;
box->face[face].poly.verts[ind][4] = (1024 - v[2] + 4) / BOX_WIDTH;
break;
case 1:
box->face[face].poly.verts[ind][3] = (1024 + v[0] + 4) / BOX_WIDTH;
box->face[face].poly.verts[ind][4] = (1024 - v[2] + 4) / BOX_WIDTH;
break;
case 2:
box->face[face].poly.verts[ind][3] = (1024 + v[0] + 4) / BOX_WIDTH;
box->face[face].poly.verts[ind][4] = (1024 + v[1] + 4) / BOX_WIDTH;
break;
case 3:
box->face[face].poly.verts[ind][3] = (1024 + v[1] + 4) / BOX_WIDTH;
box->face[face].poly.verts[ind][4] = (1024 - v[2] + 4) / BOX_WIDTH;
break;
case 4:
box->face[face].poly.verts[ind][3] = (1024 - v[0] + 4) / BOX_WIDTH;
box->face[face].poly.verts[ind][4] = (1024 - v[2] + 4) / BOX_WIDTH;
break;
case 5:
box->face[face].poly.verts[ind][3] = (1024 + v[0] + 4) / BOX_WIDTH;
box->face[face].poly.verts[ind][4] = (1024 - v[1] + 4) / BOX_WIDTH;
break;
}
}
/*
add_vertex
append a vertex to the poly vertex list.
*/
static void
add_vertex (struct box_def *box, int face, vec3_t v)
{
set_vertex (box, face, box->face[face].poly.numverts++, v);
}
/*
insert_cube_vertices
insert the given cube vertices into the vertex list of the poly in the
correct location.
*/
static void
insert_cube_vertices (struct box_def *box, struct visit_def visit, int count,
...)
{
int i;
vec3_t **v;
va_list args;
int face = visit.face;
int ind = visit.leave + 1;
#ifdef __BORLANDC__
// This is fix for borland alloca "feature" which fails to restore stack
// correcly if calling function doesn't have any references to local variables.
char dummy[5];
dummy[0]=0;
#endif
va_start (args, count);
v = (vec3_t **) alloca (count * sizeof (vec3_t *));
for (i = 0; i < count; i++) {
v[i] = va_arg (args, vec3_t *);
}
va_end (args);
if (ind == box->face[face].poly.numverts) {
// the vertex the sky poly left this cube fase through is very
// conveniently the last vertex of the face poly. this means we
// can just append the vetexen
for (i = 0; i < count; i++)
add_vertex (box, face, *v[i]);
} else {
// we have to insert the cube vertices into the face poly
// vertex list
glpoly_t *p = &box->face[face].poly;
int c = p->numverts - ind;
const int vert_size = sizeof (p->verts[0]);
memmove (p->verts[ind + count], p->verts[ind], c * vert_size);
p->numverts += count;
for (i = 0; i < count; i++)
set_vertex (box, face, ind + i, *v[i]);
}
}
/*
cross_cube_edge
add the vertex formed by the poly edge crossing the cube edge to the
polygon for the two faces on that edge. Actually, the two faces define
the edge :). The poly edge is going from face 1 to face 2 (for
enter/leave purposes).
*/
static void
cross_cube_edge (struct box_def *box, int face1, vec3_t v1, int face2,
vec3_t v2)
{
vec3_t l;
int axis;
int face = -1;
axis = find_intersect (face1, v1, face2, v2, l);
if (l[axis] > 1024)
face = axis;
else if (l[axis] < -1024)
face = axis + 3;
if (face >= 0) {
vec3_t x;
VectorAdd (v1, v2, x);
VectorScale (x, 0.5, x);
cross_cube_edge (box, face1, v1, face, x);
cross_cube_edge (box, face, x, face2, v2);
} else {
struct visit_def *visit = box->visited_faces;
visit[box->face_count - 1].leave = box->face[face1].poly.numverts;
visit[box->face_count].face = face2;
box->face_count++;
box->face_visits[face2]++;
add_vertex (box, face1, l);
add_vertex (box, face2, l);
}
}
/*
process_corners
egad, veddy complicated :)
*/
static void
process_corners (struct box_def *box)
{
struct visit_def *visit = box->visited_faces;
int max_visit = 0;
int i;
int center = -1;
if (visit[box->face_count - 1].face == visit[0].face) {
box->face_count--;
}
for (i = 0; i < 6; i++) {
if (max_visit < box->face_visits[i]) {
max_visit = box->face_visits[i];
center = i;
}
}
switch (box->face_count) {
case 1:
case 2:
case 8:
// no corners
return;
case 3:
// one corner, no edges
{
vec3_t v;
find_cube_vertex (visit[0].face, visit[1].face, visit[2].face,
v);
insert_cube_vertices (box, visit[0], 1, v);
insert_cube_vertices (box, visit[1], 1, v);
insert_cube_vertices (box, visit[2], 1, v);
}
break;
case 4:
if (max_visit > 1)
return;
if (abs (visit[2].face - visit[0].face) == 3
&& abs (visit[3].face - visit[1].face) == 3) {
// 4 vertices
int sum, diff;
vec3_t v[4];
sum =
visit[0].face + visit[1].face + visit[2].face +
visit[3].face;
diff = visit[1].face - visit[0].face;
sum %= 3;
diff = (diff + 6) % 6;
center = faces_table[sum][diff];
for (i = 0; i < 4; i++) {
find_cube_vertex (visit[i].face, visit[(i + 1) & 3].face,
center, v[i]);
add_vertex (box, center, v[i]);
}
for (i = 0; i < 4; i++)
insert_cube_vertices (box, visit[i], 2, v[i],
v[(i - 1) & 3]);
} else {
// 2 vertices
int l_f, t_f, r_f, b_f;
vec3_t v_l, v_r;
if (abs (visit[2].face - visit[0].face) == 3) {
l_f = 0;
t_f = 1;
r_f = 2;
b_f = 3;
} else if (abs (visit[3].face - visit[1].face) == 3) {
l_f = 1;
t_f = 2;
r_f = 3;
b_f = 0;
} else {
return;
}
find_cube_vertex (visit[l_f].face, visit[t_f].face,
visit[b_f].face, v_l);
find_cube_vertex (visit[r_f].face, visit[t_f].face,
visit[b_f].face, v_r);
insert_cube_vertices (box, visit[t_f], 2, v_r, v_l);
insert_cube_vertices (box, visit[b_f], 2, v_l, v_r);
insert_cube_vertices (box, visit[l_f], 1, v_l);
insert_cube_vertices (box, visit[r_f], 1, v_r);
}
break;
case 5:
if (max_visit > 1) {
// one vertex
vec3_t v;
for (i = 0; i < 4; i++) {
// don't need to check the 5th visit
if (visit[(i + 2) % 5].face == visit[(i + 4) % 5].face)
break;
}
find_cube_vertex (visit[i].face, visit[(i + 1) % 5].face,
visit[(i + 2) % 5].face, v);
insert_cube_vertices (box, visit[i], 1, v);
insert_cube_vertices (box, visit[(i + 1) % 5], 1, v);
insert_cube_vertices (box, visit[(i + 4) % 5], 1, v);
} else {
// 3 vertices
unsigned int sel =
(((abs (visit[2].face - visit[0].face) == 3) << 2) |
((abs (visit[3].face - visit[1].face) == 3) << 1)
| ((abs (visit[4].face - visit[2].face) == 3) << 0));
vec3_t v[3];
center = faces_bit_magic[sel];
// printf ("%02o %d %d %d %d %d %d\n", sel, center,
// visit[0].face,
// visit[1].face, visit[2].face, visit[3].face,
// visit[4].face);
for (i = 0; i < 3; i++)
find_cube_vertex (visit[center].face,
visit[(center + 1 + i) % 5].face,
visit[(center + 2 + i) % 5].face, v[i]);
insert_cube_vertices (box, visit[center], 3, v[0], v[1], v[2]);
insert_cube_vertices (box, visit[(center + 1) % 5], 1, v[0]);
insert_cube_vertices (box, visit[(center + 2) % 5], 2, v[1],
v[0]);
insert_cube_vertices (box, visit[(center + 3) % 5], 2, v[2],
v[1]);
insert_cube_vertices (box, visit[(center + 4) % 5], 1, v[2]);
}
break;
case 6:
if (max_visit > 2)
return;
for (i = 0; i < 5; i++) {
// don't need to check the last point
if (visit[(i + 3) % 6].face == visit[(i + 5) % 6].face
|| visit[(i + 2) % 6].face == visit[(i + 5) % 6].face)
break;
}
if (visit[(i + 3) % 6].face == visit[(i + 5) % 6].face) {
// adjacant vertices
vec3_t v[2];
find_cube_vertex (visit[i].face, visit[(i + 1) % 6].face,
visit[(i + 2) % 6].face, v[0]);
find_cube_vertex (visit[(i + 1) % 6].face,
visit[(i + 2) % 6].face,
visit[(i + 3) % 6].face, v[1]);
insert_cube_vertices (box, visit[(i + 5) % 6], 2, v[2], v[1]);
insert_cube_vertices (box, visit[i], 1, v[0]);
insert_cube_vertices (box, visit[(i + 1) % 6], 2, v[1], v[0]);
insert_cube_vertices (box, visit[(i + 2) % 6], 1, v[1]);
} else {
// opposing vertices
vec3_t v[2];
find_cube_vertex (visit[i].face, visit[(i + 1) % 6].face,
visit[(i + 2) % 6].face, v[0]);
find_cube_vertex (visit[(i + 3) % 6].face,
visit[(i + 4) % 6].face,
visit[(i + 5) % 6].face, v[1]);
insert_cube_vertices (box, visit[i], 1, v[0]);
insert_cube_vertices (box, visit[(i + 1) % 6], 1, v[0]);
insert_cube_vertices (box, visit[(i + 3) % 6], 1, v[1]);
insert_cube_vertices (box, visit[(i + 4) % 6], 1, v[1]);
insert_cube_vertices (box, visit[(i + 2) % 6], 1, v[1]);
insert_cube_vertices (box, visit[(i + 5) % 6], 1, v[0]);
}
break;
case 7:
for (i = 0; i < 6; i++) {
// don't need to check the last point
if (visit[(i + 2) % 6].face == visit[(i + 4) % 6].face
&& visit[(i + 4) % 6].face == visit[(i + 6) % 6].face)
break;
}
{
vec3_t v;
find_cube_vertex (visit[i].face, visit[(i + 1) % 6].face,
visit[(i + 2) % 6].face, v);
insert_cube_vertices (box, visit[i], 1, v);
insert_cube_vertices (box, visit[(i + 1) % 7], 1, v);
insert_cube_vertices (box, visit[(i + 6) % 7], 1, v);
}
break;
}
}
/*
render_box
draws all faces of the cube with 3 or more vertices.
*/
static void
render_box (struct box_def *box)
{
int i, j;
for (i = 0; i < 6; i++) {
if (box->face[i].poly.numverts <= 2)
continue;
glBindTexture (GL_TEXTURE_2D, box->face[i].tex);
glBegin (GL_POLYGON);
for (j = 0; j < box->face[i].poly.numverts; j++) {
glTexCoord2fv (box->face[i].poly.verts[j] + 3);
glVertex3fv (box->face[i].poly.verts[j]);
}
glEnd ();
}
}
void
R_DrawSkyBoxPoly (glpoly_t *poly)
{
int i;
struct box_def box;
/* projected vertex and face of the previous sky poly vertex */
vec3_t last_v;
int prev_face;
/* projected vertex and face of the current sky poly vertex */
vec3_t v;
int face;
memset (&box, 0, sizeof (box));
for (i = 0; i < 6; i++) {
box.face[i].tex = SKY_TEX + skytex_offs[i];
}
if (poly->numverts >= 32) {
Sys_Error ("too many verts!");
}
VectorSubtract (poly->verts[poly->numverts - 1], r_refdef.vieworg, last_v);
prev_face = determine_face (last_v);
box.visited_faces[0].face = prev_face;
box.face_count = 1;
for (i = 0; i < poly->numverts; i++) {
VectorSubtract (poly->verts[i], r_refdef.vieworg, v);
face = determine_face (v);
if (face != prev_face) {
if ((face_axis[face]) == (face_axis[prev_face])) {
int x_face;
vec3_t x;
VectorAdd (v, last_v, x);
VectorScale (x, 0.5, x);
x_face = determine_face (x);
cross_cube_edge (&box, prev_face, last_v, x_face, x);
cross_cube_edge (&box, x_face, x, face, v);
} else {
cross_cube_edge (&box, prev_face, last_v, face, v);
}
}
add_vertex (&box, face, v);
VectorCopy (v, last_v);
prev_face = face;
}
process_corners (&box);
render_box (&box);
}
void
R_DrawSkyDomePoly (glpoly_t *poly)
{
int i;
glBegin (GL_POLYGON);
for (i = 0; i < poly->numverts; i++) {
glVertex3fv (poly->verts[i]);
}
glEnd ();
}
void
R_DrawSkyChain (msurface_t *sky_chain)
{
msurface_t *sc = sky_chain;
float l = 1 / (256 * brightness->value);
glColor3f (lighthalf_v[0] * l, lighthalf_v[1] * l, lighthalf_v[2] * l);
if (skyloaded) {
glDepthRange (gldepthmax, gldepthmax);
while (sc) {
glpoly_t *p = sc->polys;
while (p) {
R_DrawSkyBoxPoly (p);
p = p->next;
}
sc = sc->texturechain;
}
glDepthRange (gldepthmin, gldepthmax);
} else {
glDisable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
glColor3f (0, 0, 0);
while (sc) {
glpoly_t *p = sc->polys;
while (p) {
R_DrawSkyDomePoly (p);
p = p->next;
}
sc = sc->texturechain;
}
glEnable (GL_TEXTURE_2D);
glEnable (GL_BLEND);
}
#if 0
// seems to work, but this is the wrong place to do it.
glColor4f (1,1,1,0);
sc = sky_chain;
while (sc) {
glpoly_t *p = sc->polys;
while (p) {
int i;
glBegin (GL_POLYGON);
for (i = 0; i < p->numverts; i++) {
glVertex3fv (p->verts[i]);
}
glEnd ();
p = p->next;
}
sc = sc->texturechain;
}
#endif
glColor3ubv (lighthalf_v);
#if 0
glDisable (GL_TEXTURE_2D);
sc = sky_chain;
glColor3f (1, 1, 1);
while (sc) {
glpoly_t *p = sc->polys;
while (p) {
int i;
glBegin (GL_LINE_LOOP);
for (i = 0; i < p->numverts; i++) {
glVertex3fv (p->verts[i]);
}
glEnd ();
p = p->next;
}
sc = sc->texturechain;
}
sc = sky_chain;
glColor3f (0, 1, 0);
glBegin (GL_POINTS);
while (sc) {
glpoly_t *p = sc->polys;
while (p) {
int i;
vec3_t x, c = { 0, 0, 0 };
for (i = 0; i < p->numverts; i++) {
VectorSubtract (p->verts[i], r_refdef.vieworg, x);
VectorAdd (x, c, c);
}
VectorScale (c, 1.0 / p->numverts, c);
VectorAdd (c, r_refdef.vieworg, c);
glVertex3fv (c);
p = p->next;
}
sc = sc->texturechain;
}
glEnd ();
if (skyloaded) {
int i, j;
glColor3f (1, 0, 0);
for (i = 0; i < 6; i++) {
vec3_t v;
glBegin (GL_LINE_LOOP);
for (j = 0; j < 4; j++) {
memcpy (v, &skyvec[i][j][2], sizeof (v));
VectorAdd (v, r_refdef.vieworg, v);
glVertex3fv (v);
}
glEnd ();
}
}
glColor3ubv (lighthalf_v);
glEnable (GL_TEXTURE_2D);
#endif
}

View file

@ -1,7 +1,7 @@
/*
gl_warp.c
sky and water polygons
water polygons
Copyright (C) 1996-1997 Id Software, Inc.
@ -29,41 +29,17 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "QF/qtypes.h"
#include "QF/compat.h"
#include "QF/console.h"
#include "QF/model.h"
#include "QF/quakefs.h"
#include "QF/cvar.h"
#include "QF/sys.h"
#include "QF/vid.h"
#include "glquake.h"
#include "render.h"
extern double realtime;
extern model_t *loadmodel;
extern int skytexturenum;
extern qboolean lighthalf;
int solidskytexture;
int alphaskytexture;
float speedscale; // for top sky and bottom sky
// Set to true if a valid skybox is loaded --KB
qboolean skyloaded = false;
msurface_t *warpface;
extern cvar_t *gl_subdivide_size;
@ -173,13 +149,11 @@ SubdividePolygon (int numverts, float *verts)
/*
================
GL_SubdivideSurface
GL_SubdivideSurface
Breaks a polygon up along axial 64 unit
boundaries so that turbulent and sky warps
can be done reasonably.
================
Breaks a polygon up along axial 64 unit
boundaries so that turbulent and sky warps
can be done reasonably.
*/
void
GL_SubdivideSurface (msurface_t *fa)
@ -212,20 +186,19 @@ GL_SubdivideSurface (msurface_t *fa)
//=========================================================
// speed up sin calculations - Ed
float turbsin[] = {
# include "gl_warp_sin.h"
};
#define TURBSCALE (256.0 / (2 * M_PI))
/*
=============
EmitWaterPolys
EmitWaterPolys
Does a water warp on the pre-fragmented glpoly_t chain
=============
Does a water warp on the pre-fragmented glpoly_t chain
*/
void
EmitWaterPolys (msurface_t *fa)
@ -261,602 +234,3 @@ EmitWaterPolys (msurface_t *fa)
glEnd ();
}
}
/*
=================================================================
Quake 2 environment sky
=================================================================
*/
#define SKY_TEX 2000
/*
=========================================================
TARGA LOADING
=========================================================
*/
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
TargaHeader targa_header;
byte *targa_rgba;
int
fgetLittleShort (QFile *f)
{
byte b1, b2;
b1 = Qgetc (f);
b2 = Qgetc (f);
return (short) (b1 + b2 * 256);
}
int
fgetLittleLong (QFile *f)
{
byte b1, b2, b3, b4;
b1 = Qgetc (f);
b2 = Qgetc (f);
b3 = Qgetc (f);
b4 = Qgetc (f);
return b1 + (b2 << 8) + (b3 << 16) + (b4 << 24);
}
/*
=============
LoadTGA
=============
*/
void
LoadTGA (QFile *fin)
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
unsigned char red = 0, green = 0, blue = 0, alphabyte = 0;
targa_header.id_length = Qgetc (fin);
targa_header.colormap_type = Qgetc (fin);
targa_header.image_type = Qgetc (fin);
targa_header.colormap_index = fgetLittleShort (fin);
targa_header.colormap_length = fgetLittleShort (fin);
targa_header.colormap_size = Qgetc (fin);
targa_header.x_origin = fgetLittleShort (fin);
targa_header.y_origin = fgetLittleShort (fin);
targa_header.width = fgetLittleShort (fin);
targa_header.height = fgetLittleShort (fin);
targa_header.pixel_size = Qgetc (fin);
targa_header.attributes = Qgetc (fin);
if (targa_header.image_type != 2 && targa_header.image_type != 10)
Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
if (targa_header.colormap_type != 0
|| (targa_header.pixel_size != 32 && targa_header.pixel_size != 24))
Sys_Error
("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
columns = targa_header.width;
rows = targa_header.height;
numPixels = columns * rows;
targa_rgba = malloc (numPixels * 4);
if (targa_header.id_length != 0)
Qseek (fin, targa_header.id_length, SEEK_CUR); // skip TARGA image
// comment
if (targa_header.image_type == 2) { // Uncompressed, RGB images
for (row = rows - 1; row >= 0; row--) {
pixbuf = targa_rgba + row * columns * 4;
for (column = 0; column < columns; column++) {
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
alphabyte = Qgetc (fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
}
}
} else if (targa_header.image_type == 10) { // Runlength encoded RGB
// images
unsigned char packetHeader, packetSize, j;
for (row = rows - 1; row >= 0; row--) {
pixbuf = targa_rgba + row * columns * 4;
for (column = 0; column < columns;) {
packetHeader = Qgetc (fin);
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
alphabyte = 255;
break;
case 32:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
alphabyte = Qgetc (fin);
break;
}
for (j = 0; j < packetSize; j++) {
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
column++;
if (column == columns) { // run spans across rows
column = 0;
if (row > 0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row * columns * 4;
}
}
} else { // non run-length packet
for (j = 0; j < packetSize; j++) {
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
alphabyte = Qgetc (fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
column++;
if (column == columns) { // pixel packet run spans
//
//
// across rows
column = 0;
if (row > 0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row * columns * 4;
}
}
}
}
breakOut:;
}
}
Qclose (fin);
}
/*
==================
R_LoadSkys
==================
*/
char *suf[6] = { "rt", "bk", "lf", "ft", "up", "dn" };
void
R_LoadSkys (const char *skyname)
{
int i;
QFile *f;
char name[64];
if (strcasecmp (skyname, "none") == 0) {
skyloaded = false;
return;
}
skyloaded = true;
for (i = 0; i < 6; i++) {
glBindTexture (GL_TEXTURE_2D, SKY_TEX + i);
snprintf (name, sizeof (name), "env/%s%s.tga", skyname, suf[i]);
COM_FOpenFile (name, &f);
if (!f) {
Con_DPrintf ("Couldn't load %s\n", name);
skyloaded = false;
continue;
}
LoadTGA (f);
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA,
GL_UNSIGNED_BYTE, targa_rgba);
free (targa_rgba);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (!skyloaded)
Con_Printf ("Unable to load skybox %s, using normal sky\n", skyname);
}
void
R_SkyBoxPolyVec (vec5_t v)
{
// avoid interpolation seams
// s = s * (254.0/256.0) + (1.0/256.0);
// t = t * (254.0/256.0) + (1.0/256.0);
glTexCoord2fv (v);
glVertex3f (r_refdef.vieworg[0] + v[2],
r_refdef.vieworg[1] + v[3], r_refdef.vieworg[2] + v[4]);
}
#define ftc(x) (x * (254.0/256.0) + (1.0/256.0))
vec5_t skyvec[6][4] = {
{
// right
{ftc (1), ftc (0), 1024, 1024, 1024},
{ftc (1), ftc (1), 1024, 1024, -1024},
{ftc (0), ftc (1), -1024, 1024, -1024},
{ftc (0), ftc (0), -1024, 1024, 1024}
},
{
// back
{ftc (1), ftc (0), -1024, 1024, 1024},
{ftc (1), ftc (1), -1024, 1024, -1024},
{ftc (0), ftc (1), -1024, -1024, -1024},
{ftc (0), ftc (0), -1024, -1024, 1024}
},
{
// left
{ftc (1), ftc (0), -1024, -1024, 1024},
{ftc (1), ftc (1), -1024, -1024, -1024},
{ftc (0), ftc (1), 1024, -1024, -1024},
{ftc (0), ftc (0), 1024, -1024, 1024}
},
{
// front
{ftc (1), ftc (0), 1024, -1024, 1024},
{ftc (1), ftc (1), 1024, -1024, -1024},
{ftc (0), ftc (1), 1024, 1024, -1024},
{ftc (0), ftc (0), 1024, 1024, 1024}
},
{
// up
{ftc (1), ftc (0), 1024, -1024, 1024},
{ftc (1), ftc (1), 1024, 1024, 1024},
{ftc (0), ftc (1), -1024, 1024, 1024},
{ftc (0), ftc (0), -1024, -1024, 1024}
},
{
// down
{ftc (1), ftc (0), 1024, 1024, -1024},
{ftc (1), ftc (1), 1024, -1024, -1024},
{ftc (0), ftc (1), -1024, -1024, -1024},
{ftc (0), ftc (0), -1024, 1024, -1024}
}
};
#undef ftc
void
R_DrawSkyBox (void)
{
int i, j;
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_ALWAYS);
// glDisable (GL_BLEND);
// glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDepthRange (gldepthmax, gldepthmax);
if (lighthalf)
glColor3f (0.5, 0.5, 0.5);
else
glColor3f (1, 1, 1);
for (i = 0; i < 6; i++) {
glBindTexture (GL_TEXTURE_2D, SKY_TEX + i);
glBegin (GL_QUADS);
for (j = 0; j < 4; j++)
R_SkyBoxPolyVec (skyvec[i][j]);
glEnd ();
}
glColor3f (1, 1, 1);
glDepthFunc (GL_LEQUAL);
glEnable (GL_DEPTH_TEST);
glDepthRange (gldepthmin, gldepthmax);
}
vec3_t domescale;
void
R_DrawSkyLayer (float s)
{
int a, b;
float x, y, a1x, a1y, a2x, a2y;
vec3_t v;
for (a = 0; a < 16; a++) {
a1x = bubble_costable[a * 2];
a1y = -bubble_sintable[a * 2];
a2x = bubble_costable[(a + 1) * 2];
a2y = -bubble_sintable[(a + 1) * 2];
glBegin (GL_TRIANGLE_STRIP);
glTexCoord2f (0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f (r_refdef.vieworg[0],
r_refdef.vieworg[1], r_refdef.vieworg[2] + domescale[2]);
for (b = 1; b < 8; b++) {
x = bubble_costable[b * 2 + 16];
y = -bubble_sintable[b * 2 + 16];
v[0] = a1x * x * domescale[0];
v[1] = a1y * x * domescale[1];
v[2] = y * domescale[2];
glTexCoord2f ((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f (v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1], v[2] + r_refdef.vieworg[2]);
v[0] = a2x * x * domescale[0];
v[1] = a2y * x * domescale[1];
v[2] = y * domescale[2];
glTexCoord2f ((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f (v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1], v[2] + r_refdef.vieworg[2]);
}
glTexCoord2f (0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f (r_refdef.vieworg[0],
r_refdef.vieworg[1], r_refdef.vieworg[2] - domescale[2]);
glEnd ();
}
}
void
R_DrawSkyDome (void)
{
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_ALWAYS);
// glDisable (GL_BLEND);
// glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthRange (gldepthmax, gldepthmax);
glDisable (GL_BLEND);
if (lighthalf)
glColor3f (0.5, 0.5, 0.5);
else
glColor3f (1, 1, 1);
// base sky
glBindTexture (GL_TEXTURE_2D, solidskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime * 8;
speedscale -= (int) speedscale & ~127;
R_DrawSkyLayer (speedscale);
glEnable (GL_BLEND);
// clouds
if (gl_skymultipass->int_val) {
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime * 16;
speedscale -= (int) speedscale & ~127;
R_DrawSkyLayer (speedscale);
}
// glDisable (GL_BLEND);
glColor3f (1, 1, 1);
glDepthFunc (GL_LEQUAL);
glEnable (GL_DEPTH_TEST);
glDepthRange (gldepthmin, gldepthmax);
}
void
R_DrawSky (void)
{
if (skyloaded)
R_DrawSkyBox ();
else
R_DrawSkyDome ();
}
//===============================================================
/*
=============
R_InitSky
A sky texture is 256*128, with the right side being a masked overlay
==============
*/
void
R_InitSky (texture_t *mt)
{
int i, j, p;
byte *src;
unsigned trans[128 * 128];
unsigned transpix;
int r, g, b;
unsigned *rgba;
src = (byte *) mt + mt->offsets[0];
// make an average value for the back to avoid
// a fringe on the top level
r = g = b = 0;
for (i = 0; i < 128; i++)
for (j = 0; j < 128; j++) {
p = src[i * 256 + j + 128];
rgba = &d_8to24table[p];
trans[(i * 128) + j] = *rgba;
r += ((byte *) rgba)[0];
g += ((byte *) rgba)[1];
b += ((byte *) rgba)[2];
}
((byte *) & transpix)[0] = r / (128 * 128);
((byte *) & transpix)[1] = g / (128 * 128);
((byte *) & transpix)[2] = b / (128 * 128);
((byte *) & transpix)[3] = 0;
if (!solidskytexture)
solidskytexture = texture_extension_number++;
glBindTexture (GL_TEXTURE_2D, solidskytexture);
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA,
GL_UNSIGNED_BYTE, trans);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
for (i = 0; i < 128; i++)
for (j = 0; j < 128; j++) {
p = src[i * 256 + j];
if (p == 0)
trans[(i * 128) + j] = transpix;
else
trans[(i * 128) + j] = d_8to24table[p];
}
if (!alphaskytexture)
alphaskytexture = texture_extension_number++;
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA,
GL_UNSIGNED_BYTE, trans);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void
EmitSkyPolys (msurface_t *fa)
{
glpoly_t *p;
float *v;
int i;
float s, t;
vec3_t dir;
float length;
for (p = fa->polys; p; p = p->next) {
glBegin (GL_POLYGON);
for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) {
VectorSubtract (v, r_origin, dir);
dir[2] *= 3; // flatten the sphere
length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2];
length = sqrt (length);
length = 6 * 63 / length;
dir[0] *= length;
dir[1] *= length;
s = (speedscale + dir[0]) * (1.0 / 128);
t = (speedscale + dir[1]) * (1.0 / 128);
glTexCoord2f (s, t);
glVertex3fv (v);
}
glEnd ();
}
}
void
R_DrawSkyChain (msurface_t *s)
{
msurface_t *fa;
// used when gl_texsort is on
glBindTexture (GL_TEXTURE_2D, solidskytexture);
speedscale = realtime * 8;
speedscale -= (int) speedscale & ~127;
for (fa = s; fa; fa = fa->texturechain)
EmitSkyPolys (fa);
glEnable (GL_BLEND);
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
speedscale = realtime * 16;
speedscale -= (int) speedscale & ~127;
for (fa = s; fa; fa = fa->texturechain)
EmitSkyPolys (fa);
glDisable (GL_BLEND);
}
/*
===============
EmitBothSkyLayers
Does a sky warp on the pre-fragmented glpoly_t chain
This will be called for brushmodels, the world
will have them chained together.
===============
*/
void
EmitBothSkyLayers (msurface_t *fa)
{
glBindTexture (GL_TEXTURE_2D, solidskytexture);
speedscale = realtime * 8;
speedscale -= (int) speedscale & ~127;
EmitSkyPolys (fa);
glEnable (GL_BLEND);
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
speedscale = realtime * 16;
speedscale -= (int) speedscale & ~127;
EmitSkyPolys (fa);
glDisable (GL_BLEND);
}

View file

@ -157,7 +157,7 @@ Host_Error (char *error, ...)
Sys_Error ("Host_Error: recursively entered");
inerror = true;
SCR_EndLoadingPlaque (); // reenable screen updates
// SCR_EndLoadingPlaque (); // reenable screen updates
va_start (argptr, error);
vsnprintf (string, sizeof (string), error, argptr);

View file

@ -279,7 +279,7 @@ Host_Map_f (void)
Host_ShutdownServer (false);
key_dest = key_game; // remove console or menu
SCR_BeginLoadingPlaque ();
// SCR_BeginLoadingPlaque ();
cls.mapstring[0] = 0;
for (i = 0; i < Cmd_Argc (); i++) {
@ -404,7 +404,7 @@ This is sent just before a server changes levels
void
Host_Reconnect_f (void)
{
SCR_BeginLoadingPlaque ();
// SCR_BeginLoadingPlaque ();
cls.signon = 0; // need new connection messages
}

206
nq/source/pcx.c Normal file
View file

@ -0,0 +1,206 @@
/*
pcx.c
pcx image handling
Copyright (C) 1996-1997 Id Software, Inc.
This program 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.
This program 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 this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/console.h"
#include "QF/pcx.h"
#include "QF/qendian.h"
#include "QF/qtypes.h"
#include "QF/quakefs.h"
#include "QF/texture.h"
#include "QF/vid.h"
#include "QF/zone.h"
tex_t *
LoadPCX (QFile *f, int convert)
{
pcx_t *pcx;
int pcx_mark;
byte *palette;
byte *pix;
byte *dataByte;
int x, y;
int runLength = 1;
int count;
tex_t *tex;
//
// parse the PCX file
//
pcx_mark = Hunk_LowMark ();
pcx = Hunk_AllocName (com_filesize, "PCX");
Qread (f, pcx, com_filesize);
pcx->xmax = LittleShort (pcx->xmax);
pcx->xmin = LittleShort (pcx->xmin);
pcx->ymax = LittleShort (pcx->ymax);
pcx->ymin = LittleShort (pcx->ymin);
pcx->hres = LittleShort (pcx->hres);
pcx->vres = LittleShort (pcx->vres);
pcx->bytes_per_line = LittleShort (pcx->bytes_per_line);
pcx->palette_type = LittleShort (pcx->palette_type);
if (pcx->manufacturer != 0x0a
|| pcx->version != 5
|| pcx->encoding != 1
|| pcx->bits_per_pixel != 8 || pcx->xmax >= 320 || pcx->ymax >= 256) {
Con_Printf ("Bad pcx file\n");
return 0;
}
palette = ((byte*)pcx) + com_filesize - 768;
dataByte = (byte*)&pcx[1];
count = (pcx->xmax + 1) * (pcx->ymax + 1);
if (convert)
count *= 4;
tex = Hunk_TempAlloc (sizeof (tex_t) + count);
tex->width = pcx->xmax + 1;
tex->height = pcx->ymax + 1;
if (convert) {
tex->palette = 0;
} else {
tex->palette = vid_basepal;
}
pix = tex->data;
for (y = 0; y < tex->height; y++) {
for (x = 0; x < tex->width;) {
runLength = 1;
if (dataByte >= palette)
break;
if ((*dataByte & 0xC0) == 0xC0) {
runLength = *dataByte++ & 0x3F;
if (dataByte >= palette)
break;
}
if (convert) {
while (count && runLength > 0) {
pix[0] = palette[*dataByte * 3];
pix[1] = palette[*dataByte * 3 + 1];
pix[2] = palette[*dataByte * 3 + 2];
pix[3] = 255;
pix += 4;
count -= 4;
runLength--;
x++;
}
} else {
while (count && runLength > 0) {
*pix++ = *dataByte;
count--;
runLength--;
x++;
}
}
if (runLength)
break;
dataByte++;
}
if (runLength)
break;
}
Hunk_FreeToLowMark (pcx_mark);
if (count || runLength) {
Con_Printf ("PCX was malformed. You should delete it.\n");
return 0;
}
return tex;
}
pcx_t *
EncodePCX (byte * data, int width, int height,
int rowbytes, byte * palette, qboolean flip, int *length)
{
int i, j;
pcx_t *pcx;
byte *pack;
if (!(pcx = Hunk_TempAlloc (width * height * 2 + 1000))) {
Con_Printf ("EncodePCX: not enough memory\n");
return 0;
}
pcx->manufacturer = 0x0a; // PCX id
pcx->version = 5; // 256 color
pcx->encoding = 1; // uncompressed
pcx->bits_per_pixel = 8; // 256 color
pcx->xmin = 0;
pcx->ymin = 0;
pcx->xmax = LittleShort ((short) (width - 1));
pcx->ymax = LittleShort ((short) (height - 1));
pcx->hres = LittleShort ((short) width);
pcx->vres = LittleShort ((short) height);
memset (pcx->palette, 0, sizeof (pcx->palette));
pcx->color_planes = 1; // chunky image
pcx->bytes_per_line = LittleShort ((short) width);
pcx->palette_type = LittleShort (2); // not a grey scale
memset (pcx->filler, 0, sizeof (pcx->filler));
// pack the image
pack = (byte*)&pcx[1];
if (flip)
data += rowbytes * (height - 1);
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
if ((*data & 0xc0) != 0xc0)
*pack++ = *data++;
else {
*pack++ = 0xc1;
*pack++ = *data++;
}
}
data += rowbytes - width;
if (flip)
data -= rowbytes * 2;
}
// write the palette
*pack++ = 0x0c; // palette ID byte
for (i = 0; i < 768; i++)
*pack++ = *palette++;
// write output file
*length = pack - (byte *) pcx;
return pcx;
}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*
r_draw.c
@description@
(description)
Copyright (C) 1996-1997 Id Software, Inc.
@ -78,12 +78,10 @@ int r_ceilv1;
qboolean r_lastvertvalid;
#ifndef USE_INTEL_ASM
#ifndef USE_INTEL_ASM
/*
================
R_EmitEdge
================
R_EmitEdge
*/
void
R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
@ -250,9 +248,7 @@ R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
/*
================
R_ClipEdge
================
R_ClipEdge
*/
void
R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
@ -335,13 +331,11 @@ R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
R_EmitEdge (pv0, pv1);
}
#endif // USE_INTEL_ASM
#endif // !USE_INTEL_ASM
/*
================
R_EmitCachedEdge
================
R_EmitCachedEdge
*/
void
R_EmitCachedEdge (void)
@ -363,15 +357,13 @@ R_EmitCachedEdge (void)
/*
================
R_RenderFace
================
R_RenderFace
*/
void
R_RenderFace (msurface_t *fa, int clipflags)
{
int i, lindex;
unsigned mask;
unsigned int mask;
mplane_t *pplane;
float distinv;
vec3_t p_normal;
@ -534,15 +526,13 @@ R_RenderFace (msurface_t *fa, int clipflags)
/*
================
R_RenderBmodelFace
================
R_RenderBmodelFace
*/
void
R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
{
int i;
unsigned mask;
unsigned int mask;
mplane_t *pplane;
float distinv;
vec3_t p_normal;
@ -639,16 +629,14 @@ R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
/*
================
R_RenderPoly
================
R_RenderPoly
*/
void
R_RenderPoly (msurface_t *fa, int clipflags)
{
int i, lindex, lnumverts, s_axis, t_axis;
float dist, lastdist, lzi, scale, u, v, frac;
unsigned mask;
unsigned int mask;
vec3_t local, transformed;
clipplane_t *pclip;
medge_t *pedges;
@ -746,19 +734,19 @@ R_RenderPoly (msurface_t *fa, int clipflags)
switch (pplane->type) {
case PLANE_X:
case PLANE_ANYX:
s_axis = 1;
t_axis = 2;
break;
s_axis = 1;
t_axis = 2;
break;
case PLANE_Y:
case PLANE_ANYY:
s_axis = 0;
t_axis = 2;
break;
s_axis = 0;
t_axis = 2;
break;
case PLANE_Z:
case PLANE_ANYZ:
s_axis = 0;
t_axis = 1;
break;
s_axis = 0;
t_axis = 1;
break;
}
r_nearzi = 0;
@ -811,9 +799,7 @@ R_RenderPoly (msurface_t *fa, int clipflags)
/*
================
R_ZDrawSubmodelPolys
================
R_ZDrawSubmodelPolys
*/
void
R_ZDrawSubmodelPolys (model_t *pmodel)

View file

@ -1,7 +1,7 @@
/*
r_sky.c
@description@
(description)
Copyright (C) 1996-1997 Id Software, Inc.
@ -32,7 +32,6 @@
#include "client.h"
#include "r_local.h"
#include "d_local.h"
int iskyspeed = 8;
@ -60,11 +59,9 @@ byte newsky[128 * 256]; // newsky and topsky both pack in
/*
=============
R_InitSky
R_InitSky
A sky texture is 256*128, with the right side being a masked overlay
==============
A sky texture is 256*128, with the right side being a masked overlay
*/
void
R_InitSky (texture_t *mt)
@ -97,9 +94,7 @@ R_InitSky (texture_t *mt)
/*
=================
R_MakeSky
=================
R_MakeSky
*/
void
R_MakeSky (void)
@ -107,7 +102,7 @@ R_MakeSky (void)
int x, y;
int ofs, baseofs;
int xshift, yshift;
unsigned *pnewsky;
unsigned int *pnewsky;
static int xlast = -1, ylast = -1;
xshift = skytime * skyspeed;
@ -119,7 +114,7 @@ R_MakeSky (void)
xlast = xshift;
ylast = yshift;
pnewsky = (unsigned *) &newsky[0];
pnewsky = (unsigned int *) &newsky[0];
for (y = 0; y < SKYSIZE; y++) {
baseofs = ((y + yshift) & SKYMASK) * 131;
@ -132,9 +127,9 @@ R_MakeSky (void)
// PORT: unaligned dword access to bottommask and bottomsky
*pnewsky = (*(pnewsky + (128 / sizeof (unsigned))) &
*(unsigned *) &bottommask[ofs]) |
*(unsigned *) &bottomsky[ofs];
*pnewsky = (*(pnewsky + (128 / sizeof (unsigned int))) &
*(unsigned int *) &bottommask[ofs]) |
*(unsigned int *) &bottomsky[ofs];
pnewsky++;
}
@ -147,12 +142,12 @@ R_MakeSky (void)
*(byte *) pnewsky = (*((byte *) pnewsky + 128) &
*(byte *) & bottommask[ofs]) |
*(byte *) & bottomsky[ofs];
pnewsky = (unsigned *) ((byte *) pnewsky + 1);
pnewsky = (unsigned int *) ((byte *) pnewsky + 1);
}
#endif
pnewsky += 128 / sizeof (unsigned);
pnewsky += 128 / sizeof (unsigned int);
}
r_skymade = 1;
@ -160,9 +155,7 @@ R_MakeSky (void)
/*
=================
R_GenSkyTile
=================
R_GenSkyTile
*/
void
R_GenSkyTile (void *pdest)
@ -170,14 +163,14 @@ R_GenSkyTile (void *pdest)
int x, y;
int ofs, baseofs;
int xshift, yshift;
unsigned *pnewsky;
unsigned *pd;
unsigned int *pnewsky;
unsigned int *pd;
xshift = skytime * skyspeed;
yshift = skytime * skyspeed;
pnewsky = (unsigned *) &newsky[0];
pd = (unsigned *) pdest;
pnewsky = (unsigned int *) &newsky[0];
pd = (unsigned int *) pdest;
for (y = 0; y < SKYSIZE; y++) {
baseofs = ((y + yshift) & SKYMASK) * 131;
@ -190,10 +183,10 @@ R_GenSkyTile (void *pdest)
// PORT: unaligned dword access to bottommask and bottomsky
*pd = (*(pnewsky + (128 / sizeof (unsigned))) &
*(unsigned *) &bottommask[ofs]) |
*pd = (*(pnewsky + (128 / sizeof (unsigned int))) &
*(unsigned int *) &bottommask[ofs]) |
*(unsigned int *) &bottomsky[ofs];
*(unsigned *) &bottomsky[ofs];
pnewsky++;
pd++;
}
@ -206,21 +199,19 @@ R_GenSkyTile (void *pdest)
*(byte *) pd = (*((byte *) pnewsky + 128) &
*(byte *) & bottommask[ofs]) |
*(byte *) & bottomsky[ofs];
pnewsky = (unsigned *) ((byte *) pnewsky + 1);
pd = (unsigned *) ((byte *) pd + 1);
pnewsky = (unsigned int *) ((byte *) pnewsky + 1);
pd = (unsigned int *) ((byte *) pd + 1);
}
#endif
pnewsky += 128 / sizeof (unsigned);
pnewsky += 128 / sizeof (unsigned int);
}
}
/*
=================
R_GenSkyTile16
=================
R_GenSkyTile16
*/
void
R_GenSkyTile16 (void *pdest)
@ -258,9 +249,7 @@ R_GenSkyTile16 (void *pdest)
/*
=============
R_SetSkyFrame
==============
R_SetSkyFrame
*/
void
R_SetSkyFrame (void)
@ -281,3 +270,15 @@ R_SetSkyFrame (void)
r_skymade = 0;
}
/*
R_LoadSkys
Stub function for loading a skybox. Currently we only have support for
skyboxes in GL targets, so we just do nothing here. --KB
*/
void
R_LoadSkys (const char *name)
{
}

244
nq/source/tga.c Normal file
View file

@ -0,0 +1,244 @@
/*
tga.c
targa image handling
Copyright (C) 1996-1997 Id Software, Inc.
This program 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.
This program 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 this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include "QF/qendian.h"
#include "QF/quakefs.h"
#include "QF/sys.h"
#include "QF/tga.h"
static int
fgetLittleShort (QFile *f)
{
byte b1, b2;
b1 = Qgetc (f);
b2 = Qgetc (f);
return (short) (b1 + b2 * 256);
}
/*
static int
fgetLittleLong (QFile *f)
{
byte b1, b2, b3, b4;
b1 = Qgetc(f);
b2 = Qgetc(f);
b3 = Qgetc(f);
b4 = Qgetc(f);
return b1 + (b2<<8) + (b3<<16) + (b4<<24);
}
*/
byte *
LoadTGA (QFile *fin)
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
unsigned char red = 0, green = 0, blue = 0, alphabyte = 0;
TargaHeader targa_header;
byte *targa_rgba;
targa_header.id_length = Qgetc (fin);
targa_header.colormap_type = Qgetc (fin);
targa_header.image_type = Qgetc (fin);
targa_header.colormap_index = fgetLittleShort (fin);
targa_header.colormap_length = fgetLittleShort (fin);
targa_header.colormap_size = Qgetc (fin);
targa_header.x_origin = fgetLittleShort (fin);
targa_header.y_origin = fgetLittleShort (fin);
targa_header.width = fgetLittleShort (fin);
targa_header.height = fgetLittleShort (fin);
targa_header.pixel_size = Qgetc (fin);
targa_header.attributes = Qgetc (fin);
if (targa_header.image_type != 2 && targa_header.image_type != 10)
Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
if (targa_header.colormap_type != 0
|| (targa_header.pixel_size != 32 && targa_header.pixel_size != 24))
Sys_Error
("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
columns = targa_header.width;
rows = targa_header.height;
numPixels = columns * rows;
targa_rgba = malloc (numPixels * 4);
if (targa_header.id_length != 0)
Qseek (fin, targa_header.id_length, SEEK_CUR); // skip TARGA image
// comment
if (targa_header.image_type == 2) { // Uncompressed, RGB images
for (row = rows - 1; row >= 0; row--) {
pixbuf = targa_rgba + row * columns * 4;
for (column = 0; column < columns; column++) {
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
alphabyte = Qgetc (fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
}
}
} else if (targa_header.image_type == 10) { // Runlength encoded RGB
// images
unsigned char packetHeader, packetSize, j;
for (row = rows - 1; row >= 0; row--) {
pixbuf = targa_rgba + row * columns * 4;
for (column = 0; column < columns;) {
packetHeader = Qgetc (fin);
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
alphabyte = 255;
break;
case 32:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
alphabyte = Qgetc (fin);
break;
}
for (j = 0; j < packetSize; j++) {
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
column++;
if (column == columns) { // run spans across rows
column = 0;
if (row > 0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row * columns * 4;
}
}
} else { // non run-length packet
for (j = 0; j < packetSize; j++) {
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = Qgetc (fin);
green = Qgetc (fin);
red = Qgetc (fin);
alphabyte = Qgetc (fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
column++;
if (column == columns) { // pixel packet run spans
// across rows
column = 0;
if (row > 0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row * columns * 4;
}
}
}
}
breakOut:;
}
}
Qclose (fin);
return targa_rgba;
}
void
WriteTGAfile (const char *tganame, byte *data, int width, int height)
{
TargaHeader header;
memset (&header, 0, sizeof (header));
header.image_type = 2; // uncompressed type
header.width = LittleShort (width);
header.height = LittleShort (height);
header.pixel_size = 24;
COM_WriteBuffers (tganame, 2, &header, sizeof (header), data,
width * height * 3);
}

View file

@ -603,10 +603,8 @@ Draw_ConsoleBackground (int lines)
}
}
if (!cls.download)
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string)
* 8 - 11, lines - 14, cl_verstring->string);
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string)
* 8 - 11, lines - 14, cl_verstring->string);
}

View file

@ -642,10 +642,9 @@ Draw_ConsoleBackground (int lines)
glMatrixMode (GL_MODELVIEW);
glPopMatrix ();
}
// draw version string if not downloading
if (!cls.download)
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string) * 8 - 11,
lines - 14, cl_verstring->string);
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string) * 8 - 11,
lines - 14, cl_verstring->string);
glColor3ubv (lighthalf_v);
}