From b147a22af1c65301787ced651b308693336c4ef3 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 26 Nov 2008 11:45:33 +0000 Subject: [PATCH] From BjornHein, "attached a proposal for an extension for the the stl-File ReaderWriter. It allows saving of an osg node tree as stl file in ASCII-Format. Standard is to generate one stl file. With an additional option it is possible to write one file per Geode. This option is not very "useful" for typical application, I use it for separating and conversion of geometric data. So it could be removed if considered to special." --- src/osgPlugins/stl/ReaderWriterSTL.cpp | 110 +++++++++++++++++++++++- src/osgWrappers/osgDB/DatabasePager.cpp | 29 +++++++ 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/src/osgPlugins/stl/ReaderWriterSTL.cpp b/src/osgPlugins/stl/ReaderWriterSTL.cpp index 7c3ffed36..7a45cd103 100644 --- a/src/osgPlugins/stl/ReaderWriterSTL.cpp +++ b/src/osgPlugins/stl/ReaderWriterSTL.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -50,6 +51,7 @@ public: supportsExtension("stl","STL binary format"); supportsExtension("sta","STL ASCII format"); supportsOption("smooth", "run SmoothingVisitor"); + supportsOption("separateFiles", "Save every geode in a different file. Can be a Huge amount of Files!!!"); } virtual const char* className() const { @@ -57,7 +59,7 @@ public: } virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*) const; - + virtual WriteResult writeNode(const osg::Node& /*node*/,const std::string& /*fileName*/,const Options* =NULL) const ; private: struct ReaderObject @@ -76,6 +78,94 @@ private: bool readStlAscii(FILE* fp); bool readStlBinary(FILE* fp); }; + + class CreateStlVisitor : public osg::NodeVisitor { + public: + + CreateStlVisitor( std::string const & fout, const osgDB::ReaderWriter::Options* options = 0): osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN ), counter(0), m_fout(fout), m_options(options) { + if (options && (options->getOptionString() == "separateFiles")) { + osg::notify(osg::INFO) << "ReaderWriterSTL::writeNode: Files are seperated written" << std::endl; + } else { + m_f = new std::ofstream(m_fout.c_str()); + *m_f << "solid " << counter << std::endl; + } + }; + + std::string i2s( int i) { + char buf[16]; // -2^31 == -2147483648 needs 11 chars + \0 -> 12 (+4 for security ;-) + sprintf(buf,"%d",i); + return buf; + } + + virtual void apply( osg::Geode& node ){ + osg::Matrix mat = osg::computeLocalToWorld( getNodePath() ); + + if (m_options && (m_options->getOptionString() == "separateFiles")) { + std::string sepFile = m_fout + i2s(counter); + m_f = new std::ofstream(sepFile.c_str()); + *m_f << "solid " << std::endl; + } + + for ( unsigned int i = 0; i < node.getNumDrawables(); ++i ) { + osg::TriangleFunctor tf; + tf.m_stream = m_f; + tf.m_mat = mat; + node.getDrawable( i )->accept( tf ); + } + + if (m_options && (m_options->getOptionString() == "separateFiles")) { + *m_f << "endsolid " << std::endl; + m_f->close(); + delete m_f; + } + + ++counter; + traverse(node); + + } + // nHandle->SetLocation( Frame( mat ) ); + ~CreateStlVisitor() { + if (m_options && (m_options->getOptionString() == "separateFiles")) { + osg::notify(osg::INFO) << "ReaderWriterSTL::writeNode: " << counter-1 << "Files were written" << std::endl; + } else { + *m_f << "endsolid " << std::endl; + m_f->close(); + delete m_f; + } + } + private: + int counter; + std::ofstream* m_f; + std::string m_fout; + osgDB::ReaderWriter::Options const * m_options; + + + struct PushPoints { + std::ofstream* m_stream; + osg::Matrix m_mat; + inline void operator () ( const osg::Vec3& _v1, const osg::Vec3& _v2, const osg::Vec3& _v3, bool treatVertexDataAsTemporary ) { + osg::Vec3 v1 = _v1 * m_mat; + osg::Vec3 v2 = _v2 * m_mat; + osg::Vec3 v3 = _v3 * m_mat; + osg::Vec3 vV1V2 = v2-v1; + osg::Vec3 vV1V3 = v3-v1; + osg::Vec3 vNormal = vV1V2.operator ^(vV1V3); + *m_stream << "facet normal " << vNormal[0] << " " << vNormal[1] << " " << vNormal[2] << std::endl; + *m_stream << "outer loop" << std::endl; + *m_stream << "vertex " << v1[0] << " " << v1[1] << " " << v1[2] << std::endl; + *m_stream << "vertex " << v2[0] << " " << v2[1] << " " << v2[2] << std::endl; + *m_stream << "vertex " << v3[0] << " " << v3[1] << " " << v3[2] << std::endl; + *m_stream << "endloop" << std::endl; + *m_stream << "endfacet " << std::endl; + } + + }; + + + }; + + + }; @@ -355,3 +445,21 @@ bool ReaderWriterSTL::ReaderObject::readStlBinary(FILE* fp) return true; } + +osgDB::ReaderWriter::WriteResult ReaderWriterSTL::writeNode(const osg::Node& node,const std::string& fout, const Options* opts) const { + std::string ext = osgDB::getLowerCaseFileExtension(fout); + if (ext != "stl" ){ + // sta - extension implies STL-Binary... + osg::notify(osg::FATAL) << "ReaderWriterSTL::writeNode: Only STL-ASCII-files supported'" << std::endl; + return WriteResult::FILE_NOT_HANDLED; + } + + try { + CreateStlVisitor createStlVisitor( fout, opts ); + const_cast(node).accept( createStlVisitor ); + } catch(...) { + return WriteResult::ERROR_IN_WRITING_FILE; + } + + return WriteResult::FILE_SAVED; +} diff --git a/src/osgWrappers/osgDB/DatabasePager.cpp b/src/osgWrappers/osgDB/DatabasePager.cpp index 0cfce857c..329502d0f 100644 --- a/src/osgWrappers/osgDB/DatabasePager.cpp +++ b/src/osgWrappers/osgDB/DatabasePager.cpp @@ -334,6 +334,16 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) __unsigned_int__getDataToCompileListSize, "Report how many items are in the _dataToCompileList queue. ", ""); + I_Method0(unsigned int, getDataToMergeListSize, + Properties::NON_VIRTUAL, + __unsigned_int__getDataToMergeListSize, + "Report how many items are in the _dataToCompileList queue. ", + ""); + I_Method0(bool, getRequestsInProgress, + Properties::NON_VIRTUAL, + __bool__getRequestsInProgress, + "Report whether any requests are in the pager. ", + ""); I_Method0(double, getMinimumTimeToMergeTile, Properties::NON_VIRTUAL, __double__getMinimumTimeToMergeTile, @@ -417,6 +427,9 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) I_SimpleProperty(unsigned int, DataToCompileListSize, __unsigned_int__getDataToCompileListSize, 0); + I_SimpleProperty(unsigned int, DataToMergeListSize, + __unsigned_int__getDataToMergeListSize, + 0); I_SimpleProperty(bool, DatabasePagerThreadPause, __bool__getDatabasePagerThreadPause, __void__setDatabasePagerThreadPause__bool); @@ -463,6 +476,9 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager) I_SimpleProperty(int, ReleaseFrames, __int__getReleaseFrames, __void__setReleaseFrames__int); + I_SimpleProperty(bool, RequestsInProgress, + __bool__getRequestsInProgress, + 0); I_SimpleProperty(OpenThreads::Thread::ThreadPriority, SchedulePriority, 0, __int__setSchedulePriority__OpenThreads_Thread_ThreadPriority); @@ -500,6 +516,16 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager::DatabaseThread) __bool__getDone, "", ""); + I_Method1(void, setActive, IN, bool, active, + Properties::NON_VIRTUAL, + __void__setActive__bool, + "", + ""); + I_Method0(bool, getActive, + Properties::NON_VIRTUAL, + __bool__getActive, + "", + ""); I_Method0(int, cancel, Properties::VIRTUAL, __int__cancel, @@ -510,6 +536,9 @@ BEGIN_OBJECT_REFLECTOR(osgDB::DatabasePager::DatabaseThread) __void__run, "Thread's run method. ", "Must be implemented by derived classes. This is where the action happens. "); + I_SimpleProperty(bool, Active, + __bool__getActive, + __void__setActive__bool); I_SimpleProperty(bool, Done, __bool__getDone, __void__setDone__bool);