3 #include "VsMouseSpring.h"
4 #include "VsCameraManipulator.h"
5 #include "VsMovableItem.h"
8 #include "VsRigidBody.h"
11 #include "VsSimulator.h"
12 #include "VsOsgUserData.h"
13 #include "VsDragger.h"
17 namespace Visualization
20 VsCameraManipulator::VsCameraManipulator(Simulator *lpSim, osgViewer::Viewer *osgViewer, osg::Viewport *osgViewport)
23 m_osgViewer = osgViewer;
24 m_osgViewport = osgViewport;
28 m_bControlDown =
false;
37 this->setMinimumZoomScale(0.00001);
40 VsCameraManipulator::~VsCameraManipulator(
void)
42 VsMouseSpring::GetInstance()->SetRigidBody(NULL);
48 bool bHandled =
false;
56 switch(ea.getEventType())
58 case(GUIEventAdapter::PUSH):
64 case(GUIEventAdapter::RELEASE):
66 VsMouseSpring::GetInstance()->Visible(
false);
70 if(m_lpPicked && m_lpSim && m_lpSim->VisualSelectionMode() != SIMULATION_SELECTION_MODE)
73 m_lpPicked->SelectedVertex(m_vSelectedVertex.x(), m_vSelectedVertex.y(), m_vSelectedVertex.z(),
true,
true);
75 if(m_lpSim->AddBodiesMode())
76 m_lpPicked->AddBodyClicked(m_vPickPoint.x(), m_vPickPoint.y(), m_vPickPoint.z(),
77 m_vPickNormal.x(), m_vPickNormal.y(), m_vPickNormal.z());
79 m_lpPicked->Selected(
true, m_bControlDown);
87 case(GUIEventAdapter::DRAG):
93 if(m_bShiftDown && m_bControlDown && CanDoMouseSpring())
94 bHandled = DoMouseSpring(ea, x, y);
114 case(GUIEventAdapter::KEYDOWN):
118 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L)
124 if(ea.getKey() == osgGA::GUIEventAdapter::KEY_Control_L)
126 m_bControlDown =
true;
130 if(m_bInDrag && m_bShiftDown && m_bControlDown)
132 bHandled = DoMouseSpring(ea, x, y);
138 case(GUIEventAdapter::KEYUP):
142 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L)
144 m_bShiftDown =
false;
148 if(ea.getKey() == osgGA::GUIEventAdapter::KEY_Control_L)
150 m_bControlDown =
false;
154 if(ea.getKey() == osgGA::GUIEventAdapter::KEY_F10 && m_lpSim)
155 m_lpSim->ResetSimulation();
157 if(ea.getKey() == osgGA::GUIEventAdapter::KEY_F5 && m_lpSim)
158 m_lpSim->ToggleSimulation();
167 bHandled = osgGA::TrackballManipulator::handle(ea, aa);
173 catch(CStdErrorInfo oError)
181 const osg::Camera *VsCameraManipulator::GetCamera(
float x,
float y,
float &local_x,
float &local_y)
183 const osg::Camera* camera = m_osgViewer->getCameraContainingPosition(x, y, local_x, local_y);
184 if (!camera) camera = m_osgViewer->getCamera();
188 const osg::Camera *VsCameraManipulator::GetCamera(
float x,
float y)
190 float local_x=0, local_y=0;
191 const osg::Camera* camera = m_osgViewer->getCameraContainingPosition(x, y, local_x, local_y);
192 if (!camera) camera = m_osgViewer->getCamera();
196 void VsCameraManipulator::pick(
const osgGA::GUIEventAdapter& ea, GUIActionAdapter& aa)
198 osgUtil::LineSegmentIntersector::Intersections intersections;
203 VsMouseSpring::GetInstance()->SetRigidBody(NULL);
208 float local_x, local_y = 0.0;
209 const osg::Camera* camera = GetCamera(x, y, local_x, local_y);
211 osgUtil::LineSegmentIntersector::CoordinateFrame cf = camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
212 osg::ref_ptr< osgUtil::LineSegmentIntersector > picker =
new osgUtil::LineSegmentIntersector(cf, local_x, local_y);
214 RigidBody *lpBody = NULL;
215 Joint *lpJoint = NULL;
216 Structure *lpStruct = NULL;
217 Light *lpLight = NULL;
218 if (m_osgViewer->computeIntersections(x,y,intersections))
221 #pragma region LineSegmentIntersector
223 for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
224 hitr != intersections.end();
228 if (hitr->drawable.valid() && hitr->drawable->getUserData())
233 if(osgData && m_lpSim)
235 lpBody = osgData->GetBody();
236 lpJoint = osgData->GetJoint();
237 lpStruct = osgData->GetStructure();
238 lpLight = osgData->GetLight();
240 m_vPickPoint = hitr->getWorldIntersectPoint();
241 m_vPickNormal = hitr->getWorldIntersectNormal();
242 m_vSelectedVertex = FindSelectedVertex(hitr);
244 switch (m_lpSim->VisualSelectionMode())
246 case GRAPHICS_SELECTION_MODE:
247 case COLLISION_SELECTION_MODE:
257 if(lpBody && lpBody->AllowMouseManipulation() && lpBody->IsVisible() && (lpBody->VisualSelectionType() & m_lpSim->VisualSelectionMode()) )
262 if(lpStruct && lpStruct->IsVisible() )
264 m_lpPicked = lpStruct;
267 if(lpLight && lpLight->IsVisible() )
269 m_lpPicked = lpLight;
274 case JOINT_SELECTION_MODE:
275 if(lpJoint && lpJoint->AllowMouseManipulation() && lpJoint->IsVisible() && (lpJoint->VisualSelectionType() & m_lpSim->VisualSelectionMode()) )
277 m_lpPicked = lpJoint;
282 case RECEPTIVE_FIELD_SELECTION_MODE:
283 if(lpBody && lpBody->AllowMouseManipulation() && lpBody->IsVisible() && (lpBody->VisualSelectionType() == COLLISION_SELECTION_MODE) )
290 case SIMULATION_SELECTION_MODE:
291 if(lpBody && lpBody->AllowMouseManipulation() && lpBody->IsVisible() && (lpBody->VisualSelectionType() & m_lpSim->VisualSelectionMode()) )
293 VsMouseSpring::GetInstance()->SetRigidBody(osgData->GetVsBody());
294 VsMouseSpring::GetInstance()->SetGrabPosition(hitr->getLocalIntersectPoint());
295 m_lpPicked = osgData->GetBody();
311 VsMouseSpring::GetInstance()->SetRigidBody(NULL);
315 osg::Vec3 VsCameraManipulator::FindSelectedVertex(osgUtil::LineSegmentIntersector::Intersections::iterator &hitr)
318 const osgUtil::LineSegmentIntersector::Intersection::IndexList& vil = hitr->indexList;
319 const osgUtil::LineSegmentIntersector::Intersection::RatioList& ral = hitr->ratioList;
320 osg::Geometry *osgGeom =
dynamic_cast<osg::Geometry *
>(hitr->drawable.get());
321 if(vil.size() > 0 && osgGeom)
324 osg::ref_ptr<osg::Vec3Array> aryVert =
dynamic_cast<osg::Vec3Array*
>(osgGeom->getVertexArray());
328 if(vil.size() != ral.size())
329 THROW_ERROR(Vs_Err_lHitArrayMismatch, Vs_Err_strHitArrayMismatch);
331 int iSize = vil.size();
332 osg::Vec3 osgHit(0, 0, 0);
333 for(
int iIdx=0; iIdx<iSize; iIdx++)
335 osgHit += ((*aryVert)[vil[iIdx]])*ral[iIdx];
338 double dblMin = 10000, dblDist = 0;
340 for(
int iIdx=0; iIdx<iSize; iIdx++)
342 osg::Vec3 osgVert = (*aryVert)[vil[iIdx]];
343 dblDist =
Std_CalculateDistance(osgHit.x(), osgHit.y(), osgHit.z(), osgVert.x(), osgVert.y(), osgVert.z());
354 return osg::Vec3(0, 0, 0);
371 bool VsCameraManipulator::CanDoMouseSpring()
373 VsRigidBody *osgRBBody = VsMouseSpring::GetInstance()->GetRigidBody();
378 RigidBody *rbBody =
dynamic_cast<RigidBody *
>(osgRBBody);
386 bool VsCameraManipulator::DoMouseSpring(
const GUIEventAdapter& ea,
float x,
float y)
388 VsMouseSpring::GetInstance()->Visible(
false);
390 VsRigidBody *osgRBBody = VsMouseSpring::GetInstance()->GetRigidBody();
395 RigidBody *rbBody =
dynamic_cast<RigidBody *
>(osgRBBody);
400 VsMouseSpring::GetInstance()->Visible(
true);
405 osg::Vec3 vGrabPos = VsMouseSpring::GetInstance()->GetGrabPosition() *osgRBBody->
GetCameraMatrixTransform()->getWorldMatrices().at(0);
406 VsMouseSpring::GetInstance()->SetStart(vGrabPos);
409 osg::Vec3 v3End = ConvertMouseTo3D(ea, x, y, vGrabPos);
410 VsMouseSpring::GetInstance()->SetEnd(v3End);
413 osg::Vec3 vSpringLength = ((v3End - vGrabPos));
414 osg::Vec3 vSpringForce = vSpringLength * m_lpSim->MouseSpringStiffness();
420 CStdFPoint fpBodyVel = rbBody->GetVelocityAtPoint(vGrabPos.x(), vGrabPos.y(), vGrabPos.z());
421 osg::Vec3 v3BodyVel(fpBodyVel.x, fpBodyVel.y, fpBodyVel.z);
422 osg::Vec3 v3DampForce = (v3BodyVel) * m_lpSim->MouseSpringDamping();
428 osg::Vec3 vTotalForce = vSpringForce - v3DampForce;
429 rbBody->AddForceAtWorldPos(vGrabPos.x(), vGrabPos.y(), vGrabPos.z(), vTotalForce.x(), vTotalForce.y(), vTotalForce.z(),
false);
437 osg::Vec3 VsCameraManipulator::ConvertMouseTo3D(
const GUIEventAdapter& ea,
int x,
int y, osg::Vec3 vGrabPos)
441 const osg::Camera *camera = m_osgViewer->getCamera();
444 const osg::Viewport* viewport = camera->getViewport();
447 viewport = m_osgViewport.get();
450 float mx = viewport->x() + (int)((
float)viewport->width()*(ea.getXnormalized()*0.5f+0.5f));
451 float my = viewport->y() + (int)((
float)viewport->height()*(ea.getYnormalized()*0.5f+0.5f));
454 osg::Matrix matrix = camera->getViewMatrix() * camera->getProjectionMatrix() * viewport->computeWindowMatrix();
457 osg::Matrix inverseWM ;
458 inverseWM.invert(matrix);
461 osg::Vec3 near_point = osg::Vec3(mx, my, 0.0) * inverseWM;
462 osg::Vec3 far_point = osg::Vec3(mx, my, 1.0) * inverseWM;
463 float mouseDistance = (near_point - vGrabPos).length();
465 osg::Vec3 clickDir = far_point - near_point;
466 clickDir.normalize();
468 osg::Vec3 desiredPosition = near_point + (clickDir * mouseDistance);
475 return desiredPosition;
478 void VsCameraManipulator::DoPan(
const GUIEventAdapter& ea,
float x,
float y)
480 float dx = x - m_fltPrevX;
481 float dy = y - m_fltPrevY;
483 unsigned int buttonMask = ea.getButtonMask();
484 if(buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON))
487 osg::Vec3 v3Eye(dx, 0, dy);
488 m_v3Eye = m_v3Eye - v3Eye;
492 void VsCameraManipulator::DoZoom(
const GUIEventAdapter& ea,
float x,
float y)
494 float dy = y - m_fltPrevY;
496 unsigned int buttonMask = ea.getButtonMask();
497 if(buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON))
499 osg::Vec3 v3Eye(0, 0, dy);
500 m_v3Eye = m_v3Eye + v3Eye;
504 void VsCameraManipulator::DoRotate(
const GUIEventAdapter& ea,
float x,
float y)
506 float dx = x - m_fltPrevX;
507 float dy = y - m_fltPrevY;
509 unsigned int buttonMask = ea.getButtonMask();
510 if(buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON))
512 osg::Matrix rotation_matrix(m_quatRotation);
514 osg::Vec3 uv = osg::Vec3(0.0f,1.0f,0.0f)*rotation_matrix;
515 osg::Vec3 sv = osg::Vec3(1.0f,0.0f,0.0f)*rotation_matrix;
516 osg::Vec3 lv = osg::Vec3(0.0f,0.0f,-1.0f)*rotation_matrix;
518 osg::Vec3 p2 = sv * x + uv * y - lv * tb_project_to_sphere(0.8f, x, y);
519 osg::Vec3 p1 = sv * m_fltPrevX + uv * m_fltPrevY - lv * tb_project_to_sphere(0.8f, m_fltPrevX, m_fltPrevY);
525 float t = (p2 - p1).length() / (2.0 * 0.8f);
527 if (t > 1.0) t = 1.0;
528 if (t < -1.0) t = -1.0;
530 float angle = osg::inRadians(asin(t));
532 osg::Quat new_rotate;
533 new_rotate.makeRotate(angle,axis);
535 m_quatRotation = m_quatRotation*new_rotate;
546 float VsCameraManipulator::tb_project_to_sphere(
float r,
float x,
float y)
552 if (d < r * 0.70710678118654752440)
558 t = r / 1.41421356237309504880;
A common class for all rigid body data specific to vortex.
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.
Declares the vortex Light class.
virtual bool handle(const GUIEventAdapter &ea, GUIActionAdapter &us)
double Std_CalculateDistance(CStdIPoint &ptA, CStdIPoint &ptB)
Calculates the distance between two points.
Declares the vortex structure class.