+#endif
+
+#if 0
+ // now add the light-space box planes if the light box is rotated, as any
+ // caster outside the oriented light box is irrelevant (even if it passed
+ // the worldspace light box, which is axial)
+ if (rtlight->matrix_lighttoworld.m[0][0] != 1 || rtlight->matrix_lighttoworld.m[1][1] != 1 || rtlight->matrix_lighttoworld.m[2][2] != 1)
+ {
+ for (i = 0;i < 6;i++)
+ {
+ vec3_t v;
+ VectorClear(v);
+ v[i >> 1] = (i & 1) ? -1 : 1;
+ Matrix4x4_Transform(&rtlight->matrix_lighttoworld, v, plane.normal);
+ VectorSubtract(plane.normal, rtlight->shadoworigin, plane.normal);
+ plane.dist = VectorNormalizeLength(plane.normal);
+ plane.dist += DotProduct(plane.normal, rtlight->shadoworigin);
+ rsurface.rtlight_frustumplanes[rsurface.rtlight_numfrustumplanes++] = plane;
+ }
+ }
+#endif
+
+#if 0
+ // add the world-space reduced box planes
+ for (i = 0;i < 6;i++)
+ {
+ VectorClear(plane.normal);
+ plane.normal[i >> 1] = (i & 1) ? -1 : 1;
+ plane.dist = (i & 1) ? -rsurface.rtlight_cullmaxs[i >> 1] : rsurface.rtlight_cullmins[i >> 1];
+ rsurface.rtlight_frustumplanes[rsurface.rtlight_numfrustumplanes++] = plane;
+ }
+#endif
+
+#if 0
+ {
+ int j, oldnum;
+ vec3_t points[8];
+ vec_t bestdist;
+ // reduce all plane distances to tightly fit the rtlight cull box, which
+ // is in worldspace
+ VectorSet(points[0], rsurface.rtlight_cullmins[0], rsurface.rtlight_cullmins[1], rsurface.rtlight_cullmins[2]);
+ VectorSet(points[1], rsurface.rtlight_cullmaxs[0], rsurface.rtlight_cullmins[1], rsurface.rtlight_cullmins[2]);
+ VectorSet(points[2], rsurface.rtlight_cullmins[0], rsurface.rtlight_cullmaxs[1], rsurface.rtlight_cullmins[2]);
+ VectorSet(points[3], rsurface.rtlight_cullmaxs[0], rsurface.rtlight_cullmaxs[1], rsurface.rtlight_cullmins[2]);
+ VectorSet(points[4], rsurface.rtlight_cullmins[0], rsurface.rtlight_cullmins[1], rsurface.rtlight_cullmaxs[2]);
+ VectorSet(points[5], rsurface.rtlight_cullmaxs[0], rsurface.rtlight_cullmins[1], rsurface.rtlight_cullmaxs[2]);
+ VectorSet(points[6], rsurface.rtlight_cullmins[0], rsurface.rtlight_cullmaxs[1], rsurface.rtlight_cullmaxs[2]);
+ VectorSet(points[7], rsurface.rtlight_cullmaxs[0], rsurface.rtlight_cullmaxs[1], rsurface.rtlight_cullmaxs[2]);
+ oldnum = rsurface.rtlight_numfrustumplanes;
+ rsurface.rtlight_numfrustumplanes = 0;
+ for (j = 0;j < oldnum;j++)
+ {
+ // find the nearest point on the box to this plane
+ bestdist = DotProduct(rsurface.rtlight_frustumplanes[j].normal, points[0]);
+ for (i = 1;i < 8;i++)
+ {
+ dist = DotProduct(rsurface.rtlight_frustumplanes[j].normal, points[i]);
+ if (bestdist > dist)
+ bestdist = dist;
+ }
+ Con_Printf("light %p %splane #%i %f %f %f : %f < %f\n", rtlight, rsurface.rtlight_frustumplanes[j].dist < bestdist + 0.03125 ? "^2" : "^1", j, rsurface.rtlight_frustumplanes[j].normal[0], rsurface.rtlight_frustumplanes[j].normal[1], rsurface.rtlight_frustumplanes[j].normal[2], rsurface.rtlight_frustumplanes[j].dist, bestdist);
+ // if the nearest point is near or behind the plane, we want this
+ // plane, otherwise the plane is useless as it won't cull anything
+ if (rsurface.rtlight_frustumplanes[j].dist < bestdist + 0.03125)
+ {
+ PlaneClassify(&rsurface.rtlight_frustumplanes[j]);
+ rsurface.rtlight_frustumplanes[rsurface.rtlight_numfrustumplanes++] = rsurface.rtlight_frustumplanes[j];
+ }
+ }
+ }
+#endif
+}
+
+void R_Shadow_DrawWorldShadow(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
+{
+ RSurf_ActiveWorldEntity();
+ if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
+ {
+ shadowmesh_t *mesh;
+ CHECKGLERROR
+ for (mesh = rsurface.rtlight->static_meshchain_shadow;mesh;mesh = mesh->next)
+ {
+ r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
+ R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f);
+ GL_LockArrays(0, mesh->numverts);
+ if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCIL)
+ {
+ // decrement stencil if backface is behind depthbuffer
+ GL_CullFace(GL_BACK); // quake is backwards, this culls front faces
+ qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
+ R_Mesh_Draw(0, mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->ebo, 0);
+ // increment stencil if frontface is behind depthbuffer
+ GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
+ qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR
+ }
+ R_Mesh_Draw(0, mesh->numverts, mesh->numtriangles, mesh->element3i, mesh->ebo, 0);
+ GL_LockArrays(0, 0);
+ }
+ CHECKGLERROR
+ }
+ else if (numsurfaces && r_refdef.worldmodel->brush.shadowmesh && r_shadow_culltriangles.integer)
+ {
+ int t, tend;
+ int surfacelistindex;
+ msurface_t *surface;
+ R_Shadow_PrepareShadowMark(r_refdef.worldmodel->brush.shadowmesh->numtriangles);
+ for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+ {
+ surface = r_refdef.worldmodel->data_surfaces + surfacelist[surfacelistindex];
+ for (t = surface->num_firstshadowmeshtriangle, tend = t + surface->num_triangles;t < tend;t++)
+ if (CHECKPVSBIT(trispvs, t))
+ shadowmarklist[numshadowmark++] = t;
+ }
+ R_Shadow_VolumeFromList(r_refdef.worldmodel->brush.shadowmesh->numverts, r_refdef.worldmodel->brush.shadowmesh->numtriangles, r_refdef.worldmodel->brush.shadowmesh->vertex3f, r_refdef.worldmodel->brush.shadowmesh->element3i, r_refdef.worldmodel->brush.shadowmesh->neighbor3i, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius + r_refdef.worldmodel->radius*2 + r_shadow_projectdistance.value, numshadowmark, shadowmarklist);
+ }
+ else if (numsurfaces)
+ r_refdef.worldmodel->DrawShadowVolume(r_refdef.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight_cullmins, rsurface.rtlight_cullmaxs);
+}
+
+void R_Shadow_DrawEntityShadow(entity_render_t *ent)
+{
+ vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
+ vec_t relativeshadowradius;
+ RSurf_ActiveModelEntity(ent, false, false);
+ Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
+ relativeshadowradius = rsurface.rtlight->radius / ent->scale;
+ relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
+ relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
+ relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius;
+ relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
+ relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
+ relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
+ ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->surfacelist, relativeshadowmins, relativeshadowmaxs);