From adcb6665d45bfb4f1bc0979a8c0477ccbc391555 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 2 Mar 2004 15:37:41 +0000 Subject: [PATCH] From Paul Martz: "These two files fix the alignment bug in the flt plugin header parsing, which I posted about on Saturday. They go in the flt plugin directory. The fix is to memcpy the data read from the flt file into individual fields in our Header struct, then replace the raw (packed) data block with our header struct. This avoids the alignment problem entirely, and all fields now contain valid data." --- src/osgPlugins/flt/HeaderRecord.cpp | 104 +++++++++++++++++++++++++++- src/osgPlugins/flt/HeaderRecord.h | 15 ++-- 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/src/osgPlugins/flt/HeaderRecord.cpp b/src/osgPlugins/flt/HeaderRecord.cpp index c23dfbf3d..e71bfeed6 100644 --- a/src/osgPlugins/flt/HeaderRecord.cpp +++ b/src/osgPlugins/flt/HeaderRecord.cpp @@ -87,8 +87,100 @@ HeaderRecord::~HeaderRecord() void HeaderRecord::endian() { - SHeader *pHeader = (SHeader*)getData(); + // OpenFlight spec dictates values that arepacked and not do not necessarily + // adhere to alignment rules. Copy values out of the OpenFlight packed header + // and into the SHeader struct and let the compiler worry about alignment + // issues within the struct. + SHeader *pHeader = (SHeader*) malloc( sizeof(SHeader) ); + char* src = (char*)getData(); + + // Numeric constant data sizes taken from OpenFlight spec + memcpy( &(pHeader->RecHeader), src, 4 ); src += 4; + memcpy( &(pHeader->szIdent), src, 8 ); src += 8; + memcpy( &(pHeader->diFormatRevLev), src, 4 ); src += 4; + memcpy( &(pHeader->diDatabaseRevLev), src, 4 ); src += 4; + memcpy( &(pHeader->szDaTimLastRev), src, 32 ); src += 32; + memcpy( &(pHeader->iNextGroup), src, 2 ); src += 2; + memcpy( &(pHeader->iNextLOD), src, 2 ); src += 2; + memcpy( &(pHeader->iNextObject), src, 2 ); src += 2; + memcpy( &(pHeader->iNextPolygon), src, 2 ); src += 2; + memcpy( &(pHeader->iMultDivUnit), src, 2 ); src += 2; + memcpy( &(pHeader->swVertexCoordUnit), src, 1 ); src += 1; + memcpy( &(pHeader->swTexWhite), src, 1 ); src += 1; + memcpy( &(pHeader->dwFlags), src, 4 ); src += 4; + src += 4*6; // Reserved + memcpy( &(pHeader->diProjection), src, 4 ); src += 4; + src += 4*7; // Reserved + memcpy( &(pHeader->iNextDegOfFreedom), src, 2 ); src += 2; + memcpy( &(pHeader->iVertexStorage), src, 2 ); src += 2; + memcpy( &(pHeader->diDatabaseSource), src, 4 ); src += 4; + memcpy( &(pHeader->dfSWDatabaseCoordX), src, 8 ); src += 8; + memcpy( &(pHeader->dfSWDatabaseCoordY), src, 8 ); src += 8; + memcpy( &(pHeader->dfDatabaseOffsetX), src, 8 ); src += 8; + memcpy( &(pHeader->dfDatabaseOffsetY), src, 8 ); src += 8; + memcpy( &(pHeader->iNextSound), src, 2 ); src += 2; + memcpy( &(pHeader->iNextPath), src, 2 ); src += 2; + src += 4*2; // Reserved + memcpy( &(pHeader->iNextClippingRegion), src, 2 ); src += 2; + memcpy( &(pHeader->iNextText), src, 2 ); src += 2; + memcpy( &(pHeader->iNextBSP), src, 2 ); src += 2; + memcpy( &(pHeader->iNextSwitch), src, 2 ); src += 2; + src += 4; // reserved + memcpy( &(pHeader->SWCorner), src, 8*2 ); src += 8*2; + memcpy( &(pHeader->NECorner), src, 8*2 ); src += 8*2; + memcpy( &(pHeader->Origin), src, 8*2 ); src += 8*2; + memcpy( &(pHeader->dfLambertUpperLat), src, 8 ); src += 8; + memcpy( &(pHeader->dfLambertLowerLat), src, 8 ); src += 8; + memcpy( &(pHeader->iNextLightSource), src, 2 ); src += 2; + memcpy( &(pHeader->iNextLightPoint), src, 2 ); src += 2; + memcpy( &(pHeader->iNextRoad), src, 2 ); src += 2; + memcpy( &(pHeader->iNextCat), src, 2 ); src += 2; + src += 2*4; // Reserved; + memcpy( &(pHeader->diEllipsoid), src, 4 ); src += 4; + + if ( pHeader->diFormatRevLev >= 1570 ) + { + memcpy( &(pHeader->iNextAdaptiveNodeID), src, 2 ); src += 2; + memcpy( &(pHeader->iNextCurveNodeID), src, 2 ); src += 2; + + if ( pHeader->diFormatRevLev >= 1580 ) + { + // As of 2004/2/23, only adding 15.8 support to header parsing. + // Delete this comment when full support for 15.8 (1580) is added. + memcpy( &(pHeader->iUTMZone), src, 2 ); src += 2; + src += 6; // Reserved + } + else + // Must be v15.7 + src += 2; // Reserved + + memcpy( &(pHeader->dfDatabaseDeltaZ), src, 8 ); src += 8; + memcpy( &(pHeader->dfRadius), src, 8 ); src += 8; + memcpy( &(pHeader->iNextMeshNodeID), src, 2 ); src += 2; + + if ( pHeader->diFormatRevLev >= 1580 ) + { + // As of 2004/2/23, only adding 15.8 support to header parsing. + // Delete this comment when full support for 15.8 (1580) is added. + memcpy( &(pHeader->iNextLightPointSysID), src, 2 ); src += 2; + src += 4; // Reserved + memcpy( &(pHeader->dfEarthMajorAxis), src, 8 ); src += 8; + memcpy( &(pHeader->dfEarthMinorAxis), src, 8 ); src += 8; + } + else + // Must be v15.7 + src += 2; // Reserved + } + + // Now that we've copied the data into SHeader, we're done with the original packed + // data as read out of the OpenFlight file. Free it, and replace it with the + // SHeader struct, so that subsequent typecasts of _pData work as expected. + free( _pData ); + _pData = (SRecHeader*)pHeader; + + + // Proceed with byteswapping ENDIAN( pHeader->diFormatRevLev ); ENDIAN( pHeader->diDatabaseRevLev ); ENDIAN( pHeader->iNextGroup ); @@ -127,6 +219,16 @@ void HeaderRecord::endian() ENDIAN( pHeader->dfDatabaseDeltaZ ); ENDIAN( pHeader->dfRadius ); ENDIAN( pHeader->iNextMeshNodeID ); + + if ( pHeader->diFormatRevLev >= 1580 ) + { + // As of 2004/2/23, only adding 15.8 support to header parsing. + // Delete this comment when full support for 15.8 (1580) is added. + ENDIAN( pHeader->iUTMZone ); + ENDIAN( pHeader->iNextLightPointSysID ); + ENDIAN( pHeader->dfEarthMajorAxis ); + ENDIAN( pHeader->dfEarthMinorAxis ); + } } } diff --git a/src/osgPlugins/flt/HeaderRecord.h b/src/osgPlugins/flt/HeaderRecord.h index befd1585e..4e1676470 100644 --- a/src/osgPlugins/flt/HeaderRecord.h +++ b/src/osgPlugins/flt/HeaderRecord.h @@ -59,22 +59,19 @@ struct SHeader float64 dfDatabaseOffsetY; int16 iNextSound; // Next Sound Bead Id int16 iNextPath; // Next Path Bead ID - int32 diReserved_1[2]; // Reserved for MultiGen int16 iNextClippingRegion;// Next Clipping Region Bead ID int16 iNextText; // Next Text Bead ID int16 iNextBSP; // Next BSP ID int16 iNextSwitch; // Next Switch Bead ID - int32 diReserved_2; // Reserved float64x2 SWCorner; // South West Corner Lat/Lon (NB: dec. degrees) float64x2 NECorner; // North East Corner Lat/Lon (NB: dec. degrees) float64x2 Origin; // Origin Lat/Lon (NB: dec. degrees, not radians) float64 dfLambertUpperLat; // Lambert Upper Latitude float64 dfLambertLowerLat; // Lambert Lower Latitude int16 iNextLightSource; // Next Light Source ID Number - int16 iReserved_3; // Reserved + int16 iNextLightPoint; // Next Light Point ID number int16 iNextRoad; // Next road bead ID number int16 iNextCat; // Next CAT bead ID number - int16 iReserved_4[4]; // Reserved int32 diEllipsoid; // Earth ellipsoid model // 0 - WGS 1984 // 1 - WGS 1972 @@ -85,14 +82,20 @@ struct SHeader // New with 15.7.0 ... int16 iNextAdaptiveNodeID; // Next Adaptive node ID number int16 iNextCurveNodeID; // Next Curve node ID number - int16 iReserved_5; // Reserved float64 dfDatabaseDeltaZ; // Delta z to place database (used in // conjunction with existing Delta x and // Delta y values) float64 dfRadius; // Radius (distance from database origin to // farthest corner) uint16 iNextMeshNodeID; // Next Mesh node ID number - uint16 iReserved_6; // Reserved + + // New with 15.8 + // As of 2004/2/23, only adding 15.8 support to header parsing. + // Delete this comment when full support for 15.8 (1580) is added. + int16 iUTMZone; // UTM zone 1-60, negative indicates southern hemisphere + uint16 iNextLightPointSysID; // Light point system ID + float64 dfEarthMajorAxis; // Custom ellipsoid Earth major axis + float64 dfEarthMinorAxis; // Custom ellipsoid Earth minor axis };