]> git.mxchange.org Git - flightgear.git/blobdiff - src/Scenery/scenery.cxx
Fix line endings
[flightgear.git] / src / Scenery / scenery.cxx
index 88badf93eea9498ce85dc92804f8071ef04a3526..e0acaaef17b5b3287b1087f64e6ca4f66727eb31 100644 (file)
@@ -100,7 +100,7 @@ void FGScenery::bind() {
 void FGScenery::unbind() {
 }
 
-void FGScenery::set_center( Point3D p ) {
+void FGScenery::set_center( const Point3D& p ) {
     center = p;
     sgdVec3 c;
     sgdSetVec3(c, p.x(), p.y(), p.z());
@@ -112,7 +112,6 @@ void FGScenery::set_center( Point3D p ) {
 }
 
 void FGScenery::register_placement_transform(ssgPlacementTransform *trans) {
-    trans->ref();
     _placement_list.push_back(trans);        
     sgdVec3 c;
     sgdSetVec3(c, center.x(), center.y(), center.z());
@@ -123,7 +122,6 @@ void FGScenery::unregister_placement_transform(ssgPlacementTransform *trans) {
     placement_list_type::iterator it = _placement_list.begin();
     while (it != _placement_list.end()) {
         if ((*it) == trans) {
-            (*it)->deRef();
             it = _placement_list.erase(it);        
         } else
             ++it;
@@ -146,7 +144,7 @@ FGScenery::get_elevation_m(double lat, double lon, double max_alt,
 }
 
 bool
-FGScenery::get_cart_elevation_m(const sgdVec3 pos, double max_altoff,
+FGScenery::get_cart_elevation_m(const sgdVec3& pos, double max_altoff,
                                 double& alt, bool exact)
 {
   Point3D saved_center = center;
@@ -155,7 +153,7 @@ FGScenery::get_cart_elevation_m(const sgdVec3 pos, double max_altoff,
     Point3D ppos(pos[0], pos[1], pos[2]);
     if (30.0*30.0 < ppos.distance3Dsquared(center)) {
       set_center( ppos );
-      replaced_center = false;
+      replaced_center = true;
     }
   }
 
@@ -186,3 +184,74 @@ FGScenery::get_cart_elevation_m(const sgdVec3 pos, double max_altoff,
   
   return hit;
 }
+
+
+bool
+FGScenery::get_cart_ground_intersection(const sgdVec3& pos,
+                                        const sgdVec3& dir,
+                                        sgdVec3& nearestHit, bool exact)
+{
+  // We assume that starting positions in the center of the earth are invalid
+  if ( fabs(pos[0]) < 1.0 && fabs(pos[1]) < 1.0 && fabs(pos[2]) < 1.0 )
+    return false;
+
+  // Well that 'exactness' is somehow problematic, but makes at least sure
+  // that we don't compute that with a cenery center at the other side of
+  // the world ...
+  Point3D saved_center = center;
+  bool replaced_center = false;
+  if (exact) {
+    Point3D ppos(pos[0], pos[1], pos[2]);
+    if (30.0*30.0 < ppos.distance3Dsquared(center)) {
+      set_center( ppos );
+      replaced_center = true;
+    }
+  }
+
+  // Not yet found any hit ...
+  bool result = false;
+
+  // Make really sure the direction is normalized, is really cheap compared to
+  // computation of ground intersection.
+  sgdVec3 normalizedDir;
+  sgdCopyVec3(normalizedDir, dir);
+  sgdNormaliseVec3(normalizedDir);
+
+  sgdVec3 sceneryCenter;
+  sgdSetVec3(sceneryCenter, center[0], center[1], center[2]);
+  sgdVec3 relativePos;
+  sgdSubVec3(relativePos, pos, sceneryCenter);
+
+  // At the moment only intersection with the terrain?
+  FGHitList hit_list;
+  hit_list.Intersect(globals->get_scenery()->get_terrain_branch(),
+                     relativePos, normalizedDir);
+
+  double dist = DBL_MAX;
+  int hitcount = hit_list.num_hits();
+  for (int i = 0; i < hitcount; ++i) {
+    // Check for the nearest hit
+    sgdVec3 diff;
+    sgdSubVec3(diff, hit_list.get_point(i), relativePos);
+    
+    // We only want hits in front of us ...
+    if (sgdScalarProductVec3(normalizedDir, diff) < 0)
+      continue;
+
+    // find the nearest hit
+    double nDist = sgdScalarProductVec3(diff, diff);
+    if (dist < nDist)
+      continue;
+
+    // Store the hit point
+    dist = nDist;
+    sgdAddVec3(nearestHit, hit_list.get_point(i), sceneryCenter);
+    result = true;
+  }
+
+  if (replaced_center)
+    set_center( saved_center );
+
+  return result;
+}
+