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 \ 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 \ 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 \ 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 \ 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 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 \ 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_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_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 # ... 3Dfx Voodoo 1 and 2 SVGAlib-based console GL
nq_3dfx_SOURCES= $(combined_SOURCES) $(ogl_SOURCES) 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 Sends a disconnect message to the server
This is also called on Host_Error, so it shouldn't cause any errors This is also called on Host_Error, so it shouldn't cause any errors
=====================
*/ */
void void
CL_Disconnect (void) CL_Disconnect (void)
@ -215,6 +213,7 @@ CL_Disconnect (void)
cls.signon = 0; cls.signon = 0;
} }
void void
CL_Disconnect_f (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 void
CL_EstablishConnection (char *host) 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 void
CL_SignonReply (void) CL_SignonReply (void)
@ -295,18 +290,16 @@ CL_SignonReply (void)
break; break;
case 4: case 4:
SCR_EndLoadingPlaque (); // allow normal screen updates // SCR_EndLoadingPlaque (); // allow normal screen updates
break; 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 void
CL_NextDemo (void) CL_NextDemo (void)
@ -316,8 +309,6 @@ CL_NextDemo (void)
if (cls.demonum == -1) if (cls.demonum == -1)
return; // don't play demos return; // don't play demos
SCR_BeginLoadingPlaque ();
if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) { if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) {
cls.demonum = 0; cls.demonum = 0;
if (!cls.demos[cls.demonum][0]) { if (!cls.demos[cls.demonum][0]) {

View file

@ -1,7 +1,7 @@
/* /*
d_sky.c d_sky.c
@description@ (description)
Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1996-1997 Id Software, Inc.
@ -39,9 +39,7 @@
/* /*
=================
D_Sky_uv_To_st D_Sky_uv_To_st
=================
*/ */
void void
D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
@ -71,9 +69,7 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
/* /*
=================
D_DrawSkyScans8 D_DrawSkyScans8
=================
*/ */
void void
D_DrawSkyScans8 (espan_t *pspan) D_DrawSkyScans8 (espan_t *pspan)

View file

@ -1,7 +1,7 @@
/* /*
draw.c draw.c
@description@ this is the only file outside the refresh that touches the vid buffer
Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1996-1997 Id Software, Inc.
@ -29,14 +29,20 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
#endif #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/draw.h"
#include "QF/quakefs.h" #include "QF/quakefs.h"
#include "QF/sound.h" #include "QF/sound.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/vid.h"
#include "QF/zone.h"
#include "client.h"
#include "d_iface.h" #include "d_iface.h"
typedef struct { typedef struct {
@ -53,6 +59,8 @@ byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_disc; qpic_t *draw_disc;
qpic_t *draw_backtile; qpic_t *draw_backtile;
cvar_t *cl_verstring;
//============================================================================= //=============================================================================
/* Support Routines */ /* 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 * qpic_t *
Draw_CachePic (char *path, qboolean alpha) 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 void
Draw_Init (void) Draw_Init (void)
{ {
@ -129,21 +195,25 @@ Draw_Init (void)
r_rectdesc.height = draw_backtile->height; r_rectdesc.height = draw_backtile->height;
r_rectdesc.ptexbytes = draw_backtile->data; r_rectdesc.ptexbytes = draw_backtile->data;
r_rectdesc.rowbytes = draw_backtile->width; r_rectdesc.rowbytes = draw_backtile->width;
cl_verstring =
Cvar_Get ("cl_verstring", PROGRAM " " VERSION, CVAR_NONE, NULL,
"Client version string");
} }
void void
Draw_Init_Cvars (void) Draw_Init_Cvars (void)
{ {
} }
/* /*
================
Draw_Character8 Draw_Character8
Draws one 8*8 graphics character with 0 being transparent. 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 It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off. smoothly scrolled off.
================
*/ */
void void
Draw_Character8 (int x, int y, int num) Draw_Character8 (int x, int y, int num)
@ -159,12 +229,10 @@ Draw_Character8 (int x, int y, int num)
if (y <= -8) if (y <= -8)
return; // totally off screen return; // totally off screen
#ifdef PARANOID
if (y > vid.height - 8 || x < 0 || x > vid.width - 8) 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) if (num < 0 || num > 255)
Sys_Error ("Con_DrawCharacter: char %i", num); return;
#endif
row = num >> 4; row = num >> 4;
col = num & 15; col = num & 15;
@ -230,11 +298,7 @@ Draw_Character8 (int x, int y, int num)
} }
} }
/*
================
Draw_String8
================
*/
void void
Draw_String8 (int x, int y, char *str) 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 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 *dest;
byte *source; unsigned short *pusdest;
int drawline;
extern byte *draw_chars;
int row, col;
if (!vid.direct) if (r_pixbytes == 1) {
return; // don't have direct FB access, so no dest = vid.conbuffer + y * vid.conrowbytes + x;
// *dest = color;
// } else {
// debugchars... // FIXME: pre-expand to native format?
pusdest = (unsigned short *)
drawline = 8; ((byte *) vid.conbuffer + y * vid.conrowbytes + (x << 1));
*pusdest = d_8to16table[color];
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;
} }
} }
/*
============= void
Draw_Pic 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 void
Draw_Pic (int x, int y, qpic_t *pic) 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; byte *dest, *source, tbyte;
unsigned short *pusdest; unsigned short *pusdest;
int v, u; int v, u;
if (x < 0 || (unsigned) (x + pic->width) > vid.width || y < 0 || if (x < 0 || (unsigned int) (x + pic->width) > vid.width || y < 0 ||
(unsigned) (y + pic->height) > vid.height) { (unsigned int) (y + pic->height) > vid.height) {
Sys_Error ("Draw_TransPic: bad coordinates"); Sys_Error ("Draw_Pic: bad coordinates");
} }
source = pic->data; source = pic->data;
@ -454,11 +436,45 @@ Draw_TransPic (int x, int y, qpic_t *pic)
} }
/* void
============= Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
Draw_TransPicTranslate 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 void
Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte * translation) 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; unsigned short *pusdest;
int v, u; int v, u;
if (x < 0 || (unsigned) (x + pic->width) > vid.width || y < 0 || if (x < 0 || (unsigned int) (x + pic->width) > vid.width || y < 0 ||
(unsigned) (y + pic->height) > vid.height) { (unsigned int) (y + pic->height) > vid.height) {
Sys_Error ("Draw_TransPic: bad coordinates"); 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 void
Draw_ConsoleBackground (int lines) Draw_ConsoleBackground (int lines)
{ {
@ -565,7 +554,7 @@ Draw_ConsoleBackground (int lines)
int f, fstep; int f, fstep;
qpic_t *conback; 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) { if (r_pixbytes == 1) {
@ -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 void
R_DrawRect8 (vrect_t *prect, int rowbytes, byte * psrc, int transparent) 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 void
R_DrawRect16 (vrect_t *prect, int rowbytes, byte * psrc, int transparent) 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 This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window. refresh window.
=============
*/ */
void void
Draw_TileClear (int x, int y, int w, int h) Draw_TileClear (int x, int y, int w, int h)
@ -780,20 +760,23 @@ Draw_TileClear (int x, int y, int w, int h)
/* /*
=============
Draw_Fill Draw_Fill
Fills a box of pixels with a single color Fills a box of pixels with a single color
=============
*/ */
void void
Draw_Fill (int x, int y, int w, int h, int c) Draw_Fill (int x, int y, int w, int h, int c)
{ {
byte *dest; byte *dest;
unsigned short *pusdest; unsigned short *pusdest;
unsigned uc; unsigned int uc;
int u, v; 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) { if (r_pixbytes == 1) {
dest = vid.buffer + y * vid.rowbytes + x; dest = vid.buffer + y * vid.rowbytes + x;
for (v = 0; v < h; v++, dest += vid.rowbytes) 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; pusdest[u] = uc;
} }
} }
//============================================================================= //=============================================================================
/*
================
Draw_FadeScreen
================
*/
void void
Draw_FadeScreen (void) Draw_FadeScreen (void)
{ {
@ -843,15 +823,15 @@ Draw_FadeScreen (void)
VID_LockBuffer (); VID_LockBuffer ();
} }
//============================================================================= //=============================================================================
/* /*
================
Draw_BeginDisc Draw_BeginDisc
Draws the little blue disc in the corner of the screen. Draws the little blue disc in the corner of the screen.
Call before beginning any disc IO. Call before beginning any disc IO.
================
*/ */
void void
Draw_BeginDisc (void) Draw_BeginDisc (void)
@ -862,12 +842,10 @@ Draw_BeginDisc (void)
/* /*
================
Draw_EndDisc Draw_EndDisc
Erases the disc icon. Erases the disc icon.
Call after completing any disc IO Call after completing any disc IO
================
*/ */
void void
Draw_EndDisc (void) Draw_EndDisc (void)
@ -875,42 +853,3 @@ Draw_EndDisc (void)
D_EndDirectRect (vid.width - 24, 0, 24, 24); 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 (); R_ForceLightUpdate ();
} }
void void
Draw_Init (void) Draw_Init (void)
{ {
@ -315,6 +316,7 @@ Draw_Init (void)
glrsurf_init (); glrsurf_init ();
} }
void void
Draw_Init_Cvars (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 Draw_TransPicTranslate
@ -603,7 +603,7 @@ Draw_ConsoleBackground (int lines)
else else
ofs = (vid.conheight - lines) / (float) vid.conheight; 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) { if (cls.state != ca_active || lines > y) {
alpha = 1.0; alpha = 1.0;
} else { } else {
@ -642,7 +642,7 @@ Draw_ConsoleBackground (int lines)
glMatrixMode (GL_MODELVIEW); glMatrixMode (GL_MODELVIEW);
glPopMatrix (); glPopMatrix ();
} }
// draw version string if not downloading
Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string) * 8 - 11, Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string) * 8 - 11,
lines - 14, cl_verstring->string); lines - 14, cl_verstring->string);
glColor3ubv (lighthalf_v); glColor3ubv (lighthalf_v);
@ -705,11 +705,10 @@ Draw_Fill (int x, int y, int w, int h, int c)
glEnable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_2D);
} }
//============================================================================= //=============================================================================
/*
Draw_FadeScreen
*/
void void
Draw_FadeScreen (void) Draw_FadeScreen (void)
{ {
@ -729,8 +728,10 @@ Draw_FadeScreen (void)
Sbar_Changed (); Sbar_Changed ();
} }
//============================================================================= //=============================================================================
/* /*
Draw_BeginDisc Draw_BeginDisc

View file

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

View file

@ -1,7 +1,7 @@
/* /*
gl_screen.c gl_screen.c
@description@ master for refresh, status bar, console, chat, notify, etc
Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1996-1997 Id Software, Inc.
@ -36,33 +36,23 @@
# include <strings.h> # include <strings.h>
#endif #endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> #include <time.h>
#include "QF/cmd.h" #include "QF/cmd.h"
#include "QF/console.h"
#include "QF/compat.h" #include "QF/compat.h"
#include "QF/cvar.h" #include "QF/console.h"
#include "QF/draw.h" #include "QF/draw.h"
#include "QF/input.h"
#include "QF/keys.h" #include "QF/keys.h"
#include "QF/mathlib.h" #include "QF/pcx.h"
#include "QF/model.h" #include "QF/skin.h"
#include "QF/qendian.h"
#include "QF/screen.h"
#include "QF/sound.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/vid.h" #include "QF/tga.h"
#include "QF/wad.h"
//#include "cl_parse.h"
#include "client.h" #include "client.h"
#include "glquake.h" #include "glquake.h"
#include "net.h" #include "host.h"
#include "protocol.h"
#include "r_local.h" #include "r_local.h"
#include "render.h"
#include "sbar.h" #include "sbar.h"
#include "view.h" #include "view.h"
@ -103,7 +93,7 @@ Con_Printf ();
net net
turn off messages option turn off messages option
the refresh is always rendered, unless the console is full screen the refresh is allways rendered, unless the console is full screen
console is: console is:
@ -111,11 +101,10 @@ console is:
half half
full full
*/ */
extern byte *vid_basepal;
extern double host_frametime;
extern double realtime;
int glx, gly, glwidth, glheight; int glx, gly, glwidth, glheight;
// only the refresh window will be updated unless these variables are flagged // only the refresh window will be updated unless these variables are flagged
@ -125,18 +114,22 @@ int scr_copyeverything;
float scr_con_current; float scr_con_current;
float scr_conlines; // lines of console to display float scr_conlines; // lines of console to display
float oldscreensize, oldfov; int oldscreensize, oldfov;
int oldsbar;
cvar_t *scr_viewsize; cvar_t *scr_viewsize;
cvar_t *scr_fov; // 10 - 170 cvar_t *scr_fov; // 10 - 170
cvar_t *scr_conspeed; cvar_t *scr_conspeed;
cvar_t *scr_consize;
cvar_t *scr_centertime; cvar_t *scr_centertime;
cvar_t *scr_showram; cvar_t *scr_showram;
cvar_t *scr_showturtle; cvar_t *scr_showturtle;
cvar_t *scr_showpause; cvar_t *scr_showpause;
cvar_t *scr_printspeed; cvar_t *scr_printspeed;
cvar_t *scr_allowsnap;
cvar_t *gl_triplebuffer; cvar_t *gl_triplebuffer;
extern cvar_t *crosshair; cvar_t *crosshair;
cvar_t *crosshaircolor;
cvar_t *cl_crossx;
cvar_t *cl_crossy;
qboolean scr_initialized; // ready to draw qboolean scr_initialized; // ready to draw
@ -156,12 +149,12 @@ viddef_t vid; // global video state
vrect_t scr_vrect; vrect_t scr_vrect;
qboolean scr_disabled_for_loading; qboolean scr_disabled_for_loading;
qboolean scr_drawloading;
float scr_disabled_time; float scr_disabled_time;
qboolean block_drawing; qboolean block_drawing;
void SCR_ScreenShot_f (void); void SCR_ScreenShot_f (void);
void SCR_RSShot_f (void);
/* /*
CENTER PRINTING CENTER PRINTING
@ -178,8 +171,8 @@ int scr_erase_center;
/* /*
SCR_CenterPrint SCR_CenterPrint
Called for important messages that should stay in the center of the Called for important messages that should stay in the center of the screen
screen for a few moments for a few moments
*/ */
void void
SCR_CenterPrint (char *str) SCR_CenterPrint (char *str)
@ -262,6 +255,7 @@ SCR_CheckDrawCenterString (void)
SCR_DrawCenterString (); SCR_DrawCenterString ();
} }
//============================================================================= //=============================================================================
@ -293,11 +287,10 @@ CalcFov (float fov_x, float width, float height)
static void static void
SCR_CalcRefdef (void) SCR_CalcRefdef (void)
{ {
int size; float size;
int h; int h;
qboolean full = false; qboolean full = false;
scr_fullupdate = 0; // force a background redraw scr_fullupdate = 0; // force a background redraw
vid.recalc_refdef = 0; vid.recalc_refdef = 0;
@ -312,29 +305,23 @@ SCR_CalcRefdef (void)
// bound field of view // bound field of view
Cvar_SetValue (scr_fov, bound (10, scr_fov->value, 170)); Cvar_SetValue (scr_fov, bound (10, scr_fov->value, 170));
// intermission is always full screen if (scr_viewsize->int_val >= 120)
if (cl.intermission)
size = 120;
else
size = scr_viewsize->int_val;
if (size >= 120)
sb_lines = 0; // no status bar at all sb_lines = 0; // no status bar at all
else if (size >= 110) else if (scr_viewsize->int_val >= 110)
sb_lines = 24; // no inventory sb_lines = 24; // no inventory
else else
sb_lines = 24 + 16 + 8; sb_lines = 24 + 16 + 8;
if (scr_viewsize->int_val >= 100) { if (scr_viewsize->int_val >= 100) {
full = true; full = true;
size = 100; size = 100.0;
} else { } else {
size = scr_viewsize->int_val; size = scr_viewsize->int_val;
} }
// intermission is always full screen
if (cl.intermission) { if (cl.intermission) {
full = true; full = true;
size = 100; size = 100.0;
sb_lines = 0; sb_lines = 0;
} }
size /= 100.0; size /= 100.0;
@ -344,27 +331,25 @@ SCR_CalcRefdef (void)
else else
h = vid.height - sb_lines; h = vid.height - sb_lines;
r_refdef.vrect.width = vid.width * size; r_refdef.vrect.width = vid.width * size + 0.5;
if (r_refdef.vrect.width < 96) { if (r_refdef.vrect.width < 96) {
size = 96.0 / r_refdef.vrect.width; size = 96.0 / r_refdef.vrect.width;
r_refdef.vrect.width = 96; // min for icons r_refdef.vrect.width = 96; // min for icons
} }
r_refdef.vrect.height = vid.height * size; r_refdef.vrect.height = vid.height * size + 0.5;
if (cl_sbar->int_val || !full) { if (cl_sbar->int_val || !full) {
if (r_refdef.vrect.height > vid.height - sb_lines) if (r_refdef.vrect.height > vid.height - sb_lines)
r_refdef.vrect.height = vid.height - sb_lines; r_refdef.vrect.height = vid.height - sb_lines;
} else { } else if (r_refdef.vrect.height > vid.height)
if (r_refdef.vrect.height > vid.height)
r_refdef.vrect.height = vid.height; r_refdef.vrect.height = vid.height;
}
r_refdef.vrect.x = (vid.width - r_refdef.vrect.width) / 2; r_refdef.vrect.x = (vid.width - r_refdef.vrect.width) / 2;
if (full) if (full)
r_refdef.vrect.y = 0; r_refdef.vrect.y = 0;
else else
r_refdef.vrect.y = (h - r_refdef.vrect.height) / 2; r_refdef.vrect.y = (h - r_refdef.vrect.height) / 2;
r_refdef.fov_x = scr_fov->value; r_refdef.fov_x = scr_fov->int_val;
r_refdef.fov_y = r_refdef.fov_y =
CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
@ -380,9 +365,11 @@ SCR_CalcRefdef (void)
void void
SCR_SizeUp_f (void) SCR_SizeUp_f (void)
{ {
if (scr_viewsize->int_val < 120) {
Cvar_SetValue (scr_viewsize, scr_viewsize->int_val + 10); Cvar_SetValue (scr_viewsize, scr_viewsize->int_val + 10);
vid.recalc_refdef = 1; vid.recalc_refdef = 1;
} }
}
/* /*
@ -397,22 +384,28 @@ SCR_SizeDown_f (void)
vid.recalc_refdef = 1; vid.recalc_refdef = 1;
} }
//============================================================================ //============================================================================
void void
SCR_Init_Cvars (void) SCR_Init_Cvars (void)
{ {
scr_fov = Cvar_Get ("fov", "90", CVAR_NONE, NULL, "10 - 170"); scr_fov = Cvar_Get ("fov", "90", CVAR_NONE, NULL, "Your point of view in degrees. Smaller than 90 zooms in.");
scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE, NULL, "None"); scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE, NULL, "Set the screen size 30 minimum, 120 maximum");
scr_conspeed = Cvar_Get ("scr_conspeed", "300", CVAR_NONE, NULL, "None"); scr_conspeed = Cvar_Get ("scr_conspeed", "300", CVAR_NONE, NULL, "How quickly console scrolls up or down");
scr_showram = Cvar_Get ("showram", "1", CVAR_NONE, NULL, "None"); scr_consize = Cvar_Get ("scr_consize", "0.5", CVAR_ARCHIVE, NULL, "fraction of the screen the console covers when down");
scr_showturtle = Cvar_Get ("showturtle", "0", CVAR_NONE, NULL, "None"); scr_showram = Cvar_Get ("showram", "1", CVAR_NONE, NULL, "Show RAM icon if game is running low on memory");
scr_showpause = Cvar_Get ("showpause", "1", CVAR_NONE, NULL, "None"); scr_showturtle = Cvar_Get ("showturtle", "0", CVAR_NONE, NULL, "Show a turtle icon if your fps is slower than 10");
scr_centertime = Cvar_Get ("scr_centertime", "2", CVAR_NONE, NULL, "None"); scr_showpause = Cvar_Get ("showpause", "1", CVAR_NONE, NULL, "Toggles display of pause graphic");
scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_NONE, NULL, "None"); scr_centertime = Cvar_Get ("scr_centertime", "2", CVAR_NONE, NULL, "How long in seconds screen hints are displayed");
scr_allowsnap = Cvar_Get ("scr_allowsnap", "1", CVAR_NONE, NULL, "None"); scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_NONE, NULL, "How fast the text is displayed at the end of the single player episodes");
gl_triplebuffer = Cvar_Get ("gl_triplebuffer", "1", CVAR_ARCHIVE, NULL, gl_triplebuffer = Cvar_Get ("gl_triplebuffer", "1", CVAR_ARCHIVE, NULL, "Set to 1 by default. Fixes status bar flicker on some hardware");
"None");
crosshaircolor = Cvar_Get ("crosshaircolor", "79", CVAR_ARCHIVE, NULL, "Color of the new crosshair");
crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE, NULL, "Crosshair type. 0 off, 1 old without color, 2 new with colors");
cl_crossx = Cvar_Get ("cl_crossx", "0", CVAR_ARCHIVE, NULL, "Sets the position of the crosshair on the X-axis.");
cl_crossy = Cvar_Get ("cl_crossy", "0", CVAR_ARCHIVE, NULL, "Sets the position of the crosshair on the Y-axis.");
} }
@ -422,9 +415,10 @@ SCR_Init (void)
// //
// register our commands // register our commands
// //
Cmd_AddCommand ("screenshot", SCR_ScreenShot_f, "No Description"); Cmd_AddCommand ("screenshot", SCR_ScreenShot_f, "Take a screenshot, saves as qfxxx.tga in the current directory");
Cmd_AddCommand ("sizeup", SCR_SizeUp_f, "No Description"); Cmd_AddCommand ("snap", SCR_RSShot_f, "Send a screenshot to someone");
Cmd_AddCommand ("sizedown", SCR_SizeDown_f, "No Description"); Cmd_AddCommand ("sizeup", SCR_SizeUp_f, "Increases the screen size");
Cmd_AddCommand ("sizedown", SCR_SizeDown_f, "Decreases the screen size");
scr_ram = Draw_PicFromWad ("ram"); scr_ram = Draw_PicFromWad ("ram");
scr_net = Draw_PicFromWad ("net"); scr_net = Draw_PicFromWad ("net");
@ -468,15 +462,31 @@ SCR_DrawTurtle (void)
} }
void
SCR_DrawNet (void)
{
// if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged <
// UPDATE_BACKUP - 1)
if (realtime - cl.last_received_message < 0.3)
return;
if (cls.demoplayback)
return;
Draw_Pic (scr_vrect.x + 64, scr_vrect.y, scr_net);
}
extern cvar_t *show_time;
extern cvar_t *show_fps;
void void
SCR_DrawFPS (void) SCR_DrawFPS (void)
{ {
extern cvar_t *show_fps;
static double lastframetime; static double lastframetime;
double t; double t;
extern int fps_count; extern int fps_count;
static int lastfps; static int lastfps;
int x, y; int i, x, y;
char st[80]; char st[80];
if (!show_fps->int_val) if (!show_fps->int_val)
@ -488,49 +498,58 @@ SCR_DrawFPS (void)
fps_count = 0; fps_count = 0;
lastframetime = t; lastframetime = t;
} }
snprintf (st, sizeof (st), "%-3d FPS", lastfps); snprintf (st, sizeof (st), "%3d FPS", lastfps);
/* Misty: New trick! (for me) the ? makes this work like a if then else -
IE: if cl_hudswap->int_val is not null, do first case, else (else is a // FIXME! This is evil. -- Deek
: here) do second case. Deek taught me this trick */ // calculate the location of the clock
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + 8) : 8; if (show_time->int_val <= 0) {
i = 8;
} else if (show_time->int_val == 1) {
i = 56;
} else {
i = 80;
}
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + i) : i;
y = vid.height - sb_lines - 8; y = vid.height - sb_lines - 8;
Draw_String8 (x, y, st); Draw_String8 (x, y, st);
} }
/* Misty: I like to see the time */ /*
SCR_DrawTime
Draw a clock on the screen
Written by Misty, rewritten by Deek.
*/
void void
SCR_DrawTime (void) SCR_DrawTime (void)
{ {
extern cvar_t *show_time;
int x, y; int x, y;
char st[80]; char st[80];
char local_time[120];
time_t systime;
/* any cvar that can take multiple settings must be able to handle abuse. time_t utc = 0;
*/ struct tm *local = NULL;
char *timefmt = NULL;
// any cvar that can take multiple settings must be able to handle abuse.
if (show_time->int_val <= 0) if (show_time->int_val <= 0)
return; return;
/* actually find the time and set systime to it */ // Get local time
time (&systime); utc = time (NULL);
local = localtime (&utc);
if (show_time->int_val == 1) { if (show_time->int_val == 1) { // Use international format
/* now set local_time to 24 hour time using hours:minutes format */ timefmt = "%k:%M";
strftime (local_time, sizeof (local_time), "%k:%M", } else if (show_time->int_val >= 2) { // US AM/PM display
localtime (&systime)); timefmt = "%l:%M %P";
} else if (show_time->int_val >= 2) {
/* >= is another abuse protector */
strftime (local_time, sizeof (local_time), "%l:%M %P",
localtime (&systime));
} }
strftime (st, sizeof (st), timefmt, local);
/* now actually print it to the screen directly above where show_fps is */ // Print it at far left/right of screen
snprintf (st, sizeof (st), "%s", local_time); x = cl_hudswap->int_val ? (vid.width - ((strlen (st) * 8) + 8)) : 8;
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + 8) : 8; y = vid.height - (sb_lines + 8);
y = vid.height - sb_lines - 16;
Draw_String8 (x, y, st); Draw_String8 (x, y, st);
} }
@ -552,20 +571,6 @@ SCR_DrawPause (void)
} }
void
SCR_DrawLoading (void)
{
qpic_t *pic;
if (!scr_drawloading)
return;
pic = Draw_CachePic ("gfx/loading.lmp", true);
Draw_Pic ((vid.width - pic->width) / 2,
(vid.height - 48 - pic->height) / 2, pic);
}
//============================================================================= //=============================================================================
@ -574,16 +579,12 @@ SCR_SetUpToDrawConsole (void)
{ {
Con_CheckResize (); Con_CheckResize ();
if (scr_drawloading)
return; // never a console with loading
// plaque
// decide on the height of the console // decide on the height of the console
if (!cl.worldmodel || cls.signon != SIGNONS) { if (cls.state != ca_active) {
scr_conlines = vid.height; // full screen scr_conlines = vid.height; // full screen
scr_con_current = scr_conlines; scr_con_current = scr_conlines;
} else if (key_dest == key_console) } else if (key_dest == key_console)
scr_conlines = vid.height / 2; // half screen scr_conlines = vid.height * bound (0.2, scr_consize->value, 1);
else else
scr_conlines = 0; // none visible scr_conlines = 0; // none visible
@ -611,7 +612,8 @@ SCR_DrawConsole (void)
{ {
if (scr_con_current) { if (scr_con_current) {
scr_copyeverything = 1; scr_copyeverything = 1;
Con_DrawConsole (scr_con_current); // , true); Con_DrawConsole (scr_con_current);
Con_DrawDownload (scr_con_current);
clearconsole = 0; clearconsole = 0;
} else { } else {
if (key_dest == key_game || key_dest == key_message) if (key_dest == key_game || key_dest == key_message)
@ -624,111 +626,225 @@ SCR_DrawConsole (void)
SCREEN SHOTS SCREEN SHOTS
*/ */
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;
void void
SCR_ScreenShot_f (void) SCR_ScreenShot_f (void)
{ {
byte *buffer; byte *buffer;
char pcxname[80]; char pcxname[MAX_OSPATH];
char checkname[MAX_OSPATH];
int i, c, temp;
// //
// find a file name to save it to // find a file name to save it to
// //
strcpy (pcxname, "nuq000.tga"); if (!COM_NextFilename (pcxname, "qf", ".tga")) {
Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
for (i = 0; i <= 999; i++) {
pcxname[3] = i / 100 + '0';
pcxname[4] = i / 10 % 10 + '0';
pcxname[5] = i % 10 + '0';
snprintf (checkname, sizeof (checkname), "%s/%s", com_gamedir, pcxname);
if (Sys_FileTime (checkname) == -1)
break; // file doesn't exist
}
if (i == 1000) {
Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n");
return; return;
} }
buffer = malloc (glwidth * glheight * 3);
glReadPixels (glx, gly, glwidth, glheight, GL_BGR_EXT, GL_UNSIGNED_BYTE,
buffer = malloc (glwidth * glheight * 3 + 18); buffer);
memset (buffer, 0, 18); WriteTGAfile (pcxname, buffer, glwidth, glheight);
buffer[2] = 2; // uncompressed type
buffer[12] = glwidth & 255;
buffer[13] = glwidth >> 8;
buffer[14] = glheight & 255;
buffer[15] = glheight >> 8;
buffer[16] = 24; // pixel size
glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE,
buffer + 18);
// swap rgb to bgr
c = 18 + glwidth * glheight * 3;
for (i = 18; i < c; i += 3) {
temp = buffer[i];
buffer[i] = buffer[i + 2];
buffer[i + 2] = temp;
}
COM_WriteFile (pcxname, buffer, glwidth * glheight * 3 + 18);
free (buffer); free (buffer);
Con_Printf ("Wrote %s\n", pcxname); Con_Printf ("Wrote %s\n", pcxname);
} }
//============================================================================= /*
Find closest color in the palette for named color
*/
int
MipColor (int r, int g, int b)
{
int i;
float dist;
int best = 0;
float bestdist;
int r1, g1, b1;
static int lr = -1, lg = -1, lb = -1;
static int lastbest;
if (r == lr && g == lg && b == lb)
return lastbest;
bestdist = 256 * 256 * 3;
for (i = 0; i < 256; i++) {
r1 = vid_basepal[i * 3] - r;
g1 = vid_basepal[i * 3 + 1] - g;
b1 = vid_basepal[i * 3 + 2] - b;
dist = r1 * r1 + g1 * g1 + b1 * b1;
if (dist < bestdist) {
bestdist = dist;
best = i;
}
}
lr = r;
lg = g;
lb = b;
lastbest = best;
return best;
}
// in gl_draw.c
extern byte *draw_chars; // 8*8 graphic characters
void void
SCR_BeginLoadingPlaque (void) SCR_DrawCharToSnap (int num, byte * dest, int width)
{ {
S_StopAllSounds (true); int row, col;
byte *source;
int drawline;
int x;
if (cls.state != ca_connected) row = num >> 4;
return; col = num & 15;
if (cls.signon != SIGNONS) source = draw_chars + (row << 10) + (col << 3);
return;
// redraw with no console and the loading plaque drawline = 8;
Con_ClearNotify ();
scr_centertime_off = 0;
scr_con_current = 0;
scr_drawloading = true; while (drawline--) {
scr_fullupdate = 0; for (x = 0; x < 8; x++)
Sbar_Changed (); if (source[x])
SCR_UpdateScreen (); dest[x] = source[x];
scr_drawloading = false; else
dest[x] = 98;
source += 128;
dest -= width;
}
scr_disabled_for_loading = true;
scr_disabled_time = realtime;
scr_fullupdate = 0;
} }
void void
SCR_EndLoadingPlaque (void) SCR_DrawStringToSnap (const char *s, byte * buf, int x, int y, int width)
{ {
scr_disabled_for_loading = false; byte *dest;
scr_fullupdate = 0; const unsigned char *p;
Con_ClearNotify ();
dest = buf + ((y * width) + x);
p = (const unsigned char *) s;
while (*p) {
SCR_DrawCharToSnap (*p++, dest, width);
dest += 8;
}
}
void
SCR_RSShot_f (void)
{
#if 0
int x, y;
unsigned char *src, *dest;
char pcxname[80];
pcx_t *pcx;
int pcx_len;
unsigned char *newbuf;
int w, h;
int dx, dy, dex, dey, nx;
int r, b, g;
int count;
float fracw, frach;
char st[80];
time_t now;
if (CL_IsUploading ())
return; // already one pending
if (cls.state < ca_onserver)
return; // gotta be connected
Con_Printf ("Remote screen shot requested.\n");
snprintf (pcxname, sizeof (pcxname), "rss.pcx");
//
// save the pcx file
//
newbuf = malloc (glheight * glwidth * 3);
glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE,
newbuf);
w = (vid.width < RSSHOT_WIDTH) ? glwidth : RSSHOT_WIDTH;
h = (vid.height < RSSHOT_HEIGHT) ? glheight : RSSHOT_HEIGHT;
fracw = (float) glwidth / (float) w;
frach = (float) glheight / (float) h;
for (y = 0; y < h; y++) {
dest = newbuf + (w * 3 * y);
for (x = 0; x < w; x++) {
r = g = b = 0;
dx = x * fracw;
dex = (x + 1) * fracw;
if (dex == dx)
dex++; // at least one
dy = y * frach;
dey = (y + 1) * frach;
if (dey == dy)
dey++; // at least one
count = 0;
for ( /* */ ; dy < dey; dy++) {
src = newbuf + (glwidth * 3 * dy) + dx * 3;
for (nx = dx; nx < dex; nx++) {
r += *src++;
g += *src++;
b += *src++;
count++;
}
}
r /= count;
g /= count;
b /= count;
*dest++ = r;
*dest++ = b;
*dest++ = g;
}
}
// convert to eight bit
for (y = 0; y < h; y++) {
src = newbuf + (w * 3 * y);
dest = newbuf + (w * y);
for (x = 0; x < w; x++) {
*dest++ = MipColor (src[0], src[1], src[2]);
src += 3;
}
}
time (&now);
strcpy (st, ctime (&now));
st[strlen (st) - 1] = 0;
SCR_DrawStringToSnap (st, newbuf, w - strlen (st) * 8, h - 1, w);
strncpy (st, cls.servername, sizeof (st));
st[sizeof (st) - 1] = 0;
SCR_DrawStringToSnap (st, newbuf, w - strlen (st) * 8, h - 11, w);
strncpy (st, name->string, sizeof (st));
st[sizeof (st) - 1] = 0;
SCR_DrawStringToSnap (st, newbuf, w - strlen (st) * 8, h - 21, w);
pcx = EncodePCX (newbuf, w, h, w, vid_basepal, true, &pcx_len);
CL_StartUpload ((void *)pcx, pcx_len);
free (newbuf);
Con_Printf ("Wrote %s\n", pcxname);
Con_Printf ("Sending shot to server...\n");
#endif
} }
//============================================================================= //=============================================================================
char *scr_notifystring; char *scr_notifystring;
qboolean scr_drawdialog;
void void
SCR_DrawNotifyString (void) SCR_DrawNotifyString (void)
@ -763,69 +879,12 @@ SCR_DrawNotifyString (void)
} }
/*
SCR_ModalMessage
Displays a text string in the center of the screen and waits
for a Y or N keypress.
*/
int
SCR_ModalMessage (char *text)
{
if (cls.state == ca_dedicated)
return true;
scr_notifystring = text;
// draw a fresh screen
scr_fullupdate = 0;
scr_drawdialog = true;
SCR_UpdateScreen ();
scr_drawdialog = false;
S_ClearBuffer (); // so dma doesn't loop current sound
do {
// key_count = -1; // wait for a key down and up
IN_SendKeyEvents ();
} while (key_lastpress != 'y' && key_lastpress != 'n'
&& key_lastpress != K_ESCAPE);
scr_fullupdate = 0;
SCR_UpdateScreen ();
return key_lastpress == 'y';
}
//============================================================================= //=============================================================================
/*
SCR_BringDownConsole
Brings the console down and fades the palettes back to normal
*/
void
SCR_BringDownConsole (void)
{
int i;
scr_centertime_off = 0;
for (i = 0; i < 20 && scr_conlines != scr_con_current; i++)
SCR_UpdateScreen ();
cl.cshifts[0].percent = 0; // no area contents palette on next
// frame
VID_SetPalette (vid_basepal);
}
void void
SCR_TileClear (void) SCR_TileClear (void)
{ {
#if 0
if (r_refdef.vrect.x > 0) { if (r_refdef.vrect.x > 0) {
// left // left
Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines); Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines);
@ -846,25 +905,25 @@ SCR_TileClear (void)
vid.height - sb_lines - vid.height - sb_lines -
(r_refdef.vrect.height + r_refdef.vrect.y)); (r_refdef.vrect.height + r_refdef.vrect.y));
} }
#endif
} }
float oldsbar = 0; extern void R_ForceLightUpdate (void);
extern void R_ForceLightUpdate ();
int oldviewsize = 0;
unsigned char lighthalf_v[3]; unsigned char lighthalf_v[3];
qboolean lighthalf; qboolean lighthalf;
extern cvar_t *gl_lightmode; extern cvar_t *gl_lightmode;
extern cvar_t *brightness;
/* /*
SCR_UpdateScreen SCR_UpdateScreen
This is called every frame, and can also be called explicitly to This is called every frame, and can also be called explicitly to flush
flush text to the screen. text to the screen.
WARNING: be very careful calling this from elsewhere, because the WARNING: be very careful calling this from elsewhere, because the refresh
refresh needs almost the entire 256k of stack space! needs almost the entire 256k of stack space!
*/ */
void void
SCR_UpdateScreen (void) SCR_UpdateScreen (void)
@ -889,11 +948,16 @@ SCR_UpdateScreen (void)
} }
} }
if (!scr_initialized || !con_initialized) if (!scr_initialized || !con_initialized) // not initialized yet
return; // not initialized yet return;
if (oldsbar != cl_sbar->value) { if (oldsbar != cl_sbar->int_val) {
oldsbar = cl_sbar->value; oldsbar = cl_sbar->int_val;
vid.recalc_refdef = true;
}
if (oldviewsize != scr_viewsize->int_val) {
oldviewsize = scr_viewsize->int_val;
vid.recalc_refdef = true; vid.recalc_refdef = true;
} }
@ -904,10 +968,8 @@ SCR_UpdateScreen (void)
c_brush_polys = 0; c_brush_polys = 0;
c_alias_polys = 0; c_alias_polys = 0;
} }
//
// determine size of refresh window if (oldfov != scr_fov->value) { // determine size of refresh window
//
if (oldfov != scr_fov->value) {
oldfov = scr_fov->value; oldfov = scr_fov->value;
vid.recalc_refdef = true; vid.recalc_refdef = true;
} }
@ -915,15 +977,7 @@ SCR_UpdateScreen (void)
if (vid.recalc_refdef) if (vid.recalc_refdef)
SCR_CalcRefdef (); SCR_CalcRefdef ();
//
// do 3D refresh drawing, and then update the screen // do 3D refresh drawing, and then update the screen
//
// LordHavoc: set lighthalf based on gl_lightmode cvar
if (lighthalf != (gl_lightmode->int_val != 0)) {
lighthalf = gl_lightmode->int_val != 0;
R_ForceLightUpdate ();
}
SCR_SetUpToDrawConsole (); SCR_SetUpToDrawConsole ();
@ -931,25 +985,16 @@ SCR_UpdateScreen (void)
GL_Set2D (); GL_Set2D ();
//
// draw any areas not covered by the refresh // draw any areas not covered by the refresh
//
SCR_TileClear (); SCR_TileClear ();
if (scr_drawdialog) { #if 0 // R_NetGraph qw-only?
Sbar_Draw (); if (r_netgraph->int_val)
Draw_FadeScreen (); R_NetGraph ();
SCR_DrawNotifyString (); #endif
scr_copyeverything = true;
} else {
if (scr_drawloading) {
SCR_DrawLoading ();
Sbar_Draw ();
} else {
if (cl.intermission == 1 && key_dest == key_game) { if (cl.intermission == 1 && key_dest == key_game) {
Sbar_IntermissionOverlay (); Sbar_IntermissionOverlay ();
} else { } else if (cl.intermission == 2 && key_dest == key_game) {
if (cl.intermission == 2 && key_dest == key_game) {
Sbar_FinaleOverlay (); Sbar_FinaleOverlay ();
SCR_CheckDrawCenterString (); SCR_CheckDrawCenterString ();
} else { } else {
@ -957,6 +1002,7 @@ SCR_UpdateScreen (void)
Draw_Crosshair (); Draw_Crosshair ();
SCR_DrawRam (); SCR_DrawRam ();
SCR_DrawNet ();
SCR_DrawFPS (); SCR_DrawFPS ();
SCR_DrawTime (); SCR_DrawTime ();
SCR_DrawTurtle (); SCR_DrawTurtle ();
@ -967,27 +1013,24 @@ SCR_UpdateScreen (void)
// FIXME: MENUCODE // FIXME: MENUCODE
// M_Draw (); // M_Draw ();
} }
}
}
}
// LordHavoc: adjustable brightness and contrast, // LordHavoc: adjustable brightness and contrast,
// also makes polyblend apply to whole screen // also makes polyblend apply to whole screen
glDisable (GL_TEXTURE_2D); glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND);
Cvar_SetValue (brightness, bound (1, brightness->value, 5)); Cvar_SetValue (brightness, bound (1, brightness->value, 5));
if (lighthalf) // LordHavoc: render was done at half if (lighthalf) { // LordHavoc: render was done at half brightness
//
//
// brightness
f = brightness->value * 2; f = brightness->value * 2;
else } else {
Cvar_SetValue (brightness, bound (1, brightness->value, 5));
f = brightness->value; f = brightness->value;
if (f > 1.0) { }
if (f >= 1.002) { // Make sure we don't get bit by roundoff errors
glBlendFunc (GL_DST_COLOR, GL_ONE); glBlendFunc (GL_DST_COLOR, GL_ONE);
glBegin (GL_QUADS); glBegin (GL_QUADS);
while (f > 1.0) { while (f >= 1.002) { // precision
if (f >= 2.0) if (f >= 2)
glColor3f (1, 1, 1); glColor3f (1, 1, 1);
else else
glColor3f (f - 1, f - 1, f - 1); glColor3f (f - 1, f - 1, f - 1);
@ -998,29 +1041,23 @@ SCR_UpdateScreen (void)
f *= 0.5; f *= 0.5;
} }
glEnd (); glEnd ();
} glColor3ubv (lighthalf_v);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Cvar_SetValue (contrast, bound (0.2, contrast->value, 1.0));
if ((gl_polyblend->int_val && v_blend[3]) || contrast->value < 1) {
glBegin (GL_QUADS);
if (contrast->value < 1) {
glColor4f (1, 1, 1, 1 - contrast->value);
glVertex2f (0, 0);
glVertex2f (vid.width, 0);
glVertex2f (vid.width, vid.height);
glVertex2f (0, vid.height);
} }
if (gl_polyblend->int_val && v_blend[3]) {
if (v_blend[3]) {
glBegin (GL_QUADS);
glColor4fv (v_blend); glColor4fv (v_blend);
glVertex2f (0, 0); glVertex2f (0, 0);
glVertex2f (vid.width, 0); glVertex2f (vid.width, 0);
glVertex2f (vid.width, vid.height); glVertex2f (vid.width, vid.height);
glVertex2f (0, vid.height); glVertex2f (0, vid.height);
}
glEnd (); glEnd ();
glColor3ubv (lighthalf_v);
} }
glDisable (GL_BLEND);
glEnable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_2D);
V_UpdatePalette (); V_UpdatePalette ();

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 gl_warp.c
sky and water polygons water polygons
Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1996-1997 Id Software, Inc.
@ -29,41 +29,17 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
#endif #endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <math.h> #include "QF/cvar.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/sys.h" #include "QF/sys.h"
#include "QF/vid.h"
#include "glquake.h" #include "glquake.h"
#include "render.h"
extern double realtime; extern double realtime;
extern model_t *loadmodel; extern model_t *loadmodel;
extern int skytexturenum;
extern qboolean lighthalf; 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; msurface_t *warpface;
extern cvar_t *gl_subdivide_size; 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 Breaks a polygon up along axial 64 unit
boundaries so that turbulent and sky warps boundaries so that turbulent and sky warps
can be done reasonably. can be done reasonably.
================
*/ */
void void
GL_SubdivideSurface (msurface_t *fa) GL_SubdivideSurface (msurface_t *fa)
@ -212,20 +186,19 @@ GL_SubdivideSurface (msurface_t *fa)
//========================================================= //=========================================================
// speed up sin calculations - Ed // speed up sin calculations - Ed
float turbsin[] = { float turbsin[] = {
# include "gl_warp_sin.h" # include "gl_warp_sin.h"
}; };
#define TURBSCALE (256.0 / (2 * M_PI)) #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 void
EmitWaterPolys (msurface_t *fa) EmitWaterPolys (msurface_t *fa)
@ -261,602 +234,3 @@ EmitWaterPolys (msurface_t *fa)
glEnd (); 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"); Sys_Error ("Host_Error: recursively entered");
inerror = true; inerror = true;
SCR_EndLoadingPlaque (); // reenable screen updates // SCR_EndLoadingPlaque (); // reenable screen updates
va_start (argptr, error); va_start (argptr, error);
vsnprintf (string, sizeof (string), error, argptr); vsnprintf (string, sizeof (string), error, argptr);

View file

@ -279,7 +279,7 @@ Host_Map_f (void)
Host_ShutdownServer (false); Host_ShutdownServer (false);
key_dest = key_game; // remove console or menu key_dest = key_game; // remove console or menu
SCR_BeginLoadingPlaque (); // SCR_BeginLoadingPlaque ();
cls.mapstring[0] = 0; cls.mapstring[0] = 0;
for (i = 0; i < Cmd_Argc (); i++) { for (i = 0; i < Cmd_Argc (); i++) {
@ -404,7 +404,7 @@ This is sent just before a server changes levels
void void
Host_Reconnect_f (void) Host_Reconnect_f (void)
{ {
SCR_BeginLoadingPlaque (); // SCR_BeginLoadingPlaque ();
cls.signon = 0; // need new connection messages 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 r_draw.c
@description@ (description)
Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1996-1997 Id Software, Inc.
@ -81,9 +81,7 @@ qboolean r_lastvertvalid;
#ifndef USE_INTEL_ASM #ifndef USE_INTEL_ASM
/* /*
================
R_EmitEdge R_EmitEdge
================
*/ */
void void
R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) 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 void
R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) 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); R_EmitEdge (pv0, pv1);
} }
#endif // USE_INTEL_ASM #endif // !USE_INTEL_ASM
/* /*
================
R_EmitCachedEdge R_EmitCachedEdge
================
*/ */
void void
R_EmitCachedEdge (void) R_EmitCachedEdge (void)
@ -363,15 +357,13 @@ R_EmitCachedEdge (void)
/* /*
================
R_RenderFace R_RenderFace
================
*/ */
void void
R_RenderFace (msurface_t *fa, int clipflags) R_RenderFace (msurface_t *fa, int clipflags)
{ {
int i, lindex; int i, lindex;
unsigned mask; unsigned int mask;
mplane_t *pplane; mplane_t *pplane;
float distinv; float distinv;
vec3_t p_normal; vec3_t p_normal;
@ -534,15 +526,13 @@ R_RenderFace (msurface_t *fa, int clipflags)
/* /*
================
R_RenderBmodelFace R_RenderBmodelFace
================
*/ */
void void
R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
{ {
int i; int i;
unsigned mask; unsigned int mask;
mplane_t *pplane; mplane_t *pplane;
float distinv; float distinv;
vec3_t p_normal; vec3_t p_normal;
@ -639,16 +629,14 @@ R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
/* /*
================
R_RenderPoly R_RenderPoly
================
*/ */
void void
R_RenderPoly (msurface_t *fa, int clipflags) R_RenderPoly (msurface_t *fa, int clipflags)
{ {
int i, lindex, lnumverts, s_axis, t_axis; int i, lindex, lnumverts, s_axis, t_axis;
float dist, lastdist, lzi, scale, u, v, frac; float dist, lastdist, lzi, scale, u, v, frac;
unsigned mask; unsigned int mask;
vec3_t local, transformed; vec3_t local, transformed;
clipplane_t *pclip; clipplane_t *pclip;
medge_t *pedges; medge_t *pedges;
@ -811,9 +799,7 @@ R_RenderPoly (msurface_t *fa, int clipflags)
/* /*
================
R_ZDrawSubmodelPolys R_ZDrawSubmodelPolys
================
*/ */
void void
R_ZDrawSubmodelPolys (model_t *pmodel) R_ZDrawSubmodelPolys (model_t *pmodel)

View file

@ -1,7 +1,7 @@
/* /*
r_sky.c r_sky.c
@description@ (description)
Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1996-1997 Id Software, Inc.
@ -32,7 +32,6 @@
#include "client.h" #include "client.h"
#include "r_local.h" #include "r_local.h"
#include "d_local.h"
int iskyspeed = 8; 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 void
R_InitSky (texture_t *mt) R_InitSky (texture_t *mt)
@ -97,9 +94,7 @@ R_InitSky (texture_t *mt)
/* /*
=================
R_MakeSky R_MakeSky
=================
*/ */
void void
R_MakeSky (void) R_MakeSky (void)
@ -107,7 +102,7 @@ R_MakeSky (void)
int x, y; int x, y;
int ofs, baseofs; int ofs, baseofs;
int xshift, yshift; int xshift, yshift;
unsigned *pnewsky; unsigned int *pnewsky;
static int xlast = -1, ylast = -1; static int xlast = -1, ylast = -1;
xshift = skytime * skyspeed; xshift = skytime * skyspeed;
@ -119,7 +114,7 @@ R_MakeSky (void)
xlast = xshift; xlast = xshift;
ylast = yshift; ylast = yshift;
pnewsky = (unsigned *) &newsky[0]; pnewsky = (unsigned int *) &newsky[0];
for (y = 0; y < SKYSIZE; y++) { for (y = 0; y < SKYSIZE; y++) {
baseofs = ((y + yshift) & SKYMASK) * 131; baseofs = ((y + yshift) & SKYMASK) * 131;
@ -132,9 +127,9 @@ R_MakeSky (void)
// PORT: unaligned dword access to bottommask and bottomsky // PORT: unaligned dword access to bottommask and bottomsky
*pnewsky = (*(pnewsky + (128 / sizeof (unsigned))) & *pnewsky = (*(pnewsky + (128 / sizeof (unsigned int))) &
*(unsigned *) &bottommask[ofs]) | *(unsigned int *) &bottommask[ofs]) |
*(unsigned *) &bottomsky[ofs]; *(unsigned int *) &bottomsky[ofs];
pnewsky++; pnewsky++;
} }
@ -147,12 +142,12 @@ R_MakeSky (void)
*(byte *) pnewsky = (*((byte *) pnewsky + 128) & *(byte *) pnewsky = (*((byte *) pnewsky + 128) &
*(byte *) & bottommask[ofs]) | *(byte *) & bottommask[ofs]) |
*(byte *) & bottomsky[ofs]; *(byte *) & bottomsky[ofs];
pnewsky = (unsigned *) ((byte *) pnewsky + 1); pnewsky = (unsigned int *) ((byte *) pnewsky + 1);
} }
#endif #endif
pnewsky += 128 / sizeof (unsigned); pnewsky += 128 / sizeof (unsigned int);
} }
r_skymade = 1; r_skymade = 1;
@ -160,9 +155,7 @@ R_MakeSky (void)
/* /*
=================
R_GenSkyTile R_GenSkyTile
=================
*/ */
void void
R_GenSkyTile (void *pdest) R_GenSkyTile (void *pdest)
@ -170,14 +163,14 @@ R_GenSkyTile (void *pdest)
int x, y; int x, y;
int ofs, baseofs; int ofs, baseofs;
int xshift, yshift; int xshift, yshift;
unsigned *pnewsky; unsigned int *pnewsky;
unsigned *pd; unsigned int *pd;
xshift = skytime * skyspeed; xshift = skytime * skyspeed;
yshift = skytime * skyspeed; yshift = skytime * skyspeed;
pnewsky = (unsigned *) &newsky[0]; pnewsky = (unsigned int *) &newsky[0];
pd = (unsigned *) pdest; pd = (unsigned int *) pdest;
for (y = 0; y < SKYSIZE; y++) { for (y = 0; y < SKYSIZE; y++) {
baseofs = ((y + yshift) & SKYMASK) * 131; baseofs = ((y + yshift) & SKYMASK) * 131;
@ -190,10 +183,10 @@ R_GenSkyTile (void *pdest)
// PORT: unaligned dword access to bottommask and bottomsky // PORT: unaligned dword access to bottommask and bottomsky
*pd = (*(pnewsky + (128 / sizeof (unsigned))) & *pd = (*(pnewsky + (128 / sizeof (unsigned int))) &
*(unsigned *) &bottommask[ofs]) | *(unsigned int *) &bottommask[ofs]) |
*(unsigned int *) &bottomsky[ofs];
*(unsigned *) &bottomsky[ofs];
pnewsky++; pnewsky++;
pd++; pd++;
} }
@ -206,21 +199,19 @@ R_GenSkyTile (void *pdest)
*(byte *) pd = (*((byte *) pnewsky + 128) & *(byte *) pd = (*((byte *) pnewsky + 128) &
*(byte *) & bottommask[ofs]) | *(byte *) & bottommask[ofs]) |
*(byte *) & bottomsky[ofs]; *(byte *) & bottomsky[ofs];
pnewsky = (unsigned *) ((byte *) pnewsky + 1); pnewsky = (unsigned int *) ((byte *) pnewsky + 1);
pd = (unsigned *) ((byte *) pd + 1); pd = (unsigned int *) ((byte *) pd + 1);
} }
#endif #endif
pnewsky += 128 / sizeof (unsigned); pnewsky += 128 / sizeof (unsigned int);
} }
} }
/* /*
=================
R_GenSkyTile16 R_GenSkyTile16
=================
*/ */
void void
R_GenSkyTile16 (void *pdest) R_GenSkyTile16 (void *pdest)
@ -258,9 +249,7 @@ R_GenSkyTile16 (void *pdest)
/* /*
=============
R_SetSkyFrame R_SetSkyFrame
==============
*/ */
void void
R_SetSkyFrame (void) R_SetSkyFrame (void)
@ -281,3 +270,15 @@ R_SetSkyFrame (void)
r_skymade = 0; 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) Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string)
* 8 - 11, lines - 14, cl_verstring->string); * 8 - 11, lines - 14, cl_verstring->string);
} }

View file

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