diff --git a/panda/src/grutil/geoMipTerrain.I b/panda/src/grutil/geoMipTerrain.I index 422a273e02..82140aaa78 100644 --- a/panda/src/grutil/geoMipTerrain.I +++ b/panda/src/grutil/geoMipTerrain.I @@ -1,6 +1,6 @@ // Filename: geoMipTerrain.I // Created by: pro-rsoft (29jun07) -// Last updated by: pro-rsoft (03mar08) +// Last updated by: pro-rsoft (24sep08) // //////////////////////////////////////////////////////////////////// // @@ -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 @@ -239,6 +265,7 @@ set_block_size(unsigned short newbs) { _max_level = (unsigned short) (log((double) _block_size) / log(2.0)); _is_dirty = true; } + //////////////////////////////////////////////////////////////////// // Function: GeoMipTerrain::is_dirty // Access: Published @@ -253,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 @@ -265,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 input_near, double input_far) { + _use_near_far = true; + _near = input_near; + _far = input_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 input_near) { + _use_near_far = true; + _near = input_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 input_far) { + _use_near_far = true; + _far = input_far; +} + //////////////////////////////////////////////////////////////////// // Function: GeoMipTerrain::get_block_node_path // Access: Published @@ -334,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((double) _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)); } //////////////////////////////////////////////////////////////////// @@ -390,6 +458,7 @@ set_heightfield(const Filename &filename, PNMFileType *ftype) { } return false; } + INLINE bool GeoMipTerrain:: set_heightfield(const PNMImage &image) { // Before we apply anything, validate the size. @@ -404,12 +473,10 @@ set_heightfield(const PNMImage &image) { } return false; } + INLINE bool GeoMipTerrain:: -set_heightfield(const Texture *tex) { - grutil_cat.warning() << "Setting a texture as heightfield image is deprecated!\n"; - PNMImage image; - tex->store(image); - return set_heightfield(image); +set_heightfield(const string &path) { + return set_heightfield(Filename(path)); } //////////////////////////////////////////////////////////////////// @@ -430,6 +497,7 @@ set_color_map(const Filename &filename, PNMFileType *ftype) { } return false; } + INLINE bool GeoMipTerrain:: set_color_map(const PNMImage &image) { _color_map.copy_from(image); @@ -437,12 +505,19 @@ set_color_map(const PNMImage &image) { _has_color_map = true; return true; } + INLINE bool GeoMipTerrain:: set_color_map(const Texture *tex) { tex->store(_color_map); _is_dirty = true; return true; } + +INLINE bool GeoMipTerrain:: +set_color_map(const string &path) { + return set_color_map(Filename(path)); +} + //////////////////////////////////////////////////////////////////// // Function: GeoMipTerrain::has_color_map // Access: Published @@ -452,6 +527,7 @@ INLINE bool GeoMipTerrain:: has_color_map() { return _has_color_map; } + //////////////////////////////////////////////////////////////////// // Function: GeoMipTerrain::clear_color_map // Access: Published @@ -464,6 +540,7 @@ clear_color_map() { _has_color_map = false; } } + //////////////////////////////////////////////////////////////////// // Function: GeoMipTerrain::get_pixel_value // Access: Private @@ -475,11 +552,13 @@ INLINE double GeoMipTerrain:: get_pixel_value(int x, int y) { x = max(min(x,int(_xsize-1)),0); y = max(min(y,int(_ysize-1)),0); - return double(_heightfield.get_bright(int(x),int(y))); -/* return double(_heightfield.get_red_val(int(x),int(y)) - + _heightfield.get_green_val(int(x),int(y)) * 256 - + _heightfield.get_blue_val(int(x),int(y)) * 65536) / 16777215.0; -*/ + if (_heightfield.is_grayscale()) { + return double(_heightfield.get_bright(x, y)); + } else { + return double(_heightfield.get_red(x, y)) + + double(_heightfield.get_green(x, y)) / 256.0 + + double(_heightfield.get_blue(x, y)) / 65536.0; + } } INLINE double GeoMipTerrain:: get_pixel_value(unsigned short mx, unsigned short my, int x, int y) { @@ -545,6 +624,7 @@ INLINE bool GeoMipTerrain:: is_power_of_two(unsigned int i) { return !((i - 1) & i); } + //////////////////////////////////////////////////////////////////// // Function: GeoMipTerrain::f_part // Access: Private @@ -559,6 +639,7 @@ INLINE double GeoMipTerrain:: f_part(double i) { return i - floor(i); } + //////////////////////////////////////////////////////////////////// // Function: GeoMipTerrain::sfav // Access: Private