~ubuntu-branches/ubuntu/trusty/openscenegraph/trusty

« back to all changes in this revision

Viewing changes to OpenSceneGraph/src/osgPlugins/OpenFlight/expGeometryRecords.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-07-29 04:34:38 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 lenny)
  • Revision ID: james.westby@ubuntu.com-20080729043438-no1h9h0dpsrlzp1y
* Non-maintainer upload.
* No longer try to detect (using /proc/cpuinfo when available) how many
  CPUs are available, fixing the FTBFS (due to -j0) on various platforms
  (Closes: #477353). The right way to do it is to support parallel=n in
  DEB_BUILD_OPTIONS (see Debian Policy §4.9.1), and adequate support has
  been implemented.
* Add patch to fix FTBFS due to the build system now refusing to handle
  whitespaces (Policy CMP0004 say the logs), thanks to Andreas Putzo who
  provided it (Closes: #482239):
   - debian/patches/fix-cmp0004-build-failure.dpatch
* Remove myself from Uploaders, as requested a while ago, done by Luk in
  his 2.2.0-2.1 NMU, which was never acknowledged.

Show diffs side-by-side

added added

removed removed

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