void CodeWriter::writePushPop(VmCommandType cmd, string segment, int index) { if (cmd == VmCommandType::C_PUSH) writePush(segment, index); else writePop(segment, index); }
bool FltExportVisitor::complete( const osg::Node& node ) { // Always write final pop level writePop(); // Done writing records, close the record data temp file. _recordsStr.close(); // Write OpenFlight file front matter: header, vertex palette, etc. writeHeader( node.getName() ); writeColorPalette(); _materialPalette->write( _dos ); _texturePalette->write( _dos ); _lightSourcePalette->write( _dos ); _vertexPalette->write( _dos ); // Write Comment ancillary record and specify the _dos DataOutputStream. writeComment( node, &_dos ); // Copy record data temp file into final OpenFlight file. // Yee-uck. TBD need better stream copy routine. char buf; std::ifstream recIn; recIn.open( _recordsTempName.c_str(), std::ios::in | std::ios::binary ); while (!recIn.eof() ) { recIn.read( &buf, 1 ); if (recIn.good()) _dos << buf; } recIn.close(); return true; }
void FltExportVisitor::handleDrawElements( const osg::DrawElements* de, const osg::Geometry& geom, const osg::Geode& geode ) { GLenum mode = de->getMode(); int n( 0 ); bool useMesh( false ); switch( mode ) { case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_QUAD_STRIP: n = de->getNumIndices(); useMesh = true; break; case GL_POINTS: n = 1; break; case GL_LINES: n = 2; break; case GL_TRIANGLES: n = 3; break; case GL_QUADS: n = 4; break; case GL_LINE_STRIP: case GL_LINE_LOOP: case GL_POLYGON: default: n = de->getNumIndices(); break; } // Push and pop subfaces if polygon offset is on. SubfaceHelper subface( *this, getCurrentStateSet() ); if (useMesh) { std::vector< unsigned int > indices; int idx; for (idx=0; idx<n; idx++) indices.push_back( de->index( idx ) ); writeMeshPrimitive( indices, mode ); } else { unsigned int first( 0 ); while (first+n <= de->getNumIndices()) { // Need: // * Geode for record name (but also need to handle // multi Geometry objects and multi PrimitiveSet objects; // all Face records can't have the same name). // * Mode writeFace( geode, geom, mode ); writeMatrix( geode.getUserData() ); writeComment( geode ); writeMultitexture( geom ); writePush(); // Write vertex list records. std::vector<unsigned int> indices; int idx; for(idx=0; idx<n; idx++) indices.push_back( de->index( first+idx ) ); int numVerts = writeVertexList( indices, n ); first += n; writeUVList( numVerts, geom ); writePop(); } } }
void FltExportVisitor::handleDrawArrayLengths( const osg::DrawArrayLengths* dal, const osg::Geometry& geom, const osg::Geode& geode ) { GLint first = dal->getFirst(); GLenum mode = dal->getMode(); int n( 0 ); bool useMesh( false ); switch( mode ) { case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_QUAD_STRIP: useMesh = true; break; case GL_POINTS: n = 1; break; case GL_LINES: n = 2; break; case GL_TRIANGLES: n = 3; break; case GL_QUADS: n = 4; break; case GL_LINE_STRIP: case GL_LINE_LOOP: case GL_POLYGON: default: break; } // Push and pop subfaces if polygon offset is on. SubfaceHelper subface( *this, getCurrentStateSet() ); if (useMesh) { int idx( 0 ); for( osg::DrawArrayLengths::const_iterator itr=dal->begin(); itr!=dal->end(); itr++ ) { std::vector< unsigned int > indices; int jdx; for (jdx=0; jdx<(*itr); idx++, jdx++) indices.push_back( idx ); writeMeshPrimitive( indices, mode ); } } else { // Hm. You wouldn't usually use DrawArrayLengths for non-strip/fan prims... for( osg::DrawArrayLengths::const_iterator itr=dal->begin(); itr!=dal->end(); itr++ ) { while (first+n <= *itr) { writeFace( geode, geom, mode ); writeMatrix( geode.getUserData() ); writeComment( geode ); writeMultitexture( geom ); writePush(); // Write vertex list records. int numVerts; if (n == 0) { numVerts = writeVertexList( first, *itr ); first += *itr; } else { numVerts = writeVertexList( first, n ); first += n; } writeUVList( numVerts, geom ); writePop(); } first += *itr; } } }
void FltExportVisitor::handleDrawArrays( const osg::DrawArrays* da, const osg::Geometry& geom, const osg::Geode& geode ) { GLint first = da->getFirst(); GLsizei count = da->getCount(); GLenum mode = da->getMode(); int n( 0 ); bool useMesh( false ); switch( mode ) { case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_QUAD_STRIP: useMesh = true; break; case GL_POINTS: n = 1; break; case GL_LINES: n = 2; break; case GL_TRIANGLES: n = 3; break; case GL_QUADS: n = 4; break; case GL_LINE_STRIP: case GL_LINE_LOOP: case GL_POLYGON: default: n = count; break; } if (useMesh) { std::vector< unsigned int > indices; int jdx; for (jdx=0; jdx<count; jdx++) indices.push_back( first+jdx ); writeMeshPrimitive( indices, mode ); } else { const unsigned int max( first+count ); while ((unsigned int)( first+n ) <= max) { writeFace( geode, geom, mode ); writeMatrix( geode.getUserData() ); writeComment( geode ); writeMultitexture( geom ); writePush(); // Write vertex list records. int numVerts = writeVertexList( first, n ); first += n; writeUVList( numVerts, geom ); writePop(); } } }
void FltExportVisitor::writeLightPoint(const osgSim::LightPointNode *lpn) { enum Directionality { OMNIDIRECTIONAL = 0, UNIDIRECTIONAL = 1, BIDIRECTIONAL = 2 }; enum DisplayMode { RASTER = 0, CALLIG = 1, EITHER = 2 }; enum Modes { ENABLE = 0, DISABLE = 1 }; enum Flags { NO_BACK_COLOR = 0x80000000u >> 1, CALLIGRAPHIC = 0x80000000u >> 3, REFLECTIVE = 0x80000000u >> 4, PERSPECTIVE = 0x80000000u >> 8, FLASHING = 0x80000000u >> 9, ROTATING = 0x80000000u >> 10, ROTATE_CC = 0x80000000u >> 11, VISIBLE_DAY = 0x80000000u >> 15, VISIBLE_DUSK = 0x80000000u >> 16, VISIBLE_NIGHT = 0x80000000u >> 17 }; int32 flags(NO_BACK_COLOR); if (lpn->getNumLightPoints() == 0) return; // In OSG, each LightPoint within a LightPointNode can have different appearance // parameters, but in OpenFlight, a Light Point Record contains a list of homogeneous // vertices. To be correct, we'd have to look at all LightPoints in the LightPointNode // and spew out multiple FLT records for each group that shared common appearance // parameters. Instead, we cheat: We take the first LightPoint and use its appearance // parameters for all LightPoints in the LightPointNode. const osgSim::LightPoint &lp0 = lpn->getLightPoint(0); // No really good mapping between OSG and FLT light point animations. float32 animPeriod(0.f); float32 animEnabled(0.f); float32 animPhaseDelay(0.f); if (lp0._blinkSequence != NULL) { flags |= FLASHING; animPeriod = 4.f; animEnabled = 2.f; animPhaseDelay = lp0._blinkSequence->getPhaseShift(); } // Note that true bidirectional light points are currently unsupported (they are unavailable // in OSG, so we never write them out to FLT as BIDIRECTIONAL. int32 directionality(OMNIDIRECTIONAL); float32 horizLobe(360.f); float32 vertLobe(360.f); float32 lobeRoll(0.f); const osgSim::DirectionalSector *ds = dynamic_cast<osgSim::DirectionalSector*>(lp0._sector.get()); if (ds) { directionality = UNIDIRECTIONAL; horizLobe = osg::RadiansToDegrees(ds->getHorizLobeAngle()); vertLobe = osg::RadiansToDegrees(ds->getVertLobeAngle()); lobeRoll = osg::RadiansToDegrees(ds->getLobeRollAngle()); } { // Braces req'd to invoke idHelper destructor (and potentially // write LongID record) before Push Record. const uint16 length(156); IdHelper id(*this, lpn->getName()); _records->writeInt16((int16) LIGHT_POINT_OP); _records->writeInt16(length); _records->writeID(id); _records->writeInt16(0); // Surface material code _records->writeInt16(0); // Feature ID _records->writeUInt32(~0u); // OpenFlight erronously say -1, so will assume ~0u is OK. Back color for bidirectional _records->writeInt32(EITHER); // Display mode _records->writeFloat32(lp0._intensity); // Intensity _records->writeFloat32(0.f); // Back intensity TBD _records->writeFloat32(0.f); // min defocus _records->writeFloat32(0.f); // max defocus _records->writeInt32(DISABLE); // Fading mode _records->writeInt32(DISABLE); // Fog punch mode _records->writeInt32(DISABLE); // Directional mode _records->writeInt32(0); // Range mode _records->writeFloat32(lpn->getMinPixelSize()); // min pixel size _records->writeFloat32(lpn->getMaxPixelSize()); // max pixel size _records->writeFloat32(lp0._radius * 2.f); // Actual size _records->writeFloat32(1.f); // transparent falloff pixel size _records->writeFloat32(1.f); // Transparent falloff exponent _records->writeFloat32(1.f); // Transparent falloff scalar _records->writeFloat32(0.f); // Transparent falloff clamp _records->writeFloat32(1.f); // Fog scalar _records->writeFloat32(0.f); // Reserved _records->writeFloat32(0.f); // Size difference threshold _records->writeInt32(directionality); // Directionality _records->writeFloat32(horizLobe); // Horizontal lobe angle _records->writeFloat32(vertLobe); // Vertical lobe angle _records->writeFloat32(lobeRoll); // Lobe roll angle _records->writeFloat32(0.f); // Directional falloff exponent _records->writeFloat32(0.f); // Directional ambient intensity _records->writeFloat32(animPeriod); // Animation period in seconds _records->writeFloat32(animPhaseDelay); // Animation phase delay in seconds _records->writeFloat32(animEnabled); // Animation enabled period in seconds _records->writeFloat32(1.f); // Significance _records->writeInt32(0); // Calligraphic draw order _records->writeInt32(flags); // Flags _records->writeVec3f(osg::Vec3f(0.f, 0.f, 0.f)); // Axis of rotation } { osg::ref_ptr<osg::Vec3dArray> v = new osg::Vec3dArray(lpn->getNumLightPoints()); osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array(lpn->getNumLightPoints()); osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array(lpn->getNumLightPoints()); osg::Vec3f normal(0.f, 0.f, 1.f); unsigned int idx; for (idx = 0; idx < lpn->getNumLightPoints(); idx++) { const osgSim::LightPoint &lp = lpn->getLightPoint(idx); (*v)[idx] = lp._position; (*c)[idx] = lp._color; const osgSim::DirectionalSector *ds = dynamic_cast<osgSim::DirectionalSector*>(lp._sector.get()); if (ds) normal = ds->getDirection(); (*n)[idx] = normal; } _vertexPalette->add((const osg::Array*)NULL, v.get(), c.get(), n.get(), NULL, true, true, false); } writeMatrix(lpn->getUserData()); writeComment(*lpn); writePush(); writeVertexList(0, lpn->getNumLightPoints()); writePop(); }
// Billboards also go through this code. The Geode is passed // to writeFace and writeMesh. If those methods successfully cast // the Geode to a Billboard, then they set the template mode // bit accordingly. void FltExportVisitor::apply( osg::Geode& node ) { _firstNode = false; ScopedStatePushPop guard( this, node.getStateSet() ); unsigned int idx; for (idx=0; idx<node.getNumDrawables(); idx++) { osg::Geometry* geom = node.getDrawable( idx )->asGeometry(); if (!geom) { std::string warning( "fltexp: Non-Geometry Drawable encountered. Ignoring." ); osg::notify( osg::WARN ) << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); continue; } ScopedStatePushPop drawableGuard( this, geom->getStateSet() ); // Push and pop subfaces if polygon offset is on. SubfaceHelper subface( *this, getCurrentStateSet() ); if (atLeastOneFace( *geom )) { // If at least one record will be a Face record, then we // need to write to the vertex palette. _vertexPalette->add( *geom ); // Iterate over all PrimitiveSets and output Face records. unsigned int jdx; for (jdx=0; jdx < geom->getNumPrimitiveSets(); jdx++) { osg::PrimitiveSet* prim = geom->getPrimitiveSet( jdx ); if ( isMesh( prim->getMode() ) ) continue; if (prim->getType() == osg::PrimitiveSet::DrawArraysPrimitiveType) handleDrawArrays( dynamic_cast<osg::DrawArrays*>( prim ), *geom, node ); else if (prim->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) handleDrawArrayLengths( dynamic_cast<osg::DrawArrayLengths*>( prim ), *geom, node ); else if ( (prim->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) || (prim->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) || (prim->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) ) handleDrawElements( dynamic_cast<osg::DrawElements*>( prim ), *geom, node ); else { std::string warning( "fltexp: Unknown PrimitiveSet type." ); osg::notify( osg::WARN ) << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } } } if (atLeastOneMesh( *geom )) { // If at least one Mesh record, write out preamble mesh records // followed by a Mesh Primitive record per PrimitiveSet. writeMesh( node, *geom ); writeMatrix( node.getUserData() ); writeComment( node ); writeMultitexture( *geom ); writeLocalVertexPool( *geom ); writePush(); unsigned int jdx; for (jdx=0; jdx < geom->getNumPrimitiveSets(); jdx++) { osg::PrimitiveSet* prim = geom->getPrimitiveSet( jdx ); if ( !isMesh( prim->getMode() ) ) continue; if (prim->getType() == osg::PrimitiveSet::DrawArraysPrimitiveType) handleDrawArrays( dynamic_cast<osg::DrawArrays*>( prim ), *geom, node ); else if (prim->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) handleDrawArrayLengths( dynamic_cast<osg::DrawArrayLengths*>( prim ), *geom, node ); else if ( (prim->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) || (prim->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) || (prim->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) ) handleDrawElements( dynamic_cast<osg::DrawElements*>( prim ), *geom, node ); else { std::string warning( "fltexp: Unknown PrimitiveSet type." ); osg::notify( osg::WARN ) << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } } writePop(); } } // Would traverse here if this node could have children. // traverse( (osg::Node&)node ); }