Panda3D
stBasicTerrain.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file stBasicTerrain.I
10  * @author drose
11  * @date 2010-10-12
12  */
13 
14 /**
15  * Specifies the image filename that will define the height map of the
16  * terrain. This will require a subsequent call to load_data() to actually
17  * read the data.
18  */
19 INLINE void STBasicTerrain::
20 set_height_map(const Filename &height_map) {
21  _height_map = height_map;
22  _is_valid = false;
23 }
24 
25 /**
26  * Returns the image filename that defines the height map of the terrain.
27  */
28 INLINE const Filename &STBasicTerrain::
29 get_height_map() const {
30  return _height_map;
31 }
32 
33 /**
34  * Returns the length, in scene graph units, of one edge of the heightmap as
35  * it is manifested by the terrain. Increasing this number spreads the
36  * heightmap out over a greater area.
37  */
38 INLINE PN_stdfloat STBasicTerrain::
39 get_size() const {
40  return _size;
41 }
42 
43 /**
44  * Convenience function to calculate the linear interpolation from A to B.
45  */
46 INLINE PN_stdfloat STBasicTerrain::
47 interpolate(PN_stdfloat a, PN_stdfloat b, PN_stdfloat t) {
48  return (a + (b - a) * t);
49 }
50 
51 /**
52  *
53  */
54 template<class ValueType>
55 STBasicTerrain::InterpolationData<ValueType>::
56 InterpolationData() : _width(0), _height(0)
57 {
58 }
59 
60 /**
61  * Resets the array to an empty array of width x height cells.
62  */
63 template<class ValueType>
64 void STBasicTerrain::InterpolationData<ValueType>::
65 reset(int width, int height) {
66  _width = width;
67  _height = height;
68  _data.clear();
69  _data.insert(_data.begin(), width * height, ValueType());
70 }
71 
72 /**
73  * Returns the value nearest to (u, v) in the data.
74  */
75 template<class ValueType>
76 ValueType STBasicTerrain::InterpolationData<ValueType>::
77 get_nearest_neighbor(PN_stdfloat u, PN_stdfloat v) const {
78  int u = int(u * _width + 0.5f);
79  int v = int(v * _height + 0.5f);
80  int index = u + v * _width;
81  nassertr(index >= 0 && index < (int)_data.size(), 0);
82  return _data[index];
83 }
84 
85 /**
86  * Interpolates the value at (u, v) between its four nearest neighbors.
87  */
88 template<class ValueType>
89 ValueType STBasicTerrain::InterpolationData<ValueType>::
90 calc_bilinear_interpolation(PN_stdfloat u, PN_stdfloat v) const {
91  u -= cfloor(u);
92  v -= cfloor(v);
93 
94  u *= (PN_stdfloat)_width;
95  v *= (PN_stdfloat)_height;
96 
97  const int lower_x = int(u);
98  const int lower_y = int(v);
99  const int higher_x = (lower_x + 1) % _width;
100  const int higher_y = (lower_y + 1) % _height;
101 
102  const PN_stdfloat ratio_x = u - PN_stdfloat(lower_x);
103  const PN_stdfloat ratio_y = v - PN_stdfloat(lower_y);
104  const PN_stdfloat inv_ratio_x = 1.0f - ratio_x;
105  const PN_stdfloat inv_ratio_y = 1.0f - ratio_y;
106 
107  nassertr(lower_x + lower_y * _width >= 0 && higher_x + higher_y * _width < (int)_data.size(), 0);
108 
109  const ValueType &t1 = _data[lower_x + lower_y * _width];
110  const ValueType &t2 = _data[higher_x + lower_y * _width];
111  const ValueType &t3 = _data[lower_x + higher_y * _width];
112  const ValueType &t4 = _data[higher_x + higher_y * _width];
113 
114  return (t1 * inv_ratio_x + t2 * ratio_x) * inv_ratio_y +
115  (t3 * inv_ratio_x + t4 * ratio_x) * ratio_y;
116 }
117 
118 /**
119  * Approximates the average value at (u, v) over the indicated radius,
120  * assuming a polynomial curve.
121  */
122 template<class ValueType>
123 ValueType STBasicTerrain::InterpolationData<ValueType>::
124 calc_smooth(PN_stdfloat u, PN_stdfloat v, PN_stdfloat radius) const {
125  ValueType retval = 0;
126 
127  if (radius <= 0.0f) {
128  retval = calc_bilinear_interpolation(u, v);
129 
130  } else {
131  const PN_stdfloat test_points[9][2] = {
132  { 0.0f * radius, 0.0f * radius },
133  { 0.8f * radius, 0.0f * radius },
134  { -0.8f * radius, 0.0f * radius },
135  { 0.0f * radius, 0.8f * radius },
136  { 0.0f * radius, -0.8f * radius },
137  { 0.25f * radius, 0.25f * radius },
138  { 0.25f * radius, -0.25f * radius },
139  { -0.25f * radius, 0.25f * radius },
140  { -0.25f * radius, -0.25f * radius }
141  };
142 
143  PN_stdfloat total_weight = 0.0f;
144  for (int i = 0; i < 9; ++i) {
145  const PN_stdfloat *test_point = test_points[i];
146  PN_stdfloat weight = (1.0f - sqrt((test_point[0] * test_point[0]) + (test_point[1] * test_point[1])));
147  total_weight += weight;
148  retval += weight * calc_bilinear_interpolation(u + test_point[0], v + test_point[1]);
149  }
150 
151  retval /= total_weight;
152  }
153 
154  return retval;
155 }
156 
157 /**
158  * Returns true if the data is present--that is, reset() was called with non-
159  * zero values--or false otherwise.
160  */
161 template<class ValueType>
162 bool STBasicTerrain::InterpolationData<ValueType>::
163 is_present() const {
164  return !_data.empty();
165 }
void set_height_map(const Filename &height_map)
Specifies the image filename that will define the height map of the terrain.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
const Filename & get_height_map() const
Returns the image filename that defines the height map of the terrain.
PN_stdfloat get_size() const
Returns the length, in scene graph units, of one edge of the heightmap as it is manifested by the ter...