]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
removed NET_MAXRATE (as it served no useful purpose), changed description of rate...
[xonotic/darkplaces.git] / gl_rmain.c
index 7f3c26b0412a5df0e64fa2193b5547938e522d21..ac4fbd087a9a366ccd7a16b7d75eb4b545e21e71 100644 (file)
@@ -804,7 +804,7 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
                                        permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
                        }
                }
-               if (rsurface_texture->skin.glow)
+               if (rsurface_texture->currentskinframe->glow)
                        permutation |= SHADERPERMUTATION_GLOW;
        }
        if (specularscale > 0)
@@ -872,16 +872,16 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
                if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
                if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
        }
-       if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
+       if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
        if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
        if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
        //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
        if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
-       if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
-       if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
+       if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
+       if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
        //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
        //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
-       if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
+       if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
        if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
        if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
        if (r_glsl_permutation->loc_FogColor >= 0)
@@ -895,14 +895,14 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
        if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
        if (r_glsl_permutation->loc_Color_Pants >= 0)
        {
-               if (rsurface_texture->skin.pants)
+               if (rsurface_texture->currentskinframe->pants)
                        qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
                else
                        qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
        }
        if (r_glsl_permutation->loc_Color_Shirt >= 0)
        {
-               if (rsurface_texture->skin.shirt)
+               if (rsurface_texture->currentskinframe->shirt)
                        qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
                else
                        qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
@@ -966,7 +966,7 @@ void gl_main_newmap(void)
                l = (int)strlen(entname) - 4;
                if (l >= 0 && !strcmp(entname + l, ".bsp"))
                {
-                       strcpy(entname + l, ".ent");
+                       memcpy(entname + l, ".ent", 5);
                        if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
                        {
                                CL_ParseEntityLump(entities);
@@ -1050,8 +1050,8 @@ void Render_Init(void)
 {
        gl_backend_init();
        R_Textures_Init();
-       GL_Main_Init();
        GL_Draw_Init();
+       GL_Main_Init();
        R_Shadow_Init();
        R_Sky_Init();
        GL_Surf_Init();
@@ -1138,7 +1138,11 @@ static void R_UpdateEntityLighting(entity_render_t *ent)
        VectorClear(ent->modellight_diffuse);
        VectorClear(ent->modellight_lightdir);
        if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
-               r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
+       {
+               vec3_t org;
+               Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+               r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
+       }
        else // highly rare
                VectorSet(ent->modellight_ambient, 1, 1, 1);
        Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
@@ -1167,6 +1171,8 @@ static void R_View_UpdateEntityVisible (void)
                {
                        ent = r_refdef.entities[i];
                        r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
+                       if (r_viewcache.entityvisible[i])
+                               R_UpdateEntityLighting(ent);
                }
        }
        else
@@ -1175,7 +1181,9 @@ static void R_View_UpdateEntityVisible (void)
                for (i = 0;i < r_refdef.numentities;i++)
                {
                        ent = r_refdef.entities[i];
-                       r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
+                       r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
+                       if (r_viewcache.entityvisible[i])
+                               R_UpdateEntityLighting(ent);
                }
        }
 }
@@ -1709,8 +1717,6 @@ matrix4x4_t r_waterscrollmatrix;
 
 void R_UpdateVariables(void)
 {
-       int i;
-
        R_Textures_Frame();
 
        r_refdef.farclip = 4096;
@@ -1775,17 +1781,6 @@ void R_UpdateVariables(void)
        }
        else
                r_refdef.fogenabled = false;
-
-       // update some cached entity properties...
-       for (i = 0;i < r_refdef.numentities;i++)
-       {
-               entity_render_t *ent = r_refdef.entities[i];
-               // some of the renderer still relies on origin...
-               Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
-               // some of the renderer still relies on scale...
-               ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
-               R_UpdateEntityLighting(ent);
-       }
 }
 
 /*
@@ -1794,43 +1789,6 @@ R_RenderView
 ================
 */
 void R_RenderView(void)
-{
-       if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
-               return; //Host_Error ("R_RenderView: NULL worldmodel");
-
-       CHECKGLERROR
-       if (r_timereport_active)
-               R_TimeReport("setup");
-
-       R_View_Update();
-       if (r_timereport_active)
-               R_TimeReport("visibility");
-
-       // GL is weird because it's bottom to top, r_view.y is top to bottom
-       R_ResetViewRendering();
-
-       R_ClearScreen();
-       if (r_timereport_active)
-               R_TimeReport("clear");
-
-       // this produces a bloom texture to be used in R_BlendView() later
-       if (r_hdr.integer)
-               R_HDR_RenderBloomTexture();
-
-       r_view.colorscale = r_hdr_scenebrightness.value;
-       R_RenderScene();
-
-       R_BlendView();
-       if (r_timereport_active)
-               R_TimeReport("blendview");
-
-       GL_Scissor(0, 0, vid.width, vid.height);
-       GL_ScissorTest(false);
-       CHECKGLERROR
-}
-
-//[515]: csqc
-void CSQC_R_ClearScreen (void)
 {
        if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
                return; //Host_Error ("R_RenderView: NULL worldmodel");
@@ -1847,17 +1805,6 @@ void CSQC_R_ClearScreen (void)
 
        R_ResetViewRendering();
 
-       R_ClearScreen();
-       if (r_timereport_active)
-               R_TimeReport("clear");
-       CHECKGLERROR
-}
-
-//[515]: csqc
-void CSQC_R_RenderScene (void)
-{
-       R_ResetViewRendering();
-
        R_ClearScreen();
        if (r_timereport_active)
                R_TimeReport("clear");
@@ -1883,6 +1830,8 @@ extern void VM_AddPolygonsToMeshQueue (void);
 extern void R_DrawPortals (void);
 void R_RenderScene(void)
 {
+       DrawQ_Finish();
+
        // don't let sound skip if going slow
        if (r_refdef.extraupdate)
                S_ExtraUpdate ();
@@ -2115,9 +2064,11 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight
        R_Mesh_VertexPointer(nomodelvertex3f);
        if (r_refdef.fogenabled)
        {
+               vec3_t org;
                memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
                R_Mesh_ColorPointer(color4f);
-               f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
+               Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+               f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
                f1 = 1 - f2;
                for (i = 0, c = color4f;i < 6;i++, c += 4)
                {
@@ -2142,8 +2093,10 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight
 
 void R_DrawNoModel(entity_render_t *ent)
 {
+       vec3_t org;
+       Matrix4x4_OriginFromMatrix(&ent->matrix, org);
        //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
-               R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
+               R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
        //else
        //      R_DrawNoModelCallback(ent, 0);
 }
@@ -2225,10 +2178,12 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_
        }
 }
 
-int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
+int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
 {
        int i;
        float *vertex3f;
+       float v[3];
+       VectorSet(v, x, y, z);
        for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
                if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
                        break;
@@ -2249,12 +2204,33 @@ void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
 {
        int i;
        int *e, element[3];
-       element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
-       element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
+       element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
+       element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
        e = mesh->element3i + mesh->numtriangles * 3;
        for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
        {
-               element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
+               element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
+               if (mesh->numtriangles < mesh->maxtriangles)
+               {
+                       *e++ = element[0];
+                       *e++ = element[1];
+                       *e++ = element[2];
+                       mesh->numtriangles++;
+               }
+               element[1] = element[2];
+       }
+}
+
+void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
+{
+       int i;
+       int *e, element[3];
+       element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
+       element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
+       e = mesh->element3i + mesh->numtriangles * 3;
+       for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
+       {
+               element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
                if (mesh->numtriangles < mesh->maxtriangles)
                {
                        *e++ = element[0];
@@ -2266,29 +2242,37 @@ void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
        }
 }
 
+#define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
 {
        int planenum, planenum2;
        int w;
        int tempnumpoints;
        mplane_t *plane, *plane2;
-       float temppoints[2][256*3];
+       double maxdist;
+       double temppoints[2][256*3];
+       // figure out how large a bounding box we need to properly compute this brush
+       maxdist = 0;
+       for (w = 0;w < numplanes;w++)
+               maxdist = max(maxdist, planes[w].dist);
+       // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
+       maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
        for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
        {
                w = 0;
                tempnumpoints = 4;
-               PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
+               PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
                for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
                {
                        if (planenum2 == planenum)
                                continue;
-                       PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
+                       PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
                        w = !w;
                }
                if (tempnumpoints < 3)
                        continue;
                // generate elements forming a triangle fan for this polygon
-               R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
+               R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
        }
 }
 
@@ -2337,6 +2321,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
        // FIXME: identify models using a better check than ent->model->brush.shadowmesh
        //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
 
+       // switch to an alternate material if this is a q1bsp animated material
        {
                texture_t *texture = t;
                model_t *model = ent->model;
@@ -2364,6 +2349,10 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                texture->currentframe = t;
        }
 
+       // pick a new currentskinframe if the material is animated
+       if (t->numskinframes >= 2)
+               t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
+
        t->currentmaterialflags = t->basematerialflags;
        t->currentalpha = ent->alpha;
        if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
@@ -2382,17 +2371,17 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                t->currenttexmatrix = identitymatrix;
 
        t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
-       t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
+       t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
        t->glosstexture = r_texture_white;
        t->specularpower = 8;
        t->specularscale = 0;
        if (r_shadow_gloss.integer > 0)
        {
-               if (t->skin.gloss)
+               if (t->currentskinframe->gloss)
                {
                        if (r_shadow_glossintensity.value > 0)
                        {
-                               t->glosstexture = t->skin.gloss;
+                               t->glosstexture = t->currentskinframe->gloss;
                                t->specularscale = r_shadow_glossintensity.value;
                        }
                }
@@ -2435,15 +2424,15 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                                int layerflags = 0;
                                if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
                                        layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
-                               currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
+                               currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
                                if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
                                {
                                        // fullbright is not affected by r_refdef.lightmapintensity
                                        R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
-                                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
-                                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
+                                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
+                                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
                                }
                                else
                                {
@@ -2458,21 +2447,21 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                                        R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
                                        if (r_ambient.value >= (1.0f/64.0f))
                                                R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
-                                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
+                                       if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
                                        {
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2]  * ent->colormod[2] * colorscale, t->currentalpha);
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2]  * ent->colormod[2] * colorscale, t->currentalpha);
                                                if (r_ambient.value >= (1.0f/64.0f))
-                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
+                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
                                        }
-                                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
+                                       if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
                                        {
-                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
+                                               R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
                                                if (r_ambient.value >= (1.0f/64.0f))
-                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
+                                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
                                        }
                                }
-                               if (t->skin.glow != NULL)
-                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
+                               if (t->currentskinframe->glow != NULL)
+                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
                                if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
                                {
                                        // if this is opaque use alpha blend which will darken the earlier
@@ -2486,7 +2475,7 @@ void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
                                        // were darkened by fog already, and we should not add fog color
                                        // (because the background was not darkened, there is no fog color
                                        // that was lost behind it).
-                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
+                                       R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
                                }
                        }
                }
@@ -2553,8 +2542,24 @@ rsurfmode_t rsurface_mode;
 texture_t *rsurface_glsl_texture;
 qboolean rsurface_glsl_uselightmap;
 
+void RSurf_CleanUp(void)
+{
+       CHECKGLERROR
+       if (rsurface_mode == RSURFMODE_GLSL)
+       {
+               qglUseProgramObjectARB(0);CHECKGLERROR
+       }
+       GL_AlphaTest(false);
+       rsurface_mode = RSURFMODE_NONE;
+       rsurface_lightmaptexture = NULL;
+       rsurface_texture = NULL;
+       rsurface_glsl_texture = NULL;
+       rsurface_glsl_uselightmap = false;
+}
+
 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
 {
+       RSurf_CleanUp();
        Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
        rsurface_entity = ent;
        rsurface_model = ent->model;
@@ -2602,30 +2607,11 @@ void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboole
        rsurface_svector3f = rsurface_modelsvector3f;
        rsurface_tvector3f = rsurface_modeltvector3f;
        rsurface_normal3f  = rsurface_modelnormal3f;
-       rsurface_mode = RSURFMODE_NONE;
-       rsurface_lightmaptexture = NULL;
-       rsurface_texture = NULL;
-       rsurface_glsl_texture = NULL;
-       rsurface_glsl_uselightmap = false;
-}
-
-void RSurf_CleanUp(void)
-{
-       CHECKGLERROR
-       if (rsurface_mode == RSURFMODE_GLSL)
-       {
-               qglUseProgramObjectARB(0);CHECKGLERROR
-       }
-       GL_AlphaTest(false);
-       rsurface_mode = RSURFMODE_NONE;
-       rsurface_lightmaptexture = NULL;
-       rsurface_texture = NULL;
-       rsurface_glsl_texture = NULL;
-       rsurface_glsl_uselightmap = false;
 }
 
 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
 {
+       // if vertices are dynamic (animated models), generate them into the temporary rsurface_array_model* arrays and point rsurface_model* at them instead of the static data from the model itself
        if (rsurface_generatedvertex)
        {
                if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
@@ -2644,6 +2630,7 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
                        Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_modelnormal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f, r_smoothnormals_areaweighting.integer);
                }
        }
+       // if vertices are deformed (sprite flares and things in maps, possibly water waves, bulges and other deformations), generate them into rsurface_deform* arrays from whatever the rsurface_model* array pointers point to (may be static model data or generated data for an animated model)
        if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
        {
                int texturesurfaceindex;
@@ -2652,7 +2639,7 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
                Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
                Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
                Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
-               // make deformed versions of only the vertices used by the specified surfaces
+               // make deformed versions of only the model vertices used by the specified surfaces
                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                {
                        int i, j;
@@ -2662,7 +2649,7 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
                        {
                                VectorClear(center);
                                for (i = 0;i < 4;i++)
-                                       VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
+                                       VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
                                VectorScale(center, 0.25f, center);
                                if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
                                {
@@ -2676,10 +2663,10 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
                                        VectorSet(up, 0, 0, 1);
                                }
                                // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
-                               Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
+                               Matrix4x4_FromVectors(&matrix1, (rsurface_modelnormal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modelsvector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modeltvector3f + 3 * surface->num_firstvertex) + j*3, center);
                                Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
                                for (i = 0;i < 4;i++)
-                                       Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
+                                       Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
                                for (i = 0;i < 4;i++)
                                        VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
                        }
@@ -2691,6 +2678,13 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
                rsurface_tvector3f = rsurface_array_deformedtvector3f;
                rsurface_normal3f = rsurface_array_deformednormal3f;
        }
+       else
+       {
+               rsurface_vertex3f = rsurface_modelvertex3f;
+               rsurface_svector3f = rsurface_modelsvector3f;
+               rsurface_tvector3f = rsurface_modeltvector3f;
+               rsurface_normal3f = rsurface_modelnormal3f;
+       }
        R_Mesh_VertexPointer(rsurface_vertex3f);
 }
 
@@ -3318,10 +3312,7 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur
        r_refdef.stats.entities_surfaces += texturenumsurfaces;
        CHECKGLERROR
        GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
-       if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
-       {
-               qglDisable(GL_CULL_FACE);CHECKGLERROR
-       }
+       GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
        if (r_showsurfaces.integer)
                R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
        else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
@@ -3337,10 +3328,6 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur
        }
        CHECKGLERROR
        GL_LockArrays(0, 0);
-       if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
-       {
-               qglEnable(GL_CULL_FACE);CHECKGLERROR
-       }
 }
 
 #define BATCHSIZE 256
@@ -3366,20 +3353,20 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
                if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
                {
                        if (batchcount > 0)
-                               R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
+                               if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
+                                       R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
                        batchcount = 0;
                        t = surface->texture;
                        rsurface_lightmaptexture = surface->lightmaptexture;
                        R_UpdateTextureInfo(ent, t);
                        rsurface_texture = t->currentframe;
                }
-               if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
-                       continue; // transparent sky is too difficult
 
                texturesurfacelist[batchcount++] = surface;
        }
        if (batchcount > 0)
-               R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
+               if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
+                       R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
        RSurf_CleanUp();
 }
 
@@ -3635,4 +3622,3 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
                }
        }
 }
-