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

Revision 13820, 8.1 kB (checked in by robert, 25 hours ago)

Release OpenSceneGraph-3.3.3

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->get();
191            switch(event->getEventType())
192            {
193                case(osgGA::GUIEventAdapter::PUSH):
194                case(osgGA::GUIEventAdapter::RELEASE):
195                case(osgGA::GUIEventAdapter::MOVE):
196                case(osgGA::GUIEventAdapter::DRAG):
197                {
198                    if (event->getNumPointerData()>=1)
199                    {
200                        const osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1);
201                        osg::Camera* camera = dynamic_cast<osg::Camera*>(pd->object.get());
202
203                        _cursorXY.set(pd->getXnormalized(), pd->getYnormalized());
204                        _camera = camera;
205                    }
206                    else
207                    {
208                        osgViewer::View* view = dynamic_cast<osgViewer::View*>(ev->getActionAdapter());
209                        osg::Camera* camera = (view!=0) ? view->getCamera() : 0;
210
211                        _cursorXY.set(event->getXnormalized(), event->getYnormalized());
212                        _camera = camera;
213                    }
214                    break;
215                }
216                case(osgGA::GUIEventAdapter::KEYDOWN):
217                {
218                    if (event->getKey()=='c')
219                    {
220                        for(unsigned int i=0; i< getNumChildren(); ++i)
221                        {
222                            osg::Node* node = getChild(i);
223                            node->setNodeMask(node->getNodeMask()!=0 ? 0 : 0xffffff);
224                        }
225                    }
226                    break;
227                }
228                default:
229                    break;
230
231            }
232        }
233        Group::traverse(nv);
234    }
235    else  if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
236    {
237#if 0
238        if (!_camera)
239        {
240            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
241            if (cv)
242            {
243                _camera = cv->getCurrentCamera();
244            }
245        }
246#endif
247        if (_camera.valid())
248        {
249            updatePosition();
250            Group::traverse(nv);
251        }
252    }
253}
Note: See TracBrowser for help on using the browser.