]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
replace funky !!a ^ !!b XOR usage by a new boolxor(a, b) macro that does that interna...
[xonotic/darkplaces.git] / gl_rmain.c
index 72831d8775a9dfb1e43c10a4fdd11e9cbbd86767..c233bc005d2161d61bedc423e2873badfb6b1f67 100644 (file)
@@ -104,6 +104,8 @@ cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture
 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
 
+extern qboolean v_flipped_state;
+
 typedef struct r_glsl_bloomshader_s
 {
        int program;
@@ -2457,13 +2459,13 @@ void R_UpdateVariables(void)
                Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
        r_refdef.polygonfactor = 0;
        r_refdef.polygonoffset = 0;
-       r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
-       r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
+       r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
+       r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
 
        r_refdef.rtworld = r_shadow_realtime_world.integer;
        r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
        r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
-       r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
+       r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
        r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
        if (r_showsurfaces.integer)
        {
@@ -2952,6 +2954,16 @@ void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_
 
        R_Mesh_Matrix(&identitymatrix);
        GL_BlendFunc(blendfunc1, blendfunc2);
+
+       if(v_flipped_state)
+       {
+               scalex1 = -scalex1;
+               scalex2 = -scalex2;
+               GL_CullFace(GL_BACK);
+       }
+       else
+               GL_CullFace(GL_FRONT);
+
        GL_DepthMask(false);
        GL_DepthRange(0, depthshort ? 0.0625 : 1);
        GL_DepthTest(!depthdisable);
@@ -3514,6 +3526,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
        rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
 }
 
+static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
 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
@@ -3545,11 +3558,13 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
        if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
        {
                int texturesurfaceindex;
-               float center[3], forward[3], right[3], up[3], v[4][3];
-               matrix4x4_t matrix1, imatrix1;
-               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);
+               float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
+               Matrix4x4_Transform3x3(&rsurface_entity->inversematrix, r_view.forward, newforward);
+               Matrix4x4_Transform3x3(&rsurface_entity->inversematrix, r_view.right, newright);
+               Matrix4x4_Transform3x3(&rsurface_entity->inversematrix, r_view.up, newup);
+               VectorNormalize(newforward);
+               VectorNormalize(newright);
+               VectorNormalize(newup);
                // make deformed versions of only the model vertices used by the specified surfaces
                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                {
@@ -3564,22 +3579,80 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta
                                VectorScale(center, 0.25f, center);
                                if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
                                {
-                                       forward[0] = rsurface_modelorg[0] - center[0];
-                                       forward[1] = rsurface_modelorg[1] - center[1];
-                                       forward[2] = 0;
-                                       VectorNormalize(forward);
-                                       right[0] = forward[1];
-                                       right[1] = -forward[0];
-                                       right[2] = 0;
-                                       VectorSet(up, 0, 0, 1);
+                                       const float *v1, *v2;
+                                       float f, l;
+                                       struct
+                                       {
+                                               float length2;
+                                               int quadedge;
+                                       }
+                                       shortest[2];
+                                       shortest[0].quadedge = shortest[1].quadedge = 0;
+                                       shortest[0].length2 = shortest[1].length2 = 0;
+                                       // find the two shortest edges, then use them to define the
+                                       // axis vectors for rotating around the central axis
+                                       for (i = 0;i < 6;i++)
+                                       {
+                                               v1 = rsurface_modelvertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
+                                               v2 = rsurface_modelvertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
+                                               l = VectorDistance2(v1, v2);
+                                               if (shortest[0].length2 > l || i == 0)
+                                               {
+                                                       shortest[1] = shortest[0];
+                                                       shortest[0].length2 = l;
+                                                       shortest[0].quadedge = i;
+                                               }
+                                               else if (shortest[1].length2 > l || i == 1)
+                                               {
+                                                       shortest[1].length2 = l;
+                                                       shortest[1].quadedge = i;
+                                               }
+                                       }
+                                       // this calculates the midpoints *2 (not bothering to average) of the two shortest edges, and subtracts one from the other to get the up vector
+                                       for (i = 0;i < 3;i++)
+                                       {
+                                               right[i] = rsurface_modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i]
+                                                        + rsurface_modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i];
+                                               up[i] = rsurface_modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i]
+                                                     + rsurface_modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i]
+                                                     - rsurface_modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][0]) + i]
+                                                     - rsurface_modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][1]) + i];
+                                       }
+                                       // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
+                                       VectorSubtract(rsurface_modelorg, center, forward);
+                                       CrossProduct(up, forward, newright);
+                                       // normalize the vectors involved
+                                       VectorNormalize(right);
+                                       VectorNormalize(newright);
+                                       // rotate the quad around the up axis vector, this is made
+                                       // especially easy by the fact we know the quad is flat,
+                                       // so we only have to subtract the center position and
+                                       // measure distance along the right vector, and then
+                                       // multiply that by the newright vector and add back the
+                                       // center position
+                                       // we also need to subtract the old position to undo the
+                                       // displacement from the center, which we do with a
+                                       // DotProduct, the subtraction/addition of center is also
+                                       // optimized into DotProducts here
+                                       l = DotProduct(newright, center) - DotProduct(right, center);
+                                       for (i = 0;i < 4;i++)
+                                       {
+                                               v1 = rsurface_modelvertex3f + 3 * (surface->num_firstvertex + j + i);
+                                               f = DotProduct(right, v1) - DotProduct(newright, v1) + l;
+                                               VectorMA(v1, f, newright, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
+                                       }
+                               }
+                               else
+                               {
+                                       VectorCopy((rsurface_modelnormal3f  + 3 * surface->num_firstvertex) + j*3, forward);
+                                       VectorCopy((rsurface_modelsvector3f + 3 * surface->num_firstvertex) + j*3, right);
+                                       VectorCopy((rsurface_modeltvector3f + 3 * surface->num_firstvertex) + j*3, up);
+                                       for (i = 0;i < 4;i++)
+                                       {
+                                               VectorSubtract((rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
+                                               VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
+                                       }
                                }
-                               // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
-                               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_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);
                        }
                        Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformednormal3f, r_smoothnormals_areaweighting.integer);
                        Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_deformednormal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformedsvector3f, rsurface_array_deformedtvector3f, r_smoothnormals_areaweighting.integer);