1
0
Fork 0

Shuffled around and restructured the terrain elevation interesection code

to make it usable by the threaded tile loader for placing objects at ground
level at load time.
This commit is contained in:
curt 2001-07-11 15:51:21 +00:00
parent bc4859c0fb
commit 4b23576df1
4 changed files with 100 additions and 80 deletions

View file

@ -14,11 +14,19 @@
#include <simgear/constants.h>
#include <simgear/sg_inlines.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/point3d.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/vector.hxx>
#include <Main/globals.hxx>
#include "hitlist.hxx"
extern ssgBranch *terrain;
// check to see if the intersection point is
// actually inside this face
static bool sgdPointInTriangle( sgdVec3 point, sgdVec3 tri[3] )
@ -304,3 +312,78 @@ void FGHitList::IntersectCachedLeaf( sgdMat4 m,
}
}
}
static void CurrentNormalInLocalPlane(sgVec3 dst, sgVec3 src) {
sgVec3 tmp;
sgSetVec3(tmp, src[0], src[1], src[2] );
sgMat4 TMP;
sgTransposeNegateMat4 ( TMP, globals->get_current_view()->get_UP() ) ;
sgXformVec3(tmp, tmp, TMP);
sgSetVec3(dst, tmp[2], tmp[1], tmp[0] );
}
// a temporary hack until we get everything rewritten with sgdVec3
static inline Point3D operator + (const Point3D& a, const sgdVec3 b)
{
return Point3D(a.x()+b[0], a.y()+b[1], a.z()+b[2]);
}
// Determine scenery altitude via ssg. Normally this just happens
// when we render the scene, but we'd also like to be able to do this
// explicitely. lat & lon are in radians. view_pos in current world
// coordinate translated near (0,0,0) (in meters.) Returns result in
// meters.
bool fgCurrentElev( sgdVec3 abs_view_pos, sgdVec3 scenery_center,
FGHitList *hit_list,
double *terrain_elev, double *radius, double *normal)
{
sgdVec3 view_pos;
sgdSubVec3( view_pos, abs_view_pos, scenery_center );
sgdVec3 orig, dir;
sgdCopyVec3(orig, view_pos );
sgdCopyVec3(dir, abs_view_pos );
hit_list->Intersect( terrain, orig, dir );
int this_hit=0;
Point3D geoc;
double result = -9999;
Point3D sc(scenery_center[0], scenery_center[1], scenery_center[2]) ;
int hitcount = hit_list->num_hits();
for ( int i = 0; i < hitcount; ++i ) {
geoc = sgCartToPolar3d( sc + hit_list->get_point(i) );
double lat_geod, alt, sea_level_r;
sgGeocToGeod(geoc.lat(), geoc.radius(), &lat_geod,
&alt, &sea_level_r);
if ( alt > result && alt < 10000 ) {
result = alt;
this_hit = i;
}
}
if ( result > -9000 ) {
*terrain_elev = result;
*radius = geoc.radius();
sgVec3 tmp;
sgSetVec3(tmp, hit_list->get_normal(this_hit));
// cout << "cur_normal: " << tmp[0] << " " << tmp[1] << " "
// << tmp[2] << endl;
/* ssgState *IntersectedLeafState =
((ssgLeaf*)hit_list->get_entity(this_hit))->getState(); */
CurrentNormalInLocalPlane(tmp, tmp);
sgdSetVec3( normal, tmp );
// cout << "NED: " << tmp[0] << " " << tmp[1] << " " << tmp[2] << endl;
return true;
} else {
SG_LOG( SG_TERRAIN, SG_INFO, "no terrain intersection" );
*terrain_elev = 0.0;
float *up = globals->get_current_view()->get_world_up();
sgdSetVec3(normal, up[0], up[1], up[2]);
return false;
}
}

View file

@ -93,4 +93,13 @@ inline void FGHitList::Intersect( ssgBranch *scene,
}
}
// Associated function, assuming a wgs84 world with 0,0,0 at the
// center, find the current terrain intersection elevation for the
// point specified.
bool fgCurrentElev( sgdVec3 abs_view_pos, sgdVec3 scenery_center,
FGHitList *hit_list,
double *terrain_elev, double *radius, double *normal );
#endif // _HITLIST_HXX

View file

@ -63,12 +63,6 @@ extern ssgBranch *ground;
FGTileMgr global_tile_mgr;
// a temporary hack until we get everything rewritten with sgdVec3
static inline Point3D operator + (const Point3D& a, const sgdVec3 b)
{
return Point3D(a.x()+b[0], a.y()+b[1], a.z()+b[2]);
}
#ifdef ENABLE_THREADS
SGLockedQueue<FGTileEntry *> FGTileMgr::attach_queue;
SGLockedQueue<FGDeferredModel *> FGTileMgr::model_queue;
@ -153,72 +147,6 @@ void FGTileMgr::sched_tile( const SGBucket& b ) {
}
static void CurrentNormalInLocalPlane(sgVec3 dst, sgVec3 src) {
sgVec3 tmp;
sgSetVec3(tmp, src[0], src[1], src[2] );
sgMat4 TMP;
sgTransposeNegateMat4 ( TMP, globals->get_current_view()->get_UP() ) ;
sgXformVec3(tmp, tmp, TMP);
sgSetVec3(dst, tmp[2], tmp[1], tmp[0] );
}
// Determine scenery altitude via ssg. Normally this just happens
// when we render the scene, but we'd also like to be able to do this
// explicitely. lat & lon are in radians. view_pos in current world
// coordinate translated near (0,0,0) (in meters.) Returns result in
// meters.
bool FGTileMgr::current_elev_ssg( sgdVec3 abs_view_pos, double *terrain_elev ) {
sgdVec3 view_pos;
sgdVec3 sc;
sgdSetVec3( sc, scenery.center.x(), scenery.center.y(), scenery.center.z());
sgdSubVec3( view_pos, abs_view_pos, sc );
sgdVec3 orig, dir;
sgdCopyVec3(orig, view_pos );
sgdCopyVec3(dir, abs_view_pos );
hit_list.Intersect( terrain, orig, dir );
int this_hit=0;
Point3D geoc;
double result = -9999;
int hitcount = hit_list.num_hits();
for ( int i = 0; i < hitcount; ++i ) {
geoc = sgCartToPolar3d( scenery.center + hit_list.get_point(i) );
double lat_geod, alt, sea_level_r;
sgGeocToGeod(geoc.lat(), geoc.radius(), &lat_geod,
&alt, &sea_level_r);
if ( alt > result && alt < 10000 ) {
result = alt;
this_hit = i;
}
}
if ( result > -9000 ) {
*terrain_elev = result;
scenery.cur_radius = geoc.radius();
sgVec3 tmp;
sgSetVec3(tmp, hit_list.get_normal(this_hit));
// cout << "cur_normal: " << tmp[0] << " " << tmp[1] << " "
// << tmp[2] << endl;
/* ssgState *IntersectedLeafState =
((ssgLeaf*)hit_list.get_entity(this_hit))->getState(); */
CurrentNormalInLocalPlane(tmp, tmp);
sgdSetVec3( scenery.cur_normal, tmp );
// cout << "NED: " << tmp[0] << " " << tmp[1] << " " << tmp[2] << endl;
return true;
} else {
SG_LOG( SG_TERRAIN, SG_INFO, "no terrain intersection" );
*terrain_elev = 0.0;
float *up = globals->get_current_view()->get_world_up();
sgdSetVec3(scenery.cur_normal, up[0], up[1], up[2]);
return false;
}
}
// schedule a needed buckets for loading
void FGTileMgr::schedule_needed() {
#ifndef FG_OLD_WEATHER
@ -401,6 +329,8 @@ int FGTileMgr::update( double lon, double lat ) {
}
}
counter_hack = (counter_hack + 1) % 5;
sgdVec3 sc;
sgdSetVec3( sc, scenery.center[0], scenery.center[1], scenery.center[2] );
if ( scenery.center == Point3D(0.0) ) {
// initializing
@ -419,7 +349,9 @@ int FGTileMgr::update( double lon, double lat ) {
prep_ssg_nodes();
sgSetVec3( tmp_view_pos, 0.0, 0.0, 0.0 );
double tmp_elev;
if ( current_elev_ssg(tmp_abs_view_pos, &tmp_elev) ) {
if ( fgCurrentElev(tmp_abs_view_pos, sc, &hit_list,
&tmp_elev, &scenery.cur_radius, scenery.cur_normal) )
{
scenery.cur_elev = tmp_elev;
} else {
scenery.cur_elev = 0.0;
@ -429,8 +361,9 @@ int FGTileMgr::update( double lon, double lat ) {
// cout << "abs view pos = " << current_view.abs_view_pos
// << " view pos = " << current_view.view_pos << endl;
double tmp_elev;
if ( current_elev_ssg(globals->get_current_view()->get_abs_view_pos(),
&tmp_elev) )
if ( fgCurrentElev(globals->get_current_view()->get_abs_view_pos(),
sc, &hit_list,
&tmp_elev, &scenery.cur_radius, scenery.cur_normal) )
{
scenery.cur_elev = tmp_elev;
} else {

View file

@ -81,10 +81,6 @@ private:
// see comment at prep_ssg_nodes()
void prep_ssg_node( int idx );
// int hitcount;
// sgdVec3 hit_pts [ MAX_HITS ] ;
// ssgEntity *last_hit;
FGHitList hit_list;
SGBucket previous_bucket;
@ -177,7 +173,6 @@ public:
const sgdVec3 p, const sgdVec3 dir,
FGHitList *list );
bool current_elev_ssg( sgdVec3 abs_view_pos, double *terrain_elev );
// Prepare the ssg nodes ... for each tile, set it's proper
// transform and update it's range selector based on current