diff --git a/applications/present3D/present3D.cpp b/applications/present3D/present3D.cpp index 1fd34f1cd..251c8a7ec 100644 --- a/applications/present3D/present3D.cpp +++ b/applications/present3D/present3D.cpp @@ -40,6 +40,7 @@ #include #include +#include #include "ReadShowFile.h" #include "PointsEventHandler.h" @@ -180,12 +181,42 @@ class FollowMouseCallback: public osgGA::GUIEventHandler osg::notify(level)<<"ea.getYmax()="<=1) + { + const osgGA::PointerData* pd = ea.getPointerData(ea.getNumPointerData()-1); + osg::Camera* camera = dynamic_cast(pd->object.get()); + + OSG_NOTICE<<"Camera "< _camera; }; osg::Node* createCursorSubgraph(const std::string& filename, float size) @@ -300,7 +332,12 @@ void processLoadedModel(osg::ref_ptr& loadedModel, int optimizer_opti { osg::ref_ptr group = new osg::Group; group->addChild(loadedModel.get()); - group->addChild(createCursorSubgraph(cursorFileName, 0.05f)); +#if 1 + OSG_NOTICE<<"Creating Cursor"<addChild(new osgPresentation::Cursor(cursorFileName, 20.0f)); +#else + group->addChild(createCursorSubgraph(cursorFileName, 20.0f)); +#endif loadedModel = group; } } diff --git a/include/osgPresentation/Cursor b/include/osgPresentation/Cursor new file mode 100644 index 000000000..d1640cb8b --- /dev/null +++ b/include/osgPresentation/Cursor @@ -0,0 +1,65 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGPRESENTATION_CURSOR +#define OSGPRESENTATION_CURSOR 1 + +#include +#include +#include + +namespace osgPresentation { + +class OSGPRESENTATION_EXPORT Cursor : public osg::Group +{ + public: + + Cursor(); + + Cursor(const std::string& filename, float size); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + Cursor(const Cursor& rhs,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(osgPresentation, Cursor) + + void setFilename(const std::string& filename) { _filename = filename; _cursorDirty=true; } + const std::string& getFilename() const { return _filename; } + + void setSize(float size) { _size = size; _cursorDirty=true; } + float getSize() const { return _size; } + + virtual void traverse(osg::NodeVisitor& nv); + + protected: + + virtual ~Cursor(); + + void initializeCursor(); + void updatePosition(); + + std::string _filename; + float _size; + + bool _cursorDirty; + + osg::ref_ptr _transform; + + osg::Vec2 _cursorXY; + osg::observer_ptr _camera; + +}; + +} + +#endif \ No newline at end of file diff --git a/src/osgPresentation/CMakeLists.txt b/src/osgPresentation/CMakeLists.txt index 6dcda2dee..92e9dcd60 100644 --- a/src/osgPresentation/CMakeLists.txt +++ b/src/osgPresentation/CMakeLists.txt @@ -11,6 +11,7 @@ SET(TARGET_H ${HEADER_PATH}/Export ${HEADER_PATH}/AnimationMaterial ${HEADER_PATH}/CompileSlideCallback + ${HEADER_PATH}/Cursor ${HEADER_PATH}/PickEventHandler ${HEADER_PATH}/PropertyManager ${HEADER_PATH}/KeyEventHandler @@ -23,6 +24,7 @@ SET(TARGET_H SET(TARGET_SRC AnimationMaterial.cpp CompileSlideCallback.cpp + Cursor.cpp PickEventHandler.cpp PropertyManager.cpp KeyEventHandler.cpp diff --git a/src/osgPresentation/Cursor.cpp b/src/osgPresentation/Cursor.cpp new file mode 100644 index 000000000..a9ec42d07 --- /dev/null +++ b/src/osgPresentation/Cursor.cpp @@ -0,0 +1,232 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace osgPresentation; + +Cursor::Cursor(): + _size(0.05f), + _cursorDirty(true) +{ + setDataVariance(osg::Object::DYNAMIC); + setCullingActive(false); + setNumChildrenRequiringEventTraversal(1); + setNumChildrenRequiringUpdateTraversal(1); +} + +Cursor::Cursor(const std::string& filename, float size): + _cursorDirty(true) +{ + setDataVariance(osg::Object::DYNAMIC); + setCullingActive(false); + setNumChildrenRequiringEventTraversal(1); + setNumChildrenRequiringUpdateTraversal(1); + + setFilename(filename); + setSize(size); +} + +Cursor::Cursor(const Cursor& rhs,const osg::CopyOp& copyop): + osg::Group(rhs, copyop), + _filename(rhs._filename), + _size(rhs._size), + _cursorDirty(true) +{ + setDataVariance(osg::Object::DYNAMIC); + setCullingActive(false); +} + +Cursor::~Cursor() +{ +} + +void Cursor::initializeCursor() +{ + if (!_cursorDirty) return; + if (_filename.empty()) return; + + removeChildren(0, getNumChildren()-1); + + OSG_INFO<<"Curosr::initializeCursor()"<setAutoRotateMode(osg::AutoTransform::ROTATE_TO_CAMERA); + _transform->setAutoScaleToScreen(true); + + osg::Geode* geode = new osg::Geode; + + osg::Geometry* geom = osg::createTexturedQuadGeometry(osg::Vec3(-_size*0.5f,-_size*0.5f,0.0f),osg::Vec3(_size,0.0f,0.0f),osg::Vec3(0.0f,_size,0.0f)); + geom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + + osg::Image* image = osgDB::readImageFile(osgDB::findDataFile(_filename)); + if (image) + { + osg::StateSet* stateset = geom->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(0, new osg::Texture2D(image),osg::StateAttribute::ON|osg::StateAttribute::PROTECTED); + stateset->setMode(GL_BLEND,osg::StateAttribute::ON|osg::StateAttribute::PROTECTED); + // stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); + stateset->setRenderBinDetails(1000, "DepthSortedBin"); + } + + geode->addDrawable(geom); + + _transform->addChild(geode); + + addChild(_transform.get()); +} + +void Cursor::updatePosition() +{ + if (!_camera) + { + OSG_INFO<<"Cursor::updatePosition() : Update position failed, no camera assigned"<(_camera->getView()); + if (view) + { + osg::DisplaySettings* ds = (view->getDisplaySettings()!=0) ? view->getDisplaySettings() : osg::DisplaySettings::instance().get(); + + double sd = ds->getScreenDistance(); + double fusionDistance = sd; + switch(view->getFusionDistanceMode()) + { + case(osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE): + fusionDistance = view->getFusionDistanceValue(); + break; + case(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE): + fusionDistance *= view->getFusionDistanceValue(); + break; + } + + distance = fusionDistance; + } + + osg::Matrix VP = _camera->getViewMatrix() * _camera->getProjectionMatrix(); + + osg::Matrix inverse_VP; + inverse_VP.invert(VP); + + osg::Vec3d eye(0.0,0.0,0.0); + osg::Vec3d farpoint(_cursorXY.x(), _cursorXY.y(), 1.0); + + osg::Vec3d eye_world = eye * osg::Matrix::inverse(_camera->getViewMatrix()); + osg::Vec3d farpoint_world = farpoint * inverse_VP; + + osg::Vec3d normal = farpoint_world-eye_world; + normal.normalize(); + + osg::Vec3d cursorPosition = eye_world + normal * distance; + _transform->setPosition(cursorPosition); +} + + +void Cursor::traverse(osg::NodeVisitor& nv) +{ + if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR) + { + if (_cursorDirty) initializeCursor(); + + // updatePosition(); + + // traverse the subgraph + Group::traverse(nv); + } + else if (nv.getVisitorType()==osg::NodeVisitor::EVENT_VISITOR) + { + osgGA::EventVisitor* ev = dynamic_cast(&nv); + if (!ev) return; + + osgGA::EventQueue::Events& events = ev->getEvents(); + for(osgGA::EventQueue::Events::iterator itr = events.begin(); + itr != events.end(); + ++itr) + { + osgGA::GUIEventAdapter* event = itr->get(); + switch(event->getEventType()) + { + case(osgGA::GUIEventAdapter::PUSH): + case(osgGA::GUIEventAdapter::RELEASE): + case(osgGA::GUIEventAdapter::MOVE): + case(osgGA::GUIEventAdapter::DRAG): + { + if (event->getNumPointerData()>=1) + { + const osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1); + osg::Camera* camera = dynamic_cast(pd->object.get()); + + _cursorXY.set(pd->getXnormalized(), pd->getYnormalized()); + _camera = camera; + } + else + { + osgViewer::View* view = dynamic_cast(ev->getActionAdapter()); + osg::Camera* camera = (view!=0) ? view->getCamera() : 0; + + _cursorXY.set(event->getXnormalized(), event->getYnormalized()); + _camera = camera; + } + break; + } + case(osgGA::GUIEventAdapter::KEYDOWN): + { + if (event->getKey()=='c') + { + for(unsigned int i=0; i< getNumChildren(); ++i) + { + osg::Node* node = getChild(i); + node->setNodeMask(node->getNodeMask()!=0 ? 0 : 0xffffff); + } + } + break; + } + default: + break; + + } + } + Group::traverse(nv); + } + else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) + { +#if 0 + if (!_camera) + { + osgUtil::CullVisitor* cv = dynamic_cast(&nv); + if (cv) + { + _camera = cv->getCurrentCamera(); + } + } +#endif + if (_camera.valid()) + { + updatePosition(); + Group::traverse(nv); + } + } +}