00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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);
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
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));
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
00167
00168
00169
00170
00171
00172
00173 density = material->density();
00174
00175
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;
00221
00222
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
00234 base::ref<CollisionModel> LODTerrain::getCollisionModel(CollisionModel::CollisionModelType modelType) const
00235 {
00236
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