Crossfire Client, Trunk  R19362
opengl.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, see the
9  * 'LICENSE' and 'COPYING' files.
10  *
11  * The authors can be reached via e-mail to crossfire-devel@real-time.com
12  */
13 
27 #include <config.h>
28 
29 #ifdef HAVE_OPENGL
30 
31 #include <client-types.h>
32 
33 #include <errno.h>
34 #include <gdk/gdkkeysyms.h>
35 #include <gtk/gtk.h>
36 
37 #ifndef WIN32
38 #include <gdk/gdkx.h>
39 #else
40 #include <windows.h>
41 #include <gdk/gdkwin32.h>
42 #endif
43 
44 #include <client.h>
45 #include "main.h"
46 #include "image.h"
47 #include "mapdata.h"
48 
49 #include "gtk2proto.h"
50 
51 /* Start of Open GL includes */
52 #include <GL/gl.h>
53 #include <GL/glu.h>
54 #ifndef WIN32
55 #include <GL/glx.h>
56 #endif
57 
58 extern int time_map_redraw;
59 
60 #ifndef WIN32
61 static Display *display; /* X display & window for glx buffer swapping */
62 static Window window;
63 #else
64 static HDC devicecontext; /* Windows device context for windows buffer swapping */
65 #endif
66 static int width=1, height=1;
67 
72 static void init_opengl_common(void)
73 {
74  GLint texSize;
75 
76  /* Need to enable texture mapping */
77  glEnable(GL_TEXTURE_2D);
78  glShadeModel(GL_SMOOTH);
79 
80  /* Need to enable alpha blending */
81  glEnable(GL_BLEND);
82  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
83 
84  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
85  glClearDepth(1.0f);
86 
87 #ifndef WIN32
88  glViewport(0, 0, (float)width, (float)height);
89 #else
90  /*
91  * There is a bug somewhere that causes the viewport to be shifted up by
92  * 25-MAPHEIGHT tiles when run in Windows. Don't know yet what causes
93  * this, but this is a bad hack to fix it.
94  */
95  glViewport(0, (use_config[CONFIG_MAPHEIGHT]-25)*32, (float)width, (float)height);
96 #endif
97 
98  glMatrixMode(GL_PROJECTION);
99  glLoadIdentity();
100 
101  /* Make the upper left 0,0 coordinate */
102  glOrtho(0.0f,width,height,0.0f,-1.0f,1.0f);
103  glMatrixMode(GL_MODELVIEW);
104  glLoadIdentity();
105 
106  glFlush();
107 
108  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
109  LOG(LOG_INFO,"gtk-v2::opengl_common", "Maximum texture size is %d\n", texSize);
110 }
111 
112 #ifndef WIN32
113 
118 void init_glx_opengl(GtkWidget* drawingarea)
119 {
120  GLXContext ctx;
121  XVisualInfo *vi;
122  int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
123  GLX_RED_SIZE, 4,
124  GLX_GREEN_SIZE, 4,
125  GLX_BLUE_SIZE, 4,
126  GLX_ALPHA_SIZE, 4,
127  GLX_DEPTH_SIZE, 16,
128  None
129  };
130  XSetWindowAttributes attr;
131 
132  /* Need to tuck these away, because they are needed for glXSwappBuffers() */
133  display = GDK_WINDOW_XDISPLAY(drawingarea->window);
134  vi = glXChooseVisual(display,
135  gdk_x11_get_default_screen (), attrListDbl);
136 
137  width = drawingarea->allocation.width;
138  height = drawingarea->allocation.height;
139 
140  /*
141  * On many systems, the default visual used by the display doesn't have the
142  * features we need (alpha channel, etc). The only way around this is to
143  * create a subwindow with the ideal visual. As an oddity, we need to
144  * create a colormap if using a different visual or we get a BadMatch
145  * error.
146  */
147  DefaultVisual(display, gdk_x11_get_default_screen ());
148  attr.colormap= XCreateColormap(display, GDK_WINDOW_XID(drawingarea->window),
149  vi->visual, AllocNone);
150 
151  window = XCreateWindow(display, GDK_WINDOW_XID(drawingarea->window),
152  0, 0, width, height, 0,
153  vi->depth,
154  InputOutput,
155  vi->visual,
156  CWColormap, &attr);
157 
158  XMapWindow(display,window);
159 
160  if (!vi) {
161  LOG(LOG_WARNING,"gtk-v2::init_glx_opengl", "Could not get double buffered screen!\n");
162  }
163 
164  ctx = glXCreateContext(display, vi, 0, GL_TRUE);
165 
166  if (!glXMakeCurrent(display, window, ctx)) {
167  LOG(LOG_ERROR,"gtk-v2::init_glx_opengl", "Could not set opengl context!\n");
168  exit(1);
169  }
170  if (glXIsDirect(display, ctx)) {
171  LOG(LOG_INFO,"gtk-v2::init_glx_opengl", "Direct rendering is available!\n");
172  } else {
173  LOG(LOG_INFO,"gtk-v2::init_glx_opengl", "Direct rendering is not available!\n");
174  }
175 
176 }
177 #endif /* #ifndef WIN32 */
178 
179 #ifdef WIN32
180 
185 void init_wgl_opengl(GtkWidget* drawingarea)
186 {
187  HGLRC glctx;
188  HDC dctx;
189  int pixelformat;
190  PIXELFORMATDESCRIPTOR pfd = {
191  sizeof(PIXELFORMATDESCRIPTOR), //size of structure
192  1, //default version
193  PFD_DRAW_TO_WINDOW | //window drawing support
194  PFD_SUPPORT_OPENGL | //opengl support
195  PFD_DOUBLEBUFFER, //double buffering support
196  PFD_TYPE_RGBA, //RGBA color mode
197  16, //16 bit color mode
198  0, 0, 0, 0, 0, 0, //ignore color bits
199  4, //4 bits alpha buffer
200  0, //ignore shift bit
201  0, //no accumulation buffer
202  0, 0, 0, 0, //ignore accumulation bits
203  16, //16 bit z-buffer size
204  0, //no stencil buffer
205  0, //no aux buffer
206  PFD_MAIN_PLANE, //main drawing plane
207  0, //reserved
208  0, 0, 0 //layer masks ignored
209  };
210 
211  width = drawingarea->allocation.width;
212  height = drawingarea->allocation.height;
213 
214  dctx = GetDC(GDK_WINDOW_HWND(drawingarea->window));
215  devicecontext = dctx;
216 
217  /* Get the closest matching pixel format to what we specified and set it */
218  pixelformat = ChoosePixelFormat(dctx, &pfd);
219  SetPixelFormat(dctx, pixelformat, &pfd);
220 
221  glctx = wglCreateContext(dctx);
222  wglMakeCurrent(dctx, glctx);
223 }
224 #endif /* #ifdef WIN32 */
225 
232 void init_opengl(GtkWidget* drawingarea)
233 {
234 
235 #ifndef WIN32
236  init_glx_opengl(drawingarea);
237 #else
238  init_wgl_opengl(drawingarea);
239 #endif
240  init_opengl_common();
241 }
242 
243 /*
244  * We set up a table of darkness - when opengl draws the first layer, it fills
245  * this in - in this way, we have a table of all the darkness values that we
246  * should use - this makes dealing with darkness much faster, as we don't have
247  * to see if the space is has valid darkness, etc. We add 2 to the value to
248  * take into acount the padding of an extra space (thus, don't need special
249  * logic for final row/column). That is +1 value. but the last row also has
250  * the right/bottom side vertices, and that is where the other +1 comes from
251  */
252 static uint16 map_darkness[(MAP_MAX_SIZE+2)*2][(MAP_MAX_SIZE+2)*2];
253 
254 /*
255  * This is darkness to use if we have no darkness information. 0 makes sense
256  * for standard behaviour, but I find setting this to 255 makes for some
257  * interesting smoothing effects relative to the edge of the screen and blocked
258  * spaces. I'm not sure if anything other than 0 and 255 would be useful.
259  */
260 #define DEFAULT_DARKNESS 0
261 
281 static void opengl_light_space(int x, int y, int mx, int my)
282 {
284  /* If we don't have darkness, or it isn't dark, don't do anything */
285  if (!the_map.cells[mx][my].have_darkness || the_map.cells[mx][my].darkness==0) {
286  return;
287  }
288 
289  glColor4ub(0, 0, 0, the_map.cells[mx][my].darkness);
290  glBegin(GL_QUADS);
291  glVertex3i(x * map_image_size, y * map_image_size, 0);
292  glVertex3i((x+1) * map_image_size, y * map_image_size, 0);
293  glVertex3i((x+1) * map_image_size, (y+1) * map_image_size, 0);
294  glVertex3i(x * map_image_size, (y+1) * map_image_size, 0);
295  glEnd();
296  }
297 
298  /* Do the upper left area */
299  glBegin(GL_QUADS);
300 
301  glColor4ub(0, 0, 0, map_darkness[x*2][y*2]);
302  glVertex3i(x * map_image_size, y * map_image_size, 0);
303 
304  glColor4ub(0, 0, 0, map_darkness[x*2 + 1][y*2]);
305  glVertex3i(x * map_image_size + map_image_half_size, y * map_image_size, 0);
306 
307  glColor4ub(0, 0, 0, map_darkness[x*2 + 1][y*2 + 1]);
309 
310  glColor4ub(0, 0, 0, map_darkness[x*2][y*2+1]);
311  glVertex3i(x * map_image_size, y * map_image_size + map_image_half_size, 0);
312 
313  glEnd();
314 
315  /* Repeat for upper right area */
316  glBegin(GL_QUADS);
317 
318  glColor4ub(0, 0, 0, map_darkness[x*2+1][y*2]);
319  glVertex3i(x * map_image_size + map_image_half_size, y * map_image_size, 0);
320 
321  glColor4ub(0, 0, 0, map_darkness[x*2+2][y*2]);
322  glVertex3i((x +1 ) * map_image_size, y * map_image_size, 0);
323 
324  glColor4ub(0, 0, 0, map_darkness[x*2+2][y*2+1]);
325  glVertex3i((x+1) * map_image_size, y * map_image_size + map_image_half_size, 0);
326 
327  glColor4ub(0, 0, 0, map_darkness[x*2+1][y*2+1]);
329 
330  glEnd();
331 
332  /* Repeat for lower left area */
333  glBegin(GL_QUADS);
334 
335  glColor4ub(0, 0, 0, map_darkness[x*2][y*2+1]);
336  glVertex3i(x * map_image_size, y * map_image_size + map_image_half_size, 0);
337 
338  glColor4ub(0, 0, 0, map_darkness[x*2+1][y*2+1]);
340 
341  glColor4ub(0, 0, 0, map_darkness[x*2+1][y*2+2]);
342  glVertex3i(x * map_image_size + map_image_half_size, (y + 1) * map_image_size, 0);
343 
344  glColor4ub(0, 0, 0, map_darkness[x*2][y*2+2]);
345  glVertex3i( x * map_image_size, (y +1)* map_image_size, 0);
346 
347  glEnd();
348 
349  /* Repeat for lower right area */
350  glBegin(GL_QUADS);
351 
352  glColor4ub(0, 0, 0, map_darkness[x*2+1][y*2+1]);
353  glVertex3i( x * map_image_size + map_image_half_size, y * map_image_size + map_image_half_size, 0);
354 
355  glColor4ub(0, 0, 0, map_darkness[x*2+2][y*2+1]);
356  glVertex3i((x+1) * map_image_size, y * map_image_size + map_image_half_size, 0);
357 
358  glColor4ub(0, 0, 0, map_darkness[x*2+2][y*2+2]);
359  glVertex3i((x+1) * map_image_size, (y +1)* map_image_size, 0);
360 
361  glColor4ub(0, 0, 0, map_darkness[x*2+1][y*2+2]);
362  glVertex3i(x * map_image_size + map_image_half_size, (y + 1) * map_image_size, 0);
363 
364  glEnd();
365 }
366 
367 /*
368  * Some basics. dx, dy are coordinate pairs for offsets. bweights and cweights
369  * are bitmasks that determine the face to draw (or'd together)
370  */
371 static int dx[8]= {0,1,1,1,0,-1,-1,-1};
372 static int dy[8]= {-1,-1,0,1,1,1,0,-1};
373 
374 static int bweights[8]= {2,0,4,0,8,0,1,0};
375 static int cweights[8]= {0,2,0,4,0,8,0,1};
376 static int bc_exclude[8]= {
377  1+2,/*north exclude northwest (bit0) and northeast(bit1)*/
378  0,
379  2+4,/*east exclude northeast and southeast*/
380  0,
381  4+8,/*and so on*/
382  0,
383  8+1,
384  0
385 };
386 
387 /*
388  * Vertices are floats. This sets the value appropriately for us to multiply
389  * the x coordinate by.
390  */
391 #define TEXTURE_OFFSET 1.0/16.0
392 
404 static void drawsmooth_opengl (int x, int y, int mx, int my, int layer)
405 {
406  int partdone[8]= {0,0,0,0,0,0,0,0}, slevels[8], sfaces[8], i,
407  weight,weightC, emx,emy, smoothface, dosmooth, lowest, havesmooth;
408 
409  dosmooth=0;
410  for (i=0; i<8; i++) {
411  emx=mx+dx[i];
412  emy=my+dy[i];
413 
414  if ( (emx<0) || (emy<0) || (emx >= the_map.x) || (emy >= the_map.y)) {
415  slevels[i]=0;
416  sfaces[i]=0; /*black picture*/
417  } else if (the_map.cells[emx][emy].smooth[layer]<=the_map.cells[mx][my].smooth[layer] ||
418  the_map.cells[emx][emy].heads[layer].face == 0) {
419  slevels[i]=0;
420  sfaces[i]=0; /*black picture*/
421  } else {
422  slevels[i]=the_map.cells[emx][emy].smooth[layer];
423  sfaces[i]=pixmaps[the_map.cells[emx][emy].heads[layer].face]->smooth_face;
424  dosmooth++;
425  }
426  }
427 
428  /*
429  * slevels[] & sfaces[] contain the smooth level. dosmooth is the number
430  * if spaces that need to be smoothed. lowlevel is the lowest level to
431  * smooth.
432  *
433  * havesmooth is how many faces we have smoothed
434  */
435  havesmooth=0;
436 
437  while (havesmooth < dosmooth) {
438  lowest=-1;
439  for (i=0; i<8; i++) {
440  if ( (slevels[i]>0) && (!partdone[i]) && ((lowest<0) || (slevels[i]<slevels[lowest]))) {
441  lowest=i;
442  }
443  }
444  if (lowest<0) {
445  break; /*no more smooth to do on this square*/
446  }
447 
448  /* The weight values is a bitmask that determines what image we draw */
449  weight=0;
450  weightC=15; /*works in backward. remove where there is nothing*/
451 
452  for (i=0; i<8; i++) { /*check all nearby squares*/
453  if (slevels[i]==slevels[lowest] && sfaces[i] == sfaces[lowest]) {
454  partdone[i]=1;
455  weight=weight+bweights[i];
456  weightC&=~bc_exclude[i];
457  havesmooth++;
458  } else {
459  /*must rmove the weight of a corner if not in smoothing*/
460  weightC&=~cweights[i];
461  }
462  }
463 
464  smoothface=sfaces[lowest];
465  if (smoothface<=0) {
466  continue; /*picture for smoothing not yet available*/
467  }
468 
469  /*
470  * Now, it's quite easy. We must draw using a 32x32 part of the picture
471  * smoothface.
472  * This part is located using the 2 weights calculated: (32*weight,0)
473  * and (32*weightC,32)
474  */
475 
476  if ( (!pixmaps[smoothface]->map_texture) || (pixmaps[smoothface] == pixmaps[0])) {
477  continue; /*don't have the picture associated*/
478  }
479 
480  if (the_map.cells[mx][my].cleared) {
481  glBindTexture(GL_TEXTURE_2D, pixmaps[smoothface]->fog_texture);
482  } else {
483  glBindTexture(GL_TEXTURE_2D, pixmaps[smoothface]->map_texture);
484  }
485 
486  /*
487  * The values of 0.0f and 0.5f are hardcoded, but as of now, it is a
488  * known fact that there are 2 rows of data in the smoothing images, so
489  * that should be OK.
490  */
491  if (weight) {
492  glBegin(GL_QUADS);
493 
494  glTexCoord2f(TEXTURE_OFFSET * weight, 0.0f);
495  glVertex3i(x * map_image_size, y * map_image_size, 0);
496 
497  glTexCoord2f(TEXTURE_OFFSET * (weight+1), 0.0f);
498  glVertex3i((x+1) * map_image_size, y * map_image_size, 0);
499 
500  glTexCoord2f(TEXTURE_OFFSET * (weight+1), 0.5f);
501  glVertex3i((x+1) * map_image_size, (y+1) * map_image_size, 0);
502 
503  glTexCoord2f(TEXTURE_OFFSET * weight, 0.5f);
504  glVertex3i(x * map_image_size, (y+1) * map_image_size, 0);
505 
506  glEnd();
507  }
508  if (weightC) {
509  glBegin(GL_QUADS);
510 
511  glTexCoord2f(TEXTURE_OFFSET * weight, 0.5f);
512  glVertex3i(x * map_image_size, y * map_image_size, 0);
513 
514  glTexCoord2f(TEXTURE_OFFSET * (weight+1), 0.5f);
515  glVertex3i((x+1) * map_image_size, y * map_image_size, 0);
516 
517  glTexCoord2f(TEXTURE_OFFSET * (weight+1), 1.0f);
518  glVertex3i((x+1) * map_image_size, (y+1) * map_image_size, 0);
519 
520  glTexCoord2f(TEXTURE_OFFSET * weight, 1.0f);
521  glVertex3i(x * map_image_size, (y+1) * map_image_size, 0);
522 
523  glEnd();
524  }
525  } /* While there's some smooth to do */
526 }
527 
532 static void draw_smoothing(int layer)
533 {
534  int x, y, mx, my;
535 
536  for(y = use_config[CONFIG_MAPHEIGHT]+MAX_MAP_OFFSET; y>=0; y--) {
537  for(x = use_config[CONFIG_MAPWIDTH]+MAX_MAP_OFFSET; x>=0; x--) {
538 
539  mx = x + pl_pos.x;
540  my = y + pl_pos.y;
541 
542  if (CAN_SMOOTH(the_map.cells[mx][my],layer)) {
543  drawsmooth_opengl(x, y, mx, my, layer);
544  }
545  }
546  }
547 }
548 
564 void opengl_gen_map(int redraw)
565 {
566  long elapsed1, elapsed2;
567  struct timeval tv1, tv2,tv3;
568  int mx,my, layer,x,y, d1, d2, d3, num_dark, got_smooth, face, t1, t2;
569 
570  if (time_map_redraw) {
571  gettimeofday(&tv1, NULL);
572  }
573 
574  glClear(GL_COLOR_BUFFER_BIT);
575 
576  /*
577  * Need to set this, as the darkness logic could have reset this. since
578  * darkness is done after all other drawing, we can do it just once here.
579  */
580  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
581 
582  /* We draw every space every time this is called. We draw from bottom
583  * right to top left - this makes stacking of big images work as expected.
584  * we also draw all of one layer before doing the next layer. This really
585  * shouldn't effect performance all that much - all that is being changed
586  * is the order of the loops we add MAX_MAP_OFFSET so that big objects off
587  * the edge of the map are drawn.
588  */
589 
590  got_smooth=0; /*smooth marker. Once we have a face and "can_smooth" on a layer, this layer and all above draw smooth */
591 
592  for (layer=0; layer<=MAXLAYERS; layer++) {
593 
594 
595  if (layer == MAXLAYERS) {
596  /*
597  * The top layer is the darkness processing - turn off the texture
598  * pattern so darkness works as expected.
599  */
600  glBindTexture(GL_TEXTURE_2D, 0);
601  }
602  for(y = use_config[CONFIG_MAPHEIGHT]+MAX_MAP_OFFSET; y>=0; y--) {
603  for(x = use_config[CONFIG_MAPWIDTH]+MAX_MAP_OFFSET; x>=0; x--) {
604  /*
605  * mx,my represent the spaces on the 'virtual' map (ie, the_map
606  * structure). x and y (from the for loop) represent the
607  * visible screen.
608  */
609  mx = x + pl_pos.x;
610  my = y + pl_pos.y;
611  /*
612  * If we get here, this denotes a special/top layer. This is
613  * the time to do lighting, smoothing, etc.
614  */
615  if (layer == MAXLAYERS) {
616  /*
617  * If off the map, don't need to do anything, because the
618  * code here doesn't do anything that would extend onto the
619  * map.
620  */
622  continue;
623  }
624  /*
625  * One could make the case it doesn't make sense to light
626  * fog of war spaces, but I find visually it looks a lot
627  * nicer if you do - otherwise, they are too bright
628  * relative to the spaces around. them.
629  */
631  opengl_light_space(x, y, mx, my);
632  }
633 
634  } else {
635  /*
636  * Only do this in the better lighting modes. Fortunately,
637  * the CFG_LT_.. values are ordered from worst to best, to
638  * are >= check works just fine, right now.
639  */
640  if (layer == 0 && use_config[CONFIG_DARKNESS] >= CFG_LT_PIXEL &&
641  ~ x <= use_config[CONFIG_MAPWIDTH] && y <= use_config[CONFIG_MAPHEIGHT]) {
642  /*
643  * The darkness code is similar to the per pixel SDL
644  * code. As such, each square we process needs to know
645  * the values for the intersection points - there is a
646  * lot of redundant calculation in this if done a
647  * square at a time, so instead, we can calculate the
648  * darkness point of all the vertices here. We
649  * calculate the upper/left 4 vertices.
650  *
651  * SDL actually gets better results I think - perhaps
652  * because the per pixel lighting uses a different
653  * algorithm - we basically let opengl do the blending.
654  * But the results we use here, while perhaps not as
655  * nice, certainly look better than per tile lighting.
656  */
657  if (the_map.cells[mx][my].have_darkness) {
658  map_darkness[x*2 + 1][y*2 + 1] = the_map.cells[mx][my].darkness;
659  } else {
660  map_darkness[x*2 + 1][y*2 + 1] = DEFAULT_DARKNESS;
661  }
662 
663  d1 = DEFAULT_DARKNESS; /* square to left */
664  d2 = DEFAULT_DARKNESS; /* square to upper left */
665  d3 = DEFAULT_DARKNESS; /* square above */
666  num_dark=1; /* Number of adjoining spaces w/darkness */
667 
668  if (x>0 && the_map.cells[mx-1][my].have_darkness) {
669  d1 = the_map.cells[mx-1][my].darkness;
670  num_dark++;
671  }
672 
673  if (x>0 && y>0 && the_map.cells[mx-1][my-1].have_darkness) {
674  d2 = the_map.cells[mx-1][my-1].darkness;
675  num_dark++;
676  }
677 
678  if (y>0 && the_map.cells[mx][my-1].have_darkness) {
679  d3 = the_map.cells[mx][my-1].darkness;
680  num_dark++;
681  }
682 #if 0
683  /*
684  * If we don't have darkness, we want to use our value
685  * and not average. That is because the value we
686  * average against is 0 - this results in lighter bands
687  * next to areas we won't have darkness info for.
688  */
689  map_darkness[x*2][y*2] = (d1 + d2 +d3 + map_darkness[x*2 + 1][y*2 + 1]) / num_dark;
690 
691  if (d1) {
692  map_darkness[x*2][y*2 + 1] = (d1 + map_darkness[x*2 + 1][y*2 + 1]) / 2;
693  } else {
694  map_darkness[x*2][y*2 + 1] = map_darkness[x*2 + 1][y*2 + 1];
695  }
696 
697  if (d3) {
698  map_darkness[x*2 +1 ][y*2] = (d3 + map_darkness[x*2 + 1][y*2 + 1]) / 2;
699  } else {
700  map_darkness[x*2 + 1][y*2] = map_darkness[x*2 + 1][y*2 + 1];
701  }
702 #else
703  /*
704  * This block does a 'max' darkness - I think it gives
705  * the best results, which is why by default it is the
706  * one used.
707  */
708  map_darkness[x*2][y*2] = MAX( MAX(d1, d2), MAX(d3, map_darkness[x*2 + 1][y*2 + 1]));
709  map_darkness[x*2][y*2 + 1] = MAX(d1, map_darkness[x*2 + 1][y*2 + 1]);
710  map_darkness[x*2 + 1][y*2] = MAX(d3, map_darkness[x*2 + 1][y*2 + 1]);
711 #endif
712  }
713 
714  if (the_map.cells[mx][my].heads[layer].face) {
715  if (pixmaps[the_map.cells[mx][my].heads[layer].face]->map_texture) {
716  int nx, ny;
717 
718  /*
719  * nx, ny are the location of the top/left side of
720  * the image to draw.
721  */
722  nx = (x+1) * map_image_size - pixmaps[the_map.cells[mx][my].heads[layer].face]->map_width;
723  ny = (y+1) * map_image_size - pixmaps[the_map.cells[mx][my].heads[layer].face]->map_height;
724  /*
725  * If both nx and ny are outside visible area,
726  * don't need to do anything more
727  */
728  if (nx > width && ny > height) {
729  continue;
730  }
731  /*
732  * There are some issues with this - it is really
733  * the head of the object that is determining fog
734  * of war logic. I don't have good solution to
735  * that, other than to live with it.
736  */
737  if (the_map.cells[mx][my].cleared) {
738  glBindTexture(GL_TEXTURE_2D, pixmaps[the_map.cells[mx][my].heads[layer].face]->fog_texture);
739  } else {
740  glBindTexture(GL_TEXTURE_2D, pixmaps[the_map.cells[mx][my].heads[layer].face]->map_texture);
741  }
742 
743  glBegin(GL_QUADS);
744 
745  glTexCoord2f(0.0f, 0.0f);
746  glVertex3i(nx, ny, 0);
747 
748  glTexCoord2f(1.0f, 0.0f);
749  glVertex3i( (x+1) * map_image_size, ny, 0);
750 
751  glTexCoord2f(1.0f, 1.0f);
752  glVertex3i( (x+1) * map_image_size, (y+1) * map_image_size, 0);
753 
754  glTexCoord2f(0.0f, 1.0f);
755  glVertex3i(nx, (y+1) * map_image_size, 0);
756 
757  glEnd();
758  }
759  if (use_config[CONFIG_SMOOTH] && CAN_SMOOTH(the_map.cells[mx][my],layer) &&
760  the_map.cells[mx][my].heads[layer].face !=0) {
761 
762  got_smooth=1;
763  }
764  }
765  if ((face=mapdata_bigface_head(x, y, layer, &t1, &t2))!=0) {
766  if (pixmaps[face]->map_texture) {
767  int nx, ny;
768 
769  /*
770  * nx, ny are the location of the top/left side of
771  * the image to draw.
772  */
773  nx = (x+1) * map_image_size - pixmaps[face]->map_width;
774  ny = (y+1) * map_image_size - pixmaps[face]->map_height;
775  /*
776  * If both nx and ny are outside visible area,
777  * don't need to do anything more
778  */
779  if (nx > width && ny > height) {
780  continue;
781  }
782  /*
783  * There are some issues with this - it is really
784  * the head of the object that is determining fog
785  * of war logic. I don't have good solution to
786  * that, other than to live with it.
787  */
788  if (the_map.cells[mx][my].cleared) {
789  glBindTexture(GL_TEXTURE_2D, pixmaps[face]->fog_texture);
790  } else {
791  glBindTexture(GL_TEXTURE_2D, pixmaps[face]->map_texture);
792  }
793 
794  glBegin(GL_QUADS);
795 
796  glTexCoord2f(0.0f, 0.0f);
797  glVertex3i(nx, ny, 0);
798 
799  glTexCoord2f(1.0f, 0.0f);
800  glVertex3i( (x+1) * map_image_size, ny, 0);
801 
802  glTexCoord2f(1.0f, 1.0f);
803  glVertex3i( (x+1) * map_image_size, (y+1) * map_image_size, 0);
804 
805  glTexCoord2f(0.0f, 1.0f);
806  glVertex3i(nx, (y+1) * map_image_size, 0);
807 
808  glEnd();
809  }
810  } /* If this space has a valid face */
811  } /* If last layer/else not last layer */
812  } /* for x loop */
813  } /* for y loop */
814 
815  /*
816  * Because of our handling with big images, we can't easily draw this
817  * when drawing the space - we may want to smooth onto another space in
818  * which the ground hasn't been drawn yet, so we have to do smoothing
819  * at the end of each layer.
820  *
821  * We use the got_smooth variable to know if there is in fact any
822  * smoothing to do - for many layers, this is not likely to be set, so
823  * we can save work by not doing this.
824  */
825  if (got_smooth) {
826  draw_smoothing(layer);
827  }
828  }
829 
830  if (time_map_redraw) {
831  gettimeofday(&tv2, NULL);
832  }
833 
834 #ifndef WIN32
835  glXSwapBuffers(display, window);
836 #else
837  SwapBuffers(devicecontext);
838 #endif
839 
840  if (time_map_redraw) {
841  gettimeofday(&tv3, NULL);
842  elapsed1 = (tv2.tv_sec - tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec);
843  elapsed2 = (tv3.tv_sec - tv2.tv_sec)*1000000 + (tv3.tv_usec - tv2.tv_usec);
844  /*
845  * I care about performance for 'long' updates, so put the check in to
846  * make these a little more noticable
847  */
848  if ((elapsed1 + elapsed2)>10000)
849  LOG(LOG_INFO,"gtk-v2::opengl_gen_map","gen took %7ld, flip took %7ld, total = %7ld",
850  elapsed1, elapsed2, elapsed1 + elapsed2);
851  }
852 } /* opengl_gen_map function */
853 
862 {
863  static uint8 *newdata;
864  static int size=0;
865  int nwidth, nheight, numshifts, i;
866  uint8 *data_to_use = data, *l;
867  uint32 g, *p;
868 
869  /*
870  * The width and height of textures has to be a power of 2. so 32x32 and
871  * 64x64 images work, but 96x96 does not. The logic below basically
872  * figures out if the width we have is in fact a power of two or not, and
873  * if not, the next power of 2 up that is.
874  */
875  for (nwidth = pi->map_width, numshifts=0; nwidth >1; nwidth >>=1, numshifts++) ;
876  nwidth <<= numshifts;
877  if (nwidth != pi->map_width) {
878  nwidth <<=1;
879  }
880 
881  for (nheight = pi->map_height, numshifts=0; nheight >1; nheight >>=1, numshifts++) ;
882  nheight <<= numshifts;
883  if (nheight != pi->map_height) {
884  nheight <<=1;
885  }
886  /*
887  * Below deals with cases where the pixmap is not a power of 2. The
888  * 'proper' opengl way of dealing with such textures is to make a mipmap -
889  * this is basically a resized version up/down to the nearest power of two,
890  * which is then rescaled when it is used to actually texture something -
891  * this means it is scaled up once, then scaled down again. For most
892  * opengl apps, this probably isn't a big deal, because the surface the
893  * texture being applied applied to is going to cause distortion. However,
894  * in this client, we are doing a 1:1 paste operation, so that scaling will
895  * certainly cause some distortion. instead, I take the approach make a
896  * bigger image, but fill the extra bits with transparent alpha bits. This
897  * way, we have no loss of quality.
898  */
899  if (pi->map_width != nwidth || pi->map_height != nheight) {
900  int y;
901  uint8 *datastart;
902 
903  /*
904  * Use a static buffer to hold image data, so we don't have to keep
905  * allocating/deallocating, but need to make sure it is big enough.
906  */
907  if (nwidth * nheight * 4 > size) {
908  size = nwidth * nheight * 4;
909  newdata = realloc(newdata, size);
910 
911  if (newdata == NULL) {
912  LOG(LOG_ERROR, "create_opengl_map_image",
913  "Could not allocate memory: %s", strerror(errno));
914  exit(EXIT_FAILURE);
915  }
916  }
917  /*
918  * Fill the top portion of the image with empty/transparent data.
919  * Also, set up datastart to point to where we should start filling in
920  * the rest of the data.
921  */
922  if (nheight > pi->map_height) {
923  memset(newdata, 0, (nheight - pi->map_height) * nwidth * 4);
924  datastart = newdata + (nheight - pi->map_height) * nwidth * 4;
925  } else {
926  datastart = newdata;
927  }
928 
929  for (y =0; y < pi->map_height; y++) {
930  memset(datastart + y * nwidth * 4, 0, (nwidth - pi->map_width) * 4);
931  memcpy(datastart + y * nwidth * 4 + (nwidth - pi->map_width) * 4,
932  data + y * pi->map_width * 4, pi->map_width * 4);
933  }
934  data_to_use = newdata;
935  pi->map_width = nwidth;
936  pi->map_height = nheight;
937  }
938 
939  glGenTextures(1, &pi->map_texture);
940  glBindTexture(GL_TEXTURE_2D, pi->map_texture);
941  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
942  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
943 
944  glTexImage2D(GL_TEXTURE_2D, 0, 4, pi->map_width, pi->map_height,
945  0, GL_RGBA, GL_UNSIGNED_BYTE, data_to_use);
946 
947  /*
948  * Generate a fog image. This isn't 100% efficient, because we copy data
949  * we may need to modify, but makes the code simpler in in the case above
950  * where we've had to change the size of the image.
951  */
952 
953  if (pi->map_width * pi->map_height * 4 > size) {
954  size = pi->map_width * pi->map_height * 4;
955  newdata = realloc(newdata, size);
956  }
957 
958  /* In this case, newdata does not contain a copy of the data - make one */
959  if (data_to_use != newdata) {
960  memcpy(newdata, data, pi->map_height * pi->map_width * 4);
961  }
962 
963  for (i=0; i < pi->map_width * pi->map_height; i++) {
964  l = (uint8 *) (newdata + i*4);
965  g = MAX(*l, *(l+1));
966  g = MAX(g, *(l+2));
967  p = (uint32*) newdata + i;
968  *p = g | (g << 8) | (g << 16) | (*(l + 3) << 24);
969  }
970 
971  glGenTextures(1, &pi->fog_texture);
972  glBindTexture(GL_TEXTURE_2D, pi->fog_texture);
973  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
974  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
975 
976  glTexImage2D(GL_TEXTURE_2D, 0, 4, pi->map_width, pi->map_height,
977  0, GL_RGBA, GL_UNSIGNED_BYTE, newdata);
978 }
979 
985 {
986  if (pi->map_texture) {
987  glDeleteTextures(1, &pi->map_texture);
988  pi->map_texture=0;
989  }
990  if (pi->fog_texture) {
991  glDeleteTextures(1, &pi->fog_texture);
992  pi->fog_texture=0;
993  }
994 }
995 
996 #include "../../pixmaps/question.111"
997 
1005 void create_opengl_question_mark(void)
1006 {
1007  GLubyte question[question_height][question_width][4];
1008  int xb, x, y, offset=0;
1009 
1010  /*
1011  * We want data in rgba format. So convert the question bits to an rgba
1012  * format. We only need to do this once
1013  */
1014  for (y=0; y<question_height; y++) {
1015  for (xb=0; xb<question_width/8; xb++) {
1016  for (x=0; x<8; x++) {
1017  if (question_bits[offset] & (1 << x)) {
1018  question[y][xb * 8 + x][0] = 255;
1019  question[y][xb * 8 + x][1] = 255;
1020  question[y][xb * 8 + x][2] = 255;
1021  question[y][xb * 8 + x][3] = 255;
1022  } else {
1023  question[y][xb * 8 + x][0] = 0;
1024  question[y][xb * 8 + x][1] = 0;
1025  question[y][xb * 8 + x][2] = 0;
1026  question[y][xb * 8 + x][3] = 0;
1027  }
1028  }
1029  offset++;
1030  }
1031  }
1032 
1033  glGenTextures(1, &pixmaps[0]->map_texture);
1034  glBindTexture(GL_TEXTURE_2D, pixmaps[0]->map_texture);
1035  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1036  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1037 
1038  glTexImage2D(GL_TEXTURE_2D, 0, 4, question_width, question_height,
1039  0, GL_RGBA, GL_UNSIGNED_BYTE, &question[0][0][0]);
1040 
1041  glGenTextures(1, &pixmaps[0]->fog_texture);
1042  glBindTexture(GL_TEXTURE_2D, pixmaps[0]->fog_texture);
1043  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1044  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1045 
1046  glTexImage2D(GL_TEXTURE_2D, 0, 4, question_width, question_height,
1047  0, GL_RGBA, GL_UNSIGNED_BYTE, &question[0][0][0]);
1048 }
1049 
1050 #endif
#define CAN_SMOOTH(__SQUARE, __LEVEL)
Definition: client.h:63
int y
Definition: mapdata.h:97
sint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh)
Definition: mapdata.c:1065
int map_image_size
Definition: map.c:58
#define MAX_MAP_OFFSET
How many spaces an object might extend off the map.
Definition: client.h:470
void opengl_free_pixmap(PixmapInfo *pi)
#define MAP_MAX_SIZE
Map size the client will request the map to be.
Definition: client.h:454
uint32 height
Definition: image.c:61
void create_opengl_map_image(uint8 *data, PixmapInfo *pi)
uint16 map_height
Definition: image.h:51
uint8 have_darkness
Definition: mapdata.h:86
sint16 face
Definition: mapdata.h:49
Contains various global definitions and XML file name and path defaults.
void LOG(LogLevel level, const char *origin, const char *format,...)
Log messages of a certain importance to stderr.
Definition: misc.c:183
Pixmap data.
void init_glx_opengl(GtkWidget *drawingarea)
void create_opengl_question_mark(void)
sint16 use_config[CONFIG_NUMS]
Definition: init.c:39
uint8 darkness
Definition: mapdata.h:84
int time_map_redraw
Definition: map.c:67
uint8 cleared
Definition: mapdata.h:88
#define CONFIG_DARKNESS
Definition: client.h:164
#define CONFIG_MAPHEIGHT
Definition: client.h:162
struct Map the_map
Definition: mapdata.c:115
struct MapCell ** cells
Definition: mapdata.h:99
int x
Definition: mapdata.h:96
unsigned short uint16
Definition: client-types.h:84
#define CFG_LT_TILE
Definition: client.h:187
uint32 width
Definition: image.c:61
void init_opengl(GtkWidget *drawingarea)
unsigned int uint32
Definition: client-types.h:82
#define MAXLAYERS
The protocol supports 10 layers, so set MAXLAYERS accordingly.
Definition: mapdata.h:36
uint16 smooth[MAXLAYERS]
Definition: mapdata.h:83
#define CONFIG_SMOOTH
Definition: client.h:168
void opengl_gen_map(int redraw)
PixmapInfo * pixmaps[MAXPIXMAPNUM]
Definition: image.c:66
#define CFG_LT_PIXEL
Definition: client.h:188
uint16 smooth_face
A face used for smoothing with this face.
Definition: image.h:53
Includes various dependencies header files needed by most everything.
unsigned char uint8
Definition: client-types.h:86
struct MapCellLayer heads[MAXLAYERS]
Definition: mapdata.h:81
tuple f
Definition: Bundle.py:36
PlayerPosition pl_pos
Definition: map.c:54
int map_image_half_size
Definition: map.c:59
#define CONFIG_MAPWIDTH
Definition: client.h:161
uint16 map_width
Definition: image.h:51