X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=r_shadow.c;h=4234f968c93faffce6e5d5b9779c785b30059a26;hb=d3b158411b1d81181e05f750d9a7b0b2268438e2;hp=dcb2b3a35d19e2891eb3d18da5557459e5e999e7;hpb=dda9525d00cbd81ad257870fbcb60079e11e367f;p=xonotic%2Fdarkplaces.git diff --git a/r_shadow.c b/r_shadow.c index dcb2b3a3..4234f968 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -145,6 +145,8 @@ cvar_t r_shadow_realtime_world = {0, "r_shadow_realtime_world", "0"}; cvar_t r_shadow_realtime_dlight = {0, "r_shadow_realtime_dlight", "0"}; cvar_t r_shadow_visiblevolumes = {0, "r_shadow_visiblevolumes", "0"}; cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"}; +cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1"}; +cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.25"}; cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"}; cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"}; cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"}; @@ -227,6 +229,8 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_realtime_dlight); Cvar_RegisterVariable(&r_shadow_visiblevolumes); Cvar_RegisterVariable(&r_shadow_gloss); + Cvar_RegisterVariable(&r_shadow_glossintensity); + Cvar_RegisterVariable(&r_shadow_gloss2intensity); Cvar_RegisterVariable(&r_shadow_debuglight); Cvar_RegisterVariable(&r_shadow_scissor); Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap); @@ -270,6 +274,57 @@ int *R_Shadow_ResizeShadowElements(int numtris) return shadowelements; } +/* +// readable version of some code found below +//if ((t >= trianglerange_start && t < trianglerange_end) ? (t < i && !trianglefacinglight[t]) : (t < 0 || (te = inelement3i + t * 3, v[0] = invertex3f + te[0] * 3, v[1] = invertex3f + te[1] * 3, v[2] = invertex3f + te[2] * 3, !PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))) +int PointInfrontOfTriangle(const float *p, const float *a, const float *b, const float *c) +{ + float dir0[3], dir1[3], normal[3]; + + // calculate two mostly perpendicular edge directions + VectorSubtract(a, b, dir0); + VectorSubtract(c, b, dir1); + + // we have two edge directions, we can calculate a third vector from + // them, which is the direction of the surface normal (it's magnitude + // is not 1 however) + CrossProduct(dir0, dir1, normal); + + // compare distance of light along normal, with distance of any point + // of the triangle along the same normal (the triangle is planar, + // I.E. flat, so all points give the same answer) + return DotProduct(p, normal) > DotProduct(a, normal); +} +int checkcastshadowfromedge(int t, int i) +{ + int *te; + float *v[3]; + if (t >= trianglerange_start && t < trianglerange_end) + { + if (t < i && !trianglefacinglight[t]) + return true; + else + return false; + } + else + { + if (t < 0) + return true; + else + { + te = inelement3i + t * 3; + v[0] = invertex3f + te[0] * 3; + v[1] = invertex3f + te[1] * 3; + v[2] = invertex3f + te[2] * 3; + if (!PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))) + return true; + else + return false; + } + } +} +*/ + int R_Shadow_ConstructShadowVolume(int innumvertices, int trianglerange_start, int trianglerange_end, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *relativelightorigin, float projectdistance) { int i, j, tris = 0, numfacing = 0, vr[3], t, outvertices = 0; @@ -446,12 +501,12 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int trianglerange_start, i } } // output the front and back triangles - outelement3i[3] = vertexremap[e[0]]; - outelement3i[4] = vertexremap[e[1]]; - outelement3i[5] = vertexremap[e[2]]; - outelement3i[0] = vertexremap[e[2]] + 1; - outelement3i[1] = vertexremap[e[1]] + 1; - outelement3i[2] = vertexremap[e[0]] + 1; + outelement3i[0] = vertexremap[e[0]]; + outelement3i[1] = vertexremap[e[1]]; + outelement3i[2] = vertexremap[e[2]]; + outelement3i[3] = vertexremap[e[2]] + 1; + outelement3i[4] = vertexremap[e[1]] + 1; + outelement3i[5] = vertexremap[e[0]] + 1; outelement3i += 6; tris += 2; } @@ -532,7 +587,7 @@ void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *el // triangle elements and vertices... by clever use of elements we // can construct the whole shadow from the unprojected vertices and // the projected vertices - if ((tris = R_Shadow_ConstructShadowVolume(numverts, 0, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, varray_vertex3f2, relativelightorigin, projectdistance))) + if ((tris = R_Shadow_ConstructShadowVolume(numverts, 0, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, varray_vertex3f2, relativelightorigin, r_shadow_projectdistance.value/*projectdistance*/))) { GL_VertexPointer(varray_vertex3f2); if (r_shadowstage == SHADOWSTAGE_STENCIL) @@ -556,8 +611,6 @@ void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *el void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *firstmesh) { shadowmesh_t *mesh; - rmeshstate_t m; - memset(&m, 0, sizeof(m)); if (r_shadowstage == SHADOWSTAGE_STENCIL) { // increment stencil if backface is behind depthbuffer @@ -719,21 +772,18 @@ void R_Shadow_Stage_Begin(void) if (r_shadow_texture3d.integer && !gl_texture3d) Cvar_SetValueQuick(&r_shadow_texture3d, 0); - //cl.worldmodel->numlights = min(cl.worldmodel->numlights, 1); if (!r_shadow_attenuation2dtexture || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer) || r_shadow_lightattenuationpower.value != r_shadow_attenpower || r_shadow_lightattenuationscale.value != r_shadow_attenscale) R_Shadow_MakeTextures(); + memset(&m, 0, sizeof(m)); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(false); GL_DepthTest(true); - GL_Color(0, 0, 0, 1); - - memset(&m, 0, sizeof(m)); R_Mesh_State_Texture(&m); - + GL_Color(0, 0, 0, 1); qglDisable(GL_SCISSOR_TEST); r_shadowstage = SHADOWSTAGE_NONE; @@ -761,15 +811,13 @@ void R_Shadow_LoadWorldLightsIfNeeded(void) void R_Shadow_Stage_ShadowVolumes(void) { rmeshstate_t m; - memset(&m, 0, sizeof(m)); R_Mesh_State_Texture(&m); - GL_Color(1, 1, 1, 1); + qglColorMask(0, 0, 0, 0); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(false); GL_DepthTest(true); - if (r_shadow_polygonoffset.value != 0) { qglPolygonOffset(1.0f, r_shadow_polygonoffset.value); @@ -777,13 +825,11 @@ void R_Shadow_Stage_ShadowVolumes(void) } else qglDisable(GL_POLYGON_OFFSET_FILL); - qglColorMask(0, 0, 0, 0); qglDepthFunc(GL_LESS); qglEnable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_ALWAYS, 128, 0xFF); r_shadowstage = SHADOWSTAGE_STENCIL; - qglClear(GL_STENCIL_BUFFER_BIT); c_rt_clears++; // LordHavoc note: many shadow volumes reside entirely inside the world @@ -798,24 +844,18 @@ void R_Shadow_Stage_ShadowVolumes(void) void R_Shadow_Stage_LightWithoutShadows(void) { rmeshstate_t m; - memset(&m, 0, sizeof(m)); R_Mesh_State_Texture(&m); - - GL_Color(1, 1, 1, 1); GL_BlendFunc(GL_ONE, GL_ONE); GL_DepthMask(false); GL_DepthTest(true); qglDisable(GL_POLYGON_OFFSET_FILL); - - //GL_DepthTest(false); - + GL_Color(1, 1, 1, 1); qglColorMask(1, 1, 1, 1); - qglDepthFunc(GL_LEQUAL); + qglDepthFunc(GL_EQUAL); qglDisable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_EQUAL, 128, 0xFF); - r_shadowstage = SHADOWSTAGE_LIGHT; c_rt_lights++; } @@ -823,26 +863,20 @@ void R_Shadow_Stage_LightWithoutShadows(void) void R_Shadow_Stage_LightWithShadows(void) { rmeshstate_t m; - memset(&m, 0, sizeof(m)); R_Mesh_State_Texture(&m); - - GL_Color(1, 1, 1, 1); GL_BlendFunc(GL_ONE, GL_ONE); GL_DepthMask(false); GL_DepthTest(true); qglDisable(GL_POLYGON_OFFSET_FILL); - - //GL_DepthTest(false); - + GL_Color(1, 1, 1, 1); qglColorMask(1, 1, 1, 1); - qglDepthFunc(GL_LEQUAL); + qglDepthFunc(GL_EQUAL); qglEnable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // only draw light where this geometry was already rendered AND the // stencil is 128 (values other than this mean shadow) qglStencilFunc(GL_EQUAL, 128, 0xFF); - r_shadowstage = SHADOWSTAGE_LIGHT; c_rt_lights++; } @@ -850,167 +884,22 @@ void R_Shadow_Stage_LightWithShadows(void) void R_Shadow_Stage_End(void) { rmeshstate_t m; - memset(&m, 0, sizeof(m)); R_Mesh_State_Texture(&m); - - GL_Color(1, 1, 1, 1); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); GL_DepthTest(true); qglDisable(GL_POLYGON_OFFSET_FILL); - + GL_Color(1, 1, 1, 1); qglColorMask(1, 1, 1, 1); qglDisable(GL_SCISSOR_TEST); qglDepthFunc(GL_LEQUAL); qglDisable(GL_STENCIL_TEST); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc(GL_ALWAYS, 128, 0xFF); - r_shadowstage = SHADOWSTAGE_NONE; } -#if 0 -int R_Shadow_ScissorForBBoxAndSphere(const float *mins, const float *maxs, const float *origin, float radius) -{ - int i, ix1, iy1, ix2, iy2; - float x1, y1, x2, y2, x, y; - vec3_t smins, smaxs; - vec4_t v, v2; - if (!r_shadow_scissor.integer) - return false; - // if view is inside the box, just say yes it's visible - if (r_origin[0] >= mins[0] && r_origin[0] <= maxs[0] - && r_origin[1] >= mins[1] && r_origin[1] <= maxs[1] - && r_origin[2] >= mins[2] && r_origin[2] <= maxs[2]) - { - qglDisable(GL_SCISSOR_TEST); - return false; - } - VectorSubtract(r_origin, origin, v); - if (DotProduct(v, v) < radius * radius) - { - qglDisable(GL_SCISSOR_TEST); - return false; - } - // 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); - if (i) - { - if (smins[0] > v2[0]) smins[0] = v2[0]; - if (smaxs[0] < v2[0]) smaxs[0] = v2[0]; - if (smins[1] > v2[1]) smins[1] = v2[1]; - if (smaxs[1] < v2[1]) smaxs[1] = v2[1]; - if (smins[2] > v2[2]) smins[2] = v2[2]; - if (smaxs[2] < v2[2]) smaxs[2] = v2[2]; - } - else - { - smins[0] = smaxs[0] = v2[0]; - smins[1] = smaxs[1] = v2[1]; - smins[2] = smaxs[2] = v2[2]; - } - } - // now we have a bbox in viewspace - // clip it to the viewspace version of the sphere - v[0] = origin[0] - r_origin[0]; - v[1] = origin[1] - r_origin[1]; - v[2] = origin[2] - r_origin[2]; - v2[0] = DotProduct(v, vright); - v2[1] = DotProduct(v, vup); - v2[2] = DotProduct(v, vpn); - if (smins[0] < v2[0] - radius) smins[0] = v2[0] - radius; - if (smaxs[0] < v2[0] - radius) smaxs[0] = v2[0] + radius; - if (smins[1] < v2[1] - radius) smins[1] = v2[1] - radius; - if (smaxs[1] < v2[1] - radius) smaxs[1] = v2[1] + radius; - if (smins[2] < v2[2] - radius) smins[2] = v2[2] - radius; - if (smaxs[2] < v2[2] - radius) smaxs[2] = v2[2] + radius; - // clip it to the view plane - if (smins[2] < 1) - smins[2] = 1; - // return true if that culled the box - if (smins[2] >= smaxs[2]) - return true; - // ok some of it is infront of the view, transform each corner back to - // worldspace and then to screenspace and make screen rect - // initialize these variables just to avoid compiler warnings - x1 = y1 = x2 = y2 = 0; - for (i = 0;i < 8;i++) - { - 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[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]); - x = v2[0]; - y = v2[1]; - if (i) - { - if (x1 > x) x1 = x; - if (x2 < x) x2 = x; - if (y1 > y) y1 = y; - if (y2 < y) y2 = y; - } - else - { - x1 = x2 = x; - y1 = y2 = y; - } - } - /* - // this code doesn't handle boxes with any points behind view properly - x1 = 1000;x2 = -1000; - y1 = 1000;y2 = -1000; - for (i = 0;i < 8;i++) - { - v[0] = (i & 1) ? mins[0] : maxs[0]; - v[1] = (i & 2) ? mins[1] : maxs[1]; - v[2] = (i & 4) ? mins[2] : maxs[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]); - if (v2[2] > 0) - { - x = v2[0]; - y = v2[1]; - - if (x1 > x) x1 = x; - if (x2 < x) x2 = x; - if (y1 > y) y1 = y; - if (y2 < y) y2 = y; - } - } - */ - ix1 = x1 - 1.0f; - iy1 = y1 - 1.0f; - ix2 = x2 + 1.0f; - iy2 = y2 + 1.0f; - //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2); - if (ix1 < r_refdef.x) ix1 = r_refdef.x; - if (iy1 < r_refdef.y) iy1 = r_refdef.y; - if (ix2 > r_refdef.x + r_refdef.width) ix2 = r_refdef.x + r_refdef.width; - if (iy2 > r_refdef.y + r_refdef.height) iy2 = r_refdef.y + r_refdef.height; - if (ix2 <= ix1 || iy2 <= iy1) - return true; - // set up the scissor rectangle - qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1); - qglEnable(GL_SCISSOR_TEST); - c_rt_scissored++; - return false; -} -#endif - int R_Shadow_ScissorForBBox(const float *mins, const float *maxs) { int i, ix1, iy1, ix2, iy2; @@ -1587,16 +1476,19 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elements, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *texcoord2f, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap) { int renders; - float color[3], color2[3]; + float color[3], color2[3], colorscale; rmeshstate_t m; if (!gl_dot3arb || !gl_texturecubemap || !gl_combine.integer || !gl_stencil) return; - if (!bumptexture) - bumptexture = r_shadow_blankbumptexture; if (!glosstexture) glosstexture = r_shadow_blankglosstexture; if (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture)) { + colorscale = r_colorscale * r_shadow_glossintensity.value; + if (!bumptexture) + bumptexture = r_shadow_blankbumptexture; + if (glosstexture == r_shadow_blankglosstexture) + colorscale *= r_shadow_gloss2intensity.value; GL_VertexPointer(vertex3f); GL_Color(1,1,1,1); if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare! @@ -1652,7 +1544,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen GL_BlendFunc(GL_DST_ALPHA, GL_ONE); if (lightcubemap) R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); - VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2); + VectorScale(lightcolor, colorscale, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { color[0] = bound(0, color2[0], 1); @@ -1706,7 +1598,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen qglColorMask(1,1,1,0); GL_BlendFunc(GL_DST_ALPHA, GL_ONE); R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz); - VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2); + VectorScale(lightcolor, colorscale, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { color[0] = bound(0, color2[0], 1); @@ -1774,7 +1666,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen GL_BlendFunc(GL_DST_ALPHA, GL_ONE); if (lightcubemap) R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter); - VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2); + VectorScale(lightcolor, colorscale, color2); for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--) { color[0] = bound(0, color2[0], 1); @@ -1807,16 +1699,18 @@ worldlight_t *r_shadow_worldlightchain; worldlight_t *r_shadow_selectedlight; vec3_t r_editlights_cursorlocation; +static int lightpvsbytes; +static qbyte lightpvs[(MAX_MAP_LEAFS + 7)/ 8]; + static int castshadowcount = 1; void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style, const char *cubemapname, int castshadow) { - int i, j, k, l, maxverts = 256, *mark, tris; - float *vertex3f = NULL; + int i, j, k, l, maxverts = 256, *mark, tris, numsurfaces; + float *vertex3f = NULL, mins[3], maxs[3]; worldlight_t *e; shadowmesh_t *mesh, *castmesh; mleaf_t *leaf; msurface_t *surf; - qbyte *pvs; surfmesh_t *surfmesh; if (radius < 15 || DotProduct(color, color) < 0.03) @@ -1840,8 +1734,8 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style e->cullradius = e->lightradius; for (k = 0;k < 3;k++) { - e->mins[k] = e->origin[k] - e->lightradius; - e->maxs[k] = e->origin[k] + e->lightradius; + mins[k] = e->origin[k] - e->lightradius; + maxs[k] = e->origin[k] + e->lightradius; } e->next = r_shadow_worldlightchain; @@ -1855,23 +1749,33 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style if (cl.worldmodel) { castshadowcount++; - i = Mod_PointContents(e->origin, cl.worldmodel); + VectorCopy(e->origin, e->mins); + VectorCopy(e->origin, e->maxs); + i = CL_PointContents(e->origin); if (r_shadow_portallight.integer && i != CONTENTS_SOLID && i != CONTENTS_SKY) { qbyte *byteleafpvs; qbyte *bytesurfacepvs; - byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->numleafs + 1); - bytesurfacepvs = Mem_Alloc(tempmempool, cl.worldmodel->numsurfaces); + byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numleafs); + bytesurfacepvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numsurfaces); Portal_Visibility(cl.worldmodel, e->origin, byteleafpvs, bytesurfacepvs, NULL, 0, true, RadiusFromBoundsAndOrigin(e->mins, e->maxs, e->origin)); - for (i = 0, leaf = cl.worldmodel->leafs + 1;i < cl.worldmodel->numleafs;i++, leaf++) - if (byteleafpvs[i+1] && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs)) - leaf->worldnodeframe = castshadowcount; + for (i = 0, leaf = cl.worldmodel->brushq1.leafs;i < cl.worldmodel->brushq1.numleafs;i++, leaf++) + { + if (byteleafpvs[i] && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs)) + { + for (k = 0;k < 3;k++) + { + if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k]; + if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k]; + } + } + } - for (i = 0, surf = cl.worldmodel->surfaces;i < cl.worldmodel->numsurfaces;i++, surf++) - if (bytesurfacepvs[i] && BoxesOverlap(surf->poly_mins, surf->poly_maxs, e->mins, e->maxs)) + for (i = 0, surf = cl.worldmodel->brushq1.surfaces;i < cl.worldmodel->brushq1.numsurfaces;i++, surf++) + if (bytesurfacepvs[i] && BoxesOverlap(surf->poly_mins, surf->poly_maxs, mins, maxs)) surf->castshadow = castshadowcount; Mem_Free(byteleafpvs); @@ -1879,58 +1783,26 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style } else { - leaf = Mod_PointInLeaf(origin, cl.worldmodel); - pvs = Mod_LeafPVS(leaf, cl.worldmodel); - for (i = 0, leaf = cl.worldmodel->leafs + 1;i < cl.worldmodel->numleafs;i++, leaf++) + lightpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, origin, 0, lightpvs, sizeof(lightpvs)); + for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.visleafs;i++, leaf++) { - if (pvs[i >> 3] & (1 << (i & 7)) && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs)) + if (lightpvs[i >> 3] & (1 << (i & 7)) && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs)) { - leaf->worldnodeframe = castshadowcount; + for (k = 0;k < 3;k++) + { + if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k]; + if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k]; + } for (j = 0, mark = leaf->firstmarksurface;j < leaf->nummarksurfaces;j++, mark++) { - surf = cl.worldmodel->surfaces + *mark; - if (surf->castshadow != castshadowcount && BoxesOverlap(surf->poly_mins, surf->poly_maxs, e->mins, e->maxs)) + surf = cl.worldmodel->brushq1.surfaces + *mark; + if (surf->castshadow != castshadowcount && BoxesOverlap(surf->poly_mins, surf->poly_maxs, mins, maxs)) surf->castshadow = castshadowcount; } } } } - e->numleafs = 0; - for (i = 0, leaf = cl.worldmodel->leafs + 1;i < cl.worldmodel->numleafs;i++, leaf++) - if (leaf->worldnodeframe == castshadowcount) - e->numleafs++; - e->numsurfaces = 0; - for (i = 0, surf = cl.worldmodel->surfaces + cl.worldmodel->firstmodelsurface;i < cl.worldmodel->nummodelsurfaces;i++, surf++) - if (surf->castshadow == castshadowcount) - e->numsurfaces++; - - if (e->numleafs) - e->leafs = Mem_Alloc(r_shadow_mempool, e->numleafs * sizeof(mleaf_t *)); - if (e->numsurfaces) - e->surfaces = Mem_Alloc(r_shadow_mempool, e->numsurfaces * sizeof(msurface_t *)); - e->numleafs = 0; - for (i = 0, leaf = cl.worldmodel->leafs + 1;i < cl.worldmodel->numleafs;i++, leaf++) - if (leaf->worldnodeframe == castshadowcount) - e->leafs[e->numleafs++] = leaf; - e->numsurfaces = 0; - for (i = 0, surf = cl.worldmodel->surfaces + cl.worldmodel->firstmodelsurface;i < cl.worldmodel->nummodelsurfaces;i++, surf++) - if (surf->castshadow == castshadowcount) - e->surfaces[e->numsurfaces++] = surf; - - // find bounding box of lit leafs - VectorCopy(e->origin, e->mins); - VectorCopy(e->origin, e->maxs); - for (j = 0;j < e->numleafs;j++) - { - leaf = e->leafs[j]; - for (k = 0;k < 3;k++) - { - if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k]; - if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k]; - } - } - for (k = 0;k < 3;k++) { if (e->mins[k] < e->origin[k] - e->lightradius) e->mins[k] = e->origin[k] - e->lightradius; @@ -1938,6 +1810,17 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style } e->cullradius = RadiusFromBoundsAndOrigin(e->mins, e->maxs, e->origin); + numsurfaces = 0; + for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++) + if (surf->castshadow == castshadowcount) + numsurfaces++; + if (numsurfaces) + e->surfaces = Mem_Alloc(r_shadow_mempool, numsurfaces * sizeof(msurface_t *)); + e->numsurfaces = 0; + for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++) + if (surf->castshadow == castshadowcount) + e->surfaces[e->numsurfaces++] = surf; + if (e->castshadows) { castshadowcount++; @@ -1991,7 +1874,7 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style Con_Printf("static shadow volume built containing %i triangles\n", l); } } - Con_Printf("%f %f %f, %f %f %f, %f, %f, %d, %d\n", e->mins[0], e->mins[1], e->mins[2], e->maxs[0], e->maxs[1], e->maxs[2], e->cullradius, e->lightradius, e->numleafs, e->numsurfaces); + Con_Printf("%f %f %f, %f %f %f, %f, %f, %d\n", e->mins[0], e->mins[1], e->mins[2], e->maxs[0], e->maxs[1], e->maxs[2], e->cullradius, e->lightradius, e->numsurfaces); } void R_Shadow_FreeWorldLight(worldlight_t *light) @@ -2007,8 +1890,6 @@ void R_Shadow_FreeWorldLight(worldlight_t *light) Mod_ShadowMesh_Free(light->shadowvolume); if (light->surfaces) Mem_Free(light->surfaces); - if (light->leafs) - Mem_Free(light->leafs); Mem_Free(light); } @@ -2245,10 +2126,10 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void) Con_Printf("No map loaded.\n"); return; } - data = cl.worldmodel->entities; + data = cl.worldmodel->brush.entities; if (!data) return; - for (entnum = 0;COM_ParseToken(&data) && com_token[0] == '{';entnum++) + for (entnum = 0;COM_ParseToken(&data, false) && com_token[0] == '{';entnum++) { light = 0; origin[0] = origin[1] = origin[2] = 0; @@ -2260,7 +2141,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void) islight = false; while (1) { - if (!COM_ParseToken(&data)) + if (!COM_ParseToken(&data, false)) break; // error if (com_token[0] == '}') break; // end of entity @@ -2270,7 +2151,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void) strcpy(key, com_token); while (key[strlen(key)-1] == ' ') // remove trailing spaces key[strlen(key)-1] = 0; - if (!COM_ParseToken(&data)) + if (!COM_ParseToken(&data, false)) break; // error strcpy(value, com_token);