Panda3D

geoMipTerrain.I

00001 // Filename: geoMipTerrain.I
00002 // Created by:  pro-rsoft (29jun07)
00003 // Modified by: CMU ETC Summer 2010 team (03aug10) (added getters
00004 //   for _auto_flatten, _near, _far).
00005 //
00006 ////////////////////////////////////////////////////////////////////
00007 //
00008 // PANDA 3D SOFTWARE
00009 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00010 //
00011 // All use of this software is subject to the terms of the revised BSD
00012 // license.  You should have received a copy of this license along
00013 // with this source code in a file named "LICENSE."
00014 //
00015 ////////////////////////////////////////////////////////////////////
00016 
00017 #include "config_grutil.h"
00018 
00019 ////////////////////////////////////////////////////////////////////
00020 //     Function: GeoMipTerrain::Constructor
00021 //       Access: Published
00022 //  Description:
00023 ////////////////////////////////////////////////////////////////////
00024 INLINE GeoMipTerrain::
00025 GeoMipTerrain(const string &name) {
00026   _root = NodePath(name);
00027   _root_flattened = false;
00028   _xsize = 0;
00029   _ysize = 0;
00030   _block_size = 16;
00031   _max_level = 4; // Always log(_block_size) / log(2.0)
00032   _min_level = 0;
00033   _factor = 100.0;
00034   _near = 16.0;
00035   _far = 128.0;
00036   _use_near_far = false;
00037   _has_color_map = false;
00038   PT(PandaNode) tmpnode = new PandaNode("tmp_focal");
00039   _auto_flatten = AFM_off;
00040   _focal_point = NodePath(tmpnode);
00041   _focal_is_temporary = true;
00042   _is_dirty = true;
00043   _bruteforce = false;
00044   _stitching = false;
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: GeoMipTerrain::Destructor
00049 //       Access: Published
00050 //  Description: This will not remove the terrain node itself.
00051 //               To have the terrain itself also deleted, please
00052 //               call remove_node() prior to destruction.
00053 ////////////////////////////////////////////////////////////////////
00054 INLINE GeoMipTerrain::
00055 ~GeoMipTerrain() { 
00056 }
00057 
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: GeoMipTerrain::heightfield
00060 //       Access: Published
00061 //  Description: Returns a reference to the heightfield (a PNMImage)
00062 //               contained inside GeoMipTerrain.  You can use
00063 //               the reference to alter the heightfield.
00064 ////////////////////////////////////////////////////////////////////
00065 INLINE PNMImage &GeoMipTerrain::
00066 heightfield() {
00067   return _heightfield;
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: GeoMipTerrain::color_map
00072 //       Access: Published
00073 //  Description: Returns a reference to the color map (a PNMImage)
00074 //               contained inside GeoMipTerrain.  You can use
00075 //               the reference to alter the color map.
00076 ////////////////////////////////////////////////////////////////////
00077 INLINE PNMImage &GeoMipTerrain::
00078 color_map() {
00079   return _color_map;
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: GeoMipTerrain::set_bruteforce
00084 //       Access: Published
00085 //  Description: Sets a boolean specifying whether the terrain will
00086 //               be rendered bruteforce. If the terrain is rendered
00087 //               bruteforce, there will be no Level of Detail, and
00088 //               the update() call will only update the
00089 //               terrain if it is marked dirty.
00090 ////////////////////////////////////////////////////////////////////
00091 INLINE void GeoMipTerrain::
00092 set_bruteforce(bool bf) {
00093   if (bf == true && _bruteforce == false) {
00094     _is_dirty = true;
00095   }
00096   _bruteforce = bf;
00097 }
00098 
00099 ////////////////////////////////////////////////////////////////////
00100 //     Function: GeoMipTerrain::get_bruteforce
00101 //       Access: Published
00102 //  Description: Returns a boolean whether the terrain is rendered
00103 //               bruteforce or not. See set_bruteforce for more
00104 //               information.
00105 ////////////////////////////////////////////////////////////////////
00106 INLINE bool GeoMipTerrain::
00107 get_bruteforce() {
00108   return _bruteforce;
00109 }
00110 
00111 ////////////////////////////////////////////////////////////////////
00112 //     Function: GeoMipTerrain::set_auto_flatten
00113 //       Access: Private
00114 //  Description: The terrain can be automatically flattened (using
00115 //               flatten_light, flatten_medium, or flatten_strong)
00116 //               after each update.  This only affects future
00117 //               updates, it doesn't flatten the current terrain.
00118 ////////////////////////////////////////////////////////////////////
00119 INLINE void GeoMipTerrain::
00120 set_auto_flatten(int mode) {
00121   _auto_flatten = mode;
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: GeoMipTerrain::set_focal_point
00126 //       Access: Published
00127 //  Description: Sets the focal point.  GeoMipTerrain generates
00128 //               high-resolution terrain around the focal point, and
00129 //               progressively lower and lower resolution terrain
00130 //               as you get farther away. If a point is supplied
00131 //               and not a NodePath, make sure it's relative to
00132 //               the terrain. Only the x and y coordinates of
00133 //               the focal point are taken in respect.
00134 ////////////////////////////////////////////////////////////////////
00135 INLINE void GeoMipTerrain::
00136 set_focal_point(double x, double y) {
00137   if (!_focal_is_temporary) {
00138     PT(PandaNode) tmpnode = new PandaNode("tmp_focal");
00139     _focal_point = NodePath(tmpnode);
00140   }
00141   _focal_point.set_pos(_root, x, y, 0);
00142   _focal_is_temporary = true;
00143 }
00144 INLINE void GeoMipTerrain::
00145 set_focal_point(LPoint2d fp) {
00146   set_focal_point(fp.get_x(), fp.get_y());
00147 }
00148 INLINE void GeoMipTerrain::
00149 set_focal_point(LPoint2f fp) {
00150   set_focal_point(double(fp.get_x()), double(fp.get_y()));
00151 }
00152 INLINE void GeoMipTerrain::
00153 set_focal_point(LPoint3d fp) {
00154   set_focal_point(fp.get_x(), fp.get_y());
00155 }
00156 INLINE void GeoMipTerrain::
00157 set_focal_point(LPoint3f fp) {
00158   set_focal_point(double(fp.get_x()), double(fp.get_y()));
00159 }
00160 INLINE void GeoMipTerrain::
00161 set_focal_point(NodePath fp) {
00162   if (_focal_is_temporary) {
00163     _focal_point.remove_node();
00164   }
00165   _focal_point = fp;
00166   _focal_is_temporary = false;
00167 }
00168 
00169 ////////////////////////////////////////////////////////////////////
00170 //     Function: GeoMipTerrain::get_focal_point
00171 //       Access: Published
00172 //  Description: Returns the focal point, as a NodePath.
00173 //               If you have set it to be just a point, it will
00174 //               return an empty node at the focal position.
00175 ////////////////////////////////////////////////////////////////////
00176 INLINE NodePath GeoMipTerrain::
00177 get_focal_point() const {
00178   return _focal_point;
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: GeoMipTerrain::get_root
00183 //       Access: Published
00184 //  Description: Returns the root of the terrain.  This is a
00185 //               single PandaNode to which all the rest of the
00186 //               terrain is parented.  The generate and update
00187 //               operations replace the nodes which are parented
00188 //               to this root, but they don't replace this root
00189 //               itself.
00190 ////////////////////////////////////////////////////////////////////
00191 INLINE NodePath GeoMipTerrain::
00192 get_root() const {
00193   return _root;
00194 }
00195 
00196 ////////////////////////////////////////////////////////////////////
00197 //     Function: GeoMipTerrain::set_min_level
00198 //       Access: Published
00199 //  Description: Sets the minimum level of detail at which blocks
00200 //               may be generated by generate() or update().
00201 //               The default value is 0, which is the highest
00202 //               quality. This value is also taken in respect when
00203 //               generating the terrain bruteforce.
00204 ////////////////////////////////////////////////////////////////////
00205 INLINE void GeoMipTerrain::
00206 set_min_level(unsigned short minlevel) {
00207   _min_level = minlevel;
00208 }
00209 
00210 ////////////////////////////////////////////////////////////////////
00211 //     Function: GeoMipTerrain::get_min_level
00212 //       Access: Published
00213 //  Description: Gets the minimum level of detail at which blocks
00214 //               may be generated by generate() or update().
00215 //               The default value is 0, which is the highest
00216 //               quality.
00217 ////////////////////////////////////////////////////////////////////
00218 INLINE unsigned short GeoMipTerrain::
00219 get_min_level() {
00220   return _min_level;
00221 }
00222 
00223 ////////////////////////////////////////////////////////////////////
00224 //     Function: GeoMipTerrain::get_max_level
00225 //       Access: Published
00226 //  Description: Returns the highest level possible for this block
00227 //               size. When a block is at this level, it will be
00228 //               the worst quality possible.
00229 ////////////////////////////////////////////////////////////////////
00230 INLINE unsigned short GeoMipTerrain::
00231 get_max_level() {
00232   return _max_level;
00233 }
00234 
00235 ////////////////////////////////////////////////////////////////////
00236 //     Function: GeoMipTerrain::get_block_size
00237 //       Access: Published
00238 //  Description: Gets the block size.
00239 ////////////////////////////////////////////////////////////////////
00240 INLINE unsigned short GeoMipTerrain::
00241 get_block_size() {
00242   return _block_size;
00243 }
00244 
00245 ////////////////////////////////////////////////////////////////////
00246 //     Function: GeoMipTerrain::set_block_size
00247 //       Access: Published
00248 //  Description: Sets the block size. If it is not a power of two,
00249 //               the closest power of two is used.
00250 ////////////////////////////////////////////////////////////////////
00251 INLINE void GeoMipTerrain::
00252 set_block_size(unsigned short newbs) {
00253   if (is_power_of_two(newbs)) {
00254     _block_size = newbs;
00255   } else {
00256     if (is_power_of_two(newbs - 1)) {
00257       _block_size = newbs - 1;
00258     } else {
00259       if (is_power_of_two(newbs + 1)) {
00260         _block_size = newbs + 1;
00261       } else {
00262         _block_size = (unsigned short) pow(2.0,
00263                             floor(log((double) newbs) / log(2.0) + 0.5));
00264       }
00265     }
00266   }
00267   _max_level = (unsigned short) (log((double) _block_size) / log(2.0));
00268   _is_dirty = true;
00269 }
00270 
00271 ////////////////////////////////////////////////////////////////////
00272 //     Function: GeoMipTerrain::is_dirty
00273 //       Access: Published
00274 //  Description: Returns a bool indicating whether the terrain is
00275 //               marked 'dirty', that means the terrain has to be
00276 //               regenerated on the next update() call, because
00277 //               for instance the heightfield has changed.
00278 //               Once the terrain has been regenerated, the dirty
00279 //               flag automatically gets reset internally.
00280 ////////////////////////////////////////////////////////////////////
00281 INLINE bool GeoMipTerrain::
00282 is_dirty() {
00283   return _is_dirty;
00284 }
00285 
00286 ////////////////////////////////////////////////////////////////////
00287 //     Function: GeoMipTerrain::set_factor
00288 //       Access: Published
00289 //  Description: DEPRECATED method. Use set_near/far instead.
00290 //               Sets the quality factor at which blocks must be
00291 //               generated. The higher this level, the better
00292 //               quality the terrain will be, but more expensive
00293 //               to render. A value of 0 makes the terrain the
00294 //               lowest quality possible, depending on blocksize.
00295 //               The default value is 100.
00296 ////////////////////////////////////////////////////////////////////
00297 INLINE void GeoMipTerrain::
00298 set_factor(float factor) {
00299   grutil_cat.debug() << "Using deprecated method set_factor, use set_near and set_far instead!\n";
00300   _use_near_far = false;
00301   _factor = factor;
00302 }
00303 
00304 ////////////////////////////////////////////////////////////////////
00305 //     Function: GeoMipTerrain::set_near_far
00306 //       Access: Published
00307 //  Description: Sets the near and far LOD distances in one call.
00308 ////////////////////////////////////////////////////////////////////
00309 INLINE void GeoMipTerrain::
00310 set_near_far(double input_near, double input_far) {
00311   _use_near_far = true;
00312   _near = input_near;
00313   _far = input_far;
00314 }
00315 
00316 ////////////////////////////////////////////////////////////////////
00317 //     Function: GeoMipTerrain::set_near
00318 //       Access: Published
00319 //  Description: Sets the near LOD distance, at which the terrain
00320 //               will be rendered at highest quality.
00321 //               This distance is in the terrain's coordinate space!
00322 ////////////////////////////////////////////////////////////////////
00323 INLINE void GeoMipTerrain::
00324 set_near(double input_near) {
00325   _use_near_far = true;
00326   _near = input_near;
00327 }
00328 
00329 ////////////////////////////////////////////////////////////////////
00330 //     Function: GeoMipTerrain::set_far
00331 //       Access: Published
00332 //  Description: Sets the far LOD distance, at which the terrain
00333 //               will be rendered at lowest quality.
00334 //               This distance is in the terrain's coordinate space!
00335 ////////////////////////////////////////////////////////////////////
00336 INLINE void GeoMipTerrain::
00337 set_far(double input_far) {
00338   _use_near_far = true;
00339   _far = input_far;
00340 }
00341 
00342 ////////////////////////////////////////////////////////////////////
00343 //     Function: GeoMipTerrain::get_far
00344 //       Access: Published
00345 //  Description: Returns the far LOD distance in the terrain coordinate
00346 //         space
00347 ////////////////////////////////////////////////////////////////////
00348 INLINE double GeoMipTerrain::
00349 get_far() {
00350   return _far;
00351 }
00352 
00353 ////////////////////////////////////////////////////////////////////
00354 //     Function: GeoMipTerrain::get_near
00355 //       Access: Published
00356 //  Description: Returns the near LOD distance in the terrain coordinate
00357 //         space
00358 ////////////////////////////////////////////////////////////////////
00359 INLINE double GeoMipTerrain::
00360 get_near() {
00361   return _near;
00362 }
00363 
00364 ////////////////////////////////////////////////////////////////////
00365 //     Function: GeoMipTerrain::get_flatten_mode
00366 //       Access: Published
00367 //  Description: Returns the automatic-flatten mode (e.g., off, 
00368 //               flatten_light, flatten_medium, or flatten_strong)
00369 ////////////////////////////////////////////////////////////////////
00370 INLINE int GeoMipTerrain::
00371 get_flatten_mode() {
00372   return _auto_flatten;
00373 }
00374 
00375 ////////////////////////////////////////////////////////////////////
00376 //     Function: GeoMipTerrain::get_block_node_path
00377 //       Access: Published
00378 //  Description: Returns the NodePath of the specified block.
00379 //               If auto-flatten is enabled and the node is
00380 //               getting removed during the flattening process,
00381 //               it will still return a NodePath with the
00382 //               appropriate terrain chunk, but it will be in
00383 //               a temporary scenegraph.
00384 //               Please note that this returns a const object and
00385 //               you can not modify the node. Modify the heightfield
00386 //               instead.
00387 ////////////////////////////////////////////////////////////////////
00388 INLINE const NodePath GeoMipTerrain::
00389 get_block_node_path(unsigned short mx, unsigned short my) {
00390   return _blocks[mx][my];
00391 }
00392 ////////////////////////////////////////////////////////////////////
00393 //     Function: GeoMipTerrain::get_block_from_pos
00394 //       Access: Published
00395 //  Description: Gets the coordinates of the block at the specified
00396 //               position. This position must be relative to the
00397 //               terrain, not to render. Returns an array containing
00398 //               two values: the block x and the block y coords.
00399 //               If the positions are out of range, the closest
00400 //               block is taken.
00401 //               Note that the VecBase returned does not represent
00402 //               a vector, position, or rotation, but it contains
00403 //               the block index of the block which you can use
00404 //               in GeoMipTerrain::get_block_node_path.
00405 ////////////////////////////////////////////////////////////////////
00406 INLINE LVecBase2f GeoMipTerrain::
00407 get_block_from_pos(double x, double y) {
00408   if (x < 0) x = 0;
00409   if (y < 0) y = 0;
00410   if (x > _xsize - 1) x = _xsize - 1;
00411   if (y > _ysize - 1) y = _ysize - 1;
00412   x = floor(x / _block_size);
00413   y = floor(y / _block_size);
00414   return LVecBase2f(x, y);
00415 }
00416 ////////////////////////////////////////////////////////////////////
00417 //     Function: GeoMipTerrain::lod_decide
00418 //       Access: Private
00419 //  Description: Calculates the level for the given mipmap.
00420 ////////////////////////////////////////////////////////////////////
00421 INLINE unsigned short GeoMipTerrain::
00422 lod_decide(unsigned short mx, unsigned short my) {
00423   float cx = mx; 
00424   float cy = my;
00425   cx = (cx * _block_size + _block_size / 2) * _root.get_sx();
00426   cy = (cy * _block_size + _block_size / 2) * _root.get_sy();
00427   float d;
00428   if (_use_near_far) {
00429     d = sqrt(pow(_focal_point.get_x(_root) - cx, 2) +
00430              pow(_focal_point.get_y(_root) - cy, 2));
00431     if (d < _near) {
00432       return 0;
00433     } else if (d > _far) {
00434       return _max_level;
00435     } else {
00436       return (unsigned short)((d - _near) / (_far - _near) * _max_level * (1.0 - (_min_level / _max_level)) + _min_level);
00437     }
00438   } else {
00439     if (_factor > 0.0) {
00440       d = sqrt(pow(_focal_point.get_x(_root) - cx, 2) +
00441                pow(_focal_point.get_y(_root) - cy, 2)) / _factor;
00442     } else {
00443       d = _max_level;
00444     }
00445     return short(floor(d));
00446   }
00447 }
00448 
00449 ////////////////////////////////////////////////////////////////////
00450 //     Function: GeoMipTerrain::set_heightfield
00451 //       Access: Published
00452 //  Description: Loads the specified heightmap image file into
00453 //               the heightfield. Returns true if succeeded, or
00454 //               false if an error has occured.
00455 //               If the heightmap is not a power of two plus one,
00456 //               it is scaled up using a gaussian filter.
00457 ////////////////////////////////////////////////////////////////////
00458 INLINE bool GeoMipTerrain::
00459 set_heightfield(const PNMImage &image) {
00460   // Before we apply anything, validate the size.
00461   if(is_power_of_two(image.get_x_size() - 1) && is_power_of_two(image.get_y_size() - 1)) {
00462     _heightfield = image;
00463     _is_dirty = true;
00464     _xsize = _heightfield.get_x_size();
00465     _ysize = _heightfield.get_y_size();
00466     return true;
00467   } else {
00468     grutil_cat.error() << "Specified image does not have a power-of-two-plus-one size!\n";
00469   }
00470   return false;
00471 }
00472 
00473 INLINE bool GeoMipTerrain::
00474 set_heightfield(const string &path) {
00475   return set_heightfield(Filename(path));
00476 }
00477 
00478 ////////////////////////////////////////////////////////////////////
00479 //     Function: GeoMipTerrain::set_color_map
00480 //       Access: Published
00481 //  Description: Loads the specified image as color map. The next
00482 //               time generate() is called, the terrain is painted
00483 //               with this color map using the vertex color column.
00484 //               Returns a boolean indicating whether the operation
00485 //               has succeeded.
00486 ////////////////////////////////////////////////////////////////////
00487 INLINE bool GeoMipTerrain::
00488 set_color_map(const Filename &filename, PNMFileType *ftype) {
00489   if (_color_map.read(filename, ftype)) {
00490     _is_dirty = true;
00491     _has_color_map = true;
00492     return true;
00493   }
00494   return false;
00495 }
00496 
00497 INLINE bool GeoMipTerrain::
00498 set_color_map(const PNMImage &image) {
00499   _color_map.copy_from(image);
00500   _is_dirty = true;
00501   _has_color_map = true;
00502   return true;
00503 }
00504 
00505 INLINE bool GeoMipTerrain::
00506 set_color_map(const Texture *tex) {
00507   tex->store(_color_map);
00508   _is_dirty = true;
00509   return true;
00510 }
00511 
00512 INLINE bool GeoMipTerrain::
00513 set_color_map(const string &path) {
00514   return set_color_map(Filename(path));
00515 }
00516 
00517 ////////////////////////////////////////////////////////////////////
00518 //     Function: GeoMipTerrain::has_color_map
00519 //       Access: Published
00520 //  Description: Returns whether a color map has been set.
00521 ////////////////////////////////////////////////////////////////////
00522 INLINE bool GeoMipTerrain::
00523 has_color_map() {
00524   return _has_color_map;
00525 }
00526 
00527 ////////////////////////////////////////////////////////////////////
00528 //     Function: GeoMipTerrain::clear_color_map
00529 //       Access: Published
00530 //  Description: Clears the color map.
00531 ////////////////////////////////////////////////////////////////////
00532 INLINE void GeoMipTerrain::
00533 clear_color_map() {
00534   if (_has_color_map) {
00535     _color_map.clear();
00536     _has_color_map = false;
00537   }
00538 }
00539 
00540 ////////////////////////////////////////////////////////////////////
00541 //     Function: GeoMipTerrain::set_border_stitching
00542 //       Access: Published
00543 //  Description: If this value is true, the LOD level at the
00544 //               borders of the terrain will be 0. This is useful
00545 //               if you have multiple terrains attached and you
00546 //               want to stitch them together, to fix seams.
00547 //               This setting also has effect when bruteforce is
00548 //               enabled, although in that case you are probably
00549 //               better off with setting the minlevels to the same
00550 //               value.
00551 ////////////////////////////////////////////////////////////////////
00552 INLINE void GeoMipTerrain::
00553 set_border_stitching(bool stitching) {
00554   if (stitching && !_stitching) {
00555     _is_dirty = true;
00556   }
00557   _stitching = stitching;
00558 }
00559 
00560 ////////////////////////////////////////////////////////////////////
00561 //     Function: GeoMipTerrain::get_stitching
00562 //       Access: Published
00563 //  Description: Returns the current stitching setting. False by
00564 //               default, unless set_stitching has been set.
00565 ////////////////////////////////////////////////////////////////////
00566 INLINE bool GeoMipTerrain::
00567 get_border_stitching() {
00568   return _stitching;
00569 }
00570 
00571 ////////////////////////////////////////////////////////////////////
00572 //     Function: GeoMipTerrain::get_pixel_value
00573 //       Access: Private
00574 //  Description: Get the elevation at a certain pixel of the image.
00575 //               This function does NOT linearly interpolate.
00576 //               For that, use GeoMipTerrain::get_elevation() instead.
00577 ////////////////////////////////////////////////////////////////////
00578 INLINE double GeoMipTerrain::
00579 get_pixel_value(int x, int y) {
00580   x = max(min(x,int(_xsize-1)),0);
00581   y = max(min(y,int(_ysize-1)),0);
00582   if (_heightfield.is_grayscale()) {
00583     return double(_heightfield.get_bright(x, y));
00584   } else {
00585     return double(_heightfield.get_red(x, y))
00586          + double(_heightfield.get_green(x, y)) / 256.0
00587          + double(_heightfield.get_blue(x, y)) / 65536.0;
00588   }
00589 }
00590 INLINE double GeoMipTerrain::
00591 get_pixel_value(unsigned short mx, unsigned short my, int x, int y) {
00592   nassertr_always(mx < (_xsize - 1) / _block_size, false);
00593   nassertr_always(my < (_ysize - 1) / _block_size, false);
00594   return get_pixel_value(mx * _block_size + x, (_ysize - 1) -
00595                          (my * _block_size + y));
00596 }
00597 
00598 ////////////////////////////////////////////////////////////////////
00599 //     Function: GeoMipTerrain::get_normal
00600 //       Access: Published
00601 //  Description: Fetches the terrain normal at (x,y), where the input
00602 //               coordinate is specified in pixels. This ignores the
00603 //               current LOD level and instead provides an
00604 //               accurate number.
00605 //               Terrain scale is NOT taken into account! To get
00606 //               accurate normals, please divide it by the
00607 //               terrain scale and normalize it again!
00608 ////////////////////////////////////////////////////////////////////
00609 INLINE LVector3f GeoMipTerrain::
00610 get_normal(unsigned short mx, unsigned short my, int x, int y) {
00611   nassertr_always(mx < (_xsize - 1) / _block_size, false);
00612   nassertr_always(my < (_ysize - 1) / _block_size, false);
00613   return get_normal(mx * _block_size + x, (_ysize - 1) -
00614                     (my * _block_size + y));
00615 }
00616 
00617 ////////////////////////////////////////////////////////////////////
00618 //     Function: GeoMipTerrain::is_power_of_two
00619 //       Access: Private
00620 //  Description: Returns a bool whether the given int i is a
00621 //               power of two or not.
00622 ////////////////////////////////////////////////////////////////////
00623 INLINE bool GeoMipTerrain::
00624 is_power_of_two(unsigned int i) {
00625   return !((i - 1) & i);
00626 }
00627 
00628 ////////////////////////////////////////////////////////////////////
00629 //     Function: GeoMipTerrain::f_part
00630 //       Access: Private
00631 //  Description: Returns the part of the number right of the
00632 //               floating-point.
00633 ////////////////////////////////////////////////////////////////////
00634 INLINE float GeoMipTerrain::
00635 f_part(float i) {
00636   return i - floor(i);
00637 }
00638 INLINE double GeoMipTerrain::
00639 f_part(double i) {
00640   return i - floor(i);
00641 }
00642 
00643 ////////////////////////////////////////////////////////////////////
00644 //     Function: GeoMipTerrain::sfav
00645 //       Access: Private
00646 //  Description: Used to calculate vertex numbers. Only to
00647 //               be used internally.
00648 ////////////////////////////////////////////////////////////////////
00649 INLINE int GeoMipTerrain::
00650 sfav(int n, int powlevel, int mypowlevel) {
00651   double t = n - 1;
00652   t /= pow(2.0, powlevel - mypowlevel);
00653   t = double(int(t > 0.0 ? t + 0.5 : t - 0.5));
00654   t *= pow(2.0, powlevel - mypowlevel);
00655   return int(t);
00656 }
00657 
 All Classes Functions Variables Enumerations