Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

physics/Shape.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Shape.cpp 1031 2004-02-11 20:46:36Z jungd $
00019   
00020 ****************************************************************************/
00021 
00022 #include <physics/Shape>
00023 
00024 #include <base/Externalizer>
00025 #include <base/externalization_error>
00026 #include <gfx/VisualTriangles>
00027 #include <physics/Box>
00028 #include <physics/Sphere>
00029 #include <physics/Cylinder>
00030 #include <physics/Capsule>
00031 #include <physics/Cone>
00032 #include <physics/Polyhedron>
00033 #include <physics/GJKCollisionModel>
00034 #include <physics/OBBCollisionModel>
00035 #include <physics/ODECollisionModel>
00036 
00037 
00038 #include <osg/Group>
00039 #include <osg/MatrixTransform>
00040 #include <osg/StateSet>
00041 #include <osg/Material>
00042 
00043 
00044 using physics::Shape;
00045 
00046 using base::Externalizer;
00047 using base::dom::DOMElement;
00048 using base::dom::DOMNode;
00049 using gfx::Visual;
00050 using gfx::VisualTriangles;
00051 using physics::Cylinder;
00052 using physics::CollisionModel;
00053 using physics::GJKCollisionModel;
00054 using physics::OBBCollisionModel;
00055 using physics::ODECollisionModel;
00056 
00057 using osg::Group;
00058 using osg::MatrixTransform;
00059 using osg::Vec3;
00060 using osg::Vec4;
00061 using osg::StateSet;
00062 
00063 
00064 base::ref<CollisionModel> Shape::getCollisionModel(CollisionModel::CollisionModelType modelType) const
00065 {
00066   if (modelType == CollisionModel::AnyModel)
00067     return ref<CollisionModel>(NewObj GJKCollisionModel(ref<const Shape>(this)));
00068 
00069   // Construct known CollisionModels from Shape or Visual
00070   //  (Shape preferred if possible)
00071 
00072   switch (modelType) {
00073   case CollisionModel::OBBModel: return getCollisionModelFromVisual(modelType); break;
00074   case CollisionModel::GJKModel: return ref<CollisionModel>(NewObj GJKCollisionModel(ref<const Shape>(this))); break;
00075   case CollisionModel::ODEModel: return ref<CollisionModel>(NewObj ODECollisionModel(ref<const Shape>(this))); break;
00076   default:
00077     throw std::invalid_argument(Exception("Collision modelType not supported"));
00078   }
00079 
00080 }
00081 
00082 
00083 base::ref<CollisionModel> Shape::getCollisionModelFromVisual(CollisionModel::CollisionModelType modelType) const
00084 {  
00085   if ((modelType == CollisionModel::GJKModel) 
00086       || (modelType == CollisionModel::AnyModel)) {
00087 
00088     Int LODChild = 0;
00089     switch (CollisionModel::getCollisionModelFidelity()) {
00090     case CollisionModel::Normal:   LODChild = 1; break;
00091     case CollisionModel::Fast:     LODChild = 3; break;
00092     case CollisionModel::Fastest:  LODChild = consts::maxInt; break;
00093     case CollisionModel::Accurate: LODChild = 0; break;
00094     default: ;
00095     }
00096 
00097     return ref<CollisionModel>(NewNamedObj("GJKCollisionModel") GJKCollisionModel(VisualTriangles(*this,LODChild)));
00098   }
00099   else
00100     throw std::invalid_argument(Exception("CollisionModelType not supported"));
00101 }
00102 
00103 
00104 
00105 
00106 osg::Node* Shape::createOSGAxes(const base::Dimension3& dim)
00107 {
00108   const Real s = 1.5;
00109   Real d = Math::minimum(0.06,Math::minimum(dim.x,dim.y,dim.z)/16.0);
00110 
00111   Group* g = NewObj Group;
00112   g->setName("debug");
00113 
00114   // color the axes X:red, Y:green and Z:blue, with white end cones
00115   StateSet* red = NewObj StateSet();
00116   osg::Material* rmat = NewObj osg::Material();
00117   Vec4 cred(1,0,0,1);
00118   //  mat->setEmission( osg::Material::FRONT_AND_BACK, Vec4(0,0,0,0) );
00119   //mat->setAmbient( osg::Material::FRONT_AND_BACK, col );
00120   rmat->setDiffuse( osg::Material::FRONT_AND_BACK, cred );
00121   rmat->setSpecular( osg::Material::FRONT_AND_BACK, Vec4(1,1,1,0) );
00122   rmat->setShininess( osg::Material::FRONT_AND_BACK, 1.0);
00123   red->setAttribute( rmat );
00124 
00125   StateSet* green = NewObj StateSet();
00126   osg::Material* gmat = NewObj osg::Material();
00127   Vec4 cgreen(0,1,0,1);
00128   //  mat->setEmission( osg::Material::FRONT_AND_BACK, Vec4(0,0,0,0) );
00129   //mat->setAmbient( osg::Material::FRONT_AND_BACK, col );
00130   gmat->setDiffuse( osg::Material::FRONT_AND_BACK, cgreen );
00131   gmat->setSpecular( osg::Material::FRONT_AND_BACK, Vec4(1,1,1,0) );
00132   gmat->setShininess( osg::Material::FRONT_AND_BACK, 1.0);
00133   green->setAttribute( gmat );
00134   
00135   StateSet* blue = NewObj StateSet();
00136   osg::Material* bmat = NewObj osg::Material();
00137   Vec4 cblue(0,0,1,1);
00138   //  mat->setEmission( osg::Material::FRONT_AND_BACK, Vec4(0,0,0,0) );
00139   //mat->setAmbient( osg::Material::FRONT_AND_BACK, col );
00140   bmat->setDiffuse( osg::Material::FRONT_AND_BACK, cblue );
00141   bmat->setSpecular( osg::Material::FRONT_AND_BACK, Vec4(1,1,1,0) );
00142   bmat->setShininess( osg::Material::FRONT_AND_BACK, 1.0);
00143   blue->setAttribute( bmat );
00144 
00145   StateSet* white = NewObj StateSet();
00146   osg::Material* wmat = NewObj osg::Material();
00147   Vec4 cwhite(1,1,1,1);
00148   //  mat->setEmission( osg::Material::FRONT_AND_BACK, Vec4(0,0,0,0) );
00149   //mat->setAmbient( osg::Material::FRONT_AND_BACK, col );
00150   wmat->setDiffuse( osg::Material::FRONT_AND_BACK, cwhite );
00151   wmat->setSpecular( osg::Material::FRONT_AND_BACK, Vec4(1,1,1,0) );
00152   wmat->setShininess( osg::Material::FRONT_AND_BACK, 1.0);
00153   white->setAttribute( wmat );
00154 
00155 
00156   // a long Clyinder for the axis and a cone-like cylinder 
00157   //  for the arrow head of each X,Y and Z.
00158 
00159   MatrixTransform* xrot = NewObj MatrixTransform();
00160   xrot->setMatrix(osg::Matrix::rotate(consts::Pi/2.0,Vec3(0,1,0)));
00161   xrot->postMult(osg::Matrix::translate(s*dim.x/4.0,0,0));
00162   g->addChild(xrot);
00163                 
00164   MatrixTransform* yrot = NewObj MatrixTransform();
00165   yrot->setMatrix(osg::Matrix::rotate(consts::Pi/2.0,Vec3(-1,0,0)));
00166   yrot->postMult(osg::Matrix::translate(0,s*dim.y/4.0,0));
00167   g->addChild(yrot);
00168                 
00169   MatrixTransform* zrot = NewObj MatrixTransform();
00170   zrot->setMatrix(osg::Matrix::translate(0,0,s*dim.z/4.0));
00171   g->addChild(zrot);
00172                 
00173   // the cylinder axes
00174   ref<Cylinder> xc(NewObj Cylinder(s*dim.x/2.0,d));
00175   xrot->addChild(xc->createOSGVisual());
00176   xrot->setStateSet(red);
00177 
00178   ref<Cylinder> yc(NewObj Cylinder(s*dim.y/2.0,d));
00179   yrot->addChild(yc->createOSGVisual());
00180   yrot->setStateSet(green);
00181 
00182   ref<Cylinder> zc(NewObj Cylinder(s*dim.z/2.0,d));
00183   zrot->addChild(zc->createOSGVisual());
00184   zrot->setStateSet(blue);
00185 
00186   // Translate each axis cone to the end
00187   MatrixTransform* xtrans = NewObj MatrixTransform();
00188   xtrans->setMatrix(osg::Matrix::translate(0,0,s*dim.x/4.0+d));
00189   xrot->addChild(xtrans);
00190   
00191   MatrixTransform* ytrans = NewObj MatrixTransform();
00192   ytrans->setMatrix(osg::Matrix::translate(0,0,s*dim.y/4.0+d));
00193   yrot->addChild(ytrans);
00194   
00195   MatrixTransform* ztrans = NewObj MatrixTransform();
00196   ztrans->setMatrix(osg::Matrix::translate(0,0,s*dim.z/4.0+d));
00197   zrot->addChild(ztrans);
00198   
00199   // the end cones
00200   ref<Cone> cone(NewObj Cone(4*d,2*d));
00201   osg::Node* coneNode = cone->createOSGVisual();
00202   coneNode->setStateSet(white);
00203   
00204   xtrans->addChild(coneNode);
00205   ytrans->addChild(coneNode);
00206   ztrans->addChild(coneNode);
00207 
00208   return g;
00209 }
00210 
00211 
00212 ref<Shape> Shape::createShapeFromInput(Externalizer& e, String format, Real version)
00213 {
00214   if (format=="") format="xml";
00215 
00216   if ((format != "xml") || (version!=1.0))  
00217     throw std::invalid_argument(Exception(String("format ")+format+" v"+base::realToString(version)+" unsupported"));
00218 
00219   DOMNode* context = e.context();
00220 
00221   DOMElement* shapeElem = e.getFirstChildElement(context, "box", false);
00222   if (shapeElem) { // its a Box
00223     ref<Box> box(NewObj Box());
00224     box->externalize(e, format, version);
00225     e.removeElement(shapeElem);
00226     return box;
00227   }
00228 
00229   shapeElem = e.getFirstChildElement(context, "sphere", false);
00230   if (shapeElem) { // its a Sphere
00231     ref<Sphere> sphere(NewObj Sphere());
00232     sphere->externalize(e, format, version);
00233     e.removeElement(shapeElem);
00234     return sphere;
00235   }
00236   
00237   shapeElem = e.getFirstChildElement(context, "capsule", false);
00238   if (shapeElem) { // its a Capsule
00239     ref<Capsule> capsule(NewObj Capsule());
00240     capsule->externalize(e, format, version);
00241     e.removeElement(shapeElem);
00242     return capsule;
00243   }
00244   
00245   shapeElem = e.getFirstChildElement(context, "cylinder", false);
00246   if (shapeElem) { // its a Cylinder
00247     ref<Cylinder> cylinder(NewObj Cylinder());
00248     cylinder->externalize(e, format, version);
00249     e.removeElement(shapeElem);
00250     return cylinder;
00251   }
00252   
00253   shapeElem = e.getFirstChildElement(context, "cone", false);
00254   if (shapeElem) { // its a Cone
00255     ref<Cone> cone(NewObj Cone());
00256     cone->externalize(e, format, version);
00257     e.removeElement(shapeElem);
00258     return cone;
00259   }
00260   
00261   shapeElem = e.getFirstChildElement(context, "polyhedron", false);
00262   if (shapeElem) { // its a Polyhedron
00263     ref<Polyhedron> polyhedron(NewObj Polyhedron());
00264     polyhedron->externalize(e, format, version);
00265     e.removeElement(shapeElem);
00266     return polyhedron;
00267   }
00268   
00269   throw base::externalization_error(Exception(String("unknown shape Element - must be one of Box, Sphere, Cylinder, Capsule, Cone or Polyhedron")));
00270 }
00271 

Generated on Thu Jul 29 15:56:29 2004 for OpenSim by doxygen 1.3.6