Panda3D
|
00001 // Filename: stBasicTerrain.I 00002 // Created by: drose (12Oct10) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: STBasicTerrain::set_height_map 00018 // Access: Published 00019 // Description: Specifies the image filename that will define the 00020 // height map of the terrain. This will require a 00021 // subsequent call to load_data() to actually read the 00022 // data. 00023 //////////////////////////////////////////////////////////////////// 00024 INLINE void STBasicTerrain:: 00025 set_height_map(const Filename &height_map) { 00026 _height_map = height_map; 00027 _is_valid = false; 00028 } 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Function: STBasicTerrain::get_height_map 00032 // Access: Published 00033 // Description: Returns the image filename that defines the 00034 // height map of the terrain. 00035 //////////////////////////////////////////////////////////////////// 00036 INLINE const Filename &STBasicTerrain:: 00037 get_height_map() const { 00038 return _height_map; 00039 } 00040 00041 //////////////////////////////////////////////////////////////////// 00042 // Function: STBasicTerrain::get_size 00043 // Access: Published 00044 // Description: Returns the length, in scene graph units, of one edge 00045 // of the heightmap as it is manifested by the terrain. 00046 // Increasing this number spreads the heightmap out over 00047 // a greater area. 00048 //////////////////////////////////////////////////////////////////// 00049 INLINE PN_stdfloat STBasicTerrain:: 00050 get_size() const { 00051 return _size; 00052 } 00053 00054 //////////////////////////////////////////////////////////////////// 00055 // Function: STBasicTerrain::interpolate 00056 // Access: Protected, Static 00057 // Description: Convenience function to calculate the linear 00058 // interpolation from A to B. 00059 //////////////////////////////////////////////////////////////////// 00060 INLINE PN_stdfloat STBasicTerrain:: 00061 interpolate(PN_stdfloat a, PN_stdfloat b, PN_stdfloat t) { 00062 return (a + (b - a) * t); 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: STBasicTerrain::InterpolationData::Constructor 00067 // Access: Public 00068 // Description: 00069 //////////////////////////////////////////////////////////////////// 00070 template<class ValueType> 00071 STBasicTerrain::InterpolationData<ValueType>:: 00072 InterpolationData() : _width(0), _height(0) 00073 { 00074 } 00075 00076 //////////////////////////////////////////////////////////////////// 00077 // Function: STBasicTerrain::InterpolationData::reset 00078 // Access: Public 00079 // Description: Resets the array to an empty array of width x height 00080 // cells. 00081 //////////////////////////////////////////////////////////////////// 00082 template<class ValueType> 00083 void STBasicTerrain::InterpolationData<ValueType>:: 00084 reset(int width, int height) { 00085 _width = width; 00086 _height = height; 00087 _data.clear(); 00088 _data.insert(_data.begin(), width * height, ValueType()); 00089 } 00090 00091 //////////////////////////////////////////////////////////////////// 00092 // Function: STBasicTerrain::InterpolationData::get_nearest_neighbor 00093 // Access: Public 00094 // Description: Returns the value nearest to (u, v) in the data. 00095 //////////////////////////////////////////////////////////////////// 00096 template<class ValueType> 00097 ValueType STBasicTerrain::InterpolationData<ValueType>:: 00098 get_nearest_neighbor(PN_stdfloat u, PN_stdfloat v) const { 00099 int u = int(u * _width + 0.5f); 00100 int v = int(v * _height + 0.5f); 00101 int index = u + v * _width; 00102 nassertr(index >= 0 && index < (int)_data.size(), 0); 00103 return _data[index]; 00104 } 00105 00106 //////////////////////////////////////////////////////////////////// 00107 // Function: STBasicTerrain::InterpolationData::calc_bilnear_interpolation 00108 // Access: Public 00109 // Description: Interpolates the value at (u, v) between its four 00110 // nearest neighbors. 00111 //////////////////////////////////////////////////////////////////// 00112 template<class ValueType> 00113 ValueType STBasicTerrain::InterpolationData<ValueType>:: 00114 calc_bilinear_interpolation(PN_stdfloat u, PN_stdfloat v) const { 00115 u -= cfloor(u); 00116 v -= cfloor(v); 00117 00118 u *= (PN_stdfloat)_width; 00119 v *= (PN_stdfloat)_height; 00120 00121 const int lower_x = int(u); 00122 const int lower_y = int(v); 00123 const int higher_x = (lower_x + 1) % _width; 00124 const int higher_y = (lower_y + 1) % _height; 00125 00126 const PN_stdfloat ratio_x = u - PN_stdfloat(lower_x); 00127 const PN_stdfloat ratio_y = v - PN_stdfloat(lower_y); 00128 const PN_stdfloat inv_ratio_x = 1.0f - ratio_x; 00129 const PN_stdfloat inv_ratio_y = 1.0f - ratio_y; 00130 00131 nassertr(lower_x + lower_y * _width >= 0 && higher_x + higher_y * _width < (int)_data.size(), 0); 00132 00133 const ValueType &t1 = _data[lower_x + lower_y * _width]; 00134 const ValueType &t2 = _data[higher_x + lower_y * _width]; 00135 const ValueType &t3 = _data[lower_x + higher_y * _width]; 00136 const ValueType &t4 = _data[higher_x + higher_y * _width]; 00137 00138 return (t1 * inv_ratio_x + t2 * ratio_x) * inv_ratio_y + 00139 (t3 * inv_ratio_x + t4 * ratio_x) * ratio_y; 00140 } 00141 00142 //////////////////////////////////////////////////////////////////// 00143 // Function: STBasicTerrain::InterpolationData::calc_smooth 00144 // Access: Public 00145 // Description: Approximates the average value at (u, v) over the 00146 // indicated radius, assuming a polynomial curve. 00147 //////////////////////////////////////////////////////////////////// 00148 template<class ValueType> 00149 ValueType STBasicTerrain::InterpolationData<ValueType>:: 00150 calc_smooth(PN_stdfloat u, PN_stdfloat v, PN_stdfloat radius) const { 00151 ValueType retval = 0; 00152 00153 if (radius <= 0.0f) { 00154 retval = calc_bilinear_interpolation(u, v); 00155 00156 } else { 00157 const PN_stdfloat test_points[9][2] = { 00158 { 0.0f * radius, 0.0f * radius }, 00159 { 0.8f * radius, 0.0f * radius }, 00160 { -0.8f * radius, 0.0f * radius }, 00161 { 0.0f * radius, 0.8f * radius }, 00162 { 0.0f * radius, -0.8f * radius }, 00163 { 0.25f * radius, 0.25f * radius }, 00164 { 0.25f * radius, -0.25f * radius }, 00165 { -0.25f * radius, 0.25f * radius }, 00166 { -0.25f * radius, -0.25f * radius } 00167 }; 00168 00169 PN_stdfloat total_weight = 0.0f; 00170 for (int i = 0; i < 9; ++i) { 00171 const PN_stdfloat *test_point = test_points[i]; 00172 PN_stdfloat weight = (1.0f - sqrt((test_point[0] * test_point[0]) + (test_point[1] * test_point[1]))); 00173 total_weight += weight; 00174 retval += weight * calc_bilinear_interpolation(u + test_point[0], v + test_point[1]); 00175 } 00176 00177 retval /= total_weight; 00178 } 00179 00180 return retval; 00181 } 00182 00183 //////////////////////////////////////////////////////////////////// 00184 // Function: STBasicTerrain::InterpolationData::is_present 00185 // Access: Public 00186 // Description: Returns true if the data is present--that is, reset() 00187 // was called with non-zero values--or false otherwise. 00188 //////////////////////////////////////////////////////////////////// 00189 template<class ValueType> 00190 bool STBasicTerrain::InterpolationData<ValueType>:: 00191 is_present() const { 00192 return !_data.empty(); 00193 }