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

physics/LODTerrain.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: LODTerrain.cpp 1031 2004-02-11 20:46:36Z jungd $
00019  
00020 ****************************************************************************/
00021 
00022 #include <physics/LODTerrain>
00023 
00024 #include <base/Externalizer>
00025 #include <base/array>
00026 #include <base/File>
00027 
00028 #include <gfx/VisualTriangles>
00029 
00030 #include <physics/Material>
00031 #include <physics/OBBCollisionModel>
00032 #include <physics/GJKCollisionModel>
00033 
00034 #include <osg/Node>
00035 #include <osg/StateSet>
00036 #include <osg/Fog>
00037 
00038 
00039 using base::array;
00040 
00041 using gfx::Segment3;
00042 using gfx::CLODTerrainRenderer;
00043 using gfx::CLODTerrainDrawable;
00044 
00045 using physics::LODTerrain;
00046 using physics::MassProperties;
00047 using physics::BoundingBox;
00048 using physics::BoundingSphere;
00049 using physics::CollisionModel;
00050 using physics::OBBCollisionModel;
00051 using physics::GJKCollisionModel;
00052 
00053 
00054 LODTerrain::LODTerrain() 
00055   : massPropertiesCached(false), boundsCached(false)
00056 {
00057   shapeHasAppearance=true;
00058 }
00059 
00060 LODTerrain::LODTerrain(const LODTerrain& t)
00061   : Terrain(t), renderer(t.renderer), drawable(t.drawable),
00062     massPropertiesCached(false), boundsCached(false)
00063   
00064 {
00065   shapeHasAppearance=true;
00066 }
00067 
00068 LODTerrain::~LODTerrain() 
00069 {
00070 }
00071 
00072 
00073 void LODTerrain::loadMap(ref<base::VFile> mapfile) throw(std::invalid_argument, base::io_error)
00074 {
00075   if (instanceof(*mapfile,base::File)) {
00076     renderer = new CLODTerrainRenderer( const_cast<char*>(mapfile->pathName().str().c_str()), 40000); // fix 40000 !!!!
00077     renderer->SetDetailThreshold(25.0f);
00078     drawable = new CLODTerrainDrawable();
00079     drawable->SetTerrain(&(*renderer));
00080     boundsCached=massPropertiesCached=false;
00081   }
00082   else
00083     throw std::invalid_argument(Exception("Can only load from standard Unix files.  Sorry"));
00084   
00085 }
00086 
00087 void LODTerrain::loadHeightField(ref<HeightField> heightfield) throw(std::invalid_argument, base::io_error)
00088 {
00089   boundsCached=massPropertiesCached=false;
00090   throw new std::invalid_argument(Exception("not implemented"));
00091 }
00092 
00093 
00094 void LODTerrain::setHeight(Real x, Real y, Real h) throw(std::out_of_range)
00095 {
00096   if (renderer==0) throw new std::out_of_range(Exception("No terrain data loaded"));
00097 
00098   if ((x < 0) || (x > renderer->GetWidth()))
00099     throw new std::out_of_range(Exception("x out of range"));
00100 
00101   if ((y < 0) || (y > renderer->GetHeight()))
00102     throw new std::out_of_range(Exception("y out of range"));
00103 
00104   // implement !!!! need to add a set method to CLODTerrainRenderer (or a get index from x,y)
00105 }
00106 
00107 Real LODTerrain::getHeight(Real x, Real y) const throw(std::out_of_range)
00108 {
00109   if (renderer==0) throw new std::out_of_range(Exception("No terrain data loaded"));
00110 
00111   if ((x < 0) || (x > renderer->GetWidth()))
00112     throw new std::out_of_range(Exception("x out of range"));
00113 
00114   if ((y < 0) || (y > renderer->GetHeight()))
00115     throw new std::out_of_range(Exception("y out of range"));
00116 
00117   gfx::CLODTerrainRenderer* r = const_cast<gfx::CLODTerrainRenderer*>(&(*renderer));  // yuk!!!
00118   return r->GetElevation(x,y);
00119 }
00120 
00121 base::Dimension3 LODTerrain::getDimension() const
00122 {
00123   return boundingBox.getDimension();
00124 }
00125 
00126 BoundingBox LODTerrain::getBoundingBox() const
00127 {
00128   if (!boundsCached)
00129     computeBounds();
00130   return boundingBox;
00131 }
00132 
00133 BoundingSphere LODTerrain::getBoundingSphere() const
00134 {
00135   if (!boundsCached)
00136     computeBounds();
00137   return boundingSphere;
00138 }
00139 
00140 
00141 void LODTerrain::computeBounds() const
00142 {
00143   if (renderer!=0) {
00144     base::Dimension3 dim(base::Dimension3(renderer->GetWidth(),
00145                                           renderer->GetHeight(),renderer->GetMaxElevation()));
00146     boundingBox.setCenter(base::Point3());
00147     boundingBox.setDimension(dim);
00148     
00149     Real radius = Math::maximum(dim.x,dim.y,dim.z)/2.0;
00150     boundingSphere = BoundingSphere(base::Point3(), radius);
00151     
00152   }
00153   else {
00154     boundingBox = BoundingBox();
00155     boundingSphere = BoundingSphere();
00156   }
00157 
00158 }
00159 
00160 
00161 const MassProperties& LODTerrain::getMassProperties(ref<const Material> material) const
00162 {
00163   if (massPropertiesCached && (density == material->density()))
00164     return massProperties;
00165 
00166   //!!! should we just make a mass properties that is infinite mass?
00167   // the c.o.m. is not at the origin anyway
00168   // (of cource, c.o.m. at origin and valid mass properties would be best)
00169   
00170   // ANS: No.  Don't use the terrain as a dynamic object in physics or
00171   //  it may cause instability.  Specifically make it a fixed object
00172 
00173   density = material->density();
00174 
00175   // construct mass property from Tesselatable 
00176   massProperties = MassProperties(gfx::VisualTriangles(*this), material);
00177   
00178   massPropertiesCached = true;
00179   return massProperties;
00180 }
00181 
00182 
00183 Segment3 LODTerrain::shortestSegmentBetween(const base::Transform& t, const Point3& p) const
00184 {
00185   Unimplemented;
00186 }
00187 
00188 
00189 Segment3 LODTerrain::shortestSegmentBetween(const base::Transform& t, const gfx::Segment3& s) const
00190 {
00191   Unimplemented;
00192 }
00193 
00194 
00195 Segment3 LODTerrain::shortestSegmentBetween(const base::Transform& t, const gfx::Triangle3& tri) const
00196 {
00197   Unimplemented;
00198 }
00199 
00200 
00201 Segment3 LODTerrain::shortestSegmentBetween(const base::Transform& t, const gfx::Quad3& q) const
00202 {
00203   Unimplemented;
00204 }
00205 
00206 
00207 Segment3 LODTerrain::shortestSegmentBetween(const base::Transform& t1, ref<const Shape> s, const base::Transform& t2) const
00208 {
00209   Unimplemented;
00210 }
00211 
00212 
00213 
00214 
00215 osg::Node* LODTerrain::createOSGVisual(Attributes visualAttributes) const
00216 {
00217   if ((node!=0) && (visualAttributes==attributes))
00218     return &(*node);
00219 
00220   if (renderer==0) return new osg::Node; // no terrain loaded
00221 
00222   // Create a osg::Geode and add the drawable to it
00223   osg::Geode* geode = new osg::Geode();
00224   geode->setName("LODTerrain");
00225   geode->addDrawable( const_cast<gfx::CLODTerrainDrawable*>(&(*drawable)) ); // !!!
00226 
00227   node = geode;
00228 
00229   return &(*node);
00230 }
00231 
00232 
00233 // Collidable
00234 base::ref<CollisionModel> LODTerrain::getCollisionModel(CollisionModel::CollisionModelType modelType) const
00235 {
00236   //!!!  throw std::runtime_error(Exception("not implemented")); 
00237   if ((collisionModel!=0) && 
00238       ((this->modelType==modelType) || (modelType==CollisionModel::AnyModel)))
00239     return collisionModel;
00240 
00241   collisionModel = Shape::getCollisionModel(modelType);
00242   this->modelType=modelType;
00243 
00244   return collisionModel;
00245 }
00246 
00247 
00248  
00249 void LODTerrain::serialize(base::Serializer& s)
00250 {
00251   throw std::runtime_error(Exception("unimplemented"));
00252 }
00253 
00254 
00255 
00256 bool LODTerrain::formatSupported(String format, Real version, ExternalizationType type) const
00257 { 
00258   return ( (format=="xml") && (version==1.0) ); 
00259 }
00260 
00261 
00262 void LODTerrain::externalize(base::Externalizer& e, String format, Real version)
00263 {
00264   if (format == "") format = "xml";
00265                                                                                                                                                                                                     
00266   if (!formatSupported(format,version,e.ioType()))
00267     throw std::invalid_argument(Exception(String("format ")+format+" v"+base::realToString(version)+" unsupported"));
00268                                                                                                                                                                                                     
00269   if (e.isOutput()) {
00270     Unimplemented;                                                                                                                                                                                                 
00271   }
00272   else {
00273     Unimplemented;                                                                                                                                                                                                 
00274   }
00275 }
00276 
00277 

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