diff --git a/include/osgManipulator/CommandManager b/include/osgManipulator/CommandManager index de7c2b756..2230eeec1 100644 --- a/include/osgManipulator/CommandManager +++ b/include/osgManipulator/CommandManager @@ -27,13 +27,12 @@ namespace osgManipulator { class OSGMANIPULATOR_EXPORT CommandManager : public osg::Referenced { public: - CommandManager(); /** * Connect a dragger to a selection. The selection will begin listening - * to commands generated by the dragger. This can be called multiple - * times to connect many selections to a dragger. + * to commands generated by the dragger. This can be called multiple + * times to connect many selections to a dragger. */ virtual bool connect(Dragger& dragger, Selection& selection); diff --git a/include/osgManipulator/Dragger b/include/osgManipulator/Dragger index 3f54f81d8..1a3668c7e 100644 --- a/include/osgManipulator/Dragger +++ b/include/osgManipulator/Dragger @@ -36,9 +36,9 @@ class OSGMANIPULATOR_EXPORT PointerInfo PointerInfo(); PointerInfo(const PointerInfo& rhs): - _pixel_x(rhs._pixel_x), - _pixel_y(rhs._pixel_y), - _camera(rhs._camera), + _nearPoint(rhs._nearPoint), + _farPoint(rhs._farPoint), + _eyeDir(rhs._eyeDir), _hitList(rhs._hitList) { _hitIter = _hitList.begin(); @@ -63,35 +63,43 @@ class OSGMANIPULATOR_EXPORT PointerInfo typedef std::list< NodePathIntersectionPair> IntersectionList; - osg::Vec2 pointToProject() const { return osg::Vec2(_pixel_x, _pixel_y); } osg::Vec3 getLocalIntersectPoint() const { return _hitIter->second; } - bool projectWindowXYIntoObject(const osg::Vec2& windowCoord, osg::Vec3& nearPoint, osg::Vec3& farPoint) const; - bool projectWindowXYIntoObject(osg::Vec3& nearPoint, osg::Vec3& farPoint) const - { - return projectWindowXYIntoObject(pointToProject(), nearPoint, farPoint); + + void setNearFarPoints (osg::Vec3 nearPoint, osg::Vec3 farPoint) { + _nearPoint = nearPoint; + _farPoint=farPoint; + _eyeDir = farPoint - nearPoint; + } + + const osg::Vec3& getEyeDir() const {return _eyeDir;} + + void getNearFarPoints( osg::Vec3& nearPoint, osg::Vec3& farPoint) const { + nearPoint = _nearPoint; + farPoint = _farPoint; } - - bool projectObjectIntoWindow(const osg::Vec3& object,osg::Vec3& window) const; - - const osg::Matrix& getViewMatrix() const { return _camera->getViewMatrix(); } bool contains(const osg::Node* node) const; void setCamera(osg::Camera* camera) { - _camera = camera; - if (_camera) + + if (camera) { - _MVPW = _camera->getViewMatrix() * _camera->getProjectionMatrix(); - if (_camera->getViewport()) _MVPW.postMult(_camera->getViewport()->computeWindowMatrix()); + _MVPW = camera->getViewMatrix() * camera->getProjectionMatrix(); + if (camera->getViewport()) _MVPW.postMult(camera->getViewport()->computeWindowMatrix()); _inverseMVPW.invert(_MVPW); + osg::Vec3 eye, center, up; + camera->getViewMatrix().getLookAt(eye, center, up); + _eyeDir = eye - center; + } else { _MVPW.makeIdentity(); _inverseMVPW.makeIdentity(); + _eyeDir = osg::Vec3(0,0,1); } } @@ -105,17 +113,19 @@ class OSGMANIPULATOR_EXPORT PointerInfo void setMousePosition(float pixel_x, float pixel_y) { - _pixel_x = pixel_x; - _pixel_y = pixel_y; + projectWindowXYIntoObject(osg::Vec2(pixel_x, pixel_y), _nearPoint, _farPoint); } + protected: + bool projectWindowXYIntoObject(const osg::Vec2& windowCoord, osg::Vec3& nearPoint, osg::Vec3& farPoint) const; public: - - float _pixel_x, _pixel_y; - osg::Camera* _camera; - IntersectionList _hitList; - IntersectionList::const_iterator _hitIter; + IntersectionList::iterator _hitIter; + + protected: + + osg::Vec3 _nearPoint,_farPoint; + osg::Vec3 _eyeDir; osg::Matrix _MVPW; osg::Matrix _inverseMVPW; @@ -139,14 +149,14 @@ class OSGMANIPULATOR_EXPORT Dragger : public Selection const CommandManager* getCommandManager() const { return _commandManager; } /** - * Set/Get parent dragger. For simple draggers parent points to itself. - * For composite draggers parent points to the parent dragger that uses - * this dragger. - */ + * Set/Get parent dragger. For simple draggers parent points to itself. + * For composite draggers parent points to the parent dragger that uses + * this dragger. + */ virtual void setParentDragger(Dragger* parent) { _parentDragger = parent; } Dragger* getParentDragger() { return _parentDragger; } const Dragger* getParentDragger() const { return _parentDragger; } - + /** Returns 0 if this Dragger is not a CompositeDragger. */ virtual const CompositeDragger* getComposite() const { return 0; } @@ -163,7 +173,7 @@ class OSGMANIPULATOR_EXPORT Dragger : public Selection CommandManager* _commandManager; - Dragger* _parentDragger; + Dragger* _parentDragger; }; @@ -210,12 +220,12 @@ class OSGMANIPULATOR_EXPORT CompositeDragger : public Dragger * could have a line with an invisible cylinder around it to enable picking on * that line. */ -void setDrawableToAlwaysCull(osg::Drawable& drawable); +void OSGMANIPULATOR_EXPORT setDrawableToAlwaysCull(osg::Drawable& drawable); /** * Convenience function for setting the material color on a node. */ -void setMaterialColor(const osg::Vec4& color, osg::Node& node); +void OSGMANIPULATOR_EXPORT setMaterialColor(const osg::Vec4& color, osg::Node& node); } diff --git a/src/osgManipulator/Dragger.cpp b/src/osgManipulator/Dragger.cpp index 9efe580ef..eb206e1d1 100644 --- a/src/osgManipulator/Dragger.cpp +++ b/src/osgManipulator/Dragger.cpp @@ -18,9 +18,9 @@ using namespace osgManipulator; PointerInfo::PointerInfo(): - _pixel_x(0.0), - _pixel_y(0.0), - _camera(0) + _nearPoint(osg::Vec3()), + _farPoint(osg::Vec3()), + _eyeDir(osg::Vec3(0,0,1)) { _hitIter = _hitList.begin(); } @@ -39,12 +39,6 @@ bool PointerInfo::projectWindowXYIntoObject(const osg::Vec2& windowCoord, osg::V return true; } -bool PointerInfo::projectObjectIntoWindow(const osg::Vec3& object,osg::Vec3& window) const -{ - window = object * _MVPW; - return true; -} - Dragger::Dragger() : _commandManager(0) { _parentDragger = this; diff --git a/src/osgManipulator/Projector.cpp b/src/osgManipulator/Projector.cpp index c7f1513ad..45d2838ec 100644 --- a/src/osgManipulator/Projector.cpp +++ b/src/osgManipulator/Projector.cpp @@ -174,12 +174,8 @@ bool getCylinderLineIntersection(const osg::Cylinder& cylinder, return true; } -osg::Vec3 getEyeDirection(const osg::Matrix& viewingMatrix, const osg::Matrix& localToWorld) +osg::Vec3 getLocalEyeDirection(const osg::Vec3& eyeDir, const osg::Matrix& localToWorld) { - osg::Vec3 eye, center, up; - viewingMatrix.getLookAt(eye, center, up); - osg::Vec3 eyeDir = eye - center; - // To take a normal from world to local you need to transform it by the transpose of the inverse of the // world to local matrix. Pre-multipling is equivalent to doing a post-multiplication of the transpose. osg::Vec3 localEyeDir = localToWorld * eyeDir; @@ -187,10 +183,10 @@ osg::Vec3 getEyeDirection(const osg::Matrix& viewingMatrix, const osg::Matrix& l return localEyeDir; } -osg::Plane computePlaneThruPointAndOrientedToEye(const osg::Matrix& viewingMatrix, const osg::Matrix& localToWorld, +osg::Plane computePlaneThruPointAndOrientedToEye(const osg::Vec3& eyeDir, const osg::Matrix& localToWorld, const osg::Vec3& point, bool front) { - osg::Vec3 planeNormal = getEyeDirection(viewingMatrix, localToWorld); + osg::Vec3 planeNormal = getLocalEyeDirection(eyeDir, localToWorld); if (! front) planeNormal = -planeNormal; osg::Plane plane; @@ -198,12 +194,12 @@ osg::Plane computePlaneThruPointAndOrientedToEye(const osg::Matrix& viewingMatri return plane; } -osg::Plane computePlaneParallelToAxisAndOrientedToEye(const osg::Matrix& viewingMatrix, const osg::Matrix& localToWorld, +osg::Plane computePlaneParallelToAxisAndOrientedToEye(const osg::Vec3& eyeDir, const osg::Matrix& localToWorld, const osg::Vec3& axisDir, float radius, osg::Vec3& planeLineStart, osg::Vec3& planeLineEnd, bool front) { - osg::Vec3 perpDir = axisDir ^ getEyeDirection(viewingMatrix, localToWorld); + osg::Vec3 perpDir = axisDir ^ getLocalEyeDirection(eyeDir, localToWorld); osg::Vec3 planeDir = perpDir ^ axisDir; planeDir.normalize(); if (! front) @@ -255,38 +251,18 @@ bool LineProjector::project(const PointerInfo& pi, osg::Vec3& projectedPoint) co osg::ref_ptr objectLine = new osg::LineSegment; objectLine->mult(*_line, getLocalToWorld()); - // Project the objectLine onto the window. - osg::ref_ptr windowLine = new osg::LineSegment; - pi.projectObjectIntoWindow(objectLine->start(), windowLine->start()); - pi.projectObjectIntoWindow(objectLine->end(), windowLine->end()); + // Get the near and far points for the mouse point. + osg::Vec3 nearPoint, farPoint; + pi.getNearFarPoints(nearPoint,farPoint); + osg::ref_ptr pointerLine = new osg::LineSegment(nearPoint,farPoint); - windowLine->start().z() = windowLine->end().z() = 0.0f; - - // Can't project if the line is straight into the screen. - if (!windowLine->valid()) - return false; - - // Compute projection of the point on the windowLine by computing the dot product. - osg::Vec2 windowLineStart(windowLine->start().x(),windowLine->start().y()); - osg::Vec2 windowLineEnd(windowLine->end().x(),windowLine->end().y()); - osg::Vec2 windowLineDirection = windowLineEnd - windowLineStart; - windowLineDirection.normalize(); - float dotProduct = (windowLineDirection) * (pi.pointToProject() - windowLineStart); - - // Get the closest point on the windowLine from (x,y). - osg::Vec2 closestWindowPt = windowLineStart + windowLineDirection * dotProduct; - - // Project the closest point back into the scene and into local space. - osg::ref_ptr projectedLocalLine = new osg::LineSegment; - pi.projectWindowXYIntoObject(closestWindowPt, projectedLocalLine->start(), projectedLocalLine->end()); - projectedLocalLine->mult(*projectedLocalLine, getWorldToLocal()); - - // Find the closest point between _line and projectedLocalLine on _line and that's the result. osg::Vec3 closestPtLine, closestPtProjWorkingLine; - if (! computeClosestPoints(*_line, *projectedLocalLine, closestPtLine, closestPtProjWorkingLine)) + if (! computeClosestPoints(*objectLine, *pointerLine, closestPtLine, closestPtProjWorkingLine)) return false; - projectedPoint = closestPtLine; + osg::Vec3 localClosestPtLine = closestPtLine * getWorldToLocal(); + + projectedPoint = localClosestPtLine; return true; } @@ -315,7 +291,7 @@ bool PlaneProjector::project(const PointerInfo& pi, osg::Vec3& projectedPoint) c // Get the near and far points for the mouse point. osg::Vec3 nearPoint, farPoint; - pi.projectWindowXYIntoObject(nearPoint,farPoint); + pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3 objectNearPoint, objectFarPoint; @@ -350,7 +326,7 @@ bool SphereProjector::project(const PointerInfo& pi, osg::Vec3& projectedPoint) // Get the near and far points for the mouse point. osg::Vec3 nearPoint, farPoint; - pi.projectWindowXYIntoObject(nearPoint,farPoint); + pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3 objectNearPoint, objectFarPoint; @@ -367,7 +343,7 @@ bool SphereProjector::project(const PointerInfo& pi, osg::Vec3& projectedPoint) bool SphereProjector::isPointInFront(const PointerInfo& pi, const osg::Matrix& localToWorld) const { osg::Vec3 centerToPoint = getSphere()->getCenter() - pi.getLocalIntersectPoint(); - if (centerToPoint * getEyeDirection(pi.getViewMatrix(), localToWorld) < 0.0) + if (centerToPoint * getLocalEyeDirection(pi.getEyeDir(), localToWorld) < 0.0) return false; return true; } @@ -456,12 +432,10 @@ bool SpherePlaneProjector::project(const PointerInfo& pi, osg::Vec3& projectedPo osg::notify(osg::WARN) << "Warning: Invalid sphere. SpherePlaneProjector::project() failed." << std::endl; return false; } - - const osg::Vec2 pointToProject = pi.pointToProject(); // Get the near and far points for the mouse point. osg::Vec3 nearPoint, farPoint; - pi.projectWindowXYIntoObject(nearPoint,farPoint); + pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3 objectNearPoint, objectFarPoint; @@ -477,7 +451,7 @@ bool SpherePlaneProjector::project(const PointerInfo& pi, osg::Vec3& projectedPo hitSphere = getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, dontCare, sphereIntersection); // Compute plane oriented to the eye. - _plane = computePlaneThruPointAndOrientedToEye(pi.getViewMatrix(), getLocalToWorld(), getSphere()->getCenter(), _front); + _plane = computePlaneThruPointAndOrientedToEye(pi.getEyeDir(), getLocalToWorld(), getSphere()->getCenter(), _front); // Find the intersection on the plane. osg::Vec3 planeIntersection; @@ -535,7 +509,7 @@ bool CylinderProjector::project(const PointerInfo& pi, osg::Vec3& projectedPoint // Get the near and far points for the mouse point. osg::Vec3 nearPoint, farPoint; - pi.projectWindowXYIntoObject(nearPoint,farPoint); + pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3 objectNearPoint, objectFarPoint; @@ -554,7 +528,7 @@ bool CylinderProjector::isPointInFront(const PointerInfo& pi, const osg::Matrix& pi.getLocalIntersectPoint(), closestPointOnAxis); osg::Vec3 perpPoint = pi.getLocalIntersectPoint() - closestPointOnAxis; - if (perpPoint * getEyeDirection(pi.getViewMatrix(), localToWorld) < 0.0) + if (perpPoint * getLocalEyeDirection(pi.getEyeDir(), localToWorld) < 0.0) return false; return true; } @@ -582,7 +556,7 @@ bool CylinderPlaneProjector::project(const PointerInfo& pi, osg::Vec3& projected // Get the near and far points for the mouse point. osg::Vec3 nearPoint, farPoint; - pi.projectWindowXYIntoObject(nearPoint,farPoint); + pi.getNearFarPoints(nearPoint,farPoint); // Transform these points into local coordinates. osg::Vec3 objectNearPoint, objectFarPoint; @@ -604,9 +578,9 @@ bool CylinderPlaneProjector::project(const PointerInfo& pi, osg::Vec3& projected } // Compute plane oriented to the eye. - _plane = computePlaneParallelToAxisAndOrientedToEye(pi.getViewMatrix(), getLocalToWorld(), _cylinderAxis, + _plane = computePlaneParallelToAxisAndOrientedToEye(pi.getEyeDir(), getLocalToWorld(), _cylinderAxis, getCylinder()->getRadius(), _planeLineStart, _planeLineEnd, - _front); + _front); // Find the intersection on the plane. osg::Vec3 planeIntersection;