Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gfxlib_struct.cpp
Go to the documentation of this file.
1 #include "gfxlib_struct.h"
2 #include "gfxlib.h"
3 #include "gldrv/gl_globals.h"
4 #include <stdio.h>
5 #include "xml_support.h"
6 #include "config_xml.h"
7 #include "vs_globals.h"
8 #include "vs_random.h"
9 #include "vsfilesystem.h"
10 
11 #include "options.h"
12 
13 #include <vector>
14 
16 
17 GLenum PolyLookup( POLYTYPE poly )
18 {
19  switch (poly)
20  {
21  case GFXTRI:
22  return GL_TRIANGLES;
23 
24  case GFXQUAD:
25  return GL_QUADS;
26 
27  case GFXTRISTRIP:
28  return GL_TRIANGLE_STRIP;
29 
30  case GFXQUADSTRIP:
31  return GL_QUAD_STRIP;
32 
33  case GFXTRIFAN:
34  return GL_TRIANGLE_FAN;
35 
36  case GFXPOLY:
37  return GL_POLYGON;
38 
39  case GFXLINE:
40  return GL_LINES;
41 
42  case GFXLINESTRIP:
43  return GL_LINE_STRIP;
44 
45  case GFXPOINT:
46  return GL_POINTS;
47 
48  default:
49  return GL_TRIANGLES;
50  }
51 }
52 #ifndef NO_VBO_SUPPORT
53 static void BindBuf( unsigned int vbo_data )
54 {
55  (*glBindBufferARB_p)(GL_ARRAY_BUFFER_ARB, vbo_data);
56 }
57 static void BindInd( unsigned int element_data )
58 {
59  (*glBindBufferARB_p)(GL_ELEMENT_ARRAY_BUFFER_ARB, element_data);
60 }
61 static void clear_gl_error()
62 {
63  glGetError();
64 }
65 static void print_gl_error(const char *fmt)
66 {
67  GLenum gl_error;
68  if ((gl_error = glGetError()))
69  VSFileSystem::vs_dprintf(1, fmt, gl_error);
70 }
71 #endif
73 {
74 #ifndef NO_VBO_SUPPORT
75  if (game_options.vbo && !vbo_data) {
77  || glUnmapBufferARB_p == 0) {
78  game_options.vbo = 0;
79  } else {
80  (*glGenBuffersARB_p)(1, (GLuint*) &vbo_data);
81  if (changed&HAS_INDEX)
82  (*glGenBuffersARB_p)(1, (GLuint*) &display_list);
83  }
84  }
85  if (vbo_data) {
86  BindBuf( vbo_data );
87  (*glBufferDataARB_p)(GL_ARRAY_BUFFER_ARB, numVertices
88  *( (changed&HAS_COLOR) ? sizeof (GFXColorVertex) : sizeof (GFXVertex) ), data.vertices,
89  (changed&CHANGE_MUTABLE) ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB);
90  if (changed&HAS_INDEX) {
92  unsigned int tot = 0;
93  for (int i = 0; i < numlists; ++i)
94  tot += offsets[i];
95  unsigned int indexsize = (changed&INDEX_BYTE)
96  ? sizeof (char)
97  : ( (changed&INDEX_SHORT)
98  ? sizeof (unsigned short)
99  : sizeof (unsigned int) );
100  (*glBufferDataARB_p)(GL_ELEMENT_ARRAY_BUFFER_ARB, tot*indexsize, &index.b[0],
101  (changed&CHANGE_MUTABLE) ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB);
102  }
103  return;
104  }
105 #endif
107  return; //don't used lists if they're mutable
108  if (display_list)
110  int a;
111  int offset = 0;
113  if (changed&HAS_COLOR) {
114  for (int i = 0; i < numlists; i++) {
115  glBegin( PolyLookup( mode[i] ) );
116  if (changed&HAS_INDEX) {
117  for (a = 0; a < offsets[i]; a++) {
118  const GFXColorVertex &vtx = data.colors[GetIndex( offset+a )];
119  GFXTexCoord224f( vtx.s, vtx.t, vtx.s, vtx.t, vtx.tx, vtx.ty, vtx.tz, vtx.tw );
120  glColor4fv( &vtx.r );
121  glNormal3fv( &vtx.i );
122  glVertex3fv( &vtx.x );
123  }
124  } else {
125  for (a = 0; a < offsets[i]; a++) {
126  const GFXColorVertex &vtx = data.colors[offset+a];
127  GFXTexCoord224f( vtx.s, vtx.t, vtx.s, vtx.t, vtx.tx, vtx.ty, vtx.tz, vtx.tw );
128  glColor4fv( &vtx.r );
129  glNormal3fv( &vtx.i );
130  glVertex3fv( &vtx.x );
131  }
132  }
133  offset += offsets[i];
134  glEnd();
135  }
136  } else {
137  for (int i = 0; i < numlists; i++) {
138  glBegin( PolyLookup( mode[i] ) );
139  if (changed&HAS_INDEX) {
140  for (a = 0; a < offsets[i]; a++) {
141  const GFXVertex &vtx = data.vertices[GetIndex( offset+a )];
142  glNormal3fv( &vtx.i );
143  GFXTexCoord224f( vtx.s, vtx.t, vtx.s, vtx.t, vtx.tx, vtx.ty, vtx.tz, vtx.tw );
144  glVertex3fv( &vtx.x );
145  }
146  } else {
147  for (a = 0; a < offsets[i]; a++) {
148  const GFXVertex &vtx = data.vertices[offset+a];
149  glNormal3fv( &vtx.i );
150  GFXTexCoord224f( vtx.s, vtx.t, vtx.s, vtx.t, vtx.tx, vtx.ty, vtx.tz, vtx.tw );
151  glVertex3fv( &vtx.x );
152  }
153  }
154  offset += offsets[i];
155  glEnd();
156  }
157  }
158  if ( !GFXEndList() ) {
160  display_list = 0;
161  }
162 }
163 
165 {
166  if (!numVertices)
167  return; //don't do anything if there are no vertices
168 
169 #ifndef NO_VBO_SUPPORT
170  if (vbo_data) {
171  clear_gl_error();
172 
173  BindBuf( vbo_data );
174  print_gl_error("VBO18.5a Error %d\n");
175 
176  if (changed&HAS_INDEX) {
178  print_gl_error("VBO18.5b Error %d\n");
179  }
180 
181  if (changed&HAS_COLOR) {
183  glClientActiveTextureARB_p( GL_TEXTURE0 );
184  glInterleavedArrays( GL_T2F_C4F_N3F_V3F, sizeof (GFXColorVertex), 0 );
185  if (gl_options.Multitexture) {
186  glClientActiveTextureARB_p( GL_TEXTURE1 );
187  glTexCoordPointer( 2, GL_FLOAT, sizeof (GFXColorVertex),
188  (void*) ( (char*) &data.colors[0].s-(char*) data.vertices ) );
189  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
190  glClientActiveTextureARB_p( GL_TEXTURE2 );
191  glTexCoordPointer( 4, GL_FLOAT, sizeof (GFXColorVertex),
192  (void*) ( (char*) &data.colors[0].tx-(char*) data.vertices ) );
193  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
194  glClientActiveTextureARB_p( GL_TEXTURE0 );
195  }
196  } else {
198  glClientActiveTextureARB_p( GL_TEXTURE0 );
199  glInterleavedArrays( GL_T2F_N3F_V3F, sizeof (GFXVertex), 0 );
200  if (gl_options.Multitexture) {
201  glClientActiveTextureARB_p( GL_TEXTURE1 );
202  glTexCoordPointer( 2, GL_FLOAT, sizeof (GFXVertex),
203  (void*) ( (char*) &data.vertices[0].s-(char*) data.vertices ) );
204  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
205  glClientActiveTextureARB_p( GL_TEXTURE2 );
206  glTexCoordPointer( 4, GL_FLOAT, sizeof (GFXVertex),
207  (void*) ( (char*) &data.vertices[0].tx-(char*) data.vertices ) );
208  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
209  glClientActiveTextureARB_p( GL_TEXTURE0 );
210  }
211  }
212  } else
213 #endif
214  if (display_list != 0) {} else {
215  if (changed&HAS_COLOR) {
217  glClientActiveTextureARB_p( GL_TEXTURE0 );
218  glInterleavedArrays( GL_T2F_C4F_N3F_V3F, sizeof (GFXColorVertex), &data.colors[0] );
219  if (gl_options.Multitexture) {
220  glClientActiveTextureARB_p( GL_TEXTURE1 );
221  glTexCoordPointer( 2, GL_FLOAT, sizeof (GFXColorVertex), &data.colors[0].s );
222  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
223  glClientActiveTextureARB_p( GL_TEXTURE2 );
224  glTexCoordPointer( 4, GL_FLOAT, sizeof (GFXColorVertex), &data.colors[0].tx );
225  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
226  glClientActiveTextureARB_p( GL_TEXTURE0 );
227  }
228  } else {
230  glClientActiveTextureARB_p( GL_TEXTURE0 );
231  glInterleavedArrays( GL_T2F_N3F_V3F, sizeof (GFXVertex), &data.vertices[0] );
232  if (gl_options.Multitexture) {
233  glClientActiveTextureARB_p( GL_TEXTURE1 );
234  glTexCoordPointer( 2, GL_FLOAT, sizeof (GFXVertex), &data.vertices[0].s );
235  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
236  glClientActiveTextureARB_p( GL_TEXTURE2 );
237  glTexCoordPointer( 4, GL_FLOAT, sizeof (GFXVertex), &data.vertices[0].tx );
238  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
239  glClientActiveTextureARB_p( GL_TEXTURE0 );
240  }
241  }
242 #ifndef NO_COMPILEDVERTEXARRAY_SUPPORT
243  if (lock && glLockArraysEXT_p)
244  (*glLockArraysEXT_p)(0, numVertices);
245 #endif
246  }
247 }
248 extern void /*GFXDRVAPI*/ GFXColor4f( const float r, const float g, const float b, const float a );
249 
251 {
252  if (vbo_data) {} else if (display_list != 0) {} else {
253 #ifndef NO_COMPILEDVERTEXARRAY_SUPPORT
254  if (lock && glUnlockArraysEXT_p && numVertices)
255  (*glUnlockArraysEXT_p)();
256 #endif
257  }
258  if (changed&HAS_COLOR)
259  GFXColor4f( 1, 1, 1, 1 );
260 }
261 
262 extern GLenum PolyLookup( POLYTYPE poly );
263 
264 void GFXVertexList::Draw( enum POLYTYPE poly, int numV )
265 {
266  INDEX index;
267  index.b = NULL;
268  Draw( &poly, index, 1, &numV );
269 }
270 void GFXVertexList::Draw( enum POLYTYPE poly, int numV, unsigned char *index )
271 {
272  char tmpchanged = changed;
273  changed = sizeof (unsigned char)|( (~HAS_INDEX)&changed );
274  INDEX tmp;
275  tmp.b = (index);
276  Draw( &poly, tmp, 1, &numV );
277  changed = tmpchanged;
278 }
279 void GFXVertexList::Draw( enum POLYTYPE poly, int numV, unsigned short *index )
280 {
281  char tmpchanged = changed;
282  changed = sizeof (unsigned short)|( (~HAS_INDEX)&changed );
283  INDEX tmp;
284  tmp.s = (index);
285  Draw( &poly, tmp, 1, &numV );
286  changed = tmpchanged;
287 }
288 void GFXVertexList::Draw( enum POLYTYPE poly, int numV, unsigned int *index )
289 {
290  char tmpchanged = changed;
291  changed = sizeof (unsigned int)|( (~HAS_INDEX)&changed );
292  INDEX tmp;
293  tmp.i = (index);
294  Draw( &poly, tmp, 1, &numV );
295  changed = tmpchanged;
296 }
297 
299 {
300  LoadDrawState();
302  Draw();
304 }
305 
307 {
309 }
310 
311 extern void GFXCallList( int list );
312 void GFXVertexList::Draw( enum POLYTYPE *mode, const INDEX index, const int numlists, const int *offsets )
313 {
314  //Hardware support for this seems... sketchy
315  if (vbo_data == 0 && display_list != 0) {
316  //Big issue: display lists cannot discriminate between lines/points/triangles,
317  //so, for now, we'll limit smoothing to single-mode GFXVertexLists, which, by the way,
318  //are the only ones being used, AFAIK.
319  bool blendchange = false;
320  if ( unique_mode && (numlists > 0) ) {
321  switch (*mode)
322  {
323  case GFXLINE:
324  case GFXLINESTRIP:
325  case GFXPOLY:
326  case GFXPOINT:
327  if ( ( (*mode == GFXPOINT)
328  && gl_options.smooth_points ) || ( (*mode != GFXPOINT) && gl_options.smooth_lines ) ) {
329  BLENDFUNC src, dst;
330  GFXGetBlendMode( src, dst );
331  if ( (dst != ZERO) && ( (src == ONE) || (src == SRCALPHA) ) ) {
333  GFXBlendMode( SRCALPHA, dst );
334  GFXEnable( SMOOTH );
335  blendchange = true;
336  }
337  }
338  break;
339  default:
340  break;
341  }
342  }
344  if (blendchange) {
345  GFXPopBlendMode();
346  GFXDisable( SMOOTH );
347  }
348 
350  } else {
351  int totoffset = 0;
352  if (changed&HAS_INDEX) {
353  char stride = changed&HAS_INDEX;
354  GLenum indextype = (changed&INDEX_BYTE)
355  ? GL_UNSIGNED_BYTE
356  : ( (changed&INDEX_SHORT)
357  ? GL_UNSIGNED_SHORT
358  : GL_UNSIGNED_INT );
359  bool use_vbo = vbo_data != 0;
360  use_vbo = use_vbo && memcmp( &index, &this->index, sizeof (INDEX) ) == 0;
361  if (use_vbo) {
362  #ifndef NO_VBO_SUPPORT
364  #else
365  use_vbo = false;
366  #endif
367  } else {
368  #ifndef NO_VBO_SUPPORT
369  if (vbo_data)
370  BindInd( 0 );
371  #endif
372  }
373  if (glMultiDrawElements_p != NULL && numlists > 1) {
374  static std::vector< bool > drawn;
375  static std::vector< const GLvoid* >glindices;
376  static std::vector< GLsizei >glcounts;
377 
378  drawn.clear();
379  drawn.resize( numlists, false );
380  for (int i = 0; i < numlists; totoffset += offsets[i++])
381  if (!drawn[i]) {
382  glindices.clear();
383  glcounts.clear();
384  int totcount = 0;
385  for (int j = i, offs = totoffset; j < numlists; offs += offsets[j++]) {
386  totcount += offsets[j];
387  if ( !drawn[j] && (mode[j] == mode[i]) ) {
388  glindices.push_back( use_vbo ? (GLvoid*) (stride*offs)
389  : (GLvoid*) &index.b[stride*offs] );
390  glcounts.push_back( offsets[j] );
391  drawn[j] = true;
392  }
393  }
394  if (glindices.size() == 1)
395  glDrawElements( PolyLookup( mode[i] ), glcounts[0], indextype, glindices[0] );
396 
397  else
399  mode[i] ), &glcounts[0], indextype, &glindices[0], glindices.size() );
401  gl_vertices_this_frame += totcount;
402  }
403  } else {
404  for (int i = 0; i < numlists; i++) {
405  glDrawElements( PolyLookup( mode[i] ), offsets[i], indextype,
406  use_vbo ? (void*) (stride*totoffset)
407  : &index.b[stride*totoffset] ); //changed&INDEX_BYTE == stride!
408  totoffset += offsets[i];
410  gl_vertices_this_frame += offsets[i];
411  }
412  }
413  } else {
414  if (glMultiDrawArrays_p) {
415  static std::vector< bool > drawn;
416  static std::vector< GLint > gloffsets;
417  static std::vector< GLsizei >glcounts;
418 
419  drawn.clear();
420  drawn.resize( numlists, false );
421  for (int i = 0; i < numlists; totoffset += offsets[i++])
422  if (!drawn[i]) {
423  gloffsets.clear();
424  glcounts.clear();
425  int totcount = 0;
426  for (int j = i, offs = totoffset; j < numlists; offs += offsets[j++]) {
427  totcount += offsets[j];
428  if ( !drawn[j] && (mode[j] == mode[i]) ) {
429  gloffsets.push_back( offs );
430  glcounts.push_back( offsets[j] );
431  drawn[j] = true;
432  }
433  }
434  bool blendchange = false;
435  switch (mode[i])
436  {
437  case GFXLINE:
438  case GFXLINESTRIP:
439  case GFXPOLY:
440  case GFXPOINT:
441  if ( ( (mode[i] == GFXPOINT)
442  && gl_options.smooth_points ) || ( (mode[i] != GFXPOINT) && gl_options.smooth_lines ) ) {
443  BLENDFUNC src, dst;
444  GFXGetBlendMode( src, dst );
445  if ( (dst != ZERO) && ( (src == ONE) || (src == SRCALPHA) ) ) {
447  GFXBlendMode( SRCALPHA, dst );
448  GFXEnable( SMOOTH );
449  blendchange = true;
450  }
451  }
452  break;
453  default:
454  break;
455  }
456  if (gloffsets.size() == 1)
457  glDrawArrays( PolyLookup( mode[i] ), gloffsets[0], glcounts[0] );
458 
459  else
460  glMultiDrawArrays_p( PolyLookup( mode[i] ), &gloffsets[0], &glcounts[0], gloffsets.size() );
461  if (blendchange) {
462  GFXPopBlendMode();
463  GFXDisable( SMOOTH );
464  }
466  gl_vertices_this_frame += totcount;
467  }
468  } else {
469  for (int i = 0; i < numlists; i++) {
470  bool blendchange = false;
471  switch (mode[i])
472  {
473  case GFXLINE:
474  case GFXLINESTRIP:
475  case GFXPOLY:
476  case GFXPOINT:
477  if ( ( (mode[i] == GFXPOINT)
478  && gl_options.smooth_points ) || ( (mode[i] != GFXPOINT) && gl_options.smooth_lines ) ) {
479  BLENDFUNC src, dst;
480  GFXGetBlendMode( src, dst );
481  if ( (dst != ZERO) && ( (src == ONE) || (src == SRCALPHA) ) ) {
483  GFXBlendMode( SRCALPHA, dst );
484  GFXEnable( SMOOTH );
485  blendchange = true;
486  }
487  }
488  break;
489  default:
490  break;
491  }
492  glDrawArrays( PolyLookup( mode[i] ), totoffset, offsets[i] );
493  totoffset += offsets[i];
494  if (blendchange) {
495  GFXPopBlendMode();
496  GFXDisable( SMOOTH );
497  }
499  gl_vertices_this_frame += offsets[i];
500  }
501  }
502  }
503  }
504 }
505 
507 {
508 #ifndef NO_VBO_SUPPORT
509  if (vbo_data) {
510  (*glDeleteBuffersARB_p)(1, (GLuint*) &vbo_data);
511  if (display_list)
512  (*glDeleteBuffersARB_p)(1, (GLuint*) &display_list);
513  } else
514 #endif
515  if (display_list)
516  GFXDeleteList( display_list ); //delete dis
517  if (offsets)
518  delete[] offsets;
519  if (mode)
520  delete[] mode;
521  if (changed&HAS_COLOR) {
522  if (data.colors)
523  free( data.colors );
524  } else if (data.vertices) {
525  free( data.vertices );
526  }
527 }
528 
529 union GFXVertexList::VDAT* GFXVertexList::Map( bool read, bool write )
530 {
531 #ifndef NO_VBO_SUPPORT
533  if (vbo_data) {
534  if (display_list) {
536  index.b =
537  (unsigned char*) (*glMapBufferARB_p)(GL_ELEMENT_ARRAY_BUFFER_ARB,
538  read ? (write ? GL_READ_WRITE_ARB : GL_READ_ONLY_ARB)
539  : GL_WRITE_ONLY_ARB);
540  }
541  BindBuf( vbo_data );
542  void *ret =
543  (*glMapBufferARB_p)(GL_ARRAY_BUFFER_ARB,
544  read ? (write ? GL_READ_WRITE_ARB : GL_READ_ONLY_ARB) : GL_WRITE_ONLY_ARB);
545  if (changed&HAS_COLOR)
546  data.colors = (GFXColorVertex*) ret;
547  else
548  data.vertices = (GFXVertex*) ret;
549  }
550 
551 #endif
552 
553 
554  return &data;
555 }
557 {
558 #ifndef NO_VBO_SUPPORT
560  if (vbo_data) {
561  if (display_list) {
563  (*glUnmapBufferARB_p)(GL_ELEMENT_ARRAY_BUFFER_ARB);
564  }
565  BindBuf( vbo_data );
566  (*glUnmapBufferARB_p)(GL_ARRAY_BUFFER_ARB);
567  data.colors = NULL;
568  data.vertices = NULL;
569  }
570 
571 #endif
572 
573 }
576 {
577  return this->Map( false, true );
578 }
579 
581 void GFXVertexList::EndMutate( int newvertexsize )
582 {
583  this->UnMap();
584  if ( !(changed&CHANGE_MUTABLE) )
586  if (newvertexsize) {
587  numVertices = newvertexsize;
588  //Must keep synchronized - we'll only permit changing vertex count on single-list objects
589  if (numlists == 1) *offsets = numVertices;
590  }
591  if (!vbo_data) {
594  } else {
596  }
598  changed &= (~CHANGE_CHANGE);
599 }
600 
601 //private, only for inheriters
603  numVertices(0),
604  mode(0),
605  unique_mode(0),
606  display_list(0),
607  vbo_data(0),
608  numlists(0),
609  offsets(0),
610  changed(0)
611 {
612  // ctor
613 }
614 
616 {
617  return mode;
618 }
619 
621 {
622  return offsets;
623 }
624 
626 {
627  return numlists;
628 }
629 
631 void SetVector( const double factor, Vector *pv ) {
632  pv->i = pv->i * factor;
633  pv->j = pv->j * factor;
634  pv->k = pv->k * factor;
635 }
636 
638 {
640  const int ROWS = 28;
641  int row[ROWS];
642  for(int i=0; i < ROWS; i++) {
643  row[i] = numVertices/ROWS*i;
644  }
645 
646  Vector vert[ROWS];
647  int direction[ROWS/2];
648 
649  int last_row_set[ROWS];
650  for(int i=0; i < ROWS; i++) {
651  last_row_set[i] = 0;
652  }
653 
654  for(int i=0; i < numVertices; i++) {
655  for(int j=0; j < ROWS; j++)
656  if(row[j] < numVertices/ROWS*(j+1))
657  vert[j] = v[row[j]].GetPosition();
658 
659  for(int j=0; j < ROWS/2; j++)
660  direction[j] = (int)vsrandom.uniformInc( 0.0, 5.0 );
661  if(i % 4 == 1) {
662  for(int j=0; j < ROWS; j+=2) {
663  if(direction[j/2] > 2) {
664  SetVector( 1.003, &vert[j] );
665  last_row_set[j] = 1;
666  } else {
667  last_row_set[j] = -1;
668  }
669  }
670 
671  }
672 
673  if(i % 4 == 0 ) {
674  for(int j=1; j < ROWS; j+=2) {
675  if(direction[(j-1)/2] > 2) {
676  SetVector( 1.003, &vert[j] );
677  last_row_set[j] = 1;
678  } else {
679  last_row_set[j] = -1;
680  }
681  }
682  }
683 
684  for(int j=0; j < ROWS; j++)
685  if(row[j] < numVertices/ROWS*(j+1))
686  v[row[j]].SetVertex( vert[j] );
687 
688  for(int j=0; j < ROWS; j++)
689  row[j]++;
690  }
691 
692  sphere->EndMutate( /*numVertices*/ );
693 }