]> git.mxchange.org Git - flightgear.git/blob - src/Scenery/tileentry.cxx
FG_ to SG_ namespace changes.
[flightgear.git] / src / Scenery / tileentry.cxx
1 // tile.cxx -- routines to handle a scenery tile
2 //
3 // Written by Curtis Olson, started May 1998.
4 //
5 // Copyright (C) 1998, 1999  Curtis L. Olson  - curt@flightgear.org
6 //
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.
11 //
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.
16 //
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.
20 //
21 // $Id$
22
23
24 #include <simgear/compiler.h>
25
26 #ifdef SG_MATH_EXCEPTION_CLASH
27 #  include <math.h>
28 #endif
29
30 #include STL_FUNCTIONAL
31 #include STL_ALGORITHM
32
33 #include <simgear/bucket/newbucket.hxx>
34 #include <simgear/debug/logstream.hxx>
35
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>
41
42 #include "tileentry.hxx"
43
44 SG_USING_STD(for_each);
45 SG_USING_STD(mem_fun_ref);
46
47
48 // Constructor
49 FGTileEntry::FGTileEntry ()
50     : ncount(0)
51 {
52     nodes.clear();
53 }
54
55
56 // Destructor
57 FGTileEntry::~FGTileEntry () {
58     // cout << "nodes = " << nodes.size() << endl;;
59     // delete[] nodes;
60 }
61
62
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 );
68           k != NULL; 
69           k = branch->getNextKid() )
70     {
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 ) ;
76         }
77     }
78 }
79
80
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() {
84     int i;
85     FG_LOG( FG_TERRAIN, FG_DEBUG,
86             "FREEING TILE = (" << tile_bucket << ")" );
87
88     FG_LOG( FG_TERRAIN, FG_DEBUG,
89             "  deleting " << nodes.size() << " nodes" );
90     nodes.clear();
91
92     // delete the ssg structures
93     FG_LOG( FG_TERRAIN, FG_DEBUG,
94             "  deleting (leaf data) vertex, normal, and "
95             << " texture coordinate arrays" );
96
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
100 #else
101         delete vec3_ptrs[i];
102 #endif
103     }
104     vec3_ptrs.clear();
105
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
109 #else
110         delete vec2_ptrs[i];
111 #endif
112     }
113     vec2_ptrs.clear();
114
115     for ( i = 0; i < (int)index_ptrs.size(); ++i ) {
116         delete index_ptrs[i];
117     }
118     index_ptrs.clear();
119
120     // delete the terrain branch
121     int pcount = terra_transform->getNumParents();
122     if ( pcount > 0 ) {
123         // find the first parent (should only be one)
124         ssgBranch *parent = terra_transform->getParent( 0 ) ;
125         if( parent ) {
126             // my_remove_branch( select_ptr );
127             parent->removeKid( terra_transform );
128             terra_transform = NULL;
129         } else {
130             FG_LOG( FG_TERRAIN, FG_ALERT,
131                     "parent pointer is NULL!  Dying" );
132             exit(-1);
133         }
134     } else {
135         FG_LOG( FG_TERRAIN, FG_ALERT,
136                 "Parent count is zero for an ssg tile!  Dying" );
137         exit(-1);
138     }
139
140     if ( lights_transform ) {
141         // delete the terrain lighting branch
142         pcount = lights_transform->getNumParents();
143         if ( pcount > 0 ) {
144             // find the first parent (should only be one)
145             ssgBranch *parent = lights_transform->getParent( 0 ) ;
146             if( parent ) {
147                 parent->removeKid( lights_transform );
148                 lights_transform = NULL;
149             } else {
150                 FG_LOG( FG_TERRAIN, FG_ALERT,
151                         "parent pointer is NULL!  Dying" );
152                 exit(-1);
153             }
154         } else {
155             FG_LOG( FG_TERRAIN, FG_ALERT,
156                     "Parent count is zero for an ssg light tile!  Dying" );
157             exit(-1);
158         }
159     }
160 }
161
162
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) {
166     SetOffset( p );
167
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 );
174 #else
175     float ranges[2];
176     ranges[0] = SG_ZERO;
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 );
182     }
183 #endif
184     sgVec3 sgTrans;
185     sgSetVec3( sgTrans, offset.x(), offset.y(), offset.z() );
186     terra_transform->setTransform( sgTrans );
187
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.
192
193         sgVec3 up;
194         sgCopyVec3( up, globals->get_current_view()->get_world_up() );
195
196         double agl;
197         if ( current_aircraft.fdm_state ) {
198             agl = current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER
199                 - scenery.cur_elev;
200         } else {
201             agl = 0.0;
202         }
203
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
207         sgVec3 to;
208         sgCopyVec3( to, sgTrans );
209         double dist = sgLengthVec3( to );
210
211         if ( general.get_glDepthBits() > 16 ) {
212             sgScaleVec3( up, 10.0 + agl / 100.0 + dist / 10000 );
213         } else {
214             sgScaleVec3( up, 10.0 + agl / 20.0 + dist / 5000 );
215         }
216         sgAddVec3( sgTrans, up );
217         lights_transform->setTransform( sgTrans );
218
219         // select which set of lights based on sun angle
220         float sun_angle = cur_light_params.sun_angle * RAD_TO_DEG;
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);
227         } else {
228             lights_brightness->select(0x00);
229         }
230     }
231 }