1999-06-12 21:15:27 +00:00
|
|
|
// 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>
|
1999-06-12 21:15:27 +00:00
|
|
|
|
2001-03-23 22:42:49 +00:00
|
|
|
#ifdef SG_MATH_EXCEPTION_CLASH
|
1999-06-12 21:15:27 +00:00
|
|
|
# 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>
|
1999-06-12 21:15:27 +00:00
|
|
|
|
2000-12-04 05:24:38 +00:00
|
|
|
#include <Aircraft/aircraft.hxx>
|
2000-12-05 14:27:27 +00:00
|
|
|
#include <Include/general.hxx>
|
2000-12-04 05:24:38 +00:00
|
|
|
#include <Main/globals.hxx>
|
|
|
|
#include <Scenery/scenery.hxx>
|
2000-12-04 23:25:05 +00:00
|
|
|
#include <Time/light.hxx>
|
2000-12-04 05:24:38 +00:00
|
|
|
|
1999-06-12 21:15:27 +00:00
|
|
|
#include "tileentry.hxx"
|
|
|
|
|
2001-03-23 22:59:18 +00:00
|
|
|
SG_USING_STD(for_each);
|
|
|
|
SG_USING_STD(mem_fun_ref);
|
1999-06-12 21:15:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Constructor
|
2000-12-03 20:15:46 +00:00
|
|
|
FGTileEntry::FGTileEntry ()
|
|
|
|
: ncount(0)
|
1999-06-12 21:15:27 +00:00
|
|
|
{
|
|
|
|
nodes.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Destructor
|
2000-12-03 20:15:46 +00:00
|
|
|
FGTileEntry::~FGTileEntry () {
|
1999-06-12 21:15:27 +00:00
|
|
|
// cout << "nodes = " << nodes.size() << endl;;
|
|
|
|
// delete[] nodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-10-26 03:45:33 +00:00
|
|
|
// 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 ) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-06-23 00:30:04 +00:00
|
|
|
// 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,
|
1999-06-12 21:15:27 +00:00
|
|
|
"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 ) {
|
2001-01-11 05:04:17 +00:00
|
|
|
#if defined(macintosh) || defined(_MSC_VER)
|
|
|
|
delete [] vec3_ptrs[i]; //that's the correct version
|
2000-02-10 23:37:56 +00:00
|
|
|
#else
|
1999-10-27 00:52:25 +00:00
|
|
|
delete vec3_ptrs[i];
|
2000-02-10 23:37:56 +00:00
|
|
|
#endif
|
1999-06-30 00:28:20 +00:00
|
|
|
}
|
1999-10-27 00:52:25 +00:00
|
|
|
vec3_ptrs.clear();
|
|
|
|
|
|
|
|
for ( i = 0; i < (int)vec2_ptrs.size(); ++i ) {
|
2001-01-11 05:04:17 +00:00
|
|
|
#if defined(macintosh) || defined(_MSC_VER)
|
|
|
|
delete [] vec2_ptrs[i]; //that's the correct version
|
2000-02-10 23:37:56 +00:00
|
|
|
#else
|
1999-10-27 00:52:25 +00:00
|
|
|
delete vec2_ptrs[i];
|
2000-02-10 23:37:56 +00:00
|
|
|
#endif
|
1999-10-26 03:45:33 +00:00
|
|
|
}
|
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-06-30 00:28:20 +00:00
|
|
|
}
|
1999-10-27 00:52:25 +00:00
|
|
|
index_ptrs.clear();
|
1999-06-29 14:57:00 +00:00
|
|
|
|
2000-12-04 05:24:38 +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)
|
2000-12-04 05:24:38 +00:00
|
|
|
ssgBranch *parent = terra_transform->getParent( 0 ) ;
|
1999-10-06 20:59:52 +00:00
|
|
|
if( parent ) {
|
1999-10-30 02:37:56 +00:00
|
|
|
// my_remove_branch( select_ptr );
|
2000-12-04 05:24:38 +00:00
|
|
|
parent->removeKid( terra_transform );
|
|
|
|
terra_transform = NULL;
|
1999-10-06 20:59:52 +00:00
|
|
|
} 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);
|
1999-06-30 00:28:20 +00:00
|
|
|
}
|
2000-12-04 05:24:38 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
1999-06-12 21:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-12-04 05:24:38 +00:00
|
|
|
// 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 );
|
2000-12-04 22:36:18 +00:00
|
|
|
lights_range->setRange( 1, vis * 1.5 + bounding_radius );
|
2000-12-04 05:24:38 +00:00
|
|
|
#else
|
|
|
|
float ranges[2];
|
|
|
|
ranges[0] = SG_ZERO;
|
|
|
|
ranges[1] = vis + bounding_radius;
|
|
|
|
terra_range->setRanges( ranges, 2 );
|
2000-12-04 23:25:05 +00:00
|
|
|
if ( lights_range ) {
|
|
|
|
ranges[1] = vis * 1.5 + bounding_radius;
|
|
|
|
lights_range->setRanges( ranges, 2 );
|
|
|
|
}
|
2000-12-04 05:24:38 +00:00
|
|
|
#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 );
|
|
|
|
|
2000-12-05 14:27:27 +00:00
|
|
|
if ( general.get_glDepthBits() > 16 ) {
|
|
|
|
sgScaleVec3( up, 10.0 + agl / 100.0 + dist / 10000 );
|
|
|
|
} else {
|
|
|
|
sgScaleVec3( up, 10.0 + agl / 20.0 + dist / 5000 );
|
|
|
|
}
|
2000-12-04 05:24:38 +00:00
|
|
|
sgAddVec3( sgTrans, up );
|
|
|
|
lights_transform->setTransform( sgTrans );
|
2000-12-04 23:25:05 +00:00
|
|
|
|
|
|
|
// select which set of lights based on sun angle
|
2001-03-24 04:48:44 +00:00
|
|
|
float sun_angle = cur_light_params.sun_angle * SGD_RADIANS_TO_DEGREES;
|
2000-12-06 22:16:12 +00:00
|
|
|
if ( sun_angle > 95 ) {
|
2000-12-04 23:25:05 +00:00
|
|
|
lights_brightness->select(0x04);
|
2000-12-06 22:16:12 +00:00
|
|
|
} else if ( sun_angle > 92 ) {
|
2000-12-04 23:25:05 +00:00
|
|
|
lights_brightness->select(0x02);
|
2000-12-05 18:58:05 +00:00
|
|
|
} else if ( sun_angle > 89 ) {
|
2000-12-04 23:25:05 +00:00
|
|
|
lights_brightness->select(0x01);
|
|
|
|
} else {
|
|
|
|
lights_brightness->select(0x00);
|
|
|
|
}
|
2000-12-04 05:24:38 +00:00
|
|
|
}
|
1999-07-04 07:37:30 +00:00
|
|
|
}
|