Browse Source

New Near/Far system, and speed optimizations

rdb 17 years ago
parent
commit
9f5c9886c4
3 changed files with 115 additions and 35 deletions
  1. 92 17
      panda/src/grutil/geoMipTerrain.I
  2. 5 6
      panda/src/grutil/geoMipTerrain.cxx
  3. 18 12
      panda/src/grutil/geoMipTerrain.h

+ 92 - 17
panda/src/grutil/geoMipTerrain.I

@@ -13,6 +13,8 @@
 //
 ////////////////////////////////////////////////////////////////////
 
+#include "config_grutil.h"
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::Constructor
 //       Access: Published
@@ -24,9 +26,13 @@ GeoMipTerrain(const string &name) {
   _root_flattened = false;
   _xsize = 0;
   _ysize = 0;
-  _min_level = 0;
   _block_size = 16;
+  _max_level = 4; // Always log(_block_size) / log(2.0)
+  _min_level = 0;
   _factor = 100.0;
+  _near = 16.0;
+  _far = 128.0;
+  _use_near_far = false;
   _has_color_map = false;
   PT(PandaNode) tmpnode = new PandaNode("tmp_focal");
   _auto_flatten = AFM_off;
@@ -58,6 +64,7 @@ INLINE PNMImage &GeoMipTerrain::
 heightfield() {
   return _heightfield;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::color_map
 //       Access: Published
@@ -69,6 +76,7 @@ INLINE PNMImage &GeoMipTerrain::
 color_map() {
   return _color_map;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::set_bruteforce
 //       Access: Published
@@ -85,6 +93,7 @@ set_bruteforce(bool bf) {
   }
   _bruteforce = bf;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::get_bruteforce
 //       Access: Published
@@ -96,6 +105,7 @@ INLINE bool GeoMipTerrain::
 get_bruteforce() {
   return _bruteforce;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::set_auto_flatten
 //       Access: Private
@@ -103,12 +113,12 @@ get_bruteforce() {
 //               flatten_light, flatten_medium, or flatten_strong)
 //               after each update.  This only affects future
 //               updates, it doesn't flatten the current terrain.
-//                
 ////////////////////////////////////////////////////////////////////
 INLINE void GeoMipTerrain::
 set_auto_flatten(int mode) {
   _auto_flatten = mode;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::set_focal_point
 //       Access: Published
@@ -153,6 +163,7 @@ set_focal_point(NodePath fp) {
   _focal_point = fp;
   _focal_is_temporary = false;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::get_focal_point
 //       Access: Published
@@ -193,6 +204,7 @@ INLINE void GeoMipTerrain::
 set_min_level(unsigned short minlevel) {
   _min_level = minlevel;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::get_min_level
 //       Access: Published
@@ -205,6 +217,19 @@ INLINE unsigned short GeoMipTerrain::
 get_min_level() {
   return _min_level;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeoMipTerrain::get_max_level
+//       Access: Published
+//  Description: Returns the highest level possible for this block
+//               size. When a block is at this level, it will be
+//               the worst quality possible.
+////////////////////////////////////////////////////////////////////
+INLINE unsigned short GeoMipTerrain::
+get_max_level() {
+  return _max_level;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::get_block_size
 //       Access: Published
@@ -214,6 +239,7 @@ INLINE unsigned short GeoMipTerrain::
 get_block_size() {
   return _block_size;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::set_block_size
 //       Access: Published
@@ -236,8 +262,10 @@ set_block_size(unsigned short newbs) {
       }
     }
   }
+  _max_level = (unsigned short) (log(float(_block_size)) / log(2.0));
   _is_dirty = true;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::is_dirty
 //       Access: Published
@@ -252,10 +280,12 @@ INLINE bool GeoMipTerrain::
 is_dirty() {
   return _is_dirty;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::set_factor
 //       Access: Published
-//  Description: Sets the quality factor at which blocks must be
+//  Description: DEPRECATED method. Use set_near/far instead.
+//               Sets the quality factor at which blocks must be
 //               generated. The higher this level, the better
 //               quality the terrain will be, but more expensive
 //               to render. A value of 0 makes the terrain the
@@ -264,22 +294,49 @@ is_dirty() {
 ////////////////////////////////////////////////////////////////////
 INLINE void GeoMipTerrain::
 set_factor(float factor) {
+  grutil_cat.debug() << "Using deprecated method set_factor, use set_near and set_far instead!\n";
+  _use_near_far = false;
   _factor = factor;
 }
+
 ////////////////////////////////////////////////////////////////////
-//     Function: GeoMipTerrain::get_factor
+//     Function: GeoMipTerrain::set_near_far
 //       Access: Published
-//  Description: Gets the quality factor at which blocks must be
-//               generated. The higher this level, the better
-//               quality the terrain will be, but more expensive
-//               to render. A value of 0 makes the terrain the
-//               lowest quality possible, depending on blocksize.
-//               The default value is 100.
+//  Description: Sets the near and far LOD distances in one call.
 ////////////////////////////////////////////////////////////////////
-INLINE float GeoMipTerrain::
-get_factor() {
-  return _factor;
+INLINE void GeoMipTerrain::
+set_near_far(double near, double far) {
+  _use_near_far = true;
+  _near = near;
+  _far = far;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeoMipTerrain::set_near
+//       Access: Published
+//  Description: Sets the near LOD distance, at which the terrain
+//               will be rendered at highest quality.
+//               This distance is in the terrain's coordinate space!
+////////////////////////////////////////////////////////////////////
+INLINE void GeoMipTerrain::
+set_near(double near) {
+  _use_near_far = true;
+  _near = near;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeoMipTerrain::set_far
+//       Access: Published
+//  Description: Sets the far LOD distance, at which the terrain
+//               will be rendered at lowest quality.
+//               This distance is in the terrain's coordinate space!
+////////////////////////////////////////////////////////////////////
+INLINE void GeoMipTerrain::
+set_far(double far) {
+  _use_near_far = true;
+  _far = far;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::get_block_node_path
 //       Access: Published
@@ -333,13 +390,25 @@ lod_decide(unsigned short mx, unsigned short my) {
   cx = (cx * _block_size + _block_size / 2) * _root.get_sx();
   cy = (cy * _block_size + _block_size / 2) * _root.get_sy();
   float d;
-  if (_factor > 0.0) {
+  if (_use_near_far) {
     d = sqrt(pow(_focal_point.get_x(_root) - cx, 2) +
-             pow(_focal_point.get_y(_root) - cy, 2)) / _factor;
+            pow(_focal_point.get_y(_root) - cy, 2));
+    if (d < _near) {
+      return 0;
+    } else if (d > _far) {
+      return _max_level;
+    } else {
+      return (d - _near) / (_far - _near) * _max_level * (1.0 - (_min_level / _max_level)) + _min_level;
+    }
   } else {
-    d = log(float(_block_size)) / log(2.0);
+    if (_factor > 0.0) {
+      d = sqrt(pow(_focal_point.get_x(_root) - cx, 2) +
+               pow(_focal_point.get_y(_root) - cy, 2)) / _factor;
+    } else {
+      d = _max_level;
+    }
+    return short(floor(d));
   }
-  return short(floor(d));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -414,6 +483,7 @@ set_heightfield(const Texture *tex) {
   _ysize = _heightfield.get_y_size();
   return true;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::set_color_map
 //       Access: Published
@@ -445,6 +515,7 @@ set_color_map(const Texture *tex) {
   _is_dirty = true;
   return true;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::has_color_map
 //       Access: Published
@@ -454,6 +525,7 @@ INLINE bool GeoMipTerrain::
 has_color_map() {
   return _has_color_map;
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::clear_color_map
 //       Access: Published
@@ -466,6 +538,7 @@ clear_color_map() {
     _has_color_map = false;
   }
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::get_pixel_value
 //       Access: Private
@@ -547,6 +620,7 @@ INLINE bool GeoMipTerrain::
 is_power_of_two(unsigned int i) {
   return !((i - 1) & i);
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::f_part
 //       Access: Private
@@ -561,6 +635,7 @@ INLINE double GeoMipTerrain::
 f_part(double i) {
   return i - floor(i);
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeoMipTerrain::sfav
 //       Access: Private

+ 5 - 6
panda/src/grutil/geoMipTerrain.cxx

@@ -1,6 +1,6 @@
 // Filename: geoMipTerrain.cxx
 // Created by:  pro-rsoft (29jun07)
-// Last updated by: pro-rsoft (08mar08)
+// Last updated by: pro-rsoft (20sep08)
 //
 ////////////////////////////////////////////////////////////////////
 //
@@ -67,7 +67,7 @@ generate_block(unsigned short mx,
 
   // Create vertex data and writers
   PT(GeomVertexData) vdata = new GeomVertexData(_root.get_name(),
-                   GeomVertexFormat::register_format(format), Geom::UH_static);
+                   GeomVertexFormat::register_format(format), Geom::UH_stream);
   GeomVertexWriter cwriter;
   if (_has_color_map) {
     cwriter=GeomVertexWriter(vdata, "color"  );
@@ -75,7 +75,7 @@ generate_block(unsigned short mx,
   GeomVertexWriter vwriter (vdata, "vertex"  );
   GeomVertexWriter twriter (vdata, "texcoord");
   GeomVertexWriter nwriter (vdata, "normal"  );
-  PT(GeomTriangles) prim = new GeomTriangles(Geom::UH_static);
+  PT(GeomTriangles) prim = new GeomTriangles(Geom::UH_stream);
 
   if (_bruteforce) {
     // LOD Level when rendering bruteforce is always 0 (no lod)
@@ -83,8 +83,7 @@ generate_block(unsigned short mx,
   }
 
   // Do some calculations with the level
-  level = min(short(max(_min_level, level)), short(log(float(_block_size))
-                                                                  / log(2.0)));
+  level = min(short(max(_min_level, level)), short(_max_level));
   unsigned short reallevel = level;
   level = int(pow(2.0, int(level)));
   
@@ -505,7 +504,7 @@ calc_levels() {
         tvector.push_back(0);
       } else {
         tvector.push_back(min(short(max(_min_level, lod_decide(mx, my))),
-                              short(log(float(_block_size)) / log(2.0))));
+                              short(_max_level)));
       }
     }
     _levels.push_back(tvector); //push the new row of levels into the 2d vector

+ 18 - 12
panda/src/grutil/geoMipTerrain.h

@@ -1,6 +1,6 @@
 // Filename: geoMipTerrain.h
 // Created by:  pro-rsoft (29jun07)
-// Last updated by: pro-rsoft (03mar08)
+// Last updated by: pro-rsoft (20sep08)
 //
 ////////////////////////////////////////////////////////////////////
 //
@@ -62,7 +62,7 @@ PUBLISHED:
                                                           int x,int y);
   INLINE void set_bruteforce(bool bf);
   INLINE bool get_bruteforce();
-
+  
   // The flatten mode specifies whether the terrain nodes are flattened
   // together after each terrain update.
   enum AutoFlattenMode {
@@ -75,9 +75,9 @@ PUBLISHED:
     // FM_strong: the terrain is flattened using flatten_strong.
     AFM_strong  = 3,
   };
-
+  
   INLINE void set_auto_flatten(int mode);
-
+  
   // The focal point is the point at which the terrain will have the
   // lowest level of detail (highest quality). Parts farther away
   // from the focal point will hae a higher level of detail. The
@@ -90,14 +90,17 @@ PUBLISHED:
   INLINE void set_focal_point(NodePath fnp);
   INLINE NodePath get_focal_point() const;
   INLINE NodePath get_root() const;
-
+  
+  INLINE void set_block_size(unsigned short newbs);
+  INLINE unsigned short get_block_size();
+  INLINE unsigned short get_max_level();
   INLINE void set_min_level(unsigned short minlevel);
   INLINE unsigned short get_min_level();
-  INLINE unsigned short get_block_size();
-  INLINE void set_block_size(unsigned short newbs);
   INLINE bool is_dirty();
-  INLINE float get_factor();
-  INLINE void  set_factor(float factor);
+  INLINE void set_factor(float factor);
+  INLINE void set_near_far(double near, double far);
+  INLINE void set_near(double near);
+  INLINE void set_far(double far);
   INLINE const NodePath get_block_node_path(unsigned short mx,
                                             unsigned short my);
   INLINE LVecBase2f get_block_from_pos(double x, double y);
@@ -106,8 +109,7 @@ PUBLISHED:
   bool update();
   
 private:
-
-
+  
   NodePath generate_block(unsigned short mx, unsigned short my, unsigned short level);
   bool update_block(unsigned short mx, unsigned short my,
                     signed short level = -1, bool forced = false);
@@ -124,7 +126,7 @@ private:
   INLINE double get_pixel_value(int x, int y);
   INLINE double get_pixel_value(unsigned short mx, unsigned short my, int x, int y);
   INLINE unsigned short lod_decide(unsigned short mx, unsigned short my);
-
+  
   NodePath _root;
   int _auto_flatten;
   bool _root_flattened;
@@ -135,7 +137,11 @@ private:
   unsigned int _xsize;
   unsigned int _ysize;
   float _factor;
+  double _near;
+  double _far;
+  bool _use_near_far; // False to use the _factor, True to use the _near and _far values.
   unsigned short _block_size;
+  unsigned short _max_level; // Highest level possible for this block size
   bool _bruteforce;
   NodePath _focal_point;
   bool _focal_is_temporary;