Introduced first cut of Present3D integration with the core OSG with the introduction of a .p3d plugin.

This commit is contained in:
Robert Osfield 2009-04-27 11:02:18 +00:00
parent 5f26d6ec99
commit 200c9e82f3
14 changed files with 6363 additions and 0 deletions

View File

@ -325,6 +325,7 @@ FIND_PACKAGE(OurDCMTK)
FIND_PACKAGE(OpenAL)
FIND_PACKAGE(XUL)
FIND_PACKAGE(FFmpeg)
FIND_PACKAGE(LibXml2)
#use pkg-config to find various modues
INCLUDE(FindPkgConfig OPTIONAL)

View File

@ -134,6 +134,10 @@ ENDIF()
ADD_SUBDIRECTORY(3dc)
IF(LIBXML2_FOUND)
ADD_SUBDIRECTORY(p3d)
ENDIF()
IF(CURL_FOUND)
ADD_SUBDIRECTORY(curl)
ENDIF()

View File

@ -0,0 +1,235 @@
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and/or modified under
* the terms of the GNU General Public License (GPL) version 2.0.
* The full license is in LICENSE.txt file included with this distribution,.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* include LICENSE.txt for more details.
*/
#include "AnimationMaterial.h"
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/Notify>
#include <osg/io_utils>
using namespace ss3d;
void AnimationMaterial::insert(double time,osg::Material* material)
{
_timeControlPointMap[time] = material;
}
bool AnimationMaterial::getMaterial(double time,osg::Material& material) const
{
if (_timeControlPointMap.empty()) return false;
switch(_loopMode)
{
case(SWING):
{
double modulated_time = (time - getFirstTime())/(getPeriod()*2.0);
double fraction_part = modulated_time - floor(modulated_time);
if (fraction_part>0.5) fraction_part = 1.0-fraction_part;
time = getFirstTime()+(fraction_part*2.0) * getPeriod();
break;
}
case(LOOP):
{
double modulated_time = (time - getFirstTime())/getPeriod();
double fraction_part = modulated_time - floor(modulated_time);
time = getFirstTime()+fraction_part * getPeriod();
break;
}
case(NO_LOOPING):
// no need to modulate the time.
break;
}
TimeControlPointMap::const_iterator second = _timeControlPointMap.lower_bound(time);
if (second==_timeControlPointMap.begin())
{
material = *(second->second);
}
else if (second!=_timeControlPointMap.end())
{
TimeControlPointMap::const_iterator first = second;
--first;
// we have both a lower bound and the next item.
// deta_time = second.time - first.time
double delta_time = second->first - first->first;
if (delta_time==0.0)
material = *(first->second);
else
{
interpolate(material,(time - first->first)/delta_time, *first->second, *second->second);
}
}
else // (second==_timeControlPointMap.end())
{
material = *(_timeControlPointMap.rbegin()->second);
}
return true;
}
template<class T>
T interp(float r, const T& lhs, const T& rhs)
{
return lhs*(1.0f-r)+rhs*r;
}
void AnimationMaterial::interpolate(osg::Material& material, float r, const osg::Material& lhs,const osg::Material& rhs) const
{
material.setColorMode(lhs.getColorMode());
material.setAmbient(osg::Material::FRONT_AND_BACK,interp(r, lhs.getAmbient(osg::Material::FRONT),rhs.getAmbient(osg::Material::FRONT)));
if (!material.getAmbientFrontAndBack())
material.setAmbient(osg::Material::BACK,interp(r, lhs.getAmbient(osg::Material::BACK),rhs.getAmbient(osg::Material::BACK)));
material.setDiffuse(osg::Material::FRONT_AND_BACK,interp(r, lhs.getDiffuse(osg::Material::FRONT),rhs.getDiffuse(osg::Material::FRONT)));
if (!material.getDiffuseFrontAndBack())
material.setDiffuse(osg::Material::BACK,interp(r, lhs.getDiffuse(osg::Material::BACK),rhs.getDiffuse(osg::Material::BACK)));
material.setSpecular(osg::Material::FRONT_AND_BACK,interp(r, lhs.getSpecular(osg::Material::FRONT),rhs.getSpecular(osg::Material::FRONT)));
if (!material.getSpecularFrontAndBack())
material.setSpecular(osg::Material::BACK,interp(r, lhs.getSpecular(osg::Material::BACK),rhs.getSpecular(osg::Material::BACK)));
material.setEmission(osg::Material::FRONT_AND_BACK,interp(r, lhs.getEmission(osg::Material::FRONT),rhs.getEmission(osg::Material::FRONT)));
if (!material.getEmissionFrontAndBack())
material.setEmission(osg::Material::BACK,interp(r, lhs.getEmission(osg::Material::BACK),rhs.getEmission(osg::Material::BACK)));
material.setShininess(osg::Material::FRONT_AND_BACK,interp(r, lhs.getShininess(osg::Material::FRONT),rhs.getShininess(osg::Material::FRONT)));
if (!material.getShininessFrontAndBack())
material.setShininess(osg::Material::BACK,interp(r, lhs.getShininess(osg::Material::BACK),rhs.getShininess(osg::Material::BACK)));
}
void AnimationMaterial::read(std::istream& in)
{
while (!in.eof())
{
double time;
osg::Vec4 color;
in >> time >> color[0] >> color[1] >> color[2] >> color[3];
if(!in.eof())
{
osg::Material* material = new osg::Material;
material->setAmbient(osg::Material::FRONT_AND_BACK,color);
material->setDiffuse(osg::Material::FRONT_AND_BACK,color);
insert(time,material);
}
}
}
void AnimationMaterial::write(std::ostream& fout) const
{
const TimeControlPointMap& tcpm = getTimeControlPointMap();
for(TimeControlPointMap::const_iterator tcpmitr=tcpm.begin();
tcpmitr!=tcpm.end();
++tcpmitr)
{
fout<<tcpmitr->first<<" "<<tcpmitr->second->getDiffuse(osg::Material::FRONT)<<std::endl;
}
}
bool AnimationMaterial::requiresBlending() const
{
const TimeControlPointMap& tcpm = getTimeControlPointMap();
for(TimeControlPointMap::const_iterator tcpmitr=tcpm.begin();
tcpmitr!=tcpm.end();
++tcpmitr)
{
if ((tcpmitr->second->getDiffuse(osg::Material::FRONT))[3]!=1.0f) return true;
}
return false;
}
void AnimationMaterialCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (_animationMaterial.valid() &&
nv->getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR &&
nv->getFrameStamp())
{
double time = nv->getFrameStamp()->getReferenceTime();
_latestTime = time;
if (!_pause)
{
// Only update _firstTime the first time, when its value is still DBL_MAX
if (_firstTime==DBL_MAX)
{
osg::notify(osg::INFO)<<"AnimationMaterialCallback::operator() resetting _firstTime to "<<time<<std::endl;
_firstTime = time;
}
update(*node);
}
}
// must call any nested node callbacks and continue subgraph traversal.
NodeCallback::traverse(node,nv);
}
double AnimationMaterialCallback::getAnimationTime() const
{
if (_firstTime==DBL_MAX) return 0.0f;
else return ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier;
}
void AnimationMaterialCallback::update(osg::Node& node)
{
osg::StateSet* stateset = node.getOrCreateStateSet();
osg::Material* material =
dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
if (!material)
{
material = new osg::Material;
stateset->setAttribute(material,osg::StateAttribute::OVERRIDE);
}
_animationMaterial->getMaterial(getAnimationTime(),*material);
}
void AnimationMaterialCallback::reset()
{
#if 1
_firstTime = DBL_MAX;
_pauseTime = DBL_MAX;
#else
_firstTime = _latestTime;
_pauseTime = _latestTime;
#endif
}
void AnimationMaterialCallback::setPause(bool pause)
{
if (_pause==pause)
{
return;
}
_pause = pause;
if (_firstTime==DBL_MAX) return;
if (_pause)
{
_pauseTime = _latestTime;
}
else
{
_firstTime += (_latestTime-_pauseTime);
}
}

View File

@ -0,0 +1,170 @@
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and/or modified under
* the terms of the GNU General Public License (GPL) version 2.0.
* The full license is in LICENSE.txt file included with this distribution,.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* include LICENSE.txt for more details.
*/
#ifndef OSG_ANIMATIONMATERIAL
#define OSG_ANIMATIONMATERIAL 1
#include <osg/Material>
#include <osg/NodeCallback>
#include <map>
#include <float.h>
namespace ss3d {
/** AnimationMaterial for specify the time varying transformation pathway to use when update camera and model objects.
* Subclassed from Transform::ComputeTransformCallback allows AnimationMaterial to
* be attached directly to Transform nodes to move subgraphs around the scene.
*/
class AnimationMaterial : public virtual osg::Object
{
public:
AnimationMaterial():_loopMode(LOOP) {}
AnimationMaterial(const AnimationMaterial& ap, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
Object(ap,copyop),
_timeControlPointMap(ap._timeControlPointMap),
_loopMode(ap._loopMode) {}
META_Object(osg,AnimationMaterial);
/** get the transformation matrix for a point in time.*/
bool getMaterial(double time,osg::Material& material) const;
void insert(double time,osg::Material* material);
double getFirstTime() const { if (!_timeControlPointMap.empty()) return _timeControlPointMap.begin()->first; else return 0.0;}
double getLastTime() const { if (!_timeControlPointMap.empty()) return _timeControlPointMap.rbegin()->first; else return 0.0;}
double getPeriod() const { return getLastTime()-getFirstTime();}
enum LoopMode
{
SWING,
LOOP,
NO_LOOPING
};
void setLoopMode(LoopMode lm) { _loopMode = lm; }
LoopMode getLoopMode() const { return _loopMode; }
typedef std::map<double, osg::ref_ptr<osg::Material> > TimeControlPointMap;
TimeControlPointMap& getTimeControlPointMap() { return _timeControlPointMap; }
const TimeControlPointMap& getTimeControlPointMap() const { return _timeControlPointMap; }
/** read the anumation path from a flat ascii file stream.*/
void read(std::istream& in);
/** write the anumation path to a flat ascii file stream.*/
void write(std::ostream& out) const;
bool requiresBlending() const;
protected:
virtual ~AnimationMaterial() {}
void interpolate(osg::Material& material, float r, const osg::Material& lhs,const osg::Material& rhs) const;
TimeControlPointMap _timeControlPointMap;
LoopMode _loopMode;
};
class AnimationMaterialCallback : public osg::NodeCallback
{
public:
AnimationMaterialCallback():
_timeOffset(0.0),
_timeMultiplier(1.0),
_firstTime(DBL_MAX),
_latestTime(0.0),
_pause(false),
_pauseTime(0.0) {}
AnimationMaterialCallback(const AnimationMaterialCallback& apc,const osg::CopyOp& copyop):
osg::NodeCallback(apc,copyop),
_animationMaterial(apc._animationMaterial),
_useInverseMatrix(apc._useInverseMatrix),
_timeOffset(apc._timeOffset),
_timeMultiplier(apc._timeMultiplier),
_firstTime(apc._firstTime),
_latestTime(apc._latestTime),
_pause(apc._pause),
_pauseTime(apc._pauseTime) {}
META_Object(osg,AnimationMaterialCallback);
AnimationMaterialCallback(AnimationMaterial* ap,double timeOffset=0.0f,double timeMultiplier=1.0f):
_animationMaterial(ap),
_useInverseMatrix(false),
_timeOffset(timeOffset),
_timeMultiplier(timeMultiplier),
_firstTime(DBL_MAX),
_latestTime(0.0),
_pause(false),
_pauseTime(0.0) {}
void setAnimationMaterial(AnimationMaterial* path) { _animationMaterial = path; }
AnimationMaterial* getAnimationMaterial() { return _animationMaterial.get(); }
const AnimationMaterial* getAnimationMaterial() const { return _animationMaterial.get(); }
void setTimeOffset(double offset) { _timeOffset = offset; }
double getTimeOffset() const { return _timeOffset; }
void setTimeMultiplier(double multiplier) { _timeMultiplier = multiplier; }
double getTimeMultiplier() const { return _timeMultiplier; }
void reset();
void setPause(bool pause);
/** get the animation time that is used to specify the position along the AnimationMaterial.
* Animation time is computed from the formula ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier.*/
double getAnimationTime() const;
/** implements the callback*/
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
void update(osg::Node& node);
public:
osg::ref_ptr<AnimationMaterial> _animationMaterial;
bool _useInverseMatrix;
double _timeOffset;
double _timeMultiplier;
double _firstTime;
double _latestTime;
bool _pause;
double _pauseTime;
protected:
~AnimationMaterialCallback(){}
};
}
#endif

View File

@ -0,0 +1,23 @@
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} )
SET(TARGET_EXTERNAL_LIBRARIES ${LIBXML2_LIBRARIES})
SET(TARGET_SRC
SlideShowConstructor.cpp
ReaderWriterP3D.cpp
PickEventHandler.cpp
AnimationMaterial.cpp
SlideEventHandler.cpp
CompileSlideCallback.cpp
)
SET(TARGET_H
SlideShowConstructor.h
PickEventHandler.h
AnimationMaterial.h
SlideEventHandler.h
CompileSlideCallback.h
)
SET(TARGET_ADDED_LIBRARIES osgVolume)
#### end var setup ###
SETUP_PLUGIN(p3d)

View File

@ -0,0 +1,48 @@
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and/or modified under
* the terms of the GNU General Public License (GPL) version 2.0.
* The full license is in LICENSE.txt file included with this distribution,.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* include LICENSE.txt for more details.
*/
#include "CompileSlideCallback.h"
#include <osgUtil/GLObjectsVisitor>
using namespace ss3d;
void CompileSlideCallback::operator()(const osg::Camera & camera) const
{
osg::GraphicsContext* context = const_cast<osg::GraphicsContext*>(camera.getGraphicsContext());
if (!context) return;
osg::State* state = context->getState();
if (!state) return;
const osg::FrameStamp* fs = state->getFrameStamp();
if (!fs) return;
if (_needCompile)
{
_frameNumber = fs->getFrameNumber();
_needCompile = false;
}
if (_frameNumber!=fs->getFrameNumber()) return;
osgUtil::GLObjectsVisitor globjVisitor(osgUtil::GLObjectsVisitor::COMPILE_DISPLAY_LISTS|
osgUtil::GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES);
globjVisitor.setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
globjVisitor.setNodeMaskOverride(0xffffffff);
globjVisitor.setState(state);
_sceneToCompile->accept(globjVisitor);
}

View File

@ -0,0 +1,44 @@
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and/or modified under
* the terms of the GNU General Public License (GPL) version 2.0.
* The full license is in LICENSE.txt file included with this distribution,.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* include LICENSE.txt for more details.
*/
#ifndef OSG_COMPILESLIDECALLBACK
#define OSG_COMPILESLIDECALLBACK 1
#include <osgViewer/Viewer>
namespace ss3d {
class CompileSlideCallback : public osg::Camera::DrawCallback
{
public:
CompileSlideCallback():
_needCompile(false),
_frameNumber(0) {}
virtual void operator()(const osg::Camera& camera) const;
void needCompile(osg::Node* node) { _needCompile=true; _sceneToCompile = node; }
protected:
virtual ~CompileSlideCallback() {}
mutable bool _needCompile;
mutable int _frameNumber;
osg::ref_ptr<osg::Node> _sceneToCompile;
};
}
#endif

View File

@ -0,0 +1,209 @@
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and/or modified under
* the terms of the GNU General Public License (GPL) version 2.0.
* The full license is in LICENSE.txt file included with this distribution,.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* include LICENSE.txt for more details.
*/
#include "PickEventHandler.h"
#include "SlideEventHandler.h"
#include <osgViewer/Viewer>
#include <osg/Notify>
#include <osgDB/FileUtils>
PickEventHandler::PickEventHandler(SlideShowConstructor::Operation operation,bool relativeJump, int slideNum, int layerNum):
_operation(operation),
_relativeJump(relativeJump),
_slideNum(slideNum),
_layerNum(layerNum)
{
}
PickEventHandler::PickEventHandler(const std::string& str, SlideShowConstructor::Operation operation,bool relativeJump, int slideNum, int layerNum):
_command(str),
_operation(operation),
_relativeJump(relativeJump),
_slideNum(slideNum),
_layerNum(layerNum)
{
}
PickEventHandler::PickEventHandler(const SlideShowConstructor::KeyPosition& keyPos,bool relativeJump, int slideNum, int layerNum):
_keyPos(keyPos),
_operation(SlideShowConstructor::EVENT),
_relativeJump(relativeJump),
_slideNum(slideNum),
_layerNum(layerNum)
{
}
bool PickEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
{
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::MOVE):
case(osgGA::GUIEventAdapter::PUSH):
case(osgGA::GUIEventAdapter::RELEASE):
{
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
osgUtil::LineSegmentIntersector::Intersections intersections;
if (viewer->computeIntersections(ea.getX(),ea.getY(), nv->getNodePath(), intersections))
{
for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr=intersections.begin();
hitr!=intersections.end();
++hitr)
{
if (ea.getEventType()==osgGA::GUIEventAdapter::MOVE)
{
osg::notify(osg::INFO)<<"Tooltip..."<<std::endl;
}
else if (ea.getEventType()==osgGA::GUIEventAdapter::RELEASE)
{
doOperation();
return true;
}
}
}
break;
}
case(osgGA::GUIEventAdapter::KEYDOWN):
{
//osg::notify(osg::NOTICE)<<"PickEventHandler KEYDOWN "<<(char)ea.getKey()<<std::endl;
//if (object) osg::notify(osg::NOTICE)<<" "<<object->className()<<std::endl;
break;
}
default:
break;
}
return false;
}
void PickEventHandler::accept(osgGA::GUIEventHandlerVisitor& v)
{
v.visit(*this);
}
void PickEventHandler::getUsage(osg::ApplicationUsage& /*usage*/) const
{
}
void PickEventHandler::setRelativeJump(int slideNum, int layerNum)
{
_relativeJump = true;
_slideNum = slideNum;
_layerNum = layerNum;
}
void PickEventHandler::setAbsoluteJump(int slideNum, int layerNum)
{
_relativeJump = false;
_slideNum = slideNum;
_layerNum = layerNum;
}
void PickEventHandler::doOperation()
{
switch(_operation)
{
case(SlideShowConstructor::RUN):
{
osg::notify(osg::NOTICE)<<"Run "<<_command<<std::endl;
osgDB::FilePathList& paths = osgDB::getDataFilePathList();
#if 0
if (!paths.empty())
{
#ifdef _WIN32
std::string delimintor(";");
#else
std::string delimintor(":");
#endif
std::string filepath("OSG_FILE_PATH=");
bool needDeliminator = false;
for(osgDB::FilePathList::iterator itr = paths.begin();
itr != paths.end();
++itr)
{
if (needDeliminator) filepath += delimintor;
filepath += *itr;
needDeliminator = true;
}
putenv( (char*) filepath.c_str());
std::string binpath("PATH=");
char* path = getenv("PATH");
if (path) binpath += path;
needDeliminator = true;
for(osgDB::FilePathList::iterator itr = paths.begin();
itr != paths.end();
++itr)
{
if (needDeliminator) binpath += delimintor;
binpath += *itr;
needDeliminator = true;
}
putenv( (char*) binpath.c_str());
}
#endif
int result = system(_command.c_str());
osg::notify(osg::INFO)<<"system("<<_command<<") result "<<result<<std::endl;
break;
}
case(SlideShowConstructor::LOAD):
{
osg::notify(osg::NOTICE)<<"Load "<<_command<<std::endl;
break;
}
case(SlideShowConstructor::EVENT):
{
osg::notify(osg::INFO)<<"Event "<<_keyPos._key<<" "<<_keyPos._x<<" "<<_keyPos._y<<std::endl;
if (SlideEventHandler::instance()) SlideEventHandler::instance()->dispatchEvent(_keyPos);
break;
}
}
if (requiresJump())
{
osg::notify(osg::NOTICE)<<"Requires jump "<<_relativeJump<<", "<<_slideNum<<", "<<_layerNum<<std::endl;
if (_relativeJump)
{
int previousSlide = SlideEventHandler::instance()->getActiveSlide();
int previousLayer = SlideEventHandler::instance()->getActiveLayer();
int newSlide = previousSlide + _slideNum;
int newLayer = previousLayer + _layerNum;
if (newLayer<0)
{
newLayer = 0;
}
osg::notify(osg::NOTICE)<<" jump to "<<newSlide<<", "<<newLayer<<std::endl;
SlideEventHandler::instance()->selectSlide(newSlide, newLayer);
}
else
{
SlideEventHandler::instance()->selectSlide(_slideNum,_layerNum);
}
}
else
{
osg::notify(osg::NOTICE)<<"No jump required."<<std::endl;
}
}

View File

@ -0,0 +1,66 @@
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and/or modified under
* the terms of the GNU General Public License (GPL) version 2.0.
* The full license is in LICENSE.txt file included with this distribution,.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* include LICENSE.txt for more details.
*/
#ifndef PICKEVENTHANDLER
#define PICKEVENTHANDLER 1
#include <osg/StateSet>
#include <osg/Point>
#include <osgGA/GUIEventHandler>
#include "SlideShowConstructor.h"
class PickEventHandler : public osgGA::GUIEventHandler
{
public:
PickEventHandler(SlideShowConstructor::Operation operation, bool relativeJump=true, int slideNum=0, int layerNum=0);
PickEventHandler(const std::string& str, SlideShowConstructor::Operation operation, bool relativeJump=true, int slideNum=0, int layerNum=0);
PickEventHandler(const SlideShowConstructor::KeyPosition& keyPos, bool relativeJump=true, int slideNum=0, int layerNum=0);
void setOperation(SlideShowConstructor::Operation operation) { _operation = operation; }
SlideShowConstructor::Operation getOperation() const { return _operation; }
void setCommand(const std::string& str) { _command = str; }
const std::string& getCommand() const { return _command; }
void setKeyPosition(const SlideShowConstructor::KeyPosition& keyPos) { _keyPos = keyPos; }
const SlideShowConstructor::KeyPosition& getKeyPosition() const { return _keyPos; }
void setRelativeJump(int slideDelta, int layerDelta);
void setAbsoluteJump(int slideNum, int layerNum);
bool getRelativeJump() const { return _relativeJump; }
int getSlideNum() const { return _slideNum; }
int getLayerNum() const { return _layerNum; }
bool requiresJump() const { return _relativeJump ? (_slideNum!=0 || _layerNum!=0) : true; }
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object* object, osg::NodeVisitor* nv);
virtual void accept(osgGA::GUIEventHandlerVisitor& v);
virtual void getUsage(osg::ApplicationUsage& usage) const;
void doOperation();
std::string _command;
SlideShowConstructor::KeyPosition _keyPos;
SlideShowConstructor::Operation _operation;
bool _relativeJump;
int _slideNum;
int _layerNum;
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and/or modified under
* the terms of the GNU General Public License (GPL) version 2.0.
* The full license is in LICENSE.txt file included with this distribution,.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* include LICENSE.txt for more details.
*/
#ifndef SLIDEEVENTHANDLER
#define SLIDEEVENTHANDLER 1
#include <osg/Switch>
#include <osg/Timer>
#include <osgGA/GUIEventHandler>
#include <osgViewer/Viewer>
#include "CompileSlideCallback.h"
#include "SlideShowConstructor.h"
struct dereference_less
{
template<class T, class U>
inline bool operator() (const T& lhs,const U& rhs) const
{
return *lhs < *rhs;
}
};
struct ObjectOperator : public osg::Referenced
{
inline bool operator < (const ObjectOperator& rhs) const { return ptr() < rhs.ptr(); }
virtual void* ptr() const = 0;
virtual void enter() = 0;
virtual void maintain() = 0;
virtual void leave() = 0;
virtual void setPause(bool pause) = 0;
virtual void reset() = 0;
virtual ~ObjectOperator() {}
};
class ActiveOperators
{
public:
ActiveOperators();
~ActiveOperators();
void collect(osg::Node* incommingNode, osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
void process();
void setPause(bool pause);
bool getPause() const { return _pause; }
void reset();
typedef std::set< osg::ref_ptr<ObjectOperator>, dereference_less > OperatorList;
protected:
void processOutgoing();
void processIncomming();
void processMaintained();
bool _pause;
OperatorList _previous;
OperatorList _current;
OperatorList _outgoing;
OperatorList _incomming;
OperatorList _maintained;
};
class SlideEventHandler : public osgGA::GUIEventHandler
{
public:
SlideEventHandler(osgViewer::Viewer* viewer=0);
static SlideEventHandler* instance();
META_Object(osgslideshowApp,SlideEventHandler);
void set(osg::Node* model);
virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); }
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
virtual void getUsage(osg::ApplicationUsage& usage) const;
osgViewer::Viewer* getViewer() { return _viewer.get(); }
enum WhichPosition
{
FIRST_POSITION = 0,
LAST_POSITION = 0xffffffff
};
void compileSlide(unsigned int slideNum);
void releaseSlide(unsigned int slideNum);
unsigned int getNumSlides();
unsigned int getActiveSlide() const { return _activeSlide; }
unsigned int getActiveLayer() const { return _activeLayer; }
bool selectSlide(unsigned int slideNum,unsigned int layerNum=FIRST_POSITION);
bool selectLayer(unsigned int layerNum);
bool nextLayerOrSlide();
bool previousLayerOrSlide();
bool nextSlide();
bool previousSlide();
bool nextLayer();
bool previousLayer();
bool home();
void setAutoSteppingActive(bool flag = true) { _autoSteppingActive = flag; }
bool getAutoSteppingActive() const { return _autoSteppingActive; }
void setTimeDelayBetweenSlides(double dt) { _timePerSlide = dt; }
double getTimeDelayBetweenSlides() const { return _timePerSlide; }
double getDuration(const osg::Node* node) const;
double getCurrentTimeDelayBetweenSlides() const;
void setReleaseAndCompileOnEachNewSlide(bool flag) { _releaseAndCompileOnEachNewSlide = flag; }
bool getReleaseAndCompileOnEachNewSlide() const { return _releaseAndCompileOnEachNewSlide; }
void setTimeDelayOnNewSlideWithMovies(float t) { _timeDelayOnNewSlideWithMovies = t; }
float getTimeDelayOnNewSlideWithMovies() const { return _timeDelayOnNewSlideWithMovies; }
void setLoopPresentation(bool loop) { _loopPresentation = loop; }
bool getLoopPresentation() const { return _loopPresentation; }
void dispatchEvent(const SlideShowConstructor::KeyPosition& keyPosition);
enum ObjectMask
{
MOVIE = 1<<0,
OBJECTS = 1<<1,
ALL_OBJECTS = MOVIE | OBJECTS
};
protected:
~SlideEventHandler() {}
SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {}
bool home(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);
void updateAlpha(bool, bool, float x, float y);
void updateLight(float x, float y);
osg::observer_ptr<osgViewer::Viewer> _viewer;
osg::observer_ptr<osg::Switch> _showSwitch;
unsigned int _activePresentation;
osg::observer_ptr<osg::Switch> _presentationSwitch;
unsigned int _activeSlide;
osg::observer_ptr<osg::Switch> _slideSwitch;
unsigned int _activeLayer;
bool _firstTraversal;
double _previousTime;
double _timePerSlide;
bool _autoSteppingActive;
bool _loopPresentation;
bool _pause;
bool _hold;
bool _updateLightActive;
bool _updateOpacityActive;
float _previousX, _previousY;
bool _cursorOn;
bool _releaseAndCompileOnEachNewSlide;
bool _firstSlideOrLayerChange;
osg::Timer_t _tickAtFirstSlideOrLayerChange;
osg::Timer_t _tickAtLastSlideOrLayerChange;
float _timeDelayOnNewSlideWithMovies;
double _minimumTimeBetweenKeyPresses;
double _timeLastKeyPresses;
ActiveOperators _activeOperators;
osg::ref_ptr<ss3d::CompileSlideCallback> _compileSlideCallback;
void updateOperators();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,518 @@
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
*
* This software is open source and may be redistributed and/or modified under
* the terms of the GNU General Public License (GPL) version 2.0.
* The full license is in LICENSE.txt file included with this distribution,.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* include LICENSE.txt for more details.
*/
#ifndef SLIDESHOWCONSTRUCTOR
#define SLIDESHOWCONSTRUCTOR
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Group>
#include <osg/ClearNode>
#include <osg/Switch>
#include <osg/AnimationPath>
#include <osg/ImageStream>
#include <osgText/Text>
#include <osgGA/GUIEventAdapter>
#include <osgDB/FileUtils>
#include "AnimationMaterial.h"
class SlideShowConstructor
{
public:
enum CoordinateFrame { SLIDE, MODEL };
struct HomePosition : public virtual osg::Referenced
{
HomePosition() {}
HomePosition(const osg::Vec3& in_eye, const osg::Vec3& in_center, const osg::Vec3& in_up):
eye(in_eye),
center(in_center),
up(in_up) {}
osg::Vec3 eye;
osg::Vec3 center;
osg::Vec3 up;
};
struct KeyPosition
{
KeyPosition(unsigned int key=0, float x=FLT_MAX, float y=FLT_MAX):
_key((osgGA::GUIEventAdapter::KeySymbol)key),
_x(x),
_y(y) {}
void set(unsigned int key=0, float x=FLT_MAX, float y=FLT_MAX)
{
_key = (osgGA::GUIEventAdapter::KeySymbol)key;
_x = x;
_y = y;
}
osgGA::GUIEventAdapter::KeySymbol _key;
float _x;
float _y;
};
struct LayerCallback : public virtual osg::Referenced
{
virtual void operator() (osg::Node* node) const = 0;
};
struct LayerAttributes : public virtual osg::Referenced
{
LayerAttributes():_duration(0),_relativeJump(true),_slideNum(0),_layerNum(0) {}
LayerAttributes(double in_duration):_duration(in_duration),_relativeJump(true),_slideNum(0),_layerNum(0) {}
void setDuration(double duration) { _duration = duration; }
double getDuration() const { return _duration; }
typedef std::vector<KeyPosition> Keys;
typedef std::vector<std::string> RunStrings;
void setKeys(const Keys& keys) { _keys = keys; }
const Keys& getKeys() const { return _keys; }
void addKey(const KeyPosition& kp) { _keys.push_back(kp); }
void setRunStrings(const RunStrings& runStrings) { _runStrings = runStrings; }
const RunStrings& getRunStrings() const { return _runStrings; }
void addRunString(const std::string& runString) { _runStrings.push_back(runString); }
void setJump(bool relativeJump, int slideNum, int layerNum)
{
_relativeJump = relativeJump;
_slideNum = slideNum;
_layerNum = layerNum;
}
bool getRelativeJump() const { return _relativeJump; }
int getSlideNum() const { return _slideNum; }
int getLayerNum() const { return _layerNum; }
bool requiresJump() const { return _relativeJump ? (_slideNum!=0 || _layerNum!=0) : true; }
double _duration;
Keys _keys;
RunStrings _runStrings;
bool _relativeJump;
int _slideNum;
int _layerNum;
void addEnterCallback(LayerCallback* lc) { _enterLayerCallbacks.push_back(lc); }
void addLeaveCallback(LayerCallback* lc) { _leaveLayerCallbacks.push_back(lc); }
void callEnterCallbacks(osg::Node* node);
void callLeaveCallbacks(osg::Node* node);
typedef std::list< osg::ref_ptr<LayerCallback> > LayerCallbacks;
LayerCallbacks _enterLayerCallbacks;
LayerCallbacks _leaveLayerCallbacks;
};
LayerAttributes* getOrCreateLayerAttributes(osg::Node* node);
void setDuration(osg::Node* node,double duration)
{
getOrCreateLayerAttributes(node)->setDuration(duration);
}
void addKey(osg::Node* node,const KeyPosition& kp)
{
getOrCreateLayerAttributes(node)->addKey(kp);
}
void addRunString(osg::Node* node, const std::string& runString)
{
getOrCreateLayerAttributes(node)->addRunString(runString);
}
void setJump(osg::Node* node, bool relativeJump, int slideNum, int layerNum)
{
getOrCreateLayerAttributes(node)->setJump(relativeJump, slideNum, layerNum);
}
void addPresentationKey(const KeyPosition& kp)
{
if (!_presentationSwitch) createPresentation();
if (_presentationSwitch.valid()) addKey( _presentationSwitch.get(), kp);
}
void addPresentationRunString(const std::string& runString)
{
if (!_presentationSwitch) createPresentation();
if (_presentationSwitch.valid()) addRunString( _presentationSwitch.get(),runString);
}
void addSlideKey(const KeyPosition& kp)
{
if (!_slide) addSlide();
if (_slide.valid()) addKey(_slide.get(),kp);
}
void addSlideRunString(const std::string& runString)
{
if (!_slide) addSlide();
if (_slide.valid()) addRunString(_slide.get(),runString);
}
void setSlideJump(bool relativeJump, int switchNum, int layerNum)
{
if (!_slide) addSlide();
if (_slide.valid()) setJump(_slide.get(),relativeJump, switchNum, layerNum);
}
void addLayerKey(const KeyPosition& kp)
{
if (!_currentLayer) addLayer();
if (_currentLayer.valid()) addKey(_currentLayer.get(),kp);
}
void addLayerRunString(const std::string& runString)
{
if (!_currentLayer) addLayer();
if (_currentLayer.valid()) addRunString(_currentLayer.get(),runString);
}
void setLayerJump(bool relativeJump, int switchNum, int layerNum)
{
if (!_currentLayer) addLayer();
if (_currentLayer.valid()) setJump(_currentLayer.get(),relativeJump, switchNum, layerNum);
}
struct FilePathData : public virtual osg::Referenced
{
FilePathData(const osgDB::FilePathList& fpl):filePathList(fpl) {}
osgDB::FilePathList filePathList;
};
struct PositionData
{
PositionData():
frame(SlideShowConstructor::SLIDE),
position(0.0f,1.0f,0.0f),
//position(0.5f,0.5f,0.0f),
scale(1.0f,1.0f,1.0f),
rotate(0.0f,0.0f,0.0f,1.0f),
rotation(0.0f,0.0f,1.0f,0.0f),
absolute_path(false),
inverse_path(false),
path_time_offset(0.0),
path_time_multiplier(1.0f),
path_loop_mode(osg::AnimationPath::NO_LOOPING),
animation_material_time_offset(0.0),
animation_material_time_multiplier(1.0),
animation_material_loop_mode(ss3d::AnimationMaterial::NO_LOOPING) {}
bool requiresPosition() const
{
return (position[0]!=0.0f || position[1]!=1.0f || position[2]!=1.0f);
}
bool requiresScale() const
{
return (scale[0]!=1.0f || scale[1]!=1.0f || scale[2]!=1.0f);
}
bool requiresRotate() const
{
return rotate[0]!=0.0f;
}
bool requiresAnimation() const
{
return (rotation[0]!=0.0f || !path.empty());
}
bool requiresMaterialAnimation() const
{
return !animation_material_filename.empty() || !fade.empty();
}
CoordinateFrame frame;
osg::Vec3 position;
osg::Vec3 scale;
osg::Vec4 rotate;
osg::Vec4 rotation;
std::string animation_name;
bool absolute_path;
bool inverse_path;
double path_time_offset;
double path_time_multiplier;
osg::AnimationPath::LoopMode path_loop_mode;
std::string path;
double animation_material_time_offset;
double animation_material_time_multiplier;
ss3d::AnimationMaterial::LoopMode animation_material_loop_mode;
std::string animation_material_filename;
std::string fade;
};
struct ModelData
{
ModelData():
effect("") {}
std::string effect;
};
struct ImageData
{
ImageData():
width(1.0f),
height(1.0f),
region(0.0f,0.0f,1.0f,1.0f),
region_in_pixel_coords(false),
texcoord_rotate(0.0f),
loopingMode(osg::ImageStream::NO_LOOPING),
page(-1),
backgroundColor(1.0f,1.0f,1.0f,1.0f) {}
float width;
float height;
osg::Vec4 region;
bool region_in_pixel_coords;
float texcoord_rotate;
osg::ImageStream::LoopingMode loopingMode;
int page;
osg::Vec4 backgroundColor;
};
struct FontData
{
FontData():
font("fonts/arial.ttf"),
layout(osgText::Text::LEFT_TO_RIGHT),
alignment(osgText::Text::LEFT_BASE_LINE),
axisAlignment(osgText::Text::XZ_PLANE),
characterSize(0.04f),
maximumHeight(1.0f),
maximumWidth(1.0f),
color(1.0f,1.0f,1.0f,1.0f) {}
std::string font;
osgText::Text::Layout layout;
osgText::Text::AlignmentType alignment;
osgText::Text::AxisAlignment axisAlignment;
float characterSize;
float maximumHeight;
float maximumWidth;
osg::Vec4 color;
};
/// Operations related to click to run/load/key events.
enum Operation
{
RUN,
LOAD,
EVENT,
JUMP
};
SlideShowConstructor();
void createPresentation();
void setBackgroundColor(const osg::Vec4& color, bool updateClearNode);
const osg::Vec4& getBackgroundColor() const { return _backgroundColor; }
void setTextColor(const osg::Vec4& color);
const osg::Vec4& getTextColor() const { return _textFontDataDefault.color; }
void setPresentationName(const std::string& name);
void setPresentationAspectRatio(float aspectRatio);
void setPresentationAspectRatio(const std::string& str);
void setPresentationDuration(double duration);
void addSlide();
void selectSlide(int slideNum);
void setSlideTitle(const std::string& name, PositionData& positionData, FontData& fontData)
{
_titlePositionData = positionData;
_titleFontData = fontData;
_slideTitle = name;
}
void setSlideBackground(const std::string& name) { _slideBackgroundImageFileName = name; }
void setSlideDuration(double duration);
void addLayer(bool inheritPreviousLayers=true, bool defineAsBaseLayer=false);
void selectLayer(int layerNum);
void setLayerDuration(double duration);
// title settings
FontData& getTitleFontData() { return _titleFontData; }
FontData& getTitleFontDataDefault() { return _titleFontDataDefault; }
PositionData& getTitlePositionData() { return _titlePositionData; }
PositionData& getTitlePositionDataDefault() { return _titlePositionDataDefault; }
// text settings
FontData& getTextFontData() { return _textFontData; }
FontData& getTextFontDataDefault() { return _textFontDataDefault; }
PositionData& getTextPositionData() { return _textPositionData; }
PositionData& getTextPositionDataDefault() { return _textPositionDataDefault; }
void translateTextCursor(const osg::Vec3& delta) { _textPositionData.position += delta; }
// image settings
PositionData& getImagePositionData() { return _imagePositionData; }
PositionData& getImagePositionDataDefault() { return _imagePositionDataDefault; }
// model settings
PositionData& getModelPositionData() { return _modelPositionData; }
PositionData& getModelPositionDataDefault() { return _modelPositionDataDefault; }
void layerClickToDoOperation(Operation operation, bool relativeJump=true, int slideNum=0, int layerNum=0);
void layerClickToDoOperation(const std::string& command, Operation operation, bool relativeJump=true, int slideNum=0, int layerNum=0);
void layerClickEventOperation(const SlideShowConstructor::KeyPosition& keyPos, bool relativeJump=true, int slideNum=0, int layerNum=0);
void addBullet(const std::string& bullet, PositionData& positionData, FontData& fontData);
void addParagraph(const std::string& paragraph, PositionData& positionData, FontData& fontData);
void addImage(const std::string& filename,const PositionData& positionData, const ImageData& imageData);
void addStereoImagePair(const std::string& filenameLeft, const ImageData& imageDataLeft, const std::string& filenameRight,const ImageData& imageDataRight, const PositionData& positionData);
void addVNC(const std::string& filename,const PositionData& positionData, const ImageData& imageData);
void addBrowser(const std::string& filename,const PositionData& positionData, const ImageData& imageData);
void addPDF(const std::string& filename,const PositionData& positionData, const ImageData& imageData);
osg::Image* addInteractiveImage(const std::string& filename,const PositionData& positionData, const ImageData& imageData);
void addModel(osg::Node* subgraph, const PositionData& positionData, const ModelData& modelData);
void addModel(const std::string& filename, const PositionData& positionData, const ModelData& modelData);
void addVolume(const std::string& filename, const PositionData& positionData);
osg::Group* takePresentation() { return _root.release(); }
osg::Group* getPresentation() { return _root.get(); }
osg::Switch* getPresentationSwitch() { return _presentationSwitch.get(); }
osg::Switch* getCurrentSlide() { return _slide.get(); }
osg::Group* getCurrentLayer() { return _currentLayer.get(); }
void setLoopPresentation(bool loop) { _loopPresentation = loop; }
bool getLoopPresentation() const { return _loopPresentation; }
void setAutoSteppingActive(bool flag = true) { _autoSteppingActive = flag; }
bool getAutoSteppingActive() const { return _autoSteppingActive; }
protected:
void findImageStreamsAndAddCallbacks(osg::Node* node);
osg::Geometry* createTexturedQuadGeometry(const osg::Vec3& pos, const osg::Vec4& rotation, float width,float height, osg::Image* image, bool& usedTextureRectangle);
osg::Vec3 computePositionInModelCoords(const PositionData& positionData) const;
void updatePositionFromInModelCoords(const osg::Vec3& vertex, PositionData& positionData) const;
osg::Vec3 convertSlideToModel(const osg::Vec3& position) const;
osg::Vec3 convertModelToSlide(const osg::Vec3& position) const;
osg::AnimationPath* readPivotPath(const std::string& filename) const;
osg::AnimationPath* readRotationPath(const std::string& filename) const;
osg::AnimationPathCallback* getAnimationPathCallback(const PositionData& positionData);
osg::Node* attachMaterialAnimation(osg::Node* model, const PositionData& positionData);
bool attachTexMat(osg::StateSet* stateset, const ImageData& imageData, float s, float t, bool textureRectangle);
osg::StateSet* createTransformStateSet()
{
osg::StateSet* stateset = new osg::StateSet;
stateset->setMode(GL_NORMALIZE,osg::StateAttribute::ON);
return stateset;
}
osg::Vec3 _slideOrigin;
osg::Vec3 _eyeOrigin;
float _slideWidth;
float _slideHeight;
float _slideDistance;
// title settings
FontData _titleFontData;
FontData _titleFontDataDefault;
PositionData _titlePositionData;
PositionData _titlePositionDataDefault;
// text settings
FontData _textFontData;
FontData _textFontDataDefault;
PositionData _textPositionData;
PositionData _textPositionDataDefault;
// image settings
PositionData _imagePositionData;
PositionData _imagePositionDataDefault;
// model settings
PositionData _modelPositionData;
PositionData _modelPositionDataDefault;
bool _loopPresentation;
bool _autoSteppingActive;
osg::Vec4 _backgroundColor;
std::string _presentationName;
double _presentationDuration;
osg::ref_ptr<osg::Group> _root;
osg::ref_ptr<osg::Switch> _presentationSwitch;
osg::ref_ptr<osg::ClearNode> _slideClearNode;
osg::ref_ptr<osg::Switch> _slide;
std::string _slideTitle;
std::string _slideBackgroundImageFileName;
osg::ref_ptr<osg::Group> _previousLayer;
osg::ref_ptr<osg::Group> _currentLayer;
osg::ref_ptr<FilePathData> _filePathData;
std::string findFileAndRecordPath(const std::string& filename);
};
#endif