2106 lines
94 KiB
C++
2106 lines
94 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.1 GWM Dec 2002
|
|
|
|
#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 <osgSim/LightPointNode>
|
|
|
|
#include <osgDB/FileNameUtils>
|
|
#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) {
|
|
unsigned int idx=gfd ? gfd->getUInt():-1;
|
|
if (idx>=0) {
|
|
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) {
|
|
unsigned int idx=gfd ? gfd->getInt():-1;
|
|
if (idx>=0) {
|
|
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 bool bs=true) { 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 bool 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
|
|
bool bothsides;
|
|
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& fileName, const Options*)
|
|
{
|
|
std::string ext = osgDB::getFileExtension(fileName);
|
|
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
|
|
|
|
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 /**/
|
|
nodeList=makeosg(sorted); // make a list of osg nodes
|
|
recs.clear();
|
|
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;
|
|
}
|
|
#ifdef _DEBUG // output a .osg version
|
|
osgDB::writeNodeFile(*groupnode,"geoosg.osg");
|
|
#endif /**/
|
|
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: // square root action
|
|
(curparent->getLastChild())->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 bool 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());
|
|
nug->setNormalArray(vinf->getNorms());
|
|
StateSet *dstate=new StateSet;
|
|
if (!bothsides) {
|
|
osg::CullFace *cf = new osg::CullFace; // to define non-default culling
|
|
cf->setMode(osg::CullFace::BACK);
|
|
dstate->setAttributeAndModes(cf,osg::StateAttribute::ON);
|
|
}
|
|
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;
|
|
nug->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
|
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) {
|
|
unsigned int idx=gfd ? gfd->getInt():-1;
|
|
if (idx>=0) {
|
|
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, true);
|
|
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;
|
|
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 ((*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 bool 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
|
|
// 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);
|
|
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 type sof 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 << " No mask " << 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;
|
|
}
|
|
geoHeader *makeHeader(const georecord *gr) {
|
|
// the header contains variables as well as a transform for the XYZup cases
|
|
const geoField *gfd;
|
|
theHeader=new geoHeaderGeo();
|
|
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);
|
|
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->setRenderBinDetails(osg::StateSet::OPAQUE_BIN + 3, "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=makeHeader(gr);
|
|
(*itr)->setNode(holder);
|
|
break;
|
|
case DB_DSK_TEXTURE:
|
|
makeTexture(gr);
|
|
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());
|
|
for (std::vector<Node *>::iterator itr=child.begin();
|
|
itr!=child.end();
|
|
++itr) {
|
|
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_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;
|