From Vivek Rajan, new osgManipulator library, with a few minor tweaks and rename for osgDragger to osgManipulator for build by Robert Osfield.

Vivek's email to osg-submissions:

"I'm happy to release the osgdragger nodekit to the OSG community. I
implemented the nodekit for my company, Fugro-Jason Inc., and they
have kindly agreed to open source it.

The nodekit contains a few draggers but it should be easy to build new
draggers on top of it. The design of the nodekit is based on a
SIGGRAPH 2002 course - "Design and Implementation of Direct
Manipulation in 3D". You can find the course notes at
http://www.pauliface.com/Sigg02/index.html. Reading pages 20 - 29 of
the course notes should give you a fair understanding of how the
nodekit works.

The source code also contains an example of how to use the draggers."
This commit is contained in:
Robert Osfield
2007-02-11 10:33:59 +00:00
parent f1a82f35b2
commit 19db0c1674
49 changed files with 6774 additions and 1 deletions

View File

@@ -0,0 +1,192 @@
/* -*-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.
#include <osgManipulator/AntiSquish>
using namespace osgManipulator;
namespace
{
class AntiSquishCallback: public osg::NodeCallback
{
public:
AntiSquishCallback(AntiSquish* asq) : osg::NodeCallback(), _antiSquish(asq) {}
virtual ~AntiSquishCallback() {};
virtual void operator() (osg::Node*, osg::NodeVisitor* nv)
{
// Get the node path.
osg::NodePath np = nv->getNodePath();
// Remove the last node which is the anti squish node itself.
np.pop_back();
// Get the accumulated modeling matrix.
osg::Matrix localToWorld = computeLocalToWorld(np);
// compute the unsquished matrix.
bool flag = false;
osg::Matrix _unsquishedMatrix = _antiSquish->computeUnSquishedMatrix(localToWorld, flag);
if (flag)
_antiSquish->setMatrix(_unsquishedMatrix);
}
protected:
AntiSquish* _antiSquish;
};
}
AntiSquish::AntiSquish() : _usePivot(true), _usePosition(false)
{
_asqCallback = new AntiSquishCallback(this);
setUpdateCallback(_asqCallback);
}
AntiSquish::AntiSquish(const osg::Vec3& pivot) : _pivot(pivot), _usePivot(true), _usePosition(false)
{
_asqCallback = new AntiSquishCallback(this);
setUpdateCallback(_asqCallback);
}
AntiSquish::AntiSquish(const osg::Vec3& pivot, const osg::Vec3& pos)
: _pivot(pivot), _usePivot(true), _position(pos), _usePosition(true)
{
_asqCallback = new AntiSquishCallback(this);
setUpdateCallback(_asqCallback);
}
AntiSquish::AntiSquish(const AntiSquish& pat,const osg::CopyOp& copyop) :
MatrixTransform(pat,copyop),
_asqCallback(pat._asqCallback),
_pivot(pat._pivot),
_usePivot(pat._usePivot),
_position(pat._position),
_usePosition(pat._usePosition),
_cachedLocalToWorld(pat._cachedLocalToWorld)
{
}
AntiSquish::~AntiSquish()
{
}
osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& flag)
{
osg::Vec3d t, s;
osg::Quat r, so;
if (LTW == _cachedLocalToWorld && _dirty == false)
{
flag = false;
return osg::Matrix::identity();
}
_cachedLocalToWorld = LTW;
LTW.decompose(t, r, s, so);
// Let's take an average of the scale.
double av = (s[0] + s[1] + s[2])/3.0;
s[0] = av; s[1] = av; s[2]=av;
if (av == 0)
{
flag = false;
return osg::Matrix::identity();
}
osg::Matrix unsquished;
//
// Final Matrix: [-Pivot][SO]^[S][SO][R][T][Pivot][LOCALTOWORLD]^[position]
// OR [SO]^[S][SO][R][T][LOCALTOWORLD]^
//
if (_usePivot)
{
osg::Matrix tmpPivot;
tmpPivot.setTrans(-_pivot);
unsquished.postMult(tmpPivot);
osg::Matrix tmps, invtmps;
so.get(tmps);
invtmps = osg::Matrix::inverse(tmps);
if (invtmps.isNaN())
{
flag = false;
return osg::Matrix::identity();
}
//SO^
unsquished.postMult(invtmps);
//S
unsquished.postMult(osg::Matrix::scale(s[0], s[1], s[2]));
//SO
unsquished.postMult(tmps);
tmpPivot.makeIdentity();
osg::Matrix tmpr;
r.get(tmpr);
//R
unsquished.postMult(tmpr);
//T
unsquished.postMult(osg::Matrix::translate(t[0],t[1],t[2]));
osg::Matrix invltw;
invltw = osg::Matrix::inverse(LTW);
if (invltw.isNaN())
{
flag =false;
return osg::Matrix::identity();
}
// LTW^
unsquished.postMult( invltw );
// Position
tmpPivot.makeIdentity();
if (_usePosition)
tmpPivot.setTrans(_position);
else
tmpPivot.setTrans(_pivot);
unsquished.postMult(tmpPivot);
}
else
{
osg::Matrix tmps, invtmps;
so.get(tmps);
invtmps = osg::Matrix::inverse(tmps);
unsquished.postMult(invtmps);
unsquished.postMult(osg::Matrix::scale(s[0], s[1], s[2]));
unsquished.postMult(tmps);
osg::Matrix tmpr;
r.get(tmpr);
unsquished.postMult(tmpr);
unsquished.postMult(osg::Matrix::translate(t[0],t[1],t[2]));
unsquished.postMult( osg::Matrix::inverse(LTW) );
}
if (unsquished.isNaN())
{
flag = false;
return osg::Matrix::identity();
}
flag = true;
_dirty = false;
return unsquished;
}

View File

@@ -0,0 +1,321 @@
/* -*-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.
#include <osgManipulator/Command>
#include <osgManipulator/Selection>
#include <osgManipulator/Constraint>
#include <algorithm>
using namespace osgManipulator;
///////////////////////////////////////////////////////////////////////////////
//
// Motion Command base class.
//
MotionCommand::MotionCommand() : _stage(NONE)
{
}
MotionCommand::~MotionCommand()
{
}
void MotionCommand::addSelection(Selection* selection)
{
_selectionList.push_back(selection);
}
void MotionCommand::removeSelection(Selection* selection)
{
_selectionList.erase(std::remove(_selectionList.begin(), _selectionList.end(), selection),
_selectionList.end());
}
///////////////////////////////////////////////////////////////////////////////
//
// Translate in line command.
//
TranslateInLineCommand::TranslateInLineCommand()
{
_line = new osg::LineSegment;
}
TranslateInLineCommand::TranslateInLineCommand(const osg::Vec3& s, const osg::Vec3& e)
{
_line = new osg::LineSegment(s,e);
}
TranslateInLineCommand::~TranslateInLineCommand()
{
}
bool TranslateInLineCommand::execute()
{
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*this);
}
return true;
}
bool TranslateInLineCommand::unexecute()
{
osg::ref_ptr<TranslateInLineCommand> inverse = new TranslateInLineCommand();
*inverse = *this;
inverse->setTranslation(-_translation);
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*inverse);
}
return true;
}
void TranslateInLineCommand::applyConstraint(const Constraint* constraint)
{
if (constraint) constraint->constrain(*this);
}
///////////////////////////////////////////////////////////////////////////////
//
// Translate in plane command.
//
TranslateInPlaneCommand::TranslateInPlaneCommand()
{
}
TranslateInPlaneCommand::TranslateInPlaneCommand(const osg::Plane& plane) : _plane(plane)
{
}
TranslateInPlaneCommand::~TranslateInPlaneCommand()
{
}
bool TranslateInPlaneCommand::execute()
{
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*this);
}
return true;
}
bool TranslateInPlaneCommand::unexecute()
{
osg::ref_ptr<TranslateInPlaneCommand> inverse = new TranslateInPlaneCommand();
*inverse = *this;
inverse->setTranslation(-_translation);
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*inverse);
}
return true;
}
void TranslateInPlaneCommand::applyConstraint(const Constraint* constraint)
{
if (constraint) constraint->constrain(*this);
}
///////////////////////////////////////////////////////////////////////////////
//
// Scale 1D command.
//
Scale1DCommand::Scale1DCommand() : _scale(1.0f)
{
}
Scale1DCommand::~Scale1DCommand()
{
}
bool Scale1DCommand::execute()
{
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*this);
}
return true;
}
bool Scale1DCommand::unexecute()
{
osg::ref_ptr<Scale1DCommand> inverse = new Scale1DCommand();
*inverse = *this;
if (_scale) inverse->setScale(1.0/_scale);
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*inverse);
}
return true;
}
void Scale1DCommand::applyConstraint(const Constraint* constraint)
{
if (constraint) constraint->constrain(*this);
}
///////////////////////////////////////////////////////////////////////////////
//
// Scale 2D command.
//
Scale2DCommand::Scale2DCommand() : _scale(1.0,1.0)
{
}
Scale2DCommand::~Scale2DCommand()
{
}
bool Scale2DCommand::execute()
{
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*this);
}
return true;
}
bool Scale2DCommand::unexecute()
{
osg::ref_ptr<Scale2DCommand> inverse = new Scale2DCommand();
*inverse = *this;
if (_scale[0] && _scale[1])
inverse->setScale(osg::Vec2(1.0/_scale[0],1.0/_scale[1]));
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*inverse);
}
return true;
}
void Scale2DCommand::applyConstraint(const Constraint* constraint)
{
if (constraint) constraint->constrain(*this);
}
///////////////////////////////////////////////////////////////////////////////
//
// Scale uniform command.
//
ScaleUniformCommand::ScaleUniformCommand() : _scale(1.0f)
{
}
ScaleUniformCommand::~ScaleUniformCommand()
{
}
bool ScaleUniformCommand::execute()
{
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*this);
}
return true;
}
bool ScaleUniformCommand::unexecute()
{
osg::ref_ptr<ScaleUniformCommand> inverse = new ScaleUniformCommand();
*inverse = *this;
if (_scale) inverse->setScale(1.0/_scale);
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*inverse);
}
return true;
}
void ScaleUniformCommand::applyConstraint(const Constraint* constraint)
{
if (constraint) constraint->constrain(*this);
}
///////////////////////////////////////////////////////////////////////////////
//
// Rotate 3D command.
//
Rotate3DCommand::Rotate3DCommand()
{
}
Rotate3DCommand::~Rotate3DCommand()
{
}
bool Rotate3DCommand::execute()
{
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*this);
}
return true;
}
bool Rotate3DCommand::unexecute()
{
osg::ref_ptr<Rotate3DCommand> inverse = new Rotate3DCommand();
*inverse = *this;
inverse->setRotation(_rotation.inverse());
for (SelectionList::iterator iter = getSelectionList().begin();
iter != getSelectionList().end();
++iter)
{
(*iter)->receive(*inverse);
}
return true;
}
void Rotate3DCommand::applyConstraint(const Constraint* constraint)
{
if (constraint) constraint->constrain(*this);
}

View File

@@ -0,0 +1,124 @@
/* -*-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.
#include <osgManipulator/CommandManager>
#include <osgManipulator/Command>
using namespace osgManipulator;
CommandManager::CommandManager()
{
}
CommandManager::~CommandManager()
{
}
bool CommandManager::connect(Dragger& dragger, Selection& selection)
{
dragger.setCommandManager(this);
// Check to see if the selection is already associated with the dragger.
if (_draggerSelectionMap.count(&dragger) > 0)
{
std::pair<DraggerSelectionMap::iterator,DraggerSelectionMap::iterator> s;
s = _draggerSelectionMap.equal_range(&dragger);
for (DraggerSelectionMap::iterator iter = s.first; iter != s.second; ++iter)
{
if (iter->second == &selection)
return false;
}
}
// Associate selection with dragger
_draggerSelectionMap.insert(DraggerSelectionMap::value_type(&dragger,&selection));
return true;
}
bool CommandManager::connect(Dragger& dragger, Constraint& constraint)
{
dragger.setCommandManager(this);
// Check to see if the selection is already associated with the dragger.
if (_draggerConstraintMap.count(&dragger) > 0)
{
std::pair<DraggerConstraintMap::iterator,DraggerConstraintMap::iterator> s;
s = _draggerConstraintMap.equal_range(&dragger);
for (DraggerConstraintMap::iterator iter = s.first; iter != s.second; ++iter)
{
if (iter->second == &constraint)
return false;
}
}
// Associate selection with dragger
_draggerConstraintMap.insert(DraggerConstraintMap::value_type(&dragger,&constraint));
return true;
}
bool CommandManager::disconnect(Dragger& dragger)
{
_draggerSelectionMap.erase(&dragger);
_draggerConstraintMap.erase(&dragger);
return true;
}
void CommandManager::dispatch(MotionCommand& command)
{
command.execute();
}
void CommandManager::addSelectionsToCommand(MotionCommand& command, Dragger& dragger)
{
// Apply constraints to the command.
if (_draggerConstraintMap.count(&dragger) > 0)
{
// Get all the selections assoicated with this dragger.
std::pair<DraggerConstraintMap::iterator,DraggerConstraintMap::iterator> s;
s = _draggerConstraintMap.equal_range(&dragger);
for (DraggerConstraintMap::iterator iter = s.first; iter != s.second; ++iter)
{
// Add the selection to the command.
if (iter->second.valid())
{
command.applyConstraint(iter->second.get());
}
}
}
// Add the dragger to the selection list first.
command.addSelection(&dragger);
// Add the remaining selections.
if (_draggerSelectionMap.count(&dragger) > 0)
{
// Get all the selections assoicated with this dragger.
std::pair<DraggerSelectionMap::iterator,DraggerSelectionMap::iterator> s;
s = _draggerSelectionMap.equal_range(&dragger);
for (DraggerSelectionMap::iterator iter = s.first; iter != s.second; ++iter)
{
// Add the selection to the command.
if (iter->second.valid())
{
command.addSelection(iter->second.get());
}
}
}
}

View File

@@ -0,0 +1,165 @@
/* -*-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.
#include <osgManipulator/Constraint>
#include <osgManipulator/Command>
#include <osg/Vec2d>
#include <math.h>
using namespace osgManipulator;
namespace
{
double round_to_nearest_int(double x) { return floor(x+0.5); }
osg::Vec3d snap_point_to_grid(const osg::Vec3d& point, const osg::Vec3d& origin, const osg::Vec3d& spacing)
{
osg::Vec3d scale;
scale[0] = spacing[0] ? round_to_nearest_int((point[0] - origin[0]) / spacing[0]) : 1.0;
scale[1] = spacing[1] ? round_to_nearest_int((point[1] - origin[1]) / spacing[1]) : 1.0;
scale[2] = spacing[2] ? round_to_nearest_int((point[2] - origin[2]) / spacing[2]) : 1.0;
osg::Vec3d snappedPoint = origin;
snappedPoint += osg::Vec3(scale[0]*spacing[0],scale[1]*spacing[1],scale[2]*spacing[2]);
return snappedPoint;
}
}
void Constraint::computeLocalToWorldAndWorldToLocal() const
{
osg::NodePath pathToRoot;
computeNodePathToRoot(const_cast<osg::Node&>(getReferenceNode()),pathToRoot);
_localToWorld = osg::computeLocalToWorld(pathToRoot);
_worldToLocal = osg::computeWorldToLocal(pathToRoot);
}
GridConstraint::GridConstraint(osg::Node& refNode, const osg::Vec3d& origin, const osg::Vec3d& spacing)
: Constraint(refNode), _origin(origin), _spacing(spacing)
{
}
bool GridConstraint::constrain(TranslateInLineCommand& command) const
{
if (command.getStage() == osgManipulator::MotionCommand::START)
computeLocalToWorldAndWorldToLocal();
else if (command.getStage() == osgManipulator::MotionCommand::FINISH)
return true;
osg::Vec3 translatedPoint = command.getLineStart() + command.getTranslation();
osg::Vec3d localTranslatedPoint = (osg::Vec3d(translatedPoint)
* command.getLocalToWorld() * getWorldToLocal());
osg::Vec3d newLocalTranslatedPoint = snap_point_to_grid(localTranslatedPoint,
_origin,
_spacing);
command.setTranslation(newLocalTranslatedPoint * getLocalToWorld() * command.getWorldToLocal() - command.getLineStart());
return true;
}
bool GridConstraint::constrain(TranslateInPlaneCommand& command) const
{
if (command.getStage() == osgManipulator::MotionCommand::START)
computeLocalToWorldAndWorldToLocal();
else if (command.getStage() == osgManipulator::MotionCommand::FINISH)
return true;
osg::Matrix commandToConstraint = command.getLocalToWorld() * getWorldToLocal();
osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal();
// Snap the reference point to grid.
osg::Vec3d localRefPoint = command.getReferencePoint() * commandToConstraint;
osg::Vec3d snappedLocalRefPoint = snap_point_to_grid(localRefPoint, _origin, _spacing);
osg::Vec3d snappedCmdRefPoint = snappedLocalRefPoint * constraintToCommand;
// Snap the translated point to grid.
osg::Vec3 translatedPoint = snappedCmdRefPoint + command.getTranslation();
osg::Vec3d localTranslatedPoint = osg::Vec3d(translatedPoint) * commandToConstraint;
osg::Vec3d newLocalTranslatedPoint = snap_point_to_grid(localTranslatedPoint, _origin, _spacing);
// Set the snapped translation.
command.setTranslation(newLocalTranslatedPoint * constraintToCommand - snappedCmdRefPoint);
return true;
}
bool GridConstraint::constrain(Scale1DCommand& command) const
{
if (command.getStage() == osgManipulator::MotionCommand::START)
computeLocalToWorldAndWorldToLocal();
else if (command.getStage() == osgManipulator::MotionCommand::FINISH)
return true;
double scaledPoint = (command.getReferencePoint() - command.getScaleCenter()) * command.getScale() + command.getScaleCenter();
osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal();
osg::Vec3d commandOrigin = _origin * constraintToCommand;
osg::Vec3d commandSpacing = (_origin + _spacing) * constraintToCommand - commandOrigin;
double spacingFactor = commandSpacing[0] ? round_to_nearest_int((scaledPoint-commandOrigin[0])/commandSpacing[0]) : 1.0;
double snappedScaledPoint = commandOrigin[0] + commandSpacing[0] * spacingFactor;
double denom = (command.getReferencePoint() - command.getScaleCenter());
double snappedScale = (denom) ? (snappedScaledPoint - command.getScaleCenter()) / denom : 1.0;
if (snappedScale < command.getMinScale()) snappedScale = command.getMinScale();
command.setScale(snappedScale);
return true;
}
bool GridConstraint::constrain(Scale2DCommand& command) const
{
if (command.getStage() == osgManipulator::MotionCommand::START)
computeLocalToWorldAndWorldToLocal();
else if (command.getStage() == osgManipulator::MotionCommand::FINISH)
return true;
osg::Vec2d scaledPoint = command.getReferencePoint() - command.getScaleCenter();
scaledPoint[0] *= command.getScale()[0];
scaledPoint[1] *= command.getScale()[1];
scaledPoint += command.getScaleCenter();
osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal();
osg::Vec3d commandOrigin = _origin * constraintToCommand;
osg::Vec3d commandSpacing = (_origin + _spacing) * constraintToCommand - commandOrigin;
osg::Vec2d spacingFactor;
spacingFactor[0] = commandSpacing[0] ? round_to_nearest_int((scaledPoint[0] - commandOrigin[0])/commandSpacing[0]) : 1.0;
spacingFactor[1] = commandSpacing[2] ? round_to_nearest_int((scaledPoint[1] - commandOrigin[2])/commandSpacing[2]) : 1.0;
osg::Vec2d snappedScaledPoint = (osg::Vec2d(commandOrigin[0],commandOrigin[2])
+ osg::Vec2d(commandSpacing[0]*spacingFactor[0],
commandSpacing[2]*spacingFactor[1]));
osg::Vec2d denom = command.getReferencePoint() - command.getScaleCenter();
osg::Vec2 snappedScale;
snappedScale[0] = denom[0] ? (snappedScaledPoint[0] - command.getScaleCenter()[0]) / denom[0] : 1.0;
snappedScale[1] = denom[1] ? (snappedScaledPoint[1] - command.getScaleCenter()[1]) / denom[1] : 1.0;
if (snappedScale[0] < command.getMinScale()[0]) snappedScale[0] = command.getMinScale()[0];
if (snappedScale[1] < command.getMinScale()[1]) snappedScale[1] = command.getMinScale()[1];
command.setScale(snappedScale);
return true;
}
bool GridConstraint::constrain(ScaleUniformCommand&) const
{
// Can you correctly snap a ScaleUniformCommand using a Grid constraint that has
// different spacings in the three axis??
return false;
}

View File

@@ -0,0 +1,127 @@
/* -*-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.
#include <osgManipulator/Dragger>
#include <osg/Material>
using namespace osgManipulator;
Dragger::Dragger() : _commandManager(0)
{
_parentDragger = this;
}
Dragger::~Dragger()
{
}
bool CompositeDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList& hl, const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
// Check if the dragger node is in the nodepath.
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
for (DraggerList::iterator itr=_draggerList.begin(); itr!=_draggerList.end(); ++itr)
{
if ((*itr)->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa))
return true;
}
return false;
}
bool CompositeDragger::containsDragger( const Dragger* dragger ) const
{
for (DraggerList::const_iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
{
if (itr->get() == dragger) return true;
}
return false;
}
CompositeDragger::DraggerList::iterator CompositeDragger::findDragger( const Dragger* dragger )
{
for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
{
if (itr->get() == dragger) return itr;
}
return _draggerList.end();
}
bool CompositeDragger::addDragger(Dragger *dragger)
{
if (dragger && !containsDragger(dragger))
{
_draggerList.push_back(dragger);
return true;
}
else return false;
}
bool CompositeDragger::removeDragger(Dragger *dragger)
{
DraggerList::iterator itr = findDragger(dragger);
if (itr != _draggerList.end())
{
_draggerList.erase(itr);
return true;
}
else return false;
}
void CompositeDragger::setCommandManager(CommandManager* cm)
{
for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
{
(*itr)->setCommandManager(cm);
}
Dragger::setCommandManager(cm);
}
void CompositeDragger::setParentDragger(Dragger* dragger)
{
for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
{
(*itr)->setParentDragger(dragger);
}
Dragger::setParentDragger(dragger);
}
class ForceCullCallback : public osg::Drawable::CullCallback
{
public:
virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const
{
return true;
}
};
void osgManipulator::setDrawableToAlwaysCull(osg::Drawable& drawable)
{
ForceCullCallback* cullCB = new ForceCullCallback;
drawable.setCullCallback (cullCB);
}
void osgManipulator::setMaterialColor(const osg::Vec4& color, osg::Node& node)
{
osg::Material* mat = dynamic_cast<osg::Material*>(node.getOrCreateStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
if (! mat)
{
mat = new osg::Material;
node.getOrCreateStateSet()->setAttribute(mat);
}
mat->setDiffuse(osg::Material::FRONT_AND_BACK, color);
}

View File

@@ -0,0 +1,37 @@
TOPDIR = ../..
include $(TOPDIR)/Make/makedefs
CXXFILES = \
AntiSquish.cpp \
Command.cpp \
CommandManager.cpp \
Constraint.cpp \
Dragger.cpp \
Projector.cpp \
RotateCylinderDragger.cpp \
RotateSphereDragger.cpp \
Scale1DDragger.cpp \
Scale2DDragger.cpp \
ScaleAxisDragger.cpp \
Selection.cpp \
TabBoxDragger.cpp \
TabPlaneDragger.cpp \
TabPlaneTrackballDragger.cpp \
TrackballDragger.cpp \
Translate1DDragger.cpp \
Translate2DDragger.cpp \
TranslateAxisDragger.cpp \
TranslatePlaneDragger.cpp
DEF += -DOSGMANIPULATOR_LIBRARY
INC +=
LIBS += -losgGA -losgUtil -losg $(GL_LIBS) $(OTHER_LIBS)
TARGET_BASENAME = osgManipulator
LIB = $(LIB_PREFIX)$(TARGET_BASENAME).$(LIB_EXT)
include $(TOPDIR)/Make/makerules

View File

@@ -0,0 +1,711 @@
/* -*-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.
#include <osgManipulator/Projector>
using namespace osgManipulator;
namespace
{
bool computeClosestPoints(const osg::LineSegment& l1, const osg::LineSegment& l2,
osg::Vec3& p1, osg::Vec3& p2)
{
// Computes the closest points (p1 and p2 on line l1 and l2 respectively) between the two lines
// An explanation of the algorithm can be found at
// http://www.geometryalgorithms.com/Archive/algorithm_0106/algorithm_0106.htm
osg::Vec3 u = l1.end() - l1.start(); u.normalize();
osg::Vec3 v = l2.end() - l2.start(); v.normalize();
osg::Vec3 w0 = l1.start() - l2.start();
float a = u * u;
float b = u * v;
float c = v * v;
float d = u * w0;
float e = v * w0;
float denominator = a*c - b*b;
// Test if lines are parallel
if (denominator == 0.0) return false;
float sc = (b*e - c*d)/denominator;
float tc = (a*e - b*d)/denominator;
p1 = l1.start() + u * sc;
p2 = l2.start() + v * tc;
return true;
}
bool computeClosestPointOnLine(const osg::Vec3& lineStart, const osg::Vec3& lineEnd,
const osg::Vec3& fromPoint, osg::Vec3& closestPoint)
{
osg::Vec3 v = lineEnd - lineStart;
osg::Vec3 w = fromPoint - lineStart;
float c1 = w * v;
float c2 = v * v;
float almostZero = 0.000001;
if (c2 < almostZero) return false;
float b = c1 / c2;
closestPoint = lineStart + v * b;
return true;
}
bool getPlaneLineIntersection(const osg::Vec4& plane,
const osg::Vec3& lineStart, const osg::Vec3& lineEnd,
osg::Vec3& isect)
{
const double deltaX = lineEnd.x() - lineStart.x();
const double deltaY = lineEnd.y() - lineStart.y();
const double deltaZ = lineEnd.z() - lineStart.z();
const double denominator = (plane[0]*deltaX + plane[1]*deltaY + plane[2]*deltaZ);
if (! denominator) return false;
const double C = (plane[0]*lineStart.x() + plane[1]*lineStart.y() + plane[2]*lineStart.z() + plane[3]) / denominator;
isect.x() = lineStart.x() - deltaX * C;
isect.y() = lineStart.y() - deltaY * C;
isect.z() = lineStart.z() - deltaZ * C;
return true;
}
bool getSphereLineIntersection(const osg::Sphere& sphere,
const osg::Vec3& lineStart, const osg::Vec3& lineEnd,
osg::Vec3& frontISect, osg::Vec3& backISect)
{
osg::Vec3 lineDirection = lineEnd - lineStart;
lineDirection.normalize();
osg::Vec3 v = lineStart - sphere.getCenter();
float B = 2.0f * (lineDirection * v);
float C = v * v - sphere.getRadius() * sphere.getRadius();
float discriminant = B * B - 4.0f * C;
if (discriminant < 0.0f) // Line and sphere don't intersect.
return false;
float discriminantSqroot = sqrtf(discriminant);
float t0 = (-B - discriminantSqroot) * 0.5f;
frontISect = lineStart + lineDirection * t0;
float t1 = (-B + discriminantSqroot) * 0.5f;
backISect = lineStart + lineDirection * t1;
return true;
}
bool getUnitCylinderLineIntersection(const osg::Vec3& lineStart, const osg::Vec3& lineEnd,
osg::Vec3& isectFront, osg::Vec3& isectBack)
{
osg::Vec3 dir = lineEnd - lineStart;
dir.normalize();
float a = dir[0] * dir[0] + dir[1] * dir[1];
float b = 2.0f * (lineStart[0] * dir[0] + lineStart[1] * dir[1]);
float c = lineStart[0] * lineStart[0] + lineStart[1] * lineStart[1] - 1;
float d = b*b - 4*a*c;
if (d < 0.0f) return false;
float dSqroot = sqrtf(d);
float t0, t1;
if (b > 0.0f)
{
t0 = -(2.0f * c) / (dSqroot + b);
t1 = -(dSqroot + b) / (2.0 * a);
}
else
{
t0 = (2.0f * c) / (dSqroot - b);
t1 = (dSqroot - b) / (2.0 * a);
}
isectFront = lineStart + dir * t0;
isectBack = lineStart + dir * t1;
return true;
}
bool getCylinderLineIntersection(const osg::Cylinder& cylinder,
const osg::Vec3& lineStart, const osg::Vec3& lineEnd,
osg::Vec3& isectFront, osg::Vec3& isectBack)
{
// Compute matrix transformation that takes the cylinder to a unit cylinder with Z-axis as it's axis and
// (0,0,0) as it's center.
float oneOverRadius = 1.0f / cylinder.getRadius();
osg::Matrix toUnitCylInZ = osg::Matrix::translate(-cylinder.getCenter())
* osg::Matrix::scale(oneOverRadius, oneOverRadius, oneOverRadius)
* osg::Matrix(cylinder.getRotation().inverse());
// Transform the lineStart and lineEnd into the unit cylinder space.
osg::Vec3 unitCylLineStart = lineStart * toUnitCylInZ;
osg::Vec3 unitCylLineEnd = lineEnd * toUnitCylInZ;
// Intersect line with unit cylinder.
osg::Vec3 unitCylIsectFront, unitCylIsectBack;
if (! getUnitCylinderLineIntersection(unitCylLineStart, unitCylLineEnd, unitCylIsectFront, unitCylIsectBack))
return false;
// Transform back from unit cylinder space.
osg::Matrix invToUnitCylInZ(osg::Matrix::inverse(toUnitCylInZ));
isectFront = unitCylIsectFront * invToUnitCylInZ;
isectBack = unitCylIsectBack * invToUnitCylInZ;
return true;
}
osg::Vec3 getEyeDirection(const osg::Matrix& viewingMatrix, 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;
localEyeDir.normalize();
return localEyeDir;
}
osg::Plane computePlaneThruPointAndOrientedToEye(const osg::Matrix& viewingMatrix, const osg::Matrix& localToWorld,
const osg::Vec3& point, bool front)
{
osg::Vec3 planeNormal = getEyeDirection(viewingMatrix, localToWorld);
if (! front) planeNormal = -planeNormal;
osg::Plane plane;
plane.set(planeNormal, point);
return plane;
}
osg::Plane computePlaneParallelToAxisAndOrientedToEye(const osg::Matrix& viewingMatrix, 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 planeDir = perpDir ^ axisDir;
planeDir.normalize();
if (! front)
planeDir = -planeDir;
osg::Vec3 planePoint = planeDir * radius + axisDir;
osg::Plane plane;
plane.set(planeDir, planePoint);
planeLineStart = planePoint;
planeLineEnd = planePoint + axisDir;
return plane;
}
}
Projector::Projector() : _worldToLocalDirty(false)
{
}
Projector::~Projector()
{
}
LineProjector::LineProjector()
{
_line = new osg::LineSegment(osg::Vec3(0.0,0.0,0.0), osg::Vec3(1.0,0.0,0.0));
}
LineProjector::LineProjector(const osg::Vec3& s, const osg::Vec3& e)
{
_line = new osg::LineSegment(s,e);
}
LineProjector::~LineProjector()
{
}
bool LineProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const
{
if (!_line->valid())
{
osg::notify(osg::WARN) << "Warning: Invalid line set. LineProjector::project() failed."<<std::endl;
return false;
}
// Transform the line to world/object coordinate space.
osg::ref_ptr<osg::LineSegment> objectLine = new osg::LineSegment;
objectLine->mult(*_line, getLocalToWorld());
// Project the objectLine onto the window.
osg::ref_ptr<osg::LineSegment> windowLine = new osg::LineSegment;
sv.projectObjectIntoWindow(objectLine->start(), windowLine->start());
sv.projectObjectIntoWindow(objectLine->end(), windowLine->end());
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) * (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<osg::LineSegment> projectedLocalLine = new osg::LineSegment;
sv.projectWindowXYIntoObject((int)closestWindowPt.x(), (int)closestWindowPt.y(), 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))
return false;
projectedPoint = closestPtLine;
return true;
}
PlaneProjector::PlaneProjector()
{
}
PlaneProjector::PlaneProjector(const osg::Plane& plane)
{
_plane = plane;
}
PlaneProjector::~PlaneProjector()
{
}
bool PlaneProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const
{
if (!_plane.valid())
{
osg::notify(osg::WARN) << "Warning: Invalid plane set. PlaneProjector::project() failed."<< std::endl;
return false;
}
// Get the near and far points for the mouse point.
osg::Vec3 nearPoint, farPoint;
sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint);
// Transform these points into local coordinates.
osg::Vec3 objectNearPoint, objectFarPoint;
objectNearPoint = nearPoint * getWorldToLocal();
objectFarPoint = farPoint * getWorldToLocal();
// Find the intersection of the plane with the line (formed by the near and far points in local coordinates).
return getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, projectedPoint);
}
SphereProjector::SphereProjector() : _sphere(new osg::Sphere), _front(true)
{
}
SphereProjector::SphereProjector(osg::Sphere& sphere) : _sphere(&sphere), _front(true)
{
}
SphereProjector::~SphereProjector()
{
}
bool SphereProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const
{
if (!_sphere->valid())
{
osg::notify(osg::WARN) << "Warning: Invalid sphere. SphereProjector::project() failed." << std::endl;
return false;
}
// Get the near and far points for the mouse point.
osg::Vec3 nearPoint, farPoint;
sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint);
// Transform these points into local coordinates.
osg::Vec3 objectNearPoint, objectFarPoint;
objectNearPoint = nearPoint * getWorldToLocal();
objectFarPoint = farPoint * getWorldToLocal();
// Find the intersection of the sphere with the line.
osg::Vec3 dontCare;
if (_front)
return getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, projectedPoint, dontCare);
return getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, dontCare, projectedPoint);
}
bool SphereProjector::isPointInFront(const osg::Vec3& point, const osgUtil::SceneView& sv, const osg::Matrix& localToWorld) const
{
osg::Vec3 centerToPoint = getSphere().getCenter() - point;
if (centerToPoint * getEyeDirection(sv.getViewMatrix(), localToWorld) < 0.0)
return false;
return true;
}
SpherePlaneProjector::SpherePlaneProjector()
{
}
SpherePlaneProjector::SpherePlaneProjector(osg::Sphere& sphere) : SphereProjector(sphere)
{
}
SpherePlaneProjector::~SpherePlaneProjector()
{
}
osg::Quat SpherePlaneProjector::getRotation(const osg::Vec3& p1, bool p1OnSphere, const osg::Vec3& p2, bool p2OnSphere,
float radialFactor) const
{
if (p1OnSphere && p2OnSphere)
{
osg::Quat rotation;
if (_front)
rotation.makeRotate(p1 - getSphere().getCenter(), p2 - getSphere().getCenter());
else
rotation.makeRotate(p2 - getSphere().getCenter(), p1 - getSphere().getCenter());
return rotation;
}
else if (!p1OnSphere && !p2OnSphere)
{
osg::Quat rotation;
rotation.makeRotate(p1 - getSphere().getCenter(), p2 - getSphere().getCenter());
osg::Vec3 axis; double angle;
rotation.getRotate(angle, axis);
osg::Vec3 realAxis;
if (axis * _plane.getNormal() > 0.0f)
realAxis = _plane.getNormal();
else
realAxis = - _plane.getNormal();
osg::Quat rollRotation(angle, realAxis);
osg::Vec3 diff1 = p1 - getSphere().getCenter();
osg::Vec3 diff2 = p2 - getSphere().getCenter();
float d = diff2.length() - diff1.length();
float theta = d / getSphere().getRadius();
if (fabs(theta) < 0.000001 || fabs(theta) > 1.0)
return rollRotation;
diff1.normalize();
osg::Vec3 pullAxis = diff1 ^ _plane.getNormal();
pullAxis.normalize();
osg::Quat pullRotation(radialFactor * theta, pullAxis);
osg::Quat totalRotation = pullRotation * rollRotation;
return totalRotation;
}
else
{
const osg::Vec3& planePoint = getSphere().getCenter();
osg::Vec3 intersection, dontCare;
if (p1OnSphere)
getSphereLineIntersection(getSphere(), p2, planePoint, intersection, dontCare);
else
getSphereLineIntersection(getSphere(), p1, planePoint, intersection, dontCare);
osg::Quat rotation;
if (p1OnSphere)
rotation.makeRotate(p1 - getSphere().getCenter(), intersection - getSphere().getCenter());
else
rotation.makeRotate(intersection - getSphere().getCenter(), p2 - getSphere().getCenter());
return rotation;
}
}
bool SpherePlaneProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const
{
if (!_sphere->valid())
{
osg::notify(osg::WARN) << "Warning: Invalid sphere. SpherePlaneProjector::project() failed." << std::endl;
return false;
}
// Get the near and far points for the mouse point.
osg::Vec3 nearPoint, farPoint;
sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint);
// Transform these points into local coordinates.
osg::Vec3 objectNearPoint, objectFarPoint;
objectNearPoint = nearPoint * getWorldToLocal();
objectFarPoint = farPoint * getWorldToLocal();
// Find the intersection of the sphere with the line.
osg::Vec3 sphereIntersection, dontCare;
bool hitSphere = false;
if (_front)
hitSphere = getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, sphereIntersection, dontCare);
else
hitSphere = getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, dontCare, sphereIntersection);
// Compute plane oriented to the eye.
_plane = computePlaneThruPointAndOrientedToEye(sv.getViewMatrix(), getLocalToWorld(), getSphere().getCenter(), _front);
// Find the intersection on the plane.
osg::Vec3 planeIntersection;
if (hitSphere)
{
if (! getPlaneLineIntersection(_plane.asVec4(), sphereIntersection, sphereIntersection + _plane.getNormal(), planeIntersection))
return false;
}
else
{
if (! getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, planeIntersection))
return false;
}
// Distance from the plane intersection point to the center of the sphere.
float dist = (planeIntersection - getSphere().getCenter()).length();
// If the distance is less that the sphere radius choose the sphere intersection else choose
// the plane intersection.
if (dist < getSphere().getRadius())
{
if (! hitSphere) return false;
projectedPoint = sphereIntersection;
_onSphere = true;
}
else
{
projectedPoint = planeIntersection;
_onSphere = false;
}
return true;
}
CylinderProjector::CylinderProjector() : _cylinder(new osg::Cylinder()), _cylinderAxis(0.0,0.0,1.0), _front(true)
{
}
CylinderProjector::CylinderProjector(osg::Cylinder& cylinder) : _front(true)
{
setCylinder(cylinder);
}
CylinderProjector::~CylinderProjector()
{
}
bool CylinderProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const
{
if (!_cylinder.valid())
{
osg::notify(osg::WARN) << "Warning: Invalid cylinder. CylinderProjector::project() failed."
<< std::endl;
return false;
}
// Get the near and far points for the mouse point.
osg::Vec3 nearPoint, farPoint;
sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint);
// Transform these points into local coordinates.
osg::Vec3 objectNearPoint, objectFarPoint;
objectNearPoint = nearPoint * getWorldToLocal();
objectFarPoint = farPoint * getWorldToLocal();
// Find the intersection of the sphere with the line.
osg::Vec3 dontCare;
return getCylinderLineIntersection(*_cylinder, objectNearPoint, objectFarPoint, projectedPoint, dontCare);
}
bool CylinderProjector::isPointInFront(const osg::Vec3& point, const osgUtil::SceneView& sv, const osg::Matrix& localToWorld) const
{
osg::Vec3 closestPointOnAxis;
computeClosestPointOnLine(getCylinder().getCenter(), getCylinder().getCenter() + _cylinderAxis,
point, closestPointOnAxis);
osg::Vec3 perpPoint = point - closestPointOnAxis;
if (perpPoint * getEyeDirection(sv.getViewMatrix(), localToWorld) < 0.0)
return false;
return true;
}
CylinderPlaneProjector::CylinderPlaneProjector()
{
}
CylinderPlaneProjector::CylinderPlaneProjector(osg::Cylinder& cylinder) : CylinderProjector(cylinder)
{
}
CylinderPlaneProjector::~CylinderPlaneProjector()
{
}
bool CylinderPlaneProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const
{
if (!_cylinder.valid())
{
osg::notify(osg::WARN) << "Warning: Invalid cylinder. CylinderProjector::project() failed."
<< std::endl;
return false;
}
// Get the near and far points for the mouse point.
osg::Vec3 nearPoint, farPoint;
sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint);
// Transform these points into local coordinates.
osg::Vec3 objectNearPoint, objectFarPoint;
objectNearPoint = nearPoint * getWorldToLocal();
objectFarPoint = farPoint * getWorldToLocal();
// Find the intersection of the sphere with the line.
osg::Vec3 cylIntersection;
bool hitCylinder = false;
if (_front)
{
osg::Vec3 dontCare;
hitCylinder = getCylinderLineIntersection(*_cylinder, objectNearPoint, objectFarPoint, cylIntersection, dontCare);
}
else
{
osg::Vec3 dontCare;
hitCylinder = getCylinderLineIntersection(*_cylinder, objectNearPoint, objectFarPoint, dontCare, cylIntersection);
}
// Compute plane oriented to the eye.
_plane = computePlaneParallelToAxisAndOrientedToEye(sv.getViewMatrix(), getLocalToWorld(), _cylinderAxis,
getCylinder().getRadius(), _planeLineStart, _planeLineEnd,
_front);
// Find the intersection on the plane.
osg::Vec3 planeIntersection;
getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, planeIntersection);
if (hitCylinder)
{
osg::Vec3 projectIntersection;
getPlaneLineIntersection(_plane.asVec4(), cylIntersection, cylIntersection + _plane.getNormal(), projectIntersection);
osg::Vec3 closestPointToCylAxis;
computeClosestPointOnLine(getCylinder().getCenter(), getCylinder().getCenter() + _cylinderAxis,
projectIntersection, closestPointToCylAxis);
// Distance from the plane intersection point to the closest point on the cylinder axis.
float dist = (projectIntersection - closestPointToCylAxis).length();
if (dist < getCylinder().getRadius())
{
if (!hitCylinder) return false;
projectedPoint = cylIntersection;
_onCylinder = true;
}
else
{
projectedPoint = planeIntersection;
_onCylinder = false;
}
}
else
{
projectedPoint = planeIntersection;
_onCylinder = false;
}
return true;
}
osg::Quat CylinderPlaneProjector::getRotation(const osg::Vec3& p1, bool p1OnCyl, const osg::Vec3& p2, bool p2OnCyl) const
{
if (p1OnCyl && p2OnCyl)
{
osg::Vec3 closestPointToCylAxis1, closestPointToCylAxis2;
computeClosestPointOnLine(getCylinder().getCenter(), getCylinder().getCenter() + _cylinderAxis * getCylinder().getHeight(),
p1, closestPointToCylAxis1);
computeClosestPointOnLine(getCylinder().getCenter(), getCylinder().getCenter() + _cylinderAxis * getCylinder().getHeight(),
p2, closestPointToCylAxis2);
osg::Vec3 v1 = p1 - closestPointToCylAxis1;
osg::Vec3 v2 = p2 - closestPointToCylAxis2;
float cosAngle = v1 * v2 / (v1.length() * v2.length());
if (cosAngle > 1.0 || cosAngle < -1.0)
return osg::Quat();
float angle = acosf(cosAngle);
osg::Vec3 rotAxis = v1 ^ v2;
return osg::Quat(angle, rotAxis);
}
else if (!p1OnCyl && !p2OnCyl)
{
osg::Vec3 closestPointToPlaneLine1, closestPointToPlaneLine2;
computeClosestPointOnLine(_planeLineStart, _planeLineEnd,
p1, closestPointToPlaneLine1);
computeClosestPointOnLine(_planeLineStart, _planeLineEnd,
p2, closestPointToPlaneLine2);
osg::Vec3 v1 = p1 - closestPointToPlaneLine1;
osg::Vec3 v2 = p2 - closestPointToPlaneLine2;
osg::Vec3 diff = v2 - v1;
float d = diff.length();
float angle = (getCylinder().getRadius() == 0.0) ? 0.0 : (d / getCylinder().getRadius());
osg::Vec3 rotAxis = _plane.getNormal() ^ v1;
if (v2.length() > v1.length())
return osg::Quat(angle, rotAxis);
else
return osg::Quat(-angle, rotAxis);
}
else
{
osg::Vec3 offCylinderPt = (p1OnCyl) ? p2 : p1;
osg::Vec3 linePtNearest;
computeClosestPointOnLine(_planeLineStart, _planeLineEnd,
offCylinderPt, linePtNearest);
osg::Vec3 dirToOffCylinderPt = offCylinderPt - linePtNearest;
dirToOffCylinderPt.normalize();
osg::Vec3 ptOnCylinder = linePtNearest + dirToOffCylinderPt * getCylinder().getRadius();
if (p1OnCyl)
return (getRotation(p1, true, ptOnCylinder, true) *
getRotation(ptOnCylinder, false, p2, false));
else
return (getRotation(p1, false, ptOnCylinder, false) *
getRotation(ptOnCylinder, true, p2, true));
}
}

View File

@@ -0,0 +1,160 @@
/* -*-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.
#include <osgManipulator/RotateCylinderDragger>
#include <osgManipulator/Command>
#include <osgManipulator/CommandManager>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/Material>
using namespace osgManipulator;
RotateCylinderDragger::RotateCylinderDragger()
{
_projector = new CylinderPlaneProjector();
setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
}
RotateCylinderDragger::~RotateCylinderDragger()
{
}
bool RotateCylinderDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
// Check if the dragger node is in the nodepath.
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
switch (ea.getEventType())
{
// Pick start.
case (osgGA::GUIEventAdapter::PUSH):
{
// Get the LocalToWorld matrix for this node and set it for the projector.
osg::NodePath nodePathToRoot;
computeNodePathToRoot(*this,nodePathToRoot);
osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot);
_projector->setLocalToWorld(localToWorld);
_startLocalToWorld = _projector->getLocalToWorld();
_startWorldToLocal = _projector->getWorldToLocal();
if (_projector->isPointInFront(hitIter->getLocalIntersectPoint(), sv, _startLocalToWorld))
_projector->setFront(true);
else
_projector->setFront(false);
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
// Generate the motion command.
osg::ref_ptr<Rotate3DCommand> cmd = new Rotate3DCommand();
cmd->setStage(MotionCommand::START);
cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Set color to pick color.
setMaterialColor(_pickColor,*this);
_prevWorldProjPt = projectedPoint * _projector->getLocalToWorld();
_prevRotation = osg::Quat();
_prevPtOnCylinder = _projector->isProjectionOnCylinder();
aa.requestRedraw();
}
return true;
}
// Pick move.
case (osgGA::GUIEventAdapter::DRAG):
{
// Get the LocalToWorld matrix for this node and set it for the projector.
osg::Matrix localToWorld = osg::Matrix(_prevRotation) * _startLocalToWorld;
_projector->setLocalToWorld(localToWorld);
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
osg::Vec3 prevProjectedPoint = _prevWorldProjPt * _projector->getWorldToLocal();
osg::Quat deltaRotation = _projector->getRotation(prevProjectedPoint, _prevPtOnCylinder,
projectedPoint, _projector->isProjectionOnCylinder());
osg::Quat rotation = deltaRotation * _prevRotation;
// Generate the motion command.
osg::ref_ptr<Rotate3DCommand> cmd = new Rotate3DCommand();
cmd->setStage(MotionCommand::MOVE);
cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal);
cmd->setRotation(rotation);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
_prevWorldProjPt = projectedPoint * _projector->getLocalToWorld();
_prevRotation = rotation;
_prevPtOnCylinder = _projector->isProjectionOnCylinder();
aa.requestRedraw();
}
return true;
}
// Pick finish.
case (osgGA::GUIEventAdapter::RELEASE):
{
osg::ref_ptr<Rotate3DCommand> cmd = new Rotate3DCommand();
cmd->setStage(MotionCommand::FINISH);
cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Reset color.
setMaterialColor(_color,*this);
aa.requestRedraw();
return true;
}
default:
return false;
}
return false;
}
void RotateCylinderDragger::setupDefaultGeometry()
{
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(const_cast<osg::Cylinder*>(&_projector->getCylinder())));
addChild(geode);
}

View File

@@ -0,0 +1,162 @@
/* -*-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.
#include <osgManipulator/RotateSphereDragger>
#include <osgManipulator/Command>
#include <osgManipulator/CommandManager>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/Material>
#include <iostream>
using namespace osgManipulator;
RotateSphereDragger::RotateSphereDragger() : _prevPtOnSphere(true)
{
_projector = new SpherePlaneProjector();
setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
}
RotateSphereDragger::~RotateSphereDragger()
{
}
bool RotateSphereDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
// Check if the dragger node is in the nodepath.
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
switch (ea.getEventType())
{
// Pick start.
case (osgGA::GUIEventAdapter::PUSH):
{
// Get the LocalToWorld matrix for this node and set it for the projector.
osg::NodePath nodePathToRoot;
computeNodePathToRoot(*this,nodePathToRoot);
osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot);
_projector->setLocalToWorld(localToWorld);
_startLocalToWorld = _projector->getLocalToWorld();
_startWorldToLocal = _projector->getWorldToLocal();
if (_projector->isPointInFront(hitIter->getLocalIntersectPoint(), sv, _startLocalToWorld))
_projector->setFront(true);
else
_projector->setFront(false);
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
// Generate the motion command.
osg::ref_ptr<Rotate3DCommand> cmd = new Rotate3DCommand();
cmd->setStage(MotionCommand::START);
cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Set color to pick color.
setMaterialColor(_pickColor,*this);
_prevRotation = osg::Quat();
_prevWorldProjPt = projectedPoint * _projector->getLocalToWorld();
_prevPtOnSphere = _projector->isProjectionOnSphere();
aa.requestRedraw();
}
return true;
}
// Pick move.
case (osgGA::GUIEventAdapter::DRAG):
{
// Get the LocalToWorld matrix for this node and set it for the projector.
osg::Matrix localToWorld = osg::Matrix(_prevRotation) * _startLocalToWorld;
_projector->setLocalToWorld(localToWorld);
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
osg::Vec3 prevProjectedPoint = _prevWorldProjPt * _projector->getWorldToLocal();
osg::Quat deltaRotation = _projector->getRotation(prevProjectedPoint, _prevPtOnSphere,
projectedPoint, _projector->isProjectionOnSphere(),1.0f);
osg::Quat rotation = deltaRotation * _prevRotation;
// Generate the motion command.
osg::ref_ptr<Rotate3DCommand> cmd = new Rotate3DCommand();
cmd->setStage(MotionCommand::MOVE);
cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal);
cmd->setRotation(rotation);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
_prevWorldProjPt = projectedPoint * _projector->getLocalToWorld();
_prevRotation = rotation;
_prevPtOnSphere = _projector->isProjectionOnSphere();
aa.requestRedraw();
}
return true;
}
// Pick finish.
case (osgGA::GUIEventAdapter::RELEASE):
{
osg::ref_ptr<Rotate3DCommand> cmd = new Rotate3DCommand();
cmd->setStage(MotionCommand::FINISH);
cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Reset color.
setMaterialColor(_color,*this);
aa.requestRedraw();
return true;
}
default:
return false;
}
return false;
}
void RotateSphereDragger::setupDefaultGeometry()
{
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(const_cast<osg::Sphere*>(&_projector->getSphere())));
addChild(geode);
}

View File

@@ -0,0 +1,216 @@
/* -*-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.
#include <osgManipulator/Scale1DDragger>
#include <osgManipulator/Command>
#include <osgManipulator/CommandManager>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Material>
using namespace osgManipulator;
namespace
{
float computeScale(const osg::Vec3& startProjectedPoint,
const osg::Vec3& projectedPoint, float scaleCenter)
{
float denom = startProjectedPoint[0] - scaleCenter;
float scale = denom ? (projectedPoint[0] - scaleCenter)/denom : 1.0;
return scale;
}
}
Scale1DDragger::Scale1DDragger(ScaleMode scaleMode) : Dragger(), _minScale(0.001), _scaleMode(scaleMode)
{
_projector = new LineProjector(osg::Vec3(-0.5f,0.0f,0.0f),osg::Vec3(0.5f,0.0f,0.0f));
setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
}
Scale1DDragger::~Scale1DDragger()
{
}
bool Scale1DDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
// Check if the dragger node is in the nodepath.
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
switch (ea.getEventType())
{
// Pick start.
case (osgGA::GUIEventAdapter::PUSH):
{
// Get the LocalToWorld matrix for this node and set it for the projector.
osg::NodePath nodePathToRoot;
computeNodePathToRoot(*this,nodePathToRoot);
osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot);
_projector->setLocalToWorld(localToWorld);
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, _startProjectedPoint))
{
_scaleCenter = 0.0f;
if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT)
{
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _leftHandleNode.get())
!= (*hitIter)._nodePath.end())
_scaleCenter = _projector->getLineEnd()[0];
else if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _rightHandleNode.get())
!= (*hitIter)._nodePath.end())
_scaleCenter = _projector->getLineStart()[0];
}
// Generate the motion command.
osg::ref_ptr<Scale1DCommand> cmd = new Scale1DCommand();
cmd->setStage(MotionCommand::START);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Set color to pick color.
setMaterialColor(_pickColor,*this);
aa.requestRedraw();
}
return true;
}
// Pick move.
case (osgGA::GUIEventAdapter::DRAG):
{
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
// Generate the motion command.
osg::ref_ptr<Scale1DCommand> cmd = new Scale1DCommand();
// Compute scale.
float scale = computeScale(_startProjectedPoint,projectedPoint,_scaleCenter);
if (scale < getMinScale()) scale = getMinScale();
// Snap the referencePoint to the line start or line end depending on which is closer.
float referencePoint = _startProjectedPoint[0];
if (fabs(_projector->getLineStart()[0] - referencePoint) <
fabs(_projector->getLineEnd()[0] - referencePoint))
referencePoint = _projector->getLineStart()[0];
else
referencePoint = _projector->getLineEnd()[0];
cmd->setStage(MotionCommand::MOVE);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
cmd->setScale(scale);
cmd->setScaleCenter(_scaleCenter);
cmd->setReferencePoint(referencePoint);
cmd->setMinScale(getMinScale());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
aa.requestRedraw();
}
return true;
}
// Pick finish.
case (osgGA::GUIEventAdapter::RELEASE):
{
osg::ref_ptr<Scale1DCommand> cmd = new Scale1DCommand();
cmd->setStage(MotionCommand::FINISH);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Reset color.
setMaterialColor(_color,*this);
aa.requestRedraw();
return true;
}
default:
return false;
}
return false;
}
void Scale1DDragger::setupDefaultGeometry()
{
// Get the line length and direction.
osg::Vec3 lineDir = _projector->getLineEnd()-_projector->getLineStart();
float lineLength = lineDir.length();
lineDir.normalize();
osg::Geode* lineGeode = new osg::Geode;
// Create a line.
{
osg::Geometry* geometry = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(2);
(*vertices)[0] = _projector->getLineStart();
(*vertices)[1] = _projector->getLineEnd();
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2));
lineGeode->addDrawable(geometry);
}
// Turn of lighting for line and set line width.
lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
osg::LineWidth* linewidth = new osg::LineWidth();
linewidth->setWidth(2.0f);
lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON);
// Add line and cones to the scene.
addChild(lineGeode);
// Create a left box.
{
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(_projector->getLineStart(), 0.05 * lineLength)));
addChild(geode);
setLeftHandleNode(*geode);
}
// Create a right box.
{
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(_projector->getLineEnd(), 0.05 * lineLength)));
addChild(geode);
setRightHandleNode(*geode);
}
}

View File

@@ -0,0 +1,258 @@
/* -*-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.
#include <osgManipulator/Scale2DDragger>
#include <osgManipulator/Command>
#include <osgManipulator/CommandManager>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Material>
using namespace osgManipulator;
namespace
{
osg::Vec2 computeScale(const osg::Vec3& startProjectedPoint,
const osg::Vec3& projectedPoint,
const osg::Vec2& scaleCenter)
{
osg::Vec2 scale(1.0,1.0);
if ((startProjectedPoint[0] - scaleCenter[0]) != 0.0)
scale[0] = (projectedPoint[0] - scaleCenter[0])/(startProjectedPoint[0] - scaleCenter[0]);
if ((startProjectedPoint[2] - scaleCenter[1]) != 0.0)
scale[1] = (projectedPoint[2] - scaleCenter[1])/(startProjectedPoint[2] - scaleCenter[1]);
return scale;
}
}
Scale2DDragger::Scale2DDragger(ScaleMode scaleMode) : Dragger(), _minScale(0.001,0.001), _scaleMode(scaleMode)
{
_projector = new PlaneProjector(osg::Plane(0.0,1.0,0.0,0.0));
setColor(osg::Vec4(0.0, 1.0, 0.0, 1.0));
setPickColor(osg::Vec4(1.0, 1.0, 0.0, 1.0));
_topLeftHandlePosition.set (-0.5,0.5);
_bottomLeftHandlePosition.set (-0.5,-0.5);
_bottomRightHandlePosition.set(0.5,-0.5);
_topRightHandlePosition.set (0.5,0.5);
}
Scale2DDragger::~Scale2DDragger()
{
}
bool Scale2DDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
// Check if the dragger node is in the nodepath.
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
switch (ea.getEventType())
{
// Pick start.
case (osgGA::GUIEventAdapter::PUSH):
{
// Get the LocalToWorld matrix for this node and set it for the projector.
osg::NodePath nodePathToRoot;
computeNodePathToRoot(*this,nodePathToRoot);
osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot);
_projector->setLocalToWorld(localToWorld);
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, _startProjectedPoint))
{
_scaleCenter.set(0.0,0.0);
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _topLeftHandleNode.get())
!= (*hitIter)._nodePath.end())
{
_referencePoint = _topLeftHandlePosition;
if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT)
_scaleCenter = _bottomRightHandlePosition;
}
else if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _bottomLeftHandleNode.get())
!= (*hitIter)._nodePath.end())
{
_referencePoint = _bottomLeftHandlePosition;
if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT)
_scaleCenter = _topRightHandlePosition;
}
else if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _bottomRightHandleNode.get())
!= (*hitIter)._nodePath.end())
{
_referencePoint = _bottomRightHandlePosition;
if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT)
_scaleCenter = _topLeftHandlePosition;
}
else if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _topRightHandleNode.get())
!= (*hitIter)._nodePath.end())
{
_referencePoint = _topRightHandlePosition;
if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT)
_scaleCenter = _bottomLeftHandlePosition;
}
// Generate the motion command.
osg::ref_ptr<Scale2DCommand> cmd = new Scale2DCommand();
cmd->setStage(MotionCommand::START);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
cmd->setReferencePoint(_referencePoint);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Set color to pick color.
setMaterialColor(_pickColor,*this);
aa.requestRedraw();
}
return true;
}
// Pick move.
case (osgGA::GUIEventAdapter::DRAG):
{
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
// Compute scale.
osg::Vec2 scale = computeScale(_startProjectedPoint,projectedPoint,_scaleCenter);
if (scale[0] < getMinScale()[0]) scale[0] = getMinScale()[0];
if (scale[1] < getMinScale()[1]) scale[1] = getMinScale()[1];
// Generate the motion command.
osg::ref_ptr<Scale2DCommand> cmd = new Scale2DCommand();
cmd->setStage(MotionCommand::MOVE);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
cmd->setScale(scale);
cmd->setScaleCenter(_scaleCenter);
cmd->setReferencePoint(_referencePoint);
cmd->setMinScale(getMinScale());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
aa.requestRedraw();
}
return true;
}
// Pick finish.
case (osgGA::GUIEventAdapter::RELEASE):
{
osg::ref_ptr<Scale2DCommand> cmd = new Scale2DCommand();
cmd->setStage(MotionCommand::FINISH);
cmd->setReferencePoint(_referencePoint);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Reset color.
setMaterialColor(_color,*this);
aa.requestRedraw();
return true;
}
default:
return false;
}
return false;
}
void Scale2DDragger::setupDefaultGeometry()
{
osg::Geode* lineGeode = new osg::Geode;
// Create a line.
{
osg::Geometry* geometry = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(4);
(*vertices)[0].set(_topLeftHandlePosition[0],0.0,_topLeftHandlePosition[1]);
(*vertices)[1].set(_bottomLeftHandlePosition[0],0.0,_bottomLeftHandlePosition[1]);
(*vertices)[2].set(_bottomRightHandlePosition[0],0.0,_bottomRightHandlePosition[1]);
(*vertices)[3].set(_topRightHandlePosition[0],0.0,_topRightHandlePosition[1]);
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,vertices->size()));
lineGeode->addDrawable(geometry);
}
// Turn of lighting for line and set line width.
lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
osg::LineWidth* linewidth = new osg::LineWidth();
linewidth->setWidth(2.0);
lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON);
// Add line and cones to the scene.
addChild(lineGeode);
// Create a top left box.
{
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_topLeftHandlePosition[0],
0.0,_topLeftHandlePosition[1]), 0.05)));
addChild(geode);
setTopLeftHandleNode(*geode);
}
// Create a bottom left box.
{
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_bottomLeftHandlePosition[0],
0.0,_bottomLeftHandlePosition[1]), 0.05)));
addChild(geode);
setBottomLeftHandleNode(*geode);
}
// Create a bottom right box.
{
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_bottomRightHandlePosition[0],
0.0,_bottomRightHandlePosition[1]), 0.05)));
addChild(geode);
setBottomRightHandleNode(*geode);
}
// Create a top right box.
{
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_topRightHandlePosition[0],
0.0,_topRightHandlePosition[1]), 0.05)));
addChild(geode);
setTopRightHandleNode(*geode);
}
}

View File

@@ -0,0 +1,101 @@
/* -*-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.
#include <osgManipulator/ScaleAxisDragger>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Quat>
using namespace osgManipulator;
ScaleAxisDragger::ScaleAxisDragger()
{
_xDragger = new osgManipulator::Scale1DDragger();
addChild(_xDragger.get());
addDragger(_xDragger.get());
_yDragger = new osgManipulator::Scale1DDragger();
addChild(_yDragger.get());
addDragger(_yDragger.get());
_zDragger = new osgManipulator::Scale1DDragger();
addChild(_zDragger.get());
addDragger(_zDragger.get());
setParentDragger(getParentDragger());
}
ScaleAxisDragger::~ScaleAxisDragger()
{
}
void ScaleAxisDragger::setupDefaultGeometry()
{
// Create a line.
osg::Geode* lineGeode = new osg::Geode;
{
osg::Geometry* geometry = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(2);
(*vertices)[0] = osg::Vec3(0.0f,0.0f,0.0f);
(*vertices)[1] = osg::Vec3(1.0f,0.0f,0.0f);
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2));
lineGeode->addDrawable(geometry);
}
// Turn of lighting for line and set line width.
{
osg::LineWidth* linewidth = new osg::LineWidth();
linewidth->setWidth(2.0f);
lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON);
lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
}
// Add line to all the individual 1D draggers.
_xDragger->addChild(lineGeode);
_yDragger->addChild(lineGeode);
_zDragger->addChild(lineGeode);
osg::Geode* geode = new osg::Geode;
// Create a box.
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(1.0f,0.0f,0.0f), 0.05)));
// Add geode to all 1D draggers.
_xDragger->addChild(geode);
_yDragger->addChild(geode);
_zDragger->addChild(geode);
// Rotate Z-axis dragger appropriately.
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f));
_zDragger->setMatrix(osg::Matrix(rotation));
}
// Rotate Y-axis dragger appropriately.
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f));
_yDragger->setMatrix(osg::Matrix(rotation));
}
// Send different colors for each dragger.
_xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
_yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f));
_zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f));
}

View File

@@ -0,0 +1,95 @@
/* -*-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.
#include <osgManipulator/Selection>
#include <osgManipulator/Command>
#include <algorithm>
using namespace osgManipulator;
class FindNodePathToRootVisitor : public osg::NodeVisitor
{
public:
osg::NodePath& _nodePathToRoot;
FindNodePathToRootVisitor(osg::NodePath& np)
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS),
_nodePathToRoot(np)
{}
virtual void apply(osg::Node& node)
{
_nodePathToRoot.push_back(&node);
traverse(node);
}
};
void osgManipulator::computeNodePathToRoot(osg::Node& node, osg::NodePath& np)
{
np.clear();
osg::ref_ptr<FindNodePathToRootVisitor> visitor = new FindNodePathToRootVisitor(np);
node.accept(*visitor);
np.pop_back();
std::reverse(np.begin(), np.end());
}
Selection::Selection()
{
}
Selection::~Selection()
{
}
bool Selection::receive(const MotionCommand& command)
{
switch (command.getStage())
{
case MotionCommand::START:
{
// Save the current matrix
_startMotionMatrix = getMatrix();
// Get the LocalToWorld and WorldToLocal matrix for this node.
osg::NodePath nodePathToRoot;
computeNodePathToRoot(*this,nodePathToRoot);
_localToWorld = osg::computeLocalToWorld(nodePathToRoot);
_worldToLocal = osg::Matrix::inverse(_localToWorld);
return true;
}
case MotionCommand::MOVE:
{
// Transform the command's motion matrix into local motion matrix.
osg::Matrix localMotionMatrix = _localToWorld * command.getWorldToLocal()
* command.getMotionMatrix()
* command.getLocalToWorld() * _worldToLocal;
// Transform by the localMotionMatrix
setMatrix(localMotionMatrix * _startMotionMatrix);
return true;
}
case MotionCommand::FINISH:
{
return true;
}
case MotionCommand::NONE:
default:
return false;
}
}

View File

@@ -0,0 +1,77 @@
/* -*-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.
#include <osgManipulator/TabBoxDragger>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Quat>
using namespace osgManipulator;
TabBoxDragger::TabBoxDragger()
{
for (int i=0; i<6; ++i)
{
_planeDraggers.push_back(new TabPlaneDragger());
addChild(_planeDraggers[i].get());
addDragger(_planeDraggers[i].get());
}
{
_planeDraggers[0]->setMatrix(osg::Matrix::translate(osg::Vec3(0.0,0.5,0.0)));
}
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, -1.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f));
_planeDraggers[1]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,-0.5,0.0)));
}
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f));
_planeDraggers[2]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,0.0,-0.5)));
}
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f));
_planeDraggers[3]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,0.0,0.5)));
}
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f));
_planeDraggers[4]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(-0.5,0.0,0.0)));
}
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), osg::Vec3(1.0f, 0.0f, 0.0f));
_planeDraggers[5]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.5,0.0,0.0)));
}
setParentDragger(getParentDragger());
}
TabBoxDragger::~TabBoxDragger()
{
}
void TabBoxDragger::setupDefaultGeometry()
{
for (unsigned int i=0; i<_planeDraggers.size(); ++i)
_planeDraggers[i]->setupDefaultGeometry(false);
}
void TabBoxDragger::setPlaneColor(const osg::Vec4& color)
{
for (unsigned int i=0; i<_planeDraggers.size(); ++i)
_planeDraggers[i]->setPlaneColor(color);
}

View File

@@ -0,0 +1,267 @@
/* -*-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.
#include <osgManipulator/TabPlaneDragger>
#include <osgManipulator/AntiSquish>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Quat>
#include <osg/PolygonMode>
#include <osg/CullFace>
#include <osg/AutoTransform>
using namespace osgManipulator;
namespace
{
osg::Node* createHandleNode(Scale2DDragger* cornerScaleDragger, float handleScaleFactor, bool twosided)
{
osg::Vec3Array* vertices = new osg::Vec3Array(4);
(*vertices)[0] = osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0],0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]) * handleScaleFactor;
(*vertices)[1] = osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0],0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]) * handleScaleFactor;
(*vertices)[2] = osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0],0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]) * handleScaleFactor;
(*vertices)[3] = osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0],0.0,cornerScaleDragger->getTopRightHandlePosition()[1]) * handleScaleFactor;
osg::Geometry* geometry = new osg::Geometry();
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size()));
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0,1.0,0.0));
geometry->setNormalArray(normals);
geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
osg::Geode* geode = new osg::Geode;
geode->setName("Dragger Handle");
geode->addDrawable(geometry);
if (!twosided)
{
osg::CullFace* cullface = new osg::CullFace;
cullface->setMode(osg::CullFace::FRONT);
geode->getOrCreateStateSet()->setAttribute(cullface, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
geode->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
}
geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
return geode;
}
osg::Node* createHandleScene(const osg::Vec3& pos, osg::Node* handleNode, float handleScaleFactor)
{
osg::AutoTransform *at = new osg::AutoTransform;
at->setPosition(pos);
at->setPivotPoint(pos * handleScaleFactor);
at->setAutoScaleToScreen(true);
at->addChild(handleNode);
AntiSquish* as = new AntiSquish;
as->setPivot(pos);
as->addChild(at);
return as;
}
void createCornerScaleDraggerGeometry(Scale2DDragger* cornerScaleDragger, osg::Node* handleNode, float handleScaleFactor)
{
// Create a top left box.
{
osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0],
0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]),
handleNode, handleScaleFactor);
cornerScaleDragger->addChild(handleScene);
cornerScaleDragger->setTopLeftHandleNode(*handleScene);
}
// Create a bottom left box.
{
osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0],
0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]),
handleNode, handleScaleFactor);
cornerScaleDragger->addChild(handleScene);
cornerScaleDragger->setBottomLeftHandleNode(*handleScene);
}
// Create a bottom right box.
{
osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0],
0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]),
handleNode, handleScaleFactor);
cornerScaleDragger->addChild(handleScene);
cornerScaleDragger->setBottomRightHandleNode(*handleScene);
}
// Create a top right box.
{
osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0],
0.0,cornerScaleDragger->getTopRightHandlePosition()[1]),
handleNode, handleScaleFactor);
cornerScaleDragger->addChild(handleScene);
cornerScaleDragger->setTopRightHandleNode(*handleScene);
}
}
void createEdgeScaleDraggerGeometry(Scale1DDragger* horzEdgeScaleDragger, Scale1DDragger* vertEdgeScaleDragger,
osg::Node* handleNode, float handleScaleFactor)
{
// Create a left box.
{
osg::Node* handleScene = createHandleScene(osg::Vec3(horzEdgeScaleDragger->getLeftHandlePosition(),0.0,0.0),
handleNode, handleScaleFactor);
horzEdgeScaleDragger->addChild(handleScene);
horzEdgeScaleDragger->setLeftHandleNode(*handleScene);
}
// Create a right box.
{
osg::Node* handleScene = createHandleScene(osg::Vec3(horzEdgeScaleDragger->getRightHandlePosition(),0.0,0.0),
handleNode, handleScaleFactor);
horzEdgeScaleDragger->addChild(handleScene);
horzEdgeScaleDragger->setRightHandleNode(*handleScene);
}
// Create a top box.
{
osg::Node* handleScene = createHandleScene(osg::Vec3(vertEdgeScaleDragger->getLeftHandlePosition(),0.0,0.0),
handleNode, handleScaleFactor);
vertEdgeScaleDragger->addChild(handleScene);
vertEdgeScaleDragger->setLeftHandleNode(*handleScene);
}
// Create a bottom box.
{
osg::Node* handleScene = createHandleScene(osg::Vec3(vertEdgeScaleDragger->getRightHandlePosition(),0.0,0.0),
handleNode, handleScaleFactor);
vertEdgeScaleDragger->addChild(handleScene);
vertEdgeScaleDragger->setRightHandleNode(*handleScene);
}
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f));
vertEdgeScaleDragger->setMatrix(osg::Matrix(rotation));
}
void createTranslateDraggerGeometry(Scale2DDragger* cornerScaleDragger, TranslatePlaneDragger* translateDragger)
{
// Create a polygon.
{
osg::Geode* geode = new osg::Geode;
osg::Geometry* geometry = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(4);
(*vertices)[0] = osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0],0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]);
(*vertices)[1] = osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0],0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]);
(*vertices)[2] = osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0],0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]);
(*vertices)[3] = osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0],0.0,cornerScaleDragger->getTopRightHandlePosition()[1]);
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size()));
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0,1.0,0.0));
geometry->setNormalArray(normals);
geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
geode->addDrawable(geometry);
osg::PolygonMode* polymode = new osg::PolygonMode;
polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
translateDragger->getTranslate2DDragger()->addChild(geode);
}
}
}
TabPlaneDragger::TabPlaneDragger() : _handleScaleFactor(20.0)
{
_cornerScaleDragger = new Scale2DDragger(Scale2DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT);
addChild(_cornerScaleDragger.get());
addDragger(_cornerScaleDragger.get());
_horzEdgeScaleDragger = new Scale1DDragger(Scale1DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT);
addChild(_horzEdgeScaleDragger.get());
addDragger(_horzEdgeScaleDragger.get());
_vertEdgeScaleDragger = new Scale1DDragger(Scale1DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT);
addChild(_vertEdgeScaleDragger.get());
addDragger(_vertEdgeScaleDragger.get());
_translateDragger = new TranslatePlaneDragger();
_translateDragger->setColor(osg::Vec4(0.7f, 0.7f, 0.7f, 1.0f));
addChild(_translateDragger.get());
addDragger(_translateDragger.get());
setParentDragger(getParentDragger());
}
TabPlaneDragger::~TabPlaneDragger()
{
}
bool TabPlaneDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList& hl, const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
if (ea.getButtonMask() & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) return false;
// Check if the dragger node is in the nodepath.
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
// Since the translate plane and the handleNode lie on the same plane the hit could've been on either one. But we
// need to handle the scaling draggers before the translation. Check if the node path has the scaling nodes else
// check for the scaling nodes in next hit.
if (_cornerScaleDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa))
return true;
if (_horzEdgeScaleDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa))
return true;
if (_vertEdgeScaleDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa))
return true;
osgUtil::IntersectVisitor::HitList::iterator nextHit = hitIter + 1;
while (nextHit != hl.end())
{
if (_cornerScaleDragger->handle(pixel_x, pixel_y, sv, hl, nextHit, ea, aa))
return true;
if (_horzEdgeScaleDragger->handle(pixel_x, pixel_y, sv, hl, nextHit, ea, aa))
return true;
if (_vertEdgeScaleDragger->handle(pixel_x, pixel_y, sv, hl, nextHit, ea, aa))
return true;
++nextHit;
}
if (_translateDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa))
return true;
return false;
}
void TabPlaneDragger::setupDefaultGeometry(bool twoSidedHandle)
{
osg::ref_ptr<osg::Node> handleNode = createHandleNode(_cornerScaleDragger.get(), _handleScaleFactor, twoSidedHandle);
createCornerScaleDraggerGeometry(_cornerScaleDragger.get(), handleNode.get(), _handleScaleFactor);
createEdgeScaleDraggerGeometry(_horzEdgeScaleDragger.get(),_vertEdgeScaleDragger.get(),handleNode.get(),_handleScaleFactor);
createTranslateDraggerGeometry(_cornerScaleDragger.get(), _translateDragger.get());
}

View File

@@ -0,0 +1,48 @@
/* -*-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.
#include <osgManipulator/TabPlaneTrackballDragger>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/PolygonMode>
#include <osg/CullFace>
#include <osg/Quat>
#include <osg/AutoTransform>
using namespace osgManipulator;
TabPlaneTrackballDragger::TabPlaneTrackballDragger()
{
_trackballDragger = new TrackballDragger(true);
addChild(_trackballDragger.get());
addDragger(_trackballDragger.get());
_tabPlaneDragger = new TabPlaneDragger();
addChild(_tabPlaneDragger.get());
addDragger(_tabPlaneDragger.get());
setParentDragger(getParentDragger());
}
TabPlaneTrackballDragger::~TabPlaneTrackballDragger()
{
}
void TabPlaneTrackballDragger::setupDefaultGeometry()
{
_trackballDragger->setupDefaultGeometry();
_tabPlaneDragger->setupDefaultGeometry();
}

View File

@@ -0,0 +1,171 @@
/* -*-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.
#include <osgManipulator/TrackballDragger>
#include <osgManipulator/AntiSquish>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/PolygonMode>
#include <osg/CullFace>
#include <osg/Quat>
#include <osg/AutoTransform>
using namespace osgManipulator;
namespace
{
osg::Geometry* createCircleGeometry(float radius, unsigned int numSegments)
{
const float angleDelta = 2.0f*osg::PI/(float)numSegments;
const float r = radius;
float angle = 0.0f;
osg::Vec3Array* vertexArray = new osg::Vec3Array(numSegments);
osg::Vec3Array* normalArray = new osg::Vec3Array(numSegments);
for(unsigned int i = 0; i < numSegments; ++i,angle+=angleDelta)
{
float c = cosf(angle);
float s = sinf(angle);
(*vertexArray)[i].set(c*r,s*r,0.0f);
(*normalArray)[i].set(c,s,0.0f);
}
osg::Geometry* geometry = new osg::Geometry();
geometry->setVertexArray(vertexArray);
geometry->setNormalArray(normalArray);
geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,vertexArray->size()));
return geometry;
}
}
TrackballDragger::TrackballDragger(bool useAutoTransform)
{
if (useAutoTransform)
{
float pixelSize = 50.0f;
osg::MatrixTransform* scaler = new osg::MatrixTransform;
scaler->setMatrix(osg::Matrix::scale(pixelSize, pixelSize, pixelSize));
osg::AutoTransform *at = new osg::AutoTransform;
at->setAutoScaleToScreen(true);
at->addChild(scaler);
AntiSquish* as = new AntiSquish;
as->addChild(at);
addChild(as);
_xDragger = new RotateCylinderDragger();
scaler->addChild(_xDragger.get());
addDragger(_xDragger.get());
_yDragger = new RotateCylinderDragger();
scaler->addChild(_yDragger.get());
addDragger(_yDragger.get());
_zDragger = new RotateCylinderDragger();
scaler->addChild(_zDragger.get());
addDragger(_zDragger.get());
_xyzDragger = new RotateSphereDragger();
scaler->addChild(_xyzDragger.get());
addDragger(_xyzDragger.get());
}
else
{
_xDragger = new RotateCylinderDragger();
addChild(_xDragger.get());
addDragger(_xDragger.get());
_yDragger = new RotateCylinderDragger();
addChild(_yDragger.get());
addDragger(_yDragger.get());
_zDragger = new RotateCylinderDragger();
addChild(_zDragger.get());
addDragger(_zDragger.get());
_xyzDragger = new RotateSphereDragger();
addChild(_xyzDragger.get());
addDragger(_xyzDragger.get());
}
setParentDragger(getParentDragger());
}
TrackballDragger::~TrackballDragger()
{
}
void TrackballDragger::setupDefaultGeometry()
{
osg::Geode* geode = new osg::Geode;
{
osg::TessellationHints* hints = new osg::TessellationHints;
hints->setCreateTop(false);
hints->setCreateBottom(false);
hints->setCreateBackFace(false);
osg::Cylinder* cylinder = new osg::Cylinder;
cylinder->setHeight(0.15f);
osg::ShapeDrawable* cylinderDrawable = new osg::ShapeDrawable(cylinder,hints);
geode->addDrawable(cylinderDrawable);
setDrawableToAlwaysCull(*cylinderDrawable);
geode->addDrawable(createCircleGeometry(1.0f, 25));
}
// Draw in line mode.
{
osg::PolygonMode* polymode = new osg::PolygonMode;
polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
geode->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
geode->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(2.0f),osg::StateAttribute::ON);
}
// Add line to all the individual 1D draggers.
_xDragger->addChild(geode);
_yDragger->addChild(geode);
_zDragger->addChild(geode);
// Rotate X-axis dragger appropriately.
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f));
_xDragger->setMatrix(osg::Matrix(rotation));
}
// Rotate Y-axis dragger appropriately.
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f));
_yDragger->setMatrix(osg::Matrix(rotation));
}
// Send different colors for each dragger.
_xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
_yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f));
_zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f));
// Add invisible sphere for pick the spherical dragger.
{
osg::Drawable* sphereDrawable = new osg::ShapeDrawable(new osg::Sphere());
setDrawableToAlwaysCull(*sphereDrawable);
osg::Geode* sphereGeode = new osg::Geode;
sphereGeode->addDrawable(sphereDrawable);
_xyzDragger->addChild(sphereGeode);
}
}

View File

@@ -0,0 +1,212 @@
/* -*-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.
#include <osgManipulator/Translate1DDragger>
#include <osgManipulator/Command>
#include <osgManipulator/CommandManager>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Material>
using namespace osgManipulator;
Translate1DDragger::Translate1DDragger() : Dragger(), _checkForNodeInNodePath(true)
{
_projector = new LineProjector;
setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
}
Translate1DDragger::Translate1DDragger(const osg::Vec3& s, const osg::Vec3& e) : Dragger(), _checkForNodeInNodePath(true)
{
_projector = new LineProjector(s,e);
setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
}
Translate1DDragger::~Translate1DDragger()
{
}
bool Translate1DDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
// Check if the dragger node is in the nodepath.
if (_checkForNodeInNodePath)
{
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
}
switch (ea.getEventType())
{
// Pick start.
case (osgGA::GUIEventAdapter::PUSH):
{
// Get the LocalToWorld matrix for this node and set it for the projector.
osg::NodePath nodePathToRoot;
computeNodePathToRoot(*this,nodePathToRoot);
osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot);
_projector->setLocalToWorld(localToWorld);
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, _startProjectedPoint))
{
// Generate the motion command.
osg::ref_ptr<TranslateInLineCommand> cmd = new TranslateInLineCommand(_projector->getLineStart(),
_projector->getLineEnd());
cmd->setStage(MotionCommand::START);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Set color to pick color.
setMaterialColor(_pickColor,*this);
aa.requestRedraw();
}
return true;
}
// Pick move.
case (osgGA::GUIEventAdapter::DRAG):
{
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
// Generate the motion command.
osg::ref_ptr<TranslateInLineCommand> cmd = new TranslateInLineCommand(_projector->getLineStart(),
_projector->getLineEnd());
cmd->setStage(MotionCommand::MOVE);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
cmd->setTranslation(projectedPoint - _startProjectedPoint);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
aa.requestRedraw();
}
return true;
}
// Pick finish.
case (osgGA::GUIEventAdapter::RELEASE):
{
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
osg::ref_ptr<TranslateInLineCommand> cmd = new TranslateInLineCommand(_projector->getLineStart(),
_projector->getLineEnd());
cmd->setStage(MotionCommand::FINISH);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Reset color.
setMaterialColor(_color,*this);
aa.requestRedraw();
}
return true;
}
default:
return false;
}
return false;
}
void Translate1DDragger::setupDefaultGeometry()
{
// Get the line length and direction.
osg::Vec3 lineDir = _projector->getLineEnd()-_projector->getLineStart();
float lineLength = lineDir.length();
lineDir.normalize();
osg::Geode* geode = new osg::Geode;
// Create a left cone.
{
osg::Cone* cone = new osg::Cone (_projector->getLineStart(), 0.025f * lineLength, 0.10f * lineLength);
osg::Quat rotation;
rotation.makeRotate(lineDir, osg::Vec3(0.0f, 0.0f, 1.0f));
cone->setRotation(rotation);
geode->addDrawable(new osg::ShapeDrawable(cone));
}
// Create a right cone.
{
osg::Cone* cone = new osg::Cone (_projector->getLineEnd(), 0.025f * lineLength, 0.10f * lineLength);
osg::Quat rotation;
rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), lineDir);
cone->setRotation(rotation);
geode->addDrawable(new osg::ShapeDrawable(cone));
}
// Create an invisible cylinder for picking the line.
{
osg::Cylinder* cylinder = new osg::Cylinder ((_projector->getLineStart()+_projector->getLineEnd())/2, 0.015f * lineLength, lineLength);
osg::Quat rotation;
rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), lineDir);
cylinder->setRotation(rotation);
osg::Drawable* cylinderGeom = new osg::ShapeDrawable(cylinder);
setDrawableToAlwaysCull(*cylinderGeom);
geode->addDrawable(cylinderGeom);
}
osg::Geode* lineGeode = new osg::Geode;
// Create a line.
{
osg::Geometry* geometry = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(2);
(*vertices)[0] = _projector->getLineStart();
(*vertices)[1] = _projector->getLineEnd();
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2));
lineGeode->addDrawable(geometry);
}
// Turn of lighting for line and set line width.
lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
osg::LineWidth* linewidth = new osg::LineWidth();
linewidth->setWidth(2.0f);
lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON);
// Add line and cones to the scene.
addChild(lineGeode);
addChild(geode);
}

View File

@@ -0,0 +1,227 @@
/* -*-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.
#include <osgManipulator/Translate2DDragger>
#include <osgManipulator/Command>
#include <osgManipulator/CommandManager>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Material>
using namespace osgManipulator;
Translate2DDragger::Translate2DDragger()
{
_projector = new PlaneProjector(osg::Plane(0.0,1.0,0.0,0.0));
_polygonOffset = new osg::PolygonOffset(-1.0f,-1.0f);
setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
}
Translate2DDragger::Translate2DDragger(const osg::Plane& plane)
{
_projector = new PlaneProjector(plane);
_polygonOffset = new osg::PolygonOffset(-1.0f,-1.0f);
setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
}
Translate2DDragger::~Translate2DDragger()
{
}
bool Translate2DDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList&,
const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
// Check if the dragger node is in the nodepath.
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
switch (ea.getEventType())
{
// Pick start.
case (osgGA::GUIEventAdapter::PUSH):
{
// Get the LocalToWorld matrix for this node and set it for the projector.
osg::NodePath nodePathToRoot;
computeNodePathToRoot(*this,nodePathToRoot);
osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot);
_projector->setLocalToWorld(localToWorld);
if (_projector->project(osg::Vec2((float)pixel_x, (float)pixel_y), sv, _startProjectedPoint))
{
// Generate the motion command.
osg::ref_ptr<TranslateInPlaneCommand> cmd = new TranslateInPlaneCommand(_projector->getPlane());
cmd->setStage(MotionCommand::START);
cmd->setReferencePoint(_startProjectedPoint);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Set color to pick color.
setMaterialColor(_pickColor,*this);
getOrCreateStateSet()->setAttributeAndModes(_polygonOffset.get(), osg::StateAttribute::ON);
aa.requestRedraw();
}
return true;
}
// Pick move.
case (osgGA::GUIEventAdapter::DRAG):
{
osg::Vec3 projectedPoint;
if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint))
{
// Generate the motion command.
osg::ref_ptr<TranslateInPlaneCommand> cmd = new TranslateInPlaneCommand(_projector->getPlane());
cmd->setStage(MotionCommand::MOVE);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
cmd->setTranslation(projectedPoint - _startProjectedPoint);
cmd->setReferencePoint(_startProjectedPoint);
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
aa.requestRedraw();
}
return true;
}
// Pick finish.
case (osgGA::GUIEventAdapter::RELEASE):
{
osg::ref_ptr<TranslateInPlaneCommand> cmd = new TranslateInPlaneCommand(_projector->getPlane());
cmd->setStage(MotionCommand::FINISH);
cmd->setReferencePoint(_startProjectedPoint);
cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal());
// Dispatch command.
if (_commandManager)
{
_commandManager->addSelectionsToCommand(*cmd, *getParentDragger());
_commandManager->dispatch(*cmd);
}
// Reset color.
setMaterialColor(_color,*this);
getOrCreateStateSet()->removeAttribute(_polygonOffset.get());
aa.requestRedraw();
return true;
}
default:
return false;
}
return false;
}
void Translate2DDragger::setupDefaultGeometry()
{
// Create a line.
osg::Geode* lineGeode = new osg::Geode;
{
osg::Geometry* geometry = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(2);
(*vertices)[0] = osg::Vec3(0.0f,0.0f,-0.5f);
(*vertices)[1] = osg::Vec3(0.0f,0.0f,0.5f);
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2));
lineGeode->addDrawable(geometry);
}
// Turn of lighting for line and set line width.
osg::LineWidth* linewidth = new osg::LineWidth();
linewidth->setWidth(2.0f);
lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON);
lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
osg::Geode* geode = new osg::Geode;
// Create left cone.
{
osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, -0.5f), 0.025f, 0.10f);
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f,0.0f,-1.0f), osg::Vec3(0.0f, 0.0f, 1.0f));
cone->setRotation(rotation);
geode->addDrawable(new osg::ShapeDrawable(cone));
}
// Create right cone.
{
osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, 0.5f), 0.025f, 0.10f);
geode->addDrawable(new osg::ShapeDrawable(cone));
}
// Create an invisible cylinder for picking the line.
{
osg::Cylinder* cylinder = new osg::Cylinder (osg::Vec3(0.0f,0.0f,0.0f), 0.015f, 1.0f);
osg::Drawable* drawable = new osg::ShapeDrawable(cylinder);
setDrawableToAlwaysCull(*drawable);
geode->addDrawable(drawable);
}
// MatrixTransform to rotate the geometry according to the normal of the plane.
osg::MatrixTransform* xform = new osg::MatrixTransform;
// Create an arrow in the X axis.
{
osg::MatrixTransform* arrow = new osg::MatrixTransform;
arrow->addChild(lineGeode);
arrow->addChild(geode);
// Rotate X-axis arrow appropriately.
osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f));
arrow->setMatrix(osg::Matrix(rotation));
xform->addChild(arrow);
}
// Create an arrow in the Z axis.
{
osg::Group* arrow = new osg::Group;
arrow->addChild(lineGeode);
arrow->addChild(geode);
xform->addChild(arrow);
}
// Rotate the xform so that the geometry lies on the plane.
{
osg::Vec3 normal = _projector->getPlane().getNormal(); normal.normalize();
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), normal);
xform->setMatrix(osg::Matrix(rotation));
}
addChild(xform);
}

View File

@@ -0,0 +1,112 @@
/* -*-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.
#include <osgManipulator/TranslateAxisDragger>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Quat>
using namespace osgManipulator;
TranslateAxisDragger::TranslateAxisDragger()
{
_xDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0));
addChild(_xDragger.get());
addDragger(_xDragger.get());
_yDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0));
addChild(_yDragger.get());
addDragger(_yDragger.get());
_zDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0));
addChild(_zDragger.get());
addDragger(_zDragger.get());
setParentDragger(getParentDragger());
}
TranslateAxisDragger::~TranslateAxisDragger()
{
}
void TranslateAxisDragger::setupDefaultGeometry()
{
// Create a line.
osg::Geode* lineGeode = new osg::Geode;
{
osg::Geometry* geometry = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(2);
(*vertices)[0] = osg::Vec3(0.0f,0.0f,0.0f);
(*vertices)[1] = osg::Vec3(0.0f,0.0f,1.0f);
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2));
lineGeode->addDrawable(geometry);
}
// Turn of lighting for line and set line width.
{
osg::LineWidth* linewidth = new osg::LineWidth();
linewidth->setWidth(2.0f);
lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON);
lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
}
// Add line to all the individual 1D draggers.
_xDragger->addChild(lineGeode);
_yDragger->addChild(lineGeode);
_zDragger->addChild(lineGeode);
osg::Geode* geode = new osg::Geode;
// Create a cone.
{
osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, 1.0f), 0.025f, 0.10f);
geode->addDrawable(new osg::ShapeDrawable(cone));
}
// Create an invisible cylinder for picking the line.
{
osg::Cylinder* cylinder = new osg::Cylinder (osg::Vec3(0.0f,0.0f,0.5f), 0.015f, 1.0f);
osg::Drawable* geometry = new osg::ShapeDrawable(cylinder);
setDrawableToAlwaysCull(*geometry);
geode->addDrawable(geometry);
}
// Add geode to all 1D draggers.
_xDragger->addChild(geode);
_yDragger->addChild(geode);
_zDragger->addChild(geode);
// Rotate X-axis dragger appropriately.
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f));
_xDragger->setMatrix(osg::Matrix(rotation));
}
// Rotate Y-axis dragger appropriately.
{
osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f));
_yDragger->setMatrix(osg::Matrix(rotation));
}
// Send different colors for each dragger.
_xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
_yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f));
_zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f));
}

View File

@@ -0,0 +1,108 @@
/* -*-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.
#include <osgManipulator/TranslatePlaneDragger>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/LineWidth>
#include <osg/Quat>
#include <osg/PolygonMode>
#include <osg/CullFace>
#include <osg/AutoTransform>
using namespace osgManipulator;
TranslatePlaneDragger::TranslatePlaneDragger() : _usingTranslate1DDragger(false)
{
_translate2DDragger = new Translate2DDragger();
_translate2DDragger->setColor(osg::Vec4(0.7f, 0.7f, 0.7f, 1.0f));
addChild(_translate2DDragger.get());
addDragger(_translate2DDragger.get());
_translate1DDragger = new Translate1DDragger(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(0.0f,1.0f,0.0f));
_translate1DDragger->setCheckForNodeInNodePath(false);
addChild(_translate1DDragger.get());
addDragger(_translate1DDragger.get());
setParentDragger(getParentDragger());
}
TranslatePlaneDragger::~TranslatePlaneDragger()
{
}
bool TranslatePlaneDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv,
const osgUtil::IntersectVisitor::HitList& hl,
const osgUtil::IntersectVisitor::HitList::iterator& hitIter,
const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
// Check if the dragger node is in the nodepath.
if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end())
return false;
if ((ea.getButtonMask() & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) &&
ea.getEventType() == osgGA::GUIEventAdapter::PUSH)
_usingTranslate1DDragger = true;
bool handled = false;
if (_usingTranslate1DDragger)
{
if (_translate1DDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa))
handled = true;
}
else
{
if (_translate2DDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa))
handled = true;
}
if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE)
_usingTranslate1DDragger = false;
return handled;
}
void TranslatePlaneDragger::setupDefaultGeometry()
{
// Create a polygon.
{
osg::Geode* geode = new osg::Geode;
osg::Geometry* geometry = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(4);
(*vertices)[0] = osg::Vec3(-0.5,0.0,0.5);
(*vertices)[1] = osg::Vec3(-0.5,0.0,-0.5);
(*vertices)[2] = osg::Vec3(0.5,0.0,-0.5);
(*vertices)[3] = osg::Vec3(0.5,0.0,0.5);
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size()));
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0,1.0,0.0));
geometry->setNormalArray(normals);
geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
geode->addDrawable(geometry);
osg::PolygonMode* polymode = new osg::PolygonMode;
polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
_translate2DDragger->addChild(geode);
}
}