AnimatLab  2
Test
VsJoint.cpp
1 // VsJoint.cpp: implementation of the VsJoint class.
2 //
4 
5 #include "StdAfx.h"
6 #include "VsMovableItem.h"
7 #include "VsBody.h"
8 #include "VsJoint.h"
9 #include "VsMotorizedJoint.h"
10 #include "VsRigidBody.h"
11 #include "VsStructure.h"
12 #include "VsSimulator.h"
13 #include "VsOsgUserData.h"
14 #include "VsOsgUserDataVisitor.h"
15 #include "VsDragger.h"
16 
17 namespace VortexAnimatSim
18 {
19  namespace Environment
20  {
21 
23 // Construction/Destruction
25 
26 VsJoint::VsJoint()
27 {
28  m_vxJoint = NULL;
29  m_lpVsParent = NULL;
30  m_lpVsChild = NULL;
31 
32  m_iCoordID = -1; //-1 if not used.
33 }
34 
35 VsJoint::~VsJoint()
36 {
37 }
38 
39 void VsJoint::Physics_SetParent(MovableItem *lpParent)
40 {
41  m_lpParentVsMI = dynamic_cast<VsMovableItem *>(lpParent);
42  m_lpVsParent = dynamic_cast<VsRigidBody *>(lpParent);
43 }
44 
45 void VsJoint::Physics_SetChild(MovableItem *lpChild)
46 {
47  m_lpVsChild = dynamic_cast<VsRigidBody *>(lpChild);
48 }
49 
50 void VsJoint::SetThisPointers()
51 {
52  VsBody::SetThisPointers();
53 
54  m_lpThisJoint = dynamic_cast<Joint *>(this);
55  if(!m_lpThisJoint)
56  THROW_TEXT_ERROR(Vs_Err_lThisPointerNotDefined, Vs_Err_strThisPointerNotDefined, "m_lpThisJoint, " + m_lpThisAB->Name());
57 
58  m_lpThisJoint->PhysicsBody(this);
59 }
60 
61 VxVector3 VsJoint::NormalizeAxis(CStdFPoint vLocalRot)
62 {
63  osg::Vec3 vPosN(1, 0, 0);
64  CStdFPoint vMatrixPos(0, 0, 0);
65 
66  osg::Matrix osgMT = SetupMatrix(vMatrixPos, vLocalRot);
67 
68  osg::Vec3 vNorm = vPosN * osgMT;
69 
70  VxVector3 axis((double) vNorm[0], (double) vNorm[1], (double) vNorm[2]);
71 
72  return axis;
73 }
74 
75 void VsJoint::UpdatePosition()
76 {
77  Vx::VxReal3 vPos;
78  m_vxJoint->getPartAttachmentPosition(0, vPos);
79 
80  UpdateWorldMatrix();
81  m_lpThisMI->AbsolutePosition(vPos[0], vPos[1], vPos[2]);
82 }
83 
84 float VsJoint::GetCurrentVxJointPos()
85 {
86  float fltDistanceUnits = m_lpThisAB->GetSimulator()->DistanceUnits();
87  float fltMassUnits = m_lpThisAB->GetSimulator()->MassUnits();
88 
89  if(m_vxJoint->isAngular(m_iCoordID) == true)
90  return m_vxJoint->getCoordinateCurrentPosition (m_iCoordID);
91  else
92  return m_vxJoint->getCoordinateCurrentPosition (m_iCoordID) * fltDistanceUnits;
93 }
94 
95 void VsJoint::Physics_CollectData()
96 {
97  if(m_lpThisJoint && m_vxJoint)
98  {
99  UpdatePosition();
100 
101  //Only update the joints data when we need to do robot synch, but still update our internal data.
102  //Only attempt to make these calls if the coordinate ID is a valid number.
103  if(m_iCoordID >= 0) //&& m_lpThisJoint->NeedsRobotSynch()
104  {
105  float fltDistanceUnits = m_lpThisAB->GetSimulator()->DistanceUnits();
106  float fltMassUnits = m_lpThisAB->GetSimulator()->MassUnits();
107 
108  if(m_vxJoint->isAngular(m_iCoordID) == true)
109  {
110  m_lpThisJoint->JointPosition(m_vxJoint->getCoordinateCurrentPosition (m_iCoordID));
111  m_lpThisJoint->JointVelocity(m_vxJoint->getCoordinateVelocity (m_iCoordID));
112  m_lpThisJoint->JointForce(m_vxJoint->getCoordinateForce(m_iCoordID) * fltMassUnits * fltDistanceUnits * fltDistanceUnits);
113  }
114  else
115  {
116  m_lpThisJoint->JointPosition(m_vxJoint->getCoordinateCurrentPosition (m_iCoordID) * fltDistanceUnits);
117  m_lpThisJoint->JointVelocity(m_vxJoint->getCoordinateVelocity(m_iCoordID) * fltDistanceUnits);
118  m_lpThisJoint->JointForce(m_vxJoint->getCoordinateForce(m_iCoordID) * fltMassUnits * fltDistanceUnits);
119  }
120  }
121  }
122 }
123 
124 osg::Group *VsJoint::ParentOSG()
125 {
126  if(m_lpVsParent)
127  return m_lpVsParent->GetMatrixTransform();
128 
129  return NULL;
130 }
131 
132 osg::Group *VsJoint::ChildOSG()
133 {
134  if(m_lpVsChild)
135  return m_lpVsChild->GetMatrixTransform();
136 
137  return NULL;
138 }
139 
140 void VsJoint::SetAlpha()
141 {
142  VsBody::SetAlpha();
143 
144  if(m_osgDefaultBallMat.valid() && m_osgDefaultBallSS.valid())
145  SetMaterialAlpha(m_osgDefaultBallMat.get(), m_osgDefaultBallSS.get(), m_lpThisMI->Alpha());
146 }
147 
148 void VsJoint::Physics_PositionChanged()
149 {
150  VsBody::Physics_PositionChanged();
151  Physics_ResetGraphicsAndPhysics();
152 }
153 
154 void VsJoint::Physics_RotationChanged()
155 {
156  Physics_ResetGraphicsAndPhysics();
157 }
158 
159 void VsJoint::Physics_Resize()
160 {
161  if(m_vxJoint)
162  {
163  DeleteJointGraphics();
165  ResetDraggerOnResize();
166  }
167 }
168 
169 void VsJoint::DeleteGraphics()
170 {
171  DeleteJointGraphics();
172  VsBody::DeleteGraphics();
173 }
174 
175 void VsJoint::DeleteJointGraphics()
176 {
177  if(m_osgJointMT.valid() && m_osgDefaultBallMT.valid()) m_osgJointMT->removeChild(m_osgDefaultBallMT.get());
178  m_osgDefaultBall.release();
179  m_osgDefaultBallMT.release();
180  m_osgDefaultBallSS.release();
181 }
182 
183 void VsJoint::ResetDraggerOnResize()
184 {
185  //Now lets re-adjust the gripper size.
186  if(m_osgDragger.valid())
187  m_osgDragger->SetupMatrix();
188 
189  //Reset the user data for the new parts.
190  if(m_osgNodeGroup.valid())
191  {
192  osg::ref_ptr<VsOsgUserDataVisitor> osgVisitor = new VsOsgUserDataVisitor(this);
193  osgVisitor->traverse(*m_osgNodeGroup);
194  }
195 }
196 
204 {
205  //Create the cylinder for the hinge
206  m_osgDefaultBall = CreateSphereGeometry(15, 15, m_lpThisJoint->Size());
207  osg::ref_ptr<osg::Geode> osgBall = new osg::Geode;
208  osgBall->addDrawable(m_osgDefaultBall.get());
209 
210  CStdFPoint vPos(0, 0, 0), vRot(VX_PI/2, 0, 0);
211  m_osgDefaultBallMT = new osg::MatrixTransform();
212  m_osgDefaultBallMT->setMatrix(SetupMatrix(vPos, vRot));
213  m_osgDefaultBallMT->addChild(osgBall.get());
214 
215  //create a material to use with the pos flap
216  if(!m_osgDefaultBallMat.valid())
217  m_osgDefaultBallMat = new osg::Material();
218 
219  //create a stateset for this node
220  m_osgDefaultBallSS = m_osgDefaultBallMT->getOrCreateStateSet();
221 
222  //set the diffuse property of this node to the color of this body
223  m_osgDefaultBallMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.1, 0.1, 0.1, 1));
224  m_osgDefaultBallMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 0.25, 1, 1));
225  m_osgDefaultBallMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0.25, 0.25, 0.25, 1));
226  m_osgDefaultBallMat->setShininess(osg::Material::FRONT_AND_BACK, 64);
227  m_osgDefaultBallSS->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
228 
229  //apply the material
230  m_osgDefaultBallSS->setAttribute(m_osgDefaultBallMat.get(), osg::StateAttribute::ON);
231 
232  m_osgJointMT->addChild(m_osgDefaultBallMT.get());
233 }
234 
235 
249 {
250  //Setup Vs pointers to child and parent.
251  m_lpVsParent = dynamic_cast<VsRigidBody *>(m_lpThisJoint->Parent());
252  if(!m_lpVsParent)
253  THROW_ERROR(Vs_Err_lUnableToConvertToVsRigidBody, Vs_Err_strUnableToConvertToVsRigidBody);
254 
255  m_lpVsChild = dynamic_cast<VsRigidBody *>(m_lpThisJoint->Child());
256  if(!m_lpVsChild)
257  THROW_ERROR(Vs_Err_lUnableToConvertToVsRigidBody, Vs_Err_strUnableToConvertToVsRigidBody);
258 
259  //The parent osg object for the joint is actually the child rigid body object.
260  m_osgParent = ParentOSG();
261  osg::ref_ptr<osg::Group> osgChild = ChildOSG();
262 
263  if(m_osgParent.valid())
264  {
265  //Add the parts to the group node.
266  CStdFPoint vPos(0, 0, 0), vRot(VX_PI/2, 0, 0);
267  vPos.Set(0, 0, 0); vRot.Set(0, VX_PI/2, 0);
268 
269  m_osgJointMT = new osg::MatrixTransform();
270  m_osgJointMT->setMatrix(SetupMatrix(vPos, vRot));
271 
272  m_osgNode = m_osgJointMT.get();
273 
274  //Create the sphere.
276 
277  BuildLocalMatrix();
278 
279  SetAlpha();
280  SetCulling();
281  SetVisible(m_lpThisMI->IsVisible());
282 
283  //Add it to the scene graph.
284  m_osgParent->addChild(m_osgRoot.get());
285 
286  //Set the position with the world coordinates.
287  Physics_UpdateAbsolutePosition();
288 
289  //We need to set the UserData on the OSG side so we can do picking.
290  //We need to use a node visitor to set the user data for all drawable nodes in all geodes for the group.
291  osg::ref_ptr<VsOsgUserDataVisitor> osgVisitor = new VsOsgUserDataVisitor(this);
292  osgVisitor->traverse(*m_osgMT);
293  }
294 }
295 
296 void VsJoint::SetupPhysics()
297 {
298 }
299 
300 void VsJoint::Initialize()
301 {
302 }
303 
304 void VsJoint::SetBody()
305 {
306 }
307 
308 void VsJoint::LocalMatrix(osg::Matrix osgLocalMT)
309 {
310  m_osgLocalMatrix = osgLocalMT;
311  m_osgFinalMatrix = m_osgLocalMatrix * m_osgChildOffsetMatrix;
312  UpdateWorldMatrix();
313 }
314 
315 void VsJoint::ChildOffsetMatrix(osg::Matrix osgMT)
316 {
317  m_osgChildOffsetMatrix = osgMT;
318  m_osgFinalMatrix = m_osgLocalMatrix * m_osgChildOffsetMatrix;
319  m_osgChildOffsetMT->setMatrix(m_osgChildOffsetMatrix);
320 }
321 
322 void VsJoint::UpdatePositionAndRotationFromMatrix()
323 {
324  VsBody::UpdatePositionAndRotationFromMatrix();
325  SetupPhysics();
326 }
327 
328 void VsJoint::Physics_UpdateMatrix()
329 {
330  LocalMatrix(SetupMatrix(m_lpThisMI->Position(), m_lpThisMI->Rotation()));
331  m_osgMT->setMatrix(m_osgLocalMatrix);
332  m_osgDragger->SetupMatrix();
333 
334  //Now lets get the localmatrix from the child object and use that for our offsetmatrix
335  VsBody *lpVsChild = dynamic_cast<VsBody *>(m_lpThisJoint->Child());
336  if(lpVsChild)
337  ChildOffsetMatrix(lpVsChild->LocalMatrix());
338 
339  //If we are here then we did not have a physics component, just and OSG one.
340  Physics_UpdateAbsolutePosition();
341 }
342 
343 void VsJoint::BuildLocalMatrix()
344 {
345  VsBody::BuildLocalMatrix();
346 }
347 
348 void VsJoint::BuildLocalMatrix(CStdFPoint localPos, CStdFPoint localRot, std::string strName)
349 {
350  if(!m_osgMT.valid())
351  {
352  m_osgMT = new osgManipulator::Selection;
353  m_osgMT->setName(strName + "_MT");
354  }
355 
356  if(!m_osgChildOffsetMT.valid())
357  {
358  m_osgChildOffsetMT = new osg::MatrixTransform;
359  m_osgChildOffsetMT->setName(strName + "ChildOffsetMT");
360  m_osgChildOffsetMT->addChild(m_osgMT.get());
361  }
362 
363  if(!m_osgRoot.valid())
364  {
365  m_osgRoot = new osg::Group;
366  m_osgRoot->setName(strName + "_Root");
367  m_osgRoot->addChild(m_osgChildOffsetMT.get());
368  }
369 
370  LocalMatrix(SetupMatrix(localPos, localRot));
371 
372  //set the matrix to the matrix transform node
373  m_osgMT->setMatrix(m_osgLocalMatrix);
374  m_osgMT->setName(strName.c_str());
375 
376  //Now lets get the localmatrix from the child object and use that for our offsetmatrix
377  VsBody *lpVsChild = dynamic_cast<VsBody *>(m_lpThisJoint->Child());
378  if(lpVsChild)
379  ChildOffsetMatrix(lpVsChild->LocalMatrix());
380 
381  //First create the node group. The reason for this is so that we can add other decorated groups on to this node.
382  //This is used to add the selected overlays.
383  if(!m_osgNodeGroup.valid())
384  {
385  m_osgNodeGroup = new osg::Group();
386  m_osgNodeGroup->addChild(m_osgNode.get());
387  m_osgNodeGroup->setName(strName + "_NodeGroup");
388 
389  m_osgMT->addChild(m_osgNodeGroup.get());
390 
391  CreateSelectedGraphics(strName);
392  }
393 }
394 
395 bool VsJoint::Physics_CalculateLocalPosForWorldPos(float fltWorldX, float fltWorldY, float fltWorldZ, CStdFPoint &vLocalPos)
396 {
397  VsMovableItem *lpParent = m_lpThisVsMI->VsParent();
398 
399  if(lpParent && m_lpVsChild)
400  {
401  fltWorldX *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
402  fltWorldY *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
403  fltWorldZ *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
404 
405  CStdFPoint vPos(fltWorldX, fltWorldY, fltWorldZ), vRot(0, 0, 0);
406  osg::Matrix osgWorldPos = SetupMatrix(vPos, vRot);
407 
408  //Get the parent object.
409  osg::Matrix osgInverse = osg::Matrix::inverse(m_lpVsChild->GetWorldMatrix());
410 
411  osg::Matrix osgCalc = osgWorldPos * osgInverse;
412 
413  osg::Vec3 vCoord = osgCalc.getTrans();
414  vLocalPos.Set(vCoord[0] * m_lpThisAB->GetSimulator()->DistanceUnits(),
415  vCoord[1] * m_lpThisAB->GetSimulator()->DistanceUnits(),
416  vCoord[2] * m_lpThisAB->GetSimulator()->DistanceUnits());
417 
418  return true;
419  }
420 
421  return false;
422 }
423 
424 void VsJoint::Physics_ResetSimulation()
425 {
426  if(m_vxJoint)
427  {
428  m_vxJoint->resetDynamics();
429 
430  UpdatePosition();
431  m_lpThisJoint->JointPosition(0);
432  m_lpThisJoint->JointVelocity(0);
433  m_lpThisJoint->JointForce(0);
434  }
435 }
436 
437 
438 bool VsJoint::Physics_SetData(const std::string &strDataType, const std::string &strValue)
439 {
440 
441  if(strDataType == "ATTACHEDPARTMOVEDORROTATED")
442  {
443  AttachedPartMovedOrRotated(strValue);
444  return true;
445  }
446 
447  return false;
448 }
449 
450 void VsJoint::Physics_QueryProperties(CStdPtrArray<TypeProperty> &aryProperties)
451 {
452 }
453 
454  } // Environment
455 } //VortexAnimatSim
osg::ref_ptr< osg::StateSet > m_osgDefaultBallSS
The osg default ball state set.
Definition: VsJoint.h:58
osg::ref_ptr< osg::Geometry > m_osgDefaultBall
The osg default ball geometry.
Definition: VsJoint.h:49
osg::ref_ptr< osg::MatrixTransform > m_osgDefaultBallMT
The osg default ball matrix transform.
Definition: VsJoint.h:52
A common class for all rigid body data specific to vortex.
Definition: VsRigidBody.h:55
virtual void CreateJointGraphics()
Creates the default ball graphics.
Definition: VsJoint.cpp:203
osg::ref_ptr< osg::Material > m_osgDefaultBallMat
The osg default ball material.
Definition: VsJoint.h:55
osg::Geometry * CreateSphereGeometry(int latres, int longres, float radius)
Classes for implementing the cm-labs vortex physics engine for AnimatLab.
osg::ref_ptr< osg::MatrixTransform > m_osgJointMT
The osg joint matrix transform.
Definition: VsJoint.h:61
virtual void SetupGraphics()
Sets up the graphics for the joint.
Definition: VsJoint.cpp:248
Vortex base body class.
Definition: VsBody.h:19
Declares the vortex structure class.