~ubuntu-branches/ubuntu/oneiric/flightgear/oneiric

« back to all changes in this revision

Viewing changes to src/Scenery/scenery.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2006-01-05 12:48:11 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060105124811-xsr6rtcrb88w19c8
Tags: 0.9.9-1ubuntu1
Resynchronise with Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
// along with this program; if not, write to the Free Software
19
19
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
20
//
21
 
// $Id: scenery.cxx,v 1.7 2004/11/19 22:10:43 curt Exp $
 
21
// $Id: scenery.cxx,v 1.12 2005/11/09 17:08:04 curt Exp $
22
22
 
23
23
 
24
24
#ifdef HAVE_CONFIG_H
30
30
 
31
31
#include <simgear/debug/logstream.hxx>
32
32
#include <simgear/scene/tgdb/userdata.hxx>
 
33
#include <simgear/math/sg_geodesy.hxx>
 
34
#include <simgear/scene/model/placementtrans.hxx>
33
35
 
34
36
#include <Main/fg_props.hxx>
35
37
 
 
38
#include "hitlist.hxx"
36
39
#include "scenery.hxx"
37
40
 
38
41
 
41
44
    SG_LOG( SG_TERRAIN, SG_INFO, "Initializing scenery subsystem" );
42
45
 
43
46
    center = Point3D(0.0);
44
 
    cur_elev = -9999;
45
47
}
46
48
 
47
49
 
92
94
 
93
95
 
94
96
void FGScenery::bind() {
95
 
    fgTie("/environment/ground-elevation-m", this,
96
 
          &FGScenery::get_cur_elev, &FGScenery::set_cur_elev);
97
97
}
98
98
 
99
99
 
100
100
void FGScenery::unbind() {
101
 
    fgUntie("/environment/ground-elevation-m");
102
 
}
 
101
}
 
102
 
 
103
void FGScenery::set_center( const Point3D& p ) {
 
104
    center = p;
 
105
    sgdVec3 c;
 
106
    sgdSetVec3(c, p.x(), p.y(), p.z());
 
107
    placement_list_type::iterator it = _placement_list.begin();
 
108
    while (it != _placement_list.end()) {
 
109
        (*it)->setSceneryCenter(c);
 
110
        ++it;
 
111
    }
 
112
}
 
113
 
 
114
void FGScenery::register_placement_transform(ssgPlacementTransform *trans) {
 
115
    trans->ref();
 
116
    _placement_list.push_back(trans);        
 
117
    sgdVec3 c;
 
118
    sgdSetVec3(c, center.x(), center.y(), center.z());
 
119
    trans->setSceneryCenter(c);
 
120
}
 
121
 
 
122
void FGScenery::unregister_placement_transform(ssgPlacementTransform *trans) {
 
123
    placement_list_type::iterator it = _placement_list.begin();
 
124
    while (it != _placement_list.end()) {
 
125
        if ((*it) == trans) {
 
126
            it = _placement_list.erase(it);        
 
127
            ssgDeRefDelete(trans);
 
128
        } else
 
129
            ++it;
 
130
    }
 
131
}
 
132
 
 
133
bool
 
134
FGScenery::get_elevation_m(double lat, double lon, double max_alt,
 
135
                           double& alt, bool exact)
 
136
{
 
137
//   std::cout << __PRETTY_FUNCTION__ << " "
 
138
//             << lat << " "
 
139
//             << lon << " "
 
140
//             << max_alt
 
141
//             << std::endl;
 
142
  sgdVec3 pos;
 
143
  sgGeodToCart(lat*SG_DEGREES_TO_RADIANS, lon*SG_DEGREES_TO_RADIANS,
 
144
               max_alt, pos);
 
145
  return get_cart_elevation_m(pos, 0, alt, exact);
 
146
}
 
147
 
 
148
bool
 
149
FGScenery::get_cart_elevation_m(const sgdVec3& pos, double max_altoff,
 
150
                                double& alt, bool exact)
 
151
{
 
152
  Point3D saved_center = center;
 
153
  bool replaced_center = false;
 
154
  if (exact) {
 
155
    Point3D ppos(pos[0], pos[1], pos[2]);
 
156
    if (30.0*30.0 < ppos.distance3Dsquared(center)) {
 
157
      set_center( ppos );
 
158
      replaced_center = false;
 
159
    }
 
160
  }
 
161
 
 
162
  // overridden with actual values if a terrain intersection is
 
163
  // found
 
164
  double hit_radius = 0.0;
 
165
  sgdVec3 hit_normal = { 0.0, 0.0, 0.0 };
 
166
  
 
167
  bool hit = false;
 
168
  if ( fabs(pos[0]) > 1.0 || fabs(pos[1]) > 1.0 || fabs(pos[2]) > 1.0 ) {
 
169
    sgdVec3 sc;
 
170
    sgdSetVec3(sc, center[0], center[1], center[2]);
 
171
    
 
172
    sgdVec3 ncpos;
 
173
    sgdCopyVec3(ncpos, pos);
 
174
    
 
175
    FGHitList hit_list;
 
176
    
 
177
    // scenery center has been properly defined so any hit should
 
178
    // be valid (and not just luck)
 
179
    hit = fgCurrentElev(ncpos, max_altoff+sgdLengthVec3(pos),
 
180
                        sc, (ssgTransform*)get_scene_graph(),
 
181
                        &hit_list, &alt, &hit_radius, hit_normal);
 
182
  }
 
183
 
 
184
  if (replaced_center)
 
185
    set_center( saved_center );
 
186
  
 
187
  return hit;
 
188
}
 
189
 
 
190
 
 
191
bool
 
192
FGScenery::get_cart_ground_intersection(const sgdVec3& pos,
 
193
                                        const sgdVec3& dir,
 
194
                                        sgdVec3& nearestHit, bool exact)
 
195
{
 
196
  // We assume that starting positions in the center of the earth are invalid
 
197
  if ( fabs(pos[0]) < 1.0 && fabs(pos[1]) < 1.0 && fabs(pos[2]) < 1.0 )
 
198
    return false;
 
199
 
 
200
  // Well that 'exactness' is somehow problematic, but makes at least sure
 
201
  // that we don't compute that with a cenery center at the other side of
 
202
  // the world ...
 
203
  Point3D saved_center = center;
 
204
  bool replaced_center = false;
 
205
  if (exact) {
 
206
    Point3D ppos(pos[0], pos[1], pos[2]);
 
207
    if (30.0*30.0 < ppos.distance3Dsquared(center)) {
 
208
      set_center( ppos );
 
209
      replaced_center = true;
 
210
    }
 
211
  }
 
212
 
 
213
  // Not yet found any hit ...
 
214
  bool result = false;
 
215
 
 
216
  // Make really sure the direction is normalized, is really cheap compared to
 
217
  // computation of ground intersection.
 
218
  sgdVec3 normalizedDir;
 
219
  sgdCopyVec3(normalizedDir, dir);
 
220
  sgdNormaliseVec3(normalizedDir);
 
221
 
 
222
  sgdVec3 sceneryCenter;
 
223
  sgdSetVec3(sceneryCenter, center[0], center[1], center[2]);
 
224
  sgdVec3 relativePos;
 
225
  sgdSubVec3(relativePos, pos, sceneryCenter);
 
226
 
 
227
  // At the moment only intersection with the terrain?
 
228
  FGHitList hit_list;
 
229
  hit_list.Intersect(globals->get_scenery()->get_terrain_branch(),
 
230
                     relativePos, normalizedDir);
 
231
 
 
232
  double dist = DBL_MAX;
 
233
  int hitcount = hit_list.num_hits();
 
234
  for (int i = 0; i < hitcount; ++i) {
 
235
    // Check for the nearest hit
 
236
    sgdVec3 diff;
 
237
    sgdSubVec3(diff, hit_list.get_point(i), relativePos);
 
238
    
 
239
    // We only want hits in front of us ...
 
240
    if (sgdScalarProductVec3(normalizedDir, diff) < 0)
 
241
      continue;
 
242
 
 
243
    // find the nearest hit
 
244
    double nDist = sgdScalarProductVec3(diff, diff);
 
245
    if (dist < nDist)
 
246
      continue;
 
247
 
 
248
    // Store the hit point
 
249
    dist = nDist;
 
250
    sgdAddVec3(nearestHit, hit_list.get_point(i), sceneryCenter);
 
251
    result = true;
 
252
  }
 
253
 
 
254
  if (replaced_center)
 
255
    set_center( saved_center );
 
256
 
 
257
  return result;
 
258
}
 
259