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

Revision 13041, 34.7 kB (checked in by robert, 2 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 "FltExportVisitor.h"
18#include "DataOutputStream.h"
19#include "Opcodes.h"
20#include "MaterialPaletteManager.h"
21#include "TexturePaletteManager.h"
22#include "VertexPaletteManager.h"
23#include <osg/CullFace>
24#include <osg/BlendFunc>
25#include <osg/Geometry>
26#include <osg/Geode>
27#include <osg/Billboard>
28#include <osg/io_utils>
29#include <osg/Material>
30#include <osg/Texture2D>
31
32#include <sstream>
33
34
35namespace flt
36{
37
38
39// Bit flags for multitexturing
40static unsigned int LAYER_1( 0x80000000 >> 0 );
41#if 0
42// unused so if'deffing out
43static unsigned int LAYER_2( 0x80000000 >> 1 );
44static unsigned int LAYER_3( 0x80000000 >> 2 );
45static unsigned int LAYER_4( 0x80000000 >> 3 );
46static unsigned int LAYER_5( 0x80000000 >> 4 );
47static unsigned int LAYER_6( 0x80000000 >> 5 );
48static unsigned int LAYER_7( 0x80000000 >> 6 );
49#endif
50
51
52bool
53FltExportVisitor::isLit( const osg::Geometry& geom ) const
54{
55    const osg::StateSet* ss = getCurrentStateSet();
56    if ( ss->getMode( GL_LIGHTING ) & osg::StateAttribute::ON )
57        return true;
58    else
59        return false; //( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX );
60}
61
62bool
63FltExportVisitor::isTextured( int unit, const osg::Geometry& geom ) const
64{
65    const osg::StateSet* ss = getCurrentStateSet();
66    bool texOn( ss->getTextureMode( unit, GL_TEXTURE_2D ) & osg::StateAttribute::ON );
67    bool hasCoords( geom.getTexCoordArray( unit ) != NULL );
68
69    return( texOn && hasCoords );
70}
71
72bool
73FltExportVisitor::isMesh( const GLenum mode ) const
74{
75    return( (mode == GL_TRIANGLE_STRIP) ||
76        (mode == GL_TRIANGLE_FAN) ||
77        (mode == GL_QUAD_STRIP) );
78}
79
80bool
81FltExportVisitor::atLeastOneFace( const osg::Geometry& geom ) const
82{
83    // Return true if at least one PrimitiveSet mode will use a Face record.
84    unsigned int jdx;
85    for (jdx=0; jdx < geom.getNumPrimitiveSets(); jdx++)
86    {
87        const osg::PrimitiveSet* prim = geom.getPrimitiveSet( jdx );
88        if( !isMesh( prim->getMode() ) )
89            return true;
90    }
91    // All PrimitiveSet modes will use Mesh records.
92    return false;
93}
94bool
95FltExportVisitor::atLeastOneMesh( const osg::Geometry& geom ) const
96{
97    // Return true if at least one PrimitiveSet mode will use a Mesh record.
98    unsigned int jdx;
99    for (jdx=0; jdx < geom.getNumPrimitiveSets(); jdx++)
100    {
101        const osg::PrimitiveSet* prim = geom.getPrimitiveSet( jdx );
102        if( isMesh( prim->getMode() ) )
103            return true;
104    }
105    // All PrimitiveSet modes will use Face records.
106    return false;
107}
108
109void
110FltExportVisitor::writeFace( const osg::Geode& geode, const osg::Geometry& geom, GLenum mode )
111{
112    enum DrawMode
113    {
114        SOLID_BACKFACE = 0,
115        SOLID_NO_BACKFACE = 1,
116        WIREFRAME_CLOSED = 2,
117        WIREFRAME_NOT_CLOSED = 3,
118        SURROUND_ALTERNATE_COLOR = 4,
119        OMNIDIRECTIONAL_LIGHT = 8,
120        UNIDIRECTIONAL_LIGHT = 9,
121        BIDIRECTIONAL_LIGHT = 10
122    };
123    enum TemplateMode
124    {
125        FIXED_NO_ALPHA_BLENDING = 0,
126        FIXED_ALPHA_BLENDING = 1,
127        AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
128        POINT_ROTATE_WITH_ALPHA_BLENDING = 4
129    };
130
131    // const unsigned int TERRAIN_BIT      = 0x80000000u >> 0;
132    // const unsigned int NO_COLOR_BIT     = 0x80000000u >> 1;
133    // const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
134    const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
135    // const unsigned int FOOTPRINT_BIT    = 0x80000000u >> 4;    // Terrain culture cutout
136    const unsigned int HIDDEN_BIT       = 0x80000000u >> 5;
137    // const unsigned int ROOFLINE_BIT     = 0x80000000u >> 6;
138
139    uint32 flags( PACKED_COLOR_BIT );
140    if (geode.getNodeMask() == 0)
141        flags |= HIDDEN_BIT;
142
143    osg::StateSet const* ss = getCurrentStateSet();
144    enum LightMode
145    {
146        FACE_COLOR = 0,
147        VERTEX_COLOR = 1,
148        FACE_COLOR_LIGHTING = 2,
149        VERTEX_COLOR_LIGHTING = 3
150    };
151    int8 lightMode;
152    osg::Vec4 packedColorRaw( 1., 1., 1., 1. );
153    uint16 transparency( 0 );
154    if (geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
155    {
156        if( isLit( geom ) )
157            lightMode = VERTEX_COLOR_LIGHTING;
158        else
159            lightMode = VERTEX_COLOR;
160    }
161    else
162    {
163        const osg::Vec4Array* c = dynamic_cast<const osg::Vec4Array*>( geom.getColorArray() );
164        if (c && (c->size() > 0))
165        {
166            packedColorRaw = (*c)[0];
167            transparency = uint16((1. - packedColorRaw[3]) * (double)0xffff);
168        }
169
170        if ( isLit( geom ) )
171            lightMode = FACE_COLOR_LIGHTING;
172        else
173            lightMode = FACE_COLOR;
174    }
175    uint32 packedColor;
176    packedColor = (int)(packedColorRaw[3]*255) << 24 |
177        (int)(packedColorRaw[2]*255) << 16 | (int)(packedColorRaw[1]*255) << 8 |
178        (int)(packedColorRaw[0]*255);
179
180
181    int8 drawType = SOLID_NO_BACKFACE;
182
183    switch( mode )
184    {
185    case GL_POINTS:
186    {
187        std::string warning( "fltexp: GL_POINTS not supported in FLT export." );
188        OSG_WARN << warning << std::endl;
189        _fltOpt->getWriteResult().warn( warning );
190        return;
191        break;
192    }
193    case GL_TRIANGLE_STRIP:
194    case GL_TRIANGLE_FAN:
195    case GL_QUAD_STRIP:
196    {
197        std::string warning( "fltexp: Wrong mode in Face record." );
198        OSG_WARN << warning << std::endl;
199        _fltOpt->getWriteResult().warn( warning );
200        return;
201        break;
202    }
203    case GL_LINES:
204    case GL_LINE_STRIP:
205        drawType = WIREFRAME_NOT_CLOSED;
206        break;
207    case GL_LINE_LOOP:
208        drawType = WIREFRAME_CLOSED;
209        break;
210    case GL_TRIANGLES:
211    case GL_QUADS:
212    case GL_POLYGON:
213    {
214        // Default to no facet culling
215        drawType = SOLID_NO_BACKFACE;
216
217        // If facet-culling isn't *dis*abled, check whether the CullFace mode is BACK
218        if (ss->getMode(GL_CULL_FACE) & osg::StateAttribute::ON)
219        {
220            osg::CullFace const* cullFace = static_cast<osg::CullFace const*>(
221                ss->getAttribute(osg::StateAttribute::CULLFACE) );
222            if( cullFace->getMode() == osg::CullFace::BACK )
223                drawType = SOLID_BACKFACE;
224
225            // Note: OpenFlt can't handle FRONT or FRONT_AND_BACK settings, so ignore these(??)
226        }
227        break;
228    }
229    }
230
231    // Determine the material properties for the face
232    int16 materialIndex( -1 );
233    if (isLit( geom ))
234    {
235        osg::Material const* currMaterial = static_cast<osg::Material const*>(
236            ss->getAttribute(osg::StateAttribute::MATERIAL) );
237        materialIndex = _materialPalette->add(currMaterial);
238    }
239
240    // Get base texture
241    int16 textureIndex( -1 );
242    if (isTextured( 0, geom ))
243    {
244        const osg::Texture2D* texture = static_cast<const osg::Texture2D*>(
245            ss->getTextureAttribute( 0, osg::StateAttribute::TEXTURE )  );
246        if (texture != NULL)
247            textureIndex = _texturePalette->add( 0, texture );
248        else
249        {
250            std::string warning( "fltexp: Face is textured, but Texture2D StateAttribute is NULL." );
251            OSG_WARN << warning << std::endl;
252            _fltOpt->getWriteResult().warn( warning );
253        }
254    }
255
256    // Set the appropriate template mode based
257    // on blending or Billboarding.
258    TemplateMode templateMode( FIXED_NO_ALPHA_BLENDING );
259    const osg::Billboard* bb = dynamic_cast< const osg::Billboard* >( &geode );
260    if (bb != NULL)
261    {
262        if( bb->getMode() == osg::Billboard::AXIAL_ROT )
263            templateMode = AXIAL_ROTATE_WITH_ALPHA_BLENDING;
264        else
265            templateMode = POINT_ROTATE_WITH_ALPHA_BLENDING;
266    }
267    else if ( ss->getMode( GL_BLEND ) & osg::StateAttribute::ON )
268    {
269        const osg::BlendFunc* bf = static_cast<const osg::BlendFunc*>(
270            ss->getAttribute(osg::StateAttribute::BLENDFUNC) );
271        if( (bf->getSource() == osg::BlendFunc::SRC_ALPHA) &&
272            (bf->getDestination() == osg::BlendFunc::ONE_MINUS_SRC_ALPHA) )
273            templateMode = FIXED_ALPHA_BLENDING;
274    }
275
276
277    uint16 length( 80 );
278    IdHelper id( *this, geode.getName() );
279
280    _records->writeInt16( (int16) FACE_OP );
281    _records->writeUInt16( length );
282    _records->writeID( id );
283    _records->writeInt32( 0 ); // IR color code
284    _records->writeInt16( 0 ); // Relative priority
285    _records->writeInt8( drawType ); // Draw type
286    _records->writeInt8( 0 ); // Texture white
287    _records->writeInt16( -1 ); // Color name index
288    _records->writeInt16( -1 ); // Alternate color name index
289    _records->writeInt8( 0 ); // Reserved
290    _records->writeInt8( templateMode ); // Template (billboard)
291    _records->writeInt16( -1 ); // Detail texture pattern index
292    _records->writeInt16( textureIndex ); // Texture pattern index
293    _records->writeInt16( materialIndex ); // Material index
294    _records->writeInt16( 0 ); // Surface material code
295    _records->writeInt16( 0 ); // Feature ID
296    _records->writeInt32( 0 ); // IR material code
297    _records->writeUInt16( transparency ); // Transparency
298    _records->writeInt8( 0 ); // LOD generation control
299    _records->writeInt8( 0 ); // Line style index
300    _records->writeUInt32( flags ); // Flags
301    _records->writeInt8( lightMode ); // Light mode
302    _records->writeFill( 7 ); // Reserved
303    _records->writeUInt32( packedColor ); // Packed color, primary
304    _records->writeUInt32( 0x00ffffff ); // Packed color, alternate
305    _records->writeInt16( -1 ); // Texture mapping index
306    _records->writeInt16( 0 ); // Reserved
307    _records->writeInt32( -1 ); // Primary color index
308    _records->writeInt32( -1 ); // Alternate color index
309    // Next four bytes:
310    //   15.8: two 2-byte "reserved" fields
311    //   15.9: one 4-byte "reserved" field;
312    _records->writeInt16( 0 ); // Reserved
313    _records->writeInt16( -1 ); // Shader index
314}
315
316
317void
318FltExportVisitor::writeMesh( const osg::Geode& geode, const osg::Geometry& geom )
319{
320    enum DrawMode
321    {
322        SOLID_BACKFACE = 0,
323        SOLID_NO_BACKFACE = 1,
324        WIREFRAME_CLOSED = 2,
325        WIREFRAME_NOT_CLOSED = 3,
326        SURROUND_ALTERNATE_COLOR = 4,
327        OMNIDIRECTIONAL_LIGHT = 8,
328        UNIDIRECTIONAL_LIGHT = 9,
329        BIDIRECTIONAL_LIGHT = 10
330    };
331    enum TemplateMode
332    {
333        FIXED_NO_ALPHA_BLENDING = 0,
334        FIXED_ALPHA_BLENDING = 1,
335        AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
336        POINT_ROTATE_WITH_ALPHA_BLENDING = 4
337    };
338
339    // const unsigned int TERRAIN_BIT      = 0x80000000u >> 0;
340    //const unsigned int NO_COLOR_BIT     = 0x80000000u >> 1;
341    //const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
342    const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
343    //const unsigned int FOOTPRINT_BIT    = 0x80000000u >> 4;    // Terrain culture cutout
344    const unsigned int HIDDEN_BIT       = 0x80000000u >> 5;
345    //const unsigned int ROOFLINE_BIT     = 0x80000000u >> 6;
346    uint32 flags( PACKED_COLOR_BIT );
347    if (geode.getNodeMask() == 0)
348        flags |= HIDDEN_BIT;
349
350    enum LightMode
351    {
352        FACE_COLOR = 0,
353        VERTEX_COLOR = 1,
354        FACE_COLOR_LIGHTING = 2,
355        VERTEX_COLOR_LIGHTING = 3
356    };
357    int8 lightMode;
358    osg::Vec4 packedColorRaw( 1., 1., 1., 1. );
359    uint16 transparency( 0 );
360    if (geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
361    {
362        if (isLit( geom ))
363            lightMode = VERTEX_COLOR_LIGHTING;
364        else
365            lightMode = VERTEX_COLOR;
366    }
367    else
368    {
369        const osg::Vec4Array* c = dynamic_cast<const osg::Vec4Array*>( geom.getColorArray() );
370        if (c && (c->size() > 0))
371        {
372            packedColorRaw = (*c)[0];
373            transparency = uint16((1. - packedColorRaw[3]) * (double)0xffff);
374        }
375
376        if (isLit( geom ))
377            lightMode = FACE_COLOR_LIGHTING;
378        else
379            lightMode = FACE_COLOR;
380    }
381    uint32 packedColor;
382    packedColor = (int)(packedColorRaw[3]*255) << 24 |
383        (int)(packedColorRaw[2]*255) << 16 | (int)(packedColorRaw[1]*255) << 8 |
384        (int)(packedColorRaw[0]*255);
385
386
387    int8 drawType;
388    osg::StateSet const* ss = getCurrentStateSet();
389
390    {
391        // Default to no facet culling
392        drawType = SOLID_NO_BACKFACE;
393
394        // If facet-culling isn't *dis*abled, check whether the CullFace mode is BACK
395        if (ss->getMode(GL_CULL_FACE) & osg::StateAttribute::ON)
396        {
397            osg::CullFace const* cullFace = static_cast<osg::CullFace const*>(
398                ss->getAttribute(osg::StateAttribute::CULLFACE) );
399            if( cullFace->getMode() == osg::CullFace::BACK )
400                drawType = SOLID_BACKFACE;
401
402            // Note: OpenFlt can't handle FRONT or FRONT_AND_BACK settings, so ignore these(??)
403        }
404    }
405
406    // Determine the material properties for the face
407    int16 materialIndex( -1 );
408    if (isLit( geom ))
409    {
410        osg::Material const* currMaterial = static_cast<osg::Material const*>(
411            ss->getAttribute(osg::StateAttribute::MATERIAL) );
412        materialIndex = _materialPalette->add(currMaterial);
413    }
414
415    // Get base texture
416    int16 textureIndex( -1 );
417    if (isTextured( 0, geom ))
418    {
419        const osg::Texture2D* texture = static_cast<const osg::Texture2D*>(
420            ss->getTextureAttribute( 0, osg::StateAttribute::TEXTURE )  );
421        if (texture != NULL)
422            textureIndex = _texturePalette->add( 0, texture );
423        else
424        {
425            std::string warning( "fltexp: Mesh is textured, but Texture2D StateAttribute is NULL." );
426            OSG_WARN << warning << std::endl;
427            _fltOpt->getWriteResult().warn( warning );
428        }
429    }
430
431    // Set the appropriate template mode based
432    // on blending or Billboarding.
433    TemplateMode templateMode( FIXED_NO_ALPHA_BLENDING );
434    const osg::Billboard* bb = dynamic_cast< const osg::Billboard* >( &geode );
435    if (bb != NULL)
436    {
437        if( bb->getMode() == osg::Billboard::AXIAL_ROT )
438            templateMode = AXIAL_ROTATE_WITH_ALPHA_BLENDING;
439        else
440            templateMode = POINT_ROTATE_WITH_ALPHA_BLENDING;
441    }
442    else if ( ss->getMode( GL_BLEND ) & osg::StateAttribute::ON )
443    {
444        const osg::BlendFunc* bf = static_cast<const osg::BlendFunc*>(
445            ss->getAttribute(osg::StateAttribute::BLENDFUNC) );
446        if( (bf->getSource() == osg::BlendFunc::SRC_ALPHA) &&
447            (bf->getDestination() == osg::BlendFunc::ONE_MINUS_SRC_ALPHA) )
448            templateMode = FIXED_ALPHA_BLENDING;
449    }
450
451
452    uint16 length( 84 );
453    IdHelper id( *this, geode.getName() );
454
455    _records->writeInt16( (int16) MESH_OP );
456    _records->writeUInt16( length );
457    _records->writeID( id );
458    _records->writeInt32( 0 ); // Reserved
459    _records->writeInt32( 0 ); // IR color code
460    _records->writeInt16( 0 ); // Relative priority
461    _records->writeInt8( drawType ); // Draw type
462    _records->writeInt8( 0 ); // Texture white
463    _records->writeInt16( -1 ); // Color name index
464    _records->writeInt16( -1 ); // Alternate color name index
465    _records->writeInt8( 0 ); // Reserved
466    _records->writeInt8( templateMode ); // Template (billboard)
467    _records->writeInt16( -1 ); // Detail texture pattern index
468    _records->writeInt16( textureIndex ); // Texture pattern index
469    _records->writeInt16( materialIndex ); // Material index
470    _records->writeInt16( 0 ); // Surface material code
471    _records->writeInt16( 0 ); // Feature ID
472    _records->writeInt32( 0 ); // IR material code
473    _records->writeUInt16( transparency ); // Transparency
474    _records->writeInt8( 0 ); // LOD generation control
475    _records->writeInt8( 0 ); // Line style index
476    _records->writeUInt32( flags ); // Flags
477    _records->writeInt8( lightMode ); // Light mode
478    _records->writeFill( 7 ); // Reserved
479    _records->writeUInt32( packedColor ); // Packed color, primary
480    _records->writeUInt32( 0x00ffffff ); // Packed color, alternate
481    _records->writeInt16( -1 ); // Texture mapping index
482    _records->writeInt16( 0 ); // Reserved
483    _records->writeInt32( -1 ); // Primary color index
484    _records->writeInt32( -1 ); // Alternate color index
485    // Next four bytes:
486    //   15.8: two 2-byte "reserved" fields
487    //   15.9: one 4-byte "reserved" field
488    _records->writeInt16( 0 ); // Reserved
489    _records->writeInt16( -1 ); // Shader index
490}
491
492int
493FltExportVisitor::writeVertexList( int first, unsigned int count )
494{
495    _records->writeInt16( (int16) VERTEX_LIST_OP );
496    _records->writeUInt16( 4 + (count*4) );
497
498    unsigned int idx;
499    for( idx=0; idx<count; idx++)
500        // I'm imagining that 'first' will be a 0-based index into the
501        //   'current' set of vertices held by the vertex palette manager.
502        _records->writeInt32( _vertexPalette->byteOffset( first+idx ) );
503
504    return count;
505}
506
507int
508FltExportVisitor::writeVertexList( const std::vector<unsigned int>& indices, unsigned int count )
509{
510    _records->writeInt16( (int16) VERTEX_LIST_OP );
511    _records->writeUInt16( 4 + (count*4) );
512
513    unsigned int idx;
514    for( idx=0; idx<count; idx++)
515        // I'm imagining that 'first' will be a 0-based index into the
516        //   'current' set of vertices held by the vertex palette manager.
517        _records->writeInt32( _vertexPalette->byteOffset( indices[ idx ] ) );
518
519    return count;
520}
521
522void
523FltExportVisitor::writeMeshPrimitive( const std::vector<unsigned int>& indices, GLenum mode )
524{
525    int16 primType;
526    switch( mode )
527    {
528    case GL_TRIANGLE_STRIP:
529        primType = 1;
530        break;
531    case GL_TRIANGLE_FAN:
532        primType = 2;
533        break;
534    case GL_QUAD_STRIP:
535        primType = 3;
536        break;
537    default:
538        // Warning should already be recorded. Do nothing.
539        return;
540        break;
541    }
542
543    uint16 length( 12 + (4 * indices.size()) );
544
545    _records->writeInt16( (int16) MESH_PRIMITIVE_OP );
546    _records->writeUInt16( length );
547    _records->writeInt16( primType ); // primitive type
548    _records->writeInt16( 4 ); // index size, 4 bytes
549    _records->writeInt32( indices.size() ); // vertex count
550
551    std::vector<unsigned int>::const_iterator it = indices.begin();
552    while (it != indices.end())
553    {
554        _records->writeUInt32( (*it) );
555        it++;
556    }
557}
558
559void
560FltExportVisitor::writeLocalVertexPool( const osg::Geometry& geom )
561{
562    // Attribute Mask
563    static const unsigned int HAS_POSITION      = 0x80000000u >> 0;
564    // static const unsigned int HAS_COLOR_INDEX   = 0x80000000u >> 1;
565    static const unsigned int HAS_RGBA_COLOR    = 0x80000000u >> 2;
566    static const unsigned int HAS_NORMAL        = 0x80000000u >> 3;
567    static const unsigned int HAS_BASE_UV       = 0x80000000u >> 4;
568    static const unsigned int HAS_UV_LAYER1     = 0x80000000u >> 5;
569    static const unsigned int HAS_UV_LAYER2     = 0x80000000u >> 6;
570    static const unsigned int HAS_UV_LAYER3     = 0x80000000u >> 7;
571    static const unsigned int HAS_UV_LAYER4     = 0x80000000u >> 8;
572    static const unsigned int HAS_UV_LAYER5     = 0x80000000u >> 9;
573    static const unsigned int HAS_UV_LAYER6     = 0x80000000u >> 10;
574    static const unsigned int HAS_UV_LAYER7     = 0x80000000u >> 11;
575
576    const osg::Array* v = geom.getVertexArray();
577    uint32 numVerts( v->getNumElements() );
578    osg::ref_ptr< const osg::Vec3dArray > v3 = VertexPaletteManager::asVec3dArray( v, numVerts );
579    if (!v3)
580    {
581        std::string warning( "fltexp: writeLocalVertexPool: VertexArray is not Vec3Array." );
582        OSG_WARN << warning << std::endl;
583        _fltOpt->getWriteResult().warn( warning );
584        return;
585    }
586
587    // Compute attribute bits and vertex size.
588    const osg::Array* c = geom.getColorArray();
589    const osg::Array* n = geom.getNormalArray();
590    const osg::Array* t = geom.getTexCoordArray( 0 );
591
592    osg::ref_ptr< const osg::Vec4Array > c4 = VertexPaletteManager::asVec4Array( c, numVerts );
593    osg::ref_ptr< const osg::Vec3Array > n3 = VertexPaletteManager::asVec3Array( n, numVerts );
594    osg::ref_ptr< const osg::Vec2Array > t2 = VertexPaletteManager::asVec2Array( t, numVerts );
595    if (c && !c4)
596        return;
597    if (n && !n3)
598        return;
599    if (t && !t2)
600        return;
601
602    std::vector< osg::ref_ptr< const osg::Vec2Array > > mtc;
603    mtc.resize( 8 );
604    int unit=1;
605    for( ;unit<8; unit++)
606        mtc[ unit ] = VertexPaletteManager::asVec2Array( geom.getTexCoordArray( unit ), numVerts );
607
608    uint32 attr( HAS_POSITION );
609    unsigned int vertSize( sizeof( float64 ) * 3 );
610
611    if ( ( c4 != NULL ) && ( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX) )
612    {
613        attr |= HAS_RGBA_COLOR;
614        vertSize += sizeof( unsigned int );
615    }
616    if ( ( n3 != NULL ) && ( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) )
617    {
618        attr |= HAS_NORMAL;
619        vertSize += ( sizeof( float32 ) * 3 );
620    }
621    if ( t2 != NULL )
622    {
623        attr |= HAS_BASE_UV;
624        vertSize += ( sizeof( float32 ) * 2 );
625    }
626    // Add multitex
627    if (isTextured( 1, geom ))
628    {
629        attr |= HAS_UV_LAYER1;
630        vertSize += ( sizeof( float32 ) * 2 );
631    }
632    if (isTextured( 2, geom ))
633    {
634        attr |= HAS_UV_LAYER2;
635        vertSize += ( sizeof( float32 ) * 2 );
636    }
637    if (isTextured( 3, geom ))
638    {
639        attr |= HAS_UV_LAYER3;
640        vertSize += ( sizeof( float32 ) * 2 );
641    }
642    if (isTextured( 4, geom ))
643    {
644        attr |= HAS_UV_LAYER4;
645        vertSize += ( sizeof( float32 ) * 2 );
646    }
647    if (isTextured( 5, geom ))
648    {
649        attr |= HAS_UV_LAYER5;
650        vertSize += ( sizeof( float32 ) * 2 );
651    }
652    if (isTextured( 6, geom ))
653    {
654        attr |= HAS_UV_LAYER6;
655        vertSize += ( sizeof( float32 ) * 2 );
656    }
657    if (isTextured( 7, geom ))
658    {
659        attr |= HAS_UV_LAYER7;
660        vertSize += ( sizeof( float32 ) * 2 );
661    }
662
663    unsigned int maxVerts = (0xffff - 12) / vertSize;
664    unsigned int thisVertCount = (maxVerts > numVerts) ? numVerts : maxVerts;
665    unsigned int currentIndexLimit = maxVerts;
666    uint16 length( 12 + (vertSize * thisVertCount) );
667
668
669    _records->writeInt16( (int16) LOCAL_VERTEX_POOL_OP );
670    _records->writeUInt16( length );
671    _records->writeUInt32( numVerts ); // number of vertices
672    _records->writeUInt32( attr ); // attribute bits
673
674    unsigned int idx;
675    for( idx=0; idx<numVerts; idx++ )
676    {
677        _records->writeVec3d( (*v3)[ idx ] );
678
679        if (attr & HAS_RGBA_COLOR)
680        {
681            osg::Vec4 color = (*c4)[ idx ];
682            unsigned int packedColor = (int)(color[3]*255) << 24 |
683                (int)(color[2]*255) << 16 | (int)(color[1]*255) << 8 |
684                (int)(color[0]*255);
685            _records->writeUInt32( packedColor );
686        }
687
688        if (attr & HAS_NORMAL)
689            _records->writeVec3f( (*n3)[ idx ] );
690
691        if (attr & HAS_BASE_UV)
692            _records->writeVec2f( (*t2)[ idx ] );
693
694        if (attr & HAS_UV_LAYER1)
695            _records->writeVec2f( (*mtc[1])[ idx ] );
696        if (attr & HAS_UV_LAYER2)
697            _records->writeVec2f( (*mtc[2])[ idx ] );
698        if (attr & HAS_UV_LAYER3)
699            _records->writeVec2f( (*mtc[3])[ idx ] );
700        if (attr & HAS_UV_LAYER4)
701            _records->writeVec2f( (*mtc[4])[ idx ] );
702        if (attr & HAS_UV_LAYER5)
703            _records->writeVec2f( (*mtc[5])[ idx ] );
704        if (attr & HAS_UV_LAYER6)
705            _records->writeVec2f( (*mtc[6])[ idx ] );
706        if (attr & HAS_UV_LAYER7)
707            _records->writeVec2f( (*mtc[7])[ idx ] );
708
709
710        // Handle continuation record if necessary.
711        if ( (idx+1 == currentIndexLimit) && (idx+1 < numVerts) )
712        {
713            currentIndexLimit += maxVerts;
714            unsigned int remaining( numVerts - (idx+1) );
715            thisVertCount = (maxVerts > remaining) ? remaining : maxVerts;
716            writeContinuationRecord( (vertSize * thisVertCount) );
717        }
718    }
719}
720
721void
722FltExportVisitor::writeMultitexture( const osg::Geometry& geom )
723{
724    unsigned int numLayers( 0 );
725    uint32 flags( 0 );
726    unsigned int idx;
727    for( idx=1; idx<8; idx++)
728    {
729        if( isTextured( idx, geom ) )
730        {
731            flags |= LAYER_1 >> (idx-1);
732            numLayers++;
733        }
734    }
735    if( numLayers == 0 )
736        return;
737
738    uint16 length( 8 + (8*numLayers) );
739
740    _records->writeInt16( (int16) MULTITEXTURE_OP );
741    _records->writeUInt16( length );
742    _records->writeInt32( flags );
743
744    const osg::StateSet* ss = getCurrentStateSet();
745    for( idx=1; idx<8; idx++)
746    {
747        if( isTextured( idx, geom ) )
748        {
749            int16 textureIndex( -1 );
750            const osg::Texture2D* texture = static_cast<const osg::Texture2D*>(
751                ss->getTextureAttribute( idx, osg::StateAttribute::TEXTURE )  );
752            if (texture != NULL)
753                textureIndex = _texturePalette->add( idx, texture );
754            else
755            {
756                std::ostringstream warning;
757                warning << "fltexp: No Texture2D for unit " << idx;
758                OSG_WARN << warning.str() << std::endl;
759                _fltOpt->getWriteResult().warn( warning.str() );
760            }
761
762            // texture index (this value is an unsigned int, but has a -1 default per oflt spec: ugh)
763            _records->writeUInt16( static_cast< uint16 >( textureIndex ) );
764            _records->writeUInt16( 0 ); // TBD effect
765             // mapping index (this value is an unsigned int, but has a -1 default per oflt spec: ugh)
766            _records->writeUInt16( static_cast< uint16 >( -1 ) );
767            _records->writeUInt16( 0 ); // data
768        }
769    }
770}
771
772void
773FltExportVisitor::writeUVList( int numVerts, const osg::Geometry& geom, const std::vector<unsigned int>& indices )
774{
775    unsigned int numLayers( 0 );
776    uint32 flags( 0 );
777    unsigned int idx;
778    for( idx=1; idx<8; idx++)
779    {
780        if( isTextured( idx, geom ) )
781        {
782            flags |= LAYER_1 >> (idx-1);
783            numLayers++;
784        }
785    }
786    if( numLayers == 0 )
787        return;
788
789    uint16 length( 8 + (8*numLayers*numVerts) );
790
791    _records->writeInt16( (int16) UV_LIST_OP );
792    _records->writeUInt16( length );
793    _records->writeInt32( flags );
794
795    osg::Vec2 defaultCoord( 0., 0. );
796    // const osg::StateSet* ss = getCurrentStateSet();
797    for( int vertexIdx=0; vertexIdx<numVerts; vertexIdx++)
798    {
799        for( idx=1; idx<8; idx++)
800        {
801            if( isTextured( idx, geom ) )
802            {
803                osg::Array* t = const_cast<osg::Array*>( geom.getTexCoordArray( idx ) );
804                osg::ref_ptr<osg::Vec2Array> t2 = dynamic_cast<osg::Vec2Array*>( t );
805                if (!t2.valid())
806                {
807                    std::ostringstream warning;
808                    warning << "fltexp: No Texture2D for unit " << idx;
809                    OSG_WARN << warning.str() << std::endl;
810                    _fltOpt->getWriteResult().warn( warning.str() );
811                    t2 = new osg::Vec2Array;
812                }
813
814                const int size = t2->getNumElements();
815                int vIdx = indices[ vertexIdx ];
816                osg::Vec2& tc( defaultCoord );
817                if (vIdx < size)
818                    tc = ( *t2 )[ vIdx ];
819                _records->writeFloat32( tc[ 0 ] );
820                _records->writeFloat32( tc[ 1 ] );
821            }
822        }
823    }
824}
825
826
827void
828FltExportVisitor::writeUVList( int numVerts, const osg::Geometry& geom, unsigned int first )
829{
830    unsigned int numLayers( 0 );
831    uint32 flags( 0 );
832    unsigned int idx;
833    for( idx=1; idx<8; idx++)
834    {
835        if( isTextured( idx, geom ) )
836        {
837            flags |= LAYER_1 >> (idx-1);
838            numLayers++;
839        }
840    }
841    if( numLayers == 0 )
842        return;
843
844    uint16 length( 8 + (8*numLayers*numVerts) );
845
846    _records->writeInt16( (int16) UV_LIST_OP );
847    _records->writeUInt16( length );
848    _records->writeInt32( flags );
849
850    osg::Vec2 defaultCoord( 0., 0. );
851    for( int vertexIdx=0; vertexIdx<numVerts; vertexIdx++)
852    {
853        for( idx=1; idx<8; idx++)
854        {
855            if( isTextured( idx, geom ) )
856            {
857                osg::Array* t = const_cast<osg::Array*>( geom.getTexCoordArray( idx ) );
858                osg::ref_ptr<osg::Vec2Array> t2 = dynamic_cast<osg::Vec2Array*>( t );
859                if (!t2.valid())
860                {
861                    std::ostringstream warning;
862                    warning << "fltexp: No Texture2D for unit " << idx;
863                    osg::notify( osg::WARN ) << warning.str() << std::endl;
864                    _fltOpt->getWriteResult().warn( warning.str() );
865                    t2 = new osg::Vec2Array;
866                }
867                else if (t2->getNumElements() < first + numVerts)
868                {
869                    std::ostringstream warning;
870                    warning << "fltexp: Invalid number of texture coordinates for unit " << idx;
871                    OSG_WARN << warning.str() << std::endl;
872                    _fltOpt->getWriteResult().warn( warning.str() );
873                }
874
875                const int size = t2->getNumElements();
876                int vIdx = first + vertexIdx;
877                osg::Vec2& tc( defaultCoord );
878                if (vIdx < size)
879                    tc = (*t2)[ vIdx ];
880                _records->writeFloat32( tc[0] );
881                _records->writeFloat32( tc[1] );
882            }
883        }
884    }
885}
886
887
888
889void
890FltExportVisitor::handleDrawArrays( const osg::DrawArrays* da, const osg::Geometry& geom, const osg::Geode& geode )
891{
892    GLint first = da->getFirst();
893    GLsizei count = da->getCount();
894    GLenum mode = da->getMode();
895
896    int n( 0 );
897    bool useMesh( false );
898    switch( mode )
899    {
900    case GL_TRIANGLE_STRIP:
901    case GL_TRIANGLE_FAN:
902    case GL_QUAD_STRIP:
903        useMesh = true;
904        break;
905    case GL_POINTS:
906        n = 1;
907        break;
908    case GL_LINES:
909        n = 2;
910        break;
911    case GL_TRIANGLES:
912        n = 3;
913        break;
914    case GL_QUADS:
915        n = 4;
916        break;
917    case GL_LINE_STRIP:
918    case GL_LINE_LOOP:
919    case GL_POLYGON:
920    default:
921        n = count;
922        break;
923    }
924
925    if (useMesh)
926    {
927        std::vector< unsigned int > indices;
928        int jdx;
929        for (jdx=0; jdx<count; jdx++)
930            indices.push_back( first+jdx );
931        writeMeshPrimitive( indices, mode );
932    }
933    else
934    {
935        const unsigned int max( first+count );
936        while ((unsigned int)( first+n ) <= max)
937        {
938            writeFace( geode, geom, mode );
939
940            writeMatrix( geode.getUserData() );
941            writeComment( geode );
942            writeMultitexture( geom );
943            writePush();
944
945            // Write vertex list records.
946            int numVerts = writeVertexList( first, n );
947            first += n;
948
949            writeUVList( numVerts, geom );
950
951            writePop();
952        }
953    }
954}
955
956void
957FltExportVisitor::handleDrawArrayLengths( const osg::DrawArrayLengths* dal, const osg::Geometry& geom, const osg::Geode& geode )
958{
959    GLint first = dal->getFirst();
960    GLenum mode = dal->getMode();
961
962    int n( 0 );
963    bool useMesh( false );
964    switch( mode )
965    {
966    case GL_TRIANGLE_STRIP:
967    case GL_TRIANGLE_FAN:
968    case GL_QUAD_STRIP:
969        useMesh = true;
970        break;
971    case GL_POINTS:
972        n = 1;
973        break;
974    case GL_LINES:
975        n = 2;
976        break;
977    case GL_TRIANGLES:
978        n = 3;
979        break;
980    case GL_QUADS:
981        n = 4;
982        break;
983    case GL_LINE_STRIP:
984    case GL_LINE_LOOP:
985    case GL_POLYGON:
986    default:
987        break;
988    }
989
990    // Push and pop subfaces if polygon offset is on.
991    SubfaceHelper subface( *this, getCurrentStateSet() );
992
993    if (useMesh)
994    {
995        int idx( 0 );
996        for( osg::DrawArrayLengths::const_iterator itr=dal->begin();
997             itr!=dal->end(); itr++ )
998        {
999            std::vector< unsigned int > indices;
1000            int jdx;
1001            for (jdx=0; jdx<(*itr); idx++, jdx++)
1002                indices.push_back( idx );
1003            writeMeshPrimitive( indices, mode );
1004        }
1005    }
1006    else
1007    {
1008        // Hm. You wouldn't usually use DrawArrayLengths for non-strip/fan prims...
1009        for( osg::DrawArrayLengths::const_iterator itr=dal->begin();
1010             itr!=dal->end(); itr++ )
1011        {
1012            while (first+n <= *itr)
1013            {
1014                writeFace( geode, geom, mode );
1015
1016                writeMatrix( geode.getUserData() );
1017                writeComment( geode );
1018                writeMultitexture( geom );
1019                writePush();
1020
1021                // Write vertex list records.
1022                int numVerts;
1023                if (n == 0)
1024                {
1025                    numVerts = writeVertexList( first, *itr );
1026                    first += *itr;
1027                }
1028                else
1029                {
1030                    numVerts = writeVertexList( first, n );
1031                    first += n;
1032                }
1033
1034                writeUVList( numVerts, geom );
1035
1036                writePop();
1037            }
1038
1039            first += *itr;
1040        }
1041    }
1042}
1043
1044void
1045FltExportVisitor::handleDrawElements( const osg::DrawElements* de, const osg::Geometry& geom, const osg::Geode& geode )
1046{
1047    GLenum mode = de->getMode();
1048
1049    int n( 0 );
1050    bool useMesh( false );
1051    switch( mode )
1052    {
1053    case GL_TRIANGLE_STRIP:
1054    case GL_TRIANGLE_FAN:
1055    case GL_QUAD_STRIP:
1056        n = de->getNumIndices();
1057        useMesh = true;
1058        break;
1059    case GL_POINTS:
1060        n = 1;
1061        break;
1062    case GL_LINES:
1063        n = 2;
1064        break;
1065    case GL_TRIANGLES:
1066        n = 3;
1067        break;
1068    case GL_QUADS:
1069        n = 4;
1070        break;
1071    case GL_LINE_STRIP:
1072    case GL_LINE_LOOP:
1073    case GL_POLYGON:
1074    default:
1075        n = de->getNumIndices();
1076        break;
1077    }
1078
1079    // Push and pop subfaces if polygon offset is on.
1080    SubfaceHelper subface( *this, getCurrentStateSet() );
1081
1082    if (useMesh)
1083    {
1084        std::vector< unsigned int > indices;
1085        int idx;
1086        for (idx=0; idx<n; idx++)
1087            indices.push_back( de->index( idx ) );
1088        writeMeshPrimitive( indices, mode );
1089    }
1090    else
1091    {
1092        unsigned int first( 0 );
1093        while (first+n <= de->getNumIndices())
1094        {
1095            // Need:
1096            // * Geode for record name (but also need to handle
1097            //   multi Geometry objects and multi PrimitiveSet objects;
1098            //   all Face records can't have the same name).
1099            // * Mode
1100            writeFace( geode, geom, mode );
1101
1102            writeMatrix( geode.getUserData() );
1103            writeComment( geode );
1104            writeMultitexture( geom );
1105            writePush();
1106
1107            // Write vertex list records.
1108            std::vector<unsigned int> indices;
1109            int idx;
1110            for(idx=0; idx<n; idx++)
1111                indices.push_back( de->index( first+idx ) );
1112            int numVerts = writeVertexList( indices, n );
1113            first += n;
1114
1115            writeUVList( numVerts, geom, indices );
1116
1117            writePop();
1118        }
1119    }
1120}
1121
1122
1123}
Note: See TracBrowser for help on using the browser.