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:
parent
bc4859c0fb
commit
4b23576df1
4 changed files with 100 additions and 80 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue