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/Cylinder>
00026
00027 #include <base/Externalizer>
00028 #include <gfx/VisualTriangles>
00029 #include <physics/Material>
00030 #include <physics/OBBCollisionModel>
00031 #include <physics/GJKCollisionModel>
00032
00033 #include <osg/Group>
00034 #include <osg/Geode>
00035 #include <osg/LOD>
00036 #include <osg/ShapeDrawable>
00037
00038 using physics::Cylinder;
00039 using physics::MassProperties;
00040 using physics::CollisionModel;
00041 using physics::OBBCollisionModel;
00042 using physics::GJKCollisionModel;
00043
00044 using gfx::Segment3;
00045 using gfx::VisualTriangles;
00046
00047 using osg::Node;
00048 using osg::Group;
00049 using osg::Geode;
00050 using osg::LOD;
00051 using osg::Vec3;
00052 using osg::Vec2;
00053
00054
00055 Cylinder::Cylinder()
00056 : _height(1.0), _radius(1.0), massPropertiesCached(false)
00057 {
00058 }
00059
00060 Cylinder::Cylinder(Real height, Real radius)
00061 : _height(height), _radius(radius), massPropertiesCached(false)
00062 {
00063 if (_radius<0) _radius=consts::epsilon;
00064 }
00065
00066 Cylinder::Cylinder(const Cylinder& c)
00067 : _height(c._height), _radius(c._radius), massPropertiesCached(false)
00068 {
00069 }
00070
00071 Cylinder::~Cylinder()
00072 {
00073 }
00074
00075
00076 const MassProperties& Cylinder::getMassProperties(ref<const Material> material) const
00077 {
00078 if (massPropertiesCached && (density == material->density()))
00079 return massProperties;
00080
00081 density = material->density();
00082 Real volume = consts::Pi*Math::sqr(_radius)*_height;
00083 massProperties.mass = volume*density;
00084
00085 const Real m = massProperties.mass;
00086 Matrix3 Ibody;
00087 Ibody.e(1,1) = m*Math::sqr(_radius)/4.0 + m*Math::sqr(_height)/12.0;
00088 Ibody.e(2,2) = Ibody.e(1,1);
00089 Ibody.e(3,3) = m*Math::sqr(_radius)/2.0;
00090
00091 massProperties.setIbody(Ibody);
00092 massProperties.centerOfMass = Point3(0.0,0.0,0.0);
00093
00094 massPropertiesCached = true;
00095 return massProperties;
00096 }
00097
00098
00099
00100 Segment3 Cylinder::shortestSegmentBetween(const base::Transform& t, const Point3& p) const
00101 {
00102 Unimplemented;
00103 }
00104
00105
00106 Segment3 Cylinder::shortestSegmentBetween(const base::Transform& t, const gfx::Segment3& s) const
00107 {
00108 Logln("Warning: Cylinder-Segment3 distance unimplemented");
00109 Point3 b(consts::maxInt, consts::maxInt, consts::maxInt);
00110 return Segment3(-b,b);
00111 }
00112
00113
00114 Segment3 Cylinder::shortestSegmentBetween(const base::Transform& t, const gfx::Triangle3& tri) const
00115 {
00116 Unimplemented;
00117 }
00118
00119
00120 Segment3 Cylinder::shortestSegmentBetween(const base::Transform& t, const gfx::Quad3& q) const
00121 {
00122 Unimplemented;
00123 }
00124
00125
00126 Segment3 Cylinder::shortestSegmentBetween(const base::Transform& t1, ref<const Shape> s, const base::Transform& t2) const
00127 {
00128 Unimplemented;
00129 }
00130
00131
00132
00133
00134 osg::Node* Cylinder::createOSGCylinder(Visual::Attributes visualAttributes,
00135 Int slices, Int stacks) const
00136 {
00137 bool onlyVerts = ((visualAttributes & Visual::VerticesOnly) != 0);
00138
00139 osg::ref_ptr<osg::ShapeDrawable> shapeDrawable = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.0f,0.0f,0.0f),radius(),height()));
00140 osg::ref_ptr<osg::TessellationHints> tessHints = new osg::TessellationHints();
00141 tessHints->setTargetNumFaces(slices*stacks);
00142 tessHints->setTessellationMode(osg::TessellationHints::USE_TARGET_NUM_FACES);
00143 tessHints->setCreateNormals(!onlyVerts);
00144 tessHints->setCreateTextureCoords(!onlyVerts);
00145 shapeDrawable->setTessellationHints(&(*tessHints));
00146
00147 osg::Geode* geode = new osg::Geode();
00148 geode->addDrawable(&(*shapeDrawable));
00149 return geode;
00150 }
00151
00152
00153
00154 osg::Node* Cylinder::createOSGVisual(Visual::Attributes visualAttributes) const
00155 {
00156 if ((node!=0) && (attributes==visualAttributes))
00157 return &(*node);
00158
00159 Real r = Math::maximum(0.5,radius());
00160 Real h = Math::maximum(1.0,height());
00161
00162 osg::Node* node0 = createOSGCylinder(visualAttributes, Int(52*r), (h<40)?Int(12*h):2000);
00163 osg::Node* node1 = createOSGCylinder(visualAttributes, Int(40*r), (h<40)?Int(8*h):1300);
00164 osg::Node* node2 = createOSGCylinder(visualAttributes, Int(20*r), (h<40)?Int(4*h):700);
00165 osg::Node* node3 = createOSGCylinder(visualAttributes, 8, 1);
00166
00167 osg::LOD* lod = new osg::LOD();
00168 lod->setName("Cylinder");
00169 lod->addChild(node0);
00170 lod->addChild(node1);
00171 lod->addChild(node2);
00172 lod->addChild(node3);
00173
00174 lod->setRange(0,0,2.0);
00175 lod->setRange(1,2.0,16.0);
00176 lod->setRange(2,16.0,120.0*Math::maximum(r,h));
00177 lod->setRange(3,120.0*Math::maximum(r,h),consts::Infinity);
00178
00179 if (!(visualAttributes & Visual::ShowAxes))
00180 node = lod;
00181 else {
00182 Group* group = new Group();
00183 group->addChild( lod );
00184 group->addChild( createOSGAxes(base::Dimension3(2.0*radius(),2.0*radius(),height())) );
00185 node = group;
00186 }
00187
00188 attributes = visualAttributes;
00189 return &(*node);
00190 }
00191
00192
00193
00194 base::ref<CollisionModel> Cylinder::getCollisionModel(CollisionModel::CollisionModelType modelType) const
00195 {
00196 if ((collisionModel!=0) &&
00197 ((this->modelType==modelType) || (modelType==CollisionModel::AnyModel)))
00198 return collisionModel;
00199
00200 collisionModel = Shape::getCollisionModel(modelType);
00201 this->modelType=modelType;
00202
00203 return collisionModel;
00204 }
00205
00206
00207 void Cylinder::serialize(base::Serializer& s)
00208 {
00209 s(_height)(_radius);
00210
00211 if (s.isInput()) {
00212 massPropertiesCached = false;
00213 node = 0;
00214 collisionModel = ref<CollisionModel>(0);
00215 }
00216 }
00217
00218
00219
00220 bool Cylinder::formatSupported(String format, Real version, ExternalizationType type) const
00221 {
00222 return ( (format=="xml") && (version==1.0) );
00223 }
00224
00225
00226 void Cylinder::externalize(base::Externalizer& e, String format, Real version)
00227 {
00228 if (format == "") format = "xml";
00229
00230 if (!formatSupported(format,version,e.ioType()))
00231 throw std::invalid_argument(Exception(String("format ")+format+" v"+base::realToString(version)+" unsupported"));
00232
00233 if (e.isOutput()) {
00234 Unimplemented;
00235 }
00236 else {
00237 Unimplemented;
00238 }
00239 }
00240
00241