shithub: qk1

Download patch

ref: 047a4434851525bc448af3b5e3461b62605c8ed1
parent: 0928124e1e88acf3e255310397412a291e4647cf
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Jan 7 20:27:39 EST 2024

move several refdef-related globals into r_refdef as view_t

--- a/chase.c
+++ b/chase.c
@@ -39,23 +39,23 @@
 
 	// calc exact destination
 	for (i=0 ; i<3 ; i++)
-		chase_dest[i] = r_refdef.vieworg[i]
+		chase_dest[i] = r_refdef.view.org[i]
 		- forward[i]*chase_back.value
 		- right[i]*chase_right.value;
-	chase_dest[2] = r_refdef.vieworg[2] + chase_up.value;
+	chase_dest[2] = r_refdef.view.org[2] + chase_up.value;
 
 	// find the spot the player is looking at
-	VectorMA (r_refdef.vieworg, 4096, forward, dest);
-	TraceLine (r_refdef.vieworg, dest, stop);
+	VectorMA (r_refdef.view.org, 4096, forward, dest);
+	TraceLine (r_refdef.view.org, dest, stop);
 
 	// calculate pitch to look at the same spot from camera
-	VectorSubtract (stop, r_refdef.vieworg, stop);
+	VectorSubtract (stop, r_refdef.view.org, stop);
 	dist = DotProduct (stop, forward);
 	if (dist < 1)
 		dist = 1;
-	r_refdef.viewangles[PITCH] = -atanf(stop[2] / dist) / M_PI * 180;
+	r_refdef.view.angles[PITCH] = -atanf(stop[2] / dist) / M_PI * 180;
 
 	// move towards destination
-	VectorCopy (chase_dest, r_refdef.vieworg);
+	VectorCopy (chase_dest, r_refdef.view.org);
 }
 
--- a/d_alpha.c
+++ b/d_alpha.c
@@ -1,7 +1,7 @@
 #include "quakedef.h"
 
 pixel_t
-blendalpha(pixel_t ca, pixel_t cb, int alpha)
+blendadditive(pixel_t ca, pixel_t cb, int alpha)
 {
 	int a, b, c;
 
@@ -11,15 +11,21 @@
 	}
 
 	ca = mulalpha(ca, alpha);
+	a = ((ca>> 0)&0xff) + ((cb>> 0)&0xff);
+	b = ((ca>> 8)&0xff) + ((cb>> 8)&0xff);
+	c = ((ca>>16)&0xff) + ((cb>>16)&0xff);
+	return (cb & 0xff000000) | min(a, 255) | min(b, 255)<<8 | min(c, 255)<<16;
+}
 
-	if(currententity != nil && currententity->effects & EF_ADDITIVE){
-		a = ((ca>> 0)&0xff) + ((cb>> 0)&0xff);
-		b = ((ca>> 8)&0xff) + ((cb>> 8)&0xff);
-		c = ((ca>>16)&0xff) + ((cb>>16)&0xff);
-		return (cb & 0xff000000) | min(a, 255) | min(b, 255)<<8 | min(c, 255)<<16;
+pixel_t
+blendalpha(pixel_t ca, pixel_t cb, int alpha)
+{
+	if(ca == 0 || (ca >> 24) != 0){
+		alpha = alpha*(ca >> 24) + 0x80;
+		alpha = ((alpha>>8) + alpha) >> 8;
 	}
 
-	return ca + mulalpha(cb, 255-alpha);
+	return mulalpha(ca, alpha) + mulalpha(cb, 255-alpha);
 }
 
 float
--- a/d_edge.c
+++ b/d_edge.c
@@ -3,8 +3,8 @@
 float scale_for_mip;
 
 // FIXME: should go away
-extern void R_RotateBmodel (entity_t *entity);
-extern void R_TransformFrustum (void);
+extern void R_RotateBmodel (entity_t *entity, view_t *v);
+extern void R_TransformFrustum (view_t *v);
 
 static int
 D_MipLevelForScale(float scale)
@@ -43,16 +43,16 @@
 
 
 static void
-D_CalcGradients(int miplevel, msurface_t *pface, vec3_t transformed_modelorg)
+D_CalcGradients(int miplevel, msurface_t *pface, vec3_t transformed_modelorg, view_t *v)
 {
-	float mipscale;
 	vec3_t p_temp1, p_saxis, p_taxis;
+	float mipscale;
 	float t;
 
 	mipscale = 1.0 / (float)(1 << miplevel);
 
-	TransformVector (pface->texinfo->vecs[0], p_saxis);
-	TransformVector (pface->texinfo->vecs[1], p_taxis);
+	TransformVector (pface->texinfo->vecs[0], p_saxis, v);
+	TransformVector (pface->texinfo->vecs[1], p_taxis, v);
 
 	t = xscaleinv * mipscale;
 
@@ -82,18 +82,20 @@
 }
 
 void
-D_DrawSurfaces (void)
+D_DrawSurfaces(view_t *v0)
 {
-	surf_t *s;
-	entity_t *e;
-	msurface_t *pface;
-	surfcache_t *pcurrentcache;
 	vec3_t local_modelorg, transformed_modelorg, world_transformed_modelorg;
+	surfcache_t *pcurrentcache;
+	msurface_t *pface;
 	int miplevel;
+	entity_t *e;
+	surf_t *s;
 	byte alpha;
 	bool blend;
+	view_t v;
 
-	TransformVector(modelorg, transformed_modelorg);
+	memmove(&v, v0, sizeof(v));
+	TransformVector(v.modelorg, transformed_modelorg, &v);
 	VectorCopy(transformed_modelorg, world_transformed_modelorg);
 
 	// TODO: could preset a lot of this at mode set time
@@ -119,9 +121,9 @@
 		dvars.ziorigin = s->d_ziorigin;
 
 		if(insubmodel(s)){
-			VectorSubtract(r_origin, e->origin, local_modelorg);
-			TransformVector(local_modelorg, transformed_modelorg);
-			R_RotateBmodel(e);
+			VectorSubtract(v.org, e->origin, local_modelorg);
+			TransformVector(local_modelorg, transformed_modelorg, &v);
+			R_RotateBmodel(e, &v);
 		}
 
 		pface = s->data;
@@ -130,7 +132,7 @@
 		}else if(s->flags & SURF_DRAWBACKGROUND){
 			D_DrawSolidSurface(s, q1pal[(int)r_clearcolor.value & 0xFF]);
 		}else if(s->flags & SURF_DRAWTURB){
-			D_CalcGradients(0, pface, transformed_modelorg);
+			D_CalcGradients(0, pface, transformed_modelorg, &v);
 			D_DrawSpans(s->spans, pface->texinfo->texture->pixels, 64, alpha, SPAN_TURB);
 		}else{
 			miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
@@ -137,8 +139,8 @@
 			if(s->flags & SURF_FENCE)
 				miplevel = max(miplevel-1, 0);
 
-			pcurrentcache = D_CacheSurface(pface, miplevel);
-			D_CalcGradients(miplevel, pface, transformed_modelorg);
+			pcurrentcache = D_CacheSurface(s->entity, pface, miplevel);
+			D_CalcGradients(miplevel, pface, transformed_modelorg, &v);
 			D_DrawSpans(s->spans, pcurrentcache->pixels, pcurrentcache->width, alpha,
 				(alpha == 255 && s->flags & SURF_FENCE) ? SPAN_FENCE : (blend ? SPAN_BLEND : SPAN_SOLID)
 			);
@@ -146,11 +148,7 @@
 
 		if(insubmodel(s)){
 			VectorCopy(world_transformed_modelorg, transformed_modelorg);
-			VectorCopy(base_vpn, vpn);
-			VectorCopy(base_vup, vup);
-			VectorCopy(base_vright, vright);
-			VectorCopy(base_modelorg, modelorg);
-			R_TransformFrustum();
+			memmove(&v, v0, sizeof(v));
 		}
 	}
 }
--- a/d_iface.h
+++ b/d_iface.h
@@ -86,9 +86,8 @@
 void D_PolysetDraw (pixel_t *colormap);
 void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts, pixel_t *colormap, byte alpha);
 void D_DrawParticle (particle_t *pparticle);
-void D_DrawPoly (void);
-void D_DrawSprite (void);
-void D_DrawSurfaces (void);
+void D_DrawSprite (view_t *v);
+void D_DrawSurfaces (view_t *v);
 void D_Init (void);
 void D_ViewChanged (void);
 void D_SetupFrame (void);
@@ -129,7 +128,7 @@
 
 extern drawsurf_t	r_drawsurf;
 
-void R_DrawSurface (void);
+void R_DrawSurface (entity_t *e);
 
 // !!! if this is changed, it must be changed in d_ifacea.h too !!!
 #define TURB_TEX_SIZE	64		// base turbulent texture size
--- a/d_local.h
+++ b/d_local.h
@@ -69,7 +69,7 @@
 
 void D_DrawSkyScans8 (espan_t *pspan);
 
-surfcache_t	*D_CacheSurface (msurface_t *surface, int miplevel);
+surfcache_t	*D_CacheSurface (entity_t *e, msurface_t *surface, int miplevel);
 
 extern int	*d_pscantable;
 extern int	d_scantable[MAXHEIGHT];
@@ -97,5 +97,6 @@
 	return a | b;
 }
 
+pixel_t blendadditive(pixel_t ca, pixel_t cb, int alpha);
 pixel_t blendalpha(pixel_t ca, pixel_t cb, int alpha);
 float alphafor(int flags);
--- a/d_part.c
+++ b/d_part.c
@@ -12,7 +12,7 @@
 	int i, izi, pix, count, u, v;
 
 	// transform point
-	VectorSubtract(pparticle->org, r_origin, local);
+	VectorSubtract(pparticle->org, r_refdef.view.org, local);
 
 	transformed[0] = DotProduct(local, r_pright);
 	transformed[1] = DotProduct(local, r_pup);
--- a/d_polyse.c
+++ b/d_polyse.c
@@ -120,7 +120,7 @@
 			z = fv->zi;
 			zbuf = zspantable[fv->v] + fv->u;
 			if(z >= *zbuf){
-				pixel_t p = addlight(skintable[fv->t >> 16][fv->s >> 16], fv->l[0], fv->l[1], fv->l[2]);
+				pixel_t p = addlight(currententity, skintable[fv->t >> 16][fv->s >> 16], fv->l[0], fv->l[1], fv->l[2]);
 				int n = d_scantable[fv->v] + fv->u;
 				if(r_drawflags & DRAW_BLEND){
 					dvars.viewbuffer[n] = blendalpha(p, dvars.viewbuffer[n], alpha);
@@ -308,7 +308,7 @@
 	z = new.zi;
 	zbuf = zspantable[new.v] + new.u;
 	if (z >= *zbuf){
-		pixel_t p = addlight(skintable[new.t >> 16][new.s >> 16], l[0], l[1], l[2]);
+		pixel_t p = addlight(currententity, skintable[new.t >> 16][new.s >> 16], l[0], l[1], l[2]);
 		int n = d_scantable[new.v] + new.u;
 		if(r_drawflags & DRAW_BLEND){
 			dvars.viewbuffer[n] = blendalpha(p, dvars.viewbuffer[n], alpha);
@@ -550,7 +550,7 @@
 			do
 			{
 				if (lzi >= *lpz){
-					pixel_t p = addlight(*lptex, llight[0], llight[1], llight[2]);
+					pixel_t p = addlight(currententity, *lptex, llight[0], llight[1], llight[2]);
 					if(r_drawflags & DRAW_BLEND){
 						*lpdest = blendalpha(
 							p,
--- a/d_sky.c
+++ b/d_sky.c
@@ -18,9 +18,9 @@
 	wu = (u - xcenter)/xscale;
 	wv = (ycenter - v)/yscale;
 
-	end[0] = vpn[0] + wu*vright[0] + wv*vup[0];
-	end[1] = vpn[1] + wu*vright[1] + wv*vup[1];
-	end[2] = vpn[2] + wu*vright[2] + wv*vup[2];
+	end[0] = r_refdef.view.pn[0] + wu*r_refdef.view.right[0] + wv*r_refdef.view.up[0];
+	end[1] = r_refdef.view.pn[1] + wu*r_refdef.view.right[1] + wv*r_refdef.view.up[1];
+	end[2] = r_refdef.view.pn[2] + wu*r_refdef.view.right[2] + wv*r_refdef.view.up[2];
 	end[2] *= 3;
 	VectorNormalize(end);
 
--- a/d_sprite.c
+++ b/d_sprite.c
@@ -9,7 +9,8 @@
 D_SpriteDrawSpans
 =====================
 */
-void D_SpriteDrawSpans (sspan_t *pspan, byte alpha)
+static void
+D_SpriteDrawSpans(sspan_t *pspan, byte alpha)
 {
 	int			count, spancount, izistep;
 	int			izi;
@@ -151,7 +152,8 @@
 D_SpriteScanLeftEdge
 =====================
 */
-void D_SpriteScanLeftEdge (void)
+static void
+D_SpriteScanLeftEdge(void)
 {
 	int			i, v, itop, ibottom, lmaxindex;
 	emitpoint_t	*pvert, *pnext;
@@ -212,7 +214,8 @@
 D_SpriteScanRightEdge
 =====================
 */
-void D_SpriteScanRightEdge (void)
+static void
+D_SpriteScanRightEdge(void)
 {
 	int			i, v, itop, ibottom;
 	emitpoint_t	*pvert, *pnext;
@@ -293,17 +296,18 @@
 D_SpriteCalculateGradients
 =====================
 */
-void D_SpriteCalculateGradients (void)
+static void
+D_SpriteCalculateGradients(view_t *v)
 {
 	vec3_t		p_normal, p_saxis, p_taxis, p_temp1;
 	float		distinv;
 
-	TransformVector (r_spritedesc.vpn, p_normal);
-	TransformVector (r_spritedesc.vright, p_saxis);
-	TransformVector (r_spritedesc.vup, p_taxis);
+	TransformVector (r_spritedesc.vpn, p_normal, v);
+	TransformVector (r_spritedesc.vright, p_saxis, v);
+	TransformVector (r_spritedesc.vup, p_taxis, v);
 	VectorInverse (p_taxis);
 
-	distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
+	distinv = 1.0 / (-DotProduct (v->modelorg, r_spritedesc.vpn));
 
 	dvars.sdivzstepu = p_saxis[0] * xscaleinv;
 	dvars.tdivzstepu = p_taxis[0] * xscaleinv;
@@ -318,7 +322,7 @@
 	dvars.tdivzorigin = p_taxis[2] - xcenter*dvars.tdivzstepu - ycenter*dvars.tdivzstepv;
 	dvars.ziorigin = p_normal[2]*distinv - xcenter*dvars.zistepu - ycenter*dvars.zistepv;
 
-	TransformVector (modelorg, p_temp1);
+	TransformVector (v->modelorg, p_temp1, v);
 
 	dvars.sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - (-(dvars.cachewidth >> 1) << 16);
 	dvars.tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - (-(sprite_height >> 1) << 16);
@@ -334,7 +338,8 @@
 D_DrawSprite
 =====================
 */
-void D_DrawSprite (void)
+void
+D_DrawSprite(view_t *v)
 {
 	int			i, nump;
 	float		ymin, ymax;
@@ -382,8 +387,8 @@
 	pverts = r_spritedesc.pverts;
 	pverts[nump] = pverts[0];
 
-	D_SpriteCalculateGradients ();
-	D_SpriteScanLeftEdge ();
-	D_SpriteScanRightEdge ();
-	D_SpriteDrawSpans (sprite_spans, currententity->alpha);
+	D_SpriteCalculateGradients(v);
+	D_SpriteScanLeftEdge();
+	D_SpriteScanRightEdge();
+	D_SpriteDrawSpans(sprite_spans, currententity->alpha);
 }
--- a/d_surf.c
+++ b/d_surf.c
@@ -180,12 +180,12 @@
 D_CacheSurface
 ================
 */
-surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
+surfcache_t *D_CacheSurface (entity_t *e, msurface_t *surface, int miplevel)
 {
 	surfcache_t	 *cache;
 
 	// if the surface is animating or flashing, flush the cache
-	r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
+	r_drawsurf.texture = R_TextureAnimation(e, surface->texinfo->texture);
 	r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
 	r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
 	r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
@@ -194,7 +194,7 @@
 	// see if the cache holds apropriate data
 	cache = surface->cachespots[miplevel];
 
-	if(currententity == cl_entities || currententity->model->name[0] == '*')
+	if(e == cl_entities || e->model->name[0] == '*')
 	if (cache && !cache->dlight && surface->dlightframe != r_framecount
 			&& cache->texture == r_drawsurf.texture
 			&& cache->lightadj[0] == r_drawsurf.lightadj[0]
@@ -234,7 +234,7 @@
 	r_drawsurf.surf = surface;
 
 	c_surf++;
-	R_DrawSurface ();
+	R_DrawSurface(e);
 
 	return surface->cachespots[miplevel];
 }
--- a/fns.h
+++ b/fns.h
@@ -5,7 +5,7 @@
 void	conscmd(void);
 void	Sys_SendKeyEvents(void);
 void	stepcd(void);
-void	stepsnd(vec3_t, vec3_t, vec3_t, vec3_t);
+void	stepsnd(const view_t *);
 void	stopcd(void);
 void	pausecd(void);
 void	resumecd(void);
--- a/host.c
+++ b/host.c
@@ -512,11 +512,12 @@
 	// update audio
 	if (cls.signon == SIGNONS)
 	{
-		stepsnd (r_origin, vpn, vright, vup);
+		stepsnd(&r_refdef.view);
 		CL_DecayLights ();
+	}else{
+		static const view_t originview = { 0 };
+		stepsnd(&originview);
 	}
-	else
-		stepsnd (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
 
 	stepcd();
 
--- a/mathlib.c
+++ b/mathlib.c
@@ -11,6 +11,19 @@
 }
 
 /*
+================
+TransformVector
+================
+*/
+void
+TransformVector(vec3_t in, vec3_t out, view_t *v)
+{
+	out[0] = DotProduct(in, v->right);
+	out[1] = DotProduct(in, v->up);
+	out[2] = DotProduct(in, v->pn);
+}
+
+/*
 ==================
 BoxOnPlaneSide
 
--- a/mathlib.h
+++ b/mathlib.h
@@ -45,7 +45,23 @@
 int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane);
 float	anglemod(float a);
 
+typedef struct clipplane_s
+{
+	vec3_t		normal;
+	float		dist;
+	struct		clipplane_s	*next;
+	byte		leftedge;
+	byte		rightedge;
+} clipplane_t;
 
+typedef struct {
+	vec3_t modelorg, org;
+	vec3_t pn, right, up;
+	vec3_t angles;
+	clipplane_t	clipplanes[4];
+}view_t;
+
+void TransformVector(vec3_t in, vec3_t out, view_t *v);
 
 #define BOX_ON_PLANE_SIDE(emins, emaxs, p)	\
 	(((p)->type < 3)?						\
--- a/model.c
+++ b/model.c
@@ -49,7 +49,7 @@
 Mod_PointInLeaf
 ===============
 */
-mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
+mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model)
 {
 	mnode_t		*node;
 	float		d;
--- a/model.h
+++ b/model.h
@@ -398,7 +398,7 @@
 void	*Mod_Extradata (model_t *mod);	// handles caching
 void	Mod_TouchModel (char *name);
 
-mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model);
+mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model);
 byte	*Mod_LeafPVS (mleaf_t *leaf, model_t *model, int *sz);
 void	Mod_Print(void);
 
--- a/r_alias.c
+++ b/r_alias.c
@@ -39,7 +39,7 @@
 #include "anorms.h"
 };
 
-static void R_AliasSetUpTransform (int trivial_accept);
+static void R_AliasSetUpTransform (int trivial_accept, view_t *v);
 static void R_AliasTransformVector (vec3_t in, vec3_t out);
 static void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, trivertx_t *pverts, stvert_t *pstverts);
 void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
@@ -50,7 +50,7 @@
 R_AliasCheckBBox
 ================
 */
-bool R_AliasCheckBBox (void)
+bool R_AliasCheckBBox (view_t *v)
 {
 	int					i, flags, frame, numv;
 	aliashdr_t			*pahdr;
@@ -69,7 +69,7 @@
 	pahdr = Mod_Extradata (pmodel);
 	pmdl = (mdl_t *)((byte *)pahdr + pahdr->model);
 
-	R_AliasSetUpTransform (0);
+	R_AliasSetUpTransform (0, v);
 
 	// construct the base bounding box for this frame
 	frame = currententity->frame;
@@ -292,7 +292,7 @@
 R_AliasSetUpTransform
 ================
 */
-static void R_AliasSetUpTransform (int trivial_accept)
+static void R_AliasSetUpTransform (int trivial_accept, view_t *v)
 {
 	int		i;
 	float	rotationmatrix[3][4], t2matrix[3][4];
@@ -326,18 +326,18 @@
 		t2matrix[i][2] = alias_up[i];
 	}
 
-	t2matrix[0][3] = -modelorg[0];
-	t2matrix[1][3] = -modelorg[1];
-	t2matrix[2][3] = -modelorg[2];
+	t2matrix[0][3] = -v->modelorg[0];
+	t2matrix[1][3] = -v->modelorg[1];
+	t2matrix[2][3] = -v->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]);
+	VectorCopy (v->right, viewmatrix[0]);
+	VectorCopy (v->up, viewmatrix[1]);
 	VectorInverse (viewmatrix[1]);
-	VectorCopy (vpn, viewmatrix[2]);
+	VectorCopy (v->pn, viewmatrix[2]);
 
 	//	viewmatrix[0][3] = 0;
 	//	viewmatrix[1][3] = 0;
@@ -640,7 +640,8 @@
 R_AliasDrawModel
 ================
 */
-void R_AliasDrawModel (alight_t *plighting)
+void
+R_AliasDrawModel(alight_t *plighting, view_t *v)
 {
 	static finalvert_t finalverts[MAXALIASVERTS];
 	static auxvert_t auxverts[MAXALIASVERTS];
@@ -653,7 +654,7 @@
 	pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model);
 
 	R_AliasSetupSkin();
-	R_AliasSetUpTransform(currententity->trivial_accept);
+	R_AliasSetUpTransform(currententity->trivial_accept, v);
 	R_AliasSetupLighting(plighting);
 	pverts = R_AliasSetupFrame ();
 
--- a/r_bsp.c
+++ b/r_bsp.c
@@ -5,9 +5,6 @@
 //
 
 entity_t		*currententity;
-vec3_t			modelorg, base_modelorg;
-								// modelorg is the viewpoint reletive to
-								// the currently rendering entity
 vec3_t			r_entorigin;	// the currently rendering entity in world
 								// coordinates
 
@@ -48,14 +45,15 @@
 R_EntityRotate
 ================
 */
-void R_EntityRotate (vec3_t vec)
+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);
+	VectorCopy(vec, tvec);
+	vec[0] = DotProduct(entity_rotation[0], tvec);
+	vec[1] = DotProduct(entity_rotation[1], tvec);
+	vec[2] = DotProduct(entity_rotation[2], tvec);
 }
 
 
@@ -64,7 +62,8 @@
 R_RotateBmodel
 ================
 */
-void R_RotateBmodel (entity_t *e)
+void
+R_RotateBmodel(entity_t *e, view_t *v)
 {
 	float	angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
 
@@ -124,24 +123,24 @@
 	temp1[2][1] = -s;
 	temp1[2][2] = c;
 
-	R_ConcatRotations (temp1, temp3, entity_rotation);
+	R_ConcatRotations(temp1, temp3, entity_rotation);
 
 	// rotate modelorg and the transformation matrix
-	R_EntityRotate (modelorg);
-	R_EntityRotate (vpn);
-	R_EntityRotate (vright);
-	R_EntityRotate (vup);
+	R_EntityRotate(v->modelorg);
+	R_EntityRotate(v->pn);
+	R_EntityRotate(v->right);
+	R_EntityRotate(v->up);
 
-	R_TransformFrustum ();
+	R_TransformFrustum(v);
 }
 
-
 /*
 ================
 R_RecursiveClipBPoly
 ================
 */
-void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
+static void
+R_RecursiveClipBPoly(bedge_t *pedges, mnode_t *pnode, msurface_t *psurf, view_t *v)
 {
 	bedge_t		*psideedges[2], *pnextedge, *ptedge;
 	int			i, side, lastside;
@@ -159,9 +158,9 @@
 	// 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);
+	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)
@@ -284,7 +283,7 @@
 					if (pn->contents != CONTENTS_SOLID)
 					{
 						r_currentbkey = ((mleaf_t *)pn)->key;
-						R_RenderBmodelFace (psideedges[i], psurf);
+						R_RenderBmodelFace(psideedges[i], psurf, v);
 					}
 				}
 				else if(i == 1){ // last, can skip the call
@@ -292,7 +291,7 @@
 					pnode = pnode->children[i];
 					goto next;
 				}else{
-					R_RecursiveClipBPoly (psideedges[i], pnode->children[i], psurf);
+					R_RecursiveClipBPoly(psideedges[i], pnode->children[i], psurf, v);
 				}
 			}
 		}
@@ -305,7 +304,8 @@
 R_DrawSolidClippedSubmodelPolygons
 ================
 */
-void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel)
+void
+R_DrawSolidClippedSubmodelPolygons(model_t *pmodel, view_t *v)
 {
 	int			i, j, lindex, o;
 	vec_t		dot;
@@ -329,7 +329,7 @@
 		// find which side of the node we are on
 		pplane = psurf->plane;
 
-		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+		dot = DotProduct(v->modelorg, pplane->normal) - pplane->dist;
 
 		// draw the polygon
 		if ((dot > 0) ^ !!(psurf->flags & SURF_PLANEBACK))
@@ -363,7 +363,7 @@
 
 				pbedge[j-1].pnext = nil;	// mark end of edges
 
-				R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf);
+				R_RecursiveClipBPoly(pbedge, currententity->topnode, psurf, v);
 			}
 			else
 			{
@@ -379,7 +379,8 @@
 R_DrawSubmodelPolygons
 ================
 */
-void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags)
+void
+R_DrawSubmodelPolygons(model_t *pmodel, view_t *v, int clipflags)
 {
 	int			i;
 	vec_t		dot;
@@ -400,7 +401,7 @@
 		// find which side of the node we are on
 		pplane = psurf->plane;
 
-		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+		dot = DotProduct(v->modelorg, pplane->normal) - pplane->dist;
 
 		// draw the polygon
 		if ((dot > 0) ^ !!(psurf->flags & SURF_PLANEBACK))
@@ -408,7 +409,7 @@
 			r_currentkey = ((mleaf_t *)currententity->topnode)->key;
 
 			// FIXME: use bounding-box-based frustum clipping info?
-			R_RenderFace (psurf, clipflags);
+			R_RenderFace(psurf, v, clipflags);
 		}
 	}
 }
@@ -419,7 +420,8 @@
 R_RecursiveWorldNode
 ================
 */
-void R_RecursiveWorldNode (mnode_t *node, int clipflags)
+static void
+R_RecursiveWorldNode(mnode_t *node, view_t *v, int clipflags)
 {
 	int			i, c, side, *pindex, rejected;
 	vec3_t		acceptpt, rejectpt;
@@ -455,8 +457,8 @@
 			rejectpt[1] = node->minmaxs[pindex[1]];
 			rejectpt[2] = node->minmaxs[pindex[2]];
 
-			d = DotProduct (rejectpt, view_clipplanes[i].normal);
-			d -= view_clipplanes[i].dist;
+			d = DotProduct (rejectpt, v->clipplanes[i].normal);
+			d -= v->clipplanes[i].dist;
 
 			if (d <= 0)
 				return;
@@ -465,8 +467,8 @@
 			acceptpt[1] = node->minmaxs[pindex[3+1]];
 			acceptpt[2] = node->minmaxs[pindex[3+2]];
 
-			d = DotProduct (acceptpt, view_clipplanes[i].normal);
-			d -= view_clipplanes[i].dist;
+			d = DotProduct (acceptpt, v->clipplanes[i].normal);
+			d -= v->clipplanes[i].dist;
 
 			if (d >= 0)
 				clipflags &= ~(1<<i);	// node is entirely on screen
@@ -505,12 +507,12 @@
 
 		// find which side of the node we are on
 		plane = node->plane;
-		dot = plane->type <= PLANE_Z ? modelorg[plane->type] : DotProduct(modelorg, plane->normal);
+		dot = plane->type <= PLANE_Z ? v->modelorg[plane->type] : DotProduct(v->modelorg, plane->normal);
 		dot -= plane->dist;
 		side = dot < 0;
 
 		// recurse down the children, front side first
-		R_RecursiveWorldNode (node->children[side], clipflags);
+		R_RecursiveWorldNode (node->children[side], v, clipflags);
 
 		// draw stuff
 		c = node->numsurfaces;
@@ -522,13 +524,13 @@
 			if(dot < -BACKFACE_EPSILON){
 				do{
 					if((surf->flags & SURF_PLANEBACK) && surf->visframe == r_framecount)
-						rejected |= !R_RenderFace(surf, clipflags);
+						rejected |= !R_RenderFace(surf, v, clipflags);
 					surf++;
 				}while(--c);
 			}else if(dot > BACKFACE_EPSILON){
 				do{
 					if(!(surf->flags & SURF_PLANEBACK) && surf->visframe == r_framecount)
-						rejected |= !R_RenderFace(surf, clipflags);
+						rejected |= !R_RenderFace(surf, v, clipflags);
 					surf++;
 				}while(--c);
 			}
@@ -559,21 +561,20 @@
 R_RenderWorld
 ================
 */
-void R_RenderWorld (void)
+void R_RenderWorld (view_t *v)
 {
 	model_t		*clmodel;
 
 	currententity = &cl_entities[0];
-	VectorCopy (r_origin, modelorg);
 	clmodel = currententity->model;
 	r_pcurrentvertbase = clmodel->vertexes;
 
 	num_node_rejects = 0;
-	R_RecursiveWorldNode (clmodel->nodes, 15);
+	R_RecursiveWorldNode(clmodel->nodes, v, 15);
 }
 
 void
-R_RenderBlendedBrushes(void)
+R_RenderBlendedBrushes(view_t *v)
 {
 	model_t *clmodel;
 	nodereject_t *rej;
@@ -581,7 +582,6 @@
 	unsigned i;
 
 	currententity = &cl_entities[0];
-	VectorCopy (r_origin, modelorg);
 	clmodel = currententity->model;
 	r_pcurrentvertbase = clmodel->vertexes;
 
@@ -595,7 +595,7 @@
 		surf = cl.worldmodel->surfaces + rej->node->firstsurface;
 		R_BeginEdgeFrame();
 		for(i = 0; i < rej->node->numsurfaces; i++, surf++)
-			R_RenderFace(surf, rej->clipflags);
-		R_ScanEdges();
+			R_RenderFace(surf, v, rej->clipflags);
+		R_ScanEdges(v);
 	}
 }
--- a/r_draw.c
+++ b/r_draw.c
@@ -8,12 +8,8 @@
 
 static unsigned int cacheoffset;
 
-int			c_faceclip;					// number of faces clipped
-
 int r_drawflags;
 
-clipplane_t	view_clipplanes[4];
-
 static medge_t			*r_pedge;
 
 static bool r_leftclipped, r_rightclipped;
@@ -69,7 +65,8 @@
 R_EmitEdge
 ================
 */
-void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
+void
+R_EmitEdge(mvertex_t *pv0, mvertex_t *pv1, view_t *view)
 {
 	edge_t	*edge, *pcheck;
 	int		u_check;
@@ -91,8 +88,8 @@
 		world = &pv0->position[0];
 
 		// transform and project
-		VectorSubtract (world, modelorg, local);
-		TransformVector (local, transformed);
+		VectorSubtract (world, view->modelorg, local);
+		TransformVector (local, transformed, view);
 
 		if (transformed[2] < NEAR_CLIP)
 			transformed[2] = NEAR_CLIP;
@@ -110,8 +107,8 @@
 	world = &pv1->position[0];
 
 	// transform and project
-	VectorSubtract (world, modelorg, local);
-	TransformVector (local, transformed);
+	VectorSubtract (world, view->modelorg, local);
+	TransformVector (local, transformed, view);
 
 	if (transformed[2] < NEAR_CLIP)
 		transformed[2] = NEAR_CLIP;
@@ -211,7 +208,8 @@
 R_ClipEdge
 ================
 */
-void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
+static void
+R_ClipEdge(mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip, view_t *v)
 {
 	float		d0, d1, f;
 	mvertex_t	clipvert;
@@ -253,7 +251,7 @@
 				r_rightexit = clipvert;
 			}
 
-			R_ClipEdge (pv0, &clipvert, clip->next);
+			R_ClipEdge(pv0, &clipvert, clip->next, v);
 			return;
 		}
 		else
@@ -294,13 +292,13 @@
 				r_rightenter = clipvert;
 			}
 
-			R_ClipEdge (&clipvert, pv1, clip->next);
+			R_ClipEdge(&clipvert, pv1, clip->next, v);
 			return;
 		}
 	}
 
 	// add the edge
-	R_EmitEdge (pv0, pv1);
+	R_EmitEdge(pv0, pv1, v);
 }
 
 
@@ -333,7 +331,7 @@
 R_RenderFace
 ================
 */
-int R_RenderFace (msurface_t *fa, int clipflags)
+int R_RenderFace (msurface_t *fa, view_t *v, int clipflags)
 {
 	int			i, lindex;
 	unsigned	mask;
@@ -358,8 +356,6 @@
 		return 1;
 	}
 
-	c_faceclip++;
-
 	// set up clip planes
 	pclip = nil;
 
@@ -367,8 +363,8 @@
 	{
 		if (clipflags & mask)
 		{
-			view_clipplanes[i].next = pclip;
-			pclip = &view_clipplanes[i];
+			v->clipplanes[i].next = pclip;
+			pclip = &v->clipplanes[i];
 		}
 	}
 
@@ -416,7 +412,8 @@
 			r_leftclipped = r_rightclipped = false;
 			R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
 						&r_pcurrentvertbase[r_pedge->v[1]],
-						pclip);
+						pclip,
+						v);
 			r_pedge->cachededgeoffset = cacheoffset;
 			if (r_leftclipped)
 				makeleftedge = true;
@@ -458,7 +455,8 @@
 			r_leftclipped = r_rightclipped = false;
 			R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
 						&r_pcurrentvertbase[r_pedge->v[0]],
-						pclip);
+						pclip,
+						v);
 			r_pedge->cachededgeoffset = cacheoffset;
 
 			if (r_leftclipped)
@@ -476,7 +474,7 @@
 	{
 		r_pedge = &tedge;
 		r_lastvertvalid = false;
-		R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
+		R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next, v);
 	}
 
 	// if there was a clip off the right edge, get the right r_nearzi
@@ -485,7 +483,7 @@
 		r_pedge = &tedge;
 		r_lastvertvalid = false;
 		r_nearzionly = true;
-		R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
+		R_ClipEdge (&r_rightexit, &r_rightenter, v->clipplanes[1].next, v);
 	}
 
 	// if no edges made it out, return without posting the surface
@@ -502,9 +500,9 @@
 
 	pplane = fa->plane;
 	// FIXME: cache this?
-	TransformVector (pplane->normal, p_normal);
+	TransformVector (pplane->normal, p_normal, v);
 	// FIXME: cache this?
-	distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
+	distinv = 1.0 / (pplane->dist - DotProduct(v->modelorg, pplane->normal));
 
 	surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
 	surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
@@ -523,7 +521,8 @@
 R_RenderBmodelFace
 ================
 */
-void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
+void
+R_RenderBmodelFace(bedge_t *pedges, msurface_t *psurf, view_t *v)
 {
 	int			i;
 	unsigned	mask;
@@ -547,8 +546,6 @@
 		return;
 	}
 
-	c_faceclip++;
-
 	// this is a dummy to give the caching mechanism someplace to write to
 	r_pedge = &tedge;
 
@@ -559,8 +556,8 @@
 	{
 		if (r_clipflags & mask)
 		{
-			view_clipplanes[i].next = pclip;
-			pclip = &view_clipplanes[i];
+			v->clipplanes[i].next = pclip;
+			pclip = &v->clipplanes[i];
 		}
 	}
 
@@ -576,7 +573,7 @@
 	for ( ; pedges ; pedges = pedges->pnext)
 	{
 		r_leftclipped = r_rightclipped = false;
-		R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
+		R_ClipEdge (pedges->v[0], pedges->v[1], pclip, v);
 
 		if (r_leftclipped)
 			makeleftedge = true;
@@ -590,7 +587,7 @@
 	if (makeleftedge)
 	{
 		r_pedge = &tedge;
-		R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
+		R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next, v);
 	}
 
 	// if there was a clip off the right edge, get the right r_nearzi
@@ -598,7 +595,7 @@
 	{
 		r_pedge = &tedge;
 		r_nearzionly = true;
-		R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
+		R_ClipEdge (&r_rightexit, &r_rightenter, v->clipplanes[1].next, v);
 	}
 
 	// if no edges made it out, return without posting the surface
@@ -615,9 +612,9 @@
 
 	pplane = psurf->plane;
 	// FIXME: cache this?
-	TransformVector (pplane->normal, p_normal);
+	TransformVector (pplane->normal, p_normal, v);
 	// FIXME: cache this?
-	distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
+	distinv = 1.0 / (pplane->dist - DotProduct(v->modelorg, pplane->normal));
 
 	surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
 	surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
--- a/r_edge.c
+++ b/r_edge.c
@@ -29,10 +29,8 @@
 static edge_t edge_head, edge_tail, edge_aftertail, edge_sentinel;
 static float fv;
 
-static void (*pdrawfunc)(void);
+void R_GenerateSpans(void);
 
-void R_GenerateSpans (void);
-
 void R_LeadingEdge (edge_t *edge);
 void R_TrailingEdge (surf_t *surf, edge_t *edge);
 
@@ -60,7 +58,6 @@
 	surfaces[1].flags = SURF_DRAWBACKGROUND;
 
 	// put the background behind everything in the world
-	pdrawfunc = R_GenerateSpans;
 	surfaces[1].key = 0x7FFFFFFF;
 	r_currentkey = 0;
 
@@ -435,7 +432,8 @@
 Each surface has a linked list of its visible spans
 ==============
 */
-void R_ScanEdges (void)
+void
+R_ScanEdges(view_t *v)
 {
 	int		iv, bottom;
 	espan_t	*basespan_p;
@@ -491,7 +489,7 @@
 			R_InsertNewEdges (newedges[iv], edge_head.next);
 		}
 
-		(*pdrawfunc) ();
+		R_GenerateSpans();
 
 		// flush the span list if we can't be sure we have enough spans left for
 		// the next scan
@@ -498,7 +496,7 @@
 		if (span_p >= max_span_p)
 		{
 			r_outofspans++;
-			D_DrawSurfaces ();
+			D_DrawSurfaces(v);
 
 			// clear the surface span pointers
 			for (s = &surfaces[1] ; s<surface_p ; s++)
@@ -525,10 +523,8 @@
 	if (newedges[iv])
 		R_InsertNewEdges (newedges[iv], edge_head.next);
 
-	(*pdrawfunc) ();
+	R_GenerateSpans();
 
 	// draw whatever's left in the span list
-	D_DrawSurfaces ();
+	D_DrawSurfaces(v);
 }
-
-
--- a/r_local.h
+++ b/r_local.h
@@ -66,30 +66,15 @@
 
 #define	DIST_NOT_SET	98765
 
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct clipplane_s
-{
-	vec3_t		normal;
-	float		dist;
-	struct		clipplane_s	*next;
-	byte		leftedge;
-	byte		rightedge;
-	byte		reserved[2];
-} clipplane_t;
-
-extern	clipplane_t	view_clipplanes[4];
-
 //=============================================================================
 
-void R_RenderWorld (void);
-void R_RenderBlendedBrushes(void);
+void R_RenderWorld (view_t *v);
+void R_RenderBlendedBrushes(view_t *v);
 
 //=============================================================================
 
 extern	mplane_t	screenedge[4];
 
-extern	vec3_t	r_origin;
-
 extern	vec3_t	r_entorigin;
 
 extern	float	screenAspect;
@@ -104,24 +89,24 @@
 void R_ResetFog(void);
 void R_InitFog(void);
 
-void R_DrawSprite (void);
-int R_RenderFace (msurface_t *fa, int clipflags);
-void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
-void R_TransformFrustum (void);
+void R_DrawSprite (view_t *v);
+int R_RenderFace (msurface_t *fa, view_t *v, int clipflags);
+void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf, view_t *v);
+void R_TransformFrustum (view_t *v);
 void R_SetSkyFrame (void);
-texture_t *R_TextureAnimation (texture_t *base);
+texture_t *R_TextureAnimation (entity_t *e, texture_t *base);
 
-pixel_t addlight(pixel_t x, int lr, int lg, int lb);
+pixel_t addlight(entity_t *e, pixel_t x, int lr, int lg, int lb);
 
-void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags);
-void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel);
+void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, view_t *v);
+void R_DrawSubmodelPolygons (model_t *pmodel, view_t *v, int clipflags);
 
 void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
 surf_t *R_GetSurf (void);
-void R_AliasDrawModel (alight_t *plighting);
+void R_AliasDrawModel (alight_t *plighting, view_t *v);
 void R_BeginEdgeFrame (void);
-void R_ScanEdges (void);
-void D_DrawSurfaces (void);
+void R_ScanEdges(view_t *v);
+void D_DrawSurfaces(view_t *v);
 void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist);
 void R_StepActiveU (edge_t *pedge);
 void R_RemoveEdges (edge_t *pedge);
@@ -133,11 +118,8 @@
 extern void R_EdgeCodeStart (void);
 extern void R_EdgeCodeEnd (void);
 
-extern void R_RotateBmodel (entity_t *e);
+extern void R_RotateBmodel (entity_t *e, view_t *v);
 
-extern int	c_faceclip;
-extern int	r_polycount;
-
 extern	model_t		*cl_worldmodel;
 
 extern int		*pfrustum_indexes[4];
@@ -166,7 +148,7 @@
 
 extern finalvert_t		*pfinalverts;
 
-bool R_AliasCheckBBox (void);
+bool R_AliasCheckBBox (view_t *v);
 
 //=========================================================
 // turbulence stuff
@@ -221,7 +203,5 @@
 void R_LightPoint (vec3_t p, int *r);
 void R_SetupFrame (void);
 void R_cshift_f (void);
-void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
-void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
 void R_SplitEntityOnNode2 (mnode_t *node);
 void R_MarkLights (dlight_t *light, int bit, mnode_t *node);
--- a/r_main.c
+++ b/r_main.c
@@ -24,14 +24,6 @@
 pixel_t *r_warpbuffer;
 
 //
-// view origin
-//
-vec3_t	vup, base_vup;
-vec3_t	vpn, base_vpn;
-vec3_t	vright, base_vright;
-vec3_t	r_origin;
-
-//
 // screen size info
 //
 refdef_t	r_refdef;
@@ -155,12 +147,12 @@
 	Cvar_RegisterVariable (&r_lavaalpha);
 	Cvar_RegisterVariable (&r_slimealpha);
 
-	view_clipplanes[0].leftedge = true;
-	view_clipplanes[1].rightedge = true;
-	view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =
-			view_clipplanes[3].leftedge = false;
-	view_clipplanes[0].rightedge = view_clipplanes[2].rightedge =
-			view_clipplanes[3].rightedge = false;
+	r_refdef.view.clipplanes[0].leftedge = true;
+	r_refdef.view.clipplanes[1].rightedge = true;
+	r_refdef.view.clipplanes[1].leftedge = r_refdef.view.clipplanes[2].leftedge =
+			r_refdef.view.clipplanes[3].leftedge = false;
+	r_refdef.view.clipplanes[0].rightedge = r_refdef.view.clipplanes[2].rightedge =
+			r_refdef.view.clipplanes[3].rightedge = false;
 
 	r_refdef.xOrigin = XCENTERING;
 	r_refdef.yOrigin = YCENTERING;
@@ -397,7 +389,7 @@
 }
 
 static int
-R_BmodelCheckBBox(model_t *clmodel, float *minmaxs)
+R_BmodelCheckBBox(model_t *clmodel, float *minmaxs, view_t *v)
 {
 	int			i, *pindex, clipflags;
 	vec3_t		acceptpt, rejectpt;
@@ -405,13 +397,10 @@
 
 	clipflags = 0;
 
-	if (currententity->angles[0] || currententity->angles[1]
-		|| currententity->angles[2])
-	{
-		for (i=0 ; i<4 ; i++)
-		{
-			d = DotProduct (currententity->origin, view_clipplanes[i].normal);
-			d -= view_clipplanes[i].dist;
+	if(currententity->angles[0] || currententity->angles[1] || currententity->angles[2]){
+		for (i=0 ; i<4 ; i++){
+			d = DotProduct (currententity->origin, v->clipplanes[i].normal);
+			d -= v->clipplanes[i].dist;
 
 			if (d <= -clmodel->radius)
 				return BMODEL_FULLY_CLIPPED;
@@ -419,11 +408,8 @@
 			if (d <= clmodel->radius)
 				clipflags |= (1<<i);
 		}
-	}
-	else
-	{
-		for (i=0 ; i<4 ; 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
@@ -434,8 +420,8 @@
 			rejectpt[1] = minmaxs[pindex[1]];
 			rejectpt[2] = minmaxs[pindex[2]];
 
-			d = DotProduct (rejectpt, view_clipplanes[i].normal);
-			d -= view_clipplanes[i].dist;
+			d = DotProduct (rejectpt, v->clipplanes[i].normal);
+			d -= v->clipplanes[i].dist;
 
 			if (d <= 0)
 				return BMODEL_FULLY_CLIPPED;
@@ -444,8 +430,8 @@
 			acceptpt[1] = minmaxs[pindex[3+1]];
 			acceptpt[2] = minmaxs[pindex[3+2]];
 
-			d = DotProduct (acceptpt, view_clipplanes[i].normal);
-			d -= view_clipplanes[i].dist;
+			d = DotProduct (acceptpt, v->clipplanes[i].normal);
+			d -= v->clipplanes[i].dist;
 
 			if (d <= 0)
 				clipflags |= (1<<i);
@@ -456,15 +442,16 @@
 }
 
 static int
-R_DrawEntity(entity_t *e)
+R_DrawEntity(entity_t *e, view_t *view)
 {
 	int			j, k, clipflags;
 	alight_t	lighting;
-	float		lightvec[3] = {-1, 0, 0}; // FIXME: remove and do real lighting
+	vec3_t		lightvec = {-1, 0, 0}; // FIXME: remove and do real lighting
 	float		minmaxs[6];
-	vec3_t		dist, oldorigin;
+	vec3_t		dist;
 	int		add;
 	model_t		*clmodel;
+	view_t v;
 
 	if(!r_drawentities.value || e == &cl_entities[cl.viewentity])
 		return 1;
@@ -474,22 +461,22 @@
 		e->alpha = 0xff;
 
 	currententity = e;
-	VectorCopy(modelorg, oldorigin);
+	memmove(&v, view, sizeof(v));
 
 	switch(e->model->type){
 	case mod_sprite:
 		VectorCopy(e->origin, r_entorigin);
-		VectorSubtract(r_origin, r_entorigin, modelorg);
-		R_DrawSprite();
+		VectorSubtract(r_refdef.view.org, r_entorigin, v.modelorg);
+		R_DrawSprite(&v);
 		break;
 
 	case mod_alias:
 		VectorCopy(e->origin, r_entorigin);
-		VectorSubtract(r_origin, r_entorigin, modelorg);
+		VectorSubtract(r_refdef.view.org, r_entorigin, v.modelorg);
 
 		// see if the bounding box lets us trivially reject, also sets
 		// trivial accept status
-		if(!R_AliasCheckBBox())
+		if(!R_AliasCheckBBox(&v))
 			break;
 
 		R_LightPoint(currententity->origin, lighting.ambientlight);
@@ -517,7 +504,7 @@
 				lighting.shadelight[j] = 192 - lighting.ambientlight[j];
 		}
 
-		R_AliasDrawModel(&lighting);
+		R_AliasDrawModel(&lighting, &v);
 		break;
 
 	case mod_brush:
@@ -531,14 +518,14 @@
 			minmaxs[3+j] = currententity->origin[j] + clmodel->maxs[j];
 		}
 
-		clipflags = R_BmodelCheckBBox(clmodel, minmaxs);
+		clipflags = R_BmodelCheckBBox(clmodel, minmaxs, &v);
 		if(clipflags == BMODEL_FULLY_CLIPPED)
 			break;
 
 		VectorCopy(e->origin, r_entorigin);
-		VectorSubtract(r_origin, r_entorigin, modelorg);
+		VectorSubtract(r_refdef.view.org, r_entorigin, v.modelorg);
 		r_pcurrentvertbase = clmodel->vertexes;
-		R_RotateBmodel(e); // FIXME: stop transforming twice
+		R_RotateBmodel(e, &v); // FIXME: stop transforming twice
 
 		// calculate dynamic lighting for bmodel if it's not an
 		// instanced model
@@ -567,15 +554,15 @@
 			if(r_pefragtopnode->contents >= 0){
 				// not a leaf; has to be clipped to the world BSP
 				r_clipflags = clipflags;
-				R_DrawSolidClippedSubmodelPolygons(clmodel);
+				R_DrawSolidClippedSubmodelPolygons(clmodel, &v);
 			}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
-				R_DrawSubmodelPolygons(clmodel, clipflags);
+				R_DrawSubmodelPolygons(clmodel, &v, clipflags);
 			}
 			if(r_drawflags & DRAW_BLEND)
-				R_ScanEdges();
+				R_ScanEdges(&v);
 
 			e->topnode = nil;
 		}
@@ -582,15 +569,6 @@
 		break;
 	}
 
-	// put back world rotation and frustum clipping
-	// FIXME: 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);
-	R_TransformFrustum();
-
 	return 1;
 }
 
@@ -599,14 +577,15 @@
 R_DrawViewModel
 =============
 */
-void R_DrawViewModel (void)
+void R_DrawViewModel (view_t *view)
 {
 	// FIXME: remove and do real lighting
-	float		lightvec[3] = {-1, 0, 0};
+	vec3_t		lightvec = {-1, 0, 0};
 	int			lnum, i;
 	vec3_t		dist;
 	float		add;
 	dlight_t	*dl;
+	view_t v;
 
 	if (!r_drawviewmodel.value)
 		return;
@@ -621,11 +600,12 @@
 	if (!currententity->model)
 		return;
 
-	VectorCopy (currententity->origin, r_entorigin);
-	VectorSubtract (r_origin, r_entorigin, modelorg);
+	memmove(&v, view, sizeof(v));
+	VectorCopy(currententity->origin, r_entorigin);
+	VectorSubtract(v.org, r_entorigin, v.modelorg);
 
-	VectorCopy (vup, viewlightvec);
-	VectorInverse (viewlightvec);
+	VectorCopy(v.up, viewlightvec);
+	VectorInverse(viewlightvec);
 
 	R_LightPoint(currententity->origin, r_viewlighting.ambientlight);
 	// always give some light on gun
@@ -661,25 +641,25 @@
 
 	r_viewlighting.plightvec = lightvec;
 
-	R_AliasDrawModel(&r_viewlighting);
+	R_AliasDrawModel(&r_viewlighting, &v);
 }
 
 void
-R_RenderSolidBrushes(void)
+R_RenderSolidBrushes(view_t *v)
 {
 	entity_t *e;
 	int i;
 
 	R_BeginEdgeFrame();
-	R_RenderWorld();
+	R_RenderWorld(v);
 	for(i = 0; i < cl_numvisedicts; i++){
 		e = cl_visedicts[i];
-		if(e->model != nil && e->model->type == mod_brush && !R_DrawEntity(e)){
+		if(e->model != nil && e->model->type == mod_brush && !R_DrawEntity(e, v)){
 			e->last_reject = ent_reject;
 			ent_reject = e;
 		}
 	}
-	R_ScanEdges();
+	R_ScanEdges(v);
 }
 
 /*
@@ -693,38 +673,40 @@
 {
 	entity_t *e;
 	int i;
+	view_t *v;
 
-	R_SetupFrame ();
-	R_MarkLeaves ();	// done here so we know if we're in water
+	R_SetupFrame();
+	R_MarkLeaves();	// done here so we know if we're in water
 
 	if (!cl_entities[0].model || !cl.worldmodel)
 		fatal ("R_RenderView: NULL worldmodel");
 	ent_reject = nil;
-	R_RenderSolidBrushes();
+	v = &r_refdef.view;
 
+	R_RenderSolidBrushes(v);
 	for(i = 0; i < cl_numvisedicts; i++){
 		e = cl_visedicts[i];
-		if(e->model->type != mod_brush && !R_DrawEntity(e)){
+		if(e->model->type != mod_brush && !R_DrawEntity(e, v)){
 			e->last_reject = ent_reject;
 			ent_reject = e;
 		}
 	}
 
-	R_DrawViewModel ();
-	R_DrawParticles ();
+	R_DrawViewModel(v);
+	R_DrawParticles();
 
 	r_drawflags = DRAW_BLEND;
-	R_RenderBlendedBrushes();
+	R_RenderBlendedBrushes(v);
 	// FIXME(sigrid): these need to be sorted with blended brushes and *all* drawn back to front
 	if(cl_numvisedicts > 0){
 		for(i = cl_numvisedicts, e = ent_reject; e != nil && i > 0; e = e->last_reject){
 			if(!enthasalpha(e))
-				R_DrawEntity(e);
+				R_DrawEntity(e, v);
 			else
 				cl_visedicts[--i] = e;
 		}
 		for(; i < cl_numvisedicts; i++)
-			R_DrawEntity(cl_visedicts[i]);
+			R_DrawEntity(cl_visedicts[i], v);
 	}
 	r_drawflags = 0;
 
--- a/r_misc.c
+++ b/r_misc.c
@@ -21,7 +21,8 @@
 R_TransformFrustum
 ===================
 */
-void R_TransformFrustum (void)
+void
+R_TransformFrustum(view_t *view)
 {
 	int		i;
 	vec3_t	v, v2;
@@ -32,35 +33,23 @@
 		v[1] = -screenedge[i].normal[0];
 		v[2] = 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];
+		v2[0] = v[1]*view->right[0] + v[2]*view->up[0] + v[0]*view->pn[0];
+		v2[1] = v[1]*view->right[1] + v[2]*view->up[1] + v[0]*view->pn[1];
+		v2[2] = v[1]*view->right[2] + v[2]*view->up[2] + v[0]*view->pn[2];
 
-		VectorCopy (v2, view_clipplanes[i].normal);
+		VectorCopy(v2, view->clipplanes[i].normal);
 
-		view_clipplanes[i].dist = DotProduct (modelorg, v2);
+		view->clipplanes[i].dist = DotProduct(view->modelorg, v2);
 	}
 }
 
-
 /*
-================
-TransformVector
-================
-*/
-void TransformVector (vec3_t in, vec3_t out)
-{
-	out[0] = DotProduct(in,vright);
-	out[1] = DotProduct(in,vup);
-	out[2] = DotProduct(in,vpn);
-}
-
-/*
 ===============
 R_SetUpFrustumIndexes
 ===============
 */
-void R_SetUpFrustumIndexes (void)
+static void
+R_SetUpFrustumIndexes(view_t *v)
 {
 	int		i, j, *pindex;
 
@@ -70,7 +59,7 @@
 	{
 		for (j=0 ; j<3 ; j++)
 		{
-			if (view_clipplanes[i].normal[j] < 0)
+			if (v->clipplanes[i].normal[j] < 0)
 			{
 				pindex[j] = j;
 				pindex[j+3] = j+3;
@@ -138,23 +127,21 @@
 	r_framecount++;
 
 /* debugging
-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;
+r_refdef.view.org[0]=  80;
+r_refdef.view.org[1]=      64;
+r_refdef.view.org[2]=      40;
+r_refdef.view.angles[0]=    0;
+r_refdef.view.angles[1]=    46.763641357;
+r_refdef.view.angles[2]=    0;
 */
 
 	// build the transformation matrix for the given view angles
-	VectorCopy (r_refdef.vieworg, modelorg);
-	VectorCopy (r_refdef.vieworg, r_origin);
+	VectorCopy(r_refdef.view.org, r_refdef.view.modelorg);
+	AngleVectors(r_refdef.view.angles, r_refdef.view.pn, r_refdef.view.right, r_refdef.view.up);
 
-	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
-
 	// current viewleaf
 	r_oldviewleaf = r_viewleaf;
-	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
+	r_viewleaf = Mod_PointInLeaf(r_refdef.view.org, cl.worldmodel);
 
 	r_dowarpold = r_dowarp;
 	r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER);
@@ -214,24 +201,9 @@
 		r_viewchanged = false;
 	}
 
-	// start off with just the four screen edge clip planes
-	R_TransformFrustum ();
-
-	// save base values
-	VectorCopy (vpn, base_vpn);
-	VectorCopy (vright, base_vright);
-	VectorCopy (vup, base_vup);
-	VectorCopy (modelorg, base_modelorg);
-
-	R_SetSkyFrame ();
-
-	R_SetUpFrustumIndexes ();
-
 	r_cache_thrash = false;
-
-	// clear frame counts
-	c_faceclip = 0;
-
-	D_SetupFrame ();
+	R_TransformFrustum(&r_refdef.view); // start off with just the four screen edge clip planes
+	R_SetSkyFrame();
+	R_SetUpFrustumIndexes(&r_refdef.view);
+	D_SetupFrame();
 }
-
--- a/r_part.c
+++ b/r_part.c
@@ -510,9 +510,9 @@
 	float			dvel;
 	float			frametime;
 
-	VectorScale (vright, xscaleshrink, r_pright);
-	VectorScale (vup, yscaleshrink, r_pup);
-	VectorCopy (vpn, r_ppn);
+	VectorScale (r_refdef.view.right, xscaleshrink, r_pright);
+	VectorScale (r_refdef.view.up, yscaleshrink, r_pup);
+	VectorCopy (r_refdef.view.pn, r_ppn);
 	frametime = cl.time - cl.oldtime;
 	time3 = frametime * 15;
 	time2 = frametime * 10; // 15;
--- a/r_shared.h
+++ b/r_shared.h
@@ -44,9 +44,6 @@
 extern int	sintable[SIN_BUFFER_SIZE];
 extern int	intsintable[SIN_BUFFER_SIZE];
 
-extern	vec3_t	vup, base_vup;
-extern	vec3_t	vpn, base_vpn;
-extern	vec3_t	vright, base_vright;
 extern	entity_t		*currententity;
 
 // NOTE: these are only initial values. limits are supposed to scale up dynamically
@@ -95,8 +92,6 @@
 extern vec3_t	sxformaxis[4];	// s axis transformed into viewspace
 extern vec3_t	txformaxis[4];	// t axis transformed into viewspac
 
-extern vec3_t	modelorg, base_modelorg;
-
 extern	float	xcenter, ycenter;
 extern	float	xscale, yscale;
 extern	float	xscaleinv, yscaleinv;
@@ -104,7 +99,6 @@
 
 extern	int d_lightstylevalue[256]; // 8.8 frac of base light value
 
-extern void TransformVector (vec3_t in, vec3_t out);
 extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
 	fixed8_t endvertu, fixed8_t endvertv);
 
--- a/r_sprite.c
+++ b/r_sprite.c
@@ -12,16 +12,17 @@
 R_RotateSprite
 ================
 */
-void R_RotateSprite (float beamlength)
+static void
+R_RotateSprite(float beamlength, view_t *v)
 {
 	vec3_t	vec;
 
-	if (beamlength == 0.0)
+	if(beamlength == 0.0)
 		return;
 
-	VectorScale (r_spritedesc.vpn, -beamlength, vec);
-	VectorAdd (r_entorigin, vec, r_entorigin);
-	VectorSubtract (modelorg, vec, modelorg);
+	VectorScale(r_spritedesc.vpn, -beamlength, vec);
+	VectorAdd(r_entorigin, vec, r_entorigin);
+	VectorSubtract(v->org, vec, v->modelorg);
 }
 
 
@@ -33,7 +34,8 @@
 Throws out the back side
 ==============
 */
-int R_ClipSpriteFace (int nump, clipplane_t *pclipplane)
+static int
+R_ClipSpriteFace(int nump, clipplane_t *pclipplane)
 {
 	int		i, outcount;
 	float	dists[MAXWORKINGVERTS+1];
@@ -111,7 +113,8 @@
 R_SetupAndDrawSprite
 ================
 */
-void R_SetupAndDrawSprite (void)
+static void
+R_SetupAndDrawSprite(view_t *v)
 {
 	int			i, nump;
 	float		dot, scale, *pv;
@@ -119,7 +122,7 @@
 	vec3_t		left, up, right, down, transformed, local;
 	emitpoint_t	outverts[MAXWORKINGVERTS+1], *pout;
 
-	dot = DotProduct (r_spritedesc.vpn, modelorg);
+	dot = DotProduct (r_spritedesc.vpn, v->modelorg);
 
 	// backface cull
 	if (dot >= 0)
@@ -163,7 +166,7 @@
 
 	for (i=0 ; i<4 ; i++)
 	{
-		nump = R_ClipSpriteFace (nump, &view_clipplanes[i]);
+		nump = R_ClipSpriteFace (nump, &v->clipplanes[i]);
 		if (nump < 3)
 			return;
 		if (nump >= MAXWORKINGVERTS)
@@ -176,8 +179,8 @@
 
 	for (i=0 ; i<nump ; i++)
 	{
-		VectorSubtract (pv, r_origin, local);
-		TransformVector (local, transformed);
+		VectorSubtract(pv, v->org, local);
+		TransformVector(local, transformed, v);
 
 		if (transformed[2] < NEAR_CLIP)
 			transformed[2] = NEAR_CLIP;
@@ -202,7 +205,7 @@
 	// draw it
 	r_spritedesc.nump = nump;
 	r_spritedesc.pverts = outverts;
-	D_DrawSprite ();
+	D_DrawSprite(v);
 }
 
 
@@ -211,7 +214,8 @@
 R_GetSpriteframe
 ================
 */
-mspriteframe_t *R_GetSpriteframe (msprite_t *psprite)
+static mspriteframe_t *
+R_GetSpriteframe(msprite_t *psprite)
 {
 	mspritegroup_t	*pspritegroup;
 	mspriteframe_t	*pspriteframe;
@@ -255,13 +259,13 @@
 	return pspriteframe;
 }
 
-
 /*
 ================
 R_DrawSprite
 ================
 */
-void R_DrawSprite (void)
+void
+R_DrawSprite(view_t *v)
 {
 	int				i;
 	msprite_t		*psprite;
@@ -284,9 +288,9 @@
 		// 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];
+		tvec[0] = -v->modelorg[0];
+		tvec[1] = -v->modelorg[1];
+		tvec[2] = -v->modelorg[2];
 		VectorNormalize (tvec);
 		dot = tvec[2];	// same as DotProduct (tvec, r_spritedesc.vup) because
 						//  r_spritedesc.vup is 0, 0, 1
@@ -296,7 +300,7 @@
 		r_spritedesc.vup[1] = 0;
 		r_spritedesc.vup[2] = 1;
 		r_spritedesc.vright[0] = tvec[1];
-								// CrossProduct(r_spritedesc.vup, -modelorg,
+								// CrossProduct(r_spritedesc.vup, -v->modelorg,
 		r_spritedesc.vright[1] = -tvec[0];
 								//              r_spritedesc.vright)
 		r_spritedesc.vright[2] = 0;
@@ -314,9 +318,9 @@
 		// position relative to the viewer
 		for (i=0 ; i<3 ; i++)
 		{
-			r_spritedesc.vup[i] = vup[i];
-			r_spritedesc.vright[i] = vright[i];
-			r_spritedesc.vpn[i] = vpn[i];
+			r_spritedesc.vup[i] = v->up[i];
+			r_spritedesc.vright[i] = v->right[i];
+			r_spritedesc.vpn[i] = v->pn[i];
 		}
 	}
 	else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT)
@@ -327,16 +331,17 @@
 		// 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
+		dot = v->pn[2];
+		// same as DotProduct (v->pn, r_spritedesc.vup) because
+		//  r_spritedesc.vup is 0, 0, 1
 		if ((dot > 0.999848) || (dot < -0.999848))	// cosf(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[0] = v->pn[1];
+										// CrossProduct (r_spritedesc.vup, v->vpn,
+		r_spritedesc.vright[1] = -v->pn[0];	//  r_spritedesc.vright)
 		r_spritedesc.vright[2] = 0;
 		VectorNormalize (r_spritedesc.vright);
 		r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
@@ -362,9 +367,9 @@
 
 		for (i=0 ; i<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;
+			r_spritedesc.vpn[i] = v->pn[i];
+			r_spritedesc.vright[i] = v->right[i] * cr + v->up[i] * sr;
+			r_spritedesc.vup[i] = v->right[i] * -sr + v->up[i] * cr;
 		}
 	}
 	else
@@ -372,8 +377,7 @@
 		fatal ("R_DrawSprite: Bad sprite type %d", psprite->type);
 	}
 
-	R_RotateSprite (psprite->beamlength);
-
-	R_SetupAndDrawSprite ();
+	R_RotateSprite(psprite->beamlength, v);
+	R_SetupAndDrawSprite(v);
 }
 
--- a/r_surf.c
+++ b/r_surf.c
@@ -16,7 +16,7 @@
 R_AddDynamicLights
 ===============
 */
-void R_AddDynamicLights (void)
+void R_AddDynamicLights (entity_t *e)
 {
 	msurface_t *surf;
 	int			lnum;
@@ -39,9 +39,8 @@
 			continue;		// not lit by this light
 
 		rad = cl_dlights[lnum].radius;
-		VectorSubtract(cl_dlights[lnum].origin, currententity->origin, entorigin);
-		dist = DotProduct (entorigin, surf->plane->normal) -
-				surf->plane->dist;
+		VectorSubtract(cl_dlights[lnum].origin, e->origin, entorigin);
+		dist = DotProduct (entorigin, surf->plane->normal) - surf->plane->dist;
 		rad -= fabs(dist);
 		minlight = cl_dlights[lnum].minlight;
 		if (rad < minlight)
@@ -91,7 +90,7 @@
 Combine and scale multiple lightmaps into the 8.8 format in blocklights
 ===============
 */
-void R_BuildLightMap (void)
+void R_BuildLightMap (entity_t *e)
 {
 	int			smax, tmax;
 	int			t;
@@ -137,7 +136,7 @@
 
 	// add all the dynamic lights
 	if (surf->dlightframe == r_framecount)
-		R_AddDynamicLights ();
+		R_AddDynamicLights(e);
 
 	// bound, invert, and shift
 	for (i=0 ; i<size ; i++)
@@ -159,12 +158,13 @@
 Returns the proper texture for a given time and base texture
 ===============
 */
-texture_t *R_TextureAnimation (texture_t *base)
+texture_t *
+R_TextureAnimation(entity_t *e, texture_t *base)
 {
 	int		reletive;
 	int		count;
 
-	if (currententity->frame)
+	if (e->frame)
 	{
 		if (base->alternate_anims)
 			base = base->alternate_anims;
@@ -188,29 +188,6 @@
 	return base;
 }
 
-inline pixel_t
-addlight(pixel_t x, int lr, int lg, int lb)
-{
-	int r, g, b;
-
-	if((x & 0xff000000U) == 0)
-		return x;
-
-	if(currententity != nil && (currententity->effects & EF_ADDITIVE) != 0)
-		return x;
-
-	r = (x>>16) & 0xff;
-	g = (x>>8)  & 0xff;
-	b = (x>>0)  & 0xff;
-
-	r = (r * ((64<<8)-(lr & 0xffff))) >> (8+VID_CBITS);
-	g = (g * ((64<<8)-(lg & 0xffff))) >> (8+VID_CBITS);
-	b = (b * ((64<<8)-(lb & 0xffff))) >> (8+VID_CBITS);
-	x = (x & 0xff000000) | r<<16 | g<<8 | b<<0;
-
-	return x;
-}
-
 #define fullbright 1
 #define additive 1
 #define addlight addlight_f1_a1
@@ -305,7 +282,7 @@
 R_DrawSurface
 ===============
 */
-void R_DrawSurface (void)
+void R_DrawSurface (entity_t *e)
 {
 	pixel_t	*basetptr;
 	int				smax, tmax, twidth, lightwidth;
@@ -319,13 +296,13 @@
 	unsigned *lp[3];
 
 	// calculate the lightings
-	R_BuildLightMap ();
+	R_BuildLightMap(e);
 
 	surfrowbytes = r_drawsurf.rowbytes;
 
 	mt = r_drawsurf.texture;
 
-	draw = drawsurf[mt->drawsurf][currententity != nil && (currententity->effects & EF_ADDITIVE) != 0][r_drawsurf.surfmip];
+	draw = drawsurf[mt->drawsurf][e != nil && (e->effects & EF_ADDITIVE) != 0][r_drawsurf.surfmip];
 
 	r_source = mt->pixels + mt->offsets[r_drawsurf.surfmip];
 
@@ -378,4 +355,27 @@
 
 		pcolumndest += horzblockstep;
 	}
+}
+
+pixel_t
+addlight(entity_t *e, pixel_t x, int lr, int lg, int lb)
+{
+	int r, g, b;
+
+	if((x & 0xff000000U) == 0)
+		return x;
+
+	if(e != nil && (e->effects & EF_ADDITIVE) != 0)
+		return x;
+
+	r = (x>>16) & 0xff;
+	g = (x>>8)  & 0xff;
+	b = (x>>0)  & 0xff;
+
+	r = (r * ((64<<8)-(lr & 0xffff))) >> (8+VID_CBITS);
+	g = (g * ((64<<8)-(lg & 0xffff))) >> (8+VID_CBITS);
+	b = (b * ((64<<8)-(lb & 0xffff))) >> (8+VID_CBITS);
+	x = (x & 0xff000000) | r<<16 | g<<8 | b<<0;
+
+	return x;
 }
--- a/render.h
+++ b/render.h
@@ -52,8 +52,6 @@
 	byte alpha;
 } entity_t;
 
-
-
 // !!! if this is changed, it must be changed in asm_draw.h too !!!
 typedef struct
 {
@@ -77,9 +75,7 @@
 	float		xOrigin;			// should probably always be 0.5
 	float		yOrigin;			// between be around 0.3 to 0.5
 
-	vec3_t		vieworg;
-	vec3_t		viewangles;
-
+	view_t		view;
 	float		fov_x, fov_y;
 
 	int			ambientlight[3];
@@ -91,7 +87,6 @@
 //
 
 extern	refdef_t	r_refdef;
-extern vec3_t	r_origin, vpn, vright, vup;
 
 extern	struct texture_s	*r_notexture_mip;
 
--- a/snd_mix.c
+++ b/snd_mix.c
@@ -318,7 +318,7 @@
 }
 
 void
-stepsnd(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
+stepsnd(view_t *v)
 {
 	long ns;
 	Chan *c, *sum;
@@ -346,10 +346,10 @@
 	}
 	sndt = nanosec();
 
-	VectorCopy(origin, listener_origin);
-	VectorCopy(forward, listener_forward);
-	VectorCopy(right, listener_right);
-	VectorCopy(up, listener_up);
+	VectorCopy(v->org, listener_origin);
+	VectorCopy(v->pn, listener_forward);
+	VectorCopy(v->right, listener_right);
+	VectorCopy(v->up, listener_up);
 	ambs();
 	sum = nil;
 	for(c=chans+Namb; c<che; c++){
--- a/snd_openal.c
+++ b/snd_openal.c
@@ -289,7 +289,7 @@
 
 
 static void
-ambs(vec3_t org)
+ambs(const vec3_t org)
 {
 	float vol, *av;
 	ALint state;
@@ -330,30 +330,30 @@
 }
 
 void
-stepsnd(vec3_t zp, vec3_t fw, vec3_t rt, vec3_t up)
+stepsnd(const view_t *v)
 {
-	vec_t fwup[6] = {fw[0], fw[1], fw[2], up[0], up[1], up[2]};
+	vec_t fwup[6] = {v->pn[0], v->pn[1], v->pn[2], v->up[0], v->up[1], v->up[2]};
 	alchan_t *c, *next;
-	static vec3_t ozp;
+	static vec3_t oorg;
 	ALint state;
 	vec3_t vel;
 
 	if(dev == nil)
 		return;
-	if(zp == vec3_origin && fw == vec3_origin && rt == vec3_origin){
+	if(v->pn[0] == 0 && v->pn[1] == 0 && v->pn[2] == 0){
 		alListenerf(AL_GAIN, 0);
 		ALERR();
 		return;
 	}
 
-	alListenerfv(AL_POSITION, zp); ALERR();
+	alListenerfv(AL_POSITION, v->org); ALERR();
 	alListenerfv(AL_ORIENTATION, fwup); ALERR();
-	VectorSubtract(zp, ozp, vel);
-	VectorCopy(zp, ozp);
+	VectorSubtract(v->org, oorg, vel);
+	VectorCopy(v->org, oorg);
 	alListenerfv(AL_VELOCITY, vel); ALERR();
 	alListenerf(AL_GAIN, volume.value); ALERR();
 
-	ambs(zp);
+	ambs(v->org);
 
 	for(c = chans; c != nil; c = next){
 		next = c->next;
--- a/view.c
+++ b/view.c
@@ -543,15 +543,15 @@
 	static float oldyaw = 0;
 	static float oldpitch = 0;
 
-	yaw = r_refdef.viewangles[YAW];
-	pitch = -r_refdef.viewangles[PITCH];
+	yaw = r_refdef.view.angles[YAW];
+	pitch = -r_refdef.view.angles[PITCH];
 
-	yaw = angledelta(yaw - r_refdef.viewangles[YAW]) * 0.4;
+	yaw = angledelta(yaw - r_refdef.view.angles[YAW]) * 0.4;
 	if (yaw > 10)
 		yaw = 10;
 	if (yaw < -10)
 		yaw = -10;
-	pitch = angledelta(-pitch - r_refdef.viewangles[PITCH]) * 0.4;
+	pitch = angledelta(-pitch - r_refdef.view.angles[PITCH]) * 0.4;
 	if (pitch > 10)
 		pitch = 10;
 	if (pitch < -10)
@@ -582,8 +582,8 @@
 	oldyaw = yaw;
 	oldpitch = pitch;
 
-	cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw;
-	cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch);
+	cl.viewent.angles[YAW] = r_refdef.view.angles[YAW] + yaw;
+	cl.viewent.angles[PITCH] = - (r_refdef.view.angles[PITCH] + pitch);
 
 	cl.viewent.angles[ROLL] -= v_idlescale.value * sinf(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
 	cl.viewent.angles[PITCH] -= v_idlescale.value * sinf(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
@@ -604,18 +604,18 @@
 	// absolutely bound refresh reletive to entity clipping hull
 	// so the view can never be inside a solid wall
 
-	if (r_refdef.vieworg[0] < ent->origin[0] - 14)
-		r_refdef.vieworg[0] = ent->origin[0] - 14;
-	else if (r_refdef.vieworg[0] > ent->origin[0] + 14)
-		r_refdef.vieworg[0] = ent->origin[0] + 14;
-	if (r_refdef.vieworg[1] < ent->origin[1] - 14)
-		r_refdef.vieworg[1] = ent->origin[1] - 14;
-	else if (r_refdef.vieworg[1] > ent->origin[1] + 14)
-		r_refdef.vieworg[1] = ent->origin[1] + 14;
-	if (r_refdef.vieworg[2] < ent->origin[2] - 22)
-		r_refdef.vieworg[2] = ent->origin[2] - 22;
-	else if (r_refdef.vieworg[2] > ent->origin[2] + 30)
-		r_refdef.vieworg[2] = ent->origin[2] + 30;
+	if (r_refdef.view.org[0] < ent->origin[0] - 14)
+		r_refdef.view.org[0] = ent->origin[0] - 14;
+	else if (r_refdef.view.org[0] > ent->origin[0] + 14)
+		r_refdef.view.org[0] = ent->origin[0] + 14;
+	if (r_refdef.view.org[1] < ent->origin[1] - 14)
+		r_refdef.view.org[1] = ent->origin[1] - 14;
+	else if (r_refdef.view.org[1] > ent->origin[1] + 14)
+		r_refdef.view.org[1] = ent->origin[1] + 14;
+	if (r_refdef.view.org[2] < ent->origin[2] - 22)
+		r_refdef.view.org[2] = ent->origin[2] - 22;
+	else if (r_refdef.view.org[2] > ent->origin[2] + 30)
+		r_refdef.view.org[2] = ent->origin[2] + 30;
 }
 
 /*
@@ -627,9 +627,9 @@
 */
 void V_AddIdle (void)
 {
-	r_refdef.viewangles[ROLL] += v_idlescale.value * sinf(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
-	r_refdef.viewangles[PITCH] += v_idlescale.value * sinf(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
-	r_refdef.viewangles[YAW] += v_idlescale.value * sinf(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
+	r_refdef.view.angles[ROLL] += v_idlescale.value * sinf(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
+	r_refdef.view.angles[PITCH] += v_idlescale.value * sinf(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
+	r_refdef.view.angles[YAW] += v_idlescale.value * sinf(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
 }
 
 
@@ -645,18 +645,18 @@
 	float		side;
 
 	side = V_CalcRoll (cl_entities[cl.viewentity].angles, cl.velocity);
-	r_refdef.viewangles[ROLL] += side;
+	r_refdef.view.angles[ROLL] += side;
 
 	if (v_dmg_time > 0)
 	{
-		r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
-		r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
+		r_refdef.view.angles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
+		r_refdef.view.angles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
 		v_dmg_time -= host_frametime;
 	}
 
 	if (cl.stats[STAT_HEALTH] <= 0)
 	{
-		r_refdef.viewangles[ROLL] = 80;	// dead view angle
+		r_refdef.view.angles[ROLL] = 80;	// dead view angle
 		return;
 	}
 
@@ -679,8 +679,8 @@
 	// view is the weapon model (only visible from inside body)
 	view = &cl.viewent;
 
-	VectorCopy (ent->origin, r_refdef.vieworg);
-	VectorCopy (ent->angles, r_refdef.viewangles);
+	VectorCopy (ent->origin, r_refdef.view.org);
+	VectorCopy (ent->angles, r_refdef.view.angles);
 	view->model = nil;
 
 	// always idle in intermission
@@ -723,17 +723,17 @@
 	bob = V_CalcBob ();
 
 	// refresh position
-	VectorCopy (ent->origin, r_refdef.vieworg);
-	r_refdef.vieworg[2] += cl.viewheight + bob;
+	VectorCopy (ent->origin, r_refdef.view.org);
+	r_refdef.view.org[2] += cl.viewheight + bob;
 
 	// never let it sit exactly on a node line, because a water plane can
 	// dissapear when viewed with the eye exactly on it.
 	// the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis
-	r_refdef.vieworg[0] += 1.0/32;
-	r_refdef.vieworg[1] += 1.0/32;
-	r_refdef.vieworg[2] += 1.0/32;
+	r_refdef.view.org[0] += 1.0/32;
+	r_refdef.view.org[1] += 1.0/32;
+	r_refdef.view.org[2] += 1.0/32;
 
-	VectorCopy (cl.viewangles, r_refdef.viewangles);
+	VectorCopy (cl.viewangles, r_refdef.view.angles);
 	V_CalcViewRoll ();
 	V_AddIdle ();
 
@@ -746,7 +746,7 @@
 	AngleVectors (angles, forward, right, up);
 
 	for (i=0 ; i<3 ; i++)
-		r_refdef.vieworg[i] += scr_ofsx.value*forward[i]
+		r_refdef.view.org[i] += scr_ofsx.value*forward[i]
 			+ scr_ofsy.value*right[i]
 			+ scr_ofsz.value*up[i];
 
@@ -785,7 +785,7 @@
 	view->colormap = vid.colormap;
 
 	// set up the refresh position
-	VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles);
+	VectorAdd (r_refdef.view.angles, cl.punchangle, r_refdef.view.angles);
 
 	// smooth out stair step ups
 	if(!noclip_anglehack && cl.onground && ent->origin[2] - v_step_z > 0){
@@ -800,7 +800,7 @@
 			v_step_time = cl.time;
 		}
 
-		r_refdef.vieworg[2] += v_step_z - ent->origin[2];
+		r_refdef.view.org[2] += v_step_z - ent->origin[2];
 		view->origin[2] += v_step_z - ent->origin[2];
 	}else{
 		v_step_z = v_step_oldz = ent->origin[2];
@@ -861,9 +861,9 @@
 		vid.width <<= 1;
 		vid.aspect *= 0.5;
 
-		r_refdef.viewangles[YAW] -= lcd_yaw.value;
+		r_refdef.view.angles[YAW] -= lcd_yaw.value;
 		for (i=0 ; i<3 ; i++)
-			r_refdef.vieworg[i] -= right[i]*lcd_x.value;
+			r_refdef.view.org[i] -= right[i]*lcd_x.value;
 		R_RenderView ();
 
 		vid.buffer += vid.width>>1;
@@ -870,9 +870,9 @@
 
 		R_PushDlights ();
 
-		r_refdef.viewangles[YAW] += lcd_yaw.value*2;
+		r_refdef.view.angles[YAW] += lcd_yaw.value*2;
 		for (i=0 ; i<3 ; i++)
-			r_refdef.vieworg[i] += 2*right[i]*lcd_x.value;
+			r_refdef.view.org[i] += 2*right[i]*lcd_x.value;
 		R_RenderView ();
 
 		vid.buffer -= vid.width>>1;