/* -*-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. */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. #ifndef OSGMANIPULATOR_PROJECTOR #define OSGMANIPULATOR_PROJECTOR 1 #include #include #include #include namespace osgManipulator { /** * Base class for Projectors. Projectors maps 2D cursor motions to 3D motions. */ class OSGMANIPULATOR_EXPORT Projector : public osg::Referenced { public: Projector(); /** * Calculates the object/world coordinates (projectedPoint) of a window * coordinate (pointToProject) when projected onto some shape or * geometry (implemented in derived classes). SceneView in used for i * projecting window coordinates into object coordinates and vice versa. * Returns true on successful projection. */ virtual bool project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const = 0; /** * Sets the matrix for transforming the projector's local coordinate * system to the world/object coordinate system. */ void setLocalToWorld(const osg::Matrix& localToWorld) { _localToWorld = localToWorld; _worldToLocalDirty = true; } /** * Gets the matrix for transforming the projector's local coordinate * system to the world/object coordinate system. */ inline const osg::Matrix& getLocalToWorld() const { return _localToWorld; } /** * Gets the matrix for transforming the world/object coordinate * system to the command's local coordinate system. */ inline const osg::Matrix& getWorldToLocal() const { if (_worldToLocalDirty) { _worldToLocal.invert(_localToWorld); _worldToLocalDirty = false; } return _worldToLocal; } protected: virtual ~Projector(); osg::Matrix _localToWorld; mutable osg::Matrix _worldToLocal; mutable bool _worldToLocalDirty; }; /** * LineProjector projects points onto the closest point on the given line. */ class OSGMANIPULATOR_EXPORT LineProjector : public Projector { public: LineProjector(); LineProjector(const osg::LineSegment::vec_type& s, const osg::LineSegment::vec_type& e); inline void setLine(const osg::LineSegment::vec_type& s, const osg::LineSegment::vec_type& e) { _line->start() = s; _line->end() = e; } inline const osg::LineSegment::vec_type& getLineStart() const { return _line->start(); } inline osg::LineSegment::vec_type& getLineStart() { return _line->start(); } inline const osg::LineSegment::vec_type& getLineEnd() const { return _line->end(); } inline osg::LineSegment::vec_type& getLineEnd() { return _line->end(); } /** * Calculates the object coordinates (projectedPoint) of a window * coordinate (pointToProject) when projected onto the given line. * Returns true on successful projection. */ virtual bool project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const; protected: virtual ~LineProjector(); osg::ref_ptr _line; }; /** * PlaneProjector projects points onto the given line. */ class OSGMANIPULATOR_EXPORT PlaneProjector : public Projector { public: PlaneProjector(); PlaneProjector(const osg::Plane& plane); inline void setPlane(const osg::Plane& plane) { _plane = plane; } inline const osg::Plane& getPlane() const { return _plane; } /** * Calculates the object coordinates (projectedPoint) of a window * coordinate (pointToProject) when projected onto the given plane. * Returns true on successful projection. */ virtual bool project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const; protected: virtual ~PlaneProjector(); osg::Plane _plane; }; /** * SphereProjector projects points onto the given sphere. */ class OSGMANIPULATOR_EXPORT SphereProjector : public Projector { public: SphereProjector(); SphereProjector(osg::Sphere* sphere); inline void setSphere(osg::Sphere* sphere) { _sphere = sphere; } inline const osg::Sphere* getSphere() const { return _sphere.get(); } /** * Calculates the object coordinates (projectedPoint) of a window * coordinate (pointToProject) when projected onto the given sphere. * Returns true on successful projection. */ virtual bool project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const; /** * Returns true is the point is in front of the cylinder given the eye * direction. */ bool isPointInFront(const PointerInfo& pi, const osg::Matrix& localToWorld) const; void setFront(bool front) { _front = front; } protected: virtual ~SphereProjector(); osg::ref_ptr _sphere; bool _front; }; /** * SpherePlaneProjector projects points onto a sphere, failing which it project * onto a plane oriented to the viewing direction. */ class OSGMANIPULATOR_EXPORT SpherePlaneProjector : public SphereProjector { public: SpherePlaneProjector(); SpherePlaneProjector(osg::Sphere* sphere); /** * Calculates the object coordinates (projectedPoint) of a window * coordinate (pointToProject) when projected onto the given sphere. * Returns true on successful projection. */ virtual bool project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const; /** * Returns true if the previous projection was on the sphere and false * if the projection was on the plane. */ bool isProjectionOnSphere() const { return _onSphere; } osg::Quat getRotation(const osg::Vec3d& p1, bool p1OnSphere, const osg::Vec3d& p2, bool p2OnSphere, float radialFactor = 0.0f) const; protected: virtual ~SpherePlaneProjector(); mutable osg::Plane _plane; mutable bool _onSphere; }; /** * CylinderProjector projects points onto the given cylinder. */ class OSGMANIPULATOR_EXPORT CylinderProjector : public Projector { public: CylinderProjector(); CylinderProjector(osg::Cylinder* cylinder); inline void setCylinder(osg::Cylinder* cylinder) { _cylinder = cylinder; _cylinderAxis = osg::Vec3d(0.0,0.0,1.0) * osg::Matrix(cylinder->getRotation()); _cylinderAxis.normalize(); } inline const osg::Cylinder* getCylinder() const { return _cylinder.get(); } /** * Calculates the object coordinates (projectedPoint) of a window * coordinate (pointToProject) when projected onto the given plane. * Returns true on successful projection. */ virtual bool project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const; /** * Returns true is the point is in front of the cylinder given the eye * direction. */ bool isPointInFront(const PointerInfo& pi, const osg::Matrix& localToWorld) const; void setFront(bool front) { _front = front; } protected: virtual ~CylinderProjector(); osg::ref_ptr _cylinder; osg::Vec3d _cylinderAxis; bool _front; }; /** * CylinderPlaneProjector projects a point onto a plane relative to the * given cylinder. For most cases, the plane will be parallel to the * cylinder axis oriented towards the eyepoint. When the eyepoint and * cylinder axis are close to parallel, then it will project onto a plane * perpendicular to the cylinder. */ class OSGMANIPULATOR_EXPORT CylinderPlaneProjector : public CylinderProjector { public: CylinderPlaneProjector(); CylinderPlaneProjector(osg::Cylinder* cylinder); /** * Calculates the object coordinates (projectedPoint) of a window * coordinate (pointToProject) when projected onto the given plane. * Returns true on successful projection. * \param[in] pi Incoming intersection information * \param[out] projectedPoint Point located on the given plane * \return bool Whether the projection onto the plane was successful. */ virtual bool project(const PointerInfo& pi, osg::Vec3d& projectedPoint) const; /** * Generates a rotation about the cylinder axis based upon the incoming * projected points on the plane computed from project(). * \param[in] p1 Initial projection point * \param[in] p2 Second projection point * \return osg::Quat Rotation about cylinder axis */ osg::Quat getRotation(const osg::Vec3d& p1, const osg::Vec3d& p2) const; protected: virtual ~CylinderPlaneProjector(); mutable osg::Plane _plane; mutable osg::Vec3d _planeLineStart, _planeLineEnd; mutable bool _parallelPlane; }; } #endif