instead of osgDB::Registry where it original lay. This has been done to allow fileName strings to be encode data rather than just file names, such as one requires when using PagedLOD along with plugins for doing dynamic tesselation.
2203 lines
98 KiB
C++
2203 lines
98 KiB
C++
// GEO format (carbon graphics Inc) loader for the OSG real time scene graph
|
|
// www.carbongraphics.com for more information about the Geo animation+ modeller
|
|
// supports geometry and group & face level animations.
|
|
// Vertex level animation partly supported - defines movement (translate, rotate, colour)!
|
|
// Loader has been divided into two parts
|
|
// 1- general geometry (here) &
|
|
// 2- animation (see geoActions.cpp).
|
|
// ver 1.2 GWM Nov 2003
|
|
|
|
#include <string>
|
|
|
|
#include <osg/Image>
|
|
#include <osg/Group>
|
|
#include <osg/LOD>
|
|
#include <osg/Billboard>
|
|
#include <osg/Sequence>
|
|
#include <osg/Switch>
|
|
#include <osg/Geode>
|
|
#include <osg/Depth>
|
|
#include <osg/LineWidth>
|
|
#include <osg/Geometry>
|
|
#include <osg/MatrixTransform>
|
|
#include <osg/Material>
|
|
#include <osg/Notify>
|
|
#include <osg/Texture2D>
|
|
#include <osg/TexEnv>
|
|
#include <osg/StateSet>
|
|
#include <osg/CullFace>
|
|
#include <osg/Point>
|
|
#include "ClipRegion.h"
|
|
|
|
#include <osgSim/LightPointNode>
|
|
|
|
#include <osgDB/FileNameUtils>
|
|
#include <osgDB/FileUtils>
|
|
#include <osgDB/Registry>
|
|
#include <osgDB/ReadFile>
|
|
#include <osgDB/WriteFile>
|
|
#include <osgDB/Input>
|
|
#include <osgDB/Output>
|
|
#include <osgUtil/Tesselator>
|
|
|
|
#include <stdio.h>
|
|
|
|
// specific to GEO
|
|
|
|
#include "geoFormat.h"
|
|
#include "geoTypes.h"
|
|
#include "geoUnits.h"
|
|
#include "osgGeoAnimation.h"
|
|
#include "osgGeoStructs.h"
|
|
#include "osgGeoNodes.h"
|
|
#include "osgGeoAction.h"
|
|
#include <osgText/Text> // needed for text nodes
|
|
|
|
|
|
//
|
|
geoHeaderGeo::geoHeaderGeo()
|
|
{ // animations for the header - actually updates all control variables
|
|
intVars=new internalVars; useVars=new userVars;
|
|
extVars=new userVars;
|
|
_initialTick = _timer.tick();
|
|
color_palette=new colourPalette;
|
|
};
|
|
const geoValue *geoHeaderGeo::getGeoVar(const unsigned fid) const {
|
|
const geoValue *st=intVars->getGeoVar(fid);
|
|
if (!st) {
|
|
st=useVars->getGeoVar(fid);
|
|
if (!st) {
|
|
st=extVars->getGeoVar(fid);
|
|
}
|
|
}
|
|
return st;
|
|
}
|
|
double *geoHeaderGeo::getVar(const unsigned fid) const {
|
|
double *dv=NULL;
|
|
dv=intVars->getVar(fid);
|
|
if (!dv) {
|
|
dv=useVars->getVar(fid);
|
|
if (!dv) {
|
|
dv=extVars->getVar(fid);
|
|
}
|
|
}
|
|
return dv;
|
|
}
|
|
void geoHeaderGeo::addUserVar(const georecord &gr)
|
|
{ // this georecord defines a single variable of type<>
|
|
useVars->addUserVar(gr);
|
|
}
|
|
//== handler for updating internal variables
|
|
void geoHeaderGeo::update(const osg::FrameStamp *_frameStamp)
|
|
{ // update the scene
|
|
osg::Timer_t _frameTick = _timer.tick();
|
|
_lastFrameTick=_frameTick;
|
|
|
|
double time = _frameStamp->getReferenceTime();
|
|
intVars->update( _frameStamp);
|
|
moveit(time);
|
|
}
|
|
void geoHeaderGeo::moveit(const double t)
|
|
{ // all the local and external variables declared in the geo modeller are here available.
|
|
if (uvarupdate) {
|
|
std::vector<geoValue> *lvals=useVars->getvars();
|
|
for (std::vector<geoValue>::iterator itr=lvals->begin();
|
|
itr!=lvals->end();
|
|
++itr) {// for each user var
|
|
double vv=uvarupdate(t, itr->getVal(), itr->getName());
|
|
// std::cout << " updatee " << itr->getName() << " " << vv << " " << itr->getVar() << std::endl;
|
|
itr->setVal(vv);
|
|
// vv=itr->getVal(); std::cout << " result " << itr->getName() << " " << vv << std::endl;
|
|
}
|
|
}
|
|
if (extvarupdate) {
|
|
std::vector<geoValue> *lvals=extVars->getvars();
|
|
for (std::vector<geoValue>::iterator itr=lvals->begin();
|
|
itr!=lvals->end();
|
|
++itr) {// for each user var
|
|
itr->setVal(extvarupdate(t, itr->getVal(), itr->getName()));
|
|
}
|
|
}
|
|
}
|
|
|
|
class geoHeaderCB: public osg::NodeCallback {
|
|
public:
|
|
geoHeaderCB() {}
|
|
~geoHeaderCB() {}
|
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
|
{ // update action vars
|
|
geoHeaderGeo *gh=(geoHeaderGeo *)node;
|
|
gh->update(nv->getFrameStamp());
|
|
nv->setNodeMaskOverride(0xffffffff); // need to make the visitor override the nodemask
|
|
// so that it visits 'invisible' nodes to update visibility. Or could use
|
|
// a visitor with setTraversalMode(TraversalMode==TRAVERSE_ALL_CHILDREN)?
|
|
traverse(node,nv);
|
|
// std::cout<<"update callback - post traverse"<< (float)_frameStamp->getReferenceTime() <<std::endl;
|
|
}
|
|
private:
|
|
};
|
|
|
|
|
|
//=============
|
|
|
|
class vertexInfo { // holds vertex information for an entire osg::geometry
|
|
public:
|
|
vertexInfo() {
|
|
norms=new osg::Vec3Array;
|
|
coords=new osg::Vec3Array;
|
|
txcoords=new osg::Vec2Array;
|
|
colorindices=new osg::IntArray;
|
|
coordindices=new osg::IntArray;
|
|
normindices=new osg::IntArray;
|
|
txindices=new osg::IntArray;
|
|
colors=new osg::Vec4Array;
|
|
cpool=NULL; npool=NULL;
|
|
polycols= new osg::Vec4Array; // polygon colours
|
|
}
|
|
typedef std::vector<geoActionBehaviour *> drBehList;
|
|
void setPools(const std::vector<osg::Vec3> *coord_pool, const std::vector<osg::Vec3> *normal_pool) {
|
|
cpool=coord_pool; npool=normal_pool;
|
|
}
|
|
inline bool hasVertexActions(void) const { return !(BehList.empty()); }
|
|
inline osg::Vec4Array *getColors() const { return colors;}
|
|
inline osg::Vec3Array *getNorms() const { return norms;}
|
|
inline osg::Vec3Array *getCoords() const { return coords;}
|
|
inline osg::Vec2Array *getTexCoords() const { return txcoords;}
|
|
inline osg::IntArray *getColorIndices() const { return colorindices;}
|
|
inline osg::IntArray *getCoordIndices() const { return coordindices;}
|
|
inline osg::IntArray *getNormIndices() const { return normindices;}
|
|
inline osg::IntArray *getTextureIndices() const { return txindices;}
|
|
void addPolcolour( osg::Vec4 cl) { polycols->push_back(cl);}
|
|
osg::Vec4Array *getPolcolours() const { return polycols;}
|
|
void addVertexActions(geoBehaviourDrawableCB *gcb) const { // add the actions to callback
|
|
if ( !(BehList.empty()) ) {
|
|
for (drBehList::const_iterator rcitr=BehList.begin();
|
|
rcitr!=BehList.end();
|
|
++rcitr)
|
|
{
|
|
gcb->addBehaviour(*rcitr);
|
|
}
|
|
}
|
|
}
|
|
bool addFlat( const georecord *gface)
|
|
{ // this must only be called with a vertex georecord.
|
|
bool isflat=false;
|
|
const geoField *gfshade=gface->getField(GEO_DB_POLY_SHADEMODEL); // shaded gouraud, flat...
|
|
int shademodel=gfshade ? gfshade->getInt() : -1;
|
|
if (shademodel==GEO_POLY_SHADEMODEL_LIT) { // flat shaded - need the index
|
|
const geoField *gfd=gface->getField(GEO_DB_POLY_NORMAL);
|
|
if (gfd) {
|
|
float *normal= (gfd) ? (gfd->getVec3Arr()):NULL;
|
|
osg::Vec3 nrm(normal[0], normal[1], normal[2]);
|
|
norms->push_back(nrm);
|
|
isflat=true;
|
|
}
|
|
}
|
|
return isflat;
|
|
}
|
|
bool addIndices(georecord *gr, const geoHeaderGeo *ghdr, const float cdef[4], const georecord *gface)
|
|
{ // this must only be called with a vertex georecord.
|
|
// gr is tha vertex; gface is the face containing the vertex
|
|
bool hbeh=false; // true if this vertex has a behaviour
|
|
if (gr->getType()==DB_DSK_VERTEX) {
|
|
const geoField *gfshade=gface->getField(GEO_DB_POLY_SHADEMODEL); // shaded gouraud, flat...
|
|
int shademodel=gfshade ? gfshade->getInt() : -1;
|
|
if (shademodel!=GEO_POLY_SHADEMODEL_LIT && shademodel!=GEO_POLY_SHADEMODEL_FLAT) {
|
|
const geoField *gfd=gr->getField(GEO_DB_VRTX_NORMAL);
|
|
if (gfd->getType()==DB_UINT) {
|
|
if (gfd) {
|
|
unsigned int idx=gfd->getUInt();
|
|
normindices->push_back(idx);
|
|
norms->push_back((*npool)[idx]);
|
|
} else {
|
|
osg::notify(osg::WARN) << "No valid vertex index" << std::endl;
|
|
}
|
|
} else if (gfd->getType()==DB_VEC3F) {
|
|
float *p=gfd->getVec3Arr();
|
|
osg::Vec3 nrm;
|
|
nrm.set(p[0],p[1],p[2]);
|
|
norms->push_back(nrm);
|
|
}
|
|
}
|
|
const geoField *gfd=gr->getField(GEO_DB_VRTX_COORD);
|
|
osg::Vec3 pos;
|
|
if (gfd->getType()==DB_INT) {
|
|
if (gfd) {
|
|
int idx=gfd->getInt();
|
|
pos=(*cpool)[idx];
|
|
coords->push_back((*cpool)[idx]); //osg::Vec3(cpool[3*idx],cpool[3*idx+1],cpool[3*idx+2]));
|
|
coordindices->push_back(coords->size());
|
|
} else {
|
|
osg::notify(osg::WARN) << "No valid vertex index" << std::endl;
|
|
}
|
|
} else if (gfd->getType()==DB_VEC3F) {
|
|
float *p=gfd->getVec3Arr();
|
|
pos.set(p[0],p[1],p[2]);
|
|
coords->push_back(pos); //osg::Vec3(cpool[3*idx],cpool[3*idx+1],cpool[3*idx+2]));
|
|
}
|
|
std::vector< georecord *>bhv=gr->getBehaviour(); // behaviours for vertices, eg tranlate, colour!
|
|
if (!bhv.empty()) {
|
|
int ncoord=coords->size();
|
|
for (std::vector< georecord *>::const_iterator rcitr=bhv.begin();
|
|
rcitr!=bhv.end();
|
|
++rcitr)
|
|
{
|
|
if ((*rcitr)->getType()==DB_DSK_TRANSLATE_ACTION) {
|
|
geoMoveVertexBehaviour *mb=new geoMoveVertexBehaviour;
|
|
mb->makeBehave((*rcitr),ghdr);
|
|
mb->setpos(pos);
|
|
mb->setindx(ncoord-1);
|
|
BehList.push_back(mb);
|
|
}
|
|
if ((*rcitr)->getType()==DB_DSK_ROTATE_ACTION) {
|
|
geoMoveVertexBehaviour *mb=new geoMoveVertexBehaviour;
|
|
mb->makeBehave((*rcitr),ghdr);
|
|
mb->setpos(pos);
|
|
mb->setindx(ncoord-1);
|
|
BehList.push_back(mb);
|
|
}
|
|
if ((*rcitr)->getType()==DB_DSK_COLOR_RAMP_ACTION) {
|
|
const geoField *gfd=gface->getField(GEO_DB_POLY_USE_MATERIAL_DIFFUSE); // true: use material...
|
|
bool usemat= gfd ? gfd->getBool() : false;
|
|
if (!usemat) { // modify the per vertex colours
|
|
gfd=gface->getField(GEO_DB_POLY_SHADEMODEL); // shaded gouraud, flat...
|
|
int shademodel=gfd ? gfd->getInt() : GEO_POLY_SHADEMODEL_LIT_GOURAUD;
|
|
gfd=gface->getField(GEO_DB_POLY_USE_VERTEX_COLORS); // true: use material...
|
|
bool usevert=gfd ? gfd->getBool() : false;
|
|
if (usevert || shademodel==GEO_POLY_SHADEMODEL_GOURAUD) { // then the vertex colours are used
|
|
geoColourBehaviour *cb=new geoColourBehaviour;
|
|
cb->setColorPalette(ghdr->getColorPalette());
|
|
cb->setVertIndices(ncoord-1,1); // part of colours array to be modified
|
|
bool ok=cb->makeBehave((*rcitr), ghdr);
|
|
if (ok) BehList.push_back(cb);
|
|
} // if the model does not use vertex colours... there can be no colour animation at vertex level
|
|
}
|
|
}
|
|
}
|
|
hbeh=true;
|
|
}
|
|
txindices->push_back(txcoords->size());
|
|
float *uvc=NULL;
|
|
gfd=gr->getField(GEO_DB_VRTX_UV_SET_0);
|
|
if (gfd) {
|
|
uvc=(float *)gfd->getstore(0);
|
|
|
|
if (uvc) { // then there are tx coords
|
|
osg::Vec2 uv(uvc[0], uvc[1]);
|
|
txcoords->push_back(uv);
|
|
} else {
|
|
txcoords->push_back(osg::Vec2(0,0));
|
|
}
|
|
} else {
|
|
txcoords->push_back(osg::Vec2(0,0));
|
|
}
|
|
gfd=gr->getField(GEO_DB_VRTX_PACKED_COLOR);
|
|
if (gfd) {
|
|
unsigned char *cp=gfd->getUCh4Arr();
|
|
float red=cp[0]/255.0f;
|
|
float green=cp[1]/255.0f;
|
|
float blue=cp[2]/255.0f;
|
|
// may need alpha in future:: float alpha=cp[3]/255.0f;
|
|
colors->push_back(Vec4(red,green,blue,1.0));
|
|
} else { // look for a colour index (exclusive!)
|
|
gfd=gr->getField(GEO_DB_VRTX_COLOR_INDEX);
|
|
if (gfd) {
|
|
uint icp=gfd->getInt();
|
|
if (icp<128*(ghdr->getColorPalette())->size()) {
|
|
float col[4];
|
|
ghdr->getPalette(icp,col);
|
|
colors->push_back(Vec4(col[0],col[1],col[2],1.0));
|
|
} else {
|
|
colors->push_back(Vec4(cdef[0],cdef[1],cdef[2],cdef[3]));
|
|
}
|
|
} else {
|
|
colors->push_back(Vec4(cdef[0],cdef[1],cdef[2],cdef[3]));
|
|
}
|
|
int idx=colors->size()-1;
|
|
colorindices->push_back(idx);
|
|
}
|
|
}
|
|
return hbeh;
|
|
}
|
|
friend inline std::ostream& operator << (std::ostream& output, const vertexInfo& vf)
|
|
{
|
|
const osg::Vec2Array *txa=vf.getTexCoords();
|
|
osg::IntArray *normindices=vf.getNormIndices();
|
|
osg::IntArray *txind = vf.getTextureIndices();
|
|
output << " vertexinfo " << txa->size() << " nrm: " << normindices->size()<<
|
|
" txinds " << txind->size()<<std::endl;
|
|
uint i;
|
|
for (i=0; i< txa->size(); i++) {
|
|
const osg::Vec2 uvt=(*txa)[i];
|
|
output << " U " << uvt.x() << " v " << uvt.y() << std::endl;
|
|
}
|
|
for (i=0; i<normindices->size(); i++) {
|
|
output << "Nind " << i << " = " << (*normindices)[i] << std::endl;
|
|
}
|
|
return output; // to enable cascading, monkey copy from osg\plane or \quat, Ubyte4, vec2,3,4,...
|
|
}
|
|
private:
|
|
const std::vector<osg::Vec3> *cpool; // passed in from the geo file
|
|
const std::vector<osg::Vec3> *npool;
|
|
osg::Vec3Array *norms;
|
|
osg::Vec3Array *coords;
|
|
osg::Vec2Array *txcoords;
|
|
osg::Vec4Array *colors;
|
|
osg::IntArray *colorindices;
|
|
osg::IntArray *coordindices;
|
|
osg::IntArray *normindices;
|
|
osg::IntArray *txindices;
|
|
drBehList BehList;
|
|
Vec4Array *polycols;
|
|
};
|
|
|
|
class geoInfo { // identifies properties required to make a new Geometry, and holds collection of vertices, indices, etc
|
|
public:
|
|
geoInfo(const int txidx=-2, const int sm=1, const int bs=1) { texture=txidx; // will be -1 or 0-number of textures
|
|
geom=NULL; nstart=0; linewidth=1;
|
|
bothsides=bs; shademodel=sm;
|
|
}
|
|
virtual ~geoInfo() { };
|
|
inline int getShademodel(void) const { return shademodel;}
|
|
inline int getBothsides(void) const { return bothsides;}
|
|
inline int getTexture(void) const { return texture;}
|
|
inline vertexInfo *getVinf(void) { return &vinf;}
|
|
void setPools(const std::vector<osg::Vec3> *coord_pool, const std::vector<osg::Vec3> *normal_pool) {
|
|
vinf.setPools(coord_pool,normal_pool);
|
|
}
|
|
float getlinewidth(void) const { return linewidth;}
|
|
void setlineWidth(const int w) { linewidth=w;}
|
|
void setGeom(osg::Geometry *nugeom) { geom=nugeom;}
|
|
osg::Geometry *getGeom() { return geom.get();}
|
|
uint getStart(uint nv) { uint ns=nstart; nstart+=nv; return ns; }
|
|
bool operator == (const geoInfo *gt) { // compare two geoInfos for same type of geometry
|
|
if (gt->texture!=texture) return false;
|
|
if (gt->bothsides == !bothsides) return false;
|
|
if (gt->shademodel!=shademodel) return false;
|
|
// other tests if failed return false
|
|
return true;
|
|
}
|
|
private:
|
|
int texture; // texture index
|
|
int bothsides; // none, back,front
|
|
int shademodel;
|
|
int linewidth;
|
|
vertexInfo vinf;
|
|
uint nstart; // start vertex for a primitive
|
|
osg::ref_ptr<osg::Geometry> geom; // the geometry created for this vinf and texture
|
|
};
|
|
|
|
|
|
class ReaderWriterGEO : public osgDB::ReaderWriter
|
|
{
|
|
public:
|
|
virtual const char* className() { return "GEO Reader/Writer"; }
|
|
|
|
virtual bool acceptsExtension(const std::string& extension)
|
|
{
|
|
return osgDB::equalCaseInsensitive(extension,"gem") || osgDB::equalCaseInsensitive(extension,"geo");
|
|
}
|
|
|
|
virtual ReadResult readObject(const std::string& fileName, const Options* opt) { return readNode(fileName,opt); }
|
|
|
|
virtual ReadResult readNode(const std::string& file, const Options*)
|
|
{
|
|
std::string ext = osgDB::getLowerCaseFileExtension(file);
|
|
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
|
|
|
|
std::string fileName = osgDB::findDataFile( file );
|
|
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
|
|
|
|
std::ifstream fin(fileName.c_str(), std::ios::binary | std::ios::in );
|
|
if (fin.is_open() )
|
|
{ // read the input file.
|
|
typedef std::vector<osg::Node*> NodeList;
|
|
NodeList nodeList;
|
|
osg::Material *mt=new osg::Material;
|
|
matlist.push_back(mt);
|
|
theHeader=NULL;
|
|
|
|
// load all nodes in file, placing them in a linear list corresponding to the on disk file.
|
|
while(!fin.eof())
|
|
{
|
|
georecord gr;
|
|
gr.readfile(fin);
|
|
// osg::notify(osg::WARN) << "end of record " << (int)gr.getType() << std::endl;
|
|
if (gr.getType() == DB_DSK_NORMAL_POOL) {
|
|
geoField *gfff=gr.getModField(GEO_DB_NORMAL_POOL_VALUES);
|
|
gfff->uncompress();// uncompress the normals
|
|
}
|
|
recs.push_back(gr); // add to a list of all records
|
|
}
|
|
fin.close();
|
|
// now sort the records so that any record followed by a PUSh has a child set = next record, etc
|
|
std::vector<georecord *> sorted=sort(recs); // tree-list of sorted record pointers
|
|
#ifdef _DEBUG
|
|
osgDB::Output fout("georex.txt"); //, std::ios_base::out );
|
|
// fout << "Debug raw file " << fileName << std::endl;
|
|
// output(fout,recs);
|
|
fout << "Debug Sorted file " << fileName << std::endl;
|
|
output(fout,sorted);
|
|
fout.close();
|
|
#endif /**/
|
|
makeHeader(*(sorted.begin()));
|
|
|
|
nodeList=makeosg(sorted); // make a list of osg nodes
|
|
geotxlist.clear();
|
|
geomatlist.clear();
|
|
txlist.clear();
|
|
txenvlist.clear();
|
|
matlist.clear();/* */
|
|
coord_pool.clear();
|
|
normal_pool.clear();
|
|
osg::Node * groupnode = NULL;
|
|
if (nodeList.empty())
|
|
{
|
|
return ReadResult("No data loaded from "+fileName);
|
|
}
|
|
else if (nodeList.size()==1)
|
|
{
|
|
groupnode = nodeList.front();
|
|
}
|
|
else
|
|
{
|
|
osg::Group *group = new Group;
|
|
group->setName("import group");
|
|
for(NodeList::iterator itr=nodeList.begin();
|
|
itr!=nodeList.end();
|
|
++itr)
|
|
{
|
|
group->addChild(*itr);
|
|
}
|
|
groupnode=group;
|
|
}
|
|
(theHeader.get())->addChild(groupnode);
|
|
groupnode=theHeader.get();
|
|
#ifdef _DEBUG // output a .osg version
|
|
osgDB::writeNodeFile(*groupnode,"geoosg.osg");
|
|
#endif /**/
|
|
recs.clear();
|
|
return groupnode;
|
|
}
|
|
return 0L;
|
|
}
|
|
std::vector<georecord *> sort(geoRecordList &recs) { // return a tree-list of sorted record pointers
|
|
// which mirrors the original .geo file (containers hold push/pop blocks).
|
|
std::vector<georecord *> sorted;
|
|
class georecord *curparent=NULL;
|
|
for (geoRecordList::iterator itr=recs.begin();
|
|
itr!=recs.end();
|
|
++itr) {
|
|
const geoField *gfd;
|
|
// osg::notify(osg::WARN) << *itr << std::endl;
|
|
// now parse for push/pops and add to lists
|
|
|
|
switch ((*itr).getType()) {
|
|
case 101: // old header - not appropriate!
|
|
curparent= &(*itr);
|
|
sorted.push_back(&(*itr));
|
|
osg::notify(osg::WARN) << "Old version 2 header block found - possible error!" << std::endl;
|
|
break;
|
|
case DB_DSK_PUSH:
|
|
if (!(curparent->getchildren().empty())) {
|
|
curparent= curparent->getLastChild(); // itr-1;
|
|
} else {
|
|
//curparent=itr-1;
|
|
}
|
|
break;
|
|
case DB_DSK_POP:
|
|
if (curparent) curparent=curparent->getparent();
|
|
break;
|
|
case DB_DSK_HEADER: // attach to previous
|
|
curparent= &(*itr);
|
|
sorted.push_back(&(*itr));
|
|
cpalrec=NULL;
|
|
break;
|
|
case DB_DSK_INTERNAL_VARS: // attach to parent
|
|
case DB_DSK_LOCAL_VARS:
|
|
case DB_DSK_EXTERNAL_VARS:
|
|
(curparent)->addBehaviourRecord(&(*itr));
|
|
break;
|
|
case DB_DSK_FLOAT_VAR: // attach to parent
|
|
case DB_DSK_INT_VAR:
|
|
case DB_DSK_LONG_VAR:
|
|
case DB_DSK_DOUBLE_VAR:
|
|
case DB_DSK_BOOL_VAR:
|
|
case DB_DSK_FLOAT2_VAR:
|
|
case DB_DSK_FLOAT3_VAR:
|
|
case DB_DSK_FLOAT4_VAR:
|
|
// else if ((*itr).isVar():
|
|
(curparent)->addBehaviourRecord(&(*itr));
|
|
break;
|
|
case DB_DSK_TEXTURE: // attach to parent
|
|
geotxlist.push_back(&(*itr));
|
|
break;
|
|
case DB_DSK_MATERIAL: // attach to parent
|
|
geomatlist.push_back(&(*itr));
|
|
break;
|
|
case DB_DSK_VIEW: // not needed for Real Time
|
|
break;
|
|
case DB_DSK_COORD_POOL: // global - attach to readerwriterGEO class for whole model
|
|
gfd=itr->getField(GEO_DB_COORD_POOL_VALUES);
|
|
{
|
|
float *crds= (gfd) ? (gfd->getVec3Arr()):NULL;
|
|
uint nm=gfd->getNum();
|
|
for (uint i=0; i<nm; i++) {
|
|
coord_pool.push_back(Vec3(crds[i*3],crds[i*3+1],crds[i*3+2]));
|
|
}
|
|
}
|
|
break;
|
|
case DB_DSK_NORMAL_POOL: // global - attach to readerwriterGEO
|
|
gfd=itr->getField(GEO_DB_NORMAL_POOL_VALUES);
|
|
{
|
|
float *nrms= (gfd) ? (gfd->getVec3Arr()):NULL;
|
|
uint nm=gfd->getNum();
|
|
for (uint i=0; i<nm; i++) {
|
|
normal_pool.push_back(Vec3(nrms[i*3],nrms[i*3+1],nrms[i*3+2]));
|
|
}
|
|
}
|
|
break;
|
|
case DB_DSK_COLOR_PALETTE: // global - attach to readerwriterGEO
|
|
cpalrec=&(*itr);
|
|
break;
|
|
case DB_DSK_BEHAVIOR: // || (*itr).isAction() // attach to previous
|
|
case DB_DSK_CLAMP_ACTION:
|
|
case DB_DSK_RANGE_ACTION:
|
|
case DB_DSK_ROTATE_ACTION:
|
|
case DB_DSK_TRANSLATE_ACTION:
|
|
case DB_DSK_SCALE_ACTION:
|
|
case DB_DSK_ARITHMETIC_ACTION:
|
|
case DB_DSK_LOGIC_ACTION:
|
|
case DB_DSK_CONDITIONAL_ACTION:
|
|
case DB_DSK_LOOPING_ACTION:
|
|
case DB_DSK_COMPARE_ACTION:
|
|
case DB_DSK_VISIBILITY_ACTION:
|
|
case DB_DSK_STRING_CONTENT_ACTION:
|
|
case DB_DSK_COLOR_RAMP_ACTION:
|
|
case DB_DSK_LINEAR_ACTION:
|
|
case DB_DSK_TASK_ACTION:
|
|
case DB_DSK_PERIODIC_ACTION:
|
|
case DB_DSK_PERIODIC2_ACTION:
|
|
case DB_DSK_TRIG_ACTION:
|
|
case DB_DSK_DISCRETE_ACTION:
|
|
case DB_DSK_INVERSE_ACTION:
|
|
case DB_DSK_TRUNCATE_ACTION:
|
|
case DB_DSK_ABS_ACTION:
|
|
case DB_DSK_IF_THEN_ELSE_ACTION:
|
|
case DB_DSK_DCS_ACTION:
|
|
case DB_DSK_SQRT_ACTION: // an action
|
|
if (curparent->getType()==DB_DSK_HEADER)
|
|
curparent->addBehaviourRecord(&(*itr));
|
|
else {
|
|
class georecord *cp=curparent->getLastChild();
|
|
if (cp) cp->addBehaviourRecord(&(*itr));
|
|
}
|
|
break;
|
|
case DB_DSK_PERSPECTIVE_GRID_INFO: // Feb 2003 not sure what this is yet!
|
|
(curparent)->addchild(&(*itr));
|
|
break;
|
|
case DB_DSK_PLANE_TEXTURE_MAPPING_INFO: // not needed for real time
|
|
case DB_DSK_CYLINDER_TEXTURE_MAPPING_INFO: // not implemented in 1.0
|
|
case DB_DSK_SPHERE_TEXTURE_MAPPING_INFO: // not implemented in 1.0
|
|
case DB_DSK_GRID_TEXTURE_MAPPING_INFO: // not implemented in 1.0
|
|
(curparent->getLastChild())->addMappingRecord(&(*itr));
|
|
break;
|
|
default:
|
|
if (curparent) {
|
|
(*itr).setparent(curparent);
|
|
curparent->addchild(&(*itr));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return sorted;
|
|
}
|
|
void outputPrim(const georecord *grec, osgDB::Output &fout) { // output to file for debug
|
|
const std::vector<georecord *> gr=grec->getchildren();
|
|
if (gr.size()>0) {
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
fout << *(*itr) << std::endl;
|
|
}
|
|
}
|
|
}
|
|
/* bool allOneSided(const georecord *grec) {
|
|
bool one=false;
|
|
const std::vector<georecord *> gr=grec->getchildren();
|
|
if (gr.size()>0) {
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end() && !one;
|
|
++itr) {
|
|
if ((*itr)->getType()==DB_DSK_POLYGON) {
|
|
const geoField *gfd=(*itr)->getField(GEO_DB_POLY_DSTYLE);
|
|
if (gfd) {
|
|
int dstyle=gfd->getInt();
|
|
one=(dstyle==GEO_POLY_DSTYLE_SOLID_BOTH_SIDES);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return one;
|
|
}*/
|
|
osg::Geometry *makeNewGeometry(const georecord *grec, geoInfo &ginf, int imat) {
|
|
const int shademodel=ginf.getShademodel();
|
|
const int bothsides=ginf.getBothsides();
|
|
osg::Geometry *nug;
|
|
int txidx=ginf.getTexture();
|
|
nug=new osg::Geometry;
|
|
const vertexInfo *vinf=ginf.getVinf();
|
|
nug->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
|
nug->setVertexArray(vinf->getCoords());
|
|
StateSet *dstate=new StateSet;
|
|
if (bothsides==0) {
|
|
osg::CullFace *cf = new osg::CullFace; // to define non-default culling
|
|
cf->setMode(osg::CullFace::BACK);
|
|
dstate->setAttributeAndModes(cf,osg::StateAttribute::ON);
|
|
}
|
|
else if (bothsides==1) {
|
|
osg::CullFace *cf = new osg::CullFace; // to define non-default culling
|
|
cf->setMode(osg::CullFace::FRONT);
|
|
dstate->setAttributeAndModes(cf,osg::StateAttribute::ON);
|
|
}
|
|
else if (bothsides==2) {
|
|
osg::CullFace *cf = new osg::CullFace; // to define non-default culling
|
|
dstate->setAttributeAndModes(cf,osg::StateAttribute::OFF);
|
|
}
|
|
Point *pt=new Point;
|
|
pt->setSize(4);
|
|
dstate->setAttribute(pt);
|
|
if (txidx>=0 && (unsigned int)txidx<txlist.size()) {
|
|
dstate->setTextureAttribute(0, txenvlist[txidx] );
|
|
dstate->setTextureAttributeAndModes(0,txlist[txidx],osg::StateAttribute::ON);
|
|
const Image *txim=txlist[txidx]->getImage();
|
|
if (txim) {
|
|
GLint icm=txim->computeNumComponents(txim->getPixelFormat());
|
|
if (icm ==2 || icm==4) { // an alpha texture
|
|
dstate->setMode(GL_BLEND,StateAttribute::ON);
|
|
dstate->setRenderingHint(StateSet::TRANSPARENT_BIN);
|
|
}
|
|
}
|
|
}
|
|
if (imat<0 || imat>=(int)matlist.size()) imat=0;
|
|
const geoField *gfd=grec->getField(GEO_DB_POLY_USE_MATERIAL_DIFFUSE); // true: use material...
|
|
bool usemat= gfd ? gfd->getBool() : false;
|
|
if (!usemat) {
|
|
matlist[imat]->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
|
dstate->setMode(GL_COLOR_MATERIAL, osg::StateAttribute::ON);
|
|
}
|
|
dstate->setAttribute(matlist[imat]);
|
|
Vec4 col=matlist[imat]->getAmbient(Material::FRONT);
|
|
if (col[3]<0.99) {
|
|
dstate->setMode(GL_BLEND,StateAttribute::ON);
|
|
dstate->setRenderingHint(StateSet::TRANSPARENT_BIN);
|
|
}
|
|
|
|
if (shademodel==GEO_POLY_SHADEMODEL_LIT ||
|
|
shademodel==GEO_POLY_SHADEMODEL_LIT_GOURAUD) dstate->setMode( GL_LIGHTING, osg::StateAttribute::ON );
|
|
else
|
|
dstate->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
|
|
{ // reclaim the colours
|
|
gfd=grec->getField(GEO_DB_POLY_USE_MATERIAL_DIFFUSE); // true: use material...
|
|
bool usemat= gfd ? gfd->getBool() : false;
|
|
if (!usemat) { // get the per vertex colours OR per face colours.
|
|
gfd=grec->getField(GEO_DB_POLY_USE_VERTEX_COLORS); // true: use material...
|
|
bool usevert=gfd ? gfd->getBool() : false;
|
|
if (usevert || shademodel==GEO_POLY_SHADEMODEL_GOURAUD) {
|
|
Vec4Array *cls=vinf->getColors();
|
|
if (cls) {
|
|
nug->setColorArray(cls);
|
|
nug->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
|
}
|
|
} else {
|
|
if (shademodel==GEO_POLY_SHADEMODEL_LIT_GOURAUD) {
|
|
nug->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
|
} else if (shademodel==GEO_POLY_SHADEMODEL_LIT) {
|
|
nug->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
|
}
|
|
osg::Vec4Array *polycols=vinf->getPolcolours();
|
|
nug->setColorArray(polycols);
|
|
nug->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
|
|
}
|
|
}
|
|
}
|
|
osg::LineWidth *lw=new osg::LineWidth;
|
|
lw->setWidth(ginf.getlinewidth());
|
|
dstate->setAttributeAndModes(lw,osg::StateAttribute::ON);
|
|
nug->setStateSet( dstate );
|
|
ginf.setGeom(nug);
|
|
return nug;
|
|
}
|
|
int getprim(const georecord *grec, geoInfo &gi)
|
|
{ // fills vinf with txcoords = texture coordinates, txindex=txindex etc
|
|
// for one primitive (one tri, quad, pol, tristrip....
|
|
vertexInfo *vinf=gi.getVinf();
|
|
int nv=0;
|
|
const std::vector<georecord *> gr=grec->getchildren();
|
|
const geoField *gfd=grec->getField(GEO_DB_POLY_PACKED_COLOR); // the colour
|
|
float defcol[4]; // a default colour for vertices
|
|
defcol[0]=defcol[1]=defcol[2]=defcol[3]=1.0f;
|
|
if (gfd) {
|
|
unsigned char *cls=gfd->getUCh4Arr();
|
|
defcol[0]=cls[0]/255.0f;
|
|
defcol[1]=cls[1]/255.0f;
|
|
defcol[2]=cls[2]/255.0f;
|
|
defcol[3]=1.0f;
|
|
} else {
|
|
gfd=grec->getField(GEO_DB_POLY_COLOR_INDEX); // the colour
|
|
if (gfd) {
|
|
int icp= gfd ? gfd->getInt() : 0;
|
|
theHeader->getPalette(icp,defcol);
|
|
} else {
|
|
defcol[0]=defcol[1]=defcol[2]=defcol[3]=1.0f;
|
|
}
|
|
}
|
|
|
|
if (gr.size()>0) {
|
|
vinf->addFlat(grec); // for flat normal shading
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
vinf->addIndices((*itr), theHeader.get(), defcol, grec);
|
|
nv++;
|
|
}
|
|
}
|
|
return nv;
|
|
}
|
|
void outputGeode(georecord grec, osgDB::Output &fout) { //
|
|
const std::vector<georecord *> gr=grec.getchildren();
|
|
if (gr.size()>0) {
|
|
fout.moveIn();
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
fout.indent() << *(*itr) << std::endl;
|
|
if ((*itr)->getType()==DB_DSK_POLYGON) {
|
|
outputPrim((*itr),fout);
|
|
}
|
|
}
|
|
fout.moveOut();
|
|
}
|
|
}
|
|
osg::MatrixTransform *makeText(georecord *gr) { // make transform, geode & text
|
|
osg::MatrixTransform *numt=NULL;
|
|
std::string ttfPath("fonts/times.ttf");
|
|
// unused
|
|
//int gFontSize1=2;
|
|
osgText::Text *text= new osgText::Text;
|
|
text->setFont(ttfPath);
|
|
const geoField *gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
const char *name=gfd ? gfd->getChar() : "a text";
|
|
gfd=gr->getField(GEO_DB_TEXT_STRING);
|
|
const char *content=gfd ? gfd->getChar() : " ";
|
|
text->setText(std::string(content));
|
|
gfd=gr->getField(GEO_DB_TEXT_SCALE_X);
|
|
//const float scx=gfd ? gfd->getFloat() : 1.0f;
|
|
gfd=gr->getField(GEO_DB_TEXT_SCALE_Y);
|
|
//const float scy=gfd ? gfd->getFloat() : 1.0f;
|
|
gfd=gr->getField(GEO_DB_TEXT_JUSTIFICATION); // GEO_DB_TEXT_DIRECTION);
|
|
int tjus=gfd? gfd->getInt() : GEO_TEXT_LEFT_JUSTIFY;
|
|
switch(tjus) {
|
|
case GEO_TEXT_LEFT_JUSTIFY: text->setAlignment(osgText::Text::LEFT_BOTTOM); break;
|
|
case GEO_TEXT_CENTER_JUSTIFY: text->setAlignment(osgText::Text::CENTER_BOTTOM); break;
|
|
case GEO_TEXT_RIGHT_JUSTIFY: text->setAlignment(osgText::Text::RIGHT_BOTTOM); break;
|
|
}
|
|
gfd=gr->getField(GEO_DB_TEXT_PACKED_COLOR);
|
|
if (gfd) {
|
|
unsigned char *cp=gfd->getUCh4Arr();
|
|
float red=(float)cp[0]/255.0f;
|
|
float green=(float)cp[1]/255.0f;
|
|
float blue=(float)cp[2]/255.0f;
|
|
text->setColor(osg::Vec4(red,green,blue,1.0f));
|
|
} else { // lok for a colour index (exclusive!)
|
|
gfd=gr->getField(GEO_DB_TEXT_COLOR_INDEX);
|
|
if (gfd) {
|
|
int icp=gfd->getInt();
|
|
float col[4];
|
|
theHeader->getPalette(icp,col);
|
|
text->setColor(osg::Vec4(col[0],col[1],col[2],1.0));
|
|
}
|
|
}
|
|
osg::Geode *geod=new osg::Geode;
|
|
osg::StateSet *textState = new osg::StateSet();
|
|
textState->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
|
geod->setStateSet( textState );
|
|
numt=new osg::MatrixTransform;
|
|
numt->setName(name);
|
|
gfd=gr->getField(GEO_DB_TEXT_MATRIX);
|
|
if (gfd) {
|
|
float *fmat=gfd->getMat44Arr();
|
|
// text->setPosition(osg::Vec3(fmat[12],fmat[13],fmat[14]));
|
|
numt->setMatrix(Matrix(fmat));
|
|
}
|
|
numt->addChild(geod);
|
|
geod->addDrawable(text);
|
|
{
|
|
std::vector< georecord *>bhv=gr->getBehaviour();
|
|
if (!bhv.empty()) { // then check for a string content/colour.. action
|
|
bool ok=false;
|
|
geoBehaviourDrawableCB *gcb=new geoBehaviourDrawableCB;
|
|
text->setUpdateCallback(gcb);
|
|
for (std::vector< georecord *>::const_iterator rcitr=bhv.begin();
|
|
rcitr!=bhv.end();
|
|
++rcitr)
|
|
{
|
|
if ((*rcitr)->getType()==DB_DSK_STRING_CONTENT_ACTION) {
|
|
geoStrContentBehaviour *cb=new geoStrContentBehaviour;
|
|
gfd=(*rcitr)->getField(GEO_DB_STRING_CONTENT_ACTION_INPUT_VAR);
|
|
if (gfd) {
|
|
ok=cb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(cb);
|
|
else delete cb;
|
|
// ok=false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return numt;
|
|
}
|
|
void addPolyActions(std::vector< georecord *>bhv, geoInfo &gi , const uint nv) {
|
|
const vertexInfo *vinf=gi.getVinf();
|
|
const uint nstart=gi.getStart(nv);
|
|
if (hasColorAction(bhv) || vinf->hasVertexActions()) {
|
|
osg::Geometry *nugeom=gi.getGeom();
|
|
geoBehaviourDrawableCB *gcb=new geoBehaviourDrawableCB;
|
|
nugeom->setUpdateCallback(gcb);
|
|
nugeom->setUseDisplayList(false); // as we are updating arrays, cannot change colours
|
|
for (std::vector< georecord *>::const_iterator rcitr=bhv.begin();
|
|
rcitr!=bhv.end();
|
|
++rcitr)
|
|
{
|
|
if ((*rcitr)->getType()==DB_DSK_COLOR_RAMP_ACTION) {
|
|
geoColourBehaviour *cb=new geoColourBehaviour;
|
|
cb->setColorPalette(theHeader->getColorPalette());
|
|
if (nugeom->getColorBinding()==osg::Geometry::BIND_PER_VERTEX) {
|
|
cb->setVertIndices(nstart,nv); // part of colours array to be modified
|
|
} else if (nugeom->getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // per primitive
|
|
const uint nst=nugeom->getNumPrimitiveSets();
|
|
cb->setVertIndices(nst,1); // part of colours array to be modified
|
|
} else { // overall
|
|
cb->setVertIndices(0,1); // part of colours array to be modified
|
|
}
|
|
bool ok=cb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(cb);
|
|
else delete cb;
|
|
}
|
|
}
|
|
vinf->addVertexActions(gcb);
|
|
}
|
|
}
|
|
void makeLightPointNode(const georecord *grec, osgSim::LightPointNode *lpn) {
|
|
// light points.. require OSG professional license
|
|
// OR LGPL software.
|
|
const std::vector<georecord *> gr=grec->getchildren();
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr)
|
|
{
|
|
if ((*itr)->getType()==DB_DSK_VERTEX)
|
|
{ // light point vertices
|
|
const geoField *gfd=(*itr)->getField(GEO_DB_VRTX_COORD);
|
|
osg::Vec3 pos;
|
|
if (gfd->getType()==DB_INT) {
|
|
if (gfd) {
|
|
int idx=gfd->getInt();
|
|
pos=coord_pool[idx];
|
|
} else {
|
|
osg::notify(osg::WARN) << "No valid vertex index" << std::endl;
|
|
}
|
|
} else if (gfd->getType()==DB_VEC3F) {
|
|
float *p=gfd->getVec3Arr();
|
|
pos.set(p[0],p[1],p[2]);
|
|
}
|
|
gfd=(*itr)->getField(GEO_DB_VRTX_PACKED_COLOR);
|
|
if (gfd) {
|
|
unsigned char *cls=gfd->getUCh4Arr();
|
|
float red=cls[0]/255.0f;
|
|
float green=cls[1]/255.0f;
|
|
float blue=cls[2]/255.0f;
|
|
//float alpha=1.0f; // cls[3]*frac/255.0f;
|
|
osg::Vec4 colour(red,green,blue,1.0f);
|
|
lpn->addLightPoint(osgSim::LightPoint(true,pos,colour,1.0f,1.0f,0,0,osgSim::LightPoint::BLENDED));
|
|
} else { // get colour from palette
|
|
gfd=(*itr)->getField(GEO_DB_VRTX_COLOR_INDEX); // use color pool...
|
|
int icp= gfd ? gfd->getInt() : 0;
|
|
float col[4];
|
|
theHeader->getPalette(icp, col);
|
|
lpn->addLightPoint(osgSim::LightPoint(pos, osg::Vec4(col[0],col[1],col[2],1.0f)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void makeLightPointGeometry(const georecord *grec, Group *nug) {
|
|
const std::vector<georecord *> gr=grec->getchildren();
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr)
|
|
{
|
|
if ((*itr)->getType()==DB_DSK_LIGHTPT) { // light points ONLY
|
|
geoInfo ginf(0,0, 1);
|
|
ginf.setPools(&coord_pool, &normal_pool); // holds all types of coords, indices etc
|
|
osgSim::LightPointNode *gd=new osgSim::LightPointNode;
|
|
// to be implemented const geoField *gfd=(*itr)->getField(GEO_DB_LIGHTPT_TYPE); // omni, uni, bi
|
|
makeLightPointNode((*itr),gd); // add vertex positions to light point set
|
|
nug->addChild(gd);
|
|
}
|
|
}
|
|
}
|
|
int makeAnimatedGeometry(const georecord grec, const int imat,Group *nug) {
|
|
// animated polygons - create a matrix & geode & poly & add to group nug
|
|
const std::vector<georecord *> gr=grec.getchildren();
|
|
int nanimations=0;
|
|
const geoField *gfd=grec.getField(GEO_DB_RENDERGROUP_CULLING); // back, front, none
|
|
unsigned int bothsides=gfd ? gfd->getUInt() : 0;
|
|
// int bothsides =allOneSided(&grec);
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
std::vector< georecord *>bhv=(*itr)->getBehaviour(); // behaviours attached to facets, eg colour!
|
|
if ((*itr)->getType()==DB_DSK_POLYGON && !bhv.empty()) { // animated facets go here
|
|
nanimations++;
|
|
if (hasMotionAction(bhv)) { // make matrix if motion needed.
|
|
const geoField *gfd=(*itr)->getField(GEO_DB_POLY_TEX0);
|
|
int txidx= gfd ? gfd->getInt() : -1;
|
|
gfd=(*itr)->getField(GEO_DB_POLY_SHADEMODEL); // shaded gouraud, flat...
|
|
int shademodel=gfd ? gfd->getInt() : GEO_POLY_SHADEMODEL_LIT_GOURAUD;
|
|
gfd=(*itr)->getField(GEO_DB_POLY_USE_MATERIAL_DIFFUSE); // true: use material...
|
|
bool usemat= gfd ? gfd->getBool() : false;
|
|
geoInfo ginf(txidx,shademodel, bothsides);
|
|
ginf.setPools(&coord_pool, &normal_pool); // holds all types of coords, indices etc
|
|
MatrixTransform *mtr=makeBehave(*itr);
|
|
Geode *gd=new Geode;
|
|
gfd=(*itr)->getField(GEO_DB_POLY_DSTYLE); // solid, wire...
|
|
int dstyle= gfd ? gfd->getInt() : GEO_POLY_DSTYLE_SOLID;
|
|
if (!usemat &&
|
|
(shademodel== GEO_POLY_SHADEMODEL_LIT ||shademodel== GEO_POLY_SHADEMODEL_LIT_GOURAUD) ) { // get the per vertex colours OR per face colours.
|
|
gfd=(*itr)->getField(GEO_DB_POLY_PACKED_COLOR); // the colour
|
|
if (gfd) {
|
|
unsigned char *cls=gfd->getUCh4Arr();
|
|
float red=cls[0]/255.0f;
|
|
float green=cls[1]/255.0f;
|
|
float blue=cls[2]/255.0f;
|
|
float alpha=1.0f; // cls[3]*frac/255.0f;
|
|
ginf.getVinf()->addPolcolour(osg::Vec4(red,green,blue,alpha));
|
|
} else { // get colour from palette
|
|
gfd=(*itr)->getField(GEO_DB_POLY_COLOR_INDEX); // use color pool...
|
|
int icp= gfd ? gfd->getInt() : 0;
|
|
float col[4];
|
|
theHeader->getPalette(icp, col);
|
|
ginf.getVinf()->addPolcolour(osg::Vec4(col[0],col[1],col[2],1.0));
|
|
}
|
|
}
|
|
nug->addChild(mtr);
|
|
mtr->addChild(gd);
|
|
osg::Geometry *nugeom=makeNewGeometry((*itr), ginf, imat);
|
|
int nv=getprim((*itr),ginf);
|
|
gd->addDrawable(nugeom); // now add the polygon
|
|
if (dstyle==GEO_POLY_DSTYLE_SOLID_BOTH_SIDES || dstyle == GEO_POLY_DSTYLE_SOLID) nugeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,nv));
|
|
if (dstyle==GEO_POLY_DSTYLE_OPEN_WIRE) nugeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,nv));
|
|
if (dstyle==GEO_POLY_DSTYLE_CLOSED_WIRE) nugeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,nv));
|
|
if (dstyle==GEO_POLY_DSTYLE_POINTS) nugeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS,0,nv));
|
|
addPolyActions(bhv, ginf ,nv);
|
|
}
|
|
}
|
|
|
|
}
|
|
return nanimations;
|
|
}
|
|
bool hasColorAction(std::vector< georecord *>bhv) { // true if one of the actions changes colour
|
|
bool ok=false;
|
|
// if (bhv) {
|
|
for (std::vector< georecord *>::const_iterator rcitr=bhv.begin();
|
|
rcitr!=bhv.end() && !ok;
|
|
++rcitr)
|
|
{
|
|
switch ((*rcitr)->getType()) {
|
|
case DB_DSK_COLOR_RAMP_ACTION:
|
|
ok=true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// }
|
|
return ok;
|
|
}
|
|
bool hasMotionAction(std::vector< georecord *>bhv) { // true if one of the actions is a motion
|
|
bool ok=false;
|
|
// if (bhv) {
|
|
for (std::vector< georecord *>::const_iterator rcitr=bhv.begin();
|
|
rcitr!=bhv.end() && !ok;
|
|
++rcitr)
|
|
{
|
|
switch ((*rcitr)->getType()) {
|
|
case DB_DSK_ROTATE_ACTION:
|
|
case DB_DSK_SCALE_ACTION:
|
|
case DB_DSK_TRANSLATE_ACTION:
|
|
ok=true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// }
|
|
return ok;
|
|
}
|
|
geoInfo *getGeometry(const georecord *grec,Geode *nug, std::vector<class geoInfo> *ia,
|
|
const unsigned int imat, const int shademodel, const int bothsides) {
|
|
int igidx=0, igeom=-1;
|
|
const geoField *gfd=grec->getField(GEO_DB_POLY_TEX0);
|
|
int txidx= gfd ? gfd->getInt() : -1;
|
|
for (std::vector<class geoInfo>::iterator itrint=ia->begin();
|
|
itrint!=ia->end() && igeom<0;
|
|
++itrint) { // find a geometry that shares this texture.
|
|
// also test for other properties of a unique material:
|
|
// - use material/vertex colours;
|
|
geoInfo gu(txidx,shademodel, bothsides);
|
|
if (gu==&(*itrint) && !(*itrint).getGeom()->getUpdateCallback()) igeom=igidx;
|
|
igidx++;
|
|
}
|
|
std::vector< georecord *>bhv=grec->getBehaviour(); // behaviours attached to facets, eg colour!
|
|
if (igeom<0 || hasColorAction(bhv)) { // we need a new geometry for this due to new texture/material combo or an action
|
|
gfd=grec->getField(GEO_DB_POLY_SHADEMODEL); // shaded gouraud, flat...
|
|
int shademodel=gfd ? gfd->getInt() : GEO_POLY_SHADEMODEL_LIT_GOURAUD;
|
|
geoInfo gi(txidx,shademodel, bothsides);
|
|
gi.setPools(&coord_pool, &normal_pool);
|
|
gfd=grec->getField(GEO_DB_POLY_LINE_WIDTH); // integer line width...
|
|
if (gfd) {
|
|
int w=gfd->getInt();
|
|
gi.setlineWidth(w);
|
|
}
|
|
osg::Geometry *nugeom=makeNewGeometry(grec, gi, imat);
|
|
nug->addDrawable(nugeom);
|
|
igeom=ia->size();
|
|
ia->push_back(gi); // look up table for which texture corresponds to which geom
|
|
}
|
|
return (&((*ia)[igeom]));
|
|
}
|
|
int makeGeometry(const georecord &grec, const unsigned int imat,Geode *nug)
|
|
{ // makegeometry makes a set of Geometrys attached to current parent (Geode nug)
|
|
const std::vector<georecord *> gr=grec.getchildren();
|
|
// std::vector<osg::Geometry *> geom;
|
|
if (gr.size()>0) {
|
|
std::vector<class geoInfo> ia; // list of texture indices & vinfo found in this geode; sort into new
|
|
const geoField *gfd=grec.getField(GEO_DB_RENDERGROUP_CULLING); // back, front, none
|
|
unsigned int bothsides=gfd ? gfd->getUInt() : 0;
|
|
// vertexInfo vinf(&coord_pool, &normal_pool); // holds all types of coords, indices etc
|
|
// bool bothsides=allOneSided(&grec);
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
std::vector< georecord *>bhv=(*itr)->getBehaviour(); // behaviours attached to facets, eg colour!
|
|
if ( !hasMotionAction(bhv)) { // animated facets go elsewhere
|
|
if ((*itr)->getType()==DB_DSK_POLYGON) { // a normal facet
|
|
const geoField *gfd=(*itr)->getField(GEO_DB_POLY_DSTYLE); // solid, wire...
|
|
int dstyle= gfd ? gfd->getInt() : GEO_POLY_DSTYLE_SOLID;
|
|
gfd=(*itr)->getField(GEO_DB_POLY_SHADEMODEL); // shaded gouraud, flat...
|
|
int shademodel=gfd ? gfd->getInt() : GEO_POLY_SHADEMODEL_LIT_GOURAUD;
|
|
geoInfo *gi=getGeometry((*itr), nug, &ia, imat,shademodel, bothsides);
|
|
|
|
//shade models GEO_POLY_SHADEMODEL_FLAT GEO_POLY_SHADEMODEL_GOURAUD
|
|
// GEO_POLY_SHADEMODEL_LIT GEO_POLY_SHADEMODEL_LIT_GOURAUD
|
|
gfd=(*itr)->getField(GEO_DB_POLY_USE_MATERIAL_DIFFUSE); // true: use material...
|
|
bool usemat= gfd ? gfd->getBool() : false;
|
|
if (!usemat ||
|
|
shademodel== GEO_POLY_SHADEMODEL_LIT /*||shademodel== GEO_POLY_SHADEMODEL_LIT_GOURAUD) */ ) { // get the per vertex colours OR per face colours.
|
|
gfd=(*itr)->getField(GEO_DB_POLY_PACKED_COLOR); // the colour
|
|
if (gfd) {
|
|
unsigned char *cls=gfd->getUCh4Arr();
|
|
float red=cls[0]/255.0f;
|
|
float green=cls[1]/255.0f;
|
|
float blue=cls[2]/255.0f;
|
|
float alpha=1.0f; // cls[3]*frac/255.0f;
|
|
gi->getVinf()->addPolcolour(osg::Vec4(red,green,blue,alpha));
|
|
} else { // get colour from palette
|
|
gfd=(*itr)->getField(GEO_DB_POLY_COLOR_INDEX); // use color pool...
|
|
int icp= gfd ? gfd->getInt() : 0;
|
|
float col[4];
|
|
theHeader->getPalette(icp, col);
|
|
gi->getVinf()->addPolcolour(osg::Vec4(col[0],col[1],col[2],1.0));
|
|
}
|
|
}
|
|
int nv=getprim((*itr), *gi);
|
|
{
|
|
const vertexInfo *vinf=gi->getVinf();
|
|
if (vinf->getNorms() && vinf->getNorms()->size()>0) {
|
|
gi->getGeom()->setNormalArray(vinf->getNorms());
|
|
gi->getGeom()->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
|
} else {
|
|
gi->getGeom()->setNormalBinding(osg::Geometry::BIND_OFF);
|
|
}
|
|
}
|
|
if (hasColorAction(bhv)) addPolyActions(bhv, *gi, nv);
|
|
|
|
if (dstyle==GEO_POLY_DSTYLE_SOLID_BOTH_SIDES || dstyle == GEO_POLY_DSTYLE_SOLID) {
|
|
osg::DrawArrays *drw=new osg::DrawArrays(osg::PrimitiveSet::POLYGON,gi->getStart(nv),nv);
|
|
gi->getGeom()->addPrimitiveSet(drw);
|
|
}
|
|
if (dstyle == GEO_POLY_DSTYLE_OPEN_WIRE) {
|
|
osg::DrawArrays *drw=new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,gi->getStart(nv),nv);
|
|
gi->getGeom()->addPrimitiveSet(drw);
|
|
}
|
|
if (dstyle == GEO_POLY_DSTYLE_CLOSED_WIRE) {
|
|
osg::DrawArrays *drw=new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,gi->getStart(nv),nv);
|
|
gi->getGeom()->addPrimitiveSet(drw);
|
|
}
|
|
if (dstyle==GEO_POLY_DSTYLE_POINTS) {
|
|
osg::DrawArrays *drw=new osg::DrawArrays(osg::PrimitiveSet::POINTS,gi->getStart(nv),nv);
|
|
gi->getGeom()->addPrimitiveSet(drw);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
{
|
|
int igeom=0;
|
|
for (std::vector<geoInfo>::iterator itr=ia.begin();
|
|
itr!=ia.end();
|
|
++itr) {
|
|
if ((*itr).getTexture() >=0) {
|
|
osg::Vec2Array *txa=ia[igeom].getVinf()->getTexCoords();
|
|
if (txa->size() > 0 ) {
|
|
((*itr).getGeom())->setTexCoordArray(0, txa);
|
|
}
|
|
}
|
|
igeom++;
|
|
}
|
|
}
|
|
}
|
|
return gr.size();
|
|
}
|
|
void makeTexts(georecord grec, Group *nug)
|
|
{ // makeTexts adds a set of text+transform Geometrys attached to current parent (Group nug)
|
|
const std::vector<georecord *> gr=grec.getchildren();
|
|
std::vector<osg::Geometry *> geom;
|
|
if (gr.size()>0) {
|
|
std::vector<int> ia; // list of texture indices found in this geode; sort into new
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
if ((*itr)->getType()==DB_DSK_TEXT) {
|
|
osg::MatrixTransform *text=makeText((*itr));
|
|
if (text) nug->addChild(text);
|
|
}
|
|
}
|
|
// osg::notify(osg::WARN) << vinf;
|
|
}
|
|
return;
|
|
}
|
|
Group *makeTextGeode(const georecord *gr)
|
|
{ // in geo text is defined with a matrix included in the geo.geode (gr is this geo.geode)
|
|
// - we need to create this tree to render text
|
|
return NULL; // temporary disable april 2003
|
|
Group *nug=new Group;
|
|
const geoField *gfd=gr->getField(GEO_DB_RENDERGROUP_MAT);
|
|
// may be used in future const unsigned int imat=gfd ? gfd->getInt():0;
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
nug->setName(gfd->getChar());
|
|
}
|
|
makeTexts((*gr),nug);
|
|
if (nug->getNumChildren() <=0) {
|
|
nug=NULL;
|
|
}
|
|
return nug;
|
|
}
|
|
Group *makeLightPointGeodes(const georecord *gr) {
|
|
const geoField *gfd=gr->getField(GEO_DB_RENDERGROUP_MAT);
|
|
Group *nug=new Group;
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
char *name = gfd->getChar();
|
|
nug->setName(name);
|
|
}
|
|
makeLightPointGeometry(gr,nug);
|
|
if (nug->getNumChildren() <=0) {
|
|
nug=NULL;
|
|
}
|
|
return nug;
|
|
}
|
|
Group *makeAnimatedGeodes(const georecord *gr)
|
|
{ // create a group full of animated geodes. Used for any animations applied to facets!
|
|
// movement actions require a transform node to be inserted, and this cannot be
|
|
// derived from Geode. So create a group, add matrix transform(s) for each animated polygon
|
|
const geoField *gfd=gr->getField(GEO_DB_RENDERGROUP_MAT);
|
|
const int imat=gfd ? gfd->getInt():0;
|
|
// gfd=gr->getField(GEO_DB_RENDERGROUP_IS_BILLBOARD);
|
|
// bool isbillb = gfd ? gfd->getBool() : false;
|
|
Group *nug=new Group;
|
|
/* if (isbillb) {
|
|
Billboard *bilb= new Billboard ;
|
|
bilb->setAxis(Vec3(0,0,1));
|
|
bilb->setNormal(Vec3(0,-1,0));
|
|
nug=bilb;
|
|
} else {
|
|
nug=new Geode;
|
|
} */
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
char *name = gfd->getChar();
|
|
nug->setName(name);
|
|
}
|
|
int nans=makeAnimatedGeometry((*gr),imat,nug);
|
|
if (nans <=0) {
|
|
nug=NULL;
|
|
}
|
|
return nug;
|
|
}
|
|
Geode *makeGeode(const georecord &gr)
|
|
{
|
|
const geoField *gfd=gr.getField(GEO_DB_RENDERGROUP_MAT);
|
|
const unsigned int imat=gfd ? gfd->getInt():0;
|
|
gfd=gr.getField(GEO_DB_RENDERGROUP_BILLBOARD);
|
|
bool isbillb = gfd ? gfd->getBool() : false;
|
|
osg::Geode *nug;
|
|
if (isbillb) {
|
|
Billboard *bilb= new Billboard ;
|
|
bilb->setAxis(Vec3(0,0,1));
|
|
bilb->setNormal(Vec3(0,-1,0));
|
|
nug=bilb;
|
|
} else {
|
|
nug=new Geode;
|
|
}
|
|
int nchild=makeGeometry(gr,imat,nug);
|
|
if (nchild>0) { // complete the geode
|
|
gfd=gr.getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
nug->setName(gfd->getChar());
|
|
}
|
|
return nug;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
osg::Group *makePage(const georecord *gr)
|
|
{
|
|
osg::Group *gp=new Group;
|
|
const geoField *gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
gp->setName(gfd->getChar());
|
|
}
|
|
return gp;
|
|
}
|
|
osg::Group *setmatrix(const georecord *gr) { // find one of the types of matrix supported
|
|
const geoField *gfd=gr->getField(GEO_DB_GRP_MATRIX_TRANSFORM);
|
|
if (!gfd) gfd=gr->getField(GEO_DB_GRP_TRANSLATE_TRANSFORM);
|
|
if (!gfd) gfd=gr->getField(GEO_DB_GRP_ROTATE_TRANSFORM);
|
|
if (!gfd) gfd=gr->getField(GEO_DB_GRP_SCALE_TRANSFORM);
|
|
if (gfd) {
|
|
MatrixTransform *tr=new MatrixTransform;
|
|
osg::Matrix mx;
|
|
float * m44=gfd->getMat44Arr();
|
|
mx.set(m44); // hope uses same convention as OSG else will need to use set(m44[0],m44[1]...)
|
|
tr->setMatrix(mx);
|
|
return tr;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
osg::Group *makeGroup(const georecord *gr) { // group or Static transform
|
|
osg::Group *gp=setmatrix(gr);
|
|
if (!gp) {
|
|
gp=new osg::Group;
|
|
}
|
|
const geoField *gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
gp->setName(gfd->getChar());
|
|
}
|
|
return gp;
|
|
}
|
|
osg::Group *makeSwitch(const georecord *gr)
|
|
{
|
|
osg::Switch *sw=new Switch;
|
|
const geoField *gfd=gr->getField(GEO_DB_SWITCH_CURRENT_MASK);
|
|
sw->setAllChildrenOff();
|
|
if (gfd) {
|
|
int imask;
|
|
|
|
imask=gfd->getInt();
|
|
|
|
// set the bits in the osg::Switch.
|
|
int selector_mask = 0x1;
|
|
for(int pos=0;pos<32;++pos)
|
|
{
|
|
sw->setValue(pos,((imask&selector_mask)!=0));
|
|
selector_mask <<= 1;
|
|
}
|
|
osg::notify(osg::WARN) << gr << " imask " << imask << std::endl;
|
|
} else {
|
|
sw->setSingleChildOn(0);
|
|
osg::notify(osg::WARN) << gr << " Switch has No mask- only 1 child " << std::endl;
|
|
}
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
sw->setName(gfd->getChar());
|
|
}
|
|
return sw;
|
|
}
|
|
|
|
osg::Sequence *makeSequence(const georecord *gr)
|
|
{
|
|
Sequence *sq=new Sequence;
|
|
const geoField *gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
sq->setName(gfd->getChar());
|
|
}
|
|
return sq;
|
|
}
|
|
osg::LOD *makeLOD(const georecord *gr)
|
|
{
|
|
osg::LOD *gp=new LOD;
|
|
const geoField *gfd=gr->getField(GEO_DB_LOD_IN);
|
|
float in = gfd ? gfd->getFloat() : 100.0;
|
|
gfd=gr->getField(GEO_DB_LOD_OUT);
|
|
float out = gfd ? gfd->getFloat() : 0.0;
|
|
gp->setRange(0,out,in);
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
gp->setName(gfd->getChar());
|
|
}
|
|
return gp;
|
|
}
|
|
osg::Drawable* createClipSurface(float xMin,float xMax,float yMin,float yMax,float z)
|
|
{ // set up the Geometry that defines the clipped region.
|
|
osg::Geometry* geom = new osg::Geometry;
|
|
|
|
osg::Vec3Array* coords = new osg::Vec3Array(4);
|
|
(*coords)[0].set(xMin,yMax,z);
|
|
(*coords)[1].set(xMin,yMin,z);
|
|
(*coords)[2].set(xMax,yMin,z);
|
|
(*coords)[3].set(xMax,yMax,z);
|
|
geom->setVertexArray(coords);
|
|
|
|
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
|
|
|
|
return geom;
|
|
}
|
|
Group *makeClipRegion(const georecord *gr) {
|
|
GeoClipRegion *clp=new GeoClipRegion;
|
|
const geoField *gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
clp->setName(gfd->getChar());
|
|
}
|
|
gfd=gr->getField(140);
|
|
float *lleft = (gfd) ? (gfd->getVec3Arr()):NULL;
|
|
gfd=gr->getField(141);
|
|
float *uright= (gfd) ? (gfd->getVec3Arr()):NULL;
|
|
if (uright && lleft) {
|
|
Geode *geod=new Geode;
|
|
Drawable *drw=createClipSurface(lleft[0],uright[0],lleft[1],uright[1],lleft[2]);
|
|
geod->addDrawable(drw);
|
|
clp->addClipNode(geod);
|
|
}
|
|
return clp;
|
|
}
|
|
geoHeader *makeHeader(const georecord *gr) {
|
|
if (!theHeader.valid()) theHeader=new geoHeaderGeo();
|
|
// the header contains variables as well as a transform for the XYZup cases
|
|
const geoField *gfd;
|
|
if (cpalrec) { // global - attach to geoheader
|
|
gfd=cpalrec->getField(GEO_DB_COLOR_PALETTE_HIGHEST_INTENSITIES);
|
|
if (gfd) {
|
|
unsigned char *cpal=gfd->getstore(0);
|
|
for (uint i=1; i<gfd->getNum(); i++) {
|
|
theHeader->addColour(cpal);
|
|
cpal+=4;
|
|
}
|
|
}
|
|
}
|
|
gfd=gr->getField(GEO_DB_HDR_UP_AXIS);
|
|
osg::Quat q;
|
|
int iup=gfd ? gfd->getInt() : GEO_DB_UP_AXIS_Y;
|
|
|
|
switch (iup) {
|
|
case GEO_DB_UP_AXIS_X:
|
|
q.set(0,1,0,1);
|
|
q/=q.length();
|
|
theHeader->setAttitude(q);
|
|
break;
|
|
case GEO_DB_UP_AXIS_Y:
|
|
q.set(1,0,0,1);
|
|
q/=q.length();
|
|
// theHeader->setMatrix(Matrix::rotate(pi2, osg::Vec3(1,0,0 )));//setAttitude(q);
|
|
theHeader->setAttitude(q);
|
|
break;
|
|
case GEO_DB_UP_AXIS_Z: // no change
|
|
q.set(0,0,0,1);
|
|
q/=q.length();
|
|
theHeader->setAttitude(q); // set(q);
|
|
break;
|
|
}
|
|
std::vector<georecord *>::const_iterator itr;
|
|
for (itr=geotxlist.begin(); itr<geotxlist.end(); itr++) {
|
|
makeTexture(*itr);
|
|
}
|
|
std::vector< georecord *>bhv=gr->getBehaviour();
|
|
if (!bhv.empty()) { // then add internal, user, extern variables
|
|
for (std::vector< georecord *>::const_iterator rcitr=bhv.begin();
|
|
rcitr!=bhv.end();
|
|
++rcitr)
|
|
{
|
|
if ((*rcitr)->getType()==DB_DSK_INTERNAL_VARS) {
|
|
theHeader->addInternalVars(**rcitr);
|
|
// theHeader->setUpdateCallback(theHeader->getInternalVars());
|
|
}
|
|
if ((*rcitr)->getType()==DB_DSK_FLOAT_VAR) {
|
|
if (theHeader.valid()) theHeader->addUserVar((**rcitr));
|
|
}
|
|
}
|
|
theHeader->setUpdateCallback(new geoHeaderCB);
|
|
}
|
|
for (itr=geomatlist.begin(); itr< geomatlist.end(); itr++) {
|
|
osg::Material *mt=new osg::Material;
|
|
(*itr)->setMaterial(mt);
|
|
matlist.push_back(mt);
|
|
}
|
|
return theHeader.get();
|
|
}
|
|
void makeTexture(const georecord *gr) {
|
|
// scans the fields of this record and puts a new texture & environment into 'pool' stor
|
|
const geoField *gfd=gr->getField(GEO_DB_TEX_FILE_NAME);
|
|
const char *name = gfd->getChar();
|
|
if (name) {
|
|
Texture2D *tx=new Texture2D;
|
|
Image *ctx=osgDB::readImageFile(name);
|
|
if (ctx) {
|
|
ctx->setFileName(name);
|
|
tx->setImage(ctx);
|
|
}
|
|
gfd=gr->getField(GEO_DB_TEX_WRAPS);
|
|
osg::Texture2D::WrapMode wm=Texture2D::REPEAT;
|
|
if (gfd) {
|
|
unsigned iwrap= gfd->getUInt();
|
|
wm = (iwrap==GEO_DB_TEX_CLAMP) ? Texture2D::CLAMP : Texture2D::REPEAT;
|
|
}
|
|
tx->setWrap(Texture2D::WRAP_S, wm);
|
|
gfd=gr->getField(GEO_DB_TEX_WRAPT);
|
|
wm=Texture2D::REPEAT;
|
|
if (gfd) {
|
|
unsigned iwrap= gfd->getUInt();
|
|
wm = (iwrap==GEO_DB_TEX_CLAMP) ? Texture2D::CLAMP : Texture2D::REPEAT;
|
|
}
|
|
tx->setWrap(Texture2D::WRAP_T, wm);
|
|
txlist.push_back(tx);
|
|
osg::TexEnv* texenv = new osg::TexEnv;
|
|
osg::TexEnv::Mode md=osg::TexEnv::MODULATE;
|
|
gfd=gr->getField(GEO_DB_TEX_ENV);
|
|
texenv->setMode(md);
|
|
if (gfd) {
|
|
unsigned imod=gfd->getUInt();
|
|
switch (imod) {
|
|
case GEO_DB_TEX_MODULATE:
|
|
md=osg::TexEnv::MODULATE;
|
|
break;
|
|
case GEO_DB_TEX_DECAL:
|
|
md=osg::TexEnv::DECAL;
|
|
break;
|
|
case GEO_DB_TEX_BLEND:
|
|
md=osg::TexEnv::BLEND;
|
|
break;
|
|
}
|
|
}
|
|
gfd=gr->getField(GEO_DB_TEX_MINFILTER);
|
|
osg::Texture::FilterMode filt=osg::Texture::NEAREST_MIPMAP_NEAREST;
|
|
if (gfd) {
|
|
unsigned imod=gfd->getUInt();
|
|
switch (imod) {
|
|
case GEO_DB_TEX_NEAREST_MIPMAP_NEAREST:
|
|
filt=osg::Texture::LINEAR_MIPMAP_LINEAR;
|
|
break;
|
|
case GEO_DB_TEX_LINEAR_MIPMAP_NEAREST:
|
|
filt=osg::Texture::LINEAR_MIPMAP_NEAREST;
|
|
break;
|
|
case GEO_DB_TEX_NEAREST_MIPMAP_LINEAR:
|
|
filt=osg::Texture::NEAREST_MIPMAP_LINEAR;
|
|
break;
|
|
case GEO_DB_TEX_LINEAR_MIPMAP_LINEAR:
|
|
filt=osg::Texture::NEAREST_MIPMAP_NEAREST;
|
|
break;
|
|
}
|
|
}
|
|
tx->setFilter(osg::Texture::MIN_FILTER, filt);
|
|
gfd=gr->getField(GEO_DB_TEX_MAGFILTER);
|
|
if (gfd) {
|
|
unsigned imod=gfd->getUInt();
|
|
switch (imod) {
|
|
case GEO_DB_TEX_NEAREST:
|
|
filt=osg::Texture::LINEAR;
|
|
break;
|
|
case GEO_DB_TEX_LINEAR:
|
|
filt=osg::Texture::NEAREST;
|
|
break;
|
|
}
|
|
}
|
|
txenvlist.push_back(texenv);
|
|
}
|
|
}
|
|
MatrixTransform *makeBehave(const georecord *gr)
|
|
{
|
|
MatrixTransform *mtr=NULL;
|
|
bool ok=false; // true if the matrix transform is required
|
|
std::vector< georecord *>bhv=gr->getBehaviour();
|
|
if (!bhv.empty()) { // then add a DCS/matrix_transform
|
|
mtr=new MatrixTransform;
|
|
geoBehaviourCB *gcb=new geoBehaviourCB;
|
|
mtr->setUpdateCallback(gcb);
|
|
|
|
for (std::vector< georecord *>::const_iterator rcitr=bhv.begin();
|
|
rcitr!=bhv.end();
|
|
++rcitr)
|
|
{
|
|
switch ((*rcitr)->getType()) {
|
|
case DB_DSK_BEHAVIOR: {
|
|
const geoField *gfd=(*rcitr)->getField(GEO_DB_BEHAVIOR_NAME);
|
|
if (gfd) {
|
|
mtr->setName(gfd->getChar());
|
|
}
|
|
}
|
|
break;
|
|
case DB_DSK_ROTATE_ACTION: {
|
|
geoMoveBehaviour *cb= new geoMoveBehaviour;
|
|
ok=cb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(cb);
|
|
else delete cb;
|
|
}
|
|
break;
|
|
|
|
case DB_DSK_SCALE_ACTION: {
|
|
geoMoveBehaviour *sb=new geoMoveBehaviour;
|
|
ok=sb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(sb);
|
|
else delete sb;
|
|
}
|
|
break;
|
|
case DB_DSK_TRANSLATE_ACTION: {
|
|
geoMoveBehaviour *cb= new geoMoveBehaviour;
|
|
ok=cb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(cb);
|
|
else delete cb;
|
|
}
|
|
break;
|
|
|
|
case DB_DSK_COMPARE_ACTION: {
|
|
geoCompareBehaviour *cb=new geoCompareBehaviour;
|
|
ok=cb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(cb);
|
|
else delete cb;
|
|
}
|
|
break;
|
|
case DB_DSK_ARITHMETIC_ACTION: {
|
|
geoArithBehaviour *cb=new geoArithBehaviour;
|
|
ok=cb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(cb);
|
|
else delete cb;
|
|
}
|
|
break;
|
|
case DB_DSK_CLAMP_ACTION: {
|
|
geoClampBehaviour *cb=new geoClampBehaviour;
|
|
ok=cb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(cb);
|
|
else delete cb;
|
|
}
|
|
break;
|
|
case DB_DSK_RANGE_ACTION: {
|
|
geoRangeBehaviour *cb=new geoRangeBehaviour;
|
|
ok=cb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(cb);
|
|
else delete cb;
|
|
}
|
|
break;
|
|
case DB_DSK_VISIBILITY_ACTION: {
|
|
geoVisibBehaviour *vb = new geoVisibBehaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
// ar3 types
|
|
case DB_DSK_TRIG_ACTION: {
|
|
geoAr3Behaviour *vb = new geoAr3Behaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
case DB_DSK_INVERSE_ACTION: {
|
|
geoAr3Behaviour *vb = new geoAr3Behaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
case DB_DSK_LINEAR_ACTION: {
|
|
geoAr3Behaviour *vb = new geoAr3Behaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
case DB_DSK_PERIODIC_ACTION: {
|
|
geoAr3Behaviour *vb = new geoAr3Behaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
case DB_DSK_PERIODIC2_ACTION: {
|
|
geoAr3Behaviour *vb = new geoAr3Behaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
case DB_DSK_TRUNCATE_ACTION: {
|
|
geoAr3Behaviour *vb = new geoAr3Behaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
case DB_DSK_ABS_ACTION: {
|
|
geoAr3Behaviour *vb = new geoAr3Behaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
/*
|
|
case DB_DSK_DCS_ACTION: */
|
|
case DB_DSK_DISCRETE_ACTION: {
|
|
geoDiscreteBehaviour *db = new geoDiscreteBehaviour;
|
|
ok=db->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(db);
|
|
else delete db;
|
|
}
|
|
break;
|
|
case DB_DSK_STRING_CONTENT_ACTION: {// cant be shared with this
|
|
// ok=false; can be a mixed action, rotate & string content
|
|
}
|
|
break;
|
|
case DB_DSK_IF_THEN_ELSE_ACTION:
|
|
{
|
|
geoAr3Behaviour *vb = new geoAr3Behaviour;
|
|
ok=vb->makeBehave((*rcitr), theHeader.get());
|
|
if (ok) gcb->addBehaviour(vb);
|
|
else delete vb;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!ok) {
|
|
mtr=NULL;
|
|
}
|
|
return mtr;
|
|
}
|
|
std::vector<Node *> makeosg(const std::vector<georecord *> gr) {
|
|
// recursive traversal of records and extract osg::Nodes equivalent
|
|
Group *geodeholder=NULL;
|
|
std::vector<Node *> nodelist;
|
|
if (gr.size()>0) {
|
|
for (std::vector<georecord *>::const_iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
const georecord *gr=*itr;
|
|
Group *mtr=makeBehave(gr);
|
|
if (gr->getType()== DB_DSK_RENDERGROUP) { // geodes can require >1 geometry for example if polygons have different texture indices.
|
|
// and for example if the node has a colour or other fine behaviour
|
|
Geode *geode=makeGeode(*gr); // geode of geometrys
|
|
Group *animatedGeodes= makeAnimatedGeodes(gr);
|
|
Group *lightptGeodes= makeLightPointGeodes(gr);
|
|
Group *textgeode=makeTextGeode(gr); // group of matrices & texts
|
|
const geoField *gfd=gr->getField(GEO_DB_GRP_ZBUFFER);
|
|
if (gfd) {
|
|
bool onoff=gfd->getBool();
|
|
if (!onoff) { // no z buffer - force to use unsorted renderBin
|
|
StateSet *dstate=new StateSet;
|
|
osg::Depth* depth = new osg::Depth;
|
|
depth->setFunction(osg::Depth::ALWAYS);
|
|
dstate->setAttribute(depth);
|
|
dstate->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
|
|
dstate->setRenderBinDetails(osg::StateSet::TRANSPARENT_BIN + 1,"RenderBin");
|
|
// dstate->setRenderBinDetails(osg::StateSet::TRANSPARENT_BIN + 12, "UnSortedBin");
|
|
if (geode) geode->setStateSet( dstate );
|
|
if (animatedGeodes) animatedGeodes->setStateSet( dstate );
|
|
if (lightptGeodes) lightptGeodes->setStateSet( dstate );
|
|
if (textgeode) textgeode->setStateSet( dstate );
|
|
}
|
|
}
|
|
|
|
if (mtr) {
|
|
if (geode) mtr->addChild(geode);
|
|
if (animatedGeodes) mtr->addChild(animatedGeodes);
|
|
if (lightptGeodes) mtr->addChild(lightptGeodes);
|
|
if (textgeode) mtr->addChild(textgeode);
|
|
nodelist.push_back(mtr);
|
|
mtr=NULL;
|
|
} else {
|
|
if (!geodeholder && (geode || textgeode)) {
|
|
geodeholder=new osg::Group;
|
|
geodeholder->setName("geodeHolder");
|
|
}
|
|
if (geode) geodeholder->addChild(geode);
|
|
if (animatedGeodes) geodeholder->addChild(animatedGeodes);
|
|
if (lightptGeodes) geodeholder->addChild(lightptGeodes);
|
|
if (textgeode) geodeholder->addChild(textgeode);
|
|
}
|
|
} else {
|
|
Group *holder=NULL;
|
|
const geoField *gfd;
|
|
switch (gr->getType()) {
|
|
case 101:
|
|
case DB_DSK_HEADER:
|
|
holder=new osg::Group; // makeGroup(gr);
|
|
if (mtr) {
|
|
mtr->addChild(holder);
|
|
holder=mtr;
|
|
}
|
|
(*itr)->setNode(holder);
|
|
break;
|
|
/* holder= theHeader.get(); // makeHeader(gr);//
|
|
(*itr)->setNode(holder);
|
|
if (mtr) {
|
|
holder->addChild(mtr);
|
|
osg::Group *grp=makeGroup(gr);
|
|
mtr->addChild(grp);
|
|
holder=mtr;
|
|
}
|
|
break; */
|
|
case DB_DSK_TEXTURE:
|
|
makeTexture(gr);
|
|
break;
|
|
case DB_DSK_BASE_GROUP: // start of a group plus extra features
|
|
holder=makeClipRegion(gr);
|
|
if (mtr) {
|
|
mtr->addChild(holder);
|
|
holder=mtr;
|
|
}
|
|
(*itr)->setNode(holder);
|
|
break;
|
|
case DB_DSK_GROUP:
|
|
holder=makeGroup(gr);
|
|
if (mtr) {
|
|
mtr->addChild(holder);
|
|
holder=mtr;
|
|
}
|
|
(*itr)->setNode(holder);
|
|
break;
|
|
case DB_DSK_LOD:
|
|
holder=makeLOD(gr);
|
|
(*itr)->setNode(holder);
|
|
break;
|
|
case DB_DSK_SEQUENCE:
|
|
holder=makeSequence(gr);
|
|
(*itr)->setNode(holder);
|
|
break;
|
|
case DB_DSK_SWITCH:
|
|
holder=makeSwitch(gr);
|
|
(*itr)->setNode(holder);
|
|
break;
|
|
case DB_DSK_CUBE:
|
|
holder=new Group;
|
|
(*itr)->setNode(holder);
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
holder->setName(gfd->getChar());
|
|
}
|
|
break;
|
|
case DB_DSK_SPHERE:
|
|
holder=new Group;
|
|
(*itr)->setNode(holder);
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
holder->setName(gfd->getChar());
|
|
}
|
|
break;
|
|
case DB_DSK_CONE:
|
|
holder=new Group;
|
|
(*itr)->setNode(holder);
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
holder->setName(gfd->getChar());
|
|
}
|
|
break;
|
|
case DB_DSK_CYLINDER:
|
|
holder=new Group;
|
|
(*itr)->setNode(holder);
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
holder->setName(gfd->getChar());
|
|
}
|
|
break;
|
|
case DB_DSK_INSTANCE:
|
|
{
|
|
MatrixTransform *mtr=new MatrixTransform;
|
|
gfd=gr->getField(GEO_DB_NODE_NAME);
|
|
if (gfd) {
|
|
mtr->setName(gfd->getChar());
|
|
}
|
|
gfd=gr->getField(GEO_DB_GRP_MATRIX_TRANSFORM); // was: GEO_DB_INSTANCE_TRANSFORM);
|
|
if (gfd) {
|
|
float *fmat=gfd->getMat44Arr();
|
|
mtr->setMatrix(Matrix(fmat));
|
|
}
|
|
gfd=gr->getField(GEO_DB_INSTANCE_DEF);
|
|
if (gfd) { // get the fID of a node
|
|
uint fid=gfd->getUInt();
|
|
georecord *grec=getInstance(fid);
|
|
if (grec) {
|
|
osg::Node *nd=grec->getNode();
|
|
if (nd) { // node already loaded, so instance
|
|
mtr->addChild(nd);
|
|
holder=mtr;
|
|
} else { // store unsatisfied instance matrix in georecord...
|
|
grec->addInstance(mtr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case DB_DSK_PAGE:
|
|
holder=makePage(gr);
|
|
(*itr)->setNode(holder);
|
|
break;
|
|
case DB_DSK_PERSPECTIVE_GRID_INFO:
|
|
{ // relates to how model is viewed in Geo modeller
|
|
osg::Group *gp=new Group;
|
|
holder=gp;
|
|
}
|
|
break;
|
|
case DB_DSK_FLOAT_VAR:
|
|
case DB_DSK_INT_VAR:
|
|
case DB_DSK_LONG_VAR:
|
|
case DB_DSK_DOUBLE_VAR:
|
|
case DB_DSK_BOOL_VAR:
|
|
case DB_DSK_FLOAT2_VAR:
|
|
case DB_DSK_FLOAT3_VAR:
|
|
case DB_DSK_FLOAT4_VAR:
|
|
case DB_DSK_INTERNAL_VARS:
|
|
case DB_DSK_LOCAL_VARS:
|
|
case DB_DSK_EXTERNAL_VARS:
|
|
case DB_DSK_CLAMP_ACTION:
|
|
case DB_DSK_RANGE_ACTION:
|
|
case DB_DSK_ROTATE_ACTION:
|
|
case DB_DSK_TRANSLATE_ACTION:
|
|
case DB_DSK_SCALE_ACTION:
|
|
case DB_DSK_ARITHMETIC_ACTION:
|
|
case DB_DSK_LOGIC_ACTION:
|
|
case DB_DSK_CONDITIONAL_ACTION:
|
|
case DB_DSK_LOOPING_ACTION:
|
|
case DB_DSK_COMPARE_ACTION:
|
|
case DB_DSK_VISIBILITY_ACTION:
|
|
case DB_DSK_STRING_CONTENT_ACTION:
|
|
default: {
|
|
osg::Group *gp=new Group;
|
|
std::cout << "Unhandled item " << gr->getType() <<
|
|
"address " << (*itr) << std::endl;
|
|
holder=gp;
|
|
}
|
|
break;
|
|
}
|
|
if (holder) nodelist.push_back(holder);
|
|
|
|
std::vector<Node *> child=makeosg((*itr)->getchildren());
|
|
GeoClipRegion *clip=dynamic_cast<GeoClipRegion *>(holder);
|
|
for (std::vector<Node *>::iterator itr=child.begin();
|
|
itr!=child.end();
|
|
++itr) {
|
|
if (clip) clip->addClippedChild(*itr);
|
|
else holder->addChild(*itr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (geodeholder) {
|
|
osgUtil::Tesselator tesselator;
|
|
for(unsigned int ige=0;ige<geodeholder->getNumChildren();++ige) {
|
|
osg::Geode *geode=dynamic_cast<osg::Geode*>(geodeholder->getChild(ige));
|
|
if (geode) {
|
|
for(unsigned int i=0;i<geode->getNumDrawables();++i)
|
|
{
|
|
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
|
|
if (geom) tesselator.retesselatePolygons(*geom);
|
|
}
|
|
}
|
|
}
|
|
nodelist.push_back(geodeholder);
|
|
}
|
|
return nodelist;
|
|
}
|
|
void output(osgDB::Output &fout,std::vector<georecord> gr)
|
|
{ // debugging - print the tree of records
|
|
if (gr.size()>0) {
|
|
for (std::vector<georecord>::iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
fout.indent() << "Node type " << (*itr).getType() << " ";
|
|
fout.indent() << (*itr) << std::endl;
|
|
}
|
|
}
|
|
}
|
|
void output(osgDB::Output &fout,std::vector<georecord *> gr)
|
|
{ // debugging - print the tree of records
|
|
fout.moveIn();
|
|
if (gr.size()>0) {
|
|
for (std::vector<georecord *>::iterator itr=gr.begin();
|
|
itr!=gr.end();
|
|
++itr) {
|
|
fout.indent() << "Node type " << (*itr)->getType() << " ";
|
|
fout.indent() << (**itr) << std::endl;
|
|
fout.indent() << std::endl;
|
|
output(fout,(*itr)->getchildren());
|
|
}
|
|
}
|
|
fout.moveOut();
|
|
}
|
|
georecord *getInstance(uint fid) { // find record with instance fid
|
|
for (geoRecordList::iterator itr=recs.begin();
|
|
itr!=recs.end();
|
|
++itr) {
|
|
const geoField *gfd;
|
|
switch ((*itr).getType()) {
|
|
case DB_DSK_GROUP:
|
|
gfd=(*itr).getField(GEO_DB_GRP_INSTANCE_DEF);
|
|
if (gfd) {
|
|
uint fidnod=gfd->getUInt();
|
|
if (fidnod==fid) return &(*itr);
|
|
}
|
|
break;
|
|
case DB_DSK_LOD:
|
|
gfd=(*itr).getField(GEO_DB_INSTANCE_DEF);
|
|
if (gfd) {
|
|
uint fidnod=gfd->getUInt();
|
|
if (fidnod==fid) return &(*itr);
|
|
}
|
|
break;
|
|
case DB_DSK_SEQUENCE:
|
|
gfd=(*itr).getField(GEO_DB_INSTANCE_DEF);
|
|
if (gfd) {
|
|
uint fidnod=gfd->getUInt();
|
|
if (fidnod==fid) return &(*itr);
|
|
}
|
|
break;
|
|
case DB_DSK_SWITCH:
|
|
gfd=(*itr).getField(GEO_DB_INSTANCE_DEF);
|
|
if (gfd) {
|
|
uint fidnod=gfd->getUInt();
|
|
if (fidnod==fid) return &(*itr);
|
|
}
|
|
break;
|
|
case DB_DSK_RENDERGROUP:
|
|
gfd=(*itr).getField(GEO_DB_INSTANCE_DEF);
|
|
if (gfd) {
|
|
uint fidnod=gfd->getUInt();
|
|
if (fidnod==fid) return &(*itr);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
private:
|
|
geoRecordList recs; // the records read from file
|
|
std::vector<osg::Vec3> coord_pool; // current vertex ooords
|
|
std::vector<osg::Vec3> normal_pool; // current pool of normal vectors
|
|
osg::ref_ptr<geoHeaderGeo> theHeader; // an OSG class - has animation vars etc
|
|
std::vector<georecord *> geotxlist; // list of geo::textures for this model
|
|
std::vector<georecord *> geomatlist; // list of geo::materials for this model
|
|
std::vector<osg::Texture2D *> txlist; // list of osg::textures for this model
|
|
std::vector<osg::TexEnv *> txenvlist; // list of texture environments for the textures
|
|
std::vector<osg::Material *> matlist; // list of materials for current model
|
|
georecord *cpalrec; // colour palette record
|
|
};
|
|
|
|
//=======
|
|
void internalVars::addInternalVars(const georecord &gr){
|
|
const georecord::geoFieldList gfl=gr.getFields();
|
|
for (georecord::geoFieldList::const_iterator itr=gfl.begin();
|
|
itr!=gfl.end();
|
|
++itr)
|
|
{// for each variable
|
|
if ((*itr).getToken() >0) {
|
|
geoValue *nm=new geoValue((*itr).getToken(),(*itr).getUInt());
|
|
vars.push_back(*nm);
|
|
}
|
|
}
|
|
}
|
|
|
|
void userVars::addUserVar(const georecord &gr) {
|
|
const georecord::geoFieldList gfl=gr.getFields();
|
|
if (gr.getType() == DB_DSK_FLOAT_VAR) {
|
|
unsigned int tok=0; // ? what for?
|
|
const geoField *gfd= gr.getField(GEO_DB_FLOAT_VAR_FID);
|
|
unsigned int fid=gfd ? gfd->getUInt():0;
|
|
geoValue *nm=new geoValue(tok,fid);
|
|
|
|
gfd= gr.getField(GEO_DB_FLOAT_VAR_NAME);
|
|
const char *name=gfd->getChar();
|
|
nm->setName(name);
|
|
|
|
gfd= gr.getField(GEO_DB_FLOAT_VAR_VALUE);
|
|
nm->setVal(gfd ? gfd->getFloat():0.0f);
|
|
|
|
gfd= gr.getField(GEO_DB_FLOAT_VAR_DEFAULT);
|
|
//nm->setdefault(gfd ? gfd->getFloat():0.0f);
|
|
//float fdef=gfd ? gfd->getFloat():0.0f;
|
|
|
|
gfd= gr.getField(GEO_DB_FLOAT_VAR_CONSTRAINED);
|
|
if (gfd) {
|
|
nm->setConstrained();
|
|
gfd= gr.getField(GEO_DB_FLOAT_VAR_MIN);
|
|
if (gfd) {
|
|
nm->setMinRange(gfd->getFloat());
|
|
}
|
|
gfd= gr.getField(GEO_DB_FLOAT_VAR_MAX);
|
|
if (gfd) {
|
|
nm->setMaxRange(gfd->getFloat());
|
|
}
|
|
}
|
|
gfd= gr.getField(GEO_DB_FLOAT_VAR_STEP);
|
|
//float fstp=gfd ? gfd->getFloat():0;
|
|
vars.push_back(*nm);
|
|
}
|
|
}
|
|
|
|
void internalVars::update(const osg::FrameStamp *_frameStamp) {
|
|
double stmptime=_frameStamp->getReferenceTime();
|
|
int iord=0;
|
|
for (std::vector<geoValue>::const_iterator itr=vars.begin(); //gfl.begin();
|
|
itr!=vars.end(); // gfl.end();
|
|
++itr, iord++)
|
|
{// for each field
|
|
unsigned int typ=itr->getToken();
|
|
switch (typ) {
|
|
case GEO_DB_INTERNAL_VAR_FRAMECOUNT:
|
|
vars[iord].setVal((float)_frameStamp->getFrameNumber());
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_CURRENT_TIME:
|
|
{
|
|
static double timestart=-1;
|
|
if (timestart<0) {
|
|
time_t long_time;
|
|
struct tm *newtime;
|
|
|
|
long_time=time( NULL ); // * Get time as long integer.
|
|
newtime = localtime( &long_time ); // * Convert to local time.
|
|
timestart=newtime->tm_hour*3600 +newtime->tm_min*60+ newtime->tm_sec;
|
|
}
|
|
double timeofday=timestart+_frameStamp->getReferenceTime();
|
|
vars[iord].setVal(timeofday);
|
|
}
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_ELAPSED_TIME:
|
|
vars[iord].setVal(_frameStamp->getReferenceTime());
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_SINE:
|
|
vars[iord].setVal(sin(stmptime));
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_COSINE:
|
|
vars[iord].setVal(cos(stmptime));
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_TANGENT:
|
|
vars[iord].setVal(tan(stmptime));
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_MOUSE_X: // this is all windowing system dependent
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_MOUSE_Y:
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_LEFT_MOUSE:
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_MIDDLE_MOUSE:
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_RIGHT_MOUSE:
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_TEMP_FLOAT:
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_TEMP_INT:
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_TEMP_BOOL:
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
case GEO_DB_INTERNAL_VAR_TEMP_STRING:
|
|
// vars[iord]=_frameStamp->getReferenceTime();
|
|
break;
|
|
}
|
|
}
|
|
// std::cout<<"update callback - post traverse"<< (float)_frameStamp->getReferenceTime() <<std::endl;
|
|
}
|
|
|
|
void geoField::parseExt(std::ifstream &fin) const { // Feb 2003 parse onme extension fields
|
|
static int nread=0; // debug only
|
|
// unused
|
|
//geoExtensionDefRec *geoExt=(geoExtensionDefRec *)storage;
|
|
for (uint i=0; i<numItems; i++) {
|
|
geoExtensionDefRec rec;
|
|
fin.read((char *)&rec,sizeof(rec));
|
|
geoField ginner; // inside reading
|
|
ginner.readfile(fin,0);
|
|
}
|
|
nread++;
|
|
}
|
|
void geoField::readfile(std::ifstream &fin, const uint id) { // is part of a record id
|
|
unsigned char tokid, type;
|
|
unsigned short nits;
|
|
if (!fin.eof()) {
|
|
fin.read((char *)&tokid,1);fin.read((char *)&type,1);
|
|
fin.read((char *)&nits,sizeof(unsigned short));
|
|
// osg::notify(osg::WARN) << "geoField " << (int)tokid << " type " << (int)type << " nit " << (int)nits << std::endl;
|
|
if (type == DB_EXTENDED_FIELD_STRUCT) { // change for true extended type
|
|
fin.read((char *)&tokenId,sizeof(tokenId));fin.read((char *)&TypeId,sizeof(TypeId));
|
|
fin.read((char *)&numItems,sizeof(unsigned int));
|
|
} else {
|
|
tokenId=tokid; TypeId=type;
|
|
numItems=nits;
|
|
}
|
|
if (id== 0 && tokenId == GEO_DB_NODE_EXTENDED && numItems==1) { // Feb 2003 parse extension template records
|
|
if (TypeId == DB_SHORT ||
|
|
TypeId == DB_USHORT) {
|
|
short upad;
|
|
fin.read((char *)&upad,SIZEOF_SHORT); // skip the padding on extension template
|
|
upad=1;
|
|
} else if (TypeId == DB_CHAR ||
|
|
TypeId == DB_UCHAR) {
|
|
char cpad[4];
|
|
fin.read(cpad,SIZEOF_CHAR); // skip the padding
|
|
} else {
|
|
}
|
|
}
|
|
if (id== DB_DSK_HEADER && tokenId == GEO_DB_HDR_EXT_TEMPLATE) { // Feb 2003 parse extension records
|
|
// osg::notify(osg::WARN) << "header extension template " << (int)getType() << std::endl;
|
|
parseExt(fin); // multiple structs occur here
|
|
} else {
|
|
if (numItems>0) {
|
|
storageRead(fin); // allocate & fill the storage
|
|
if (tokenId == GEO_DB_NODE_EXT) { // added Nov 2003 to parse extension nodes
|
|
if (TypeId == DB_SHORT ||TypeId == DB_USHORT) fin.ignore(2); // skip padding
|
|
// if (TypeId == DB_CHAR ||TypeId == DB_UCHAR) fin.ignore(3); // skip padding
|
|
}
|
|
if (tokenId == GEO_DB_NODE_EXTENDED) {
|
|
if (id==DB_DSK_POLYGON || id==DB_DSK_RENDERGROUP || id==DB_DSK_GROUP
|
|
|| id==DB_DSK_LOD || id==DB_DSK_MESH || id==DB_DSK_CUBE
|
|
|| id==DB_DSK_SPHERE || id==DB_DSK_CONE || id==DB_DSK_CYLINDER
|
|
|| id==DB_DSK_TEXTURE || id==DB_DSK_MATERIAL || id==DB_DSK_VIEW) {
|
|
if (TypeId == DB_SHORT ||TypeId == DB_USHORT) fin.ignore(2); // skip padding
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// now register with Registry to instantiate the above
|
|
// reader/writer.
|
|
osgDB::RegisterReaderWriterProxy<ReaderWriterGEO> gReaderWriter_GEO_Proxy;
|