// FIXME: make sure the pos.lat/pos.lon values are in degrees ...
double alt;
- if (globals->get_scenery()->get_elevation_m(pos.lat(), pos.lon(), 20000.0, alt))
+ if (globals->get_scenery()->get_elevation_m(pos.lat(), pos.lon(), 20000.0, alt, 0))
tgt_altitude = alt * SG_METER_TO_FEET;
//cerr << "Target altitude : " << tgt_altitude << endl;
// FIXME: make shure the pos.lat/pos.lon values are in degrees ...
double alt;
- if (globals->get_scenery()->get_elevation_m(lat, lon, 20000.0, alt))
+ if (globals->get_scenery()->get_elevation_m(lat, lon, 20000.0, alt, 0))
_aip.getSGLocation()->set_cur_elev_m(alt);
}
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/scene/model/placement.hxx>
+#include <simgear/scene/material/mat.hxx>
#include <simgear/timing/timestamp.hxx>
#include <Scenery/scenery.hxx>
return dist*SG_METER_TO_FEET;
}
+// Legacy interface just kept because of JSBSim
bool
FGInterface::get_agl_m(double t, const double pt[3],
double contact[3], double normal[3], double vel[3],
int *type, double *loadCapacity,
double *frictionFactor, double *agl)
{
- return ground_cache.get_agl(t, pt, 2.0, contact, normal, vel, type,
- loadCapacity, frictionFactor, agl);
+ const SGMaterial* material;
+ bool ret = ground_cache.get_agl(t, pt, 2.0, contact, normal, vel, type,
+ &material, agl);
+ if (material) {
+ *loadCapacity = material->get_load_resistence();
+ *frictionFactor = material->get_friction_factor();
+
+ } else {
+ *loadCapacity = DBL_MAX;
+ *frictionFactor = 1.0;
+ }
+ return ret;
}
+// Legacy interface just kept because of JSBSim
bool
FGInterface::get_agl_ft(double t, const double pt[3],
double contact[3], double normal[3], double vel[3],
// Convert units and do the real work.
sgdVec3 pt_m;
sgdScaleVec3( pt_m, pt, SG_FEET_TO_METER );
+
+ const SGMaterial* material;
bool ret = ground_cache.get_agl(t, pt_m, 2.0, contact, normal, vel,
- type, loadCapacity, frictionFactor, agl);
+ type, &material, agl);
// Convert units back ...
sgdScaleVec3( contact, SG_METER_TO_FEET );
sgdScaleVec3( vel, SG_METER_TO_FEET );
*agl *= SG_METER_TO_FEET;
- // FIXME: scale the load limit to something in the english unit system.
- // Be careful with the DBL_MAX which is returned by default.
+
+ // return material properties if available
+ if (material) {
+ // FIXME: convert units?? now pascal to lbf/ft^2
+ *loadCapacity = 0.020885434*material->get_load_resistence();
+ *frictionFactor = material->get_friction_factor();
+ } else {
+ *loadCapacity = DBL_MAX;
+ *frictionFactor = 1.0;
+ }
return ret;
}
bool
FGInterface::get_agl_m(double t, const double pt[3], double max_altoff,
double contact[3], double normal[3], double vel[3],
- int *type, double *loadCapacity,
- double *frictionFactor, double *agl)
+ int *type, const SGMaterial** material, double *agl)
{
return ground_cache.get_agl(t, pt, max_altoff, contact, normal, vel, type,
- loadCapacity, frictionFactor, agl);
+ material, agl);
}
bool
FGInterface::get_agl_ft(double t, const double pt[3], double max_altoff,
double contact[3], double normal[3], double vel[3],
- int *type, double *loadCapacity,
- double *frictionFactor, double *agl)
+ int *type, const SGMaterial** material, double *agl)
{
// Convert units and do the real work.
sgdVec3 pt_m;
sgdScaleVec3( pt_m, pt, SG_FEET_TO_METER );
bool ret = ground_cache.get_agl(t, pt_m, SG_FEET_TO_METER * max_altoff,
contact, normal, vel,
- type, loadCapacity, frictionFactor, agl);
+ type, material, agl);
// Convert units back ...
sgdScaleVec3( contact, SG_METER_TO_FEET );
sgdScaleVec3( vel, SG_METER_TO_FEET );
*agl *= SG_METER_TO_FEET;
- // FIXME: scale the load limit to something in the english unit system.
- // Be careful with the DBL_MAX which is returned by default.
return ret;
}
}
}
- double contact[3], normal[3], vel[3], lc, ff, agl;
+ double contact[3], normal[3], vel[3], agl;
int type;
// Ignore the return value here, since it just tells us if
// the returns stem from the groundcache or from the coarse
// computations below the groundcache. The contact point is still something
// valid, the normals and the other returns just contain some defaults.
- get_agl_m(ref_time, pos, 2.0, contact, normal, vel, &type, &lc, &ff, &agl);
+ get_agl_m(ref_time, pos, 2.0, contact, normal, vel, &type, 0, &agl);
Point3D geodPos = sgCartToGeod(Point3D(contact[0], contact[1], contact[2]));
return geodPos.elev();
}
enum GroundType {
Unknown = 0, //??
Solid, // Whatever we will roll on with infinite load factor.
- Forest, // Ground unsuitable for taxiing.
Water, // For the beaver ...
Catapult, // Carrier cats.
Wire // Carrier wires.
double contact[3], double normal[3], double vel[3],
int *type, double *loadCapacity,
double *frictionFactor, double *agl);
+
+ // Return the altitude above ground below the wgs84 point pt
+ // Search for the nearest triangle to pt.
+ // Return ground properties like the ground type, a pointer to the
+ // material and finally the altitude above ground.
bool get_agl_m(double t, const double pt[3], double max_altoff,
double contact[3], double normal[3], double vel[3],
- int *type, double *loadCapacity,
- double *frictionFactor, double *agl);
+ int *type, const SGMaterial** material, double *agl);
bool get_agl_ft(double t, const double pt[3], double max_altoff,
double contact[3], double normal[3], double vel[3],
- int *type, double *loadCapacity,
- double *frictionFactor, double *agl);
+ int *type, const SGMaterial** material, double *agl);
double get_groundlevel_m(double lat, double lon, double alt);
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/scene/material/mat.hxx>
+#include <simgear/scene/material/matlib.hxx>
#include <Main/globals.hxx>
#include <Scenery/scenery.hxx>
}
else {
-
// Initialize velocity field.
sgdSetVec3( gp.vel, 0.0, 0.0, 0.0 );
sgdSetVec3( gp.rot, 0.0, 0.0, 0.0 );
sgdSetVec3( gp.pivot, 0.0, 0.0, 0.0 );
- }
-
- // Get the texture name and decide what ground type we have.
- ssgState *st = l->getState();
- if (st != NULL && st->isAKindOf(ssgTypeSimpleState())) {
- ssgSimpleState *ss = (ssgSimpleState*)st;
- SGPath fullPath( ss->getTextureFilename() ? ss->getTextureFilename(): "" );
- string file = fullPath.file();
- SGPath dirPath(fullPath.dir());
- string category = dirPath.file();
-
- if (category == "Runway")
- gp.type = FGInterface::Solid;
- else {
- if (file == "asphault.rgb" || file == "airport.rgb")
- gp.type = FGInterface::Solid;
- else if (file == "water.rgb" || file == "water-lake.rgb")
- gp.type = FGInterface::Water;
- else if (file == "forest.rgb" || file == "cropwood.rgb")
- gp.type = FGInterface::Forest;
- }
+
+ // get some material information for use in the gear model
+ gp.material = globals->get_matlib()->findMaterial(l);
+ if (gp.material)
+ gp.type = gp.material->get_solid() ? FGInterface::Solid : FGInterface::Water;
}
return gp;
for (int i = 0; i < nt; ++i) {
Triangle t;
t.sphere.empty();
+ t.material = gp.material;
short v[3];
l->getTriangle(i, &v[0], &v[1], &v[2]);
for (int k = 0; k < 3; ++k) {
sgdCopyVec3(dst.rotation_pivot, src.rotation_pivot);
dst.type = src.type;
+ dst.material = src.material;
if (dt*sgdLengthSquaredVec3(src.velocity) != 0) {
sgdVec3 pivotoff, vel;
bool
FGGroundCache::get_agl(double t, const double dpt[3], double max_altoff,
double contact[3], double normal[3], double vel[3],
- int *type, double *loadCapacity,
- double *frictionFactor, double *agl)
+ int *type, const SGMaterial** material, double *agl)
{
bool ret = false;
*type = FGInterface::Unknown;
// *agl = 0.0;
- *loadCapacity = DBL_MAX;
- *frictionFactor = 1.0;
+ if (material)
+ *material = 0;
sgdSetVec3( vel, 0.0, 0.0, 0.0 );
sgdSetVec3( contact, 0.0, 0.0, 0.0 );
sgdSetVec3( normal, 0.0, 0.0, 0.0 );
sgdAddVec3(vel, triangle.velocity);
// Save the ground type.
*type = triangle.type;
- // FIXME: figure out how to get that sign ...
-// *agl = sqrt(sqdist);
- *agl = sgdLengthVec3( dpt ) - sgdLengthVec3( contact );
-// *loadCapacity = DBL_MAX;
-// *frictionFactor = 1.0;
+ sgdVec3 dstToContact;
+ sgdSubVec3(dstToContact, contact, dpt);
+ *agl = sgdScalarProductVec3(dir, dstToContact);
+ if (material)
+ *material = triangle.material;
}
}
}
// The altitude is the distance of the requested point from the
// contact point.
- *agl = sgdLengthVec3( dpt ) - sgdLengthVec3( contact );
+ sgdVec3 dstToContact;
+ sgdSubVec3(dstToContact, contact, dpt);
+ *agl = sgdScalarProductVec3(dir, dstToContact);
*type = FGInterface::Unknown;
- *loadCapacity = DBL_MAX;
- *frictionFactor = 1.0;
return ret;
}
#include <simgear/compiler.h>
#include <simgear/constants.h>
+class SGMaterial;
+
class FGGroundCache {
public:
FGGroundCache();
// and finally the altitude above ground.
bool get_agl(double t, const double pt[3], double max_altoff,
double contact[3], double normal[3], double vel[3],
- int *type, double *loadCapacity,
- double *frictionFactor, double *agl);
+ int *type, const SGMaterial** material, double *agl);
// Return 1 if the hook intersects with a wire.
// That test is done by checking if the quad spanned by the points pt*
private:
struct Triangle {
+ Triangle() : material(0) {}
// The edge vertices.
sgdVec3 vertices[3];
// The surface normal.
sgdVec3 rotation_pivot;
// Ground type
int type;
+ // the simgear material reference, contains friction coeficients ...
+ const SGMaterial* material;
};
struct Catapult {
sgdVec3 start;
// Helper class to hold some properties of the ground triangle.
struct GroundProperty {
- GroundProperty() : type(0) {}
+ GroundProperty() : type(0), material(0) {}
int type;
int wire_id;
sgdVec3 vel;
sgdVec3 rot;
sgdVec3 pivot;
- // not yet implemented ...
-// double loadCapacity;
+ const SGMaterial* material;
};
// compute the ground property of this leaf.
} else {
// Do full intersection test.
double lev;
- if (globals->get_scenery()->get_elevation_m(lat, lon, alt+2, lev))
+ if (globals->get_scenery()->get_elevation_m(lat, lon, alt+2, lev, 0))
view_location->set_cur_elev_m( lev );
else
view_location->set_cur_elev_m( -9999.0 );
// returned results are in meters
bool fgCurrentElev( sgdVec3 abs_view_pos, double max_alt_m,
sgdVec3 scenery_center,
- ssgTransform *terra_transform,
+ ssgBranch *branch,
FGHitList *hit_list,
double *terrain_elev, double *radius, double *normal,
int & this_hit )
sgMat4 fxform;
sgMakeIdentMat4 ( fxform ) ;
- ssgGetEntityTransform( terra_transform, fxform );
+ ssgGetEntityTransform( branch, fxform );
sgdMat4 xform;
sgdSetMat4(xform,fxform);
- hit_list->Intersect( terra_transform, xform, orig, dir );
+ hit_list->Intersect( branch, xform, orig, dir );
this_hit = -1;
int max_hit = -1;
bool fgCurrentElev( sgdVec3 abs_view_pos,
double max_alt_m,
sgdVec3 scenery_center,
- ssgTransform *terra_transform,
+ ssgBranch *branch,
FGHitList *hit_list,
double *terrain_elev,
double *radius,
bool
FGScenery::get_elevation_m(double lat, double lon, double max_alt,
- double& alt, bool exact)
+ double& alt, const SGMaterial** material,
+ bool exact)
{
-// std::cout << __PRETTY_FUNCTION__ << " "
-// << lat << " "
-// << lon << " "
-// << max_alt
-// << std::endl;
sgdVec3 pos;
sgGeodToCart(lat*SG_DEGREES_TO_RADIANS, lon*SG_DEGREES_TO_RADIANS,
max_alt, pos);
- return get_cart_elevation_m(pos, 0, alt, exact);
-}
-
-bool
-FGScenery::get_material_m(double lat, double lon, double max_alt,
- double& alt, string & material, bool exact)
-{
- sgdVec3 pos;
- sgGeodToCart(lat*SG_DEGREES_TO_RADIANS, lon*SG_DEGREES_TO_RADIANS,
- max_alt, pos);
-
- return get_cart_material_m(pos, 0, alt, material, exact);
+ return get_cart_elevation_m(pos, 0, alt, material, exact);
}
bool
FGScenery::get_cart_elevation_m(const sgdVec3& pos, double max_altoff,
- double& alt, bool exact)
+ double& alt, const SGMaterial** material,
+ bool exact)
{
Point3D saved_center = center;
bool replaced_center = false;
// scenery center has been properly defined so any hit should
// be valid (and not just luck)
hit = fgCurrentElev(ncpos, max_altoff+sgdLengthVec3(pos),
- sc, (ssgTransform*)get_scene_graph(),
+ sc, get_scene_graph(),
&hit_list, &alt, &hit_radius, hit_normal, this_hit);
- }
- if (replaced_center)
- set_center( saved_center );
-
- return hit;
-}
-
-bool
-FGScenery::get_cart_material_m(const sgdVec3& pos, double max_altoff,
- double& alt, string& material, bool exact)
-{
- Point3D saved_center = center;
- bool replaced_center = false;
- if (exact) {
- Point3D ppos(pos[0], pos[1], pos[2]);
- if (30.0*30.0 < ppos.distance3Dsquared(center)) {
- set_center( ppos );
- replaced_center = true;
- }
- }
-
- material = "";
-
- // overridden with actual values if a terrain intersection is
- // found
- int this_hit;
- double hit_radius = 0.0;
- sgdVec3 hit_normal = { 0.0, 0.0, 0.0 };
-
- bool hit = false;
- if ( fabs(pos[0]) > 1.0 || fabs(pos[1]) > 1.0 || fabs(pos[2]) > 1.0 ) {
- sgdVec3 sc;
- sgdSetVec3(sc, center[0], center[1], center[2]);
-
- sgdVec3 ncpos;
- sgdCopyVec3(ncpos, pos);
-
- FGHitList hit_list;
-
- // scenery center has been properly defined so any hit should
- // be valid (and not just luck)
- hit = fgCurrentElev(ncpos, max_altoff+sgdLengthVec3(pos),
- sc, (ssgTransform*)get_scene_graph(),
- &hit_list, &alt, &hit_radius, hit_normal,
- this_hit );
-
- if( hit )
- {
- ssgEntity *entity = hit_list.get_entity( this_hit );
-
- if( entity != NULL && entity->isAKindOf(ssgTypeLeaf()) )
- {
- ssgLeaf *leaf = (ssgLeaf*) hit_list.get_entity( this_hit );
- ssgState *st = leaf->getState();
-
- if( st != NULL && st->isAKindOf(ssgTypeSimpleState()) )
- {
- ssgSimpleState *ss = (ssgSimpleState *) st;
-
- if( !globals->get_matlib()->find( ss, material ) )
- {
- material = "not-in-matlib";
- }
- }
- }
- }
- else
- {
- material = "no-hit";
+ if (material) {
+ *material = 0;
+ if (hit) {
+ ssgEntity *entity = hit_list.get_entity( this_hit );
+ if (entity && entity->isAKindOf(ssgTypeLeaf())) {
+ ssgLeaf* leaf = static_cast<ssgLeaf*>(entity);
+ *material = globals->get_matlib()->findMaterial(leaf);
+ }
+ }
}
}
return hit;
}
-
bool
FGScenery::get_cart_ground_intersection(const sgdVec3& pos,
const sgdVec3& dir,
class ssgRoot;
class ssgBranch;
+class SGMaterial;
// Define a structure containing global scenery parameters
/// value is undefined.
/// All values are meant to be in meters or degrees.
bool get_elevation_m(double lat, double lon, double max_alt,
- double& alt, bool exact = false);
- bool get_material_m(double lat, double lon, double max_alt,
- double& alt, string & material, bool exact = false);
+ double& alt, const SGMaterial** material,
+ bool exact = false);
/// Compute the elevation of the scenery beow the cartesian point pos.
/// you the returned scenery altitude is not higher than the position
/// value is undefined.
/// All values are meant to be in meters.
bool get_cart_elevation_m(const sgdVec3& pos, double max_altoff,
- double& radius, bool exact = false);
- bool get_cart_material_m(const sgdVec3& pos, double max_altoff,
- double& radius, string& material, bool exact = false);
+ double& radius, const SGMaterial** material,
+ bool exact = false);
/// Compute the nearest intersection point of the line starting from
/// start going in direction dir with the terrain.