root/OpenSceneGraph/trunk/src/osgPlugins/flt/LocalVertexPoolRecord.cpp @ 3527

Revision 3527, 15.1 kB (checked in by robert, 9 years ago)

From Fred Mammond, fixes for x86_64 build

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// LocalVertexPoolRecords.cpp
2
3#ifdef _WIN32
4#pragma warning(disable:4786) // Truncated debug names.
5#endif
6
7#include "LocalVertexPoolRecord.h"
8#include "Registry.h"
9#include <assert.h>
10
11// The sizes (in bytes) of the various attribute sections of the vertex data.
12#define SIZE_POSITION       24 // 3 * float64 = 3 * 8
13#define SIZE_COLOR           4 // 1 uint32
14#define SIZE_NORMAL         12 // 3 * float32 = 3 * 4
15#define SIZE_BASE_UV         8 // 2 * float32 = 2 * 4
16#define SIZE_UV_1           SIZE_BASE_UV
17#define SIZE_UV_2           SIZE_BASE_UV
18#define SIZE_UV_3           SIZE_BASE_UV
19#define SIZE_UV_4           SIZE_BASE_UV
20#define SIZE_UV_5           SIZE_BASE_UV
21#define SIZE_UV_6           SIZE_BASE_UV
22#define SIZE_UV_7           SIZE_BASE_UV
23
24
25using namespace flt;
26
27
28////////////////////////////////////////////////////////////////////
29//
30//                       LocalVertexPoolRecord
31//
32////////////////////////////////////////////////////////////////////
33
34RegisterRecordProxy<LocalVertexPoolRecord> g_LocalVertexPoolProxy;
35LocalVertexPoolRecord *_current = NULL;
36
37LocalVertexPoolRecord::LocalVertexPoolRecord()
38  : AncillaryRecord(),
39    _vertexSizeBytesCache(0)
40{
41}
42
43
44// virtual
45LocalVertexPoolRecord::~LocalVertexPoolRecord()
46{
47}
48
49
50///////////////////////////////////////////////////////////////////////////////
51//
52//  Return the address of the beginning of the vertices.
53//
54///////////////////////////////////////////////////////////////////////////////
55
56char *LocalVertexPoolRecord::_getStartOfVertices() const
57{
58  SLocalVertexPool *pool = (SLocalVertexPool *) this->getData();
59  char *vertex = (char *) (&(pool[1]));
60  return vertex;
61}
62
63
64///////////////////////////////////////////////////////////////////////////////
65//
66//  Return the address of the beginning of the specified vertex attribute.
67//
68///////////////////////////////////////////////////////////////////////////////
69
70char *LocalVertexPoolRecord::_getStartOfAttribute ( const uint32 &whichVertex, const uint32 &offset ) const
71{
72  assert ( whichVertex < this->getNumVertices() );
73
74  // Get pointer to start of vertex data.
75  char *startOfVertices = (char *) this->_getStartOfVertices();
76
77  // The number of vertices.
78  //uint32 numVertices = this->getNumVertices();
79
80  // NOTE This function formerly computed sizeOfVertex by taking the record length and dividing
81  //   by the number of vertices. This is wrong in 15.7 and beyond, as the record could
82  //   exceed 65535 bytes and be continued, in which case the "original" record length
83  //   field does not contain the actual length of the data.
84
85  // The size of each individual vertex depends on its attributes, and is cached.
86  size_t sizeOfVertex = this->_getVertexSizeBytes();
87
88  // Set the start of the desired vertex's data.
89  char *startOfAttribute = &startOfVertices[whichVertex * sizeOfVertex];
90
91  // Now adjust for the offset within this vertex.
92  startOfAttribute += offset;
93
94  // Return the pointer.
95  return startOfAttribute;
96}
97
98
99///////////////////////////////////////////////////////////////////////////////
100//
101//  Return the specified vertex attribute.
102//
103///////////////////////////////////////////////////////////////////////////////
104
105bool LocalVertexPoolRecord::getColorIndex ( const uint32 &whichVertex, uint32 &colorIndex ) const
106{
107  ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, COLOR_INDEX );
108
109  // Offset to the start of the color.
110  uint32 *color = (uint32 *) this->_getStartOfAttribute ( whichVertex, _offset.color );
111  if ( NULL == color )
112    return false;
113
114  // Set the color index and return.
115  colorIndex = *color;
116  return true;
117}
118
119
120///////////////////////////////////////////////////////////////////////////////
121//
122//  Return the specified vertex attribute.
123//
124///////////////////////////////////////////////////////////////////////////////
125
126bool LocalVertexPoolRecord::getColorRGBA ( const uint32 &whichVertex, float32 &r, float32 &g, float32 &b, float32 &a ) const
127{
128  ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, RGB_COLOR );
129
130  // Offset to the start of the color.
131  uint32 *color = (uint32 *) this->_getStartOfAttribute ( whichVertex, _offset.color );
132  if ( NULL == color )
133    return false;
134
135  // Since we already byte-swapped, we have to check the endian of this
136  // machine so that we know how to grab the channels.
137  uint32 red, green, blue, alpha;
138
139  // If this machine is little-endian...
140  if ( flt::isLittleEndianMachine() )
141  {
142    red   = ( ( (*color) & 0xFF000000 ) >>  0 );
143    green = ( ( (*color) & 0x00FF0000 ) >>  8 );
144    blue  = ( ( (*color) & 0x0000FF00 ) >> 16 );
145    alpha = ( ( (*color) & 0x000000FF ) >> 24 );
146  }
147
148  // Otherwise, big-endian...
149  else
150  {
151    red   = ( ( (*color) & 0x000000FF ) >>  0 );
152    green = ( ( (*color) & 0x0000FF00 ) >>  8 );
153    blue  = ( ( (*color) & 0x00FF0000 ) >> 16 );
154    alpha = ( ( (*color) & 0xFF000000 ) >> 24 );
155  }
156
157  // Normalize.
158  float32 scale = 1.0f / 255.0f;
159  r = scale * red;
160  g = scale * green;
161  b = scale * blue;
162  a = scale * alpha;
163
164  // It worked.
165  return true;
166}
167
168
169///////////////////////////////////////////////////////////////////////////////
170//
171//  Return the specified vertex attribute.
172//
173///////////////////////////////////////////////////////////////////////////////
174
175bool LocalVertexPoolRecord::getNormal ( const uint32 &whichVertex, float32 &nx, float32 &ny, float32 &nz ) const
176{
177  ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, NORMAL );
178
179  // Offset to the start of the normals.
180  float32 *vec = (float32 *) this->_getStartOfAttribute ( whichVertex, _offset.normal );
181  if ( NULL == vec )
182    return false;
183
184  // Set the normal vector and return.
185  nx = vec[0];
186  ny = vec[1];
187  nz = vec[2];
188  return true;
189}
190
191
192///////////////////////////////////////////////////////////////////////////////
193//
194//  Return the specified vertex attribute.
195//
196///////////////////////////////////////////////////////////////////////////////
197
198bool LocalVertexPoolRecord::getPosition ( const uint32 &whichVertex, float64 &px, float64 &py, float64 &pz ) const
199{
200  ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, POSITION );
201
202  // Offset to the start of the normals.
203  float64 *point = (float64 *) this->_getStartOfAttribute ( whichVertex, _offset.position );
204  if ( NULL == point )
205    return false;
206
207  // Set the normal vector and return.
208  px = point[0];
209  py = point[1];
210  pz = point[2];
211  return true;
212}
213
214
215///////////////////////////////////////////////////////////////////////////////
216//
217//  Return the specified vertex attribute.
218//
219///////////////////////////////////////////////////////////////////////////////
220
221bool LocalVertexPoolRecord::getUV ( const uint32 &whichVertex, const AttributeMask &whichUV, float32 &u, float32 &v ) const
222{
223  ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, (uint32) whichUV );
224
225  // Offset to the start of the normals.
226  float32 *uv = (float32 *) this->_getStartOfAttribute ( whichVertex, this->_getOffset ( whichUV ) );
227  if ( NULL == uv )
228    return false;
229
230  // Set the normal vector and return.
231  u = uv[0];
232  v = uv[1];
233  return true;
234}
235
236
237///////////////////////////////////////////////////////////////////////////////
238//
239//  Getthe offset that corresponds to the given attribute.
240//
241///////////////////////////////////////////////////////////////////////////////
242
243uint32 LocalVertexPoolRecord::_getOffset ( const AttributeMask &attribute ) const
244{
245  switch ( attribute )
246  {
247  case POSITION:    return _offset.position;
248  case COLOR_INDEX: return _offset.color;
249  case RGB_COLOR:   return _offset.color;
250  case NORMAL:      return _offset.normal;
251  case BASE_UV:     return _offset.baseUV;
252  case UV_1:        return _offset.uv1;
253  case UV_2:        return _offset.uv2;
254  case UV_3:        return _offset.uv3;
255  case UV_4:        return _offset.uv4;
256  case UV_5:        return _offset.uv5;
257  case UV_6:        return _offset.uv6;
258  case UV_7:        return _offset.uv7;
259  default:
260    assert ( 0 );
261    return 0;
262  }
263}
264
265
266///////////////////////////////////////////////////////////////////////////////
267//
268//  Convert the data from big-endian to little-endian.
269//
270///////////////////////////////////////////////////////////////////////////////
271
272void LocalVertexPoolRecord::endian()
273{
274  // Should only be in here for little-endian machines.
275  assert ( flt::isLittleEndianMachine() );
276
277  // Get a pointer to the vertex pool structure. Note: The members of
278  // SLocalVertexPool have already been endian-corrected in
279  // _initAttributeOffsets().
280  SLocalVertexPool *pool = (SLocalVertexPool *) this->getData();
281
282  // Get pointer to start of vertex data.
283  char *vertex = this->_getStartOfVertices();
284
285  // Loop through the vertices and byte-swap the data.
286  for ( uint32 i = 0; i < pool->numVerts; ++i )
287  {
288    if ( this->hasAttribute ( POSITION ) )
289    {
290      // Get the size of the coordinates.
291      size_t size = sizeof ( float64 );
292
293      // Get the values.
294      float64 *x = (float64 *) vertex;
295      float64 *y = &(x[1]);
296      float64 *z = &(y[1]);
297
298      // Swap the data.
299      flt::swapBytes ( size, x );
300      flt::swapBytes ( size, y );
301      flt::swapBytes ( size, z );
302
303      // Move pointer to the end of this chunk of data.
304      vertex = (char *) ( &(z[1]) );
305    }
306
307    if ( this->hasAttribute ( COLOR_INDEX ) ||
308         this->hasAttribute ( RGB_COLOR ) )
309    {
310      // Get the size of the coordinates.
311      size_t size = sizeof ( uint32 );
312
313      // Get the value.
314      uint32 *color = (uint32 *) vertex;
315
316      // Swap the data.
317      flt::swapBytes ( size, color );
318
319      // Move pointer to the end of this chunk of data.
320      vertex = (char *) ( &(color[1]) );
321    }
322
323    if ( this->hasAttribute ( NORMAL ) )
324    {
325      // Get the size of the elements.
326      size_t size = sizeof ( float32 );
327
328      // Get the values.
329      float32 *x = (float32 *) vertex;
330      float32 *y = &(x[1]);
331      float32 *z = &(y[1]);
332
333      // Swap the data.
334      flt::swapBytes ( size, x );
335      flt::swapBytes ( size, y );
336      flt::swapBytes ( size, z );
337
338      // Move pointer to the end of this chunk of data.
339      vertex = (char *) ( &(z[1]) );
340    }
341
342    if ( this->hasAttribute ( BASE_UV ) ||
343         this->hasAttribute ( UV_1 ) ||
344         this->hasAttribute ( UV_2 ) ||
345         this->hasAttribute ( UV_3 ) ||
346         this->hasAttribute ( UV_4 ) ||
347         this->hasAttribute ( UV_5 ) ||
348         this->hasAttribute ( UV_6 ) ||
349         this->hasAttribute ( UV_7 ) )
350    {
351      // Get the size of the elements.
352      size_t size = sizeof ( float32 );
353
354      // Get the values.
355      float32 *u = (float32 *) vertex;
356      float32 *v = &(u[1]);
357
358      // Swap the data.
359      flt::swapBytes ( size, u );
360      flt::swapBytes ( size, v );
361
362      // Move pointer to the end of this chunk of data.
363      vertex = (char *) ( &(v[1]) );
364    }
365  }
366
367  // Should be true. It means that we walked the pointer "vertex" to the
368  // end of the record, but not past it.
369  // If equal, vertex pool record was not continued.
370  // If 16bit record length is less than length of vertex pool, then the original vertex
371  //   pool record was continued with one or more CONTINUATION_OP records.
372  assert ( pool->RecHeader._wLength <= ( ( (unsigned long) vertex ) - ( (unsigned long) pool ) ) );
373}
374
375
376///////////////////////////////////////////////////////////////////////////////
377//
378//  The offsets to the start of each attribute depends on the what attributes
379//  are in the vertices. Here we initialize those integer data members.
380//
381///////////////////////////////////////////////////////////////////////////////
382
383void LocalVertexPoolRecord::_initAttributeOffsets()
384{
385  // When we get to here we just got done reading the data (i.e., it is still
386  // big-endian). Correct the endian of the members of SLocalVertexPool
387  // because we need the SLocalVertexPool::attributeMask to determine the
388  // offsets (but do not endian-correct the vertex data that follows). The
389  // rest of the data (the vertices) will be endian-corrected in endian().
390
391  // If we are on a little-endian machine...
392  if ( flt::isLittleEndianMachine() )
393  {
394    // Fix these data members.
395    SLocalVertexPool *pool = (SLocalVertexPool *) this->getData();
396    ENDIAN ( pool->numVerts );
397    ENDIAN ( pool->attributeMask );
398  }
399
400  // Initialize.
401  uint32 current = 0;
402
403  // The order is important because the data will be in this order. We drop
404  // down through here and set the offsets. Each time we update the current
405  // position so that we can set the next one.
406
407  if ( this->hasAttribute ( POSITION ) )
408  {
409    _offset.position = current;
410    current += SIZE_POSITION;
411  }
412
413  if ( this->hasAttribute ( COLOR_INDEX ) || this->hasAttribute ( RGB_COLOR ) )
414  {
415    // According to 15.7 manual, we should not have both flags.
416    assert ( false == ( this->hasAttribute ( COLOR_INDEX ) && this->hasAttribute ( RGB_COLOR ) ) );
417
418    _offset.color = current;
419    current += SIZE_COLOR;
420  }
421
422  if ( this->hasAttribute ( NORMAL ) )
423  {
424    _offset.normal = current;
425    current += SIZE_NORMAL;
426  }
427
428  if ( this->hasAttribute ( BASE_UV ) )
429  {
430    _offset.baseUV = current;
431    current += SIZE_BASE_UV;
432  }
433
434  if ( this->hasAttribute ( UV_1 ) )
435  {
436    _offset.uv1 = current;
437    current += SIZE_UV_1;
438  }
439
440  if ( this->hasAttribute ( UV_2 ) )
441  {
442    _offset.uv2 = current;
443    current += SIZE_UV_2;
444  }
445
446  if ( this->hasAttribute ( UV_3 ) )
447  {
448    _offset.uv3 = current;
449    current += SIZE_UV_3;
450  }
451
452  if ( this->hasAttribute ( UV_4 ) )
453  {
454    _offset.uv4 = current;
455    current += SIZE_UV_4;
456  }
457
458  if ( this->hasAttribute ( UV_5 ) )
459  {
460    _offset.uv5 = current;
461    current += SIZE_UV_5;
462  }
463
464  if ( this->hasAttribute ( UV_6 ) )
465  {
466    _offset.uv6 = current;
467    current += SIZE_UV_6;
468  }
469
470  if ( this->hasAttribute ( UV_7 ) )
471  {
472    _offset.uv7 = current;
473    current += SIZE_UV_7;
474  }
475}
476
477
478///////////////////////////////////////////////////////////////////////////////
479//
480//  Compute the size of each vertex based on its attributes. Cache the
481//  result for later reference.
482//
483///////////////////////////////////////////////////////////////////////////////
484
485int LocalVertexPoolRecord::_getVertexSizeBytes() const
486{
487  if (_vertexSizeBytesCache == 0)
488  {
489    if ( hasAttribute ( POSITION ) )
490      _vertexSizeBytesCache += SIZE_POSITION;
491
492    if ( hasAttribute ( COLOR_INDEX ) || hasAttribute ( RGB_COLOR ) )
493      _vertexSizeBytesCache += SIZE_COLOR;
494
495    if ( hasAttribute ( NORMAL ) )
496      _vertexSizeBytesCache += SIZE_NORMAL;
497
498    if ( hasAttribute ( BASE_UV ) )
499      _vertexSizeBytesCache += SIZE_BASE_UV;
500
501    if ( hasAttribute ( UV_1 ) )
502      _vertexSizeBytesCache += SIZE_UV_1;
503
504    if ( hasAttribute ( UV_2 ) )
505      _vertexSizeBytesCache += SIZE_UV_2;
506
507    if ( hasAttribute ( UV_3 ) )
508      _vertexSizeBytesCache += SIZE_UV_3;
509
510    if ( hasAttribute ( UV_4 ) )
511      _vertexSizeBytesCache += SIZE_UV_4;
512
513    if ( hasAttribute ( UV_5 ) )
514      _vertexSizeBytesCache += SIZE_UV_5;
515
516    if ( hasAttribute ( UV_6 ) )
517      _vertexSizeBytesCache += SIZE_UV_6;
518
519    if ( hasAttribute ( UV_7 ) )
520      _vertexSizeBytesCache += SIZE_UV_7;
521  }
522
523  return _vertexSizeBytesCache;
524}
525
526
527///////////////////////////////////////////////////////////////////////////////
528//
529//  This is called after the record is read.
530//
531///////////////////////////////////////////////////////////////////////////////
532
533void LocalVertexPoolRecord::postReadInit()
534{
535  // Initialize the attribute offsets.
536  this->_initAttributeOffsets();
537
538  // Call the base class's function.
539  AncillaryRecord::postReadInit();
540}
541
Note: See TracBrowser for help on using the browser.