<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">[PATCH] Move r_sprite.c to common directory

No code changes, just move the file and remove the duplicate.

diff -urN a/NQ/r_sprite.c head/NQ/r_sprite.c
--- a/NQ/r_sprite.c	2006-02-19 09:16:04.000000000 +1030
+++ head/NQ/r_sprite.c	1970-01-01 09:30:00.000000000 +0930
@@ -1,381 +0,0 @@
-/*
-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 the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-// r_sprite.c
-
-#include "console.h"
-#include "quakedef.h"
-#include "r_local.h"
-#include "sys.h"
-
-static int clip_current;
-static vec5_t clip_verts[2][MAXWORKINGVERTS];
-static int sprite_width, sprite_height;
-
-spritedesc_t r_spritedesc;
-
-
-/*
-================
-R_RotateSprite
-================
-*/
-static void
-R_RotateSprite(float beamlength)
-{
-    vec3_t vec;
-
-    if (beamlength == 0.0)
-	return;
-
-    VectorScale(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-&gt;dist;
-    pclipnormal = pclipplane-&gt;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 &lt; 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 &lt; nump; i++, instep += sizeof(vec5_t) / sizeof(float)) {
-	if (dists[i] &gt;= 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] &gt; 0) == (dists[i + 1] &gt; 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;
-}
-
-
-/*
-================
-R_SetupAndDrawSprite
-================
-*/
-static void
-R_SetupAndDrawSprite()
-{
-    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(r_spritedesc.vpn, modelorg);
-
-// backface cull
-    if (dot &gt;= 0)
-	return;
-
-// build the sprite poster in worldspace
-    VectorScale(r_spritedesc.vright, r_spritedesc.pspriteframe-&gt;right, right);
-    VectorScale(r_spritedesc.vup, r_spritedesc.pspriteframe-&gt;up, up);
-    VectorScale(r_spritedesc.vright, r_spritedesc.pspriteframe-&gt;left, left);
-    VectorScale(r_spritedesc.vup, r_spritedesc.pspriteframe-&gt;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 &lt; 4; i++) {
-	nump = R_ClipSpriteFace(nump, &amp;view_clipplanes[i]);
-	if (nump &lt; 3)
-	    return;
-	if (nump &gt;= MAXWORKINGVERTS)
-	    Sys_Error("%s: too many points", __func__);
-    }
-
-// transform vertices into viewspace and project
-    pv = &amp;clip_verts[clip_current][0][0];
-    r_spritedesc.nearzi = -999999;
-
-    for (i = 0; i &lt; nump; i++) {
-	VectorSubtract(pv, r_origin, local);
-	TransformVector(local, transformed);
-
-	if (transformed[2] &lt; NEAR_CLIP)
-	    transformed[2] = NEAR_CLIP;
-
-	pout = &amp;outverts[i];
-	pout-&gt;zi = 1.0 / transformed[2];
-	if (pout-&gt;zi &gt; r_spritedesc.nearzi)
-	    r_spritedesc.nearzi = pout-&gt;zi;
-
-	pout-&gt;s = pv[3];
-	pout-&gt;t = pv[4];
-
-	scale = xscale * pout-&gt;zi;
-	pout-&gt;u = (xcenter + scale * transformed[0]);
-
-	scale = yscale * pout-&gt;zi;
-	pout-&gt;v = (ycenter - scale * transformed[1]);
-
-	pv += sizeof(vec5_t) / sizeof(*pv);
-    }
-
-// draw it
-    r_spritedesc.nump = nump;
-    r_spritedesc.pverts = outverts;
-    D_DrawSprite();
-}
-
-
-/*
-================
-R_GetSpriteframe
-================
-*/
-static mspriteframe_t *
-R_GetSpriteframe(msprite_t *psprite)
-{
-    mspritegroup_t *pspritegroup;
-    mspriteframe_t *pspriteframe;
-    int i, numframes, frame;
-    float *pintervals, fullinterval, targettime, time;
-
-    frame = currententity-&gt;frame;
-
-    if ((frame &gt;= psprite-&gt;numframes) || (frame &lt; 0)) {
-	Con_Printf("R_DrawSprite: no such frame %d\n", frame);
-	frame = 0;
-    }
-
-    if (psprite-&gt;frames[frame].type == SPR_SINGLE) {
-	pspriteframe = psprite-&gt;frames[frame].frameptr;
-    } else {
-	pspritegroup = (mspritegroup_t *)psprite-&gt;frames[frame].frameptr;
-	pintervals = pspritegroup-&gt;intervals;
-	numframes = pspritegroup-&gt;numframes;
-	fullinterval = pintervals[numframes - 1];
-
-	time = cl.time + currententity-&gt;syncbase;
-
-	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
-	// are positive, so we don't have to worry about division by 0
-	targettime = time - ((int)(time / fullinterval)) * fullinterval;
-
-	for (i = 0; i &lt; (numframes - 1); i++) {
-	    if (pintervals[i] &gt; targettime)
-		break;
-	}
-
-	pspriteframe = pspritegroup-&gt;frames[i];
-    }
-
-    return pspriteframe;
-}
-
-
-/*
-================
-R_DrawSprite
-================
-*/
-void
-R_DrawSprite(void)
-{
-    int i;
-    msprite_t *psprite;
-    vec3_t tvec;
-    float dot, angle, sr, cr;
-
-    psprite = currententity-&gt;model-&gt;cache.data;
-
-    r_spritedesc.pspriteframe = R_GetSpriteframe(psprite);
-
-    sprite_width = r_spritedesc.pspriteframe-&gt;width;
-    sprite_height = r_spritedesc.pspriteframe-&gt;height;
-
-// TODO: make this caller-selectable
-    if (psprite-&gt;type == SPR_FACING_UPRIGHT) {
-	// generate the sprite's axes, with vup straight up in worldspace, and
-	// r_spritedesc.vright perpendicular to modelorg.
-	// This will not work if the view direction is very close to straight up or
-	// down, because the cross product will be between two nearly parallel
-	// vectors and starts to approach an undefined state, so we don't draw if
-	// the two vectors are less than 1 degree apart
-	tvec[0] = -modelorg[0];
-	tvec[1] = -modelorg[1];
-	tvec[2] = -modelorg[2];
-	VectorNormalize(tvec);
-	dot = tvec[2];		// same as DotProduct (tvec, r_spritedesc.vup) because
-	//  r_spritedesc.vup is 0, 0, 1
-	if ((dot &gt; 0.999848) || (dot &lt; -0.999848))	// cos(1 degree) = 0.999848
-	    return;
-	r_spritedesc.vup[0] = 0;
-	r_spritedesc.vup[1] = 0;
-	r_spritedesc.vup[2] = 1;
-	r_spritedesc.vright[0] = tvec[1];
-	// CrossProduct(r_spritedesc.vup, -modelorg,
-	r_spritedesc.vright[1] = -tvec[0];
-	//              r_spritedesc.vright)
-	r_spritedesc.vright[2] = 0;
-	VectorNormalize(r_spritedesc.vright);
-	r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
-	r_spritedesc.vpn[1] = r_spritedesc.vright[0];
-	r_spritedesc.vpn[2] = 0;
-	// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
-	//  r_spritedesc.vpn)
-    } else if (psprite-&gt;type == SPR_VP_PARALLEL) {
-	// generate the sprite's axes, completely parallel to the viewplane. There
-	// are no problem situations, because the sprite is always in the same
-	// position relative to the viewer
-	for (i = 0; i &lt; 3; i++) {
-	    r_spritedesc.vup[i] = vup[i];
-	    r_spritedesc.vright[i] = vright[i];
-	    r_spritedesc.vpn[i] = vpn[i];
-	}
-    } else if (psprite-&gt;type == SPR_VP_PARALLEL_UPRIGHT) {
-	// generate the sprite's axes, with vup straight up in worldspace, and
-	// r_spritedesc.vright parallel to the viewplane.
-	// This will not work if the view direction is very close to straight up or
-	// down, because the cross product will be between two nearly parallel
-	// vectors and starts to approach an undefined state, so we don't draw if
-	// the two vectors are less than 1 degree apart
-	dot = vpn[2];		// same as DotProduct (vpn, r_spritedesc.vup) because
-	//  r_spritedesc.vup is 0, 0, 1
-	if ((dot &gt; 0.999848) || (dot &lt; -0.999848))	// cos(1 degree) = 0.999848
-	    return;
-	r_spritedesc.vup[0] = 0;
-	r_spritedesc.vup[1] = 0;
-	r_spritedesc.vup[2] = 1;
-	r_spritedesc.vright[0] = vpn[1];
-	// CrossProduct (r_spritedesc.vup, vpn,
-	r_spritedesc.vright[1] = -vpn[0];	//  r_spritedesc.vright)
-	r_spritedesc.vright[2] = 0;
-	VectorNormalize(r_spritedesc.vright);
-	r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
-	r_spritedesc.vpn[1] = r_spritedesc.vright[0];
-	r_spritedesc.vpn[2] = 0;
-	// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
-	//  r_spritedesc.vpn)
-    } else if (psprite-&gt;type == SPR_ORIENTED) {
-	// generate the sprite's axes, according to the sprite's world orientation
-	AngleVectors(currententity-&gt;angles, r_spritedesc.vpn,
-		     r_spritedesc.vright, r_spritedesc.vup);
-    } else if (psprite-&gt;type == SPR_VP_PARALLEL_ORIENTED) {
-	// generate the sprite's axes, parallel to the viewplane, but rotated in
-	// that plane around the center according to the sprite entity's roll
-	// angle. So vpn stays the same, but vright and vup rotate
-	angle = currententity-&gt;angles[ROLL] * (M_PI * 2 / 360);
-	sr = sin(angle);
-	cr = cos(angle);
-
-	for (i = 0; i &lt; 3; i++) {
-	    r_spritedesc.vpn[i] = vpn[i];
-	    r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
-	    r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
-	}
-    } else {
-	Sys_Error("%s: Bad sprite type %d", __func__, psprite-&gt;type);
-    }
-
-    R_RotateSprite(psprite-&gt;beamlength);
-
-    R_SetupAndDrawSprite();
-}
diff -urN a/QW/client/r_sprite.c head/QW/client/r_sprite.c
--- a/QW/client/r_sprite.c	2006-02-19 09:16:04.000000000 +1030
+++ head/QW/client/r_sprite.c	1970-01-01 09:30:00.000000000 +0930
@@ -1,381 +0,0 @@
-/*
-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 the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-// r_sprite.c
-
-#include "console.h"
-#include "quakedef.h"
-#include "r_local.h"
-#include "sys.h"
-
-static int clip_current;
-static vec5_t clip_verts[2][MAXWORKINGVERTS];
-static int sprite_width, sprite_height;
-
-spritedesc_t r_spritedesc;
-
-
-/*
-================
-R_RotateSprite
-================
-*/
-static void
-R_RotateSprite(float beamlength)
-{
-    vec3_t vec;
-
-    if (beamlength == 0.0)
-	return;
-
-    VectorScale(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-&gt;dist;
-    pclipnormal = pclipplane-&gt;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 &lt; 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 &lt; nump; i++, instep += sizeof(vec5_t) / sizeof(float)) {
-	if (dists[i] &gt;= 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] &gt; 0) == (dists[i + 1] &gt; 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;
-}
-
-
-/*
-================
-R_SetupAndDrawSprite
-================
-*/
-static void
-R_SetupAndDrawSprite()
-{
-    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(r_spritedesc.vpn, modelorg);
-
-// backface cull
-    if (dot &gt;= 0)
-	return;
-
-// build the sprite poster in worldspace
-    VectorScale(r_spritedesc.vright, r_spritedesc.pspriteframe-&gt;right, right);
-    VectorScale(r_spritedesc.vup, r_spritedesc.pspriteframe-&gt;up, up);
-    VectorScale(r_spritedesc.vright, r_spritedesc.pspriteframe-&gt;left, left);
-    VectorScale(r_spritedesc.vup, r_spritedesc.pspriteframe-&gt;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 &lt; 4; i++) {
-	nump = R_ClipSpriteFace(nump, &amp;view_clipplanes[i]);
-	if (nump &lt; 3)
-	    return;
-	if (nump &gt;= MAXWORKINGVERTS)
-	    Sys_Error("%s: too many points", __func__);
-    }
-
-// transform vertices into viewspace and project
-    pv = &amp;clip_verts[clip_current][0][0];
-    r_spritedesc.nearzi = -999999;
-
-    for (i = 0; i &lt; nump; i++) {
-	VectorSubtract(pv, r_origin, local);
-	TransformVector(local, transformed);
-
-	if (transformed[2] &lt; NEAR_CLIP)
-	    transformed[2] = NEAR_CLIP;
-
-	pout = &amp;outverts[i];
-	pout-&gt;zi = 1.0 / transformed[2];
-	if (pout-&gt;zi &gt; r_spritedesc.nearzi)
-	    r_spritedesc.nearzi = pout-&gt;zi;
-
-	pout-&gt;s = pv[3];
-	pout-&gt;t = pv[4];
-
-	scale = xscale * pout-&gt;zi;
-	pout-&gt;u = (xcenter + scale * transformed[0]);
-
-	scale = yscale * pout-&gt;zi;
-	pout-&gt;v = (ycenter - scale * transformed[1]);
-
-	pv += sizeof(vec5_t) / sizeof(*pv);
-    }
-
-// draw it
-    r_spritedesc.nump = nump;
-    r_spritedesc.pverts = outverts;
-    D_DrawSprite();
-}
-
-
-/*
-================
-R_GetSpriteframe
-================
-*/
-static mspriteframe_t *
-R_GetSpriteframe(msprite_t *psprite)
-{
-    mspritegroup_t *pspritegroup;
-    mspriteframe_t *pspriteframe;
-    int i, numframes, frame;
-    float *pintervals, fullinterval, targettime, time;
-
-    frame = currententity-&gt;frame;
-
-    if ((frame &gt;= psprite-&gt;numframes) || (frame &lt; 0)) {
-	Con_Printf("R_DrawSprite: no such frame %d\n", frame);
-	frame = 0;
-    }
-
-    if (psprite-&gt;frames[frame].type == SPR_SINGLE) {
-	pspriteframe = psprite-&gt;frames[frame].frameptr;
-    } else {
-	pspritegroup = (mspritegroup_t *)psprite-&gt;frames[frame].frameptr;
-	pintervals = pspritegroup-&gt;intervals;
-	numframes = pspritegroup-&gt;numframes;
-	fullinterval = pintervals[numframes - 1];
-
-	time = cl.time + currententity-&gt;syncbase;
-
-	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
-	// are positive, so we don't have to worry about division by 0
-	targettime = time - ((int)(time / fullinterval)) * fullinterval;
-
-	for (i = 0; i &lt; (numframes - 1); i++) {
-	    if (pintervals[i] &gt; targettime)
-		break;
-	}
-
-	pspriteframe = pspritegroup-&gt;frames[i];
-    }
-
-    return pspriteframe;
-}
-
-
-/*
-================
-R_DrawSprite
-================
-*/
-void
-R_DrawSprite(void)
-{
-    int i;
-    msprite_t *psprite;
-    vec3_t tvec;
-    float dot, angle, sr, cr;
-
-    psprite = currententity-&gt;model-&gt;cache.data;
-
-    r_spritedesc.pspriteframe = R_GetSpriteframe(psprite);
-
-    sprite_width = r_spritedesc.pspriteframe-&gt;width;
-    sprite_height = r_spritedesc.pspriteframe-&gt;height;
-
-// TODO: make this caller-selectable
-    if (psprite-&gt;type == SPR_FACING_UPRIGHT) {
-	// generate the sprite's axes, with vup straight up in worldspace, and
-	// r_spritedesc.vright perpendicular to modelorg.
-	// This will not work if the view direction is very close to straight up or
-	// down, because the cross product will be between two nearly parallel
-	// vectors and starts to approach an undefined state, so we don't draw if
-	// the two vectors are less than 1 degree apart
-	tvec[0] = -modelorg[0];
-	tvec[1] = -modelorg[1];
-	tvec[2] = -modelorg[2];
-	VectorNormalize(tvec);
-	dot = tvec[2];		// same as DotProduct (tvec, r_spritedesc.vup) because
-	//  r_spritedesc.vup is 0, 0, 1
-	if ((dot &gt; 0.999848) || (dot &lt; -0.999848))	// cos(1 degree) = 0.999848
-	    return;
-	r_spritedesc.vup[0] = 0;
-	r_spritedesc.vup[1] = 0;
-	r_spritedesc.vup[2] = 1;
-	r_spritedesc.vright[0] = tvec[1];
-	// CrossProduct(r_spritedesc.vup, -modelorg,
-	r_spritedesc.vright[1] = -tvec[0];
-	//              r_spritedesc.vright)
-	r_spritedesc.vright[2] = 0;
-	VectorNormalize(r_spritedesc.vright);
-	r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
-	r_spritedesc.vpn[1] = r_spritedesc.vright[0];
-	r_spritedesc.vpn[2] = 0;
-	// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
-	//  r_spritedesc.vpn)
-    } else if (psprite-&gt;type == SPR_VP_PARALLEL) {
-	// generate the sprite's axes, completely parallel to the viewplane. There
-	// are no problem situations, because the sprite is always in the same
-	// position relative to the viewer
-	for (i = 0; i &lt; 3; i++) {
-	    r_spritedesc.vup[i] = vup[i];
-	    r_spritedesc.vright[i] = vright[i];
-	    r_spritedesc.vpn[i] = vpn[i];
-	}
-    } else if (psprite-&gt;type == SPR_VP_PARALLEL_UPRIGHT) {
-	// generate the sprite's axes, with vup straight up in worldspace, and
-	// r_spritedesc.vright parallel to the viewplane.
-	// This will not work if the view direction is very close to straight up or
-	// down, because the cross product will be between two nearly parallel
-	// vectors and starts to approach an undefined state, so we don't draw if
-	// the two vectors are less than 1 degree apart
-	dot = vpn[2];		// same as DotProduct (vpn, r_spritedesc.vup) because
-	//  r_spritedesc.vup is 0, 0, 1
-	if ((dot &gt; 0.999848) || (dot &lt; -0.999848))	// cos(1 degree) = 0.999848
-	    return;
-	r_spritedesc.vup[0] = 0;
-	r_spritedesc.vup[1] = 0;
-	r_spritedesc.vup[2] = 1;
-	r_spritedesc.vright[0] = vpn[1];
-	// CrossProduct (r_spritedesc.vup, vpn,
-	r_spritedesc.vright[1] = -vpn[0];	//  r_spritedesc.vright)
-	r_spritedesc.vright[2] = 0;
-	VectorNormalize(r_spritedesc.vright);
-	r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
-	r_spritedesc.vpn[1] = r_spritedesc.vright[0];
-	r_spritedesc.vpn[2] = 0;
-	// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
-	//  r_spritedesc.vpn)
-    } else if (psprite-&gt;type == SPR_ORIENTED) {
-	// generate the sprite's axes, according to the sprite's world orientation
-	AngleVectors(currententity-&gt;angles, r_spritedesc.vpn,
-		     r_spritedesc.vright, r_spritedesc.vup);
-    } else if (psprite-&gt;type == SPR_VP_PARALLEL_ORIENTED) {
-	// generate the sprite's axes, parallel to the viewplane, but rotated in
-	// that plane around the center according to the sprite entity's roll
-	// angle. So vpn stays the same, but vright and vup rotate
-	angle = currententity-&gt;angles[ROLL] * (M_PI * 2 / 360);
-	sr = sin(angle);
-	cr = cos(angle);
-
-	for (i = 0; i &lt; 3; i++) {
-	    r_spritedesc.vpn[i] = vpn[i];
-	    r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
-	    r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
-	}
-    } else {
-	Sys_Error("%s: Bad sprite type %d", __func__, psprite-&gt;type);
-    }
-
-    R_RotateSprite(psprite-&gt;beamlength);
-
-    R_SetupAndDrawSprite();
-}
diff -urN a/common/r_sprite.c head/common/r_sprite.c
--- a/common/r_sprite.c	1970-01-01 09:30:00.000000000 +0930
+++ head/common/r_sprite.c	2006-02-19 09:09:33.000000000 +1030
@@ -0,0 +1,381 @@
+/*
+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 the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// r_sprite.c
+
+#include "console.h"
+#include "quakedef.h"
+#include "r_local.h"
+#include "sys.h"
+
+static int clip_current;
+static vec5_t clip_verts[2][MAXWORKINGVERTS];
+static int sprite_width, sprite_height;
+
+spritedesc_t r_spritedesc;
+
+
+/*
+================
+R_RotateSprite
+================
+*/
+static void
+R_RotateSprite(float beamlength)
+{
+    vec3_t vec;
+
+    if (beamlength == 0.0)
+	return;
+
+    VectorScale(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-&gt;dist;
+    pclipnormal = pclipplane-&gt;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 &lt; 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 &lt; nump; i++, instep += sizeof(vec5_t) / sizeof(float)) {
+	if (dists[i] &gt;= 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] &gt; 0) == (dists[i + 1] &gt; 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;
+}
+
+
+/*
+================
+R_SetupAndDrawSprite
+================
+*/
+static void
+R_SetupAndDrawSprite()
+{
+    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(r_spritedesc.vpn, modelorg);
+
+// backface cull
+    if (dot &gt;= 0)
+	return;
+
+// build the sprite poster in worldspace
+    VectorScale(r_spritedesc.vright, r_spritedesc.pspriteframe-&gt;right, right);
+    VectorScale(r_spritedesc.vup, r_spritedesc.pspriteframe-&gt;up, up);
+    VectorScale(r_spritedesc.vright, r_spritedesc.pspriteframe-&gt;left, left);
+    VectorScale(r_spritedesc.vup, r_spritedesc.pspriteframe-&gt;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 &lt; 4; i++) {
+	nump = R_ClipSpriteFace(nump, &amp;view_clipplanes[i]);
+	if (nump &lt; 3)
+	    return;
+	if (nump &gt;= MAXWORKINGVERTS)
+	    Sys_Error("%s: too many points", __func__);
+    }
+
+// transform vertices into viewspace and project
+    pv = &amp;clip_verts[clip_current][0][0];
+    r_spritedesc.nearzi = -999999;
+
+    for (i = 0; i &lt; nump; i++) {
+	VectorSubtract(pv, r_origin, local);
+	TransformVector(local, transformed);
+
+	if (transformed[2] &lt; NEAR_CLIP)
+	    transformed[2] = NEAR_CLIP;
+
+	pout = &amp;outverts[i];
+	pout-&gt;zi = 1.0 / transformed[2];
+	if (pout-&gt;zi &gt; r_spritedesc.nearzi)
+	    r_spritedesc.nearzi = pout-&gt;zi;
+
+	pout-&gt;s = pv[3];
+	pout-&gt;t = pv[4];
+
+	scale = xscale * pout-&gt;zi;
+	pout-&gt;u = (xcenter + scale * transformed[0]);
+
+	scale = yscale * pout-&gt;zi;
+	pout-&gt;v = (ycenter - scale * transformed[1]);
+
+	pv += sizeof(vec5_t) / sizeof(*pv);
+    }
+
+// draw it
+    r_spritedesc.nump = nump;
+    r_spritedesc.pverts = outverts;
+    D_DrawSprite();
+}
+
+
+/*
+================
+R_GetSpriteframe
+================
+*/
+static mspriteframe_t *
+R_GetSpriteframe(msprite_t *psprite)
+{
+    mspritegroup_t *pspritegroup;
+    mspriteframe_t *pspriteframe;
+    int i, numframes, frame;
+    float *pintervals, fullinterval, targettime, time;
+
+    frame = currententity-&gt;frame;
+
+    if ((frame &gt;= psprite-&gt;numframes) || (frame &lt; 0)) {
+	Con_Printf("R_DrawSprite: no such frame %d\n", frame);
+	frame = 0;
+    }
+
+    if (psprite-&gt;frames[frame].type == SPR_SINGLE) {
+	pspriteframe = psprite-&gt;frames[frame].frameptr;
+    } else {
+	pspritegroup = (mspritegroup_t *)psprite-&gt;frames[frame].frameptr;
+	pintervals = pspritegroup-&gt;intervals;
+	numframes = pspritegroup-&gt;numframes;
+	fullinterval = pintervals[numframes - 1];
+
+	time = cl.time + currententity-&gt;syncbase;
+
+	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
+	// are positive, so we don't have to worry about division by 0
+	targettime = time - ((int)(time / fullinterval)) * fullinterval;
+
+	for (i = 0; i &lt; (numframes - 1); i++) {
+	    if (pintervals[i] &gt; targettime)
+		break;
+	}
+
+	pspriteframe = pspritegroup-&gt;frames[i];
+    }
+
+    return pspriteframe;
+}
+
+
+/*
+================
+R_DrawSprite
+================
+*/
+void
+R_DrawSprite(void)
+{
+    int i;
+    msprite_t *psprite;
+    vec3_t tvec;
+    float dot, angle, sr, cr;
+
+    psprite = currententity-&gt;model-&gt;cache.data;
+
+    r_spritedesc.pspriteframe = R_GetSpriteframe(psprite);
+
+    sprite_width = r_spritedesc.pspriteframe-&gt;width;
+    sprite_height = r_spritedesc.pspriteframe-&gt;height;
+
+// TODO: make this caller-selectable
+    if (psprite-&gt;type == SPR_FACING_UPRIGHT) {
+	// generate the sprite's axes, with vup straight up in worldspace, and
+	// r_spritedesc.vright perpendicular to modelorg.
+	// This will not work if the view direction is very close to straight up or
+	// down, because the cross product will be between two nearly parallel
+	// vectors and starts to approach an undefined state, so we don't draw if
+	// the two vectors are less than 1 degree apart
+	tvec[0] = -modelorg[0];
+	tvec[1] = -modelorg[1];
+	tvec[2] = -modelorg[2];
+	VectorNormalize(tvec);
+	dot = tvec[2];		// same as DotProduct (tvec, r_spritedesc.vup) because
+	//  r_spritedesc.vup is 0, 0, 1
+	if ((dot &gt; 0.999848) || (dot &lt; -0.999848))	// cos(1 degree) = 0.999848
+	    return;
+	r_spritedesc.vup[0] = 0;
+	r_spritedesc.vup[1] = 0;
+	r_spritedesc.vup[2] = 1;
+	r_spritedesc.vright[0] = tvec[1];
+	// CrossProduct(r_spritedesc.vup, -modelorg,
+	r_spritedesc.vright[1] = -tvec[0];
+	//              r_spritedesc.vright)
+	r_spritedesc.vright[2] = 0;
+	VectorNormalize(r_spritedesc.vright);
+	r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
+	r_spritedesc.vpn[1] = r_spritedesc.vright[0];
+	r_spritedesc.vpn[2] = 0;
+	// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
+	//  r_spritedesc.vpn)
+    } else if (psprite-&gt;type == SPR_VP_PARALLEL) {
+	// generate the sprite's axes, completely parallel to the viewplane. There
+	// are no problem situations, because the sprite is always in the same
+	// position relative to the viewer
+	for (i = 0; i &lt; 3; i++) {
+	    r_spritedesc.vup[i] = vup[i];
+	    r_spritedesc.vright[i] = vright[i];
+	    r_spritedesc.vpn[i] = vpn[i];
+	}
+    } else if (psprite-&gt;type == SPR_VP_PARALLEL_UPRIGHT) {
+	// generate the sprite's axes, with vup straight up in worldspace, and
+	// r_spritedesc.vright parallel to the viewplane.
+	// This will not work if the view direction is very close to straight up or
+	// down, because the cross product will be between two nearly parallel
+	// vectors and starts to approach an undefined state, so we don't draw if
+	// the two vectors are less than 1 degree apart
+	dot = vpn[2];		// same as DotProduct (vpn, r_spritedesc.vup) because
+	//  r_spritedesc.vup is 0, 0, 1
+	if ((dot &gt; 0.999848) || (dot &lt; -0.999848))	// cos(1 degree) = 0.999848
+	    return;
+	r_spritedesc.vup[0] = 0;
+	r_spritedesc.vup[1] = 0;
+	r_spritedesc.vup[2] = 1;
+	r_spritedesc.vright[0] = vpn[1];
+	// CrossProduct (r_spritedesc.vup, vpn,
+	r_spritedesc.vright[1] = -vpn[0];	//  r_spritedesc.vright)
+	r_spritedesc.vright[2] = 0;
+	VectorNormalize(r_spritedesc.vright);
+	r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
+	r_spritedesc.vpn[1] = r_spritedesc.vright[0];
+	r_spritedesc.vpn[2] = 0;
+	// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
+	//  r_spritedesc.vpn)
+    } else if (psprite-&gt;type == SPR_ORIENTED) {
+	// generate the sprite's axes, according to the sprite's world orientation
+	AngleVectors(currententity-&gt;angles, r_spritedesc.vpn,
+		     r_spritedesc.vright, r_spritedesc.vup);
+    } else if (psprite-&gt;type == SPR_VP_PARALLEL_ORIENTED) {
+	// generate the sprite's axes, parallel to the viewplane, but rotated in
+	// that plane around the center according to the sprite entity's roll
+	// angle. So vpn stays the same, but vright and vup rotate
+	angle = currententity-&gt;angles[ROLL] * (M_PI * 2 / 360);
+	sr = sin(angle);
+	cr = cos(angle);
+
+	for (i = 0; i &lt; 3; i++) {
+	    r_spritedesc.vpn[i] = vpn[i];
+	    r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
+	    r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
+	}
+    } else {
+	Sys_Error("%s: Bad sprite type %d", __func__, psprite-&gt;type);
+    }
+
+    R_RotateSprite(psprite-&gt;beamlength);
+
+    R_SetupAndDrawSprite();
+}
</pre></body></html>