1
0
Fork 0
flightgear/src/Scenery/tileentry.cxx

232 lines
6.1 KiB
C++
Raw Normal View History

// tile.cxx -- routines to handle a scenery tile
//
// Written by Curtis Olson, started May 1998.
//
// Copyright (C) 1998, 1999 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
2000-02-15 03:30:01 +00:00
#include <simgear/compiler.h>
#ifdef FG_MATH_EXCEPTION_CLASH
# include <math.h>
#endif
#include STL_FUNCTIONAL
#include STL_ALGORITHM
2000-02-16 23:01:03 +00:00
#include <simgear/bucket/newbucket.hxx>
#include <simgear/debug/logstream.hxx>
#include <Aircraft/aircraft.hxx>
#include <Include/general.hxx>
#include <Main/globals.hxx>
#include <Scenery/scenery.hxx>
#include <Time/light.hxx>
#include "tileentry.hxx"
FG_USING_STD(for_each);
FG_USING_STD(mem_fun_ref);
// Constructor
FGTileEntry::FGTileEntry ()
: ncount(0)
{
nodes.clear();
}
// Destructor
FGTileEntry::~FGTileEntry () {
// cout << "nodes = " << nodes.size() << endl;;
// delete[] nodes;
}
// recurse an ssg tree and call removeKid() on every node from the
// bottom up. Leaves the original branch in existance, but empty so
// it can be removed by the calling routine.
static void my_remove_branch( ssgBranch * branch ) {
for ( ssgEntity *k = branch->getKid( 0 );
k != NULL;
k = branch->getNextKid() )
{
if ( k -> isAKindOf ( ssgTypeBranch() ) ) {
my_remove_branch( (ssgBranch *)k );
branch -> removeKid ( k );
} else if ( k -> isAKindOf ( ssgTypeLeaf() ) ) {
branch -> removeKid ( k ) ;
}
}
}
// Clean up the memory used by this tile and delete the arrays used by
1999-06-29 14:57:00 +00:00
// ssg as well as the whole ssg branch
1999-10-27 00:52:25 +00:00
void FGTileEntry::free_tile() {
int i;
1999-09-01 18:52:31 +00:00
FG_LOG( FG_TERRAIN, FG_DEBUG,
"FREEING TILE = (" << tile_bucket << ")" );
1999-06-29 14:57:00 +00:00
1999-09-01 18:52:31 +00:00
FG_LOG( FG_TERRAIN, FG_DEBUG,
" deleting " << nodes.size() << " nodes" );
nodes.clear();
1999-06-29 14:57:00 +00:00
1999-09-01 18:52:31 +00:00
// delete the ssg structures
FG_LOG( FG_TERRAIN, FG_DEBUG,
1999-10-27 00:52:25 +00:00
" deleting (leaf data) vertex, normal, and "
<< " texture coordinate arrays" );
for ( i = 0; i < (int)vec3_ptrs.size(); ++i ) {
2000-09-10 00:04:50 +00:00
#ifdef macintosh
delete [] vec3_ptrs[i];
#else
1999-10-27 00:52:25 +00:00
delete vec3_ptrs[i];
#endif
}
1999-10-27 00:52:25 +00:00
vec3_ptrs.clear();
for ( i = 0; i < (int)vec2_ptrs.size(); ++i ) {
2000-09-10 00:04:50 +00:00
#ifdef macintosh
delete [] vec2_ptrs[i];
#else
1999-10-27 00:52:25 +00:00
delete vec2_ptrs[i];
#endif
}
1999-10-27 00:52:25 +00:00
vec2_ptrs.clear();
for ( i = 0; i < (int)index_ptrs.size(); ++i ) {
delete index_ptrs[i];
}
1999-10-27 00:52:25 +00:00
index_ptrs.clear();
1999-06-29 14:57:00 +00:00
// delete the terrain branch
int pcount = terra_transform->getNumParents();
1999-06-29 14:57:00 +00:00
if ( pcount > 0 ) {
// find the first parent (should only be one)
ssgBranch *parent = terra_transform->getParent( 0 ) ;
if( parent ) {
// my_remove_branch( select_ptr );
parent->removeKid( terra_transform );
terra_transform = NULL;
} else {
FG_LOG( FG_TERRAIN, FG_ALERT,
"parent pointer is NULL! Dying" );
exit(-1);
}
1999-06-29 14:57:00 +00:00
} else {
FG_LOG( FG_TERRAIN, FG_ALERT,
"Parent count is zero for an ssg tile! Dying" );
exit(-1);
}
if ( lights_transform ) {
// delete the terrain lighting branch
pcount = lights_transform->getNumParents();
if ( pcount > 0 ) {
// find the first parent (should only be one)
ssgBranch *parent = lights_transform->getParent( 0 ) ;
if( parent ) {
parent->removeKid( lights_transform );
lights_transform = NULL;
} else {
FG_LOG( FG_TERRAIN, FG_ALERT,
"parent pointer is NULL! Dying" );
exit(-1);
}
} else {
FG_LOG( FG_TERRAIN, FG_ALERT,
"Parent count is zero for an ssg light tile! Dying" );
exit(-1);
}
}
}
// Update the ssg transform node for this tile so it can be
// properly drawn relative to our (0,0,0) point
void FGTileEntry::prep_ssg_node( const Point3D& p, float vis) {
SetOffset( p );
// #define USE_UP_AND_COMING_PLIB_FEATURE
#ifdef USE_UP_AND_COMING_PLIB_FEATURE
terra_range->setRange( 0, SG_ZERO );
terra_range->setRange( 1, vis + bounding_radius );
lights_range->setRange( 0, SG_ZERO );
lights_range->setRange( 1, vis * 1.5 + bounding_radius );
#else
float ranges[2];
ranges[0] = SG_ZERO;
ranges[1] = vis + bounding_radius;
terra_range->setRanges( ranges, 2 );
if ( lights_range ) {
ranges[1] = vis * 1.5 + bounding_radius;
lights_range->setRanges( ranges, 2 );
}
#endif
sgVec3 sgTrans;
sgSetVec3( sgTrans, offset.x(), offset.y(), offset.z() );
terra_transform->setTransform( sgTrans );
if ( lights_transform ) {
// we need to lift the lights above the terrain to avoid
// z-buffer fighting. We do this based on our altitude and
// the distance this tile is away from scenery center.
sgVec3 up;
sgCopyVec3( up, globals->get_current_view()->get_world_up() );
double agl;
if ( current_aircraft.fdm_state ) {
agl = current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER
- scenery.cur_elev;
} else {
agl = 0.0;
}
// sgTrans just happens to be the
// vector from scenery center to the center of this tile which
// is what we want to calculate the distance of
sgVec3 to;
sgCopyVec3( to, sgTrans );
double dist = sgLengthVec3( to );
if ( general.get_glDepthBits() > 16 ) {
sgScaleVec3( up, 10.0 + agl / 100.0 + dist / 10000 );
} else {
sgScaleVec3( up, 10.0 + agl / 20.0 + dist / 5000 );
}
sgAddVec3( sgTrans, up );
lights_transform->setTransform( sgTrans );
// select which set of lights based on sun angle
float sun_angle = cur_light_params.sun_angle * RAD_TO_DEG;
2000-12-06 22:16:12 +00:00
if ( sun_angle > 95 ) {
lights_brightness->select(0x04);
2000-12-06 22:16:12 +00:00
} else if ( sun_angle > 92 ) {
lights_brightness->select(0x02);
} else if ( sun_angle > 89 ) {
lights_brightness->select(0x01);
} else {
lights_brightness->select(0x00);
}
}
}