From 3378f85d91d461876a705db1074a65a706c88951 Mon Sep 17 00:00:00 2001 From: torcs-ng Date: Sun, 14 Oct 2012 17:35:09 +0000 Subject: [PATCH] update osggraph : add ReaderWriterACC git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@4998 30fe4595-0a0c-4342-8851-515496e4dcbd Former-commit-id: 44dbfd483f99655aaaa524d88426eb14cc6af13a Former-commit-id: ce9a9d0f6623567dd55b57cbd427e38f6af0f13a --- src/modules/graphic/osggraph/AccException.cpp | 10 + src/modules/graphic/osggraph/AccException.h | 19 + src/modules/graphic/osggraph/AccGeode.cpp | 1292 +++++++++++++++++ src/modules/graphic/osggraph/AccGeode.h | 100 ++ src/modules/graphic/osggraph/CMakeLists.txt | 6 +- src/modules/graphic/osggraph/OsgMain.h | 34 + .../graphic/osggraph/ReaderWriterACC.cpp | 748 ++++++++++ .../graphic/osggraph/ReaderWriterACC.h | 1029 +++++++++++++ src/modules/graphic/osggraph/osggraph.cpp | 28 +- 9 files changed, 3250 insertions(+), 16 deletions(-) create mode 100644 src/modules/graphic/osggraph/AccException.cpp create mode 100644 src/modules/graphic/osggraph/AccException.h create mode 100644 src/modules/graphic/osggraph/AccGeode.cpp create mode 100644 src/modules/graphic/osggraph/AccGeode.h create mode 100644 src/modules/graphic/osggraph/OsgMain.h create mode 100644 src/modules/graphic/osggraph/ReaderWriterACC.cpp create mode 100644 src/modules/graphic/osggraph/ReaderWriterACC.h diff --git a/src/modules/graphic/osggraph/AccException.cpp b/src/modules/graphic/osggraph/AccException.cpp new file mode 100644 index 000000000..e501faba4 --- /dev/null +++ b/src/modules/graphic/osggraph/AccException.cpp @@ -0,0 +1,10 @@ +#include "AccException.h" + +using namespace ac3d; + +Exception::Exception(std::string error) +{ + _error = error; +} + +Exception::~Exception(){} diff --git a/src/modules/graphic/osggraph/AccException.h b/src/modules/graphic/osggraph/AccException.h new file mode 100644 index 000000000..de35a9ec0 --- /dev/null +++ b/src/modules/graphic/osggraph/AccException.h @@ -0,0 +1,19 @@ +#ifndef AC3D_EXCEPTION +#define AC3D_EXCEPTION 1 + +#include + +namespace ac3d +{ + class Exception + { + public: + Exception(std::string error); + ~Exception(); + std::string getError(){return _error;}; + private: + std::string _error; + }; +} + +#endif diff --git a/src/modules/graphic/osggraph/AccGeode.cpp b/src/modules/graphic/osggraph/AccGeode.cpp new file mode 100644 index 000000000..c8c4d28af --- /dev/null +++ b/src/modules/graphic/osggraph/AccGeode.cpp @@ -0,0 +1,1292 @@ +/* Code for writing AC3D format files, constructs one object per Geode + * since geodes only have 1 material, and AC3D allows multiple materials you + * may not get an exact vopy of an ac3d file used as input. + * + * originally by Roger James. + * upgraded to different types of Geometry primitive by Geoff Michel. + * Old GeoSet parsing code is commented out - will be removed eventually. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AccException.h" +#include "AccGeode.h" + +using namespace ac3d; +using namespace std; + +void Geode::OutputVertex(int Index, const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, ostream& fout) +{ + int LocalTexIndex; + int LocalVertexIndex; + if (NULL == pVertexIndices) + LocalVertexIndex = Index; + else + LocalVertexIndex = pVertexIndices->index(Index); + if (NULL != pTexCoords) + { + // Got some tex coords + // Check for an index + if (NULL != pTexIndices) + // Access tex coord array indirectly + LocalTexIndex = pTexIndices->index(Index); + else + LocalTexIndex = Index; + fout << LocalVertexIndex << " " << pTexCoords[LocalTexIndex][0] << " " << pTexCoords[LocalTexIndex][1] << std::endl; + } + else + fout << LocalVertexIndex << " 0 0" << std::endl; +} + +void Geode::OutputLines(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, ostream& fout) +{ + unsigned int indexEnd = drawArray->getFirst() + drawArray->getCount(); + for(unsigned int vindex=drawArray->getFirst(); vindexgetFirst() + drawArray->getCount(); + OutputSurfHead(iCurrentMaterial,surfaceFlags,indexEnd-drawArray->getFirst(), fout); + + for(unsigned int vindex=drawArray->getFirst(); vindexgetFirst() + drawArray->getCount(); + OutputSurfHead(iCurrentMaterial,surfaceFlags,indexEnd-drawArray->getFirst(), fout); + + for(unsigned int vindex=drawArray->getFirst(); vindexgetFirst() + drawArray->getCount(); + + for(unsigned int vindex=drawArray->getFirst(); vindexgetFirst() + drawArray->getCount(); + unsigned int evenodd=0; + + for(unsigned int vindex=drawArray->getFirst(); vindexgetFirst() + drawArray->getCount(); + + for(unsigned int vindex=drawArray->getFirst()+1; vindexgetFirst(), pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+1, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputQuads(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout) +{ + unsigned int primCount = 0; + unsigned int indexEnd = drawArray->getFirst() + drawArray->getCount(); + + for(unsigned int vindex=drawArray->getFirst(); vindexgetFirst() + drawArray->getCount(); + + for(unsigned int vindex=drawArray->getFirst(); vindexgetFirst() + drawArray->getCount(); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,drawArray->getCount(), fout); + + for(unsigned int vindex=drawArray->getFirst(); vindexgetFirst(); + + for(osg::DrawArrayLengths::const_iterator primItr = drawArrayLengths->begin(); primItr end(); ++primItr) + { + unsigned int localPrimLength; + localPrimLength = 2; + + for(GLsizei primCount = 0; primCount < *primItr; ++primCount) + { + if ((primCount%localPrimLength)==0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + } + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + ++vindex; + } + } +} + +void Geode::OutputTriangleDARR(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, ostream& fout) +{ + unsigned int vindex = drawArrayLengths->getFirst(); + + for(osg::DrawArrayLengths::const_iterator primItr = drawArrayLengths->begin(); primItr end(); ++primItr) + { + unsigned int localPrimLength; + localPrimLength = 3; + + for(GLsizei primCount = 0; primCount < *primItr; ++primCount) + { + if ((primCount%localPrimLength)==0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + } + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + ++vindex; + } + } +} + +void Geode::OutputQuadsDARR(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, ostream& fout) +{ + unsigned int vindex = drawArrayLengths->getFirst(); + + for(osg::DrawArrayLengths::const_iterator primItr = drawArrayLengths->begin(); primItr end()-4; primItr+=4) + { + unsigned int localPrimLength; + localPrimLength = 4; + + for(GLsizei primCount = 0; primCount < *primItr; ++primCount) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+2, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+3, pVertexIndices, pTexCoords, pTexIndices, fout); + + vindex+=4; + } + } +} + +void Geode::OutputQuadStripDARR(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, ostream& fout) +{ + unsigned int vindex = drawArrayLengths->getFirst(); + + for(osg::DrawArrayLengths::const_iterator primItr = drawArrayLengths->begin(); primItr end()-2; primItr+=2) + { + unsigned int localPrimLength; + localPrimLength = *primItr; + + for(GLsizei primCount = 0; primCount < *primItr; ++primCount) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+3, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+2, pVertexIndices, pTexCoords, pTexIndices, fout); + + vindex+=2; + } + } +} + +void Geode::OutputPolygonDARR(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, ostream& fout) +{ + unsigned int vindex = drawArrayLengths->getFirst(); + + for(osg::DrawArrayLengths::const_iterator primItr = drawArrayLengths->begin(); primItr end(); ++primItr) + { + unsigned int localPrimLength; + localPrimLength = *primItr; + + for(GLsizei primCount = 0; primCount < *primItr; ++primCount) + { + if ((primCount%localPrimLength)==0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + } + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + ++vindex; + } + } +} + +void Geode::OutputTriangleStripDARR(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, ostream& fout) +{ + unsigned int vindex = drawArrayLengths->getFirst(); + + for(osg::DrawArrayLengths::const_iterator primItr = drawArrayLengths->begin(); primItr end(); ++primItr) + { + // RFJ!!!!!!!!!! fixes for indexing + int localPrimLength= *primItr; + bool evenodd=true; + + for(GLsizei primCount = 0; primCount < localPrimLength - 2; ++primCount) + { + OutputSurfHead(iCurrentMaterial, surfaceFlags, 3, fout); + + if (evenodd) + { + OutputVertex(vindex + primCount, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex + primCount + 1, pVertexIndices, pTexCoords, pTexIndices, fout); + } else + { + OutputVertex(vindex + primCount + 1 , pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex + primCount, pVertexIndices, pTexCoords, pTexIndices, fout); + } + OutputVertex(vindex + primCount + 2, pVertexIndices, pTexCoords, pTexIndices, fout); + evenodd=!evenodd; + } + vindex += localPrimLength; + } +} + +void Geode::OutputTriangleFanDARR(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, ostream& fout) +{ + unsigned int vindex = drawArrayLengths->getFirst(); + + for(osg::DrawArrayLengths::const_iterator primItr = drawArrayLengths->begin(); primItr end(); ++primItr) + { + int localPrimLength = *primItr; + + for(GLsizei primCount = 0; primCount < localPrimLength - 2; primCount++) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,3, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+1+primCount, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex+2+primCount, pVertexIndices, pTexCoords, pTexIndices, fout); + } + vindex += localPrimLength; + } +} + +// DrawElements .... Ubyte +void Geode::OutputTriangleDelsUByte(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUByte* drawElements, ostream& fout) +{ + unsigned int primLength =3; + unsigned int primCount = 0; + + for(osg::DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItrend(); ++primCount,++primItr) + { + if ((primCount%primLength) == 0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + } + + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputTriangleStripDelsUByte(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUByte* drawElements, ostream& fout) +{ + unsigned int localPrimLength = 3; + bool evenodd=true; + + for(osg::DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItrend()-2; ++primItr) + { + unsigned int vindex=*primItr; + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + if (evenodd) + { + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + } else + { + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + evenodd=!evenodd; + } +} + +void Geode::OutputTriangleFanDelsUByte(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUByte* drawElements, ostream& fout) +{ + const unsigned int localPrimLength = 3; + unsigned int vindex=*(drawElements->begin()); + + for(osg::DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItrend()-2; ++primItr) + { + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputQuadStripDelsUByte(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUByte* drawElements, ostream& fout) +{ + const unsigned int localPrimLength=4; + for(osg::DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItrend()-3; primItr+=2) + { + unsigned int vindex=*primItr; + + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+3); + unsigned int vindexp3=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp3, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputQuadsDelsUByte(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUByte* drawElements, ostream& fout) +{ + const unsigned int localPrimLength=4; + + for(osg::DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItrend()-3; primItr+=4) + { + unsigned int vindex=*primItr; + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + unsigned int vindexp3=*(primItr+3); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp3, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputPolygonDelsUByte(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUByte* drawElements, ostream& fout) +{ + unsigned int primLength =drawElements->size(); + unsigned int primCount = 0; + + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + + for(osg::DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItrend(); ++primCount,++primItr) + { + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +// DrawElements .... UShort +void Geode::OutputTriangleDelsUShort(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUShort* drawElements, ostream& fout) +{ + unsigned int primLength =3; + unsigned int primCount = 0; + + for(osg::DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItrend(); ++primCount,++primItr) + { + if ((primCount%primLength) == 0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + } + + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputTriangleStripDelsUShort(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUShort* drawElements, ostream& fout) +{ + unsigned int localPrimLength = 3; + bool evenodd=true; + + for(osg::DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItrend()-2; ++primItr) + { + unsigned int vindex=*primItr; + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + if (evenodd) + { + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + } else + { + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + evenodd=!evenodd; + } +} + +void Geode::OutputTriangleFanDelsUShort(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUShort* drawElements, ostream& fout) +{ + const unsigned int localPrimLength = 3; + unsigned int vindex=*(drawElements->begin()); + + for(osg::DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItrend()-2; ++primItr) + { + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputQuadStripDelsUShort(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUShort* drawElements, ostream& fout) +{ + const unsigned int localPrimLength=4; + + for(osg::DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItrend()-3; primItr+=2) + { + unsigned int vindex=*primItr; + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+3); + unsigned int vindexp3=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp3, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputQuadsDelsUShort(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUShort* drawElements, ostream& fout) +{ + const unsigned int localPrimLength=4; + + for(osg::DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItrend()-3; primItr+=4) + { + unsigned int vindex=*primItr; + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + unsigned int vindexp3=*(primItr+3); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp3, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputPolygonDelsUShort(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUShort* drawElements, ostream& fout) +{ + unsigned int primLength =drawElements->size(); + unsigned int primCount = 0; + + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + + for(osg::DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItrend(); ++primCount,++primItr) + { + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +// DrawElements .... UInt +void Geode::OutputTriangleDelsUInt(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUInt* drawElements, ostream& fout) +{ + unsigned int primLength =3; + unsigned int primCount = 0; + + for(osg::DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItrend(); ++primCount,++primItr) + { + if ((primCount%primLength) == 0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + } + + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputTriangleStripDelsUInt(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUInt* drawElements, ostream& fout) +{ + unsigned int localPrimLength = 3; + bool evenodd=true; + + for(osg::DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItrend()-2; ++primItr) + { + unsigned int vindex=*primItr; + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + if (evenodd) + { + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + } else + { + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + evenodd=!evenodd; + } +} + +void Geode::OutputTriangleFanDelsUInt(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUInt* drawElements, ostream& fout) +{ + const unsigned int localPrimLength = 3; + unsigned int vindex=*(drawElements->begin()); + + for(osg::DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItrend()-2; ++primItr) + { + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputQuadStripDelsUInt(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUInt* drawElements, ostream& fout) +{ + const unsigned int localPrimLength = 4; + for(osg::DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItrend()-3; primItr+=2) + { + unsigned int vindex=*primItr; + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+3); + unsigned int vindexp3=*(primItr+2); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp3, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputQuadsDelsUInt(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUInt* drawElements, ostream& fout) +{ + const unsigned int localPrimLength=4; + + for(osg::DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItrend()-3; primItr+=4) + { + unsigned int vindex=*primItr; + unsigned int vindexp1=*(primItr+1); + unsigned int vindexp2=*(primItr+2); + unsigned int vindexp3=*(primItr+3); + + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp1, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp2, pVertexIndices, pTexCoords, pTexIndices, fout); + OutputVertex(vindexp3, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +void Geode::OutputPolygonDelsUInt(const int iCurrentMaterial, const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, + const osg::DrawElementsUInt* drawElements, ostream& fout) +{ + unsigned int primLength =drawElements->size(); + unsigned int primCount = 0; + + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + + for(osg::DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItrend(); ++primCount,++primItr) + { + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } +} + +const int Geode::ProcessMaterial(ostream& fout, const unsigned int igeode) +{ + // outputs materials from one geode + // extended for multiple geode models, GWM 2003. + // called before all the geometry as ac3d expects all materials in the header. + // returns number of materials made + unsigned int i; + const unsigned int iNumDrawables = getNumDrawables(); + const osg::StateSet::RefAttributePair* pRAP; + unsigned int iNumMaterials=0; + // Let ac3d optimise the file + // whiz round and get a list of materials + // these may be duplicates of materials on other Geode/geometry sets. + // Scan for materials + for (i = 0; i < iNumDrawables; i++) + { + const osg::Drawable* Drawable = getDrawable(i); + if (Drawable) + { + const osg::StateSet* theState = Drawable->getStateSet(); + if (theState) + { + pRAP = theState->getAttributePair(osg::StateAttribute::MATERIAL); + if (NULL != pRAP) + { + const osg::Material *pMaterial = dynamic_cast(pRAP->first.get()); + if (NULL != pMaterial) + { + const osg::Vec4& Diffuse = pMaterial->getDiffuse(osg::Material::FRONT_AND_BACK); + const osg::Vec4& Ambient = pMaterial->getAmbient(osg::Material::FRONT_AND_BACK); + const osg::Vec4& Emissive = pMaterial->getEmission(osg::Material::FRONT_AND_BACK); + const osg::Vec4& Specular = pMaterial->getSpecular(osg::Material::FRONT_AND_BACK); + fout << "MATERIAL " + << "\"osg"<getShininess(osg::Material::FRONT_AND_BACK) << " " + << "trans " << 1.0 - Diffuse[3] << std::endl; + iNumMaterials++; + } + } + } + } + } + return iNumMaterials; +} +void Geode::ProcessGeometry(ostream& fout, const unsigned int ioffset) +{ + // outputs one geode + // extended for multiple geode models, GWM 2003. + unsigned int i, j; //, k, m; + const unsigned int iNumDrawables = getNumDrawables(); + int iNumMaterials = 0; + const osg::StateSet::RefAttributePair* pRAP=NULL; + // Let ac3d optimise the file + // whiz round and get a list of materails + // write them out + // write out an object for each drawable. + // Write out world object + int ngeometry=0; // not all drawables are geometry, text is not converted to facets. + + for (i = 0; i < iNumDrawables; i++) + { // so here we count the geometries to be converted to AC3D + const osg::Drawable* Drawable = getDrawable(i); + if (Drawable) + { + const osg::Geometry *pGeometry = Drawable->asGeometry(); + if (NULL != pGeometry) ngeometry++; + } + } + if (ngeometry>1) + { // create a group + fout << "OBJECT group" << std::endl; + fout << "kids " << ngeometry << std::endl; + } + + // Process each drawable in turn + for (i = 0; i < iNumDrawables; i++) + { + const osg::Drawable* Drawable = getDrawable(i); + if (Drawable) + { + const osg::StateSet* theState = Drawable->getStateSet(); + const osg::Geometry *pGeometry = Drawable->asGeometry(); + if (NULL != pGeometry) + { + int iCurrentMaterial = -1; + + if (theState) { + pRAP = theState->getAttributePair(osg::StateAttribute::MATERIAL); + if (NULL != pRAP) + { + iCurrentMaterial = ioffset+iNumMaterials; + iNumMaterials++; + } + } + + //const osg::Vec3Array + const osg::Array *pVertexArray = pGeometry->getVertexArray(); + if (NULL != pVertexArray) + { + const unsigned int iNumVertices = pVertexArray->getNumElements(); // size(); + const osg::IndexArray *pVertexIndices = pGeometry->getVertexIndices(); + const osg::IndexArray * pTexIndices = pGeometry->getTexCoordIndices(0); + const osg::Vec2 *pTexCoords = NULL; + fout << "OBJECT poly" << std::endl; + fout << "name \"" << getName() << "\"" << std::endl; + + // Use zero offset co-ordinate as location IS OPTIONAL + // fout << "loc " << "0 0 0" << std::endl; + /* you could have an offset for the coordinates; it was suggested that the first coord would do. + if((*pVertexArray).getType()==osg::Array::Vec3ArrayType) { + const osg::Vec3Array *verts=static_cast(pVertexArray); + fout << (*verts)[0][0] << " " << (*verts)[0][1] << " " << (*verts)[0][2] << std::endl; + } else if((*pVertexArray).getType()==osg::Array::Vec2ArrayType) { + const osg::Vec2Array *verts=static_cast(pVertexArray); + fout << (*verts)[0][0] << " " << (*verts)[0][1] << " " << 0 << std::endl; + } else if((*pVertexArray).getType()==osg::Array::Vec4ArrayType) { + const osg::Vec4Array *verts=static_cast(pVertexArray); + fout << (*verts)[0][0] << " " << (*verts)[0][1] << " " << (*verts)[0][2] << std::endl; + } + << (*pVertexArray)[0][0] << " " + << (*pVertexArray)[0][1] << " " + << (*pVertexArray)[0][2] << std::endl; */ + + // Check for a texture + if (theState) + { + const osg::StateSet::TextureModeList& TextureModeList = theState->getTextureModeList(); + const osg::StateSet::TextureAttributeList& TextureAttributeList = theState->getTextureAttributeList(); + if (TextureAttributeList.size() > 0) + { + // Dont yet know how to handle more than one texture + assert(TextureAttributeList.size() == 1); + assert(TextureModeList.size() == 1); + const osg::StateSet::ModeList& ModeList = TextureModeList[0]; + assert(ModeList.size() == 1); + // Check for a single mode of GL_TEXTURE_2D and ON + osg::StateSet::ModeList::value_type ModeValuePair = *ModeList.begin(); + assert(ModeValuePair.first == GL_TEXTURE_2D); + assert(ModeValuePair.second == osg::StateAttribute::ON); + const osg::StateSet::AttributeList& AttributeList = TextureAttributeList[0]; + // assert(AttributeList.size() == 1); + const osg::Texture2D *pTexture2D = dynamic_cast(AttributeList.begin()->second.first.get()); + // assert(NULL != pTexture2D); + if (NULL != pTexture2D) + { + float fRep_s, fRep_t; + float fOffset_s, fOffset_t; + + pTexCoords = (const osg::Vec2*)pGeometry->getTexCoordArray(0)->getDataPointer(); + + // OK now see if I can calcualate the repeats + osg::Texture::WrapMode eWrapMode_s = pTexture2D->getWrap(osg::Texture::WRAP_S); + //osg::Texture::WrapMode eWrapMode_t = pTexture2D->getWrap(osg::Texture::WRAP_T); + + if (eWrapMode_s == osg::Texture::REPEAT) + { + if (NULL != pTexCoords) + { + // Find max min s coords + float fMin = std::numeric_limits::max(); + float fMax = std::numeric_limits::min(); + unsigned int iNumTexCoords = pGeometry->getTexCoordArray(0)->getNumElements(); + + for (j = 0; j < iNumTexCoords; j++) + { + if (pTexCoords[j][0] > fMax) + fMax = pTexCoords[j][0]; + if (pTexCoords[j][0] < fMin) + fMin = pTexCoords[j][0]; + } + fRep_s = fMax - fMin; + fOffset_s = fMin; + fMin = std::numeric_limits::max(); + fMax = std::numeric_limits::min(); + for (j = 0; j < iNumTexCoords; j++) + { + if (pTexCoords[j][1] > fMax) + fMax = pTexCoords[j][1]; + if (pTexCoords[j][1] < fMin) + fMin = pTexCoords[j][1]; + } + fRep_t = fMax - fMin; + fOffset_t = fMin; + } + else + { + fRep_s = 1.0; + fOffset_s = 0.0; + fRep_t = 1.0; + fOffset_t = 0.0; + } + } + else + { + fRep_s = 1.0; + fOffset_s = 0.0; + fRep_t = 1.0; + fOffset_t = 0.0; + } + { // replace back slash with / for ac3d convention GWM Sep 2003 + std::string fname=pTexture2D->getImage()->getFileName(); + unsigned int pos; + for (pos=0; pos< fname.length(); pos++) + { + if (fname[pos] == '\\') + fname[pos]='/'; + } + fout << "texture \"" << fname << "\"" << std::endl; + } + // fout << "texrep " << fRep_s << " " << fRep_t << std::endl; + // fout << "texoff " << fOffset_s << " " << fOffset_s << std::endl; + // Temp frig + fout << "texrep 1 1" << std::endl; + fout << "texoff 0 0" << std::endl; + } + } + } + + fout << "numvert " << iNumVertices << std::endl; + for (j = 0; j < iNumVertices; j++) + { // use 3 types of osg::Vec for coordinates.... + if((*pVertexArray).getType()==osg::Array::Vec3ArrayType) + { + const osg::Vec3Array *verts=static_cast(pVertexArray); + fout << (*verts)[j][0] << " " << (*verts)[j][1] << " " << (*verts)[j][2] << std::endl; + } else if((*pVertexArray).getType()==osg::Array::Vec2ArrayType) + { + const osg::Vec2Array *verts=static_cast(pVertexArray); + fout << (*verts)[j][0] << " " << (*verts)[j][1] << " " << 0 << std::endl; + } else if((*pVertexArray).getType()==osg::Array::Vec4ArrayType) + { + const osg::Vec4Array *verts=static_cast(pVertexArray); + fout << (*verts)[j][0] << " " << (*verts)[j][1] << " " << (*verts)[j][2] << std::endl; + } + } + + // Generate a surface for each primitive + unsigned int iNumSurfaces = 0; // complex tri-strip etc prims use more triangles + osg::Geometry::PrimitiveSetList::const_iterator pItr; + + for(pItr = pGeometry->getPrimitiveSetList().begin(); pItr != pGeometry->getPrimitiveSetList().end(); ++pItr) + { + const osg::PrimitiveSet* primitiveset = pItr->get(); + //const osg::PrimitiveSet::Type type = primitiveset->getType(); + unsigned int iNumPrimitives = primitiveset->getNumPrimitives(); + unsigned int iNumIndices = primitiveset->getNumIndices(); + GLenum mode=primitiveset->getMode(); + switch(mode) + { + case(osg::PrimitiveSet::POINTS): + iNumSurfaces+=1; // all points go in one big list + break; + case(osg::PrimitiveSet::LINES): // each line is a pair of vertices + case(osg::PrimitiveSet::TRIANGLES): // each tri = 3 verts + case(osg::PrimitiveSet::QUADS): + case(osg::PrimitiveSet::LINE_LOOP): + case(osg::PrimitiveSet::LINE_STRIP): + case(osg::PrimitiveSet::POLYGON): + iNumSurfaces+=iNumPrimitives; + break; + case(osg::PrimitiveSet::TRIANGLE_STRIP): + case(osg::PrimitiveSet::TRIANGLE_FAN): + iNumSurfaces+=iNumIndices-2*iNumPrimitives; + break; + case(osg::PrimitiveSet::QUAD_STRIP): + iNumSurfaces+=(iNumIndices-2*iNumPrimitives)/2; + break; + default: + break; // unknown shape + } + } + fout << "numsurf " << iNumSurfaces << std::endl; + + for(pItr = pGeometry->getPrimitiveSetList().begin(); pItr != pGeometry->getPrimitiveSetList().end(); ++pItr) + { + const osg::PrimitiveSet* primitiveset = pItr->get(); + GLenum mode=primitiveset->getMode(); + unsigned int primLength; + unsigned int surfaceFlags = 0x00; + + switch(mode) + { + case(osg::PrimitiveSet::POINTS): + primLength = 1; + surfaceFlags = 0x02; + break; + case(osg::PrimitiveSet::LINES): + primLength = 2; + surfaceFlags = 0x02; + break; + case(osg::PrimitiveSet::TRIANGLES): + primLength = 3; + break; + case(osg::PrimitiveSet::QUADS): + primLength = 4; + break; + default: + primLength = 0; + break; // compute later when =0. + } + +// osg::StateAttribute::GLModeValue backface =theState->getMode(osg::StateAttribute::CULLFACE); +// if (backface==osg::StateAttribute::ON) surfaceFlags |= 0x10; +// else if (backface==osg::StateAttribute::OFF) surfaceFlags &= 0x0f; + const osg::DrawArrays* drawArray = static_cast(primitiveset); + switch(primitiveset->getType()) + { + case(osg::PrimitiveSet::DrawArraysPrimitiveType): + { + switch(mode) + { + case(osg::PrimitiveSet::POINTS): + break; + case(osg::PrimitiveSet::LINES): + OutputLines(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + case(osg::PrimitiveSet::LINE_LOOP): + OutputLineLoop(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + case(osg::PrimitiveSet::LINE_STRIP): + OutputLineStrip(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + case(osg::PrimitiveSet::TRIANGLES): + OutputTriangle(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + case(osg::PrimitiveSet::QUADS): + OutputQuads(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_STRIP): + OutputTriangleStrip(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_FAN): + OutputTriangleFan(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + case(osg::PrimitiveSet::QUAD_STRIP): + OutputQuadStrip(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + case(osg::PrimitiveSet::POLYGON): + OutputPolygon(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArray, fout); + break; + default: + break; // unknown shape + } + break; + } + case(osg::PrimitiveSet::DrawArrayLengthsPrimitiveType): + { + + const osg::DrawArrayLengths* drawArrayLengths = static_cast(primitiveset); + switch(mode) + { + case(osg::PrimitiveSet::LINES): + OutputLineDARR(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArrayLengths, fout); + break; + case(osg::PrimitiveSet::TRIANGLES): + OutputTriangleDARR(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArrayLengths, fout); + break; + case(osg::PrimitiveSet::QUADS): + OutputQuadsDARR(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArrayLengths, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_STRIP): + OutputTriangleStripDARR(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArrayLengths, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_FAN): + OutputTriangleFanDARR(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArrayLengths, fout); + break; + case(osg::PrimitiveSet::QUAD_STRIP): + OutputQuadStripDARR(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArrayLengths, fout); + break; + case(osg::PrimitiveSet::POLYGON): + OutputPolygonDARR(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawArrayLengths, fout); + break; + default: + break; // unknown shape + } + /* const osg::DrawArrayLengths* drawArrayLengths = static_cast(primitiveset); + unsigned int vindex = drawArrayLengths->getFirst(); + for(osg::DrawArrayLengths::const_iterator primItr = drawArrayLengths->begin(); primItr !=drawArrayLengths->end(); ++primItr) + { + unsigned int localPrimLength; + if (primLength == 0) localPrimLength = *primItr; + else localPrimLength = primLength; + + for(GLsizei primCount = 0; primCount < *primItr; ++primCount) + { + if ((primCount%localPrimLength)==0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,localPrimLength, fout); + } + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + ++vindex; + } + + }*/ + break; + } + case(osg::PrimitiveSet::DrawElementsUBytePrimitiveType): + { + const osg::DrawElementsUByte* drawElements = static_cast(primitiveset); + switch(mode) + { + case(osg::PrimitiveSet::TRIANGLES): + OutputTriangleDelsUByte(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::QUADS): + OutputQuadsDelsUByte(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_STRIP): + OutputTriangleStripDelsUByte(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_FAN): + OutputTriangleFanDelsUByte(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::QUAD_STRIP): + OutputQuadStripDelsUByte(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::POLYGON): + OutputPolygonDelsUByte(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + default: + break; // unknown shape + } +/* if (primLength == 0) + primLength = primitiveset->getNumIndices(); + + const osg::DrawElementsUByte* drawElements = static_cast(primitiveset); + + unsigned int primCount = 0; + for(osg::DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primCount,++primItr) + { + + if ((primCount%primLength) == 0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + } + + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } + */ + + break; + } + case(osg::PrimitiveSet::DrawElementsUShortPrimitiveType): + { + const osg::DrawElementsUShort* drawElements = static_cast(primitiveset); + switch(mode) + { + case(osg::PrimitiveSet::TRIANGLES): + OutputTriangleDelsUShort(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::QUADS): + OutputQuadsDelsUShort(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_STRIP): + OutputTriangleStripDelsUShort(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_FAN): + OutputTriangleFanDelsUShort(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::QUAD_STRIP): + OutputQuadStripDelsUShort(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::POLYGON): + OutputPolygonDelsUShort(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + default: + break; // unknown shape + } +/* if (primLength == 0) + if (primLength == 0) + primLength = primitiveset->getNumIndices(); + + const osg::DrawElementsUShort* drawElements = static_cast(primitiveset); + + unsigned int primCount = 0; + + for(osg::DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primCount,++primItr) + { + + if ((primCount%primLength) == 0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + } + + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } */ + + break; + } + case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType): + { + const osg::DrawElementsUInt* drawElements = static_cast(primitiveset); + switch(mode) + { + case(osg::PrimitiveSet::TRIANGLES): + OutputTriangleDelsUInt(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::QUADS): + OutputQuadsDelsUInt(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_STRIP): + OutputTriangleStripDelsUInt(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::TRIANGLE_FAN): + OutputTriangleFanDelsUInt(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::QUAD_STRIP): + OutputQuadStripDelsUInt(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + case(osg::PrimitiveSet::POLYGON): + OutputPolygonDelsUInt(iCurrentMaterial,surfaceFlags, pVertexIndices, pTexCoords, pTexIndices, drawElements, fout); + break; + default: + break; // unknown shape + } +/* if (primLength == 0) + if (primLength == 0) + primLength = primitiveset->getNumIndices(); + + const osg::DrawElementsUInt* drawElements = static_cast(primitiveset); + + unsigned int primCount=0; + for(osg::DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primCount,++primItr) + { + + if ((primCount%primLength)==0) + { + OutputSurfHead(iCurrentMaterial,surfaceFlags,primLength, fout); + } + + unsigned int vindex=*primItr; + OutputVertex(vindex, pVertexIndices, pTexCoords, pTexIndices, fout); + } */ + + break; + } + default: + { + break; + } + } + } + } + fout << "kids 0" << endl; + } + } + else + { // not sure what else it could be, but perhaps, perhaps, perhaps. + } + } +} diff --git a/src/modules/graphic/osggraph/AccGeode.h b/src/modules/graphic/osggraph/AccGeode.h new file mode 100644 index 000000000..b4ab419aa --- /dev/null +++ b/src/modules/graphic/osggraph/AccGeode.h @@ -0,0 +1,100 @@ +#ifndef AC3D_GEODE +#define AC3D_GEODE 1 + +#include +#include + +namespace ac3d +{ + class Geode : public osg::Geode + { + public: + const int ProcessMaterial(std::ostream& fout, const unsigned int igeode); + void ProcessGeometry(std::ostream& fout, const unsigned int igeode); + private: + void OutputTriangle(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + void OutputTriangleStrip(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + void OutputTriangleFan(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + void OutputQuads(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + void OutputQuadStrip(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + void OutputLineStrip(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + void OutputLineLoop(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + void OutputLines(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + void OutputPolygon(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrays* drawArray, std::ostream& fout); + //== output for prims with draw array lengths + void OutputLineDARR(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, std::ostream& fout); + void OutputTriangleDARR(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, std::ostream& fout); + void OutputTriangleStripDARR(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, std::ostream& fout); + void OutputTriangleFanDARR(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, std::ostream& fout); + void OutputQuadStripDARR(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, std::ostream& fout); + void OutputQuadsDARR(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, std::ostream& fout); + void OutputPolygonDARR(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawArrayLengths* drawArrayLengths, std::ostream& fout); + // OutputTriangleDelsUByte + // draw elements - 3 types: UByte, UShort, Uint + void OutputTriangleDelsUByte(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUByte* drawElements, std::ostream& fout); + void OutputTriangleStripDelsUByte(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUByte* drawElements, std::ostream& fout); + void OutputTriangleFanDelsUByte(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUByte* drawElements, std::ostream& fout); + void OutputQuadStripDelsUByte(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUByte* drawElements, std::ostream& fout); + void OutputQuadsDelsUByte(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUByte* drawElements, std::ostream& fout); + void OutputPolygonDelsUByte(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUByte* drawElements, std::ostream& fout); + // for UShorts + void OutputTriangleDelsUShort(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUShort* drawElements, std::ostream& fout); + void OutputTriangleStripDelsUShort(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUShort* drawElements, std::ostream& fout); + void OutputTriangleFanDelsUShort(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUShort* drawElements, std::ostream& fout); + void OutputQuadStripDelsUShort(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUShort* drawElements, std::ostream& fout); + void OutputQuadsDelsUShort(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUShort* drawElements, std::ostream& fout); + void OutputPolygonDelsUShort(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUShort* drawElements, std::ostream& fout); + // for UInts + void OutputTriangleDelsUInt(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUInt* drawElements, std::ostream& fout); + void OutputTriangleStripDelsUInt(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUInt* drawElements, std::ostream& fout); + void OutputTriangleFanDelsUInt(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUInt* drawElements, std::ostream& fout); + void OutputQuadStripDelsUInt(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUInt* drawElements, std::ostream& fout); + void OutputQuadsDelsUInt(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUInt* drawElements, std::ostream& fout); + void OutputPolygonDelsUInt(const int iCurrentMaterial,const unsigned int surfaceFlags, + const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices,const osg::DrawElementsUInt* drawElements, std::ostream& fout); + // general output for all types + void OutputVertex(int Index, const osg::IndexArray *pVertexIndices, const osg::Vec2 *pTexCoords, const osg::IndexArray *pTexIndices, std::ostream& fout); + inline void OutputSurfHead(const int iCurrentMaterial,const unsigned int surfaceFlags, const int nv, std::ostream& fout) + { + fout << "SURF 0x" << std::hex << ((int)surfaceFlags) << std::endl; + if (iCurrentMaterial >= 0) + fout << "mat " << std::dec << iCurrentMaterial << std::endl; + fout << "refs " << std::dec << nv << std::endl; + } + }; +} + +#endif diff --git a/src/modules/graphic/osggraph/CMakeLists.txt b/src/modules/graphic/osggraph/CMakeLists.txt index 18d5afe1a..44ca977ee 100644 --- a/src/modules/graphic/osggraph/CMakeLists.txt +++ b/src/modules/graphic/osggraph/CMakeLists.txt @@ -1,7 +1,9 @@ INCLUDE(../../../../cmake/macros.cmake) -SET(OSGGRAPH_HEADERS grmain.h osggraph.h) -SET(OSGGRAPH_SOURCES grmain.cpp osggraph.cpp) +SET(OSGGRAPH_HEADERS AccGeode.h AccException.h ReaderWriterACC.h + OsgMain.h osggraph.h) +SET(OSGGRAPH_SOURCES AccGeode.cpp AccException.cpp ReaderWriterACC.cpp + osggraph.cpp) ADD_INTERFACE_INCLUDEDIR() ADD_SDLIB_INCLUDEDIR(portability math tgf tgfclient robottools) diff --git a/src/modules/graphic/osggraph/OsgMain.h b/src/modules/graphic/osggraph/OsgMain.h new file mode 100644 index 000000000..c3361f2f5 --- /dev/null +++ b/src/modules/graphic/osggraph/OsgMain.h @@ -0,0 +1,34 @@ +/*************************************************************************** + + file : OsgMain.h + created : Fri Aug 18 00:00:41 CEST 2000 + copyright : (C) 2012 by Xavier Bertaux + email : bertauxx@yahoo.fr + version : $Id: OsgMain.h 4693 2012-04-13 03:12:09Z torcs-ng $ + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _GRMAIN_H_ +#define _GRMAIN_H_ + +#ifdef WIN32 +#include +#include +#include +#endif + +#include +#include //tSituation + +//#include "grcam.h" + +#endif /* _GRMAIN_H_ */ diff --git a/src/modules/graphic/osggraph/ReaderWriterACC.cpp b/src/modules/graphic/osggraph/ReaderWriterACC.cpp new file mode 100644 index 000000000..79b9e3ebe --- /dev/null +++ b/src/modules/graphic/osggraph/ReaderWriterACC.cpp @@ -0,0 +1,748 @@ +// 30 Oct 2002 +// ACC3D loader for models generated by the AC3D modeller (www.ac3d.org) +// part of this source code were supplied by the AC3D project (Andy Colebourne) +// eg the basic parsing of an AC3D file. +// Conversion from AC3D scenegraph to OSG by GW Michel. + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "AccException.h" +#include "AccGeode.h" +#include "ReaderWriterACC.h" + +using namespace osgDB; + +class geodeVisitor : public osg::NodeVisitor +{ // collects geodes from scene sub-graph attached to 'this' + public: + geodeVisitor(): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + ~geodeVisitor() { _geodelist.clear();} + + // one apply for each type of Node that might be a user transform + virtual void apply(osg::Geode& geode) + { + _geodelist.push_back(&geode); + } + + virtual void apply(osg::Group& gp) + { + traverse(gp); // must continue subgraph traversal. + } + + std::vector getGeodes() {return _geodelist;} + + protected: + typedef std::vector Geodelist; + Geodelist _geodelist; +}; + +ReaderWriterACC::ReaderWriterACC() +{ + supportsExtension("acc","Speed Dreams Database format"); + m_bCar = false; + m_transparentGroup = NULL; + m_opaqueGroup = NULL; +} + +const char* ReaderWriterACC::className() +{ + return "ACC Speed Dreams Database Reader"; +} + +void ReaderWriterACC::SetCar(bool b) +{ + m_bCar = b; +} + +osg::Node* ReaderWriterACC::readFile(std::istream& stream, const osgDB::ReaderWriter::Options* options) +{ + FileData fileData(options); + osg::Group *pWorld = new osg::Group; + osg::Matrix identityTransform; + + while ((stream.good())&&(!stream.eof())) + { + osg::Node* node = readObject(stream, fileData, identityTransform, TextureData()); + if (node) + pWorld->addChild(node); + } + return pWorld; +} + +osg::Node* ReaderWriterACC::readObject(std::istream& stream, FileData& fileData, const osg::Matrix& parentTransform, TextureData textureData) +{ + int textureId = 0; + std::string texname0,texname1,texname2,texname3; + // most of this logic came from Andy Colebourne (developer of the AC3D editor) so it had better be right! + // The transform configured in this current object level + osg::Matrix transform; + // The vertex pool in this object + osg::ref_ptr vertexSet = new VertexSet; + osg::ref_ptr group = NULL; + //osg::ref_ptr group = new osg::Group; + osg::Vec2 textureOffset(0, 0); + osg::Vec2 textureRepeat(1, 1); + float creaseAngle = 61; + unsigned objectType = ac3d::ObjectTypeGroup; + std::string strName; + + while (!stream.eof() && stream.good()) + { + std::string token; + stream >> token; + + if (token == "MATERIAL") + { + MaterialData mat; + mat.readMaterial(stream); + fileData.addMaterial(mat); + } + else if (token == "OBJECT") + { + std::string type; + stream >> type; + + if (!m_bCar) + { + group = new osg::Group(); + group->setDataVariance(osg::Object::STATIC); + } + else + { + group = m_opaqueGroup; + } + + if (type == "group") + { + objectType = ac3d::ObjectTypeGroup; + + } + else if (type == "world") + { + objectType = ac3d::ObjectTypeGroup; + if (m_bCar) + { + group = new osg::Group(); + //group->setDataVariance(osg::Object::STATIC); + group->setName("World"); + m_transparentGroup = new osg::Group(); + m_transparentGroup->setName("Transparent"); + m_opaqueGroup = new osg::Group(); + m_opaqueGroup->setName("Opaque"); + group->addChild(m_opaqueGroup); + group->addChild(m_transparentGroup); + } + } + else if (type == "poly") + { + objectType = ac3d::ObjectTypeNormal; + } + else + objectType = ac3d::ObjectTypeNormal; + } + else if (token == "crease") + { + stream >> creaseAngle; + } + else if (token == "data") + { + int len; + stream >> len; + std::vector tmp(len); + stream.read(&(tmp[0]), len); + } + else if (token == "name") + { + strName = readString(stream); + m_bBlockTransparent = false; + + if (m_bCar) + { + bool b; + if (strName == "GRILL1_s_0") + b = true; + if (!strncmp(strName.c_str(), "WI", 2)) + { + group = m_transparentGroup; + m_bBlockTransparent = false; + } + else + m_bBlockTransparent = true; + } + else + { + if (group) + group->setName(strName.c_str()); + } + } + else if (token == "texture") + { + // read the texture name + std::string texname = readString(stream); + + // strip absolute paths + if (texname[0] == '/' || (isalpha(texname[0]) && texname[1] == ':')) + { + std::string::size_type p = texname.rfind('\\'); + if (p != std::string::npos) + texname = texname.substr(p+1, std::string::npos); + p = texname.rfind('/'); + if (p != std::string::npos) + texname = texname.substr(p+1, std::string::npos); + } + if (texname == "empty_texture_no_mapping") + texname = ""; + + if (!m_bCar) + { + switch (textureId) + { + case 0: + texname0 = texname; + break; + + case 1: + texname1 = texname; + break; + + case 2: + texname2 = texname; + break; + + case 3: + texname3 = texname; + break; + } + } + else + { + if (textureId == 0) + texname0 = texname; + } + textureId++; + } + else if (token == "base") + { + //TODO + } + else if (token == "tiled") + { + //TODO + } + else if (token == "skids") + { + //TODO + } + else if (token == "shad") + { + + } + else if (token == "texrep") + { + stream >> textureRepeat[0] >> textureRepeat[1]; + } + else if (token == "texoff") + { + stream >> textureOffset[0] >> textureOffset[1]; + } + else if (token == "rot") + { + for (unsigned n = 0; n < 3; ++n) + for (unsigned m = 0; m < 3; ++m) + stream >> transform(m, n); + } + else if (token == "loc") + { + for (unsigned n = 0; n < 3; ++n) + stream >> transform(3, n); + } + else if (token == "url") + { + std::string url; + stream >> url; + group->addDescription(url); + } + else if (token == "numvert") + { + osg::Matrix currentTransform = transform*parentTransform; + + unsigned num; + stream >> num; + + if (num != 0) + { + vertexSet->reserve(num); + char line[256]; + stream.getline(line,256); + + for (unsigned n = 0; n < num; ++n) + { + stream.getline(line,256); + std::stringstream ss(line); + osg::Vec3 p,nm; + ss >> p[0] >> p[1] >> p[2]; + + nm[0] = 0.0; + nm[1] = 1.0; + nm[2] = 0.0; + + ss >> nm[0] >> nm[1] >> nm[2]; + + vertexSet->addVertex(currentTransform.preMult(p)); + } + } + } + else if (token == "numsurf") + { + textureData = fileData.toTextureData(texname0,texname1,texname2,texname3,m_bBlockTransparent); + + unsigned num; + stream >> num; + + if (0 < num) + { + // list of materials required- generate one geode per material + std::vector primitiveBins(fileData.getNumMaterials()); + + for (unsigned n = 0; n < num; ++n) + { + std::string token; + stream >> token; + + if (token != "SURF") + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: expected SURF line while reading object \"" + << group->getName() << "\"!" << std::endl; + return group.release(); + } + + stream >> token; + unsigned flags = strtol(token.c_str(), NULL, 0); + unsigned v = flags &0xF; + bool bNotStrip = false; + if (v!=4) + bNotStrip = false; + + stream >> token; + if (token != "mat") + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: expected mat line while reading object \"" + << group->getName() << "\"!" << std::endl; + return group.release(); + } + + // read the material index + unsigned matIdx; + stream >> matIdx; + if (primitiveBins.size() <= matIdx) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: invalid material number while reading object \"" + << group->getName() << "\"" << std::endl; + return group.release(); + } + + // now get the correct PrimitiveBin + PrimitiveBin* primitiveBin = 0; + primitiveBin = primitiveBins[matIdx].getOrCreatePrimitiveBin(flags, vertexSet.get()); + if (!primitiveBin) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: unexpected primitive flags while reading object \"" + << group->getName() << "\"" << std::endl; + return group.release(); + } + + // read the refs + stream >> token; + if (token != "refs") + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: expected refs line while reading object \"" + << group->getName() << "\"" << std::endl; + return group.release(); + } + + unsigned nRefs = 0; + stream >> nRefs; + if (!stream) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: could not read number of refs while reading object \"" + << group->getName() << "\"" << std::endl; + return group.release(); + } + + // in case this is an invalid refs count for this primitive + // read further, but do not store that primitive + bool acceptPrimitive = primitiveBin->beginPrimitive(nRefs); + int UVCount = 1; + + for (unsigned i = 0; i < nRefs; ++i) + { + // Read the vertex index + unsigned index; + stream >> index; + if (vertexSet->size() <= index) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: invalid ref vertex index while reading object \"" + << group->getName() << "\"" << std::endl; + return group.release(); + } + + // Read the texture corrdinates + osg::Vec2 texCoord,texCoord2,texCoord3; + std::string strUVs; + std::getline(stream,strUVs); + + char * pch; + pch = strtok ((char*)strUVs.c_str()," "); + texCoord[0] = atof(pch); + pch = strtok (NULL, " "); + texCoord[1] = atof(pch); + pch = strtok (NULL, " "); + + UVCount = 1; + if (pch) + { + texCoord2[0] = atof(pch); + pch = strtok (NULL, " "); + texCoord2[1] = atof(pch); + pch = strtok (NULL, " "); + UVCount = 2; + } + + if (pch) + { + texCoord3[0] = atof(pch); + pch = strtok (NULL, " "); + texCoord3[1] = atof(pch); + pch = strtok (NULL, " "); + UVCount = 3; + } + + if (!stream) + { + osg::notify(osg::WARN) << "osgDB TORCS reader: could not parse texture coords while reading object \"" + << group->getName() << "\" setting to (0,0)" << std::endl; + stream.clear(); + std::string dummy; + std::getline(stream, dummy); + } + + if (acceptPrimitive) + { + texCoord[0] = textureOffset[0] + texCoord[0]*textureRepeat[0]; + texCoord[1] = textureOffset[1] + texCoord[1]*textureRepeat[1]; + + if (!primitiveBin->vertex(index, texCoord,texCoord2,texCoord3)) + { + return group.release(); + } + } + } + + if (acceptPrimitive) + { + if (!primitiveBin->endPrimitive()) + { + return group.release(); + } + } + } + + for (unsigned i = 0; i < primitiveBins.size(); ++i) + primitiveBins[i].finalize(group.get(), fileData.getMaterial(i), textureData); + } + } + else if (token == "kids") + { + osg::Node *k = NULL; + + unsigned num; + stream >> num; + if (num != 0) + { + for (unsigned n = 0; n < num; n++) + { + k = readObject(stream, fileData, transform*parentTransform, textureData); + if (k == 0) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: error reading child object" << std::endl; + return group.release(); + } + else + { + osg::LightSource *ls = dynamic_cast(k); + if (ls) + { + osg::StateSet* lightStateSet = group->getOrCreateStateSet(); + group->setStateSet(lightStateSet); + group->setCullingActive(false); + ls->setStateSetModes(*lightStateSet, osg::StateAttribute::ON); + } + + if(!m_bCar) + group->addChild(k); + } + } + bool bFinished = true; + } + else if (objectType == ac3d::ObjectTypeLight) + { // add a light source to the scene 1 Nov 2003 + osg::Light* ac3dLight = fileData.getNextLight(); + osg::Matrix tt = transform*parentTransform; + ac3dLight->setPosition(osg::Vec4(tt(3, 0), tt(3, 1), tt(3, 2), 1)); + ac3dLight->setDirection(osg::Matrix::transform3x3(osg::Vec3(0.0f, 0.0f, -1.0f), tt)); + ac3dLight->setAmbient(osg::Vec4(0.5f,0.5f,0.5f,1.0f)); + ac3dLight->setDiffuse(osg::Vec4(0.5f,0.5f,0.5f,1.0f)); + ac3dLight->setSpecular(osg::Vec4(1.0f,1.0f,0.5f,1.0f)); + + osg::LightSource* ac3dLightSource = new osg::LightSource; + ac3dLightSource->setDataVariance(osg::Object::STATIC); + ac3dLightSource->setLight(ac3dLight); + ac3dLightSource->setLocalStateSetModes(osg::StateAttribute::ON); + + // for some mad reason, you need to set this so that the light works. WHY? + return ac3dLightSource; + } + return group.release(); + } + else + { + std::string strUnknown = token; + osg::notify(osg::WARN) << "osgDB TORCS reader: unknown token refs line while reading object \"" + <<" token:"< local_opt; + if (options) + local_opt = static_cast(options->clone(osg::CopyOp::DEEP_COPY_ALL)); + else + local_opt = new Options; + local_opt->getDatabasePathList().push_back(osgDB::getFilePath(fileName)); + + ReadResult result = readNode(fin, local_opt.get()); + if (result.validNode()) + result.getNode()->setName(fileName); + return result; +} + +osgDB::ReaderWriter::ReadResult ReaderWriterACC::readNode(std::istream& fin, const Options* options) +{ + std::string header; + fin >> header; + if (header.substr(0, 4) != "AC3D") + return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; + + return readFile(fin, options); +} + +osgDB::ReaderWriter::WriteResult ReaderWriterACC::writeNode(const osg::Node& node,const std::string& fileName, const Options* /*options*/) +{ + std::string ext = osgDB::getFileExtension(fileName); + if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; + geodeVisitor vs; // this collects geodes. + std::vectoriNumMaterials; + const_cast(node).accept(vs); // this parses the tree to streamd Geodes + std::vector glist=vs.getGeodes(); + osgDB::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary); + // Write out the file header + std::vector::iterator itr; + fout << "AC3Db" << std::endl; + // output the Materials + int iNumGeodesWithGeometry = 0; + for (itr=glist.begin();itr!= glist.end();itr++) + { + iNumMaterials.push_back(const_cast(static_cast(*itr))->ProcessMaterial(fout,itr-glist.begin())); + unsigned int iNumDrawables = (*itr)->getNumDrawables(); + int iNumGeometries = 0; + for (unsigned int i = 0; i < iNumDrawables; i++) + { + const osg::Drawable* pDrawable = (*itr)->getDrawable(i); + if (NULL != pDrawable) + { + const osg::Geometry *pGeometry = pDrawable->asGeometry(); + if (NULL != pGeometry) + iNumGeometries++; + } + } + if (iNumGeometries > 0) + iNumGeodesWithGeometry++; + } + // output the Geometry + unsigned int nfirstmat=0; + fout << "OBJECT world" << std::endl; + + fout << "kids " << iNumGeodesWithGeometry << std::endl; + for (itr=glist.begin();itr!= glist.end();itr++) { + const_cast(static_cast(*itr))->ProcessGeometry(fout,nfirstmat); + nfirstmat+=iNumMaterials[itr-glist.begin()]; + } + fout.close(); + return WriteResult::FILE_SAVED; +} + +osgDB::ReaderWriter::WriteResult ReaderWriterACC::writeNode(const osg::Node& node,std::ostream& fout, const Options* opts) +{ + try + { + // write ac file. + if(dynamic_cast(&node)) + { + const osg::Group *gp=dynamic_cast(&node); + const unsigned int nch=gp->getNumChildren(); + for (unsigned int i=0; igetChild(i)), fout, opts); + } + } + else + osg::notify(osg::WARN)<<"File must start with a geode "<> std::ws; + + if (stream.peek() != '\"') + { + // Not quoted, just read the string + stream >> s; + } + else + { + // look for quoted strings + + // throw away the quote + stream.get(); + + // extract characters until either an error happens or a quote is found + while (stream.good()) + { + std::istream::char_type c; + stream.get(c); + if (c == '\"') + break; + s += c; + } + } + + return s; +} + +void setAlphaClamp(osg::StateSet* stateSet,float clamp) +{ + osg::AlphaFunc* alphaFunc = new osg::AlphaFunc; + alphaFunc->setFunction(osg::AlphaFunc::GREATER,clamp); + stateSet->setAttributeAndModes( alphaFunc, osg::StateAttribute::ON ); +} + +void setTranslucent(osg::StateSet* stateSet) +{ + osg::BlendFunc* blendFunc = new osg::BlendFunc; + blendFunc->setDataVariance(osg::Object::STATIC); + blendFunc->setSource(osg::BlendFunc::SRC_ALPHA); + blendFunc->setDestination(osg::BlendFunc::ONE_MINUS_SRC_ALPHA); + stateSet->setAttribute(blendFunc); + stateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); +} + +unsigned int GetUVCount(unsigned flags) +{ + switch(flags) + { + case 0x14: + return 1; + case 0x24: + return 2; + case 0x34: + return 2; + case 0x44: + return 2; + } + + return 0; +} diff --git a/src/modules/graphic/osggraph/ReaderWriterACC.h b/src/modules/graphic/osggraph/ReaderWriterACC.h new file mode 100644 index 000000000..402f46271 --- /dev/null +++ b/src/modules/graphic/osggraph/ReaderWriterACC.h @@ -0,0 +1,1029 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "AccException.h" +#include "AccGeode.h" + +namespace ac3d +{ + enum + { + ObjectTypeNormal = 0, + ObjectTypeGroup = 1, + ObjectTypeLight = 2, + + SurfaceTypePolygon = 0, + SurfaceTypeLineLoop = 1, + SurfaceTypeLineStrip = 2, + + SurfaceShaded = 1<<4, + SurfaceTwoSided = 1<<5 + }; +} + +void setTranslucent(osg::StateSet* stateSet); +std::string readString(std::istream& stream); +void setAlphaClamp(osg::StateSet* stateSet,float clamp); +unsigned int GetUVCount(unsigned flags); + +// Just a container to store an ac3d material +class MaterialData +{ + public: + MaterialData() : + mMaterial(new osg::Material), + mColorArray(new osg::Vec4Array(1)) + { + mMaterial->setDataVariance(osg::Object::STATIC); + mColorArray->setDataVariance(osg::Object::STATIC); + } + + void readMaterial(std::istream& stream) + { + // note that this might be quoted + std::string name = readString(stream); + mMaterial->setName(name); + std::string tmp; + stream >> tmp; + osg::Vec4 diffuse; + stream >> diffuse[0] >> diffuse[1] >> diffuse[2]; + mMaterial->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse); + stream >> tmp; + osg::Vec4 ambient; + stream >> ambient[0] >> ambient[1] >> ambient[2]; + mMaterial->setAmbient(osg::Material::FRONT_AND_BACK, ambient); + stream >> tmp; + osg::Vec4 emmissive; + stream >> emmissive[0] >> emmissive[1] >> emmissive[2]; + mMaterial->setEmission(osg::Material::FRONT_AND_BACK, emmissive); + stream >> tmp; + osg::Vec4 specular; + stream >> specular[0] >> specular[1] >> specular[2]; + mMaterial->setSpecular(osg::Material::FRONT_AND_BACK, specular); + stream >> tmp; + float shininess; + stream >> shininess; + mMaterial->setShininess(osg::Material::FRONT_AND_BACK, shininess); + stream >> tmp; + float transparency; + stream >> transparency; + mMaterial->setTransparency(osg::Material::FRONT_AND_BACK, transparency); + mTranslucent = 0 < transparency; + + // must correspond to the material we use for the color array below + mMaterial->setColorMode(osg::Material::DIFFUSE); + // this must be done past the transparency setting ... + (*mColorArray)[0] = mMaterial->getDiffuse(osg::Material::FRONT_AND_BACK); + } + + void toStateSet(osg::StateSet* stateSet) const + { + stateSet->setAttribute(mMaterial.get()); + if (mTranslucent) + setTranslucent(stateSet); + } + + osg::Vec4Array* getColorArray() const + { + return mColorArray.get(); + } + +private: + osg::ref_ptr mMaterial; + osg::ref_ptr mColorArray; + bool mTranslucent; +}; + +class TextureData +{ + public: + TextureData() : + mTranslucent(false), + mRepeat(true), + mAlphaClamp(0.0f) + { + } + + void SetBlockTransparent(bool bStatus) { mTranslucent = bStatus;} + + bool setTexture(const std::string& name,const std::string& name1,const std::string& name2,const std::string& name3, const osgDB::ReaderWriter::Options* options, osg::TexEnv* modulateTexEnv,const bool bBlockTransparent) + { + mTexture2DRepeat = new osg::Texture2D; + mTexture2DRepeat->setDataVariance(osg::Object::STATIC); + mTexture2DRepeat->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); + mTexture2DRepeat->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); + + mTexture2DClamp = new osg::Texture2D; + mTexture2DClamp->setDataVariance(osg::Object::STATIC); + mTexture2DClamp->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE); + mTexture2DClamp->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE); + + std::string absFileName = osgDB::findDataFile(name, options); + if (absFileName.empty()) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: could not find texture \"" << name << "\"" << std::endl; + return false; + } + mImage = osgDB::readRefImageFile(absFileName, options); + if (!mImage.valid()) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: could not read texture \"" << name << "\"" << std::endl; + return false; + } + + mTexture2DRepeat->setImage(mImage.get()); + mTexture2DClamp->setImage(mImage.get()); + mTranslucent = mImage->isImageTranslucent(); + + if (bBlockTransparent) + mTranslucent = false; + + // Use a shared modulate TexEnv + mModulateTexEnv = modulateTexEnv; + + if (name1!="") + { + std::string absFileName = osgDB::findDataFile(name1, options); + mImage2 = osgDB::readRefImageFile(absFileName, options); + if (!mImage2.valid()) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: could not read texture \"" << name << "\"" << std::endl; + return false; + } + + mTexture2DClamp2 = new osg::Texture2D; + mTexture2DClamp2->setDataVariance(osg::Object::STATIC); + mTexture2DClamp2->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); + mTexture2DClamp2->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); + mTexture2DClamp2->setImage(mImage2.get()); + } + + if (strstr(name.c_str(),"tree")!=NULL || strstr(name.c_str(),"trans-")!=NULL || strstr(name.c_str(),"arbor")!=NULL) + { + mAlphaClamp=0.65f; + } + return true; + } + + void setRepeat(bool repeat) + { + mRepeat = repeat; + } + + bool valid() const + { + return mImage.valid(); + } + + std::string getFileName() const + { + if (!mImage.valid()) + return std::string(); + return mImage->getFileName(); + } + + void toTextureStateSet(osg::StateSet* stateSet) const + { + if (!valid()) + return; + stateSet->setTextureAttribute(0, mModulateTexEnv.get()); + if (mRepeat) + stateSet->setTextureAttribute(0, mTexture2DRepeat.get()); + else + stateSet->setTextureAttribute(0, mTexture2DClamp.get()); + stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + + if (mTexture2DClamp2.valid()) + { + stateSet->setTextureAttribute(1, mTexture2DClamp2.get()); + stateSet->setTextureMode(1, GL_TEXTURE_2D, osg::StateAttribute::ON); + } + + if (mTranslucent) + setTranslucent(stateSet); + + if (mAlphaClamp>0.0f) + setAlphaClamp(stateSet,mAlphaClamp); + } +private: + osg::ref_ptr mModulateTexEnv; + osg::ref_ptr mTexture2DClamp; + osg::ref_ptr mTexture2DRepeat; + osg::ref_ptr mTexture2DClamp2; + osg::ref_ptr mImage; + osg::ref_ptr mImage2; + bool mTranslucent; + float mAlphaClamp; + bool mRepeat; + bool mCar; +}; + +class FileData +{ + public: + FileData(const osgDB::ReaderWriter::Options* options) : mOptions(options), mLightIndex(1) + { + mModulateTexEnv = new osg::TexEnv; + mModulateTexEnv->setDataVariance(osg::Object::STATIC); + mModulateTexEnv->setMode(osg::TexEnv::MODULATE); + } + + TextureData toTextureData(const std::string& texName0,const std::string& texName1,const std::string& texName2,const std::string& texName3,const bool bBlockTransparent) + { + std::string strTrans = "_NO"; + if (bBlockTransparent) + strTrans = "_YES"; + + std::string texName = texName0+texName1+texName2+texName3+strTrans; + TextureDataMap::iterator i = mTextureStates.find(texName); + if (i == mTextureStates.end()) + mTextureStates[texName].setTexture(texName0,texName1,texName2,texName3, mOptions.get(), mModulateTexEnv.get(),bBlockTransparent); + return mTextureStates[texName]; + } + + osg::Light* getNextLight() + { + osg::Light* light = new osg::Light; + light->setDataVariance(osg::Object::STATIC); + light->setLightNum(mLightIndex++); + return light; + } + + void addMaterial(const MaterialData& material) + { + mMaterials.push_back(material); + } + unsigned getNumMaterials() const + { + return mMaterials.size(); + } + const MaterialData& getMaterial(unsigned idx) const + { + return mMaterials[idx]; + } + +private: + /// Stores the ac3d file reader options, only used for reading texture files + osg::ref_ptr mOptions; + + /// The list of ac3d MATERIALS + std::vector mMaterials; + + /// Local per model texture attribute cache. + /// ... images are usualy cached in the registries object cache + typedef std::map TextureDataMap; + TextureDataMap mTextureStates; + /// A common shared TexEnv set to modulate + osg::ref_ptr mModulateTexEnv; + + /// Hack to include light nodes from ac3d into the scenegraph + unsigned mLightIndex; +}; + +struct RefData +{ + RefData(const osg::Vec2& _texCoord,const osg::Vec2& _texCoord1,const osg::Vec2& _texCoord2) + { + texCoord = _texCoord; + texCoord1 = _texCoord1; + texCoord2 = _texCoord2; + } + osg::Vec2 texCoord; + osg::Vec2 texCoord1; + osg::Vec2 texCoord2; + osg::Vec3 normal; +}; + +struct VertexData +{ + VertexData(const osg::Vec3& vertex) : _vertex(vertex) {} + unsigned addRefData(const RefData& refData) + { + unsigned index = _refs.size(); + _refs.push_back(refData); + return index; + } + + osg::Vec3 _vertex; + std::vector _refs; +}; + +struct VertexIndex +{ + VertexIndex(unsigned _vertexIndex = 0, unsigned _refIndex = 0) : + vertexIndex(_vertexIndex), refIndex(_refIndex) + {} + unsigned vertexIndex; + unsigned refIndex; +}; + +class VertexSet : public osg::Referenced +{ +public: + VertexSet() + {} + + void reserve(unsigned n) + { + _vertices.reserve(n); + } + + unsigned size() const + { + return _vertices.size(); + } + + void addVertex(const osg::Vec3& vertex) + { + _vertices.push_back(vertex); + } + + const osg::Vec3& getVertex(unsigned index) + { + return _vertices[index]._vertex; + } + + const osg::Vec3& getVertex(const VertexIndex& vertexIndex) + { + return _vertices[vertexIndex.vertexIndex]._vertex; + } + + const osg::Vec3& getNormal(const VertexIndex& vertexIndex) + { + return _vertices[vertexIndex.vertexIndex]._refs[vertexIndex.refIndex].normal; + } + + const osg::Vec2& getTexCoord(const VertexIndex& vertexIndex) + { + return _vertices[vertexIndex.vertexIndex]._refs[vertexIndex.refIndex].texCoord; + } + + const osg::Vec2& getTexCoord1(const VertexIndex& vertexIndex) + { + return _vertices[vertexIndex.vertexIndex]._refs[vertexIndex.refIndex].texCoord1; + } + + const osg::Vec2& getTexCoord2(const VertexIndex& vertexIndex) + { + return _vertices[vertexIndex.vertexIndex]._refs[vertexIndex.refIndex].texCoord2; + } + + VertexIndex addRefData(unsigned i, const RefData& refData) + { + if (_vertices.size() <= i) + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: internal error, got invalid vertex index!" << std::endl; + return VertexIndex(0, 0); + } + return VertexIndex(i, _vertices[i].addRefData(refData)); + } + +private: + std::vector _vertices; +}; + +class PrimitiveBin : public osg::Referenced +{ + public: + PrimitiveBin(unsigned flags, VertexSet* vertexSet) : + _geode(new osg::Geode), + _vertexSet(vertexSet), + _flags(flags) + { + _geode->setDataVariance(osg::Object::STATIC); + } + + virtual bool beginPrimitive(unsigned nRefs) = 0; + virtual bool vertex(unsigned vertexIndex, const osg::Vec2& texCoord, const osg::Vec2& texCoord1, const osg::Vec2& texCoord2) = 0; + virtual bool endPrimitive() = 0; + virtual osg::Geode* finalize(const MaterialData& material, const TextureData& textureData) = 0; + + protected: + bool isLineLoop() const + { + return (_flags & ac3d::SurfaceTypeLineLoop)!=0; + } + + bool isLineStrip() const + { + return (_flags & ac3d::SurfaceTypeLineStrip)!=0; + } + + bool isTwoSided() const + { + //return (_flags & SurfaceTwoSided)!=0; + return true; + } + + bool isSmooth() const + { + return (_flags & ac3d::SurfaceShaded)!=0; + } + + bool isTriangleStrip() const + { + if (_flags == 0x14) + return true; + + if(_flags == 0x24) + return true; + + if (_flags == 0x34) + return true; + + if (_flags == 0x44) + return true; + + return false; + } + + bool isTriangleFan() const + { + if (_flags == 0x30) + return true; + + return false; + } + + osg::ref_ptr _geode; + osg::ref_ptr _vertexSet; + + private: + unsigned _flags; +}; + +class LineBin : public PrimitiveBin +{ + private: + osg::ref_ptr _geometry; + osg::ref_ptr _vertices; + osg::ref_ptr _texCoords; + struct Ref + { + osg::Vec2 texCoord; + unsigned index; + }; + std::vector _refs; + + public: + LineBin(unsigned flags, VertexSet* vertexSet) : + PrimitiveBin(flags, vertexSet), + _geometry(new osg::Geometry), + _vertices(new osg::Vec3Array), + _texCoords(new osg::Vec2Array) + { + _geometry->setDataVariance(osg::Object::STATIC); + _vertices->setDataVariance(osg::Object::STATIC); + _texCoords->setDataVariance(osg::Object::STATIC); + _geometry->setVertexArray(_vertices.get()); + _geometry->setTexCoordArray(0, _texCoords.get()); + osg::StateSet* stateSet = _geode->getOrCreateStateSet(); + stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + } + + virtual bool beginPrimitive(unsigned nRefs) + { + // Check if we have enough for a line or someting broken ... + if (nRefs < 2) + { + osg::notify(osg::WARN) << "osgDB TORCS reader: detected line with less than 2 vertices!" << std::endl; + return false; + } + + _refs.reserve(nRefs); + _refs.resize(0); + return true; + } + + virtual bool vertex(unsigned vertexIndex, const osg::Vec2& texCoord, const osg::Vec2& texCoord1, const osg::Vec2& texCoord2) + { + Ref ref; + ref.index = vertexIndex; + ref.texCoord = texCoord; + _refs.push_back(ref); + return true; + } + + virtual bool endPrimitive() + { + GLint type; + if (isLineLoop()) + type = osg::PrimitiveSet::LINE_LOOP; + else if (isLineStrip()) + type = osg::PrimitiveSet::LINE_STRIP; + else + { + osg::notify(osg::FATAL) << "osgDB TORCS reader: non surface flags in surface bin!" << std::endl; + return false; + } + unsigned nRefs = _refs.size(); + unsigned start = _vertices->size(); + + for (unsigned i = 0; i < nRefs; ++i) + { + osg::Vec3 vertex = _vertexSet->getVertex(_refs[i].index); + _vertices->push_back(vertex); + _texCoords->push_back(_refs[i].texCoord); + } + _geometry->addPrimitiveSet(new osg::DrawArrays(type, start, nRefs)); + + return true; + } + + virtual osg::Geode* finalize(const MaterialData& material, const TextureData& textureData) + { + _geode->addDrawable(_geometry.get()); + material.toStateSet(_geode->getOrCreateStateSet()); + _geometry->setColorArray(material.getColorArray()); + _geometry->setColorBinding(osg::Geometry::BIND_OVERALL); + _geometry->setNormalBinding(osg::Geometry::BIND_OFF); + return _geode.get(); + } +}; + +class SurfaceBin : public PrimitiveBin +{ + private: + struct Ref + { + osg::Vec2 texCoord; + osg::Vec2 texCoord1; + osg::Vec2 texCoord2; + unsigned index; + }; + std::vector _refs; + + struct TriangleData + { + VertexIndex index[3]; + }; + std::vector _triangles; + + std::vector > _trianglestrips; + //std::vector _trianglestrip; + + struct QuadData + { + VertexIndex index[4]; + }; + + std::vector _quads; + + struct PolygonData + { + std::vector index; + }; + + std::vector _polygons; + std::vector _toTessellatePolygons; + + public: + SurfaceBin(unsigned flags, VertexSet *vertexSet) : + PrimitiveBin(flags, vertexSet) + {} + + virtual bool beginPrimitive(unsigned nRefs) + { + _refs.reserve(nRefs); + _refs.clear(); + + // Check if we have enough for a line or someting broken ... + if (nRefs < 3) + { + osg::notify(osg::WARN) << "osgDB TORCS reader: detected surface with less than 3 vertices!" << std::endl; + return false; + } + return true; + } + + virtual bool vertex(unsigned vertexIndex, const osg::Vec2& texCoord, const osg::Vec2& texCoord1, const osg::Vec2& texCoord2) + { + Ref ref; + ref.index = vertexIndex; + ref.texCoord = texCoord; + ref.texCoord1 = texCoord1; + ref.texCoord2 = texCoord2; + _refs.push_back(ref); + return true; + } + + virtual bool endPrimitive() + { + unsigned nRefs = _refs.size(); + + // Compute the normal times the enclosed area. + // During that check if the surface is convex. If so, put in the surface as such. + bool needTessellation = true; + osg::Vec3 prevEdgeNormal; + osg::Vec3 weightedNormal(0, 0, 0); + osg::Vec3 v0 = _vertexSet->getVertex(_refs[0].index); + + for (unsigned i = 2; i < nRefs; ++i) + { + osg::Vec3 side1 = _vertexSet->getVertex(_refs[i-1].index) - v0; + osg::Vec3 side2 = _vertexSet->getVertex(_refs[i].index) - v0; + osg::Vec3 newNormal = side1^side2; + if (!needTessellation) + { + if (3 < nRefs && newNormal*weightedNormal < 0) + { + needTessellation = true; + } + if (i < 3) + { + prevEdgeNormal = newNormal; + } + else // if (3 <= i) // due to the for loop + { + osg::Vec3 sideim1 = _vertexSet->getVertex(_refs[i-1].index) - _vertexSet->getVertex(_refs[i-2].index); + osg::Vec3 sidei = _vertexSet->getVertex(_refs[i].index) - _vertexSet->getVertex(_refs[i-2].index); + osg::Vec3 edgeNormal = sideim1^sidei; + if (edgeNormal*prevEdgeNormal < 0) + { + needTessellation = true; + } + prevEdgeNormal = edgeNormal; + } + } + + weightedNormal += newNormal; + } + + if (needTessellation) + { + if (isTriangleStrip()) + { + int index = _trianglestrips.size(); + _trianglestrips.resize(index+1); + for (unsigned i = 0; i < nRefs; ++i) + { + RefData refData(_refs[i].texCoord,_refs[i].texCoord1,_refs[i].texCoord2); + VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); + _trianglestrips[index].push_back( vertexIndex ); + } + } + else if (isTriangleFan()) + { + //Convert fan to triangles + int i = 0; + int tricount=nRefs-2; + + RefData refData(_refs[i].texCoord,_refs[i].texCoord1,_refs[i].texCoord2); + VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); + i++; + + while (iaddRefData(_refs[i].index, refData1); + + RefData refData2(_refs[i].texCoord,_refs[i].texCoord1,_refs[i].texCoord2); + VertexIndex vertexIndex2 = _vertexSet->addRefData(_refs[i+1].index, refData2); + + tri.index[0] = vertexIndex; + tri.index[1] = vertexIndex1; + tri.index[2] = vertexIndex2; + + if ((tri.index[0].vertexIndex!=tri.index[1].vertexIndex)&&(tri.index[1].vertexIndex!=tri.index[2].vertexIndex)&&(tri.index[0].vertexIndex!=tri.index[2].vertexIndex)) + _triangles.push_back(tri); + + i++; + } + } + else + { + unsigned polygonIndex = _toTessellatePolygons.size(); + _toTessellatePolygons.resize(polygonIndex + 1); + for (unsigned i = 0; i < nRefs; ++i) + { + RefData refData(_refs[i].texCoord,_refs[i].texCoord1,_refs[i].texCoord2); + VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); + _toTessellatePolygons[polygonIndex].index.push_back(vertexIndex); + } + } + } + else if (nRefs == 3) + { + unsigned triangleIndex = _triangles.size(); + _triangles.resize(triangleIndex + 1); + for (unsigned i = 0; i < 3; ++i) + { + RefData refData(_refs[i].texCoord,_refs[i].texCoord1,_refs[i].texCoord2); + VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); + _triangles[triangleIndex].index[i] = vertexIndex; + } + } + else if (nRefs == 4) + { + unsigned quadIndex = _quads.size(); + _quads.resize(quadIndex + 1); + for (unsigned i = 0; i < 4; ++i) + { + RefData refData(_refs[i].texCoord,_refs[i].texCoord1,_refs[i].texCoord2); + VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); + _quads[quadIndex].index[i] = vertexIndex; + } + } + else + { + unsigned polygonIndex = _polygons.size(); + _polygons.resize(polygonIndex + 1); + for (unsigned i = 0; i < nRefs; ++i) { + RefData refData(_refs[i].texCoord,_refs[i].texCoord1,_refs[i].texCoord2); + VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); + _polygons[polygonIndex].index.push_back(vertexIndex); + } + } + return true; + } + + void pushVertex(const VertexIndex& vertexIndex, osg::Vec3Array* vertexArray, + osg::Vec3Array* normalArray, osg::Vec2Array* texcoordArray, osg::Vec2Array* texcoordArray1, osg::Vec2Array* texcoordArray2) + { + vertexArray->push_back(_vertexSet->getVertex(vertexIndex)); + normalArray->push_back(_vertexSet->getNormal(vertexIndex)); + if (texcoordArray) + texcoordArray->push_back(_vertexSet->getTexCoord(vertexIndex)); + if (texcoordArray1) + texcoordArray1->push_back(_vertexSet->getTexCoord1(vertexIndex)); + if (texcoordArray2) + texcoordArray2->push_back(_vertexSet->getTexCoord2(vertexIndex)); + + } + + virtual osg::Geode* finalize(const MaterialData& material, const TextureData& textureData) + { + osg::StateSet* stateSet = _geode->getOrCreateStateSet(); + material.toStateSet(stateSet); + textureData.toTextureStateSet(stateSet); + stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON); + + // Single- or doublesided culling + if (isTwoSided()) + { + stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); + } else + { + osg::CullFace* cullFace = new osg::CullFace; + cullFace->setDataVariance(osg::Object::STATIC); + cullFace->setMode(osg::CullFace::BACK); + stateSet->setAttribute(cullFace); + stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON); + } + + // Flat or smooth shading + osg::ShadeModel* shadeModel = new osg::ShadeModel; + shadeModel->setDataVariance(osg::Object::STATIC); + shadeModel->setMode(osg::ShadeModel::SMOOTH); + stateSet->setAttribute(shadeModel); + + // Set up the arrays, allways store texture coords, may be we need them later ... + osg::Geometry* geometry = new osg::Geometry; + _geode->addDrawable(geometry); + geometry->setDataVariance(osg::Object::STATIC); + geometry->setColorArray(material.getColorArray()); + geometry->setColorBinding(osg::Geometry::BIND_OVERALL); + geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + osg::Vec3Array* normalArray = new osg::Vec3Array; + normalArray->setDataVariance(osg::Object::STATIC); + geometry->setNormalArray(normalArray); + osg::Vec3Array* vertexArray = new osg::Vec3Array; + vertexArray->setDataVariance(osg::Object::STATIC); + geometry->setVertexArray(vertexArray); + osg::Vec2Array* texcoordArray = 0; + osg::Vec2Array* texcoordArray1 = 0; + osg::Vec2Array* texcoordArray2 = 0; + + if (textureData.valid()) + { + texcoordArray = new osg::Vec2Array; + texcoordArray->setDataVariance(osg::Object::STATIC); + geometry->setTexCoordArray(0, texcoordArray); + + texcoordArray1 = new osg::Vec2Array; + texcoordArray1->setDataVariance(osg::Object::STATIC); + geometry->setTexCoordArray(1, texcoordArray1); + } + + // At first handle the the polygons to tessellate, fix them and append the other polygons later + if (!_toTessellatePolygons.empty()) + { + unsigned start = vertexArray->size(); + osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON, start); + drawArrayLengths->reserve(_toTessellatePolygons.size()); + for (unsigned i = 0; i < _toTessellatePolygons.size(); ++i) + { + for (unsigned j = 0; j < _toTessellatePolygons[i].index.size(); ++j) + { + pushVertex(_toTessellatePolygons[i].index[j], vertexArray, normalArray, texcoordArray, texcoordArray1, texcoordArray2); + } + drawArrayLengths->push_back(_toTessellatePolygons[i].index.size()); + } + geometry->addPrimitiveSet(drawArrayLengths); + osgUtil::Tessellator Tessellator; + Tessellator.retessellatePolygons(*geometry); + } + + // handle triangles + if (!_triangles.empty()) + { + unsigned start = vertexArray->size(); + for (unsigned i = 0; i < _triangles.size(); ++i) + { + for (unsigned j = 0; j < 3; ++j) + { + pushVertex(_triangles[i].index[j], vertexArray, normalArray, texcoordArray, texcoordArray1, texcoordArray2); + } + } + osg::DrawArrays* drawArray = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, start, 3*_triangles.size()); + geometry->addPrimitiveSet(drawArray); + } + + // handle quads + if (!_quads.empty()) + { + unsigned start = vertexArray->size(); + for (unsigned i = 0; i < _quads.size(); ++i) + { + for (unsigned j = 0; j < 4; ++j) + { + pushVertex(_quads[i].index[j], vertexArray, normalArray, texcoordArray, texcoordArray1, texcoordArray2); + } + } + osg::DrawArrays* drawArray = new osg::DrawArrays(osg::PrimitiveSet::QUADS, start, 4*_quads.size()); + geometry->addPrimitiveSet(drawArray); + } + + // handle polygons + if (!_polygons.empty()) + { + unsigned start = vertexArray->size(); + osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON, start); + drawArrayLengths->reserve(_polygons.size()); + + for (unsigned i = 0; i < _polygons.size(); ++i) + { + for (unsigned j = 0; j < _polygons[i].index.size(); ++j) + { + pushVertex(_polygons[i].index[j], vertexArray, normalArray, texcoordArray, texcoordArray1, texcoordArray2); + } + drawArrayLengths->push_back(_polygons[i].index.size()); + } + geometry->addPrimitiveSet(drawArrayLengths); + } + + //handle triangle strips + if (!_trianglestrips.empty()) + { + for (unsigned j=0;j<_trianglestrips.size();j++) + { + unsigned start = vertexArray->size(); + for (unsigned i = 0; i < _trianglestrips[j].size(); ++i) + { + pushVertex(_trianglestrips[j][i], vertexArray, normalArray, texcoordArray, texcoordArray1, texcoordArray2); + } + + osg::DrawArrays* drawArray = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, start, _trianglestrips[j].size()); + geometry->addPrimitiveSet(drawArray); + } + } + + osgUtil::SmoothingVisitor v; + v.smooth(*geometry); + return _geode.get(); + } +}; + +struct Bins +{ + PrimitiveBin* getOrCreatePrimitiveBin(unsigned flags, VertexSet* vertexSet) + { + if ((flags & ac3d::SurfaceTypeLineLoop) || (flags & ac3d::SurfaceTypeLineStrip)) + { + if (!lineBin.valid()) + { + lineBin = new LineBin(flags, vertexSet); + } + return lineBin.get(); + } + else if (flags & ac3d::SurfaceShaded) + { + if (flags & ac3d::SurfaceTwoSided) + { + if (!smoothDoubleSurfaceBin.valid()) + { + smoothDoubleSurfaceBin = new SurfaceBin(flags, vertexSet); + } + return smoothDoubleSurfaceBin.get(); + } + else + { + if (!smoothSingleSurfaceBin.valid()) + { + smoothSingleSurfaceBin = new SurfaceBin(flags, vertexSet); + } + return smoothSingleSurfaceBin.get(); + } + } + else + { + if (flags & ac3d::SurfaceTwoSided) + { + if (!flatDoubleSurfaceBin.valid()) + { + flatDoubleSurfaceBin = new SurfaceBin(flags, vertexSet); + } + return flatDoubleSurfaceBin.get(); + } + else + { + if (!flatSingleSurfaceBin.valid()) + { + flatSingleSurfaceBin = new SurfaceBin(flags, vertexSet); + } + return flatSingleSurfaceBin.get(); + } + } + } + + void finalize(osg::Group* group, const MaterialData& material, const TextureData& textureData) + { + if (lineBin.valid()) + { + group->addChild(lineBin->finalize(material, textureData)); + } + if (smoothDoubleSurfaceBin.valid()) + { + group->addChild(smoothDoubleSurfaceBin->finalize(material, textureData)); + } + if (smoothSingleSurfaceBin.valid()) + { + osg::Geode *pGeode = smoothSingleSurfaceBin->finalize(material, textureData); + group->addChild(pGeode); + } + if (flatDoubleSurfaceBin.valid()) + { + group->addChild(flatDoubleSurfaceBin->finalize(material, textureData)); + } + if (flatSingleSurfaceBin.valid()) + { + group->addChild(flatSingleSurfaceBin->finalize(material, textureData)); + } + } + +private: + osg::ref_ptr lineBin; + osg::ref_ptr flatDoubleSurfaceBin; + osg::ref_ptr flatSingleSurfaceBin; + osg::ref_ptr smoothDoubleSurfaceBin; + osg::ref_ptr smoothSingleSurfaceBin; +}; + +class ReaderWriterACC : public osgDB::ReaderWriter +{ + public: + ReaderWriterACC(); + virtual const char* className(); + virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& file,const Options* options); + virtual osgDB::ReaderWriter::ReadResult readNode(std::istream& fin, const Options* options); + virtual osgDB::ReaderWriter::WriteResult writeNode(const osg::Node& node,const std::string& fileName, const Options* /*options*/); + virtual osgDB::ReaderWriter::WriteResult writeNode(const osg::Node& node,std::ostream& fout, const Options* opts); + void SetCar(bool b); + osg::Node* readFile(std::istream& stream, const osgDB::ReaderWriter::Options* options); + osg::Node* readObject(std::istream& stream, FileData& fileData, const osg::Matrix& parentTransform, TextureData textureData); + + protected: + //Used for cars + osg::Group *m_transparentGroup; + osg::Group *m_opaqueGroup; + bool m_bCar; + bool m_bBlockTransparent; +}; + diff --git a/src/modules/graphic/osggraph/osggraph.cpp b/src/modules/graphic/osggraph/osggraph.cpp index 16c59b4ed..9007b1d98 100644 --- a/src/modules/graphic/osggraph/osggraph.cpp +++ b/src/modules/graphic/osggraph/osggraph.cpp @@ -1,10 +1,10 @@ /*************************************************************************** - file : osggraph.cpp + file : osggraph.cpp created : Thu Aug 17 23:19:19 CEST 2000 - copyright : (C) 2012 by Xavier Bertaux - email : torcs@free.fr - version : $Id: osggraph.cpp 3741 2011-07-21 22:29:34Z pouillot $ + copyright : (C) 2012 by Xavier Bertaux + email : bertauxx@yahoo.fr + version : $Id: osggraph.cpp 3741 2011-07-21 22:29:34Z torcs-ng $ ***************************************************************************/ @@ -19,7 +19,7 @@ #include "osggraph.h" -#include "osgMain.h" +#include "OsgMain.h" //#include "grsound.h" //#include "grtexture.h" @@ -85,24 +85,24 @@ OsgGraph::~OsgGraph() bool OsgGraph::loadTrack(tTrack* pTrack) { //GfLogDebug("SsgGraph::loadTrack\n"); - return ::initTrack(pTrack) == 0; + //return ::initTrack(pTrack) == 0; } bool OsgGraph::loadCars(tSituation* pSituation) { //GfLogDebug("SsgGraph::loadCars\n"); - return ::initCars(pSituation) == 0; + //return ::initCars(pSituation) == 0; } bool OsgGraph::setupView(int x, int y, int width, int height, void* pMenuScreen) { //GfLogDebug("SsgGraph::setupView\n"); - return ::initView(x, y, width, height, GR_VIEW_STD, pMenuScreen) == 0; + //return ::initView(x, y, width, height, GR_VIEW_STD, pMenuScreen) == 0; } void OsgGraph::redrawView(tSituation* pSituation) { - ::refresh(pSituation); + //::refresh(pSituation); } // void OsgGraph::bendCar(int index, sgVec3 poc, sgVec3 force, int count) @@ -113,25 +113,25 @@ void OsgGraph::redrawView(tSituation* pSituation) void OsgGraph::unloadCars() { //GfLogDebug("SsgGraph::unloadCars\n"); - ::shutdownCars(); + //::shutdownCars(); } void OsgGraph::unloadTrack() { //GfLogDebug("SsgGraph::unloadTrack\n"); - ::shutdownTrack(); + //::shutdownTrack(); } void OsgGraph::shutdownView() { //GfLogDebug("SsgGraph::shutdownView\n"); - ::shutdownView(); + //::shutdownView(); } // Implementation of ISoundEngine **************************************** SoundCam * OsgGraph::getCurCam() { - SoundCam *cam = new SoundCam; + /*SoundCam *cam = new SoundCam; osgCamera *gcam = osgGetCurCamera(); cam->Centerv = gcam->getCenterv(); @@ -139,5 +139,5 @@ SoundCam * OsgGraph::getCurCam() cam->Speedv = gcam->getSpeedv(); cam->Posv = gcam->getPosv(); - return cam; + return cam;*/ }