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

Revision 2783, 15.1 kB (checked in by robert, 11 years ago)

From Paul Marz : "Input.h, Input.cpp -- Here's where support for reading the continuation
record goes. I added a new function to read a continued record body. I added
code in the existing ReadRecord? routine to peek ahead for a CONTINUATION_OP
if the current record could possibly be continued.

opcodes.h -- Besides adding the opcode for CONTINUATION_OP, I also added new
15.8 opcodes. I labeled opcodes as "ignored" if I could easily discern that
our loader wasn't doing anything with them. For historical reasons, I added
all obsolete opcodes, prefixed with "OBS_".

LocalVertexPoolRecord?.h, LocalVertexPoolRecord?.cpp -- This is one of three
types of records that can be continued with a CONTINUATION_OP record. I
removed all invalid assertions that assumed the record length would always
be less than 65535. I replaced the "vertex size" calculation with a more
efficient method based on caching the size from attribute bits, rather than
taking the length of the record and dividing it by numVerts (which would
have been incorrect if the record had been continued)."

  • 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 <= ( ( (uint32) vertex ) - ( (uint32) 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.