UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
patches.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 1997-2001 Id Software, Inc.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 #include "lighting.h"
26 #include "bsp.h"
27 #include "../../shared/images.h"
28 
31 
32 /*
33 ===================================================================
34 TEXTURE LIGHT VALUES
35 ===================================================================
36 */
37 
42 {
43  int j, texels = 0;
44  char path[MAX_QPATH];
45  int color[3];
46  SDL_Surface* surf;
47 
48  /* always set index 0 even if no textures */
49  VectorSet(texture_reflectivity[0], 0.5, 0.5, 0.5);
50 
51  VectorSet(color, 0, 0, 0);
52 
53  for (int i = 0; i < curTile->numtexinfo; i++) {
54  /* see if an earlier texinfo already got the value */
55  for (j = 0; j < i; j++) {
58  break;
59  }
60  }
61  if (j != i) /* earlier texinfo found, continue */
62  continue;
63 
64  /* load the image file */
65  Com_sprintf(path, sizeof(path), "textures/%s", curTile->texinfo[i].texture);
66  if (!(surf = Img_LoadImage(path))) {
67  Verb_Printf(VERB_NORMAL, "Couldn't load %s\n", path);
68  VectorSet(texture_reflectivity[i], 0.5, 0.5, 0.5);
69  continue;
70  }
71 
72  /* calculate average color */
73  texels = surf->w * surf->h;
74  color[0] = color[1] = color[2] = 0;
75 
76  for(j = 0; j < texels; j++){
77  const byte* pos = (byte*)surf->pixels + j * 4;
78  color[0] += *pos++; /* r */
79  color[1] += *pos++; /* g */
80  color[2] += *pos++; /* b */
81  }
82 
83  Verb_Printf(VERB_EXTRA, "Loaded %s (%dx%d)\n", curTile->texinfo[i].texture, surf->w, surf->h);
84 
85  SDL_FreeSurface(surf);
86 
87  for(j = 0; j < 3; j++){
88  const float r = color[j] / texels / 255.0;
89  texture_reflectivity[i][j] = r;
90  }
91  }
92 }
93 
94 
96 {
98  w->numpoints = f->numedges;
99 
100  for (int i = 0; i < f->numedges; i++) {
101  const int se = curTile->surfedges[f->firstedge + i];
102  int v;
103  if (se < 0)
104  v = curTile->edges[-se].v[1];
105  else
106  v = curTile->edges[se].v[0];
107 
108  dBspVertex_t* dv = &curTile->vertexes[v];
109  VectorCopy(dv->point, w->p[i]);
110  }
111 
113 
114  return w;
115 }
116 
117 static inline bool HasLight (const dBspSurface_t* f)
118 {
119  const dBspTexinfo_t* tex;
120 
121  tex = &curTile->texinfo[f->texinfo];
122  return (tex->surfaceFlags & SURF_LIGHT) && tex->value;
123 }
124 
130 static inline void EmissiveLight (patch_t* patch)
131 {
132  const dBspTexinfo_t* tex = &curTile->texinfo[patch->face->texinfo];
133  const vec_t* ref = texture_reflectivity[patch->face->texinfo];
134 
135  VectorScale(ref, tex->value, patch->light);
136 }
137 
145 static void BuildPatch (int fn, winding_t* w)
146 {
147  patch_t* patch;
148  dBspPlane_t* plane;
149 
150  patch = Mem_AllocType(patch_t);
151 
152  face_patches[fn] = patch;
153 
154  patch->face = &curTile->faces[fn];
155  patch->winding = w;
156 
157  /* resolve the normal */
158  plane = &curTile->planes[patch->face->planenum];
159 
160  if (patch->face->side)
161  VectorNegate(plane->normal, patch->normal);
162  else
163  VectorCopy(plane->normal, patch->normal);
164 
165  WindingCenter(w, patch->origin);
166 
167  /* nudge the origin out along the normal */
168  VectorMA(patch->origin, 2.0, patch->normal, patch->origin);
169 
170  patch->area = WindingArea(w);
171 
172  if (patch->area < 1.0) /* clamp area */
173  patch->area = 1.0;
174 
175  EmissiveLight(patch); /* surface light */
176 }
177 
178 static entity_t* EntityForModel (int modnum)
179 {
180  char name[16];
181 
182  Com_sprintf(name, sizeof(name), "*%i", modnum);
183  /* search the entities for one using modnum */
184  for (int i = 0; i < num_entities; i++) {
185  const char* s = ValueForKey(&entities[i], "model");
186  if (Q_streq(s, name))
187  return &entities[i];
188  }
189 
190  /* return the world */
191  return &entities[0];
192 }
193 
198 void BuildPatches (void)
199 {
200  OBJZERO(face_patches);
201 
202  for (int i = 0; i < curTile->nummodels; i++) {
203  const dBspModel_t* mod = &curTile->models[i];
204  const entity_t* ent = EntityForModel(i);
205  vec3_t origin;
206  /* bmodels with origin brushes (like func_door) need to be offset into their
207  * in-use position */
208  GetVectorForKey(ent, "origin", origin);
209 
210  for (int j = 0; j < mod->numfaces; j++) {
211  const int facenum = mod->firstface + j;
212  dBspSurface_t* f = &curTile->faces[facenum];
213 
214  /* store the origin in case of moving bmodels (e.g. func_door) */
215  VectorCopy(origin, face_offset[facenum]);
216 
217  if (!HasLight(f)) /* no light */
218  continue;
219 
220  winding_t* w = WindingFromFace(f);
221 
222  for (int k = 0; k < w->numpoints; k++)
223  VectorAdd(w->p[k], origin, w->p[k]);
224 
225  BuildPatch(facenum, w);
226  }
227  }
228 }
229 
230 /*
231 =======================================================================
232 SUBDIVIDE
233 =======================================================================
234 */
235 
236 #define PATCH_SUBDIVIDE 64
237 
238 static void FinishSubdividePatch (patch_t* patch, patch_t* newp)
239 {
240  VectorCopy(patch->normal, newp->normal);
241 
242  VectorCopy(patch->light, newp->light);
243 
244  patch->area = WindingArea(patch->winding);
245 
246  if (patch->area < 1.0)
247  patch->area = 1.0;
248 
249  newp->area = WindingArea(newp->winding);
250 
251  if (newp->area < 1.0)
252  newp->area = 1.0;
253 
254  WindingCenter(patch->winding, patch->origin);
255  /* nudge the patch origin out along the normal */
256  VectorMA(patch->origin, 2.0, patch->normal, patch->origin);
257 
258  WindingCenter(newp->winding, newp->origin);
259  /* nudge the patch origin out along the normal */
260  VectorMA(newp->origin, 2.0, newp->normal, newp->origin);
261 }
262 
266 static void SubdividePatch(patch_t* patch)
267 {
268  winding_t* w, *o1, *o2;
269  vec3_t mins, maxs;
270  vec3_t split;
271  vec_t dist;
272  int i;
273  patch_t* newp;
274 
275  w = patch->winding;
276  WindingBounds(w, mins, maxs);
277 
278  VectorClear(split);
279 
280  for (i = 0; i < 3; i++) {
281  if (floor((mins[i] + 1) / PATCH_SUBDIVIDE) < floor((maxs[i] - 1) / PATCH_SUBDIVIDE)) {
282  split[i] = 1.0;
283  break;
284  }
285  }
286  /* no splitting needed */
287  if (i == 3)
288  return;
289 
290  /* split the winding */
291  dist = PATCH_SUBDIVIDE * (1 + floor((mins[i] + 1) / PATCH_SUBDIVIDE));
292  ClipWindingEpsilon(w, split, dist, ON_EPSILON, &o1, &o2);
293 
294  /* create a new patch */
295  newp = Mem_AllocType(patch_t);
296 
297  newp->next = patch->next;
298  patch->next = newp;
299 
300  patch->winding = o1;
301  newp->winding = o2;
302 
303  FinishSubdividePatch(patch, newp);
304 
305  SubdividePatch(patch);
306  SubdividePatch(newp);
307 }
308 
312 void SubdividePatches (void)
313 {
314  for (int i = 0; i < MAX_MAP_FACES; i++) {
315  patch_t* p = face_patches[i];
316 
317  if (p) /* break it up */
318  SubdividePatch(p);
319  }
320 }
321 
325 void FreePatches (void)
326 {
327  for (int i = 0; i < MAX_MAP_FACES; i++) {
328  patch_t* p = face_patches[i];
329  while (p) {
330  patch_t* pnext = p->next;
331  Mem_Free(p);
332  p = pnext;
333  }
334  }
335 }
dBspEdge_t edges[MAX_MAP_EDGES]
Definition: typedefs.h:493
#define VectorCopy(src, dest)
Definition: vector.h:51
#define VectorSet(v, x, y, z)
Definition: vector.h:59
unsigned short v[2]
Definition: typedefs.h:400
#define MAX_MAP_FACES
Definition: defines.h:144
void WindingBounds(const winding_t *w, vec3_t mins, vec3_t maxs)
Definition: polylib.cpp:97
void VectorMA(const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector)
Sets vector_out (vc) to vevtor1 (va) + scale * vector2 (vb)
Definition: mathlib.cpp:261
static void EmissiveLight(patch_t *patch)
Check for light emitted by texture.
Definition: patches.cpp:130
void FreePatches(void)
After light sources have been created, patches may be freed.
Definition: patches.cpp:325
static entity_t * EntityForModel(int modnum)
Definition: patches.cpp:178
#define PATCH_SUBDIVIDE
Definition: patches.cpp:236
voidpf uLong int origin
Definition: ioapi.h:45
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
dBspModel_t models[MAX_MAP_MODELS]
Definition: typedefs.h:468
#define VectorNegate(src, dest)
Definition: vector.h:58
float vec_t
Definition: ufotypes.h:37
vec3_t origin
Definition: lighting.h:37
entity_t entities[MAX_MAP_ENTITIES]
Definition: bspfile.cpp:395
int nummodels
Definition: typedefs.h:467
uint32_t value
Definition: typedefs.h:391
winding_t * winding
Definition: lighting.h:35
#define VectorScale(in, scale, out)
Definition: vector.h:79
int numtexinfo
Definition: typedefs.h:486
void RemoveColinearPoints(winding_t *w)
Definition: polylib.cpp:55
static winding_t * WindingFromFace(const dBspSurface_t *f)
Definition: patches.cpp:95
uint32_t surfaceFlags
Definition: typedefs.h:390
vec3_t light
Definition: lighting.h:41
dBspTexinfo_t texinfo[MAX_MAP_TEXINFO]
Definition: typedefs.h:487
void CalcTextureReflectivity(void)
Calculates the texture color that is used for light emitting surfaces.
Definition: patches.cpp:41
static void FinishSubdividePatch(patch_t *patch, patch_t *newp)
Definition: patches.cpp:238
void GetVectorForKey(const entity_t *ent, const char *key, vec3_t vec)
Converts the value of a entity parameter into a vec3_t.
Definition: bspfile.cpp:592
dBspSurface_t faces[MAX_MAP_FACES]
Definition: typedefs.h:490
#define OBJZERO(obj)
Definition: shared.h:178
winding_t * AllocWinding(int points)
Allocate a new winding (polygon)
Definition: polylib.cpp:38
void ClipWindingEpsilon(const winding_t *in, const vec3_t normal, const vec_t dist, const vec_t epsilon, winding_t **front, winding_t **back)
Definition: polylib.cpp:204
void BuildPatches(void)
Create surface fragments for light-emitting surfaces so that light sources may be computed along them...
Definition: patches.cpp:198
void WindingCenter(const winding_t *w, vec3_t center)
Definition: polylib.cpp:106
dBspPlane_t planes[MAX_MAP_PLANES]
Definition: typedefs.h:475
SDL_Surface * Img_LoadImage(char const *name)
Loads the specified image from the game filesystem and populates the provided SDL_Surface.
Definition: images.cpp:435
for storing the vertices of the side of a brush or other polygon
Definition: polylib.h:30
float area
Definition: lighting.h:40
vec3_t normal
Definition: lighting.h:38
short numedges
Definition: typedefs.h:408
static void BuildPatch(int fn, winding_t *w)
Build a patch for a surface that emits light.
Definition: patches.cpp:145
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
float point[3]
Definition: typedefs.h:362
dMapTile_t * curTile
Definition: bsp.cpp:32
int numfaces
Definition: typedefs.h:358
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
#define VectorClear(a)
Definition: vector.h:55
static bool HasLight(const dBspSurface_t *f)
Definition: patches.cpp:117
#define VectorAdd(a, b, dest)
Definition: vector.h:47
vec_t WindingArea(const winding_t *w)
Definition: polylib.cpp:81
#define SURF_LIGHT
Definition: defines.h:254
#define MAX_QPATH
Definition: filesys.h:40
QGL_EXTERN GLint i
Definition: r_gl.h:113
vec3_t p[4]
Definition: polylib.h:32
vec3_t face_offset[MAX_MAP_FACES]
Definition: lightmap.cpp:34
struct patch_s * next
Definition: lighting.h:43
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
#define Mem_Free(ptr)
Definition: mem.h:35
int surfedges[MAX_MAP_SURFEDGES]
Definition: typedefs.h:506
patch_t * face_patches[MAX_MAP_FACES]
Definition: patches.cpp:30
short side
Definition: typedefs.h:405
vec_t vec3_t[3]
Definition: ufotypes.h:39
short texinfo
Definition: typedefs.h:409
static vec3_t texture_reflectivity[MAX_MAP_TEXINFO]
Definition: patches.cpp:29
#define Mem_AllocType(type)
Definition: mem.h:39
#define Q_streq(a, b)
Definition: shared.h:136
dBspVertex_t vertexes[MAX_MAP_VERTS]
Definition: typedefs.h:481
const char * ValueForKey(const entity_t *ent, const char *key)
Definition: bspfile.cpp:558
uint16_t planenum
Definition: typedefs.h:404
vec3_t normal
Definition: typedefs.h:373
static void SubdividePatch(patch_t *patch)
Chops the patch by a global grid.
Definition: patches.cpp:266
uint8_t byte
Definition: ufotypes.h:34
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
#define MAX_MAP_TEXINFO
Definition: defines.h:138
int num_entities
Definition: bspfile.cpp:394
int firstface
Definition: typedefs.h:358
void SubdividePatches(void)
Iterate all of the head face patches, subdividing them as necessary.
Definition: patches.cpp:312
dBspSurface_t * face
Definition: lighting.h:34
char texture[32]
Definition: typedefs.h:392
int numpoints
Definition: polylib.h:31
#define ON_EPSILON
Definition: defines.h:374