Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
csTerrainSegmentCellCollider Class Reference

#include <segmentcell.h>

Public Member Functions

 csTerrainSegmentCellCollider (iTerrainCell *cell, const csVector3 &start, const csVector3 &end)
 
int GetIntersection (csVector3 &result, csVector2 &cell_result)
 

Detailed Description

Definition at line 20 of file segmentcell.h.

Constructor & Destructor Documentation

csTerrainSegmentCellCollider::csTerrainSegmentCellCollider ( iTerrainCell *  cell,
const csVector3 start,
const csVector3 end 
)
inline

Definition at line 51 of file segmentcell.h.

References csMax(), csMin(), SMALL_EPSILON, csVector3::x, csVector3::y, and csVector3::z.

53  : start(start), end(end), pos(cell->GetPosition ()), size(cell->GetSize ()),
54  vertical (false), verticalhit (false)
55  {
56  // Constants
57  const float rootOf2 = 1.414213f;
58  const float halfRoot2 = rootOf2 / 2;
59 
60  this->cell = cell;
61 
62  width = cell->GetGridWidth ();
63  height = cell->GetGridHeight ();
64 
65  scale_u = size.x / (width - 1);
66  scale_v = size.z / (height - 1);
67 
68  // Offset from grid 0,0
69  const csVector2 gridOffsetStart = csVector2(start.x - pos.x,
70  -(start.z - (pos.y + size.z)));
71  const csVector2 gridOffsetEnd = csVector2(end.x - pos.x,
72  -(end.z - (pos.y + size.z)));
73 
74  // U, V and height of segment start in cell space
75  u0 = (gridOffsetStart.x) / scale_u;
76  v0 = (gridOffsetStart.y) / scale_v;
77  h0 = start.y;
78 
79  // U, V and height of segment end in cell space
80  u1 = (gridOffsetEnd.x) / scale_u;
81  v1 = (gridOffsetEnd.y) / scale_v;
82  h1 = end.y;
83 
84  // Compute differences for ray (lengths along axes) and their inverse
85  du = u1 - u0;
86  dv = v1 - v0;
87  dh = h1 - h0;
88 
89  // vertical case
90  if (du == 0 && dv == 0)
91  {
92  vertical = true;
93 
94  float height = cell->GetHeight (gridOffsetStart);
95  if (csMin(h0, h1) <= height &&
96  csMax(h0, h1) >= height)
97  {
98  verticalhit = true;
99  }
100  }
101 
102  if (fabs (du) < SMALL_EPSILON) du = SMALL_EPSILON;
103  if (fabs (dv) < SMALL_EPSILON) dv = SMALL_EPSILON;
104 
105  oneOverdu = 1 / du;
106  oneOverdv = 1 / dv;
107 
108  // Distance to intersection with u/v axes
109  eu = u0 - floor(u0);
110  ev = v0 - floor(v0);
111 
112  // Differences and distance to intersection with diagonal
113  dp = (du + dv) / rootOf2;
114 
115  if (fabs (dp) < SMALL_EPSILON) dp = SMALL_EPSILON;
116 
117  oneOverdp = 1 / dp;
118  ep = fabs(dp) * (1 - eu - ev) / (dv + du); // line-line intersection
119 
120  // Fixup for positive directions
121  if (du > 0) eu = 1 - eu;
122  if (dv > 0) ev = 1 - ev;
123  if (ep < 0) ep += halfRoot2;
124 
125  // Stepping variables
126  t = 0;
127  h = h0;
128  cell_height = cell->GetHeight (gridOffsetStart);
129 
130  firsttime = true;
131  }

Member Function Documentation

int csTerrainSegmentCellCollider::GetIntersection ( csVector3 result,
csVector2 &  cell_result 
)
inline

Definition at line 136 of file segmentcell.h.

References EPSILON, csVector3::x, csVector3::y, and csVector3::z.

137  {
138  // Constants
139  const float rootOf2 = 1.414213f;
140  const float halfRoot2 = rootOf2 / 2;
141 
142  if (t < 0 || t >= 1) return -1;
143  if (!(t < 0) && !(t >= 0)) return -1;
144 
145  float r_h0 = h;
146  float tstep = 0;
147 
148  if (vertical)
149  {
150  if (verticalhit && firsttime)
151  {
152  firsttime = false;
153 
154  cell_result.x = u0;
155  cell_result.y = v0;
156 
157  result.x = pos.x + cell_result.x * scale_u;
158  result.y = cell_height;
159  result.z = pos.y + height - cell_result.y * scale_v;
160 
161  return 1;
162  }
163  else
164  {
165  return -1;
166  }
167  }
168 
169  if (!firsttime)
170  {
171  float tToU = eu * fabs (oneOverdu); // Time to reach U intersection
172  float tToV = ev * fabs (oneOverdv); // Time to reach V intersection
173  float tToP = ep * fabs (oneOverdp); // Time to reach P intersection
174 
175  if (tToU <= tToV && tToU <= tToP)
176  {
177  // U intersection first
178  if (t + tToU > 1) tToU = 1 - t;
179 
180  tstep = tToU;
181  t += tToU;
182 
183  // Update distances
184  eu = 0;
185  ev -= fabs(dv) * tToU;
186  ep -= fabs(dp) * tToU;
187 
188  // Update height
189  h += dh * tToU;
190  }
191  else if (tToV <= tToU && tToV <= tToP)
192  {
193  // V intersection first
194  if (t + tToV > 1) tToV = 1 - t;
195 
196  tstep = tToV;
197  t += tToV;
198 
199  // Update distances
200  eu -= fabs(du) * tToV;
201  ev = 0;
202  ep -= fabs(dp) * tToV;
203 
204  // Update height
205  h += dh * tToV;
206  }
207  else
208  {
209  // P intersection first
210  if (t + tToP > 1) tToP = 1 - t;
211 
212  tstep = tToP;
213  t += tToP;
214 
215  // Update distances
216  eu -= fabs(du) * tToP;
217  ev -= fabs(dv) * tToP;
218  ep = 0;
219 
220  // Update height
221  h += dh * tToP;
222  }
223 
224  // Wrap around
225  if (eu <= 0) eu = 1;
226  if (ev <= 0) ev = 1;
227  if (ep <= 0) ep = halfRoot2;
228  }
229 
230  firsttime = false;
231 
232  // Check for intersection
233  float r_h1 = h;
234  float h_h0 = cell_height;
235 
236  csVector2 uv = csVector2 ((u0 + du * t) * scale_u,
237  (v0 + dv * t) * scale_v);
238  float h_h1 = cell->GetHeight (uv);
239 
240  // Remember height value
241  cell_height = h_h1;
242 
243  // Check intersection
244  int cmp_h0 = sign (r_h0 - h_h0);
245  int cmp_h1 = sign (r_h1 - h_h1);
246 
247  if (cmp_h0 * cmp_h1 == -1 || fabs (r_h1 - h_h1) < EPSILON)
248  {
249  float correct_t = t;
250 
251  if (cmp_h0 * cmp_h1 == -1)
252  {
253  // A B C
254  // (vertex) ------(intersection)------- (vertex)
255  // AC = tstep (in terms of t), we have to subtract
256  // BC from correct_t. AB / BC equals the height ratio
257  float coeff = fabs(r_h0 - h_h0) / fabs(r_h1 - h_h1);
258 
259  // AB / BC = coeff
260  // AB + BC = tstep
261  // AB = coeff * BC
262  // BC * (coeff + 1) = tstep
263 
264  correct_t -= tstep / (coeff + 1);
265  }
266 
267  cell_result.x = u0 + du * correct_t;
268  cell_result.y = v0 + dv * correct_t;
269 
270  result.x = pos.x + cell_result.x * scale_u;
271  result.y = h0 + dh * correct_t;
272  result.z = pos.y + height - cell_result.y * scale_v;
273 
274  return (cell_result.x >=0 && cell_result.x <= width - 1 &&
275  cell_result.y >=0 && cell_result.y <= height - 1);
276  }
277 
278  return 0;
279  }

The documentation for this class was generated from the following file: