r_refdef.vieworg and r_refdef.viewangles replaced by r_refdef.viewentitymatrix
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 14 Nov 2003 14:02:56 +0000 (14:02 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 14 Nov 2003 14:02:56 +0000 (14:02 +0000)
fixed intermission camera bug (now the right place and angles by copying the entity matrix directly to r_refdef)
fixed intermission listener bug (now the right place by copying the entity matrix to listener variables)
fixed envmap command saving (now reads the correct part of the screen according to GL's bottom to top coordinates, so this works again)
fixed envmap command rendering (it was not hiding view and exterior models)
fixed timerefresh command rendering (it was not properly setting up the view)
merged chase.c into view.c because it really didn't have any good reasons to be separate
renamed listener_forward to listener_viewforward, listener_up to listener_viewup, listener_origin to listener_vieworigin, and converted listener_right to listener_viewleft
renamed vpn to r_viewforward, vup to r_viewup, vright to r_viewright (deprecated, trying to use just r_viewleft but haven't finished converting things over to it yet), r_origin to r_vieworigin

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3646 d7cf8633-e32d-0410-b094-e92efae38249

23 files changed:
chase.c [deleted file]
cl_particles.c
cl_screen.c
client.h
gl_backend.c
gl_backend.h
gl_models.c
gl_rmain.c
gl_rsurf.c
host.c
makefile
meshqueue.c
r_crosshairs.c
r_light.c
r_lightning.c
r_shadow.c
r_sky.c
r_sprites.c
render.h
snd_dma.c
sound.h
todo
view.c

diff --git a/chase.c b/chase.c
deleted file mode 100644 (file)
index cef9305..0000000
--- a/chase.c
+++ /dev/null
@@ -1,81 +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.
-
-*/
-// chase.c -- chase camera code
-
-#include "quakedef.h"
-#include "cl_collision.h"
-
-cvar_t chase_back = {CVAR_SAVE, "chase_back", "48"};
-cvar_t chase_up = {CVAR_SAVE, "chase_up", "24"};
-cvar_t chase_active = {CVAR_SAVE, "chase_active", "0"};
-// GAME_GOODVSBAD2
-cvar_t chase_stevie = {0, "chase_stevie", "0"};
-
-void Chase_Init (void)
-{
-       Cvar_RegisterVariable (&chase_back);
-       Cvar_RegisterVariable (&chase_up);
-       Cvar_RegisterVariable (&chase_active);
-       if (gamemode == GAME_GOODVSBAD2)
-               Cvar_RegisterVariable (&chase_stevie);
-}
-
-void Chase_Reset (void)
-{
-       // for respawning and teleporting
-//     start position 12 units behind head
-}
-
-void Chase_Update (void)
-{
-       vec_t camback, camup, dist, forward[3], stop[3], chase_dest[3], normal[3], projectangles[3];
-
-       camback = bound(0, chase_back.value, 128);
-       if (chase_back.value != camback)
-               Cvar_SetValueQuick(&chase_back, camback);
-       camup = bound(-48, chase_up.value, 96);
-       if (chase_up.value != camup)
-               Cvar_SetValueQuick(&chase_up, camup);
-
-       // this + 22 is to match view_ofs for compatibility with older versions
-       camup += 22;
-
-       VectorCopy(cl.viewangles, projectangles);
-       if (gamemode == GAME_GOODVSBAD2 && chase_stevie.integer)
-       {
-               projectangles[0] = 90;
-               r_refdef.viewangles[0] = 90;
-               camback = 2048;
-       }
-       AngleVectors (projectangles, forward, NULL, NULL);
-
-       dist = -chase_back.value - 8;
-       chase_dest[0] = r_refdef.vieworg[0] + forward[0] * dist;
-       chase_dest[1] = r_refdef.vieworg[1] + forward[1] * dist;
-       chase_dest[2] = r_refdef.vieworg[2] + forward[2] * dist + chase_up.value;
-
-       CL_TraceLine(r_refdef.vieworg, chase_dest, stop, normal, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY);
-       chase_dest[0] = stop[0] + forward[0] * 8 + normal[0] * 4;
-       chase_dest[1] = stop[1] + forward[1] * 8 + normal[1] * 4;
-       chase_dest[2] = stop[2] + forward[2] * 8 + normal[2] * 4;
-
-       VectorCopy (chase_dest, r_refdef.vieworg);
-}
-
index 59b745f..7d24c80 100644 (file)
@@ -49,12 +49,12 @@ void R_CalcBeam_Vertex3f (float *vert, vec3_t org1, vec3_t org2, float width)
        VectorNormalizeFast (normal);
 
        // calculate 'right' vector for start
-       VectorSubtract (r_origin, org1, diff);
+       VectorSubtract (r_vieworigin, org1, diff);
        VectorNormalizeFast (diff);
        CrossProduct (normal, diff, right1);
 
        // calculate 'right' vector for end
-       VectorSubtract (r_origin, org2, diff);
+       VectorSubtract (r_vieworigin, org2, diff);
        VectorNormalizeFast (diff);
        CrossProduct (normal, diff, right2);
 
@@ -1819,7 +1819,7 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2)
 #ifndef WORKINGLQUAKE
        if (fogenabled && p->blendmode != PBLEND_MOD)
        {
-               VectorSubtract(org, r_origin, fogvec);
+               VectorSubtract(org, r_vieworigin, fogvec);
                fog = exp(fogdensity/DotProduct(fogvec,fogvec));
                ifog = 1 - fog;
                cr = cr * ifog;
@@ -1857,7 +1857,7 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2)
                if (p->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
                {
                        // double-sided
-                       if (DotProduct(p->vel2, r_origin) > DotProduct(p->vel2, org))
+                       if (DotProduct(p->vel2, r_vieworigin) > DotProduct(p->vel2, org))
                        {
                                VectorNegate(p->vel2, v);
                                VectorVectors(v, right, up);
@@ -1869,8 +1869,8 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2)
                }
                else
                {
-                       VectorScale(vright, p->scalex, right);
-                       VectorScale(vup, p->scaley, up);
+                       VectorScale(r_viewleft, -p->scalex, right);
+                       VectorScale(r_viewup, p->scaley, up);
                }
                particle_vertex3f[ 0] = org[0] - right[0] - up[0];
                particle_vertex3f[ 1] = org[1] - right[1] - up[1];
@@ -1947,7 +1947,7 @@ void R_DrawParticles (void)
        if ((!cl_numparticles) || (!r_drawparticles.integer))
                return;
 
-       minparticledist = DotProduct(r_origin, vpn) + 4.0f;
+       minparticledist = DotProduct(r_vieworigin, r_viewforward) + 4.0f;
 
 #ifdef WORKINGLQUAKE
        glBindTexture(GL_TEXTURE_2D, particlefonttexture);
@@ -1956,7 +1956,7 @@ void R_DrawParticles (void)
        glDepthMask(0);
        // LordHavoc: only render if not too close
        for (i = 0, p = particles;i < cl_numparticles;i++, p++)
-               if (DotProduct(p->org, vpn) >= minparticledist)
+               if (DotProduct(p->org, r_viewforward) >= minparticledist)
                        R_DrawParticle(p);
        glDepthMask(1);
        glDisable(GL_BLEND);
@@ -1965,7 +1965,7 @@ void R_DrawParticles (void)
        // LordHavoc: only render if not too close
        c_particles += cl_numparticles;
        for (i = 0, p = particles;i < cl_numparticles;i++, p++)
-               if (DotProduct(p->org, vpn) >= minparticledist || p->orientation == PARTICLE_BEAM)
+               if (DotProduct(p->org, r_viewforward) >= minparticledist || p->orientation == PARTICLE_BEAM)
                        R_MeshQueue_AddTransparent(p->org, R_DrawParticleCallback, p, 0);
 #endif
 }
index c485c80..0a58d68 100644 (file)
@@ -32,7 +32,6 @@ qboolean      scr_drawloading = false;
 static qbyte menuplyr_pixels[4096];
 
 void DrawCrosshair(int num);
-void V_CalcRefdef (void);
 static void SCR_ScreenShot_f (void);
 static void R_Envmap_f (void);
 
@@ -366,13 +365,12 @@ void R_TimeReport_Start(void)
        if (r_timereport_active)
        {
                speedstringcount = 0;
-               AngleVectors (r_refdef.viewangles, vpn, NULL, NULL);
                sprintf(r_speeds_string,
-                       "org:'%+8.2f %+8.2f %+8.2f' ang:'%+4.0f %+4.0f %+4.0f' dir:'%+2.3f %+2.3f %+2.3f'\n"
+                       "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n"
                        "world:%6i faces%6i nodes%6i leafs%6i dlitwalls\n"
                        "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n"
                        "%6i modeltris%6i meshs%6i meshtris\n",
-                       r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2], r_refdef.viewangles[0], r_refdef.viewangles[1], r_refdef.viewangles[2], vpn[0], vpn[1], vpn[2],
+                       r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], r_viewforward[0], r_viewforward[1], r_viewforward[2],
                        c_faces, c_nodes, c_leafs, c_light_polys,
                        c_models, c_bmodels, c_sprites, c_particles, c_dlights,
                        c_alias_polys, c_meshs, c_meshelements / 3);
@@ -635,7 +633,7 @@ void DrawQ_SetClipArea(float x, float y, float width, float height)
        dq->scaley = height;
        dq->flags = 0;
        dq->color = 0;
-       
+
        r_refdef.drawqueuesize += dq->size;
 }
 
@@ -656,7 +654,7 @@ void DrawQ_ResetClipArea(void)
        dq->scaley = 0;
        dq->flags = 0;
        dq->color = 0;
-       
+
        r_refdef.drawqueuesize += dq->size;
 }
 
@@ -742,7 +740,7 @@ static void SCR_CalcRefdef (void)
        if (cl.worldmodel)
        {
                Mod_CheckLoaded(cl.worldmodel);
-               contents = CL_PointSuperContents(r_refdef.vieworg);
+               contents = CL_PointSuperContents(r_vieworigin);
                if (contents & SUPERCONTENTS_LIQUIDSMASK)
                {
                        r_refdef.fov_x *= (sin(cl.time * 4.7) * 0.015 + 0.985);
@@ -870,10 +868,10 @@ static void R_Envmap_f (void)
        for (j = 0;j < 6;j++)
        {
                sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
-               VectorCopy(envmapinfo[j].angles, r_refdef.viewangles);
+               Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
                R_ClearScreen();
-               R_RenderView ();
-               SCR_ScreenShot(filename, vid.realx, vid.realy, size, size, false);
+               R_RenderView();
+               SCR_ScreenShot(filename, vid.realx, vid.realy + vid.realheight - (r_refdef.y + r_refdef.height), size, size, false);
        }
 
        envmap = false;
index 4183a3f..c588db9 100644 (file)
--- a/client.h
+++ b/client.h
@@ -636,9 +636,8 @@ typedef struct
        int x, y, width, height;
        float fov_x, fov_y;
 
-       // view point
-       vec3_t vieworg;
-       vec3_t viewangles;
+       // view transform
+       matrix4x4_t viewentitymatrix;
 
        // fullscreen color blend
        float viewblend[4];
index 5651885..a4fd9fc 100644 (file)
@@ -229,14 +229,17 @@ void GL_SetupView_Orientation_Identity (void)
        memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
 }
 
-void GL_SetupView_Orientation_FromEntity (vec3_t origin, vec3_t angles)
+void GL_SetupView_Orientation_FromEntity(matrix4x4_t *matrix)
 {
-       Matrix4x4_CreateRotate(&backend_viewmatrix, -90, 1, 0, 0);
-       Matrix4x4_ConcatRotate(&backend_viewmatrix, 90, 0, 0, 1);
-       Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
-       Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
-       Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
-       Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
+       matrix4x4_t tempmatrix, basematrix;
+       Matrix4x4_Invert_Simple(&tempmatrix, matrix);
+       Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
+       Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
+       Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix);
+       //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
+       //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
+       //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
+       //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
        memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
 }
 
index 43a1822..dd43b40 100644 (file)
@@ -9,7 +9,7 @@ extern int polygonelements[768];
 
 void GL_SetupView_ViewPort(int x, int y, int width, int height);
 void GL_SetupView_Orientation_Identity(void);
-void GL_SetupView_Orientation_FromEntity(vec3_t origin, vec3_t angles);
+void GL_SetupView_Orientation_FromEntity(matrix4x4_t *matrix);
 void GL_SetupView_Mode_Perspective(double fovx, double fovy, double zNear, double zFar);
 void GL_SetupView_Mode_PerspectiveInfiniteFarClip(double fovx, double fovy, double zNear);
 void GL_SetupView_Mode_Ortho(double x1, double y1, double x2, double y2, double zNear, double zFar);
index 937c1d8..f7afd47 100644 (file)
@@ -175,7 +175,7 @@ void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
        fog = 0;
        if (fogenabled)
        {
-               VectorSubtract(ent->origin, r_origin, diff);
+               VectorSubtract(ent->origin, r_vieworigin, diff);
                fog = DotProduct(diff,diff);
                if (fog < 0.01f)
                        fog = 0.01f;
@@ -344,7 +344,7 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
        fog = 0;
        if (fogenabled)
        {
-               VectorSubtract(ent->origin, r_origin, diff);
+               VectorSubtract(ent->origin, r_vieworigin, diff);
                fog = DotProduct(diff,diff);
                if (fog < 0.01f)
                        fog = 0.01f;
@@ -704,7 +704,7 @@ void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
        fog = 0;
        if (fogenabled)
        {
-               VectorSubtract(ent->origin, r_origin, diff);
+               VectorSubtract(ent->origin, r_vieworigin, diff);
                fog = DotProduct(diff,diff);
                if (fog < 0.01f)
                        fog = 0.01f;
index 968f821..0efd397 100644 (file)
@@ -39,10 +39,11 @@ qboolean envmap;
 float r_farclip;
 
 // view origin
-vec3_t r_origin;
-vec3_t vpn;
-vec3_t vright;
-vec3_t vup;
+vec3_t r_vieworigin;
+vec3_t r_viewforward;
+vec3_t r_viewleft;
+vec3_t r_viewright;
+vec3_t r_viewup;
 
 //
 // screen size info
@@ -117,22 +118,23 @@ qboolean intimerefresh = 0;
 static void R_TimeRefresh_f (void)
 {
        int i;
-       float start, stop, time;
+       float timestart, timedelta, oldangles[3];
 
        intimerefresh = 1;
-       start = Sys_DoubleTime ();
+       VectorCopy(cl.viewangles, oldangles);
+       VectorClear(cl.viewangles);
+
+       timestart = Sys_DoubleTime();
        for (i = 0;i < 128;i++)
        {
-               r_refdef.viewangles[0] = 0;
-               r_refdef.viewangles[1] = i/128.0*360.0;
-               r_refdef.viewangles[2] = 0;
+               Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1);
                CL_UpdateScreen();
        }
+       timedelta = Sys_DoubleTime() - timestart;
 
-       stop = Sys_DoubleTime ();
+       VectorCopy(oldangles, cl.viewangles);
        intimerefresh = 0;
-       time = stop-start;
-       Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
+       Con_Printf ("%f seconds (%f fps)\n", timedelta, 128/timedelta);
 }
 
 vec3_t fogcolor;
@@ -431,7 +433,8 @@ static void R_MarkEntities (void)
                R_LerpAnimation(ent);
                R_UpdateEntLights(ent);
                if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
-                && !VIS_CullBox(ent->mins, ent->maxs))
+                && !VIS_CullBox(ent->mins, ent->maxs)
+                && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL))))
                {
                        ent->visframe = r_framecount;
                        R_FarClip_Box(ent->mins, ent->maxs);
@@ -617,7 +620,7 @@ void R_ShadowVolumeLighting(int visiblevolumes)
                                if (ent->model && ent->model->DrawLight)
                                {
                                        Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
-                                       Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
                                        Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
                                        Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
                                        Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
@@ -636,7 +639,7 @@ void R_ShadowVolumeLighting(int visiblevolumes)
                                                 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
                                                {
                                                        Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
-                                                       Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+                                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
                                                        Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
                                                        Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
                                                        Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
@@ -705,7 +708,7 @@ void R_ShadowVolumeLighting(int visiblevolumes)
                                if (ent->model && ent->model->DrawLight)
                                {
                                        Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                                       Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
                                        Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
                                        Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
                                        Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
@@ -721,7 +724,7 @@ void R_ShadowVolumeLighting(int visiblevolumes)
                                                 && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
                                                {
                                                        Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
-                                                       Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+                                                       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, relativeeyeorigin);
                                                        Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
                                                        Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
                                                        Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
@@ -746,24 +749,24 @@ static void R_SetFrustum (void)
        // degrees assumed a square view (wrong), so I removed it, Quake2 has it
        // disabled as well.
 
-       // rotate VPN right by FOV_X/2 degrees
-       RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
-       frustum[0].dist = DotProduct (r_origin, frustum[0].normal);
+       // rotate R_VIEWFORWARD right by FOV_X/2 degrees
+       RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
+       frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
        PlaneClassify(&frustum[0]);
 
-       // rotate VPN left by FOV_X/2 degrees
-       RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
-       frustum[1].dist = DotProduct (r_origin, frustum[1].normal);
+       // rotate R_VIEWFORWARD left by FOV_X/2 degrees
+       RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
+       frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
        PlaneClassify(&frustum[1]);
 
-       // rotate VPN up by FOV_X/2 degrees
-       RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
-       frustum[2].dist = DotProduct (r_origin, frustum[2].normal);
+       // rotate R_VIEWFORWARD up by FOV_X/2 degrees
+       RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
+       frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
        PlaneClassify(&frustum[2]);
 
-       // rotate VPN down by FOV_X/2 degrees
-       RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
-       frustum[3].dist = DotProduct (r_origin, frustum[3].normal);
+       // rotate R_VIEWFORWARD down by FOV_X/2 degrees
+       RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
+       frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
        PlaneClassify(&frustum[3]);
 }
 
@@ -785,12 +788,18 @@ static void R_SetupFrame (void)
 
        r_framecount++;
 
-// build the transformation matrix for the given view angles
-       VectorCopy (r_refdef.vieworg, r_origin);
+       // break apart the viewentity matrix into vectors for various purposes
+       Matrix4x4_ToVectors(&r_refdef.viewentitymatrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
+       VectorNegate(r_viewleft, r_viewright);
 
-       AngleVectors (r_refdef.viewangles, vpn, vright, vup);
+       GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
+       if ((r_shadow_realtime_world.integer || r_shadow_shadows.integer) && gl_stencil)
+               GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
+       else
+               GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
+       GL_SetupView_Orientation_FromEntity(&r_refdef.viewentitymatrix);
 
-       R_AnimateLight ();
+       R_AnimateLight();
 }
 
 
@@ -814,15 +823,15 @@ static void R_BlendView(void)
        GL_VertexPointer(vertex3f);
        GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
        r = 64000;
-       vertex3f[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
-       vertex3f[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
-       vertex3f[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
-       vertex3f[3] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r + vup[0] * r * 3;
-       vertex3f[4] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r + vup[1] * r * 3;
-       vertex3f[5] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r + vup[2] * r * 3;
-       vertex3f[6] = r_origin[0] + vpn[0] * 1.5 + vright[0] * r * 3 - vup[0] * r;
-       vertex3f[7] = r_origin[1] + vpn[1] * 1.5 + vright[1] * r * 3 - vup[1] * r;
-       vertex3f[8] = r_origin[2] + vpn[2] * 1.5 + vright[2] * r * 3 - vup[2] * r;
+       vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r;
+       vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r;
+       vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r;
+       vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3;
+       vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3;
+       vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3;
+       vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r;
+       vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r;
+       vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r;
        R_Mesh_Draw(3, 1, polygonelements);
 }
 
@@ -864,22 +873,16 @@ void R_RenderView (void)
        R_TimeReport("setup");
 
        if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
-               cl.worldmodel->brush.FatPVS(cl.worldmodel, r_origin, 2, r_pvsbits, sizeof(r_pvsbits));
+               cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
 
        R_WorldVisibility(world);
        R_TimeReport("worldvis");
 
-       R_FarClip_Start(r_origin, vpn, 768.0f);
+       R_FarClip_Start(r_vieworigin, r_viewforward, 768.0f);
        R_MarkEntities();
        r_farclip = R_FarClip_Finish() + 256.0f;
        R_TimeReport("markentity");
 
-       GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
-       if ((r_shadow_realtime_world.integer || r_shadow_shadows.integer) && gl_stencil)
-               GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
-       else
-               GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
-       GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
        qglDepthFunc(GL_LEQUAL);
 
        R_Mesh_Start();
@@ -970,7 +973,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa
        {
                for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
                {
-                       VectorSubtract(v, r_origin, diff);
+                       VectorSubtract(v, r_vieworigin, diff);
                        f2 = exp(fogdensity/DotProduct(diff, diff));
                        f1 = 1 - f2;
                        c[0] = c[0] * f1 + fogcolor[0] * f2;
@@ -1047,7 +1050,7 @@ void R_DrawNoModelCallback(const void *calldata1, int calldata2)
        {
                memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
                GL_ColorPointer(color4f);
-               VectorSubtract(ent->origin, r_origin, diff);
+               VectorSubtract(ent->origin, r_vieworigin, diff);
                f2 = exp(fogdensity/DotProduct(diff, diff));
                f1 = 1 - f2;
                for (i = 0, c = color4f;i < 6;i++, c += 4)
@@ -1086,12 +1089,12 @@ void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, flo
        VectorNormalizeFast (normal);
 
        // calculate 'right' vector for start
-       VectorSubtract (r_origin, org1, diff);
+       VectorSubtract (r_vieworigin, org1, diff);
        VectorNormalizeFast (diff);
        CrossProduct (normal, diff, right1);
 
        // calculate 'right' vector for end
-       VectorSubtract (r_origin, org2, diff);
+       VectorSubtract (r_vieworigin, org2, diff);
        VectorNormalizeFast (diff);
        CrossProduct (normal, diff, right2);
 
@@ -1118,7 +1121,7 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depth
 
        if (fogenabled)
        {
-               VectorSubtract(origin, r_origin, diff);
+               VectorSubtract(origin, r_vieworigin, diff);
                ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
        }
 
index fdab82c..84a9a67 100644 (file)
@@ -780,7 +780,7 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        }
 
        R_Mesh_Matrix(&ent->matrix);
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
 
        memset(&m, 0, sizeof(m));
        texture = surf->texinfo->texture->currentframe;
@@ -892,7 +892,7 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m
        float base, colorscale;
        rmeshstate_t m;
        float modelorg[3];
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
        memset(&m, 0, sizeof(m));
        if (rendertype == SURFRENDER_ADD)
        {
@@ -939,7 +939,7 @@ static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurfac
 {
        rmeshstate_t m;
        float modelorg[3];
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
        memset(&m, 0, sizeof(m));
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        GL_DepthMask(false);
@@ -959,7 +959,7 @@ static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface
 {
        rmeshstate_t m;
        float modelorg[3];
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
        memset(&m, 0, sizeof(m));
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        GL_DepthMask(false);
@@ -1099,7 +1099,7 @@ static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const te
        const msurface_t *surf;
        rmeshstate_t m;
        float modelorg[3];
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
        memset(&m, 0, sizeof(m));
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        GL_DepthMask(false);
@@ -1326,7 +1326,7 @@ void R_PrepareSurfaces(entity_render_t *ent)
                return;
 
        model = ent->model;
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
        numsurfaces = model->brushq1.nummodelsurfaces;
        surfaces = model->brushq1.surfaces + model->brushq1.firstmodelsurface;
        surfacevisframes = model->brushq1.surfacevisframes + model->brushq1.firstmodelsurface;
@@ -1416,7 +1416,7 @@ static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
                         ((i & 0x0038) >> 3) * (1.0f / 7.0f),
                         ((i & 0x01C0) >> 6) * (1.0f / 7.0f),
                         0.125f);
-       if (PlaneDiff(r_origin, (&portal->plane)) < 0)
+       if (PlaneDiff(r_vieworigin, (&portal->plane)) < 0)
        {
                for (i = portal->numpoints - 1, v = varray_vertex3f;i >= 0;i--, v += 3)
                        VectorCopy(portal->points[i].position, v);
@@ -1465,7 +1465,7 @@ void R_PrepareBrushModel(entity_render_t *ent)
        if (model == NULL)
                return;
 #if WORLDNODECULLBACKFACES
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
 #endif
        numsurfaces = model->brushq1.nummodelsurfaces;
        surf = model->brushq1.surfaces + model->brushq1.firstmodelsurface;
@@ -1504,7 +1504,7 @@ void R_SurfaceWorldNode (entity_render_t *ent)
                return;
        surfacevisframes = model->brushq1.surfacevisframes + model->brushq1.firstmodelsurface;
        surfacepvsframes = model->brushq1.surfacepvsframes + model->brushq1.firstmodelsurface;
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
 
        for (leaf = model->brushq1.pvsleafchain;leaf;leaf = leaf->pvschain)
        {
@@ -1556,7 +1556,7 @@ static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
        // RecursiveWorldNode
        surfaces = ent->model->brushq1.surfaces;
        surfacevisframes = ent->model->brushq1.surfacevisframes;
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
        viewleaf->worldnodeframe = r_framecount;
        leafstack[0] = viewleaf;
        leafstackpos = 1;
@@ -1652,7 +1652,7 @@ void R_WorldVisibility(entity_render_t *ent)
        vec3_t modelorg;
        mleaf_t *viewleaf;
 
-       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
        viewleaf = (ent->model && ent->model->brushq1.PointInLeaf) ? ent->model->brushq1.PointInLeaf(ent->model, modelorg) : NULL;
        R_PVSUpdate(ent, viewleaf);
 
@@ -2101,7 +2101,7 @@ void R_Q3BSP_DrawSky(entity_render_t *ent)
        model = ent->model;
        if (r_drawcollisionbrushes.integer < 2)
        {
-               Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+               Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
                if (ent == &cl_entities[0].render && model->brushq3.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
                {
                        if (r_q3bsp_framecount != r_framecount)
@@ -2131,7 +2131,7 @@ void R_Q3BSP_Draw(entity_render_t *ent)
        model = ent->model;
        if (r_drawcollisionbrushes.integer < 2)
        {
-               Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+               Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
                if (ent == &cl_entities[0].render && model->brushq3.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
                {
                        if (r_q3bsp_framecount != r_framecount)
@@ -2173,7 +2173,7 @@ void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
        {
                model = ent->model;
                R_Mesh_Matrix(&ent->matrix);
-               Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+               Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
                lightmins[0] = relativelightorigin[0] - lightradius;
                lightmins[1] = relativelightorigin[1] - lightradius;
                lightmins[2] = relativelightorigin[2] - lightradius;
@@ -2209,7 +2209,7 @@ void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t
        {
                model = ent->model;
                R_Mesh_Matrix(&ent->matrix);
-               Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+               Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
                lightmins[0] = relativelightorigin[0] - lightradius;
                lightmins[1] = relativelightorigin[1] - lightradius;
                lightmins[2] = relativelightorigin[2] - lightradius;
diff --git a/host.c b/host.c
index 75ee9b3..8f5b001 100644 (file)
--- a/host.c
+++ b/host.c
@@ -688,7 +688,7 @@ void _Host_Frame (float time)
        static double time3 = 0;
        int pass1, pass2, pass3;
        usercmd_t cmd; // Used for receiving input
-       
+
        if (setjmp(host_abortserver))
                return;                 // something bad happened, or the server disconnected
 
@@ -709,7 +709,7 @@ void _Host_Frame (float time)
 
        // Collect input into cmd
        IN_ProcessMove(&cmd);
-       
+
        // process console commands
        Cbuf_Execute();
 
@@ -766,12 +766,13 @@ void _Host_Frame (float time)
                time2 = Sys_DoubleTime();
 
        // update audio
-       if (cls.signon == SIGNONS)
+       if (cls.signon == SIGNONS && cl.viewentity >= 0 && cl.viewentity < MAX_EDICTS && cl_entities[cl.viewentity].state_current.active)
        {
                // LordHavoc: this used to use renderer variables (eww)
-               vec3_t forward, right, up;
-               AngleVectors(cl.viewangles, forward, right, up);
-               S_Update(cl_entities[cl.viewentity].render.origin, forward, right, up);
+               vec3_t forward, right, up, origin;
+               Matrix4x4_ToVectors(&cl_entities[cl.viewentity].render.matrix, forward, right, up, origin);
+               VectorNegate(right, right);
+               S_Update(origin, forward, right, up);
        }
        else
                S_Update(vec3_origin, vec3_origin, vec3_origin, vec3_origin);
@@ -861,7 +862,6 @@ void Host_Init (void)
        Host_InitLocal();
        Key_Init();
        Con_Init();
-       Chase_Init();
        PR_Init();
        PRVM_Init();
        Mod_Init();
@@ -897,7 +897,7 @@ void Host_Init (void)
                VID_Open();
                SCR_BeginLoadingPlaque();
        }
-       
+
        MR_Init();
 }
 
@@ -927,7 +927,7 @@ void Host_Shutdown(void)
 
        // AK shutdown PRVM
        // AK hmm, no PRVM_Shutdown(); yet
-       
+
 
        Host_WriteConfiguration ();
 
index be168a3..b520083 100644 (file)
--- a/makefile
+++ b/makefile
@@ -42,7 +42,7 @@ CMD_RM=rm -f
 endif
 
 # Objects
-CLIENTOBJECTS= cgame.o cgamevm.o chase.o cl_collision.o cl_demo.o cl_input.o \
+CLIENTOBJECTS= cgame.o cgamevm.o cl_collision.o cl_demo.o cl_input.o \
                cl_main.o cl_parse.o cl_particles.o cl_screen.o cl_video.o \
                console.o dpvsimpledecode.o fractalnoise.o gl_backend.o \
                gl_draw.o gl_models.o gl_rmain.o gl_rsurf.o gl_textures.o \
index fdbb60e..52366e9 100644 (file)
@@ -112,7 +112,7 @@ void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const void
        mq->callback = callback;
        mq->data1 = data1;
        mq->data2 = data2;
-       mq->dist = DotProduct(center, vpn) - mqt_viewplanedist;
+       mq->dist = DotProduct(center, r_viewforward) - mqt_viewplanedist;
        mq->next = NULL;
 }
 
@@ -167,7 +167,7 @@ void R_MeshQueue_BeginScene(void)
        mq_count = 0;
        mqt_count = 0;
        mq_listhead = NULL;
-       mqt_viewplanedist = DotProduct(r_origin, vpn);
+       mqt_viewplanedist = DotProduct(r_vieworigin, r_viewforward);
 }
 
 void R_MeshQueue_EndScene(void)
index 6cd5cfa..12ca524 100644 (file)
@@ -80,12 +80,12 @@ void R_DrawWorldCrosshair(void)
 
        // get the forward vector for the gun (not the view)
        AngleVectors(cl.viewangles, v2, NULL, NULL);
-       //VectorCopy(r_origin, v1);
+       //VectorCopy(r_vieworigin, v1);
        VectorMA(v1, 8192, v2, v2);
        spritescale = CL_TraceLine(v1, v2, spriteorigin, NULL, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY) * (8192.0f / 40.0f) * crosshair_size.value;
 
        // draw the sprite
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, pic->tex, true, spriteorigin, vright, vup, spritescale, -spritescale, -spritescale, spritescale, color[0], color[1], color[2], color[3]);
+       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, pic->tex, true, spriteorigin, r_viewright, r_viewup, spritescale, -spritescale, -spritescale, spritescale, color[0], color[1], color[2], color[3]);
 }
 
 void R_Draw2DCrosshair(void)
index c393f55..1ff9bfb 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -146,12 +146,12 @@ void R_DrawCoronas(void)
        if (!r_coronas.integer)
                return;
        R_Mesh_Matrix(&r_identitymatrix);
-       viewdist = DotProduct(r_origin, vpn);
+       viewdist = DotProduct(r_vieworigin, r_viewforward);
        for (i = 0;i < r_numdlights;i++)
        {
                rd = r_dlight + i;
-               dist = (DotProduct(rd->origin, vpn) - viewdist);
-               if (dist >= 24.0f && CL_TraceLine(rd->origin, r_origin, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1)
+               dist = (DotProduct(rd->origin, r_viewforward) - viewdist);
+               if (dist >= 24.0f && CL_TraceLine(rd->origin, r_vieworigin, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1)
                {
                        cscale = (1.0f / 131072.0f);
                        scale = rd->cullradius * 0.25f;
@@ -160,7 +160,7 @@ void R_DrawCoronas(void)
                                cscale *= 4.0f;
                                scale *= 2.0f;
                        }
-                       R_DrawSprite(GL_ONE, GL_ONE, lightcorona, true, rd->origin, vright, vup, scale, -scale, -scale, scale, rd->light[0] * cscale, rd->light[1] * cscale, rd->light[2] * cscale, 1);
+                       R_DrawSprite(GL_ONE, GL_ONE, lightcorona, true, rd->origin, r_viewright, r_viewup, scale, -scale, -scale, scale, rd->light[0] * cscale, rd->light[1] * cscale, rd->light[2] * cscale, 1);
                }
        }
 }
index be535c8..9cc7d0e 100644 (file)
@@ -216,7 +216,7 @@ void R_FogLightningBeam_Vertex3f_Color4f(const float *v, float *c, int numverts,
        float ifog;
        for (i = 0;i < numverts;i++, v += 3, c += 4)
        {
-               VectorSubtract(v, r_origin, fogvec);
+               VectorSubtract(v, r_vieworigin, fogvec);
                ifog = 1 - exp(fogdensity/DotProduct(fogvec,fogvec));
                c[0] = r * ifog;
                c[1] = g * ifog;
@@ -248,7 +248,7 @@ void R_DrawLightningBeamCallback(const void *calldata1, int calldata2)
 
        // calculate up vector such that it points toward viewer, and rotates around the beamdir
        // get direction from start of beam to viewer
-       VectorSubtract(r_origin, b->start, up);
+       VectorSubtract(r_vieworigin, b->start, up);
        // remove the portion of the vector that moves along the beam
        // (this leaves only a vector pointing directly away from the beam)
        t1 = -DotProduct(up, beamdir);
index a5d5c74..1826d96 100644 (file)
@@ -945,14 +945,14 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
        // if view is inside the box, just say yes it's visible
        // LordHavoc: for some odd reason scissor seems broken without stencil
        // (?!?  seems like a driver bug) so abort if gl_stencil is false
-       if (!gl_stencil || BoxesOverlap(r_origin, r_origin, mins, maxs))
+       if (!gl_stencil || BoxesOverlap(r_vieworigin, r_vieworigin, mins, maxs))
        {
                qglDisable(GL_SCISSOR_TEST);
                return false;
        }
        for (i = 0;i < 3;i++)
        {
-               if (vpn[i] >= 0)
+               if (r_viewforward[i] >= 0)
                {
                        v[i] = mins[i];
                        v2[i] = maxs[i];
@@ -963,13 +963,13 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
                        v2[i] = mins[i];
                }
        }
-       f = DotProduct(vpn, r_origin) + 1;
-       if (DotProduct(vpn, v2) <= f)
+       f = DotProduct(r_viewforward, r_vieworigin) + 1;
+       if (DotProduct(r_viewforward, v2) <= f)
        {
                // entirely behind nearclip plane
                return true;
        }
-       if (DotProduct(vpn, v) >= f)
+       if (DotProduct(r_viewforward, v) >= f)
        {
                // entirely infront of nearclip plane
                x1 = y1 = x2 = y2 = 0;
@@ -1004,12 +1004,12 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
                // create viewspace bbox
                for (i = 0;i < 8;i++)
                {
-                       v[0] = ((i & 1) ? mins[0] : maxs[0]) - r_origin[0];
-                       v[1] = ((i & 2) ? mins[1] : maxs[1]) - r_origin[1];
-                       v[2] = ((i & 4) ? mins[2] : maxs[2]) - r_origin[2];
-                       v2[0] = DotProduct(v, vright);
-                       v2[1] = DotProduct(v, vup);
-                       v2[2] = DotProduct(v, vpn);
+                       v[0] = ((i & 1) ? mins[0] : maxs[0]) - r_vieworigin[0];
+                       v[1] = ((i & 2) ? mins[1] : maxs[1]) - r_vieworigin[1];
+                       v[2] = ((i & 4) ? mins[2] : maxs[2]) - r_vieworigin[2];
+                       v2[0] = -DotProduct(v, r_viewleft);
+                       v2[1] = DotProduct(v, r_viewup);
+                       v2[2] = DotProduct(v, r_viewforward);
                        if (i)
                        {
                                if (smins[0] > v2[0]) smins[0] = v2[0];
@@ -1042,9 +1042,9 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
                        v2[0] = (i & 1) ? smins[0] : smaxs[0];
                        v2[1] = (i & 2) ? smins[1] : smaxs[1];
                        v2[2] = (i & 4) ? smins[2] : smaxs[2];
-                       v[0] = v2[0] * vright[0] + v2[1] * vup[0] + v2[2] * vpn[0] + r_origin[0];
-                       v[1] = v2[0] * vright[1] + v2[1] * vup[1] + v2[2] * vpn[1] + r_origin[1];
-                       v[2] = v2[0] * vright[2] + v2[1] * vup[2] + v2[2] * vpn[2] + r_origin[2];
+                       v[0] = v2[0] * -r_viewleft[0] + v2[1] * r_viewup[0] + v2[2] * r_viewforward[0] + r_vieworigin[0];
+                       v[1] = v2[0] * -r_viewleft[1] + v2[1] * r_viewup[1] + v2[2] * r_viewforward[1] + r_vieworigin[1];
+                       v[2] = v2[0] * -r_viewleft[2] + v2[1] * r_viewup[2] + v2[2] * r_viewforward[2] + r_vieworigin[2];
                        v[3] = 1.0f;
                        GL_TransformToScreen(v, v2);
                        //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
@@ -2055,7 +2055,7 @@ rtexture_t *lighttextures[5];
 void R_Shadow_DrawCursorCallback(const void *calldata1, int calldata2)
 {
        float scale = r_editlights_cursorgrid.value * 0.5f;
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[0], false, r_editlights_cursorlocation, vright, vup, scale, -scale, -scale, scale, 1, 1, 1, 0.5f);
+       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[0], false, r_editlights_cursorlocation, r_viewright, r_viewup, scale, -scale, -scale, scale, 1, 1, 1, 0.5f);
 }
 
 void R_Shadow_DrawLightSpriteCallback(const void *calldata1, int calldata2)
@@ -2068,7 +2068,7 @@ void R_Shadow_DrawLightSpriteCallback(const void *calldata1, int calldata2)
                intensity = 0.75 + 0.25 * sin(realtime * M_PI * 4.0);
        if (!light->meshchain_shadow)
                intensity *= 0.5f;
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[calldata2], false, light->origin, vright, vup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
+       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, lighttextures[calldata2], false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
 }
 
 void R_Shadow_DrawLightSprites(void)
@@ -2097,12 +2097,12 @@ void R_Shadow_SelectLightInView(void)
        bestrating = 0;
        for (light = r_shadow_worldlightchain;light;light = light->next)
        {
-               VectorSubtract(light->origin, r_refdef.vieworg, temp);
-               rating = (DotProduct(temp, vpn) / sqrt(DotProduct(temp, temp)));
+               VectorSubtract(light->origin, r_vieworigin, temp);
+               rating = (DotProduct(temp, r_viewforward) / sqrt(DotProduct(temp, temp)));
                if (rating >= 0.95)
                {
                        rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
-                       if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.vieworg, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1.0f)
+                       if (bestrating < rating && CL_TraceLine(light->origin, r_vieworigin, NULL, NULL, true, NULL, SUPERCONTENTS_SOLID) == 1.0f)
                        {
                                bestrating = rating;
                                best = light;
@@ -2396,8 +2396,8 @@ void R_Shadow_SetCursorLocationForView(void)
 {
        vec_t dist, push, frac;
        vec3_t dest, endpos, normal;
-       VectorMA(r_refdef.vieworg, r_editlights_cursordistance.value, vpn, dest);
-       frac = CL_TraceLine(r_refdef.vieworg, dest, endpos, normal, true, NULL, SUPERCONTENTS_SOLID);
+       VectorMA(r_vieworigin, r_editlights_cursordistance.value, r_viewforward, dest);
+       frac = CL_TraceLine(r_vieworigin, dest, endpos, normal, true, NULL, SUPERCONTENTS_SOLID);
        if (frac < 1)
        {
                dist = frac * r_editlights_cursordistance.value;
@@ -2405,7 +2405,7 @@ void R_Shadow_SetCursorLocationForView(void)
                if (push > dist)
                        push = dist;
                push = -push;
-               VectorMA(endpos, push, vpn, endpos);
+               VectorMA(endpos, push, r_viewforward, endpos);
                VectorMA(endpos, r_editlights_cursorpushoff.value, normal, endpos);
        }
        r_editlights_cursorlocation[0] = floor(endpos[0] / r_editlights_cursorgrid.value + 0.5f) * r_editlights_cursorgrid.value;
diff --git a/r_sky.c b/r_sky.c
index 474d01f..7af15ba 100644 (file)
--- a/r_sky.c
+++ b/r_sky.c
@@ -362,7 +362,7 @@ void R_Sky(void)
        matrix4x4_t skymatrix;
        if (skyrendermasked)
        {
-               Matrix4x4_CreateTranslate(&skymatrix, r_origin[0], r_origin[1], r_origin[2]);
+               Matrix4x4_CreateTranslate(&skymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2]);
                R_Mesh_Matrix(&skymatrix);
                if (skyrendersphere)
                {
index d9d8024..4e3df26 100644 (file)
@@ -11,7 +11,7 @@ static int R_SpriteSetup (const entity_render_t *ent, int type, float org[3], fl
        case SPR_VP_PARALLEL_UPRIGHT:
                // flames and such
                // vertical beam sprite, faces view plane
-               VectorNegate(vpn, matrix3[0]);
+               VectorNegate(r_viewforward, matrix3[0]);
                matrix3[0][2] = 0;
                VectorNormalizeFast(matrix3[0]);
                matrix3[1][0] = matrix3[0][1];
@@ -24,7 +24,7 @@ static int R_SpriteSetup (const entity_render_t *ent, int type, float org[3], fl
        case SPR_FACING_UPRIGHT:
                // flames and such
                // vertical beam sprite, faces viewer's origin (not the view plane)
-               VectorSubtract(ent->origin, r_origin, matrix3[0]);
+               VectorSubtract(ent->origin, r_vieworigin, matrix3[0]);
                matrix3[0][2] = 0;
                VectorNormalizeFast(matrix3[0]);
                matrix3[1][0] = matrix3[0][1];
@@ -40,25 +40,25 @@ static int R_SpriteSetup (const entity_render_t *ent, int type, float org[3], fl
        case SPR_VP_PARALLEL:
                // normal sprite
                // faces view plane
-               VectorCopy(vpn, matrix3[0]);
-               VectorNegate(vright, matrix3[1]);
-               VectorCopy(vup, matrix3[2]);
+               VectorCopy(r_viewforward, matrix3[0]);
+               VectorCopy(r_viewleft, matrix3[1]);
+               VectorCopy(r_viewup, matrix3[2]);
                break;
        case SPR_ORIENTED:
                // bullet marks on walls
                // ignores viewer entirely
                AngleVectorsFLU (ent->angles, matrix3[0], matrix3[1], matrix3[2]);
                // nudge it toward the view, so it will be infront of the wall
-               VectorSubtract(org, vpn, org);
+               VectorSubtract(org, r_viewforward, org);
                break;
        case SPR_VP_PARALLEL_ORIENTED:
                // I have no idea what people would use this for
                // oriented relative to view space
                // FIXME: test this and make sure it mimicks software
                AngleVectorsFLU (ent->angles, matrix1[0], matrix1[1], matrix1[2]);
-               VectorCopy(vpn, matrix2[0]);
-               VectorNegate(vright, matrix2[1]);
-               VectorCopy(vup, matrix2[2]);
+               VectorCopy(r_viewforward, matrix2[0]);
+               VectorCopy(r_viewleft, matrix2[1]);
+               VectorCopy(r_viewup, matrix2[2]);
                R_ConcatRotations (matrix1[0], matrix2[0], matrix3[0]);
                break;
        }
@@ -106,7 +106,7 @@ void R_DrawSpriteModelCallback(const void *calldata1, int calldata2)
 
        if (fogenabled)
        {
-               VectorSubtract(ent->origin, r_origin, diff);
+               VectorSubtract(ent->origin, r_vieworigin, diff);
                fog = exp(fogdensity/DotProduct(diff,diff));
                if (fog > 1)
                        fog = 1;
index 0438bab..33d3acd 100644 (file)
--- a/render.h
+++ b/render.h
@@ -90,10 +90,11 @@ extern      int             c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c
 //
 // view origin
 //
-extern vec3_t  vup;
-extern vec3_t  vpn;
-extern vec3_t  vright;
-extern vec3_t  r_origin;
+extern vec3_t  r_vieworigin;
+extern vec3_t  r_viewforward;
+extern vec3_t  r_viewleft;
+extern vec3_t  r_viewright;
+extern vec3_t  r_viewup;
 
 extern mleaf_t         *r_viewleaf, *r_oldviewleaf;
 extern unsigned short  d_lightstylevalue[256]; // 8.8 fraction of base light value
@@ -129,7 +130,7 @@ int R_CullBox(const vec3_t mins, const vec3_t maxs);
 extern qboolean fogenabled;
 extern vec3_t fogcolor;
 extern vec_t fogdensity;
-#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0])*((v)[0] - r_origin[0])+((v)[1] - r_origin[1])*((v)[1] - r_origin[1])+((v)[2] - r_origin[2])*((v)[2] - r_origin[2])))))
+#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_vieworigin[0])*((v)[0] - r_vieworigin[0])+((v)[1] - r_vieworigin[1])*((v)[1] - r_vieworigin[1])+((v)[2] - r_vieworigin[2])*((v)[2] - r_vieworigin[2])))))
 #define calcfogbyte(v) ((qbyte) (bound(0, ((int) ((float) (calcfog((v)) * 255.0f))), 255)))
 
 // start a farclip measuring session
index 1255ef3..32de766 100644 (file)
--- a/snd_dma.c
+++ b/snd_dma.c
@@ -48,10 +48,10 @@ qboolean snd_initialized = false;
 volatile dma_t *shm = 0;
 volatile dma_t sn;
 
-vec3_t listener_origin;
-vec3_t listener_forward;
-vec3_t listener_right;
-vec3_t listener_up;
+vec3_t listener_vieworigin;
+vec3_t listener_viewforward;
+vec3_t listener_viewleft;
+vec3_t listener_viewup;
 vec_t sound_nominal_clip_dist=1000.0;
 mempool_t *snd_mempool;
 
@@ -432,15 +432,15 @@ void SND_Spatialize(channel_t *ch, int isstatic)
                }
 
                // calculate stereo seperation and distance attenuation
-               VectorSubtract(ch->origin, listener_origin, source_vec);
+               VectorSubtract(ch->origin, listener_vieworigin, source_vec);
                dist = VectorNormalizeLength(source_vec);
                // distance
                scale = ch->master_vol * (1.0 - (dist * ch->dist_mult));
                // panning
-               pan = scale * DotProduct(listener_right, source_vec);
+               pan = scale * DotProduct(listener_viewleft, source_vec);
                // calculate the volumes
-               ch->leftvol = (int) (scale - pan);
-               ch->rightvol = (int) (scale + pan);
+               ch->leftvol = (int) (scale + pan);
+               ch->rightvol = (int) (scale - pan);
        }
 
        // LordHavoc: allow adjusting volume of static sounds
@@ -676,7 +676,7 @@ void S_UpdateAmbientSounds (void)
        if (!snd_ambient || ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brush.AmbientSoundLevelsForPoint)
                return;
 
-       cl.worldmodel->brush.AmbientSoundLevelsForPoint(cl.worldmodel, listener_origin, ambientlevels, sizeof(ambientlevels));
+       cl.worldmodel->brush.AmbientSoundLevelsForPoint(cl.worldmodel, listener_vieworigin, ambientlevels, sizeof(ambientlevels));
 
 // calc ambient sound levels
        for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
@@ -717,7 +717,7 @@ S_Update
 Called once each time through the main loop
 ============
 */
-void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
+void S_Update(vec3_t origin, vec3_t forward, vec3_t left, vec3_t up)
 {
        int                     i, j;
        int                     total;
@@ -727,10 +727,10 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
        if (!snd_initialized || (snd_blocked > 0))
                return;
 
-       VectorCopy(origin, listener_origin);
-       VectorCopy(forward, listener_forward);
-       VectorCopy(right, listener_right);
-       VectorCopy(up, listener_up);
+       VectorCopy(origin, listener_vieworigin);
+       VectorCopy(forward, listener_viewforward);
+       VectorCopy(left, listener_viewleft);
+       VectorCopy(up, listener_viewup);
 
 // update general area ambient sound sources
        S_UpdateAmbientSounds ();
@@ -924,7 +924,7 @@ static void S_Play_Common(float fvol, float attenuation)
                else
                        i++;
 
-               S_StartSound(-1, 0, sfx, listener_origin, fvol, attenuation);
+               S_StartSound(-1, 0, sfx, listener_vieworigin, fvol, attenuation);
        }
 }
 
diff --git a/sound.h b/sound.h
index 2d179a7..3ff662e 100644 (file)
--- a/sound.h
+++ b/sound.h
@@ -94,7 +94,7 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
 void S_StopSound (int entnum, int entchannel);
 void S_StopAllSounds(qboolean clear);
 void S_ClearBuffer (void);
-void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void S_Update(vec3_t origin, vec3_t forward, vec3_t left, vec3_t up);
 void S_ExtraUpdate (void);
 
 sfx_t *S_GetCached(const char *name);
@@ -148,10 +148,10 @@ extern qboolean fakedma;
 extern int fakedma_updates;
 extern int paintedtime;
 extern int soundtime;
-extern vec3_t listener_origin;
-extern vec3_t listener_forward;
-extern vec3_t listener_right;
-extern vec3_t listener_up;
+extern vec3_t listener_vieworigin;
+extern vec3_t listener_viewforward;
+extern vec3_t listener_viewleft;
+extern vec3_t listener_viewup;
 extern volatile dma_t *shm;
 extern volatile dma_t sn;
 extern vec_t sound_nominal_clip_dist;
diff --git a/todo b/todo
index 1058877..f360866 100644 (file)
--- a/todo
+++ b/todo
@@ -1,4 +1,5 @@
 - todo: difficulty ratings are: 0 = trivial, 1 = easy, 2 = easy-moderate, 3 = moderate, 4 = moderate-hard, 5 = hard, 6 = hard++, 7 = nightmare, d = done, -n = done but have not notified the people who asked for it, f = failed
+-n darkplaces: add PF_copyentity error checking for copying to world (yummyluv)
 -n darkplaces: add airborn blood images to the particlefont which would look like a cloud of droplets (Vermeulen)
 -n darkplaces: add bullet hole decals to the particlefont (Vermeulen)
 -n darkplaces: add cl_particles_quality cvar (1-10) which would scale count of particles and inversely scale alpha of particles (TheBeast)
 -n darkplaces: server is starting before the "port" cvar is set by commandline and scripts? (yummyluv)
 -n darkplaces: typing ip in join game menu should show 'trying' and 'no response' after a while, or 'no network' if networking is not initialized (yummyluv)
 -n dpmod: make grapple off-hand (joe hill)
-d darkplaces: limit maximum lerp time on animations to .1 seconds (Vermeulen)
--n darkplaces: add PF_copyentity error checking for copying to world (yummyluv)
+0 darkplaces: GAME_FNIGGIUM: "data" directory (not "id1" at all)
+0 darkplaces: GAME_FNIGGIUM: 22050/44100 khz sound default
+0 darkplaces: GAME_FNIGGIUM: console doesn't show unless you manually pull it down
+0 darkplaces: GAME_FNIGGIUM: minimum resolution: 640x480
+0 darkplaces: GAME_FNIGGIUM: startup loading screen (gfx/loadback.tga or whatever)
 0 darkplaces: add DP_GFX_QUAKE3MODELTAGS, DP_GFX_SKINFILES, and any other new extensions to the wiki
 0 darkplaces: add DP_LITSUPPORT extension and document it
 0 darkplaces: add DP_SV_ROTATINGBMODEL extension to explain that MOVETYPE_PUSH/SOLID_BSP support rotation in darkplaces and a demonstration of how to use it without qc modifications (Uffe, Supajoe)
@@ -38,6 +42,7 @@ d darkplaces: limit maximum lerp time on animations to .1 seconds (Vermeulen)
 0 darkplaces: add a .collision_cancollide QC function call to decide if an entity should collide with another, or pass through it (Uffe)
 0 darkplaces: add a clipmask thingy to allow QC to mask off collisions as it wishes (Uffe)
 0 darkplaces: add a config saving command (Speeds)
+0 darkplaces: add a loading screen before loading commences so that people have something to look at when the engine starts... (SeienAbunae)
 0 darkplaces: add a scr_screenshot_jpeg_quality cvar (Electro)
 0 darkplaces: add ability to load gfx/particlefont.tga (Vermeulen, frightfan, Error)
 0 darkplaces: add automatic binding to whatever address the machine's hostname resolves to (in addition to 0.0.0.0); see original quake code for examples (yummyluv)
@@ -296,6 +301,10 @@ d darkplaces: limit maximum lerp time on animations to .1 seconds (Vermeulen)
 ? darkplaces: fix colormapping (Demonix)
 ? darkplaces: fix connecting to proquake servers through routers (Demonix)
 ? dpmod: apparently can't fire in start.bsp? (scar3crow)
+bug darkplaces: Zerstorer: riot shotgun rotates even as a view model: need to ignore that model flag when a view model
+bug darkplaces: collision: 'wall stuttering' collision bugs: getting stuck and nudged out constantly when sliding along certain walls
+bug darkplaces: collision: q3bsp curve problems: comparing nudged impacts causes player to hit edges of triangles in a q3bsp curve closer than the surface
+bug darkplaces: physics: rotating MOVETYPE_PUSH code calls blocked when it's just a touch, it isn't even trying to push (SeienAbunae)
 d darkplaces: (goodvsbad2) increase chase_stevie height to 2048 (yummyluv)
 d darkplaces: .skin loading for models (override skins - not exactly shaders, but adequate, missing replacements are nodraw, this allows q3 player models with optional accessories) (Electro)
 d darkplaces: 12bit color textures in 16bit mode?? (Tomaz)
@@ -351,6 +360,7 @@ d darkplaces: get rid of stencil options and make 32bit color automatically use
 d darkplaces: gl_flashblend 1 should disable dlighting of models (Tomaz)
 d darkplaces: have a look at CFQ and figure out why its b0rked (it assumed nq noclip movement)
 d darkplaces: heartbeat should print an error message if used with no server running (yummyluv)
+d darkplaces: limit maximum lerp time on animations to .1 seconds (Vermeulen)
 d darkplaces: loadgame broken (Linny Amore)
 d darkplaces: make LHNET_Read print out the names of read errors (yummyluv)
 d darkplaces: make client load .ent files
@@ -396,4 +406,7 @@ f darkplaces: look at and integrate Vic's updated zone.[ch] (Vic)
 f darkplaces: make a flag for rtlights that makes them appear in normal mode (not just r_shadow_realtime_world mode) (Vermeulen)
 f darkplaces: shadows are not working with model tag attachments (Electro)
 f dpmod: make tarbabies have a self.resist_explosive = 3; like zombies (SeienAbunae)
+resolvedbug darkplaces: intermission: origin and angles are wrong: probably not getting them from entity correctly (resolved: rewrote view setup and fixed timerefresh and envmap command bugs in the process, and also fixed listener positioning during intermissions)
+resolvedbug darkplaces: intermission: statusbar disappears (resolved: not fixed, people seem to kind of prefer it this way)
+resolvedbug darkplaces: intermission: view model isn't disappearing (resolved: fixed)
 
diff --git a/view.c b/view.c
index e9f663b..edb23b9 100644 (file)
--- a/view.c
+++ b/view.c
@@ -58,6 +58,12 @@ cvar_t       v_centerspeed = {0, "v_centerspeed","500"};
 
 cvar_t cl_stairsmoothspeed = {CVAR_SAVE, "cl_stairsmoothspeed", "160"};
 
+cvar_t chase_back = {CVAR_SAVE, "chase_back", "48"};
+cvar_t chase_up = {CVAR_SAVE, "chase_up", "24"};
+cvar_t chase_active = {CVAR_SAVE, "chase_active", "0"};
+// GAME_GOODVSBAD2
+cvar_t chase_stevie = {0, "chase_stevie", "0"};
+
 float  v_dmg_time, v_dmg_roll, v_dmg_pitch;
 
 
@@ -295,91 +301,126 @@ static void V_BonusFlash_f (void)
 
 extern matrix4x4_t viewmodelmatrix;
 
+#include "cl_collision.h"
+
 /*
 ==================
 V_CalcRefdef
 
 ==================
 */
+extern float timerefreshangle;
 void V_CalcRefdef (void)
 {
        static float oldz;
        entity_t *ent;
+       float vieworg[3], viewangles[3], newz;
+       Matrix4x4_CreateIdentity(&viewmodelmatrix);
+       Matrix4x4_CreateIdentity(&r_refdef.viewentitymatrix);
        if (cls.state == ca_connected && cls.signon == SIGNONS)
        {
-               // ent is the player model (visible when out of body)
+               // ent is the view entity (visible when out of body)
                ent = &cl_entities[cl.viewentity];
-               VectorCopy(ent->render.origin, r_refdef.vieworg);
-               VectorCopy(cl.viewangles, r_refdef.viewangles);
-               if (oldz < ent->render.origin[2])
-               {
-                       if (cl.time > cl.oldtime)
-                               oldz += (cl.time - cl.oldtime) * cl_stairsmoothspeed.value;
-                       oldz -= ent->render.origin[2];
-                       oldz = bound(-16, oldz, 0);
-                       r_refdef.vieworg[2] += oldz;
-                       oldz += ent->render.origin[2];
-               }
-               else
-                       oldz = ent->render.origin[2];
                if (cl.intermission)
                {
-                       // entity is a fixed camera
-                       VectorCopy(ent->render.angles, r_refdef.viewangles);
-               }
-               else if (chase_active.value)
-               {
-                       // observing entity from third person
-                       Chase_Update();
+                       // entity is a fixed camera, just copy the matrix
+                       Matrix4x4_Copy(&r_refdef.viewentitymatrix, &ent->render.matrix);
+                       Matrix4x4_Copy(&viewmodelmatrix, &ent->render.matrix);
                }
                else
                {
-                       // first person view from entity
-                       // angles
-                       if (cl.stats[STAT_HEALTH] <= 0)
-                               r_refdef.viewangles[ROLL] = 80; // dead view angle
-                       VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles);
-                       r_refdef.viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.velocity);
-                       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;
-                               v_dmg_time -= cl.frametime;
-                       }
-                       if (v_idlescale.value)
+                       // player can look around, so take the origin from the entity,
+                       // and the angles from the input system
+                       Matrix4x4_OriginFromMatrix(&ent->render.matrix, vieworg);
+                       VectorCopy(cl.viewangles, viewangles);
+
+                       // stair smoothing
+                       newz = vieworg[2];
+                       oldz -= newz;
+                       oldz += (cl.time - cl.oldtime) * cl_stairsmoothspeed.value;
+                       oldz = bound(-16, oldz, 0);
+                       vieworg[2] += oldz;
+                       oldz += newz;
+
+                       if (chase_active.value)
                        {
-                               r_refdef.viewangles[ROLL] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
-                               r_refdef.viewangles[PITCH] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
-                               r_refdef.viewangles[YAW] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
+                               // observing entity from third person
+                               vec_t camback, camup, dist, forward[3], stop[3], chase_dest[3], normal[3];
+
+                               camback = bound(0, chase_back.value, 128);
+                               if (chase_back.value != camback)
+                                       Cvar_SetValueQuick(&chase_back, camback);
+                               camup = bound(-48, chase_up.value, 96);
+                               if (chase_up.value != camup)
+                                       Cvar_SetValueQuick(&chase_up, camup);
+
+                               // this + 22 is to match view_ofs for compatibility with older versions
+                               camup += 22;
+
+                               if (gamemode == GAME_GOODVSBAD2 && chase_stevie.integer)
+                               {
+                                       // look straight down from high above
+                                       viewangles[0] = 90;
+                                       camback = 2048;
+                               }
+                               AngleVectors(viewangles, forward, NULL, NULL);
+
+                               // trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
+                               dist = -camback - 8;
+                               chase_dest[0] = vieworg[0] + forward[0] * dist;
+                               chase_dest[1] = vieworg[1] + forward[1] * dist;
+                               chase_dest[2] = vieworg[2] + forward[2] * dist + camup;
+                               CL_TraceLine(vieworg, chase_dest, stop, normal, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY);
+                               vieworg[0] = stop[0] + forward[0] * 8 + normal[0] * 4;
+                               vieworg[1] = stop[1] + forward[1] * 8 + normal[1] * 4;
+                               vieworg[2] = stop[2] + forward[2] * 8 + normal[2] * 4;
                        }
-                       // origin
-                       VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg);
-                       r_refdef.vieworg[2] += cl.viewheight;
-                       if (cl.stats[STAT_HEALTH] > 0 && cl_bob.value && cl_bobcycle.value)
+                       else
                        {
-                               double bob, cycle;
-                               // LordHavoc: this code is *weird*, but not replacable (I think it
-                               // should be done in QC on the server, but oh well, quake is quake)
-                               // LordHavoc: figured out bobup: the time at which the sin is at 180
-                               // degrees (which allows lengthening or squishing the peak or valley)
-                               cycle = cl.time / cl_bobcycle.value;
-                               cycle -= (int) cycle;
-                               if (cycle < cl_bobup.value)
-                                       cycle = sin(M_PI * cycle / cl_bobup.value);
-                               else
-                                       cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
-                               // bob is proportional to velocity in the xy plane
-                               // (don't count Z, or jumping messes it up)
-                               bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value;
-                               bob = bob*0.3 + bob*0.7*cycle;
-                               r_refdef.vieworg[2] += bound(-7, bob, 4);
+                               // first person view from entity
+                               // angles
+                               if (cl.stats[STAT_HEALTH] <= 0)
+                                       viewangles[ROLL] = 80;  // dead view angle
+                               VectorAdd(viewangles, cl.punchangle, viewangles);
+                               viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.velocity);
+                               if (v_dmg_time > 0)
+                               {
+                                       viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
+                                       viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
+                                       v_dmg_time -= cl.frametime;
+                               }
+                               // origin
+                               VectorAdd(vieworg, cl.punchvector, vieworg);
+                               vieworg[2] += cl.viewheight;
+                               if (cl.stats[STAT_HEALTH] > 0 && cl_bob.value && cl_bobcycle.value)
+                               {
+                                       double bob, cycle;
+                                       // LordHavoc: this code is *weird*, but not replacable (I think it
+                                       // should be done in QC on the server, but oh well, quake is quake)
+                                       // LordHavoc: figured out bobup: the time at which the sin is at 180
+                                       // degrees (which allows lengthening or squishing the peak or valley)
+                                       cycle = cl.time / cl_bobcycle.value;
+                                       cycle -= (int) cycle;
+                                       if (cycle < cl_bobup.value)
+                                               cycle = sin(M_PI * cycle / cl_bobup.value);
+                                       else
+                                               cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
+                                       // bob is proportional to velocity in the xy plane
+                                       // (don't count Z, or jumping messes it up)
+                                       bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value;
+                                       bob = bob*0.3 + bob*0.7*cycle;
+                                       vieworg[2] += bound(-7, bob, 4);
+                               }
                        }
+                       // calculate a view matrix for rendering the scene
+                       if (v_idlescale.value)
+                               Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0] + v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value, viewangles[1] + v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value, viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1);
+                       else
+                               Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1);
+                       // calculate a viewmodel matrix for use in view-attached entities
+                       Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2], 0.3);
                }
-               // calculate a viewmodel matrix for use in view-attached entities
-               Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2], r_refdef.viewangles[0] + v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value, r_refdef.viewangles[1] - v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value, r_refdef.viewangles[2] - v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 0.3);
        }
-       else
-               Matrix4x4_CreateIdentity(&viewmodelmatrix);
 }
 
 void V_FadeViewFlashs(void)
@@ -405,7 +446,7 @@ void V_CalcViewBlend(void)
        if (cls.state == ca_connected && cls.signon == SIGNONS)
        {
                // set contents color
-               switch (CL_PointQ1Contents(r_refdef.vieworg))
+               switch (CL_PointQ1Contents(r_vieworigin))
                {
                case CONTENTS_EMPTY:
                case CONTENTS_SOLID:
@@ -525,5 +566,11 @@ void V_Init (void)
        Cvar_RegisterVariable (&v_kickpitch);
 
        Cvar_RegisterVariable (&cl_stairsmoothspeed);
+
+       Cvar_RegisterVariable (&chase_back);
+       Cvar_RegisterVariable (&chase_up);
+       Cvar_RegisterVariable (&chase_active);
+       if (gamemode == GAME_GOODVSBAD2)
+               Cvar_RegisterVariable (&chase_stevie);
 }