Added osgPresentation::Cursor class to wrap up 3D cursor in the scene functionality
This commit is contained in:
parent
835ee7aa8e
commit
82401defc7
@ -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;
|
||||
}
|
||||
}
|
||||
|
65
include/osgPresentation/Cursor
Normal file
65
include/osgPresentation/Cursor
Normal 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
|
@ -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
|
||||
|
232
src/osgPresentation/Cursor.cpp
Normal file
232
src/osgPresentation/Cursor.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user