From Corbin Holtz, "I have completed my mods to the OpenFlight loader (modified files are

attached):
   * Light point strings using the REPLICATE opcode should now be supported
(>=15.6?)

   * Directional lights should now work as in Performer using a viewing
frustrum defined by a direction vector, horizontal angular width, vertical
angular width, and roll angle about the direction vector.  The current
directional light implementation had some bad assumptions which caused
problems with direction vectors not on the XY plane.

   * IVE and OSG reader/writers were updated as appropriate"
This commit is contained in:
Robert Osfield
2004-05-08 22:18:38 +00:00
parent b6c1c44bd0
commit 86d323752d
15 changed files with 817 additions and 135 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -19,6 +19,7 @@
#include <osg/Quat>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Matrix>
#include <osg/Math>
#include <osg/Object>
@@ -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

View File

@@ -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()

View File

@@ -42,6 +42,37 @@ void MatrixRecord::endian()
}
}
////////////////////////////////////////////////////////////////////
//
// TranslateRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<TranslateRecord> 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<TranslateRecord> g_TranslateProxy;
TranslateRecord::TranslateRecord()
{
}
// virtual
TranslateRecord::~TranslateRecord()
{
}
// virtual
void TranslateRecord::endian()
{
}
////////////////////////////////////////////////////////////////////
//
// ScaleRecord

View File

@@ -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();
};
////////////////////////////////////////////////////////////////////
//

View File

@@ -29,6 +29,8 @@
#include <osg/Image>
#include <osg/Notify>
#include <osg/Sequence>
#include <osg/ShapeDrawable>
#include <osg/Quat>
#include <osgSim/MultiSwitch>
#include <osgSim/DOFTransform>
@@ -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 );

View File

@@ -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);

View File

@@ -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.");
}
}

View File

@@ -0,0 +1,15 @@
#ifndef IVE_DIRECTIONALSECTOR
#define IVE_DIRECTIONALSECTOR 1
#include <osgSim/Sector>
#include "ReadWrite.h"
namespace ive{
class DirectionalSector : public osgSim::DirectionalSector, public ReadWrite {
public:
void write(DataOutputStream* out);
void read(DataInputStream* in);
};
}
#endif

View File

@@ -65,6 +65,7 @@ CXXFILES =\
AzimSector.cpp\
BlinkSequence.cpp\
ConeSector.cpp\
DirectionalSector.cpp\
ElevationSector.cpp\
LightPoint.cpp\
LightPointNode.cpp\

View File

@@ -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<osgSim::ConeSector*>(_sector.get())){
((ive::ConeSector*)(_sector.get()))->write(out);
}
else if(dynamic_cast<osgSim::DirectionalSector*>(_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()");
}

View File

@@ -92,6 +92,7 @@ namespace ive {
#define IVEMULTISWITCH 0x00100008
#define IVEVISIBILITYGROUP 0x00100009
#define IVEDIRECTIONALSECTOR 0x0010000A
class ReadWrite{

View File

@@ -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 &sector = static_cast<osgSim::DirectionalSector &>(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 &sector = static_cast<const osgSim::DirectionalSector &>(obj);
const osg::Vec3& axis = sector.getDirection();
fw.indent()<<"direction "<<axis<<std::endl;
float horizangle = sector.getHorizLobeAngle();
float vertangle = sector.getVertLobeAngle();
float rollangle = sector.getLobeRollAngle();
float fadeangle = sector.getFadeAngle();
fw.indent()<<"angles "<<horizangle<<" "<<vertangle<<" "<<rollangle<<" "<<fadeangle<<std::endl;
return true;
}

View File

@@ -12,6 +12,7 @@
*/
#include <osgSim/Sector>
#include <osg/Vec2>
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 ;
}