UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_material.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 1997-2001 Id Software, Inc.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "r_local.h"
27 #include "r_error.h"
28 #include "r_lightmap.h"
29 #include "../../shared/parse.h"
30 
32 
35 
36 #define UPDATE_THRESHOLD 0.02
37 
41 {
42  if (refdef.time - m->time < UPDATE_THRESHOLD)
43  return;
44 
45  m->time = refdef.time;
46 
47  for (materialStage_t* s = m->stages; s; s = s->next) {
48  if (s->flags & STAGE_PULSE) {
49  float phase = refdef.time * s->pulse.hz;
50  float moduloPhase = phase - floor(phase); /* extract fractional part of phase */
51 
52  if (moduloPhase < s->pulse.dutycycle) {
53  moduloPhase /= s->pulse.dutycycle;
54  s->pulse.dhz = (1.0 - cos(moduloPhase * (2 * M_PI))) / 2.0;
55  } else {
56  s->pulse.dhz = 0;
57  }
58  }
59 
60  if (s->flags & STAGE_STRETCH) {
61  s->stretch.dhz = (1.0 - cos(refdef.time * s->stretch.hz * (2 * M_PI)) ) / 2.0;
62  s->stretch.damp = 1.5 - s->stretch.dhz * s->stretch.amp;
63  }
64 
65  if (s->flags & STAGE_ROTATE)
66  s->rotate.deg = refdef.time * s->rotate.hz * 360.0;
67 
68  if (s->flags & STAGE_SCROLL_S)
69  s->scroll.ds = s->scroll.s * refdef.time;
70 
71  if (s->flags & STAGE_SCROLL_T)
72  s->scroll.dt = s->scroll.t * refdef.time;
73 
74  if (s->flags & STAGE_ANIM) {
75  if (refdef.time >= s->anim.dtime) { /* change frames */
76  int frame;
77  s->anim.dtime = refdef.time + (1.0 / s->anim.fps);
78  s->anim.dframe++;
79  switch (s->anim.type) {
80  case ANIM_NORMAL:
81  frame = s->anim.dframe % s->anim.num_frames;
82  break;
83  case ANIM_ALTERNATE:
84  frame = abs(s->anim.dframe % (s->anim.num_frames + 1) - (s->anim.num_frames / 2));
85  break;
86  case ANIM_BACKWARDS:
87  frame = s->anim.num_frames - 1;
88  frame -= s->anim.dframe % s->anim.num_frames;
89  break;
90  case ANIM_RANDOM:
91  frame = rand() % s->anim.num_frames;
92  break;
93  case ANIM_RANDOMFORCE:
94  frame = rand() % s->anim.num_frames;
95  if (s->image == s->anim.images[frame])
96  frame = (frame + 1) % s->anim.num_frames;
97  break;
98  default:
99  continue;
100  }
101  assert(frame >= 0);
102  assert(frame < s->anim.num_frames);
103  s->image = s->anim.images[frame];
104  }
105  }
106  }
107 }
108 
109 static void R_StageGlow (const materialStage_t* stage)
110 {
111  image_t* glowmap;
112 
113  if (stage->flags & STAGE_GLOWMAPLINK)
114  glowmap = stage->image;
115  else
116  glowmap = stage->image->glowmap;
117 
118  if (glowmap) {
119  R_EnableGlowMap(glowmap);
121  R_ProgramParameter1f("GLOWSCALE", stage->glowscale);
122  } else {
123  R_EnableGlowMap(nullptr);
124  }
125 }
126 
130 static void R_StageLighting (const mBspSurface_t* surf, const materialStage_t* stage)
131 {
132  /* if the surface has a lightmap, and the stage specifies lighting.. */
133  if ((surf->flags & MSURF_LIGHTMAP) &&
134  (stage->flags & (STAGE_LIGHTMAP | STAGE_LIGHTING))) {
137 
138  /* hardware lighting */
140  if (r_materials->integer > 1) {
141  if ((stage->flags & STAGE_LIGHTING)) {
144  } else {
145  R_SetSurfaceBumpMappingParameters(surf, nullptr, nullptr);
146  R_EnableLighting(nullptr, false);
147  }
148  }
149  } else {
151  return;
152  R_EnableLighting(nullptr, false);
153 
155  }
156 }
157 
162 static inline void R_StageVertex (const mBspSurface_t* surf, const materialStage_t* stage, const vec3_t in, vec3_t out)
163 {
164  VectorCopy(in, out);
165 }
166 
171 static inline void R_StageTextureMatrix (const mBspSurface_t* surf, const materialStage_t* stage)
172 {
173  static bool identity = true;
174  float s, t;
175 
176  if (!(stage->flags & STAGE_TEXTURE_MATRIX)) {
177  if (!identity)
178  glLoadIdentity();
179 
180  identity = true;
181  return;
182  }
183 
184  glLoadIdentity();
185 
186  s = surf->stcenter[0] / surf->texinfo->image->width;
187  t = surf->stcenter[1] / surf->texinfo->image->height;
188 
189  if (stage->flags & STAGE_STRETCH) {
190  glTranslatef(-s, -t, 0.0);
191  glScalef(stage->stretch.damp, stage->stretch.damp, 1.0);
192  glTranslatef(-s, -t, 0.0);
193  }
194 
195  if (stage->flags & STAGE_ROTATE) {
196  glTranslatef(-s, -t, 0.0);
197  glRotatef(stage->rotate.deg, 0.0, 0.0, 1.0);
198  glTranslatef(-s, -t, 0.0);
199  }
200 
201  if (stage->flags & STAGE_SCALE_S)
202  glScalef(stage->scale.s, 1.0, 1.0);
203 
204  if (stage->flags & STAGE_SCALE_T)
205  glScalef(1.0, stage->scale.t, 1.0);
206 
207  if (stage->flags & STAGE_SCROLL_S)
208  glTranslatef(stage->scroll.ds, 0.0, 0.0);
209 
210  if (stage->flags & STAGE_SCROLL_T)
211  glTranslatef(0.0, stage->scroll.dt, 0.0);
212 
213  identity = false;
214 }
215 
219 static void R_StageTexCoord (const materialStage_t* stage, const vec3_t v, const vec2_t in, vec2_t out)
220 {
221  if (stage->flags & STAGE_ENVMAP) { /* generate texcoords */
222  vec3_t tmp;
224  VectorNormalizeFast(tmp);
225  Vector2Copy(tmp, out);
226  } else { /* or use the ones we were given */
227  Vector2Copy(in, out);
228  }
229 }
230 
232 static const float dirtmap[] = {
233  0.6, 0.5, 0.3, 0.4, 0.7, 0.3, 0.0, 0.4,
234  0.5, 0.2, 0.8, 0.5, 0.3, 0.2, 0.5, 0.3
235 };
236 
240 static void R_StageColor (const materialStage_t* stage, const vec3_t v, vec4_t color)
241 {
242  if (stage->flags & (STAGE_TERRAIN | STAGE_TAPE)) {
243  float a;
244 
245  if (stage->flags & STAGE_COLOR) /* honor stage color */
246  VectorCopy(stage->color, color);
247  else /* or use white */
248  VectorSet(color, 1.0, 1.0, 1.0);
249 
250  /* resolve alpha for vert based on z axis height */
251  if (stage->flags & STAGE_TERRAIN) {
252  if (v[2] < stage->terrain.floor)
253  a = 0.0;
254  else if (v[2] > stage->terrain.ceil)
255  a = 1.0;
256  else
257  a = (v[2] - stage->terrain.floor) / stage->terrain.height;
258  } else {
259  if (v[2] < stage->tape.max && v[2] > stage->tape.min) {
260  if (v[2] > stage->tape.center) {
261  const float delta = v[2] - stage->tape.center;
262  a = 1 - (delta / stage->tape.max);
263  } else {
264  const float delta = stage->tape.center - v[2];
265  a = 1 - (delta / stage->tape.min);
266  }
267  } else {
268  a = 0.0;
269  }
270  }
271 
272  color[3] = a;
273  } else if (stage->flags & STAGE_DIRTMAP) {
274  /* resolve dirtmap based on vertex position */
275  const vec3_t hash_mult = {1.3, 3.1, 7.3};
276  const int index = ((int) DotProduct(v, hash_mult)) % lengthof(dirtmap);
277 
278  if (stage->flags & STAGE_COLOR) /* honor stage color */
279  VectorCopy(stage->color, color);
280  else /* or use white */
281  VectorSet(color, 1.0, 1.0, 1.0);
282  color[3] = dirtmap[index] * stage->dirt.intensity;
283  } else { /* simply use white */
284  Vector4Set(color, 1.0, 1.0, 1.0, 1.0);
285  }
286 }
287 
292 static void R_SetSurfaceStageState (const mBspSurface_t* surf, const materialStage_t* stage)
293 {
294  /* bind the texture */
295  R_BindTexture(stage->image->texnum);
296 
297  /* and optionally the lightmap */
298  R_StageLighting(surf, stage);
299 
300  R_StageGlow(stage);
301 
302  /* load the texture matrix for rotations, stretches, etc.. */
303  R_StageTextureMatrix(surf, stage);
304 
305  /* set the blend function, ensuring a good default */
306  if (stage->flags & STAGE_BLEND)
307  R_BlendFunc(stage->blend.src, stage->blend.dest);
308  else
309  R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
310 
311  /* for terrain, enable the color array */
312  if (stage->flags & (STAGE_TAPE | STAGE_TERRAIN | STAGE_DIRTMAP))
313  R_EnableColorArray(true);
314  else
315  R_EnableColorArray(false);
316 
317  /* when not using the color array, resolve the shade color */
319  vec4_t color;
320 
321  if (stage->flags & STAGE_COLOR) /* explicit */
322  VectorCopy(stage->color, color);
323 
324  else if (stage->flags & STAGE_ENVMAP) /* implied */
325  VectorCopy(surf->lightColor, color);
327  else /* default */
328  VectorSet(color, 1.0, 1.0, 1.0);
329 
330  /* modulate the alpha value for pulses */
331  if (stage->flags & STAGE_PULSE) {
332  /* disable fog, since it also sets alpha */
333  R_EnableFog(false);
334  color[3] = stage->pulse.dhz;
335  } else {
336  /* ensure fog is available */
337  R_EnableFog(true);
338  color[3] = 1.0;
339  }
340 
341  R_Color(color);
342  }
343 }
344 
350 {
351  int i;
352 
356 
357  for (i = 0; i < surf->numedges; i++) {
358  const float* v = &r_mapTiles[surf->tile]->bsp.verts[surf->index * 3 + i * 3];
359  const float* st = &r_mapTiles[surf->tile]->bsp.texcoords[surf->index * 2 + i * 2];
360 
361  R_StageVertex(surf, stage, v, &r_state.vertex_array_3d[i * 3]);
362 
363  R_StageTexCoord(stage, v, st, &texunit_diffuse.texcoord_array[i * 2]);
364 
365  if (texunit_lightmap.enabled) {
366  st = &r_mapTiles[surf->tile]->bsp.lmtexcoords[surf->index * 2 + i * 2];
367  texunit_lightmap.texcoord_array[i * 2 + 0] = st[0];
368  texunit_lightmap.texcoord_array[i * 2 + 1] = st[1];
369  }
370 
372  R_StageColor(stage, v, &r_state.color_array[i * 4]);
373 
374  /* normals and tangents */
376  const float* n = &r_mapTiles[surf->tile]->bsp.normals[surf->index * 3 + i * 3];
377  memcpy(&r_state.normal_array[i * 3], n, sizeof(vec3_t));
378 
380  const float* t = &r_mapTiles[surf->tile]->bsp.tangents[surf->index * 4 + i * 4];
381  memcpy(&r_state.tangent_array[i * 4], t, sizeof(vec3_t));
382  }
383  }
384  }
385 
386  glDrawArrays(GL_TRIANGLE_FAN, 0, i);
387 
388  refdef.batchCount++;
389 
390  R_CheckError();
391 }
392 
400 {
401  if (!r_materials->integer || r_wire->integer)
402  return;
403 
404  if (!surfs->count)
405  return;
406 
407  assert(r_state.blend_enabled);
408 
410  R_EnableModelLights(nullptr, 0, false, false);
411 
412  R_EnableColorArray(true);
413 
415 
416  R_EnableColorArray(false);
417 
418  R_EnableLighting(nullptr, false);
419 
421 
422 #ifndef GL_VERSION_ES_CM_1_0
423  glEnable(GL_POLYGON_OFFSET_FILL);
424 #endif
425  glPolygonOffset(-1.f, -1.f);
426 
427  glMatrixMode(GL_TEXTURE); /* some stages will manipulate texcoords */
428 
429  for (int i = 0; i < surfs->count; i++) {
430  mBspSurface_t* surf = surfs->surfaces[i];
431  material_t* m = &surf->texinfo->image->material;
432  int j = -1;
433 
434  if (surf->frame != r_locals.frame)
435  continue;
436 
437  R_UpdateMaterial(m);
438 
439  for (materialStage_t* s = m->stages; s; s = s->next, j--) {
440  if (!(s->flags & STAGE_RENDER))
441  continue;
442 
443  R_SetSurfaceStageState(surf, s);
444 
445  R_DrawSurfaceStage(surf, s);
446  }
447  }
448 
449  R_Color(nullptr);
450 
451  /* polygon offset parameters */
452  glPolygonOffset(0.0, 0.0);
453 #ifndef GL_VERSION_ES_CM_1_0
454  glDisable(GL_POLYGON_OFFSET_FILL);
455 #endif
456 
457  glLoadIdentity();
458  glMatrixMode(GL_MODELVIEW);
459 
460  R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
461 
462  R_EnableFog(true);
463 
464  R_EnableColorArray(false);
465 
467 
468  R_EnableBumpmap(nullptr);
469 
470  R_EnableLighting(nullptr, false);
471 
472  R_EnableGlowMap(nullptr);
473 
474  R_Color(nullptr);
475 }
476 
480 static GLenum R_ConstByName (const char* c)
481 {
482  if (Q_streq(c, "GL_ONE"))
483  return GL_ONE;
484  if (Q_streq(c, "GL_ZERO"))
485  return GL_ZERO;
486  if (Q_streq(c, "GL_SRC_ALPHA"))
487  return GL_SRC_ALPHA;
488  if (Q_streq(c, "GL_ONE_MINUS_SRC_ALPHA"))
489  return GL_ONE_MINUS_SRC_ALPHA;
490  if (Q_streq(c, "GL_SRC_COLOR"))
491  return GL_SRC_COLOR;
492  if (Q_streq(c, "GL_DST_COLOR"))
493  return GL_DST_COLOR;
494  if (Q_streq(c, "GL_ONE_MINUS_SRC_COLOR"))
495  return GL_ONE_MINUS_SRC_COLOR;
496  if (Q_streq(c, "GL_ONE_MINUS_DST_COLOR"))
497  return GL_ONE_MINUS_DST_COLOR;
498 
499  Com_Printf("R_ConstByName: Failed to resolve: %s\n", c);
500  return GL_ZERO;
501 }
502 
503 static void R_CreateMaterialData_ (model_t* mod)
504 {
505  for (int i = 0; i < mod->bsp.numsurfaces; i++) {
506  mBspSurface_t* surf = &mod->bsp.surfaces[i];
507  /* create flare */
508  R_CreateSurfaceFlare(surf);
509  }
510 }
511 
512 static void R_CreateMaterialData (void)
513 {
514  int i;
515 
516  for (i = 0; i < r_numMapTiles; i++)
518 
519  for (i = 0; i < r_numModelsInline; i++)
521 }
522 
524 {
525  if (!s->image) {
526  Com_Printf("R_LoadAnimImages: Texture not defined in anim stage.\n");
527  return -1;
528  }
529 
530  char name[MAX_QPATH];
531  Q_strncpyz(name, s->image->name, sizeof(name));
532  int j = strlen(name);
533 
534  if (name[j - 1] != '0') {
535  Com_Printf("R_LoadAnimImages: Texture name does not end in 0: %s\n", name);
536  return -1;
537  }
538 
539  /* the first image was already loaded by the stage parse, so just copy
540  * the pointer into the images array */
541 
542  s->anim.images[0] = s->image;
543  name[j - 1] = 0;
544 
545  /* now load the rest */
546  for (int i = 0; i < s->anim.num_frames; i++) {
547  const char* c = va("%s%d", name, i);
548  image_t* image = R_FindImage(c, it_material);
549  s->anim.images[i] = image;
550  if (image == r_noTexture) {
551  Com_Printf("R_LoadAnimImages: Failed to resolve texture: %s\n", c);
552  return -1;
553  }
554  }
555 
556  return 0;
557 }
558 
563 static int R_ParseStage (materialStage_t* s, const char** buffer)
564 {
565  int i;
566 
567  while (true) {
568  const char* c = Com_Parse(buffer);
569 
570  if (c[0] == '\0')
571  break;
572 
573  if (Q_streq(c, "glowscale")) {
574  s->glowscale = atof(Com_Parse(buffer));
575  if (s->glowscale < 0.0) {
576  Com_Printf("R_LoadMaterials: Invalid glowscale value for %s\n", c);
577  s->glowscale = defaultMaterial.glowscale;
578  }
579  continue;
580  }
581 
582  if (Q_streq(c, "texture")) {
583  c = Com_Parse(buffer);
584  s->image = R_FindImage(va("textures/%s", c), it_material);
585 
586  if (s->image == r_noTexture) {
587  Com_Printf("R_ParseStage: Failed to resolve texture: %s\n", c);
588  return -1;
589  }
590 
591  s->flags |= STAGE_TEXTURE;
592  continue;
593  }
594 
595  if (Q_streq(c, "envmap")) {
596  c = Com_Parse(buffer);
597  i = atoi(c);
598 
599  if (i > -1 && i < MAX_ENVMAPTEXTURES)
600  s->image = r_envmaptextures[i];
601  else
602  s->image = R_FindImage(va("pics/envmaps/%s", c), it_material);
603 
604  if (s->image == r_noTexture) {
605  Com_Printf("R_ParseStage: Failed to resolve envmap: %s\n", c);
606  return -1;
607  }
608 
609  s->flags |= STAGE_ENVMAP;
610  continue;
611  }
612 
613  if (Q_streq(c, "blend")) {
614  c = Com_Parse(buffer);
615  s->blend.src = R_ConstByName(c);
616 
617  if (s->blend.src == -1) {
618  Com_Printf("R_ParseStage: Failed to resolve blend src: %s\n", c);
619  return -1;
620  }
621 
622  c = Com_Parse(buffer);
623  s->blend.dest = R_ConstByName(c);
624 
625  if (s->blend.dest == -1) {
626  Com_Printf("R_ParseStage: Failed to resolve blend dest: %s\n", c);
627  return -1;
628  }
629 
630  s->flags |= STAGE_BLEND;
631  continue;
632  }
633 
634  if (Q_streq(c, "color")) {
635  for (i = 0; i < 3; i++) {
636  c = Com_Parse(buffer);
637  s->color[i] = atof(c);
638 
639  if (s->color[i] < 0.0 || s->color[i] > 1.0) {
640  Com_Printf("R_ParseStage: Failed to resolve color: %s\n", c);
641  return -1;
642  }
643  }
644 
645  s->flags |= STAGE_COLOR;
646  continue;
647  }
648 
649  if (Q_streq(c, "pulse")) {
650  c = Com_Parse(buffer);
651  s->pulse.hz = atof(c);
652  s->pulse.dutycycle = 1.0;
653 
654  if (s->pulse.hz < 0.0) {
655  Com_Printf("R_ParseStage: Failed to resolve frequency: %s\n", c);
656  return -1;
657  }
658 
659  s->flags |= STAGE_PULSE;
660  continue;
661  }
662 
663  if (Q_streq(c, "dutycycle")) {
664  c = Com_Parse(buffer);
665  s->pulse.dutycycle = atof(c);
666 
667  if (s->pulse.dutycycle < 0.0 || s->pulse.dutycycle > 1.0) {
668  Com_Printf("R_ParseStage: Failed to resolve pulse duty cycle: %s\n", c);
669  return -1;
670  }
671 
672  continue;
673  }
674 
675  if (Q_streq(c, "stretch")) {
676  c = Com_Parse(buffer);
677  s->stretch.amp = atof(c);
678 
679  if (s->stretch.amp < 0.0) {
680  Com_Printf("R_ParseStage: Failed to resolve amplitude: %s\n", c);
681  return -1;
682  }
683 
684  c = Com_Parse(buffer);
685  s->stretch.hz = atof(c);
686 
687  if (s->stretch.hz < 0.0) {
688  Com_Printf("R_ParseStage: Failed to resolve frequency: %s\n", c);
689  return -1;
690  }
691 
692  s->flags |= STAGE_STRETCH;
693  continue;
694  }
695 
696  if (Q_streq(c, "rotate")) {
697  c = Com_Parse(buffer);
698  s->rotate.hz = atof(c);
699 
700  if (s->rotate.hz < 0.0) {
701  Com_Printf("R_ParseStage: Failed to resolve rotate: %s\n", c);
702  return -1;
703  }
704 
705  s->flags |= STAGE_ROTATE;
706  continue;
707  }
708 
709  if (Q_streq(c, "scroll.s")) {
710  c = Com_Parse(buffer);
711  s->scroll.s = atof(c);
712 
713  s->flags |= STAGE_SCROLL_S;
714  continue;
715  }
716 
717  if (Q_streq(c, "scroll.t")) {
718  c = Com_Parse(buffer);
719  s->scroll.t = atof(c);
720 
721  s->flags |= STAGE_SCROLL_T;
722  continue;
723  }
724 
725  if (Q_streq(c, "scale.s")) {
726  c = Com_Parse(buffer);
727  s->scale.s = atof(c);
728 
729  s->flags |= STAGE_SCALE_S;
730  continue;
731  }
732 
733  if (Q_streq(c, "scale.t")) {
734  c = Com_Parse(buffer);
735  s->scale.t = atof(c);
736 
737  s->flags |= STAGE_SCALE_T;
738  continue;
739  }
740 
741  if (Q_streq(c, "terrain")) {
742  c = Com_Parse(buffer);
743  s->terrain.floor = atof(c);
744 
745  c = Com_Parse(buffer);
746  s->terrain.ceil = atof(c);
747  if (s->terrain.ceil < s->terrain.floor) {
748  Com_Printf("R_ParseStage: Inverted terrain ceiling and floor "
749  "values for %s\n", (s->image ? s->image->name : "nullptr"));
750  return -1;
751  }
752 
753  s->terrain.height = s->terrain.ceil - s->terrain.floor;
754 
755  if (s->terrain.height == 0.0) {
756  Com_Printf("R_ParseStage: Zero height terrain specified for %s\n",
757  (s->image ? s->image->name : "nullptr"));
758  return -1;
759  }
760 
761  s->flags |= STAGE_TERRAIN;
762  continue;
763  }
764 
765  if (Q_streq(c, "tape")) {
766  c = Com_Parse(buffer);
767  s->tape.center = atof(c);
768 
769  /* how much downwards? */
770  c = Com_Parse(buffer);
771  s->tape.floor = atof(c);
772 
773  /* how much upwards? */
774  c = Com_Parse(buffer);
775  s->tape.ceil = atof(c);
776 
777  s->tape.min = s->tape.center - s->tape.floor;
778  s->tape.max = s->tape.center + s->tape.ceil;
779  s->tape.height = s->tape.floor + s->tape.ceil;
780 
781  if (s->tape.height == 0.0) {
782  Com_Printf("R_ParseStage: Zero height tape specified for %s\n",
783  (s->image ? s->image->name : "nullptr"));
784  return -1;
785  }
786 
787  s->flags |= STAGE_TAPE;
788  continue;
789  }
790 
791  if (Q_streq(c, "dirtmap")) {
792  c = Com_Parse(buffer);
793  s->dirt.intensity = atof(c);
794  if (s->dirt.intensity <= 0.0 || s->dirt.intensity > 1.0) {
795  Com_Printf("R_ParseStage: Invalid dirtmap intensity for %s\n",
796  (s->image ? s->image->name : "nullptr"));
797  return -1;
798  }
799  s->flags |= STAGE_DIRTMAP;
800  continue;
801  }
802 
803  if (char const* const rest = Q_strstart(c, "anim")) {
804  switch (rest[0]) {
805  case 'a':
806  s->anim.type = ANIM_ALTERNATE;
807  break;
808  case 'b':
809  s->anim.type = ANIM_BACKWARDS;
810  break;
811  case 'r':
812  s->anim.type = ANIM_RANDOM;
813  break;
814  case 'f':
816  break;
817  default:
818  s->anim.type = ANIM_NORMAL;
819  break;
820  }
821  c = Com_Parse(buffer);
822  s->anim.num_frames = atoi(c);
823 
824  if (s->anim.num_frames < 1 || s->anim.num_frames > MAX_ANIM_FRAMES) {
825  Com_Printf("R_ParseStage: Invalid number of anim frames for %s (max is %i)\n",
826  (s->image ? s->image->name : "nullptr"), MAX_ANIM_FRAMES);
827  return -1;
828  }
829 
830  c = Com_Parse(buffer);
831  s->anim.fps = atof(c);
832 
833  if (s->anim.fps <= 0) {
834  Com_Printf("R_ParseStage: Invalid anim fps for %s\n",
835  (s->image ? s->image->name : "nullptr"));
836  return -1;
837  }
838 
839  /* the frame images are loaded once the stage is parsed completely */
840 
841  s->flags |= STAGE_ANIM;
842  continue;
843  }
844 
845  if (Q_streq(c, "glowmaplink")) {
846  s->flags |= STAGE_GLOWMAPLINK;
847  continue;
848  }
849 
850  if (Q_streq(c, "lightmap")) {
851  s->flags |= STAGE_LIGHTMAP;
852  continue;
853  }
854 
855  if (Q_streq(c, "flare")) {
856  c = Com_Parse(buffer);
857  i = atoi(c);
858 
859  if (i > -1 && i < NUM_FLARETEXTURES)
860  s->image = r_flaretextures[i];
861  else
862  s->image = R_FindImage(va("pics/flares/%s", c), it_material);
863 
864  if (s->image == r_noTexture) {
865  Com_Printf("R_ParseStage: Failed to resolve flare: %s\n", c);
866  return -1;
867  }
868 
869  s->flags |= STAGE_FLARE;
870  continue;
871  }
872 
873  if (*c == '}') {
874  Com_DPrintf(DEBUG_RENDERER, "Parsed stage\n"
875  " flags: %d\n"
876  " image: %s\n"
877  " blend: %d %d\n"
878  " color: %3f %3f %3f\n"
879  " pulse: %3f\n"
880  " pulse duty cycle: %1.2f\n"
881  " stretch: %3f %3f\n"
882  " rotate: %3f\n"
883  " scroll.s: %3f\n"
884  " scroll.t: %3f\n"
885  " scale.s: %3f\n"
886  " scale.t: %3f\n"
887  " terrain.floor: %5f\n"
888  " terrain.ceil: %5f\n"
889  " anim.num_frames: %d\n"
890  " anim.fps: %3f\n",
891  s->flags, (s->image ? s->image->name : "nullptr"),
892  s->blend.src, s->blend.dest,
893  s->color[0], s->color[1], s->color[2],
894  s->pulse.hz, s->pulse.dutycycle, s->stretch.amp, s->stretch.hz,
895  s->rotate.hz, s->scroll.s, s->scroll.t,
896  s->scale.s, s->scale.t, s->terrain.floor, s->terrain.ceil,
897  s->anim.num_frames, s->anim.fps);
898 
899  /* a texture or envmap means render it */
900  if (s->flags & (STAGE_TEXTURE | STAGE_ENVMAP))
901  s->flags |= STAGE_RENDER;
902 
903  if (s->flags & (STAGE_TERRAIN | STAGE_DIRTMAP))
904  s->flags |= STAGE_LIGHTING;
905 
906  return 0;
907  }
908 
909  Com_Printf("Invalid token: '%s'\n", c);
910  }
911 
912  Com_Printf("R_ParseStage: Malformed stage\n");
913  return -1;
914 }
915 
920 void R_LoadMaterials (const char* map)
921 {
923  map = r_overridematerial->string;
924  }
925 
926  /* clear previously loaded materials */
928 
929  if (map[0] == '+' || map[0] == '-')
930  map++;
931  else if (map[0] == '-')
932  return;
933 
934  /* load the materials file for parsing */
935  char path[MAX_QPATH];
936  Com_sprintf(path, sizeof(path), "materials/%s.mat", Com_SkipPath(map));
937 
938  byte* fileBuffer;
939  if (FS_LoadFile(path, &fileBuffer) < 1) {
940  Com_DPrintf(DEBUG_RENDERER, "Couldn't load %s\n", path);
941  return;
942  } else {
943  Com_Printf("load material file: '%s'\n", path);
944  if (!r_materials->integer)
945  Com_Printf("...ignore materials (r_materials is deactivated)\n");
946  }
947 
948  const char* buffer = (const char*)fileBuffer;
949 
950  bool inmaterial = false;
951  image_t* image = nullptr;
952  material_t* m = nullptr;
953 
954  while (true) {
955  const char* c = Com_Parse(&buffer);
956 
957  if (c[0] == '\0')
958  break;
959 
960  if (*c == '{' && !inmaterial) {
961  inmaterial = true;
962  continue;
963  }
964 
965  if (Q_streq(c, "material")) {
966  c = Com_Parse(&buffer);
967  image = R_GetImage(va("textures/%s", c));
968  if (image == nullptr)
969  Com_DPrintf(DEBUG_RENDERER, "R_LoadMaterials: skip texture: %s - not used in the map\n", c);
970 
971  continue;
972  }
973 
974  if (!image)
975  continue;
976 
977  m = &image->material;
978 
979  if (Q_streq(c, "normalmap")){
980  c = Com_Parse(&buffer);
981  image->normalmap = R_FindImage(va("textures/%s", c), it_normalmap);
982 
983  if (image->normalmap == r_noTexture){
984  Com_Printf("R_LoadMaterials: Failed to resolve normalmap: %s\n", c);
985  image->normalmap = nullptr;
986  }
987  }
988 
989  if (Q_streq(c, "glowmap")){
990  c = Com_Parse(&buffer);
991  image->glowmap = R_FindImage(va("textures/%s", c), it_glowmap);
992 
993  if (image->glowmap == r_noTexture){
994  Com_Printf("R_LoadMaterials: Failed to resolve glowmap: %s\n", c);
995  image->glowmap = nullptr;
996  }
997  }
998 
999  if (Q_streq(c, "bump")) {
1000  m->bump = atof(Com_Parse(&buffer));
1001  if (m->bump < 0.0) {
1002  Com_Printf("R_LoadMaterials: Invalid bump value for %s\n", image->name);
1003  m->bump = defaultMaterial.bump;
1004  }
1005  }
1006 
1007  if (Q_streq(c, "parallax")) {
1008  m->parallax = atof(Com_Parse(&buffer));
1009  if (m->parallax < 0.0) {
1010  Com_Printf("R_LoadMaterials: Invalid parallax value for %s\n", image->name);
1011  m->parallax = defaultMaterial.parallax;
1012  }
1013  }
1014 
1015  if (Q_streq(c, "hardness")) {
1016  m->hardness = atof(Com_Parse(&buffer));
1017  if (m->hardness < 0.0) {
1018  Com_Printf("R_LoadMaterials: Invalid hardness value for %s\n", image->name);
1019  m->hardness = defaultMaterial.hardness;
1020  }
1021  }
1022 
1023  if (Q_streq(c, "specular")) {
1024  m->specular = atof(Com_Parse(&buffer));
1025  if (m->specular < 0.0) {
1026  Com_Printf("R_LoadMaterials: Invalid specular value for %s\n", image->name);
1027  m->specular = defaultMaterial.specular;
1028  }
1029  }
1030 
1031  if (Q_streq(c, "glowscale")) {
1032  m->glowscale = atof(Com_Parse(&buffer));
1033  if (m->glowscale < 0.0) {
1034  Com_Printf("R_LoadMaterials: Invalid glowscale value for %s\n", image->name);
1035  m->glowscale = defaultMaterial.glowscale;
1036  }
1037  }
1038 
1039  if (*c == '{' && inmaterial) {
1041  s->glowscale = defaultMaterial.glowscale;
1042 
1043  if (R_ParseStage(s, &buffer) == -1) {
1044  Mem_Free(s);
1045  continue;
1046  }
1047 
1048  /* load animation frame images */
1049  if (s->flags & STAGE_ANIM) {
1050  if (R_LoadAnimImages(s) == -1) {
1051  Mem_Free(s);
1052  continue;
1053  }
1054  }
1055 
1056  /* append the stage to the chain */
1057  if (!m->stages)
1058  m->stages = s;
1059  else {
1060  materialStage_t* ss = m->stages;
1061  while (ss->next)
1062  ss = ss->next;
1063  ss->next = s;
1064  }
1065 
1066  m->flags |= s->flags;
1067  m->num_stages++;
1068  continue;
1069  }
1070 
1071  if (*c == '}' && inmaterial) {
1072  Com_DPrintf(DEBUG_RENDERER, "Parsed material %s with %d stages\n", image->name, m->num_stages);
1073  inmaterial = false;
1074  image = nullptr;
1075  /* multiply stage glowscale values by material glowscale */
1076  materialStage_t* ss = m->stages;
1077  while (ss) {
1078  ss->glowscale *= m->glowscale;
1079  ss = ss->next;
1080  }
1081  }
1082  }
1083 
1084  FS_FreeFile(fileBuffer);
1085 
1087 }
1088 
1092 void R_UpdateDefaultMaterial (const char* cvarName, const char* oldValue, const char* newValue, void* data)
1093 {
1094  defaultMaterial.specular = r_default_specular->value;
1095  defaultMaterial.hardness = r_default_hardness->value;
1096 }
float min
Definition: r_material.h:109
#define UPDATE_THRESHOLD
Definition: r_material.cpp:36
float s
Definition: r_material.h:91
float t
Definition: r_material.h:96
#define VectorCopy(src, dest)
Definition: vector.h:51
void R_EnableTexture(gltexunit_t *texunit, bool enable)
Definition: r_state.cpp:303
void R_EnableBumpmap(const image_t *normalmap)
Enables bumpmapping and binds the given normalmap.
Definition: r_state.cpp:465
unsigned flags
Definition: r_material.h:133
float hz
Definition: r_material.h:86
#define VectorSet(v, x, y, z)
Definition: vector.h:59
cvar_t * r_default_specular
Definition: r_main.cpp:82
#define STAGE_TAPE
Definition: r_material.h:44
image_t * image
Definition: r_model_brush.h:71
static int R_ParseStage(materialStage_t *s, const char **buffer)
Material stage parser.
Definition: r_material.cpp:563
void R_LoadMaterials(const char *map)
Load material definitions for each map that has one.
Definition: r_material.cpp:920
const char * Com_SkipPath(const char *pathname)
Returns just the filename from a given path.
Definition: shared.cpp:37
#define STAGE_RENDER
Definition: r_material.h:55
#define STAGE_STRETCH
Definition: r_material.h:37
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition: shared.cpp:410
void R_CreateSurfaceFlare(mBspSurface_t *surf)
Definition: r_flare.cpp:24
float max
Definition: r_material.h:110
static void R_StageTexCoord(const materialStage_t *stage, const vec3_t v, const vec2_t in, vec2_t out)
Generates a single texture coordinate for the specified stage and vertex.
Definition: r_material.cpp:219
model_t * r_mapTiles[MAX_MAPTILES]
The world model(s)
Definition: r_model.cpp:32
void R_BindLightmapTexture(GLuint texnum)
Definition: r_state.cpp:90
#define STAGE_TERRAIN
Definition: r_material.h:43
stretch_t stretch
Definition: r_material.h:138
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
GLfloat * vertex_array_3d
Definition: r_state.h:100
static void R_CreateMaterialData(void)
Definition: r_material.cpp:512
float floor
Definition: r_material.h:106
#define STAGE_ROTATE
Definition: r_material.h:38
unsigned int src
Definition: r_material.h:77
void R_BlendFunc(GLenum src, GLenum dest)
Definition: r_state.cpp:232
surfaces are assigned to arrays based on their primary rendering type and then sorted by world textur...
static void R_StageTextureMatrix(const mBspSurface_t *surf, const materialStage_t *stage)
Manages texture matrix manipulations for stages supporting rotations, scrolls, and stretches (rotate...
Definition: r_material.cpp:171
GLfloat * normal_array
Definition: r_state.h:104
float value
Definition: cvar.h:80
local graphics definitions
static void R_DrawSurfaceStage(mBspSurface_t *surf, materialStage_t *stage)
Render the specified stage for the surface. Resolve vertex attributes via helper functions, outputting to the default vertex arrays.
Definition: r_material.cpp:349
float bump
Definition: r_material.h:159
static void R_SetSurfaceStageState(const mBspSurface_t *surf, const materialStage_t *stage)
Manages all state for the specified surface and stage.
Definition: r_material.cpp:292
static const float dirtmap[]
Array with 'random' alpha values for the dirtmap.
Definition: r_material.cpp:232
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition: files.cpp:384
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
image_t * r_envmaptextures[MAX_ENVMAPTEXTURES]
Definition: r_image.cpp:50
image_t * r_noTexture
Definition: r_main.cpp:51
float t
Definition: r_material.h:91
float intensity
Definition: r_material.h:69
void VectorNormalizeFast(vec3_t v)
fast vector normalize routine that does not check to make sure that length != 0, nor does it return l...
Definition: mathlib.cpp:762
void R_UpdateDefaultMaterial(const char *cvarName, const char *oldValue, const char *newValue, void *data)
Change listener callback for material value cvars.
float floor
Definition: r_material.h:100
model_t r_modelsInline[MAX_MOD_KNOWN]
Definition: r_model.cpp:36
animLoop_t type
Definition: r_material.h:125
float ceil
Definition: r_material.h:101
int width
Definition: r_image.h:64
int integer
Definition: cvar.h:81
#define STAGE_DIRTMAP
Definition: r_material.h:47
#define texunit_lightmap
Definition: r_state.h:69
const GLuint *typedef GLuint *typedef GLenum
Definition: r_gl.h:190
static void R_UpdateMaterial(material_t *m)
Materials "think" every few milliseconds to advance animations.
Definition: r_material.cpp:40
float center
Definition: r_material.h:111
int r_numMapTiles
Definition: r_model.cpp:33
float deg
Definition: r_material.h:73
#define DEFAULT_BUMP
Definition: r_material.h:150
#define DEFAULT_GLOWSCALE
Definition: r_material.h:154
unsigned int dest
Definition: r_material.h:77
#define Q_strvalid(string)
Definition: shared.h:141
void R_SetSurfaceBumpMappingParameters(const mBspSurface_t *surf, const image_t *normalMap, const image_t *specularMap)
Definition: r_surface.cpp:32
void R_Color(const vec4_t rgba)
Change the color to given value.
Definition: r_state.cpp:1011
float amp
Definition: r_material.h:87
#define STAGE_FLARE
Definition: r_material.h:48
bool lighting_enabled
Definition: r_state.h:154
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
Definition: r_image.cpp:603
float dhz
Definition: r_material.h:81
vec3_t viewOrigin
Definition: cl_renderer.h:172
lightmap definitions
static void R_StageVertex(const mBspSurface_t *surf, const materialStage_t *stage, const vec3_t in, vec3_t out)
Vertex deformation.
Definition: r_material.cpp:162
GLfloat * tangent_array
Definition: r_state.h:105
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
#define STAGE_LIGHTMAP
Definition: r_material.h:45
materialStage_t * stages
Definition: r_material.h:164
#define STAGE_TEXTURE_MATRIX
Definition: r_material.h:58
float dt
Definition: r_material.h:92
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition: vector.h:44
cvar_t * r_default_hardness
Definition: r_main.cpp:83
void R_ImageClearMaterials(void)
Free previously loaded materials and their stages.
Definition: r_image.cpp:61
void R_ReallocateTexunitArray(gltexunit_t *texunit, int size)
Reallocate texcoord array of the specified texunit, if needed.
Definition: r_state.cpp:1059
float hz
Definition: r_material.h:81
rendererData_t refdef
Definition: r_main.cpp:45
#define Vector4Set(v, r, g, b, a)
Definition: vector.h:62
rlocals_t r_locals
Definition: r_main.cpp:49
char name[MAX_QPATH]
Definition: r_image.h:62
mBspSurface_t ** surfaces
#define M_PI
Definition: mathlib.h:34
float * texcoords
int frame
Definition: r_local.h:109
float * tangents
#define MAX_ENVMAPTEXTURES
Definition: r_image.h:111
#define NUM_FLARETEXTURES
Definition: r_image.h:114
void R_ResetArrayState(void)
Definition: r_array.cpp:185
void R_EnableColorArray(bool enable)
Definition: r_state.cpp:332
scroll_t scroll
Definition: r_material.h:140
struct image_s * images[MAX_ANIM_FRAMES]
Definition: r_material.h:126
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition: shared.cpp:587
blendmode_t blend
Definition: r_material.h:135
#define STAGE_TEXTURE
Definition: r_material.h:32
static int R_LoadAnimImages(materialStage_t *s)
Definition: r_material.cpp:523
GLuint glElementIndex_t
Definition: r_gl.h:57
mBspTexInfo_t * texinfo
#define STAGE_ENVMAP
Definition: r_material.h:33
float dutycycle
Definition: r_material.h:82
material_t defaultMaterial
Definition: r_material.cpp:34
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
float height
Definition: r_material.h:102
#define MAX_ANIM_FRAMES
Definition: r_material.h:64
int r_numModelsInline
Definition: r_model.cpp:37
struct image_s * glowmap
Definition: r_image.h:70
mBspSurface_t * surfaces
unsigned flags
Definition: r_material.h:157
#define DEFAULT_SPECULAR
Definition: r_material.h:152
float ds
Definition: r_material.h:92
struct image_s * specularmap
Definition: r_image.h:71
float specular
Definition: r_material.h:162
bool color_array_enabled
Definition: r_state.h:151
QGL_EXTERN GLuint index
Definition: r_gl.h:110
#define STAGE_SCROLL_T
Definition: r_material.h:40
cvar_t * r_wire
Definition: r_main.cpp:91
#define STAGE_PULSE
Definition: r_material.h:36
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
static void R_CreateMaterialData_(model_t *mod)
Definition: r_material.cpp:503
void R_DrawMaterialSurfaces(const mBspSurfaces_t *surfs, glElementIndex_t *indexPtr)
Iterates the specified surfaces list, updating materials as they are encountered, and rendering all v...
Definition: r_material.cpp:399
float fps
Definition: r_material.h:127
float * lmtexcoords
cvar_t * r_overridematerial
Definition: r_main.cpp:81
#define STAGE_COLOR
Definition: r_material.h:35
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition: parse.cpp:107
float parallax
Definition: r_material.h:160
#define texunit_diffuse
Definition: r_state.h:68
#define STAGE_SCROLL_S
Definition: r_material.h:39
r_program_t * world_program
Definition: r_state.h:132
image_t * r_flaretextures[NUM_FLARETEXTURES]
Definition: r_image.cpp:53
mBspSurfaces_t r_material_surfaces
Definition: r_material.cpp:31
#define STAGE_LIGHTING
Definition: r_material.h:52
#define STAGE_SCALE_S
Definition: r_material.h:41
#define MAX_QPATH
Definition: filesys.h:40
float * verts
QGL_EXTERN GLint i
Definition: r_gl.h:113
int num_stages
Definition: r_material.h:165
char * string
Definition: cvar.h:73
float damp
Definition: r_material.h:87
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
float s
Definition: r_material.h:96
int height
Definition: r_image.h:64
terrain_t terrain
Definition: r_material.h:142
static GLenum R_ConstByName(const char *c)
Translate string into glmode.
Definition: r_material.cpp:480
#define Mem_Free(ptr)
Definition: mem.h:35
cvar_t * r_materials
Definition: r_main.cpp:80
Error checking function.
vec_t vec3_t[3]
Definition: ufotypes.h:39
#define Vector2Copy(src, dest)
Definition: vector.h:52
vec_t vec2_t[2]
Definition: ufotypes.h:38
#define STAGE_SCALE_T
Definition: r_material.h:42
memPool_t * vid_imagePool
Definition: cl_main.cpp:88
bool R_EnableLighting(r_program_t *program, bool enable)
Enables hardware-accelerated lighting with the specified program. This should be called after any tex...
Definition: r_state.cpp:350
rstate_t r_state
Definition: r_main.cpp:48
float hz
Definition: r_material.h:73
bool glowmap_enabled
Definition: r_state.h:158
static void R_StageColor(const materialStage_t *stage, const vec3_t v, vec4_t color)
Generates a single color for the specified stage and vertex.
Definition: r_material.cpp:240
#define lengthof(x)
Definition: shared.h:105
#define DEFAULT_HARDNESS
Definition: r_material.h:153
#define R_CheckError()
Definition: r_error.h:30
GLsizei const GLvoid * data
Definition: r_gl.h:152
GLfloat * color_array
Definition: r_state.h:102
struct image_s * normalmap
Definition: r_image.h:69
rotate_t rotate
Definition: r_material.h:139
float height
Definition: r_material.h:108
float glowscale
Definition: r_material.h:163
#define Q_streq(a, b)
Definition: shared.h:136
float time
Definition: r_material.h:158
float * normals
#define Mem_PoolAllocType(type, pool)
Definition: mem.h:43
#define STAGE_GLOWMAPLINK
Definition: r_material.h:49
void R_ReallocateStateArrays(int size)
Reallocate arrays of GL primitives if needed.
Definition: r_state.cpp:1029
image_t * R_GetImage(const char *name)
Definition: r_image.cpp:452
struct image_s * image
Definition: r_material.h:134
#define STAGE_BLEND
Definition: r_material.h:34
int num_frames
Definition: r_material.h:124
uint8_t byte
Definition: ufotypes.h:34
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
bool blend_enabled
Definition: r_state.h:149
void R_ProgramParameter1f(const char *name, GLfloat value)
Definition: r_program.cpp:121
#define STAGE_ANIM
Definition: r_material.h:46
float ceil
Definition: r_material.h:107
material_t material
Definition: r_image.h:68
#define DEBUG_RENDERER
Definition: defines.h:62
static void R_StageLighting(const mBspSurface_t *surf, const materialStage_t *stage)
Manages state for stages supporting static, dynamic, and per-pixel lighting.
Definition: r_material.cpp:130
static struct mdfour * m
Definition: md4.cpp:35
float hardness
Definition: r_material.h:161
void R_EnableModelLights(const light_t **lights, int numLights, bool inShadow, bool enable)
Enable or disable realtime dynamic lighting for models.
Definition: r_light.cpp:149
#define VectorSubtract(a, b, dest)
Definition: vector.h:45
static void R_StageGlow(const materialStage_t *stage)
Definition: r_material.cpp:109
#define R_BindTexture(tn)
Definition: r_state.h:184
const struct image_s * active_normalmap
Definition: r_state.h:166
void R_EnableGlowMap(const image_t *image)
Definition: r_state.cpp:664
void R_EnableFog(bool enable)
Definition: r_state.cpp:586
struct materialStage_s * next
Definition: r_material.h:147
void FS_FreeFile(void *buffer)
Definition: files.cpp:411
#define MSURF_LIGHTMAP
Definition: r_model_brush.h:51
GLuint texnum
Definition: r_image.h:66
unsigned int index
vec_t vec4_t[4]
Definition: ufotypes.h:40
#define DEFAULT_PARALLAX
Definition: r_material.h:151
mBspModel_t bsp
Definition: r_model.h:60