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/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
00096
00097
00098
00099
00100
00101
00102
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)
00114 return *tesselation;
00115 else
00116 delete tesselation;
00117 }
00118
00119 tesselation = new Tesselation();
00120 this->properties = properties;
00121
00122 HeightField& hf(heightfield);
00123
00124
00125
00126
00127
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
00137
00138
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
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
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();
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