UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_misc.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 "r_local.h"
26 #include "r_misc.h"
27 #include "r_error.h"
28 #include "r_font.h"
29 #include "r_model.h"
30 #include "../../shared/images.h"
31 
32 static const byte gridtexture[8][8] = {
33  {1, 1, 1, 1, 1, 1, 1, 1},
34  {1, 0, 0, 0, 0, 0, 0, 1},
35  {1, 0, 0, 0, 0, 0, 0, 1},
36  {1, 0, 0, 0, 0, 0, 0, 1},
37  {1, 0, 0, 0, 0, 0, 0, 1},
38  {1, 0, 0, 0, 0, 0, 0, 1},
39  {1, 0, 0, 0, 0, 0, 0, 1},
40  {1, 1, 1, 1, 1, 1, 1, 1},
41 };
42 
43 static const byte dummytexture[4] = {255, 255, 255, 255};
44 
45 #define MISC_TEXTURE_SIZE 16
46 void R_InitMiscTexture (void)
47 {
48  int x, y;
50 
51  OBJZERO(data);
52 
53  /* also use this for bad textures, but without alpha */
54  for (x = 0; x < 8; x++) {
55  for (y = 0; y < 8; y++) {
56  data[y][x][0] = gridtexture[x][y] * 255;
57  data[y][x][3] = 255;
58  }
59  }
60  r_noTexture = R_LoadImageData("***r_notexture***", (byte*) data, 8, 8, it_effect);
61 
62  for (x = 0; x < MISC_TEXTURE_SIZE; x++) {
63  for (y = 0; y < MISC_TEXTURE_SIZE; y++) {
64  data[y][x][0] = rand() % 255;
65  data[y][x][1] = rand() % 255;
66  data[y][x][2] = rand() % 48;
67  data[y][x][3] = rand() % 48;
68  }
69  }
70  r_warpTexture = R_LoadImageData("***r_warptexture***", (byte*)data, MISC_TEXTURE_SIZE, MISC_TEXTURE_SIZE, it_effect);
71 
72  /* 1x1 pixel white texture to be used when texturing is required, but texture is not available */
73  r_dummyTexture = R_LoadImageData("***r_dummytexture***", dummytexture, 1, 1, it_effect);
74 
75  /* empty pic in the texture chain for cinematic frames */
76  R_LoadImageData("***cinematic***", nullptr, VID_NORM_WIDTH, VID_NORM_HEIGHT, it_pic);
77 }
78 
79 /*
80 ==============================================================================
81 SCREEN SHOTS
82 ==============================================================================
83 */
84 
85 enum {
90 };
91 
101 void R_ScreenShot (int x, int y, int width, int height, const char* filename, const char* ext)
102 {
103  char checkName[MAX_OSPATH];
104  int type, quality = 100;
105  int rowPack;
106 
107  glGetIntegerv(GL_PACK_ALIGNMENT, &rowPack);
108  glPixelStorei(GL_PACK_ALIGNMENT, 1);
109 
110  /* Find out what format to save in */
111  if (ext == nullptr)
113 
114  if (!Q_strcasecmp(ext, "png"))
115  type = SSHOTTYPE_PNG;
116  else if (!Q_strcasecmp(ext, "jpg"))
117  type = SSHOTTYPE_JPG;
118  else
119  type = SSHOTTYPE_TGA_COMP;
120 
121  /* Set necessary values */
122  switch (type) {
123  case SSHOTTYPE_TGA_COMP:
124  Com_Printf("Taking TGA screenshot...\n");
125  ext = "tga";
126  break;
127 
128  case SSHOTTYPE_PNG:
129  Com_Printf("Taking PNG screenshot...\n");
130  ext = "png";
131  break;
132 
133  case SSHOTTYPE_JPG:
134  if (Cmd_Argc() == 3)
135  quality = atoi(Cmd_Argv(2));
136  else
138  if (quality > 100 || quality <= 0)
139  quality = 100;
140 
141  Com_Printf("Taking JPG screenshot (at %i%% quality)...\n", quality);
142  ext = "jpg";
143  break;
144  }
145 
146  /* Find a file name to save it to */
147  if (filename) {
148  Com_sprintf(checkName, sizeof(checkName), "scrnshot/%s.%s", filename, ext);
149  } else {
150  int shotNum;
151  for (shotNum = 0; shotNum < 1000; shotNum++) {
152  Com_sprintf(checkName, sizeof(checkName), "scrnshot/ufo%i%i.%s", shotNum / 10, shotNum % 10, ext);
153  if (FS_CheckFile("%s", checkName) == -1)
154  break;
155  }
156  if (shotNum == 1000) {
157  Com_Printf("R_ScreenShot_f: screenshot limit (of 1000) exceeded!\n");
158  return;
159  }
160  }
161 
162  /* Open it */
163  ScopedFile f;
164  FS_OpenFile(checkName, &f, FILE_WRITE);
165  if (!f) {
166  Com_Printf("R_ScreenShot_f: Couldn't create file: %s\n", checkName);
167  return;
168  }
169 
170  /* Allocate room for a copy of the framebuffer */
171  byte* const buffer = Mem_PoolAllocTypeN(byte, width * height * 3, vid_imagePool);
172  if (!buffer) {
173  Com_Printf("R_ScreenShot_f: Could not allocate %i bytes for screenshot!\n", width * height * 3);
174  return;
175  }
176 
177  /* Read the framebuffer into our storage */
178  glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
179  R_CheckError();
180 
181  /* Write */
182  switch (type) {
183  case SSHOTTYPE_TGA_COMP:
184  R_WriteCompressedTGA(&f, buffer, width, height);
185  break;
186 
187  case SSHOTTYPE_PNG:
188  R_WritePNG(&f, buffer, width, height);
189  break;
190 
191  case SSHOTTYPE_JPG:
192  R_WriteJPG(&f, buffer, width, height, quality);
193  break;
194  }
195 
196  /* Finish */
197  Mem_Free(buffer);
198 
199  Com_Printf("Wrote %s to %s\n", checkName, FS_Gamedir());
200  glPixelStorei(GL_PACK_ALIGNMENT, rowPack);
201 }
202 
203 void R_ScreenShot_f (void)
204 {
205  const char* ext = nullptr;
206  if (Cmd_Argc() > 1)
207  ext = Cmd_Argv(1);
208  R_ScreenShot(0, 0, viddef.context.width, viddef.context.height, nullptr, ext);
209 }
210 
220 void R_Transform (const vec3_t transform, const vec3_t rotate, const vec3_t scale)
221 {
222  if (transform != nullptr) {
223  glTranslatef(transform[0], transform[1], transform[2]);
224  }
225 
226  if (rotate != nullptr) {
227  glRotatef(rotate[0], 0, 0, 1);
228  glRotatef(rotate[1], 0, 1, 0);
229  glRotatef(rotate[2], 1, 0, 0);
230  }
231 
232  if (scale != nullptr) {
233  glScalef(scale[0], scale[1], scale[2]);
234  }
235 }
236 
240 void R_PushMatrix (void)
241 {
242  glPushMatrix();
243 }
244 
248 void R_PopMatrix (void)
249 {
250  glPopMatrix();
251 }
252 
256 void R_DumpOpenGlState (void)
257 {
258 #define CAPABILITY( X ) {GL_ ## X, # X}
259  /* List taken from here: http://www.khronos.org/opengles/sdk/1.1/docs/man/glIsEnabled.xml */
260  const struct { GLenum idx; const char* text; } openGLCaps[] = {
261  CAPABILITY(ALPHA_TEST),
262  CAPABILITY(BLEND),
263  CAPABILITY(COLOR_ARRAY),
264  CAPABILITY(COLOR_LOGIC_OP),
265  CAPABILITY(COLOR_MATERIAL),
266  CAPABILITY(CULL_FACE),
267  CAPABILITY(DEPTH_TEST),
268  CAPABILITY(DITHER),
269  CAPABILITY(FOG),
270  CAPABILITY(LIGHTING),
271  CAPABILITY(LINE_SMOOTH),
272  CAPABILITY(MULTISAMPLE),
273  CAPABILITY(NORMAL_ARRAY),
274  CAPABILITY(NORMALIZE),
275  CAPABILITY(POINT_SMOOTH),
276  CAPABILITY(POLYGON_OFFSET_FILL),
277  CAPABILITY(RESCALE_NORMAL),
278  CAPABILITY(SAMPLE_ALPHA_TO_COVERAGE),
279  CAPABILITY(SAMPLE_ALPHA_TO_ONE),
280  CAPABILITY(SAMPLE_COVERAGE),
281  CAPABILITY(SCISSOR_TEST),
282  CAPABILITY(STENCIL_TEST),
283  CAPABILITY(VERTEX_ARRAY)
284  };
285 #undef CAPABILITY
286 
287  char s[1024] = "";
288  GLint i;
289  GLint maxTexUnits = 0;
290  GLint activeTexUnit = 0;
291  GLint activeClientTexUnit = 0;
292  GLint activeTexId = 0;
293  GLfloat texEnvMode = 0;
294  const char* texEnvModeStr = "UNKNOWN";
295  GLfloat color[4];
296 
297  for (int i = 0; i < lengthof(openGLCaps); i++) {
298  if (glIsEnabled(openGLCaps[i].idx)) {
299  Q_strcat(s, sizeof(s), "%s ", openGLCaps[i].text);
300  }
301  }
302  glGetFloatv(GL_CURRENT_COLOR, color);
303 
304  Com_Printf("OpenGL enabled caps: %s color %f %f %f %f \n", s, color[0], color[1], color[2], color[3]);
305 
306  glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexUnit);
307  glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &activeClientTexUnit);
308 
309  glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTexUnits);
310  for (i = GL_TEXTURE0; i < GL_TEXTURE0 + maxTexUnits; i++) {
311  qglActiveTexture(i);
312  qglClientActiveTexture(i);
313 
314  strcpy(s, "");
315  if (glIsEnabled (GL_TEXTURE_2D))
316  strcat(s, "enabled, ");
317  if (glIsEnabled (GL_TEXTURE_COORD_ARRAY))
318  strcat(s, "with texcoord array, ");
319  if (i == activeTexUnit)
320  strcat(s, "active, ");
321  if (i == activeClientTexUnit)
322  strcat(s, "client active, ");
323 
324  glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexId);
325  glGetTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &texEnvMode);
326  if (fabs(texEnvMode - GL_ADD) < 0.1f)
327  texEnvModeStr = "ADD";
328  if (fabs(texEnvMode - GL_MODULATE) < 0.1f)
329  texEnvModeStr = "MODULATE";
330  if (fabs(texEnvMode - GL_DECAL) < 0.1f)
331  texEnvModeStr = "DECAL";
332  if (fabs(texEnvMode - GL_BLEND) < 0.1f)
333  texEnvModeStr = "BLEND";
334  if (fabs(texEnvMode - GL_REPLACE) < 0.1f)
335  texEnvModeStr = "REPLACE";
336  if (fabs(texEnvMode - GL_COMBINE) < 0.1f)
337  texEnvModeStr = "COMBINE";
338 
339  Com_Printf("Texunit: %d texID %d %s texEnv mode %s\n", i - GL_TEXTURE0, activeTexId, s, texEnvModeStr);
340  }
341 
342  qglActiveTexture(activeTexUnit);
343  qglClientActiveTexture(activeClientTexUnit);
344 }
345 
350 {
351  /* De-allocate old GL state, these functinos will call glDeleteTexture(), so they should go before everything else */
355  R_BeginBuildingLightmaps(); /* This function will also call glDeleteTexture() */
356  /* Re-initialize GL state */
358  R_InitPrograms();
360  /* Re-upload all textures */
362  R_ReloadImages();
363  /* Re-upload other GL stuff */
364  R_InitFBObjects();
365  R_UpdateDefaultMaterial("", "", "", nullptr);
366 
367  /* Re-upload the battlescape terrain geometry */
368  if (!qglBindBuffer)
369  return;
370 
371  for (int tile = 0; tile < r_numMapTiles; tile++) {
372  model_t* mod = r_mapTiles[tile];
373 
374  int vertind = 0, coordind = 0, tangind = 0;
375  mBspSurface_t* surf = mod->bsp.surfaces;
376 
377  for (int i = 0; i < mod->bsp.numsurfaces; i++, surf++) {
378  vertind += 3 * surf->numedges;
379  coordind += 2 * surf->numedges;
380  tangind += 4 * surf->numedges;
381  }
382 
383  qglGenBuffers(1, &mod->bsp.vertex_buffer);
384  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer);
385  qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW);
386 
387  qglGenBuffers(1, &mod->bsp.texcoord_buffer);
388  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer);
389  qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW);
390 
391  qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer);
392  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer);
393  qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW);
394 
395  qglGenBuffers(1, &mod->bsp.normal_buffer);
396  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer);
397  qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW);
398 
399  qglGenBuffers(1, &mod->bsp.tangent_buffer);
400  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer);
401  qglBufferData(GL_ARRAY_BUFFER, tangind * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW);
402 
403  qglGenBuffers(1, &mod->bsp.index_buffer);
404  qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mod->bsp.index_buffer);
405  qglBufferData(GL_ELEMENT_ARRAY_BUFFER, mod->bsp.numIndexes * sizeof(glElementIndex_t), mod->bsp.indexes, GL_STATIC_DRAW);
406  qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
407 
408  for (int i = 0; i < mod->bsp.numsurfaces; i++)
410  }
411 
413  qglBindBuffer(GL_ARRAY_BUFFER, 0);
414 }
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition: cmd.cpp:516
image_t * r_dummyTexture
Definition: r_main.cpp:53
cvar_t * r_screenshot_jpeg_quality
Definition: r_main.cpp:67
int FS_CheckFile(const char *fmt,...)
Just returns the filelength and -1 if the file wasn't found.
Definition: files.cpp:298
void R_ShutdownFBObjects(void)
Delete all registered framebuffer and render buffer objects, clear memory.
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
void R_Transform(const vec3_t transform, const vec3_t rotate, const vec3_t scale)
Perform translate, rotate and scale operations on the current matrix.
Definition: r_misc.cpp:220
void R_ScreenShot_f(void)
Definition: r_misc.cpp:203
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition: files.cpp:162
unsigned int texcoord_buffer
static const vec3_t scale
model_t * r_mapTiles[MAX_MAPTILES]
The world model(s)
Definition: r_model.cpp:32
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
const char * filename
Definition: ioapi.h:41
const GLenum *typedef GLint
Definition: r_gl.h:205
void R_EndBuildingLightmaps(void)
Definition: r_lightmap.cpp:298
#define CAPABILITY(X)
void R_SetDefaultState(void)
Definition: r_state.cpp:860
image_t * R_LoadImageData(const char *name, const byte *pic, int width, int height, imagetype_t type)
Creates a new image from RGBA data. Stores it in the gltextures array and also uploads it...
Definition: r_image.cpp:475
viddef_t viddef
Definition: cl_video.cpp:34
local graphics definitions
cvar_t * r_screenshot_format
Definition: r_main.cpp:66
unsigned width
Definition: cl_video.h:44
#define MAX_OSPATH
Definition: filesys.h:44
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
void R_WriteJPG(qFILE *f, byte *buffer, int width, int height, int quality)
Definition: images.cpp:224
image_t * r_noTexture
Definition: r_main.cpp:51
void R_UpdateDefaultMaterial(const char *cvarName, const char *oldValue, const char *newValue, void *data)
Change listener callback for material value cvars.
Definition: r_image.h:45
void R_CreateSurfaceLightmap(mBspSurface_t *surf)
Definition: r_lightmap.cpp:223
int integer
Definition: cvar.h:81
const GLuint *typedef GLuint *typedef GLenum
Definition: r_gl.h:190
int r_numMapTiles
Definition: r_model.cpp:33
void R_InitMiscTexture(void)
Definition: r_misc.cpp:46
const char * FS_Gamedir(void)
Called to find where to write a file (savegames, etc)
Definition: files.cpp:68
glElementIndex_t * indexes
static const byte dummytexture[4]
Definition: r_misc.cpp:43
#define OBJZERO(obj)
Definition: shared.h:178
unsigned int normal_buffer
float * texcoords
int Cmd_Argc(void)
Return the number of arguments of the current command. "command parameter" will result in a argc of 2...
Definition: cmd.cpp:505
void R_InitFBObjects(void)
float * tangents
unsigned int tangent_buffer
void R_ResetArrayState(void)
Definition: r_array.cpp:185
void R_ShutdownPrograms(void)
Definition: r_program.cpp:265
GLuint glElementIndex_t
Definition: r_gl.h:57
#define Q_strcasecmp(a, b)
Definition: shared.h:131
viddefContext_t context
Definition: cl_video.h:67
mBspSurface_t * surfaces
void R_ScreenShot(int x, int y, int width, int height, const char *filename, const char *ext)
Definition: r_misc.cpp:101
unsigned int vertex_buffer
#define VID_NORM_WIDTH
Definition: cl_renderer.h:40
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
unsigned int lmtexcoord_buffer
float * lmtexcoords
#define VID_NORM_HEIGHT
Definition: cl_renderer.h:41
void R_ReloadImages(void)
Definition: r_image.cpp:835
float * verts
QGL_EXTERN GLint i
Definition: r_gl.h:113
void R_PopMatrix(void)
Removes the current matrix from the stack.
Definition: r_misc.cpp:248
char * string
Definition: cvar.h:73
#define Mem_Free(ptr)
Definition: mem.h:35
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
Error checking function.
void R_DumpOpenGlState(void)
Dumps OpenGL state for debugging - typically every capability set with glEnable().
Definition: r_misc.cpp:256
image_t * r_warpTexture
Definition: r_main.cpp:52
vec_t vec3_t[3]
Definition: ufotypes.h:39
void R_FontCleanCache(void)
Clears font cache and frees memory associated with the cache.
Definition: r_font.cpp:121
void R_WritePNG(qFILE *f, byte *buffer, int width, int height)
Definition: images.cpp:56
void R_ReinitOpenglContext(void)
Re-initializes OpenGL state machine, all textures and renderer variables, this needed when applicatio...
Definition: r_misc.cpp:349
memPool_t * vid_imagePool
Definition: cl_main.cpp:88
#define lengthof(x)
Definition: shared.h:105
#define R_CheckError()
Definition: r_error.h:30
GLsizei const GLvoid * data
Definition: r_gl.h:152
Brush model header file.
#define MISC_TEXTURE_SIZE
Definition: r_misc.cpp:45
void R_BeginBuildingLightmaps(void)
Definition: r_lightmap.cpp:273
void R_PushMatrix(void)
Push a new matrix to the stack.
Definition: r_misc.cpp:240
float * normals
unsigned height
Definition: cl_video.h:45
uint8_t byte
Definition: ufotypes.h:34
void R_InitPrograms(void)
Definition: r_program.cpp:1022
unsigned int index_buffer
static const byte gridtexture[8][8]
Definition: r_misc.cpp:32
mBspModel_t bsp
Definition: r_model.h:60
void R_WriteCompressedTGA(qFILE *f, const byte *buffer, int width, int height)
Definition: images.cpp:101