00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "lighting.h"
00026 #include "bsp.h"
00027 #include "../../shared/images.h"
00028
00029 static vec3_t texture_reflectivity[MAX_MAP_TEXINFO];
00030 patch_t *face_patches[MAX_MAP_FACES];
00031
00032
00033
00034
00035
00036
00037
00038 void CalcTextureReflectivity (void)
00039 {
00040 int i, j, texels = 0;
00041 char path[MAX_QPATH];
00042 int color[3];
00043 SDL_Surface *surf;
00044
00045
00046 VectorSet(texture_reflectivity[0], 0.5, 0.5, 0.5);
00047
00048 VectorSet(color, 0, 0, 0);
00049
00050 for (i = 0; i < curTile->numtexinfo; i++) {
00051
00052 for (j = 0; j < i; j++) {
00053 if (!strcmp(curTile->texinfo[i].texture, curTile->texinfo[j].texture)) {
00054 VectorCopy(texture_reflectivity[j], texture_reflectivity[i]);
00055 break;
00056 }
00057 }
00058 if (j != i)
00059 continue;
00060
00061
00062 Com_sprintf(path, sizeof(path), "textures/%s", curTile->texinfo[i].texture);
00063 if (!Img_LoadImage(path, &surf)) {
00064 Verb_Printf(VERB_NORMAL, "Couldn't load %s\n", path);
00065 VectorSet(texture_reflectivity[i], 0.5, 0.5, 0.5);
00066 continue;
00067 }
00068
00069
00070 texels = surf->w * surf->h;
00071 color[0] = color[1] = color[2] = 0;
00072
00073 for(j = 0; j < texels; j++){
00074 const byte *pos = (byte *)surf->pixels + j * 4;
00075 color[0] += *pos++;
00076 color[1] += *pos++;
00077 color[2] += *pos++;
00078 }
00079
00080 Verb_Printf(VERB_EXTRA, "Loaded %s (%dx%d)\n", curTile->texinfo[i].texture, surf->w, surf->h);
00081
00082 SDL_FreeSurface(surf);
00083
00084 for(j = 0; j < 3; j++){
00085 const float r = color[j] / texels / 255.0;
00086 texture_reflectivity[i][j] = r;
00087 }
00088 }
00089 }
00090
00091
00092 static winding_t *WindingFromFace (const dBspSurface_t *f)
00093 {
00094 int i, v;
00095 dBspVertex_t *dv;
00096 winding_t *w;
00097
00098 w = AllocWinding(f->numedges);
00099 w->numpoints = f->numedges;
00100
00101 for (i = 0; i < f->numedges; i++) {
00102 const int se = curTile->surfedges[f->firstedge + i];
00103 if (se < 0)
00104 v = curTile->edges[-se].v[1];
00105 else
00106 v = curTile->edges[se].v[0];
00107
00108 dv = &curTile->vertexes[v];
00109 VectorCopy(dv->point, w->p[i]);
00110 }
00111
00112 RemoveColinearPoints(w);
00113
00114 return w;
00115 }
00116
00117 static inline qboolean HasLight (const dBspSurface_t *f)
00118 {
00119 const dBspTexinfo_t *tex;
00120
00121 tex = &curTile->texinfo[f->texinfo];
00122 return (tex->surfaceFlags & SURF_LIGHT) && tex->value;
00123 }
00124
00130 static inline void EmissiveLight (patch_t *patch)
00131 {
00132 if (HasLight(patch->face)) {
00133 const dBspTexinfo_t *tex = &curTile->texinfo[patch->face->texinfo];
00134 const vec_t *ref = texture_reflectivity[patch->face->texinfo];
00135
00136 VectorScale(ref, tex->value, patch->light);
00137 }
00138 }
00139
00140 static void BuildPatch (int fn, winding_t *w)
00141 {
00142 patch_t *patch;
00143 dBspPlane_t *plane;
00144
00145 patch = (patch_t *)Mem_Alloc(sizeof(*patch));
00146
00147 face_patches[fn] = patch;
00148
00149 patch->face = &curTile->faces[fn];
00150 patch->winding = w;
00151
00152
00153 plane = &curTile->planes[patch->face->planenum];
00154
00155 if (patch->face->side)
00156 VectorNegate(plane->normal, patch->normal);
00157 else
00158 VectorCopy(plane->normal, patch->normal);
00159
00160 WindingCenter(w, patch->origin);
00161
00162
00163 VectorMA(patch->origin, 2.0, patch->normal, patch->origin);
00164
00165 patch->area = WindingArea(w);
00166
00167 if (patch->area < 1.0)
00168 patch->area = 1.0;
00169
00170 EmissiveLight(patch);
00171 }
00172
00173 static entity_t *EntityForModel (int modnum)
00174 {
00175 int i;
00176 char name[16];
00177
00178 Com_sprintf(name, sizeof(name), "*%i", modnum);
00179
00180 for (i = 0; i < num_entities; i++) {
00181 const char *s = ValueForKey(&entities[i], "model");
00182 if (!strcmp(s, name))
00183 return &entities[i];
00184 }
00185
00186
00187 return &entities[0];
00188 }
00189
00194 void BuildPatches (void)
00195 {
00196 int i, j, k;
00197 winding_t *w;
00198 vec3_t origin;
00199
00200 memset(face_patches, 0, sizeof(face_patches));
00201
00202 for (i = 0; i < curTile->nummodels; i++) {
00203 const dBspModel_t *mod = &curTile->models[i];
00204 const entity_t *ent = EntityForModel(i);
00205
00206
00207 GetVectorForKey(ent, "origin", origin);
00208
00209 for (j = 0; j < mod->numfaces; j++) {
00210 const int facenum = mod->firstface + j;
00211 dBspSurface_t *f = &curTile->faces[facenum];
00212
00213
00214 VectorCopy(origin, face_offset[facenum]);
00215
00216 if (!HasLight(f))
00217 continue;
00218
00219 w = WindingFromFace(f);
00220
00221 for (k = 0; k < w->numpoints; k++)
00222 VectorAdd(w->p[k], origin, w->p[k]);
00223
00224 BuildPatch(facenum, w);
00225 }
00226 }
00227 }
00228
00229
00230
00231
00232
00233
00234
00235 #define PATCH_SUBDIVIDE 64
00236
00237 static void FinishSubdividePatch (patch_t *patch, patch_t *newp)
00238 {
00239 VectorCopy(patch->normal, newp->normal);
00240
00241 VectorCopy(patch->light, newp->light);
00242
00243 patch->area = WindingArea(patch->winding);
00244
00245 if (patch->area < 1.0)
00246 patch->area = 1.0;
00247
00248 newp->area = WindingArea(newp->winding);
00249
00250 if (newp->area < 1.0)
00251 newp->area = 1.0;
00252
00253 WindingCenter(patch->winding, patch->origin);
00254
00255 VectorMA(patch->origin, 2.0, patch->normal, patch->origin);
00256
00257 WindingCenter(newp->winding, newp->origin);
00258
00259 VectorMA(newp->origin, 2.0, newp->normal, newp->origin);
00260 }
00261
00265 static void SubdividePatch(patch_t *patch)
00266 {
00267 winding_t *w, *o1, *o2;
00268 vec3_t mins, maxs;
00269 vec3_t split;
00270 vec_t dist;
00271 int i;
00272 patch_t *newp;
00273
00274 w = patch->winding;
00275 WindingBounds(w, mins, maxs);
00276
00277 VectorClear(split);
00278
00279 for (i = 0; i < 3; i++) {
00280 if (floor((mins[i] + 1) / PATCH_SUBDIVIDE) < floor((maxs[i] - 1) / PATCH_SUBDIVIDE)) {
00281 split[i] = 1.0;
00282 break;
00283 }
00284 }
00285
00286 if (i == 3)
00287 return;
00288
00289
00290 dist = PATCH_SUBDIVIDE * (1 + floor((mins[i] + 1) / PATCH_SUBDIVIDE));
00291 ClipWindingEpsilon(w, split, dist, ON_EPSILON, &o1, &o2);
00292
00293
00294 newp = (patch_t *)Mem_Alloc(sizeof(*newp));
00295
00296 newp->next = patch->next;
00297 patch->next = newp;
00298
00299 patch->winding = o1;
00300 newp->winding = o2;
00301
00302 FinishSubdividePatch(patch, newp);
00303
00304 SubdividePatch(patch);
00305 SubdividePatch(newp);
00306 }
00307
00311 void SubdividePatches (void)
00312 {
00313 int i;
00314
00315 for (i = 0; i < MAX_MAP_FACES; i++) {
00316 patch_t *p = face_patches[i];
00317
00318 if (p)
00319 SubdividePatch(p);
00320 }
00321 }
00322
00326 void FreePatches (void)
00327 {
00328 int i;
00329
00330 for (i = 0; i < MAX_MAP_FACES; i++) {
00331 patch_t *p = face_patches[i];
00332 while (p) {
00333 patch_t *pnext = p->next;
00334 Mem_Free(p);
00335 p = pnext;
00336 }
00337 }
00338 }