void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
{
+#if 0
int i;
msurface_t *surf;
float projectdistance, f, temp[3], lightradius2;
R_Mesh_Matrix(&ent->matrix);
lightradius2 = lightradius * lightradius;
R_UpdateTextureInfo(ent);
- projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
+ projectdistance = lightradius + ent->model->radius;//projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
+ //projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
for (i = 0, surf = ent->model->brushq1.surfaces + ent->model->brushq1.firstmodelsurface;i < ent->model->brushq1.nummodelsurfaces;i++, surf++)
{
if (surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && surf->flags & SURF_SHADOWCAST)
temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1];
temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2];
if (DotProduct(temp, temp) < lightradius2)
- R_Shadow_Volume(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_vertex3f, surf->mesh.data_element3i, surf->mesh.data_neighbor3i, relativelightorigin, lightradius, projectdistance);
+ R_Shadow_VolumeFromSphere(surf->mesh.num_vertices, surf->mesh.num_triangles, surf->mesh.data_vertex3f, surf->mesh.data_element3i, surf->mesh.data_neighbor3i, relativelightorigin, projectdistance, lightradius);
}
}
}
+#else
+ int i, j, t;
+ const int *e;
+ msurface_t *surf;
+ float projectdistance;
+ const float *v[3];
+ vec3_t lightmins, lightmaxs;
+ if (ent->model == NULL)
+ return;
+ R_Mesh_Matrix(&ent->matrix);
+ R_UpdateTextureInfo(ent);
+ projectdistance = lightradius + ent->model->radius;//projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
+ //projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
+ lightmins[0] = relativelightorigin[0] - lightradius;
+ lightmins[1] = relativelightorigin[1] - lightradius;
+ lightmins[2] = relativelightorigin[2] - lightradius;
+ lightmaxs[0] = relativelightorigin[0] + lightradius;
+ lightmaxs[1] = relativelightorigin[1] + lightradius;
+ lightmaxs[2] = relativelightorigin[2] + lightradius;
+ R_Shadow_PrepareShadowMark(ent->model->brush.shadowmesh->numtriangles);
+ for (i = 0, surf = ent->model->brushq1.surfaces + ent->model->brushq1.firstmodelsurface;i < ent->model->brushq1.nummodelsurfaces;i++, surf++)
+ {
+ if (BoxesOverlap(lightmins, lightmaxs, surf->poly_mins, surf->poly_maxs) && surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && (surf->flags & SURF_SHADOWCAST))
+ {
+ for (j = 0, t = surf->num_firstshadowmeshtriangle, e = ent->model->brush.shadowmesh->element3i + t * 3;j < surf->mesh.num_triangles;j++, t++, e += 3)
+ {
+ v[0] = ent->model->brush.shadowmesh->vertex3f + e[0] * 3;
+ v[1] = ent->model->brush.shadowmesh->vertex3f + e[1] * 3;
+ v[2] = ent->model->brush.shadowmesh->vertex3f + e[2] * 3;
+ if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ shadowmarklist[numshadowmark++] = t;
+ }
+ }
+ }
+ R_Shadow_VolumeFromList(ent->model->brush.shadowmesh->numverts, ent->model->brush.shadowmesh->numtriangles, ent->model->brush.shadowmesh->vertex3f, ent->model->brush.shadowmesh->element3i, ent->model->brush.shadowmesh->neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist);
+#endif
}
void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap)
void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
{
+#if 0
int i;
q3mface_t *face;
vec3_t modelorg, lightmins, lightmaxs;
model_t *model;
float projectdistance;
- projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
+ projectdistance = lightradius + ent->model->radius;//projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
if (r_drawcollisionbrushes.integer < 2)
{
model = ent->model;
//else
for (i = 0, face = model->brushq3.data_thismodel->firstface;i < model->brushq3.data_thismodel->numfaces;i++, face++)
if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs))
- R_Shadow_Volume(face->num_vertices, face->num_triangles, face->data_vertex3f, face->data_element3i, face->data_neighbor3i, relativelightorigin, lightradius, projectdistance);
+ R_Shadow_VolumeFromSphere(face->num_vertices, face->num_triangles, face->data_vertex3f, face->data_element3i, face->data_neighbor3i, relativelightorigin, projectdistance, lightradius);
}
+#else
+ int i, j, t;
+ const int *e;
+ q3mface_t *face;
+ vec3_t modelorg, lightmins, lightmaxs;
+ model_t *model;
+ float projectdistance;
+ projectdistance = lightradius + ent->model->radius;//projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
+ if (r_drawcollisionbrushes.integer < 2)
+ {
+ model = ent->model;
+ R_Mesh_Matrix(&ent->matrix);
+ Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
+ lightmins[0] = relativelightorigin[0] - lightradius;
+ lightmins[1] = relativelightorigin[1] - lightradius;
+ lightmins[2] = relativelightorigin[2] - lightradius;
+ lightmaxs[0] = relativelightorigin[0] + lightradius;
+ lightmaxs[1] = relativelightorigin[1] + lightradius;
+ lightmaxs[2] = relativelightorigin[2] + lightradius;
+ R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
+ for (i = 0, face = model->brushq3.data_thismodel->firstface;i < model->brushq3.data_thismodel->numfaces;i++, face++)
+ {
+ if (BoxesOverlap(lightmins, lightmaxs, face->mins, face->maxs))
+ {
+ for (j = 0, t = face->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;j < face->num_triangles;j++, t++, e += 3)
+ {
+ const float *v[3];
+ v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
+ v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
+ v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
+ if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ shadowmarklist[numshadowmark++] = t;
+ }
+ }
+ }
+ R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist);
+ }
+#endif
}
void R_Q3BSP_DrawFaceLight(entity_render_t *ent, q3mface_t *face, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap)
int maxshadowelements;
int *shadowelements;
-int maxtrianglefacinglight;
-qbyte *trianglefacinglight;
-int *trianglefacinglightlist;
+
+int maxshadowmark;
+int numshadowmark;
+int *shadowmark;
+int *shadowmarklist;
+int shadowmarkcount;
int maxvertexupdate;
int *vertexupdate;
vertexupdate = NULL;
vertexremap = NULL;
vertexupdatenum = 0;
- maxtrianglefacinglight = 0;
- trianglefacinglight = NULL;
- trianglefacinglightlist = NULL;
+ maxshadowmark = 0;
+ numshadowmark = 0;
+ shadowmark = NULL;
+ shadowmarklist = NULL;
+ shadowmarkcount = 0;
r_shadow_normalcubetexture = NULL;
r_shadow_attenuation2dtexture = NULL;
r_shadow_attenuation3dtexture = NULL;
vertexupdate = NULL;
vertexremap = NULL;
vertexupdatenum = 0;
- maxtrianglefacinglight = 0;
- trianglefacinglight = NULL;
- trianglefacinglightlist = NULL;
+ maxshadowmark = 0;
+ numshadowmark = 0;
+ shadowmark = NULL;
+ shadowmarklist = NULL;
+ shadowmarkcount = 0;
Mem_FreePool(&r_shadow_mempool);
}
}
};
-void R_Shadow_ResizeTriangleFacingLight(int numtris)
-{
- // make sure trianglefacinglight is big enough for this volume
- // ameks ru ertaignelaficgnilhg tsib gie ongu hof rhtsiv lomu e
- // m4k3 5ur3 7r14ng13f4c1n5115h7 15 b15 3n0u5h f0r 7h15 v01um3
- if (maxtrianglefacinglight < numtris)
- {
- maxtrianglefacinglight = numtris;
- if (trianglefacinglight)
- Mem_Free(trianglefacinglight);
- if (trianglefacinglightlist)
- Mem_Free(trianglefacinglightlist);
- trianglefacinglight = Mem_Alloc(r_shadow_mempool, maxtrianglefacinglight);
- trianglefacinglightlist = Mem_Alloc(r_shadow_mempool, sizeof(int) * maxtrianglefacinglight);
- }
-}
-
int *R_Shadow_ResizeShadowElements(int numtris)
{
// make sure shadowelements is big enough for this volume
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)
+void R_Shadow_PrepareShadowMark(int numtris)
{
- int *te;
- float *v[3];
- if (t >= trianglerange_start && t < trianglerange_end)
+ // make sure shadowmark is big enough for this volume
+ if (maxshadowmark < numtris)
{
- if (t < i && !trianglefacinglight[t])
- return true;
- else
- return false;
+ maxshadowmark = numtris;
+ if (shadowmark)
+ Mem_Free(shadowmark);
+ if (shadowmarklist)
+ Mem_Free(shadowmarklist);
+ shadowmark = Mem_Alloc(r_shadow_mempool, maxshadowmark * sizeof(*shadowmark));
+ shadowmarklist = Mem_Alloc(r_shadow_mempool, maxshadowmark * sizeof(*shadowmarklist));
+ shadowmarkcount = 0;
}
- else
+ shadowmarkcount++;
+ // if shadowmarkcount wrapped we clear the array and adjust accordingly
+ if (shadowmarkcount == 0)
{
- 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;
- }
+ shadowmarkcount = 1;
+ memset(shadowmark, 0, maxshadowmark * sizeof(*shadowmark));
}
+ numshadowmark = 0;
}
-*/
-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 R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
{
- int i, j, tris = 0, numfacing = 0, vr[3], t, outvertices = 0;
- const float *v[3];
- const int *e, *n, *te;
+ int i, j, tris = 0, vr[3], t, outvertices = 0;
+ const int *e, *n;
float f, temp[3];
- // make sure trianglefacinglight is big enough for this volume
- if (maxtrianglefacinglight < trianglerange_end)
- R_Shadow_ResizeTriangleFacingLight(trianglerange_end);
-
if (maxvertexupdate < innumvertices)
{
maxvertexupdate = innumvertices;
Mem_Free(vertexremap);
vertexupdate = Mem_Alloc(r_shadow_mempool, maxvertexupdate * sizeof(int));
vertexremap = Mem_Alloc(r_shadow_mempool, maxvertexupdate * sizeof(int));
+ vertexupdatenum = 0;
}
vertexupdatenum++;
-
- if (r_shadow_singlepassvolumegeneration.integer)
+ if (vertexupdatenum == 0)
{
- // one pass approach (identify lit/dark faces and generate sides while doing so)
- for (i = trianglerange_start, e = inelement3i + i * 3, n = inneighbor3i + i * 3;i < trianglerange_end;i++, e += 3, n += 3)
- {
- // calculate triangle facing flag
- v[0] = invertex3f + e[0] * 3;
- v[1] = invertex3f + e[1] * 3;
- v[2] = invertex3f + e[2] * 3;
- if((trianglefacinglight[i] = PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))
- {
- // make sure the vertices are created
- for (j = 0;j < 3;j++)
- {
- if (vertexupdate[e[j]] != vertexupdatenum)
- {
- vertexupdate[e[j]] = vertexupdatenum;
- vertexremap[e[j]] = outvertices;
- VectorCopy(v[j], outvertex3f);
- VectorSubtract(v[j], relativelightorigin, temp);
- f = projectdistance / VectorLength(temp);
- VectorMA(relativelightorigin, f, temp, (outvertex3f + 3));
- outvertex3f += 6;
- outvertices += 2;
- }
- }
- // output the front and back triangles
- vr[0] = vertexremap[e[0]];
- vr[1] = vertexremap[e[1]];
- vr[2] = vertexremap[e[2]];
- outelement3i[0] = vr[0];
- outelement3i[1] = vr[1];
- outelement3i[2] = vr[2];
- outelement3i[3] = vr[2] + 1;
- outelement3i[4] = vr[1] + 1;
- outelement3i[5] = vr[0] + 1;
- outelement3i += 6;
- tris += 2;
- // output the sides (facing outward from this triangle)
- t = n[0];
- 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]))))
- {
- outelement3i[0] = vr[1];
- outelement3i[1] = vr[0];
- outelement3i[2] = vr[0] + 1;
- outelement3i[3] = vr[1];
- outelement3i[4] = vr[0] + 1;
- outelement3i[5] = vr[1] + 1;
- outelement3i += 6;
- tris += 2;
- }
- t = n[1];
- 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]))))
- {
- outelement3i[0] = vr[2];
- outelement3i[1] = vr[1];
- outelement3i[2] = vr[1] + 1;
- outelement3i[3] = vr[2];
- outelement3i[4] = vr[1] + 1;
- outelement3i[5] = vr[2] + 1;
- outelement3i += 6;
- tris += 2;
- }
- t = n[2];
- 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]))))
- {
- outelement3i[0] = vr[0];
- outelement3i[1] = vr[2];
- outelement3i[2] = vr[2] + 1;
- outelement3i[3] = vr[0];
- outelement3i[4] = vr[2] + 1;
- outelement3i[5] = vr[0] + 1;
- outelement3i += 6;
- tris += 2;
- }
- }
- else
- {
- // this triangle is not facing the light
- // output the sides (facing inward to this triangle)
- t = n[0];
- if (t < i && t >= trianglerange_start && t < trianglerange_end && trianglefacinglight[t])
- {
- vr[0] = vertexremap[e[0]];
- vr[1] = vertexremap[e[1]];
- outelement3i[0] = vr[1];
- outelement3i[1] = vr[0] + 1;
- outelement3i[2] = vr[0];
- outelement3i[3] = vr[1];
- outelement3i[4] = vr[1] + 1;
- outelement3i[5] = vr[0] + 1;
- outelement3i += 6;
- tris += 2;
- }
- t = n[1];
- if (t < i && t >= trianglerange_start && t < trianglerange_end && trianglefacinglight[t])
- {
- vr[1] = vertexremap[e[1]];
- vr[2] = vertexremap[e[2]];
- outelement3i[0] = vr[2];
- outelement3i[1] = vr[1] + 1;
- outelement3i[2] = vr[1];
- outelement3i[3] = vr[2];
- outelement3i[4] = vr[2] + 1;
- outelement3i[5] = vr[1] + 1;
- outelement3i += 6;
- tris += 2;
- }
- t = n[2];
- if (t < i && t >= trianglerange_start && t < trianglerange_end && trianglefacinglight[t])
- {
- vr[0] = vertexremap[e[0]];
- vr[2] = vertexremap[e[2]];
- outelement3i[0] = vr[0];
- outelement3i[1] = vr[2] + 1;
- outelement3i[2] = vr[2];
- outelement3i[3] = vr[0];
- outelement3i[4] = vr[0] + 1;
- outelement3i[5] = vr[2] + 1;
- outelement3i += 6;
- tris += 2;
- }
- }
- }
+ vertexupdatenum = 1;
+ memset(vertexupdate, 0, maxvertexupdate * sizeof(int));
+ memset(vertexremap, 0, maxvertexupdate * sizeof(int));
}
- else
+
+ for (i = 0;i < numshadowmarktris;i++)
{
- // two pass approach (identify lit/dark faces and then generate sides)
- for (i = trianglerange_start, e = inelement3i + i * 3, numfacing = 0;i < trianglerange_end;i++, e += 3)
+ t = shadowmarktris[i];
+ shadowmark[t] = shadowmarkcount;
+ e = inelement3i + t * 3;
+ // make sure the vertices are created
+ for (j = 0;j < 3;j++)
{
- // calculate triangle facing flag
- v[0] = invertex3f + e[0] * 3;
- v[1] = invertex3f + e[1] * 3;
- v[2] = invertex3f + e[2] * 3;
- if((trianglefacinglight[i] = PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2])))
+ if (vertexupdate[e[j]] != vertexupdatenum)
{
- trianglefacinglightlist[numfacing++] = i;
- // make sure the vertices are created
- for (j = 0;j < 3;j++)
- {
- if (vertexupdate[e[j]] != vertexupdatenum)
- {
- vertexupdate[e[j]] = vertexupdatenum;
- vertexremap[e[j]] = outvertices;
- VectorSubtract(v[j], relativelightorigin, temp);
- f = projectdistance / VectorLength(temp);
- VectorCopy(v[j], outvertex3f);
- VectorMA(relativelightorigin, f, temp, (outvertex3f + 3));
- outvertex3f += 6;
- outvertices += 2;
- }
- }
- // output the front and back triangles
- 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;
+ vertexupdate[e[j]] = vertexupdatenum;
+ vertexremap[e[j]] = outvertices;
+ VectorSubtract(invertex3f + e[j] * 3, projectorigin, temp);
+ f = projectdistance / VectorLength(temp);
+ VectorCopy(invertex3f + e[j] * 3, outvertex3f);
+ VectorMA(projectorigin, f, temp, (outvertex3f + 3));
+ outvertex3f += 6;
+ outvertices += 2;
}
}
- for (i = 0;i < numfacing;i++)
- {
- t = trianglefacinglightlist[i];
- e = inelement3i + t * 3;
- n = inneighbor3i + t * 3;
- // output the sides (facing outward from this triangle)
- t = n[0];
- if ((t >= trianglerange_start && t < trianglerange_end) ? (!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]))))
- {
- vr[0] = vertexremap[e[0]];
- vr[1] = vertexremap[e[1]];
- outelement3i[0] = vr[1];
- outelement3i[1] = vr[0];
- outelement3i[2] = vr[0] + 1;
- outelement3i[3] = vr[1];
- outelement3i[4] = vr[0] + 1;
- outelement3i[5] = vr[1] + 1;
- outelement3i += 6;
- tris += 2;
- }
- t = n[1];
- if ((t >= trianglerange_start && t < trianglerange_end) ? (!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]))))
- {
- vr[1] = vertexremap[e[1]];
- vr[2] = vertexremap[e[2]];
- outelement3i[0] = vr[2];
- outelement3i[1] = vr[1];
- outelement3i[2] = vr[1] + 1;
- outelement3i[3] = vr[2];
- outelement3i[4] = vr[1] + 1;
- outelement3i[5] = vr[2] + 1;
- outelement3i += 6;
- tris += 2;
- }
- t = n[2];
- if ((t >= trianglerange_start && t < trianglerange_end) ? (!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]))))
- {
- vr[0] = vertexremap[e[0]];
- vr[2] = vertexremap[e[2]];
- outelement3i[0] = vr[0];
- outelement3i[1] = vr[2];
- outelement3i[2] = vr[2] + 1;
- outelement3i[3] = vr[0];
- outelement3i[4] = vr[2] + 1;
- outelement3i[5] = vr[0] + 1;
- outelement3i += 6;
- tris += 2;
- }
+ // output the front and back triangles
+ 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;
+ }
+
+ for (i = 0;i < numshadowmarktris;i++)
+ {
+ t = shadowmarktris[i];
+ e = inelement3i + t * 3;
+ n = inneighbor3i + t * 3;
+ // output the sides (facing outward from this triangle)
+ if (shadowmark[n[0]] != shadowmarkcount)
+ {
+ vr[0] = vertexremap[e[0]];
+ vr[1] = vertexremap[e[1]];
+ outelement3i[0] = vr[1];
+ outelement3i[1] = vr[0];
+ outelement3i[2] = vr[0] + 1;
+ outelement3i[3] = vr[1];
+ outelement3i[4] = vr[0] + 1;
+ outelement3i[5] = vr[1] + 1;
+ outelement3i += 6;
+ tris += 2;
+ }
+ if (shadowmark[n[1]] != shadowmarkcount)
+ {
+ vr[1] = vertexremap[e[1]];
+ vr[2] = vertexremap[e[2]];
+ outelement3i[0] = vr[2];
+ outelement3i[1] = vr[1];
+ outelement3i[2] = vr[1] + 1;
+ outelement3i[3] = vr[2];
+ outelement3i[4] = vr[1] + 1;
+ outelement3i[5] = vr[2] + 1;
+ outelement3i += 6;
+ tris += 2;
+ }
+ if (shadowmark[n[2]] != shadowmarkcount)
+ {
+ vr[0] = vertexremap[e[0]];
+ vr[2] = vertexremap[e[2]];
+ outelement3i[0] = vr[0];
+ outelement3i[1] = vr[2];
+ outelement3i[2] = vr[2] + 1;
+ outelement3i[3] = vr[0];
+ outelement3i[4] = vr[2] + 1;
+ outelement3i[5] = vr[0] + 1;
+ outelement3i += 6;
+ tris += 2;
}
}
if (outnumvertices)
float varray_vertex3f2[65536*3];
-void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance)
+void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, int nummarktris, const int *marktris)
{
int tris, outverts;
if (projectdistance < 0.1)
Con_Printf("R_Shadow_Volume: projectdistance %f\n");
return;
}
- if (!numverts)
+ if (!numverts || !nummarktris)
return;
-
// make sure shadowelements is big enough for this volume
- if (maxshadowelements < numtris * 24)
- R_Shadow_ResizeShadowElements(numtris);
+ if (maxshadowelements < nummarktris * 24)
+ R_Shadow_ResizeShadowElements((nummarktris + 256) * 24);
+ tris = R_Shadow_ConstructShadowVolume(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, varray_vertex3f2, projectorigin, projectdistance, nummarktris, marktris);
+ R_Shadow_RenderVolume(outverts, tris, varray_vertex3f2, shadowelements);
+}
- // check which triangles are facing the light, and then output
+void R_Shadow_VolumeFromBox(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, const vec3_t mins, const vec3_t maxs)
+{
+ int i;
+ const float *v[3];
+
+ // check which triangles are facing the , and then output
// 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, r_shadow_projectdistance.value/*projectdistance*/)))
+
+ // identify lit faces within the bounding box
+ R_Shadow_PrepareShadowMark(numtris);
+ for (i = 0;i < numtris;i++)
{
- GL_VertexPointer(varray_vertex3f2);
- if (r_shadowstage == SHADOWSTAGE_STENCIL)
- {
- // decrement stencil if frontface is behind depthbuffer
- qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
- qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
- R_Mesh_Draw(outverts, tris, shadowelements);
- c_rt_shadowmeshes++;
- c_rt_shadowtris += numtris;
- // increment stencil if backface is behind depthbuffer
- qglCullFace(GL_BACK); // quake is backwards, this culls front faces
- qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
- }
- R_Mesh_Draw(outverts, tris, shadowelements);
+ v[0] = invertex3f + elements[i*3+0] * 3;
+ v[1] = invertex3f + elements[i*3+1] * 3;
+ v[2] = invertex3f + elements[i*3+2] * 3;
+ if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]) && maxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && mins[0] < max(v[0][0], max(v[1][0], v[2][0])) && maxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && mins[1] < max(v[0][1], max(v[1][1], v[2][1])) && maxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && mins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ shadowmarklist[numshadowmark++] = i;
+ }
+ R_Shadow_VolumeFromList(numverts, numtris, invertex3f, elements, neighbors, projectorigin, projectdistance, numshadowmark, shadowmarklist);
+}
+
+void R_Shadow_VolumeFromSphere(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, float radius)
+{
+ vec3_t mins, maxs;
+ mins[0] = projectorigin[0] - radius;
+ mins[1] = projectorigin[1] - radius;
+ mins[2] = projectorigin[2] - radius;
+ maxs[0] = projectorigin[0] + radius;
+ maxs[1] = projectorigin[1] + radius;
+ maxs[2] = projectorigin[2] + radius;
+ R_Shadow_VolumeFromBox(numverts, numtris, invertex3f, elements, neighbors, projectorigin, projectdistance, mins, maxs);
+}
+
+void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *vertex3f, const int *element3i)
+{
+ GL_VertexPointer(vertex3f);
+ if (r_shadowstage == SHADOWSTAGE_STENCIL)
+ {
+ // decrement stencil if frontface is behind depthbuffer
+ qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
+ qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+ R_Mesh_Draw(numvertices, numtriangles, element3i);
c_rt_shadowmeshes++;
- c_rt_shadowtris += numtris;
+ c_rt_shadowtris += numtriangles;
+ // increment stencil if backface is behind depthbuffer
+ qglCullFace(GL_BACK); // quake is backwards, this culls front faces
+ qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
}
+ R_Mesh_Draw(numvertices, numtriangles, element3i);
+ c_rt_shadowmeshes++;
+ c_rt_shadowtris += numtriangles;
}
void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *firstmesh)
// (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
void R_RTLight_Compile(rtlight_t *rtlight)
{
+#if 0
int i, j, k, l, maxverts = 256, tris;
float *vertex3f = NULL, mins[3], maxs[3];
shadowmesh_t *mesh, *castmesh = NULL;
for (mesh = rtlight->static_meshchain_light;mesh;mesh = mesh->next)
l += mesh->numtriangles;
Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i shadow volume triangles, %i light triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], k, l);
+#endif
}
void R_RTLight_Uncompile(rtlight_t *rtlight)