[renderer] Merge the two software renderers

I got tired of having to maintain two separate software renderers, but
didn't want to just nuke sw32, so its core changes are merged into sw.

Alias model rendering is broken, but I know exactly what's wrong and how
to fix it, just need to take care due to asm.
This commit is contained in:
Bill Currie 2022-03-09 14:26:16 +09:00
parent cfe0455cce
commit 6377734e32
64 changed files with 3044 additions and 13029 deletions

View file

@ -95,8 +95,8 @@ if test "x$HAVE_X" = xyes; then
QF_NEED(iqm, [vulkan])
QF_NEED(sprite, [vulkan])
fi
QF_NEED(vid_render, [sw sw32 gl glsl])
QF_NEED(render, [sw sw32 gl glsl])
QF_NEED(vid_render, [sw gl glsl])
QF_NEED(render, [sw gl glsl])
QF_NEED(models, [sw gl glsl])
QF_NEED(alias, [sw gl glsl])
QF_NEED(brush, [sw gl glsl])
@ -120,8 +120,8 @@ if test "x$HAVE_SDL" = xyes; then
NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA desktop/quakeforge-nq-sdl.desktop"
CL_TARGETS="$CL_TARGETS SDL"
VID_TARGETS="$VID_TARGETS libs/video/targets/libQFsdl.la"
QF_NEED(vid_render, [sw sw32 gl glsl])
QF_NEED(render, [sw sw32 gl glsl])
QF_NEED(vid_render, [sw gl glsl])
QF_NEED(render, [sw gl glsl])
QF_NEED(models, [sw gl glsl])
QF_NEED(alias, [sw gl glsl])
QF_NEED(brush, [sw gl glsl])
@ -175,7 +175,7 @@ if test "x$mingw" = xyes; then
QF_NEED(iqm, [vulkan])
QF_NEED(sprite, [vulkan])
fi
QF_NEED(vid_render, [sw sw32 gl glsl])
QF_NEED(vid_render, [sw gl glsl])
QF_NEED(models, [sw gl glsl])
QF_NEED(alias, [sw gl glsl])
QF_NEED(brush, [sw gl glsl])
@ -356,8 +356,8 @@ QF_SUBST(progs_gz)
QF_PROCESS_NEED_LIST(top, [libs hw nq qtv qw tools ruamoko])
QF_PROCESS_NEED_LIBS(swrend, [asm])
QF_PROCESS_NEED_LIBS(render, [gl glsl sw sw32 vulkan], [libs/video/renderer])
QF_PROCESS_NEED_LIST(vid_render, [gl glsl sw sw32 vulkan])
QF_PROCESS_NEED_LIBS(render, [gl glsl sw vulkan], [libs/video/renderer])
QF_PROCESS_NEED_LIST(vid_render, [gl glsl sw vulkan])
QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models])
QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias])
QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush])
@ -407,7 +407,7 @@ if test "x$static_plugins" = xauto; then
fi
fi
if test "x$static_plugins" = xyes; then
QF_PROCESS_NEED_STATIC_PLUGINS(vid_render, [sw sw32 glsl gl vulkan], [libs/video/renderer])
QF_PROCESS_NEED_STATIC_PLUGINS(vid_render, [sw glsl gl vulkan], [libs/video/renderer])
QF_PROCESS_NEED_STATIC_PLUGINS(console, [server], [libs/console], [server])
QF_PROCESS_NEED_STATIC_PLUGINS(console, [client], [libs/console], [client])
@ -422,7 +422,7 @@ if test "x$static_plugins" = xyes; then
CDTYPE="$CDTYPE (static)"
fi
else
QF_PROCESS_NEED_PLUGINS(vid_render, [sw sw32 glsl gl vulkan], [libs/video/renderer])
QF_PROCESS_NEED_PLUGINS(vid_render, [sw glsl gl vulkan], [libs/video/renderer])
QF_PROCESS_NEED_PLUGINS(console, [server], [libs/console], [server])
QF_PROCESS_NEED_PLUGINS(console, [client], [libs/console], [client])
QF_PROCESS_NEED_PLUGINS(snd_output, [sdl mme sgi sun win dx oss jack alsa], [libs/audio/targets])

View file

@ -83,7 +83,6 @@ struct gl_ctx_s *X11_GL_Context (void);
void X11_GL_Init_Cvars (void);
struct sw_ctx_s *X11_SW_Context (void);
struct sw_ctx_s *X11_SW32_Context (void);
void X11_SW_Init_Cvars (void); // sw and sw32 cvars shared
struct vulkan_ctx_s *X11_Vulkan_Context (void);

View file

@ -18,7 +18,6 @@ typedef struct vid_internal_s {
struct gl_ctx_s *(*gl_context) (void);
struct sw_ctx_s *(*sw_context) (void);
struct sw_ctx_s *(*sw32_context) (void);
struct vulkan_ctx_s *(*vulkan_context) (void);
} vid_internal_t;
@ -26,10 +25,10 @@ extern struct cvar_s *vid_fullscreen;
extern struct cvar_s *vid_system_gamma;
extern struct cvar_s *vid_gamma;
extern unsigned short sw32_8to16table[256];
void VID_GetWindowSize (int def_w, int def_h);
extern unsigned short d_8to16table[256];
void VID_InitGamma (const byte *);
qboolean VID_SetGamma (double);
void VID_UpdateGamma (struct cvar_s *);

View file

@ -1,19 +1,46 @@
#ifndef __vid_sw_h
#define __vid_sw_h
#include "QF/qtypes.h"
struct surf_s;
struct vrect_s;
struct particle_s;
struct spanpackage_s;
struct qpic_s;
struct espan_s;
struct sspan_s;
typedef struct sw_draw_s {
#define SW_DRAW_FUNC(name, rettype, params) \
rettype (*name) params;
#include "vid_sw_draw.h"
} sw_draw_t;
struct vrect_s;
typedef struct sw_ctx_s {
int pixbytes;
void (*choose_visual) (struct sw_ctx_s *ctx);
void (*create_context) (struct sw_ctx_s *ctx);
void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette);
void (*update) (struct sw_ctx_s *ctx, struct vrect_s *rects);
void (*choose_visual) (struct sw_ctx_s *ctx);
void (*create_context) (struct sw_ctx_s *ctx);
void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette);
void (*update) (struct sw_ctx_s *ctx, struct vrect_s *rects);
sw_draw_t *draw;
} sw_ctx_t;
extern sw_ctx_t *sw_ctx;
extern sw_ctx_t *sw32_ctx;
#define SW_DRAW_FUNC(name, rettype, params) \
rettype name##_8 params;
#include "vid_sw_draw.h"
#define SW_DRAW_FUNC(name, rettype, params) \
rettype name##_16 params;
#include "vid_sw_draw.h"
#define SW_DRAW_FUNC(name, rettype, params) \
rettype name##_32 params;
#include "vid_sw_draw.h"
struct tex_s *sw_SCR_CaptureBGR (void);
struct tex_s *sw32_SCR_CaptureBGR (void);
#endif//__vid_sw_h

25
include/vid_sw_draw.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef SW_DRAW_FUNC
#define SW_DRAW_FUNC(name, rettype, params)
#endif
SW_DRAW_FUNC(draw_solid_usrface, void, (struct surf_s *surf, int color))
SW_DRAW_FUNC(draw_particle, void, (struct particle_s *particle))
SW_DRAW_FUNC(polyset_draw_spans, void, (struct spanpackage_s *spanpackage))
SW_DRAW_FUNC(draw_character, void, (int x, int y, byte *source, int drawline))
SW_DRAW_FUNC(draw_pixel, void, (int x, int y, byte color))
SW_DRAW_FUNC(draw_subpic, void, (int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height))
SW_DRAW_FUNC(draw_console_background, void, (int lines, byte *data))
SW_DRAW_FUNC(draw_rect, void, (struct vrect_s *rect, int rowbytes, byte *src, int transparent))
SW_DRAW_FUNC(draw_fill, void, (int x, int y, int w, int h, int c))
SW_DRAW_FUNC(draw_fadescreen, void, (void))
SW_DRAW_FUNC(draw_blendscreen, void, (quat_t color))
SW_DRAW_FUNC(warp_screen, void, (void))
SW_DRAW_FUNC(draw_turbulent_span, void, (void))
SW_DRAW_FUNC(draw_spans, void, (struct espan_s *span))
SW_DRAW_FUNC(draw_sky_scans, void, (struct espan_s *span))
SW_DRAW_FUNC(sprite_draw_spans, void, (struct sspan_s *span))
SW_DRAW_FUNC(draw_z_point, void, (void))
SW_DRAW_FUNC(line_grapn, void, (int x, int y, int *h_vals, int count, int height))
SW_DRAW_FUNC(make_sky, void, (void))
SW_DRAW_FUNC(capture_bgr, struct tex_s *, (void))
#undef SW_DRAW_FUNC

View file

@ -11,7 +11,6 @@ noinst_LTLIBRARIES += \
#plugins
EXTRA_LTLIBRARIES += \
libs/video/renderer/vid_render_sw.la \
libs/video/renderer/vid_render_sw32.la \
libs/video/renderer/vid_render_gl.la \
libs/video/renderer/vid_render_glsl.la \
libs/video/renderer/vid_render_vulkan.la
@ -19,7 +18,6 @@ EXTRA_LTLIBRARIES += \
#helper libraries
EXTRA_LTLIBRARIES += \
libs/video/renderer/librender_sw.la \
libs/video/renderer/librender_sw32.la \
libs/video/renderer/librender_gl.la \
libs/video/renderer/librender_glsl.la \
libs/video/renderer/librender_vulkan.la
@ -140,7 +138,6 @@ libs_video_renderer_librender_sw_la_SOURCES = \
libs/video/renderer/sw/d_copy.S \
libs/video/renderer/sw/d_draw.S \
libs/video/renderer/sw/d_edge.c \
libs/video/renderer/sw/d_fill.c \
libs/video/renderer/sw/d_init.c \
libs/video/renderer/sw/d_modech.c \
libs/video/renderer/sw/d_part.c \
@ -183,47 +180,6 @@ libs_video_renderer_librender_sw_la_SOURCES = \
libs/video/renderer/sw/transform.S \
libs/video/renderer/sw/vid_common_sw.c
video_renderer_sw32_libs= \
libs/video/renderer/librender_sw32.la \
libs/models/libmodels_sw.la
libs_video_renderer_vid_render_sw32_la_LDFLAGS= $(plugin_ldflags)
libs_video_renderer_vid_render_sw32_la_LIBADD= $(video_renderer_sw32_libs)
libs_video_renderer_vid_render_sw32_la_DEPENDENCIES=$(video_renderer_sw32_libs)
libs_video_renderer_vid_render_sw32_la_SOURCES=\
$(video_renderer_common_sources) \
libs/video/renderer/vid_render_sw32.c
libs_video_renderer_librender_sw32_la_SOURCES = \
libs/video/renderer/sw32/d_edge.c \
libs/video/renderer/sw32/d_fill.c \
libs/video/renderer/sw32/d_init.c \
libs/video/renderer/sw32/d_modech.c \
libs/video/renderer/sw32/d_part.c \
libs/video/renderer/sw32/d_polyse.c \
libs/video/renderer/sw32/d_scan.c \
libs/video/renderer/sw32/d_sky.c \
libs/video/renderer/sw32/d_sprite.c \
libs/video/renderer/sw32/d_surf.c \
libs/video/renderer/sw32/d_vars.c \
libs/video/renderer/sw32/d_zpoint.c \
libs/video/renderer/sw32/draw.c \
libs/video/renderer/sw32/namehack.h \
libs/video/renderer/sw32/screen.c \
libs/video/renderer/sw32/sw32_graph.c \
libs/video/renderer/sw32/sw32_raclip.c \
libs/video/renderer/sw32/sw32_ralias.c \
libs/video/renderer/sw32/sw32_rbsp.c \
libs/video/renderer/sw32/sw32_rdraw.c \
libs/video/renderer/sw32/sw32_redge.c \
libs/video/renderer/sw32/sw32_riqm.c \
libs/video/renderer/sw32/sw32_rmain.c \
libs/video/renderer/sw32/sw32_rmisc.c \
libs/video/renderer/sw32/sw32_rpart.c \
libs/video/renderer/sw32/sw32_rsky.c \
libs/video/renderer/sw32/sw32_rsprite.c \
libs/video/renderer/sw32/sw32_rsurf.c \
libs/video/renderer/sw32/vid_common_sw32.c
pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist
pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc
renderpass_src = libs/video/renderer/vulkan/deferred.plist

View file

@ -99,8 +99,8 @@ LClampHigh5:
#define pspans 4+16
.align 4
.globl C(D_DrawSpans8)
C(D_DrawSpans8):
.globl C(draw_spans_8)
C(draw_spans_8):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables

View file

@ -35,6 +35,8 @@
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static int miplevel;
@ -72,15 +74,14 @@ D_MipLevelForScale (float scale)
// FIXME: clean this up
static void
D_DrawSolidSurface (surf_t *surf, int color)
void
draw_solid_usrface_8 (surf_t *surf, int color)
{
espan_t *span;
byte *pdest;
int u, u2, pix;
pix = (color << 24) | (color << 16) | (color << 8) | color;
for (span = surf->spans; span; span = span->pnext) {
for (espan_t *span = surf->spans; span; span = span->pnext) {
pdest = (byte *) d_viewbuffer + screenwidth * span->v;
u = span->u;
u2 = span->u + span->count - 1;
@ -103,6 +104,39 @@ D_DrawSolidSurface (surf_t *surf, int color)
}
}
void
draw_solid_usrface_16 (surf_t *surf, int color)
{
short *pdest, pix;
int u, u2;
pix = d_8to16table[color];
for (espan_t *span = surf->spans; span; span = span->pnext) {
pdest = (short *) d_viewbuffer + screenwidth * span->v;
u = span->u;
u2 = span->u + span->count - 1;
for (;u <= u2; u++) {
pdest[u] = pix;
}
}
}
void
draw_solid_usrface_32 (surf_t *surf, int color)
{
int *pdest, pix;
int u, u2;
pix = d_8to24table[color];
for (espan_t *span = surf->spans; span; span = span->pnext) {
pdest = (int *) d_viewbuffer + screenwidth * span->v;
u = span->u;
u2 = span->u + span->count - 1;
for (;u <= u2; u++) {
pdest[u] = pix;
}
}
}
static void
D_CalcGradients (msurface_t *pface)
@ -167,7 +201,8 @@ D_DrawSurfaces (void)
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
D_DrawSolidSurface (s, ((size_t) s->data & 0xFF));
int color = (size_t) s->data & 0xff;
sw_ctx->draw->draw_solid_usrface (s, color);
D_DrawZSpans (s->spans);
}
} else {
@ -183,10 +218,10 @@ D_DrawSurfaces (void)
if (s->flags & SURF_DRAWSKY) {
if (!r_skymade) {
R_MakeSky ();
sw_ctx->draw->make_sky ();
}
D_DrawSkyScans (s->spans);
sw_ctx->draw->draw_sky_scans (s->spans);
D_DrawZSpans (s->spans);
} else if (s->flags & SURF_DRAWBACKGROUND) {
// set up a gradient for the background surface that places
@ -195,7 +230,8 @@ D_DrawSurfaces (void)
d_zistepv = 0;
d_ziorigin = -0.9;
D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF);
int color = r_clearcolor->int_val & 0xff;
sw_ctx->draw->draw_solid_usrface (s, color);
D_DrawZSpans (s->spans);
} else if (s->flags & SURF_DRAWTURB) {
pface = s->data;

View file

@ -35,6 +35,7 @@
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
#define NUM_MIPS 4
@ -45,6 +46,7 @@ float d_scalemip[NUM_MIPS - 1];
static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 };
float d_zitable[65536];
void (*d_drawspans) (espan_t *pspan);
@ -60,7 +62,16 @@ D_Init (void)
vr_data.vid->vid_internal->flush_caches = D_FlushCaches;
vr_data.vid->vid_internal->init_caches = D_InitCaches;
// LordHavoc: compute 1/zi table for use in rendering code everywhere
if (!d_zitable[1]) {
int i;
d_zitable[0] = 0;
for (i = 1;i < 65536;i++)
d_zitable[i] = (65536.0 * 65536.0 / (double) i);
}
VID_InitBuffers ();
VID_MakeColormaps ();
}
void
@ -82,7 +93,7 @@ D_SetupFrame (void)
if (r_dowarp)
screenwidth = WARP_WIDTH;
else
screenwidth = vid.rowbytes;
screenwidth = vid.rowbytes / sw_ctx->pixbytes;
d_roverwrapped = false;
d_initial_rover = sc_rover;
@ -92,7 +103,7 @@ D_SetupFrame (void)
for (i = 0; i < (NUM_MIPS - 1); i++)
d_scalemip[i] = basemip[i] * d_mipscale->value;
d_drawspans = D_DrawSpans8;
d_drawspans = sw_ctx->draw->draw_spans;
}
void

View file

@ -31,8 +31,9 @@
#include "QF/render.h"
#include "QF/sys.h"
#include "r_internal.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_sw.h"
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
@ -70,7 +71,7 @@ D_ViewChanged (void)
if (r_dowarp)
rowpixels = WARP_WIDTH;
else
rowpixels = vid.rowbytes;
rowpixels = vid.rowbytes / sw_ctx->pixbytes;
scale_for_mip = xscale;
if (yscale > xscale)

View file

@ -30,6 +30,8 @@
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
#ifdef PIC
@ -38,7 +40,7 @@
#ifndef USE_INTEL_ASM
void
D_DrawParticle (particle_t *pparticle)
draw_particle_8 (particle_t *pparticle)
{
vec3_t local, transformed;
float zi;
@ -163,3 +165,260 @@ D_DrawParticle (particle_t *pparticle)
}
}
#endif // !USE_INTEL_ASM
void
draw_particle_16 (particle_t *pparticle)
{
vec3_t local, transformed;
float zi;
short *pz;
int i, izi, pix, count, u, v;
// transform point
VectorSubtract (pparticle->pos, r_origin, local);
transformed[0] = DotProduct (local, r_pright);
transformed[1] = DotProduct (local, r_pup);
transformed[2] = DotProduct (local, r_ppn);
if (transformed[2] < PARTICLE_Z_CLIP)
return;
// project the point
// FIXME: preadjust xcenter and ycenter
zi = 1.0 / transformed[2];
u = (int) (xcenter + zi * transformed[0] + 0.5);
v = (int) (ycenter - zi * transformed[1] + 0.5);
if ((v > d_vrectbottom_particle)
|| (u > d_vrectright_particle)
|| (v < d_vrecty) || (u < d_vrectx)) {
return;
}
pz = d_pzbuffer + (d_zwidth * v) + u;
izi = (int) (zi * 0x8000);
pix = izi >> d_pix_shift;
if (pix < d_pix_min)
pix = d_pix_min;
else if (pix > d_pix_max)
pix = d_pix_max;
unsigned short *pdest = (unsigned short *) d_viewbuffer +
d_scantable[v] + u,
pixcolor = d_8to16table[(int) pparticle->icolor];
switch (pix) {
case 1:
count = 1 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
}
break;
case 2:
count = 2 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
}
break;
case 3:
count = 3 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
}
break;
case 4:
count = 4 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
if (pz[3] <= izi) {
pz[3] = izi;
pdest[3] = pixcolor;
}
}
break;
default:
count = pix << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
for (i = 0; i < pix; i++) {
if (pz[i] <= izi) {
pz[i] = izi;
pdest[i] = pixcolor;
}
}
}
break;
}
}
void
draw_particle_32 (particle_t *pparticle)
{
vec3_t local, transformed;
float zi;
short *pz;
int i, izi, pix, count, u, v;
// transform point
VectorSubtract (pparticle->pos, r_origin, local);
transformed[0] = DotProduct (local, r_pright);
transformed[1] = DotProduct (local, r_pup);
transformed[2] = DotProduct (local, r_ppn);
if (transformed[2] < PARTICLE_Z_CLIP)
return;
// project the point
// FIXME: preadjust xcenter and ycenter
zi = 1.0 / transformed[2];
u = (int) (xcenter + zi * transformed[0] + 0.5);
v = (int) (ycenter - zi * transformed[1] + 0.5);
if ((v > d_vrectbottom_particle)
|| (u > d_vrectright_particle)
|| (v < d_vrecty) || (u < d_vrectx)) {
return;
}
pz = d_pzbuffer + (d_zwidth * v) + u;
izi = (int) (zi * 0x8000);
pix = izi >> d_pix_shift;
if (pix < d_pix_min)
pix = d_pix_min;
else if (pix > d_pix_max)
pix = d_pix_max;
int *pdest = (int *) d_viewbuffer + d_scantable[v] + u,
pixcolor = d_8to24table[(int) pparticle->icolor];
switch (pix) {
case 1:
count = 1 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
}
break;
case 2:
count = 2 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
}
break;
case 3:
count = 3 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
}
break;
case 4:
count = 4 << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
if (pz[3] <= izi) {
pz[3] = izi;
pdest[3] = pixcolor;
}
}
break;
default:
count = pix << d_y_aspect_shift;
for (; count; count--, pz += d_zwidth, pdest += screenwidth) {
for (i = 0; i < pix; i++) {
if (pz[i] <= izi) {
pz[i] = izi;
pdest[i] = pixcolor;
}
}
}
break;
}
}

View file

@ -55,8 +55,8 @@
#define P 12+4
.align 4
.globl C(D_DrawParticle)
C(D_DrawParticle):
.globl C(draw_particle_8)
C(draw_particle_8):
pushl %ebp // preserve caller's stack frame
pushl %edi // preserve register variables
pushl %ebx

View file

@ -756,8 +756,8 @@ LDone:
.globl C(D_PolysetAff8Start)
C(D_PolysetAff8Start):
.globl C(D_PolysetDrawSpans8)
C(D_PolysetDrawSpans8):
.globl C(polyset_draw_spans_8)
C(polyset_draw_spans_8):
pushl %esi // preserve register variables
pushl %ebx

View file

@ -33,6 +33,7 @@
#include "d_local.h"
#include "r_internal.h"
#include "vid_sw.h"
int ubasestep, errorterm, erroradjustup, erroradjustdown;
@ -594,7 +595,7 @@ InitGel (byte * palette)
#ifndef USE_INTEL_ASM
void
D_PolysetDrawSpans8 (spanpackage_t * pspanpackage)
polyset_draw_spans_8 (spanpackage_t * pspanpackage)
{
int lcount;
byte *lpdest;
@ -651,6 +652,178 @@ D_PolysetDrawSpans8 (spanpackage_t * pspanpackage)
}
#endif // !USE_INTEL_ASM
void
polyset_draw_spans_16 (spanpackage_t * pspanpackage)
{
int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan;
// LordHavoc: compute skin row table
for (i = 0, j = -r_affinetridesc.skinheight * r_affinetridesc.skinwidth;
i < r_affinetridesc.skinheight*2;i++, j += r_affinetridesc.skinwidth)
texscantable[i] = j;
texscan = texscantable + r_affinetridesc.skinheight;
{
int lcount, count = 0;
short *lpdest;
byte *lptex;
int lsfrac, ltfrac;
int llight;
int lzi;
short *lpz;
do
{
lcount = d_aspancount - pspanpackage->count;
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_aspancount += d_countextrastep;
errorterm -= erroradjustdown;
}
else
d_aspancount += ubasestep;
if (lcount)
{
lpdest = (short *) pspanpackage->pdest;
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight = pspanpackage->light;
lzi = pspanpackage->zi;
do
{
if ((lzi >> 16) < *lpz) // hidden
{
count = 0;
goto skiploop16;
}
drawloop16:
*lpz++ = lzi >> 16;
*lpdest++ = ((short *)acolormap)[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + (lsfrac >> 16)]];
lzi += r_zistepx;
lsfrac += r_sstepx;
ltfrac += r_tstepx;
llight += r_lstepx;
}
while (--lcount);
goto done16;
do
{
if ((lzi >> 16) >= *lpz) // draw
{
lsfrac += r_sstepx * count;
ltfrac += r_tstepx * count;
llight += r_lstepx * count;
lpdest += count;
goto drawloop16;
}
skiploop16:
count++;
lzi += r_zistepx;
lpz++;
}
while (--lcount);
done16: ;
}
pspanpackage++;
}
while (pspanpackage->count != -999999);
}
}
void
polyset_draw_spans_32 (spanpackage_t * pspanpackage)
{
int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan;
// LordHavoc: compute skin row table
for (i = 0, j = -r_affinetridesc.skinheight * r_affinetridesc.skinwidth;
i < r_affinetridesc.skinheight*2;i++, j += r_affinetridesc.skinwidth)
texscantable[i] = j;
texscan = texscantable + r_affinetridesc.skinheight;
{
int lcount, count = 0;
int *lpdest;
byte *lptex;
int lsfrac, ltfrac;
int llight;
int lzi;
short *lpz;
do
{
lcount = d_aspancount - pspanpackage->count;
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_aspancount += d_countextrastep;
errorterm -= erroradjustdown;
}
else
d_aspancount += ubasestep;
if (lcount)
{
lpdest = (int *) pspanpackage->pdest;
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight = pspanpackage->light;
lzi = pspanpackage->zi;
do
{
if ((lzi >> 16) < *lpz) // hidden
{
count = 0;
goto skiploop32;
}
drawloop32:
*lpz++ = lzi >> 16;
*lpdest++ =
vid.colormap32[(llight & 0xFF00) |
lptex[texscan[ltfrac >> 16] +
(lsfrac >> 16)]];
lzi += r_zistepx;
lsfrac += r_sstepx;
ltfrac += r_tstepx;
llight += r_lstepx;
}
while (--lcount);
goto done32;
do
{
if ((lzi >> 16) >= *lpz) // draw
{
lsfrac += r_sstepx * count;
ltfrac += r_tstepx * count;
llight += r_lstepx * count;
lpdest += count;
goto drawloop32;
}
skiploop32:
count++;
lzi += r_zistepx;
lpz++;
}
while (--lcount);
done32: ;
}
pspanpackage++;
}
while (pspanpackage->count != -999999);
}
}
void
D_RasterizeAliasPolySmooth (void)
@ -824,7 +997,7 @@ D_RasterizeAliasPolySmooth (void)
originalcount = a_spans[initialrightheight].count;
a_spans[initialrightheight].count = -999999; // mark end of the
// spanpackages
D_PolysetDrawSpans8 (a_spans);
sw_ctx->draw->polyset_draw_spans (a_spans);
// scan out the bottom part of the right edge, if it exists
if (pedgetable->numrightedges == 2) {
@ -847,7 +1020,7 @@ D_RasterizeAliasPolySmooth (void)
d_countextrastep = ubasestep + 1;
a_spans[initialrightheight + height].count = -999999;
// mark end of the spanpackages
D_PolysetDrawSpans8 (pstart);
sw_ctx->draw->polyset_draw_spans (pstart);
}
}

View file

@ -33,6 +33,8 @@
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
byte *r_turb_pbase;
byte *r_turb_pdest;
@ -47,7 +49,7 @@ int r_turb_spancount;
the sine warp, to keep the edges from wrapping
*/
void
D_WarpScreen (void)
warp_screen_8 (void)
{
int w, h;
int u, v;
@ -96,6 +98,105 @@ D_WarpScreen (void)
}
}
void
warp_screen_16 (void)
{
int w, h;
int u, v;
int scr_x = vr_data.scr_view->xpos;
int scr_y = vr_data.scr_view->ylen;
int scr_w = vr_data.scr_view->xpos;
int scr_h = vr_data.scr_view->ylen;
short *dest;
int *turb;
int *col;
short **row;
short *rowptr[MAXHEIGHT];
int column[MAXWIDTH];
float wratio, hratio;
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
wratio = w / (float) scr_w;
hratio = h / (float) scr_h;
for (v = 0; v < scr_h + AMP2 * 2; v++) {
rowptr[v] = (short *) d_viewbuffer +
(r_refdef.vrect.y * screenwidth) +
(screenwidth * (int) ((float) v * hratio * h /
(h + AMP2 * 2)));
}
for (u = 0; u < scr_w + AMP2 * 2; u++) {
column[u] = r_refdef.vrect.x +
(int) ((float) u * wratio * w / (w + AMP2 * 2));
}
turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1));
dest = (short *) vid.buffer + scr_y * (vid.rowbytes >> 1) + scr_x;
for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 1)) {
col = &column[turb[v]];
row = &rowptr[v];
for (u = 0; u < scr_w; u += 4) {
dest[u + 0] = row[turb[u + 0]][col[u + 0]];
dest[u + 1] = row[turb[u + 1]][col[u + 1]];
dest[u + 2] = row[turb[u + 2]][col[u + 2]];
dest[u + 3] = row[turb[u + 3]][col[u + 3]];
}
}
}
void
warp_screen_32 (void)
{
int w, h;
int u, v;
int scr_x = vr_data.scr_view->xpos;
int scr_y = vr_data.scr_view->ylen;
int scr_w = vr_data.scr_view->xpos;
int scr_h = vr_data.scr_view->ylen;
int *dest;
int *turb;
int *col;
int **row;
int *rowptr[MAXHEIGHT];
int column[MAXWIDTH];
float wratio, hratio;
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
wratio = w / (float) scr_w;
hratio = h / (float) scr_h;
for (v = 0; v < scr_h + AMP2 * 2; v++) {
rowptr[v] = (int *) d_viewbuffer +
(r_refdef.vrect.y * screenwidth) +
(screenwidth * (int) ((float) v * hratio * h /
(h + AMP2 * 2)));
}
for (u = 0; u < scr_w + AMP2 * 2; u++) {
column[u] = r_refdef.vrect.x +
(int) ((float) u * wratio * w / (w + AMP2 * 2));
}
turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1));
dest = (int *) vid.buffer + scr_y * (vid.rowbytes >> 2) + scr_x;
for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 2)) {
col = &column[turb[v]];
row = &rowptr[v];
for (u = 0; u < scr_w; u += 4) {
dest[u + 0] = row[turb[u + 0]][col[u + 0]];
dest[u + 1] = row[turb[u + 1]][col[u + 1]];
dest[u + 2] = row[turb[u + 2]][col[u + 2]];
dest[u + 3] = row[turb[u + 3]][col[u + 3]];
}
}
}
#ifdef PIC
#undef USE_INTEL_ASM //XXX asm pic hack
@ -103,7 +204,7 @@ D_WarpScreen (void)
#ifndef USE_INTEL_ASM
void
D_DrawTurbulent8Span (void)
draw_turbulent_span_8 (void)
{
int sturb, tturb;
@ -121,6 +222,41 @@ D_DrawTurbulent8Span (void)
}
#endif // !USE_INTEL_ASM
void
draw_turbulent_span_16 (void)
{
int sturb, tturb;
short *pdest = (short *) r_turb_pdest;
do {
sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) &
(CYCLE - 1)]) >> 16) & 63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) &
(CYCLE - 1)]) >> 16) & 63;
*pdest++ = d_8to16table[r_turb_pbase[(tturb << 6) + sturb]];
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
r_turb_pdest = (byte *)pdest;
}
void
draw_turbulent_span_32 (void)
{
int sturb, tturb;
int *pdest = (int *) r_turb_pdest;
do {
sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) &
(CYCLE - 1)]) >> 16) & 63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) &
(CYCLE - 1)]) >> 16) & 63;
*pdest++ = d_8to24table[r_turb_pbase[(tturb << 6) + sturb]];
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
r_turb_pdest = (byte *)pdest;
}
void
Turbulent (espan_t *pspan)
{
@ -236,7 +372,7 @@ Turbulent (espan_t *pspan)
r_turb_s = r_turb_s & ((CYCLE << 16) - 1);
r_turb_t = r_turb_t & ((CYCLE << 16) - 1);
D_DrawTurbulent8Span ();
sw_ctx->draw->draw_turbulent_span ();
r_turb_s = snext;
r_turb_t = tnext;
@ -248,7 +384,7 @@ Turbulent (espan_t *pspan)
#ifndef USE_INTEL_ASM
void
D_DrawSpans8 (espan_t *pspan)
draw_spans_8 (espan_t *pspan)
{
int count, spancount;
unsigned char *pbase, *pdest;
@ -373,6 +509,285 @@ D_DrawSpans8 (espan_t *pspan)
}
#endif
void
draw_spans_16 (espan_t *pspan)
{
short *pbase = (short *) cacheblock, *pdest;
int count;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv;
float sdivz8stepu, tdivz8stepu, zi8stepu;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
do {
pdest = (short *) d_viewbuffer + (screenwidth * pspan->v) +
pspan->u;
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu;
tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = d_zitable[(unsigned short) zi];
s = (int) (sdivz * z) + sadjust;
s = bound(0, s, bbextents);
t = (int) (tdivz * z) + tadjust;
t = bound(0, t, bbextentt);
while(count >= 8) {
count -= 8;
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sadjust;
snext = bound(8, snext, bbextents);
tnext = (int) (tdivz * z) + tadjust;
tnext = bound(8, tnext, bbextentt);
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s = snext;t = tnext;
pdest += 8;
}
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span
// (so can't step off polygon), clamp, calculate s and t steps
// across span by division, biasing steps low so we don't run
// off the texture
//countminus1 = (float) (count - 1);
sdivz += d_sdivzstepu * count; //minus1;
tdivz += d_tdivzstepu * count; //minus1;
zi += d_zistepu * 65536.0f * count; //minus1;
z = d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sadjust;
snext = bound(count, snext, bbextents);
tnext = (int) (tdivz * z) + tadjust;
tnext = bound(count, tnext, bbextentt);
if (count > 1) {
sstep = (snext - s) / count; //(count - 1);
tstep = (tnext - t) / count; //(count - 1);
if (count & 4)
{
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;t += tstep;
pdest += 4;
}
if (count & 2)
{
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest += 2;
}
if (count & 1)
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
}
else
{
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
}
}
} while ((pspan = pspan->pnext) != NULL);
}
void
draw_spans_32 (espan_t *pspan)
{
int *pbase = (int *) cacheblock, *pdest;
int count;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv;
float sdivz8stepu, tdivz8stepu, zi8stepu;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
do {
pdest = (int *) d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu;
tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = d_zitable[(unsigned short) zi];
s = (int) (sdivz * z) + sadjust;
s = bound(0, s, bbextents);
t = (int) (tdivz * z) + tadjust;
t = bound(0, t, bbextentt);
while(count >= 8) {
count -= 8;
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sadjust;
snext = bound(8, snext, bbextents);
tnext = (int) (tdivz * z) + tadjust;
tnext = bound(8, tnext, bbextentt);
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s = snext;
t = tnext;
pdest += 8;
}
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span
// (so can't step off polygon), clamp, calculate s and t steps
// across span by division, biasing steps low so we don't run
// off the texture
//countminus1 = (float) (count - 1);
sdivz += d_sdivzstepu * count; //minus1;
tdivz += d_tdivzstepu * count; //minus1;
zi += d_zistepu * 65536.0f * count; //minus1;
z = d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sadjust;
snext = bound(count, snext, bbextents);
tnext = (int) (tdivz * z) + tadjust;
tnext = bound(count, tnext, bbextentt);
if (count > 1) {
sstep = (snext - s) / count; //(count - 1);
tstep = (tnext - t) / count; //(count - 1);
if (count & 4)
{
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest += 4;
}
if (count & 2)
{
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest += 2;
}
if (count & 1)
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
}
else
{
pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)];
}
}
} while ((pspan = pspan->pnext) != NULL);
}
#ifndef USE_INTEL_ASM
void
D_DrawZSpans (espan_t *pspan)

View file

@ -49,8 +49,8 @@
//----------------------------------------------------------------------
.align 4
.globl C(D_DrawTurbulent8Span)
C(D_DrawTurbulent8Span):
.globl C(draw_turbulent_span_8)
C(draw_turbulent_span_8):
pushl %ebp // preserve caller's stack frame pointer
pushl %esi // preserve register variables
pushl %edi

View file

@ -32,6 +32,7 @@
#include "d_local.h"
#include "r_internal.h"
#include "vid_sw.h"
#define SKY_SPAN_SHIFT 5
#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT)
@ -65,7 +66,7 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
}
void
D_DrawSkyScans (espan_t *pspan)
draw_sky_scans_8 (espan_t *pspan)
{
int count, spancount, u, v;
unsigned char *pdest;
@ -133,3 +134,141 @@ D_DrawSkyScans (espan_t *pspan)
} while ((pspan = pspan->pnext) != NULL);
}
void
draw_sky_scans_16 (espan_t *pspan)
{
int count, spancount, u, v;
short *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
snext = 0; // ditto
tnext = 0; // ditto
do {
pdest = (short *) d_viewbuffer + screenwidth * pspan->v + pspan->u;
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
do {
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
count -= spancount;
if (count) {
u += spancount;
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
} else {
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = (float) (spancount - 1);
if (spancountminus1 > 0) {
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
do {
*pdest++ = ((short *) r_skysource)
[((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
void
draw_sky_scans_32 (espan_t *pspan)
{
int count, spancount, u, v;
int *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
snext = 0; // ditto
tnext = 0; // ditto
do {
pdest = (int *) d_viewbuffer + screenwidth * pspan->v + pspan->u;
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
do {
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
count -= spancount;
if (count) {
u += spancount;
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
} else {
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = (float) (spancount - 1);
if (spancountminus1 > 0) {
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
do {
*pdest++ = ((int *) r_skysource)
[((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}

View file

@ -95,8 +95,8 @@ LClampHigh5:
#define pspans 4+16
.align 4
.globl C(D_SpriteDrawSpans)
C(D_SpriteDrawSpans):
.globl C(sprite_draw_spans_8)
C(sprite_draw_spans_8):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables

View file

@ -32,6 +32,8 @@
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static int sprite_height;
static int minindex, maxindex;
@ -45,7 +47,7 @@ static sspan_t *sprite_spans;
#ifndef USE_INTEL_ASM
void
D_SpriteDrawSpans (sspan_t *pspan)
sprite_draw_spans_8 (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
@ -194,6 +196,307 @@ D_SpriteDrawSpans (sspan_t *pspan)
}
#endif
void
sprite_draw_spans_16 (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase;
short *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = (byte *) cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
do {
pdest = (short *) d_viewbuffer + screenwidth * pspan->v + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan2;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu;
tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = d_zitable[(int) zi];
// we count on FP exceptions being turned off to avoid range
// problems
izi = (int) (zi * 0x8000);
s = (int) (sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int) (tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of
// span, calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = d_zitable[(int) zi];
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from causing overstepping
// & running off the texture's edge
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel in
// span (so can't step off polygon), clamp, calculate s
// and t steps across span by division, biasing steps
// low so we don't run off the texture
spancountminus1 = (float) (spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * 65536.0f * spancountminus1;
z = d_zitable[(int) zi];
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from from causing
// overstepping & running off the
// edge of the texture
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
if (spancount > 1) {
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do {
btemp = pbase[(s >> 16) + (t >> 16) * cachewidth];
if (btemp != TRANSPARENT_COLOR) {
if (*pz <= (izi >> 16)) {
*pz = izi >> 16;
*pdest = d_8to16table[btemp];
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan2:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
void
sprite_draw_spans_32 (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase;
int *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = (byte *) cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
do {
pdest = (int *) d_viewbuffer + screenwidth * pspan->v + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan4;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu;
tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = d_zitable[(int) zi];
// we count on FP exceptions being turned off to avoid range
// problems
izi = (int) (zi * 0x8000);
s = (int) (sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int) (tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of
// span, calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = d_zitable[(int) zi];
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from causing overstepping
// & running off the texture's edge
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel in
// span (so can't step off polygon), clamp, calculate s
// and t steps across span by division, biasing steps low
// so we don't run off the texture
spancountminus1 = (float) (spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * 65536.0f * spancountminus1;
z = d_zitable[(int) zi];
snext = (int) (sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps fromcausing overstepping
// & running off the texture's edge
tnext = (int) (tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
if (spancount > 1) {
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do {
btemp = pbase[(s >> 16) + (t >> 16) * cachewidth];
if (btemp != TRANSPARENT_COLOR) {
if (*pz <= (izi >> 16)) {
*pz = izi >> 16;
*pdest = d_8to24table[btemp];
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan4:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
static void
D_SpriteScanLeftEdge (void)
{
@ -412,5 +715,5 @@ D_DrawSprite (void)
D_SpriteCalculateGradients ();
D_SpriteScanLeftEdge ();
D_SpriteScanRightEdge ();
D_SpriteDrawSpans (sprite_spans);
sw_ctx->draw->sprite_draw_spans (sprite_spans);
}

View file

@ -37,6 +37,7 @@
#include "compat.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_sw.h"
float surfscale;
@ -69,7 +70,7 @@ D_SurfaceCacheForRes (void *data, int width, int height)
if (pix > 64000)
size += (pix - 64000) * 3;
return size;
return size * sw_ctx->pixbytes;
}
static void
@ -141,7 +142,7 @@ D_SCAlloc (int width, int size)
if ((width < 0) || (width > 512)) // FIXME shouldn't really have a max
Sys_Error ("D_SCAlloc: bad cache width %d", width);
if ((size <= 0) || (size > 0x40000)) // FIXME ditto
if ((size <= 0) || (size > 0x40000 * sw_ctx->pixbytes)) // FIXME ditto
Sys_Error ("D_SCAlloc: bad cache size %d", size);
// This adds the offset of data[0] in the surfcache_t struct.
@ -195,7 +196,8 @@ D_SCAlloc (int width, int size)
new->width = width;
// DEBUG
if (width > 0)
new->height = (size - sizeof (*new) + sizeof (new->data)) / width;
new->height = (size - sizeof (*new) + sizeof (new->data)) /
(width * sw_ctx->pixbytes);
new->owner = NULL; // should be set properly after return
@ -252,14 +254,14 @@ D_CacheSurface (msurface_t *surface, int miplevel)
surfscale = 1.0 / (1 << miplevel);
r_drawsurf.surfmip = miplevel;
r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
r_drawsurf.rowbytes = r_drawsurf.surfwidth;
r_drawsurf.rowbytes = r_drawsurf.surfwidth * sw_ctx->pixbytes;
r_drawsurf.surfheight = surface->extents[1] >> miplevel;
// allocate memory if needed
if (!cache) {
// if a texture just animated, don't reallocate it
cache = D_SCAlloc (r_drawsurf.surfwidth,
r_drawsurf.surfwidth * r_drawsurf.surfheight);
r_drawsurf.rowbytes * r_drawsurf.surfheight);
surface->cachespots[miplevel] = cache;
cache->owner = &surface->cachespots[miplevel];
cache->mipscale = surfscale;

View file

@ -30,10 +30,12 @@
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
void
D_DrawZPoint (void)
draw_z_point_8 (void)
{
byte *pdest;
short *pz;
@ -48,3 +50,35 @@ D_DrawZPoint (void)
*pdest = r_zpointdesc.color;
}
}
void
draw_z_point_16 (void)
{
short *pz;
int izi;
pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
izi = (int) (r_zpointdesc.zi * 0x8000);
if (*pz <= izi) {
*pz = izi;
((short *) d_viewbuffer) [d_scantable[r_zpointdesc.v]
+ r_zpointdesc.u] = d_8to16table[r_zpointdesc.color];
}
}
void
draw_z_point_32 (void)
{
short *pz;
int izi;
pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
izi = (int) (r_zpointdesc.zi * 0x8000);
if (*pz <= izi) {
*pz = izi;
((int *) d_viewbuffer) [d_scantable[r_zpointdesc.v]
+ r_zpointdesc.u] = d_8to24table[r_zpointdesc.color];
}
}

File diff suppressed because it is too large Load diff

View file

@ -37,9 +37,8 @@
#include "vid_sw.h"
/* SCREEN SHOTS */
tex_t *
sw_SCR_CaptureBGR (void)
capture_bgr_8 (void)
{
int count, x, y;
tex_t *tex;
@ -66,3 +65,21 @@ sw_SCR_CaptureBGR (void)
}
return tex;
}
tex_t *
capture_bgr_16 (void)
{
return capture_bgr_8 ();//FIXME
}
tex_t *
capture_bgr_32 (void)
{
return capture_bgr_8 ();//FIXME
}
tex_t *
sw_SCR_CaptureBGR (void)
{
return sw_ctx->draw->capture_bgr ();
}

View file

@ -55,8 +55,8 @@ C(R_Surf8Start):
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock_mip0)
C(R_DrawSurfaceBlock_mip0):
.globl C(R_DrawSurfaceBlock8_mip0)
C(R_DrawSurfaceBlock8_mip0):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
@ -70,7 +70,7 @@ C(R_DrawSurfaceBlock_mip0):
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
movl C(psource),%esi
Lv_loop_mip0:
@ -256,8 +256,8 @@ LBPatch15:
movl %edx,C(lightright)
jc Lblockloop8_mip0
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
// if (psource >= r_sourcemax)
// psource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip0
@ -281,8 +281,8 @@ LSkip_mip0:
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock_mip1)
C(R_DrawSurfaceBlock_mip1):
.globl C(R_DrawSurfaceBlock8_mip1)
C(R_DrawSurfaceBlock8_mip1):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
@ -296,7 +296,7 @@ C(R_DrawSurfaceBlock_mip1):
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
movl C(psource),%esi
Lv_loop_mip1:
@ -426,8 +426,8 @@ LBPatch29:
jc Lblockloop8_mip1
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
// if (psource >= r_sourcemax)
// psource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip1
@ -451,8 +451,8 @@ LSkip_mip1:
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock_mip2)
C(R_DrawSurfaceBlock_mip2):
.globl C(R_DrawSurfaceBlock8_mip2)
C(R_DrawSurfaceBlock8_mip2):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
@ -466,7 +466,7 @@ C(R_DrawSurfaceBlock_mip2):
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
movl C(psource),%esi
Lv_loop_mip2:
@ -566,8 +566,8 @@ LBPatch21:
jc Lblockloop8_mip2
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
// if (psource >= r_sourcemax)
// psource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip2
@ -591,8 +591,8 @@ LSkip_mip2:
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock_mip3)
C(R_DrawSurfaceBlock_mip3):
.globl C(R_DrawSurfaceBlock8_mip3)
C(R_DrawSurfaceBlock8_mip3):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
@ -606,7 +606,7 @@ C(R_DrawSurfaceBlock_mip3):
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
movl C(psource),%esi
Lv_loop_mip3:
@ -708,8 +708,8 @@ LBPatch31:
addl %edx,%esi
addl %ebp,%edi
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
// if (psource >= r_sourcemax)
// psource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip3

View file

@ -33,23 +33,21 @@
#include "QF/render.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
/*
R_LineGraph
Called by only R_DisplayTime
*/
void
R_LineGraph (int x, int y, int *h_vals, int count, int height)
line_grapn_8 (int x, int y, int *h_vals, int count, int height)
{
int h, i, s, color;
int offset = vid.rowbytes;
byte *dest;
// FIXME: disable on no-buffer adapters, or put in the driver
s = height;
while (count--) {
dest = ((byte*)vid.buffer) + vid.rowbytes * y + x++;
dest = ((byte*)vid.buffer) + offset * y + x++;
h = *h_vals++;
@ -65,8 +63,80 @@ R_LineGraph (int x, int y, int *h_vals, int count, int height)
if (h > s)
h = s;
for (i = 0; i < h; i++, dest -= vid.rowbytes) {
for (i = 0; i < h; i++, dest -= offset) {
dest[0] = color;
}
}
}
void
line_grapn_16 (int x, int y, int *h_vals, int count, int height)
{
int h, i, s, color;
int offset = vid.rowbytes >> 1;
uint16_t *dest;
// FIXME: disable on no-buffer adapters, or put in the driver
s = height;
while (count--) {
dest = ((uint16_t*)vid.buffer) + offset * y + x++;
h = *h_vals++;
if (h == 10000)
color = d_8to16table[0x6f]; // yellow
else if (h == 9999)
color = d_8to16table[0x4f]; // red
else if (h == 9998)
color = d_8to16table[0xd0]; // blue
else
color = d_8to16table[0xff]; // pink
if (h > s)
h = s;
for (i = 0; i < h; i++, dest -= offset) {
dest[0] = color;
}
}
}
void
line_grapn_32 (int x, int y, int *h_vals, int count, int height)
{
int h, i, s, color;
int offset = vid.rowbytes >> 2;
uint32_t *dest;
// FIXME: disable on no-buffer adapters, or put in the driver
s = height;
while (count--) {
dest = ((uint32_t*)vid.buffer) + offset * y + x++;
h = *h_vals++;
if (h == 10000)
color = d_8to24table[0x6f]; // yellow
else if (h == 9999)
color = d_8to24table[0x4f]; // red
else if (h == 9998)
color = d_8to24table[0xd0]; // blue
else
color = d_8to24table[0xff]; // pink
if (h > s)
h = s;
for (i = 0; i < h; i++, dest -= offset) {
dest[0] = color;
}
}
}
void
R_LineGraph (int x, int y, int *h_vals, int count, int height)
{
sw_ctx->draw->line_grapn (x, y, h_vals, count, height);
}

View file

@ -39,6 +39,7 @@
#include "d_ifacea.h"
#include "r_internal.h"
#include "vid_sw.h"
#define LIGHT_MIN 5 // lowest light value we'll allow, to
// avoid the need for inner-loop light
@ -563,6 +564,12 @@ R_AliasSetupSkin (entity_t *ent)
r_affinetridesc.skinheight = pmdl->skinheight;
acolormap = vid.colormap8;
if (sw_ctx->pixbytes != 1) {
if (sw_ctx->pixbytes == 2)
acolormap = vid.colormap16;
else
acolormap = vid.colormap32;
}
if (ent->renderer.skin) {
tex_t *base;
@ -655,6 +662,12 @@ R_AliasDrawModel (alight_t *plighting)
if (!acolormap)
acolormap = vid.colormap8;
if (acolormap == vid.colormap8 && sw_ctx->pixbytes != 1) {
if (sw_ctx->pixbytes == 2)
acolormap = vid.colormap16;
else
acolormap = vid.colormap32;
}
if (r_affinetridesc.drawtype) {
D_PolysetUpdateTables (); // FIXME: precalc...

View file

@ -54,11 +54,28 @@
#include "mod_internal.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
#ifdef PIC
# undef USE_INTEL_ASM //XXX asm pic hack
#endif
static sw_draw_t sw_draw_8 = {
#define SW_DRAW_FUNC(name, rettype, params) \
.name = name##_8,
#include "vid_sw_draw.h"
};
static sw_draw_t sw_draw_16 = {
#define SW_DRAW_FUNC(name, rettype, params) \
.name = name##_16,
#include "vid_sw_draw.h"
};
static sw_draw_t sw_draw_32 = {
#define SW_DRAW_FUNC(name, rettype, params) \
.name = name##_32,
#include "vid_sw_draw.h"
};
void *colormap;
static vec3_t viewlightvec;
static alight_t r_viewlighting = { 128, 192, viewlightvec };
@ -117,6 +134,15 @@ sw_R_Init (void)
{
int dummy;
switch (sw_ctx->pixbytes) {
case 1: sw_ctx->draw = &sw_draw_8; break;
case 2: sw_ctx->draw = &sw_draw_16; break;
case 4: sw_ctx->draw = &sw_draw_32; break;
default:
Sys_Error("R_Init: unsupported pixbytes %i",
sw_ctx->pixbytes);
}
r_ent_queue = EntQueue_New (mod_num_types);
// get stack position so we can guess if we are going to overflow
@ -806,7 +832,7 @@ R_RenderView_ (void)
dp_time2 = Sys_DoubleTime ();
if (r_dowarp)
D_WarpScreen ();
sw_ctx->draw->warp_screen ();
if (r_timegraph->int_val)
R_TimeGraph ();

View file

@ -48,6 +48,7 @@
#include "compat.h"
#include "r_internal.h"
#include "vid_sw.h"
void
R_DrawParticles (void)
@ -58,9 +59,10 @@ R_DrawParticles (void)
R_RunParticles (vr_data.frametime);
void (*draw) (struct particle_s *particle) = sw_ctx->draw->draw_particle;
for (unsigned i = 0; i < r_psystem.numparticles; i++) {
particle_t *p = &r_psystem.particles[i];
D_DrawParticle (p);
draw (p);
}
}

View file

@ -28,9 +28,13 @@
# include "config.h"
#endif
#include <string.h>
#include "QF/render.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static int iskyspeed = 8;
@ -47,10 +51,12 @@ int r_skymade;
byte bottomsky[128 * 131];
byte bottommask[128 * 131];
byte newsky[128 * 256]; // newsky and topsky both pack in here, 128
// bytes of newsky on the left of each scan,
// 128 bytes of topsky on the right, because
// the low-level drawers need 256-byte widths
// sky and topsky both pack in here, 128
// bytes of sky on the left of each scan,
// 128 bytes of topsky on the right, because
// the low-level drawers need 256-byte widths
byte skydata[128 * 256];
byte skytex[128 * 256 * 4];
/*
@ -61,115 +67,115 @@ byte newsky[128 * 256]; // newsky and topsky both pack in here, 128
void
R_InitSky (texture_t *mt)
{
int i, j;
byte *src;
src = (byte *) mt + mt->offsets[0];
for (i = 0; i < 128; i++) {
for (j = 0; j < 128; j++) {
newsky[(i * 256) + j + 128] = src[i * 256 + j + 128];
}
}
for (i = 0; i < 128; i++) {
for (j = 0; j < 131; j++) {
if (src[i * 256 + (j & 0x7F)]) {
bottomsky[(i * 131) + j] = src[i * 256 + (j & 0x7F)];
bottommask[(i * 131) + j] = 0;
} else {
bottomsky[(i * 131) + j] = 0;
bottommask[(i * 131) + j] = 0xff;
}
}
}
r_skysource = newsky;
memcpy (skydata, (byte *) mt + mt->offsets[0], 128 * 256);
r_skysource = skytex;
}
void
R_MakeSky (void)
make_sky_8 (void)
{
int x, y;
int ofs, baseofs;
int xshift, yshift;
byte *pnewsky;
int x, y, xshift1, yshift1, xshift2, yshift2;
byte *base1, *base2;
static int xlast = -1, ylast = -1;
xshift = r_skytime * r_skyspeed;
yshift = r_skytime * r_skyspeed;
xshift2 = r_skytime * r_skyspeed * 2.0f;
yshift2 = r_skytime * r_skyspeed * 2.0f;
if ((xshift == xlast) && (yshift == ylast))
if ((xshift2 == xlast) && (yshift2 == ylast))
return;
xlast = xshift;
ylast = yshift;
xlast = xshift2;
ylast = yshift2;
xshift1 = xshift2 >> 1;
yshift1 = yshift2 >> 1;
pnewsky = &newsky[0];
for (y = 0; y < SKYSIZE; y++) {
baseofs = ((y + yshift) & SKYMASK) * 131;
for (x = 0; x < SKYSIZE; x++) {
ofs = baseofs + ((x + xshift) & SKYMASK);
*pnewsky = (*(pnewsky + 128) & bottommask[ofs]) | bottomsky[ofs];
pnewsky = pnewsky + 1;
byte *out = (byte *) skytex;
for (y = 0;y < 128;y++)
{
base1 = &skydata[((y + yshift1) & 127) * 256];
base2 = &skydata[((y + yshift2) & 127) * 256 + 128];
for (x = 0;x < 128;x++)
{
if (base1[(x + xshift1) & 127])
*out = base1[(x + xshift1) & 127];
else
*out = base2[(x + xshift2) & 127];
out++;
}
pnewsky += 128;
out += 128;
}
r_skymade = 1;
}
void
R_GenSkyTile (void *pdest)
make_sky_16 (void)
{
int x, y;
int ofs, baseofs;
int xshift, yshift;
unsigned int *pnewsky;
unsigned int *pd;
int x, y, xshift1, yshift1, xshift2, yshift2;
byte *base1, *base2;
static int xlast = -1, ylast = -1;
xshift = r_skytime * r_skyspeed;
yshift = r_skytime * r_skyspeed;
xshift2 = r_skytime * r_skyspeed * 2.0f;
yshift2 = r_skytime * r_skyspeed * 2.0f;
pnewsky = (unsigned int *) &newsky[0];
pd = (unsigned int *) pdest;
if ((xshift2 == xlast) && (yshift2 == ylast))
return;
for (y = 0; y < SKYSIZE; y++) {
baseofs = ((y + yshift) & SKYMASK) * 131;
xlast = xshift2;
ylast = yshift2;
xshift1 = xshift2 >> 1;
yshift1 = yshift2 >> 1;
// FIXME: clean this up
#if UNALIGNED_OK
for (x = 0; x < SKYSIZE; x += 4) {
ofs = baseofs + ((x + xshift) & SKYMASK);
// PORT: unaligned dword access to bottommask and bottomsky
*pd = (*(pnewsky + (128 / sizeof (unsigned int))) &
*(unsigned int *) &bottommask[ofs]) |
*(unsigned int *) &bottomsky[ofs];
pnewsky++;
pd++;
unsigned short *out = (unsigned short *) skytex;
for (y = 0;y < 128;y++)
{
base1 = &skydata[((y + yshift1) & 127) * 256];
base2 = &skydata[((y + yshift2) & 127) * 256 + 128];
for (x = 0;x < 128;x++)
{
if (base1[(x + xshift1) & 127])
*out = d_8to16table[base1[(x + xshift1) & 127]];
else
*out = d_8to16table[base2[(x + xshift2) & 127]];
out++;
}
#else
for (x = 0; x < SKYSIZE; x++) {
ofs = baseofs + ((x + xshift) & SKYMASK);
*(byte *) pd = (*((byte *) pnewsky + 128) &
*(byte *) & bottommask[ofs]) |
*(byte *) & bottomsky[ofs];
pnewsky = (unsigned int *) ((byte *) pnewsky + 1);
pd = (unsigned int *) ((byte *) pd + 1);
}
#endif
pnewsky += 128 / sizeof (unsigned int);
out += 128;
}
r_skymade = 1;
}
void
make_sky_32 (void)
{
int x, y, xshift1, yshift1, xshift2, yshift2;
byte *base1, *base2;
static int xlast = -1, ylast = -1;
xshift2 = r_skytime * r_skyspeed * 2.0f;
yshift2 = r_skytime * r_skyspeed * 2.0f;
if ((xshift2 == xlast) && (yshift2 == ylast))
return;
xlast = xshift2;
ylast = yshift2;
xshift1 = xshift2 >> 1;
yshift1 = yshift2 >> 1;
unsigned int *out = (unsigned int *) skytex;
for (y = 0;y < 128;y++) {
base1 = &skydata[((y + yshift1) & 127) * 256];
base2 = &skydata[((y + yshift2) & 127) * 256 + 128];
for (x = 0;x < 128;x++) {
if (base1[(x + xshift1) & 127])
*out = d_8to24table[base1[(x + xshift1) & 127]];
else
*out = d_8to24table[base2[(x + xshift2) & 127]];
out++;
}
out += 128;
}
r_skymade = 1;
}
void
R_SetSkyFrame (void)

View file

@ -1,5 +1,5 @@
/*
sw_rsurf.c
rsurf.c
surface-related refresh code
@ -33,43 +33,63 @@
#include "QF/scene/entity.h"
#include "compat.h"
#include "r_internal.h"
#ifdef PIC
# undef USE_INTEL_ASM //XXX asm pic hack
#endif
#include "vid_sw.h"
drawsurf_t r_drawsurf;
int sourcesstep, sourcetstep;
#ifndef USE_INTEL_ASM
static int lightleft;
#endif
static int blocksize;
int sourcetstep;
static int lightleft, blocksize;
int lightdelta, lightdeltastep;
int lightright, lightleftstep, lightrightstep, blockdivshift;
static unsigned int blockdivmask;
void *prowdestbase;
unsigned char *pbasesource;
int surfrowbytes; // used by ASM files
unsigned int *r_lightptr;
byte *prowdestbase;
byte *psource;
int surfrowbytes;
unsigned int *r_lightptr;
int r_stepback;
int r_lightwidth;
static int r_numhblocks;
int r_numvblocks;
static unsigned char *r_source;
unsigned char *r_sourcemax;
static byte *r_source;
byte *r_sourcemax;
void R_DrawSurfaceBlock_mip0 (void);
void R_DrawSurfaceBlock_mip1 (void);
void R_DrawSurfaceBlock_mip2 (void);
void R_DrawSurfaceBlock_mip3 (void);
void R_DrawSurfaceBlock8_mip0 (void);
void R_DrawSurfaceBlock8_mip1 (void);
void R_DrawSurfaceBlock8_mip2 (void);
void R_DrawSurfaceBlock8_mip3 (void);
static void R_DrawSurfaceBlock16_mip0 (void);
static void R_DrawSurfaceBlock16_mip1 (void);
static void R_DrawSurfaceBlock16_mip2 (void);
static void R_DrawSurfaceBlock16_mip3 (void);
static void R_DrawSurfaceBlock32_mip0 (void);
static void R_DrawSurfaceBlock32_mip1 (void);
static void R_DrawSurfaceBlock32_mip2 (void);
static void R_DrawSurfaceBlock32_mip3 (void);
static void (*surfmiptable[4]) (void) = {
R_DrawSurfaceBlock_mip0, R_DrawSurfaceBlock_mip1,
R_DrawSurfaceBlock_mip2, R_DrawSurfaceBlock_mip3};
static void (*surfmiptable8[4]) (void) = {
R_DrawSurfaceBlock8_mip0,
R_DrawSurfaceBlock8_mip1,
R_DrawSurfaceBlock8_mip2,
R_DrawSurfaceBlock8_mip3
};
static unsigned int blocklights[34 * 34]; //FIXME make dynamic
static void (*surfmiptable16[4]) (void) = {
R_DrawSurfaceBlock16_mip0,
R_DrawSurfaceBlock16_mip1,
R_DrawSurfaceBlock16_mip2,
R_DrawSurfaceBlock16_mip3
};
static void (*surfmiptable32[4]) (void) = {
R_DrawSurfaceBlock32_mip0,
R_DrawSurfaceBlock32_mip1,
R_DrawSurfaceBlock32_mip2,
R_DrawSurfaceBlock32_mip3
};
static unsigned blocklights[34 * 34]; //FIXME make dynamic
static void
@ -182,14 +202,30 @@ R_BuildLightMap (void)
if (surf->dlightframe == r_framecount)
R_AddDynamicLights ();
// bound, invert, and shift
for (i = 0; i < size; i++) {
t = (255 * 256 - (int) blocklights[i]) >> (8 - VID_CBITS);
/*
* JohnnyonFlame:
* 32 and 16bpp modes uses the positive lighting, unlike 8bpp
*/
switch (sw_ctx->pixbytes) {
case 1:
// bound, invert, and shift
for (i = 0; i < size; i++) {
t = (255 * 256 - blocklights[i]) >> (8 - VID_CBITS);
if (t < (1 << 6))
t = (1 << 6);
if (t < (1 << 6))
t = (1 << 6);
blocklights[i] = t;
blocklights[i] = t;
}
break;
default:
// LordHavoc: changed to positive (not inverse) lighting
for (i = 0; i < size; i++) {
t = bound(256, blocklights[i] >> (8 - VID_CBITS),
256 * (VID_GRADES - 1));
blocklights[i] = t;
}
break;
}
}
@ -230,34 +266,47 @@ R_DrawSurface (void)
//==============================
pblockdrawer = surfmiptable[r_drawsurf.surfmip];
// TODO: needs to be set only when there is a display settings change
horzblockstep = blocksize;
smax = mt->width >> r_drawsurf.surfmip;
twidth = texwidth;
tmax = mt->height >> r_drawsurf.surfmip;
sourcetstep = texwidth;
r_stepback = tmax * twidth;
r_sourcemax = r_source + (tmax * smax);
soffset = r_drawsurf.surf->texturemins[0];
basetoffset = r_drawsurf.surf->texturemins[1];
// << 16 components are to guarantee positive values for %
soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
+ (tmax << 16)) % tmax) * twidth)];
switch (sw_ctx->pixbytes) {
case 1:
pblockdrawer = surfmiptable8[r_drawsurf.surfmip];
break;
case 2:
pblockdrawer = surfmiptable16[r_drawsurf.surfmip];
break;
case 4:
pblockdrawer = surfmiptable32[r_drawsurf.surfmip];
break;
default:
Sys_Error("R_DrawSurface: unsupported r_pixbytes %i", sw_ctx->pixbytes);
pblockdrawer = NULL;
}
pcolumndest = r_drawsurf.surfdat;
horzblockstep = blocksize * sw_ctx->pixbytes;
r_sourcemax = r_source + (tmax * smax);
// << 16 components are to guarantee positive values for %
basetptr = r_source + (((basetoffset >> r_drawsurf.surfmip) +
(tmax << 16)) % tmax) * twidth;
soffset = (((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax);
pcolumndest = (byte *) r_drawsurf.surfdat;
for (u = 0; u < r_numhblocks; u++) {
r_lightptr = blocklights + u;
prowdestbase = pcolumndest;
pbasesource = basetptr + soffset;
psource = basetptr + soffset;
(*pblockdrawer) ();
@ -269,15 +318,16 @@ R_DrawSurface (void)
}
}
//=============================================================================
#ifndef USE_INTEL_ASM
void
R_DrawSurfaceBlock_mip0 (void)
R_DrawSurfaceBlock8_mip0 (void)
{
int v, i, b, lightstep, lighttemp, light;
unsigned char pix, *psource, *prowdest;
int v, i, b, lightstep, light;
unsigned char pix, *prowdest;
psource = pbasesource;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
@ -290,15 +340,13 @@ R_DrawSurfaceBlock_mip0 (void)
lightrightstep = (r_lightptr[1] - lightright) >> 4;
for (i = 0; i < 16; i++) {
lighttemp = lightleft - lightright;
lightstep = lighttemp >> 4;
lightstep = (lightleft - lightright) >> 4;
light = lightright;
for (b = 15; b >= 0; b--) {
pix = psource[b];
prowdest[b] = ((unsigned char *) vid.colormap8)
[(light & 0xFF00) + pix];
prowdest[b] = vid.colormap8[(light & 0xFF00) + pix];
light += lightstep;
}
@ -314,12 +362,11 @@ R_DrawSurfaceBlock_mip0 (void)
}
void
R_DrawSurfaceBlock_mip1 (void)
R_DrawSurfaceBlock8_mip1 (void)
{
int v, i, b, lightstep, lighttemp, light;
unsigned char pix, *psource, *prowdest;
int v, i, b, lightstep, light;
unsigned char pix, *prowdest;
psource = pbasesource;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
@ -332,15 +379,13 @@ R_DrawSurfaceBlock_mip1 (void)
lightrightstep = (r_lightptr[1] - lightright) >> 3;
for (i = 0; i < 8; i++) {
lighttemp = lightleft - lightright;
lightstep = lighttemp >> 3;
lightstep = (lightleft - lightright) >> 3;
light = lightright;
for (b = 7; b >= 0; b--) {
pix = psource[b];
prowdest[b] = ((unsigned char *) vid.colormap8)
[(light & 0xFF00) + pix];
prowdest[b] = vid.colormap8[(light & 0xFF00) + pix];
light += lightstep;
}
@ -356,12 +401,11 @@ R_DrawSurfaceBlock_mip1 (void)
}
void
R_DrawSurfaceBlock_mip2 (void)
R_DrawSurfaceBlock8_mip2 (void)
{
int v, i, b, lightstep, lighttemp, light;
unsigned char pix, *psource, *prowdest;
int v, i, b, lightstep, light;
unsigned char pix, *prowdest;
psource = pbasesource;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
@ -374,15 +418,13 @@ R_DrawSurfaceBlock_mip2 (void)
lightrightstep = (r_lightptr[1] - lightright) >> 2;
for (i = 0; i < 4; i++) {
lighttemp = lightleft - lightright;
lightstep = lighttemp >> 2;
lightstep = (lightleft - lightright) >> 2;
light = lightright;
for (b = 3; b >= 0; b--) {
pix = psource[b];
prowdest[b] = ((unsigned char *) vid.colormap8)
[(light & 0xFF00) + pix];
prowdest[b] = vid.colormap8[(light & 0xFF00) + pix];
light += lightstep;
}
@ -398,12 +440,11 @@ R_DrawSurfaceBlock_mip2 (void)
}
void
R_DrawSurfaceBlock_mip3 (void)
R_DrawSurfaceBlock8_mip3 (void)
{
int v, i, b, lightstep, lighttemp, light;
unsigned char pix, *psource, *prowdest;
int v, i, b, lightstep, light;
unsigned char pix, *prowdest;
psource = pbasesource;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
@ -416,15 +457,13 @@ R_DrawSurfaceBlock_mip3 (void)
lightrightstep = (r_lightptr[1] - lightright) >> 1;
for (i = 0; i < 2; i++) {
lighttemp = lightleft - lightright;
lightstep = lighttemp >> 1;
lightstep = (lightleft - lightright) >> 1;
light = lightright;
for (b = 1; b >= 0; b--) {
pix = psource[b];
prowdest[b] = ((unsigned char *) vid.colormap8)
[(light & 0xFF00) + pix];
prowdest[b] = vid.colormap8[(light & 0xFF00) + pix];
light += lightstep;
}
@ -442,33 +481,423 @@ R_DrawSurfaceBlock_mip3 (void)
#endif
static void
R_GenTurbTile (byte *pbasetex, void *pdest)
R_DrawSurfaceBlock16_mip0 (void)
{
int *turb;
int i, j, s, t;
byte *pd;
int k, v;
int lightstep, light;
unsigned short *prowdest;
turb = sintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1));
pd = (byte *) pdest;
prowdest = (unsigned short *) prowdestbase;
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
s = (((j << 16) + turb[i & (CYCLE - 1)]) >> 16) & 63;
t = (((i << 16) + turb[j & (CYCLE - 1)]) >> 16) & 63;
*pd++ = *(pbasetex + (t << 6) + s);
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 4;
lightrightstep = (r_lightptr[1] - lightright) >> 4;
for (k = 0; k < 16; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 4;
prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]];
light += lightstep;
prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]];
light += lightstep;
prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]];
light += lightstep;
prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]];
light += lightstep;
prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]];
light += lightstep;
prowdest[8] = vid.colormap16[(light & 0xFF00) + psource[8]];
light += lightstep;
prowdest[9] = vid.colormap16[(light & 0xFF00) + psource[9]];
light += lightstep;
prowdest[10] = vid.colormap16[(light & 0xFF00) + psource[10]];
light += lightstep;
prowdest[11] = vid.colormap16[(light & 0xFF00) + psource[11]];
light += lightstep;
prowdest[12] = vid.colormap16[(light & 0xFF00) + psource[12]];
light += lightstep;
prowdest[13] = vid.colormap16[(light & 0xFF00) + psource[13]];
light += lightstep;
prowdest[14] = vid.colormap16[(light & 0xFF00) + psource[14]];
light += lightstep;
prowdest[15] = vid.colormap16[(light & 0xFF00) + psource[15]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 1);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
void
R_GenTile (msurface_t *psurf, void *pdest)
static void
R_DrawSurfaceBlock16_mip1 (void)
{
if (psurf->flags & SURF_DRAWTURB) {
R_GenTurbTile (((byte *) psurf->texinfo->texture +
psurf->texinfo->texture->offsets[0]), pdest);
} else if (psurf->flags & SURF_DRAWSKY) {
R_GenSkyTile (pdest);
} else {
Sys_Error ("Unknown tile type");
int k, v;
int lightstep, light;
unsigned short *prowdest;
prowdest = (unsigned short *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 3;
lightrightstep = (r_lightptr[1] - lightright) >> 3;
for (k = 0; k < 8; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 3;
prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]];
light += lightstep;
prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]];
light += lightstep;
prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]];
light += lightstep;
prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]];
light += lightstep;
prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 1);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock16_mip2 (void)
{
int k, v;
int lightstep, light;
unsigned short *prowdest;
prowdest = (unsigned short *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 2;
lightrightstep = (r_lightptr[1] - lightright) >> 2;
for (k = 0; k < 4; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 2;
prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 1);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock16_mip3 (void)
{
int v;
unsigned short *prowdest;
prowdest = (unsigned short *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 1;
lightrightstep = (r_lightptr[1] - lightright) >> 1;
prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]];
prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) &
0xFF00) + psource[1]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 1);
prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]];
prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) &
0xFF00) + psource[1]];
psource += sourcetstep;
prowdest += (surfrowbytes >> 1);
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock32_mip0 (void)
{
int k, v;
int lightstep, light;
unsigned int *prowdest;
prowdest = (unsigned int *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 4;
lightrightstep = (r_lightptr[1] - lightright) >> 4;
for (k = 0; k < 16; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 4;
prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]];
light += lightstep;
prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]];
light += lightstep;
prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]];
light += lightstep;
prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]];
light += lightstep;
prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]];
light += lightstep;
prowdest[8] = vid.colormap32[(light & 0xFF00) + psource[8]];
light += lightstep;
prowdest[9] = vid.colormap32[(light & 0xFF00) + psource[9]];
light += lightstep;
prowdest[10] = vid.colormap32[(light & 0xFF00) + psource[10]];
light += lightstep;
prowdest[11] = vid.colormap32[(light & 0xFF00) + psource[11]];
light += lightstep;
prowdest[12] = vid.colormap32[(light & 0xFF00) + psource[12]];
light += lightstep;
prowdest[13] = vid.colormap32[(light & 0xFF00) + psource[13]];
light += lightstep;
prowdest[14] = vid.colormap32[(light & 0xFF00) + psource[14]];
light += lightstep;
prowdest[15] = vid.colormap32[(light & 0xFF00) + psource[15]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock32_mip1 (void)
{
int k, v;
int lightstep, light;
unsigned int *prowdest;
prowdest = (unsigned int *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 3;
lightrightstep = (r_lightptr[1] - lightright) >> 3;
for (k = 0; k < 8; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 3;
prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]];
light += lightstep;
prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]];
light += lightstep;
prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]];
light += lightstep;
prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]];
light += lightstep;
prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock32_mip2 (void)
{
int k, v;
int lightstep, light;
unsigned int *prowdest;
prowdest = (unsigned int *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 2;
lightrightstep = (r_lightptr[1] - lightright) >> 2;
for (k = 0; k < 4; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 2;
prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock32_mip3 (void)
{
int v;
unsigned int *prowdest;
prowdest = (unsigned int *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 1;
lightrightstep = (r_lightptr[1] - lightright) >> 1;
prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]];
prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) &
0xFF00) + psource[1]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]];
prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) &
0xFF00) + psource[1]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
/*
void
R_DrawSurfaceBlock32 (void)
{
int k, v;
int lightstep, light;
unsigned int *prowdest;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> blockdivshift;
lightrightstep = (r_lightptr[1] - lightright) >> blockdivshift;
for (k = 0; k < blocksize; k++) {
int b;
lightstep = (lightright - lightleft) >> blockdivshift;
light = lightleft;
for (b = 0;b < blocksize;b++, light += lightstep)
prowdest[b] = vid.colormap32[(light & 0xFF00) + psource[b]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
*/

View file

@ -1,9 +1,9 @@
/*
vid_common_sw.c
Common software video driver functions
general video driver functions
Copyright (C) 2001 Jeff Teunissen <deek@quakeforge.net>
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
@ -28,11 +28,130 @@
# include "config.h"
#endif
#include <stdlib.h>
#include <math.h>
#include "QF/cvar.h"
#include "QF/mathlib.h"
#include "QF/qargs.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/vid.h"
#include "compat.h"
#include "r_internal.h"
#include "vid_internal.h"
unsigned short d_8to16table[256];
/*
VID_MakeColormap32
LordHavoc: makes a 32bit color*light table, RGBA order, no endian,
may need to be re-ordered to hardware at display time
*/
static void
VID_MakeColormap32 (void *outcolormap, byte *pal)
{
int c, l;
byte *out;
out = (byte *)&d_8to24table;
/*
* Generates colors not affected by lighting, such as
* HUD pieces and general sprites (such as explosions)
*/
for (c = 0; c < 256; c++) {
*out++ = pal[c*3+2];
*out++ = pal[c*3+1];
*out++ = pal[c*3+0];
*out++ = 255;
}
d_8to24table[255] = 0; // 255 is transparent
out = (byte *) outcolormap;
/*
* Generates colors affected by lighting, such as the
* world and other models that give it life, like foes and pickups.
*/
for (l = 0;l < VID_GRADES;l++)
{
for (c = 0;c < vid.fullbright;c++)
{
out[(l*256+c)*4+0] = bound(0, (pal[c*3+2] * l) >> (VID_CBITS - 1),
255);
out[(l*256+c)*4+1] = bound(0, (pal[c*3+1] * l) >> (VID_CBITS - 1),
255);
out[(l*256+c)*4+2] = bound(0, (pal[c*3+0] * l) >> (VID_CBITS - 1),
255);
out[(l*256+c)*4+3] = 255;
}
for (;c < 255;c++)
{
out[(l*256+c)*4+0] = pal[c*3+2];
out[(l*256+c)*4+1] = pal[c*3+1];
out[(l*256+c)*4+2] = pal[c*3+0];
out[(l*256+c)*4+3] = 255;
}
out[(l*256+255)*4+0] = 0;
out[(l*256+255)*4+1] = 0;
out[(l*256+255)*4+2] = 0;
out[(l*256+255)*4+3] = 0;
}
}
static unsigned short
lh24to16bit (int red, int green, int blue)
{
red = bound(0, red, 255);
green = bound(0, green, 255);
blue = bound(0, blue, 255);
red >>= 3;
green >>= 2;
blue >>= 3;
red <<= 11;
green <<= 5;
return (unsigned short) (red | green | blue);
}
/*
VID_MakeColormap16
LordHavoc: makes a 16bit color*light table, RGB order, native endian,
may need to be translated to hardware order at display time
*/
static void
VID_MakeColormap16 (void *outcolormap, byte *pal)
{
int c, l;
unsigned short *out;
out = (unsigned short *)&d_8to16table;
for (c = 0; c < 256; c++)
*out++ = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
d_8to16table[255] = 0; // 255 is transparent
out = (unsigned short *) outcolormap;
for (l = 0;l < VID_GRADES;l++)
{
for (c = 0;c < vid.fullbright;c++)
out[l*256+c] = lh24to16bit(
(pal[c*3+0] * l) >> (VID_CBITS - 1),
(pal[c*3+1] * l) >> (VID_CBITS - 1),
(pal[c*3+2] * l) >> (VID_CBITS - 1));
for (;c < 255;c++)
out[l*256+c] = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
out[l*256+255] = 0;
}
}
/*
VID_MakeColormaps
LordHavoc: makes 8bit, 16bit, and 32bit colormaps and palettes
*/
void
VID_MakeColormaps (void)
{
vid.colormap16 = malloc (256*VID_GRADES * sizeof (unsigned short));
vid.colormap32 = malloc (256*VID_GRADES * sizeof (unsigned int));
SYS_CHECKMEM (vid.colormap16 && vid.colormap32);
VID_MakeColormap16(vid.colormap16, vid.palette);
VID_MakeColormap32(vid.colormap32, vid.palette);
}

View file

@ -1,325 +0,0 @@
/*
d_edge.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/cvar.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static int miplevel;
float sw32_scale_for_mip;
static vec3_t transformed_modelorg;
void
sw32_D_DrawPoly (void)
{
// this driver takes spans, not polygons
}
int
sw32_D_MipLevelForScale (float scale)
{
int lmiplevel;
if (scale >= sw32_d_scalemip[0])
lmiplevel = 0;
else if (scale >= sw32_d_scalemip[1])
lmiplevel = 1;
else if (scale >= sw32_d_scalemip[2])
lmiplevel = 2;
else
lmiplevel = 3;
if (lmiplevel < sw32_d_minmip)
lmiplevel = sw32_d_minmip;
return lmiplevel;
}
// FIXME: clean this up
static void
D_DrawSolidSurface (surf_t *surf, int color)
{
espan_t *span;
switch(sw32_ctx->pixbytes) {
case 1:
{
byte *pdest, pix;
int u, u2;
pix = color;
for (span = surf->spans; span; span = span->pnext)
{
pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * span->v;
u = span->u;
u2 = span->u + span->count - 1;
for (;u <= u2; u++)
pdest[u] = pix;
}
}
break;
case 2:
{
short *pdest, pix;
int u, u2;
pix = sw32_8to16table[color];
for (span = surf->spans; span; span = span->pnext)
{
pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * span->v;
u = span->u;
u2 = span->u + span->count - 1;
for (;u <= u2; u++)
pdest[u] = pix;
}
}
break;
case 4:
{
int *pdest, pix;
int u, u2;
pix = d_8to24table[color];
for (span = surf->spans; span; span = span->pnext)
{
pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * span->v;
u = span->u;
u2 = span->u + span->count - 1;
for (;u <= u2; u++)
pdest[u] = pix;
}
}
break;
default:
Sys_Error("D_DrawSolidSurface: unsupported r_pixbytes %i",
sw32_ctx->pixbytes);
}
}
static void
D_CalcGradients (msurface_t *pface)
{
float mipscale, t;
vec3_t p_temp1, p_saxis, p_taxis;
mipscale = 1.0 / (float) (1 << miplevel);
sw32_TransformVector (pface->texinfo->vecs[0], p_saxis);
sw32_TransformVector (pface->texinfo->vecs[1], p_taxis);
t = sw32_xscaleinv * mipscale;
sw32_d_sdivzstepu = p_saxis[0] * t;
sw32_d_tdivzstepu = p_taxis[0] * t;
t = sw32_yscaleinv * mipscale;
sw32_d_sdivzstepv = -p_saxis[1] * t;
sw32_d_tdivzstepv = -p_taxis[1] * t;
sw32_d_sdivzorigin = p_saxis[2] * mipscale -
sw32_xcenter * sw32_d_sdivzstepu -
sw32_ycenter * sw32_d_sdivzstepv;
sw32_d_tdivzorigin = p_taxis[2] * mipscale -
sw32_xcenter * sw32_d_tdivzstepu -
sw32_ycenter * sw32_d_tdivzstepv;
VectorScale (transformed_modelorg, mipscale, p_temp1);
t = 0x10000 * mipscale;
sw32_sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
((pface->texturemins[0] << 16) >> miplevel)
+ pface->texinfo->vecs[0][3] * t;
sw32_tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
((pface->texturemins[1] << 16) >> miplevel)
+ pface->texinfo->vecs[1][3] * t;
// -1 (-epsilon) so we never wander off the edge of the texture
sw32_bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
sw32_bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}
void
sw32_D_DrawSurfaces (void)
{
surf_t *s;
msurface_t *pface;
surfcache_t *pcurrentcache;
vec3_t world_transformed_modelorg;
vec3_t local_modelorg;
currententity = &r_worldentity;
sw32_TransformVector (modelorg, transformed_modelorg);
VectorCopy (transformed_modelorg, world_transformed_modelorg);
// TODO: could preset a lot of this at mode set time
if (r_drawflat->int_val) {
for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) {
if (!s->spans)
continue;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
D_DrawSolidSurface (s, ((intptr_t) s->data & 0xFF));
sw32_D_DrawZSpans (s->spans);
}
} else {
for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) {
if (!s->spans)
continue;
sw32_r_drawnpolycount++;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
if (s->flags & SURF_DRAWSKY) {
if (!sw32_r_skymade) {
sw32_R_MakeSky ();
}
sw32_D_DrawSkyScans (s->spans);
sw32_D_DrawZSpans (s->spans);
} else if (s->flags & SURF_DRAWBACKGROUND) {
// set up a gradient for the background surface that places
// it effectively at infinity distance from the viewpoint
d_zistepu = 0;
d_zistepv = 0;
d_ziorigin = -0.9;
D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF);
sw32_D_DrawZSpans (s->spans);
} else if (s->flags & SURF_DRAWTURB) {
pface = s->data;
miplevel = 0;
sw32_cacheblock = ((byte *) pface->texinfo->texture +
pface->texinfo->texture->offsets[0]);
sw32_cachewidth = 64;
if (s->insubmodel) {
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; // FIXME: make this passed in
// to sw32_R_RotateBmodel ()
VectorSubtract (r_origin,
Transform_GetWorldPosition (currententity->transform),
local_modelorg);
sw32_TransformVector (local_modelorg, transformed_modelorg);
sw32_R_RotateBmodel (); // FIXME: don't mess with the
// frustum, make entity passed in
}
D_CalcGradients (pface);
sw32_Turbulent (s->spans);
sw32_D_DrawZSpans (s->spans);
if (s->insubmodel) {
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
currententity = &r_worldentity;
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
sw32_R_TransformFrustum ();
}
} else {
if (s->insubmodel) {
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; // FIXME: make this passed in
// to sw32_R_RotateBmodel ()
VectorSubtract (r_origin,
Transform_GetWorldPosition (currententity->transform),
local_modelorg);
sw32_TransformVector (local_modelorg, transformed_modelorg);
sw32_R_RotateBmodel (); // FIXME: don't mess with the
// frustum, make entity passed in
}
pface = s->data;
miplevel = sw32_D_MipLevelForScale (s->nearzi * sw32_scale_for_mip
* pface->texinfo->mipadjust);
// FIXME: make this passed in to D_CacheSurface
pcurrentcache = sw32_D_CacheSurface (pface, miplevel);
sw32_cacheblock = (byte *) pcurrentcache->data;
sw32_cachewidth = pcurrentcache->width;
D_CalcGradients (pface);
sw32_D_DrawSpans (s->spans);
sw32_D_DrawZSpans (s->spans);
if (s->insubmodel) {
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
sw32_R_TransformFrustum ();
currententity = &r_worldentity;
}
}
}
}
}

View file

@ -1,164 +0,0 @@
/*
d_fill.c
clears a specified rectangle to the specified color
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/sys.h"
#include "d_iface.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
void
sw32_D_FillRect (vrect_t *rect, int color)
{
switch (sw32_ctx->pixbytes)
{
case 1:
{
int rx, ry, rwidth, rheight;
byte *dest, pix;
pix = color;
rx = rect->x;
ry = rect->y;
rwidth = rect->width;
rheight = rect->height;
if (rx < 0) {
rwidth += rx;
rx = 0;
}
if (ry < 0) {
rheight += ry;
ry = 0;
}
if ((unsigned) (rx + rwidth) > vid.width)
rwidth = vid.width - rx;
if ((unsigned) (ry + rheight) > vid.height)
rheight = vid.height - rx;
if (rwidth < 1 || rheight < 1)
return;
dest = (byte *) vid.buffer + ry * vid.rowbytes + rx;
for (ry = 0; ry < rheight; ry++)
{
for (rx = 0; rx < rwidth; rx++)
dest[rx] = pix;
dest += vid.rowbytes;
}
}
break;
case 2:
{
int rx, ry, rwidth, rheight;
unsigned short *dest, pix;
pix = sw32_8to16table[color];
rx = rect->x;
ry = rect->y;
rwidth = rect->width;
rheight = rect->height;
if (rx < 0) {
rwidth += rx;
rx = 0;
}
if (ry < 0) {
rheight += ry;
ry = 0;
}
if ((unsigned) (rx + rwidth) > vid.width)
rwidth = vid.width - rx;
if ((unsigned) (ry + rheight) > vid.height)
rheight = vid.height - rx;
if (rwidth < 1 || rheight < 1)
return;
dest = (unsigned short *) vid.buffer + ry * (vid.rowbytes >> 1) +
rx;
for (ry = 0; ry < rheight; ry++)
{
for (rx = 0; rx < rwidth; rx++)
dest[rx] = pix;
dest += (vid.rowbytes >> 1);
}
}
break;
case 4:
{
int rx, ry, rwidth, rheight;
unsigned int *dest, pix;
pix = d_8to24table[color];
rx = rect->x;
ry = rect->y;
rwidth = rect->width;
rheight = rect->height;
if (rx < 0) {
rwidth += rx;
rx = 0;
}
if (ry < 0) {
rheight += ry;
ry = 0;
}
if ((unsigned) (rx + rwidth) > vid.width)
rwidth = vid.width - rx;
if ((unsigned) (ry + rheight) > vid.height)
rheight = vid.height - rx;
if (rwidth < 1 || rheight < 1)
return;
dest = (unsigned int *) vid.buffer + ry * (vid.rowbytes >> 2) + rx;
for (ry = 0; ry < rheight; ry++)
{
for (rx = 0; rx < rwidth; rx++)
dest[rx] = pix;
dest += (vid.rowbytes >> 2);
}
}
break;
default:
Sys_Error("D_FillRect: unsupported r_pixbytes %i", sw32_ctx->pixbytes);
}
}

View file

@ -1,112 +0,0 @@
/*
d_init.c
rasterization driver initialization
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/cvar.h"
#include "QF/render.h"
#include "compat.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
#define NUM_MIPS 4
surfcache_t *sw32_d_initial_rover;
qboolean sw32_d_roverwrapped;
int sw32_d_minmip;
float sw32_d_scalemip[NUM_MIPS - 1];
static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 };
float sw32_d_zitable[65536];
void
sw32_D_Init (void)
{
sw32_r_drawpolys = false;
sw32_r_worldpolysbacktofront = false;
// LordHavoc: compute 1/zi table for use in rendering code everywhere
if (!sw32_d_zitable[1]) {
int i;
sw32_d_zitable[0] = 0;
for (i = 1;i < 65536;i++)
sw32_d_zitable[i] = (65536.0 * 65536.0 / (double) i);
}
vr_data.vid->vid_internal->surf_cache_size = sw32_D_SurfaceCacheForRes;
vr_data.vid->vid_internal->flush_caches = sw32_D_FlushCaches;
vr_data.vid->vid_internal->init_caches = sw32_D_InitCaches;
VID_InitBuffers ();
VID_MakeColormaps();
}
void
sw32_D_TurnZOn (void)
{
// not needed for software version
}
void
sw32_D_SetupFrame (void)
{
int i;
if (sw32_r_dowarp)
sw32_d_viewbuffer = sw32_r_warpbuffer;
else
sw32_d_viewbuffer = vid.buffer;
if (sw32_r_dowarp)
sw32_screenwidth = WARP_WIDTH;
else
sw32_screenwidth = vid.rowbytes / sw32_ctx->pixbytes;
sw32_d_roverwrapped = false;
sw32_d_initial_rover = sw32_sc_rover;
sw32_d_minmip = bound (0, d_mipcap->value, 3);
for (i = 0; i < (NUM_MIPS - 1); i++)
sw32_d_scalemip[i] = basemip[i] * d_mipscale->value;
}
void
sw32_D_UpdateRects (vrect_t *prect)
{
// the software driver draws these directly to the vid buffer
}

View file

@ -1,100 +0,0 @@
/*
d_modech.c
called when mode has just changed
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/render.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_sw.h"
int sw32_d_vrectx, sw32_d_vrecty, sw32_d_vrectright_particle, sw32_d_vrectbottom_particle;
int sw32_d_y_aspect_shift, sw32_d_pix_min, sw32_d_pix_max, sw32_d_pix_shift;
int sw32_d_scantable[MAXHEIGHT];
short *sw32_zspantable[MAXHEIGHT];
static void
D_Patch (void)
{
}
void
sw32_D_ViewChanged (void)
{
int rowpixels;
if (sw32_r_dowarp)
rowpixels = WARP_WIDTH;
else
rowpixels = vid.rowbytes / sw32_ctx->pixbytes;
sw32_scale_for_mip = sw32_xscale;
if (sw32_yscale > sw32_xscale)
sw32_scale_for_mip = sw32_yscale;
sw32_d_zrowbytes = vid.width * 2;
sw32_d_zwidth = vid.width;
sw32_d_pix_min = r_refdef.vrect.width / 320;
if (sw32_d_pix_min < 1)
sw32_d_pix_min = 1;
sw32_d_pix_max = (int) ((float) r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
sw32_d_pix_shift = 8 - (int) ((float) r_refdef.vrect.width / 320.0 + 0.5);
if (sw32_d_pix_max < 1)
sw32_d_pix_max = 1;
if (sw32_pixelAspect > 1.4)
sw32_d_y_aspect_shift = 1;
else
sw32_d_y_aspect_shift = 0;
sw32_d_vrectx = r_refdef.vrect.x;
sw32_d_vrecty = r_refdef.vrect.y;
sw32_d_vrectright_particle = r_refdef.vrectright - sw32_d_pix_max;
sw32_d_vrectbottom_particle =
r_refdef.vrectbottom - (sw32_d_pix_max << sw32_d_y_aspect_shift);
{
unsigned i;
for (i = 0; i < vid.height; i++) {
sw32_d_scantable[i] = i * rowpixels;
sw32_zspantable[i] = sw32_d_pzbuffer + i * sw32_d_zwidth;
}
}
D_Patch ();
}

View file

@ -1,374 +0,0 @@
/*
d_part.c
software driver module for drawing particles
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/sys.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
void
sw32_D_DrawParticle (particle_t *pparticle)
{
vec3_t local, transformed;
float zi;
short *pz;
int i, izi, pix, count, u, v;
// transform point
VectorSubtract (pparticle->pos, r_origin, local);
transformed[0] = DotProduct (local, r_pright);
transformed[1] = DotProduct (local, r_pup);
transformed[2] = DotProduct (local, r_ppn);
if (transformed[2] < PARTICLE_Z_CLIP)
return;
// project the point
// FIXME: preadjust sw32_xcenter and sw32_ycenter
zi = 1.0 / transformed[2];
u = (int) (sw32_xcenter + zi * transformed[0] + 0.5);
v = (int) (sw32_ycenter - zi * transformed[1] + 0.5);
if ((v > sw32_d_vrectbottom_particle)
|| (u > sw32_d_vrectright_particle)
|| (v < sw32_d_vrecty) || (u < sw32_d_vrectx)) {
return;
}
pz = sw32_d_pzbuffer + (sw32_d_zwidth * v) + u;
izi = (int) (zi * 0x8000);
pix = izi >> sw32_d_pix_shift;
if (pix < sw32_d_pix_min)
pix = sw32_d_pix_min;
else if (pix > sw32_d_pix_max)
pix = sw32_d_pix_max;
switch(sw32_ctx->pixbytes)
{
case 1:
{
byte *pdest = (byte *) sw32_d_viewbuffer + sw32_d_scantable[v] + u,
pixcolor = pparticle->icolor;
switch (pix) {
case 1:
count = 1 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
}
break;
case 2:
count = 2 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
}
break;
case 3:
count = 3 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
}
break;
case 4:
count = 4 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
if (pz[3] <= izi) {
pz[3] = izi;
pdest[3] = pixcolor;
}
}
break;
default:
count = pix << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
for (i = 0; i < pix; i++) {
if (pz[i] <= izi) {
pz[i] = izi;
pdest[i] = pixcolor;
}
}
}
break;
}
}
break;
case 2:
{
unsigned short *pdest = (unsigned short *) sw32_d_viewbuffer +
sw32_d_scantable[v] + u,
pixcolor = sw32_8to16table[(int) pparticle->icolor];
switch (pix) {
case 1:
count = 1 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
}
break;
case 2:
count = 2 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
}
break;
case 3:
count = 3 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
}
break;
case 4:
count = 4 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
if (pz[3] <= izi) {
pz[3] = izi;
pdest[3] = pixcolor;
}
}
break;
default:
count = pix << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
for (i = 0; i < pix; i++) {
if (pz[i] <= izi) {
pz[i] = izi;
pdest[i] = pixcolor;
}
}
}
break;
}
}
break;
case 4:
{
int *pdest = (int *) sw32_d_viewbuffer + sw32_d_scantable[v] + u,
pixcolor = d_8to24table[(int) pparticle->icolor];
switch (pix) {
case 1:
count = 1 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
}
break;
case 2:
count = 2 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
}
break;
case 3:
count = 3 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
}
break;
case 4:
count = 4 << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
if (pz[0] <= izi) {
pz[0] = izi;
pdest[0] = pixcolor;
}
if (pz[1] <= izi) {
pz[1] = izi;
pdest[1] = pixcolor;
}
if (pz[2] <= izi) {
pz[2] = izi;
pdest[2] = pixcolor;
}
if (pz[3] <= izi) {
pz[3] = izi;
pdest[3] = pixcolor;
}
}
break;
default:
count = pix << sw32_d_y_aspect_shift;
for (; count; count--, pz += sw32_d_zwidth,
pdest += sw32_screenwidth) {
for (i = 0; i < pix; i++) {
if (pz[i] <= izi) {
pz[i] = izi;
pdest[i] = pixcolor;
}
}
}
break;
}
}
break;
default:
Sys_Error("D_DrawParticles: unsupported r_pixbytes %i",
sw32_ctx->pixbytes);
}
}

View file

@ -1,797 +0,0 @@
/*
d_polyse.c
routines for drawing sets of polygons sharing the same texture
(used for Alias models)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/sys.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_sw.h"
static int ubasestep, errorterm, erroradjustup, erroradjustdown;
// TODO: put in span spilling to shrink list size
// !!! if this is changed, it must be changed in d_polysa.s too !!!
#define DPS_MAXSPANS MAXHEIGHT+1 // +1 for spanpackage marking end
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct {
int pdest;
short *pz;
int count;
byte *ptex;
int sfrac, tfrac, light, zi;
} spanpackage_t;
typedef struct {
int isflattop;
int numleftedges;
int *pleftedgevert0;
int *pleftedgevert1;
int *pleftedgevert2;
int numrightedges;
int *prightedgevert0;
int *prightedgevert1;
int *prightedgevert2;
} edgetable;
static int r_p0[6], r_p1[6], r_p2[6];
static int d_xdenom;
static edgetable *pedgetable;
static edgetable edgetables[12] = {
{0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2},
{0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL},
{1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
{0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0},
{0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL},
{0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
{0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1},
{0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL},
{0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
{1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
{1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
{0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
};
static int r_sstepx, r_tstepx, r_lstepx, r_lstepy, r_sstepy, r_tstepy;
static int r_zistepx, r_zistepy;
static int d_aspancount, d_countextrastep;
static spanpackage_t *a_spans;
static spanpackage_t *d_pedgespanpackage;
static int ystart;
static int d_pdest;
static byte *d_ptex;
static short *d_pz;
static int d_sfrac, d_tfrac, d_light, d_zi;
static int d_ptexextrastep, d_sfracextrastep;
static int d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
static int d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
static int d_sfracbasestep, d_tfracbasestep;
static int d_ziextrastep, d_zibasestep;
static int d_pzextrastep, d_pzbasestep;
typedef struct {
int quotient;
int remainder;
} adivtab_t;
static adivtab_t adivtab[32 * 32] = {
#include "adivtab.h"
};
void
sw32_D_PolysetSetEdgeTable (void)
{
int edgetableindex;
// assume the vertices are already in top to bottom order
edgetableindex = 0;
// determine which edges are right & left, and the order in which
// to rasterize them
if (r_p0[1] >= r_p1[1]) {
if (r_p0[1] == r_p1[1]) {
if (r_p0[1] < r_p2[1])
pedgetable = &edgetables[2];
else
pedgetable = &edgetables[5];
return;
} else {
edgetableindex = 1;
}
}
if (r_p0[1] == r_p2[1]) {
if (edgetableindex)
pedgetable = &edgetables[8];
else
pedgetable = &edgetables[9];
return;
} else if (r_p1[1] == r_p2[1]) {
if (edgetableindex)
pedgetable = &edgetables[10];
else
pedgetable = &edgetables[11];
return;
}
if (r_p0[1] > r_p2[1])
edgetableindex += 2;
if (r_p1[1] > r_p2[1])
edgetableindex += 4;
pedgetable = &edgetables[edgetableindex];
}
static void
D_DrawNonSubdiv (void)
{
mtriangle_t *ptri;
finalvert_t *pfv, *index0, *index1, *index2;
int i;
int lnumtriangles;
pfv = sw32_r_affinetridesc.pfinalverts;
ptri = sw32_r_affinetridesc.ptriangles;
lnumtriangles = sw32_r_affinetridesc.numtriangles;
for (i = 0; i < lnumtriangles; i++, ptri++) {
index0 = pfv + ptri->vertindex[0];
index1 = pfv + ptri->vertindex[1];
index2 = pfv + ptri->vertindex[2];
d_xdenom =
(index0->v[1] - index1->v[1]) * (index0->v[0] - index2->v[0]) -
(index0->v[0] - index1->v[0]) * (index0->v[1] - index2->v[1]);
if (d_xdenom >= 0)
continue;
r_p0[0] = index0->v[0]; // u
r_p0[1] = index0->v[1]; // v
r_p0[2] = index0->v[2]; // s
r_p0[3] = index0->v[3]; // t
r_p0[4] = index0->v[4]; // light
r_p0[5] = index0->v[5]; // iz
r_p1[0] = index1->v[0];
r_p1[1] = index1->v[1];
r_p1[2] = index1->v[2];
r_p1[3] = index1->v[3];
r_p1[4] = index1->v[4];
r_p1[5] = index1->v[5];
r_p2[0] = index2->v[0];
r_p2[1] = index2->v[1];
r_p2[2] = index2->v[2];
r_p2[3] = index2->v[3];
r_p2[4] = index2->v[4];
r_p2[5] = index2->v[5];
if (!ptri->facesfront) {
if (index0->flags & ALIAS_ONSEAM)
r_p0[2] += sw32_r_affinetridesc.seamfixupX16;
if (index1->flags & ALIAS_ONSEAM)
r_p1[2] += sw32_r_affinetridesc.seamfixupX16;
if (index2->flags & ALIAS_ONSEAM)
r_p2[2] += sw32_r_affinetridesc.seamfixupX16;
}
sw32_D_PolysetSetEdgeTable ();
sw32_D_RasterizeAliasPolySmooth ();
}
}
void
sw32_D_PolysetDraw (void)
{
spanpackage_t spans[DPS_MAXSPANS + 1 +
((CACHE_SIZE - 1) / sizeof (spanpackage_t)) + 1];
// one extra because of cache line pretouching
a_spans = (spanpackage_t *)
(((intptr_t) &spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
D_DrawNonSubdiv ();
}
void
sw32_D_PolysetScanLeftEdge (int height)
{
do {
d_pedgespanpackage->pdest = d_pdest;
d_pedgespanpackage->pz = d_pz;
d_pedgespanpackage->count = d_aspancount;
d_pedgespanpackage->ptex = d_ptex;
d_pedgespanpackage->sfrac = d_sfrac;
d_pedgespanpackage->tfrac = d_tfrac;
// FIXME: need to clamp l, s, t, at both ends?
d_pedgespanpackage->light = d_light;
d_pedgespanpackage->zi = d_zi;
d_pedgespanpackage++;
errorterm += erroradjustup;
if (errorterm >= 0) {
d_pdest += d_pdestextrastep;
d_pz += d_pzextrastep;
d_aspancount += d_countextrastep;
d_ptex += d_ptexextrastep;
d_sfrac += d_sfracextrastep;
d_ptex += d_sfrac >> 16;
d_sfrac &= 0xFFFF;
d_tfrac += d_tfracextrastep;
if (d_tfrac & 0x10000) {
d_ptex += sw32_r_affinetridesc.skinwidth;
d_tfrac &= 0xFFFF;
}
d_light += d_lightextrastep;
d_zi += d_ziextrastep;
errorterm -= erroradjustdown;
} else {
d_pdest += d_pdestbasestep;
d_pz += d_pzbasestep;
d_aspancount += ubasestep;
d_ptex += d_ptexbasestep;
d_sfrac += d_sfracbasestep;
d_ptex += d_sfrac >> 16;
d_sfrac &= 0xFFFF;
d_tfrac += d_tfracbasestep;
if (d_tfrac & 0x10000) {
d_ptex += sw32_r_affinetridesc.skinwidth;
d_tfrac &= 0xFFFF;
}
d_light += d_lightbasestep;
d_zi += d_zibasestep;
}
} while (--height);
}
static void
D_PolysetSetUpForLineScan (fixed8_t startvertu, fixed8_t startvertv,
fixed8_t endvertu, fixed8_t endvertv)
{
double dm, dn;
int tm, tn;
adivtab_t *ptemp;
// TODO: implement x86 version
errorterm = -1;
tm = endvertu - startvertu;
tn = endvertv - startvertv;
if (((tm <= 16) && (tm >= -15)) && ((tn <= 16) && (tn >= -15))) {
ptemp = &adivtab[((tm + 15) << 5) + (tn + 15)];
ubasestep = ptemp->quotient;
erroradjustup = ptemp->remainder;
erroradjustdown = tn;
} else {
dm = (double) tm;
dn = (double) tn;
FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
erroradjustdown = dn;
}
}
void
sw32_D_PolysetCalcGradients (int skinwidth)
{
float xstepdenominv, ystepdenominv, t0, t1;
float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
p00_minus_p20 = r_p0[0] - r_p2[0];
p01_minus_p21 = r_p0[1] - r_p2[1];
p10_minus_p20 = r_p1[0] - r_p2[0];
p11_minus_p21 = r_p1[1] - r_p2[1];
xstepdenominv = 1.0 / (float) d_xdenom;
ystepdenominv = -xstepdenominv;
// ceil () for light so positive steps are exaggerated, negative steps
// diminished, pushing us away from underflow toward overflow. Underflow
// is very visible, overflow is very unlikely, because of ambient lighting
t0 = r_p0[4] - r_p2[4];
t1 = r_p1[4] - r_p2[4];
r_lstepx = (int)
ceil ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
r_lstepy = (int)
ceil ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
t0 = r_p0[2] - r_p2[2];
t1 = r_p1[2] - r_p2[2];
r_sstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_sstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
ystepdenominv);
t0 = r_p0[3] - r_p2[3];
t1 = r_p1[3] - r_p2[3];
r_tstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_tstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
ystepdenominv);
t0 = r_p0[5] - r_p2[5];
t1 = r_p1[5] - r_p2[5];
r_zistepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
xstepdenominv);
r_zistepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
ystepdenominv);
// a_sstepxfrac = r_sstepx & 0xFFFF;
// a_tstepxfrac = r_tstepx & 0xFFFF;
// a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
}
static void
D_PolysetDrawSpans (spanpackage_t * pspanpackage)
{
int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan;
// LordHavoc: compute skin row table
for (i = 0, j = -sw32_r_affinetridesc.skinheight * sw32_r_affinetridesc.skinwidth;
i < sw32_r_affinetridesc.skinheight*2;i++, j += sw32_r_affinetridesc.skinwidth)
texscantable[i] = j;
texscan = texscantable + sw32_r_affinetridesc.skinheight;
switch(sw32_ctx->pixbytes) {
case 1:
{
int lcount, count = 0;
byte *lpdest;
byte *lptex;
int lsfrac, ltfrac;
int llight;
int lzi;
short *lpz;
do
{
lcount = d_aspancount - pspanpackage->count;
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_aspancount += d_countextrastep;
errorterm -= erroradjustdown;
}
else
d_aspancount += ubasestep;
if (lcount)
{
lpdest = (byte *) sw32_d_viewbuffer + pspanpackage->pdest;
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight = pspanpackage->light;
lzi = pspanpackage->zi;
// LordHavoc: optimized zbuffer check (switchs between
// loops when state changes, and quickly skips groups
// of hidden pixels)
do
{
if ((lzi >> 16) < *lpz) // hidden
{
count = 0;
goto skiploop8;
}
drawloop8:
*lpz++ = lzi >> 16;
*lpdest++ = ((byte *)sw32_acolormap)
[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] +
(lsfrac >> 16)]];
lzi += r_zistepx;
lsfrac += r_sstepx;
ltfrac += r_tstepx;
llight += r_lstepx;
}
while (--lcount);
goto done8;
do
{
if ((lzi >> 16) >= *lpz) // draw
{
lsfrac += r_sstepx * count;
ltfrac += r_tstepx * count;
llight += r_lstepx * count;
lpdest += count;
goto drawloop8;
}
skiploop8:
count++;
lzi += r_zistepx;
lpz++;
}
while (--lcount);
done8: ;
}
pspanpackage++;
}
while (pspanpackage->count != -999999);
}
break;
case 2:
{
int lcount, count = 0;
short *lpdest;
byte *lptex;
int lsfrac, ltfrac;
int llight;
int lzi;
short *lpz;
do
{
lcount = d_aspancount - pspanpackage->count;
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_aspancount += d_countextrastep;
errorterm -= erroradjustdown;
}
else
d_aspancount += ubasestep;
if (lcount)
{
lpdest = (short *) sw32_d_viewbuffer + pspanpackage->pdest;
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight = pspanpackage->light;
lzi = pspanpackage->zi;
do
{
if ((lzi >> 16) < *lpz) // hidden
{
count = 0;
goto skiploop16;
}
drawloop16:
*lpz++ = lzi >> 16;
*lpdest++ = ((short *)sw32_acolormap)[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + (lsfrac >> 16)]];
lzi += r_zistepx;
lsfrac += r_sstepx;
ltfrac += r_tstepx;
llight += r_lstepx;
}
while (--lcount);
goto done16;
do
{
if ((lzi >> 16) >= *lpz) // draw
{
lsfrac += r_sstepx * count;
ltfrac += r_tstepx * count;
llight += r_lstepx * count;
lpdest += count;
goto drawloop16;
}
skiploop16:
count++;
lzi += r_zistepx;
lpz++;
}
while (--lcount);
done16: ;
}
pspanpackage++;
}
while (pspanpackage->count != -999999);
}
break;
case 4:
{
int lcount, count = 0;
int *lpdest;
byte *lptex;
int lsfrac, ltfrac;
int llight;
int lzi;
short *lpz;
do
{
lcount = d_aspancount - pspanpackage->count;
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_aspancount += d_countextrastep;
errorterm -= erroradjustdown;
}
else
d_aspancount += ubasestep;
if (lcount)
{
lpdest = (int *) sw32_d_viewbuffer + pspanpackage->pdest;
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight = pspanpackage->light;
lzi = pspanpackage->zi;
do
{
if ((lzi >> 16) < *lpz) // hidden
{
count = 0;
goto skiploop32;
}
drawloop32:
*lpz++ = lzi >> 16;
*lpdest++ =
vid.colormap32[(llight & 0xFF00) |
lptex[texscan[ltfrac >> 16] +
(lsfrac >> 16)]];
lzi += r_zistepx;
lsfrac += r_sstepx;
ltfrac += r_tstepx;
llight += r_lstepx;
}
while (--lcount);
goto done32;
do
{
if ((lzi >> 16) >= *lpz) // draw
{
lsfrac += r_sstepx * count;
ltfrac += r_tstepx * count;
llight += r_lstepx * count;
lpdest += count;
goto drawloop32;
}
skiploop32:
count++;
lzi += r_zistepx;
lpz++;
}
while (--lcount);
done32: ;
}
pspanpackage++;
}
while (pspanpackage->count != -999999);
}
break;
default:
Sys_Error("D_PolysetDrawSpans: unsupported r_pixbytes %i",
sw32_ctx->pixbytes);
}
}
void
sw32_D_RasterizeAliasPolySmooth (void)
{
int initialleftheight, initialrightheight;
int *plefttop, *prighttop, *pleftbottom, *prightbottom;
int working_lstepx, originalcount;
plefttop = pedgetable->pleftedgevert0;
prighttop = pedgetable->prightedgevert0;
pleftbottom = pedgetable->pleftedgevert1;
prightbottom = pedgetable->prightedgevert1;
initialleftheight = pleftbottom[1] - plefttop[1];
initialrightheight = prightbottom[1] - prighttop[1];
// set the s, t, and light gradients, which are consistent across the
// triangle, because being a triangle, things are affine
sw32_D_PolysetCalcGradients (sw32_r_affinetridesc.skinwidth);
// rasterize the polygon
// scan out the top (and possibly only) part of the left edge
D_PolysetSetUpForLineScan (plefttop[0], plefttop[1],
pleftbottom[0], pleftbottom[1]);
d_pedgespanpackage = a_spans;
ystart = plefttop[1];
d_aspancount = plefttop[0] - prighttop[0];
d_ptex = (byte *) sw32_r_affinetridesc.pskin + (plefttop[2] >> 16) +
(plefttop[3] >> 16) * sw32_r_affinetridesc.skinwidth;
d_sfrac = plefttop[2] & 0xFFFF;
d_tfrac = plefttop[3] & 0xFFFF;
d_pzbasestep = sw32_d_zwidth + ubasestep;
d_pzextrastep = d_pzbasestep + 1;
d_light = plefttop[4];
d_zi = plefttop[5];
d_pdestbasestep = sw32_screenwidth + ubasestep;
d_pdestextrastep = d_pdestbasestep + 1;
// LordHavoc: d_pdest has been changed to pixel offset
d_pdest = ystart * sw32_screenwidth + plefttop[0];
d_pz = sw32_d_pzbuffer + ystart * sw32_d_zwidth + plefttop[0];
// TODO: can reuse partial expressions here
// for negative steps in x along left edge, bias toward overflow rather
// than underflow (sort of turning the floor () we did in the gradient
// calcs into ceil (), but plus a little bit)
if (ubasestep < 0)
working_lstepx = r_lstepx - 1;
else
working_lstepx = r_lstepx;
d_countextrastep = ubasestep + 1;
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
((r_tstepy + r_tstepx * ubasestep) >> 16) * sw32_r_affinetridesc.skinwidth;
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
sw32_r_affinetridesc.skinwidth;
d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF;
d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF;
d_lightextrastep = d_lightbasestep + working_lstepx;
d_ziextrastep = d_zibasestep + r_zistepx;
sw32_D_PolysetScanLeftEdge (initialleftheight);
// scan out the bottom part of the left edge, if it exists
if (pedgetable->numleftedges == 2) {
int height;
plefttop = pleftbottom;
pleftbottom = pedgetable->pleftedgevert2;
D_PolysetSetUpForLineScan (plefttop[0], plefttop[1],
pleftbottom[0], pleftbottom[1]);
height = pleftbottom[1] - plefttop[1];
// TODO: make this a function; modularize this function in general
ystart = plefttop[1];
d_aspancount = plefttop[0] - prighttop[0];
d_ptex = (byte *) sw32_r_affinetridesc.pskin + (plefttop[2] >> 16) +
(plefttop[3] >> 16) * sw32_r_affinetridesc.skinwidth;
d_sfrac = 0;
d_tfrac = 0;
d_light = plefttop[4];
d_zi = plefttop[5];
d_pdestbasestep = sw32_screenwidth + ubasestep;
d_pdestextrastep = d_pdestbasestep + 1;
// LordHavoc: d_pdest and relatives have been changed to pixel
// offsets into framebuffer
d_pdest = ystart * sw32_screenwidth + plefttop[0];
d_pzbasestep = sw32_d_zwidth + ubasestep;
d_pzextrastep = d_pzbasestep + 1;
d_pz = sw32_d_pzbuffer + ystart * sw32_d_zwidth + plefttop[0];
if (ubasestep < 0)
working_lstepx = r_lstepx - 1;
else
working_lstepx = r_lstepx;
d_countextrastep = ubasestep + 1;
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
((r_tstepy + r_tstepx * ubasestep) >> 16) *
sw32_r_affinetridesc.skinwidth;
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
sw32_r_affinetridesc.skinwidth;
d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF;
d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF;
d_lightextrastep = d_lightbasestep + working_lstepx;
d_ziextrastep = d_zibasestep + r_zistepx;
sw32_D_PolysetScanLeftEdge (height);
}
// scan out the top (and possibly only) part of the right edge, updating
// the count field
d_pedgespanpackage = a_spans;
D_PolysetSetUpForLineScan (prighttop[0], prighttop[1],
prightbottom[0], prightbottom[1]);
d_aspancount = 0;
d_countextrastep = ubasestep + 1;
originalcount = a_spans[initialrightheight].count;
a_spans[initialrightheight].count = -999999; // mark end of the
// spanpackages
D_PolysetDrawSpans (a_spans);
// scan out the bottom part of the right edge, if it exists
if (pedgetable->numrightedges == 2) {
int height;
spanpackage_t *pstart;
pstart = a_spans + initialrightheight;
pstart->count = originalcount;
d_aspancount = prightbottom[0] - prighttop[0];
prighttop = prightbottom;
prightbottom = pedgetable->prightedgevert2;
height = prightbottom[1] - prighttop[1];
D_PolysetSetUpForLineScan (prighttop[0], prighttop[1],
prightbottom[0], prightbottom[1]);
d_countextrastep = ubasestep + 1;
a_spans[initialrightheight + height].count = -999999;
// mark end of the spanpackages
D_PolysetDrawSpans (pstart);
}
}

View file

@ -1,883 +0,0 @@
/*
d_scan.c
Portable C scan-level rasterization code, all pixel depths.
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/qendian.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/ui/view.h"
#include "compat.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static byte *r_turb_pbase;
static void *r_turb_pdest;
static fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
static int *r_turb_turb;
static int r_turb_spancount;
/*
D_WarpScreen
this performs a slight compression of the screen at the same time as
the sine warp, to keep the edges from wrapping
*/
void
sw32_D_WarpScreen (void)
{
switch(sw32_ctx->pixbytes) {
case 1:
{
int w, h;
int u, v;
int scr_x = vr_data.scr_view->xpos;
int scr_y = vr_data.scr_view->ylen;
int scr_w = vr_data.scr_view->xpos;
int scr_h = vr_data.scr_view->ylen;
byte *dest;
int *turb;
int *col;
byte **row;
byte *rowptr[MAXHEIGHT];
int column[MAXWIDTH];
float wratio, hratio;
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
wratio = w / (float) scr_w;
hratio = h / (float) scr_h;
for (v = 0; v < scr_h + AMP2 * 2; v++) {
rowptr[v] = (byte *) sw32_d_viewbuffer + (r_refdef.vrect.y *
sw32_screenwidth) +
(sw32_screenwidth * (int) ((float) v * hratio * h /
(h + AMP2 * 2)));
}
for (u = 0; u < scr_w + AMP2 * 2; u++) {
column[u] = r_refdef.vrect.x +
(int) ((float) u * wratio * w / (w + AMP2 * 2));
}
turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1));
dest = (byte *)vid.buffer + scr_y * vid.rowbytes + scr_x;
for (v = 0; v < scr_h; v++, dest += vid.rowbytes) {
col = &column[turb[v]];
row = &rowptr[v];
for (u = 0; u < scr_w; u += 4) {
dest[u + 0] = row[turb[u + 0]][col[u + 0]];
dest[u + 1] = row[turb[u + 1]][col[u + 1]];
dest[u + 2] = row[turb[u + 2]][col[u + 2]];
dest[u + 3] = row[turb[u + 3]][col[u + 3]];
}
}
}
break;
case 2:
{
int w, h;
int u, v;
int scr_x = vr_data.scr_view->xpos;
int scr_y = vr_data.scr_view->ylen;
int scr_w = vr_data.scr_view->xpos;
int scr_h = vr_data.scr_view->ylen;
short *dest;
int *turb;
int *col;
short **row;
short *rowptr[MAXHEIGHT];
int column[MAXWIDTH];
float wratio, hratio;
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
wratio = w / (float) scr_w;
hratio = h / (float) scr_h;
for (v = 0; v < scr_h + AMP2 * 2; v++) {
rowptr[v] = (short *) sw32_d_viewbuffer +
(r_refdef.vrect.y * sw32_screenwidth) +
(sw32_screenwidth * (int) ((float) v * hratio * h /
(h + AMP2 * 2)));
}
for (u = 0; u < scr_w + AMP2 * 2; u++) {
column[u] = r_refdef.vrect.x +
(int) ((float) u * wratio * w / (w + AMP2 * 2));
}
turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1));
dest = (short *) vid.buffer + scr_y * (vid.rowbytes >> 1) + scr_x;
for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 1)) {
col = &column[turb[v]];
row = &rowptr[v];
for (u = 0; u < scr_w; u += 4) {
dest[u + 0] = row[turb[u + 0]][col[u + 0]];
dest[u + 1] = row[turb[u + 1]][col[u + 1]];
dest[u + 2] = row[turb[u + 2]][col[u + 2]];
dest[u + 3] = row[turb[u + 3]][col[u + 3]];
}
}
}
break;
case 4:
{
int w, h;
int u, v;
int scr_x = vr_data.scr_view->xpos;
int scr_y = vr_data.scr_view->ylen;
int scr_w = vr_data.scr_view->xpos;
int scr_h = vr_data.scr_view->ylen;
int *dest;
int *turb;
int *col;
int **row;
int *rowptr[MAXHEIGHT];
int column[MAXWIDTH];
float wratio, hratio;
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
wratio = w / (float) scr_w;
hratio = h / (float) scr_h;
for (v = 0; v < scr_h + AMP2 * 2; v++) {
rowptr[v] = (int *) sw32_d_viewbuffer +
(r_refdef.vrect.y * sw32_screenwidth) +
(sw32_screenwidth * (int) ((float) v * hratio * h /
(h + AMP2 * 2)));
}
for (u = 0; u < scr_w + AMP2 * 2; u++) {
column[u] = r_refdef.vrect.x +
(int) ((float) u * wratio * w / (w + AMP2 * 2));
}
turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1));
dest = (int *) vid.buffer + scr_y * (vid.rowbytes >> 2) + scr_x;
for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 2)) {
col = &column[turb[v]];
row = &rowptr[v];
for (u = 0; u < scr_w; u += 4) {
dest[u + 0] = row[turb[u + 0]][col[u + 0]];
dest[u + 1] = row[turb[u + 1]][col[u + 1]];
dest[u + 2] = row[turb[u + 2]][col[u + 2]];
dest[u + 3] = row[turb[u + 3]][col[u + 3]];
}
}
}
break;
default:
Sys_Error("D_WarpScreen: unsupported r_pixbytes %i", sw32_ctx->pixbytes);
}
}
static void
D_DrawTurbulentSpan (void)
{
int sturb, tturb;
switch (sw32_ctx->pixbytes) {
case 1:
{
byte *pdest = (byte *) r_turb_pdest;
do {
sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) &
(CYCLE - 1)]) >> 16) & 63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) &
(CYCLE - 1)]) >> 16) & 63;
*pdest++ = r_turb_pbase[(tturb << 6) + sturb];
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
r_turb_pdest = (byte *)pdest;
}
break;
case 2:
{
short *pdest = (short *) r_turb_pdest;
do {
sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) &
(CYCLE - 1)]) >> 16) & 63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) &
(CYCLE - 1)]) >> 16) & 63;
*pdest++ = sw32_8to16table[r_turb_pbase[(tturb << 6) + sturb]];
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
r_turb_pdest = (byte *)pdest;
}
break;
case 4:
{
int *pdest = (int *) r_turb_pdest;
do {
sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) &
(CYCLE - 1)]) >> 16) & 63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) &
(CYCLE - 1)]) >> 16) & 63;
*pdest++ = d_8to24table[r_turb_pbase[(tturb << 6) + sturb]];
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
r_turb_pdest = (byte *)pdest;
}
break;
default:
Sys_Error("D_DrawTurbulentSpan: unsupported r_pixbytes %i",
sw32_ctx->pixbytes);
}
}
void
sw32_Turbulent (espan_t *pspan)
{
int count;
fixed16_t snext, tnext;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz16stepu, tdivz16stepu, zi16stepu;
r_turb_turb = sw32_sintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1));
r_turb_sstep = 0; // keep compiler happy
r_turb_tstep = 0; // ditto
r_turb_pbase = (byte *) sw32_cacheblock;
sdivz16stepu = sw32_d_sdivzstepu * 16;
tdivz16stepu = sw32_d_tdivzstepu * 16;
zi16stepu = d_zistepu * 16 * 65536;
do {
r_turb_pdest = (byte *) sw32_d_viewbuffer + ((sw32_screenwidth * pspan->v) +
pspan->u) * sw32_ctx->pixbytes;
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = sw32_d_zitable[(unsigned short) zi];
r_turb_s = (int) (sdivz * z) + sw32_sadjust;
if (r_turb_s > sw32_bbextents)
r_turb_s = sw32_bbextents;
else if (r_turb_s < 0)
r_turb_s = 0;
r_turb_t = (int) (tdivz * z) + sw32_tadjust;
if (r_turb_t > sw32_bbextentt)
r_turb_t = sw32_bbextentt;
else if (r_turb_t < 0)
r_turb_t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 16)
r_turb_spancount = 16;
else
r_turb_spancount = count;
count -= r_turb_spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz16stepu;
tdivz += tdivz16stepu;
zi += zi16stepu;
z = sw32_d_zitable[(unsigned short) zi];
snext = (int) (sdivz * z) + sw32_sadjust;
if (snext > sw32_bbextents)
snext = sw32_bbextents;
else if (snext < 16)
snext = 16; // prevent round-off error on <0
// steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int) (tdivz * z) + sw32_tadjust;
if (tnext > sw32_bbextentt)
tnext = sw32_bbextentt;
else if (tnext < 16)
tnext = 16; // guard against round-off error on
// <0 steps
r_turb_sstep = (snext - r_turb_s) >> 4;
r_turb_tstep = (tnext - r_turb_t) >> 4;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel in
// span (so can't step off polygon), clamp, calculate s and t
// steps across span by division, biasing steps low so we
// don't run off the texture
spancountminus1 = (float) (r_turb_spancount - 1);
sdivz += sw32_d_sdivzstepu * spancountminus1;
tdivz += sw32_d_tdivzstepu * spancountminus1;
zi += d_zistepu * 65536.0f * spancountminus1;
z = sw32_d_zitable[(unsigned short) zi];
snext = (int) (sdivz * z) + sw32_sadjust;
if (snext > sw32_bbextents)
snext = sw32_bbextents;
else if (snext < 16)
snext = 16; // prevent round-off error on <0 steps
// from causing overstepping & running
// off the edge of the texture
tnext = (int) (tdivz * z) + sw32_tadjust;
if (tnext > sw32_bbextentt)
tnext = sw32_bbextentt;
else if (tnext < 16)
tnext = 16; // guard against round-off error on
// <0 steps
if (r_turb_spancount > 1) {
r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
}
}
r_turb_s = r_turb_s & ((CYCLE << 16) - 1);
r_turb_t = r_turb_t & ((CYCLE << 16) - 1);
D_DrawTurbulentSpan ();
r_turb_s = snext;
r_turb_t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
void
sw32_D_DrawSpans (espan_t *pspan)
{
switch(sw32_ctx->pixbytes) {
case 1:
{
byte *pbase = (byte *) sw32_cacheblock, *pdest;
int count;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv;
float sdivz8stepu, tdivz8stepu, zi8stepu;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
sdivz8stepu = sw32_d_sdivzstepu * 8;
tdivz8stepu = sw32_d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
do {
pdest = (byte *) sw32_d_viewbuffer + (sw32_screenwidth * pspan->v) +
pspan->u;
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = sw32_d_zitable[(unsigned short) zi];
s = (int) (sdivz * z) + sw32_sadjust;
s = bound(0, s, sw32_bbextents);
t = (int) (tdivz * z) + sw32_tadjust;
t = bound(0, t, sw32_bbextentt);
while(count >= 8) {
count -= 8;
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = sw32_d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sw32_sadjust;
snext = bound(8, snext, sw32_bbextents);
tnext = (int) (tdivz * z) + sw32_tadjust;
tnext = bound(8, tnext, sw32_bbextentt);
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[4] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[5] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[6] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[7] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s = snext;
t = tnext;
pdest += 8;
}
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span
// (so can't step off polygon), clamp, calculate s and t steps
// across span by division, biasing steps low so we don't run
// off the texture
//countminus1 = (float) (count - 1);
sdivz += sw32_d_sdivzstepu * count; //minus1;
tdivz += sw32_d_tdivzstepu * count; //minus1;
zi += d_zistepu * 65536.0f * count; //minus1;
z = sw32_d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sw32_sadjust;
snext = bound(count, snext, sw32_bbextents);
tnext = (int) (tdivz * z) + sw32_tadjust;
tnext = bound(count, tnext, sw32_bbextentt);
if (count > 1) {
sstep = (snext - s) / count; //(count - 1);
tstep = (tnext - t) / count; //(count - 1);
if (count & 4)
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest += 4;
}
if (count & 2)
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest += 2;
}
if (count & 1)
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
}
else
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
}
}
} while ((pspan = pspan->pnext) != NULL);
}
break;
case 2:
{
short *pbase = (short *) sw32_cacheblock, *pdest;
int count;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv;
float sdivz8stepu, tdivz8stepu, zi8stepu;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
sdivz8stepu = sw32_d_sdivzstepu * 8;
tdivz8stepu = sw32_d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
do {
pdest = (short *) sw32_d_viewbuffer + (sw32_screenwidth * pspan->v) +
pspan->u;
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = sw32_d_zitable[(unsigned short) zi];
s = (int) (sdivz * z) + sw32_sadjust;
s = bound(0, s, sw32_bbextents);
t = (int) (tdivz * z) + sw32_tadjust;
t = bound(0, t, sw32_bbextentt);
while(count >= 8) {
count -= 8;
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = sw32_d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sw32_sadjust;
snext = bound(8, snext, sw32_bbextents);
tnext = (int) (tdivz * z) + sw32_tadjust;
tnext = bound(8, tnext, sw32_bbextentt);
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[4] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[5] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[6] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[7] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s = snext;t = tnext;
pdest += 8;
}
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span
// (so can't step off polygon), clamp, calculate s and t steps
// across span by division, biasing steps low so we don't run
// off the texture
//countminus1 = (float) (count - 1);
sdivz += sw32_d_sdivzstepu * count; //minus1;
tdivz += sw32_d_tdivzstepu * count; //minus1;
zi += d_zistepu * 65536.0f * count; //minus1;
z = sw32_d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sw32_sadjust;
snext = bound(count, snext, sw32_bbextents);
tnext = (int) (tdivz * z) + sw32_tadjust;
tnext = bound(count, tnext, sw32_bbextentt);
if (count > 1) {
sstep = (snext - s) / count; //(count - 1);
tstep = (tnext - t) / count; //(count - 1);
if (count & 4)
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;t += tstep;
pdest += 4;
}
if (count & 2)
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest += 2;
}
if (count & 1)
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
}
else
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
}
}
} while ((pspan = pspan->pnext) != NULL);
}
break;
case 4:
{
int *pbase = (int *) sw32_cacheblock, *pdest;
int count;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv;
float sdivz8stepu, tdivz8stepu, zi8stepu;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
sdivz8stepu = sw32_d_sdivzstepu * 8;
tdivz8stepu = sw32_d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
do {
pdest = (int *) sw32_d_viewbuffer + (sw32_screenwidth * pspan->v) + pspan->u;
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = sw32_d_zitable[(unsigned short) zi];
s = (int) (sdivz * z) + sw32_sadjust;
s = bound(0, s, sw32_bbextents);
t = (int) (tdivz * z) + sw32_tadjust;
t = bound(0, t, sw32_bbextentt);
while(count >= 8) {
count -= 8;
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = sw32_d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sw32_sadjust;
snext = bound(8, snext, sw32_bbextents);
tnext = (int) (tdivz * z) + sw32_tadjust;
tnext = bound(8, tnext, sw32_bbextentt);
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[4] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[5] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[6] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[7] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s = snext;
t = tnext;
pdest += 8;
}
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span
// (so can't step off polygon), clamp, calculate s and t steps
// across span by division, biasing steps low so we don't run
// off the texture
//countminus1 = (float) (count - 1);
sdivz += sw32_d_sdivzstepu * count; //minus1;
tdivz += sw32_d_tdivzstepu * count; //minus1;
zi += d_zistepu * 65536.0f * count; //minus1;
z = sw32_d_zitable[(unsigned short) zi];
// prevent round-off error on <0 steps from from causing
// overstepping & running off the edge of the texture
snext = (int) (sdivz * z) + sw32_sadjust;
snext = bound(count, snext, sw32_bbextents);
tnext = (int) (tdivz * z) + sw32_tadjust;
tnext = bound(count, tnext, sw32_bbextentt);
if (count > 1) {
sstep = (snext - s) / count; //(count - 1);
tstep = (tnext - t) / count; //(count - 1);
if (count & 4)
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest += 4;
}
if (count & 2)
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
s += sstep;
t += tstep;
pdest += 2;
}
if (count & 1)
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
}
else
{
pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)];
}
}
} while ((pspan = pspan->pnext) != NULL);
}
break;
default:
Sys_Error("D_DrawSpans: unsupported r_pixbytes %i", sw32_ctx->pixbytes);
}
}
void
sw32_D_DrawZSpans (espan_t *pspan)
{
int count, doublecount, izistep;
int izi;
short *pdest;
unsigned int ltemp;
double zi;
float du, dv;
// FIXME: check for clamping/range problems
// we count on FP exceptions being turned off to avoid range problems
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
do {
pdest = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
// calculate the initial 1/z
du = (float) pspan->u;
dv = (float) pspan->v;
zi = d_ziorigin + dv * d_zistepv + du * d_zistepu;
// we count on FP exceptions being turned off to avoid range problems
izi = (int) (zi * 0x8000 * 0x10000);
// LordHavoc: added big endian case, the old code is not correct on
// big-endian (results in swapped depth pairs), and is tuned more for
// x86, PowerPC compilers can probably do a good job with raw loop
// unrolling if it is even necessary...
if (bigendien)
{
do
{
*pdest++ = (short) (izi >> 16);
izi += izistep;
}
while(--count);
}
else
{
if ((intptr_t) pdest & 0x02) {
*pdest++ = (short) (izi >> 16);
izi += izistep;
count--;
}
if ((doublecount = count >> 1) > 0) {
do {
ltemp = izi >> 16;
izi += izistep;
ltemp |= izi & 0xFFFF0000;
izi += izistep;
*(int *) pdest = ltemp;
pdest += 2;
} while (--doublecount > 0);
}
if (count & 1)
*pdest = (short) (izi >> 16);
}
} while ((pspan = pspan->pnext) != NULL);
}

View file

@ -1,286 +0,0 @@
/*
d_sky.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_sw.h"
#define SKY_SPAN_SHIFT 5
#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT)
static void
D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
{
float wu, wv, temp;
vec3_t end;
int half_width = vid.width >> 1;
int half_height = vid.height >> 1;
if (r_refdef.vrect.width >= r_refdef.vrect.height)
temp = (float) r_refdef.vrect.width;
else
temp = (float) r_refdef.vrect.height;
wu = 8192.0 * (float) (u - half_width) / temp;
wv = 8192.0 * (float) (half_height - v) / temp;
end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0];
end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1];
end[2] = 4096 * vpn[2] + wu * vright[2] + wv * vup[2];
end[2] *= 3;
VectorNormalize (end);
temp = sw32_r_skytime * sw32_r_skyspeed; // TODO: add D_SetupFrame & set this there
*s = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[0]) * 0x10000);
*t = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[1]) * 0x10000);
}
void
sw32_D_DrawSkyScans (espan_t *pspan)
{
switch(sw32_ctx->pixbytes) {
case 1:
{
int count, spancount, u, v;
byte *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
snext = 0; // ditto
tnext = 0; // ditto
do {
pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
do {
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
count -= spancount;
if (count) {
u += spancount;
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
} else {
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = (float) (spancount - 1);
if (spancountminus1 > 0) {
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
do {
*pdest++ = ((byte *) sw32_r_skysource)
[((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
break;
case 2:
{
int count, spancount, u, v;
short *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
snext = 0; // ditto
tnext = 0; // ditto
do {
pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
do {
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
count -= spancount;
if (count) {
u += spancount;
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
} else {
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = (float) (spancount - 1);
if (spancountminus1 > 0) {
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
do {
*pdest++ = ((short *) sw32_r_skysource)
[((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
break;
case 4:
{
int count, spancount, u, v;
int *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
snext = 0; // ditto
tnext = 0; // ditto
do {
pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
do {
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
count -= spancount;
if (count) {
u += spancount;
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
} else {
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = (float) (spancount - 1);
if (spancountminus1 > 0) {
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
do {
*pdest++ = ((int *) sw32_r_skysource)
[((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
break;
default:
Sys_Error("D_DrawSkyScans: unsupported r_pixbytes %i", sw32_ctx->pixbytes);
}
}

View file

@ -1,732 +0,0 @@
/*
d_sprite.c
software top-level rasterization driver module for drawing sprites
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "compat.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static int sprite_height;
static int minindex, maxindex;
static sspan_t *sprite_spans;
void
sw32_D_SpriteDrawSpans (sspan_t *pspan)
{
switch(sw32_ctx->pixbytes) {
case 1:
{
int count, spancount, izistep;
int izi;
byte *pbase;
byte *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = (byte *) sw32_cacheblock;
sdivz8stepu = sw32_d_sdivzstepu * 8;
tdivz8stepu = sw32_d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536.0f;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
do {
pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan1;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = sw32_d_zitable[(int) zi];
// we count on FP exceptions being turned off to avoid range
// problems
izi = (int) (zi * 0x8000);
s = (int) (sdivz * z) + sw32_sadjust;
if (s > sw32_bbextents)
s = sw32_bbextents;
else if (s < 0)
s = 0;
t = (int) (tdivz * z) + sw32_tadjust;
if (t > sw32_bbextentt)
t = sw32_bbextentt;
else if (t < 0)
t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of
// span, calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = sw32_d_zitable[(int) zi];
snext = (int) (sdivz * z) + sw32_sadjust;
if (snext > sw32_bbextents)
snext = sw32_bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from causing overstepping
// & running off the texture's edge
tnext = (int) (tdivz * z) + sw32_tadjust;
if (tnext > sw32_bbextentt)
tnext = sw32_bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off
// error on <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel
// in span (so can't step off polygon), clamp,
// calculate s and t steps across span by division,
// biasing steps low so we don't run off the texture
spancountminus1 = (float) (spancount - 1);
sdivz += sw32_d_sdivzstepu * spancountminus1;
tdivz += sw32_d_tdivzstepu * spancountminus1;
zi += d_zistepu * 65536.0f * spancountminus1;
z = sw32_d_zitable[(int) zi];
snext = (int) (sdivz * z) + sw32_sadjust;
if (snext > sw32_bbextents)
snext = sw32_bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from from causing
// overstepping & running off the
// edge of the texture
tnext = (int) (tdivz * z) + sw32_tadjust;
if (tnext > sw32_bbextentt)
tnext = sw32_bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
if (spancount > 1) {
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do {
btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
if (btemp != TRANSPARENT_COLOR) {
if (*pz <= (izi >> 16)) {
*pz = izi >> 16;
*pdest = btemp;
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan1:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
break;
case 2:
{
int count, spancount, izistep;
int izi;
byte *pbase;
short *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = (byte *) sw32_cacheblock;
sdivz8stepu = sw32_d_sdivzstepu * 8;
tdivz8stepu = sw32_d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
do {
pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan2;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = sw32_d_zitable[(int) zi];
// we count on FP exceptions being turned off to avoid range
// problems
izi = (int) (zi * 0x8000);
s = (int) (sdivz * z) + sw32_sadjust;
if (s > sw32_bbextents)
s = sw32_bbextents;
else if (s < 0)
s = 0;
t = (int) (tdivz * z) + sw32_tadjust;
if (t > sw32_bbextentt)
t = sw32_bbextentt;
else if (t < 0)
t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of
// span, calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = sw32_d_zitable[(int) zi];
snext = (int) (sdivz * z) + sw32_sadjust;
if (snext > sw32_bbextents)
snext = sw32_bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from causing overstepping
// & running off the texture's edge
tnext = (int) (tdivz * z) + sw32_tadjust;
if (tnext > sw32_bbextentt)
tnext = sw32_bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel in
// span (so can't step off polygon), clamp, calculate s
// and t steps across span by division, biasing steps
// low so we don't run off the texture
spancountminus1 = (float) (spancount - 1);
sdivz += sw32_d_sdivzstepu * spancountminus1;
tdivz += sw32_d_tdivzstepu * spancountminus1;
zi += d_zistepu * 65536.0f * spancountminus1;
z = sw32_d_zitable[(int) zi];
snext = (int) (sdivz * z) + sw32_sadjust;
if (snext > sw32_bbextents)
snext = sw32_bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from from causing
// overstepping & running off the
// edge of the texture
tnext = (int) (tdivz * z) + sw32_tadjust;
if (tnext > sw32_bbextentt)
tnext = sw32_bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
if (spancount > 1) {
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do {
btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
if (btemp != TRANSPARENT_COLOR) {
if (*pz <= (izi >> 16)) {
*pz = izi >> 16;
*pdest = sw32_8to16table[btemp];
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan2:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
break;
case 4:
{
int count, spancount, izistep;
int izi;
byte *pbase;
int *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = (byte *) sw32_cacheblock;
sdivz8stepu = sw32_d_sdivzstepu * 8;
tdivz8stepu = sw32_d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8 * 65536;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
do {
pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan4;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float) pspan->u;
dv = (float) pspan->v;
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
z = sw32_d_zitable[(int) zi];
// we count on FP exceptions being turned off to avoid range
// problems
izi = (int) (zi * 0x8000);
s = (int) (sdivz * z) + sw32_sadjust;
if (s > sw32_bbextents)
s = sw32_bbextents;
else if (s < 0)
s = 0;
t = (int) (tdivz * z) + sw32_tadjust;
if (t > sw32_bbextentt)
t = sw32_bbextentt;
else if (t < 0)
t = 0;
do {
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count) {
// calculate s/z, t/z, zi->fixed s and t at far end of
// span, calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = sw32_d_zitable[(int) zi];
snext = (int) (sdivz * z) + sw32_sadjust;
if (snext > sw32_bbextents)
snext = sw32_bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps from causing overstepping
// & running off the texture's edge
tnext = (int) (tdivz * z) + sw32_tadjust;
if (tnext > sw32_bbextentt)
tnext = sw32_bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
} else {
// calculate s/z, t/z, zi->fixed s and t at last pixel in
// span (so can't step off polygon), clamp, calculate s
// and t steps across span by division, biasing steps low
// so we don't run off the texture
spancountminus1 = (float) (spancount - 1);
sdivz += sw32_d_sdivzstepu * spancountminus1;
tdivz += sw32_d_tdivzstepu * spancountminus1;
zi += d_zistepu * 65536.0f * spancountminus1;
z = sw32_d_zitable[(int) zi];
snext = (int) (sdivz * z) + sw32_sadjust;
if (snext > sw32_bbextents)
snext = sw32_bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0
// steps fromcausing overstepping
// & running off the texture's edge
tnext = (int) (tdivz * z) + sw32_tadjust;
if (tnext > sw32_bbextentt)
tnext = sw32_bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on
// <0 steps
if (spancount > 1) {
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do {
btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
if (btemp != TRANSPARENT_COLOR) {
if (*pz <= (izi >> 16)) {
*pz = izi >> 16;
*pdest = d_8to24table[btemp];
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan4:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
break;
default:
Sys_Error("D_SpriteDrawSpans: unsupported r_pixbytes %i",
sw32_ctx->pixbytes);
}
}
static void
D_SpriteScanLeftEdge (void)
{
int i, v, itop, ibottom, lmaxindex;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
if (i == 0)
i = sw32_r_spritedesc.nump;
lmaxindex = maxindex;
if (lmaxindex == 0)
lmaxindex = sw32_r_spritedesc.nump;
vtop = ceil (sw32_r_spritedesc.pverts[i].v);
do {
pvert = &sw32_r_spritedesc.pverts[i];
pnext = pvert - 1;
vbottom = ceil (pnext->v);
if (vtop < vbottom) {
du = pnext->u - pvert->u;
dv = pnext->v - pvert->v;
slope = du / dv;
u_step = (int) (slope * 0x10000);
// adjust u to ceil the integer portion
u = (int) ((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
(0x10000 - 1);
itop = (int) vtop;
ibottom = (int) vbottom;
for (v = itop; v < ibottom; v++) {
pspan->u = u >> 16;
pspan->v = v;
u += u_step;
pspan++;
}
}
vtop = vbottom;
i--;
if (i == 0)
i = sw32_r_spritedesc.nump;
} while (i != lmaxindex);
}
static void
D_SpriteScanRightEdge (void)
{
int i, v, itop, ibottom;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
vvert = sw32_r_spritedesc.pverts[i].v;
if (vvert < r_refdef.fvrecty_adj)
vvert = r_refdef.fvrecty_adj;
if (vvert > r_refdef.fvrectbottom_adj)
vvert = r_refdef.fvrectbottom_adj;
vtop = ceil (vvert);
do {
pvert = &sw32_r_spritedesc.pverts[i];
pnext = pvert + 1;
vnext = pnext->v;
if (vnext < r_refdef.fvrecty_adj)
vnext = r_refdef.fvrecty_adj;
if (vnext > r_refdef.fvrectbottom_adj)
vnext = r_refdef.fvrectbottom_adj;
vbottom = ceil (vnext);
if (vtop < vbottom) {
uvert = pvert->u;
if (uvert < r_refdef.fvrectx_adj)
uvert = r_refdef.fvrectx_adj;
if (uvert > r_refdef.fvrectright_adj)
uvert = r_refdef.fvrectright_adj;
unext = pnext->u;
if (unext < r_refdef.fvrectx_adj)
unext = r_refdef.fvrectx_adj;
if (unext > r_refdef.fvrectright_adj)
unext = r_refdef.fvrectright_adj;
du = unext - uvert;
dv = vnext - vvert;
slope = du / dv;
u_step = (int) (slope * 0x10000);
// adjust u to ceil the integer portion
u = (int) ((uvert + (slope * (vtop - vvert))) * 0x10000) +
(0x10000 - 1);
itop = (int) vtop;
ibottom = (int) vbottom;
for (v = itop; v < ibottom; v++) {
pspan->count = (u >> 16) - pspan->u;
u += u_step;
pspan++;
}
}
vtop = vbottom;
vvert = vnext;
i++;
if (i == sw32_r_spritedesc.nump)
i = 0;
} while (i != maxindex);
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
}
static void
D_SpriteCalculateGradients (void)
{
vec3_t p_normal, p_saxis, p_taxis, p_temp1;
float distinv;
sw32_TransformVector (sw32_r_spritedesc.vpn, p_normal);
sw32_TransformVector (sw32_r_spritedesc.vright, p_saxis);
sw32_TransformVector (sw32_r_spritedesc.vup, p_taxis);
VectorNegate (p_taxis, p_taxis);
distinv = 1.0 / (-DotProduct (modelorg, sw32_r_spritedesc.vpn));
distinv = min (distinv, 1.0);
sw32_d_sdivzstepu = p_saxis[0] * sw32_xscaleinv;
sw32_d_tdivzstepu = p_taxis[0] * sw32_xscaleinv;
sw32_d_sdivzstepv = -p_saxis[1] * sw32_yscaleinv;
sw32_d_tdivzstepv = -p_taxis[1] * sw32_yscaleinv;
d_zistepu = p_normal[0] * sw32_xscaleinv * distinv;
d_zistepv = -p_normal[1] * sw32_yscaleinv * distinv;
sw32_d_sdivzorigin = p_saxis[2] - sw32_xcenter * sw32_d_sdivzstepu -
sw32_ycenter * sw32_d_sdivzstepv;
sw32_d_tdivzorigin = p_taxis[2] - sw32_xcenter * sw32_d_tdivzstepu -
sw32_ycenter * sw32_d_tdivzstepv;
d_ziorigin = p_normal[2] * distinv - sw32_xcenter * d_zistepu -
sw32_ycenter * d_zistepv;
sw32_TransformVector (modelorg, p_temp1);
sw32_sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
(-(sw32_cachewidth >> 1) << 16);
sw32_tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
(-(sprite_height >> 1) << 16);
// -1 (-epsilon) so we never wander off the edge of the texture
sw32_bbextents = (sw32_cachewidth << 16) - 1;
sw32_bbextentt = (sprite_height << 16) - 1;
}
void
sw32_D_DrawSprite (void)
{
int i, nump;
float ymin, ymax;
emitpoint_t *pverts;
sspan_t spans[MAXHEIGHT + 1];
sprite_spans = spans;
// find the top and bottom vertices, and make sure there's at least one
// scan to draw
ymin = 999999.9;
ymax = -999999.9;
pverts = sw32_r_spritedesc.pverts;
for (i = 0; i < sw32_r_spritedesc.nump; i++) {
if (pverts->v < ymin) {
ymin = pverts->v;
minindex = i;
}
if (pverts->v > ymax) {
ymax = pverts->v;
maxindex = i;
}
pverts++;
}
ymin = ceil (ymin);
ymax = ceil (ymax);
if (ymin >= ymax)
return; // doesn't cross any scans at all
sw32_cachewidth = sw32_r_spritedesc.pspriteframe->width;
sprite_height = sw32_r_spritedesc.pspriteframe->height;
sw32_cacheblock = &sw32_r_spritedesc.pspriteframe->pixels[0];
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump = sw32_r_spritedesc.nump;
pverts = sw32_r_spritedesc.pverts;
pverts[nump] = pverts[0];
D_SpriteCalculateGradients ();
D_SpriteScanLeftEdge ();
D_SpriteScanRightEdge ();
sw32_D_SpriteDrawSpans (sprite_spans);
}

View file

@ -1,287 +0,0 @@
/*
d_surf.c
rasterization driver surface heap manager
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include <stdlib.h>
#include "QF/qargs.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "compat.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_sw.h"
static float surfscale;
static int sc_size;
surfcache_t *sw32_sc_rover;
static surfcache_t *sc_base;
#define GUARDSIZE 4
void *
sw32_D_SurfaceCacheAddress (void)
{
return sc_base;
}
int
sw32_D_SurfaceCacheForRes (void *data, int width, int height)
{
int size, pix;
if (COM_CheckParm ("-surfcachesize")) {
size = atoi (com_argv[COM_CheckParm ("-surfcachesize") + 1]) * 1024;
return size;
}
size = SURFCACHE_SIZE_AT_320X200;
pix = width * height;
if (pix > 64000)
size += (pix - 64000) * 3;
size *= sw32_ctx->pixbytes;
return size;
}
static void
D_CheckCacheGuard (void)
{
byte *s;
int i;
s = (byte *) sc_base + sc_size;
for (i = 0; i < GUARDSIZE; i++)
if (s[i] != (byte) i)
Sys_Error ("D_CheckCacheGuard: failed");
}
static void
D_ClearCacheGuard (void)
{
byte *s;
int i;
s = (byte *) sc_base + sc_size;
for (i = 0; i < GUARDSIZE; i++)
s[i] = (byte) i;
}
void
sw32_D_InitCaches (void *data, void *buffer, int size)
{
Sys_MaskPrintf (SYS_dev, "D_InitCaches: %ik surface cache\n", size/1024);
sc_size = size - GUARDSIZE;
sc_base = (surfcache_t *) buffer;
sw32_sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
sw32_d_pzbuffer = vid.zbuffer;
D_ClearCacheGuard ();
}
void
sw32_D_FlushCaches (void *data)
{
surfcache_t *c;
if (!sc_base)
return;
for (c = sc_base; c; c = c->next) {
if (c->owner)
*c->owner = NULL;
}
sw32_sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
}
static surfcache_t *
D_SCAlloc (int width, int size)
{
surfcache_t *new;
qboolean wrapped_this_time;
if ((width < 0) || (width > 512)) // FIXME shouldn't really have a max
Sys_Error ("D_SCAlloc: bad cache width %d", width);
if ((size <= 0) || (size > (0x40000 * sw32_ctx->pixbytes))) //FIXME ditto
Sys_Error ("D_SCAlloc: bad cache size %d", size);
/* This adds the offset of data[0] in the surfcache_t struct. */
size += field_offset (surfcache_t, data);
#define SIZE_ALIGN (sizeof(surfcache_t*)-1)
size = (size + SIZE_ALIGN) & ~SIZE_ALIGN;
#undef SIZE_ALIGN
size = (size + 3) & ~3;
if (size > sc_size)
Sys_Error ("D_SCAlloc: %i > cache size", size);
// if there is not size bytes after the rover, reset to the start
wrapped_this_time = false;
if (!sw32_sc_rover || (byte *) sw32_sc_rover - (byte *) sc_base > sc_size - size) {
if (sw32_sc_rover) {
wrapped_this_time = true;
}
sw32_sc_rover = sc_base;
}
// colect and free surfcache_t blocks until the rover block is large enough
new = sw32_sc_rover;
if (sw32_sc_rover->owner)
*sw32_sc_rover->owner = NULL;
while (new->size < size) {
// free another
sw32_sc_rover = sw32_sc_rover->next;
if (!sw32_sc_rover)
Sys_Error ("D_SCAlloc: hit the end of memory");
if (sw32_sc_rover->owner)
*sw32_sc_rover->owner = NULL;
new->size += sw32_sc_rover->size;
new->next = sw32_sc_rover->next;
}
// create a fragment out of any leftovers
if (new->size - size > 256) {
sw32_sc_rover = (surfcache_t *) ((byte *) new + size);
sw32_sc_rover->size = new->size - size;
sw32_sc_rover->next = new->next;
sw32_sc_rover->width = 0;
sw32_sc_rover->owner = NULL;
new->next = sw32_sc_rover;
new->size = size;
} else
sw32_sc_rover = new->next;
new->width = width;
// DEBUG
if (width > 0)
new->height = (size - sizeof (*new) + sizeof (new->data)) /
(width * sw32_ctx->pixbytes);
new->owner = NULL; // should be set properly after return
if (sw32_d_roverwrapped) {
if (wrapped_this_time || (sw32_sc_rover >= sw32_d_initial_rover))
r_cache_thrash = true;
} else if (wrapped_this_time) {
sw32_d_roverwrapped = true;
}
D_CheckCacheGuard (); // DEBUG
return new;
}
surfcache_t *
sw32_D_CacheSurface (msurface_t *surface, int miplevel)
{
surfcache_t *cache;
// if the surface is animating or flashing, flush the cache
sw32_r_drawsurf.texture = R_TextureAnimation (currententity, surface);
sw32_r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
sw32_r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
sw32_r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
sw32_r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
// see if the cache holds apropriate data
cache = surface->cachespots[miplevel];
if (cache && !cache->dlight && surface->dlightframe != r_framecount
&& cache->texture == sw32_r_drawsurf.texture
&& cache->lightadj[0] == sw32_r_drawsurf.lightadj[0]
&& cache->lightadj[1] == sw32_r_drawsurf.lightadj[1]
&& cache->lightadj[2] == sw32_r_drawsurf.lightadj[2]
&& cache->lightadj[3] == sw32_r_drawsurf.lightadj[3])
return cache;
// determine shape of surface
surfscale = 1.0 / (1 << miplevel);
sw32_r_drawsurf.surfmip = miplevel;
sw32_r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
sw32_r_drawsurf.rowbytes = sw32_r_drawsurf.surfwidth * sw32_ctx->pixbytes;
sw32_r_drawsurf.surfheight = surface->extents[1] >> miplevel;
// allocate memory if needed
if (!cache) {
// if a texture just animated, don't reallocate it
cache = D_SCAlloc (sw32_r_drawsurf.surfwidth,
sw32_r_drawsurf.rowbytes * sw32_r_drawsurf.surfheight);
surface->cachespots[miplevel] = cache;
cache->owner = &surface->cachespots[miplevel];
cache->mipscale = surfscale;
}
if (surface->dlightframe == r_framecount)
cache->dlight = 1;
else
cache->dlight = 0;
sw32_r_drawsurf.surfdat = (byte *) cache->data;
cache->texture = sw32_r_drawsurf.texture;
cache->lightadj[0] = sw32_r_drawsurf.lightadj[0];
cache->lightadj[1] = sw32_r_drawsurf.lightadj[1];
cache->lightadj[2] = sw32_r_drawsurf.lightadj[2];
cache->lightadj[3] = sw32_r_drawsurf.lightadj[3];
// draw and light the surface texture
sw32_r_drawsurf.surf = surface;
sw32_c_surf++;
sw32_R_DrawSurface ();
return surface->cachespots[miplevel];
}

View file

@ -1,55 +0,0 @@
/*
d_vars.c
global refresh variables
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/qtypes.h"
// all global and static refresh variables are collected in a contiguous block
// to avoid cache conflicts.
// global refresh variables -----------------------------
// FIXME: make into one big structure, like cl or sv
// FIXME: do separately for refresh engine and driver
float sw32_d_sdivzstepu, sw32_d_tdivzstepu, sw32_d_zistepu;
float sw32_d_sdivzstepv, sw32_d_tdivzstepv, sw32_d_zistepv;
float sw32_d_sdivzorigin, sw32_d_tdivzorigin, sw32_d_ziorigin;
fixed16_t sw32_sadjust, sw32_tadjust, sw32_bbextents, sw32_bbextentt;
byte *sw32_cacheblock;
int sw32_cachewidth;
byte *sw32_d_viewbuffer;
short *sw32_d_pzbuffer;
int sw32_d_zrowbytes;
int sw32_d_zwidth;

View file

@ -1,73 +0,0 @@
/*
d_zpoint.c
software driver module for drawing z-buffered points
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/sys.h"
#include "d_local.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
void
sw32_D_DrawZPoint (void)
{
short *pz;
int izi;
pz = sw32_d_pzbuffer + (sw32_d_zwidth * sw32_r_zpointdesc.v) + sw32_r_zpointdesc.u;
izi = (int) (sw32_r_zpointdesc.zi * 0x8000);
if (*pz <= izi) {
*pz = izi;
switch(sw32_ctx->pixbytes)
{
case 1:
((byte *) sw32_d_viewbuffer) [sw32_d_scantable[sw32_r_zpointdesc.v] +
sw32_r_zpointdesc.u] = sw32_r_zpointdesc.color;
break;
case 2:
((short *) sw32_d_viewbuffer) [sw32_d_scantable[sw32_r_zpointdesc.v] +
sw32_r_zpointdesc.u] =
sw32_8to16table[sw32_r_zpointdesc.color];
break;
case 4:
((int *) sw32_d_viewbuffer) [sw32_d_scantable[sw32_r_zpointdesc.v] +
sw32_r_zpointdesc.u] =
d_8to24table[sw32_r_zpointdesc.color];
break;
default:
Sys_Error("D_DrawZPoint: unsupported r_pixbytes %i", sw32_ctx->pixbytes);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,473 +0,0 @@
#ifdef NH_DEFINE
#undef NH_DEFINE
#define D_CacheSurface sw32_D_CacheSurface
#define D_DrawParticle sw32_D_DrawParticle
#define D_DrawPoly sw32_D_DrawPoly
#define D_DrawSkyScans sw32_D_DrawSkyScans
#define D_DrawSpans sw32_D_DrawSpans
#define D_DrawSprite sw32_D_DrawSprite
#define D_DrawSurfaces sw32_D_DrawSurfaces
#define D_DrawZPoint sw32_D_DrawZPoint
#define D_DrawZSpans sw32_D_DrawZSpans
#define D_FillRect sw32_D_FillRect
#define D_FlushCaches sw32_D_FlushCaches
#define D_Init sw32_D_Init
#define D_InitCaches sw32_D_InitCaches
#define D_MipLevelForScale sw32_D_MipLevelForScale
#define D_PolysetCalcGradients sw32_D_PolysetCalcGradients
#define D_PolysetDraw sw32_D_PolysetDraw
#define D_PolysetScanLeftEdge sw32_D_PolysetScanLeftEdge
#define D_PolysetSetEdgeTable sw32_D_PolysetSetEdgeTable
#define D_RasterizeAliasPolySmooth sw32_D_RasterizeAliasPolySmooth
#define D_SetupFrame sw32_D_SetupFrame
#define D_SpriteDrawSpans sw32_D_SpriteDrawSpans
#define D_SurfaceCacheAddress sw32_D_SurfaceCacheAddress
#define D_SurfaceCacheForRes sw32_D_SurfaceCacheForRes
#define D_TurnZOn sw32_D_TurnZOn
#define D_UpdateRects sw32_D_UpdateRects
#define D_ViewChanged sw32_D_ViewChanged
#define D_WarpScreen sw32_D_WarpScreen
#define Draw_AltString sw32_Draw_AltString
#define Draw_BlendScreen sw32_Draw_BlendScreen
#define Draw_CachePic sw32_Draw_CachePic
#define Draw_Character sw32_Draw_Character
#define Draw_ConsoleBackground sw32_Draw_ConsoleBackground
#define Draw_Crosshair sw32_Draw_Crosshair
#define Draw_CrosshairAt sw32_Draw_CrosshairAt
#define Draw_DestroyPic sw32_Draw_DestroyPic
#define Draw_FadeScreen sw32_Draw_FadeScreen
#define Draw_Fill sw32_Draw_Fill
#define Draw_Init sw32_Draw_Init
#define Draw_MakePic sw32_Draw_MakePic
#define Draw_Pic sw32_Draw_Pic
#define Draw_PicFromWad sw32_Draw_PicFromWad
#define Draw_Picf sw32_Draw_Picf
#define Draw_String sw32_Draw_String
#define Draw_SubPic sw32_Draw_SubPic
#define Draw_TextBox sw32_Draw_TextBox
#define Draw_TileClear sw32_Draw_TileClear
#define Draw_UncachePic sw32_Draw_UncachePic
#define Draw_nString sw32_Draw_nString
#define R_AliasCheckBBox sw32_R_AliasCheckBBox
#define R_AliasClipTriangle sw32_R_AliasClipTriangle
#define R_AliasClipAndProjectFinalVert sw32_R_AliasClipAndProjectFinalVert
#define R_AliasDrawModel sw32_R_AliasDrawModel
#define R_AliasProjectFinalVert sw32_R_AliasProjectFinalVert
#define R_AliasSetUpTransform sw32_R_AliasSetUpTransform
#define R_AliasTransformAndProjectFinalVerts sw32_R_AliasTransformAndProjectFinalVerts
#define R_AliasTransformFinalVert sw32_R_AliasTransformFinalVert
#define R_AliasTransformVector sw32_R_AliasTransformVector
#define R_Alias_clip_bottom sw32_R_Alias_clip_bottom
#define R_Alias_clip_left sw32_R_Alias_clip_left
#define R_Alias_clip_right sw32_R_Alias_clip_right
#define R_Alias_clip_top sw32_R_Alias_clip_top
#define R_IQMDrawModel sw32_R_IQMDrawModel
#define R_BeginEdgeFrame sw32_R_BeginEdgeFrame
#define R_ClearState sw32_R_ClearState
#define R_ClipEdge sw32_R_ClipEdge
#define R_DrawParticles sw32_R_DrawParticles
#define R_DrawSolidClippedSubmodelPolygons sw32_R_DrawSolidClippedSubmodelPolygons
#define R_DrawSprite sw32_R_DrawSprite
#define R_DrawSubmodelPolygons sw32_R_DrawSubmodelPolygons
#define R_DrawSurface sw32_R_DrawSurface
#define R_EmitEdge sw32_R_EmitEdge
#define R_GenerateSpans sw32_R_GenerateSpans
#define R_InitParticles sw32_R_InitParticles
#define R_InitSky sw32_R_InitSky
#define R_InitTurb sw32_R_InitTurb
#define R_InsertNewEdges sw32_R_InsertNewEdges
#define R_LineGraph sw32_R_LineGraph
#define R_LoadSky_f sw32_R_LoadSky_f
#define R_LoadSkys sw32_R_LoadSkys
#define R_MakeSky sw32_R_MakeSky
#define R_NewMap sw32_R_NewMap
#define R_Particle_New sw32_R_Particle_New
#define R_Particle_NewRandom sw32_R_Particle_NewRandom
#define R_Particles_Init_Cvars sw32_R_Particles_Init_Cvars
#define R_PrintAliasStats sw32_R_PrintAliasStats
#define R_PrintTimes sw32_R_PrintTimes
#define R_ReadPointFile_f sw32_R_ReadPointFile_f
#define R_RemoveEdges sw32_R_RemoveEdges
#define R_RenderBmodelFace sw32_R_RenderBmodelFace
#define R_RenderFace sw32_R_RenderFace
#define R_RenderPoly sw32_R_RenderPoly
#define R_RenderView sw32_R_RenderView
#define R_RenderWorld sw32_R_RenderWorld
#define R_RotateBmodel sw32_R_RotateBmodel
#define R_ScanEdges sw32_R_ScanEdges
#define R_SetSkyFrame sw32_R_SetSkyFrame
#define R_SetupFrame sw32_R_SetupFrame
#define R_StepActiveU sw32_R_StepActiveU
#define R_Textures_Init sw32_R_Textures_Init
#define R_TimeRefresh_f sw32_R_TimeRefresh_f
#define R_TransformFrustum sw32_R_TransformFrustum
#define R_TransformPlane sw32_R_TransformPlane
#define R_ViewChanged sw32_R_ViewChanged
#define R_ZDrawSubmodelPolys sw32_R_ZDrawSubmodelPolys
#define SCR_ScreenShot sw32_SCR_ScreenShot
#define SCR_ScreenShot_f sw32_SCR_ScreenShot_f
#define R_RenderFrame sw32_R_RenderFrame
#define TransformVector sw32_TransformVector
#define Turbulent sw32_Turbulent
#define acolormap sw32_acolormap
#define aliastransform sw32_aliastransform
#define aliasxcenter sw32_aliasxcenter
#define aliasxscale sw32_aliasxscale
#define aliasycenter sw32_aliasycenter
#define aliasyscale sw32_aliasyscale
#define auxedges sw32_auxedges
#define bbextents sw32_bbextents
#define bbextentt sw32_bbextentt
#define c_faceclip sw32_c_faceclip
#define c_surf sw32_c_surf
#define cacheblock sw32_cacheblock
#define cachewidth sw32_cachewidth
#define d_initial_rover sw32_d_initial_rover
#define d_minmip sw32_d_minmip
#define d_pix_max sw32_d_pix_max
#define d_pix_min sw32_d_pix_min
#define d_pix_shift sw32_d_pix_shift
#define d_pzbuffer sw32_d_pzbuffer
#define d_roverwrapped sw32_d_roverwrapped
#define d_scalemip sw32_d_scalemip
#define d_scantable sw32_d_scantable
#define d_sdivzorigin sw32_d_sdivzorigin
#define d_sdivzstepu sw32_d_sdivzstepu
#define d_sdivzstepv sw32_d_sdivzstepv
#define d_tdivzorigin sw32_d_tdivzorigin
#define d_tdivzstepu sw32_d_tdivzstepu
#define d_tdivzstepv sw32_d_tdivzstepv
#define d_viewbuffer sw32_d_viewbuffer
#define d_vrectbottom_particle sw32_d_vrectbottom_particle
#define d_vrectright_particle sw32_d_vrectright_particle
#define d_vrectx sw32_d_vrectx
#define d_vrecty sw32_d_vrecty
#define d_y_aspect_shift sw32_d_y_aspect_shift
#define d_ziorigin sw32_d_ziorigin
#define d_zistepu sw32_d_zistepu
#define d_zistepv sw32_d_zistepv
#define d_zitable sw32_d_zitable
#define d_zrowbytes sw32_d_zrowbytes
#define d_zwidth sw32_d_zwidth
#define edge_max sw32_edge_max
#define edge_p sw32_edge_p
#define insubmodel sw32_insubmodel
#define intsintable sw32_intsintable
#define newedges sw32_newedges
#define numbtofpolys sw32_numbtofpolys
#define pauxverts sw32_pauxverts
#define pfinalverts sw32_pfinalverts
#define pfrustum_indexes sw32_pfrustum_indexes
#define pixelAspect sw32_pixelAspect
#define r_affinetridesc sw32_r_affinetridesc
#define r_aliastransition sw32_r_aliastransition
#define r_aliasuvscale sw32_r_aliasuvscale
#define r_ambientlight sw32_r_ambientlight
#define r_amodels_drawn sw32_r_amodels_drawn
#define r_apverts sw32_r_apverts
#define r_ceilv1 sw32_r_ceilv1
#define r_clipflags sw32_r_clipflags
#define r_currentbkey sw32_r_currentbkey
#define r_currentkey sw32_r_currentkey
#define r_dowarp sw32_r_dowarp
#define r_dowarpold sw32_r_dowarpold
#define r_drawculledpolys sw32_r_drawculledpolys
#define r_drawnpolycount sw32_r_drawnpolycount
#define r_drawpolys sw32_r_drawpolys
#define r_drawsurf sw32_r_drawsurf
#define r_easter_eggs_f sw32_r_easter_eggs_f
#define r_edges sw32_r_edges
#define r_emitted sw32_r_emitted
#define r_frustum_indexes sw32_r_frustum_indexes
#define r_lastvertvalid sw32_r_lastvertvalid
#define r_leftclipped sw32_r_leftclipped
#define r_leftenter sw32_r_leftenter
#define r_leftexit sw32_r_leftexit
#define r_lzi1 sw32_r_lzi1
#define r_maxedgesseen sw32_r_maxedgesseen
#define r_maxsurfsseen sw32_r_maxsurfsseen
#define r_nearzi sw32_r_nearzi
#define r_nearzionly sw32_r_nearzionly
#define r_numallocatededges sw32_r_numallocatededges
#define r_outofedges sw32_r_outofedges
#define r_outofsurfaces sw32_r_outofsurfaces
#define r_particles_style_f sw32_r_particles_style_f
#define r_pedge sw32_r_pedge
#define r_pixbytes sw32_r_pixbytes
#define r_plightvec sw32_r_plightvec
#define r_polycount sw32_r_polycount
#define r_resfudge sw32_r_resfudge
#define r_rightclipped sw32_r_rightclipped
#define r_rightenter sw32_r_rightenter
#define r_rightexit sw32_r_rightexit
#define r_shadelight sw32_r_shadelight
#define r_skymade sw32_r_skymade
#define r_skysource sw32_r_skysource
#define r_skyspeed sw32_r_skyspeed
#define r_skytime sw32_r_skytime
#define r_spritedesc sw32_r_spritedesc
#define r_u1 sw32_r_u1
#define r_v1 sw32_r_v1
#define r_viewchanged sw32_r_viewchanged
#define r_warpbuffer sw32_r_warpbuffer
#define r_worldmodelorg sw32_r_worldmodelorg
#define r_worldpolysbacktofront sw32_r_worldpolysbacktofront
#define r_zpointdesc sw32_r_zpointdesc
#define removeedges sw32_removeedges
#define sadjust sw32_sadjust
#define sc_rover sw32_sc_rover
#define scale_for_mip sw32_scale_for_mip
#define screenedge sw32_screenedge
#define screenwidth sw32_screenwidth
#define sintable sw32_sintable
#define surf_max sw32_surf_max
#define surface_p sw32_surface_p
extern struct surf_s *sw32_surfaces;
//#define surfaces sw32_surfaces
#define tadjust sw32_tadjust
#define view_clipplanes sw32_view_clipplanes
#define xcenter sw32_xcenter
#define xscale sw32_xscale
#define xscaleinv sw32_xscaleinv
#define xscaleshrink sw32_xscaleshrink
#define ycenter sw32_ycenter
#define yscale sw32_yscale
#define yscaleinv sw32_yscaleinv
#define yscaleshrink sw32_yscaleshrink
#define zspantable sw32_zspantable
#else
#undef D_CacheSurface
#undef D_DrawParticle
#undef D_DrawPoly
#undef D_DrawSkyScans
#undef D_DrawSpans
#undef D_DrawSprite
#undef D_DrawSurfaces
#undef D_DrawZPoint
#undef D_DrawZSpans
#undef D_FillRect
#undef D_FlushCaches
#undef D_Init
#undef D_InitCaches
#undef D_MipLevelForScale
#undef D_PolysetCalcGradients
#undef D_PolysetDraw
#undef D_PolysetScanLeftEdge
#undef D_PolysetSetEdgeTable
#undef D_RasterizeAliasPolySmooth
#undef D_SetupFrame
#undef D_SpriteDrawSpans
#undef D_SurfaceCacheAddress
#undef D_SurfaceCacheForRes
#undef D_TurnZOn
#undef D_UpdateRects
#undef D_ViewChanged
#undef D_WarpScreen
#undef Draw_AltString
#undef Draw_BlendScreen
#undef Draw_CachePic
#undef Draw_Character
#undef Draw_ConsoleBackground
#undef Draw_Crosshair
#undef Draw_CrosshairAt
#undef Draw_DestroyPic
#undef Draw_FadeScreen
#undef Draw_Fill
#undef Draw_Init
#undef Draw_MakePic
#undef Draw_Pic
#undef Draw_PicFromWad
#undef Draw_Picf
#undef Draw_String
#undef Draw_SubPic
#undef Draw_TextBox
#undef Draw_TileClear
#undef Draw_UncachePic
#undef Draw_nString
#undef R_AliasCheckBBox
#undef R_AliasClipTriangle
#undef R_AliasClipAndProjectFinalVert
#undef R_AliasDrawModel
#undef R_AliasProjectFinalVert
#undef R_AliasSetUpTransform
#undef R_AliasTransformAndProjectFinalVerts
#undef R_AliasTransformFinalVert
#undef R_AliasTransformVector
#undef R_Alias_clip_bottom
#undef R_Alias_clip_left
#undef R_Alias_clip_right
#undef R_Alias_clip_top
#undef R_IQMDrawModel
#undef R_BeginEdgeFrame
#undef R_ClearState
#undef R_ClipEdge
#undef R_DrawParticles
#undef R_DrawSolidClippedSubmodelPolygons
#undef R_DrawSprite
#undef R_DrawSubmodelPolygons
#undef R_DrawSurface
#undef R_EmitEdge
#undef R_GenerateSpans
#undef R_Init
#undef R_InitParticles
#undef R_InitSky
#undef R_InitTurb
#undef R_InsertNewEdges
#undef R_LineGraph
#undef R_LoadSky_f
#undef R_LoadSkys
#undef R_MakeSky
#undef R_NewMap
#undef R_Particle_New
#undef R_Particle_NewRandom
#undef R_Particles_Init_Cvars
#undef R_PrintAliasStats
#undef R_PrintTimes
#undef R_ReadPointFile_f
#undef R_RemoveEdges
#undef R_RenderBmodelFace
#undef R_RenderFace
#undef R_RenderPoly
#undef R_RenderView
#undef R_RenderWorld
#undef R_RotateBmodel
#undef R_ScanEdges
#undef R_SetSkyFrame
#undef R_SetupFrame
#undef R_StepActiveU
#undef R_Textures_Init
#undef R_TimeRefresh_f
#undef R_TransformFrustum
#undef R_TransformPlane
#undef R_ViewChanged
#undef R_ZDrawSubmodelPolys
#undef SCR_CaptureBGR
#undef SCR_ScreenShot
#undef SCR_ScreenShot_f
#undef R_RenderFrame
#undef TransformVector
#undef Turbulent
#undef VID_InitBuffers
#undef VID_ShiftPalette
#undef acolormap
#undef aliasxcenter
#undef aliasxscale
#undef aliasycenter
#undef aliasyscale
#undef auxedges
#undef bbextents
#undef bbextentt
#undef c_faceclip
#undef c_surf
#undef cacheblock
#undef cachewidth
#undef d_initial_rover
#undef d_minmip
#undef d_pix_max
#undef d_pix_min
#undef d_pix_shift
#undef d_pzbuffer
#undef d_roverwrapped
#undef d_scalemip
#undef d_scantable
#undef d_sdivzorigin
#undef d_sdivzstepu
#undef d_sdivzstepv
#undef d_tdivzorigin
#undef d_tdivzstepu
#undef d_tdivzstepv
#undef d_viewbuffer
#undef d_vrectbottom_particle
#undef d_vrectright_particle
#undef d_vrectx
#undef d_vrecty
#undef d_y_aspect_shift
#undef d_zitable
#undef d_zrowbytes
#undef d_zwidth
#undef edge_max
#undef edge_p
#undef insubmodel
#undef intsintable
#undef newedges
#undef numbtofpolys
#undef pauxverts
#undef pfinalverts
#undef pfrustum_indexes
#undef pixelAspect
#undef r_affinetridesc
#undef r_aliastransition
#undef r_aliasuvscale
#undef r_ambientlight
#undef r_amodels_drawn
#undef r_apverts
#undef r_ceilv1
#undef r_clipflags
#undef r_currentbkey
#undef r_currentkey
#undef r_dowarp
#undef r_dowarpold
#undef r_drawculledpolys
#undef r_drawnpolycount
#undef r_drawpolys
#undef r_drawsurf
#undef r_easter_eggs_f
#undef r_edges
#undef r_emitted
#undef r_frustum_indexes
#undef r_lastvertvalid
#undef r_leftclipped
#undef r_leftenter
#undef r_leftexit
#undef r_lzi1
#undef r_maxedgesseen
#undef r_maxsurfsseen
#undef r_nearzi
#undef r_nearzionly
#undef r_numallocatededges
#undef r_outofedges
#undef r_outofsurfaces
#undef r_particles_style_f
#undef r_pedge
#undef r_pixbytes
#undef r_plightvec
#undef r_polycount
#undef r_resfudge
#undef r_rightclipped
#undef r_rightenter
#undef r_rightexit
#undef r_shadelight
#undef r_skymade
#undef r_skysource
#undef r_skyspeed
#undef r_skytime
#undef r_spritedesc
#undef r_u1
#undef r_v1
#undef r_viewchanged
#undef r_warpbuffer
#undef r_worldmodelorg
#undef r_worldpolysbacktofront
#undef r_zpointdesc
#undef removeedges
#undef sadjust
#undef sc_rover
#undef scale_for_mip
#undef screenedge
#undef screenwidth
#undef sintable
#undef surf_max
#undef surface_p
//#undef surfaces
#undef tadjust
#undef view_clipplanes
#undef xcenter
#undef xscale
#undef xscaleinv
#undef xscaleshrink
#undef ycenter
#undef yscale
#undef yscaleinv
#undef yscaleshrink
#undef zspantable
#endif

View file

@ -1,68 +0,0 @@
/*
screen.c
master for refresh, status bar, console, chat, notify, etc
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include "QF/image.h"
#include "QF/sys.h"
#include "r_internal.h"
#include "vid_sw.h"
/* SCREEN SHOTS */
tex_t *
sw32_SCR_CaptureBGR (void)
{
int count, x, y;
tex_t *tex;
const byte *src;
byte *dst;
count = vid.width * vid.height;
tex = malloc (sizeof (tex_t) + count * 3);
tex->data = (byte *) (tex + 1);
SYS_CHECKMEM (tex);
tex->width = vid.width;
tex->height = vid.height;
tex->format = tex_rgb;
tex->palette = 0;
src = vid.buffer;
for (y = 0; y < tex->height; y++) {
dst = tex->data + (tex->height - 1 - y) * tex->width * 3;
for (x = 0; x < tex->width; x++) {
*dst++ = vid.basepal[*src * 3 + 2]; // blue
*dst++ = vid.basepal[*src * 3 + 1]; // green
*dst++ = vid.basepal[*src * 3 + 0]; // red
src++;
}
}
return tex;
}

View file

@ -1,102 +0,0 @@
/*
sw32_graph.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/cvar.h"
#include "QF/draw.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
/*
R_LineGraph
Called by only R_DisplayTime
*/
void
sw32_R_LineGraph (int x, int y, int *h_vals, int count, int height)
{
int h, i, s, color;
// FIXME: disable on no-buffer adapters, or put in the driver
s = height;
while (count--) {
h = *h_vals++;
if (h == 10000)
color = 0x6f; // yellow
else if (h == 9999)
color = 0x4f; // red
else if (h == 9998)
color = 0xd0; // blue
else
color = 0xff; // pink
if (h > s)
h = s;
switch(sw32_ctx->pixbytes) {
case 1:
{
byte *dest = (byte *) vid.buffer + vid.rowbytes * y + x;
for (i = 0; i < h; i++, dest -= vid.rowbytes)
*dest = color;
}
break;
case 2:
{
short *dest = (short *) vid.buffer +
(vid.rowbytes >> 1) * y + x;
color = sw32_8to16table[color];
for (i = 0; i < h; i++, dest -= (vid.rowbytes >> 1))
*dest = color;
}
break;
case 4:
{
int *dest = (int *) vid.buffer +
(vid.rowbytes >> 2) * y + x;
color = d_8to24table[color];
for (i = 0; i < h; i++, dest -= (vid.rowbytes >> 2))
*dest = color;
}
break;
default:
Sys_Error("R_LineGraph: unsupported r_pixbytes %i",
sw32_ctx->pixbytes);
}
}
}

View file

@ -1,315 +0,0 @@
/*
r_aclip.c
clip routines for drawing Alias models directly to the screen
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/render.h"
#include "d_local.h"
#include "r_internal.h"
static finalvert_t fv[2][8];
static auxvert_t av[8];
/*
R_Alias_clip_z
pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
*/
static void
R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
auxvert_t *pav0, *pav1, avout;
pav0 = &av[pfv0 - &fv[0][0]];
pav1 = &av[pfv1 - &fv[0][0]];
if (pfv0->v[1] >= pfv1->v[1]) {
scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
(pav1->fv[2] - pav0->fv[2]);
avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale;
out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale;
out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale;
} else {
scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
(pav0->fv[2] - pav1->fv[2]);
avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale;
avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale;
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale;
out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale;
out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale;
}
sw32_R_AliasProjectFinalVert (out, &avout);
if (out->v[0] < r_refdef.aliasvrect.x)
out->flags |= ALIAS_LEFT_CLIP;
if (out->v[1] < r_refdef.aliasvrect.y)
out->flags |= ALIAS_TOP_CLIP;
if (out->v[0] > r_refdef.aliasvrectright)
out->flags |= ALIAS_RIGHT_CLIP;
if (out->v[1] > r_refdef.aliasvrectbottom)
out->flags |= ALIAS_BOTTOM_CLIP;
}
void
sw32_R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
int i;
if (pfv0->v[1] >= pfv1->v[1]) {
scale = (float) (r_refdef.aliasvrect.x - pfv0->v[0]) /
(pfv1->v[0] - pfv0->v[0]);
for (i = 0; i < 6; i++)
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5;
} else {
scale = (float) (r_refdef.aliasvrect.x - pfv1->v[0]) /
(pfv0->v[0] - pfv1->v[0]);
for (i = 0; i < 6; i++)
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5;
}
}
void
sw32_R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
int i;
if (pfv0->v[1] >= pfv1->v[1]) {
scale = (float) (r_refdef.aliasvrectright - pfv0->v[0]) /
(pfv1->v[0] - pfv0->v[0]);
for (i = 0; i < 6; i++)
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5;
} else {
scale = (float) (r_refdef.aliasvrectright - pfv1->v[0]) /
(pfv0->v[0] - pfv1->v[0]);
for (i = 0; i < 6; i++)
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5;
}
}
void
sw32_R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
int i;
if (pfv0->v[1] >= pfv1->v[1]) {
scale = (float) (r_refdef.aliasvrect.y - pfv0->v[1]) /
(pfv1->v[1] - pfv0->v[1]);
for (i = 0; i < 6; i++)
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5;
} else {
scale = (float) (r_refdef.aliasvrect.y - pfv1->v[1]) /
(pfv0->v[1] - pfv1->v[1]);
for (i = 0; i < 6; i++)
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5;
}
}
void
sw32_R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
int i;
if (pfv0->v[1] >= pfv1->v[1]) {
scale = (float) (r_refdef.aliasvrectbottom - pfv0->v[1]) /
(pfv1->v[1] - pfv0->v[1]);
for (i = 0; i < 6; i++)
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5;
} else {
scale = (float) (r_refdef.aliasvrectbottom - pfv1->v[1]) /
(pfv0->v[1] - pfv1->v[1]);
for (i = 0; i < 6; i++)
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5;
}
}
static int
R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
void (*clip) (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out))
{
int i, j, k;
int flags, oldflags;
j = count - 1;
k = 0;
for (i = 0; i < count; j = i, i++) {
oldflags = in[j].flags & flag;
flags = in[i].flags & flag;
if (flags && oldflags)
continue;
if (oldflags ^ flags) {
clip (&in[j], &in[i], &out[k]);
out[k].flags = 0;
if (out[k].v[0] < r_refdef.aliasvrect.x)
out[k].flags |= ALIAS_LEFT_CLIP;
if (out[k].v[1] < r_refdef.aliasvrect.y)
out[k].flags |= ALIAS_TOP_CLIP;
if (out[k].v[0] > r_refdef.aliasvrectright)
out[k].flags |= ALIAS_RIGHT_CLIP;
if (out[k].v[1] > r_refdef.aliasvrectbottom)
out[k].flags |= ALIAS_BOTTOM_CLIP;
k++;
}
if (!flags) {
out[k] = in[i];
k++;
}
}
return k;
}
void
sw32_R_AliasClipTriangle (mtriangle_t *ptri)
{
int i, k, pingpong;
mtriangle_t mtri;
unsigned int clipflags;
// copy vertexes and fix seam texture coordinates
if (ptri->facesfront) {
fv[0][0] = pfinalverts[ptri->vertindex[0]];
fv[0][1] = pfinalverts[ptri->vertindex[1]];
fv[0][2] = pfinalverts[ptri->vertindex[2]];
} else {
for (i = 0; i < 3; i++) {
fv[0][i] = pfinalverts[ptri->vertindex[i]];
if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM))
fv[0][i].v[2] += sw32_r_affinetridesc.seamfixupX16;
}
}
// clip
clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
if (clipflags & ALIAS_Z_CLIP) {
for (i = 0; i < 3; i++)
av[i] = sw32_pauxverts[ptri->vertindex[i]];
k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
if (k == 0)
return;
pingpong = 1;
clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
} else {
pingpong = 0;
k = 3;
}
if (clipflags & ALIAS_LEFT_CLIP) {
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_LEFT_CLIP, k, sw32_R_Alias_clip_left);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_RIGHT_CLIP) {
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_RIGHT_CLIP, k, sw32_R_Alias_clip_right);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_BOTTOM_CLIP) {
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_BOTTOM_CLIP, k, sw32_R_Alias_clip_bottom);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_TOP_CLIP) {
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_TOP_CLIP, k, sw32_R_Alias_clip_top);
if (k == 0)
return;
pingpong ^= 1;
}
for (i = 0; i < k; i++) {
if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
fv[pingpong][i].flags = 0;
}
// draw triangles
mtri.facesfront = ptri->facesfront;
sw32_r_affinetridesc.ptriangles = &mtri;
sw32_r_affinetridesc.pfinalverts = fv[pingpong];
// FIXME: do all at once as trifan?
mtri.vertindex[0] = 0;
for (i = 1; i < k - 1; i++) {
mtri.vertindex[1] = i;
mtri.vertindex[2] = i + 1;
sw32_D_PolysetDraw ();
}
}

View file

@ -1,681 +0,0 @@
/*
sw32_ralias.c
routines for setting up to draw alias models
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#define NH_DEFINE
#include "namehack.h"
#include "QF/image.h"
#include "QF/render.h"
#include "QF/skin.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "d_ifacea.h"
#include "r_internal.h"
#include "vid_sw.h"
#define LIGHT_MIN 5 // lowest light value we'll allow, to
// avoid the need for inner-loop light
// clamping
affinetridesc_t sw32_r_affinetridesc;
void *sw32_acolormap; // FIXME: should go away
trivertx_t *sw32_r_apverts;
// TODO: these probably will go away with optimized rasterization
static mdl_t *pmdl;
vec3_t sw32_r_plightvec;
int sw32_r_ambientlight;
float sw32_r_shadelight;
static aliashdr_t *paliashdr;
finalvert_t *sw32_pfinalverts;
auxvert_t *sw32_pauxverts;
float sw32_ziscale;
static model_t *pmodel;
static vec3_t alias_forward, alias_right, alias_up;
static maliasskindesc_t *pskindesc;
int sw32_r_amodels_drawn;
static int a_skinwidth;
static int r_anumverts;
float sw32_aliastransform[3][4];
typedef struct {
int index0;
int index1;
} aedge_t;
static aedge_t aedges[12] = {
{0, 1}, {1, 2}, {2, 3}, {3, 0},
{4, 5}, {5, 6}, {6, 7}, {7, 4},
{0, 5}, {1, 4}, {2, 7}, {3, 6}
};
qboolean
sw32_R_AliasCheckBBox (void)
{
int i, flags, frame, numv;
aliashdr_t *pahdr;
float zi, basepts[8][3], v0, v1, frac;
finalvert_t *pv0, *pv1, viewpts[16];
auxvert_t *pa0, *pa1, viewaux[16];
maliasframedesc_t *pframedesc;
qboolean zclipped, zfullyclipped;
unsigned int anyclip, allclip;
int minz;
// expand, rotate, and translate points into worldspace
currententity->visibility.trivial_accept = 0;
pmodel = currententity->renderer.model;
if (!(pahdr = pmodel->aliashdr))
pahdr = Cache_Get (&pmodel->cache);
pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model);
sw32_R_AliasSetUpTransform (0);
// construct the base bounding box for this frame
frame = currententity->animation.frame;
// TODO: don't repeat this check when drawing?
if ((frame >= pmdl->numframes) || (frame < 0)) {
Sys_MaskPrintf (SYS_dev, "No such frame %d %s\n", frame, pmodel->path);
frame = 0;
}
pframedesc = &pahdr->frames[frame];
// x worldspace coordinates
basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =
(float) pframedesc->bboxmin.v[0];
basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =
(float) pframedesc->bboxmax.v[0];
// y worldspace coordinates
basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =
(float) pframedesc->bboxmin.v[1];
basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =
(float) pframedesc->bboxmax.v[1];
// z worldspace coordinates
basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =
(float) pframedesc->bboxmin.v[2];
basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =
(float) pframedesc->bboxmax.v[2];
zclipped = false;
zfullyclipped = true;
minz = 9999;
for (i = 0; i < 8; i++) {
sw32_R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]);
if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) {
// we must clip points that are closer than the near clip plane
viewpts[i].flags = ALIAS_Z_CLIP;
zclipped = true;
} else {
if (viewaux[i].fv[2] < minz)
minz = viewaux[i].fv[2];
viewpts[i].flags = 0;
zfullyclipped = false;
}
}
if (zfullyclipped) {
if (!pmodel->aliashdr)
Cache_Release (&pmodel->cache);
return false; // everything was near-z-clipped
}
numv = 8;
if (zclipped) {
// organize points by edges, use edges to get new points (possible
// trivial reject)
for (i = 0; i < 12; i++) {
// edge endpoints
pv0 = &viewpts[aedges[i].index0];
pv1 = &viewpts[aedges[i].index1];
pa0 = &viewaux[aedges[i].index0];
pa1 = &viewaux[aedges[i].index1];
// if one end is clipped and the other isn't, make a new point
if (pv0->flags ^ pv1->flags) {
frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
(pa1->fv[2] - pa0->fv[2]);
viewaux[numv].fv[0] = pa0->fv[0] +
(pa1->fv[0] - pa0->fv[0]) * frac;
viewaux[numv].fv[1] = pa0->fv[1] +
(pa1->fv[1] - pa0->fv[1]) * frac;
viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
viewpts[numv].flags = 0;
numv++;
}
}
}
// project the vertices that remain after clipping
anyclip = 0;
allclip = ALIAS_XY_CLIP_MASK;
// TODO: probably should do this loop in ASM, especially if we use floats
for (i = 0; i < numv; i++) {
// we don't need to bother with vertices that were z-clipped
if (viewpts[i].flags & ALIAS_Z_CLIP)
continue;
zi = 1.0 / viewaux[i].fv[2];
// FIXME: do with chop mode in ASM, or convert to float
v0 = (viewaux[i].fv[0] * sw32_xscale * zi) + sw32_xcenter;
v1 = (viewaux[i].fv[1] * sw32_yscale * zi) + sw32_ycenter;
flags = 0;
if (v0 < r_refdef.fvrectx)
flags |= ALIAS_LEFT_CLIP;
if (v1 < r_refdef.fvrecty)
flags |= ALIAS_TOP_CLIP;
if (v0 > r_refdef.fvrectright)
flags |= ALIAS_RIGHT_CLIP;
if (v1 > r_refdef.fvrectbottom)
flags |= ALIAS_BOTTOM_CLIP;
anyclip |= flags;
allclip &= flags;
}
if (allclip) {
if (!pmodel->aliashdr)
Cache_Release (&pmodel->cache);
return false; // trivial reject off one side
}
currententity->visibility.trivial_accept = !anyclip & !zclipped;
if (currententity->visibility.trivial_accept) {
if (minz > (sw32_r_aliastransition + (pmdl->size * sw32_r_resfudge))) {
currententity->visibility.trivial_accept |= 2;
}
}
if (!pmodel->aliashdr)
Cache_Release (&pmodel->cache);
return true;
}
void
sw32_R_AliasTransformVector (vec3_t in, vec3_t out)
{
out[0] = DotProduct (in, sw32_aliastransform[0])
+ sw32_aliastransform[0][3];
out[1] = DotProduct (in, sw32_aliastransform[1])
+ sw32_aliastransform[1][3];
out[2] = DotProduct (in, sw32_aliastransform[2])
+ sw32_aliastransform[2][3];
}
void
sw32_R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av)
{
if (av->fv[2] < ALIAS_Z_CLIP_PLANE) {
fv->flags |= ALIAS_Z_CLIP;
return;
}
sw32_R_AliasProjectFinalVert (fv, av);
if (fv->v[0] < r_refdef.aliasvrect.x)
fv->flags |= ALIAS_LEFT_CLIP;
if (fv->v[1] < r_refdef.aliasvrect.y)
fv->flags |= ALIAS_TOP_CLIP;
if (fv->v[0] > r_refdef.aliasvrectright)
fv->flags |= ALIAS_RIGHT_CLIP;
if (fv->v[1] > r_refdef.aliasvrectbottom)
fv->flags |= ALIAS_BOTTOM_CLIP;
}
static void
R_AliasTransformFinalVert16 (auxvert_t *av, trivertx_t *pverts)
{
trivertx_t * pextra;
float vextra[3];
pextra = pverts + pmdl->numverts;
vextra[0] = pverts->v[0] + pextra->v[0] / (float)256;
vextra[1] = pverts->v[1] + pextra->v[1] / (float)256;
vextra[2] = pverts->v[2] + pextra->v[2] / (float)256;
av->fv[0] = DotProduct (vextra, sw32_aliastransform[0]) +
sw32_aliastransform[0][3];
av->fv[1] = DotProduct (vextra, sw32_aliastransform[1]) +
sw32_aliastransform[1][3];
av->fv[2] = DotProduct (vextra, sw32_aliastransform[2]) +
sw32_aliastransform[2][3];
}
static void
R_AliasTransformFinalVert8 (auxvert_t *av, trivertx_t *pverts)
{
av->fv[0] = DotProduct (pverts->v, sw32_aliastransform[0]) +
sw32_aliastransform[0][3];
av->fv[1] = DotProduct (pverts->v, sw32_aliastransform[1]) +
sw32_aliastransform[1][3];
av->fv[2] = DotProduct (pverts->v, sw32_aliastransform[2]) +
sw32_aliastransform[2][3];
}
/*
R_AliasPreparePoints
General clipped case
*/
static void
R_AliasPreparePoints (void)
{
int i;
stvert_t *pstverts;
finalvert_t *fv;
auxvert_t *av;
mtriangle_t *ptri;
finalvert_t *pfv[3];
pstverts = (stvert_t *) ((byte *) paliashdr + paliashdr->stverts);
r_anumverts = pmdl->numverts;
fv = pfinalverts;
av = sw32_pauxverts;
if (pmdl->ident == HEADER_MDL16) {
for (i = 0; i < r_anumverts; i++, fv++, av++, sw32_r_apverts++,
pstverts++) {
R_AliasTransformFinalVert16 (av, sw32_r_apverts);
sw32_R_AliasTransformFinalVert (fv, sw32_r_apverts, pstverts);
R_AliasClipAndProjectFinalVert (fv, av);
}
}
else {
for (i = 0; i < r_anumverts; i++, fv++, av++, sw32_r_apverts++,
pstverts++) {
R_AliasTransformFinalVert8 (av, sw32_r_apverts);
sw32_R_AliasTransformFinalVert (fv, sw32_r_apverts, pstverts);
R_AliasClipAndProjectFinalVert (fv, av);
}
}
// clip and draw all triangles
sw32_r_affinetridesc.numtriangles = 1;
ptri = (mtriangle_t *) ((byte *) paliashdr + paliashdr->triangles);
for (i = 0; i < pmdl->numtris; i++, ptri++) {
pfv[0] = &pfinalverts[ptri->vertindex[0]];
pfv[1] = &pfinalverts[ptri->vertindex[1]];
pfv[2] = &pfinalverts[ptri->vertindex[2]];
if (pfv[0]->flags & pfv[1]->flags & pfv[2]->
flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))
continue; // completely clipped
if (!((pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &
(ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))) { // totally unclipped
sw32_r_affinetridesc.pfinalverts = pfinalverts;
sw32_r_affinetridesc.ptriangles = ptri;
sw32_D_PolysetDraw ();
} else { // partially clipped
sw32_R_AliasClipTriangle (ptri);
}
}
}
void
sw32_R_AliasSetUpTransform (int trivial_accept)
{
int i;
float rotationmatrix[3][4], t2matrix[3][4];
static float tmatrix[3][4];
static float viewmatrix[3][4];
mat4f_t mat;
Transform_GetWorldMatrix (currententity->transform, mat);
VectorCopy (mat[0], alias_forward);
VectorNegate (mat[1], alias_right);
VectorCopy (mat[2], alias_up);
tmatrix[0][0] = pmdl->scale[0];
tmatrix[1][1] = pmdl->scale[1];
tmatrix[2][2] = pmdl->scale[2];
tmatrix[0][3] = pmdl->scale_origin[0];
tmatrix[1][3] = pmdl->scale_origin[1];
tmatrix[2][3] = pmdl->scale_origin[2];
// TODO: can do this with simple matrix rearrangement
for (i = 0; i < 3; i++) {
t2matrix[i][0] = alias_forward[i];
t2matrix[i][1] = -alias_right[i];
t2matrix[i][2] = alias_up[i];
}
t2matrix[0][3] = -modelorg[0];
t2matrix[1][3] = -modelorg[1];
t2matrix[2][3] = -modelorg[2];
// FIXME: can do more efficiently than full concatenation
R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
// TODO: should be global, set when vright, etc., set
VectorCopy (vright, viewmatrix[0]);
VectorCopy (vup, viewmatrix[1]);
VectorNegate (viewmatrix[1], viewmatrix[1]);
VectorCopy (vpn, viewmatrix[2]);
// viewmatrix[0][3] = 0;
// viewmatrix[1][3] = 0;
// viewmatrix[2][3] = 0;
R_ConcatTransforms (viewmatrix, rotationmatrix, sw32_aliastransform);
// do the scaling up of x and y to screen coordinates as part of the transform
// for the unclipped case (it would mess up clipping in the clipped case).
// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
// correspondingly so the projected x and y come out right
// FIXME: make this work for clipped case too?
if (trivial_accept) {
for (i = 0; i < 4; i++) {
sw32_aliastransform[0][i] *= sw32_aliasxscale *
(1.0 / ((float) 0x8000 * 0x10000));
sw32_aliastransform[1][i] *= sw32_aliasyscale *
(1.0 / ((float) 0x8000 * 0x10000));
sw32_aliastransform[2][i] *= 1.0 / ((float) 0x8000 * 0x10000);
}
}
}
/*
sw32_R_AliasTransformFinalVert
now this function just copies the texture coordinates and calculates lighting
actual 3D transform is done by R_AliasTransformFinalVert8/16 functions above
*/
void
sw32_R_AliasTransformFinalVert (finalvert_t *fv, trivertx_t *pverts,
stvert_t *pstverts)
{
int temp;
float lightcos, *plightnormal;
fv->v[2] = pstverts->s;
fv->v[3] = pstverts->t;
fv->flags = pstverts->onseam;
// lighting
// LordHavoc: flipped lightcos so it is + for bright, not -
plightnormal = r_avertexnormals[pverts->lightnormalindex];
lightcos = -DotProduct (plightnormal, sw32_r_plightvec);
temp = sw32_r_ambientlight;
if (lightcos > 0) {
temp += (int) (sw32_r_shadelight * lightcos);
// clamp; because we limited the minimum ambient and shading light,
// we don't have to clamp low light, just bright
if (temp < 0)
temp = 0;
}
fv->v[4] = temp;
}
void
sw32_R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts)
{
int i, temp;
float lightcos, *plightnormal, zi;
trivertx_t *pverts;
pverts = sw32_r_apverts;
for (i = 0; i < r_anumverts; i++, fv++, pverts++, pstverts++) {
// transform and project
zi = 1.0 / (DotProduct (pverts->v, sw32_aliastransform[2]) +
sw32_aliastransform[2][3]);
// x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
// scaled up by 1/2**31, and the scaling cancels out for x and y in
// the projection
fv->v[5] = zi;
fv->v[0] = ((DotProduct (pverts->v, sw32_aliastransform[0]) +
sw32_aliastransform[0][3]) * zi) + sw32_aliasxcenter;
fv->v[1] = ((DotProduct (pverts->v, sw32_aliastransform[1]) +
sw32_aliastransform[1][3]) * zi) + sw32_aliasycenter;
fv->v[2] = pstverts->s;
fv->v[3] = pstverts->t;
fv->flags = pstverts->onseam;
// lighting
// LordHavoc: flipped lightcos so it is + for bright, not -
plightnormal = r_avertexnormals[pverts->lightnormalindex];
lightcos = -DotProduct (plightnormal, sw32_r_plightvec);
temp = sw32_r_ambientlight;
if (lightcos > 0) {
temp += (int) (sw32_r_shadelight * lightcos);
// clamp; because we limited the minimum ambient and shading
// light, we don't have to clamp low light, just bright
if (temp < 0)
temp = 0;
}
fv->v[4] = temp;
}
}
void
sw32_R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av)
{
float zi;
// project points
zi = 1.0 / av->fv[2];
fv->v[5] = zi * sw32_ziscale;
fv->v[0] = (av->fv[0] * sw32_aliasxscale * zi) + sw32_aliasxcenter;
fv->v[1] = (av->fv[1] * sw32_aliasyscale * zi) + sw32_aliasycenter;
}
static void
R_AliasPrepareUnclippedPoints (void)
{
stvert_t *pstverts;
pstverts = (stvert_t *) ((byte *) paliashdr + paliashdr->stverts);
r_anumverts = pmdl->numverts;
sw32_R_AliasTransformAndProjectFinalVerts (pfinalverts, pstverts);
sw32_r_affinetridesc.pfinalverts = pfinalverts;
sw32_r_affinetridesc.ptriangles = (mtriangle_t *)
((byte *) paliashdr + paliashdr->triangles);
sw32_r_affinetridesc.numtriangles = pmdl->numtris;
sw32_D_PolysetDraw ();
}
static void
R_AliasSetupSkin (entity_t *ent)
{
int skinnum;
skinnum = ent->renderer.skinnum;
if ((skinnum >= pmdl->numskins) || (skinnum < 0)) {
Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n",
skinnum);
skinnum = 0;
}
pskindesc = R_AliasGetSkindesc (&ent->animation, skinnum, paliashdr);
a_skinwidth = pmdl->skinwidth;
sw32_r_affinetridesc.pskin = (void *) ((byte *) paliashdr + pskindesc->skin);
sw32_r_affinetridesc.skinwidth = a_skinwidth;
sw32_r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16;
sw32_r_affinetridesc.skinheight = pmdl->skinheight;
sw32_acolormap = vid.colormap8;
if (ent->renderer.skin) {
tex_t *base;
base = ent->renderer.skin->texels;
if (base) {
sw32_r_affinetridesc.pskin = base->data;
sw32_r_affinetridesc.skinwidth = base->width;
sw32_r_affinetridesc.skinheight = base->height;
}
sw32_acolormap = ent->renderer.skin->colormap;
}
}
static void
R_AliasSetupLighting (alight_t *plighting)
{
// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't
// have to clamp off the bottom
sw32_r_ambientlight = plighting->ambientlight;
if (sw32_r_ambientlight < LIGHT_MIN)
sw32_r_ambientlight = LIGHT_MIN;
sw32_r_ambientlight = (/*255 -*/ sw32_r_ambientlight) << VID_CBITS;
// if (sw32_r_ambientlight < LIGHT_MIN)
// sw32_r_ambientlight = LIGHT_MIN;
sw32_r_shadelight = plighting->shadelight;
if (sw32_r_shadelight < 0)
sw32_r_shadelight = 0;
sw32_r_shadelight *= VID_GRADES;
// rotate the lighting vector into the model's frame of reference
sw32_r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
sw32_r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
sw32_r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
}
/*
R_AliasSetupFrame
set sw32_r_apverts
*/
static void
R_AliasSetupFrame (entity_t *ent)
{
maliasframedesc_t *frame;
frame = R_AliasGetFramedesc (&ent->animation, paliashdr);
sw32_r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame);
}
void
sw32_R_AliasDrawModel (alight_t *plighting)
{
entity_t *ent = currententity;
int size;
finalvert_t *finalverts;
sw32_r_amodels_drawn++;
if (!(paliashdr = ent->renderer.model->aliashdr))
paliashdr = Cache_Get (&ent->renderer.model->cache);
pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model);
size = (CACHE_SIZE - 1)
+ sizeof (finalvert_t) * (pmdl->numverts + 1)
+ sizeof (auxvert_t) * pmdl->numverts;
finalverts = (finalvert_t *) Hunk_TempAlloc (0, size);
if (!finalverts)
Sys_Error ("R_AliasDrawModel: out of memory");
// cache align
pfinalverts = (finalvert_t *)
(((intptr_t) &finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
sw32_pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1];
R_AliasSetupSkin (ent);
sw32_R_AliasSetUpTransform (ent->visibility.trivial_accept);
R_AliasSetupLighting (plighting);
R_AliasSetupFrame (ent);
if (!sw32_acolormap)
sw32_acolormap = vid.colormap8;
if (sw32_acolormap == &vid.colormap8 && sw32_ctx->pixbytes != 1)
{
if (sw32_ctx->pixbytes == 2)
sw32_acolormap = vid.colormap16;
else if (sw32_ctx->pixbytes == 4)
sw32_acolormap = vid.colormap32;
else
Sys_Error("R_AliasDrawmodel: unsupported r_pixbytes %i",
sw32_ctx->pixbytes);
}
if (ent != vr_data.view_model)
sw32_ziscale = (float) 0x8000 *(float) 0x10000;
else
sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0;
if (ent->visibility.trivial_accept) {
R_AliasPrepareUnclippedPoints ();
} else {
R_AliasPreparePoints ();
}
if (!ent->renderer.model->aliashdr) {
Cache_Release (&ent->renderer.model->cache);
}
}

View file

@ -1,536 +0,0 @@
/*
sw32_r_bsp.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include <math.h>
#include <stdlib.h>
#include "qfalloca.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "r_internal.h"
// current entity info
qboolean sw32_insubmodel;
vec3_t sw32_r_worldmodelorg;
static float entity_rotation[3][3];
int sw32_r_currentbkey;
typedef enum { touchessolid, drawnode, nodrawnode } solidstate_t;
#define MAX_BMODEL_VERTS 500 // 6K
#define MAX_BMODEL_EDGES 1000 // 12K
static mvertex_t *pbverts;
static bedge_t *pbedges;
static int numbverts, numbedges;
int sw32_numbtofpolys;
static btofpoly_t *pbtofpolys;
static mvertex_t *pfrontenter, *pfrontexit;
static qboolean makeclippededge;
static void
R_EntityRotate (vec3_t vec)
{
vec3_t tvec;
VectorCopy (vec, tvec);
vec[0] = DotProduct (entity_rotation[0], tvec);
vec[1] = DotProduct (entity_rotation[1], tvec);
vec[2] = DotProduct (entity_rotation[2], tvec);
}
void
sw32_R_RotateBmodel (void)
{
mat4f_t mat;
Transform_GetWorldMatrix (currententity->transform, mat);
VectorCopy (mat[0], entity_rotation[0]);
VectorCopy (mat[1], entity_rotation[1]);
VectorCopy (mat[2], entity_rotation[2]);
// rotate modelorg and the transformation matrix
R_EntityRotate (modelorg);
R_EntityRotate (vpn);
R_EntityRotate (vright);
R_EntityRotate (vup);
sw32_R_TransformFrustum ();
}
static void
R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
{
bedge_t *psideedges[2], *pnextedge, *ptedge;
int i, side, lastside;
float dist, frac, lastdist;
plane_t *splitplane, tplane;
mvertex_t *pvert, *plastvert, *ptvert;
mnode_t *pn;
psideedges[0] = psideedges[1] = NULL;
makeclippededge = false;
// transform the BSP plane into model space
// FIXME: cache these?
splitplane = pnode->plane;
tplane.dist = splitplane->dist -
DotProduct (r_entorigin, splitplane->normal);
tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
// clip edges to BSP plane
for (; pedges; pedges = pnextedge) {
pnextedge = pedges->pnext;
// set the status for the last point as the previous point
// FIXME: cache this stuff somehow?
plastvert = pedges->v[0];
lastdist = DotProduct (plastvert->position, tplane.normal) -
tplane.dist;
if (lastdist > 0)
lastside = 0;
else
lastside = 1;
pvert = pedges->v[1];
dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
if (dist > 0)
side = 0;
else
side = 1;
if (side != lastside) {
// clipped
if (numbverts >= MAX_BMODEL_VERTS)
return;
// generate the clipped vertex
frac = lastdist / (lastdist - dist);
ptvert = &pbverts[numbverts++];
ptvert->position[0] = plastvert->position[0] +
frac * (pvert->position[0] - plastvert->position[0]);
ptvert->position[1] = plastvert->position[1] +
frac * (pvert->position[1] - plastvert->position[1]);
ptvert->position[2] = plastvert->position[2] +
frac * (pvert->position[2] - plastvert->position[2]);
// split into two edges, one on each side, and remember entering
// and exiting points
// FIXME: share the clip edge by having a winding direction flag?
if (numbedges >= (MAX_BMODEL_EDGES - 1)) {
Sys_Printf ("Out of edges for bmodel\n");
return;
}
ptedge = &pbedges[numbedges];
ptedge->pnext = psideedges[lastside];
psideedges[lastside] = ptedge;
ptedge->v[0] = plastvert;
ptedge->v[1] = ptvert;
ptedge = &pbedges[numbedges + 1];
ptedge->pnext = psideedges[side];
psideedges[side] = ptedge;
ptedge->v[0] = ptvert;
ptedge->v[1] = pvert;
numbedges += 2;
if (side == 0) {
// entering for front, exiting for back
pfrontenter = ptvert;
makeclippededge = true;
} else {
pfrontexit = ptvert;
makeclippededge = true;
}
} else {
// add the edge to the appropriate side
pedges->pnext = psideedges[side];
psideedges[side] = pedges;
}
}
// if anything was clipped, reconstitute and add the edges along the clip
// plane to both sides (but in opposite directions)
if (makeclippededge) {
if (numbedges >= (MAX_BMODEL_EDGES - 2)) {
Sys_Printf ("Out of edges for bmodel\n");
return;
}
ptedge = &pbedges[numbedges];
ptedge->pnext = psideedges[0];
psideedges[0] = ptedge;
ptedge->v[0] = pfrontexit;
ptedge->v[1] = pfrontenter;
ptedge = &pbedges[numbedges + 1];
ptedge->pnext = psideedges[1];
psideedges[1] = ptedge;
ptedge->v[0] = pfrontenter;
ptedge->v[1] = pfrontexit;
numbedges += 2;
}
// draw or recurse further
for (i = 0; i < 2; i++) {
if (psideedges[i]) {
// draw if we've reached a non-solid leaf, done if all that's left
// is a solid leaf, and continue down the tree if it's not a leaf
pn = pnode->children[i];
// we're done with this branch if the node or leaf isn't in the PVS
if (pn->visframe == r_visframecount) {
if (pn->contents < 0) {
if (pn->contents != CONTENTS_SOLID) {
sw32_r_currentbkey = ((mleaf_t *) pn)->key;
sw32_R_RenderBmodelFace (psideedges[i], psurf);
}
} else {
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
psurf);
}
}
}
}
}
void
sw32_R_DrawSolidClippedSubmodelPolygons (model_t *model)
{
int i, j, lindex;
vec_t dot;
msurface_t *psurf;
int numsurfaces;
plane_t *pplane;
mvertex_t bverts[MAX_BMODEL_VERTS];
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
medge_t *pedge, *pedges;
mod_brush_t *brush = &model->brush;
// FIXME: use bounding-box-based frustum clipping info?
psurf = &brush->surfaces[brush->firstmodelsurface];
numsurfaces = brush->nummodelsurfaces;
pedges = brush->edges;
for (i = 0; i < numsurfaces; i++, psurf++) {
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
// FIXME: use bounding-box-based frustum clipping info?
// copy the edges to bedges, flipping if necessary so always
// clockwise winding
// FIXME: if edges and vertices get caches, these assignments must
// move outside the loop, and overflow checking must be done here
pbverts = bverts;
pbedges = bedges;
numbverts = numbedges = 0;
if (psurf->numedges > 0) {
pbedge = &bedges[numbedges];
numbedges += psurf->numedges;
for (j = 0; j < psurf->numedges; j++) {
lindex = brush->surfedges[psurf->firstedge + j];
if (lindex > 0) {
pedge = &pedges[lindex];
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
} else {
lindex = -lindex;
pedge = &pedges[lindex];
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
}
pbedge[j].pnext = &pbedge[j + 1];
}
pbedge[j - 1].pnext = NULL; // mark end of edges
R_RecursiveClipBPoly (pbedge,
currententity->visibility.topnode,
psurf);
} else {
Sys_Error ("no edges in bmodel");
}
}
}
}
void
sw32_R_DrawSubmodelPolygons (model_t *model, int clipflags)
{
int i;
vec_t dot;
msurface_t *psurf;
int numsurfaces;
plane_t *pplane;
mod_brush_t *brush = &model->brush;
// FIXME: use bounding-box-based frustum clipping info?
psurf = &brush->surfaces[brush->firstmodelsurface];
numsurfaces = brush->nummodelsurfaces;
for (i = 0; i < numsurfaces; i++, psurf++) {
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
sw32_r_currentkey
= ((mleaf_t *) currententity->visibility.topnode)->key;
// FIXME: use bounding-box-based frustum clipping info?
sw32_R_RenderFace (psurf, clipflags);
}
}
}
static inline void
visit_leaf (mleaf_t *leaf)
{
// deal with model fragments in this leaf
if (leaf->efrags)
R_StoreEfrags (leaf->efrags);
leaf->key = sw32_r_currentkey;
sw32_r_currentkey++; // all bmodels in a leaf share the same key
}
static inline int
get_side (mnode_t *node)
{
// find which side of the node we are on
plane_t *plane = node->plane;
if (plane->type < 3)
return (modelorg[plane->type] - plane->dist) < 0;
return (DotProduct (modelorg, plane->normal) - plane->dist) < 0;
}
static void
visit_node (mod_brush_t *brush, mnode_t *node, int side, int clipflags)
{
int c;
msurface_t *surf;
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
side = (~side + 1) & SURF_PLANEBACK;
// draw stuff
if ((c = node->numsurfaces)) {
surf = brush->surfaces + node->firstsurface;
for (; c; c--, surf++) {
if (surf->visframe != r_visframecount)
continue;
// side is either 0 or SURF_PLANEBACK
if (side ^ (surf->flags & SURF_PLANEBACK))
continue; // wrong side
if (sw32_r_drawpolys) {
if (sw32_r_worldpolysbacktofront) {
if (sw32_numbtofpolys < MAX_BTOFPOLYS) {
pbtofpolys[sw32_numbtofpolys].clipflags = clipflags;
pbtofpolys[sw32_numbtofpolys].psurf = surf;
sw32_numbtofpolys++;
}
} else {
sw32_R_RenderPoly (surf, clipflags);
}
} else {
sw32_R_RenderFace (surf, clipflags);
}
}
// all surfaces on the same node share the same sequence number
sw32_r_currentkey++;
}
}
static inline int
test_node (mnode_t *node, int *clipflags)
{
int i, *pindex;
vec3_t acceptpt, rejectpt;
double d;
if (node->contents < 0)
return 0;
if (node->visframe != r_visframecount)
return 0;
// cull the clipping planes if not trivial accept
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
// twice as fast in ASM
if (*clipflags) {
for (i = 0; i < 4; i++) {
if (!(*clipflags & (1 << i)))
continue; // don't need to clip against it
// generate accept and reject points
// FIXME: do with fast look-ups or integer tests based on the
// sign bit of the floating point values
pindex = sw32_pfrustum_indexes[i];
rejectpt[0] = (float) node->minmaxs[pindex[0]];
rejectpt[1] = (float) node->minmaxs[pindex[1]];
rejectpt[2] = (float) node->minmaxs[pindex[2]];
d = DotProduct (rejectpt, sw32_view_clipplanes[i].normal);
d -= sw32_view_clipplanes[i].dist;
if (d <= 0)
return 0;
acceptpt[0] = (float) node->minmaxs[pindex[3 + 0]];
acceptpt[1] = (float) node->minmaxs[pindex[3 + 1]];
acceptpt[2] = (float) node->minmaxs[pindex[3 + 2]];
d = DotProduct (acceptpt, sw32_view_clipplanes[i].normal);
d -= sw32_view_clipplanes[i].dist;
if (d >= 0)
*clipflags &= ~(1 << i); // node is entirely on screen
}
}
return 1;
}
static void
R_VisitWorldNodes (mod_brush_t *brush, int clipflags)
{
typedef struct {
mnode_t *node;
int side, clipflags;
} rstack_t;
rstack_t *node_ptr;
rstack_t *node_stack;
mnode_t *node;
mnode_t *front;
int side, cf;
node = brush->nodes;
// +2 for paranoia
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack;
cf = clipflags;
while (1) {
while (test_node (node, &cf)) {
cf = clipflags;
side = get_side (node);
front = node->children[side];
if (test_node (front, &cf)) {
node_ptr->node = node;
node_ptr->side = side;
node_ptr->clipflags = clipflags;
node_ptr++;
clipflags = cf;
node = front;
continue;
}
if (front->contents < 0 && front->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) front);
visit_node (brush, node, side, clipflags);
node = node->children[!side];
}
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
if (node_ptr != node_stack) {
node_ptr--;
node = node_ptr->node;
side = node_ptr->side;
clipflags = node_ptr->clipflags;
visit_node (brush, node, side, clipflags);
node = node->children[!side];
continue;
}
break;
}
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
}
void
sw32_R_RenderWorld (void)
{
int i;
btofpoly_t btofpolys[MAX_BTOFPOLYS];
mod_brush_t *brush;
pbtofpolys = btofpolys;
currententity = &r_worldentity;
VectorCopy (r_origin, modelorg);
brush = &currententity->renderer.model->brush;
r_pcurrentvertbase = brush->vertexes;
R_VisitWorldNodes (brush, 15);
// if the driver wants the polygons back to front, play the visible ones
// back in that order
if (sw32_r_worldpolysbacktofront) {
for (i = sw32_numbtofpolys - 1; i >= 0; i--) {
sw32_R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags);
}
}
}

View file

@ -1,804 +0,0 @@
/*
sw32_r_draw.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/render.h"
#include "compat.h"
#include "r_internal.h"
#define MAXLEFTCLIPEDGES 100
// !!! if these are changed, they must be changed in asm_draw.h too !!!
#define FULLY_CLIPPED_CACHED 0x80000000
#define FRAMECOUNT_MASK 0x7FFFFFFF
static unsigned int cacheoffset;
int sw32_c_faceclip; // number of faces clipped
zpointdesc_t sw32_r_zpointdesc;
static polydesc_t r_polydesc;
clipplane_t sw32_view_clipplanes[4];
medge_t *sw32_r_pedge;
qboolean sw32_r_leftclipped, sw32_r_rightclipped;
static qboolean makeleftedge, makerightedge;
qboolean sw32_r_nearzionly;
int sw32_sintable[SIN_BUFFER_SIZE];
int sw32_intsintable[SIN_BUFFER_SIZE];
mvertex_t sw32_r_leftenter, sw32_r_leftexit;
mvertex_t sw32_r_rightenter, sw32_r_rightexit;
typedef struct {
float u, v;
int ceilv;
} evert_t;
int sw32_r_emitted;
float sw32_r_nearzi;
float sw32_r_u1, sw32_r_v1, sw32_r_lzi1;
int sw32_r_ceilv1;
qboolean sw32_r_lastvertvalid;
void
sw32_R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
{
edge_t *edge, *pcheck;
int u_check;
float u, u_step;
vec3_t local, transformed;
float *world;
int v, v2, ceilv0;
float scale, lzi0, u0, v0;
int side;
if (sw32_r_lastvertvalid) {
u0 = sw32_r_u1;
v0 = sw32_r_v1;
lzi0 = sw32_r_lzi1;
ceilv0 = sw32_r_ceilv1;
} else {
world = &pv0->position[0];
// transform and project
VectorSubtract (world, modelorg, local);
sw32_TransformVector (local, transformed);
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
lzi0 = 1.0 / transformed[2];
// FIXME: build x/sw32_yscale into transform?
scale = sw32_xscale * lzi0;
u0 = (sw32_xcenter + scale * transformed[0]);
if (u0 < r_refdef.fvrectx_adj)
u0 = r_refdef.fvrectx_adj;
if (u0 > r_refdef.fvrectright_adj)
u0 = r_refdef.fvrectright_adj;
scale = sw32_yscale * lzi0;
v0 = (sw32_ycenter - scale * transformed[1]);
if (v0 < r_refdef.fvrecty_adj)
v0 = r_refdef.fvrecty_adj;
if (v0 > r_refdef.fvrectbottom_adj)
v0 = r_refdef.fvrectbottom_adj;
ceilv0 = (int) ceil (v0);
}
world = &pv1->position[0];
// transform and project
VectorSubtract (world, modelorg, local);
sw32_TransformVector (local, transformed);
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
sw32_r_lzi1 = 1.0 / transformed[2];
scale = sw32_xscale * sw32_r_lzi1;
sw32_r_u1 = (sw32_xcenter + scale * transformed[0]);
if (sw32_r_u1 < r_refdef.fvrectx_adj)
sw32_r_u1 = r_refdef.fvrectx_adj;
if (sw32_r_u1 > r_refdef.fvrectright_adj)
sw32_r_u1 = r_refdef.fvrectright_adj;
scale = sw32_yscale * sw32_r_lzi1;
sw32_r_v1 = (sw32_ycenter - scale * transformed[1]);
if (sw32_r_v1 < r_refdef.fvrecty_adj)
sw32_r_v1 = r_refdef.fvrecty_adj;
if (sw32_r_v1 > r_refdef.fvrectbottom_adj)
sw32_r_v1 = r_refdef.fvrectbottom_adj;
if (sw32_r_lzi1 > lzi0)
lzi0 = sw32_r_lzi1;
if (lzi0 > sw32_r_nearzi) // for mipmap finding
sw32_r_nearzi = lzi0;
// for right edges, all we want is the effect on 1/z
if (sw32_r_nearzionly)
return;
sw32_r_emitted = 1;
sw32_r_ceilv1 = (int) ceil (sw32_r_v1);
// create the edge
if (ceilv0 == sw32_r_ceilv1) {
// we cache unclipped horizontal edges as fully clipped
if (cacheoffset != 0x7FFFFFFF) {
cacheoffset = FULLY_CLIPPED_CACHED |
(r_framecount & FRAMECOUNT_MASK);
}
return; // horizontal edge
}
side = ceilv0 > sw32_r_ceilv1;
edge = sw32_edge_p++;
edge->owner = sw32_r_pedge;
edge->nearzi = lzi0;
if (side == 0) {
// trailing edge (go from p1 to p2)
v = ceilv0;
v2 = sw32_r_ceilv1 - 1;
edge->surfs[0] = sw32_surface_p - sw32_surfaces;
edge->surfs[1] = 0;
u_step = ((sw32_r_u1 - u0) / (sw32_r_v1 - v0));
u = u0 + ((float) v - v0) * u_step;
} else {
// leading edge (go from p2 to p1)
v2 = ceilv0 - 1;
v = sw32_r_ceilv1;
edge->surfs[0] = 0;
edge->surfs[1] = sw32_surface_p - sw32_surfaces;
u_step = ((u0 - sw32_r_u1) / (v0 - sw32_r_v1));
u = sw32_r_u1 + ((float) v - sw32_r_v1) * u_step;
}
edge->u_step = u_step * 0x100000;
edge->u = u * 0x100000 + 0xFFFFF;
// we need to do this to avoid stepping off the edges if a very nearly
// horizontal edge is less than epsilon above a scan, and numeric error
// causes it to incorrectly extend to the scan, and the extension of the
// line goes off the edge of the screen
// FIXME: is this actually needed?
if (edge->u < r_refdef.vrect_x_adj_shift20)
edge->u = r_refdef.vrect_x_adj_shift20;
if (edge->u > r_refdef.vrectright_adj_shift20)
edge->u = r_refdef.vrectright_adj_shift20;
// sort the edge in normally
u_check = edge->u;
if (edge->surfs[0])
u_check++; // sort trailers after leaders
if (!sw32_newedges[v] || sw32_newedges[v]->u >= u_check) {
edge->next = sw32_newedges[v];
sw32_newedges[v] = edge;
} else {
pcheck = sw32_newedges[v];
while (pcheck->next && pcheck->next->u < u_check)
pcheck = pcheck->next;
edge->next = pcheck->next;
pcheck->next = edge;
}
edge->nextremove = sw32_removeedges[v2];
sw32_removeedges[v2] = edge;
}
void
sw32_R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
{
float d0, d1, f;
mvertex_t clipvert;
if (clip) {
do {
d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
if (d0 >= 0) {
// point 0 is unclipped
if (d1 >= 0) {
// both points are unclipped
continue;
}
// only point 1 is clipped
// we don't cache clipped edges
cacheoffset = 0x7FFFFFFF;
f = d0 / (d0 - d1);
clipvert.position[0] = pv0->position[0] +
f * (pv1->position[0] - pv0->position[0]);
clipvert.position[1] = pv0->position[1] +
f * (pv1->position[1] - pv0->position[1]);
clipvert.position[2] = pv0->position[2] +
f * (pv1->position[2] - pv0->position[2]);
if (clip->leftedge) {
sw32_r_leftclipped = true;
sw32_r_leftexit = clipvert;
} else if (clip->rightedge) {
sw32_r_rightclipped = true;
sw32_r_rightexit = clipvert;
}
sw32_R_ClipEdge (pv0, &clipvert, clip->next);
return;
} else {
// point 0 is clipped
if (d1 < 0) {
// both points are clipped
// we do cache fully clipped edges
if (!sw32_r_leftclipped)
cacheoffset = FULLY_CLIPPED_CACHED |
(r_framecount & FRAMECOUNT_MASK);
return;
}
// only point 0 is clipped
sw32_r_lastvertvalid = false;
// we don't cache partially clipped edges
cacheoffset = 0x7FFFFFFF;
f = d0 / (d0 - d1);
clipvert.position[0] = pv0->position[0] +
f * (pv1->position[0] - pv0->position[0]);
clipvert.position[1] = pv0->position[1] +
f * (pv1->position[1] - pv0->position[1]);
clipvert.position[2] = pv0->position[2] +
f * (pv1->position[2] - pv0->position[2]);
if (clip->leftedge) {
sw32_r_leftclipped = true;
sw32_r_leftenter = clipvert;
} else if (clip->rightedge) {
sw32_r_rightclipped = true;
sw32_r_rightenter = clipvert;
}
sw32_R_ClipEdge (&clipvert, pv1, clip->next);
return;
}
} while ((clip = clip->next) != NULL);
}
// add the edge
sw32_R_EmitEdge (pv0, pv1);
}
static void
R_EmitCachedEdge (void)
{
edge_t *pedge_t;
pedge_t = (edge_t *) ((intptr_t) sw32_r_edges + sw32_r_pedge->cachededgeoffset);
if (!pedge_t->surfs[0])
pedge_t->surfs[0] = sw32_surface_p - sw32_surfaces;
else
pedge_t->surfs[1] = sw32_surface_p - sw32_surfaces;
if (pedge_t->nearzi > sw32_r_nearzi) // for mipmap finding
sw32_r_nearzi = pedge_t->nearzi;
sw32_r_emitted = 1;
}
void
sw32_R_RenderFace (msurface_t *fa, int clipflags)
{
int i, lindex;
unsigned int mask;
plane_t *pplane;
float distinv;
vec3_t p_normal;
medge_t *pedges, tedge;
clipplane_t *pclip;
mod_brush_t *brush = &currententity->renderer.model->brush;
// skip out if no more surfs
if ((sw32_surface_p) >= sw32_surf_max) {
sw32_r_outofsurfaces++;
return;
}
// ditto if not enough edges left, or switch to auxedges if possible
if ((sw32_edge_p + fa->numedges + 4) >= sw32_edge_max) {
sw32_r_outofedges += fa->numedges;
return;
}
sw32_c_faceclip++;
// set up clip planes
pclip = NULL;
for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) {
if (clipflags & mask) {
sw32_view_clipplanes[i].next = pclip;
pclip = &sw32_view_clipplanes[i];
}
}
// push the edges through
sw32_r_emitted = 0;
sw32_r_nearzi = 0;
sw32_r_nearzionly = false;
makeleftedge = makerightedge = false;
pedges = brush->edges;
sw32_r_lastvertvalid = false;
for (i = 0; i < fa->numedges; i++) {
lindex = brush->surfedges[fa->firstedge + i];
if (lindex > 0) {
sw32_r_pedge = &pedges[lindex];
// if the edge is cached, we can just reuse the edge
if (!insubmodel) {
if (sw32_r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) {
if ((sw32_r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
(unsigned int) r_framecount) {
sw32_r_lastvertvalid = false;
continue;
}
} else {
if ((((uintptr_t) sw32_edge_p - (uintptr_t) sw32_r_edges) >
sw32_r_pedge->cachededgeoffset) &&
(((edge_t *) ((intptr_t) sw32_r_edges +
sw32_r_pedge->cachededgeoffset))->owner ==
sw32_r_pedge)) {
R_EmitCachedEdge ();
sw32_r_lastvertvalid = false;
continue;
}
}
}
// assume it's cacheable
cacheoffset = (byte *) sw32_edge_p - (byte *) sw32_r_edges;
sw32_r_leftclipped = sw32_r_rightclipped = false;
sw32_R_ClipEdge (&r_pcurrentvertbase[sw32_r_pedge->v[0]],
&r_pcurrentvertbase[sw32_r_pedge->v[1]], pclip);
sw32_r_pedge->cachededgeoffset = cacheoffset;
if (sw32_r_leftclipped)
makeleftedge = true;
if (sw32_r_rightclipped)
makerightedge = true;
sw32_r_lastvertvalid = true;
} else {
lindex = -lindex;
sw32_r_pedge = &pedges[lindex];
// if the edge is cached, we can just reuse the edge
if (!insubmodel) {
if (sw32_r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) {
if ((sw32_r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
(unsigned int) r_framecount) {
sw32_r_lastvertvalid = false;
continue;
}
} else {
// it's cached if the cached edge is valid and is owned
// by this medge_t
if ((((uintptr_t) sw32_edge_p - (uintptr_t) sw32_r_edges) >
sw32_r_pedge->cachededgeoffset) &&
(((edge_t *) ((intptr_t) sw32_r_edges +
sw32_r_pedge->cachededgeoffset))->owner ==
sw32_r_pedge)) {
R_EmitCachedEdge ();
sw32_r_lastvertvalid = false;
continue;
}
}
}
// assume it's cacheable
cacheoffset = (byte *) sw32_edge_p - (byte *) sw32_r_edges;
sw32_r_leftclipped = sw32_r_rightclipped = false;
sw32_R_ClipEdge (&r_pcurrentvertbase[sw32_r_pedge->v[1]],
&r_pcurrentvertbase[sw32_r_pedge->v[0]], pclip);
sw32_r_pedge->cachededgeoffset = cacheoffset;
if (sw32_r_leftclipped)
makeleftedge = true;
if (sw32_r_rightclipped)
makerightedge = true;
sw32_r_lastvertvalid = true;
}
}
// if there was a clip off the left edge, add that edge too
// FIXME: faster to do in screen space?
// FIXME: share clipped edges?
if (makeleftedge) {
sw32_r_pedge = &tedge;
sw32_r_lastvertvalid = false;
sw32_R_ClipEdge (&sw32_r_leftexit, &sw32_r_leftenter, pclip->next);
}
// if there was a clip off the right edge, get the right sw32_r_nearzi
if (makerightedge) {
sw32_r_pedge = &tedge;
sw32_r_lastvertvalid = false;
sw32_r_nearzionly = true;
sw32_R_ClipEdge (&sw32_r_rightexit, &sw32_r_rightenter, sw32_view_clipplanes[1].next);
}
// if no edges made it out, return without posting the surface
if (!sw32_r_emitted)
return;
sw32_r_polycount++;
sw32_surface_p->data = (void *) fa;
sw32_surface_p->nearzi = sw32_r_nearzi;
sw32_surface_p->flags = fa->flags;
sw32_surface_p->insubmodel = insubmodel;
sw32_surface_p->spanstate = 0;
sw32_surface_p->entity = currententity;
sw32_surface_p->key = sw32_r_currentkey++;
sw32_surface_p->spans = NULL;
pplane = fa->plane;
// FIXME: cache this?
sw32_TransformVector (pplane->normal, p_normal);
// FIXME: cache this?
distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
distinv = min (distinv, 1.0);
sw32_surface_p->d_zistepu = p_normal[0] * sw32_xscaleinv * distinv;
sw32_surface_p->d_zistepv = -p_normal[1] * sw32_yscaleinv * distinv;
sw32_surface_p->d_ziorigin = p_normal[2] * distinv -
sw32_xcenter * sw32_surface_p->d_zistepu - sw32_ycenter * sw32_surface_p->d_zistepv;
//JDC VectorCopy (r_worldmodelorg, sw32_surface_p->modelorg);
sw32_surface_p++;
}
void
sw32_R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
{
int i;
unsigned int mask;
plane_t *pplane;
float distinv;
vec3_t p_normal;
medge_t tedge;
clipplane_t *pclip;
// skip out if no more surfs
if (sw32_surface_p >= sw32_surf_max) {
sw32_r_outofsurfaces++;
return;
}
// ditto if not enough edges left, or switch to auxedges if possible
if ((sw32_edge_p + psurf->numedges + 4) >= sw32_edge_max) {
sw32_r_outofedges += psurf->numedges;
return;
}
sw32_c_faceclip++;
// this is a dummy to give the caching mechanism someplace to write to
sw32_r_pedge = &tedge;
// set up clip planes
pclip = NULL;
for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) {
if (sw32_r_clipflags & mask) {
sw32_view_clipplanes[i].next = pclip;
pclip = &sw32_view_clipplanes[i];
}
}
// push the edges through
sw32_r_emitted = 0;
sw32_r_nearzi = 0;
sw32_r_nearzionly = false;
makeleftedge = makerightedge = false;
// FIXME: keep clipped bmodel edges in clockwise order so last vertex
// caching can be used?
sw32_r_lastvertvalid = false;
for (; pedges; pedges = pedges->pnext) {
sw32_r_leftclipped = sw32_r_rightclipped = false;
sw32_R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
if (sw32_r_leftclipped)
makeleftedge = true;
if (sw32_r_rightclipped)
makerightedge = true;
}
// if there was a clip off the left edge, add that edge too
// FIXME: faster to do in screen space?
// FIXME: share clipped edges?
if (makeleftedge) {
sw32_r_pedge = &tedge;
sw32_R_ClipEdge (&sw32_r_leftexit, &sw32_r_leftenter, pclip->next);
}
// if there was a clip off the right edge, get the right sw32_r_nearzi
if (makerightedge) {
sw32_r_pedge = &tedge;
sw32_r_nearzionly = true;
sw32_R_ClipEdge (&sw32_r_rightexit, &sw32_r_rightenter, sw32_view_clipplanes[1].next);
}
// if no edges made it out, return without posting the surface
if (!sw32_r_emitted)
return;
sw32_r_polycount++;
sw32_surface_p->data = (void *) psurf;
sw32_surface_p->nearzi = sw32_r_nearzi;
sw32_surface_p->flags = psurf->flags;
sw32_surface_p->insubmodel = true;
sw32_surface_p->spanstate = 0;
sw32_surface_p->entity = currententity;
sw32_surface_p->key = sw32_r_currentbkey;
sw32_surface_p->spans = NULL;
pplane = psurf->plane;
// FIXME: cache this?
sw32_TransformVector (pplane->normal, p_normal);
// FIXME: cache this?
distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
distinv = min (distinv, 1.0);
sw32_surface_p->d_zistepu = p_normal[0] * sw32_xscaleinv * distinv;
sw32_surface_p->d_zistepv = -p_normal[1] * sw32_yscaleinv * distinv;
sw32_surface_p->d_ziorigin = p_normal[2] * distinv -
sw32_xcenter * sw32_surface_p->d_zistepu - sw32_ycenter * sw32_surface_p->d_zistepv;
//JDC VectorCopy (r_worldmodelorg, sw32_surface_p->modelorg);
sw32_surface_p++;
}
void
sw32_R_RenderPoly (msurface_t *fa, int clipflags)
{
int i, lindex, lnumverts, s_axis, t_axis;
float dist, lastdist, lzi, scale, u, v, frac;
unsigned int mask;
vec3_t local, transformed;
clipplane_t *pclip;
medge_t *pedges;
plane_t *pplane;
mvertex_t verts[2][100]; // FIXME: do real number
polyvert_t pverts[100]; // FIXME: do real number, safely
int vertpage, newverts, newpage, lastvert;
qboolean visible;
mod_brush_t *brush = &currententity->renderer.model->brush;
// FIXME: clean this up and make it faster
// FIXME: guard against running out of vertices
s_axis = t_axis = 0; // keep compiler happy
// set up clip planes
pclip = NULL;
for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) {
if (clipflags & mask) {
sw32_view_clipplanes[i].next = pclip;
pclip = &sw32_view_clipplanes[i];
}
}
// reconstruct the polygon
// FIXME: these should be precalculated and loaded off disk
pedges = brush->edges;
lnumverts = fa->numedges;
vertpage = 0;
for (i = 0; i < lnumverts; i++) {
lindex = brush->surfedges[fa->firstedge + i];
if (lindex > 0) {
sw32_r_pedge = &pedges[lindex];
verts[0][i] = r_pcurrentvertbase[sw32_r_pedge->v[0]];
} else {
sw32_r_pedge = &pedges[-lindex];
verts[0][i] = r_pcurrentvertbase[sw32_r_pedge->v[1]];
}
}
// clip the polygon, done if not visible
while (pclip) {
lastvert = lnumverts - 1;
lastdist = DotProduct (verts[vertpage][lastvert].position,
pclip->normal) - pclip->dist;
visible = false;
newverts = 0;
newpage = vertpage ^ 1;
for (i = 0; i < lnumverts; i++) {
dist = DotProduct (verts[vertpage][i].position, pclip->normal) -
pclip->dist;
if ((lastdist > 0) != (dist > 0)) {
frac = dist / (dist - lastdist);
verts[newpage][newverts].position[0] =
verts[vertpage][i].position[0] +
((verts[vertpage][lastvert].position[0] -
verts[vertpage][i].position[0]) * frac);
verts[newpage][newverts].position[1] =
verts[vertpage][i].position[1] +
((verts[vertpage][lastvert].position[1] -
verts[vertpage][i].position[1]) * frac);
verts[newpage][newverts].position[2] =
verts[vertpage][i].position[2] +
((verts[vertpage][lastvert].position[2] -
verts[vertpage][i].position[2]) * frac);
newverts++;
}
if (dist >= 0) {
verts[newpage][newverts] = verts[vertpage][i];
newverts++;
visible = true;
}
lastvert = i;
lastdist = dist;
}
if (!visible || (newverts < 3))
return;
lnumverts = newverts;
vertpage ^= 1;
pclip = pclip->next;
}
// transform and project, remembering the z values at the vertices and
// sw32_r_nearzi, and extract the s and t coordinates at the vertices
pplane = fa->plane;
switch (pplane->type) {
case PLANE_X:
case PLANE_ANYX:
s_axis = 1;
t_axis = 2;
break;
case PLANE_Y:
case PLANE_ANYY:
s_axis = 0;
t_axis = 2;
break;
case PLANE_Z:
case PLANE_ANYZ:
s_axis = 0;
t_axis = 1;
break;
}
sw32_r_nearzi = 0;
for (i = 0; i < lnumverts; i++) {
// transform and project
VectorSubtract (verts[vertpage][i].position, modelorg, local);
sw32_TransformVector (local, transformed);
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
lzi = 1.0 / transformed[2];
if (lzi > sw32_r_nearzi) // for mipmap finding
sw32_r_nearzi = lzi;
// FIXME: build x/sw32_yscale into transform?
scale = sw32_xscale * lzi;
u = (sw32_xcenter + scale * transformed[0]);
if (u < r_refdef.fvrectx_adj)
u = r_refdef.fvrectx_adj;
if (u > r_refdef.fvrectright_adj)
u = r_refdef.fvrectright_adj;
scale = sw32_yscale * lzi;
v = (sw32_ycenter - scale * transformed[1]);
if (v < r_refdef.fvrecty_adj)
v = r_refdef.fvrecty_adj;
if (v > r_refdef.fvrectbottom_adj)
v = r_refdef.fvrectbottom_adj;
pverts[i].u = u;
pverts[i].v = v;
pverts[i].zi = lzi;
pverts[i].s = verts[vertpage][i].position[s_axis];
pverts[i].t = verts[vertpage][i].position[t_axis];
}
// build the polygon descriptor, including fa, sw32_r_nearzi, and u, v, s, t,
// and z for each vertex
r_polydesc.numverts = lnumverts;
r_polydesc.nearzi = sw32_r_nearzi;
r_polydesc.pcurrentface = fa;
r_polydesc.pverts = pverts;
// draw the polygon
sw32_D_DrawPoly ();
}
void
sw32_R_ZDrawSubmodelPolys (model_t *model)
{
int i, numsurfaces;
msurface_t *psurf;
float dot;
plane_t *pplane;
mod_brush_t *brush = &model->brush;
psurf = &brush->surfaces[brush->firstmodelsurface];
numsurfaces = brush->nummodelsurfaces;
for (i = 0; i < numsurfaces; i++, psurf++) {
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
// FIXME: use bounding-box-based frustum clipping info?
sw32_R_RenderPoly (psurf, 15);
}
}
}

View file

@ -1,544 +0,0 @@
/*
sw32_redge.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/render.h"
#include "QF/sound.h"
#include "d_ifacea.h"
#include "r_internal.h"
#include "vid_internal.h"
/*
FIXME
the complex cases add new polys on most lines, so dont optimize for
keeping them the same have multiple free span lists to try to get better
coherence ? low depth complexity-- 1 to 3 or so this breaks spans at every
edge, even hidden ones (bad)
have a sentinal at both ends?
*/
edge_t *sw32_auxedges;
edge_t *sw32_r_edges, *sw32_edge_p, *sw32_edge_max;
surf_t *sw32_surfaces, *sw32_surface_p, *sw32_surf_max;
/*
surfaces are generated in back to front order by the bsp, so if a surf
pointer is greater than another one, it should be drawn in front
sw32_surfaces[1] is the background, and is used as the active surface stack
*/
edge_t *sw32_newedges[MAXHEIGHT];
edge_t *sw32_removeedges[MAXHEIGHT];
static espan_t *span_p, *max_span_p;
int sw32_r_currentkey;
static int current_iv;
static int edge_head_u_shift20, edge_tail_u_shift20;
static void (*pdrawfunc) (void);
static edge_t edge_head;
static edge_t edge_tail;
static edge_t edge_aftertail;
static edge_t edge_sentinel;
static float fv;
static void
R_DrawCulledPolys (void)
{
surf_t *s;
msurface_t *pface;
currententity = &r_worldentity;
if (sw32_r_worldpolysbacktofront) {
for (s = sw32_surface_p - 1; s > &sw32_surfaces[1]; s--) {
if (!s->spans)
continue;
if (!(s->flags & SURF_DRAWBACKGROUND)) {
pface = (msurface_t *) s->data;
sw32_R_RenderPoly (pface, 15);
}
}
} else {
for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) {
if (!s->spans)
continue;
if (!(s->flags & SURF_DRAWBACKGROUND)) {
pface = (msurface_t *) s->data;
sw32_R_RenderPoly (pface, 15);
}
}
}
}
void
sw32_R_BeginEdgeFrame (void)
{
int v;
sw32_edge_p = sw32_r_edges;
sw32_edge_max = &sw32_r_edges[sw32_r_numallocatededges];
sw32_surface_p = &sw32_surfaces[2]; // background is surface 1,
// surface 0 is a dummy
sw32_surfaces[1].spans = NULL; // no background spans yet
sw32_surfaces[1].flags = SURF_DRAWBACKGROUND;
// put the background behind everything in the world
pdrawfunc = sw32_R_GenerateSpans;
sw32_surfaces[1].key = 0x7FFFFFFF;
sw32_r_currentkey = 0;
// FIXME: set with memset
for (v = r_refdef.vrect.y; v < r_refdef.vrectbottom; v++) {
sw32_newedges[v] = sw32_removeedges[v] = NULL;
}
}
/*
sw32_R_InsertNewEdges
Adds the edges in the linked list edgestoadd, adding them to the edges
in the linked list edgelist. edgestoadd is assumed to be sorted on u,
and non-empty (this is actually sw32_newedges[v]). edgelist is assumed to
be sorted on u, with a sentinel at the end (actually, this is the
active edge table starting at edge_head.next).
*/
void
sw32_R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
{
edge_t *next_edge;
do {
next_edge = edgestoadd->next;
edgesearch:
if (edgelist->u >= edgestoadd->u)
goto addedge;
edgelist = edgelist->next;
if (edgelist->u >= edgestoadd->u)
goto addedge;
edgelist = edgelist->next;
if (edgelist->u >= edgestoadd->u)
goto addedge;
edgelist = edgelist->next;
if (edgelist->u >= edgestoadd->u)
goto addedge;
edgelist = edgelist->next;
goto edgesearch;
// insert edgestoadd before edgelist
addedge:
edgestoadd->next = edgelist;
edgestoadd->prev = edgelist->prev;
edgelist->prev->next = edgestoadd;
edgelist->prev = edgestoadd;
} while ((edgestoadd = next_edge) != NULL);
}
void
sw32_R_RemoveEdges (edge_t *pedge)
{
do {
pedge->next->prev = pedge->prev;
pedge->prev->next = pedge->next;
} while ((pedge = pedge->nextremove) != NULL);
}
void
sw32_R_StepActiveU (edge_t *pedge)
{
edge_t *pnext_edge, *pwedge;
while (1) {
nextedge:
pedge->u += pedge->u_step;
if (pedge->u < pedge->prev->u)
goto pushback;
pedge = pedge->next;
pedge->u += pedge->u_step;
if (pedge->u < pedge->prev->u)
goto pushback;
pedge = pedge->next;
pedge->u += pedge->u_step;
if (pedge->u < pedge->prev->u)
goto pushback;
pedge = pedge->next;
pedge->u += pedge->u_step;
if (pedge->u < pedge->prev->u)
goto pushback;
pedge = pedge->next;
goto nextedge;
pushback:
if (pedge == &edge_aftertail)
return;
// push it back to keep it sorted
pnext_edge = pedge->next;
// pull the edge out of the edge list
pedge->next->prev = pedge->prev;
pedge->prev->next = pedge->next;
// find out where the edge goes in the edge list
pwedge = pedge->prev->prev;
while (pwedge->u > pedge->u) {
pwedge = pwedge->prev;
}
// put the edge back into the edge list
pedge->next = pwedge->next;
pedge->prev = pwedge;
pedge->next->prev = pedge;
pwedge->next = pedge;
pedge = pnext_edge;
if (pedge == &edge_tail)
return;
}
}
static void
R_CleanupSpan (void)
{
surf_t *surf;
int iu;
espan_t *span;
// now that we've reached the right edge of the screen, we're done with any
// unfinished surfaces, so emit a span for whatever's on top
surf = sw32_surfaces[1].next;
iu = edge_tail_u_shift20;
if (iu > surf->last_u) {
span = span_p++;
span->u = surf->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf->spans;
surf->spans = span;
}
// reset spanstate for all surfaces in the surface stack
do {
surf->spanstate = 0;
surf = surf->next;
} while (surf != &sw32_surfaces[1]);
}
static void
R_TrailingEdge (surf_t *surf, edge_t *edge)
{
espan_t *span;
int iu;
// don't generate a span if this is an inverted span, with the end edge
// preceding the start edge (that is, we haven't seen the start edge yet)
if (--surf->spanstate == 0) {
if (surf == sw32_surfaces[1].next) {
// emit a span (current top going away)
iu = edge->u >> 20;
if (iu > surf->last_u) {
span = span_p++;
span->u = surf->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf->spans;
surf->spans = span;
}
// set last_u on the surface below
surf->next->last_u = iu;
}
surf->prev->next = surf->next;
surf->next->prev = surf->prev;
}
}
static void
R_LeadingEdge (edge_t *edge)
{
espan_t *span;
surf_t *surf, *surf2;
int iu;
double fu, newzi, testzi, newzitop, newzibottom;
if (edge->surfs[1]) {
// it's adding a new surface in, so find the correct place
surf = &sw32_surfaces[edge->surfs[1]];
// don't start a span if this is an inverted span, with the end edge
// preceding the start edge (that is, we've already seen the end edge)
if (++surf->spanstate == 1) {
surf2 = sw32_surfaces[1].next;
if (surf->key < surf2->key)
goto newtop;
// if it's two surfaces on the same plane, the one that's already
// active is in front, so keep going unless it's a bmodel
if (surf->insubmodel && (surf->key == surf2->key)) {
// must be two bmodels in the same leaf; sort on 1/z
fu = (float) (edge->u - 0xFFFFF) * (1.0 / 0x100000);
newzi = surf->d_ziorigin + fv * surf->d_zistepv +
fu * surf->d_zistepu;
newzibottom = newzi * 0.99;
testzi = surf2->d_ziorigin + fv * surf2->d_zistepv +
fu * surf2->d_zistepu;
if (newzibottom >= testzi) {
goto newtop;
}
newzitop = newzi * 1.01;
if (newzitop >= testzi) {
if (surf->d_zistepu >= surf2->d_zistepu) {
goto newtop;
}
}
}
continue_search:
do {
surf2 = surf2->next;
} while (surf->key > surf2->key);
if (surf->key == surf2->key) {
// if it's two surfaces on the same plane, the already active
// one is in front, so keep going unless it's a bmodel
if (!surf->insubmodel)
goto continue_search;
// must be two bmodels in the same leaf; sort on 1/z
fu = (float) (edge->u - 0xFFFFF) * (1.0 / 0x100000);
newzi = surf->d_ziorigin + fv * surf->d_zistepv +
fu * surf->d_zistepu;
newzibottom = newzi * 0.99;
testzi = surf2->d_ziorigin + fv * surf2->d_zistepv +
fu * surf2->d_zistepu;
if (newzibottom >= testzi) {
goto gotposition;
}
newzitop = newzi * 1.01;
if (newzitop >= testzi) {
if (surf->d_zistepu >= surf2->d_zistepu) {
goto gotposition;
}
}
goto continue_search;
}
goto gotposition;
newtop:
// emit a span (obscures current top)
iu = edge->u >> 20;
if (iu > surf2->last_u) {
span = span_p++;
span->u = surf2->last_u;
span->count = iu - span->u;
span->v = current_iv;
span->pnext = surf2->spans;
surf2->spans = span;
}
// set last_u on the new span
surf->last_u = iu;
gotposition:
// insert before surf2
surf->next = surf2;
surf->prev = surf2->prev;
surf2->prev->next = surf;
surf2->prev = surf;
}
}
}
void
sw32_R_GenerateSpans (void)
{
edge_t *edge;
surf_t *surf;
// clear active surfaces to just the background surface
sw32_surfaces[1].next = sw32_surfaces[1].prev = &sw32_surfaces[1];
sw32_surfaces[1].last_u = edge_head_u_shift20;
// generate spans
for (edge = edge_head.next; edge != &edge_tail; edge = edge->next) {
if (edge->surfs[0]) {
// it has a left surface, so a surface is going away for this span
surf = &sw32_surfaces[edge->surfs[0]];
R_TrailingEdge (surf, edge);
if (!edge->surfs[1])
continue;
}
R_LeadingEdge (edge);
}
R_CleanupSpan ();
}
/*
R_ScanEdges
Input:
sw32_newedges[] array
this has links to edges, which have links to surfaces
Output:
Each surface has a linked list of its visible spans
*/
void
sw32_R_ScanEdges (void)
{
int iv, bottom;
byte basespans[MAXSPANS * sizeof (espan_t) + CACHE_SIZE];
espan_t *basespan_p;
surf_t *s;
basespan_p = (espan_t *)
((intptr_t) (basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
span_p = basespan_p;
// clear active edges to just the background edges around the whole screen
// FIXME: most of this needs to be set up only once
edge_head.u = r_refdef.vrect.x << 20;
edge_head_u_shift20 = edge_head.u >> 20;
edge_head.u_step = 0;
edge_head.prev = NULL;
edge_head.next = &edge_tail;
edge_head.surfs[0] = 0;
edge_head.surfs[1] = 1;
edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
edge_tail_u_shift20 = edge_tail.u >> 20;
edge_tail.u_step = 0;
edge_tail.prev = &edge_head;
edge_tail.next = &edge_aftertail;
edge_tail.surfs[0] = 1;
edge_tail.surfs[1] = 0;
edge_aftertail.u = -1; // force a move
edge_aftertail.u_step = 0;
edge_aftertail.next = &edge_sentinel;
edge_aftertail.prev = &edge_tail;
// FIXME: do we need this now that we clamp x in r_draw.c?
edge_sentinel.u = 32767 << 16; // make sure nothing sorts past this
edge_sentinel.prev = &edge_aftertail;
// process all scan lines
bottom = r_refdef.vrectbottom - 1;
for (iv = r_refdef.vrect.y; iv < bottom; iv++) {
current_iv = iv;
fv = (float) iv;
// mark that the head (background start) span is pre-included
sw32_surfaces[1].spanstate = 1;
if (sw32_newedges[iv]) {
sw32_R_InsertNewEdges (sw32_newedges[iv], edge_head.next);
}
(*pdrawfunc) ();
// flush the span list if we can't be sure we have enough spans left
// for the next scan
if (span_p > max_span_p) {
S_ExtraUpdate (); // don't let sound get messed up if going slow
if (sw32_r_drawculledpolys)
R_DrawCulledPolys ();
else
sw32_D_DrawSurfaces ();
// clear the surface span pointers
for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++)
s->spans = NULL;
span_p = basespan_p;
}
if (sw32_removeedges[iv])
sw32_R_RemoveEdges (sw32_removeedges[iv]);
if (edge_head.next != &edge_tail)
sw32_R_StepActiveU (edge_head.next);
}
// do the last scan (no need to step or sort or remove on the last scan)
current_iv = iv;
fv = (float) iv;
// mark that the head (background start) span is pre-included
sw32_surfaces[1].spanstate = 1;
if (sw32_newedges[iv])
sw32_R_InsertNewEdges (sw32_newedges[iv], edge_head.next);
(*pdrawfunc) ();
// draw whatever's left in the span list
if (sw32_r_drawculledpolys)
R_DrawCulledPolys ();
else
sw32_D_DrawSurfaces ();
}

View file

@ -1,330 +0,0 @@
/*
sw32_riqm.c
32bit SW IQM rendering
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2012/5/18
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
*/
#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>
#define NH_DEFINE
#include "namehack.h"
#include "QF/cvar.h"
#include "QF/image.h"
#include "QF/render.h"
#include "QF/skin.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "d_ifacea.h"
#include "r_internal.h"
#define LIGHT_MIN 5 // lowest light value we'll allow, to
// avoid the need for inner-loop light
// clamping
static vec3_t r_plightvec;
static int r_ambientlight;
static float r_shadelight;
static inline int
calc_light (float *normal)
{
float lightcos = DotProduct (normal, r_plightvec);
int temp = r_ambientlight;
if (lightcos < 0) {
temp += (int) (r_shadelight * lightcos);
// clamp; because we limited the minimum ambient and shading
// light, we don't have to clamp low light, just bright
if (temp < 0)
temp = 0;
}
return temp;
}
static void
R_IQMTransformAndProjectFinalVerts (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame)
{
finalvert_t *fv = pfinalverts;
float zi;
int i;
for (i = 0; i < iqm->num_verts; i++, fv++) {
byte *vert = iqm->vertices + i * iqm->stride;
uint32_t bind = *(uint32_t *) (vert + sw->bindices->offset);
vec_t *mat = (vec_t *) &frame[bind];
float *position = (float *) (vert + sw->position->offset);
float *normal = (float *) (vert + sw->normal->offset);
int32_t *texcoord = (int32_t *) (vert + sw->texcoord->offset);
vec3_t tv, tn;
Mat4MultVec (mat, position, tv);
Mat4as3MultVec (mat, normal, tn);
zi = 1.0 / (DotProduct (tv, sw32_aliastransform[2])
+ sw32_aliastransform[2][3]);
fv->v[5] = zi;
fv->v[0] = (DotProduct (tv, sw32_aliastransform[0])
+ sw32_aliastransform[0][3]) * zi + aliasxcenter;
fv->v[1] = (DotProduct (tv, sw32_aliastransform[1])
+ sw32_aliastransform[1][3]) * zi + aliasxcenter;
fv->v[2] = texcoord[0];
fv->v[3] = texcoord[1];
fv->v[4] = calc_light (tn);
}
}
static void
iqm_setup_skin (swiqm_t *sw, int skinnum)
{
tex_t *skin = sw->skins[skinnum];
sw32_r_affinetridesc.pskin = skin->data;
sw32_r_affinetridesc.skinwidth = skin->width;
sw32_r_affinetridesc.skinheight = skin->height;
sw32_r_affinetridesc.seamfixupX16 = (skin->width >> 1) << 16;
}
static void
R_IQMPrepareUnclippedPoints (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame)
{
int i;
R_IQMTransformAndProjectFinalVerts (iqm, sw, frame);
sw32_r_affinetridesc.pfinalverts = pfinalverts;
for (i = 0; i < iqm->num_meshes; i++) {
iqmmesh *mesh = &iqm->meshes[i];
uint16_t *tris;
iqm_setup_skin (sw, i);
tris = iqm->elements + mesh->first_triangle;
sw32_r_affinetridesc.ptriangles = (mtriangle_t *) tris;
sw32_r_affinetridesc.numtriangles = mesh->num_triangles;
sw32_D_PolysetDraw ();
}
}
static void
R_IQMPreparePoints (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame)
{
finalvert_t *fv = pfinalverts;
auxvert_t *av = pauxverts;
int i;
uint32_t j;
finalvert_t *pfv[3];
for (i = 0; i < iqm->num_verts; i++, fv++, av++) {
byte *vert = iqm->vertices + i * iqm->stride;
uint32_t bind = *(uint32_t *) (vert + sw->bindices->offset);
vec_t *mat = (vec_t *) &frame[bind];
float *position = (float *) (vert + sw->position->offset);
float *normal = (float *) (vert + sw->normal->offset);
int32_t *texcoord = (int32_t *) (vert + sw->texcoord->offset);
vec3_t tv, tn;
Mat4MultVec (mat, position, tv);
Mat4as3MultVec (mat, normal, tn);
av->fv[0] = DotProduct (tv, sw32_aliastransform[0])
+ sw32_aliastransform[0][3];
av->fv[1] = DotProduct (tv, sw32_aliastransform[1])
+ sw32_aliastransform[1][3];
av->fv[2] = DotProduct (tv, sw32_aliastransform[2])
+ sw32_aliastransform[2][3];
fv->v[2] = texcoord[0];
fv->v[3] = texcoord[1];
fv->flags = 0;
fv->v[4] = calc_light (tn);
sw32_R_AliasClipAndProjectFinalVert (fv, av);
}
for (i = 0; i < iqm->num_meshes; i++) {
iqmmesh *mesh = &iqm->meshes[i];
mtriangle_t *mtri;
iqm_setup_skin (sw, i);
mtri = (mtriangle_t *) iqm->elements + mesh->first_triangle;
sw32_r_affinetridesc.numtriangles = 1;
for (j = 0; j < mesh->num_triangles; j++, mtri++) {
pfv[0] = &pfinalverts[mtri->vertindex[0]];
pfv[1] = &pfinalverts[mtri->vertindex[1]];
pfv[2] = &pfinalverts[mtri->vertindex[2]];
if (pfv[0]->flags & pfv[1]->flags & pfv[2]->flags
& (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))
continue; // completely clipped
if (!((pfv[0]->flags | pfv[1]->flags | pfv[2]->flags)
& (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))) {// totally unclipped
sw32_r_affinetridesc.pfinalverts = pfinalverts;
sw32_r_affinetridesc.ptriangles = mtri;
sw32_D_PolysetDraw ();
} else { // partially clipped
sw32_R_AliasClipTriangle (mtri);
}
}
}
}
static void
R_IQMSetupLighting (entity_t *ent, alight_t *plighting)
{
// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't
// have to clamp off the bottom
r_ambientlight = plighting->ambientlight;
if (r_ambientlight < LIGHT_MIN)
r_ambientlight = LIGHT_MIN;
r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
if (r_ambientlight < LIGHT_MIN)
r_ambientlight = LIGHT_MIN;
r_shadelight = plighting->shadelight;
if (r_shadelight < 0)
r_shadelight = 0;
r_shadelight *= VID_GRADES;
// rotate the lighting vector into the model's frame of reference
mat4f_t mat;
Transform_GetWorldMatrix (ent->transform, mat);
//FIXME vectorize
r_plightvec[0] = DotProduct (plighting->plightvec, mat[0]);
r_plightvec[1] = DotProduct (plighting->plightvec, mat[1]);
r_plightvec[2] = DotProduct (plighting->plightvec, mat[2]);
}
static void
R_IQMSetUpTransform (int trivial_accept)
{
int i;
float rotationmatrix[3][4];
static float viewmatrix[3][4];
vec3_t forward, left, up;
mat4f_t mat;
Transform_GetWorldMatrix (currententity->transform, mat);
VectorCopy (mat[0], forward);
VectorCopy (mat[1], left);
VectorCopy (mat[2], up);
// TODO: can do this with simple matrix rearrangement
for (i = 0; i < 3; i++) {
rotationmatrix[i][0] = forward[i];
rotationmatrix[i][1] = left[i];
rotationmatrix[i][2] = up[i];
}
rotationmatrix[0][3] = -modelorg[0];
rotationmatrix[1][3] = -modelorg[1];
rotationmatrix[2][3] = -modelorg[2];
// TODO: should be global, set when vright, etc., set
VectorCopy (vright, viewmatrix[0]);
VectorCopy (vup, viewmatrix[1]);
VectorNegate (viewmatrix[1], viewmatrix[1]);
VectorCopy (vpn, viewmatrix[2]);
// viewmatrix[0][3] = 0;
// viewmatrix[1][3] = 0;
// viewmatrix[2][3] = 0;
R_ConcatTransforms (viewmatrix, rotationmatrix, sw32_aliastransform);
// do the scaling up of x and y to screen coordinates as part of the transform
// for the unclipped case (it would mess up clipping in the clipped case).
// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
// correspondingly so the projected x and y come out right
// FIXME: make this work for clipped case too?
if (trivial_accept) {
for (i = 0; i < 4; i++) {
sw32_aliastransform[0][i] *= aliasxscale *
(1.0 / ((float) 0x8000 * 0x10000));
sw32_aliastransform[1][i] *= aliasyscale *
(1.0 / ((float) 0x8000 * 0x10000));
sw32_aliastransform[2][i] *= 1.0 / ((float) 0x8000 * 0x10000);
}
}
}
void
sw32_R_IQMDrawModel (alight_t *plighting)
{
entity_t *ent = currententity;
model_t *model = ent->renderer.model;
iqm_t *iqm = (iqm_t *) model->aliashdr;
swiqm_t *sw = (swiqm_t *) iqm->extra_data;
int size;
float blend;
iqmframe_t *frame;
size = (CACHE_SIZE - 1)
+ sizeof (finalvert_t) * (iqm->num_verts + 1)
+ sizeof (auxvert_t) * iqm->num_verts;
blend = R_IQMGetLerpedFrames (ent, iqm);
frame = R_IQMBlendPalette (iqm, ent->animation.pose1, ent->animation.pose2,
blend, size,
sw->blend_palette, sw->palette_size);
pfinalverts = (finalvert_t *) &frame[sw->palette_size];
pfinalverts = (finalvert_t *)
(((intptr_t) &pfinalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
pauxverts = (auxvert_t *) &pfinalverts[iqm->num_verts + 1];
R_IQMSetUpTransform (ent->visibility.trivial_accept);
R_IQMSetupLighting (ent, plighting);
//if (!sw32_acolormap)
sw32_acolormap = vid.colormap8;
if (ent != vr_data.view_model)
sw32_ziscale = (float) 0x8000 *(float) 0x10000;
else
sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0;
if (ent->visibility.trivial_accept)
R_IQMPrepareUnclippedPoints (iqm, sw, frame);
else
R_IQMPreparePoints (iqm, sw, frame);
}

View file

@ -1,877 +0,0 @@
/*
sw32_rmain.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <math.h>
#include "QF/cmd.h"
#include "QF/cvar.h"
#include "QF/mathlib.h"
#include "QF/render.h"
#include "QF/screen.h"
#include "QF/sound.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "compat.h"
#include "mod_internal.h"
#include "r_internal.h"
#include "vid_internal.h"
//define PASSAGES
static vec3_t viewlightvec;
static alight_t r_viewlighting = { 128, 192, viewlightvec };
int sw32_r_numallocatededges;
qboolean sw32_r_drawpolys;
qboolean sw32_r_drawculledpolys;
qboolean sw32_r_worldpolysbacktofront;
float sw32_r_aliasuvscale = 1.0;
int sw32_r_outofsurfaces;
int sw32_r_outofedges;
qboolean sw32_r_dowarp, sw32_r_dowarpold, sw32_r_viewchanged;
int sw32_c_surf;
int sw32_r_maxsurfsseen, sw32_r_maxedgesseen;
static int r_cnumsurfs;
static qboolean r_surfsonstack;
int sw32_r_clipflags;
byte *sw32_r_warpbuffer;
static byte *r_stack_start;
// screen size info
float sw32_xcenter, sw32_ycenter;
float sw32_xscale, sw32_yscale;
float sw32_xscaleinv, sw32_yscaleinv;
float sw32_xscaleshrink, sw32_yscaleshrink;
float sw32_aliasxscale, sw32_aliasyscale, sw32_aliasxcenter, sw32_aliasycenter;
int sw32_screenwidth;
float sw32_pixelAspect;
static float screenAspect;
static float verticalFieldOfView;
static float xOrigin, yOrigin;
plane_t sw32_screenedge[4];
// refresh flags
int sw32_r_polycount;
int sw32_r_drawnpolycount;
int *sw32_pfrustum_indexes[4];
int sw32_r_frustum_indexes[4 * 6];
float sw32_r_aliastransition, sw32_r_resfudge;
static float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
static float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
void
sw32_R_Textures_Init (void)
{
int x, y, m;
byte *dest;
// create a simple checkerboard texture for the default
r_notexture_mip =
Hunk_AllocName (0, sizeof (texture_t) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2,
"notexture");
r_notexture_mip->width = r_notexture_mip->height = 16;
r_notexture_mip->offsets[0] = sizeof (texture_t);
r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16 * 16;
r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8 * 8;
r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4 * 4;
for (m = 0; m < 4; m++) {
dest = (byte *) r_notexture_mip + r_notexture_mip->offsets[m];
for (y = 0; y < (16 >> m); y++)
for (x = 0; x < (16 >> m); x++) {
if ((y < (8 >> m)) ^ (x < (8 >> m)))
*dest++ = 0;
else
*dest++ = 0xff;
}
}
}
void
sw32_R_Init (void)
{
int dummy;
r_ent_queue = EntQueue_New (mod_num_types);
// get stack position so we can guess if we are going to overflow
r_stack_start = (byte *) & dummy;
R_Init_Cvars ();
sw32_R_Particles_Init_Cvars ();
sw32_Draw_Init ();
SCR_Init ();
sw32_R_InitTurb ();
Cmd_AddCommand ("timerefresh", sw32_R_TimeRefresh_f, "Tests the current "
"refresh rate for the current location");
Cmd_AddCommand ("loadsky", sw32_R_LoadSky_f, "Load a skybox");
Cvar_SetValue (r_maxedges, (float) NUMSTACKEDGES);
Cvar_SetValue (r_maxsurfs, (float) NUMSTACKSURFACES);
sw32_view_clipplanes[0].leftedge = true;
sw32_view_clipplanes[1].rightedge = true;
sw32_view_clipplanes[1].leftedge = sw32_view_clipplanes[2].leftedge =
sw32_view_clipplanes[3].leftedge = false;
sw32_view_clipplanes[0].rightedge = sw32_view_clipplanes[2].rightedge =
sw32_view_clipplanes[3].rightedge = false;
r_refdef.xOrigin = XCENTERING;
r_refdef.yOrigin = YCENTERING;
sw32_D_Init ();
Skin_Init ();
}
void
sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
{
mod_brush_t *brush = &worldmodel->brush;
memset (&r_worldentity, 0, sizeof (r_worldentity));
r_worldentity.renderer.model = worldmodel;
// clear out efrags in case the level hasn't been reloaded
for (unsigned i = 0; i < brush->modleafs; i++)
brush->leafs[i].efrags = NULL;
if (brush->skytexture)
sw32_R_InitSky (brush->skytexture);
// Force a vis update
r_viewleaf = NULL;
R_MarkLeaves ();
R_ClearParticles ();
r_cnumsurfs = r_maxsurfs->int_val;
if (r_cnumsurfs <= MINSURFACES)
r_cnumsurfs = MINSURFACES;
if (r_cnumsurfs > NUMSTACKSURFACES) {
sw32_surfaces = Hunk_AllocName (0, r_cnumsurfs * sizeof (surf_t),
"surfaces");
sw32_surface_p = sw32_surfaces;
sw32_surf_max = &sw32_surfaces[r_cnumsurfs];
r_surfsonstack = false;
// surface 0 doesn't really exist; it's just a dummy because index 0
// is used to indicate no edge attached to surface
sw32_surfaces--;
} else {
r_surfsonstack = true;
}
sw32_r_maxedgesseen = 0;
sw32_r_maxsurfsseen = 0;
sw32_r_numallocatededges = r_maxedges->int_val;
if (sw32_r_numallocatededges < MINEDGES)
sw32_r_numallocatededges = MINEDGES;
if (sw32_r_numallocatededges <= NUMSTACKEDGES) {
sw32_auxedges = NULL;
} else {
sw32_auxedges = Hunk_AllocName (0,
sw32_r_numallocatededges * sizeof (edge_t),
"edges");
}
sw32_r_dowarpold = false;
sw32_r_viewchanged = false;
}
/*
R_ViewChanged
Called every time the vid structure or r_refdef changes.
Guaranteed to be called before the first refresh
*/
void
sw32_R_ViewChanged (void)
{
int i;
float res_scale;
sw32_r_viewchanged = true;
r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x / 360 * M_PI);
r_refdef.fvrectx = (float) r_refdef.vrect.x;
r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5;
r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x << 20) + (1 << 19) - 1;
r_refdef.fvrecty = (float) r_refdef.vrect.y;
r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5;
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
r_refdef.vrectright_adj_shift20 =
(r_refdef.vrectright << 20) + (1 << 19) - 1;
r_refdef.fvrectright = (float) r_refdef.vrectright;
r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5;
r_refdef.vrectrightedge = (float) r_refdef.vrectright - 0.99;
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
r_refdef.fvrectbottom = (float) r_refdef.vrectbottom;
r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5;
r_refdef.aliasvrect.x = (int) (r_refdef.vrect.x * sw32_r_aliasuvscale);
r_refdef.aliasvrect.y = (int) (r_refdef.vrect.y * sw32_r_aliasuvscale);
r_refdef.aliasvrect.width = (int) (r_refdef.vrect.width * sw32_r_aliasuvscale);
r_refdef.aliasvrect.height = (int) (r_refdef.vrect.height *
sw32_r_aliasuvscale);
r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
r_refdef.aliasvrect.width;
r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
r_refdef.aliasvrect.height;
sw32_pixelAspect = 1;//FIXME vid.aspect;
xOrigin = r_refdef.xOrigin;
yOrigin = r_refdef.yOrigin;
screenAspect = r_refdef.vrect.width * sw32_pixelAspect / r_refdef.vrect.height;
// 320*200 1.0 sw32_pixelAspect = 1.6 screenAspect
// 320*240 1.0 sw32_pixelAspect = 1.3333 screenAspect
// proper 320*200 sw32_pixelAspect = 0.8333333
verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect;
// values for perspective projection
// if math were exact, the values would range from 0.5 to to range+0.5
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
// the polygon rasterization will never render in the first row or column
// but will definately render in the [range] row and column, so adjust the
// buffer origin to get an exact edge to edge fill
sw32_xcenter = ((float) r_refdef.vrect.width * XCENTERING) +
r_refdef.vrect.x - 0.5;
sw32_aliasxcenter = sw32_xcenter * sw32_r_aliasuvscale;
sw32_ycenter = ((float) r_refdef.vrect.height * YCENTERING) +
r_refdef.vrect.y - 0.5;
sw32_aliasycenter = sw32_ycenter * sw32_r_aliasuvscale;
sw32_xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
sw32_aliasxscale = sw32_xscale * sw32_r_aliasuvscale;
sw32_xscaleinv = 1.0 / sw32_xscale;
sw32_yscale = sw32_xscale * sw32_pixelAspect;
sw32_aliasyscale = sw32_yscale * sw32_r_aliasuvscale;
sw32_yscaleinv = 1.0 / sw32_yscale;
sw32_xscaleshrink = (r_refdef.vrect.width - 6) / r_refdef.horizontalFieldOfView;
sw32_yscaleshrink = sw32_xscaleshrink * sw32_pixelAspect;
// left side clip
sw32_screenedge[0].normal[0] = -1.0 / (xOrigin *
r_refdef.horizontalFieldOfView);
sw32_screenedge[0].normal[1] = 0;
sw32_screenedge[0].normal[2] = 1;
sw32_screenedge[0].type = PLANE_ANYZ;
// right side clip
sw32_screenedge[1].normal[0] = 1.0 / ((1.0 - xOrigin) *
r_refdef.horizontalFieldOfView);
sw32_screenedge[1].normal[1] = 0;
sw32_screenedge[1].normal[2] = 1;
sw32_screenedge[1].type = PLANE_ANYZ;
// top side clip
sw32_screenedge[2].normal[0] = 0;
sw32_screenedge[2].normal[1] = -1.0 / (yOrigin * verticalFieldOfView);
sw32_screenedge[2].normal[2] = 1;
sw32_screenedge[2].type = PLANE_ANYZ;
// bottom side clip
sw32_screenedge[3].normal[0] = 0;
sw32_screenedge[3].normal[1] = 1.0 / ((1.0 - yOrigin) * verticalFieldOfView);
sw32_screenedge[3].normal[2] = 1;
sw32_screenedge[3].type = PLANE_ANYZ;
for (i = 0; i < 4; i++)
VectorNormalize (sw32_screenedge[i].normal);
res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) /
(320.0 * 152.0)) * (2.0 /
r_refdef.horizontalFieldOfView);
sw32_r_aliastransition = r_aliastransbase->value * res_scale;
sw32_r_resfudge = r_aliastransadj->value * res_scale;
sw32_D_ViewChanged ();
}
static inline void
draw_sprite_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
sw32_R_DrawSprite ();
}
static inline void
setup_lighting (alight_t *lighting)
{
float minlight = 0;
int j;
// FIXME: remove and do real lighting
vec3_t dist;
float add;
float lightvec[3] = { -1, 0, 0 };
minlight = max (currententity->renderer.model->min_light,
currententity->renderer.min_light);
// 128 instead of 255 due to clamping below
j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin),
minlight * 128);
lighting->ambientlight = j;
lighting->shadelight = j;
lighting->plightvec = lightvec;
for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) {
if (r_dlights[lnum].die >= vr_data.realtime) {
VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist);
add = r_dlights[lnum].radius - VectorLength (dist);
if (add > 0)
lighting->ambientlight += add;
}
}
// clamp lighting so it doesn't overbright as much
if (lighting->ambientlight > 128)
lighting->ambientlight = 128;
if (lighting->ambientlight + lighting->shadelight > 192)
lighting->shadelight = 192 - lighting->ambientlight;
}
static inline void
draw_alias_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
currententity->visibility.trivial_accept = 0; //FIXME
if (R_AliasCheckBBox ()) {
alight_t lighting;
setup_lighting (&lighting);
sw32_R_AliasDrawModel (&lighting);
}
}
static inline void
draw_iqm_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
currententity->visibility.trivial_accept = 0; //FIXME
alight_t lighting;
setup_lighting (&lighting);
sw32_R_IQMDrawModel (&lighting);
}
static void
R_DrawEntitiesOnList (void)
{
if (!r_drawentities->int_val)
return;
#define RE_LOOP(type_name) \
do { \
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
VectorCopy (Transform_GetWorldPosition (ent->transform), \
r_entorigin); \
currententity = ent; \
draw_##type_name##_entity (ent); \
} \
} while (0)
RE_LOOP (alias);
RE_LOOP (iqm);
RE_LOOP (sprite);
}
static void
R_DrawViewModel (void)
{
// FIXME: remove and do real lighting
float lightvec[3] = { -1, 0, 0 };
int j;
unsigned int lnum;
vec3_t dist;
float add;
float minlight;
dlight_t *dl;
if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val
|| !r_drawentities->int_val)
return;
currententity = vr_data.view_model;
if (!currententity->renderer.model)
return;
VectorCopy (Transform_GetWorldPosition (currententity->transform),
r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
VectorCopy (vup, viewlightvec);
VectorNegate (viewlightvec, viewlightvec);
minlight = max (currententity->renderer.min_light,
currententity->renderer.model->min_light);
j = max (R_LightPoint (&r_worldentity.renderer.model->brush,
r_entorigin), minlight * 128);
r_viewlighting.ambientlight = j;
r_viewlighting.shadelight = j;
// add dynamic lights
for (lnum = 0; lnum < r_maxdlights; lnum++) {
dl = &r_dlights[lnum];
if (!dl->radius)
continue;
if (!dl->radius)
continue;
if (dl->die < vr_data.realtime)
continue;
VectorSubtract (r_entorigin, dl->origin, dist);
add = dl->radius - VectorLength (dist);
if (add > 0)
r_viewlighting.ambientlight += add;
}
// clamp lighting so it doesn't overbright as much
if (r_viewlighting.ambientlight > 128)
r_viewlighting.ambientlight = 128;
if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192)
r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight;
r_viewlighting.plightvec = lightvec;
sw32_R_AliasDrawModel (&r_viewlighting);
}
static int
R_BmodelCheckBBox (model_t *clmodel, float *minmaxs)
{
int i, *pindex, clipflags;
vec3_t acceptpt, rejectpt;
double d;
mat4f_t mat;
clipflags = 0;
Transform_GetWorldMatrix (currententity->transform, mat);
if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) {
for (i = 0; i < 4; i++) {
d = DotProduct (mat[3], sw32_view_clipplanes[i].normal);
d -= sw32_view_clipplanes[i].dist;
if (d <= -clmodel->radius)
return BMODEL_FULLY_CLIPPED;
if (d <= clmodel->radius)
clipflags |= (1 << i);
}
} else {
for (i = 0; i < 4; i++) {
// generate accept and reject points
// FIXME: do with fast look-ups or integer tests based on the
// sign bit of the floating point values
pindex = sw32_pfrustum_indexes[i];
rejectpt[0] = minmaxs[pindex[0]];
rejectpt[1] = minmaxs[pindex[1]];
rejectpt[2] = minmaxs[pindex[2]];
d = DotProduct (rejectpt, sw32_view_clipplanes[i].normal);
d -= sw32_view_clipplanes[i].dist;
if (d <= 0)
return BMODEL_FULLY_CLIPPED;
acceptpt[0] = minmaxs[pindex[3 + 0]];
acceptpt[1] = minmaxs[pindex[3 + 1]];
acceptpt[2] = minmaxs[pindex[3 + 2]];
d = DotProduct (acceptpt, sw32_view_clipplanes[i].normal);
d -= sw32_view_clipplanes[i].dist;
if (d <= 0)
clipflags |= (1 << i);
}
}
return clipflags;
}
static void
R_DrawBEntitiesOnList (void)
{
int j, clipflags;
unsigned int k;
vec3_t oldorigin;
vec3_t origin;
model_t *clmodel;
float minmaxs[6];
if (!r_drawentities->int_val)
return;
VectorCopy (modelorg, oldorigin);
insubmodel = true;
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
currententity = ent;
VectorCopy (Transform_GetWorldPosition (ent->transform), origin);
clmodel = ent->renderer.model;
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
for (j = 0; j < 3; j++) {
minmaxs[j] = origin[j] + clmodel->mins[j];
minmaxs[3 + j] = origin[j] + clmodel->maxs[j];
}
clipflags = R_BmodelCheckBBox (clmodel, minmaxs);
if (clipflags != BMODEL_FULLY_CLIPPED) {
mod_brush_t *brush = &clmodel->brush;
VectorCopy (origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
// FIXME: is this needed?
VectorCopy (modelorg, sw32_r_worldmodelorg);
r_pcurrentvertbase = brush->vertexes;
// FIXME: stop transforming twice
sw32_R_RotateBmodel ();
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (brush->firstmodelsurface != 0) {
vec3_t lightorigin;
for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) ||
(!r_dlights[k].radius)) {
continue;
}
VectorSubtract (r_dlights[k].origin, origin, lightorigin);
R_RecursiveMarkLights (brush, lightorigin,
&r_dlights[k], k,
brush->nodes
+ brush->hulls[0].firstclipnode);
}
}
// if the driver wants polygons, deliver those.
// Z-buffering is on at this point, so no clipping to the
// world tree is needed, just frustum clipping
if (sw32_r_drawpolys | sw32_r_drawculledpolys) {
sw32_R_ZDrawSubmodelPolys (clmodel);
} else {
if (ent->visibility.topnode) {
mnode_t *topnode = ent->visibility.topnode;
if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world
// BSP
sw32_r_clipflags = clipflags;
sw32_R_DrawSolidClippedSubmodelPolygons (clmodel);
} else {
// falls entirely in one leaf, so we just put
// all the edges in the edge list and let 1/z
// sorting handle drawing order
sw32_R_DrawSubmodelPolygons (clmodel, clipflags);
}
}
}
// put back world rotation and frustum clipping
// FIXME: sw32_R_RotateBmodel should just work off base_vxx
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
VectorCopy (oldorigin, modelorg);
sw32_R_TransformFrustum ();
}
}
insubmodel = false;
}
static void
R_PrintDSpeeds (void)
{
float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time,
dv_time;
r_time2 = Sys_DoubleTime ();
dp_time = (dp_time2 - dp_time1) * 1000;
rw_time = (rw_time2 - rw_time1) * 1000;
db_time = (db_time2 - db_time1) * 1000;
se_time = (se_time2 - se_time1) * 1000;
de_time = (de_time2 - de_time1) * 1000;
dv_time = (dv_time2 - dv_time1) * 1000;
ms = (r_time2 - r_time1) * 1000;
Sys_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n",
(int) ms, dp_time, (int) rw_time, db_time, (int) se_time,
de_time, dv_time);
}
static void
R_EdgeDrawing (void)
{
edge_t ledges[NUMSTACKEDGES +
((CACHE_SIZE - 1) / sizeof (edge_t)) + 1];
surf_t lsurfs[NUMSTACKSURFACES +
((CACHE_SIZE - 1) / sizeof (surf_t)) + 1];
if (sw32_auxedges) {
sw32_r_edges = sw32_auxedges;
} else {
sw32_r_edges = (edge_t *)
(((intptr_t) &ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
}
if (r_surfsonstack) {
sw32_surfaces = (surf_t *)
(((intptr_t) &lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
sw32_surf_max = &sw32_surfaces[r_cnumsurfs];
// surface 0 doesn't really exist; it's just a dummy because index 0
// is used to indicate no edge attached to surface
sw32_surfaces--;
}
sw32_R_BeginEdgeFrame ();
if (r_dspeeds->int_val) {
rw_time1 = Sys_DoubleTime ();
}
sw32_R_RenderWorld ();
if (sw32_r_drawculledpolys)
sw32_R_ScanEdges ();
// only the world can be drawn back to front with no z reads or compares,
// just z writes, so have the driver turn z compares on now
sw32_D_TurnZOn ();
if (r_dspeeds->int_val) {
rw_time2 = Sys_DoubleTime ();
db_time1 = rw_time2;
}
R_DrawBEntitiesOnList ();
if (r_dspeeds->int_val) {
db_time2 = Sys_DoubleTime ();
se_time1 = db_time2;
}
if (!r_dspeeds->int_val) {
S_ExtraUpdate (); // don't let sound get messed up if going slow
}
if (!(sw32_r_drawpolys | sw32_r_drawculledpolys))
sw32_R_ScanEdges ();
}
// LordHavoc: took out of stack and made 4x size for 32bit capacity
static byte warpbuffer[WARP_WIDTH * WARP_HEIGHT * 4];
/*
R_RenderView
r_refdef must be set before the first call
*/
static void
R_RenderView_ (void)
{
if (r_norefresh->int_val)
return;
if (!r_worldentity.renderer.model) {
return;
}
sw32_r_warpbuffer = warpbuffer;
if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val)
r_time1 = Sys_DoubleTime ();
sw32_R_SetupFrame ();
#ifdef PASSAGES
SetVisibilityByPassages ();
#else
R_MarkLeaves (); // done here so we know if we're in water
#endif
R_PushDlights (vec3_origin);
if (!r_dspeeds->int_val) {
S_ExtraUpdate (); // don't let sound get messed up if going slow
}
R_EdgeDrawing ();
if (!r_dspeeds->int_val) {
S_ExtraUpdate (); // don't let sound get messed up if going slow
}
if (r_dspeeds->int_val) {
se_time2 = Sys_DoubleTime ();
de_time1 = se_time2;
}
R_DrawEntitiesOnList ();
if (r_dspeeds->int_val) {
de_time2 = Sys_DoubleTime ();
dv_time1 = de_time2;
}
R_DrawViewModel ();
if (r_dspeeds->int_val) {
dv_time2 = Sys_DoubleTime ();
dp_time1 = Sys_DoubleTime ();
}
sw32_R_DrawParticles ();
if (r_dspeeds->int_val)
dp_time2 = Sys_DoubleTime ();
if (sw32_r_dowarp)
sw32_D_WarpScreen ();
if (r_timegraph->int_val)
R_TimeGraph ();
if (r_zgraph->int_val)
R_ZGraph ();
if (r_aliasstats->int_val)
sw32_R_PrintAliasStats ();
if (r_speeds->int_val)
sw32_R_PrintTimes ();
if (r_dspeeds->int_val)
R_PrintDSpeeds ();
if (r_reportsurfout->int_val && sw32_r_outofsurfaces)
Sys_Printf ("Short %d surfaces\n", sw32_r_outofsurfaces);
if (r_reportedgeout->int_val && sw32_r_outofedges)
Sys_Printf ("Short roughly %d edges\n", sw32_r_outofedges * 2 / 3);
}
void
sw32_R_RenderView (void)
{
int dummy;
int delta;
delta = (byte *) & dummy - r_stack_start;
if (delta < -10000 || delta > 10000)
Sys_Error ("R_RenderView: called without enough stack");
if (Hunk_LowMark (0) & 3)
Sys_Error ("Hunk is missaligned");
if ((intptr_t) (&dummy) & 3)
Sys_Error ("Stack is missaligned");
if ((intptr_t) (&sw32_r_warpbuffer) & 3)
Sys_Error ("Globals are missaligned");
R_RenderView_ ();
}
void
sw32_R_InitTurb (void)
{
int i;
for (i = 0; i < MAXWIDTH; i++) {
sw32_sintable[i] = AMP + sin (i * 3.14159 * 2 / CYCLE) * AMP;
sw32_intsintable[i] = AMP2 + sin (i * 3.14159 * 2 / CYCLE) * AMP2;
// AMP2 not 20
}
}
void
sw32_R_ClearState (void)
{
r_worldentity.renderer.model = 0;
R_ClearEfrags ();
R_ClearDlights ();
R_ClearParticles ();
}

View file

@ -1,321 +0,0 @@
/*
sw32_rmisc.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/cmd.h"
#include "QF/cvar.h"
#include "QF/draw.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/ui/view.h"
#include "QF/scene/entity.h"
#include "compat.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static void
R_CheckVariables (void)
{
}
/*
R_TimeRefresh_f
For program optimization
*/
void
sw32_R_TimeRefresh_f (void)
{
/* FIXME update for simd
int i;
float start, stop, time;
int startangle;
vrect_t vr;
startangle = r_refdef.viewangles[1];
start = Sys_DoubleTime ();
for (i = 0; i < 128; i++) {
r_refdef.viewangles[1] = i / 128.0 * 360.0;
sw32_R_RenderView ();
vr.x = r_refdef.vrect.x;
vr.y = r_refdef.vrect.y;
vr.width = r_refdef.vrect.width;
vr.height = r_refdef.vrect.height;
vr.next = NULL;
sw32_ctx->update (&vr);
}
stop = Sys_DoubleTime ();
time = stop - start;
Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time);
r_refdef.viewangles[1] = startangle;
*/
}
void
sw32_R_LoadSky_f (void)
{
if (Cmd_Argc () != 2) {
Sys_Printf ("loadsky <name> : load a skybox\n");
return;
}
sw32_R_LoadSkys (Cmd_Argv (1));
}
void
sw32_R_PrintTimes (void)
{
float r_time2;
float ms;
r_time2 = Sys_DoubleTime ();
ms = 1000 * (r_time2 - r_time1);
Sys_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n",
ms, sw32_c_faceclip, sw32_r_polycount, sw32_r_drawnpolycount, sw32_c_surf);
sw32_c_surf = 0;
}
void
sw32_R_PrintAliasStats (void)
{
Sys_Printf ("%3i polygon model drawn\n", sw32_r_amodels_drawn);
}
void
sw32_R_TransformFrustum (void)
{
int i;
vec3_t v, v2;
for (i = 0; i < 4; i++) {
v[0] = sw32_screenedge[i].normal[2];
v[1] = -sw32_screenedge[i].normal[0];
v[2] = sw32_screenedge[i].normal[1];
v2[0] = v[1] * vright[0] + v[2] * vup[0] + v[0] * vpn[0];
v2[1] = v[1] * vright[1] + v[2] * vup[1] + v[0] * vpn[1];
v2[2] = v[1] * vright[2] + v[2] * vup[2] + v[0] * vpn[2];
VectorCopy (v2, sw32_view_clipplanes[i].normal);
sw32_view_clipplanes[i].dist = DotProduct (modelorg, v2);
}
}
void
sw32_TransformVector (const vec3_t in, vec3_t out)
{
out[0] = DotProduct (in, vright);
out[1] = DotProduct (in, vup);
out[2] = DotProduct (in, vpn);
}
void
sw32_R_TransformPlane (plane_t *p, float *normal, float *dist)
{
float d;
d = DotProduct (r_origin, p->normal);
*dist = p->dist - d;
// TODO: when we have rotating entities, this will need to use the view matrix
sw32_TransformVector (p->normal, normal);
}
static void
R_SetUpFrustumIndexes (void)
{
int i, j, *pindex;
pindex = sw32_r_frustum_indexes;
for (i = 0; i < 4; i++) {
for (j = 0; j < 3; j++) {
if (sw32_view_clipplanes[i].normal[j] < 0) {
pindex[j] = j;
pindex[j + 3] = j + 3;
} else {
pindex[j] = j + 3;
pindex[j + 3] = j;
}
}
// FIXME: do just once at start
sw32_pfrustum_indexes[i] = pindex;
pindex += 6;
}
}
void
sw32_R_SetupFrame (void)
{
int edgecount;
vrect_t vrect;
float w, h;
// don't allow cheats in multiplayer
Cvar_SetValue (r_ambient, 0);
Cvar_SetValue (r_drawflat, 0);
if (r_numsurfs->int_val) {
if ((sw32_surface_p - sw32_surfaces) > sw32_r_maxsurfsseen)
sw32_r_maxsurfsseen = sw32_surface_p - sw32_surfaces;
Sys_Printf ("Used %ld of %ld surfs; %d max\n",
(long) (sw32_surface_p - sw32_surfaces),
(long) (sw32_surf_max - sw32_surfaces), sw32_r_maxsurfsseen);
}
if (r_numedges->int_val) {
edgecount = sw32_edge_p - sw32_r_edges;
if (edgecount > sw32_r_maxedgesseen)
sw32_r_maxedgesseen = edgecount;
Sys_Printf ("Used %d of %d edges; %d max\n", edgecount,
sw32_r_numallocatededges, sw32_r_maxedgesseen);
}
r_refdef.ambientlight = max (r_ambient->value, 0);
R_CheckVariables ();
R_AnimateLight ();
EntQueue_Clear (r_ent_queue);
r_framecount++;
sw32_numbtofpolys = 0;
// debugging
#if 0
r_refdef.vieworg[0] = 80;
r_refdef.vieworg[1] = 64;
r_refdef.vieworg[2] = 40;
r_refdef.viewangles[0] = 0;
r_refdef.viewangles[1] = 46.763641357;
r_refdef.viewangles[2] = 0;
#endif
// build the transformation matrix for the given view angles
VectorCopy (r_refdef.viewposition, modelorg);
VectorCopy (r_refdef.viewposition, r_origin);
VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn);
VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright);
VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup);
R_SetFrustum ();
// current viewleaf
r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model);
sw32_r_dowarpold = sw32_r_dowarp;
sw32_r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <=
CONTENTS_WATER);
if ((sw32_r_dowarp != sw32_r_dowarpold) || sw32_r_viewchanged) {
if (sw32_r_dowarp) {
if ((vid.width <= WARP_WIDTH)
&& (vid.height <= WARP_HEIGHT)) {
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
R_SetVrect (&vrect, &r_refdef.vrect, vr_data.lineadj);
sw32_R_ViewChanged ();
} else {
w = vid.width;
h = vid.height;
if (w > WARP_WIDTH) {
h *= (float) WARP_WIDTH / w;
w = WARP_WIDTH;
}
if (h > WARP_HEIGHT) {
h = WARP_HEIGHT;
w *= (float) WARP_HEIGHT / h;
}
vrect.x = 0;
vrect.y = 0;
vrect.width = (int) w;
vrect.height = (int) h;
R_SetVrect (&vrect, &r_refdef.vrect,
(int) ((float) vr_data.lineadj *
(h / (float) vid.height)));
sw32_R_ViewChanged ();
}
} else {
r_refdef.vrect.x = vr_data.scr_view->xpos;
r_refdef.vrect.y = vr_data.scr_view->ypos;
r_refdef.vrect.width = vr_data.scr_view->xlen;
r_refdef.vrect.height = vr_data.scr_view->ylen;
sw32_R_ViewChanged ();
}
sw32_r_viewchanged = false;
}
// start off with just the four screen edge clip planes
sw32_R_TransformFrustum ();
// save base values
VectorCopy (vpn, base_vpn);
VectorCopy (vright, base_vright);
VectorCopy (vup, base_vup);
VectorCopy (modelorg, base_modelorg);
sw32_R_SetSkyFrame ();
R_SetUpFrustumIndexes ();
r_cache_thrash = false;
// clear frame counts
sw32_c_faceclip = 0;
sw32_r_polycount = 0;
sw32_r_drawnpolycount = 0;
sw32_r_amodels_drawn = 0;
sw32_r_outofsurfaces = 0;
sw32_r_outofedges = 0;
sw32_D_SetupFrame ();
}

View file

@ -1,108 +0,0 @@
/*
sw32_rpart.c
24 bit color software renderer particle effects.
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/cvar.h"
#include "QF/mersenne.h"
#include "QF/qargs.h"
#include "QF/quakefs.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/scene/entity.h"
#include "compat.h"
#include "r_internal.h"
void
sw32_R_DrawParticles (void)
{
VectorScale (vright, xscaleshrink, r_pright);
VectorScale (vup, yscaleshrink, r_pup);
VectorCopy (vpn, r_ppn);
R_RunParticles (vr_data.frametime);
for (unsigned i = 0; i < r_psystem.numparticles; i++) {
particle_t *p = &r_psystem.particles[i];
sw32_D_DrawParticle (p);
}
}
static void
r_particles_nearclip_f (cvar_t *var)
{
Cvar_SetValue (r_particles_nearclip, bound (r_nearclip->value, var->value,
r_farclip->value));
}
static void
r_particles_f (cvar_t *var)
{
R_MaxParticlesCheck (var, r_particles_max);
}
static void
r_particles_max_f (cvar_t *var)
{
R_MaxParticlesCheck (r_particles, var);
}
void
sw32_R_Particles_Init_Cvars (void)
{
r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f,
"Toggles drawing of particles.");
r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE,
r_particles_max_f, "Maximum amount of "
"particles to display. No maximum, minimum "
"is 0.");
r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32",
CVAR_ARCHIVE, r_particles_nearclip_f,
"Distance of the particle near clipping "
"plane from the player.");
}
psystem_t * __attribute__((const))//FIXME
sw32_ParticleSystem (void)
{
return &r_psystem;
}

View file

@ -1,224 +0,0 @@
/*
r_sky.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#ifdef HAVE_STRING_H
# include "string.h"
#endif
#ifdef HAVE_STRINGS_H
# include "strings.h"
#endif
#include "QF/sys.h"
#include "QF/render.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
static int iskyspeed = 8;
static int iskyspeed2 = 2;
float sw32_r_skyspeed;
float sw32_r_skytime;
byte *sw32_r_skysource;
int sw32_r_skymade;
// TODO: clean up these routines
/*
byte bottomsky[128 * 131];
byte bottommask[128 * 131];
byte newsky[128 * 256]; // newsky and topsky both pack in here,
// 128 bytes of newsky on the left of
// each scan, 128 bytes of topsky on
// the right, because the low-level
// drawers need 256-byte scan widths
*/
static byte skydata[128*256]; // sky layers for making skytex
static byte skytex[128*256*4]; // current sky texture
/*
R_InitSky
A sky texture is 256*128, with the right side being a masked overlay
*/
void
sw32_R_InitSky (texture_t *mt)
{
/*
int i, j;
byte *src;
src = (byte *) mt + mt->offsets[0];
for (i = 0; i < 128; i++) {
for (j = 0; j < 128; j++) {
newsky[(i * 256) + j + 128] = src[i * 256 + j + 128];
}
}
for (i = 0; i < 128; i++) {
for (j = 0; j < 131; j++) {
if (src[i * 256 + (j & 0x7F)]) {
bottomsky[(i * 131) + j] = src[i * 256 + (j & 0x7F)];
bottommask[(i * 131) + j] = 0;
} else {
bottomsky[(i * 131) + j] = 0;
bottommask[(i * 131) + j] = 0xff;
}
}
}
sw32_r_skysource = newsky;
*/
// LordHavoc: save sky for use
memcpy(skydata, (byte *) mt + mt->offsets[0], 128*256);
sw32_r_skysource = skytex;
}
void
sw32_R_MakeSky (void)
{
int x, y, xshift1, yshift1, xshift2, yshift2;
byte *base1, *base2;
static int xlast = -1, ylast = -1;
xshift2 = sw32_r_skytime * sw32_r_skyspeed * 2.0f;
yshift2 = sw32_r_skytime * sw32_r_skyspeed * 2.0f;
if ((xshift2 == xlast) && (yshift2 == ylast))
return;
xlast = xshift2;
ylast = yshift2;
xshift1 = xshift2 >> 1;
yshift1 = yshift2 >> 1;
switch(sw32_ctx->pixbytes)
{
case 1:
{
byte *out = (byte *) skytex;
for (y = 0;y < 128;y++)
{
base1 = &skydata[((y + yshift1) & 127) * 256];
base2 = &skydata[((y + yshift2) & 127) * 256 + 128];
for (x = 0;x < 128;x++)
{
if (base1[(x + xshift1) & 127])
*out = base1[(x + xshift1) & 127];
else
*out = base2[(x + xshift2) & 127];
out++;
}
out += 128;
}
}
break;
case 2:
{
unsigned short *out = (unsigned short *) skytex;
for (y = 0;y < 128;y++)
{
base1 = &skydata[((y + yshift1) & 127) * 256];
base2 = &skydata[((y + yshift2) & 127) * 256 + 128];
for (x = 0;x < 128;x++)
{
if (base1[(x + xshift1) & 127])
*out = sw32_8to16table[base1[(x + xshift1) & 127]];
else
*out = sw32_8to16table[base2[(x + xshift2) & 127]];
out++;
}
out += 128;
}
}
break;
case 4:
{
unsigned int *out = (unsigned int *) skytex;
for (y = 0;y < 128;y++)
{
base1 = &skydata[((y + yshift1) & 127) * 256];
base2 = &skydata[((y + yshift2) & 127) * 256 + 128];
for (x = 0;x < 128;x++)
{
if (base1[(x + xshift1) & 127])
*out = d_8to24table[base1[(x + xshift1) & 127]];
else
*out = d_8to24table[base2[(x + xshift2) & 127]];
out++;
}
out += 128;
}
}
break;
default:
Sys_Error("R_MakeSky: unsupported r_pixbytes %i", sw32_ctx->pixbytes);
}
sw32_r_skymade = 1;
}
void
sw32_R_SetSkyFrame (void)
{
int g, s1, s2;
float temp;
sw32_r_skyspeed = iskyspeed;
g = GreatestCommonDivisor (iskyspeed, iskyspeed2);
s1 = iskyspeed / g;
s2 = iskyspeed2 / g;
temp = SKYSIZE * s1 * s2;
sw32_r_skytime = vr_data.realtime - ((int) (vr_data.realtime / temp) * temp);
sw32_r_skymade = 0;
}
/*
Stub function for loading a skybox. Currently we have support for
skyboxes only in GL targets, so we just do nothing here. --KB
*/
void
sw32_R_LoadSkys (const char *name)
{
}

View file

@ -1,261 +0,0 @@
/*
sw32_rsprite.c
(description)
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <string.h>
#endif
#include <math.h>
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "r_internal.h"
static int clip_current;
static vec5_t clip_verts[2][MAXWORKINGVERTS];
static int sprite_width, sprite_height;
spritedesc_t sw32_r_spritedesc;
static void
R_RotateSprite (float beamlength)
{
vec3_t vec;
if (beamlength == 0.0)
return;
VectorScale (sw32_r_spritedesc.vpn, -beamlength, vec);
VectorAdd (r_entorigin, vec, r_entorigin);
VectorSubtract (modelorg, vec, modelorg);
}
/*
R_ClipSpriteFace
Clips the winding at clip_verts[clip_current] and changes clip_current
Throws out the back side
*/
static int
R_ClipSpriteFace (int nump, clipplane_t *pclipplane)
{
int i, outcount;
float dists[MAXWORKINGVERTS + 1];
float frac, clipdist, *pclipnormal;
float *in, *instep, *outstep, *vert2;
clipdist = pclipplane->dist;
pclipnormal = pclipplane->normal;
// calc dists
if (clip_current) {
in = clip_verts[1][0];
outstep = clip_verts[0][0];
clip_current = 0;
} else {
in = clip_verts[0][0];
outstep = clip_verts[1][0];
clip_current = 1;
}
instep = in;
for (i = 0; i < nump; i++, instep += sizeof (vec5_t) / sizeof (float)) {
dists[i] = DotProduct (instep, pclipnormal) - clipdist;
}
// handle wraparound case
dists[nump] = dists[0];
memcpy (instep, in, sizeof (vec5_t));
// clip the winding
instep = in;
outcount = 0;
for (i = 0; i < nump; i++, instep += sizeof (vec5_t) / sizeof (float)) {
if (dists[i] >= 0) {
memcpy (outstep, instep, sizeof (vec5_t));
outstep += sizeof (vec5_t) / sizeof (float);
outcount++;
}
if (dists[i] == 0 || dists[i + 1] == 0)
continue;
if ((dists[i] > 0) == (dists[i + 1] > 0))
continue;
// split it into a new vertex
frac = dists[i] / (dists[i] - dists[i + 1]);
vert2 = instep + sizeof (vec5_t) / sizeof (float);
outstep[0] = instep[0] + frac * (vert2[0] - instep[0]);
outstep[1] = instep[1] + frac * (vert2[1] - instep[1]);
outstep[2] = instep[2] + frac * (vert2[2] - instep[2]);
outstep[3] = instep[3] + frac * (vert2[3] - instep[3]);
outstep[4] = instep[4] + frac * (vert2[4] - instep[4]);
outstep += sizeof (vec5_t) / sizeof (float);
outcount++;
}
return outcount;
}
static void
R_SetupAndDrawSprite (void)
{
int i, nump;
float dot, scale, *pv;
vec5_t *pverts;
vec3_t left, up, right, down, transformed, local;
emitpoint_t outverts[MAXWORKINGVERTS + 1], *pout;
dot = DotProduct (sw32_r_spritedesc.vpn, modelorg);
// backface cull
if (dot >= 0)
return;
// build the sprite poster in worldspace
VectorScale (sw32_r_spritedesc.vright, sw32_r_spritedesc.pspriteframe->right, right);
VectorScale (sw32_r_spritedesc.vup, sw32_r_spritedesc.pspriteframe->up, up);
VectorScale (sw32_r_spritedesc.vright, sw32_r_spritedesc.pspriteframe->left, left);
VectorScale (sw32_r_spritedesc.vup, sw32_r_spritedesc.pspriteframe->down, down);
pverts = clip_verts[0];
pverts[0][0] = r_entorigin[0] + up[0] + left[0];
pverts[0][1] = r_entorigin[1] + up[1] + left[1];
pverts[0][2] = r_entorigin[2] + up[2] + left[2];
pverts[0][3] = 0;
pverts[0][4] = 0;
pverts[1][0] = r_entorigin[0] + up[0] + right[0];
pverts[1][1] = r_entorigin[1] + up[1] + right[1];
pverts[1][2] = r_entorigin[2] + up[2] + right[2];
pverts[1][3] = sprite_width;
pverts[1][4] = 0;
pverts[2][0] = r_entorigin[0] + down[0] + right[0];
pverts[2][1] = r_entorigin[1] + down[1] + right[1];
pverts[2][2] = r_entorigin[2] + down[2] + right[2];
pverts[2][3] = sprite_width;
pverts[2][4] = sprite_height;
pverts[3][0] = r_entorigin[0] + down[0] + left[0];
pverts[3][1] = r_entorigin[1] + down[1] + left[1];
pverts[3][2] = r_entorigin[2] + down[2] + left[2];
pverts[3][3] = 0;
pverts[3][4] = sprite_height;
// clip to the frustum in worldspace
nump = 4;
clip_current = 0;
for (i = 0; i < 4; i++) {
nump = R_ClipSpriteFace (nump, &sw32_view_clipplanes[i]);
if (nump < 3)
return;
if (nump >= MAXWORKINGVERTS)
Sys_Error ("R_SetupAndDrawSprite: too many points");
}
// transform vertices into viewspace and project
pv = &clip_verts[clip_current][0][0];
sw32_r_spritedesc.nearzi = -999999;
for (i = 0; i < nump; i++) {
VectorSubtract (pv, r_origin, local);
sw32_TransformVector (local, transformed);
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
pout = &outverts[i];
pout->zi = 1.0 / transformed[2];
if (pout->zi > sw32_r_spritedesc.nearzi)
sw32_r_spritedesc.nearzi = pout->zi;
pout->s = pv[3];
pout->t = pv[4];
scale = sw32_xscale * pout->zi;
pout->u = (sw32_xcenter + scale * transformed[0]);
scale = sw32_yscale * pout->zi;
pout->v = (sw32_ycenter - scale * transformed[1]);
pv += sizeof (vec5_t) / sizeof (*pv);
}
// draw it
sw32_r_spritedesc.nump = nump;
sw32_r_spritedesc.pverts = outverts;
sw32_D_DrawSprite ();
}
void
sw32_R_DrawSprite (void)
{
msprite_t *sprite = currententity->renderer.model->cache.data;
sw32_r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite,
&currententity->animation);
sprite_width = sw32_r_spritedesc.pspriteframe->width;
sprite_height = sw32_r_spritedesc.pspriteframe->height;
if (!R_BillboardFrame (currententity, sprite->type, modelorg,
r_spritedesc.vup,
r_spritedesc.vright,
r_spritedesc.vpn)) {
// the orientation is undefined so can't draw the sprite
return;
}
R_RotateSprite (sprite->beamlength);
R_SetupAndDrawSprite ();
}

View file

@ -1,898 +0,0 @@
/*
sw32_rsurf.c
surface-related refresh code
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "compat.h"
#include "r_internal.h"
#include "vid_sw.h"
drawsurf_t sw32_r_drawsurf;
static int lightleft, blocksize, sourcetstep;
static int lightright, lightleftstep, lightrightstep, blockdivshift;
static unsigned int blockdivmask;
static byte *prowdestbase;
static byte *psource;
static int surfrowbytes;
static int *r_lightptr;
static int r_stepback;
static int r_lightwidth;
static int r_numhblocks, r_numvblocks;
static byte *r_source, *r_sourcemax;
static void R_DrawSurfaceBlock8_mip0 (void);
static void R_DrawSurfaceBlock8_mip1 (void);
static void R_DrawSurfaceBlock8_mip2 (void);
static void R_DrawSurfaceBlock8_mip3 (void);
static void R_DrawSurfaceBlock16_mip0 (void);
static void R_DrawSurfaceBlock16_mip1 (void);
static void R_DrawSurfaceBlock16_mip2 (void);
static void R_DrawSurfaceBlock16_mip3 (void);
static void R_DrawSurfaceBlock32_mip0 (void);
static void R_DrawSurfaceBlock32_mip1 (void);
static void R_DrawSurfaceBlock32_mip2 (void);
static void R_DrawSurfaceBlock32_mip3 (void);
static void (*surfmiptable8[4]) (void) = {
R_DrawSurfaceBlock8_mip0,
R_DrawSurfaceBlock8_mip1,
R_DrawSurfaceBlock8_mip2,
R_DrawSurfaceBlock8_mip3
};
static void (*surfmiptable16[4]) (void) = {
R_DrawSurfaceBlock16_mip0,
R_DrawSurfaceBlock16_mip1,
R_DrawSurfaceBlock16_mip2,
R_DrawSurfaceBlock16_mip3
};
static void (*surfmiptable32[4]) (void) = {
R_DrawSurfaceBlock32_mip0,
R_DrawSurfaceBlock32_mip1,
R_DrawSurfaceBlock32_mip2,
R_DrawSurfaceBlock32_mip3
};
static int blocklights[34 * 34]; //FIXME make dynamic
static void
R_AddDynamicLights (void)
{
msurface_t *surf;
unsigned int lnum;
int sd, td;
float dist, rad, minlight;
vec3_t impact, local, lightorigin;
vec4f_t entorigin = { 0, 0, 0, 1 };
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
surf = sw32_r_drawsurf.surf;
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
tex = surf->texinfo;
if (currententity->transform) {
//FIXME give world entity a transform
entorigin = Transform_GetWorldPosition (currententity->transform);
}
for (lnum = 0; lnum < r_maxdlights; lnum++) {
if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32))))
continue; // not lit by this light
VectorSubtract (r_dlights[lnum].origin, entorigin, lightorigin);
rad = r_dlights[lnum].radius;
dist = DotProduct (lightorigin, surf->plane->normal) -
surf->plane->dist;
rad -= fabs (dist);
minlight = r_dlights[lnum].minlight;
if (rad < minlight)
continue;
minlight = rad - minlight;
for (i = 0; i < 3; i++)
impact[i] = lightorigin[i] - surf->plane->normal[i] * dist;
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
local[0] -= surf->texturemins[0];
local[1] -= surf->texturemins[1];
for (t = 0; t < tmax; t++) {
td = local[1] - t * 16;
if (td < 0)
td = -td;
for (s = 0; s < smax; s++) {
sd = local[0] - s * 16;
if (sd < 0)
sd = -sd;
if (sd > td)
dist = sd + (td >> 1);
else
dist = td + (sd >> 1);
if (dist < minlight)
blocklights[t * smax + s] += (rad - dist) * 256;
}
}
}
}
/*
R_BuildLightMap
Combine and scale multiple lightmaps into the 8.8 format in blocklights
*/
static void
R_BuildLightMap (void)
{
int smax, tmax;
int t;
int i, size;
byte *lightmap;
unsigned int scale;
int maps;
msurface_t *surf;
surf = sw32_r_drawsurf.surf;
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
size = smax * tmax;
lightmap = surf->samples;
if (!r_worldentity.renderer.model->brush.lightdata) {
for (i = 0; i < size; i++)
blocklights[i] = 0;
return;
}
// clear to ambient
for (i = 0; i < size; i++)
blocklights[i] = r_refdef.ambientlight << 8;
// add all the lightmaps
if (lightmap)
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) {
scale = sw32_r_drawsurf.lightadj[maps]; // 8.8 fraction
for (i = 0; i < size; i++)
blocklights[i] += lightmap[i] * scale;
lightmap += size; // skip to next lightmap
}
// add all the dynamic lights
if (surf->dlightframe == r_framecount)
R_AddDynamicLights ();
/*
* JohnnyonFlame:
* 32 and 16bpp modes uses the positive lighting, unlike 8bpp
*/
switch (sw32_ctx->pixbytes) {
case 1:
// bound, invert, and shift
for (i = 0; i < size; i++) {
t = (255 * 256 - blocklights[i]) >> (8 - VID_CBITS);
if (t < (1 << 6))
t = (1 << 6);
blocklights[i] = t;
}
break;
default:
// LordHavoc: changed to positive (not inverse) lighting
for (i = 0; i < size; i++) {
t = bound(256, blocklights[i] >> (8 - VID_CBITS),
256 * (VID_GRADES - 1));
blocklights[i] = t;
}
break;
}
}
void
sw32_R_DrawSurface (void)
{
byte *basetptr;
int smax, tmax, twidth;
int u;
int soffset, basetoffset, texwidth;
int horzblockstep;
byte *pcolumndest;
void (*pblockdrawer) (void);
texture_t *mt;
// calculate the lightings
R_BuildLightMap ();
surfrowbytes = sw32_r_drawsurf.rowbytes;
mt = sw32_r_drawsurf.texture;
r_source = (byte *) mt + mt->offsets[sw32_r_drawsurf.surfmip];
// the fractional light values should range from 0 to
// (VID_GRADES - 1) << 16 from a source range of 0 - 255
texwidth = mt->width >> sw32_r_drawsurf.surfmip;
blocksize = 16 >> sw32_r_drawsurf.surfmip;
blockdivshift = 4 - sw32_r_drawsurf.surfmip;
blockdivmask = (1 << blockdivshift) - 1;
r_lightwidth = (sw32_r_drawsurf.surf->extents[0] >> 4) + 1;
r_numhblocks = sw32_r_drawsurf.surfwidth >> blockdivshift;
r_numvblocks = sw32_r_drawsurf.surfheight >> blockdivshift;
//==============================
smax = mt->width >> sw32_r_drawsurf.surfmip;
twidth = texwidth;
tmax = mt->height >> sw32_r_drawsurf.surfmip;
sourcetstep = texwidth;
r_stepback = tmax * twidth;
soffset = sw32_r_drawsurf.surf->texturemins[0];
basetoffset = sw32_r_drawsurf.surf->texturemins[1];
switch (sw32_ctx->pixbytes) {
case 1:
pblockdrawer = surfmiptable8[sw32_r_drawsurf.surfmip];
break;
case 2:
pblockdrawer = surfmiptable16[sw32_r_drawsurf.surfmip];
break;
case 4:
pblockdrawer = surfmiptable32[sw32_r_drawsurf.surfmip];
break;
default:
Sys_Error("R_DrawSurface: unsupported r_pixbytes %i", sw32_ctx->pixbytes);
pblockdrawer = NULL;
}
horzblockstep = blocksize * sw32_ctx->pixbytes;
r_sourcemax = r_source + (tmax * smax);
// << 16 components are to guarantee positive values for %
basetptr = r_source + (((basetoffset >> sw32_r_drawsurf.surfmip) +
(tmax << 16)) % tmax) * twidth;
soffset = (((soffset >> sw32_r_drawsurf.surfmip) + (smax << 16)) % smax);
pcolumndest = (byte *) sw32_r_drawsurf.surfdat;
for (u = 0; u < r_numhblocks; u++) {
r_lightptr = blocklights + u;
prowdestbase = pcolumndest;
psource = basetptr + soffset;
(*pblockdrawer) ();
soffset = soffset + blocksize;
if (soffset >= smax)
soffset = 0;
pcolumndest += horzblockstep;
}
}
//=============================================================================
static void
R_DrawSurfaceBlock8_mip0 (void)
{
int v, i, b, lightstep, light;
unsigned char pix, *prowdest;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 4;
lightrightstep = (r_lightptr[1] - lightright) >> 4;
for (i = 0; i < 16; i++) {
lightstep = (lightleft - lightright) >> 4;
light = lightright;
for (b = 15; b >= 0; b--) {
pix = psource[b];
prowdest[b] = vid.colormap8[(light & 0xFF00) + pix];
light += lightstep;
}
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += surfrowbytes;
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock8_mip1 (void)
{
int v, i, b, lightstep, light;
unsigned char pix, *prowdest;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 3;
lightrightstep = (r_lightptr[1] - lightright) >> 3;
for (i = 0; i < 8; i++) {
lightstep = (lightleft - lightright) >> 3;
light = lightright;
for (b = 7; b >= 0; b--) {
pix = psource[b];
prowdest[b] = vid.colormap8[(light & 0xFF00) + pix];
light += lightstep;
}
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += surfrowbytes;
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock8_mip2 (void)
{
int v, i, b, lightstep, light;
unsigned char pix, *prowdest;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 2;
lightrightstep = (r_lightptr[1] - lightright) >> 2;
for (i = 0; i < 4; i++) {
lightstep = (lightleft - lightright) >> 2;
light = lightright;
for (b = 3; b >= 0; b--) {
pix = psource[b];
prowdest[b] = vid.colormap8[(light & 0xFF00) + pix];
light += lightstep;
}
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += surfrowbytes;
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock8_mip3 (void)
{
int v, i, b, lightstep, light;
unsigned char pix, *prowdest;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 1;
lightrightstep = (r_lightptr[1] - lightright) >> 1;
for (i = 0; i < 2; i++) {
lightstep = (lightleft - lightright) >> 1;
light = lightright;
for (b = 1; b >= 0; b--) {
pix = psource[b];
prowdest[b] = vid.colormap8[(light & 0xFF00) + pix];
light += lightstep;
}
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += surfrowbytes;
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock16_mip0 (void)
{
int k, v;
int lightstep, light;
unsigned short *prowdest;
prowdest = (unsigned short *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 4;
lightrightstep = (r_lightptr[1] - lightright) >> 4;
for (k = 0; k < 16; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 4;
prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]];
light += lightstep;
prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]];
light += lightstep;
prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]];
light += lightstep;
prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]];
light += lightstep;
prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]];
light += lightstep;
prowdest[8] = vid.colormap16[(light & 0xFF00) + psource[8]];
light += lightstep;
prowdest[9] = vid.colormap16[(light & 0xFF00) + psource[9]];
light += lightstep;
prowdest[10] = vid.colormap16[(light & 0xFF00) + psource[10]];
light += lightstep;
prowdest[11] = vid.colormap16[(light & 0xFF00) + psource[11]];
light += lightstep;
prowdest[12] = vid.colormap16[(light & 0xFF00) + psource[12]];
light += lightstep;
prowdest[13] = vid.colormap16[(light & 0xFF00) + psource[13]];
light += lightstep;
prowdest[14] = vid.colormap16[(light & 0xFF00) + psource[14]];
light += lightstep;
prowdest[15] = vid.colormap16[(light & 0xFF00) + psource[15]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 1);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock16_mip1 (void)
{
int k, v;
int lightstep, light;
unsigned short *prowdest;
prowdest = (unsigned short *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 3;
lightrightstep = (r_lightptr[1] - lightright) >> 3;
for (k = 0; k < 8; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 3;
prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]];
light += lightstep;
prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]];
light += lightstep;
prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]];
light += lightstep;
prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]];
light += lightstep;
prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 1);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock16_mip2 (void)
{
int k, v;
int lightstep, light;
unsigned short *prowdest;
prowdest = (unsigned short *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 2;
lightrightstep = (r_lightptr[1] - lightright) >> 2;
for (k = 0; k < 4; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 2;
prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 1);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock16_mip3 (void)
{
int v;
unsigned short *prowdest;
prowdest = (unsigned short *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 1;
lightrightstep = (r_lightptr[1] - lightright) >> 1;
prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]];
prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) &
0xFF00) + psource[1]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 1);
prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]];
prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) &
0xFF00) + psource[1]];
psource += sourcetstep;
prowdest += (surfrowbytes >> 1);
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock32_mip0 (void)
{
int k, v;
int lightstep, light;
unsigned int *prowdest;
prowdest = (unsigned int *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 4;
lightrightstep = (r_lightptr[1] - lightright) >> 4;
for (k = 0; k < 16; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 4;
prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]];
light += lightstep;
prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]];
light += lightstep;
prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]];
light += lightstep;
prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]];
light += lightstep;
prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]];
light += lightstep;
prowdest[8] = vid.colormap32[(light & 0xFF00) + psource[8]];
light += lightstep;
prowdest[9] = vid.colormap32[(light & 0xFF00) + psource[9]];
light += lightstep;
prowdest[10] = vid.colormap32[(light & 0xFF00) + psource[10]];
light += lightstep;
prowdest[11] = vid.colormap32[(light & 0xFF00) + psource[11]];
light += lightstep;
prowdest[12] = vid.colormap32[(light & 0xFF00) + psource[12]];
light += lightstep;
prowdest[13] = vid.colormap32[(light & 0xFF00) + psource[13]];
light += lightstep;
prowdest[14] = vid.colormap32[(light & 0xFF00) + psource[14]];
light += lightstep;
prowdest[15] = vid.colormap32[(light & 0xFF00) + psource[15]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock32_mip1 (void)
{
int k, v;
int lightstep, light;
unsigned int *prowdest;
prowdest = (unsigned int *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 3;
lightrightstep = (r_lightptr[1] - lightright) >> 3;
for (k = 0; k < 8; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 3;
prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]];
light += lightstep;
prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]];
light += lightstep;
prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]];
light += lightstep;
prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]];
light += lightstep;
prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock32_mip2 (void)
{
int k, v;
int lightstep, light;
unsigned int *prowdest;
prowdest = (unsigned int *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 2;
lightrightstep = (r_lightptr[1] - lightright) >> 2;
for (k = 0; k < 4; k++)
{
light = lightleft;
lightstep = (lightright - lightleft) >> 2;
prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]];
light += lightstep;
prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]];
light += lightstep;
prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]];
light += lightstep;
prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
static void
R_DrawSurfaceBlock32_mip3 (void)
{
int v;
unsigned int *prowdest;
prowdest = (unsigned int *) prowdestbase;
for (v = 0; v < r_numvblocks; v++)
{
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> 1;
lightrightstep = (r_lightptr[1] - lightright) >> 1;
prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]];
prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) &
0xFF00) + psource[1]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]];
prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) &
0xFF00) + psource[1]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
/*
void
R_DrawSurfaceBlock32 (void)
{
int k, v;
int lightstep, light;
unsigned int *prowdest;
prowdest = prowdestbase;
for (v = 0; v < r_numvblocks; v++) {
lightleft = r_lightptr[0];
lightright = r_lightptr[1];
r_lightptr += r_lightwidth;
lightleftstep = (r_lightptr[0] - lightleft) >> blockdivshift;
lightrightstep = (r_lightptr[1] - lightright) >> blockdivshift;
for (k = 0; k < blocksize; k++) {
int b;
lightstep = (lightright - lightleft) >> blockdivshift;
light = lightleft;
for (b = 0;b < blocksize;b++, light += lightstep)
prowdest[b] = vid.colormap32[(light & 0xFF00) + psource[b]];
psource += sourcetstep;
lightright += lightrightstep;
lightleft += lightleftstep;
prowdest += (surfrowbytes >> 2);
}
if (psource >= r_sourcemax)
psource -= r_stepback;
}
}
*/

View file

@ -1,157 +0,0 @@
/*
vid_common_sw32.c
general video driver functions
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/cvar.h"
#include "QF/mathlib.h"
#include "QF/qargs.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/vid.h"
#include "compat.h"
#include "r_internal.h"
#include "vid_internal.h"
unsigned short sw32_8to16table[256];
/*
VID_MakeColormap32
LordHavoc: makes a 32bit color*light table, RGBA order, no endian,
may need to be re-ordered to hardware at display time
*/
static void
VID_MakeColormap32 (void *outcolormap, byte *pal)
{
int c, l;
byte *out;
out = (byte *)&d_8to24table;
/*
* Generates colors not affected by lighting, such as
* HUD pieces and general sprites (such as explosions)
*/
for (c = 0; c < 256; c++) {
*out++ = pal[c*3+2];
*out++ = pal[c*3+1];
*out++ = pal[c*3+0];
*out++ = 255;
}
d_8to24table[255] = 0; // 255 is transparent
out = (byte *) outcolormap;
/*
* Generates colors affected by lighting, such as the
* world and other models that give it life, like foes and pickups.
*/
for (l = 0;l < VID_GRADES;l++)
{
for (c = 0;c < vid.fullbright;c++)
{
out[(l*256+c)*4+0] = bound(0, (pal[c*3+2] * l) >> (VID_CBITS - 1),
255);
out[(l*256+c)*4+1] = bound(0, (pal[c*3+1] * l) >> (VID_CBITS - 1),
255);
out[(l*256+c)*4+2] = bound(0, (pal[c*3+0] * l) >> (VID_CBITS - 1),
255);
out[(l*256+c)*4+3] = 255;
}
for (;c < 255;c++)
{
out[(l*256+c)*4+0] = pal[c*3+2];
out[(l*256+c)*4+1] = pal[c*3+1];
out[(l*256+c)*4+2] = pal[c*3+0];
out[(l*256+c)*4+3] = 255;
}
out[(l*256+255)*4+0] = 0;
out[(l*256+255)*4+1] = 0;
out[(l*256+255)*4+2] = 0;
out[(l*256+255)*4+3] = 0;
}
}
static unsigned short
lh24to16bit (int red, int green, int blue)
{
red = bound(0, red, 255);
green = bound(0, green, 255);
blue = bound(0, blue, 255);
red >>= 3;
green >>= 2;
blue >>= 3;
red <<= 11;
green <<= 5;
return (unsigned short) (red | green | blue);
}
/*
VID_MakeColormap16
LordHavoc: makes a 16bit color*light table, RGB order, native endian,
may need to be translated to hardware order at display time
*/
static void
VID_MakeColormap16 (void *outcolormap, byte *pal)
{
int c, l;
unsigned short *out;
out = (unsigned short *)&sw32_8to16table;
for (c = 0; c < 256; c++)
*out++ = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
sw32_8to16table[255] = 0; // 255 is transparent
out = (unsigned short *) outcolormap;
for (l = 0;l < VID_GRADES;l++)
{
for (c = 0;c < vid.fullbright;c++)
out[l*256+c] = lh24to16bit(
(pal[c*3+0] * l) >> (VID_CBITS - 1),
(pal[c*3+1] * l) >> (VID_CBITS - 1),
(pal[c*3+2] * l) >> (VID_CBITS - 1));
for (;c < 255;c++)
out[l*256+c] = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
out[l*256+255] = 0;
}
}
/*
VID_MakeColormaps
LordHavoc: makes 8bit, 16bit, and 32bit colormaps and palettes
*/
void
VID_MakeColormaps (void)
{
vid.colormap16 = malloc (256*VID_GRADES * sizeof (unsigned short));
vid.colormap32 = malloc (256*VID_GRADES * sizeof (unsigned int));
SYS_CHECKMEM (vid.colormap16 && vid.colormap32);
VID_MakeColormap16(vid.colormap16, vid.palette);
VID_MakeColormap32(vid.colormap32, vid.palette);
}

View file

@ -1,232 +0,0 @@
/*
vid_render_gl.c
SW32 version of the renderer
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
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
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define NH_DEFINE
#include "sw32/namehack.h"
#include "QF/plugin/general.h"
#include "QF/plugin/vid_render.h"
#include "QF/ui/view.h"
#include "mod_internal.h"
#include "r_internal.h"
#include "vid_internal.h"
#include "vid_sw.h"
#include "sw32/namehack.h"
sw_ctx_t *sw32_ctx;
static void
sw32_vid_render_choose_visual (void *data)
{
sw32_ctx->choose_visual (sw32_ctx);
}
static void
sw32_vid_render_create_context (void *data)
{
sw32_ctx->create_context (sw32_ctx);
}
static void
sw32_vid_render_set_palette (void *data, const byte *palette)
{
sw32_ctx->set_palette (sw32_ctx, palette);
}
static vid_model_funcs_t model_funcs = {
0,
sw_Mod_LoadLighting,
0,//Mod_SubdivideSurface,
0,//Mod_ProcessTexture,
Mod_LoadIQM,
Mod_LoadAliasModel,
Mod_LoadSpriteModel,
sw_Mod_MakeAliasModelDisplayLists,
sw_Mod_LoadSkin,
0,
0,
sw_Mod_IQMFinish,
1,
sw_Mod_SpriteLoadFrames,
Skin_SetColormap,
Skin_SetSkin,
sw_Skin_SetupSkin,
Skin_SetTranslation,
sw_Skin_ProcessTranslation,
sw_Skin_InitTranslations,
};
static void
sw32_vid_render_init (void)
{
if (!vr_data.vid->vid_internal->sw_context) {
Sys_Error ("Sorry, software rendering not supported by this program.");
}
sw32_ctx = vr_data.vid->vid_internal->sw32_context ();
vr_data.vid->vid_internal->data = sw32_ctx;
vr_data.vid->vid_internal->set_palette = sw32_vid_render_set_palette;
vr_data.vid->vid_internal->choose_visual = sw32_vid_render_choose_visual;
vr_data.vid->vid_internal->create_context = sw32_vid_render_create_context;
vr_funcs = &sw32_vid_render_funcs;
m_funcs = &model_funcs;
}
static void
sw32_vid_render_shutdown (void)
{
}
static void
sw32_begin_frame (void)
{
if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen
vr_data.scr_copyeverything = 1;
sw32_Draw_TileClear (0, 0, vid.width, vid.height);
}
}
static void
sw32_render_view (void)
{
sw32_R_RenderView ();
}
static void
sw32_set_2d (void)
{
}
static void
sw32_end_frame (void)
{
// update one of three areas
vrect_t vrect;
if (vr_data.scr_copyeverything) {
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
vrect.next = 0;
} else if (scr_copytop) {
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height - vr_data.lineadj;
vrect.next = 0;
} else {
vrect.x = vr_data.scr_view->xpos;
vrect.y = vr_data.scr_view->ypos;
vrect.width = vr_data.scr_view->xlen;
vrect.height = vr_data.scr_view->ylen;
vrect.next = 0;
}
sw32_ctx->update (sw32_ctx, &vrect);
}
vid_render_funcs_t sw32_vid_render_funcs = {
sw32_vid_render_init,
sw32_Draw_Character,
sw32_Draw_String,
sw32_Draw_nString,
sw32_Draw_AltString,
sw32_Draw_ConsoleBackground,
sw32_Draw_Crosshair,
sw32_Draw_CrosshairAt,
sw32_Draw_TileClear,
sw32_Draw_Fill,
sw32_Draw_TextBox,
sw32_Draw_FadeScreen,
sw32_Draw_BlendScreen,
sw32_Draw_CachePic,
sw32_Draw_UncachePic,
sw32_Draw_MakePic,
sw32_Draw_DestroyPic,
sw32_Draw_PicFromWad,
sw32_Draw_Pic,
sw32_Draw_Picf,
sw32_Draw_SubPic,
sw32_SCR_CaptureBGR,
sw32_ParticleSystem,
sw32_R_Init,
sw32_R_ClearState,
sw32_R_LoadSkys,
sw32_R_NewMap,
sw32_R_LineGraph,
sw32_R_ViewChanged,
sw32_begin_frame,
sw32_render_view,
sw32_set_2d,
sw32_end_frame,
&model_funcs
};
static general_funcs_t plugin_info_general_funcs = {
.shutdown = sw32_vid_render_shutdown,
};
static general_data_t plugin_info_general_data;
static plugin_funcs_t plugin_info_funcs = {
.general = &plugin_info_general_funcs,
.vid_render = &sw32_vid_render_funcs,
};
static plugin_data_t plugin_info_data = {
.general = &plugin_info_general_data,
.vid_render = &vid_render_data,
};
static plugin_t plugin_info = {
qfp_vid_render,
0,
QFPLUGIN_VERSION,
"0.1",
"SW32 Renderer",
"Copyright (C) 1996-1997 Id Software, Inc.\n"
"Copyright (C) 1999-2012 contributors of the QuakeForge project\n"
"Please see the file \"AUTHORS\" for a list of contributors",
&plugin_info_funcs,
&plugin_info_data,
};
PLUGIN_INFO(vid_render, sw32)
{
return &plugin_info;
}

View file

@ -110,8 +110,6 @@ modestate_t modestate = MS_UNINIT;
byte vid_curpal[256 * 3];
unsigned short d_8to16table[256];
int mode;
typedef struct {

View file

@ -101,7 +101,6 @@ VID_Init (byte *palette, byte *colormap)
vid_internal.gl_context = X11_GL_Context;
vid_internal.sw_context = X11_SW_Context;
vid_internal.sw32_context = X11_SW32_Context;
#ifdef HAVE_VULKAN
vid_internal.vulkan_context = X11_Vulkan_Context;
#endif

View file

@ -642,18 +642,6 @@ x11_create_context (sw_ctx_t *ctx)
sw_ctx_t *
X11_SW_Context (void)
{
sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t));
ctx->pixbytes = 1;
ctx->set_palette = x11_set_palette;
ctx->choose_visual = x11_choose_visual;
ctx->create_context = x11_create_context;
ctx->update = x11_sw8_update;
return ctx;
}
sw_ctx_t *
X11_SW32_Context (void)
{
sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t));
ctx->pixbytes = 1;