Added osgPresentation::Cursor class to wrap up 3D cursor in the scene functionality

This commit is contained in:
Robert Osfield 2013-08-08 16:49:33 +00:00
parent 835ee7aa8e
commit 82401defc7
4 changed files with 339 additions and 3 deletions

View File

@ -40,6 +40,7 @@
#include <osgPresentation/SlideEventHandler>
#include <osgPresentation/SlideShowConstructor>
#include <osgPresentation/Cursor>
#include "ReadShowFile.h"
#include "PointsEventHandler.h"
@ -180,12 +181,42 @@ class FollowMouseCallback: public osgGA::GUIEventHandler
osg::notify(level)<<"ea.getYmax()="<<ea.getYmax()<<std::endl;
_mousePostition.set(ea.getXnormalized(), ea.getYnormalized());
#if 1
if (ea.getNumPointerData()>=1)
{
const osgGA::PointerData* pd = ea.getPointerData(ea.getNumPointerData()-1);
osg::Camera* camera = dynamic_cast<osg::Camera*>(pd->object.get());
OSG_NOTICE<<"Camera "<<camera<<", xNormalized() = "<<pd->getXnormalized()<<", yNormalized() = "<<pd->getYnormalized()<<std::endl;
_mousePostition.set(pd->getXnormalized(), pd->getYnormalized());
_camera = camera;
}
#endif
break;
case(osgGA::GUIEventAdapter::FRAME):
{
osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
if (_camera.valid())
{
osg::Matrix VP = _camera->getViewMatrix() * _camera->getProjectionMatrix();
osg::Matrix inverse_VP;
inverse_VP.invert(VP);
osg::Vec3d start_eye(_mousePostition.x(), _mousePostition.y(), 0.0);
osg::Vec3d end_eye(_mousePostition.x(), _mousePostition.y(), 1.0);
osg::Vec3d start_world = start_eye * inverse_VP;
osg::Vec3d end_world = start_eye * inverse_VP;
OSG_NOTICE<<"start_world="<<start_world<<std::endl;
OSG_NOTICE<<"end_world="<<end_world<<std::endl;
if (end_world.valid()) transform->setPosition(end_world);
}
#if 0
osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
osg::Camera* camera = view->getCamera();
osg::Matrix VP = camera->getViewMatrix() * camera->getProjectionMatrix();
@ -207,7 +238,7 @@ class FollowMouseCallback: public osgGA::GUIEventHandler
{
OSG_NOTICE<<"Ignoring invalid end_world position"<<std::endl;
}
#endif
break;
}
case(osgGA::GUIEventAdapter::KEYDOWN):
@ -237,6 +268,7 @@ class FollowMouseCallback: public osgGA::GUIEventHandler
}
osg::Vec2d _mousePostition;
osg::observer_ptr<osg::Camera> _camera;
};
osg::Node* createCursorSubgraph(const std::string& filename, float size)
@ -300,7 +332,12 @@ void processLoadedModel(osg::ref_ptr<osg::Node>& loadedModel, int optimizer_opti
{
osg::ref_ptr<osg::Group> group = new osg::Group;
group->addChild(loadedModel.get());
group->addChild(createCursorSubgraph(cursorFileName, 0.05f));
#if 1
OSG_NOTICE<<"Creating Cursor"<<std::endl;
group->addChild(new osgPresentation::Cursor(cursorFileName, 20.0f));
#else
group->addChild(createCursorSubgraph(cursorFileName, 20.0f));
#endif
loadedModel = group;
}
}

View File

@ -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 <osg/AutoTransform>
#include <osg/Camera>
#include <osgPresentation/Export>
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<osg::AutoTransform> _transform;
osg::Vec2 _cursorXY;
osg::observer_ptr<osg::Camera> _camera;
};
}
#endif

View File

@ -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

View File

@ -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 <osgPresentation/Cursor>
#include <osgUtil/CullVisitor>
#include <osgGA/EventVisitor>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgViewer/View>
#include <osg/Texture2D>
#include <osg/io_utils>
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()"<<std::endl;
_cursorDirty = false;
_transform = new osg::AutoTransform;
_transform->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"<<std::endl;
return;
}
double distance = 1.0f;
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_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<osgGA::EventVisitor*>(&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<osg::Camera*>(pd->object.get());
_cursorXY.set(pd->getXnormalized(), pd->getYnormalized());
_camera = camera;
}
else
{
osgViewer::View* view = dynamic_cast<osgViewer::View*>(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<osgUtil::CullVisitor*>(&nv);
if (cv)
{
_camera = cv->getCurrentCamera();
}
}
#endif
if (_camera.valid())
{
updatePosition();
Group::traverse(nv);
}
}
}