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

physics/SimpleTerrain.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: SimpleTerrain.cpp 1031 2004-02-11 20:46:36Z jungd $
00019   $Revision: 1.2 $
00020   $Date: 2004-02-11 15:46:36 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <physics/SimpleTerrain>
00026 #include <physics/Material>
00027 #include <physics/OBBCollisionModel>
00028 
00029 #include <gfx/Tesselation>
00030 #include <gfx/Color3>
00031 #include <gfx/Triangle3>
00032 #include <base/array>
00033 
00034 using base::array;
00035 
00036 using gfx::Triangle3;
00037 using gfx::Color3;
00038 using gfx::Tesselation;
00039 
00040 using physics::SimpleTerrain;
00041 using physics::MassProperties;
00042 using physics::BoundingBox;
00043 using physics::BoundingSphere;
00044 using physics::CollisionModel;
00045 using physics::OBBCollisionModel;
00046 
00047 
00048 SimpleTerrain::SimpleTerrain(HeightField& heightfield) 
00049         : Terrain(heightfield), massPropertiesCached(false), tesselated(false),
00050                 collisionModelCached(false)
00051 {
00052 }
00053 
00054 SimpleTerrain::SimpleTerrain(const SimpleTerrain& t)
00055         : Terrain(t), massPropertiesCached(false), tesselated(false),
00056                 collisionModelCached(false)
00057 {
00058 }
00059 
00060 SimpleTerrain::~SimpleTerrain() 
00061 {
00062         if (tesselated) delete tesselation; 
00063         if (collisionModelCached) delete collisionModel;
00064 }
00065 
00066 
00067 Real& SimpleTerrain::height(Real x, Real y) throw(std::out_of_range)
00068 {
00069         return heightfield.height(x,y);
00070 }
00071 
00072 const Real& SimpleTerrain::height(Real x, Real y) const throw(std::out_of_range)
00073 {
00074         return heightfield.height(x,y);
00075 }
00076 
00077 
00078 
00079 BoundingBox SimpleTerrain::getBoundingBox() const
00080 {
00081         return BoundingBox();//!!!
00082 }
00083 
00084 BoundingSphere SimpleTerrain::getBoundingSphere() const
00085 {
00086         return BoundingSphere(); //!!!
00087 }
00088 
00089 
00090 const MassProperties& SimpleTerrain::getMassProperties(const Material& material) const
00091 {
00092   if (massPropertiesCached && (massProperties.density == material.density()))
00093     return massProperties;
00094 
00095   //!!! should we just make a mass properties that is infinite mass?
00096   // the c.o.m. is not at the origin anyway
00097   // (of cource, c.o.m. at origin and valid mass properties would be best)
00098   
00099   // ANS: No.  Don't use the terrain as a dynamic object in physics or
00100   //  it may cause instability.  Specifically make it a fixed object
00101 
00102   // construct mass property from Tesselatable 
00103   massProperties = MassProperties(*this, material);
00104   
00105   massPropertiesCached = true;
00106   return massProperties;
00107 }
00108 
00109 
00110 const Tesselation& SimpleTerrain::getTesselation(Int properties) const
00111 {
00112   if (tesselated) {
00113     if (properties == this->properties)  // same properties, used cached Tesselation
00114       return *tesselation; 
00115     else
00116       delete tesselation;  // different properties, re-tesselate
00117   }
00118   
00119   tesselation = new Tesselation();
00120   this->properties = properties;
00121   
00122   HeightField& hf(heightfield);
00123   
00124   //!!! texture coords. not yet implemented
00125   //!!! sides and bottom not yet implemented
00126   
00127   // First, build an array of vertices (one per height field sample)
00128   array<Point3> vertices(hf.nx()*hf.ny());
00129   SInt vi=0;
00130   for(Int yi=0; yi<hf.ny(); yi++)
00131     for(Int xi=0; xi<hf.nx(); xi++) {
00132       vertices[vi] = Point3(xi*hf.dx(), hf.height(xi,yi),hf.ysize()-yi*hf.dy());
00133       vi++;
00134     }
00135   
00136   // Now calulcate normals
00137   //  (inefficient! - compute the 8 triangles that share each vertex, and average
00138   //   their normals)
00139   array<Vector3> normals(hf.nx()*hf.ny());
00140   array<Triangle3> tri(8);
00141 #define vAt(xxi,yyi) ( (((xxi) < 0) || ((xxi) >= (SInt)hf.nx()) || ((yyi) < 0) || ((yyi) >= (SInt)hf.ny()))?\
00142   Point3((xxi)*hf.dx(),0.0,hf.ysize()-(yyi)*hf.dy()):(vertices[(yyi)*hf.nx()+(xxi)]) )
00143   
00144   if (properties & VertexNormals) {
00145     
00146     for(SInt yi=0; yi<(SInt)hf.ny(); yi++)
00147       for(SInt xi=0; xi<(SInt)hf.nx(); xi++) {
00148         tri[0].p1 = vAt(xi,yi); tri[0].p2 = vAt(xi+1,yi);   tri[0].p3 = vAt(xi+1,yi+1);
00149         tri[1].p1 = vAt(xi,yi); tri[1].p2 = vAt(xi+1,yi+1); tri[1].p3 = vAt(xi, yi+1);
00150         tri[2].p1 = vAt(xi,yi); tri[2].p2 = vAt(xi, yi+1);  tri[2].p3 = vAt(xi-1, yi+1);
00151         tri[3].p1 = vAt(xi,yi); tri[3].p2 = vAt(xi-1,yi+1); tri[3].p3 = vAt(xi-1,yi);
00152         tri[4].p1 = vAt(xi,yi); tri[4].p2 = vAt(xi-1,yi);   tri[4].p3 = vAt(xi-1,yi-1);
00153         tri[5].p1 = vAt(xi,yi); tri[5].p2 = vAt(xi-1,yi-1); tri[5].p3 = vAt(xi,yi-1);
00154         tri[6].p1 = vAt(xi,yi); tri[6].p2 = vAt(xi,yi-1);   tri[6].p3 = vAt(xi+1,yi-1);
00155         tri[7].p1 = vAt(xi,yi); tri[7].p2 = vAt(xi+1,yi-1); tri[7].p3 = vAt(xi+1,yi);
00156         
00157         // average normals
00158         Vector3 norm;
00159         for(Int t=0; t<8; t++) 
00160           norm += tri[t].normal();
00161         norm /= 8.0;
00162         
00163         normals[yi*hf.nx() + xi] = norm;
00164       }
00165   }
00166   
00167   array<Point3>  vertexArray( (hf.nx()-1)*(hf.ny()-1)*2*3 );
00168   array<Vector3> normalArray( (hf.nx()-1)*(hf.ny()-1)*2*3 );
00169   
00170   // Build vertex arrays
00171 #define nAt(xi,yi) normals[(yi)*hf.nx()+(xi)]
00172   SInt index=0;
00173   for(SInt xi=1; xi<(SInt)hf.nx(); xi++)
00174     for(SInt yi=1; yi<(SInt)hf.ny(); yi++) {
00175       vertexArray[index+2]   = vAt(xi, yi);
00176       vertexArray[index+1] = vAt(xi-1,yi-1);
00177       vertexArray[index] = vAt(xi-1, yi);
00178       if (properties & VertexNormals) {
00179         normalArray[index+2]   = nAt(xi,yi);
00180         normalArray[index+1] = nAt(xi-1,yi-1);
00181         normalArray[index] = nAt(xi-1,yi);
00182       }
00183       index+=3;
00184       
00185       vertexArray[index+2]   = vAt(xi-1, yi-1);
00186       vertexArray[index+1] = vAt(xi,yi);
00187       vertexArray[index] = vAt(xi, yi-1);
00188       if (properties & VertexNormals) {
00189         normalArray[index+2]   = nAt(xi-1,yi-1);
00190         normalArray[index+1] = nAt(xi,yi);
00191         normalArray[index] = nAt(xi,yi-1);
00192       }
00193       index+=3;
00194     }
00195   
00196   TriangleArray& terrainTris = *new TriangleArray(&vertexArray,0,
00197                                                   (properties & VertexNormals)?&normalArray:0,
00198                                                   0,0,false);
00199   
00200   tesselation->insert(terrainTris);
00201   tesselated=true;
00202 
00203   return *tesselation;
00204 }
00205 
00206 
00207 osg::GeoSet& SimpleTerrain::getGeoSet(Int properties=VertexNormals) const
00208 {
00209   return *new osg::GeoSet(); // implement!!!
00210 }
00211 
00212 
00213 CollisionModel& SimpleTerrain::getCollisionModel(CollisionModel::CollisionModelType modelType) const
00214 {
00215         if (collisionModelCached && 
00216                         ((this->modelType==modelType) || (modelType==CollisionModel::AnyModel)))
00217                 return *collisionModel;
00218         
00219         if (   (modelType == CollisionModel::OBBModel) 
00220                         || (modelType == CollisionModel::AnyModel)) {
00221                 if (collisionModelCached) delete collisionModel;
00222                 collisionModel = new OBBCollisionModel(*this);
00223                 this->modelType=modelType;
00224                 collisionModelCached=true;
00225                 return *collisionModel;
00226         }
00227         else
00228                 throw std::invalid_argument(Exception("CollisionModelType not supported"));
00229 }
00230 
00231  

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