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
gl_vertex_list.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Daniel Horn & Alan Shieh
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 //#include "gl_globals.h"
22 
23 #include "gfxlib_struct.h"
24 #include "vegastrike.h"
25 #include "vs_globals.h"
26 #include "vsfilesystem.h"
27 #include <assert.h>
28 #ifndef NO_GFX //Server cannot depend on GL, but still needs a mesh library.
29 #include "gl_globals.h"
30 #else
31 #define GFX_BUFFER_MAP_UNMAP false
32 #endif
33 //Untransformed and transformed data
34 
35 #ifndef GFX_SCALE
36 #define GFX_SCALE 1./1024.
37 #endif
38 
39 #include "gnuhash.h"
40 
42 
44 {
45  bool operator()( const GFXVertex *a, const GFXVertex *b ) const
46  {
47  if ((sizeof(GFXVertex) % sizeof(unsigned int)) != 0) {
48  return memcmp( a, b, sizeof (GFXVertex) ) < 0;
49  } else {
50  // faster memcmp, since it gets unrolled by the compiler
51  const unsigned int *ia = reinterpret_cast<const unsigned int*>(a);
52  const unsigned int *ib = reinterpret_cast<const unsigned int*>(b);
53 
54  for (size_t i=0; i < (sizeof(*a) / sizeof(*ia)); ++i) {
55  if (ia[i] < ib[i])
56  return true;
57  else if (ia[i] > ib[i])
58  return false;
59  }
60 
61  return false;
62  }
63  }
64 };
65 
66 #include <map>
67 
68 void GFXOptimizeList( GFXVertex *old, int numV, GFXVertex **nw, int *nnewV, unsigned int **ind )
69 {
70  std::map< GFXVertex*, int, VertexCompare >vtxcache;
71 
72  *ind = (unsigned int*) malloc( sizeof (unsigned int)*numV );
73  *nw = (GFXVertex*) malloc( numV*sizeof (GFXVertex) );
74  int _nnewV = *nnewV = 0;
75  int i;
76  bool quickpath = true;
77  for (i = 0; i < numV; i++) {
78  std::map< GFXVertex*, int, VertexCompare >::const_iterator it = vtxcache.find( old+i );
79  if ( it != vtxcache.end() ) {
80  if (quickpath && i > 0) {
81  quickpath = false;
82  memcpy( *nw, old, sizeof(GFXVertex)*size_t(i) );
83  }
84  (*ind)[i] = it->second;
85  } else {
86  if (!quickpath)
87  memcpy( (*nw)+_nnewV, old+i, sizeof (GFXVertex) );
88  vtxcache[old+i] = ( (*ind)[i] ) = _nnewV;
89  ++_nnewV;
90  }
91  }
92  if (quickpath && i > 0)
93  memcpy( *nw, old, sizeof(GFXVertex)*size_t(i) );
94  *nnewV = _nnewV;
95 
96  VSFileSystem::vs_dprintf(3, "Optimized vertex list - vertices: %d -> %d\n", numV, *nnewV);
97 }
98 
99 void GFXVertexList::Init( enum POLYTYPE *poly,
100  int numVertices,
101  const GFXVertex *vertices,
102  const GFXColorVertex *colors,
103  int numlists,
104  int *offsets,
105  bool Mutable,
106  unsigned int *indices )
107 {
108  vbo_data = 0;
109 
110  int stride = 0;
111 
112  changed = HAS_COLOR*( (colors != NULL) ? 1 : 0 );
113  if (numlists > 0) {
114  mode = new POLYTYPE[numlists];
115  unique_mode = true;
116  POLYTYPE umode = *poly;
117  for (int pol = 0; pol < numlists; pol++) {
118  mode[pol] = poly[pol]; //PolyLookup (poly[pol]);
119  if ( unique_mode && (poly[pol] != umode) ) unique_mode = false;
120  }
121  } else {
122  mode = NULL;
123  unique_mode = false;
124  }
125  this->numlists = numlists;
126  this->numVertices = numVertices;
127  if (numVertices) {
128  if (vertices) {
129  if (!GFX_BUFFER_MAP_UNMAP) {
130  data.vertices = (GFXVertex*) malloc( sizeof (GFXVertex)*numVertices );
131  memcpy( data.vertices, vertices, sizeof (GFXVertex)*numVertices );
132  } else {
133  data.vertices = const_cast< GFXVertex* > (vertices); //will *not* modify
134  }
135  } else if (colors) {
136  if (!GFX_BUFFER_MAP_UNMAP) {
137  data.colors = (GFXColorVertex*) malloc( sizeof (GFXColorVertex)*numVertices );
138  memcpy( data.colors, colors, sizeof (GFXColorVertex)*numVertices );
139  } else {
140  data.colors = const_cast< GFXColorVertex* > (colors);
141  }
142  }
143  } else {
144  data.vertices = NULL;
145  data.colors = NULL;
146  }
147  this->offsets = new int[numlists];
148  memcpy( this->offsets, offsets, sizeof (int)*numlists );
149  int i;
150  unsigned int numindices = 0;
151  for (i = 0; i < numlists; i++)
152  numindices += offsets[i];
153  display_list = 0;
154  if (Mutable)
156  else
158  if (indices) {
159  stride = INDEX_BYTE;
160  if (numVertices > 255)
161  stride = INDEX_SHORT;
162  if (numVertices > 65535)
163  stride = INDEX_INT;
164 
165  index.b = (unsigned char*) malloc( stride*numindices );
166  switch (stride)
167  {
168  case INDEX_BYTE:
169  VSFileSystem::vs_dprintf(3, "Optimized vertex list - using 8-bit indices\n");
170  for (unsigned int i = 0; i < numindices; i++)
171  index.b[i] = indices[i];
172  break;
173  case INDEX_SHORT:
174  VSFileSystem::vs_dprintf(3, "Optimized vertex list - using 16-bit indices\n");
175  for (unsigned int i = 0; i < numindices; i++)
176  index.s[i] = indices[i];
177  break;
178  case INDEX_INT:
179  VSFileSystem::vs_dprintf(2, "Optimized vertex list - using 32-bit indices\n");
180  for (unsigned int i = 0; i < numindices; i++)
181  index.i[i] = indices[i];
182  break;
183  }
184  } else {
185  index.b = NULL;
186  }
187  changed |= stride;
190  if (GFX_BUFFER_MAP_UNMAP) {
191  if (!vbo_data) {
192  //backstore required
193  if (numVertices) {
194  if (vertices) {
195  data.vertices = (GFXVertex*) malloc( sizeof (GFXVertex)*numVertices );
196  memcpy( data.vertices, vertices, sizeof (GFXVertex)*numVertices );
197  } else if (colors) {
198  data.colors = (GFXColorVertex*) malloc( sizeof (GFXColorVertex)*numVertices );
199  memcpy( data.colors, colors, sizeof (GFXColorVertex)*numVertices );
200  }
201  }
202  } else {
203  if (index.b)
204  free( index.b );
205  index.b = NULL;
206  data.vertices = NULL;
207  data.colors = NULL;
208  }
209  }
210  if (Mutable)
211  changed |= CHANGE_MUTABLE; //for display lists
212  else
213  changed &= (~CHANGE_CHANGE);
214 }
215 
217 {
218  int tot = 0;
219  for (int i = 0; i < numlists; i++) {
220  switch (mode[i])
221  {
222  case GFXTRI:
223  tot += offsets[i]/3;
224  break;
225  case GFXTRISTRIP:
226  case GFXTRIFAN:
227  case GFXPOLY:
228  tot += offsets[i]-2;
229  break;
230  default:
231  break;
232  }
233  }
234  return tot;
235 }
236 
238 {
239  int tot = 0;
240  for (int i = 0; i < numlists; i++) {
241  switch (mode[i])
242  {
243  case GFXQUAD:
244  tot += offsets[i]/4;
245  break;
246  case GFXQUADSTRIP:
247  tot += (offsets[i]-2)/2;
248  break;
249  default:
250  break;
251  }
252  }
253  return tot;
254 }
255 
256 void GFXVertexList::VtxCopy( GFXVertexList *thus, GFXVertex *dst, int offset, int howmany )
257 {
258  memcpy( dst, &thus->data.vertices[offset], sizeof (GFXVertex)*howmany );
259 }
260 
261 void GFXVertexList::ColVtxCopy( GFXVertexList *thus, GFXVertex *dst, int offset, int howmany )
262 {
263  for (int i = 0; i < howmany; i++)
264  dst[i].
265  SetTexCoord( thus->data.colors[i+offset].s, thus->data.colors[i+offset].t ).
266  SetNormal( Vector( thus->data.colors[i+offset].i, thus->data.colors[i+offset].j, thus->data.colors[i+offset].k ) ).
267  SetVertex( Vector( thus->data.colors[i+offset].x, thus->data.colors[i+offset].y, thus->data.colors[i+offset].z ) ).
268  SetTangent( Vector( thus->data.colors[i+offset].tx,
269  thus->data.colors[i+offset].ty,
270  thus->data.colors[i+offset].tz ), thus->data.colors[i+offset].tw );
271 }
272 
274 {
275  if (data.colors == 0 && data.vertices == 0)
276  return; //
277  if (numVertices > 0) {
278  Vector firstNormal;
279  if (changed&HAS_COLOR)
280  firstNormal = data.colors[0].GetNormal();
281  else
282  firstNormal = data.vertices[0].GetNormal();
283  float mag = firstNormal.Magnitude();
284  if (mag > GFX_SCALE/1.5 && mag < GFX_SCALE*1.5)
285  return;
286  if (mag < GFX_SCALE/100 && mag < .00001)
287  firstNormal.Set( 1, 0, 0 );
288  firstNormal.Normalize();
289  if (changed&HAS_COLOR)
290  data.colors[0].SetNormal( firstNormal );
291  else
292  data.vertices[0].SetNormal( firstNormal );
293  if (changed&HAS_COLOR) {
294  for (int i = 0; i < numVertices; i++) {
295  //data.colors[i].SetNormal(data.colors[i].GetNormal().Normalize());
296  data.colors[i].i *= GFX_SCALE;
297  data.colors[i].j *= GFX_SCALE;
298  data.colors[i].k *= GFX_SCALE;
299  }
300  } else {
301  for (int i = 0; i < numVertices; i++) {
302  //data.vertices[i].SetNormal(data.vertices[i].GetNormal().Normalize());
303  data.vertices[i].i *= GFX_SCALE;
304  data.vertices[i].j *= GFX_SCALE;
305  data.vertices[i].k *= GFX_SCALE;
306  }
307  }
308  }
309 }
310 
311 unsigned int GFXVertexList::GetIndex( int offset ) const
312 {
313  return ( changed&sizeof (unsigned char) )
314  ? (unsigned int) (index.b[offset])
315  : ( ( changed&sizeof (unsigned short) )
316  ? (unsigned int) (index.s[offset])
317  : index.i[offset] );
318 }
319 
320 void GFXVertexList::ColIndVtxCopy( GFXVertexList *thus, GFXVertex *dst, int offset, int howmany )
321 {
322  for (int i = 0; i < howmany; i++) {
323  unsigned int j = thus->GetIndex( i+offset );
324  dst[i].
325  SetTexCoord( thus->data.colors[j].s, thus->data.colors[j].t ).
326  SetNormal( Vector( thus->data.colors[j].i, thus->data.colors[j].j, thus->data.colors[j].k ) ).
327  SetVertex( Vector( thus->data.colors[j].x, thus->data.colors[j].y, thus->data.colors[j].z ) ).
328  SetTangent( Vector( thus->data.colors[j].tx,
329  thus->data.colors[j].ty,
330  thus->data.colors[j].tz ), thus->data.colors[j].tw );
331  }
332 }
333 
334 void GFXVertexList::IndVtxCopy( GFXVertexList *thus, GFXVertex *dst, int offset, int howmany )
335 {
336  for (int i = 0; i < howmany; i++) {
337  unsigned int j = thus->GetIndex( i+offset );
338  dst[i].
339  SetTexCoord( thus->data.vertices[j].s, thus->data.vertices[j].t ).
340  SetNormal( Vector( thus->data.vertices[j].i, thus->data.vertices[j].j, thus->data.vertices[j].k ) ).
341  SetVertex( Vector( thus->data.vertices[j].x, thus->data.vertices[j].y, thus->data.vertices[j].z ) ).
342  SetTangent( Vector( thus->data.vertices[j].tx,
343  thus->data.vertices[j].ty,
344  thus->data.vertices[j].tz ), thus->data.vertices[j].tw );
345  }
346 }
347 
349 {
350  return (changed&HAS_COLOR) != 0;
351 }
352 
354 {
355  return data.vertices+index;
356 }
357 
359 {
360  return data.colors+index;
361 }
362 
363 void GFXVertexList::GetPolys( GFXVertex **vert, int *numpolys, int *numtris )
364 {
365  if (numVertices == 0) {
366  *numpolys = 0;
367  *numtris = 0;
368  *vert = 0;
369  return;
370  }
371  this->Map( true, false );
372  void (*vtxcpy)( GFXVertexList *thus, GFXVertex *dst, int offset, int howmany );
373  vtxcpy = (changed&HAS_COLOR)
374  ? ( (changed&HAS_INDEX)
375  ? ColIndVtxCopy
376  : ColVtxCopy )
377  : ( (changed&HAS_INDEX)
378  ? IndVtxCopy
379  : VtxCopy );
380  //int offst = (changed&HAS_COLOR)?sizeof(GFXColorVertex):sizeof(GFXVertex);
381  int i;
382  int cur = 0;
383  GFXVertex *res;
384  *numtris = numTris();
385  *numpolys = *numtris+numQuads();
386  int curtri = 0;
387  int curquad = 3*(*numtris);
388  res = (GFXVertex*) malloc( ( (*numtris)*3+4*( *numpolys-(*numtris) ) )*sizeof (GFXVertex) );
389  *vert = res;
390  for (i = 0; i < numlists; i++) {
391  int j;
392  switch (mode[i])
393  {
394  case GFXTRI:
395  (*vtxcpy)(this, &res[curtri], cur, offsets[i]);
396  curtri += offsets[i];
397  break;
398  case GFXTRIFAN:
399  case GFXPOLY:
400  for (j = 1; j < offsets[i]-1; j++) {
401  (*vtxcpy)(this, &res[curtri++], cur, 1);
402  (*vtxcpy)(this, &res[curtri++], (cur+j), 1);
403  (*vtxcpy)(this, &res[curtri++], (cur+j+1), 1);
404  }
405  break;
406  case GFXTRISTRIP:
407  for (j = 2; j < offsets[i]; j += 2) {
408  (*vtxcpy)(this, &res[curtri++], (cur+j-2), 1);
409  (*vtxcpy)(this, &res[curtri++], (cur+j-1), 1);
410  (*vtxcpy)(this, &res[curtri++], (cur+j), 1);
411  if (j+1 < offsets[i]) {
412  //copy reverse
413  (*vtxcpy)(this, &res[curtri++], (cur+j), 1);
414  (*vtxcpy)(this, &res[curtri++], (cur+j-1), 1);
415  (*vtxcpy)(this, &res[curtri++], (cur+j+1), 1);
416  }
417  }
418  break;
419  case GFXQUAD:
420  (*vtxcpy)(this, &res[curquad], (cur), offsets[i]);
421  curquad += offsets[i];
422  break;
423  case GFXQUADSTRIP:
424  for (j = 2; j < offsets[i]-1; j += 2) {
425  (*vtxcpy)(this, &res[curquad++], (cur+j-2), 1);
426  (*vtxcpy)(this, &res[curquad++], (cur+j-1), 1);
427  (*vtxcpy)(this, &res[curquad++], (cur+j+1), 1);
428  (*vtxcpy)(this, &res[curquad++], (cur+j), 1);
429  }
430  break;
431  default:
432  break;
433  }
434  cur += offsets[i];
435  }
436  this->UnMap();
437 }
438 
440 {
441 }
442