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