From 6a04fc3deeca173dd80262c271200890e8b1984b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sat, 3 Aug 2002 18:11:21 +0000 Subject: [PATCH] Integrated Ulrich Hertlien's osg::Sequence node, and osgsequence demo, and support for osg::Sequence in the pfb loader. --- AUTHORS | 2 + Make/makedirdefs | 1 + .../Demos/osgsequence/osgsequence.cpp | 95 +++++++++ VisualStudio/VisualStudio.dsw | 54 +++++ VisualStudio/osg/osg.dsp | 8 + VisualStudio/osgPlugins/iv/iv.dsp | 8 + include/osg/NodeVisitor | 2 + include/osg/Sequence | 95 +++++++++ src/Demos/osgsequence/Makefile | 15 ++ src/Demos/osgsequence/Makefile.inst | 11 + src/Demos/osgsequence/osgsequence.cpp | 194 ++++++++++++++++++ src/osg/Makefile | 3 +- src/osg/Sequence.cpp | 172 ++++++++++++++++ src/osg/Texture.cpp | 5 + src/osgDB/DynamicLibrary.cpp | 7 +- src/osgPlugins/osg/Makefile | 1 + src/osgPlugins/osg/Sequence.cpp | 157 ++++++++++++++ src/osgPlugins/pfb/ConvertFromPerformer.cpp | 49 ++++- src/osgPlugins/pfb/ReaderWriterPFB.cpp | 33 ++- 19 files changed, 894 insertions(+), 18 deletions(-) create mode 100644 VisualStudio/Demos/osgsequence/osgsequence.cpp create mode 100644 include/osg/Sequence create mode 100644 src/Demos/osgsequence/Makefile create mode 100644 src/Demos/osgsequence/Makefile.inst create mode 100644 src/Demos/osgsequence/osgsequence.cpp create mode 100644 src/osg/Sequence.cpp create mode 100644 src/osgPlugins/osg/Sequence.cpp diff --git a/AUTHORS b/AUTHORS index 7a26ae7a3..a810bc082 100644 --- a/AUTHORS +++ b/AUTHORS @@ -62,6 +62,8 @@ Randall Hopper Ulrich Hertlein - support for IBM Mirror Repeat extension in osg::Texture - support for texture subloading in osg::Texture + - osg::Sequence support. + - improvements to the pfb loader. - .lwo and .obj plugins. Axel Volley diff --git a/Make/makedirdefs b/Make/makedirdefs index 415671036..f0c7e5457 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -86,6 +86,7 @@ DEMOS_DIRS = \ osgreflect\ osgscribe\ osgstereoimage\ + osgsequence\ osgtext\ osgtexture\ osgviews\ diff --git a/VisualStudio/Demos/osgsequence/osgsequence.cpp b/VisualStudio/Demos/osgsequence/osgsequence.cpp new file mode 100644 index 000000000..e76282260 --- /dev/null +++ b/VisualStudio/Demos/osgsequence/osgsequence.cpp @@ -0,0 +1,95 @@ +# Microsoft Developer Studio Project File - Name="Demo osgsequence" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Demo osgsequence - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "osgsequence.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "osgsequence.mak" CFG="Demo osgsequence - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Demo osgsequence - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Demo osgsequence - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Demo osgsequence - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgsequence.exe" /libpath:"../../../lib" + +!ELSEIF "$(CFG)" == "Demo osgsequence - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /FR /YX /FD /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glut32.lib glu32.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgsequenced.exe" /pdbtype:sept /libpath:"../../../lib" +# SUBTRACT LINK32 /incremental:no + +!ENDIF + +# Begin Target + +# Name "Demo osgsequence - Win32 Release" +# Name "Demo osgsequence - Win32 Debug" +# Begin Source File + +SOURCE=..\..\..\src\Demos\osgsequence\osgsequence.cpp +# End Source File +# End Target +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Project diff --git a/VisualStudio/VisualStudio.dsw b/VisualStudio/VisualStudio.dsw index 08906acf4..d76e3ad89 100644 --- a/VisualStudio/VisualStudio.dsw +++ b/VisualStudio/VisualStudio.dsw @@ -1104,6 +1104,60 @@ Package=<4> +Project: "Demo osgsequence"=.\Demos\osgsequence\osgsequence.dsp - Package Owner=<4> + + + +Package=<5> + +{{{ + +}}} + + + +Package=<4> + +{{{ + + Begin Project Dependency + + Project_Dep_Name Core osg + + End Project Dependency + + Begin Project Dependency + + Project_Dep_Name Core osgDB + + End Project Dependency + + Begin Project Dependency + + Project_Dep_Name Core osgGA + + End Project Dependency + + Begin Project Dependency + + Project_Dep_Name Core osgGLUT + + End Project Dependency + + Begin Project Dependency + + Project_Dep_Name Core osgUtil + + End Project Dependency + +}}} + + + +############################################################################### + + + Project: "Demo osgstereoimage"=.\Demos\osgstereoimage\osgstereoimage.dsp - Package Owner=<4> diff --git a/VisualStudio/osg/osg.dsp b/VisualStudio/osg/osg.dsp index 47898d2e3..744d4922c 100755 --- a/VisualStudio/osg/osg.dsp +++ b/VisualStudio/osg/osg.dsp @@ -329,6 +329,10 @@ SOURCE=..\..\src\osg\Quat.cpp # End Source File # Begin Source File +SOURCE=..\..\src\osg\Sequence.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\osg\ShadeModel.cpp # End Source File # Begin Source File @@ -677,6 +681,10 @@ SOURCE=..\..\Include\Osg\Referenced # End Source File # Begin Source File +SOURCE=..\..\Include\Osg\Sequence +# End Source File +# Begin Source File + SOURCE=..\..\Include\Osg\ShadeModel # End Source File # Begin Source File diff --git a/VisualStudio/osgPlugins/iv/iv.dsp b/VisualStudio/osgPlugins/iv/iv.dsp index e96f50b83..2092632cc 100644 --- a/VisualStudio/osgPlugins/iv/iv.dsp +++ b/VisualStudio/osgPlugins/iv/iv.dsp @@ -157,6 +157,14 @@ SOURCE=..\..\..\src\osgPlugins\iv\indexedfaceset.h # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\iv\atrvec3list.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\iv\indexedtristripset.h +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\iv\ltstr.h # End Source File # Begin Source File diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index c38dab9a5..3bcc98ff1 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -23,6 +23,7 @@ class Switch; class Impostor; class EarthSky; class OccluderNode; +class Sequence; /** Visitor for type safe operations on osg::Node's. Based on GOF's Visitor pattern. The NodeVisitor @@ -177,6 +178,7 @@ class SG_EXPORT NodeVisitor : public Referenced virtual void apply(Projection& node) { apply((Group&)node); } virtual void apply(Transform& node) { apply((Group&)node); } virtual void apply(Switch& node) { apply((Group&)node); } + virtual void apply(Sequence& node) { apply((Switch&)node); } virtual void apply(LOD& node) { apply((Group&)node); } virtual void apply(Impostor& node) { apply((LOD&)node); } virtual void apply(EarthSky& node) { apply((Group&)node); } diff --git a/include/osg/Sequence b/include/osg/Sequence new file mode 100644 index 000000000..3d9fa921b --- /dev/null +++ b/include/osg/Sequence @@ -0,0 +1,95 @@ +// -*-c++-*- + +//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield +//Distributed under the terms of the GNU Library General Public License (LGPL) +//as published by the Free Software Foundation. + +#ifndef OSG_SEQUENCE +#define OSG_SEQUENCE 1 + +#include + +namespace osg { + +/** Sequence is a Group node which allows automatic, time based + switching between children. +*/ +class SG_EXPORT Sequence : public Switch +{ +public : + + Sequence(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + Sequence(const Sequence&, const CopyOp& copyop=CopyOp::SHALLOW_COPY); + + META_Node(osg, Sequence); + + virtual void traverse(NodeVisitor& nv); + + /** Set time in seconds for child */ + void setTime(int frame, float t); + + /** Get time for child */ + const float getTime(int frame) const; + + /** Interval modes */ + enum LoopMode { + LOOP, + SWING + }; + + /** Set sequence mode & interval. */ + void setInterval(LoopMode mode, int begin, int end); + + /** Get sequence mode & interval. */ + inline void getInterval(LoopMode& mode, int& begin, int& end) const { + mode = _loopMode; + begin = _begin; + end = _end; + } + + /** Set duration: speed-up & number of repeats */ + void setDuration(float speed, int nreps = -1); + + /** Get duration */ + inline void getDuration(float& speed, int& nreps) const { + speed = _speed; + nreps = _nreps; + } + + /** Sequence modes */ + enum SequenceMode { + START, + STOP, + PAUSE, + RESUME + }; + + /** Set sequence mode. Start/stop & pause/resume. */ + void setMode(SequenceMode mode); + + /** Get sequence mode. */ + inline SequenceMode getMode() const { return _mode; } + +protected : + + virtual ~Sequence() {} + + float _last; + std::vector _frameTime; + + int _step; + + LoopMode _loopMode; + int _begin, _end; + + float _speed; + int _nreps, _nrepsremain; + + SequenceMode _mode; +}; + +} + +#endif diff --git a/src/Demos/osgsequence/Makefile b/src/Demos/osgsequence/Makefile new file mode 100644 index 000000000..134e095d9 --- /dev/null +++ b/src/Demos/osgsequence/Makefile @@ -0,0 +1,15 @@ +TOPDIR = ../../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgsequence.cpp\ + +LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + Makefile.inst=Makefile + +EXEC = osgsequence + +include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgsequence/Makefile.inst b/src/Demos/osgsequence/Makefile.inst new file mode 100644 index 000000000..3698d4abd --- /dev/null +++ b/src/Demos/osgsequence/Makefile.inst @@ -0,0 +1,11 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgtexture.cpp\ + +LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgtexture + +include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgsequence/osgsequence.cpp b/src/Demos/osgsequence/osgsequence.cpp new file mode 100644 index 000000000..2f13a00d4 --- /dev/null +++ b/src/Demos/osgsequence/osgsequence.cpp @@ -0,0 +1,194 @@ +// -*-c++-*- + +#include +#include +#include + +#include + +#include + +#include +#include + + +// +// A simple demo demonstrating usage of osg::Sequence. +// + +// simple event handler to start/stop sequences +class MyEventHandler : public osgGA::GUIEventHandler { +public: + /// Constructor. + MyEventHandler(std::vector* seq) : GUIEventHandler() { + _seq = seq; + } + + /// Handle events. + virtual bool handle(const osgGA::GUIEventAdapter& ea, + osgGA::GUIActionAdapter&) { + bool handled = false; + + if (ea.getEventType() == osgGA::GUIEventAdapter::KEYBOARD) { + const char keys[] = "!@#$%^&*()"; + for (unsigned int i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) { + if (i < _seq->size() && ea.getKey() == keys[i]) { + // toggle sequence + osg::Sequence* seq = (*_seq)[i]; + osg::Sequence::SequenceMode mode = seq->getMode(); + switch (mode) { + case osg::Sequence::START: + seq->setMode(osg::Sequence::PAUSE); + break; + case osg::Sequence::STOP: + seq->setMode(osg::Sequence::START); + break; + case osg::Sequence::PAUSE: + seq->setMode(osg::Sequence::RESUME); + break; + default: + break; + } + cerr << "Toggled sequence " << i << endl; + handled = true; + } + } + } + + return handled; + } + + /// accept visits. + virtual void accept(osgGA::GUIEventHandlerVisitor&) { } + +private: + std::vector* _seq; +}; + +void write_usage(std::ostream& out, const std::string& name) +{ + out << std::endl; + out <<"usage:"<< std::endl; + out <<" "<& model) +{ + osg::Sequence* seqNode = osgNew osg::Sequence; + + // add children, show each child for 1.0 seconds + for (unsigned int i = 0; i < model.size(); i++) { + seqNode->addChild(model[i]); + seqNode->setTime(i, 1.0f); + } + + // interval + seqNode->setInterval(mode, 0, -1); + + // speed-up factor and number of repeats for entire sequence + seqNode->setDuration(speed, nreps); + + // stopped + seqNode->setMode(osg::Sequence::STOP); + + return seqNode; +} + +int main( int argc, char **argv ) +{ + // initialize the GLUT + glutInit( &argc, argv ); + + if (argc < 2) + { + write_usage(osg::notify(osg::NOTICE), argv[0]); + return 0; + } + + // create commandline args + std::vector commandLine; + for (int i = 1; i < argc; i++) + commandLine.push_back(argv[i]); + + // initialize the viewer + osgGLUT::Viewer viewer; + viewer.setWindowTitle(argv[0]); + + // configure the viewer from the commandline arguments, and eat any + // parameters that have been matched. + viewer.readCommandLine(commandLine); + + // assumes any remaining parameters are models + std::vector model; + for (unsigned int i = 0; i < commandLine.size(); i++) { + cerr << "Loading " << commandLine[i] << endl; + osg::Node* node = osgDB::readNodeFile(commandLine[i]); + if (node) + model.push_back(node); + } + if (model.empty()) { + write_usage(osg::notify(osg::NOTICE),argv[0]); + return -1; + } + + // root + osg::Group* rootNode = osgNew osg::Group; + + // create sequences + std::vector seq; + + const osg::Sequence::LoopMode mode[] = { osg::Sequence::LOOP, + osg::Sequence::SWING, + osg::Sequence::LOOP }; + const float speed[] = { 0.5f, 1.0f, 1.5f }; + const int nreps[] = { -1, 5, 1 }; + + float x = 0.0f; + for (unsigned int i = 0; i < (sizeof(speed) / sizeof(speed[0])); i++) { + osg::Sequence* seqNode = generateSeq(mode[i], speed[i], nreps[i], + model); + if (!seqNode) + continue; + seq.push_back(seqNode); + + // position sequence + osg::Matrix matrix; + matrix.makeTranslate(x, 0.0, 0.0); + + osg::Transform* xform = osgNew osg::Transform; + xform->setMatrix(matrix); + xform->addChild(seqNode); + + rootNode->addChild(xform); + + x += seqNode->getBound()._radius * 1.5f; + } + + // add model to viewer. + viewer.addViewport(rootNode); + + // register additional event handler + viewer.setEventHandler(osgNew MyEventHandler(&seq), 0); + + // register trackball, flight and drive. + viewer.registerCameraManipulator(new osgGA::TrackballManipulator); + + viewer.open(); + viewer.run(); + + return 0; +} diff --git a/src/osg/Makefile b/src/osg/Makefile index 8a909cb33..9e07f8594 100644 --- a/src/osg/Makefile +++ b/src/osg/Makefile @@ -62,6 +62,7 @@ CXXFILES =\ Primitive.cpp\ Projection.cpp\ Quat.cpp\ + Sequence.cpp\ ShadeModel.cpp\ ShadowVolumeOccluder.cpp\ State.cpp\ @@ -77,7 +78,7 @@ CXXFILES =\ Transform.cpp\ Version.cpp\ Viewport.cpp\ - + DEF += -DSG_LIBRARY LIBS += $(GL_LIBS) $(OTHER_LIBS) diff --git a/src/osg/Sequence.cpp b/src/osg/Sequence.cpp new file mode 100644 index 000000000..b4456542e --- /dev/null +++ b/src/osg/Sequence.cpp @@ -0,0 +1,172 @@ +// -*-c++-*- + +#include + +#include + +using namespace osg; + +/** + * Sequence constructor. + */ +Sequence::Sequence() : + Switch(), + _last(-1.0f), + _step(1) +{ + _frameTime.clear(); + setInterval(LOOP, 0, -1); + setMode(STOP); + + setNumChildrenRequiringAppTraversal(1); +} + +Sequence::Sequence(const Sequence& seq, const CopyOp& copyop) : + Switch(seq, copyop), + _last(seq._last), + _frameTime(seq._frameTime), + _step(seq._step) +{ + setInterval(seq._loopMode, seq._begin, seq._end); + setDuration(seq._speed, seq._nreps); + setMode(seq._mode); + + setNumChildrenRequiringAppTraversal(1); +} + +void Sequence::setTime(int frame, float t) +{ + int sz = _frameTime.size(); + //cerr << "sz=" << sz << " frame=" << frame << endl; + if (frame < sz) + _frameTime[frame] = t; + else + for (int i = sz; i < (frame+1); i++) { + _frameTime.push_back(t); + } +} + +const float Sequence::getTime(int frame) const +{ + if (frame >= 0 && frame < (int) _frameTime.size()) + return _frameTime[frame]; + else + return -1.0f; +} + +void Sequence::setInterval(LoopMode mode, int begin, int end) +{ + _loopMode = mode; + _begin = begin; + _end = end; + + // switch to beginning of interval + unsigned int nch = getNumChildren(); + begin = (_begin < 0 ? nch + _begin : _begin); + end = (_end < 0 ? nch + _end : _end); + + setValue(begin); + _step = (begin < end ? 1 : -1); +} + +void Sequence::setDuration(float speed, int nreps) +{ + _speed = (speed <= 0.0f ? 0.0f : speed); + _nreps = (nreps < 0 ? -1 : nreps); + _nrepsremain = _nreps; +} + +void Sequence::setMode(SequenceMode mode) +{ + switch (mode) { + case START: + // restarts sequence in 'traverse' + setValue(ALL_CHILDREN_OFF); + _mode = mode; + break; + case STOP: + _mode = mode; + break; + case PAUSE: + if (_mode == START) + _mode = PAUSE; + break; + case RESUME: + if (_mode == PAUSE) + _mode = START; + break; + } +} + +void Sequence::traverse(NodeVisitor& nv) +{ + osgUtil::AppVisitor* app = dynamic_cast(&nv); + if (app && _mode == START && _nrepsremain) { + double t = nv.getFrameStamp()->getReferenceTime(); + if (_last == -1.0) + _last = t; + + // first and last frame of interval + unsigned int nch = getNumChildren(); + int begin = (_begin < 0 ? nch + _begin : _begin); + int end = (_end < 0 ? nch + _end : _end); + + int sw = getValue(); + if (sw == ALL_CHILDREN_OFF || sw == ALL_CHILDREN_ON) { + sw = begin; + _step = (begin < end ? 1 : -1); + } + + // default timeout for unset values + if (sw >= (int) _frameTime.size()) { + setTime(sw, 1.0f); + } + + // frame time-out? + float dur = _frameTime[sw] * _speed; + if ((t - _last) > dur) { + + sw += _step; + + // check interval + int ibegin = (begin < end ? begin : end); + int iend = (end > begin ? end : begin); + //cerr << this << " interval " << ibegin << "," << iend << endl; + + if (sw < ibegin || sw > iend) { + // stop at last frame + if (sw < ibegin) + sw = ibegin; + else + sw = iend; + + // repeat counter + if (_nrepsremain > 0) + _nrepsremain--; + + if (_nrepsremain == 0) { + // stop + setMode(STOP); + } + else { + // wrap around + switch (_loopMode) { + case LOOP: + //cerr << this << " loop" << endl; + sw = begin; + break; + case SWING: + //cerr << this << " swing" << endl; + _step = -_step; + break; + } + } + } + + _last = t; + } + //cerr << this << " child=" << sw << endl; + setValue(sw); + } + Switch::traverse(nv); +} diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index d991bf2b0..e9a7902bd 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -207,6 +207,11 @@ void Texture::dirtyTextureObject() void Texture::apply(State& state) const { +// Texture* texture = const_cast(this); +// texture->_min_filter = LINEAR_MIPMAP_LINEAR; +// texture->_mag_filter = ANISOTROPIC; + + // get the contextID (user defined ID of 0 upwards) for the // current OpenGL context. const uint contextID = state.getContextID(); diff --git a/src/osgDB/DynamicLibrary.cpp b/src/osgDB/DynamicLibrary.cpp index df2ff97f8..215b736ac 100644 --- a/src/osgDB/DynamicLibrary.cpp +++ b/src/osgDB/DynamicLibrary.cpp @@ -108,7 +108,12 @@ DynamicLibrary::PROC_ADDRESS DynamicLibrary::getProcAddress(const std::string& p return NULL; } #else // other unix - return dlsym( _handle, procName.c_str() ); + void* sym = dlsym( _handle, procName.c_str() ); + if (!sym) { + notify(WARN) << "DynamicLibrary::failed looking up " << procName << std::endl; + notify(WARN) << "DynamicLibrary::error " << dlerror() << std::endl; + } + return sym; #endif return NULL; } diff --git a/src/osgPlugins/osg/Makefile b/src/osgPlugins/osg/Makefile index cf03022af..477239938 100644 --- a/src/osgPlugins/osg/Makefile +++ b/src/osgPlugins/osg/Makefile @@ -39,6 +39,7 @@ CXXFILES =\ ReaderWriterOSG.cpp\ ShadeModel.cpp\ StateSet.cpp\ + Sequence.cpp\ Stencil.cpp\ Switch.cpp\ TexEnv.cpp\ diff --git a/src/osgPlugins/osg/Sequence.cpp b/src/osgPlugins/osg/Sequence.cpp new file mode 100644 index 000000000..b2de2cfbe --- /dev/null +++ b/src/osgPlugins/osg/Sequence.cpp @@ -0,0 +1,157 @@ +#include "osg/Sequence" + +#include "osgDB/Registry" +#include "osgDB/Input" +#include "osgDB/Output" + +using namespace osg; +using namespace osgDB; + +// forward declare functions to use later. +bool Sequence_readLocalData(Object& obj, Input& fr); +bool Sequence_writeLocalData(const Object& obj, Output& fw); + +// register the read and write functions with the osgDB::Registry. +RegisterDotOsgWrapperProxy g_SequenceProxy +( + osgNew osg::Sequence, + "Sequence", + "Object Node Group Switch Sequence", + &Sequence_readLocalData, + &Sequence_writeLocalData +); + +static bool Sequence_matchLoopMode(const char* str, + Sequence::LoopMode& mode) +{ + if (strcmp(str, "LOOP") == 0) + mode = Sequence::LOOP; + else if (strcmp(str, "SWING") == 0) + mode = Sequence::SWING; + else + return false; + + return true; +} + +static const char* Sequence_getLoopMode(Sequence::LoopMode mode) +{ + switch (mode) { + case Sequence::SWING: + return "SWING"; + case Sequence::LOOP: + default: + return "LOOP"; + } +} + +// only storing 'START' and 'STOP' since 'PAUSE' doesn't make sense to me +static bool Sequence_matchSeqMode(const char* str, + Sequence::SequenceMode& mode) +{ + if (strcmp(str, "START") == 0) + mode = Sequence::START; + else if (strcmp(str, "STOP") == 0) + mode = Sequence::STOP; + else + return false; + + return true; +} + +static const char* Sequence_getSeqMode(Sequence::SequenceMode mode) +{ + switch (mode) { + case Sequence::START: + return "START"; + default: + return "STOP"; + } +} + +bool Sequence_readLocalData(Object& obj, Input& fr) +{ + bool iteratorAdvanced = false; + + Sequence& sw = static_cast(obj); + + if (fr.matchSequence("frameTime {")) { + int entry = fr[0].getNoNestedBrackets(); + fr += 2; + + int i = 0; + while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) { + float t; + if (fr[0].getFloat(t)) { + sw.setTime(i, t); + ++fr; + i++; + } + } + + iteratorAdvanced = true; + ++fr; + } + else if (fr.matchSequence("interval")) { + Sequence::LoopMode mode; + int begin, end; + if (Sequence_matchLoopMode(fr[1].getStr(), mode) && + fr[2].getInt(begin) && fr[3].getInt(end)) { + sw.setInterval(mode, begin, end); + iteratorAdvanced = true; + fr += 4; + } + } + else if (fr.matchSequence("duration")) { + if (fr[1].isFloat() && fr[2].isInt()) { + float speed; + int nreps; + fr[1].getFloat(speed); + fr[2].getInt(nreps); + sw.setDuration(speed, nreps); + iteratorAdvanced = true; + fr += 3; + } + } + else if (fr.matchSequence("mode")) { + Sequence::SequenceMode mode; + if (Sequence_matchSeqMode(fr[1].getStr(), mode)) { + sw.setMode(mode); + iteratorAdvanced = true; + fr += 2; + } + } + + return iteratorAdvanced; +} + +bool Sequence_writeLocalData(const Object& obj, Output& fw) +{ + const Sequence& sw = static_cast(obj); + + // frame times + fw.indent() << "frameTime {" << std::endl; + fw.moveIn(); + for (unsigned int i = 0; i < sw.getNumChildren(); i++) { + fw.indent() << sw.getTime(i) << std::endl; + } + fw.moveOut(); + fw.indent() << "}" << std::endl; + + // loop mode & interval + Sequence::LoopMode mode; + int begin, end; + sw.getInterval(mode, begin, end); + fw.indent() << "interval " << Sequence_getLoopMode(mode) << " " << begin << " " << end << std::endl; + + // duration + float speed; + int nreps; + sw.getDuration(speed, nreps); + fw.indent() << "duration " << speed << " " << nreps << std::endl; + + // sequence mode + fw.indent() << "mode " << Sequence_getSeqMode(sw.getMode()) << std::endl; + + return true; +} diff --git a/src/osgPlugins/pfb/ConvertFromPerformer.cpp b/src/osgPlugins/pfb/ConvertFromPerformer.cpp index 4306a4d75..685047559 100644 --- a/src/osgPlugins/pfb/ConvertFromPerformer.cpp +++ b/src/osgPlugins/pfb/ConvertFromPerformer.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -254,23 +255,25 @@ osg::Node* ConvertFromPerformer::visitSwitch(osg::Group* osgParent,pfSwitch* swi } -osg::Node* ConvertFromPerformer::visitSequence(osg::Group* osgParent,pfSequence* sequence) +osg::Node* ConvertFromPerformer::visitSequence(osg::Group* osgParent, + pfSequence* sequence) { - osg::notify(osg::WARN)<<"Warning : cannot convert pfSequence as no osg::Sequence exists, using osg::Switch instead."<(getOsgObject(sequence)); + osg::Sequence* osgSequence = dynamic_cast(getOsgObject(sequence)); if (osgSequence) { if (osgParent) osgParent->addChild(osgSequence); return osgSequence; } - osgSequence = new osg::Switch; + osgSequence = new osg::Sequence; if (osgParent) osgParent->addChild(osgSequence); registerPfObjectForOsgObject(sequence,osgSequence); +#if 0 if (sequence->getNumChildren()>0) { // set switch to first child as a 'hack' to prevent all @@ -279,11 +282,44 @@ osg::Node* ConvertFromPerformer::visitSequence(osg::Group* osgParent,pfSequence* // be removed. osgSequence->setValue(0); } +#endif + // add children for(int i=0;igetNumChildren();++i) { + osgSequence->setTime(i, sequence->getTime(i)); visitNode(osgSequence,sequence->getChild(i)); } + + // interval + int mode, begin, end; + sequence->getInterval(&mode, &begin, &end); + + osg::Sequence::LoopMode loopMode = osg::Sequence::LOOP; + if (mode == PFSEQ_SWING) + loopMode = osg::Sequence::SWING; + osgSequence->setInterval(loopMode, begin, end); + + // duration + float speed; + int repeat; + sequence->getDuration(&speed, &repeat); + osgSequence->setDuration(speed, repeat); + + // mode + mode = sequence->getMode(); + + osg::Sequence::SequenceMode seqMode = osg::Sequence::START; + switch (mode) { + case PFSEQ_STOP: + seqMode = osg::Sequence::STOP; + break; + case PFSEQ_PAUSE: + seqMode = osg::Sequence::PAUSE; + break; + } + osgSequence->setMode(seqMode); + return (osg::Node*)osgSequence; } @@ -483,6 +519,7 @@ osg::Drawable* ConvertFromPerformer::visitGeoSet(osg::Geode* osgGeode,pfGeoSet* // and then convert back to a osg::Geometry afterwards. //osg::ref_ptr osgGeoSet = new osg::GeoSet; osg::GeoSet* osgGeoSet = new osg::GeoSet; + osgGeoSet->ref(); int i; @@ -714,7 +751,7 @@ osg::Drawable* ConvertFromPerformer::visitGeoSet(osg::Geode* osgGeode,pfGeoSet* osgGeode->addDrawable(osgDrawable); registerPfObjectForOsgObject(geoset,osgDrawable); } - + osgGeoSet->unref(); return osgDrawable; } @@ -1191,7 +1228,7 @@ osg::Texture* ConvertFromPerformer::visitTexture(osg::StateSet* osgStateSet,pfTe unsigned int dataType = GL_UNSIGNED_BYTE; // copy image data - int size = s * t * comp; + int size = s * t * r * comp; unsigned char* data = (unsigned char*) malloc(size); memcpy(data, imageData, size); diff --git a/src/osgPlugins/pfb/ReaderWriterPFB.cpp b/src/osgPlugins/pfb/ReaderWriterPFB.cpp index 496cc89c2..bc04be2dd 100644 --- a/src/osgPlugins/pfb/ReaderWriterPFB.cpp +++ b/src/osgPlugins/pfb/ReaderWriterPFB.cpp @@ -102,6 +102,7 @@ class ReaderWriterPFB : public osgDB::ReaderWriter initPerformer(); pfTexture* tex = new pfTexture; + tex->ref(); if (tex->loadFile(fileName.c_str())) { int s=0; @@ -116,23 +117,34 @@ class ReaderWriterPFB : public osgDB::ReaderWriter unsigned int pixelFormat = comp == 1 ? GL_LUMINANCE : - comp == 2 ? GL_LUMINANCE_ALPHA : - comp == 3 ? GL_RGB : - comp == 4 ? GL_RGBA : (GLenum)-1; + comp == 2 ? GL_LUMINANCE_ALPHA : + comp == 3 ? GL_RGB : + comp == 4 ? GL_RGBA : (GLenum)-1; unsigned int dataType = GL_UNSIGNED_BYTE; + // copy image data + int size = s * t * r * comp; + unsigned char* data = (unsigned char*) malloc(size); + memcpy(data, imageData, size); + osg::Image* image = new osg::Image; image->setFileName(fileName.c_str()); image->setImage(s,t,r, - internalFormat, - pixelFormat, - dataType, - (unsigned char*)imageData); + internalFormat, + pixelFormat, + dataType, + data); + + // free texture & image data + tex->unrefDelete(); return image; } + // free texture & image data + tex->unrefDelete(); + return ReadResult::FILE_NOT_HANDLED; } @@ -146,12 +158,13 @@ class ReaderWriterPFB : public osgDB::ReaderWriter initPerformer(); pfNode* root = pfdLoadFile(fileName.c_str()); - if (root) { - + root->ref(); ConvertFromPerformer converter; - return converter.convert(root); + osg::Node* node = converter.convert(root); + root->unrefDelete(); + return node; } else {