AnimatLab  2
Test
OsgMovableItem.cpp
1 #include "StdAfx.h"
2 #include <stdarg.h>
3 #include "OsgCalculateBoundingBox.h"
4 #include "OsgMovableItem.h"
5 #include "OsgBody.h"
6 #include "OsgRigidBody.h"
7 #include "OsgJoint.h"
8 #include "OsgOrganism.h"
9 #include "OsgStructure.h"
10 #include "OsgUserData.h"
11 #include "OsgUserDataVisitor.h"
12 
13 #include "OsgMouseSpring.h"
14 #include "OsgLight.h"
15 #include "OsgCameraManipulator.h"
16 #include "OsgDragger.h"
17 #include "OsgSimulator.h"
18 
19 namespace OsgAnimatSim
20 {
21  namespace Environment
22  {
23 
25 // Construction/Destruction
27 
28 OsgMovableItem::OsgMovableItem()
29 {
30  m_bCullBackfaces = false; //No backface culling by default.
31  m_eTextureMode = GL_TEXTURE_2D;
32 
33  m_lpOsgSim = NULL;
34  m_lpThisAB = NULL;
35  m_lpThisMI = NULL;
36  m_lpThisVsMI = NULL;
37  m_lpParentVsMI = NULL;
38 }
39 
40 
41 OsgMovableItem::~OsgMovableItem()
42 {
43 }
44 
45 void OsgMovableItem::SetThisPointers()
46 {
47  m_lpThisAB = dynamic_cast<AnimatBase *>(this);
48  if(!m_lpThisAB)
49  THROW_TEXT_ERROR(Osg_Err_lThisPointerNotDefined, Osg_Err_strThisPointerNotDefined, "m_lpThisAB");
50 
51  m_lpThisMI = dynamic_cast<MovableItem *>(this);
52  if(!m_lpThisMI)
53  THROW_TEXT_ERROR(Osg_Err_lThisPointerNotDefined, Osg_Err_strThisPointerNotDefined, "m_lpThisMI, " + m_lpThisAB->Name());
54 
55  m_lpThisVsMI = dynamic_cast<OsgMovableItem *>(this);
56  if(!m_lpThisVsMI)
57  THROW_TEXT_ERROR(Osg_Err_lThisPointerNotDefined, Osg_Err_strThisPointerNotDefined, "m_lpThisVsMI, " + m_lpThisAB->Name());
58 
59  m_lpThisMI->PhysicsMovableItem(this);
60 }
61 
62 OsgSimulator *OsgMovableItem::GetOsgSimulator()
63 {
64  if(!m_lpOsgSim)
65  {
66  m_lpOsgSim = dynamic_cast<OsgSimulator *>(m_lpThisAB->GetSimulator());
67  if(!m_lpThisVsMI)
68  THROW_TEXT_ERROR(Osg_Err_lThisPointerNotDefined, Osg_Err_strThisPointerNotDefined, "m_lpOsgSim, " + m_lpThisAB->Name());
69  }
70 
71  return m_lpOsgSim;
72 }
73 
74 std::string OsgMovableItem::Physics_ID()
75 {
76  if(m_lpThisAB)
77  return m_lpThisAB->ID();
78  else
79  return "";
80 }
81 
82 void OsgMovableItem::FinalMatrix(osg::Matrix vFinal)
83 {
84  m_osgFinalMatrix = vFinal;
85  UpdateWorldMatrix();
86  Physics_UpdateAbsolutePosition();
87 }
88 
89 #pragma region Selection-Code
90 
91 void OsgMovableItem::Physics_Selected(bool bValue, bool bSelectMultiple)
92 {
93  if(m_osgNodeGroup.valid() && m_osgDragger.valid() && m_osgSelectedGroup.valid())
94  {
95  bool bIsReceptiveFieldMode = (m_lpThisAB->GetSimulator()->VisualSelectionMode() & RECEPTIVE_FIELD_SELECTION_MODE);
96 
97  //If selecting and not already selected then select it
98  bool bNodeFound = m_osgNodeGroup->containsNode(m_osgSelectedGroup.get());
99  if(bValue && !bNodeFound)
100  {
101  m_osgNodeGroup->addChild(m_osgSelectedGroup.get());
102  if(!bIsReceptiveFieldMode)
103  m_osgDragger->AddToScene();
104  else
105  ShowSelectedVertex();
106  }
107  //if de-selecting and selected then de-select the node
108  else if(!bValue && bNodeFound)
109  {
110  m_osgNodeGroup->removeChild(m_osgSelectedGroup.get());
111  m_osgDragger->RemoveFromScene();
112  HideSelectedVertex();
113  }
114  }
115 }
116 
117 void OsgMovableItem::CreateSelectedGraphics(std::string strName)
118 {
119  m_osgSelectedGroup = new osg::Group();
120  m_osgSelectedGroup->setName(strName + "_SelectedGroup");
121  m_osgSelectedGroup->addChild(m_osgNode.get());
122 
123  // set up the state so that the underlying color is not seen through
124  // and that the drawing mode is changed to wireframe, and a polygon offset
125  // is added to ensure that we see the wireframe itself, and turn off
126  // so texturing too.
127  osg::StateSet* stateset = new osg::StateSet;
128  osg::PolygonOffset* polyoffset = new osg::PolygonOffset;
129  polyoffset->setFactor(-1.0f);
130  polyoffset->setUnits(-1.0f);
131  osg::PolygonMode* polymode = new osg::PolygonMode;
132  polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);
133  stateset->setAttributeAndModes(polyoffset,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
134  stateset->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
135 
136  osg::Material* material = new osg::Material;
137  stateset->setAttributeAndModes(material,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
138  stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
139 
140  stateset->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
141 
142  m_osgSelectedGroup->setStateSet(stateset);
143 
144  CreateDragger(strName);
145  CreateSelectedVertex(strName);
146 
147  //If we are re-creating the graphics for this item and it was already selected then make sure to draw the drag handles.
148  if(m_lpThisMI->IsSelected())
149  Physics_Selected(true, false);
150 }
151 
152 void OsgMovableItem::CreateDragger(std::string strName)
153 {
154  if(m_lpThisAB->GetSimulator())
155  {
156  if(GetOsgSimulator()->OsgCmdMgr())
157  {
158  if(m_osgDragger.valid())
159  m_osgDragger.release();
160 
161  m_osgDragger = new OsgDragger(this, m_lpThisMI->AllowTranslateDragX(), m_lpThisMI->AllowTranslateDragY(), m_lpThisMI->AllowTranslateDragX(),
162  m_lpThisMI->AllowRotateDragX(), m_lpThisMI->AllowRotateDragY(), m_lpThisMI->AllowRotateDragZ(),
163  m_lpThisMI->UserDefinedDraggerRadius());
164  m_osgDragger->setName(strName + "_Dragger");
165 
166  m_osgDragger->setupDefaultGeometry();
167 
168  GetOsgSimulator()->OsgCmdMgr()->connect(*m_osgDragger, *m_osgMT);
169 
170  //Add pointers to this object to the grip so it will no which body part to
171  //call the EndGripDrag method on when the drag is finished.
172  m_osgDragger->setUserData(new OsgUserData(this));
173  }
174  }
175 }
176 
177 void OsgMovableItem::CreateSelectedVertex(std::string strName)
178 {
179  if(!m_osgSelVertexNode.valid())
180  {
181  m_osgSelVertexNode = new osg::Geode();
182  m_osgSelVertexNode->setName(strName + "SelVertex");
183  float fltRadius = m_lpThisAB->GetSimulator()->RecFieldSelRadius();
184  osg::ShapeDrawable *osgDraw = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0, 0, 0), fltRadius));
185  osgDraw->setColor(osg::Vec4(0, 1, 0, 0));
186  m_osgSelVertexNode->addDrawable(osgDraw);
187  }
188 
189  if(!m_osgSelVertexMT.valid())
190  {
191  m_osgSelVertexMT = new osg::MatrixTransform();
192 
193  //Initially have it at the center. It will get moved as vertices are picked.
194  osg::Matrix osgMT;
195  osgMT.makeIdentity();
196  m_osgSelVertexMT->setMatrix(osgMT);
197 
198  m_osgSelVertexMT->addChild(m_osgSelVertexNode.get());
199  }
200 }
201 
202 void OsgMovableItem::DeleteSelectedVertex()
203 {
204  HideSelectedVertex();
205 
206  if(m_osgSelVertexNode.valid()) m_osgSelVertexNode.release();
207  if(m_osgSelVertexMT.valid()) m_osgSelVertexMT.release();
208 }
209 
210 #pragma endregion
211 
212 float *OsgMovableItem::Physics_GetDataPointer(const std::string &strDataType) {return NULL;}
213 
214 void OsgMovableItem::LocalMatrix(osg::Matrix osgLocalMT)
215 {
216  m_osgLocalMatrix = osgLocalMT;
217  m_osgFinalMatrix = osgLocalMT;
218  UpdateWorldMatrix();
219 }
220 
221 void OsgMovableItem::GeometryRotationMatrix(osg::Matrix osgGeometryMT)
222 {
223  if(!m_osgGeometryRotationMT.valid())
224  {
225  m_osgGeometryRotationMT = new osg::MatrixTransform;
226  m_osgGeometryRotationMT->setName(m_lpThisAB->Name() + "_GeometryMT");
227  }
228  m_osgGeometryRotationMT->setMatrix(osgGeometryMT);
229 }
230 
231 void OsgMovableItem::AttachedPartMovedOrRotated(std::string strID)
232 {
233  //Physics_ResetGraphicsAndPhysics();
234 }
235 
236 void OsgMovableItem::CreateGraphicsGeometry() {}
237 
238 void OsgMovableItem::CreatePhysicsGeometry() {}
239 
240 void OsgMovableItem::ResizePhysicsGeometry() {}
241 
242 void OsgMovableItem::ResetPhyiscsAndChildJoints()
243 {
244  StartGripDrag();
245  EndGripDrag();
246 }
247 
248 void OsgMovableItem::InitializeGraphicsGeometry()
249 {
250  CreateGraphicsGeometry();
251  m_osgGeometry->setName(m_lpThisAB->Name() + "_Geometry");
252 
253  osg::Geode *osgGroup = new osg::Geode;
254  osgGroup->addDrawable(m_osgGeometry.get());
255  osgGroup->setName(m_lpThisAB->Name() + "_Node");
256 
257  //If they have not defined a geometry rotation matrix then lets add one that
258  //has no rotation so we can have a consistent node graph.
259  if(!m_osgGeometryRotationMT.valid())
260  {
261  CStdFPoint vPos(0, 0, 0), vRot(0, 0, 0);
262  GeometryRotationMatrix(SetupMatrix(vPos, vRot));
263  }
264 
265  m_osgGeometryRotationMT->addChild(osgGroup);
266  m_osgNode = m_osgGeometryRotationMT.get();
267 }
268 
269 void OsgMovableItem::CreateGeometry(bool bOverrideStatic)
270 {
271  InitializeGraphicsGeometry();
272  CreatePhysicsGeometry();
273 }
274 
275 void OsgMovableItem::SetupGraphics()
276 {
277  m_osgParent = ParentOSG();
278 
279  if(m_osgParent.valid())
280  {
281  BuildLocalMatrix();
282 
283  SetColor(*m_lpThisMI->Ambient(), *m_lpThisMI->Diffuse(), *m_lpThisMI->Specular(), m_lpThisMI->Shininess());
284  SetTexture(m_lpThisMI->Texture());
285  SetCulling();
286  SetVisible(m_lpThisMI->IsVisible());
287 
288  //Add it to the scene graph after checking if we add it to the
289  //parent node or the osg root node. For dynamic rigid bodies we add
290  //to the root node, for sensors, graphics, and joints we add to parent.
291  if(AddOsgNodeToParent())
292  m_osgParent->addChild(m_osgRoot.get());
293  else
294  GetOsgSimulator()->OSGRoot()->addChild(m_osgRoot.get());
295 
296  //Set the position with the world coordinates.
297  Physics_UpdateAbsolutePosition();
298 
299  //We need to set the UserData on the OSG side so we can do picking.
300  //We need to use a node visitor to set the user data for all drawable nodes in all geodes for the group.
301  osg::ref_ptr<OsgUserDataVisitor> osgVisitor = new OsgUserDataVisitor(this);
302  osgVisitor->traverse(*m_osgMT);
303  }
304 }
305 
306 void OsgMovableItem::DeleteGraphics()
307 {
308  if(m_osgParent.valid() && m_osgRoot.valid())
309  {
310  if(m_osgParent->containsNode(m_osgRoot.get()))
311  m_osgParent->removeChild(m_osgRoot.get());
312  }
313 
314  if(m_osgRoot.valid() && GetOsgSimulator() && GetOsgSimulator()->OSGRoot() && GetOsgSimulator()->OSGRoot()->containsNode(m_osgRoot.get()))
315  GetOsgSimulator()->OSGRoot()->removeChild(m_osgRoot.get());
316 
317  if(m_osgSelVertexNode.valid()) m_osgSelVertexNode.release();
318  if(m_osgSelVertexMT.valid()) m_osgSelVertexMT.release();
319 
320  if(m_osgCull.valid()) m_osgCull.release();
321  if(m_osgTexture.valid()) m_osgTexture.release();
322  if(m_osgStateSet.valid()) m_osgStateSet.release();
323  if(m_osgMaterial.valid()) m_osgMaterial.release();
324 
325  if(m_osgGeometry.valid()) m_osgGeometry.release();
326  if(m_osgNode.valid()) m_osgNode.release();
327  if(m_osgSelectedGroup.valid()) m_osgSelectedGroup.release();
328  if(m_osgNodeGroup.valid()) m_osgNodeGroup.release();
329  if(m_osgGeometryRotationMT.valid()) m_osgGeometryRotationMT.release();
330  if(m_osgMT.valid()) m_osgMT.release();
331  if(m_osgRoot.valid()) m_osgRoot.release();
332  if(m_osgParent.valid()) m_osgParent.release();
333 }
334 
335 OsgMovableItem *OsgMovableItem::VsParent()
336 {
337  return m_lpParentVsMI;
338 }
339 
340 osg::Matrix OsgMovableItem::GetWorldMatrix()
341 {
342  return m_osgWorldMatrix;
343 }
344 
345 osg::Matrix OsgMovableItem::GetComMatrix(bool bInvert)
346 {
347  osg::Matrix osgMatrix;
348  osgMatrix.makeIdentity();
349  return osgMatrix;
350 }
351 
352 osg::Matrix OsgMovableItem::GetParentWorldMatrix()
353 {
354  if(m_lpParentVsMI)
355  return m_lpParentVsMI->GetWorldMatrix();
356 
357  osg::Matrix osgMatrix;
358  osgMatrix.makeIdentity();
359  return osgMatrix;
360 }
361 
362 osg::Matrix OsgMovableItem::GetParentPhysicsWorldMatrix()
363 {
364  if(m_lpParentVsMI)
365  return m_lpParentVsMI->GetPhysicsWorldMatrix();
366 
367  osg::Matrix osgMatrix;
368  osgMatrix.makeIdentity();
369  return osgMatrix;
370 }
371 
372 osg::Matrix OsgMovableItem::GetParentComMatrix(bool bInvert)
373 {
374  if(m_lpParentVsMI)
375  return m_lpParentVsMI->GetComMatrix(bInvert);
376 
377  osg::Matrix osgMatrix;
378  osgMatrix.makeIdentity();
379  return osgMatrix;
380 }
381 
382 void OsgMovableItem::UpdateWorldMatrix()
383 {
384  if(AddOsgNodeToParent())
385  {
386  osg::Matrix osgParentMatrix = GetParentWorldMatrix();
387 
388  //Multiply the two matrices together to get the new world location.
389  m_osgWorldMatrix = m_osgFinalMatrix * osgParentMatrix;
390  }
391  else
392  {
393  if(m_osgMT.valid())
394  m_osgWorldMatrix = m_osgMT->getMatrix();
395  }
396 }
397 
398 CStdFPoint OsgMovableItem::GetOSGWorldCoords()
399 {
400  UpdateWorldMatrix();
401  osg::Vec3 vCoord = m_osgWorldMatrix.getTrans();
402  CStdFPoint vPoint(vCoord[0], vCoord[1], vCoord[2]);
403 
404  return vPoint;
405 }
406 
407 osg::Matrix OsgMovableItem::GetOSGWorldMatrix(bool bUpdate)
408 {
409  if(bUpdate)
410  UpdateWorldMatrix();
411 
412  return m_osgWorldMatrix;
413 }
414 
415 bool OsgMovableItem::Physics_CalculateLocalPosForWorldPos(float fltWorldX, float fltWorldY, float fltWorldZ, CStdFPoint &vLocalPos)
416 {
417  OsgMovableItem *lpParent = m_lpThisVsMI->VsParent();
418 
419  if(lpParent)
420  {
421  fltWorldX *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
422  fltWorldY *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
423  fltWorldZ *= m_lpThisAB->GetSimulator()->InverseDistanceUnits();
424 
425  CStdFPoint vPos(fltWorldX, fltWorldY, fltWorldZ), vRot(0, 0, 0);
426  osg::Matrix osgWorldPos = SetupMatrix(vPos, vRot);
427 
428  //Get the parent object.
429  osg::Matrix osgInverse = osg::Matrix::inverse(lpParent->GetWorldMatrix());
430 
431  osg::Matrix osgCalc = osgWorldPos * osgInverse;
432 
433  osg::Vec3 vCoord = osgCalc.getTrans();
434  vLocalPos.Set(vCoord[0] * m_lpThisAB->GetSimulator()->DistanceUnits(),
435  vCoord[1] * m_lpThisAB->GetSimulator()->DistanceUnits(),
436  vCoord[2] * m_lpThisAB->GetSimulator()->DistanceUnits());
437 
438  return true;
439  }
440 
441  return false;
442 }
443 
444 osg::MatrixTransform* OsgMovableItem::GetMatrixTransform()
445 {
446  return m_osgMT.get();
447 }
448 
465 {
466  if(m_osgGeometryRotationMT.valid())
467  return m_osgGeometryRotationMT.get();
468  else
469  return m_osgMT.get();
470 }
471 
472 osg::Matrix OsgMovableItem::CalculateTransformRelativeToParent(osg::Matrix osgLocalMatrix)
473 {
474  if(!m_lpParentVsMI || AddOsgNodeToParent())
475  return osgLocalMatrix;
476  else
477  {
478  //Get the parent object.
479  osg::Matrix osgInverse = osg::Matrix::inverse(m_lpParentVsMI->GetWorldMatrix());
480 
481  osg::Matrix osgLocal = osgLocalMatrix * osgInverse;
482  return osgLocal;
483  }
484 }
485 
486 
487 void OsgMovableItem::UpdatePositionAndRotationFromMatrix()
488 {
489  if(m_osgMT.valid())
490  UpdatePositionAndRotationFromMatrix(m_osgMT->getMatrix());
491 }
492 
493 void OsgMovableItem::UpdatePositionAndRotationFromMatrix(osg::Matrix osgMT)
494 {
495  LocalMatrix(osgMT);
496 
497  if(m_osgMT.valid())
498  m_osgMT->setMatrix(m_osgLocalMatrix);
499 
500  //Calculate the relative matrix from this par to its parent.
501  //Because we are using bullet the LocalMatrix may really be the World matrix instead of local.
502  //I should rename this, but it would require a lot of changes.
503  osg::Matrix osgLocal = CalculateTransformRelativeToParent(m_osgLocalMatrix);
504 
505  //If we are int he middle of a reset then do not fire the change events.
507  bool bFirePosChangeEvents = !m_lpThisAB->GetSimulator()->IsResetting();
508 
509  //Lets get the current world coordinates for this body part and then recalculate the
510  //new local position for the part and then finally reset its new local position.
511  osg::Vec3 vL = osgLocal.getTrans();
512  CStdFPoint vLocal(vL.x(), vL.y(), vL.z());
513  vLocal.ClearNearZero();
514  m_lpThisMI->Position(vLocal, false, bFirePosChangeEvents, false);
515 
516  //Now lets get the euler angle rotation
517  CStdFPoint vRot = EulerRotationFromMatrix(osgLocal);
518  m_lpThisMI->Rotation(vRot, bFirePosChangeEvents, false);
519 
520  if(m_osgDragger.valid())
521  m_osgDragger->SetupMatrix();
522 
524  //osg::Matrix osgTest = SetupMatrix(vLocal, vRot);
525  //if(!OsgMatricesEqual(osgTest, m_osgLocalMatrix))
526  // THROW_ERROR(Osg_Err_lUpdateMatricesDoNotMatch, Osg_Err_strUpdateMatricesDoNotMatch);
527 }
528 
529 void OsgMovableItem::Physics_UpdateMatrix()
530 {
531  if(m_osgMT.valid())
532  {
533  CStdFPoint vPos = m_lpThisMI->Position();
534  CStdFPoint vRot = m_lpThisMI->Rotation();
535 
536  if(!AddOsgNodeToParent())
537  {
538  osg::Matrix osgParentMatrix = GetParentWorldMatrix();
539  osg::Matrix osgLocal = SetupMatrix(vPos, vRot);
540  osg::Matrix osgWorldMT = osgLocal * osgParentMatrix;
541 
542  osg::Vec3d vWorldPos = osgWorldMT.getTrans();
543  vPos.Set(vWorldPos[0], vWorldPos[1], vWorldPos[2]);
544  vRot = EulerRotationFromMatrix(osgWorldMT);
545  }
546 
547  LocalMatrix(SetupMatrix(vPos, vRot));
548  m_osgMT->setMatrix(m_osgLocalMatrix);
549  UpdateWorldMatrix();
550 
551  if(m_osgDragger.valid())
552  m_osgDragger->SetupMatrix();
553 
554  Physics_UpdateAbsolutePosition();
555  }
556 }
557 
558 void OsgMovableItem::Physics_UpdateAbsolutePosition()
559 {
560  //If we are here then we did not have a physics component, just and OSG one.
561  CStdFPoint vPos = OsgMovableItem::GetOSGWorldCoords();
562  vPos.ClearNearZero();
563  m_lpThisMI->AbsolutePosition(vPos.x, vPos.y, vPos.z);
564 }
565 
566 void OsgMovableItem::BuildLocalMatrix()
567 {
568  //build the local matrix
569  BuildLocalMatrix(m_lpThisMI->Position(), CStdFPoint(0, 0, 0), m_lpThisMI->Rotation(), m_lpThisAB->Name());
570 }
571 
572 void OsgMovableItem::BuildLocalMatrix(CStdFPoint vLocalOffset)
573 {
574  //build the local matrix
575  BuildLocalMatrix(m_lpThisMI->Position(), vLocalOffset, m_lpThisMI->Rotation(), m_lpThisAB->Name());
576 }
577 
578 void OsgMovableItem::BuildLocalMatrix(CStdFPoint localPos, CStdFPoint vLocalOffset, CStdFPoint localRot, std::string strName)
579 {
580  if(!m_osgMT.valid())
581  {
582  m_osgMT = new osgManipulator::Selection;
583  m_osgMT->setName(strName + "_MT");
584  }
585 
586  if(!m_osgRoot.valid())
587  {
588  m_osgRoot = new osg::Group;
589  m_osgRoot->setName(strName + "_Root");
590  }
591 
592  if(!m_osgRoot->containsNode(m_osgMT.get()))
593  m_osgRoot->addChild(m_osgMT.get());
594 
595  osg::Matrix localMT;
596  CStdFPoint vOffsetPos = (localPos - vLocalOffset); //localPos;
597  if(AddOsgNodeToParent())
598  localMT = SetupMatrix(vOffsetPos, localRot);
599  else
600  localMT = SetupMatrix(vOffsetPos, localRot) * m_osgParent->getMatrix();
601 
602  LocalMatrix(localMT);
603 
604  //set the matrix to the matrix transform node
605  m_osgMT->setMatrix(m_osgLocalMatrix);
606 
607  UpdateWorldMatrix();
608 
609  //First create the node group. The reason for this is so that we can add other decorated groups on to this node.
610  //This is used to add the selected overlays.
611  if(!m_osgNodeGroup.valid() && m_osgNode.valid())
612  {
613  m_osgNodeGroup = new osg::Group();
614  m_osgNodeGroup->addChild(m_osgNode.get());
615  m_osgNodeGroup->setName(strName + "_NodeGroup");
616 
617  m_osgMT->addChild(m_osgNodeGroup.get());
618 
619  CreateSelectedGraphics(strName);
620  }
621 }
622 
623 void OsgMovableItem::Physics_LoadLocalTransformMatrix(CStdXml &oXml)
624 {
625  osg::Matrix osgMT = LoadMatrix(oXml, "LocalMatrix");
626  UpdatePositionAndRotationFromMatrix(osgMT);
627 }
628 
629 void OsgMovableItem::Physics_SaveLocalTransformMatrix(CStdXml &oXml)
630 {
631  SaveMatrix(oXml, "LocalMatrix", m_osgMT->getMatrix());
632 }
633 
634 std::string OsgMovableItem::Physics_GetLocalTransformMatrixString()
635 {
636  return SaveMatrixString(m_osgMT->getMatrix());
637 }
638 
639 void OsgMovableItem::Physics_ResizeDragHandler(float fltRadius)
640 {
641  bool bInScene = false;
642  if(m_osgDragger.valid() && m_osgDragger->IsInScene())
643  {
644  m_osgDragger->RemoveFromScene();
645  bInScene = true;
646  }
647 
648  CreateDragger(m_lpThisAB->Name());
649 
650  if(bInScene)
651  m_osgDragger->AddToScene();
652 }
653 
654 void OsgMovableItem::Physics_ResetGraphicsAndPhysics()
655 {
656  BuildLocalMatrix();
657 
658  SetupPhysics();
659 }
660 
661 void OsgMovableItem::Physics_PositionChanged()
662 {
663  Physics_UpdateMatrix();
664 }
665 
666 void OsgMovableItem::Physics_RotationChanged()
667 {
668  Physics_UpdateMatrix();
669 }
670 
671 BoundingBox OsgMovableItem::Physics_GetBoundingBox()
672 {
673  BoundingBox abb;
674  osg::BoundingBox bb;
675 
676  osg::Geode *osgGroup = dynamic_cast<osg::Geode *>(m_osgNode.get());
677  if(osgGroup)
678  {
679  bb = osgGroup->getBoundingBox();
680  abb.Set(bb.xMin(), bb.yMin(), bb.zMin(), bb.xMax(), bb.yMax(), bb.zMax());
681  }
682  else if(m_osgNode.valid())
683  {
684  osg::BoundingSphere osgBound = m_osgNode->getBound();
685  abb.Set(-osgBound.radius(), -osgBound.radius(), -osgBound.radius(), osgBound.radius(), osgBound.radius(), osgBound.radius());
686  }
687  else
688  abb.Set(-0.5, -0.5, -0.5, 0.5, 0.5, 0.5);
689 
690  return abb;
691 }
692 
693 float OsgMovableItem::Physics_GetBoundingRadius()
694 {
695  if(m_osgNode.valid())
696  {
697  osg::BoundingSphere osgBound = m_osgNode->getBound();
698  return osgBound.radius();
699  }
700 
701  return 0.5f;
702 }
703 
704 void OsgMovableItem::SetTexture(std::string strTexture)
705 {
706  if(m_osgNode.valid())
707  {
708  if(!Std_IsBlank(strTexture))
709  {
710  std::string strFile = AnimatSim::GetFilePath(m_lpThisAB->GetSimulator()->ProjectPath(), strTexture);
711  osg::ref_ptr<osg::Image> image = osgDB::readImageFile(strFile);
712  if(!image)
713  THROW_PARAM_ERROR(Osg_Err_lTextureLoad, Osg_Err_strTextureLoad, "Image File", strFile);
714 
715  osg::StateSet* state = m_osgNode->getOrCreateStateSet();
716  m_osgTexture = new osg::Texture2D(image.get());
717  m_osgTexture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
718 
719  m_osgTexture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
720  m_osgTexture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
721 
722  state->setTextureAttributeAndModes(0, m_osgTexture.get());
723  state->setTextureMode(0, m_eTextureMode, osg::StateAttribute::ON);
724  state->setMode(GL_BLEND,osg::StateAttribute::ON);
725 
726  //state->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
727  }
728  else if(m_osgTexture.valid()) //If we have already set it and we are clearing it then reset the state
729  {
730  m_osgTexture.release();
731  osg::StateSet* state = m_osgNode->getOrCreateStateSet();
732  state->setTextureAttributeAndModes(0, NULL);
733  state->setTextureMode(0, m_eTextureMode, osg::StateAttribute::OFF);
734  }
735  }
736 }
737 
738 void OsgMovableItem::Physics_CollectData()
739 {
740  //If we are here then we did not have a physics component, just and OSG one.
741  Physics_UpdateAbsolutePosition();
742 
743  //TODO: Get Rotation
744  //m_lpThis->ReportRotation(QuaterionToEuler(m_osgLocalMatrix.getRotate());
745 }
746 
747 void OsgMovableItem::Physics_ResetSimulation()
748 {
749  if(m_osgMT.valid())
750  {
751  BuildLocalMatrix();
752 
753  //Set the position with the world coordinates.
754  Physics_UpdateAbsolutePosition();
755  CStdFPoint vRot = m_lpThisMI->Rotation();
756  m_lpThisMI->ReportRotation(vRot);
757  }
758 }
759 
760 
761 void OsgMovableItem::SetCulling()
762 {
763  if(m_osgMT.valid())
764  {
765  if(m_bCullBackfaces)
766  {
767  if(!m_osgCull.valid())
768  {
769  m_osgCull = new osg::CullFace();
770  m_osgCull->setMode(osg::CullFace::BACK);
771  }
772  osg::StateSet* ss = m_osgMT->getOrCreateStateSet();
773  ss->setAttributeAndModes(m_osgCull.get(), osg::StateAttribute::ON);
774  }
775  else if(m_osgCull.valid())
776  {
777  osg::StateSet* ss = m_osgMT->getOrCreateStateSet();
778  ss->setAttributeAndModes(m_osgCull.get(), osg::StateAttribute::OFF);
779  }
780  }
781 }
782 
783 void OsgMovableItem::ShowSelectedVertex() {}
784 
785 void OsgMovableItem::HideSelectedVertex() {}
786 
787 void OsgMovableItem::SetAlpha()
788 {
789  switch (m_lpThisAB->GetSimulator()->VisualSelectionMode())
790  {
791  case GRAPHICS_SELECTION_MODE:
792  m_lpThisMI->Alpha(m_lpThisMI->GraphicsAlpha());
793  HideSelectedVertex();
794  break;
795 
796  case COLLISION_SELECTION_MODE:
797  m_lpThisMI->Alpha(m_lpThisMI->CollisionsAlpha());
798  HideSelectedVertex();
799  break;
800 
801  case JOINT_SELECTION_MODE:
802  m_lpThisMI->Alpha(m_lpThisMI->JointsAlpha());
803  HideSelectedVertex();
804  break;
805 
806  case RECEPTIVE_FIELD_SELECTION_MODE:
807  m_lpThisMI->Alpha(m_lpThisMI->ReceptiveFieldsAlpha());
808  ShowSelectedVertex();
809  break;
810 
811  case SIMULATION_SELECTION_MODE:
812  m_lpThisMI->Alpha(m_lpThisMI->SimulationAlpha());
813  HideSelectedVertex();
814  break;
815 
816  default:
817  m_lpThisMI->Alpha(m_lpThisMI->GraphicsAlpha());
818  HideSelectedVertex();
819  break;
820  }
821 
822  if(m_osgMaterial.valid() && m_osgStateSet.valid())
823  SetMaterialAlpha(m_osgMaterial.get(), m_osgStateSet.get(), m_lpThisMI->Alpha());
824 }
825 
826 void OsgMovableItem::SetMaterialAlpha(osg::Material *osgMat, osg::StateSet *ss, float fltAlpha)
827 {
828  osgMat->setAlpha(osg::Material::FRONT_AND_BACK, fltAlpha);
829 
830  if(fltAlpha < 1)
831  ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
832  else
833  ss->setRenderingHint(osg::StateSet::OPAQUE_BIN);
834 }
835 
836 void OsgMovableItem::SetColor(CStdColor &vAmbient, CStdColor &vDiffuse, CStdColor &vSpecular, float fltShininess)
837 {
838  if(m_osgNode.valid())
839  {
840 
841  //create a material to use with this node
842  if(!m_osgMaterial)
843  m_osgMaterial = new osg::Material();
844 
845  //create a stateset for this node
846  m_osgStateSet = m_osgNode->getOrCreateStateSet();
847 
848  //set the diffuse property of this node to the color of this body
849  m_osgMaterial->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(vAmbient[0], vAmbient[1], vAmbient[2], 1));
850  m_osgMaterial->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(vDiffuse[0], vDiffuse[1], vDiffuse[2], vDiffuse[3]));
851  m_osgMaterial->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(vSpecular[0], vSpecular[1], vSpecular[2], 1));
852  m_osgMaterial->setShininess(osg::Material::FRONT_AND_BACK, fltShininess);
853  m_osgStateSet->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
854  SetAlpha();
855 
856  //apply the material
857  m_osgStateSet->setAttribute(m_osgMaterial.get(), osg::StateAttribute::ON);
858  }
859 }
860 
861 void OsgMovableItem::SetVisible(osg::Node *osgNode, bool bVisible)
862 {
863  if(osgNode)
864  {
865  if(bVisible)
866  osgNode->setNodeMask(0x1);
867  else
868  osgNode->setNodeMask(0x0);
869  }
870 }
871 
872 void OsgMovableItem::SetVisible(bool bVisible)
873 {
874  SetVisible(m_osgNode.get(), bVisible);
875 }
876 
877 void OsgMovableItem::CreateItem()
878 {
879  m_lpThisAB->Initialize();
880  SetupGraphics();
881  SetupPhysics();
882 }
883 
884 void OsgMovableItem::StartGripDrag()
885 {
886 }
887 
888 void OsgMovableItem::EndGripDrag()
889 {
890  this->UpdatePositionAndRotationFromMatrix();
891 }
892 //
893 //osg::Vec3 OsgMovableItem::FindPointOnSurface(osg::Vec3 vDirection)
894 //{
895 // //If the parent object is not set then we cannot do orientation.
896 // if(!m_lpThisMI)
897 // return osg::Vec3(0, 0, 0);
898 //
899 // CStdFPoint vAbsPos = m_lpThisMI->AbsolutePosition();
900 // osg::Vec3 vPos(vAbsPos.x, vAbsPos.y, vAbsPos.z);
901 //
902 // osg::Vec3 vStart = vPos - (vDirection*10);
903 // osg::Vec3 vEnd = vPos + (vDirection*10);
904 //
905 // osg::LineSegment* osgLine = new osg::LineSegment();
906 // osgLine->set(vStart, vEnd);
907 //
908 // osgUtil::IntersectVisitor findIntersectVisitor;
909 // findIntersectVisitor.addLineSegment(osgLine);
910 // findIntersectVisitor.apply(*m_osgNodeGroup.get()); //
911 //
912 // osgUtil::IntersectVisitor::HitList tankIntersectHits;
913 // tankIntersectHits = findIntersectVisitor.getHitList(osgLine);
914 // osgUtil::Hit heightTestResults;
915 // if ( tankIntersectHits.empty() )
916 // return osg::Vec3(0, 0, 0);
917 //
918 // heightTestResults = tankIntersectHits.front();
919 // osg::Vec3d vIntersect = heightTestResults.getLocalIntersectPoint();;
920 //
921 // return vIntersect;
922 //}
923 //
924 //void OsgMovableItem::Physics_OrientNewPart(float fltXPos, float fltYPos, float fltZPos, float fltXNorm, float fltYNorm, float fltZNorm)
925 //{
926 // //If the parent object is not set then we cannot do orientation.
927 // if(!m_lpThisMI || !m_lpThisMI->Parent())
928 // return;
929 //
930 // osg::Vec3 vClickPos(fltXPos, fltYPos, fltZPos), vClickNormal(fltXNorm, fltYNorm, fltZNorm);
931 // osg::Vec3 vPointOnSurf = FindPointOnSurface(vClickNormal);
932 //
933 // osg::Vec3 vWorldPos = vClickPos + vPointOnSurf;
934 //
935 // CStdFPoint vParentPos = m_lpThisMI->Parent()->AbsolutePosition();
936 // osg::Vec3 vParent(vParentPos.x, vParentPos.y, vParentPos.z);
937 //
938 // osg::Vec3 vLocalPos = vWorldPos - vParent;
939 //
940 //
941 // osg::Vec3 vInitDir(0, 0, 1);
942 // float fltDot = vInitDir * vClickNormal;
943 // float fltAngle = acos(fltDot);
944 // osg::Vec3 vAxis = vInitDir ^ vClickNormal;
945 //
946 // //Setup the new local matrix.
947 // osg::Matrix osgM;
948 // osgM.makeIdentity();
949 // osgM.makeRotate(fltAngle, vAxis);
950 // osgM.makeTranslate(vLocalPos);
951 //
952 // UpdatePositionAndRotationFromMatrix(osgM);
953 //
954 // //rbNewPart.DxLocation = v + rbNewPart.FindPointOnSurface(new Vector3(), -rbParent.FaceNormal);
955 //
956 // //Vector3 v3InitDir = new Vector3(0,0,1);
957 // //
958 // //float fltAngle = (float)Math.Acos(Vector3.Dot(v3InitDir,Direction));
959 //
960 // //Vector3 v3Axis = Vector3.Cross(v3InitDir, Direction);
961 //
962 // //m_mtxOrientation.RotateAxis(v3Axis,fltAngle);
963 //}
964 
965 
966 void OsgMovableItem::Physics_OrientNewPart(float fltXPos, float fltYPos, float fltZPos, float fltXNorm, float fltYNorm, float fltZNorm)
967 {
968  //If the parent object is not set then we cannot do orientation.
969  if(!m_lpThisMI || !m_lpThisMI->Parent())
970  return;
971 
972  CStdFPoint vParentPos = m_lpThisMI->Parent()->AbsolutePosition();
973  osg::Vec3 vParent(vParentPos.x, vParentPos.y, vParentPos.z);
974 
975  osg::Vec3 vClickPos(fltXPos, fltYPos, fltZPos), vClickNormal(fltXNorm, fltYNorm, fltZNorm);
976 
977  //Lets get the bounding radius for this part
978  float fltRadius = Physics_GetBoundingRadius();
979 
980  //Now add the part at the specified position, but a radius away.
981  osg::Vec3 vWorldPos = vClickPos + (vClickNormal*fltRadius);
982 
983  //Calculate the local position relative to the parent.
984  osg::Vec3 vLocalPos = vWorldPos - vParent;
985 
986  //Now reset our position
987  m_lpThisMI->Position(vLocalPos[0], vLocalPos[1], vLocalPos[2], false, true, true);
988 }
989 
990  } // Environment
991 //} //OsgAnimatSim
992 
993 }
osg::ref_ptr< osg::MatrixTransform > m_osgGeometryRotationMT
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.
Declares the vortex organism class.
bool Std_IsBlank(std::string strVal)
Trims a string and tests if a string is blank.
Declares the vortex structure class.