3 #include "OsgCameraManipulator.h"
4 #include "OsgMovableItem.h"
6 #include "OsgRigidBody.h"
8 #include "OsgMouseSpring.h"
11 #include "OsgUserData.h"
12 #include "OsgDragger.h"
13 #include "OsgSimulator.h"
17 namespace Visualization
20 OsgCameraManipulator::OsgCameraManipulator(Simulator *lpSim, osgViewer::Viewer *osgViewer, osg::Viewport *osgViewport)
24 m_osgViewer = osgViewer;
25 m_osgViewport = osgViewport;
29 m_bControlDown =
false;
38 this->setMinimumDistance(0.00001);
41 OsgCameraManipulator::~OsgCameraManipulator(
void)
43 m_lpOsgSim->MouseSpring()->SetRigidBody(NULL);
49 bool bHandled =
false;
57 switch(ea.getEventType())
59 case(GUIEventAdapter::PUSH):
65 case(GUIEventAdapter::RELEASE):
67 m_lpOsgSim->MouseSpring()->Visible(
false);
71 if(m_lpPicked && m_lpSim && m_lpSim->VisualSelectionMode() != SIMULATION_SELECTION_MODE)
74 m_lpPicked->SelectedVertex(m_vSelectedVertex.x(), m_vSelectedVertex.y(), m_vSelectedVertex.z(),
true,
true);
76 if(m_lpSim->AddBodiesMode())
77 m_lpPicked->AddBodyClicked(m_vPickPoint.x(), m_vPickPoint.y(), m_vPickPoint.z(),
78 m_vPickNormal.x(), m_vPickNormal.y(), m_vPickNormal.z());
80 m_lpPicked->Selected(
true, m_bControlDown);
88 case(GUIEventAdapter::DRAG):
94 if(m_bShiftDown && m_bControlDown && CanDoMouseSpring())
95 bHandled = DoMouseSpring(ea, x, y);
115 case(GUIEventAdapter::KEYDOWN):
119 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L)
125 if(ea.getKey() == osgGA::GUIEventAdapter::KEY_Control_L)
127 m_bControlDown =
true;
131 if(m_bInDrag && m_bShiftDown && m_bControlDown)
133 bHandled = DoMouseSpring(ea, x, y);
139 case(GUIEventAdapter::KEYUP):
143 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L)
145 m_bShiftDown =
false;
149 if(ea.getKey() == osgGA::GUIEventAdapter::KEY_Control_L)
151 m_bControlDown =
false;
155 if(ea.getKey() == osgGA::GUIEventAdapter::KEY_F10 && m_lpSim)
156 m_lpSim->ResetSimulation();
158 if(ea.getKey() == osgGA::GUIEventAdapter::KEY_F5 && m_lpSim)
159 m_lpSim->ToggleSimulation();
168 bHandled = osgGA::TrackballManipulator::handle(ea, aa);
174 catch(CStdErrorInfo oError)
182 const osg::Camera *OsgCameraManipulator::GetCamera(
float x,
float y,
float &local_x,
float &local_y)
184 const osg::Camera* camera = m_osgViewer->getCameraContainingPosition(x, y, local_x, local_y);
185 if (!camera) camera = m_osgViewer->getCamera();
189 const osg::Camera *OsgCameraManipulator::GetCamera(
float x,
float y)
191 float local_x=0, local_y=0;
192 const osg::Camera* camera = m_osgViewer->getCameraContainingPosition(x, y, local_x, local_y);
193 if (!camera) camera = m_osgViewer->getCamera();
197 void OsgCameraManipulator::pick(
const osgGA::GUIEventAdapter& ea, GUIActionAdapter& aa)
199 osgUtil::LineSegmentIntersector::Intersections intersections;
204 m_lpOsgSim->MouseSpring()->SetRigidBody(NULL);
209 float local_x, local_y = 0.0;
210 const osg::Camera* camera = GetCamera(x, y, local_x, local_y);
212 osgUtil::LineSegmentIntersector::CoordinateFrame cf = camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
213 osg::ref_ptr< osgUtil::LineSegmentIntersector > picker =
new osgUtil::LineSegmentIntersector(cf, local_x, local_y);
215 RigidBody *lpBody = NULL;
216 Joint *lpJoint = NULL;
217 Structure *lpStruct = NULL;
218 Light *lpLight = NULL;
219 if (m_osgViewer->computeIntersections(x,y,intersections))
222 #pragma region LineSegmentIntersector
224 for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
225 hitr != intersections.end();
229 if (hitr->drawable.valid() && hitr->drawable->getUserData())
234 if(osgData && m_lpSim)
236 lpBody = osgData->GetBody();
237 lpJoint = osgData->GetJoint();
238 lpStruct = osgData->GetStructure();
239 lpLight = osgData->GetLight();
241 m_vPickPoint = hitr->getWorldIntersectPoint();
242 m_vPickNormal = hitr->getWorldIntersectNormal();
243 m_vSelectedVertex = FindSelectedVertex(hitr);
245 switch (m_lpSim->VisualSelectionMode())
247 case GRAPHICS_SELECTION_MODE:
248 case COLLISION_SELECTION_MODE:
258 if(lpBody && lpBody->AllowMouseManipulation() && lpBody->IsVisible() && (lpBody->VisualSelectionType() & m_lpSim->VisualSelectionMode()) )
263 if(lpStruct && lpStruct->IsVisible() )
265 m_lpPicked = lpStruct;
268 if(lpLight && lpLight->IsVisible() )
270 m_lpPicked = lpLight;
275 case JOINT_SELECTION_MODE:
276 if(lpJoint && lpJoint->AllowMouseManipulation() && lpJoint->IsVisible() && (lpJoint->VisualSelectionType() & m_lpSim->VisualSelectionMode()) )
278 m_lpPicked = lpJoint;
283 case RECEPTIVE_FIELD_SELECTION_MODE:
284 if(lpBody && lpBody->AllowMouseManipulation() && lpBody->IsVisible() && (lpBody->VisualSelectionType() == COLLISION_SELECTION_MODE) )
291 case SIMULATION_SELECTION_MODE:
292 if(lpBody && lpBody->AllowMouseManipulation() && lpBody->IsVisible() && (lpBody->VisualSelectionType() & m_lpSim->VisualSelectionMode()) )
294 m_lpOsgSim->MouseSpring()->SetRigidBody(osgData->GetBody());
295 m_lpOsgSim->MouseSpring()->SetGrabPosition(hitr->getLocalIntersectPoint());
296 m_lpPicked = osgData->GetBody();
312 m_lpOsgSim->MouseSpring()->SetRigidBody(NULL);
316 osg::Vec3 OsgCameraManipulator::FindSelectedVertex(osgUtil::LineSegmentIntersector::Intersections::iterator &hitr)
319 const osgUtil::LineSegmentIntersector::Intersection::IndexList& vil = hitr->indexList;
320 const osgUtil::LineSegmentIntersector::Intersection::RatioList& ral = hitr->ratioList;
321 osg::Geometry *osgGeom =
dynamic_cast<osg::Geometry *
>(hitr->drawable.get());
322 if(vil.size() > 0 && osgGeom)
325 osg::ref_ptr<osg::Vec3Array> aryVert =
dynamic_cast<osg::Vec3Array*
>(osgGeom->getVertexArray());
329 if(vil.size() != ral.size())
330 THROW_ERROR(Osg_Err_lHitArrayMismatch, Osg_Err_strHitArrayMismatch);
332 int iSize = vil.size();
333 osg::Vec3 osgHit(0, 0, 0);
334 for(
int iIdx=0; iIdx<iSize; iIdx++)
336 osgHit += ((*aryVert)[vil[iIdx]])*ral[iIdx];
339 double dblMin = 10000, dblDist = 0;
341 for(
int iIdx=0; iIdx<iSize; iIdx++)
343 osg::Vec3 osgVert = (*aryVert)[vil[iIdx]];
344 dblDist =
Std_CalculateDistance(osgHit.x(), osgHit.y(), osgHit.z(), osgVert.x(), osgVert.y(), osgVert.z());
355 return osg::Vec3(0, 0, 0);
372 bool OsgCameraManipulator::CanDoMouseSpring()
374 if(m_lpOsgSim->MouseSpring()->GetRigidBody() && m_lpOsgSim->MouseSpring()->GetMovableItem())
380 bool OsgCameraManipulator::DoMouseSpring(
const GUIEventAdapter& ea,
float x,
float y)
382 m_lpOsgSim->MouseSpring()->Visible(
false);
384 OsgMovableItem *osgRBBody = m_lpOsgSim->MouseSpring()->GetMovableItem();
385 RigidBody *rbBody = m_lpOsgSim->MouseSpring()->GetRigidBody();
387 if (!osgRBBody || !rbBody)
390 m_lpOsgSim->MouseSpring()->Visible(
true);
395 osg::Vec3 vGrabPos = m_lpOsgSim->MouseSpring()->GetGrabPosition() *osgRBBody->
GetCameraMatrixTransform()->getWorldMatrices().at(0);
396 m_lpOsgSim->MouseSpring()->SetStart(vGrabPos);
399 osg::Vec3 v3End = ConvertMouseTo3D(ea, x, y, vGrabPos);
400 m_lpOsgSim->MouseSpring()->SetEnd(v3End);
403 osg::Vec3 vSpringLength = ((v3End - vGrabPos));
404 osg::Vec3 vSpringForce = vSpringLength * m_lpSim->MouseSpringStiffness();
410 CStdFPoint fpBodyVel = rbBody->GetVelocityAtPoint(vGrabPos.x(), vGrabPos.y(), vGrabPos.z());
411 osg::Vec3 v3BodyVel(fpBodyVel.x, fpBodyVel.y, fpBodyVel.z);
412 osg::Vec3 v3DampForce = (v3BodyVel) * m_lpSim->MouseSpringDamping();
418 osg::Vec3 vTotalForce = vSpringForce - v3DampForce;
419 rbBody->AddForceAtWorldPos(vGrabPos.x(), vGrabPos.y(), vGrabPos.z(), vTotalForce.x(), vTotalForce.y(), vTotalForce.z(),
false);
421 m_lpSim->MouseSpringForceMagnitude(vTotalForce.length(),
true);
422 m_lpSim->MouseSpringDampingForceMagnitude(v3DampForce.length(),
true);
423 m_lpSim->MouseSpringLengthMagnitude(vSpringLength.length(),
true);
431 osg::Vec3 OsgCameraManipulator::ConvertMouseTo3D(
const GUIEventAdapter& ea,
int x,
int y, osg::Vec3 vGrabPos)
435 const osg::Camera *camera = m_osgViewer->getCamera();
438 const osg::Viewport* viewport = camera->getViewport();
441 viewport = m_osgViewport.get();
444 float mx = viewport->x() + (int)((
float)viewport->width()*(ea.getXnormalized()*0.5f+0.5f));
445 float my = viewport->y() + (int)((
float)viewport->height()*(ea.getYnormalized()*0.5f+0.5f));
448 osg::Matrix matrix = camera->getViewMatrix() * camera->getProjectionMatrix() * viewport->computeWindowMatrix();
451 osg::Matrix inverseWM ;
452 inverseWM.invert(matrix);
455 osg::Vec3 near_point = osg::Vec3(mx, my, 0.0) * inverseWM;
456 osg::Vec3 far_point = osg::Vec3(mx, my, 1.0) * inverseWM;
457 float mouseDistance = (near_point - vGrabPos).length();
459 osg::Vec3 clickDir = far_point - near_point;
460 clickDir.normalize();
462 osg::Vec3 desiredPosition = near_point + (clickDir * mouseDistance);
469 return desiredPosition;
472 void OsgCameraManipulator::DoPan(
const GUIEventAdapter& ea,
float x,
float y)
474 float dx = x - m_fltPrevX;
475 float dy = y - m_fltPrevY;
477 unsigned int buttonMask = ea.getButtonMask();
478 if(buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON))
481 osg::Vec3 v3Eye(dx, 0, dy);
482 m_v3Eye = m_v3Eye - v3Eye;
486 void OsgCameraManipulator::DoZoom(
const GUIEventAdapter& ea,
float x,
float y)
488 float dy = y - m_fltPrevY;
490 unsigned int buttonMask = ea.getButtonMask();
491 if(buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON))
493 osg::Vec3 v3Eye(0, 0, dy);
494 m_v3Eye = m_v3Eye + v3Eye;
498 void OsgCameraManipulator::DoRotate(
const GUIEventAdapter& ea,
float x,
float y)
500 float dx = x - m_fltPrevX;
501 float dy = y - m_fltPrevY;
503 unsigned int buttonMask = ea.getButtonMask();
504 if(buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON))
506 osg::Matrix rotation_matrix(m_quatRotation);
508 osg::Vec3 uv = osg::Vec3(0.0f,1.0f,0.0f)*rotation_matrix;
509 osg::Vec3 sv = osg::Vec3(1.0f,0.0f,0.0f)*rotation_matrix;
510 osg::Vec3 lv = osg::Vec3(0.0f,0.0f,-1.0f)*rotation_matrix;
512 osg::Vec3 p2 = sv * x + uv * y - lv * tb_project_to_sphere(0.8f, x, y);
513 osg::Vec3 p1 = sv * m_fltPrevX + uv * m_fltPrevY - lv * tb_project_to_sphere(0.8f, m_fltPrevX, m_fltPrevY);
519 float t = (p2 - p1).length() / (2.0 * 0.8f);
521 if (t > 1.0) t = 1.0;
522 if (t < -1.0) t = -1.0;
524 float angle = osg::inRadians(asin(t));
526 osg::Quat new_rotate;
527 new_rotate.makeRotate(angle,axis);
529 m_quatRotation = m_quatRotation*new_rotate;
540 float OsgCameraManipulator::tb_project_to_sphere(
float r,
float x,
float y)
546 if (d < r * 0.70710678118654752440)
552 t = r / 1.41421356237309504880;
Declares the vortex Light class.
virtual osg::MatrixTransform * GetCameraMatrixTransform()
Gets the matrix transform used by the camera for the mouse spring.
Classes for implementing the cm-labs vortex physics engine for AnimatLab.
virtual bool handle(const GUIEventAdapter &ea, GUIActionAdapter &us)
Declares the vortex structure class.
double Std_CalculateDistance(CStdIPoint &ptA, CStdIPoint &ptB)
Calculates the distance between two points.