From 9f5c9886c4df4f8363b09d65bc7a61ece39b8494 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 22 Sep 2008 17:14:10 +0000 Subject: [PATCH] New Near/Far system, and speed optimizations --- panda/src/grutil/geoMipTerrain.I | 109 ++++++++++++++++++++++++----- panda/src/grutil/geoMipTerrain.cxx | 11 ++- panda/src/grutil/geoMipTerrain.h | 30 ++++---- 3 files changed, 115 insertions(+), 35 deletions(-) diff --git a/panda/src/grutil/geoMipTerrain.I b/panda/src/grutil/geoMipTerrain.I index bbb46397da..ba2c8954c0 100644 --- a/panda/src/grutil/geoMipTerrain.I +++ b/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 diff --git a/panda/src/grutil/geoMipTerrain.cxx b/panda/src/grutil/geoMipTerrain.cxx index 8d533f7e1c..213913ea54 100644 --- a/panda/src/grutil/geoMipTerrain.cxx +++ b/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 diff --git a/panda/src/grutil/geoMipTerrain.h b/panda/src/grutil/geoMipTerrain.h index 5adf47d09d..1cb09958c1 100644 --- a/panda/src/grutil/geoMipTerrain.h +++ b/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;