1 // tile.cxx -- routines to handle a scenery tile
3 // Written by Curtis Olson, started May 1998.
5 // Copyright (C) 1998, 1999 Curtis L. Olson - curt@flightgear.org
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <simgear/compiler.h>
26 #ifdef SG_MATH_EXCEPTION_CLASH
30 #include STL_FUNCTIONAL
31 #include STL_ALGORITHM
33 #include <simgear/bucket/newbucket.hxx>
34 #include <simgear/debug/logstream.hxx>
36 #include <Aircraft/aircraft.hxx>
37 #include <Include/general.hxx>
38 #include <Main/globals.hxx>
39 #include <Scenery/scenery.hxx>
40 #include <Time/light.hxx>
42 #include "tileentry.hxx"
44 SG_USING_STD(for_each);
45 SG_USING_STD(mem_fun_ref);
49 FGTileEntry::FGTileEntry ()
57 FGTileEntry::~FGTileEntry () {
58 // cout << "nodes = " << nodes.size() << endl;;
63 // recurse an ssg tree and call removeKid() on every node from the
64 // bottom up. Leaves the original branch in existance, but empty so
65 // it can be removed by the calling routine.
66 static void my_remove_branch( ssgBranch * branch ) {
67 for ( ssgEntity *k = branch->getKid( 0 );
69 k = branch->getNextKid() )
71 if ( k -> isAKindOf ( ssgTypeBranch() ) ) {
72 my_remove_branch( (ssgBranch *)k );
73 branch -> removeKid ( k );
74 } else if ( k -> isAKindOf ( ssgTypeLeaf() ) ) {
75 branch -> removeKid ( k ) ;
81 // Clean up the memory used by this tile and delete the arrays used by
82 // ssg as well as the whole ssg branch
83 void FGTileEntry::free_tile() {
85 FG_LOG( FG_TERRAIN, FG_DEBUG,
86 "FREEING TILE = (" << tile_bucket << ")" );
88 FG_LOG( FG_TERRAIN, FG_DEBUG,
89 " deleting " << nodes.size() << " nodes" );
92 // delete the ssg structures
93 FG_LOG( FG_TERRAIN, FG_DEBUG,
94 " deleting (leaf data) vertex, normal, and "
95 << " texture coordinate arrays" );
97 for ( i = 0; i < (int)vec3_ptrs.size(); ++i ) {
98 #if defined(macintosh) || defined(_MSC_VER)
99 delete [] vec3_ptrs[i]; //that's the correct version
106 for ( i = 0; i < (int)vec2_ptrs.size(); ++i ) {
107 #if defined(macintosh) || defined(_MSC_VER)
108 delete [] vec2_ptrs[i]; //that's the correct version
115 for ( i = 0; i < (int)index_ptrs.size(); ++i ) {
116 delete index_ptrs[i];
120 // delete the terrain branch
121 int pcount = terra_transform->getNumParents();
123 // find the first parent (should only be one)
124 ssgBranch *parent = terra_transform->getParent( 0 ) ;
126 // my_remove_branch( select_ptr );
127 parent->removeKid( terra_transform );
128 terra_transform = NULL;
130 FG_LOG( FG_TERRAIN, FG_ALERT,
131 "parent pointer is NULL! Dying" );
135 FG_LOG( FG_TERRAIN, FG_ALERT,
136 "Parent count is zero for an ssg tile! Dying" );
140 if ( lights_transform ) {
141 // delete the terrain lighting branch
142 pcount = lights_transform->getNumParents();
144 // find the first parent (should only be one)
145 ssgBranch *parent = lights_transform->getParent( 0 ) ;
147 parent->removeKid( lights_transform );
148 lights_transform = NULL;
150 FG_LOG( FG_TERRAIN, FG_ALERT,
151 "parent pointer is NULL! Dying" );
155 FG_LOG( FG_TERRAIN, FG_ALERT,
156 "Parent count is zero for an ssg light tile! Dying" );
163 // Update the ssg transform node for this tile so it can be
164 // properly drawn relative to our (0,0,0) point
165 void FGTileEntry::prep_ssg_node( const Point3D& p, float vis) {
168 // #define USE_UP_AND_COMING_PLIB_FEATURE
169 #ifdef USE_UP_AND_COMING_PLIB_FEATURE
170 terra_range->setRange( 0, SG_ZERO );
171 terra_range->setRange( 1, vis + bounding_radius );
172 lights_range->setRange( 0, SG_ZERO );
173 lights_range->setRange( 1, vis * 1.5 + bounding_radius );
177 ranges[1] = vis + bounding_radius;
178 terra_range->setRanges( ranges, 2 );
179 if ( lights_range ) {
180 ranges[1] = vis * 1.5 + bounding_radius;
181 lights_range->setRanges( ranges, 2 );
185 sgSetVec3( sgTrans, offset.x(), offset.y(), offset.z() );
186 terra_transform->setTransform( sgTrans );
188 if ( lights_transform ) {
189 // we need to lift the lights above the terrain to avoid
190 // z-buffer fighting. We do this based on our altitude and
191 // the distance this tile is away from scenery center.
194 sgCopyVec3( up, globals->get_current_view()->get_world_up() );
197 if ( current_aircraft.fdm_state ) {
198 agl = current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER
204 // sgTrans just happens to be the
205 // vector from scenery center to the center of this tile which
206 // is what we want to calculate the distance of
208 sgCopyVec3( to, sgTrans );
209 double dist = sgLengthVec3( to );
211 if ( general.get_glDepthBits() > 16 ) {
212 sgScaleVec3( up, 10.0 + agl / 100.0 + dist / 10000 );
214 sgScaleVec3( up, 10.0 + agl / 20.0 + dist / 5000 );
216 sgAddVec3( sgTrans, up );
217 lights_transform->setTransform( sgTrans );
219 // select which set of lights based on sun angle
220 float sun_angle = cur_light_params.sun_angle * SGD_RADIANS_TO_DEGREES;
221 if ( sun_angle > 95 ) {
222 lights_brightness->select(0x04);
223 } else if ( sun_angle > 92 ) {
224 lights_brightness->select(0x02);
225 } else if ( sun_angle > 89 ) {
226 lights_brightness->select(0x01);
228 lights_brightness->select(0x00);