diff --git a/Make/dependencies b/Make/dependencies index 772634a8e..64fdaaf50 100644 --- a/Make/dependencies +++ b/Make/dependencies @@ -1,7 +1,7 @@ ################################################################ # Dependency library which have been installed on this system -GDAL_INSTALLED = no +GDAL_INSTALLED = yes JASPER_INSTALLED = no FREETYPE_INSTALLED = yes diff --git a/VisualStudio/osgPlugins/ive/ive.dsp b/VisualStudio/osgPlugins/ive/ive.dsp index 1506a6c11..136dcf540 100755 --- a/VisualStudio/osgPlugins/ive/ive.dsp +++ b/VisualStudio/osgPlugins/ive/ive.dsp @@ -330,6 +330,10 @@ SOURCE=..\..\..\src\osgPlugins\ive\Transform.cpp # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\ive\DirectionalSector.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\ive\AzimElevationSector.cpp # End Source File # Begin Source File @@ -606,6 +610,10 @@ SOURCE=..\..\..\src\osgPlugins\ive\Transform.h # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\ive\DirectionalSector.h +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\ive\AzimElevationSector.h # End Source File # Begin Source File diff --git a/include/osgSim/Sector b/include/osgSim/Sector index 269c139bd..c398ea7b3 100644 --- a/include/osgSim/Sector +++ b/include/osgSim/Sector @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,7 @@ class OSGSIM_EXPORT AzimRange float dotproduct = eyeLocal.x()*_sinAzim+eyeLocal.y()*_cosAzim; float length = sqrt(osg::square(eyeLocal.x())+osg::square(eyeLocal.y())); if (dotproduct<_cosFadeAngle*length) return 0.0f; // out of sector. - if (dotproduct>_cosAngle*length) return 1.0f; // fully in sector. + if (dotproduct>=_cosAngle*length) return 1.0f; // fully in sector. return (dotproduct-_cosFadeAngle*length)/((_cosAngle-_cosFadeAngle)*length); } @@ -243,6 +244,76 @@ class OSGSIM_EXPORT ConeSector : public Sector float _cosAngleFade; }; + +/* The DirectionalSector class was created to better handle OpenFlight directional + lightpoints. The Elevation and Azimuth Sectors above impose invalid limits on + the elevation range which cause lightpoints whose direction vectors are not + on the XY plane to be displayed incorrectly. Corbin Holtz 4/04 */ + +class OSGSIM_EXPORT DirectionalSector : public Sector +{ + public: + + DirectionalSector(): + Sector(), + _direction(0.0f, 0.0f, 1.0f), + _rollAngle(0.0f), + _cosHorizAngle(-1.0f), + _cosVertAngle(-1.0f), + _cosHorizFadeAngle(-1.0f), + _cosVertFadeAngle(-1.0f) {computeMatrix();} + + DirectionalSector(const DirectionalSector& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY): + Sector(copy,copyop), + _direction(copy._direction), + _rollAngle(copy._rollAngle), + _local_to_LP(copy._local_to_LP), + _cosHorizAngle(copy._cosHorizAngle), + _cosVertAngle(copy._cosVertAngle), + _cosHorizFadeAngle(copy._cosHorizFadeAngle), + _cosVertFadeAngle(copy._cosVertFadeAngle) {} + + DirectionalSector(const osg::Vec3& direction,float horizLobeAngle, float vertLobeAngle, float lobeRollAngle, float fadeAngle=0.0f); + + META_Object(osgSim,DirectionalSector) + + void setDirection(const osg::Vec3& direction); + + const osg::Vec3& getDirection() const; + + void setHorizLobeAngle(float angle); + + float getHorizLobeAngle() const; + + void setLobeRollAngle(float angle); + + float getLobeRollAngle() const; + + void setVertLobeAngle(float angle); + + float getVertLobeAngle() const; + + void setFadeAngle(float angle); + + float getFadeAngle() const; + + virtual float operator() (const osg::Vec3& eyeLocal) const; + + void computeMatrix() ; + + protected: + + virtual ~DirectionalSector() {} + + osg::Vec3 _direction ; + float _rollAngle ; + osg::Matrix _local_to_LP ; + float _cosHorizAngle; + float _cosVertAngle; + float _cosHorizFadeAngle; + float _cosVertFadeAngle; +}; + } #endif diff --git a/src/osgPlugins/flt/Pool.h b/src/osgPlugins/flt/Pool.h index 96ace4431..febfbeb1e 100644 --- a/src/osgPlugins/flt/Pool.h +++ b/src/osgPlugins/flt/Pool.h @@ -162,13 +162,14 @@ public: struct PoolLtPtAppearance : public osg::Referenced { unsigned int _iBackColorIdx; - float _sfIntensity; + float _bIntensity; float _sfMinPixelSize; float _sfMaxPixelSize; float _sfActualSize; int _iDirectionality; float _sfHLobeAngle; float _sfVLobeAngle; + float _sfLobeRollAngle; }; LtPtAppearancePool() diff --git a/src/osgPlugins/flt/TransformationRecords.cpp b/src/osgPlugins/flt/TransformationRecords.cpp index 388073540..aba153b1b 100644 --- a/src/osgPlugins/flt/TransformationRecords.cpp +++ b/src/osgPlugins/flt/TransformationRecords.cpp @@ -42,6 +42,37 @@ void MatrixRecord::endian() } } +//////////////////////////////////////////////////////////////////// +// +// TranslateRecord +// +//////////////////////////////////////////////////////////////////// + +RegisterRecordProxy g_TranslateProxy; + +TranslateRecord::TranslateRecord() +{ +} + + +// virtual +TranslateRecord::~TranslateRecord() +{ +} + + +// virtual +void TranslateRecord::endian() +{ + STranslate *pSTranslate = (STranslate*)getData() ; + if ( pSTranslate) + { + pSTranslate->From.endian() ; + pSTranslate->Delta.endian() ; + } +} + + #if 0 //////////////////////////////////////////////////////////////////// // @@ -68,31 +99,6 @@ void RotatAboutEdgeRecord::endian() } -//////////////////////////////////////////////////////////////////// -// -// TranslateRecord -// -//////////////////////////////////////////////////////////////////// - -RegisterRecordProxy g_TranslateProxy; - -TranslateRecord::TranslateRecord() -{ -} - - -// virtual -TranslateRecord::~TranslateRecord() -{ -} - - -// virtual -void TranslateRecord::endian() -{ -} - - //////////////////////////////////////////////////////////////////// // // ScaleRecord diff --git a/src/osgPlugins/flt/TransformationRecords.h b/src/osgPlugins/flt/TransformationRecords.h index 67d3508ab..f7743cfbb 100644 --- a/src/osgPlugins/flt/TransformationRecords.h +++ b/src/osgPlugins/flt/TransformationRecords.h @@ -46,6 +46,41 @@ class MatrixRecord : public AncillaryRecord virtual void endian(); }; +//////////////////////////////////////////////////////////////////// +// +// TranslateRecord +// +//////////////////////////////////////////////////////////////////// + + +typedef struct TranslateTag +{ + SRecHeader RecHeader; + int32 diReserved; + float64x3 From; // reference FROM point + float64x3 Delta; // Delta to translate node by +} STranslate; + + +class TranslateRecord : public AncillaryRecord +{ + public: + TranslateRecord(); + + virtual Record* clone() const { return new TranslateRecord(); } + virtual const char* className() const { return "TranslateRecord"; } + virtual int classOpcode() const { return TRANSLATE_OP; } + virtual size_t sizeofData() const { return sizeof(STranslate); } + virtual void accept(RecordVisitor& rv) { rv.apply(*this); } +// virtual void traverse(RecordVisitor& rv); + + virtual STranslate* getData() const { return (STranslate*)_pData; } + + protected: + virtual ~TranslateRecord(); + + virtual void endian(); +}; #if 0 //////////////////////////////////////////////////////////////////// // @@ -84,41 +119,6 @@ class RotatAboutEdgeRecord : public AncillaryRecord }; -//////////////////////////////////////////////////////////////////// -// -// TranslateRecord -// -//////////////////////////////////////////////////////////////////// - - -struct STranslate -{ - SRecHeader RecHeader; - int32 diReserved; - float64x3 From; // reference FROM point - float64x3 Delta; // Delta to translate node by -}; - - -class TranslateRecord : public AncillaryRecord -{ - public: - TranslateRecord(); - - virtual Record* clone() const { return new TranslateRecord(); } - virtual const char* className() const { return "TranslateRecord"; } - virtual int classOpcode() const { return TRANSLATE_OP; } - virtual size_t sizeofData() const { return sizeof(STranslate); } - virtual void accept(RecordVisitor& rv) { rv.apply(*this); } -// virtual void traverse(RecordVisitor& rv); - - virtual STranslate* getData() const { return (STranslate*)_pData; } - - protected: - virtual ~TranslateRecord(); - - virtual void endian(); -}; //////////////////////////////////////////////////////////////////// // diff --git a/src/osgPlugins/flt/flt2osg.cpp b/src/osgPlugins/flt/flt2osg.cpp index 2e1229eca..2ebe6d73e 100644 --- a/src/osgPlugins/flt/flt2osg.cpp +++ b/src/osgPlugins/flt/flt2osg.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -83,7 +85,8 @@ #include "AttrData.h" #include "BSPRecord.h" - +static int dprint = 0 ; +#define DPRINT if(dprint)fprintf using namespace flt; @@ -292,6 +295,8 @@ osg::Group* ConvertFromFLT::visitPrimaryNode(osg::Group& osgParent, PrimNodeReco if (child && child->isPrimaryNode()) { + DPRINT(stderr, "**************************************\nvisitPrimaryNode: Got child opcode %d\n", child->getOpcode()) ; + switch (child->getOpcode()) { case MESH_OP: @@ -306,17 +311,13 @@ osg::Group* ConvertFromFLT::visitPrimaryNode(osg::Group& osgParent, PrimNodeReco { FaceRecord* fr = (FaceRecord*)child; if( fr->getData()->swTemplateTrans == 2) //Axis type rotate - visitFace(&billboardBuilder, fr); + visitFace(&billboardBuilder, osgParent, fr); else - visitFace(&geoSetBuilder, fr); + visitFace(&geoSetBuilder, osgParent, fr); } break; case LIGHT_POINT_OP: -#ifdef USE_DEPRECATED_LIGHTPOINT - visitLightPoint(&geoSetBuilder, (LightPointRecord*)child); -#else visitLightPoint(osgParent, (LightPointRecord*)child); -#endif break; case INDEXED_LIGHT_PT_OP: visitLightPointIndex(osgParent, (LightPointIndexRecord*)child); @@ -762,13 +763,14 @@ void ConvertFromFLT::visitLtPtAppearancePalette(osg::Group& /*osgParent*/, LtPtA LtPtAppearancePool::PoolLtPtAppearance* entry = new LtPtAppearancePool::PoolLtPtAppearance; entry->_iBackColorIdx = ltPtApp->backColor; - entry->_sfIntensity = ltPtApp->intensity; + entry->_bIntensity = ltPtApp->intensity; entry->_sfMinPixelSize = ltPtApp->minPixelSize; entry->_sfMaxPixelSize = ltPtApp->maxPixelSize; entry->_sfActualSize = ltPtApp->actualSize; entry->_iDirectionality = ltPtApp->directionality; entry->_sfHLobeAngle = ltPtApp->horizLobeAngle; entry->_sfVLobeAngle = ltPtApp->vertLobeAngle; + entry->_sfLobeRollAngle = ltPtApp->lobeRollAngle; pool->add(ltPtApp->index, entry); } @@ -1773,7 +1775,7 @@ ConvertFromFLT::addUVList( DynGeoSet* dgset, UVListRecord* uvr ) } } -void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec) +void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, osg::Group& osgParent, FaceRecord* rec) { DynGeoSet* dgset = pBuilder->getDynGeoSet(); osg::StateSet* osgStateSet = dgset->getStateSet(); @@ -1815,7 +1817,7 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec) setTransparency ( osgStateSet, bBlend ); // Vertices - addVertices(pBuilder, rec); + addVertices(pBuilder, osgParent, rec); // Add face to builder pool pBuilder->addPrimitive(); @@ -1867,25 +1869,40 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec) Record* child = rec->getChild(n); if (child && child->isOfType(FACE_OP)) - visitFace(pBuilder, (FaceRecord*)child); + visitFace(pBuilder, osgParent, (FaceRecord*)child); } _nSubfaceLevel--; } } +/* C.Holtz: These global variables are to support the REPLICATE ancillary record + used for lightpoint strings in 15.7 (it really should support replication of any + node, but I really only needed lightpoint strings and it's such a hack, I don't + want to propagate it anywhere is doesn't really need to be :) */ +static osg::Matrix theMatrix ; +static osg::Matrix theGeneralMatrix ; +static osg::Vec3 from, delta ; +static int num_replicate ; +static int got_gm, got_m, got_t, got_replicate ; // Return number of vertices added to builder. -int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec) +int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, osg::Group& osgParent, PrimNodeRecord* primRec) { int i; int vertices=0; DynGeoSet* dgset = pBuilder->getDynGeoSet(); + /* Clear the replicate stuff each time through */ + got_gm = got_m = got_t = got_replicate = 0 ; + + DPRINT(stderr, ">>> addVerticies...%d children\n", primRec->getNumChildren()) ; for(i=0; i < primRec->getNumChildren(); i++) { Record* child = primRec->getChild(i); if (child == NULL) break; + DPRINT(stderr, " child opcode = %d\n", child->getOpcode()) ; + switch (child->getOpcode()) { case VERTEX_LIST_OP: @@ -1896,6 +1913,83 @@ int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec vertices += visitLocalVertexPool(pBuilder, (LocalVertexPoolRecord *)child); break; + case TRANSLATE_OP: + if (1) { + // This will be for replicated verticies + STranslate *pSTranslate = ((TranslateRecord *)child)->getData() ; + // scale position. + from.set(pSTranslate->From[0],pSTranslate->From[1],pSTranslate->From[2]) ; + from *= _unitScale ; + delta.set(pSTranslate->Delta[0],pSTranslate->Delta[1],pSTranslate->Delta[2]) ; + delta *= _unitScale ; + DPRINT(stderr, " ** addVerticies: Got Translate: F=%lf, %lf, %lf / D=%lf, %lf, %lf\n", + from[0], from[1], from[2], delta[0], delta[1], delta[2]) ; + got_t = 1 ; + } + break ; + + case MATRIX_OP: + { + // This will be for replicated verticies + SMatrix *pSMatrix = ((MatrixRecord *)child)->getData() ; + for(int i=0;i<4;++i) + { + for(int j=0;j<4;++j) + { + theMatrix(i,j) = pSMatrix->sfMat[i][j]; + } + } + // scale position. + osg::Vec3 pos = theMatrix.getTrans(); + theMatrix *= osg::Matrix::translate(-pos); + pos *= (float)_unitScale; + theMatrix *= osg::Matrix::translate(pos); + if(dprint)std::cout << " ** addVerticies: Got Matrix: " << theMatrix << std::endl ; + got_m = 1 ; + } + break ; + + case GENERAL_MATRIX_OP: + { + // This will be for replicated verticies + SGeneralMatrix *pSMatrix = ((GeneralMatrixRecord *)child)->getData() ; + for(int i=0;i<4;++i) + { + for(int j=0;j<4;++j) + { + theGeneralMatrix(i,j) = pSMatrix->sfMat[i][j]; + } + } + // scale position. + osg::Vec3 pos = theGeneralMatrix.getTrans(); + theGeneralMatrix *= osg::Matrix::translate(-pos); + pos *= (float)_unitScale; + theGeneralMatrix *= osg::Matrix::translate(pos); + if(dprint)std::cout << " ** addVerticies: Got GeneralMatrix: " << theGeneralMatrix << std::endl ; + got_gm = 1 ; + } + break ; + + case REPLICATE_OP: + { + // This will be for replicated verticies + SReplicate *pSReplicate = (SReplicate *)(child->getData()) ; + ENDIAN(pSReplicate->iNumber) ; + num_replicate = pSReplicate->iNumber ; + DPRINT(stderr, " ** addVerticies: Got Replicate: %d times\n", num_replicate) ; + got_replicate = 1 ; + } + break ; + + case LIGHT_POINT_OP: + { + /* Apparently, lightpoints are allowed to be clildren + of faces in older versions (<15.4?) */ + DPRINT(stderr, " ** addVerticies: Got LIGHT_POINT_OP\n") ; + visitLightPoint(osgParent, (LightPointRecord*)child) ; + } + break ; + default : vertices += addVertex(pBuilder, child); break; @@ -1924,6 +2018,7 @@ int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* r DynGeoSet* dgset = pBuilder->getDynGeoSet(); int vertices = rec->numberOfVertices(); + DPRINT(stderr, ">>> visitVertexList...%d vertices\n", vertices) ; // Add vertices to GeoSetBuilder for (int j=0; j < vertices; j++) { @@ -1937,6 +2032,7 @@ int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* r { Record* child = rec->getChild(i); CERR << "OPCODE: " << child->getOpcode() << "\n"; + if (!child->isAncillaryRecord()) break; @@ -1980,14 +2076,40 @@ int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* r // Return 1 if record is a known vertex record else return 0. int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) { + + int i ; + + DPRINT(stderr, ">>> addVertex...") ; + switch(rec->getOpcode()) { case VERTEX_C_OP: + DPRINT(stderr, "VERTEX_C_OP\n") ; { SVertex* pVert = (SVertex*)rec->getData(); osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z()); coord *= (float)_unitScale; dgset->addCoord(coord); + if ( got_replicate ) { + /* Handle vertex replication */ + DPRINT(stderr, " ### addVertex: Replicating (%f,%f,%f) %d times...\n", + coord[0], coord[1], coord[2], num_replicate) ; + for ( i = 0 ; i < num_replicate ; i++ ) { + if ( got_t ) { + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } else { + /* If we didn't get a translate record, try to get the delta from the matrix */ + delta = theMatrix.getTrans() ; + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } + } + } if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool()) @@ -1995,11 +2117,32 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) break; case VERTEX_CN_OP: + DPRINT(stderr, "VERTEX_CN_OP\n") ; { SNormalVertex* pVert = (SNormalVertex*)rec->getData(); osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z()); coord *= (float)_unitScale; dgset->addCoord(coord); + if ( got_replicate ) { + /* Handle vertex replication */ + DPRINT(stderr, " ### addVertex: Replicating (%f,%f,%f) %d times...\n", + coord[0], coord[1], coord[2], num_replicate) ; + for ( i = 0 ; i < num_replicate ; i++ ) { + if ( got_t ) { + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } else { + /* If we didn't get a translate record, try to get the delta from the matrix */ + delta = theMatrix.getTrans() ; + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } + } + } if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_NORMAL(dgset, pVert) if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) @@ -2008,11 +2151,32 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) break; case VERTEX_CNT_OP: + DPRINT(stderr, "VERTEX_CNT_OP\n") ; { SNormalTextureVertex* pVert = (SNormalTextureVertex*)rec->getData(); osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z()); coord *= (float)_unitScale; dgset->addCoord(coord); + if ( got_replicate ) { + /* Handle vertex replication */ + DPRINT(stderr, " ### addVertex: Replicating (%f,%f,%f) %d times...\n", + coord[0], coord[1], coord[2], num_replicate) ; + for ( i = 0 ; i < num_replicate ; i++ ) { + if ( got_t ) { + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } else { + /* If we didn't get a translate record, try to get the delta from the matrix */ + delta = theMatrix.getTrans() ; + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } + } + } if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_NORMAL(dgset, pVert) if (dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) @@ -2023,11 +2187,32 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) break; case VERTEX_CT_OP: + DPRINT(stderr, "VERTEX_CT_OP\n") ; { STextureVertex* pVert = (STextureVertex*)rec->getData(); osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z()); coord *= (float)_unitScale; dgset->addCoord(coord); + if ( got_replicate ) { + /* Handle vertex replication */ + DPRINT(stderr, " ### addVertex: Replicating (%f,%f,%f) %d times...\n", + coord[0], coord[1], coord[2], num_replicate) ; + for ( i = 0 ; i < num_replicate ; i++ ) { + if ( got_t ) { + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } else { + /* If we didn't get a translate record, try to get the delta from the matrix */ + delta = theMatrix.getTrans() ; + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } + } + } if (dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_TCOORD(dgset, pVert) if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) @@ -2036,11 +2221,32 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) break; case OLD_VERTEX_OP: + DPRINT(stderr, "OLD_VERTEX_OP\n") ; { SOldVertex* pVert = (SOldVertex*)rec->getData(); osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]); coord *= (float)_unitScale; dgset->addCoord(coord); + if ( got_replicate ) { + /* Handle vertex replication */ + DPRINT(stderr, " ### addVertex: Replicating (%f,%f,%f) %d times...\n", + coord[0], coord[1], coord[2], num_replicate) ; + for ( i = 0 ; i < num_replicate ; i++ ) { + if ( got_t ) { + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } else { + /* If we didn't get a translate record, try to get the delta from the matrix */ + delta = theMatrix.getTrans() ; + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } + } + } if ((dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) && (rec->getSize() >= sizeof(SOldVertex))) ADD_OLD_TCOORD(dgset, pVert) @@ -2048,11 +2254,32 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) break; case OLD_VERTEX_COLOR_OP: + DPRINT(stderr, "OLD_VERTEX_COLOR_OP\n") ; { SOldVertexColor* pVert = (SOldVertexColor*)rec->getData(); osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]); coord *= (float)_unitScale; dgset->addCoord(coord); + if ( got_replicate ) { + /* Handle vertex replication */ + DPRINT(stderr, " ### addVertex: Replicating (%f,%f,%f) %d times...\n", + coord[0], coord[1], coord[2], num_replicate) ; + for ( i = 0 ; i < num_replicate ; i++ ) { + if ( got_t ) { + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } else { + /* If we didn't get a translate record, try to get the delta from the matrix */ + delta = theMatrix.getTrans() ; + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } + } + } if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_OLD_COLOR(dgset, pVert, rec->getFltFile()->getColorPool()) if ((dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) @@ -2062,11 +2289,32 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) break; case OLD_VERTEX_COLOR_NORMAL_OP: + DPRINT(stderr, "OLD_VERTEX_COLOR_NORMAL_OP\n") ; { SOldVertexColorNormal* pVert = (SOldVertexColorNormal*)rec->getData(); osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]); coord *= (float)_unitScale; dgset->addCoord(coord); + if ( got_replicate ) { + /* Handle vertex replication */ + DPRINT(stderr, " ### addVertex: Replicating (%f,%f,%f) %d times...\n", + coord[0], coord[1], coord[2], num_replicate) ; + for ( i = 0 ; i < num_replicate ; i++ ) { + if ( got_t ) { + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } else { + /* If we didn't get a translate record, try to get the delta from the matrix */ + delta = theMatrix.getTrans() ; + coord += delta ; + DPRINT(stderr, " >> Replicated vertex as (%f,%f,%f)\n", + coord[0], coord[1], coord[2]) ; + dgset->addCoord(coord) ; + } + } + } if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) { osg::Vec3 normal(pVert->n[0], pVert->n[1], pVert->n[2]); @@ -2082,8 +2330,13 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) break; default : + DPRINT(stderr, "*** UNKNOWN (%d)***\n", rec->getOpcode()) ; return 0; } + + /* Clear out the replicate stuff so that it doesn't get reused if we + return to this function from somewhere other than addVerticies() */ + got_gm = got_m = got_t = got_replicate = 0 ; return 1; } @@ -2184,7 +2437,7 @@ osg::Group* ConvertFromFLT::visitExternal(osg::Group& osgParent, ExternalRecord* } -void ConvertFromFLT::visitLightPoint(GeoSetBuilder* pBuilder, LightPointRecord* rec) +void ConvertFromFLT::visitLightPoint(GeoSetBuilder* pBuilder,osg::Group& osgParent, LightPointRecord* rec) { DynGeoSet* dgset = pBuilder->getDynGeoSet(); osg::StateSet* stateSet = dgset->getStateSet(); @@ -2221,7 +2474,7 @@ void ConvertFromFLT::visitLightPoint(GeoSetBuilder* pBuilder, LightPointRecord* } // Visit vertices - addVertices(pBuilder, rec); + addVertices(pBuilder, osgParent, rec); pBuilder->addPrimitive(); } @@ -2244,58 +2497,128 @@ void ConvertFromFLT::visitLightPoint(osg::Group& osgParent, LightPointRecord* re if( child->classOpcode() == COMMENT_OP) visitComment(*lpNode, (CommentRecord*)child); } + DPRINT(stderr, "visitLightPoint: visiting node '%s'...(%d children)\n", pSLightPoint->szIdent, rec->getNumChildren()) ; + lpNode->setName(pSLightPoint->szIdent) ; + lpNode->setMinPixelSize( pSLightPoint->sfMinPixelSize); lpNode->setMaxPixelSize( pSLightPoint->sfMaxPixelSize); + DPRINT(stderr, " MinPixelSize = %f\n", pSLightPoint->sfMinPixelSize) ; + DPRINT(stderr, " MaxPixelSize = %f\n", pSLightPoint->sfMaxPixelSize) ; - addVertices(&pBuilder, rec); + addVertices(&pBuilder, osgParent, rec); const DynGeoSet::CoordList& coords = dgset->getCoordList(); const DynGeoSet::ColorList& colors = dgset->getColorList(); const DynGeoSet::NormalList& norms = dgset->getNormalList(); - float lobeVert = osg::DegreesToRadians( pSLightPoint->sfLobeVert ); - float lobeHorz = osg::DegreesToRadians( pSLightPoint->sfLobeHoriz ); + DPRINT(stderr, " Num Coords=%d, Num Colors=%d, Num Norms=%d\n", coords.size(), colors.size(), norms.size()) ; + + bool directional = false; + int numInternalLightPoints = 0; // Number of osgSim::LightPoint objects to add per OpenFlight light point vertex + switch (pSLightPoint->diDirection) + { + case 0: // Omnidirectional; + DPRINT(stderr, " OMNIDIRECTIONAL\n") ; + directional = false; + numInternalLightPoints = 1; + break; + case 1: // Unidirectional; + DPRINT(stderr, " UNIDIRECTIONAL\n") ; + directional = true; + numInternalLightPoints = 1; + break; + case 2: // Bidirectional; + DPRINT(stderr, " BIDIRECTIONAL\n") ; + directional = true; + numInternalLightPoints = 2; + break; + } + + float lobeVert=0.f, lobeHorz=0.f, lobeRoll=0.f; + if ( directional) + { + lobeVert = osg::DegreesToRadians( pSLightPoint->sfLobeVert ); + lobeHorz = osg::DegreesToRadians( pSLightPoint->sfLobeHoriz ); + lobeRoll = osg::DegreesToRadians( pSLightPoint->sfLobeRoll ); + } float pointRadius = pSLightPoint->afActualPixelSize * _unitScale; + DPRINT(stderr, " Vertical Lobe Angle = %f\n", osg::RadiansToDegrees(lobeVert)) ; + DPRINT(stderr, " Horizontal Lobe Angle = %f\n", osg::RadiansToDegrees(lobeHorz)) ; + DPRINT(stderr, " Lobe Roll Angle = %f\n", osg::RadiansToDegrees(lobeRoll)) ; + DPRINT(stderr, " Point Radius = %f\n", pointRadius) ; + + /* From my experience during all this testing, I think it's safe to assume that + each light point in a single light point node should share the same color + and normal. Even if multiple normals are found, they seem to be wrong for some + reason */ + osg::Vec4 color( 1.0f, 1.0f, 1.0f, 1.0f); + osg::Vec3 normal( 1.0f, 0.0f, 0.0f); + for ( unsigned int nl = 0; nl < coords.size(); nl++) { - osg::Vec4 color( 1.0f, 1.0f, 1.0f, 1.0f); - if( nl < colors.size()) color = colors[nl]; + //if( nl < colors.size()) color = colors[nl]; + if( colors.size()>0) color = colors[0]; + DPRINT(stderr, " Color = %f, %f, %f, %f\n", color.x(), color.y(), color.z(), color.w()) ; osgSim::LightPoint lp( true, coords[ nl], color, pSLightPoint->sfIntensityFront, pointRadius); if( pSLightPoint->diDirection ) { - // calc elevation angles - osg::Vec3 normal( 1.0f, 0.0f, 0.0f); - if( nl < norms.size()) normal = norms[nl]; - - float elevAngle = osg::PI_2 - acos( normal.z() ); - if( normal.z() < 0.0f) elevAngle = -elevAngle; - float minElevation = elevAngle - lobeVert/2.0f; - float maxElevation = elevAngle + lobeVert/2.0f; - - // calc azimuth angles - osg::Vec2 pNormal( normal.x(), normal.y() ); - float lng = pNormal.normalize(); - float azimAngle = 0.0f; - if( lng > 0.0000001) - { - azimAngle = acos( pNormal.y() ); - if( pNormal.y() > 0.0f ) azimAngle = - azimAngle; - - float minAzimuth = azimAngle - lobeHorz/2.0f; - float maxAzimuth = azimAngle + lobeHorz/2.0f; - - float fadeRange = 0.0f; - lp._sector = new osgSim::AzimElevationSector( minAzimuth, maxAzimuth, minElevation, maxElevation, fadeRange); + DPRINT(stderr, " LP is directional...\n") ; + if ( !pSLightPoint->diDirectionalMode ) { + DPRINT(stderr, "%%%%%%%% WARNING: diDirection is set, but diDirectionalMode is off!!!\n") ; } - } + + // calc elevation angles + //if( nl < norms.size()) normal = norms[nl]; + if( norms.size()>0) normal = norms[0]; + DPRINT(stderr, " Normal = %f, %f, %f\n", normal.x(), normal.y(), normal.z()) ; + + // Verify normal. If normal is 0,0,0, then LP isn't really directional + if ( (fabsf(normal.x()) < 0.0001) && (fabsf(normal.y()) < 0.0001) && (fabsf(normal.z()) < 0.0001) ) { + DPRINT(stderr, "%%%%%%%% WARNING: diDirection is set, but normal is not set!!!\n") ; + DPRINT(stderr, " ADDING LIGHTPOINT\n") ; + lpNode->addLightPoint( lp); + continue ; + } + if ( normal.isNaN() ) { + DPRINT(stderr, "%%%%%%%% WARNING: diDirection is set, but normal is NaN!!!\n") ; + DPRINT(stderr, " ADDING LIGHTPOINT\n") ; + lpNode->addLightPoint( lp); + continue ; + } + + lp._sector = new osgSim::DirectionalSector( normal, lobeHorz, lobeVert, lobeRoll); + + if( pSLightPoint->diDirection == 2 ) + { + DPRINT(stderr, " ** LP is BIdirectional...\n") ; + + osg::Vec4 backcolor = pSLightPoint->dwBackColor.get() ; + if ( backcolor.w() == 0.0 ) backcolor[3] = 1.0 ; + osgSim::LightPoint lp2( true, coords[ nl], backcolor, 1.0f, pointRadius); + DPRINT(stderr, " Backface Color = %f, %f, %f, %f\n", backcolor.x(), backcolor.y(), backcolor.z(), backcolor.w()) ; + // calc elevation angles + osg::Vec3 backnormal = - normal ; + DPRINT(stderr, " Normal = %f, %f, %f\n", backnormal.x(), backnormal.y(), backnormal.z()) ; + + lp2._sector = new osgSim::DirectionalSector( backnormal, lobeHorz, lobeVert, lobeRoll); + + DPRINT(stderr, " ADDING BACKFACING LIGHTPOINT\n") ; + lpNode->addLightPoint(lp2); + } + } + + DPRINT(stderr, " ADDING LIGHTPOINT\n") ; lpNode->addLightPoint( lp); + } + DPRINT (stderr, "lpNode has %d children\n", lpNode->getNumLightPoints()) ; osgParent.addChild( lpNode); + } @@ -2336,7 +2659,7 @@ void ConvertFromFLT::visitLightPointIndex(osg::Group& osgParent, LightPointIndex lpNode->setMinPixelSize( ltPtApp->_sfMinPixelSize ); lpNode->setMaxPixelSize( ltPtApp->_sfMaxPixelSize ); - addVertices(&pBuilder, rec); + addVertices(&pBuilder, osgParent, rec); const DynGeoSet::CoordList& coords = dgset->getCoordList(); const DynGeoSet::ColorList& colors = dgset->getColorList(); @@ -2360,11 +2683,12 @@ void ConvertFromFLT::visitLightPointIndex(osg::Group& osgParent, LightPointIndex break; } - float lobeVert=0.f, lobeHorz=0.f; + float lobeVert=0.f, lobeHorz=0.f, lobeRoll=0.f; if ( directional) { lobeVert = osg::DegreesToRadians( ltPtApp->_sfVLobeAngle ); lobeHorz = osg::DegreesToRadians( ltPtApp->_sfHLobeAngle ); + lobeRoll = osg::DegreesToRadians( ltPtApp->_sfLobeRollAngle ); } float pointRadius = ltPtApp->_sfActualSize * _unitScale; @@ -2387,7 +2711,9 @@ void ConvertFromFLT::visitLightPointIndex(osg::Group& osgParent, LightPointIndex if (ltPtAnim && ltPtAnim->_blink.valid()) blink = ltPtAnim->_blink.get(); - osgSim::LightPoint lp( true, coords[nl], color, ltPtApp->_sfIntensity, pointRadius, + // note in corbin's code the ltPtApp->_bIntensity was set to 1.0, however, + // I have left the original setting in place. + osgSim::LightPoint lp( true, coords[nl], color, ltPtApp->_bIntensity, pointRadius, 0, blink ); if (directional) @@ -2400,28 +2726,7 @@ void ConvertFromFLT::visitLightPointIndex(osg::Group& osgParent, LightPointIndex // Negate the normal for the back facing internal light point normal = -normal; - float elevAngle = osg::PI_2 - acos( normal.z() ); - if (normal.z() < 0.0f) - elevAngle = -elevAngle; - float minElevation = elevAngle - lobeVert/2.0f; - float maxElevation = elevAngle + lobeVert/2.0f; - - // calc azimuth angles - osg::Vec2 pNormal( normal.x(), normal.y() ); - float lng = pNormal.normalize(); - float azimAngle = 0.0f; - if( lng > 0.0000001) - { - azimAngle = acos( pNormal.y() ); - if (pNormal.x() < 0.0f) - azimAngle = -azimAngle; - - float minAzimuth = azimAngle - lobeHorz/2.0f; - float maxAzimuth = azimAngle + lobeHorz/2.0f; - - float fadeRange = 0.0f; - lp._sector = new osgSim::AzimElevationSector( minAzimuth, maxAzimuth, minElevation, maxElevation, fadeRange); - } + lp._sector = new osgSim::DirectionalSector( normal, lobeHorz, lobeVert, lobeRoll); } lpNode->addLightPoint(lp); @@ -2521,7 +2826,7 @@ void ConvertFromFLT::visitMesh ( osg::Group &parent, GeoSetBuilder *pBuilder, Me setTransparency ( osgStateSet, bBlend ); // Add the vertices. - addVertices ( pBuilder, rec ); + addVertices ( pBuilder, parent, rec ); // Add the mesh primitives. addMeshPrimitives ( parent, pBuilder, rec ); diff --git a/src/osgPlugins/flt/flt2osg.h b/src/osgPlugins/flt/flt2osg.h index 10e6ea79c..6e31b3b66 100644 --- a/src/osgPlugins/flt/flt2osg.h +++ b/src/osgPlugins/flt/flt2osg.h @@ -160,10 +160,10 @@ class ConvertFromFLT osg::Group* visitInstanceDefinition(osg::Group& osgParent,InstanceDefinitionRecord* rec); osg::Group* visitInstanceReference(osg::Group& osgParent,InstanceReferenceRecord* rec); - void visitFace(GeoSetBuilder* pParent, FaceRecord* rec); + void visitFace(GeoSetBuilder* pParent, osg::Group& osgParent, FaceRecord* rec); void visitMesh(osg::Group& osgParent,GeoSetBuilder* pParent, MeshRecord* rec); void visitMeshPrimitive(osg::Group& osgParent, MeshPrimitiveRecord* rec); - void visitLightPoint(GeoSetBuilder* pBuilder, LightPointRecord* rec); + void visitLightPoint(GeoSetBuilder* pBuilder, osg::Group& osgParent, LightPointRecord* rec); void visitLightPoint(osg::Group& osgParent, LightPointRecord* rec); void visitLightPointIndex(osg::Group& osgParent, LightPointIndexRecord* rec); osg::Group* visitLightPointSystem(osg::Group& osgParent, LightPointSystemRecord* rec); @@ -179,7 +179,7 @@ class ConvertFromFLT private: int addMeshPrimitives ( osg::Group &osgParent, GeoSetBuilder *pBuilder, MeshRecord *rec ); - int addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec); + int addVertices(GeoSetBuilder* pBuilder, osg::Group& osgParent, PrimNodeRecord* primRec); int addVertex(DynGeoSet* dgset, Record* rec); int addVertex(GeoSetBuilder* pBuilder, Record* rec) {return addVertex( pBuilder->getDynGeoSet(), rec);} ; Record* getVertexFromPool(int nOffset); diff --git a/src/osgPlugins/ive/DirectionalSector.cpp b/src/osgPlugins/ive/DirectionalSector.cpp new file mode 100644 index 000000000..88cc01ff4 --- /dev/null +++ b/src/osgPlugins/ive/DirectionalSector.cpp @@ -0,0 +1,47 @@ +/********************************************************************** + * + * FILE: DirectionalSector.cpp + * + * DESCRIPTION: Read/Write osgSim::DirectionalSector in binary format to disk. + * + * CREATED BY: Auto generated by iveGenerator.exe + * and later modified by Rune Schmidt Jensen. + * + * HISTORY: Created 9.9.2003 + * + **********************************************************************/ + +#include "Exception.h" +#include "DirectionalSector.h" + +using namespace ive; + +void DirectionalSector::write(DataOutputStream* out){ + // Write DirectionalSector's identification. + out->writeInt(IVEDIRECTIONALSECTOR); + // Write DirectionalSector's properties. + out->writeVec3(getDirection()); + out->writeFloat(getHorizLobeAngle()); + out->writeFloat(getVertLobeAngle()); + out->writeFloat(getLobeRollAngle()); + out->writeFloat(getFadeAngle()); +} + +void DirectionalSector::read(DataInputStream* in){ + // Peek on DirectionalSector's identification. + int id = in->peekInt(); + if(id == IVEDIRECTIONALSECTOR){ + // Read DirectionalSector's identification. + id = in->readInt(); + // Read DirectionalSector's properties + setDirection(in->readVec3()); + setHorizLobeAngle(in->readFloat()); + setVertLobeAngle(in->readFloat()); + setLobeRollAngle(in->readFloat()); + setFadeAngle(in->readFloat()); + + } + else{ + throw Exception("DirectionalSector::read(): Expected DirectionalSector identification."); + } +} diff --git a/src/osgPlugins/ive/DirectionalSector.h b/src/osgPlugins/ive/DirectionalSector.h new file mode 100644 index 000000000..d268030b7 --- /dev/null +++ b/src/osgPlugins/ive/DirectionalSector.h @@ -0,0 +1,15 @@ +#ifndef IVE_DIRECTIONALSECTOR +#define IVE_DIRECTIONALSECTOR 1 + +#include +#include "ReadWrite.h" + +namespace ive{ +class DirectionalSector : public osgSim::DirectionalSector, public ReadWrite { +public: + void write(DataOutputStream* out); + void read(DataInputStream* in); +}; +} + +#endif diff --git a/src/osgPlugins/ive/GNUmakefile b/src/osgPlugins/ive/GNUmakefile index f684be3d8..2fbba5729 100644 --- a/src/osgPlugins/ive/GNUmakefile +++ b/src/osgPlugins/ive/GNUmakefile @@ -65,6 +65,7 @@ CXXFILES =\ AzimSector.cpp\ BlinkSequence.cpp\ ConeSector.cpp\ + DirectionalSector.cpp\ ElevationSector.cpp\ LightPoint.cpp\ LightPointNode.cpp\ diff --git a/src/osgPlugins/ive/LightPoint.cpp b/src/osgPlugins/ive/LightPoint.cpp index 218de0856..d09ca36b0 100644 --- a/src/osgPlugins/ive/LightPoint.cpp +++ b/src/osgPlugins/ive/LightPoint.cpp @@ -18,6 +18,7 @@ #include "ElevationSector.h" #include "AzimSector.h" #include "ConeSector.h" +#include "DirectionalSector.h" using namespace ive; @@ -47,6 +48,9 @@ void LightPoint::write(DataOutputStream* out){ else if(dynamic_cast(_sector.get())){ ((ive::ConeSector*)(_sector.get()))->write(out); } + else if(dynamic_cast(_sector.get())){ + ((ive::DirectionalSector*)(_sector.get()))->write(out); + } else throw Exception("Unknown sector in LightPoint::write()"); } @@ -99,6 +103,11 @@ void LightPoint::read(DataInputStream* in){ ((ive::ConeSector*)(sector))->read(in); _sector = sector; } + else if(attributeID == IVEDIRECTIONALSECTOR){ + sector = new osgSim::DirectionalSector(); + ((ive::DirectionalSector*)(sector))->read(in); + _sector = sector; + } else throw Exception("Unknown sector in LightPoint::read()"); } diff --git a/src/osgPlugins/ive/ReadWrite.h b/src/osgPlugins/ive/ReadWrite.h index a901da172..011336a6a 100644 --- a/src/osgPlugins/ive/ReadWrite.h +++ b/src/osgPlugins/ive/ReadWrite.h @@ -92,6 +92,7 @@ namespace ive { #define IVEMULTISWITCH 0x00100008 #define IVEVISIBILITYGROUP 0x00100009 +#define IVEDIRECTIONALSECTOR 0x0010000A class ReadWrite{ diff --git a/src/osgPlugins/osgSim/IO_Sector.cpp b/src/osgPlugins/osgSim/IO_Sector.cpp index 967c29e85..36da0832e 100644 --- a/src/osgPlugins/osgSim/IO_Sector.cpp +++ b/src/osgPlugins/osgSim/IO_Sector.cpp @@ -221,3 +221,69 @@ bool ConeSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw) return true; } +/******************************************************************/ + +bool DirectionalSector_readLocalData(osg::Object &obj, osgDB::Input &fr); +bool DirectionalSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw); + +osgDB::RegisterDotOsgWrapperProxy DirectionalSector_Proxy +( + new osgSim::DirectionalSector, + "DirectionalSector", + "Object DirectionalSector", + &DirectionalSector_readLocalData, + &DirectionalSector_writeLocalData, + osgDB::DotOsgWrapper::READ_AND_WRITE +); + +bool DirectionalSector_readLocalData(osg::Object &obj, osgDB::Input &fr) +{ + bool iteratorAdvanced = false; + osgSim::DirectionalSector §or = static_cast(obj); + + if (fr.matchSequence("direction %f %f %f")) + { + float x, y, z; + + fr[1].getFloat(x); + fr[2].getFloat(y); + fr[3].getFloat(z); + fr += 4; + sector.setDirection(osg::Vec3(x, y, z)); + iteratorAdvanced = true; + } + if (fr.matchSequence("angles %f %f %f %f")) + { + float horizangle; + float vertangle; + float rollangle; + float fadeangle; + fr[1].getFloat(horizangle); + fr[2].getFloat(vertangle); + fr[3].getFloat(rollangle); + fr[4].getFloat(fadeangle); + fr += 5; + sector.setHorizLobeAngle(horizangle); + sector.setVertLobeAngle(vertangle); + sector.setLobeRollAngle(rollangle); + sector.setFadeAngle(fadeangle); + iteratorAdvanced = true; + } + return iteratorAdvanced; +} + +bool DirectionalSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw) +{ + const osgSim::DirectionalSector §or = static_cast(obj); + + const osg::Vec3& axis = sector.getDirection(); + fw.indent()<<"direction "< +#include using namespace osgSim; @@ -213,3 +214,154 @@ float ConeSector::operator() (const osg::Vec3& eyeLocal) const if (dotproduct<_cosAngleFade*length) return 0.0f; // out of sector return (dotproduct-_cosAngleFade*length)/((_cosAngle-_cosAngleFade)*length); } + +// +// DirectionalSector +// +DirectionalSector::DirectionalSector(const osg::Vec3& direction,float horizLobeAngle, float vertLobeAngle, float lobeRollAngle, float fadeAngle): + Sector() +{ + setDirection(direction); + setHorizLobeAngle(horizLobeAngle); + setVertLobeAngle(vertLobeAngle); + setLobeRollAngle(lobeRollAngle); + setFadeAngle(fadeAngle); +} + +void DirectionalSector::computeMatrix() +{ + float cR = cos(_rollAngle) ; + float sR = sin(_rollAngle) ; + osg::Vec3 &D(_direction) ; // Just for clarity + + _local_to_LP.set( + cR*D[1]+sR*D[0]*D[2], -cR*D[0]+sR*D[1]*D[2], -sR*(D[0]*D[0]+D[1]*D[1]), 0.0, + D[0], D[1], D[2], 0.0, + sR*D[1]-cR*D[0]*D[2], -sR*D[0]-cR*D[1]*D[2], cR*(D[0]*D[0]+D[1]*D[1]), 0.0, + 0.0, 0.0, 0.0, 1.0) ; + +} + + +void DirectionalSector::setDirection(const osg::Vec3& direction) +{ + _direction = direction ; + computeMatrix() ; +} + +const osg::Vec3& DirectionalSector::getDirection() const +{ + return _direction; +} + +void DirectionalSector::setHorizLobeAngle(float angle) +{ + _cosHorizAngle = cos(angle*0.5); +} + +float DirectionalSector::getHorizLobeAngle() const +{ + return acos(_cosHorizAngle)*2.0; +} + +void DirectionalSector::setVertLobeAngle(float angle) +{ + _cosVertAngle = cos(angle*0.5); +} + +float DirectionalSector::getVertLobeAngle() const +{ + return acos(_cosVertAngle)*2.0; +} + +void DirectionalSector::setLobeRollAngle(float angle) +{ + _rollAngle = angle ; + computeMatrix() ; +} + +float DirectionalSector::getLobeRollAngle() const +{ + return _rollAngle ; +} + +void DirectionalSector::setFadeAngle(float angle) +{ + float ang = acos(_cosHorizAngle)+angle ; + if ( ang > osg::PI ) _cosHorizFadeAngle = -1.0 ; + else _cosHorizFadeAngle = cos(ang); + + ang = acos(_cosVertAngle)+angle ; + if ( ang > osg::PI ) _cosVertFadeAngle = -1.0 ; + else _cosVertFadeAngle = cos(ang); +} + +float DirectionalSector::getFadeAngle() const +{ + return acos(_cosHorizFadeAngle)-acos(_cosHorizAngle); +} + +float DirectionalSector::operator() (const osg::Vec3& eyeLocal) const +{ + float elev_intensity, azim_intensity ; + + // Tranform eyeLocal into the LightPoint frame + osg::Vec3 EPlp = _local_to_LP * eyeLocal ; + + /*fprintf(stderr, " eyeLocal = %f, %f, %f\n", eyeLocal[0], eyeLocal[1], eyeLocal[2]) ; + fprintf(stderr, " EPlp = %f, %f, %f\n", EPlp[0], EPlp[1], EPlp[2]) ;*/ + + // Elevation check + // Project EPlp into LP YZ plane and dot with LPy + osg::Vec2 EPyz(EPlp[1], EPlp[2]) ; + EPyz.normalize() ; + /*fprintf(stderr, " EPyz.normalize() = %f, %f\n", EPyz[0], EPyz[1]) ; + fprintf(stderr, " _cosVertFadeAngle = %f\n", _cosVertFadeAngle) ; + fprintf(stderr, " _cosVertAngle = %f\n", _cosVertAngle) ;*/ + // cosElev = EPyz* LPy = EPyz[0] + if ( EPyz[0] < _cosVertFadeAngle ) { + // Completely outside elevation range + //fprintf(stderr, " >> outside el range\n") ; + return(0.0f) ; + } + if ( EPyz[0] < _cosVertAngle ) { + // In the fade range + //fprintf(stderr, " >> inside el fade range\n") ; + elev_intensity = (_cosVertAngle-EPyz[0])/(_cosVertAngle-_cosVertFadeAngle) ; + } else { + // Fully in elevation range + elev_intensity = 1.0 ; + //fprintf(stderr, " >> fully inside el range\n") ; + } + // Elevation check passed + + // Azimuth check + // Project EPlp into LP XY plane and dot with LPy + osg::Vec2 EPxy(EPlp[0], EPlp[1]) ; + EPxy.normalize() ; + /*fprintf(stderr, " EPxy.normalize() = %f, %f\n", EPxy[0], EPxy[1]) ; + fprintf(stderr, " _cosHorizFadeAngle = %f\n", _cosHorizFadeAngle) ; + fprintf(stderr, " _cosHorizAngle = %f\n", _cosHorizAngle) ;*/ + // cosAzim = EPxy * LPy = EPxy[1] + // if cosElev < 0.0, then need to negate EP for azimuth check + if ( EPyz[0] < 0.0 ) EPxy.set(-EPxy[0], -EPxy[1]) ; + if ( EPxy[1] < _cosHorizFadeAngle ) { + // Completely outside azimuth range + //fprintf(stderr, " >> outside az range\n") ; + return(0.0f) ; + } + if ( EPxy[1] < _cosHorizAngle ) { + // In fade range + //fprintf(stderr, " >> inside az fade range\n") ; + azim_intensity = (_cosHorizAngle-EPxy[1])/(_cosHorizAngle-_cosHorizFadeAngle) ; + } else { + // Fully in azimuth range + //fprintf(stderr, " >> fully inside az range\n") ; + azim_intensity = 1.0 ; + } + // Azimuth check passed + + // We're good! Return full intensity + //fprintf(stderr, " %%%% Returing intensity = %f\n", elev_intensity * azim_intensity) ; + return elev_intensity * azim_intensity ; +}