root/OpenSceneGraph/trunk/src/osgPresentation/Cursor.cpp @ 13890

Revision 13890, 8.2 kB (checked in by robert, 99 minutes ago)

Fixed typo in OPENSCENEGRAPH_OPENGL_HEADER name

Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgPresentation/Cursor>
15
16#include <osgUtil/CullVisitor>
17#include <osgGA/EventVisitor>
18#include <osgDB/ReadFile>
19#include <osgDB/FileUtils>
20#include <osgViewer/View>
21#include <osg/Texture2D>
22#include <osg/io_utils>
23
24using namespace osgPresentation;
25
26Cursor::Cursor():
27    _size(0.05f),
28    _cursorDirty(true)
29{
30    setDataVariance(osg::Object::DYNAMIC);
31    setCullingActive(false);
32    setNumChildrenRequiringEventTraversal(1);
33    setNumChildrenRequiringUpdateTraversal(1);
34}
35
36Cursor::Cursor(const std::string& filename, float size):
37    _cursorDirty(true)
38{
39    setDataVariance(osg::Object::DYNAMIC);
40    setCullingActive(false);
41    setNumChildrenRequiringEventTraversal(1);
42    setNumChildrenRequiringUpdateTraversal(1);
43
44    setFilename(filename);
45    setSize(size);
46}
47
48Cursor::Cursor(const Cursor& rhs,const osg::CopyOp& copyop):
49    osg::Group(rhs, copyop),
50    _filename(rhs._filename),
51    _size(rhs._size),
52    _cursorDirty(true)
53{
54    setDataVariance(osg::Object::DYNAMIC);
55    setCullingActive(false);
56}
57
58Cursor::~Cursor()
59{
60}
61
62void Cursor::initializeCursor()
63{
64    if (!_cursorDirty) return;
65    if (_filename.empty()) return;
66
67    removeChildren(0, getNumChildren()-1);
68
69    OSG_INFO<<"Curosr::initializeCursor()"<<std::endl;
70    _cursorDirty = false;
71
72    _transform = new osg::AutoTransform;
73
74    _transform->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_CAMERA);
75    _transform->setAutoScaleToScreen(true);
76
77    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
78
79
80    osg::ref_ptr<osg::Image> image = osgDB::readImageFile(osgDB::findDataFile(_filename));
81    osg::ref_ptr<osg::Texture2D> texture = (image.valid()) ? new osg::Texture2D(image.get()) : 0;
82
83    // full cursor
84    {
85        osg::ref_ptr<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));
86        geode->addDrawable(geom.get());
87
88        osg::StateSet* stateset = geom->getOrCreateStateSet();
89        stateset->setMode(GL_BLEND,osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
90        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
91        stateset->setRenderBinDetails(1001, "DepthSortedBin");
92
93        if (texture.valid()) stateset->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
94    }
95
96    {
97        osg::ref_ptr<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));
98        geode->addDrawable(geom.get());
99
100        osg::Vec4Array* colors = new osg::Vec4Array;
101        colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,0.25f));
102        geom->setColorArray(colors, osg::Array::BIND_OVERALL);
103
104        osg::StateSet* stateset = geom->getOrCreateStateSet();
105        stateset->setMode(GL_BLEND,osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
106        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
107        stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
108        stateset->setRenderBinDetails(1000, "DepthSortedBin");
109
110        if (texture.valid()) stateset->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
111    }
112
113
114
115    _transform->addChild(geode.get());
116
117    addChild(_transform.get());
118}
119
120void Cursor::updatePosition()
121{
122    if (!_camera)
123    {
124        OSG_INFO<<"Cursor::updatePosition() : Update position failed, no camera assigned"<<std::endl;
125        return;
126    }
127
128    double distance = 1.0f;
129
130    osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
131    if (view)
132    {
133        osg::DisplaySettings* ds = (view->getDisplaySettings()!=0) ? view->getDisplaySettings() : osg::DisplaySettings::instance().get();
134
135        double sd = ds->getScreenDistance();
136        double fusionDistance = sd;
137        switch(view->getFusionDistanceMode())
138        {
139            case(osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE):
140                fusionDistance = view->getFusionDistanceValue();
141                break;
142            case(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE):
143                fusionDistance *= view->getFusionDistanceValue();
144                break;
145        }
146
147        distance = fusionDistance;
148    }
149
150    osg::Matrix VP =  _camera->getViewMatrix() * _camera->getProjectionMatrix();
151
152    osg::Matrix inverse_VP;
153    inverse_VP.invert(VP);
154
155    osg::Vec3d eye(0.0,0.0,0.0);
156    osg::Vec3d farpoint(_cursorXY.x(), _cursorXY.y(), 1.0);
157
158    osg::Vec3d eye_world = eye * osg::Matrix::inverse(_camera->getViewMatrix());
159    osg::Vec3d farpoint_world = farpoint * inverse_VP;
160
161    osg::Vec3d normal = farpoint_world-eye_world;
162    normal.normalize();
163
164    osg::Vec3d cursorPosition = eye_world + normal * distance;
165    _transform->setPosition(cursorPosition);
166}
167
168
169void Cursor::traverse(osg::NodeVisitor& nv)
170{
171    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
172    {
173        if (_cursorDirty) initializeCursor();
174
175        // updatePosition();
176
177        // traverse the subgraph
178        Group::traverse(nv);
179    }
180    else if (nv.getVisitorType()==osg::NodeVisitor::EVENT_VISITOR)
181    {
182        osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
183        if (!ev) return;
184
185        osgGA::EventQueue::Events& events = ev->getEvents();
186        for(osgGA::EventQueue::Events::iterator itr = events.begin();
187            itr != events.end();
188            ++itr)
189        {
190            osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
191            if (!event) continue;
192
193            switch(event->getEventType())
194            {
195                case(osgGA::GUIEventAdapter::PUSH):
196                case(osgGA::GUIEventAdapter::RELEASE):
197                case(osgGA::GUIEventAdapter::MOVE):
198                case(osgGA::GUIEventAdapter::DRAG):
199                {
200                    if (event->getNumPointerData()>=1)
201                    {
202                        const osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1);
203                        osg::Camera* camera = dynamic_cast<osg::Camera*>(pd->object.get());
204
205                        _cursorXY.set(pd->getXnormalized(), pd->getYnormalized());
206                        _camera = camera;
207                    }
208                    else
209                    {
210                        osgViewer::View* view = dynamic_cast<osgViewer::View*>(ev->getActionAdapter());
211                        osg::Camera* camera = (view!=0) ? view->getCamera() : 0;
212
213                        _cursorXY.set(event->getXnormalized(), event->getYnormalized());
214                        _camera = camera;
215                    }
216                    break;
217                }
218                case(osgGA::GUIEventAdapter::KEYDOWN):
219                {
220                    if (event->getKey()=='c')
221                    {
222                        for(unsigned int i=0; i< getNumChildren(); ++i)
223                        {
224                            osg::Node* node = getChild(i);
225                            node->setNodeMask(node->getNodeMask()!=0 ? 0 : 0xffffff);
226                        }
227                    }
228                    break;
229                }
230                default:
231                    break;
232
233            }
234        }
235        Group::traverse(nv);
236    }
237    else  if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
238    {
239#if 0
240        if (!_camera)
241        {
242            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
243            if (cv)
244            {
245                _camera = cv->getCurrentCamera();
246            }
247        }
248#endif
249        if (_camera.valid())
250        {
251            updatePosition();
252            Group::traverse(nv);
253        }
254    }
255}
Note: See TracBrowser for help on using the browser.