AnimatLab  2
Test
OsgJoint.cpp
1 // OsgJoint.cpp: implementation of the OsgJoint class.
2 //
4 
5 #include "StdAfx.h"
6 #include <stdarg.h>
7 #include "OsgMovableItem.h"
8 #include "OsgBody.h"
9 #include "OsgJoint.h"
10 #include "OsgRigidBody.h"
11 #include "OsgStructure.h"
12 #include "OsgUserData.h"
13 #include "OsgUserDataVisitor.h"
14 
15 #include "OsgMouseSpring.h"
16 #include "OsgLight.h"
17 #include "OsgCameraManipulator.h"
18 #include "OsgDragger.h"
19 
20 namespace OsgAnimatSim
21 {
22  namespace Environment
23  {
24 
26 // Construction/Destruction
28 
29 OsgJoint::OsgJoint()
30 {
31  m_lpVsParent = NULL;
32  m_lpVsChild = NULL;
33  m_vJointGraphicsRotOffset.Set(0, osg::PI/2, 0) ;
34 }
35 
36 OsgJoint::~OsgJoint()
37 {
38 }
39 
40 void OsgJoint::Physics_SetParent(MovableItem *lpParent)
41 {
42  m_lpParentVsMI = dynamic_cast<OsgMovableItem *>(lpParent);
43  m_lpVsParent = dynamic_cast<OsgBody *>(lpParent);
44 }
45 
46 void OsgJoint::Physics_SetChild(MovableItem *lpChild)
47 {
48  m_lpVsChild = dynamic_cast<OsgRigidBody *>(lpChild);
49 }
50 
51 void OsgJoint::SetThisPointers()
52 {
53  OsgBody::SetThisPointers();
54 
55  m_lpThisJoint = dynamic_cast<Joint *>(this);
56  if(!m_lpThisJoint)
57  THROW_TEXT_ERROR(Osg_Err_lThisPointerNotDefined, Osg_Err_strThisPointerNotDefined, "m_lpThisJoint, " + m_lpThisAB->Name());
58 
59  m_lpThisJoint->PhysicsBody(this);
60 }
61 
62 osg::Vec3d OsgJoint::NormalizeAxis(CStdFPoint vLocalRot)
63 {
64  osg::Vec3 vPosN(1, 0, 0);
65  CStdFPoint vMatrixPos(0, 0, 0);
66 
67  osg::Matrix osgMT = SetupMatrix(vMatrixPos, vLocalRot);
68 
69  osg::Vec3 vNorm = vPosN * osgMT;
70 
71  return vNorm;
72 }
73 
74 osg::MatrixTransform *OsgJoint::ParentOSG()
75 {
76  if(m_lpVsParent)
77  return m_lpVsParent->GetMatrixTransform();
78 
79  return NULL;
80 }
81 
82 osg::MatrixTransform *OsgJoint::ChildOSG()
83 {
84  if(m_lpVsChild)
85  return m_lpVsChild->GetMatrixTransform();
86 
87  return NULL;
88 }
89 
90 void OsgJoint::SetAlpha()
91 {
92  OsgBody::SetAlpha();
93 
94  if(m_osgDefaultBallMat.valid() && m_osgDefaultBallSS.valid())
95  SetMaterialAlpha(m_osgDefaultBallMat.get(), m_osgDefaultBallSS.get(), m_lpThisMI->Alpha());
96 }
97 
98 void OsgJoint::Physics_PositionChanged()
99 {
100  OsgBody::Physics_PositionChanged();
101  Physics_ResetGraphicsAndPhysics();
102 }
103 
104 void OsgJoint::Physics_RotationChanged()
105 {
106  Physics_ResetGraphicsAndPhysics();
107 }
108 
109 void OsgJoint::Physics_ResetGraphicsAndPhysics()
110 {
111  OsgMovableItem::Physics_ResetGraphicsAndPhysics();
112 
113  if(m_osgDragger.valid())
114  m_osgDragger->SetupMatrix();
115 }
116 
117 void OsgJoint::DeleteGraphics()
118 {
119  DeleteJointGraphics();
120  OsgBody::DeleteGraphics();
121 }
122 
123 void OsgJoint::DeleteJointGraphics()
124 {
125  if(m_osgJointMT.valid() && m_osgDefaultBallMT.valid()) m_osgJointMT->removeChild(m_osgDefaultBallMT.get());
126  if(m_osgDefaultBall.valid()) m_osgDefaultBall.release();
127  if(m_osgDefaultBallMT.valid()) m_osgDefaultBallMT.release();
128  if(m_osgDefaultBallSS.valid()) m_osgDefaultBallSS.release();
129 }
130 
131 void OsgJoint::ResetDraggerOnResize()
132 {
133  //Now lets re-adjust the gripper size.
134  if(m_osgDragger.valid())
135  m_osgDragger->SetupMatrix();
136 
137  //Reset the user data for the new parts.
138  if(m_osgNodeGroup.valid())
139  {
140  osg::ref_ptr<OsgUserDataVisitor> osgVisitor = new OsgUserDataVisitor(this);
141  osgVisitor->traverse(*m_osgNodeGroup);
142  }
143 }
144 
152 {
153  //Create the cylinder for the hinge
154  m_osgDefaultBall = CreateSphereGeometry(15, 15, m_lpThisJoint->Size());
155  osg::ref_ptr<osg::Geode> osgBall = new osg::Geode;
156  osgBall->addDrawable(m_osgDefaultBall.get());
157 
158  CStdFPoint vPos(0, 0, 0), vRot(osg::PI/2, 0, 0);
159  m_osgDefaultBallMT = new osg::MatrixTransform();
160  m_osgDefaultBallMT->setMatrix(SetupMatrix(vPos, vRot));
161  m_osgDefaultBallMT->addChild(osgBall.get());
162 
163  //create a material to use with the pos flap
164  if(!m_osgDefaultBallMat.valid())
165  m_osgDefaultBallMat = new osg::Material();
166 
167  //create a stateset for this node
168  m_osgDefaultBallSS = m_osgDefaultBallMT->getOrCreateStateSet();
169 
170  //set the diffuse property of this node to the color of this body
171  m_osgDefaultBallMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0.1, 0.1, 0.1, 1));
172  m_osgDefaultBallMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 0.25, 1, 1));
173  m_osgDefaultBallMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0.25, 0.25, 0.25, 1));
174  m_osgDefaultBallMat->setShininess(osg::Material::FRONT_AND_BACK, 64);
175  m_osgDefaultBallSS->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
176 
177  //apply the material
178  m_osgDefaultBallSS->setAttribute(m_osgDefaultBallMat.get(), osg::StateAttribute::ON);
179 
180  m_osgJointMT->addChild(m_osgDefaultBallMT.get());
181 }
182 
183 
197 {
198  //Setup Vs pointers to child and parent.
199  m_lpVsParent = dynamic_cast<OsgRigidBody *>(m_lpThisJoint->Parent());
200  if(!m_lpVsParent)
201  THROW_ERROR(Osg_Err_lUnableToConvertToVsRigidBody, Osg_Err_strUnableToConvertToVsRigidBody);
202 
203  m_lpVsChild = dynamic_cast<OsgRigidBody *>(m_lpThisJoint->Child());
204  if(!m_lpVsChild)
205  THROW_ERROR(Osg_Err_lUnableToConvertToVsRigidBody, Osg_Err_strUnableToConvertToVsRigidBody);
206 
207  //The parent osg object for the joint is actually the child rigid body object.
208  m_osgParent = ParentOSG();
209 
210  if(m_osgParent.valid())
211  {
212  //Add the parts to the group node.
213  CStdFPoint vPos(0, 0, 0), vRot = m_vJointGraphicsRotOffset;
214 
215  m_osgJointMT = new osg::MatrixTransform();
216  m_osgJointMT->setMatrix(SetupMatrix(vPos, vRot));
217 
218  m_osgNode = m_osgJointMT.get();
219 
220  //Create the sphere.
222 
224 
225  SetAlpha();
226  SetCulling();
227  SetVisible(m_lpThisMI->IsVisible());
228 
229  //Add it to the scene graph.
230  m_osgParent->addChild(m_osgRoot.get());
231 
232  //Set the position with the world coordinates.
233  Physics_UpdateAbsolutePosition();
234 
235  //We need to set the UserData on the OSG side so we can do picking.
236  //We need to use a node visitor to set the user data for all drawable nodes in all geodes for the group.
237  osg::ref_ptr<OsgUserDataVisitor> osgVisitor = new OsgUserDataVisitor(this);
238  osgVisitor->traverse(*m_osgMT);
239  }
240 }
241 
242 void OsgJoint::SetupPhysics()
243 {
244 }
245 
246 void OsgJoint::Initialize()
247 {
248 }
249 
250 osg::Matrix OsgJoint::GetChildWorldMatrix()
251 {
252  if(m_lpVsChild)
253  return m_lpVsChild->GetWorldMatrix();
254 
255  osg::Matrix osgMatrix;
256  osgMatrix.makeIdentity();
257  return osgMatrix;
258 }
259 
260 osg::Matrix OsgJoint::GetChildPhysicsWorldMatrix()
261 {
262  if(m_lpVsChild)
263  return m_lpVsChild->GetPhysicsWorldMatrix();
264 
265  osg::Matrix osgMatrix;
266  osgMatrix.makeIdentity();
267  return osgMatrix;
268 }
269 
270 osg::Matrix OsgJoint::GetChildComMatrix(bool bInvert)
271 {
272  if(m_lpVsChild)
273  return m_lpVsChild->GetComMatrix(bInvert);
274 
275  osg::Matrix osgMatrix;
276  osgMatrix.makeIdentity();
277  return osgMatrix;
278 }
279 
280 //When moving the joint using the drag handler we need to delete the physics for this joint, and then
281 //recreate it using the new position/orientation.
282 void OsgJoint::StartGripDrag()
283 {
284  //Delete the physics for the joint
285  DeletePhysics(false);
286 }
287 
288 //Now recreate the joint.
289 void OsgJoint::EndGripDrag()
290 {
291  UpdatePositionAndRotationFromMatrix();
292 
293  //It does not seem like we should have to reset the graphics here, just the physics.
294  //However, we must do this in order to properly reconfigure the OSG matrix transforms that
295  //are then used to setup the physics.
296  DeleteGraphics();
297  SetupGraphics();
298 
299  //Now we can setup the physics
300  SetupPhysics();
301 }
302 
303 void OsgJoint::UpdatePositionAndRotationFromMatrix()
304 {
305  osg::Matrix mtParent = GetParentWorldMatrix();
306  osg::Matrix mtChild = GetChildWorldMatrix();
307  osg::Matrix mtLocal = m_osgMT->getMatrix();
308 
309  //Lets get the world location of the new transform matrix. This is relative to the parent body.
310  osg::Matrix mtWorld = mtLocal * mtParent;
311 
312  //Now calculate the local transform relative to the child for the update
313  osg::Matrix mtJointRelToChild = mtWorld * osg::Matrix::inverse(mtChild);
314 
315  OsgBody::UpdatePositionAndRotationFromMatrix(mtJointRelToChild);
316 }
317 
318 void OsgJoint::Physics_UpdateMatrix()
319 {
320  CStdFPoint vPos = m_lpThisMI->Position();
321  CStdFPoint vRot = m_lpThisMI->Rotation();
322  LocalMatrix(SetupMatrix(vPos, vRot));
323  m_osgMT->setMatrix(m_osgLocalMatrix);
324 
325  //If we are here then we did not have a physics component, just and OSG one.
326  Physics_UpdateAbsolutePosition();
327 }
328 
340 {
341  OsgBody::BuildLocalMatrix();
342 }
343 
344 void OsgJoint::BuildLocalMatrix(CStdFPoint localPos, CStdFPoint vLocalOffset, CStdFPoint localRot, std::string strName)
345 {
346  if(!m_osgMT.valid())
347  {
348  m_osgMT = new osgManipulator::Selection;
349  m_osgMT->setName(strName + "_MT");
350  }
351 
352  if(!m_osgRoot.valid())
353  {
354  m_osgRoot = new osg::Group;
355  m_osgRoot->setName(strName + "_Root");
356  }
357 
358  if(!m_osgRoot->containsNode(m_osgMT.get()))
359  m_osgRoot->addChild(m_osgMT.get());
360 
361  //We must add the osg graphics to the parent osg node /because if we do not then the joint will move
362  //when the child moves, and that is not correct. However, the joint is really attached relative to the
363  //child. So we need to calculate the local transform needed relative to the parent.
364  osg::Matrix mtParent = GetParentWorldMatrix();
365  osg::Matrix mtChild = GetChildWorldMatrix();
366  osg::Matrix mtLocal = SetupMatrix(localPos, localRot);
367 
368  osg::Matrix mtJointMTFromChild = mtLocal * mtChild;
369  osg::Matrix mtLocalRelToParent = mtJointMTFromChild * osg::Matrix::inverse(mtParent);
370 
371  LocalMatrix(mtLocalRelToParent);
372 
373  //set the matrix to the matrix transform node
374  m_osgMT->setMatrix(m_osgLocalMatrix);
375  m_osgMT->setName(strName.c_str());
376 
377  //First create the node group. The reason for this is so that we can add other decorated groups on to this node.
378  //This is used to add the selected overlays.
379  if(!m_osgNodeGroup.valid())
380  {
381  m_osgNodeGroup = new osg::Group();
382  m_osgNodeGroup->addChild(m_osgNode.get());
383  m_osgNodeGroup->setName(strName + "_NodeGroup");
384 
385  m_osgMT->addChild(m_osgNodeGroup.get());
386 
387  CreateSelectedGraphics(strName);
388  }
389 }
390 
391 bool OsgJoint::Physics_CalculateLocalPosForWorldPos(float fltWorldX, float fltWorldY, float fltWorldZ, CStdFPoint &vLocalPos)
392 {
393  if(m_lpVsParent && m_lpVsChild)
394  {
395  fltWorldX *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
396  fltWorldY *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
397  fltWorldZ *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
398 
399  CStdFPoint vPos(fltWorldX, fltWorldY, fltWorldZ), vRot(0, 0, 0);
400  osg::Matrix osgWorldPos = SetupMatrix(vPos, vRot);
401 
402  //Get the parent object.
403  osg::Matrix osgInverse = osg::Matrix::inverse(m_lpVsChild->GetWorldMatrix());
404 
405  osg::Matrix osgCalc = osgWorldPos * osgInverse;
406 
407  osg::Vec3 vCoord = osgCalc.getTrans();
408  vLocalPos.Set(vCoord[0] * m_lpThisAB->GetSimulator()->DistanceUnits(),
409  vCoord[1] * m_lpThisAB->GetSimulator()->DistanceUnits(),
410  vCoord[2] * m_lpThisAB->GetSimulator()->DistanceUnits());
411 
412  return true;
413  }
414 
415  return false;
416 }
417 
418 bool OsgJoint::Physics_SetData(const std::string &strDataType, const std::string &strValue)
419 {
420 
421  if(strDataType == "ATTACHEDPARTMOVEDORROTATED")
422  {
423  AttachedPartMovedOrRotated(strValue);
424  return true;
425  }
426 
427  return false;
428 }
429 
430 void OsgJoint::Physics_QueryProperties(CStdPtrArray<TypeProperty> &aryProperties)
431 {
432 }
433 
434 void OsgJoint::Physics_Resize()
435 {
436  if(Physics_IsDefined())
437  {
438  DeleteJointGraphics();
440  ResetDraggerOnResize();
441  }
442 }
443 
444 void OsgJoint::Physics_ResetSimulation()
445 {
446  if(Physics_IsDefined())
447  {
448  m_lpThisJoint->JointPosition(0);
449  m_lpThisJoint->JointVelocity(0);
450  m_lpThisJoint->JointForce(0);
451  }
452 }
453 
454 
455  } // Environment
456 } //OsgAnimatSim
virtual void CreateJointGraphics()
Creates the default ball graphics.
Definition: OsgJoint.cpp:151
Declares the vortex Light class.
A common class for all rigid body data specific to vortex.
Definition: OsgRigidBody.h:50
virtual void SetupGraphics()
Sets up the graphics for the joint.
Definition: OsgJoint.cpp:196
osg::ref_ptr< osg::Geometry > m_osgDefaultBall
The osg default ball geometry.
Definition: OsgJoint.h:34
Classes for implementing the cm-labs vortex physics engine for AnimatLab.
Vortex base body class.
Definition: OsgBody.h:26
virtual void BuildLocalMatrix()
Builds the local matrix.
Definition: OsgJoint.cpp:339
osg::ref_ptr< osg::StateSet > m_osgDefaultBallSS
The osg default ball state set.
Definition: OsgJoint.h:43
CStdFPoint m_vJointGraphicsRotOffset
Rotational offset needed to make the joint graphics match the physics.
Definition: OsgJoint.h:49
osg::ref_ptr< osg::MatrixTransform > m_osgJointMT
The osg joint matrix transform.
Definition: OsgJoint.h:46
osg::ref_ptr< osg::Material > m_osgDefaultBallMat
The osg default ball material.
Definition: OsgJoint.h:40
osg::ref_ptr< osg::MatrixTransform > m_osgDefaultBallMT
The osg default ball matrix transform.
Definition: OsgJoint.h:37
Declares the vortex structure class.
osg::Geometry ANIMAT_OSG_PORT * CreateSphereGeometry(int latres, int longres, float radius)