00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <physics/Solid>
00026 #include <base/ref>
00027
00028 #include <osg/Node>
00029 #include <osg/Transform>
00030 #include <osg/Geode>
00031
00032 using physics::Solid;
00033 using physics::Shape;
00034 using physics::Material;
00035 using physics::CollisionModel;
00036 using physics::MassProperties;
00037
00038 using osg::Node;
00039 using osg::MatrixTransform;
00040 using osg::Geode;
00041
00042
00043 Solid::Solid(ref<const Shape> shape, ref<const Material> material)
00044 : Body(shape), material(material)
00045 {
00046 }
00047
00048 Solid::Solid(const Solid& s)
00049 : Body(s), material(s.material)
00050 {
00051 }
00052
00053 Solid::~Solid()
00054 {
00055 }
00056
00057
00058
00059 MassProperties Solid::massProperties() const
00060 {
00061
00062
00063
00064 MassProperties massProps;
00065 try {
00066
00067 massProps = getShape()->getMassProperties(material);
00068
00069 } catch (std::exception& e) {
00070 Logln("Couldn't calculate Mass properties of shape " << getShape()->className() << ", using default.");
00071
00072
00073 BoundingBox bb(getShape()->getBoundingBox());
00074 Real dx = bb.getDimension().x;
00075 Real dy = bb.getDimension().y;
00076 Real dz = bb.getDimension().z;
00077
00078 Real volume = dx*dy*dz;
00079 if (base::equals(volume,0)) {
00080 Logln("Warning: Bounding box of shape is empty.");
00081 dx=dy=dz=volume=1.0;
00082 }
00083
00084 massProps.mass = volume*material->density();
00085 Real k = massProps.mass/12.0;
00086 Matrix3 Ibody;
00087 Ibody(1,1) = (dy*dy + dz*dz)*k;
00088 Ibody(2,2) = (dx*dx + dz*dz)*k;
00089 Ibody(3,3) = (dx*dx + dy*dy)*k;
00090 massProps.setIbody(Ibody);
00091 }
00092 return massProps;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102 void Solid::updateVisual()
00103 {
00104 if (node != 0) {
00105
00106 Matrix4 m(getOrientation());
00107 m.setTranslationComponent(getPosition());
00108 worldTransform->setMatrix(m);
00109 }
00110 }
00111
00112
00113 osg::Node* Solid::createOSGVisual(Visual::Attributes visualAttributes) const
00114 {
00115 if ((node!=0) && (attributes==visualAttributes))
00116 return &(*node);
00117
00118 if (!getShape()->visualTypeSupported(OSGVisual))
00119 throw std::runtime_error(Exception("Shape doesn't support OSGVisual"));
00120
00121 osg::Node& shapeNode = *getShape()->createOSGVisual(visualAttributes);
00122
00123
00124 if (!getShape()->includesAppearance()) {
00125 shapeNode.setStateSet( &(*material->createState()) );
00126 }
00127
00128
00129
00130 MatrixTransform* transform = new MatrixTransform();
00131 transform->setName(className());
00132 transform->addChild(&shapeNode);
00133 worldTransform = transform;
00134
00135 Matrix4 m(getOrientation());
00136 m.setTranslationComponent(getPosition());
00137 worldTransform->setMatrix(m);
00138
00139 if (visualAttributes & Visual::ShowCollisionModel) {
00140 ref<CollisionModel> collisionModel = getShape()->getCollisionModel(CollisionModel::AnyModel);
00141 if (collisionModel->visualTypeSupported(OSGVisual))
00142 transform->addChild( collisionModel->createOSGVisual(visualAttributes) );
00143 }
00144
00145 node = transform;
00146
00147 return &(*node);
00148 }