|
楼主 |
发表于 2010-3-3 14:41:30
|
显示全部楼层
感谢array的提示,结合伪插件的思想,我将“三维渲染引擎设计与实践”中的pagelod动态加载的数据(.trans)改为.DBtrans然后编写DBtrans伪插件,主要从数据库中读取流转换为节点,功能上算是达到目的了,但是我想这并不是一种很好的方法,因为频繁的操作数据库,其实应该会影响速度的。
伪插件代码如下:
#include <iostream>
#include <sstream>
#include <stdio.h>
#define OTL_STL
#define OTL_STREAM_READ_ITERATOR_ON
#define OTL_ODBC
#include "../Include/otlv4.h"
#define EXTENSION_NAME "DBtrans"
otl_connect m_db; // connect object
bool connet2Database(const std::string& Connectionstring)
{
otl_connect:tl_initialize(); // 单线程模式(默认)
bool sucess=true;
try
{
m_db.rlogon(Connectionstring.c_str()); // connect to Oracle
}
catch(otl_exception& p){ // intercept OTL exceptions
std::cerr<<p.msg<<std::endl; // print out error message
std::cerr<<p.stm_text<<std::endl; // print out SQL that caused the error
std::cerr<<p.var_info<<std::endl; // print out the variable that caused the error
sucess=false;
}
return sucess;
}
bool IsOpen()
{
return m_db.connected;
}
void Close()
{
m_db.logoff();
}
static bool getFilenameAndParams(const std::string& input, std::string& filename, std::string& params)
{
// find the start of the params list, accounting for nesting of [] and () brackets,
// note, we are working backwards.
int noNestedBrackets = 0;
std::string::size_type pos = input.size();
for(; pos>0; )
{
--pos;
char c = input[pos];
if (c==']') ++noNestedBrackets;
else if (c=='[') --noNestedBrackets;
else if (c==')') ++noNestedBrackets;
else if (c=='(') --noNestedBrackets;
else if (c=='.' && noNestedBrackets==0) break;
}
// get the next "extension", which actually contains the pseudo-loader parameters
params = input.substr(pos+1, std::string::npos );
if( params.empty() )
{
osg::notify(osg::WARN) << "Missing parameters for " EXTENSION_NAME " pseudo-loader" << std::endl;
return false;
}
// clear the params sting of any brackets.
std::string::size_type params_pos = params.size();
for(; params_pos>0; )
{
--params_pos;
char c = params[params_pos];
if (c==']' || c=='[' || c==')' || c=='(')
{
params.erase(params_pos,1);
}
}
// strip the "params extension", which must leave a sub-filename.
filename = input.substr(0, pos );
return true;
}
osg::Node* readNodeFileFromDB(const std::string& filename,const osgDB::ReaderWriter::Options* options )
{
if(!IsOpen())
connet2Database("UID=saWD=sa;DSN=ExpoTd");
if (IsOpen())
{
std::string sqlstr="select Geometry from Expo_Td where Name = '"+ filename+"'";
otl_stream i;
i.set_lob_stream_mode(true);
i.open(1,sqlstr.c_str(),m_db);
/*while (!i.eof())
{*/
otl_lob_stream lob;
std::string outputstr;
i>>lob;
while (!lob.eof())
{
otl_long_string f2(3000);
lob>>f2;
for (int i=0;i<f2.len();i++)
outputstr.push_back(f2[i]);
}
lob.close();
std::istringstream istrstream(outputstr);
osgDB::ReaderWriter* rw =osgDB::Registry::instance()->getReaderWriterForExtension("osg");
osgDB::ReaderWriter::ReadResult rr = rw->readNode(istrstream);
osg::Node* node=rr.takeNode();
return node;
//}
}
else
return NULL;
}
///////////////////////////////////////////////////////////////////////////
/**
* An OSG reader plugin for the ".trans" pseudo-loader, which inserts a
* translation transform above the loaded geometry.
* This pseudo-loader make it simple to change the origin of a saved model
* by specifying a correcting translation as part of the filename.
*
* Usage: <modelfile.ext>.<tx>,<ty>,<tz>.globe
* where:
* <modelfile.ext> = an model filename.
* <tx> = translation along the X axis.
* <ty> = translation along the Y axis.
* <tz> = translation along the Z axis.
*
* example: osgviewer cow.osg.25,0,0.trans cessna.osg
*/
class ReaderWriterDBTRANS : public osgDB::ReaderWriter
{
public:
ReaderWriterDBTRANS()
{
supportsExtension(EXTENSION_NAME,"DBTranslation Psuedo loader.");
}
virtual const char* className() const { return "dbtranslation pseudo-loader"; }
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
{
std::string ext = osgDB::getLowerCaseFileExtension(fileName);
if( !acceptsExtension(ext) )
return ReadResult::FILE_NOT_HANDLED;
osg::notify(osg::INFO) << "ReaderWriterDBTRANS( \"" << fileName << "\" )" << std::endl;
// strip the pseudo-loader extension
std::string tmpName = osgDB::getNameLessExtension( fileName );
if (tmpName.empty())
return ReadResult::FILE_NOT_HANDLED;
std::string subFileName, params;
if (!getFilenameAndParams(tmpName, subFileName, params))
{
return ReadResult::FILE_NOT_HANDLED;
}
if( subFileName.empty())
{
osg::notify(osg::WARN) << "Missing subfilename for " EXTENSION_NAME " pseudo-loader" << std::endl;
return ReadResult::FILE_NOT_HANDLED;
}
osg::notify(osg::INFO) << " params = \"" << params << "\"" << std::endl;
osg::notify(osg::INFO) << " subFileName = \"" << subFileName << "\"" << std::endl;
float tx, ty, tz;
int count = sscanf( params.c_str(), "%f,%f,%f", &tx, &ty, &tz );
if( count != 3 )
{
osg::notify(osg::WARN) << "Bad parameters for " EXTENSION_NAME " pseudo-loader: \"" << params << "\"" << std::endl;
return ReadResult::FILE_NOT_HANDLED;
}
// recursively load the subfile.
//osg::Node *node = osgDB::readNodeFile( subFileName, options );
osg::Node* node=readNodeFileFromDB(subFileName,options);
if( !node )
{
// propagate the read failure upwards
osg::notify(osg::WARN) << "Subfile \"" << subFileName << "\" could not be loaded" << std::endl;
return ReadResult::FILE_NOT_HANDLED;
}
osg::MatrixTransform *xform = new osg::MatrixTransform;
xform->setDataVariance( osg::Object::STATIC );
xform->setMatrix( osg::Matrix::translate( tx, ty, tz ) );
xform->addChild( node );
return xform;
}
};
// Add ourself to the Registry to instantiate the reader/writer.
REGISTER_OSGPLUGIN(DBtrans, ReaderWriterDBTRANS)
请各位高手指点 |
|