From fda3b230f973c11a561f7d89a626c354b00e5a08 Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sat, 9 Mar 2013 15:38:52 +1030 Subject: [PATCH 01/14] light: lightinfo_t structure cleanup, part 1 The big lightinfo_t structure includes a lot of things that are only loosely related and not used together. Start the cleanup by pulling out the texture coordinate tranformation data that is used to generate the surface sample points. Signed-off-by: Kevin Shanahan --- light/ltface.c | 201 ++++++++++++++++++++++++++----------------------- 1 file changed, 106 insertions(+), 95 deletions(-) diff --git a/light/ltface.c b/light/ltface.c index 239a8638..7b2fc9ea 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -24,60 +24,70 @@ static const vec3_t bsp_origin = { 0, 0, 0 }; /* ======================================================================== */ -// Solve three simultaneous equations -// mtx is modified by the function... +typedef struct { + vec3_t data[3]; /* permuted 3x3 matrix */ + int row[3]; /* row permutations */ + int col[3]; /* column permutations */ +} pmatrix3_t; + +/* + * To do arbitrary transformation of texture coordinates to world + * coordinates requires solving for three simultaneous equations. We + * set up the LU decomposed form of the transform matrix here. + */ #define ZERO_EPSILON (0.001) static qboolean -LU_Decompose(vec3_t mtx[3], int r[3], int c[2]) +PMatrix3_LU_Decompose(pmatrix3_t *matrix) { - int i, j, k; // loop variables + int i, j, k, tmp; vec_t max; int max_r, max_c; - // Do gauss elimination + /* Do gauss elimination */ for (i = 0; i < 3; ++i) { max = 0; max_r = max_c = i; for (j = i; j < 3; ++j) { for (k = i; k < 3; ++k) { - if (fabs(mtx[j][k]) > max) { - max = fabs(mtx[j][k]); + if (fabs(matrix->data[j][k]) > max) { + max = fabs(matrix->data[j][k]); max_r = j; max_c = k; } } } - // Check for parallel planes + /* Check for parallel planes */ if (max < ZERO_EPSILON) return false; - // Swap rows/columns if necessary + /* Swap rows/columns if necessary */ if (max_r != i) { for (j = 0; j < 3; ++j) { - max = mtx[i][j]; - mtx[i][j] = mtx[max_r][j]; - mtx[max_r][j] = max; + max = matrix->data[i][j]; + matrix->data[i][j] = matrix->data[max_r][j]; + matrix->data[max_r][j] = max; } - k = r[i]; - r[i] = r[max_r]; - r[max_r] = k; + tmp = matrix->row[i]; + matrix->row[i] = matrix->row[max_r]; + matrix->row[max_r] = tmp; } if (max_c != i) { for (j = 0; j < 3; ++j) { - max = mtx[j][i]; - mtx[j][i] = mtx[j][max_c]; - mtx[j][max_c] = max; + max = matrix->data[j][i]; + matrix->data[j][i] = matrix->data[j][max_c]; + matrix->data[j][max_c] = max; } - k = c[i]; - c[i] = c[max_c]; - c[max_c] = k; + tmp = matrix->col[i]; + matrix->col[i] = matrix->col[max_c]; + matrix->col[max_c] = tmp; } - // Do pivot + + /* Do pivot */ for (j = i + 1; j < 3; ++j) { - mtx[j][i] /= mtx[i][i]; + matrix->data[j][i] /= matrix->data[i][i]; for (k = i + 1; k < 3; ++k) - mtx[j][k] -= mtx[j][i] * mtx[i][k]; + matrix->data[j][k] -= matrix->data[j][i] * matrix->data[i][k]; } } @@ -85,21 +95,24 @@ LU_Decompose(vec3_t mtx[3], int r[3], int c[2]) } static void -solve3(const vec3_t mtx[3], const int r[3], const int c[3], - const vec3_t rhs, vec3_t soln) +Solve3(const pmatrix3_t *matrix, const vec3_t rhs, vec3_t out) { - vec3_t y; + /* Use local short names just for readability (should optimize away) */ + const vec3_t *data = matrix->data; + const int *r = matrix->row; + const int *c = matrix->col; + vec3_t tmp; - // forward-substitution - y[0] = rhs[r[0]]; - y[1] = rhs[r[1]] - mtx[1][0] * y[0]; - y[2] = rhs[r[2]] - mtx[2][0] * y[0] - mtx[2][1] * y[1]; + /* forward-substitution */ + tmp[0] = rhs[r[0]]; + tmp[1] = rhs[r[1]] - data[1][0] * tmp[0]; + tmp[2] = rhs[r[2]] - data[2][0] * tmp[0] - data[2][1] * tmp[1]; - // back-substitution - soln[c[2]] = y[2] / mtx[2][2]; - soln[c[1]] = (y[1] - mtx[1][2] * soln[c[2]]) / mtx[1][1]; - soln[c[0]] = (y[0] - mtx[0][1] * soln[c[1]] - mtx[0][2] * soln[c[2]]) - / mtx[0][0]; + /* back-substitution */ + out[c[2]] = tmp[2] / data[2][2]; + out[c[1]] = (tmp[1] - data[1][2] * out[c[2]]) / data[1][1]; + out[c[0]] = (tmp[0] - data[0][1] * out[c[1]] - data[0][2] * out[c[2]]) + / data[0][0]; } /* @@ -121,85 +134,82 @@ solve3(const vec3_t mtx[3], const int r[3], const int c[3], * ============================================================================ */ +typedef struct { + pmatrix3_t transform; + const texinfo_t *texinfo; + vec_t facedist; +} texorg_t; + /* Allow space for 4x4 oversampling */ #define SINGLEMAP (18*18*4*4) typedef struct { const modelinfo_t *modelinfo; - const dface_t *face; - vec_t facedist; - vec3_t facenormal; - - /* FIXME - Comment this properly */ - vec_t worldtotex[2][4]; // Copy of face->texinfo->vecs - vec3_t LU[3]; - int row_p[3]; - int col_p[3]; vec_t exactmid[2]; - int texmins[2], texsize[2]; - int lightstyles[256]; + vec_t facedist; + vec3_t facenormal; int numsurfpt; - int numlightstyles; - vec3_t surfpt[SINGLEMAP]; + + int numlightstyles; + int lightstyles[MAXLIGHTMAPS]; vec_t lightmaps[MAXLIGHTMAPS][SINGLEMAP]; vec3_t colormaps[MAXLIGHTMAPS][SINGLEMAP]; } lightinfo_t; /* * ================ - * CalcFaceVectors - * Fills in texorg, worldtotex. and textoworld + * CreateFaceTransform + * Fills in the transform matrix for converting tex coord <-> world coord * ================ */ static void -CalcFaceVectors(lightinfo_t *l) +CreateFaceTransform(const dface_t *face, pmatrix3_t *transform) { - texinfo_t *tex; - int i, j; + const dplane_t *plane; + const texinfo_t *tex; + int i; - /* convert from float to vec_t */ - tex = &texinfo[l->face->texinfo]; - for (i = 0; i < 2; i++) - for (j = 0; j < 4; j++) - l->worldtotex[i][j] = tex->vecs[i][j]; - - /* Prepare LU and row, column permutations */ - for (i = 0; i < 3; ++i) - l->row_p[i] = l->col_p[i] = i; - VectorCopy(l->worldtotex[0], l->LU[0]); - VectorCopy(l->worldtotex[1], l->LU[1]); - VectorCopy(l->facenormal, l->LU[2]); + /* Prepare the transform matrix and init row/column permutations */ + plane = &dplanes[face->planenum]; + tex = &texinfo[face->texinfo]; + for (i = 0; i < 3; i++) { + transform->data[0][i] = tex->vecs[0][i]; + transform->data[1][i] = tex->vecs[1][i]; + transform->data[2][i] = plane->normal[i]; + transform->row[i] = transform->col[i] = i; + } + if (face->side) + VectorSubtract(vec3_origin, transform->data[2], transform->data[2]); /* Decompose the matrix. If we can't, texture axes are invalid. */ - if (!LU_Decompose(l->LU, l->row_p, l->col_p)) { - const vec_t *p = dvertexes[dedges[l->face->firstedge].v[0]].point; - + if (!PMatrix3_LU_Decompose(transform)) { + const vec_t *p = dvertexes[dedges[face->firstedge].v[0]].point; Error("Bad texture axes on face:\n" " face point at (%5.3f, %5.3f, %5.3f)\n", p[0], p[1], p[2]); } } static void -tex_to_world(vec_t s, vec_t t, const lightinfo_t *l, vec3_t world) +TexCoordToWorld(vec_t s, vec_t t, const texorg_t *texorg, vec3_t world) { vec3_t rhs; - rhs[0] = s - l->worldtotex[0][3]; - rhs[1] = t - l->worldtotex[1][3]; - rhs[2] = l->facedist + 1; // one "unit" in front of surface + rhs[0] = s - texorg->texinfo->vecs[0][3]; + rhs[1] = t - texorg->texinfo->vecs[1][3]; + rhs[2] = texorg->facedist + 1; /* one "unit" in front of surface */ - solve3(l->LU, l->row_p, l->col_p, rhs, world); + Solve3(&texorg->transform, rhs, world); } /* * Functions to aid in calculation of polygon centroid */ static void -tri_centroid(const dvertex_t *v0, const dvertex_t *v1, const dvertex_t *v2, +TriCentroid(const dvertex_t *v0, const dvertex_t *v1, const dvertex_t *v2, vec3_t out) { int i; @@ -209,7 +219,7 @@ tri_centroid(const dvertex_t *v0, const dvertex_t *v1, const dvertex_t *v2, } static vec_t -tri_area(const dvertex_t *v0, const dvertex_t *v1, const dvertex_t *v2) +TriArea(const dvertex_t *v0, const dvertex_t *v1, const dvertex_t *v2) { int i; vec3_t edge0, edge1, cross; @@ -224,7 +234,7 @@ tri_area(const dvertex_t *v0, const dvertex_t *v1, const dvertex_t *v2) } static void -face_centroid(const dface_t *f, vec3_t out) +FaceCentroid(const dface_t *f, vec3_t out) { int i, e; dvertex_t *v0, *v1, *v2; @@ -250,10 +260,10 @@ face_centroid(const dface_t *f, vec3_t out) v2 = dvertexes + dedges[-e].v[0]; } - area = tri_area(v0, v1, v2); + area = TriArea(v0, v1, v2); poly_area += area; - tri_centroid(v0, v1, v2, centroid); + TriCentroid(v0, v1, v2, centroid); VectorMA(poly_centroid, area, centroid, poly_centroid); } @@ -263,27 +273,24 @@ face_centroid(const dface_t *f, vec3_t out) /* * ================ * CalcFaceExtents - * Fills in s->texmins[], s->texsize[] and sets exactmid[] + * Fills in l->texmins[], l->texsize[] and sets exactmid[] * ================ */ static void -CalcFaceExtents(lightinfo_t *l, const vec3_t offset) +CalcFaceExtents(const dface_t *face, const vec3_t offset, lightinfo_t *l) { - const dface_t *s; vec_t mins[2], maxs[2], val; vec3_t centroid; int i, j, e; dvertex_t *v; texinfo_t *tex; - s = l->face; - mins[0] = mins[1] = 999999; maxs[0] = maxs[1] = -99999; - tex = &texinfo[s->texinfo]; + tex = &texinfo[face->texinfo]; - for (i = 0; i < s->numedges; i++) { - e = dsurfedges[s->firstedge + i]; + for (i = 0; i < face->numedges; i++) { + e = dsurfedges[face->firstedge + i]; if (e >= 0) v = dvertexes + dedges[e].v[0]; else @@ -302,7 +309,7 @@ CalcFaceExtents(lightinfo_t *l, const vec3_t offset) } } - face_centroid(s, centroid); + FaceCentroid(face, centroid); for (i = 0; i < 2; i++) { l->exactmid[i] = @@ -330,7 +337,7 @@ CalcFaceExtents(lightinfo_t *l, const vec3_t offset) * ================= */ static void -CalcPoints(const dmodel_t *model, lightinfo_t *l) +CalcPoints(const dmodel_t *model, const texorg_t *texorg, lightinfo_t *l) { int i; int s, t; @@ -348,7 +355,7 @@ CalcPoints(const dmodel_t *model, lightinfo_t *l) mids = l->exactmid[0]; midt = l->exactmid[1]; - tex_to_world(mids, midt, l, facemid); + TexCoordToWorld(mids, midt, texorg, facemid); h = (l->texsize[1] + 1) * oversample; w = (l->texsize[0] + 1) * oversample; @@ -364,7 +371,7 @@ CalcPoints(const dmodel_t *model, lightinfo_t *l) /* if a line can be traced from surf to facemid, point is good */ for (i = 0; i < 6; i++) { - tex_to_world(us, ut, l, surf); + TexCoordToWorld(us, ut, texorg, surf); if (TestLineModel(model, facemid, surf)) break; /* got it */ @@ -837,6 +844,8 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) int width; vec3_t point; + texorg_t texorg; + face = dfaces + surfnum; /* some surfaces don't need lightmaps */ @@ -849,7 +858,6 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) memset(&l, 0, sizeof(l)); l.modelinfo = modelinfo; - l.face = face; /* rotate plane */ VectorCopy(dplanes[face->planenum].normal, l.facenormal); @@ -863,9 +871,12 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) l.facedist = -l.facedist; } - CalcFaceVectors(&l); - CalcFaceExtents(&l, modelinfo->offset); - CalcPoints(modelinfo->model, &l); + CreateFaceTransform(face, &texorg.transform); + texorg.texinfo = &texinfo[face->texinfo]; + texorg.facedist = l.facedist; + + CalcFaceExtents(face, modelinfo->offset, &l); + CalcPoints(modelinfo->model, &texorg, &l); lightmapwidth = l.texsize[0] + 1; From 63393eee8e8e520b90182d6aa22558da828cfc79 Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sat, 9 Mar 2013 15:58:26 +1030 Subject: [PATCH 02/14] light: define a plane_t structure and use for lightinfo_t Signed-off-by: Kevin Shanahan --- light/ltface.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/light/ltface.c b/light/ltface.c index 7b2fc9ea..3c9edde3 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -137,9 +137,14 @@ Solve3(const pmatrix3_t *matrix, const vec3_t rhs, vec3_t out) typedef struct { pmatrix3_t transform; const texinfo_t *texinfo; - vec_t facedist; + vec_t planedist; } texorg_t; +typedef struct { + vec3_t normal; + vec_t dist; +} plane_t; + /* Allow space for 4x4 oversampling */ #define SINGLEMAP (18*18*4*4) @@ -149,8 +154,7 @@ typedef struct { vec_t exactmid[2]; int texmins[2], texsize[2]; - vec_t facedist; - vec3_t facenormal; + plane_t plane; int numsurfpt; vec3_t surfpt[SINGLEMAP]; @@ -200,7 +204,7 @@ TexCoordToWorld(vec_t s, vec_t t, const texorg_t *texorg, vec3_t world) rhs[0] = s - texorg->texinfo->vecs[0][3]; rhs[1] = t - texorg->texinfo->vecs[1][3]; - rhs[2] = texorg->facedist + 1; /* one "unit" in front of surface */ + rhs[2] = texorg->planedist + 1; /* one "unit" in front of surface */ Solve3(&texorg->transform, rhs, world); } @@ -464,7 +468,7 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) vec_t newlightmap[SINGLEMAP]; vec3_t newcolormap[SINGLEMAP]; - dist = DotProduct(light->origin, l->facenormal) - l->facedist; + dist = DotProduct(light->origin, l->plane.normal) - l->plane.dist; /* don't bother with lights behind the surface */ if (dist < 0) @@ -515,7 +519,7 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) /* Check spotlight cone */ VectorScale(ray, 1.0 / dist, ray); - angle = DotProduct(ray, l->facenormal); + angle = DotProduct(ray, l->plane.normal); spotscale = 1; if (light->spotlight) { vec_t falloff = DotProduct(light->spotvec, ray); @@ -580,7 +584,7 @@ SkyLightFace(lightinfo_t *l, const vec3_t colors) vec3_t *colormap; /* Don't bother if surface facing away from sun */ - if (DotProduct(sunvec, l->facenormal) < -ANGLE_EPSILON) + if (DotProduct(sunvec, l->plane.normal) < -ANGLE_EPSILON) return; /* if sunlight is set, use a style 0 light map */ @@ -599,7 +603,7 @@ SkyLightFace(lightinfo_t *l, const vec3_t colors) /* Check each point... */ VectorCopy(sunvec, incoming); VectorNormalize(incoming); - angle = DotProduct(incoming, l->facenormal); + angle = DotProduct(incoming, l->plane.normal); angle = (1.0 - scalecos) + scalecos * angle; #if 0 @@ -610,7 +614,7 @@ SkyLightFace(lightinfo_t *l, const vec3_t colors) vec3_t sun_vectors[5]; // Try to hit parallel surfaces? - oldangle = DotProduct(incoming, l->facenormal); + oldangle = DotProduct(incoming, l->plane.normal); if (oldangle < ANGLE_EPSILON) { printf("real small angle! (%f)\n", oldangle); angle = (1.0 - scalecos) + scalecos * ANGLE_EPSILON; @@ -826,6 +830,7 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) { const entity_t *entity; dface_t *face; + plane_t *plane; lightinfo_t l; int s, t; int i, j, k, c; @@ -842,7 +847,7 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) vec3_t colors = { 0, 0, 0 }; int width; - vec3_t point; + vec3_t planepoint; texorg_t texorg; @@ -859,21 +864,23 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) memset(&l, 0, sizeof(l)); l.modelinfo = modelinfo; - /* rotate plane */ - VectorCopy(dplanes[face->planenum].normal, l.facenormal); - l.facedist = dplanes[face->planenum].dist; - VectorScale(l.facenormal, l.facedist, point); - VectorAdd(point, modelinfo->offset, point); - l.facedist = DotProduct(point, l.facenormal); + /* Offset the plane according to the model offset */ + plane = &l.plane; + VectorCopy(dplanes[face->planenum].normal, plane->normal); + plane->dist = dplanes[face->planenum].dist; + VectorScale(plane->normal, plane->dist, planepoint); + VectorAdd(planepoint, modelinfo->offset, planepoint); + plane->dist = DotProduct(plane->normal, planepoint); + /* flip if needed */ if (face->side) { - VectorSubtract(vec3_origin, l.facenormal, l.facenormal); - l.facedist = -l.facedist; + VectorSubtract(vec3_origin, plane->normal, plane->normal); + plane->dist = -plane->dist; } CreateFaceTransform(face, &texorg.transform); texorg.texinfo = &texinfo[face->texinfo]; - texorg.facedist = l.facedist; + texorg.planedist = plane->dist; CalcFaceExtents(face, modelinfo->offset, &l); CalcPoints(modelinfo->model, &texorg, &l); From ea440c6da0c193fd9901c6e378b07180c9d4accd Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sat, 9 Mar 2013 16:36:57 +1030 Subject: [PATCH 03/14] light: factor out WorldToTexCoord as a serparte function Signed-off-by: Kevin Shanahan --- light/ltface.c | 59 +++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/light/ltface.c b/light/ltface.c index 3c9edde3..e497e29a 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -209,6 +209,18 @@ TexCoordToWorld(vec_t s, vec_t t, const texorg_t *texorg, vec3_t world) Solve3(&texorg->transform, rhs, world); } +static void +WorldToTexCoord(const vec3_t world, const texinfo_t *tex, vec_t coord[2]) +{ + int i; + + for (i = 0; i < 2; i++) + coord[i] = + world[0] * tex->vecs[i][0] + + world[1] * tex->vecs[i][1] + + world[2] * tex->vecs[i][2] + tex->vecs[i][3]; +} + /* * Functions to aid in calculation of polygon centroid */ @@ -283,49 +295,38 @@ FaceCentroid(const dface_t *f, vec3_t out) static void CalcFaceExtents(const dface_t *face, const vec3_t offset, lightinfo_t *l) { - vec_t mins[2], maxs[2], val; - vec3_t centroid; - int i, j, e; - dvertex_t *v; - texinfo_t *tex; + vec_t mins[2], maxs[2], texcoord[2]; + vec3_t world, centroid; + int i, j, edge, vert; + const dvertex_t *dvertex; + const texinfo_t *tex; - mins[0] = mins[1] = 999999; - maxs[0] = maxs[1] = -99999; + mins[0] = mins[1] = VECT_MAX; + maxs[0] = maxs[1] = -VECT_MAX; tex = &texinfo[face->texinfo]; for (i = 0; i < face->numedges; i++) { - e = dsurfedges[face->firstedge + i]; - if (e >= 0) - v = dvertexes + dedges[e].v[0]; - else - v = dvertexes + dedges[-e].v[1]; + edge = dsurfedges[face->firstedge + i]; + vert = (edge >= 0) ? dedges[edge].v[0] : dedges[-edge].v[1]; + dvertex = &dvertexes[vert]; + VectorAdd(dvertex->point, offset, world); + WorldToTexCoord(world, tex, texcoord); for (j = 0; j < 2; j++) { - // This is world->tex with world offset... - val = (v->point[0] + offset[0]) * tex->vecs[j][0] - + (v->point[1] + offset[1]) * tex->vecs[j][1] - + (v->point[2] + offset[2]) * tex->vecs[j][2] - + tex->vecs[j][3]; - if (val < mins[j]) - mins[j] = val; - if (val > maxs[j]) - maxs[j] = val; + if (texcoord[j] < mins[j]) + mins[j] = texcoord[j]; + if (texcoord[j] > maxs[j]) + maxs[j] = texcoord[j]; } } FaceCentroid(face, centroid); + VectorAdd(centroid, offset, world); + WorldToTexCoord(world, tex, l->exactmid); for (i = 0; i < 2; i++) { - l->exactmid[i] = - (centroid[0] + offset[0]) * tex->vecs[i][0] - + (centroid[1] + offset[1]) * tex->vecs[i][1] - + (centroid[2] + offset[2]) * tex->vecs[i][2] - + tex->vecs[i][3]; - - mins[i] = floor(mins[i] / 16); maxs[i] = ceil(maxs[i] / 16); - l->texmins[i] = mins[i]; l->texsize[i] = maxs[i] - mins[i]; if (l->texsize[i] > 17) From a919ad08bcea053a864245727cc4ca6907416a0b Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sat, 9 Mar 2013 17:34:31 +1030 Subject: [PATCH 04/14] light: split lightinfo_t into surface information and lightmap data A lot of churn for a small gain, but now the surface information is separate from the lightmap data. And we can pass the surface information around via a const pointer. Signed-off-by: Kevin Shanahan --- light/ltface.c | 359 +++++++++++++++++++++++-------------------------- 1 file changed, 166 insertions(+), 193 deletions(-) diff --git a/light/ltface.c b/light/ltface.c index e497e29a..167b76ed 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -150,19 +150,22 @@ typedef struct { typedef struct { const modelinfo_t *modelinfo; + plane_t plane; + /* FIXME - to be removed... */ vec_t exactmid[2]; int texmins[2], texsize[2]; - plane_t plane; - int numsurfpt; - vec3_t surfpt[SINGLEMAP]; + int numpoints; + vec3_t points[SINGLEMAP]; +} lightsurf_t; - int numlightstyles; - int lightstyles[MAXLIGHTMAPS]; +typedef struct { + int numstyles; + int styles[MAXLIGHTMAPS]; vec_t lightmaps[MAXLIGHTMAPS][SINGLEMAP]; vec3_t colormaps[MAXLIGHTMAPS][SINGLEMAP]; -} lightinfo_t; +} lightdata_t; /* * ================ @@ -289,11 +292,11 @@ FaceCentroid(const dface_t *f, vec3_t out) /* * ================ * CalcFaceExtents - * Fills in l->texmins[], l->texsize[] and sets exactmid[] + * Fills in surf->texmins[], surf->texsize[] and sets surf->exactmid[] * ================ */ static void -CalcFaceExtents(const dface_t *face, const vec3_t offset, lightinfo_t *l) +CalcFaceExtents(const dface_t *face, const vec3_t offset, lightsurf_t *surf) { vec_t mins[2], maxs[2], texcoord[2]; vec3_t world, centroid; @@ -323,13 +326,13 @@ CalcFaceExtents(const dface_t *face, const vec3_t offset, lightinfo_t *l) FaceCentroid(face, centroid); VectorAdd(centroid, offset, world); - WorldToTexCoord(world, tex, l->exactmid); + WorldToTexCoord(world, tex, surf->exactmid); for (i = 0; i < 2; i++) { mins[i] = floor(mins[i] / 16); maxs[i] = ceil(maxs[i] / 16); - l->texmins[i] = mins[i]; - l->texsize[i] = maxs[i] - mins[i]; - if (l->texsize[i] > 17) + surf->texmins[i] = mins[i]; + surf->texsize[i] = maxs[i] - mins[i]; + if (surf->texsize[i] > 17) Error("Bad surface extents"); } } @@ -342,13 +345,13 @@ CalcFaceExtents(const dface_t *face, const vec3_t offset, lightinfo_t *l) * ================= */ static void -CalcPoints(const dmodel_t *model, const texorg_t *texorg, lightinfo_t *l) +CalcPoints(const dmodel_t *model, const texorg_t *texorg, lightsurf_t *surf) { int i; int s, t; int w, h, step; vec_t starts, startt, us, ut; - vec_t *surf; + vec_t *point; vec_t mids, midt; vec3_t facemid, move; @@ -356,29 +359,29 @@ CalcPoints(const dmodel_t *model, const texorg_t *texorg, lightinfo_t *l) /* the points are biased towards the center of the surface */ /* to help avoid edge cases just inside walls */ - surf = l->surfpt[0]; - mids = l->exactmid[0]; - midt = l->exactmid[1]; + point = surf->points[0]; + mids = surf->exactmid[0]; + midt = surf->exactmid[1]; TexCoordToWorld(mids, midt, texorg, facemid); - h = (l->texsize[1] + 1) * oversample; - w = (l->texsize[0] + 1) * oversample; - starts = (l->texmins[0] - 0.5 + (0.5 / oversample)) * 16; - startt = (l->texmins[1] - 0.5 + (0.5 / oversample)) * 16; + h = (surf->texsize[1] + 1) * oversample; + w = (surf->texsize[0] + 1) * oversample; + starts = (surf->texmins[0] - 0.5 + (0.5 / oversample)) * 16; + startt = (surf->texmins[1] - 0.5 + (0.5 / oversample)) * 16; step = 16 / oversample; - l->numsurfpt = w * h; + surf->numpoints = w * h; for (t = 0; t < h; t++) { - for (s = 0; s < w; s++, surf += 3) { + for (s = 0; s < w; s++, point += 3) { us = starts + s * step; ut = startt + t * step; /* if a line can be traced from surf to facemid, point is good */ for (i = 0; i < 6; i++) { - TexCoordToWorld(us, ut, texorg, surf); + TexCoordToWorld(us, ut, texorg, point); - if (TestLineModel(model, facemid, surf)) + if (TestLineModel(model, facemid, point)) break; /* got it */ if (i & 1) { // i is odd if (us > mids) { @@ -403,9 +406,9 @@ CalcPoints(const dmodel_t *model, const texorg_t *texorg, lightinfo_t *l) } /* move surf 8 pixels towards the center */ - VectorSubtract(facemid, surf, move); + VectorSubtract(facemid, point, move); VectorNormalize(move); - VectorMA(surf, 8, move, surf); + VectorMA(point, 8, move, point); } } } @@ -422,27 +425,27 @@ static int c_culldistplane; static int c_proper; static vec_t -GetLightValue(const entity_t *light, vec_t distance) +GetLightValue(const entity_t *entity, vec_t distance) { vec_t value; - if (light->formula == LF_INFINITE || light->formula == LF_LOCALMIN) - return light->light; + if (entity->formula == LF_INFINITE || entity->formula == LF_LOCALMIN) + return entity->light; - value = scaledist * light->atten * distance; - switch (light->formula) { + value = scaledist * entity->atten * distance; + switch (entity->formula) { case LF_INVERSE: - return light->light / (value / LF_SCALE); + return entity->light / (value / LF_SCALE); case LF_INVERSE2A: value += LF_SCALE; /* Fall through */ case LF_INVERSE2: - return light->light / ((value * value) / (LF_SCALE * LF_SCALE)); + return entity->light / ((value * value) / (LF_SCALE * LF_SCALE)); case LF_LINEAR: - if (light->light > 0) - return (light->light - value > 0) ? light->light - value : 0; + if (entity->light > 0) + return (entity->light - value > 0) ? entity->light - value : 0; else - return (light->light + value < 0) ? light->light + value : 0; + return (entity->light + value < 0) ? entity->light + value : 0; default: Error("Internal error: unknown light formula"); } @@ -455,12 +458,15 @@ GetLightValue(const entity_t *light, vec_t distance) * ================ */ static void -SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) +SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, + const vec3_t colors, lightdata_t *lightdata) { + const modelinfo_t *modelinfo = lightsurf->modelinfo; + const plane_t *plane = &lightsurf->plane; vec_t dist; vec_t angle, spotscale; vec_t add; - const vec_t *surf; + const vec_t *surfpoint; qboolean newmap, hit; int mapnum; int c; @@ -469,14 +475,14 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) vec_t newlightmap[SINGLEMAP]; vec3_t newcolormap[SINGLEMAP]; - dist = DotProduct(light->origin, l->plane.normal) - l->plane.dist; + dist = DotProduct(entity->origin, plane->normal) - plane->dist; /* don't bother with lights behind the surface */ if (dist < 0) return; /* don't bother with light too far away */ - if (dist > light->fadedist) { + if (dist > entity->fadedist) { c_culldistplane++; return; } @@ -485,8 +491,8 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) * Find the lightmap with matching style */ newmap = true; - for (mapnum = 0; mapnum < l->numlightstyles; mapnum++) { - if (l->lightstyles[mapnum] == light->style) { + for (mapnum = 0; mapnum < lightdata->numstyles; mapnum++) { + if (lightdata->styles[mapnum] == entity->style) { newmap = false; break; } @@ -497,8 +503,8 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) lightsamp = newlightmap; colorsamp = newcolormap; } else { - lightsamp = l->lightmaps[mapnum]; - colorsamp = l->colormaps[mapnum]; + lightsamp = lightdata->lightmaps[mapnum]; + colorsamp = lightdata->colormaps[mapnum]; } /* @@ -507,42 +513,42 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) hit = false; c_proper++; - surf = l->surfpt[0]; - for (c = 0; c < l->numsurfpt; c++, surf += 3) { + surfpoint = lightsurf->points[0]; + for (c = 0; c < lightsurf->numpoints; c++, surfpoint += 3) { vec3_t ray; - VectorSubtract(light->origin, surf, ray); + VectorSubtract(entity->origin, surfpoint, ray); dist = VectorLength(ray); /* Quick distance check first */ - if (dist > light->fadedist) + if (dist > entity->fadedist) continue; /* Check spotlight cone */ VectorScale(ray, 1.0 / dist, ray); - angle = DotProduct(ray, l->plane.normal); + angle = DotProduct(ray, plane->normal); spotscale = 1; - if (light->spotlight) { - vec_t falloff = DotProduct(light->spotvec, ray); - if (falloff > light->spotfalloff) + if (entity->spotlight) { + vec_t falloff = DotProduct(entity->spotvec, ray); + if (falloff > entity->spotfalloff) continue; - if (falloff > light->spotfalloff2) { + if (falloff > entity->spotfalloff2) { /* Interpolate between the two spotlight falloffs */ - spotscale = falloff - light->spotfalloff2; - spotscale /= light->spotfalloff - light->spotfalloff2; + spotscale = falloff - entity->spotfalloff2; + spotscale /= entity->spotfalloff - entity->spotfalloff2; spotscale = 1.0 - spotscale; } } /* Test for line of sight */ - if (!TestLine(light->origin, surf)) + if (!TestLine(entity->origin, surfpoint)) continue; - if (l->modelinfo->shadowself) - if (!TestLineModel(l->modelinfo->model, light->origin, surf)) + if (modelinfo->shadowself) + if (!TestLineModel(modelinfo->model, entity->origin, surfpoint)) continue; angle = (1.0 - scalecos) + scalecos * angle; - add = GetLightValue(light, dist) * angle * spotscale; + add = GetLightValue(entity, dist) * angle * spotscale; lightsamp[c] += add; if (colored) VectorMA(colorsamp[c], add / 255.0f, colors, colorsamp[c]); @@ -553,19 +559,19 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) } if (newmap && hit) { - if (l->numlightstyles == MAXLIGHTMAPS) { + if (lightdata->numstyles == MAXLIGHTMAPS) { logprint("WARNING: Too many light styles on a face\n" " lightmap point near (%s)\n" - " light->origin (%s)\n", - VecStr(l->surfpt[0]), VecStr(light->origin)); + " entity->origin (%s)\n", + VecStr(lightsurf->points[0]), VecStr(entity->origin)); return; } /* the style has some real data now */ - mapnum = l->numlightstyles++; - l->lightstyles[mapnum] = light->style; - memcpy(l->lightmaps[mapnum], newlightmap, sizeof(newlightmap)); - memcpy(l->colormaps[mapnum], newcolormap, sizeof(newcolormap)); + mapnum = lightdata->numstyles++; + lightdata->styles[mapnum] = entity->style; + memcpy(lightdata->lightmaps[mapnum], newlightmap, sizeof(newlightmap)); + memcpy(lightdata->colormaps[mapnum], newcolormap, sizeof(newcolormap)); } } @@ -575,94 +581,54 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors) * ============= */ static void -SkyLightFace(lightinfo_t *l, const vec3_t colors) +SkyLightFace(const lightsurf_t *lightsurf, const vec3_t colors, + lightdata_t *lightdata) { + const modelinfo_t *modelinfo = lightsurf->modelinfo; + const plane_t *plane = &lightsurf->plane; + const vec_t *surfpoint; int i, mapnum; - vec_t *surf; vec3_t incoming; vec_t angle; vec_t *lightmap; vec3_t *colormap; /* Don't bother if surface facing away from sun */ - if (DotProduct(sunvec, l->plane.normal) < -ANGLE_EPSILON) + if (DotProduct(sunvec, plane->normal) < -ANGLE_EPSILON) return; /* if sunlight is set, use a style 0 light map */ - for (mapnum = 0; mapnum < l->numlightstyles; mapnum++) - if (l->lightstyles[mapnum] == 0) + for (mapnum = 0; mapnum < lightdata->numstyles; mapnum++) + if (lightdata->styles[mapnum] == 0) break; - if (mapnum == l->numlightstyles) { - if (l->numlightstyles == MAXLIGHTMAPS) + if (mapnum == lightdata->numstyles) { + if (lightdata->numstyles == MAXLIGHTMAPS) return; /* oh well, too many lightmaps... */ - l->lightstyles[mapnum] = 0; - l->numlightstyles++; + lightdata->styles[mapnum] = 0; + lightdata->numstyles++; } - lightmap = l->lightmaps[mapnum]; - colormap = l->colormaps[mapnum]; + lightmap = lightdata->lightmaps[mapnum]; + colormap = lightdata->colormaps[mapnum]; /* Check each point... */ VectorCopy(sunvec, incoming); VectorNormalize(incoming); - angle = DotProduct(incoming, l->plane.normal); + angle = DotProduct(incoming, plane->normal); angle = (1.0 - scalecos) + scalecos * angle; -#if 0 - /* Experimental - lighting of faces parallel to sunlight*/ - { - int a, b, c, j; - vec_t oldangle, offset; - vec3_t sun_vectors[5]; - - // Try to hit parallel surfaces? - oldangle = DotProduct(incoming, l->plane.normal); - if (oldangle < ANGLE_EPSILON) { - printf("real small angle! (%f)\n", oldangle); - angle = (1.0 - scalecos) + scalecos * ANGLE_EPSILON; - } - - a = fabs(sunvec[0]) > fabs(sunvec[1]) ? - (fabs(sunvec[0]) > fabs(sunvec[2]) ? 0 : 2) : - (fabs(sunvec[1]) > fabs(sunvec[2]) ? 1 : 2); - b = (a + 1) % 3; - c = (a + 2) % 3; - - offset = sunvec[a] * ANGLE_EPSILON * 2.0; // approx... - for (j = 0; j < 5; ++j) - VectorCopy(sunvec, sun_vectors[j]); - sun_vectors[1][b] += offset; - sun_vectors[2][b] -= offset; - sun_vectors[3][c] += offset; - sun_vectors[4][c] -= offset; - - surf = l->surfpt[0]; - for (i = 0; i < l->numsurfpt; i++, surf += 3) { - for (j = 0; j < 1 || (oldangle < ANGLE_EPSILON && j < 5); ++j) { - if (TestSky(surf, sun_vectors[j])) { - lightmap[i] += angle * sunlight; - if (colored) - VectorMA(colormap[i], angle * sunlight / 255.0f, colors, - colormap[i]); - break; - } - } - } - } -#else - surf = l->surfpt[0]; - for (i = 0; i < l->numsurfpt; i++, surf += 3) { + surfpoint = lightsurf->points[0]; + for (i = 0; i < lightsurf->numpoints; i++, surfpoint += 3) { vec3_t skypoint; - if (!TestSky(surf, sunvec, skypoint)) + if (!TestSky(surfpoint, sunvec, skypoint)) continue; - if (l->modelinfo->shadowself) - if (!TestLineModel(l->modelinfo->model, surf, skypoint)) + if (modelinfo->shadowself) + if (!TestLineModel(modelinfo->model, surfpoint, skypoint)) continue; lightmap[i] += angle * sunlight; if (colored) VectorMA(colormap[i], angle * sunlight / 255.0f, colors, colormap[i]); } -#endif } /* @@ -671,8 +637,10 @@ SkyLightFace(lightinfo_t *l, const vec3_t colors) * ============ */ static void -FixMinlight(lightinfo_t *l, const int minlight, const vec3_t mincolor) +FixMinlight(const lightsurf_t *lightsurf, const int minlight, + const vec3_t mincolor, lightdata_t *lightdata) { + const modelinfo_t *modelinfo = lightsurf->modelinfo; int i, j, k; vec_t *lightmap; vec3_t *colormap; @@ -681,28 +649,28 @@ FixMinlight(lightinfo_t *l, const int minlight, const vec3_t mincolor) /* Find a style 0 lightmap */ lightmap = NULL; colormap = NULL; - for (i = 0; i < l->numlightstyles; i++) { - if (l->lightstyles[i] == 0) { - lightmap = l->lightmaps[i]; - colormap = l->colormaps[i]; + for (i = 0; i < lightdata->numstyles; i++) { + if (lightdata->styles[i] == 0) { + lightmap = lightdata->lightmaps[i]; + colormap = lightdata->colormaps[i]; break; } } if (!lightmap) { - if (l->numlightstyles == MAXLIGHTMAPS) + if (lightdata->numstyles == MAXLIGHTMAPS) return; /* oh well... FIXME - should we warn? */ - lightmap = l->lightmaps[l->numlightstyles]; - for (i = 0; i < l->numsurfpt; i++) + lightmap = lightdata->lightmaps[lightdata->numstyles]; + for (i = 0; i < lightsurf->numpoints; i++) lightmap[i] = minlight; if (colored) { - colormap = l->colormaps[l->numlightstyles]; - for (i = 0; i < l->numsurfpt; i++) + colormap = lightdata->colormaps[lightdata->numstyles]; + for (i = 0; i < lightsurf->numpoints; i++) VectorScale(mincolor, minlight / 255.0f, colormap[i]); } - l->lightstyles[l->numlightstyles++] = 0; + lightdata->styles[lightdata->numstyles++] = 0; } else { - for (i = 0; i < l->numsurfpt; i++) { + for (i = 0; i < lightsurf->numpoints; i++) { if (lightmap[i] < minlight) lightmap[i] = minlight; if (colored) { @@ -723,29 +691,29 @@ FixMinlight(lightinfo_t *l, const int minlight, const vec3_t mincolor) /* Find the lightmap with correct style */ lightmap = NULL; colormap = NULL; - for (j = 0; j < l->numlightstyles; j++) { - if (l->lightstyles[j] == 0) { - lightmap = l->lightmaps[j]; - colormap = l->colormaps[j]; + for (j = 0; j < lightdata->numstyles; j++) { + if (lightdata->styles[j] == 0) { + lightmap = lightdata->lightmaps[j]; + colormap = lightdata->colormaps[j]; break; } } if (!lightmap) { - if (l->numlightstyles == MAXLIGHTMAPS) + if (lightdata->numstyles == MAXLIGHTMAPS) continue; /* oh well... FIXME - should we warn? */ - lightmap = l->lightmaps[l->numlightstyles]; - colormap = l->colormaps[l->numlightstyles]; - l->numlightstyles++; + lightmap = lightdata->lightmaps[lightdata->numstyles]; + colormap = lightdata->colormaps[lightdata->numstyles]; + lightdata->numstyles++; } - for (j = 0; j < l->numsurfpt; j++) { + for (j = 0; j < lightsurf->numpoints; j++) { qboolean trace = false; if (lightmap[j] < entity->light) { - trace = TestLine(entity->origin, l->surfpt[j]); + trace = TestLine(entity->origin, lightsurf->points[j]); if (!trace) continue; - if (l->modelinfo->shadowself) { - trace = TestLineModel(l->modelinfo->model, entity->origin, l->surfpt[j]); + if (modelinfo->shadowself) { + trace = TestLineModel(modelinfo->model, entity->origin, lightsurf->points[j]); if (!trace) continue; } @@ -756,12 +724,13 @@ FixMinlight(lightinfo_t *l, const int minlight, const vec3_t mincolor) for (k = 0; k < 3; k++) { if (colormap[j][k] < mincolor[k]) { if (!trace) { - trace = TestLine(entity->origin, l->surfpt[j]); + trace = TestLine(entity->origin, lightsurf->points[j]); if (!trace) break; - if (l->modelinfo->shadowself) { - trace = TestLineModel(l->modelinfo->model, - entity->origin, l->surfpt[j]); + if (modelinfo->shadowself) { + trace = TestLineModel(modelinfo->model, + entity->origin, + lightsurf->points[j]); if (!trace) break; } @@ -832,7 +801,8 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) const entity_t *entity; dface_t *face; plane_t *plane; - lightinfo_t l; + lightdata_t lightdata; + lightsurf_t lightsurf; int s, t; int i, j, k, c; @@ -862,11 +832,12 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) if (texinfo[face->texinfo].flags & TEX_SPECIAL) return; /* non-lit texture */ - memset(&l, 0, sizeof(l)); - l.modelinfo = modelinfo; + memset(&lightdata, 0, sizeof(lightdata)); + memset(&lightsurf, 0, sizeof(lightsurf)); + lightsurf.modelinfo = modelinfo; /* Offset the plane according to the model offset */ - plane = &l.plane; + plane = &lightsurf.plane; VectorCopy(dplanes[face->planenum].normal, plane->normal); plane->dist = dplanes[face->planenum].dist; VectorScale(plane->normal, plane->dist, planepoint); @@ -883,17 +854,17 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) texorg.texinfo = &texinfo[face->texinfo]; texorg.planedist = plane->dist; - CalcFaceExtents(face, modelinfo->offset, &l); - CalcPoints(modelinfo->model, &texorg, &l); + CalcFaceExtents(face, modelinfo->offset, &lightsurf); + CalcPoints(modelinfo->model, &texorg, &lightsurf); - lightmapwidth = l.texsize[0] + 1; + lightmapwidth = lightsurf.texsize[0] + 1; - size = lightmapwidth * (l.texsize[1] + 1); + size = lightmapwidth * (lightsurf.texsize[1] + 1); if (size > SINGLEMAP) Error("Bad lightmap size"); for (i = 0; i < MAXLIGHTMAPS; i++) - l.lightstyles[i] = 255; + lightdata.styles[i] = 255; /* Under normal circumstances, the lighting procedure is: * - cast all light entities @@ -908,7 +879,7 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) * - cast _negative_ sky light (if any) */ - l.numlightstyles = 0; + lightdata.numstyles = 0; if (nominlimit) { /* cast only positive lights */ for (i = 0, entity = entities; i < num_entities; i++, entity++) { @@ -917,19 +888,19 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) if (colored) { if (entity->light) { PositiveColors(entity->light, colors, entity->lightcolor); - SingleLightFace(entity, &l, colors); + SingleLightFace(entity, &lightsurf, colors, &lightdata); } } else if (entity->light > 0) { - SingleLightFace(entity, &l, colors); + SingleLightFace(entity, &lightsurf, colors, &lightdata); } } /* cast positive sky light */ if (sunlight) { if (colored) { PositiveColors(sunlight, sunlight_color, colors); - SkyLightFace(&l, colors); + SkyLightFace(&lightsurf, colors, &lightdata); } else if (sunlight > 0) { - SkyLightFace(&l, colors); + SkyLightFace(&lightsurf, colors, &lightdata); } } } else { @@ -938,18 +909,20 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) if (entity->formula == LF_LOCALMIN) continue; if (entity->light) - SingleLightFace(entity, &l, entity->lightcolor); + SingleLightFace(entity, &lightsurf, entity->lightcolor, + &lightdata); } /* cast sky light */ if (sunlight) - SkyLightFace(&l, sunlight_color); + SkyLightFace(&lightsurf, sunlight_color, &lightdata); } /* Minimum lighting - Use the greater of global or model minlight. */ if (modelinfo->minlight > worldminlight) - FixMinlight(&l, modelinfo->minlight, modelinfo->mincolor); + FixMinlight(&lightsurf, modelinfo->minlight, modelinfo->mincolor, + &lightdata); else - FixMinlight(&l, worldminlight, minlight_color); + FixMinlight(&lightsurf, worldminlight, minlight_color, &lightdata); if (nominlimit) { /* cast only negative lights */ @@ -959,32 +932,32 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) if (colored) { if (entity->light) { NegativeColors(entity->light, colors, entity->lightcolor); - SingleLightFace(entity, &l, colors); + SingleLightFace(entity, &lightsurf, colors, &lightdata); } } else if (entity->light < 0) { - SingleLightFace(entity, &l, colors); + SingleLightFace(entity, &lightsurf, colors, &lightdata); } } /* cast negative sky light */ if (sunlight) { if (colored) { NegativeColors(sunlight, colors, sunlight_color); - SkyLightFace(&l, colors); + SkyLightFace(&lightsurf, colors, &lightdata); } else if (sunlight < 0) { - SkyLightFace(&l, colors); + SkyLightFace(&lightsurf, colors, &lightdata); } } /* Fix any negative values */ - for (i = 0; i < l.numlightstyles; i++) { - for (j = 0; j < l.numsurfpt; j++) { - if (l.lightmaps[i][j] < 0) { - l.lightmaps[i][j] = 0; + for (i = 0; i < lightdata.numstyles; i++) { + for (j = 0; j < lightsurf.numpoints; j++) { + if (lightdata.lightmaps[i][j] < 0) { + lightdata.lightmaps[i][j] = 0; } if (colored) { for (k = 0; k < 3; k++) { - if (l.colormaps[i][j][k] < 0) { - l.colormaps[i][j][k] = 0; + if (lightdata.colormaps[i][j][k] < 0) { + lightdata.colormaps[i][j][k] = 0; } } } @@ -992,32 +965,32 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) } } - if (!l.numlightstyles) + if (!lightdata.numstyles) return; /* no light hitting it */ /* save out the values */ for (i = 0; i < MAXLIGHTMAPS; i++) - face->styles[i] = l.lightstyles[i]; + face->styles[i] = lightdata.styles[i]; - lightmapsize = size * l.numlightstyles; + lightmapsize = size * lightdata.numstyles; GetFileSpace(&out, &lit_out, lightmapsize); face->lightofs = out - filebase; /* extra filtering */ - width = (l.texsize[0] + 1) * oversample; + width = (lightsurf.texsize[0] + 1) * oversample; - for (i = 0; i < l.numlightstyles; i++) { - if (l.lightstyles[i] == 0xff) + for (i = 0; i < lightdata.numstyles; i++) { + if (lightdata.styles[i] == 0xff) Error("Wrote empty lightmap"); - lightmap = l.lightmaps[i]; - colormap = l.colormaps[i]; + lightmap = lightdata.lightmaps[i]; + colormap = lightdata.colormaps[i]; c = 0; - for (t = 0; t <= l.texsize[1]; t++) { - for (s = 0; s <= l.texsize[0]; s++, c++) { + for (t = 0; t <= lightsurf.texsize[1]; t++) { + for (s = 0; s <= lightsurf.texsize[0]; s++, c++) { if (oversample > 1) { total = 0; VectorCopy(vec3_origin, colors); From 5dce6ccc303750796b2d09611d17310430c5ee2c Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sat, 9 Mar 2013 19:04:44 +1030 Subject: [PATCH 05/14] light: factor out init of lightsurf and lightdata Signed-off-by: Kevin Shanahan --- light/ltface.c | 89 ++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/light/ltface.c b/light/ltface.c index 167b76ed..949b945d 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -414,6 +414,49 @@ CalcPoints(const dmodel_t *model, const texorg_t *texorg, lightsurf_t *surf) } } +static void +Lightsurf_Init(const modelinfo_t *modelinfo, const dface_t *face, + lightsurf_t *lightsurf) +{ + plane_t *plane; + vec3_t planepoint; + texorg_t texorg; + + memset(lightsurf, 0, sizeof(*lightsurf)); + lightsurf->modelinfo = modelinfo; + + /* Set up the plane, including model offset */ + plane = &lightsurf->plane; + VectorCopy(dplanes[face->planenum].normal, plane->normal); + plane->dist = dplanes[face->planenum].dist; + VectorScale(plane->normal, plane->dist, planepoint); + VectorAdd(planepoint, modelinfo->offset, planepoint); + plane->dist = DotProduct(plane->normal, planepoint); + if (face->side) { + VectorSubtract(vec3_origin, plane->normal, plane->normal); + plane->dist = -plane->dist; + } + + /* Set up the texorg for coordinate transformation */ + CreateFaceTransform(face, &texorg.transform); + texorg.texinfo = &texinfo[face->texinfo]; + texorg.planedist = plane->dist; + + /* Set up the surface points */ + CalcFaceExtents(face, modelinfo->offset, lightsurf); + CalcPoints(modelinfo->model, &texorg, lightsurf); +} + +static void +Lightdata_Init(lightdata_t *lightdata) +{ + int i; + + memset(lightdata, 0, sizeof(*lightdata)); + for (i = 0; i < MAXLIGHTMAPS; i++) + lightdata->styles[i] = 255; +} + /* * ============================================================================ @@ -800,7 +843,6 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) { const entity_t *entity; dface_t *face; - plane_t *plane; lightdata_t lightdata; lightsurf_t lightsurf; int s, t; @@ -809,8 +851,6 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) vec_t max; vec_t total; int size; - int lightmapwidth; - int lightmapsize; byte *out; byte *lit_out = NULL; vec_t *lightmap; @@ -818,9 +858,6 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) vec3_t colors = { 0, 0, 0 }; int width; - vec3_t planepoint; - - texorg_t texorg; face = dfaces + surfnum; @@ -832,39 +869,8 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) if (texinfo[face->texinfo].flags & TEX_SPECIAL) return; /* non-lit texture */ - memset(&lightdata, 0, sizeof(lightdata)); - memset(&lightsurf, 0, sizeof(lightsurf)); - lightsurf.modelinfo = modelinfo; - - /* Offset the plane according to the model offset */ - plane = &lightsurf.plane; - VectorCopy(dplanes[face->planenum].normal, plane->normal); - plane->dist = dplanes[face->planenum].dist; - VectorScale(plane->normal, plane->dist, planepoint); - VectorAdd(planepoint, modelinfo->offset, planepoint); - plane->dist = DotProduct(plane->normal, planepoint); - - /* flip if needed */ - if (face->side) { - VectorSubtract(vec3_origin, plane->normal, plane->normal); - plane->dist = -plane->dist; - } - - CreateFaceTransform(face, &texorg.transform); - texorg.texinfo = &texinfo[face->texinfo]; - texorg.planedist = plane->dist; - - CalcFaceExtents(face, modelinfo->offset, &lightsurf); - CalcPoints(modelinfo->model, &texorg, &lightsurf); - - lightmapwidth = lightsurf.texsize[0] + 1; - - size = lightmapwidth * (lightsurf.texsize[1] + 1); - if (size > SINGLEMAP) - Error("Bad lightmap size"); - - for (i = 0; i < MAXLIGHTMAPS; i++) - lightdata.styles[i] = 255; + Lightsurf_Init(modelinfo, face, &lightsurf); + Lightdata_Init(&lightdata); /* Under normal circumstances, the lighting procedure is: * - cast all light entities @@ -879,7 +885,6 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) * - cast _negative_ sky light (if any) */ - lightdata.numstyles = 0; if (nominlimit) { /* cast only positive lights */ for (i = 0, entity = entities; i < num_entities; i++, entity++) { @@ -973,8 +978,8 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) for (i = 0; i < MAXLIGHTMAPS; i++) face->styles[i] = lightdata.styles[i]; - lightmapsize = size * lightdata.numstyles; - GetFileSpace(&out, &lit_out, lightmapsize); + size = (lightsurf.texsize[0] + 1) * (lightsurf.texsize[1] + 1); + GetFileSpace(&out, &lit_out, size * lightdata.numstyles); face->lightofs = out - filebase; From 3749cfa734a3aefc140f1efc1987dbd384901b3d Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sat, 9 Mar 2013 19:14:33 +1030 Subject: [PATCH 06/14] light: pass the dface pointer into lightface Signed-off-by: Kevin Shanahan --- include/light/light.h | 4 +--- light/light.c | 2 +- light/ltface.c | 8 ++------ 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/include/light/light.h b/include/light/light.h index c2cdeba0..900a9a69 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -49,9 +49,7 @@ typedef struct { /* tracelist is a null terminated array of BSP models to use for LOS tests */ extern const dmodel_t *const *tracelist; -void LightFace(int surfnum, const modelinfo_t *modelinfo); -void LightLeaf(dleaf_t * leaf); - +void LightFace(dface_t *face, const modelinfo_t *modelinfo); void MakeTnodes(void); extern float scaledist; diff --git a/light/light.c b/light/light.c index 4d6ce306..b344dfe4 100644 --- a/light/light.c +++ b/light/light.c @@ -95,7 +95,7 @@ LightThread(void *junk) if (i == nummodels) Error("%s: no model has face %d", __func__, facenum); - LightFace(facenum, &modelinfo[i]); + LightFace(dfaces + facenum, &modelinfo[i]); } return NULL; diff --git a/light/ltface.c b/light/ltface.c index 949b945d..07e55383 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -839,10 +839,9 @@ NegativeColors(int light, vec3_t dest, const vec3_t src) * ============ */ void -LightFace(int surfnum, const modelinfo_t *modelinfo) +LightFace(dface_t *face, const modelinfo_t *modelinfo) { const entity_t *entity; - dface_t *face; lightdata_t lightdata; lightsurf_t lightsurf; int s, t; @@ -859,15 +858,12 @@ LightFace(int surfnum, const modelinfo_t *modelinfo) int width; - face = dfaces + surfnum; - /* some surfaces don't need lightmaps */ face->lightofs = -1; for (j = 0; j < MAXLIGHTMAPS; j++) face->styles[j] = 255; - if (texinfo[face->texinfo].flags & TEX_SPECIAL) - return; /* non-lit texture */ + return; Lightsurf_Init(modelinfo, face, &lightsurf); Lightdata_Init(&lightdata); From eb92d5eac1ed35a13114bd72d970e1fdfa36aa78 Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sat, 9 Mar 2013 19:18:36 +1030 Subject: [PATCH 07/14] light: remove a couple of unneeded function declarations from header Signed-off-by: Kevin Shanahan --- include/light/light.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/light/light.h b/include/light/light.h index 900a9a69..f9d7bb87 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -71,9 +71,6 @@ void GetFileSpace(byte **lightdata, byte **colordata, int size); extern byte *filebase; extern byte *lit_filebase; -void TransformSample(vec3_t in, vec3_t out); -void RotateSample(vec3_t in, vec3_t out); - extern int oversample; extern qboolean compress_ents; extern qboolean facecounter; From f7e76f16b601ef81b6267af8a30ed38a43a041b9 Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sun, 10 Mar 2013 09:37:33 +1030 Subject: [PATCH 08/14] light: factor out writing light data from LightFace Signed-off-by: Kevin Shanahan --- light/ltface.c | 198 +++++++++++++++++++++++-------------------------- 1 file changed, 93 insertions(+), 105 deletions(-) diff --git a/light/ltface.c b/light/ltface.c index 07e55383..b2d50afe 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -833,6 +833,84 @@ NegativeColors(int light, vec3_t dest, const vec3_t src) } } +static void +WriteLightdata(dface_t *face, const lightsurf_t *lightsurf, + const lightdata_t *lightdata) +{ + int size, style, width, s, t, i, j, k; + const vec_t *lightmap; + const vec3_t *colormap; + vec_t light; + vec3_t color; + byte *out, *lit; + + if (!lightdata->numstyles) + return; + + size = (lightsurf->texsize[0] + 1) * (lightsurf->texsize[1] + 1); + GetFileSpace(&out, &lit, size * lightdata->numstyles); + + face->lightofs = out - filebase; + for (style = 0; style < MAXLIGHTMAPS; style++) + face->styles[style] = lightdata->styles[style]; + + width = (lightsurf->texsize[0] + 1) * oversample; + for (style = 0; style < lightdata->numstyles; style++) { + if (lightdata->styles[style] == 255) + Error("Wrote empty lightmap"); + + lightmap = lightdata->lightmaps[style]; + colormap = lightdata->colormaps[style]; + + i = 0; + for (t = 0; t <= lightsurf->texsize[1]; t++) { + for (s = 0; s <= lightsurf->texsize[0]; s++, i++) { + if (oversample == 1) { + light = lightmap[i]; + if (colored) + VectorCopy(colormap[i], color); + } else { + light = 0; + VectorCopy(vec3_origin, color); + for (j = 0; j < oversample; j++) { + for (k = 0; k < oversample; k++) { + int sample = (t * oversample + j) * width; + sample += s * oversample + k; + light += lightmap[sample]; + if (colored) + VectorAdd(color, colormap[sample], color); + } + } + light /= oversample * oversample; + VectorScale(color, 1.0 / oversample / oversample, color); + } + + light *= rangescale; + if (colored) { + vec_t max = 0; + VectorScale(color, rangescale, color); + for (j = 0; j < 3; j++) + if (color[j] > max) + max = color[j]; + if (max > 255) + VectorScale(color, 255.0f / max, color); + } + if (light > 255) + light = 255; + else if (light < 0) + light = 0; + + if (colored) { + *lit++ = color[0]; + *lit++ = color[1]; + *lit++ = color[2]; + } + *out++ = light; + } + } + } +} + /* * ============ * LightFace @@ -841,22 +919,11 @@ NegativeColors(int light, vec3_t dest, const vec3_t src) void LightFace(dface_t *face, const modelinfo_t *modelinfo) { + int i, j, k; + vec3_t color; const entity_t *entity; lightdata_t lightdata; lightsurf_t lightsurf; - int s, t; - int i, j, k, c; - - vec_t max; - vec_t total; - int size; - byte *out; - byte *lit_out = NULL; - vec_t *lightmap; - vec3_t *colormap; - vec3_t colors = { 0, 0, 0 }; - - int width; /* some surfaces don't need lightmaps */ face->lightofs = -1; @@ -888,20 +955,20 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) continue; if (colored) { if (entity->light) { - PositiveColors(entity->light, colors, entity->lightcolor); - SingleLightFace(entity, &lightsurf, colors, &lightdata); + PositiveColors(entity->light, color, entity->lightcolor); + SingleLightFace(entity, &lightsurf, color, &lightdata); } } else if (entity->light > 0) { - SingleLightFace(entity, &lightsurf, colors, &lightdata); + SingleLightFace(entity, &lightsurf, color, &lightdata); } } /* cast positive sky light */ if (sunlight) { if (colored) { - PositiveColors(sunlight, sunlight_color, colors); - SkyLightFace(&lightsurf, colors, &lightdata); + PositiveColors(sunlight, sunlight_color, color); + SkyLightFace(&lightsurf, color, &lightdata); } else if (sunlight > 0) { - SkyLightFace(&lightsurf, colors, &lightdata); + SkyLightFace(&lightsurf, color, &lightdata); } } } else { @@ -932,20 +999,20 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) continue; if (colored) { if (entity->light) { - NegativeColors(entity->light, colors, entity->lightcolor); - SingleLightFace(entity, &lightsurf, colors, &lightdata); + NegativeColors(entity->light, color, entity->lightcolor); + SingleLightFace(entity, &lightsurf, color, &lightdata); } } else if (entity->light < 0) { - SingleLightFace(entity, &lightsurf, colors, &lightdata); + SingleLightFace(entity, &lightsurf, color, &lightdata); } } /* cast negative sky light */ if (sunlight) { if (colored) { - NegativeColors(sunlight, colors, sunlight_color); - SkyLightFace(&lightsurf, colors, &lightdata); + NegativeColors(sunlight, color, sunlight_color); + SkyLightFace(&lightsurf, color, &lightdata); } else if (sunlight < 0) { - SkyLightFace(&lightsurf, colors, &lightdata); + SkyLightFace(&lightsurf, color, &lightdata); } } @@ -966,84 +1033,5 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) } } - if (!lightdata.numstyles) - return; /* no light hitting it */ - - /* save out the values */ - - for (i = 0; i < MAXLIGHTMAPS; i++) - face->styles[i] = lightdata.styles[i]; - - size = (lightsurf.texsize[0] + 1) * (lightsurf.texsize[1] + 1); - GetFileSpace(&out, &lit_out, size * lightdata.numstyles); - - face->lightofs = out - filebase; - - /* extra filtering */ - width = (lightsurf.texsize[0] + 1) * oversample; - - for (i = 0; i < lightdata.numstyles; i++) { - if (lightdata.styles[i] == 0xff) - Error("Wrote empty lightmap"); - - lightmap = lightdata.lightmaps[i]; - colormap = lightdata.colormaps[i]; - c = 0; - - for (t = 0; t <= lightsurf.texsize[1]; t++) { - for (s = 0; s <= lightsurf.texsize[0]; s++, c++) { - if (oversample > 1) { - total = 0; - VectorCopy(vec3_origin, colors); - for (j = 0; j < oversample; j++) { - for (k = 0; k < oversample; k++) { - int sample = (t * oversample + j) * width; - sample += s * oversample + k; - total += lightmap[sample]; - if (colored) - VectorAdd(colors, colormap[sample], colors); - } - } - total /= oversample * oversample; - VectorScale(colors, 1.0 / oversample / oversample, colors); - } else { - total = lightmap[c]; - if (colored) - VectorCopy(colormap[c], colors); - } - - total *= rangescale; /* scale before clamping */ - if (colored) { - /* Scale back intensity, instead of capping individual - * colors - */ - VectorScale(colors, rangescale, colors); - max = 0.0; - for (j = 0; j < 3; j++) - if (colors[j] > max) { - max = colors[j]; - } else if (colors[j] < 0.0f) { - Error("color %i < 0", j); - } - if (max > 255.0f) - VectorScale(colors, 255.0f / max, colors); - } - - if (total > 255.0f) - total = 255.0f; - else if (total < 0) { - //Error ("light < 0"); - total = 0; - } - - /* Write out the lightmap in the appropriate format */ - if (colored) { - *lit_out++ = colors[0]; - *lit_out++ = colors[1]; - *lit_out++ = colors[2]; - } - *out++ = total; - } - } - } + WriteLightdata(face, &lightsurf, &lightdata); } From f2395a3dd3ca516739fe954b9fc9c467a819673d Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sun, 10 Mar 2013 15:45:06 +1030 Subject: [PATCH 09/14] light: re-arrange lightdata_t structure into array of lightmap_t More messing with data structures. Now a single sample has a brightness and colour component and a lightmap structure captures all the non-surface lightmap data. The pointer arithmetic for iterating over the supersamples in WriteLightmaps is perhaps a little silly, but it works well enough. It might be smarter to generate the sample points in a different order instead. Maybe later. Signed-off-by: Kevin Shanahan --- light/ltface.c | 326 ++++++++++++++++++++++--------------------------- 1 file changed, 143 insertions(+), 183 deletions(-) diff --git a/light/ltface.c b/light/ltface.c index b2d50afe..5a081ab6 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -161,11 +161,14 @@ typedef struct { } lightsurf_t; typedef struct { - int numstyles; - int styles[MAXLIGHTMAPS]; - vec_t lightmaps[MAXLIGHTMAPS][SINGLEMAP]; - vec3_t colormaps[MAXLIGHTMAPS][SINGLEMAP]; -} lightdata_t; + vec_t light; + vec3_t color; +} lightsample_t; + +typedef struct { + int style; + lightsample_t samples[SINGLEMAP]; +} lightmap_t; /* * ================ @@ -448,13 +451,13 @@ Lightsurf_Init(const modelinfo_t *modelinfo, const dface_t *face, } static void -Lightdata_Init(lightdata_t *lightdata) +Lightmaps_Init(lightmap_t *lightmaps) { int i; - memset(lightdata, 0, sizeof(*lightdata)); + memset(lightmaps, 0, sizeof(lightmap_t) * MAXLIGHTMAPS); for (i = 0; i < MAXLIGHTMAPS; i++) - lightdata->styles[i] = 255; + lightmaps[i].style = 255; } @@ -464,9 +467,6 @@ Lightdata_Init(lightdata_t *lightdata) * ============================================================================ */ -static int c_culldistplane; -static int c_proper; - static vec_t GetLightValue(const entity_t *entity, vec_t distance) { @@ -502,21 +502,18 @@ GetLightValue(const entity_t *entity, vec_t distance) */ static void SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, - const vec3_t colors, lightdata_t *lightdata) + const vec3_t colors, lightmap_t *lightmaps) { const modelinfo_t *modelinfo = lightsurf->modelinfo; const plane_t *plane = &lightsurf->plane; vec_t dist; vec_t angle, spotscale; vec_t add; - const vec_t *surfpoint; qboolean newmap, hit; - int mapnum; - int c; - vec_t *lightsamp; - vec3_t *colorsamp; - vec_t newlightmap[SINGLEMAP]; - vec3_t newcolormap[SINGLEMAP]; + int i, mapnum; + const vec_t *surfpoint; + lightsample_t *sample; + lightmap_t newlightmap; dist = DotProduct(entity->origin, plane->normal) - plane->dist; @@ -525,39 +522,34 @@ SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, return; /* don't bother with light too far away */ - if (dist > entity->fadedist) { - c_culldistplane++; + if (dist > entity->fadedist) return; - } /* * Find the lightmap with matching style */ newmap = true; - for (mapnum = 0; mapnum < lightdata->numstyles; mapnum++) { - if (lightdata->styles[mapnum] == entity->style) { + for (mapnum = 0; mapnum < MAXLIGHTMAPS; mapnum++) { + if (lightmaps[mapnum].style == 255) + break; + if (lightmaps[mapnum].style == entity->style) { newmap = false; + sample = lightmaps[mapnum].samples; break; } } if (newmap) { - memset(newlightmap, 0, sizeof(newlightmap)); - memset(newcolormap, 0, sizeof(newcolormap)); - lightsamp = newlightmap; - colorsamp = newcolormap; - } else { - lightsamp = lightdata->lightmaps[mapnum]; - colorsamp = lightdata->colormaps[mapnum]; + memset(&newlightmap, 0, sizeof(newlightmap)); + newlightmap.style = entity->style; + sample = newlightmap.samples; } /* * Check it for real */ hit = false; - c_proper++; - surfpoint = lightsurf->points[0]; - for (c = 0; c < lightsurf->numpoints; c++, surfpoint += 3) { + for (i = 0; i < lightsurf->numpoints; i++, sample++, surfpoint += 3) { vec3_t ray; VectorSubtract(entity->origin, surfpoint, ray); @@ -592,17 +584,17 @@ SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, angle = (1.0 - scalecos) + scalecos * angle; add = GetLightValue(entity, dist) * angle * spotscale; - lightsamp[c] += add; + sample->light += add; if (colored) - VectorMA(colorsamp[c], add / 255.0f, colors, colorsamp[c]); + VectorMA(sample->color, add / 255.0f, colors, sample->color); /* Check if we really hit, ignore tiny lights */ - if (newmap && lightsamp[c] > 1) + if (newmap && sample->light >= 1) hit = true; } if (newmap && hit) { - if (lightdata->numstyles == MAXLIGHTMAPS) { + if (mapnum == MAXLIGHTMAPS) { logprint("WARNING: Too many light styles on a face\n" " lightmap point near (%s)\n" " entity->origin (%s)\n", @@ -610,11 +602,8 @@ SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, return; } - /* the style has some real data now */ - mapnum = lightdata->numstyles++; - lightdata->styles[mapnum] = entity->style; - memcpy(lightdata->lightmaps[mapnum], newlightmap, sizeof(newlightmap)); - memcpy(lightdata->colormaps[mapnum], newcolormap, sizeof(newcolormap)); + /* the new lightmap has some real data now */ + memcpy(&lightmaps[mapnum], &newlightmap, sizeof(newlightmap)); } } @@ -625,7 +614,7 @@ SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, */ static void SkyLightFace(const lightsurf_t *lightsurf, const vec3_t colors, - lightdata_t *lightdata) + lightmap_t *lightmaps) { const modelinfo_t *modelinfo = lightsurf->modelinfo; const plane_t *plane = &lightsurf->plane; @@ -633,44 +622,43 @@ SkyLightFace(const lightsurf_t *lightsurf, const vec3_t colors, int i, mapnum; vec3_t incoming; vec_t angle; - vec_t *lightmap; - vec3_t *colormap; + lightsample_t *sample; /* Don't bother if surface facing away from sun */ if (DotProduct(sunvec, plane->normal) < -ANGLE_EPSILON) return; /* if sunlight is set, use a style 0 light map */ - for (mapnum = 0; mapnum < lightdata->numstyles; mapnum++) - if (lightdata->styles[mapnum] == 0) + for (mapnum = 0; mapnum < MAXLIGHTMAPS; mapnum++) { + if (lightmaps[mapnum].style == 0) break; - if (mapnum == lightdata->numstyles) { - if (lightdata->numstyles == MAXLIGHTMAPS) - return; /* oh well, too many lightmaps... */ - lightdata->styles[mapnum] = 0; - lightdata->numstyles++; + if (lightmaps[mapnum].style == 255) { + lightmaps[mapnum].style = 0; + break; + } } - lightmap = lightdata->lightmaps[mapnum]; - colormap = lightdata->colormaps[mapnum]; + if (mapnum == MAXLIGHTMAPS) + return; /* oh well, too many lightmaps... */ - /* Check each point... */ VectorCopy(sunvec, incoming); VectorNormalize(incoming); angle = DotProduct(incoming, plane->normal); angle = (1.0 - scalecos) + scalecos * angle; + /* Check each point... */ + sample = lightmaps[mapnum].samples; surfpoint = lightsurf->points[0]; - for (i = 0; i < lightsurf->numpoints; i++, surfpoint += 3) { + for (i = 0; i < lightsurf->numpoints; i++, sample++, surfpoint += 3) { vec3_t skypoint; if (!TestSky(surfpoint, sunvec, skypoint)) continue; if (modelinfo->shadowself) if (!TestLineModel(modelinfo->model, surfpoint, skypoint)) continue; - lightmap[i] += angle * sunlight; + sample->light += angle * sunlight; if (colored) - VectorMA(colormap[i], angle * sunlight / 255.0f, colors, - colormap[i]); + VectorMA(sample->color, angle * sunlight / 255.0f, colors, + sample->color); } } @@ -681,47 +669,35 @@ SkyLightFace(const lightsurf_t *lightsurf, const vec3_t colors, */ static void FixMinlight(const lightsurf_t *lightsurf, const int minlight, - const vec3_t mincolor, lightdata_t *lightdata) + const vec3_t mincolor, lightmap_t *lightmaps) { const modelinfo_t *modelinfo = lightsurf->modelinfo; - int i, j, k; - vec_t *lightmap; - vec3_t *colormap; + int mapnum, i, j, k; + lightsample_t *sample; const entity_t *entity; + const vec_t *surfpoint; /* Find a style 0 lightmap */ - lightmap = NULL; - colormap = NULL; - for (i = 0; i < lightdata->numstyles; i++) { - if (lightdata->styles[i] == 0) { - lightmap = lightdata->lightmaps[i]; - colormap = lightdata->colormaps[i]; + for (mapnum = 0; mapnum < MAXLIGHTMAPS; mapnum++) { + if (lightmaps[mapnum].style == 0) + break; + if (lightmaps[mapnum].style == 255) { + lightmaps[mapnum].style = 0; break; } } + if (mapnum == MAXLIGHTMAPS) + return; /* oh well... FIXME - should we warn? */ - if (!lightmap) { - if (lightdata->numstyles == MAXLIGHTMAPS) - return; /* oh well... FIXME - should we warn? */ - lightmap = lightdata->lightmaps[lightdata->numstyles]; - for (i = 0; i < lightsurf->numpoints; i++) - lightmap[i] = minlight; + sample = lightmaps[mapnum].samples; + for (i = 0; i < lightsurf->numpoints; i++, sample++) { + if (sample->light < minlight) + sample->light = minlight; if (colored) { - colormap = lightdata->colormaps[lightdata->numstyles]; - for (i = 0; i < lightsurf->numpoints; i++) - VectorScale(mincolor, minlight / 255.0f, colormap[i]); - } - lightdata->styles[lightdata->numstyles++] = 0; - } else { - for (i = 0; i < lightsurf->numpoints; i++) { - if (lightmap[i] < minlight) - lightmap[i] = minlight; - if (colored) { - for (j = 0; j < 3; j++) { - vec_t lightval = minlight * mincolor[j] / 255.0f; - if (colormap[i][j] < lightval) - colormap[i][j] = lightval; - } + for (j = 0; j < 3; j++) { + vec_t lightval = minlight * mincolor[j] / 255.0f; + if (sample->color[j] < lightval) + sample->color[j] = lightval; } } } @@ -731,54 +707,37 @@ FixMinlight(const lightsurf_t *lightsurf, const int minlight, if (entity->formula != LF_LOCALMIN) continue; - /* Find the lightmap with correct style */ - lightmap = NULL; - colormap = NULL; - for (j = 0; j < lightdata->numstyles; j++) { - if (lightdata->styles[j] == 0) { - lightmap = lightdata->lightmaps[j]; - colormap = lightdata->colormaps[j]; - break; - } - } - if (!lightmap) { - if (lightdata->numstyles == MAXLIGHTMAPS) - continue; /* oh well... FIXME - should we warn? */ - lightmap = lightdata->lightmaps[lightdata->numstyles]; - colormap = lightdata->colormaps[lightdata->numstyles]; - lightdata->numstyles++; - } - - for (j = 0; j < lightsurf->numpoints; j++) { + sample = lightmaps[mapnum].samples; + surfpoint = lightsurf->points[0]; + for (j = 0; j < lightsurf->numpoints; j++, sample++, surfpoint += 3) { qboolean trace = false; - if (lightmap[j] < entity->light) { - trace = TestLine(entity->origin, lightsurf->points[j]); + if (sample->light < entity->light) { + trace = TestLine(entity->origin, surfpoint); if (!trace) continue; if (modelinfo->shadowself) { - trace = TestLineModel(modelinfo->model, entity->origin, lightsurf->points[j]); + trace = TestLineModel(modelinfo->model, entity->origin, surfpoint); if (!trace) continue; } - lightmap[j] = entity->light; + sample->light = entity->light; } if (!colored) continue; for (k = 0; k < 3; k++) { - if (colormap[j][k] < mincolor[k]) { + if (sample->color[k] < mincolor[k]) { if (!trace) { - trace = TestLine(entity->origin, lightsurf->points[j]); + trace = TestLine(entity->origin, surfpoint); if (!trace) break; if (modelinfo->shadowself) { trace = TestLineModel(modelinfo->model, - entity->origin, - lightsurf->points[j]); + entity->origin, surfpoint); if (!trace) break; } } - colormap[j][k] = mincolor[k]; + sample->color[k] = mincolor[k]; } } } @@ -834,64 +793,60 @@ NegativeColors(int light, vec3_t dest, const vec3_t src) } static void -WriteLightdata(dface_t *face, const lightsurf_t *lightsurf, - const lightdata_t *lightdata) +WriteLightmaps(dface_t *face, const lightsurf_t *lightsurf, + const lightmap_t *lightmaps) { - int size, style, width, s, t, i, j, k; - const vec_t *lightmap; - const vec3_t *colormap; + int numstyles, size, mapnum, width, s, t, i, j; + const lightsample_t *sample; vec_t light; vec3_t color; byte *out, *lit; - if (!lightdata->numstyles) + numstyles = 0; + for (mapnum = 0; mapnum < MAXLIGHTMAPS; mapnum++) { + face->styles[mapnum] = lightmaps[mapnum].style; + if (lightmaps[mapnum].style != 255) + numstyles++; + } + if (!numstyles) return; size = (lightsurf->texsize[0] + 1) * (lightsurf->texsize[1] + 1); - GetFileSpace(&out, &lit, size * lightdata->numstyles); - + GetFileSpace(&out, &lit, size * numstyles); face->lightofs = out - filebase; - for (style = 0; style < MAXLIGHTMAPS; style++) - face->styles[style] = lightdata->styles[style]; width = (lightsurf->texsize[0] + 1) * oversample; - for (style = 0; style < lightdata->numstyles; style++) { - if (lightdata->styles[style] == 255) - Error("Wrote empty lightmap"); + for (mapnum = 0; mapnum < MAXLIGHTMAPS; mapnum++) { + if (lightmaps[mapnum].style == 255) + break; - lightmap = lightdata->lightmaps[style]; - colormap = lightdata->colormaps[style]; - - i = 0; + sample = lightmaps[mapnum].samples; for (t = 0; t <= lightsurf->texsize[1]; t++) { - for (s = 0; s <= lightsurf->texsize[0]; s++, i++) { - if (oversample == 1) { - light = lightmap[i]; - if (colored) - VectorCopy(colormap[i], color); - } else { - light = 0; - VectorCopy(vec3_origin, color); - for (j = 0; j < oversample; j++) { - for (k = 0; k < oversample; k++) { - int sample = (t * oversample + j) * width; - sample += s * oversample + k; - light += lightmap[sample]; - if (colored) - VectorAdd(color, colormap[sample], color); - } - } - light /= oversample * oversample; - VectorScale(color, 1.0 / oversample / oversample, color); - } + for (s = 0; s <= lightsurf->texsize[0]; s++) { + /* Take the average of any oversampling */ + light = 0; + VectorCopy(vec3_origin, color); + for (i = 0; i < oversample; i++) { + for (j = 0; j < oversample; j++) { + light += sample->light; + if (colored) + VectorAdd(color, sample->color, color); + sample++; + } + sample += width - oversample; + } + light /= oversample * oversample; + VectorScale(color, 1.0 / oversample / oversample, color); + + /* Scale and clamp any out-of-range samples */ light *= rangescale; if (colored) { vec_t max = 0; VectorScale(color, rangescale, color); - for (j = 0; j < 3; j++) - if (color[j] > max) - max = color[j]; + for (i = 0; i < 3; i++) + if (color[i] > max) + max = color[i]; if (max > 255) VectorScale(color, 255.0f / max, color); } @@ -906,7 +861,9 @@ WriteLightdata(dface_t *face, const lightsurf_t *lightsurf, *lit++ = color[2]; } *out++ = light; + sample -= width * oversample - oversample; } + sample += width * oversample - width; } } } @@ -922,18 +879,19 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) int i, j, k; vec3_t color; const entity_t *entity; - lightdata_t lightdata; + lightsample_t *sample; lightsurf_t lightsurf; + lightmap_t lightmaps[MAXLIGHTMAPS]; /* some surfaces don't need lightmaps */ face->lightofs = -1; - for (j = 0; j < MAXLIGHTMAPS; j++) - face->styles[j] = 255; + for (i = 0; i < MAXLIGHTMAPS; i++) + face->styles[i] = 255; if (texinfo[face->texinfo].flags & TEX_SPECIAL) return; Lightsurf_Init(modelinfo, face, &lightsurf); - Lightdata_Init(&lightdata); + Lightmaps_Init(lightmaps); /* Under normal circumstances, the lighting procedure is: * - cast all light entities @@ -956,19 +914,19 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) if (colored) { if (entity->light) { PositiveColors(entity->light, color, entity->lightcolor); - SingleLightFace(entity, &lightsurf, color, &lightdata); + SingleLightFace(entity, &lightsurf, color, lightmaps); } } else if (entity->light > 0) { - SingleLightFace(entity, &lightsurf, color, &lightdata); + SingleLightFace(entity, &lightsurf, color, lightmaps); } } /* cast positive sky light */ if (sunlight) { if (colored) { PositiveColors(sunlight, sunlight_color, color); - SkyLightFace(&lightsurf, color, &lightdata); + SkyLightFace(&lightsurf, color, lightmaps); } else if (sunlight > 0) { - SkyLightFace(&lightsurf, color, &lightdata); + SkyLightFace(&lightsurf, color, lightmaps); } } } else { @@ -978,19 +936,19 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) continue; if (entity->light) SingleLightFace(entity, &lightsurf, entity->lightcolor, - &lightdata); + lightmaps); } /* cast sky light */ if (sunlight) - SkyLightFace(&lightsurf, sunlight_color, &lightdata); + SkyLightFace(&lightsurf, sunlight_color, lightmaps); } /* Minimum lighting - Use the greater of global or model minlight. */ if (modelinfo->minlight > worldminlight) FixMinlight(&lightsurf, modelinfo->minlight, modelinfo->mincolor, - &lightdata); + lightmaps); else - FixMinlight(&lightsurf, worldminlight, minlight_color, &lightdata); + FixMinlight(&lightsurf, worldminlight, minlight_color, lightmaps); if (nominlimit) { /* cast only negative lights */ @@ -1000,32 +958,34 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) if (colored) { if (entity->light) { NegativeColors(entity->light, color, entity->lightcolor); - SingleLightFace(entity, &lightsurf, color, &lightdata); + SingleLightFace(entity, &lightsurf, color, lightmaps); } } else if (entity->light < 0) { - SingleLightFace(entity, &lightsurf, color, &lightdata); + SingleLightFace(entity, &lightsurf, color, lightmaps); } } /* cast negative sky light */ if (sunlight) { if (colored) { NegativeColors(sunlight, color, sunlight_color); - SkyLightFace(&lightsurf, color, &lightdata); + SkyLightFace(&lightsurf, color, lightmaps); } else if (sunlight < 0) { - SkyLightFace(&lightsurf, color, &lightdata); + SkyLightFace(&lightsurf, color, lightmaps); } } /* Fix any negative values */ - for (i = 0; i < lightdata.numstyles; i++) { - for (j = 0; j < lightsurf.numpoints; j++) { - if (lightdata.lightmaps[i][j] < 0) { - lightdata.lightmaps[i][j] = 0; - } + for (i = 0; i < MAXLIGHTMAPS; i++) { + if (lightmaps[i].style == 255) + break; + sample = lightmaps[i].samples; + for (j = 0; j < lightsurf.numpoints; j++, sample++) { + if (sample->light < 0) + sample->light = 0; if (colored) { for (k = 0; k < 3; k++) { - if (lightdata.colormaps[i][j][k] < 0) { - lightdata.colormaps[i][j][k] = 0; + if (sample->color[k] < 0) { + sample->color[k] = 0; } } } @@ -1033,5 +993,5 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) } } - WriteLightdata(face, &lightsurf, &lightdata); + WriteLightmaps(face, &lightsurf, lightmaps); } From 46277eec41529d67446fa9d298db709dc7cc4a3b Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sun, 10 Mar 2013 16:52:17 +1030 Subject: [PATCH 10/14] light: fix -nominlimit option causing extra bright lighting This option has been broken for a while, because we only dealt with positive vs. negative colours and didn't properly handle the light intensity. All this messing around to try and correctly handle negative colors seems just stupid. I might have to remove support for that in future... is there really any good use for it? Signed-off-by: Kevin Shanahan --- light/ltface.c | 181 ++++++++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 92 deletions(-) diff --git a/light/ltface.c b/light/ltface.c index 5a081ab6..423ddaed 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -468,27 +468,27 @@ Lightmaps_Init(lightmap_t *lightmaps) */ static vec_t -GetLightValue(const entity_t *entity, vec_t distance) +GetLightValue(const lightsample_t *light, const entity_t *entity, vec_t dist) { vec_t value; if (entity->formula == LF_INFINITE || entity->formula == LF_LOCALMIN) - return entity->light; + return light->light; - value = scaledist * entity->atten * distance; + value = scaledist * entity->atten * dist; switch (entity->formula) { case LF_INVERSE: - return entity->light / (value / LF_SCALE); + return light->light / (value / LF_SCALE); case LF_INVERSE2A: value += LF_SCALE; /* Fall through */ case LF_INVERSE2: - return entity->light / ((value * value) / (LF_SCALE * LF_SCALE)); + return light->light / ((value * value) / (LF_SCALE * LF_SCALE)); case LF_LINEAR: - if (entity->light > 0) - return (entity->light - value > 0) ? entity->light - value : 0; + if (light->light > 0) + return (light->light - value > 0) ? light->light - value : 0; else - return (entity->light + value < 0) ? entity->light + value : 0; + return (light->light + value < 0) ? light->light + value : 0; default: Error("Internal error: unknown light formula"); } @@ -501,8 +501,8 @@ GetLightValue(const entity_t *entity, vec_t distance) * ================ */ static void -SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, - const vec3_t colors, lightmap_t *lightmaps) +SingleLightFace(const entity_t *entity, const lightsample_t *light, + const lightsurf_t *lightsurf, lightmap_t *lightmaps) { const modelinfo_t *modelinfo = lightsurf->modelinfo; const plane_t *plane = &lightsurf->plane; @@ -583,10 +583,10 @@ SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, continue; angle = (1.0 - scalecos) + scalecos * angle; - add = GetLightValue(entity, dist) * angle * spotscale; + add = GetLightValue(light, entity, dist) * angle * spotscale; sample->light += add; if (colored) - VectorMA(sample->color, add / 255.0f, colors, sample->color); + VectorMA(sample->color, add / 255.0f, light->color, sample->color); /* Check if we really hit, ignore tiny lights */ if (newmap && sample->light >= 1) @@ -613,7 +613,7 @@ SingleLightFace(const entity_t *entity, const lightsurf_t *lightsurf, * ============= */ static void -SkyLightFace(const lightsurf_t *lightsurf, const vec3_t colors, +SkyLightFace(const lightsample_t *light, const lightsurf_t *lightsurf, lightmap_t *lightmaps) { const modelinfo_t *modelinfo = lightsurf->modelinfo; @@ -655,9 +655,9 @@ SkyLightFace(const lightsurf_t *lightsurf, const vec3_t colors, if (modelinfo->shadowself) if (!TestLineModel(modelinfo->model, surfpoint, skypoint)) continue; - sample->light += angle * sunlight; + sample->light += angle * light->light; if (colored) - VectorMA(sample->color, angle * sunlight / 255.0f, colors, + VectorMA(sample->color, angle * light->light / 255.0f, light->color, sample->color); } } @@ -668,8 +668,8 @@ SkyLightFace(const lightsurf_t *lightsurf, const vec3_t colors, * ============ */ static void -FixMinlight(const lightsurf_t *lightsurf, const int minlight, - const vec3_t mincolor, lightmap_t *lightmaps) +FixMinlight(const lightsample_t *minlight, const lightsurf_t *lightsurf, + lightmap_t *lightmaps) { const modelinfo_t *modelinfo = lightsurf->modelinfo; int mapnum, i, j, k; @@ -691,11 +691,11 @@ FixMinlight(const lightsurf_t *lightsurf, const int minlight, sample = lightmaps[mapnum].samples; for (i = 0; i < lightsurf->numpoints; i++, sample++) { - if (sample->light < minlight) - sample->light = minlight; + if (sample->light < minlight->light) + sample->light = minlight->light; if (colored) { for (j = 0; j < 3; j++) { - vec_t lightval = minlight * mincolor[j] / 255.0f; + vec_t lightval = minlight->light * minlight->color[j] / 255.0f; if (sample->color[j] < lightval) sample->color[j] = lightval; } @@ -725,7 +725,7 @@ FixMinlight(const lightsurf_t *lightsurf, const int minlight, if (!colored) continue; for (k = 0; k < 3; k++) { - if (sample->color[k] < mincolor[k]) { + if (sample->color[k] < entity->lightcolor[k]) { if (!trace) { trace = TestLine(entity->origin, surfpoint); if (!trace) @@ -737,7 +737,7 @@ FixMinlight(const lightsurf_t *lightsurf, const int minlight, break; } } - sample->color[k] = mincolor[k]; + sample->color[k] = entity->lightcolor[k]; } } } @@ -746,50 +746,63 @@ FixMinlight(const lightsurf_t *lightsurf, const int minlight, /* - * light is the light intensity, needed to check if +ve or -ve. - * src and dest are the source and destination color vectors (vec3_t). - * dest becomes a copy of src where - * PositiveColors zeros negative light components. - * NegativeColors zeros positive light components. + * PositiveLight zeros negative light components. + * NegativeLight zeros positive light components. */ -static void -PositiveColors(int light, vec3_t dest, const vec3_t src) +static qboolean +PositiveLight(int light, const vec3_t color, lightsample_t *out) { int i; + qboolean positive = false; - if (light >= 0) { + if (light > 0) { + out->light = light; + positive = true; for (i = 0; i < 3; i++) - if (src[i] < 0) - dest[i] = 0; + if (color[i] > 0) + out->color[i] = color[i]; else - dest[i] = src[i]; - } else { + out->color[i] = 0; + } else if (light < 0) { + out->light = -light; for (i = 0; i < 3; i++) - if (src[i] > 0) - dest[i] = 0; - else - dest[i] = src[i]; + if (color[i] < 0) { + out->color[i] = -color[i]; + positive = true; + } else { + out->color[i] = 0; + } } + + return positive; } -static void -NegativeColors(int light, vec3_t dest, const vec3_t src) +static qboolean +NegativeLight(int light, const vec3_t color, lightsample_t *out) { int i; + qboolean negative = false; - if (light >= 0) { + if (light < 0) { + out->light = light; + negative = true; for (i = 0; i < 3; i++) - if (src[i] > 0) - dest[i] = 0; + if (color[i] > 0) + out->color[i] = color[i]; else - dest[i] = src[i]; - } else { + out->color[i] = 0; + } else if (light > 0) { + out->light = -light; for (i = 0; i < 3; i++) - if (src[i] < 0) - dest[i] = 0; - else - dest[i] = src[i]; + if (color[i] < 0) { + out->color[i] = -color[i]; + negative = true; + } else { + out->color[i] = 0; + } } + + return negative; } static void @@ -877,7 +890,7 @@ void LightFace(dface_t *face, const modelinfo_t *modelinfo) { int i, j, k; - vec3_t color; + lightsample_t light; const entity_t *entity; lightsample_t *sample; lightsurf_t lightsurf; @@ -911,68 +924,52 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) for (i = 0, entity = entities; i < num_entities; i++, entity++) { if (entity->formula == LF_LOCALMIN) continue; - if (colored) { - if (entity->light) { - PositiveColors(entity->light, color, entity->lightcolor); - SingleLightFace(entity, &lightsurf, color, lightmaps); - } - } else if (entity->light > 0) { - SingleLightFace(entity, &lightsurf, color, lightmaps); - } + if (PositiveLight(entity->light, entity->lightcolor, &light)) + SingleLightFace(entity, &light, &lightsurf, lightmaps); } /* cast positive sky light */ - if (sunlight) { - if (colored) { - PositiveColors(sunlight, sunlight_color, color); - SkyLightFace(&lightsurf, color, lightmaps); - } else if (sunlight > 0) { - SkyLightFace(&lightsurf, color, lightmaps); - } - } + if (PositiveLight(sunlight, sunlight_color, &light)) + SkyLightFace(&light, &lightsurf, lightmaps); } else { /* (!nominlimit) => cast all lights */ for (i = 0, entity = entities; i < num_entities; i++, entity++) { if (entity->formula == LF_LOCALMIN) continue; - if (entity->light) - SingleLightFace(entity, &lightsurf, entity->lightcolor, - lightmaps); + if (entity->light) { + light.light = entity->light; + VectorCopy(entity->lightcolor, light.color); + SingleLightFace(entity, &light, &lightsurf, lightmaps); + } } /* cast sky light */ - if (sunlight) - SkyLightFace(&lightsurf, sunlight_color, lightmaps); + if (sunlight) { + light.light = sunlight; + VectorCopy(sunlight_color, light.color); + SkyLightFace(&light, &lightsurf, lightmaps); + } } /* Minimum lighting - Use the greater of global or model minlight. */ - if (modelinfo->minlight > worldminlight) - FixMinlight(&lightsurf, modelinfo->minlight, modelinfo->mincolor, - lightmaps); - else - FixMinlight(&lightsurf, worldminlight, minlight_color, lightmaps); + if (modelinfo->minlight > worldminlight) { + light.light = modelinfo->minlight; + VectorCopy(modelinfo->mincolor, light.color); + } else { + light.light = worldminlight; + VectorCopy(minlight_color, light.color); + } + FixMinlight(&light, &lightsurf, lightmaps); if (nominlimit) { /* cast only negative lights */ for (i = 0, entity = entities; i < num_entities; i++, entity++) { if (entity->formula == LF_LOCALMIN) continue; - if (colored) { - if (entity->light) { - NegativeColors(entity->light, color, entity->lightcolor); - SingleLightFace(entity, &lightsurf, color, lightmaps); - } - } else if (entity->light < 0) { - SingleLightFace(entity, &lightsurf, color, lightmaps); - } + if (NegativeLight(entity->light, entity->lightcolor, &light)) + SingleLightFace(entity, &light, &lightsurf, lightmaps); } /* cast negative sky light */ - if (sunlight) { - if (colored) { - NegativeColors(sunlight, color, sunlight_color); - SkyLightFace(&lightsurf, color, lightmaps); - } else if (sunlight < 0) { - SkyLightFace(&lightsurf, color, lightmaps); - } - } + if (NegativeLight(sunlight, sunlight_color, &light)) + SkyLightFace(&light, &lightsurf, lightmaps); /* Fix any negative values */ for (i = 0; i < MAXLIGHTMAPS; i++) { From d57e7d50fd4ec60a4ac79a324fc061e787116d01 Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sun, 10 Mar 2013 17:17:42 +1030 Subject: [PATCH 11/14] light: use lightsample_t for modelinfo->minlight Signed-off-by: Kevin Shanahan --- include/light/light.h | 8 ++++++-- light/light.c | 17 +++++++++-------- light/ltface.c | 12 +++--------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/include/light/light.h b/include/light/light.h index f9d7bb87..22f03cb6 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -38,11 +38,15 @@ qboolean TestLine(const vec3_t start, const vec3_t stop); qboolean TestLineModel(const dmodel_t *model, const vec3_t start, const vec3_t stop); +typedef struct { + vec_t light; + vec3_t color; +} lightsample_t; + typedef struct { const dmodel_t *model; qboolean shadowself; - int minlight; - vec3_t mincolor; + lightsample_t minlight; vec3_t offset; } modelinfo_t; diff --git a/light/light.c b/light/light.c index b344dfe4..4236954b 100644 --- a/light/light.c +++ b/light/light.c @@ -109,6 +109,7 @@ FindModelInfo(void) char modelname[20]; const char *attribute; const dmodel_t **shadowmodels; + modelinfo_t *info; shadowmodels = malloc(sizeof(dmodel_t *) * (nummodels + 1)); memset(shadowmodels, 0, sizeof(dmodel_t *) * (nummodels + 1)); @@ -120,8 +121,8 @@ FindModelInfo(void) memset(modelinfo, 0, sizeof(*modelinfo) * nummodels); modelinfo[0].model = &dmodels[0]; - for (i = 1; i < nummodels; i++) { - modelinfo[i].model = &dmodels[i]; + for (i = 1, info = modelinfo + 1; i < nummodels; i++, info++) { + info->model = &dmodels[i]; /* Find the entity for the model */ snprintf(modelname, sizeof(modelname), "*%d", i); @@ -137,27 +138,27 @@ FindModelInfo(void) } else { shadow = atoi(ValueForKey(entity, "_shadowself")); if (shadow) - modelinfo[i].shadowself = true; + info->shadowself = true; } /* Set up the offset for rotate_* entities */ attribute = ValueForKey(entity, "classname"); if (!strncmp(attribute, "rotate_", 7)) - GetVectorForKey(entity, "origin", modelinfo[i].offset); + GetVectorForKey(entity, "origin", info->offset); /* Grab the bmodel minlight values, if any */ attribute = ValueForKey(entity, "_minlight"); if (attribute[0]) - modelinfo[i].minlight = atoi(attribute); - GetVectorForKey(entity, "_mincolor", modelinfo[i].mincolor); - if (!VectorCompare(modelinfo[i].mincolor, vec3_origin)) { + info->minlight.light = atoi(attribute); + GetVectorForKey(entity, "_mincolor", info->minlight.color); + if (!VectorCompare(info->minlight.color, vec3_origin)) { if (!colored) { colored = true; logprint("Colored light entities detected: " ".lit output enabled.\n"); } } else { - VectorCopy(vec3_white, modelinfo[i].mincolor); + VectorCopy(vec3_white, info->minlight.color); } } diff --git a/light/ltface.c b/light/ltface.c index 423ddaed..69e5381e 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -160,11 +160,6 @@ typedef struct { vec3_t points[SINGLEMAP]; } lightsurf_t; -typedef struct { - vec_t light; - vec3_t color; -} lightsample_t; - typedef struct { int style; lightsample_t samples[SINGLEMAP]; @@ -950,14 +945,13 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) } /* Minimum lighting - Use the greater of global or model minlight. */ - if (modelinfo->minlight > worldminlight) { - light.light = modelinfo->minlight; - VectorCopy(modelinfo->mincolor, light.color); + if (modelinfo->minlight.light > worldminlight) { + FixMinlight(&modelinfo->minlight, &lightsurf, lightmaps); } else { light.light = worldminlight; VectorCopy(minlight_color, light.color); + FixMinlight(&light, &lightsurf, lightmaps); } - FixMinlight(&light, &lightsurf, lightmaps); if (nominlimit) { /* cast only negative lights */ From f82562f9e48095546a4ac57526c930cc3b30362c Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sun, 10 Mar 2013 18:28:00 +1030 Subject: [PATCH 12/14] light: use lightsample_t for entity light values Signed-off-by: Kevin Shanahan --- include/light/entities.h | 9 +++++---- include/light/light.h | 1 - light/entities.c | 24 ++++++++++++------------ light/light.c | 1 + light/ltface.c | 20 +++++++++----------- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/include/light/entities.h b/include/light/entities.h index 0e77c4f5..d0869682 100644 --- a/include/light/entities.h +++ b/include/light/entities.h @@ -20,7 +20,9 @@ #ifndef __LIGHT_ENTITIES_H__ #define __LIGHT_ENTITIES_H__ +#include #include +#include #define DEFAULTLIGHTLEVEL 300 @@ -59,12 +61,11 @@ typedef struct entity_s { float spotangle2; float spotfalloff2; - int style; - int light; - float atten; + lightsample_t light; light_formula_t formula; - vec3_t lightcolor; vec_t fadedist; + float atten; + int style; char target[MAX_ENT_VALUE]; char targetname[MAX_ENT_VALUE]; diff --git a/include/light/light.h b/include/light/light.h index 22f03cb6..05908ab2 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #define ON_EPSILON 0.1 diff --git a/light/entities.c b/light/entities.c index 55044131..357650d2 100644 --- a/light/entities.c +++ b/light/entities.c @@ -166,8 +166,8 @@ vec_from_mangle(vec3_t v, const vec3_t m) static void CheckEntityFields(entity_t *entity) { - if (!entity->light) - entity->light = DEFAULTLIGHTLEVEL; + if (!entity->light.light) + entity->light.light = DEFAULTLIGHTLEVEL; if (entity->atten <= 0.0) entity->atten = 1.0; @@ -184,19 +184,19 @@ CheckEntityFields(entity_t *entity) entity->formula = LF_LINEAR; } - if (!VectorCompare(entity->lightcolor, vec3_origin)) { + if (!VectorCompare(entity->light.color, vec3_origin)) { if (!colored) { colored = true; logprint("Colored light entities detected: " ".lit output enabled.\n"); } } else { - VectorCopy(vec3_white, entity->lightcolor); + VectorCopy(vec3_white, entity->light.color); } if (entity->formula == LF_LINEAR) { /* Linear formula always has a falloff point */ - entity->fadedist = fabs(entity->light / entity->atten / scaledist); + entity->fadedist = fabs(entity->light.light / entity->atten / scaledist); } else if (fadegate < EQUAL_EPSILON) { /* If fadegate is tiny, other lights have effectively infinite reach */ entity->fadedist = VECT_MAX; @@ -208,17 +208,17 @@ CheckEntityFields(entity_t *entity) entity->fadedist = VECT_MAX; break; case LF_INVERSE: - entity->fadedist = entity->light * entity->atten * scaledist; + entity->fadedist = entity->light.light * entity->atten * scaledist; entity->fadedist *= LF_SCALE / fadegate; entity->fadedist = fabs(entity->fadedist); break; case LF_INVERSE2: - entity->fadedist = entity->light * entity->atten * scaledist; + entity->fadedist = entity->light.light * entity->atten * scaledist; entity->fadedist *= LF_SCALE / sqrt(fadegate); entity->fadedist = fabs(entity->fadedist); break; case LF_INVERSE2A: - entity->fadedist = entity->light * entity->atten * scaledist; + entity->fadedist = entity->light.light * entity->atten * scaledist; entity->fadedist -= LF_SCALE; entity->fadedist *= LF_SCALE / sqrt(fadegate); entity->fadedist = fabs(entity->fadedist); @@ -306,7 +306,7 @@ LoadEntities(void) else if (!strcmp(key, "origin")) scan_vec3(entity->origin, com_token, "origin"); else if (!strncmp(key, "light", 5) || !strcmp(key, "_light")) - entity->light = atof(com_token); + entity->light.light = atof(com_token); else if (!strcmp(key, "style")) { entity->style = atof(com_token); if (entity->style < 0 || entity->style > 254) @@ -324,7 +324,7 @@ LoadEntities(void) vec_from_mangle(entity->spotvec, vec); entity->spotlight = true; } else if (!strcmp(key, "_color") || !strcmp(key, "color")) - scan_vec3(entity->lightcolor, com_token, "color"); + scan_vec3(entity->light.color, com_token, "color"); else if (!strcmp(key, "_sunlight")) sunlight = atof(com_token); else if (!strcmp(key, "_sun_mangle")) { @@ -354,8 +354,8 @@ LoadEntities(void) } } if (!strcmp(entity->classname, "worldspawn")) { - if (entity->light > 0 && !worldminlight) { - worldminlight = entity->light; + if (entity->light.light > 0 && !worldminlight) { + worldminlight = entity->light.light; logprint("using minlight value %i from worldspawn.\n", worldminlight); } else if (worldminlight) { diff --git a/light/light.c b/light/light.c index 4236954b..121ed065 100644 --- a/light/light.c +++ b/light/light.c @@ -20,6 +20,7 @@ #include #include +#include float scaledist = 1.0; float rangescale = 0.5; diff --git a/light/ltface.c b/light/ltface.c index 69e5381e..e134753c 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -18,6 +18,7 @@ */ #include +#include static const float scalecos = 0.5; static const vec3_t bsp_origin = { 0, 0, 0 }; @@ -706,7 +707,7 @@ FixMinlight(const lightsample_t *minlight, const lightsurf_t *lightsurf, surfpoint = lightsurf->points[0]; for (j = 0; j < lightsurf->numpoints; j++, sample++, surfpoint += 3) { qboolean trace = false; - if (sample->light < entity->light) { + if (sample->light < entity->light.light) { trace = TestLine(entity->origin, surfpoint); if (!trace) continue; @@ -715,12 +716,12 @@ FixMinlight(const lightsample_t *minlight, const lightsurf_t *lightsurf, if (!trace) continue; } - sample->light = entity->light; + sample->light = entity->light.light; } if (!colored) continue; for (k = 0; k < 3; k++) { - if (sample->color[k] < entity->lightcolor[k]) { + if (sample->color[k] < entity->light.color[k]) { if (!trace) { trace = TestLine(entity->origin, surfpoint); if (!trace) @@ -732,7 +733,7 @@ FixMinlight(const lightsample_t *minlight, const lightsurf_t *lightsurf, break; } } - sample->color[k] = entity->lightcolor[k]; + sample->color[k] = entity->light.color[k]; } } } @@ -919,7 +920,7 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) for (i = 0, entity = entities; i < num_entities; i++, entity++) { if (entity->formula == LF_LOCALMIN) continue; - if (PositiveLight(entity->light, entity->lightcolor, &light)) + if (PositiveLight(entity->light.light, entity->light.color, &light)) SingleLightFace(entity, &light, &lightsurf, lightmaps); } /* cast positive sky light */ @@ -930,11 +931,8 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) for (i = 0, entity = entities; i < num_entities; i++, entity++) { if (entity->formula == LF_LOCALMIN) continue; - if (entity->light) { - light.light = entity->light; - VectorCopy(entity->lightcolor, light.color); - SingleLightFace(entity, &light, &lightsurf, lightmaps); - } + if (entity->light.light) + SingleLightFace(entity, &entity->light, &lightsurf, lightmaps); } /* cast sky light */ if (sunlight) { @@ -958,7 +956,7 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) for (i = 0, entity = entities; i < num_entities; i++, entity++) { if (entity->formula == LF_LOCALMIN) continue; - if (NegativeLight(entity->light, entity->lightcolor, &light)) + if (NegativeLight(entity->light.light, entity->light.color, &light)) SingleLightFace(entity, &light, &lightsurf, lightmaps); } /* cast negative sky light */ From e8d640f88f1275668b10fe1770c79d3f53b23df6 Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sun, 10 Mar 2013 18:42:35 +1030 Subject: [PATCH 13/14] light: use lightsample_t for minlight and sunlight Signed-off-by: Kevin Shanahan --- include/light/light.h | 7 +++---- light/entities.c | 20 ++++++++++---------- light/light.c | 9 ++++----- light/ltface.c | 20 +++++++------------- 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/include/light/light.h b/include/light/light.h index 05908ab2..67cdc70f 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -58,11 +58,10 @@ void MakeTnodes(void); extern float scaledist; extern float rangescale; extern float fadegate; -extern int worldminlight; extern const vec3_t vec3_white; -extern vec3_t minlight_color; -extern int sunlight; -extern vec3_t sunlight_color; + +extern lightsample_t minlight; +extern lightsample_t sunlight; extern vec3_t sunvec; /* diff --git a/light/entities.c b/light/entities.c index 357650d2..f34e6aee 100644 --- a/light/entities.c +++ b/light/entities.c @@ -326,16 +326,16 @@ LoadEntities(void) } else if (!strcmp(key, "_color") || !strcmp(key, "color")) scan_vec3(entity->light.color, com_token, "color"); else if (!strcmp(key, "_sunlight")) - sunlight = atof(com_token); + sunlight.light = atof(com_token); else if (!strcmp(key, "_sun_mangle")) { scan_vec3(vec, com_token, "_sun_mangle"); vec_from_mangle(sunvec, vec); VectorNormalize(sunvec); VectorScale(sunvec, -16384, sunvec); } else if (!strcmp(key, "_sunlight_color")) - scan_vec3(sunlight_color, com_token, "_sunlight_color"); + scan_vec3(sunlight.color, com_token, "_sunlight_color"); else if (!strcmp(key, "_minlight_color")) - scan_vec3(minlight_color, com_token, "_minlight_color"); + scan_vec3(minlight.color, com_token, "_minlight_color"); } /* @@ -354,19 +354,19 @@ LoadEntities(void) } } if (!strcmp(entity->classname, "worldspawn")) { - if (entity->light.light > 0 && !worldminlight) { - worldminlight = entity->light.light; + if (entity->light.light > 0 && !minlight.light) { + minlight.light = entity->light.light; logprint("using minlight value %i from worldspawn.\n", - worldminlight); - } else if (worldminlight) { + (int)minlight.light); + } else if (minlight.light) { logprint("Using minlight value %i from command line.\n", - worldminlight); + (int)minlight.light); } } } - if (!VectorCompare(sunlight_color, vec3_white) || - !VectorCompare(minlight_color, vec3_white)) { + if (!VectorCompare(sunlight.color, vec3_white) || + !VectorCompare(minlight.color, vec3_white)) { if (!colored) { colored = true; logprint("Colored light entities detected: " diff --git a/light/light.c b/light/light.c index 121ed065..968adcb3 100644 --- a/light/light.c +++ b/light/light.c @@ -25,11 +25,10 @@ float scaledist = 1.0; float rangescale = 0.5; float fadegate = EQUAL_EPSILON; -int worldminlight = 0; -int sunlight = 0; const vec3_t vec3_white = { 255, 255, 255 }; -vec3_t minlight_color = { 255, 255, 255 }; /* defaults to white light */ -vec3_t sunlight_color = { 255, 255, 255 }; /* defaults to white light */ + +lightsample_t minlight = { 0, { 255, 255, 255 } }; +lightsample_t sunlight = { 0, { 255, 255, 255 } }; vec3_t sunvec = { 0, 0, 16384 }; /* defaults to straight down */ byte *filebase; // start of lightmap data @@ -247,7 +246,7 @@ main(int argc, const char **argv) fadegate = atof(argv[i + 1]); i++; } else if (!strcmp(argv[i], "-light")) { - worldminlight = atof(argv[i + 1]); + minlight.light = atof(argv[i + 1]); i++; } else if (!strcmp(argv[i], "-compress")) { compress_ents = true; diff --git a/light/ltface.c b/light/ltface.c index e134753c..b63527a9 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -924,7 +924,7 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) SingleLightFace(entity, &light, &lightsurf, lightmaps); } /* cast positive sky light */ - if (PositiveLight(sunlight, sunlight_color, &light)) + if (PositiveLight(sunlight.light, sunlight.color, &light)) SkyLightFace(&light, &lightsurf, lightmaps); } else { /* (!nominlimit) => cast all lights */ @@ -935,21 +935,15 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) SingleLightFace(entity, &entity->light, &lightsurf, lightmaps); } /* cast sky light */ - if (sunlight) { - light.light = sunlight; - VectorCopy(sunlight_color, light.color); - SkyLightFace(&light, &lightsurf, lightmaps); - } + if (sunlight.light) + SkyLightFace(&sunlight, &lightsurf, lightmaps); } /* Minimum lighting - Use the greater of global or model minlight. */ - if (modelinfo->minlight.light > worldminlight) { + if (modelinfo->minlight.light > minlight.light) FixMinlight(&modelinfo->minlight, &lightsurf, lightmaps); - } else { - light.light = worldminlight; - VectorCopy(minlight_color, light.color); - FixMinlight(&light, &lightsurf, lightmaps); - } + else + FixMinlight(&minlight, &lightsurf, lightmaps); if (nominlimit) { /* cast only negative lights */ @@ -960,7 +954,7 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) SingleLightFace(entity, &light, &lightsurf, lightmaps); } /* cast negative sky light */ - if (NegativeLight(sunlight, sunlight_color, &light)) + if (NegativeLight(sunlight.light, sunlight.color, &light)) SkyLightFace(&light, &lightsurf, lightmaps); /* Fix any negative values */ From 359ddfa41e5464ea0a221f48413d3a1c24326046 Mon Sep 17 00:00:00 2001 From: Kevin Shanahan Date: Sun, 10 Mar 2013 20:21:26 +1030 Subject: [PATCH 14/14] light: remove nominlimit option and negative color value support "nominlimit" is a more sensible default - people expect negative lights to be able to subtract from minlight. The negative colors never really worked properly and there's not really any worthwhile use for the (that I know of). Hopefully nobody will be too upset by these two changes to the old behaviour. Signed-off-by: Kevin Shanahan --- changelog.txt | 2 + include/light/light.h | 3 - light.txt | 14 ++-- light/light.c | 5 +- light/ltface.c | 154 ++++++++++-------------------------------- 5 files changed, 42 insertions(+), 136 deletions(-) diff --git a/changelog.txt b/changelog.txt index 37271139..61c7f017 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,8 @@ Unreleased * light: implemented self shadowing and full shadows for brush models +* light: removed the "-nominlimit" option (now the default behaviour) +* light: remove support for negative color components (never worked properly) 2013-03-07 TyrUtils v0.6 diff --git a/include/light/light.h b/include/light/light.h index 67cdc70f..ea92aa9f 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -75,10 +75,7 @@ extern byte *lit_filebase; extern int oversample; extern qboolean compress_ents; -extern qboolean facecounter; extern qboolean colored; -extern qboolean bsp30; extern qboolean litfile; -extern qboolean nominlimit; #endif /* __LIGHT_LIGHT_H__ */ diff --git a/light.txt b/light.txt index 067a7bfd..dae76287 100644 --- a/light.txt +++ b/light.txt @@ -23,9 +23,6 @@ OPTIONS -light n Set a global minimum light level. Overrides default light level set in worldspawn. - -nominlimit Allow negative lights to reduce surface lighting below - the global minumum light level. - -dist n Scales the fade distance of all lights by a factor of n. If n > 1 lights fade more quickly with distance and if n < 1, lights fade more slowly with distance and light @@ -61,7 +58,7 @@ ENTITY PARAMETERS Set a global minimum light level of "n" across the whole map. This is an easy way to eliminate completely dark areas of the level, however - you may lose some contrast as a result, so use with care. + you may lose some contrast as a result, so use with care. Default 0. "_sunlight" "n" @@ -81,9 +78,8 @@ ENTITY PARAMETERS "_sunlight_color" "r g b" Specify red(r), green(g) and blue(b) components for the colour of the - sunlight. RGB component values are between -255 and 255. Negative - values will cause colour subtraction from light cast by other entities. - Default is white light ("255 255 255"). + sunlight. RGB component values are between 0 and 255. Default is white + light ("255 255 255"). MODEL PARAMETERS @@ -147,8 +143,8 @@ ENTITY PARAMETERS "_color" "r g b" Specify red(r), green(g) and blue(b) components for the colour of the - light. RGB component values are between -255 and 255. Negative values - will cause colour subtraction from light cast by other entities. + light. RGB component values are between 0 and 255. Default is white + light ("255 255 255"). "target" "name" diff --git a/light/light.c b/light/light.c index 968adcb3..54abcd6b 100644 --- a/light/light.c +++ b/light/light.c @@ -45,7 +45,6 @@ const dmodel_t *const *tracelist; int oversample = 1; qboolean compress_ents; qboolean colored; -qboolean nominlimit; void GetFileSpace(byte **lightdata, byte **colordata, int size) @@ -253,8 +252,6 @@ main(int argc, const char **argv) logprint("light entity compression enabled\n"); } else if (!strcmp(argv[i], "-lit")) { colored = true; - } else if (!strcmp(argv[i], "-nominlimit")) { - nominlimit = true; } else if (argv[i][0] == '-') Error("Unknown option \"%s\"", argv[i]); else @@ -264,7 +261,7 @@ main(int argc, const char **argv) if (i != argc - 1) { printf("usage: light [-threads num] [-light num] [-extra|-extra4]\n" " [-dist n] [-range n] [-gate n] [-lit] " - " [-compress] [-nominlimit] bspfile\n"); + " [-compress] bspfile\n"); exit(1); } diff --git a/light/ltface.c b/light/ltface.c index b63527a9..1a04e1e6 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -740,67 +740,6 @@ FixMinlight(const lightsample_t *minlight, const lightsurf_t *lightsurf, } } - -/* - * PositiveLight zeros negative light components. - * NegativeLight zeros positive light components. - */ -static qboolean -PositiveLight(int light, const vec3_t color, lightsample_t *out) -{ - int i; - qboolean positive = false; - - if (light > 0) { - out->light = light; - positive = true; - for (i = 0; i < 3; i++) - if (color[i] > 0) - out->color[i] = color[i]; - else - out->color[i] = 0; - } else if (light < 0) { - out->light = -light; - for (i = 0; i < 3; i++) - if (color[i] < 0) { - out->color[i] = -color[i]; - positive = true; - } else { - out->color[i] = 0; - } - } - - return positive; -} - -static qboolean -NegativeLight(int light, const vec3_t color, lightsample_t *out) -{ - int i; - qboolean negative = false; - - if (light < 0) { - out->light = light; - negative = true; - for (i = 0; i < 3; i++) - if (color[i] > 0) - out->color[i] = color[i]; - else - out->color[i] = 0; - } else if (light > 0) { - out->light = -light; - for (i = 0; i < 3; i++) - if (color[i] < 0) { - out->color[i] = -color[i]; - negative = true; - } else { - out->color[i] = 0; - } - } - - return negative; -} - static void WriteLightmaps(dface_t *face, const lightsurf_t *lightsurf, const lightmap_t *lightmaps) @@ -886,7 +825,6 @@ void LightFace(dface_t *face, const modelinfo_t *modelinfo) { int i, j, k; - lightsample_t light; const entity_t *entity; lightsample_t *sample; lightsurf_t lightsurf; @@ -902,74 +840,50 @@ LightFace(dface_t *face, const modelinfo_t *modelinfo) Lightsurf_Init(modelinfo, face, &lightsurf); Lightmaps_Init(lightmaps); - /* Under normal circumstances, the lighting procedure is: - * - cast all light entities - * - cast sky lighting - * - do minlighting. - * - * However, if nominlimit is enabled then we need to do the following: - * - cast _positive_ lights - * - cast _positive_ skylight (if any) - * - do minlighting - * - cast _negative_ lights - * - cast _negative_ sky light (if any) + /* + * The lighting procedure is: cast all positive lights, fix + * minlight levels, then cast all negative lights. Finally, we + * clamp any values that may have gone negative. */ - if (nominlimit) { - /* cast only positive lights */ - for (i = 0, entity = entities; i < num_entities; i++, entity++) { - if (entity->formula == LF_LOCALMIN) - continue; - if (PositiveLight(entity->light.light, entity->light.color, &light)) - SingleLightFace(entity, &light, &lightsurf, lightmaps); - } - /* cast positive sky light */ - if (PositiveLight(sunlight.light, sunlight.color, &light)) - SkyLightFace(&light, &lightsurf, lightmaps); - } else { - /* (!nominlimit) => cast all lights */ - for (i = 0, entity = entities; i < num_entities; i++, entity++) { - if (entity->formula == LF_LOCALMIN) - continue; - if (entity->light.light) - SingleLightFace(entity, &entity->light, &lightsurf, lightmaps); - } - /* cast sky light */ - if (sunlight.light) - SkyLightFace(&sunlight, &lightsurf, lightmaps); + /* positive lights */ + for (i = 0, entity = entities; i < num_entities; i++, entity++) { + if (entity->formula == LF_LOCALMIN) + continue; + if (entity->light.light > 0) + SingleLightFace(entity, &entity->light, &lightsurf, lightmaps); } + if (sunlight.light > 0) + SkyLightFace(&sunlight, &lightsurf, lightmaps); - /* Minimum lighting - Use the greater of global or model minlight. */ + /* minlight - Use the greater of global or model minlight. */ if (modelinfo->minlight.light > minlight.light) FixMinlight(&modelinfo->minlight, &lightsurf, lightmaps); else FixMinlight(&minlight, &lightsurf, lightmaps); - if (nominlimit) { - /* cast only negative lights */ - for (i = 0, entity = entities; i < num_entities; i++, entity++) { - if (entity->formula == LF_LOCALMIN) - continue; - if (NegativeLight(entity->light.light, entity->light.color, &light)) - SingleLightFace(entity, &light, &lightsurf, lightmaps); - } - /* cast negative sky light */ - if (NegativeLight(sunlight.light, sunlight.color, &light)) - SkyLightFace(&light, &lightsurf, lightmaps); + /* negative lights */ + for (i = 0, entity = entities; i < num_entities; i++, entity++) { + if (entity->formula == LF_LOCALMIN) + continue; + if (entity->light.light < 0) + SingleLightFace(entity, &entity->light, &lightsurf, lightmaps); + } + if (sunlight.light < 0) + SkyLightFace(&sunlight, &lightsurf, lightmaps); - /* Fix any negative values */ - for (i = 0; i < MAXLIGHTMAPS; i++) { - if (lightmaps[i].style == 255) - break; - sample = lightmaps[i].samples; - for (j = 0; j < lightsurf.numpoints; j++, sample++) { - if (sample->light < 0) - sample->light = 0; - if (colored) { - for (k = 0; k < 3; k++) { - if (sample->color[k] < 0) { - sample->color[k] = 0; - } + /* Fix any negative values */ + for (i = 0; i < MAXLIGHTMAPS; i++) { + if (lightmaps[i].style == 255) + break; + sample = lightmaps[i].samples; + for (j = 0; j < lightsurf.numpoints; j++, sample++) { + if (sample->light < 0) + sample->light = 0; + if (colored) { + for (k = 0; k < 3; k++) { + if (sample->color[k] < 0) { + sample->color[k] = 0; } } }