root/OpenSceneGraph/trunk/src/osgPlugins/OpenFlight/VertexPaletteManager.cpp @ 13041

Revision 13041, 15.7 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1/*
2 * This library is open source and may be redistributed and/or modified under
3 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or (at
4 * your option) any later version. The full license is in the LICENSE file
5 * included with this distribution, and on the openscenegraph.org website.
6 *
7 * This library is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * OpenSceneGraph Public License for more details.
11*/
12
13//
14// Copyright(c) 2008 Skew Matrix Software LLC.
15//
16
17#include "VertexPaletteManager.h"
18#include "DataOutputStream.h"
19#include "Opcodes.h"
20#include "Utils.h"
21#include <osg/Notify>
22#include <osg/Geometry>
23#include <map>
24
25
26namespace flt
27{
28
29
30VertexPaletteManager::VertexPaletteManager( const ExportOptions& fltOpt )
31  : _currentSizeBytes( 8 ),
32    _current( NULL ),
33    _vertices( NULL ),
34    _fltOpt( fltOpt )
35{
36}
37
38VertexPaletteManager::~VertexPaletteManager()
39{
40    if (!_verticesTempName.empty())
41    {
42        // Delete our temp file.
43        if (_verticesStr.is_open())
44        {
45            OSG_WARN << "fltexp: VertexPaletteManager destructor has an open temp file." << std::endl;
46            // This should not happen. FltExportVisitor::complete should close
47            // this file before we get to this destructor.
48            return;
49        }
50        OSG_INFO << "fltexp: Deleting temp file " << _verticesTempName << std::endl;
51        FLTEXP_DELETEFILE( _verticesTempName.c_str() );
52    }
53}
54
55void
56VertexPaletteManager::add( const osg::Geometry& geom )
57{
58    const osg::Array* v = geom.getVertexArray();
59    if (!v)
60    {
61        OSG_WARN << "fltexp: Attempting to add NULL vertex array in VertexPaletteManager." << std::endl;
62        return;
63    }
64    const osg::Array* c = geom.getColorArray();
65    const osg::Array* n = geom.getNormalArray();
66    const osg::Array* t = geom.getTexCoordArray( 0 );
67
68    const unsigned int size = v->getNumElements();
69    osg::ref_ptr< const osg::Vec3dArray > v3 = asVec3dArray( v, size );
70    osg::ref_ptr< const osg::Vec4Array > c4 = asVec4Array( c, size );
71    osg::ref_ptr< const osg::Vec3Array > n3 = asVec3Array( n, size );
72    osg::ref_ptr< const osg::Vec2Array > t2 = asVec2Array( t, size );
73    if (v && !v3)
74        return;
75    if (c && !c4)
76        return;
77    if (n && !n3)
78        return;
79    if (t && !t2)
80        return;
81
82    const bool cpv =( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX );
83    const bool npv =( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX );
84    add( v, v3.get(), c4.get(), n3.get(), t2.get(), cpv, npv );
85}
86void
87VertexPaletteManager::add( const osg::Array* key,
88    const osg::Vec3dArray* v, const osg::Vec4Array* c,
89    const osg::Vec3Array* n, const osg::Vec2Array* t,
90    bool colorPerVertex, bool normalPerVertex, bool allowSharing )
91{
92    bool needsInit( true );
93
94    if (allowSharing)
95    {
96        ArrayMap::iterator it = _arrayMap.find( key );
97        if (it != _arrayMap.end())
98            needsInit = false;
99        _current = &( _arrayMap[ key ] );
100    }
101    else
102    {
103        _current = &( _nonShared );
104    }
105
106    if (needsInit)
107    {
108        _current->_byteStart = _currentSizeBytes;
109
110        _current->_idxCount = v->size();
111
112        _current->_idxSizeBytes = recordSize( recordType( v, c, n, t ) );
113        _currentSizeBytes += ( _current->_idxSizeBytes * _current->_idxCount );
114
115        // Next we'll write the vertex palette record data. But,
116        //   if we don't have a DataOutputStream yet, open the temp file.
117        if (!_vertices)
118        {
119            _verticesTempName = _fltOpt.getTempDir() + "/ofw_temp_vertices";
120            _verticesStr.open( _verticesTempName.c_str(), std::ios::out | std::ios::binary );
121            _vertices = new DataOutputStream( _verticesStr.rdbuf(), _fltOpt.getValidateOnly() );
122        }
123        writeRecords( v, c, n, t, colorPerVertex, normalPerVertex );
124    }
125}
126
127unsigned int
128VertexPaletteManager::byteOffset( unsigned int idx ) const
129{
130    if (!_current)
131    {
132        OSG_WARN << "fltexp: No current vertex array in VertexPaletteManager." << std::endl;
133        return 4;
134    }
135    if (idx >= _current->_idxCount)
136    {
137        OSG_WARN << "fltexp: Index out of range in VertexPaletteManager." << std::endl;
138        return 4;
139    }
140
141    return( _current->_byteStart + (_current->_idxSizeBytes * idx) );
142}
143
144void
145VertexPaletteManager::write( DataOutputStream& dos ) const
146{
147    if (_currentSizeBytes == 8)
148        // Empty palette. Don't write anything.
149        return;
150
151    dos.writeInt16( (int16) VERTEX_PALETTE_OP );
152    dos.writeUInt16( 8 );
153    dos.writeInt32( _currentSizeBytes );
154
155    // Close the temp file. We're done writing new data to it.
156    _verticesStr.close();
157
158    // Open that temp file again, this time for reading.
159    //   Then copy to dos.
160    char buf;
161    osgDB::ifstream vertIn;
162    vertIn.open( _verticesTempName.c_str(), std::ios::in | std::ios::binary );
163    while (!vertIn.eof() )
164    {
165        vertIn.read( &buf, 1 );
166        if (vertIn.good())
167            dos << buf;
168    }
169    vertIn.close();
170}
171
172
173
174VertexPaletteManager::PaletteRecordType
175VertexPaletteManager::recordType( const osg::Array* v, const osg::Array* c,
176    const osg::Array* n, const osg::Array* t )
177{
178    if (t)
179    {
180        // Texture coordinates
181        if (n)
182            return VERTEX_CNT;
183        else
184            return VERTEX_CT;
185    }
186    else
187    {
188        // No texture coordinates
189        if (n)
190            return VERTEX_CN;
191        else
192            return VERTEX_C;
193    }
194}
195
196unsigned int
197VertexPaletteManager::recordSize( PaletteRecordType recType )
198{
199    switch (recType)
200    {
201    case VERTEX_C:
202        return 40;
203        break;
204    case VERTEX_CN:
205        return (_fltOpt.getFlightFileVersionNumber() > ExportOptions::VERSION_15_7) ? 56 : 52;
206        break;
207    case VERTEX_CT:
208        return 48;
209        break;
210    case VERTEX_CNT:
211        return 64;
212        break;
213    default:
214        return 0;
215    }
216}
217
218void
219VertexPaletteManager::writeRecords( const osg::Vec3dArray* v, const osg::Vec4Array* c,
220    const osg::Vec3Array* n, const osg::Vec2Array* t,
221    bool colorPerVertex, bool normalPerVertex )
222{
223    const PaletteRecordType recType = recordType( v, c, n, t );
224    const int16 sizeBytes = recordSize( recType );
225
226    int16 opcode = 0;
227    switch( recType )
228    {
229    case VERTEX_C:
230        opcode = VERTEX_C_OP;
231        break;
232    case VERTEX_CN:
233        opcode = VERTEX_CN_OP;
234        if (!n)
235            OSG_WARN << "fltexp: VPM::writeRecords: no normal array." << std::endl;
236        break;
237    case VERTEX_CNT:
238        opcode = VERTEX_CNT_OP;
239        if (!n)
240            OSG_WARN << "fltexp: VPM::writeRecords: no normal array." << std::endl;
241        if (!t)
242            OSG_WARN << "fltexp: VPM::writeRecords: no tex coord array." << std::endl;
243        break;
244    case VERTEX_CT:
245        opcode = VERTEX_CT_OP;
246        if (!t)
247            OSG_WARN << "fltexp: VPM::writeRecords: no tex coord array." << std::endl;
248        break;
249    }
250
251    enum FlagBits
252    {
253        START_HARD_EDGE = (0x8000 >> 0),
254        NORMAL_FROZEN   = (0x8000 >> 1),
255        NO_COLOR        = (0x8000 >> 2),
256        PACKED_COLOR    = (0x8000 >> 3)
257    };
258    uint32 flags( NO_COLOR );
259    if (colorPerVertex)
260        flags = PACKED_COLOR;
261
262
263    size_t idx;
264    for( idx=0; idx<v->size(); idx++)
265    {
266        uint32  packedColor( 0 );
267        if (c && colorPerVertex)
268        {
269            osg::Vec4 color = (*c)[ idx ];
270            packedColor = (int)(color[3]*255) << 24 |
271                (int)(color[2]*255) << 16 | (int)(color[1]*255) << 8 |
272                (int)(color[0]*255);
273        }
274
275        // Write fields common to all record types.
276        _vertices->writeInt16( opcode );
277        _vertices->writeUInt16( sizeBytes );
278        _vertices->writeUInt16( 0 ); // Color name
279        _vertices->writeInt16( flags ); // Flags
280        _vertices->writeVec3d( (*v)[ idx ] ); // Vertex
281
282        // Now write record-specific fields.
283        switch( recType )
284        {
285        case VERTEX_C:
286        {
287            _vertices->writeInt32( packedColor ); // Packed color
288            _vertices->writeUInt32( 0 ); // Vertex color index
289            break;
290        }
291        case VERTEX_CN:
292        {
293            if (!normalPerVertex) // Normal
294                _vertices->writeVec3f( (*n)[ 0 ] );
295            else
296                _vertices->writeVec3f( (*n)[ idx ] );
297            _vertices->writeInt32( packedColor ); // Packed color
298            _vertices->writeUInt32( 0 ); // Vertex color index
299            if (_fltOpt.getFlightFileVersionNumber() > ExportOptions::VERSION_15_7)
300                _vertices->writeUInt32( 0 ); // Reserved
301            break;
302        }
303        case VERTEX_CNT:
304        {
305            if (!normalPerVertex) // Normal
306                _vertices->writeVec3f( (*n)[ 0 ] );
307            else
308                _vertices->writeVec3f( (*n)[ idx ] );
309            _vertices->writeVec2f( (*t)[ idx ] ); // Tex coord
310            _vertices->writeInt32( packedColor ); // Packed color
311            _vertices->writeUInt32( 0 ); // Vertex color index
312            _vertices->writeUInt32( 0 ); // Reserved
313            break;
314        }
315        case VERTEX_CT:
316        {
317            _vertices->writeVec2f( (*t)[ idx ] ); // Tex coord
318            _vertices->writeInt32( packedColor ); // Packed color
319            _vertices->writeUInt32( 0 ); // Vertex color index
320            break;
321        }
322        }
323    }
324}
325
326
327
328osg::ref_ptr< const osg::Vec2Array >
329VertexPaletteManager::asVec2Array( const osg::Array* in, const unsigned int n )
330{
331    if (!in)
332        return NULL;
333
334    osg::Array::Type arrayType = in->getType();
335    if (arrayType == osg::Array::Vec2ArrayType)
336    {
337        if (n <= in->getNumElements())
338        {
339            osg::ref_ptr< const osg::Vec2Array > v2f =
340                dynamic_cast< const osg::Vec2Array* >( in );
341            return v2f;
342        }
343    }
344
345    const unsigned int nToCopy = ( (n < in->getNumElements()) ? n : in->getNumElements() );
346    osg::ref_ptr< osg::Vec2Array > ret = new osg::Vec2Array( n );
347
348    switch( arrayType )
349    {
350    case osg::Array::Vec2ArrayType:
351    {
352        // No need to convert data, but must copy into correctly-sized array.
353        // If the size was correct, we wouldn't be here.
354        osg::ref_ptr< const osg::Vec2Array > v2f =
355            dynamic_cast< const osg::Vec2Array* >( in );
356        ret->assign( v2f->begin(), v2f->end() );;
357        ret->resize( n );
358        return ret.get();
359    }
360    case osg::Array::Vec2dArrayType:
361    {
362        osg::ref_ptr< const osg::Vec2dArray > v2d =
363            dynamic_cast< const osg::Vec2dArray* >( in );
364        unsigned int idx;
365        for (idx=0; idx<nToCopy; idx++ )
366            (*ret)[ idx ] = (*v2d)[ idx ]; // convert Vec2 double to Vec2 float
367        return ret.get();
368    }
369    default:
370    {
371        OSG_WARN << "fltexp: Unsupported array type in conversion to Vec2Array: " << arrayType << std::endl;
372        return NULL;
373    }
374    }
375}
376osg::ref_ptr< const osg::Vec3Array >
377VertexPaletteManager::asVec3Array( const osg::Array* in, const unsigned int n )
378{
379    if (!in)
380        return NULL;
381
382    osg::Array::Type arrayType = in->getType();
383    if (arrayType == osg::Array::Vec3ArrayType)
384    {
385        if (n <= in->getNumElements())
386        {
387            osg::ref_ptr< const osg::Vec3Array > v3f =
388                dynamic_cast< const osg::Vec3Array* >( in );
389            return v3f;
390        }
391    }
392
393    const unsigned int nToCopy = ( (n < in->getNumElements()) ? n : in->getNumElements() );
394    osg::ref_ptr< osg::Vec3Array > ret = new osg::Vec3Array( n );
395
396    switch( arrayType )
397    {
398    case osg::Array::Vec3ArrayType:
399    {
400        // No need to convert data, but must copy into correctly-sized array.
401        // If the size was correct, we wouldn't be here.
402        osg::ref_ptr< const osg::Vec3Array > v3f =
403            dynamic_cast< const osg::Vec3Array* >( in );
404        ret->assign( v3f->begin(), v3f->end() );;
405        ret->resize( n );
406        return ret.get();
407    }
408    case osg::Array::Vec3dArrayType:
409    {
410        osg::ref_ptr< const osg::Vec3dArray > v3d =
411            dynamic_cast< const osg::Vec3dArray* >( in );
412        unsigned int idx;
413        for (idx=0; idx<nToCopy; idx++ )
414            (*ret)[ idx ] = (*v3d)[ idx ]; // convert Vec3 double to Vec3 float
415        return ret.get();
416    }
417    default:
418    {
419        OSG_WARN << "fltexp: Unsupported array type in conversion to Vec3Array: " << arrayType << std::endl;
420        return NULL;
421    }
422    }
423}
424osg::ref_ptr< const osg::Vec3dArray >
425VertexPaletteManager::asVec3dArray( const osg::Array* in, const unsigned int n )
426{
427    if (!in)
428        return NULL;
429
430    osg::Array::Type arrayType = in->getType();
431    if (arrayType == osg::Array::Vec3dArrayType)
432    {
433        if (n <= in->getNumElements())
434        {
435            osg::ref_ptr< const osg::Vec3dArray > v3d =
436                dynamic_cast< const osg::Vec3dArray* >( in );
437            return v3d;
438        }
439    }
440
441    const unsigned int nToCopy = ( (n < in->getNumElements()) ? n : in->getNumElements() );
442    osg::ref_ptr< osg::Vec3dArray > ret = new osg::Vec3dArray( n );
443
444    switch( arrayType )
445    {
446    case osg::Array::Vec3dArrayType:
447    {
448        // No need to convert data, but must copy into correctly-sized array.
449        // If the size was correct, we wouldn't be here.
450        osg::ref_ptr< const osg::Vec3dArray > v3d =
451            dynamic_cast< const osg::Vec3dArray* >( in );
452        ret->assign( v3d->begin(), v3d->end() );;
453        ret->resize( n );
454        return ret.get();
455    }
456    case osg::Array::Vec3ArrayType:
457    {
458        osg::ref_ptr< const osg::Vec3Array > v3f =
459            dynamic_cast< const osg::Vec3Array* >( in );
460        unsigned int idx;
461        for (idx=0; idx<nToCopy; idx++ )
462            (*ret)[ idx ] = (*v3f)[ idx ]; // convert Vec3 float to Vec3 double
463        return ret.get();
464    }
465    default:
466    {
467        OSG_WARN << "fltexp: Unsupported array type in conversion to Vec3dArray: " << arrayType << std::endl;
468        return NULL;
469    }
470    }
471}
472osg::ref_ptr< const osg::Vec4Array >
473VertexPaletteManager::asVec4Array( const osg::Array* in, const unsigned int n )
474{
475    if (!in)
476        return NULL;
477
478    osg::Array::Type arrayType = in->getType();
479    if (arrayType == osg::Array::Vec4ArrayType)
480    {
481        if (n <= in->getNumElements())
482        {
483            osg::ref_ptr< const osg::Vec4Array > v4f =
484                dynamic_cast< const osg::Vec4Array* >( in );
485            return v4f;
486        }
487    }
488
489    const unsigned int nToCopy = ( (n < in->getNumElements()) ? n : in->getNumElements() );
490    osg::ref_ptr< osg::Vec4Array > ret = new osg::Vec4Array( n );
491
492    switch( arrayType )
493    {
494    case osg::Array::Vec4ArrayType:
495    {
496        // No need to convert data, but must copy into correctly-sized array.
497        // If the size was correct, we wouldn't be here.
498        osg::ref_ptr< const osg::Vec4Array > v4f =
499            dynamic_cast< const osg::Vec4Array* >( in );
500        ret->assign( v4f->begin(), v4f->end() );;
501        ret->resize( n );
502        return ret.get();
503    }
504    case osg::Array::Vec4ubArrayType:
505    {
506        osg::ref_ptr< const osg::Vec4ubArray > v4ub =
507            dynamic_cast< const osg::Vec4ubArray* >( in );
508        unsigned int idx;
509        for (idx=0; idx<nToCopy; idx++ )
510        {
511            // convert Vec4 unsigned byte to Vec4 float
512            osg::Vec4& dest = (*ret)[ idx ];
513            osg::Vec4ub src = (*v4ub)[ idx ];
514            dest[0] = src[0] / 255.f;
515            dest[1] = src[1] / 255.f;
516            dest[2] = src[2] / 255.f;
517            dest[3] = src[3] / 255.f;
518        }
519        return ret.get();
520    }
521    default:
522    {
523        OSG_WARN << "fltexp: Unsupported array type in conversion to Vec4Array: " << arrayType << std::endl;
524        return NULL;
525    }
526    }
527}
528
529
530
531VertexPaletteManager::ArrayInfo::ArrayInfo()
532  : _byteStart( 0 ),
533    _idxSizeBytes( 0 ),
534    _idxCount( 0 )
535{
536}
537
538
539}
Note: See TracBrowser for help on using the browser.