diff options
Diffstat (limited to 'libraries/ode-0.9\/contrib/TerrainAndCone/dTerrainY.cpp')
-rwxr-xr-x | libraries/ode-0.9\/contrib/TerrainAndCone/dTerrainY.cpp | 662 |
1 files changed, 662 insertions, 0 deletions
diff --git a/libraries/ode-0.9\/contrib/TerrainAndCone/dTerrainY.cpp b/libraries/ode-0.9\/contrib/TerrainAndCone/dTerrainY.cpp new file mode 100755 index 0000000..ff779ac --- /dev/null +++ b/libraries/ode-0.9\/contrib/TerrainAndCone/dTerrainY.cpp | |||
@@ -0,0 +1,662 @@ | |||
1 | //Benoit CHAPEROT 2003-2004 www.jstarlab.com | ||
2 | //some code inspired by Magic Software | ||
3 | #include <ode/common.h> | ||
4 | #include <ode/collision.h> | ||
5 | #include <ode/matrix.h> | ||
6 | #include <ode/rotation.h> | ||
7 | #include <ode/odemath.h> | ||
8 | #include "collision_kernel.h" | ||
9 | #include "collision_std.h" | ||
10 | #include "collision_std_internal.h" | ||
11 | #include "collision_util.h" | ||
12 | //#include <drawstuff/drawstuff.h> | ||
13 | #include "windows.h" | ||
14 | #include "ode\ode.h" | ||
15 | |||
16 | #define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip))) | ||
17 | #define MAXCONTACT 10 | ||
18 | #define TERRAINTOL 0.0f | ||
19 | |||
20 | static bool IsAPowerOfTwo(int f) | ||
21 | { | ||
22 | dAASSERT(f!=0); | ||
23 | while ((f&1) != 1) | ||
24 | f >>= 1; | ||
25 | |||
26 | return (f == 1); | ||
27 | } | ||
28 | |||
29 | static int GetPowerOfTwo(int f) | ||
30 | { | ||
31 | dAASSERT(f!=0); | ||
32 | int n = 0; | ||
33 | while ((f&1) != 1) | ||
34 | { | ||
35 | n++; | ||
36 | f >>= 1; | ||
37 | } | ||
38 | |||
39 | return n; | ||
40 | } | ||
41 | |||
42 | dxTerrainY::dxTerrainY (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable) : | ||
43 | dxGeom (space,bPlaceable) | ||
44 | { | ||
45 | dIASSERT(IsAPowerOfTwo(nNumNodesPerSide)); | ||
46 | dIASSERT(pHeights); | ||
47 | dIASSERT(vLength > 0.f); | ||
48 | dIASSERT(nNumNodesPerSide > 0); | ||
49 | type = dTerrainYClass; | ||
50 | m_vLength = vLength; | ||
51 | m_pHeights = new dReal[nNumNodesPerSide * nNumNodesPerSide]; | ||
52 | dIASSERT(m_pHeights); | ||
53 | m_nNumNodesPerSide = nNumNodesPerSide; | ||
54 | m_vNodeLength = m_vLength / m_nNumNodesPerSide; | ||
55 | m_nNumNodesPerSideShift = GetPowerOfTwo(m_nNumNodesPerSide); | ||
56 | m_nNumNodesPerSideMask = m_nNumNodesPerSide - 1; | ||
57 | m_vMinHeight = dInfinity; | ||
58 | m_vMaxHeight = -dInfinity; | ||
59 | m_bFinite = bFinite; | ||
60 | |||
61 | for (int i=0;i<nNumNodesPerSide * nNumNodesPerSide;i++) | ||
62 | { | ||
63 | m_pHeights[i] = pHeights[i]; | ||
64 | if (m_pHeights[i] < m_vMinHeight) m_vMinHeight = m_pHeights[i]; | ||
65 | if (m_pHeights[i] > m_vMaxHeight) m_vMaxHeight = m_pHeights[i]; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | dxTerrainY::~dxTerrainY() | ||
70 | { | ||
71 | dIASSERT(m_pHeights); | ||
72 | delete [] m_pHeights; | ||
73 | } | ||
74 | |||
75 | void dxTerrainY::computeAABB() | ||
76 | { | ||
77 | if (m_bFinite) | ||
78 | { | ||
79 | if (gflags & GEOM_PLACEABLE) | ||
80 | { | ||
81 | dReal dx[6],dy[6],dz[6]; | ||
82 | dx[0] = 0; | ||
83 | dx[1] = final_posr->R[0] * m_vLength; | ||
84 | dx[2] = final_posr->R[1] * m_vMinHeight; | ||
85 | dx[3] = final_posr->R[1] * m_vMaxHeight; | ||
86 | dx[4] = 0; | ||
87 | dx[5] = final_posr->R[2] * m_vLength; | ||
88 | |||
89 | dy[0] = 0; | ||
90 | dy[1] = final_posr->R[4] * m_vLength; | ||
91 | dy[2] = final_posr->R[5] * m_vMinHeight; | ||
92 | dy[3] = final_posr->R[5] * m_vMaxHeight; | ||
93 | dy[4] = 0; | ||
94 | dy[5] = final_posr->R[6] * m_vLength; | ||
95 | |||
96 | dz[0] = 0; | ||
97 | dz[1] = final_posr->R[8] * m_vLength; | ||
98 | dz[2] = final_posr->R[9] * m_vMinHeight; | ||
99 | dz[3] = final_posr->R[9] * m_vMaxHeight; | ||
100 | dz[4] = 0; | ||
101 | dz[5] = final_posr->R[10] * m_vLength; | ||
102 | |||
103 | aabb[0] = final_posr->pos[0] + MIN(dx[0],dx[1]) + MIN(dx[2],dx[3]) + MIN(dx[4],dx[5]); | ||
104 | aabb[1] = final_posr->pos[0] + MAX(dx[0],dx[1]) + MAX(dx[2],dx[3]) + MAX(dx[4],dx[5]); | ||
105 | aabb[2] = final_posr->pos[1] + MIN(dy[0],dy[1]) + MIN(dy[2],dy[3]) + MIN(dy[4],dy[5]); | ||
106 | aabb[3] = final_posr->pos[1] + MAX(dy[0],dy[1]) + MAX(dy[2],dy[3]) + MAX(dy[4],dy[5]); | ||
107 | aabb[4] = final_posr->pos[2] + MIN(dz[0],dz[1]) + MIN(dz[2],dz[3]) + MIN(dz[4],dz[5]); | ||
108 | aabb[5] = final_posr->pos[2] + MAX(dz[0],dz[1]) + MAX(dz[2],dz[3]) + MAX(dz[4],dz[5]); | ||
109 | } | ||
110 | else | ||
111 | { | ||
112 | aabb[0] = 0; | ||
113 | aabb[1] = m_vLength; | ||
114 | aabb[2] = m_vMinHeight; | ||
115 | aabb[3] = m_vMaxHeight; | ||
116 | aabb[4] = 0; | ||
117 | aabb[5] = m_vLength; | ||
118 | } | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | if (gflags & GEOM_PLACEABLE) | ||
123 | { | ||
124 | aabb[0] = -dInfinity; | ||
125 | aabb[1] = dInfinity; | ||
126 | aabb[2] = -dInfinity; | ||
127 | aabb[3] = dInfinity; | ||
128 | aabb[4] = -dInfinity; | ||
129 | aabb[5] = dInfinity; | ||
130 | } | ||
131 | else | ||
132 | { | ||
133 | aabb[0] = -dInfinity; | ||
134 | aabb[1] = dInfinity; | ||
135 | aabb[2] = m_vMinHeight; | ||
136 | aabb[3] = m_vMaxHeight; | ||
137 | aabb[4] = -dInfinity; | ||
138 | aabb[5] = dInfinity; | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | |||
143 | dReal dxTerrainY::GetHeight(int x,int z) | ||
144 | { | ||
145 | return m_pHeights[ (((unsigned int)(z) & m_nNumNodesPerSideMask) << m_nNumNodesPerSideShift) | ||
146 | + ((unsigned int)(x) & m_nNumNodesPerSideMask)]; | ||
147 | } | ||
148 | |||
149 | dReal dxTerrainY::GetHeight(dReal x,dReal z) | ||
150 | { | ||
151 | int nX = int(floor(x / m_vNodeLength)); | ||
152 | int nZ = int(floor(z / m_vNodeLength)); | ||
153 | dReal dx = (x - (dReal(nX) * m_vNodeLength)) / m_vNodeLength; | ||
154 | dReal dz = (z - (dReal(nZ) * m_vNodeLength)) / m_vNodeLength; | ||
155 | dIASSERT((dx >= 0.f) && (dx <= 1.f)); | ||
156 | dIASSERT((dz >= 0.f) && (dz <= 1.f)); | ||
157 | |||
158 | dReal y,y0; | ||
159 | |||
160 | if (dx + dz < 1.f) | ||
161 | { | ||
162 | y0 = GetHeight(nX,nZ); | ||
163 | y = y0 | ||
164 | + (GetHeight(nX+1,nZ) - y0) * dx | ||
165 | + (GetHeight(nX,nZ+1) - y0) * dz; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | y0 = GetHeight(nX+1,nZ+1); | ||
170 | y = y0 | ||
171 | + (GetHeight(nX+1,nZ) - y0) * (1.f - dz) | ||
172 | + (GetHeight(nX,nZ+1) - y0) * (1.f - dx); | ||
173 | } | ||
174 | |||
175 | return y; | ||
176 | } | ||
177 | |||
178 | bool dxTerrainY::IsOnTerrain(int nx,int nz,int w,dReal *pos) | ||
179 | { | ||
180 | dVector3 Min,Max; | ||
181 | Min[0] = nx * m_vNodeLength; | ||
182 | Min[2] = nz * m_vNodeLength; | ||
183 | Max[0] = (nx+1) * m_vNodeLength; | ||
184 | Max[2] = (nz+1) * m_vNodeLength; | ||
185 | dReal Tol = m_vNodeLength * TERRAINTOL; | ||
186 | |||
187 | if ((pos[0]<Min[0]-Tol) || (pos[0]>Max[0]+Tol)) | ||
188 | return false; | ||
189 | |||
190 | if ((pos[2]<Min[2]-Tol) || (pos[2]>Max[2]+Tol)) | ||
191 | return false; | ||
192 | |||
193 | dReal dx = (pos[0] - (dReal(nx) * m_vNodeLength)) / m_vNodeLength; | ||
194 | dReal dz = (pos[2] - (dReal(nz) * m_vNodeLength)) / m_vNodeLength; | ||
195 | |||
196 | if ((w == 0) && (dx + dz > 1.f+TERRAINTOL)) | ||
197 | return false; | ||
198 | |||
199 | if ((w == 1) && (dx + dz < 1.f-TERRAINTOL)) | ||
200 | return false; | ||
201 | |||
202 | return true; | ||
203 | } | ||
204 | |||
205 | dGeomID dCreateTerrainY(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable) | ||
206 | { | ||
207 | return new dxTerrainY(space, pHeights,vLength,nNumNodesPerSide,bFinite,bPlaceable); | ||
208 | } | ||
209 | |||
210 | dReal dGeomTerrainYPointDepth (dGeomID g, dReal x, dReal y, dReal z) | ||
211 | { | ||
212 | dUASSERT (g && g->type == dTerrainYClass,"argument not a terrain"); | ||
213 | g->recomputePosr(); | ||
214 | dxTerrainY *t = (dxTerrainY*) g; | ||
215 | return t->GetHeight(x,z) - y; | ||
216 | } | ||
217 | |||
218 | typedef dReal dGetDepthFn(dGeomID g, dReal x, dReal y, dReal z); | ||
219 | #define RECOMPUTE_RAYNORMAL | ||
220 | //#define DO_RAYDEPTH | ||
221 | |||
222 | #define DMESS(A) \ | ||
223 | dMessage(0,"Contact Plane (%d %d %d) %.5e %.5e (%.5e %.5e %.5e)(%.5e %.5e %.5e)).", \ | ||
224 | x,z,A, \ | ||
225 | pContact->depth, \ | ||
226 | dGeomSphereGetRadius(o2), \ | ||
227 | pContact->pos[0], \ | ||
228 | pContact->pos[1], \ | ||
229 | pContact->pos[2], \ | ||
230 | pContact->normal[0], \ | ||
231 | pContact->normal[1], \ | ||
232 | pContact->normal[2]); | ||
233 | /* | ||
234 | (y is up) | ||
235 | |||
236 | A-B-E.x | ||
237 | |/| | ||
238 | C-D | ||
239 | | | ||
240 | F | ||
241 | . | ||
242 | z | ||
243 | */ | ||
244 | int dxTerrainY::dCollideTerrainUnit( | ||
245 | int x,int z,dxGeom *o2,int numMaxContacts, | ||
246 | int flags,dContactGeom *contact, int skip) | ||
247 | { | ||
248 | dColliderFn *CollideRayN; | ||
249 | dColliderFn *CollideNPlane; | ||
250 | dGetDepthFn *GetDepth; | ||
251 | int numContacts = 0; | ||
252 | int numPlaneContacts = 0; | ||
253 | int i; | ||
254 | |||
255 | if (numContacts == numMaxContacts) | ||
256 | return numContacts; | ||
257 | |||
258 | dContactGeom PlaneContact[MAXCONTACT]; | ||
259 | flags = (flags & 0xffff0000) | MAXCONTACT; | ||
260 | |||
261 | switch (o2->type) | ||
262 | { | ||
263 | case dSphereClass: | ||
264 | CollideRayN = dCollideRaySphere; | ||
265 | CollideNPlane = dCollideSpherePlane; | ||
266 | GetDepth = dGeomSpherePointDepth; | ||
267 | break; | ||
268 | case dBoxClass: | ||
269 | CollideRayN = dCollideRayBox; | ||
270 | CollideNPlane = dCollideBoxPlane; | ||
271 | GetDepth = dGeomBoxPointDepth; | ||
272 | break; | ||
273 | case dCCylinderClass: | ||
274 | CollideRayN = dCollideRayCCylinder; | ||
275 | CollideNPlane = dCollideCCylinderPlane; | ||
276 | GetDepth = dGeomCCylinderPointDepth; | ||
277 | break; | ||
278 | case dRayClass: | ||
279 | CollideRayN = NULL; | ||
280 | CollideNPlane = dCollideRayPlane; | ||
281 | GetDepth = NULL; | ||
282 | break; | ||
283 | case dConeClass: | ||
284 | CollideRayN = dCollideRayCone; | ||
285 | CollideNPlane = dCollideConePlane; | ||
286 | GetDepth = dGeomConePointDepth; | ||
287 | break; | ||
288 | default: | ||
289 | dIASSERT(0); | ||
290 | } | ||
291 | |||
292 | dReal Plane[4],lBD,lCD,lBC; | ||
293 | dVector3 A,B,C,D,BD,CD,BC,AB,AC; | ||
294 | A[0] = x * m_vNodeLength; | ||
295 | A[2] = z* m_vNodeLength; | ||
296 | A[1] = GetHeight(x,z); | ||
297 | B[0] = (x+1) * m_vNodeLength; | ||
298 | B[2] = z * m_vNodeLength; | ||
299 | B[1] = GetHeight(x+1,z); | ||
300 | C[0] = x * m_vNodeLength; | ||
301 | C[2] = (z+1) * m_vNodeLength; | ||
302 | C[1] = GetHeight(x,z+1); | ||
303 | D[0] = (x+1) * m_vNodeLength; | ||
304 | D[2] = (z+1) * m_vNodeLength; | ||
305 | D[1] = GetHeight(x+1,z+1); | ||
306 | |||
307 | dOP(BC,-,C,B); | ||
308 | lBC = dLENGTH(BC); | ||
309 | dOPEC(BC,/=,lBC); | ||
310 | |||
311 | dOP(BD,-,D,B); | ||
312 | lBD = dLENGTH(BD); | ||
313 | dOPEC(BD,/=,lBD); | ||
314 | |||
315 | dOP(CD,-,D,C); | ||
316 | lCD = dLENGTH(CD); | ||
317 | dOPEC(CD,/=,lCD); | ||
318 | |||
319 | dOP(AB,-,B,A); | ||
320 | dNormalize3(AB); | ||
321 | |||
322 | dOP(AC,-,C,A); | ||
323 | dNormalize3(AC); | ||
324 | |||
325 | if (CollideRayN) | ||
326 | { | ||
327 | #ifdef RECOMPUTE_RAYNORMAL | ||
328 | dVector3 E,F; | ||
329 | dVector3 CE,FB,AD; | ||
330 | dVector3 Normal[3]; | ||
331 | E[0] = (x+2) * m_vNodeLength; | ||
332 | E[2] = z * m_vNodeLength; | ||
333 | E[1] = GetHeight(x+2,z); | ||
334 | F[0] = x * m_vNodeLength; | ||
335 | F[2] = (z+2) * m_vNodeLength; | ||
336 | F[1] = GetHeight(x,z+2); | ||
337 | dOP(AD,-,D,A); | ||
338 | dNormalize3(AD); | ||
339 | dOP(CE,-,E,C); | ||
340 | dNormalize3(CE); | ||
341 | dOP(FB,-,B,F); | ||
342 | dNormalize3(FB); | ||
343 | |||
344 | //BC | ||
345 | dCROSS(Normal[0],=,BC,AD); | ||
346 | dNormalize3(Normal[0]); | ||
347 | |||
348 | //BD | ||
349 | dCROSS(Normal[1],=,BD,CE); | ||
350 | dNormalize3(Normal[1]); | ||
351 | |||
352 | //CD | ||
353 | dCROSS(Normal[2],=,CD,FB); | ||
354 | dNormalize3(Normal[2]); | ||
355 | #endif | ||
356 | int nA[3],nB[3]; | ||
357 | dContactGeom ContactA[3],ContactB[3]; | ||
358 | dxRay rayBC(0,lBC); | ||
359 | dGeomRaySet(&rayBC, B[0], B[1], B[2], BC[0], BC[1], BC[2]); | ||
360 | nA[0] = CollideRayN(&rayBC,o2,flags,&ContactA[0],sizeof(dContactGeom)); | ||
361 | dGeomRaySet(&rayBC, C[0], C[1], C[2], -BC[0], -BC[1], -BC[2]); | ||
362 | nB[0] = CollideRayN(&rayBC,o2,flags,&ContactB[0],sizeof(dContactGeom)); | ||
363 | |||
364 | dxRay rayBD(0,lBD); | ||
365 | dGeomRaySet(&rayBD, B[0], B[1], B[2], BD[0], BD[1], BD[2]); | ||
366 | nA[1] = CollideRayN(&rayBD,o2,flags,&ContactA[1],sizeof(dContactGeom)); | ||
367 | dGeomRaySet(&rayBD, D[0], D[1], D[2], -BD[0], -BD[1], -BD[2]); | ||
368 | nB[1] = CollideRayN(&rayBD,o2,flags,&ContactB[1],sizeof(dContactGeom)); | ||
369 | |||
370 | dxRay rayCD(0,lCD); | ||
371 | dGeomRaySet(&rayCD, C[0], C[1], C[2], CD[0], CD[1], CD[2]); | ||
372 | nA[2] = CollideRayN(&rayCD,o2,flags,&ContactA[2],sizeof(dContactGeom)); | ||
373 | dGeomRaySet(&rayCD, D[0], D[1], D[2], -CD[0], -CD[1], -CD[2]); | ||
374 | nB[2] = CollideRayN(&rayCD,o2,flags,&ContactB[2],sizeof(dContactGeom)); | ||
375 | |||
376 | for (i=0;i<3;i++) | ||
377 | { | ||
378 | if (nA[i] & nB[i]) | ||
379 | { | ||
380 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
381 | pContact->pos[0] = (ContactA[i].pos[0] + ContactB[i].pos[0])/2; | ||
382 | pContact->pos[1] = (ContactA[i].pos[1] + ContactB[i].pos[1])/2; | ||
383 | pContact->pos[2] = (ContactA[i].pos[2] + ContactB[i].pos[2])/2; | ||
384 | #ifdef RECOMPUTE_RAYNORMAL | ||
385 | pContact->normal[0] = -Normal[i][0]; | ||
386 | pContact->normal[1] = -Normal[i][1]; | ||
387 | pContact->normal[2] = -Normal[i][2]; | ||
388 | #else | ||
389 | pContact->normal[0] = (ContactA[i].normal[0] + ContactB[i].normal[0])/2; //0.f; | ||
390 | pContact->normal[1] = (ContactA[i].normal[1] + ContactB[i].normal[1])/2; //0.f; | ||
391 | pContact->normal[2] = (ContactA[i].normal[2] + ContactB[i].normal[2])/2; //-1.f; | ||
392 | dNormalize3(pContact->normal); | ||
393 | #endif | ||
394 | #ifdef DO_RAYDEPTH | ||
395 | dxRay rayV(0,1000.f); | ||
396 | dGeomRaySet(&rayV, pContact->pos[0], | ||
397 | pContact->pos[1], | ||
398 | pContact->pos[2], | ||
399 | -pContact->normal[0], | ||
400 | -pContact->normal[1], | ||
401 | -pContact->normal[2]); | ||
402 | |||
403 | dContactGeom ContactV; | ||
404 | if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom))) | ||
405 | { | ||
406 | pContact->depth = ContactV.depth; | ||
407 | numContacts++; | ||
408 | } | ||
409 | #else | ||
410 | |||
411 | if (GetDepth == NULL) | ||
412 | { | ||
413 | dxRay rayV(0,1000.f); | ||
414 | dGeomRaySet(&rayV, pContact->pos[0], | ||
415 | pContact->pos[1], | ||
416 | pContact->pos[2], | ||
417 | -pContact->normal[0], | ||
418 | -pContact->normal[1], | ||
419 | -pContact->normal[2]); | ||
420 | |||
421 | dContactGeom ContactV; | ||
422 | |||
423 | if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom))) | ||
424 | { | ||
425 | pContact->depth = ContactV.depth; | ||
426 | numContacts++; | ||
427 | } | ||
428 | } | ||
429 | else | ||
430 | { | ||
431 | pContact->depth = GetDepth(o2, | ||
432 | pContact->pos[0], | ||
433 | pContact->pos[1], | ||
434 | pContact->pos[2]); | ||
435 | numContacts++; | ||
436 | } | ||
437 | |||
438 | #endif | ||
439 | if (numContacts == numMaxContacts) | ||
440 | return numContacts; | ||
441 | |||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | dCROSS(Plane,=,AC,AB); | ||
447 | dNormalize3(Plane); | ||
448 | Plane[3] = Plane[0] * A[0] + Plane[1] * A[1] + Plane[2] * A[2]; | ||
449 | dxPlane planeABC(0,Plane[0],Plane[1],Plane[2],Plane[3]); | ||
450 | numPlaneContacts = CollideNPlane(o2,&planeABC,flags,PlaneContact,sizeof(dContactGeom)); | ||
451 | |||
452 | for (i=0;i<numPlaneContacts;i++) | ||
453 | { | ||
454 | if (IsOnTerrain(x,z,0,PlaneContact[i].pos)) | ||
455 | { | ||
456 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
457 | pContact->pos[0] = PlaneContact[i].pos[0]; | ||
458 | pContact->pos[1] = PlaneContact[i].pos[1]; | ||
459 | pContact->pos[2] = PlaneContact[i].pos[2]; | ||
460 | pContact->normal[0] = -PlaneContact[i].normal[0]; | ||
461 | pContact->normal[1] = -PlaneContact[i].normal[1]; | ||
462 | pContact->normal[2] = -PlaneContact[i].normal[2]; | ||
463 | pContact->depth = PlaneContact[i].depth; | ||
464 | |||
465 | //DMESS(0); | ||
466 | numContacts++; | ||
467 | |||
468 | if (numContacts == numMaxContacts) | ||
469 | return numContacts; | ||
470 | } | ||
471 | } | ||
472 | |||
473 | dCROSS(Plane,=,BD,CD); | ||
474 | dNormalize3(Plane); | ||
475 | Plane[3] = Plane[0] * D[0] + Plane[1] * D[1] + Plane[2] * D[2]; | ||
476 | dxPlane planeDCB(0,Plane[0],Plane[1],Plane[2],Plane[3]); | ||
477 | numPlaneContacts = CollideNPlane(o2,&planeDCB,flags,PlaneContact,sizeof(dContactGeom)); | ||
478 | |||
479 | for (i=0;i<numPlaneContacts;i++) | ||
480 | { | ||
481 | if (IsOnTerrain(x,z,1,PlaneContact[i].pos)) | ||
482 | { | ||
483 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
484 | pContact->pos[0] = PlaneContact[i].pos[0]; | ||
485 | pContact->pos[1] = PlaneContact[i].pos[1]; | ||
486 | pContact->pos[2] = PlaneContact[i].pos[2]; | ||
487 | pContact->normal[0] = -PlaneContact[i].normal[0]; | ||
488 | pContact->normal[1] = -PlaneContact[i].normal[1]; | ||
489 | pContact->normal[2] = -PlaneContact[i].normal[2]; | ||
490 | pContact->depth = PlaneContact[i].depth; | ||
491 | //DMESS(1); | ||
492 | numContacts++; | ||
493 | |||
494 | if (numContacts == numMaxContacts) | ||
495 | return numContacts; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | return numContacts; | ||
500 | } | ||
501 | |||
502 | int dCollideTerrainY(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip) | ||
503 | { | ||
504 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
505 | dIASSERT (o1->type == dTerrainYClass); | ||
506 | int i,j; | ||
507 | |||
508 | if ((flags & 0xffff) == 0) | ||
509 | flags = (flags & 0xffff0000) | 1; | ||
510 | |||
511 | int numMaxTerrainContacts = (flags & 0xffff); | ||
512 | dxTerrainY *terrain = (dxTerrainY*) o1; | ||
513 | |||
514 | dReal aabbbak[6]; | ||
515 | int gflagsbak; | ||
516 | |||
517 | dVector3 pos0; | ||
518 | int numTerrainContacts = 0; | ||
519 | |||
520 | dxPosR *bak; | ||
521 | dxPosR X1; | ||
522 | |||
523 | if (terrain->gflags & GEOM_PLACEABLE) | ||
524 | { | ||
525 | dOP(pos0,-,o2->final_posr->pos,terrain->final_posr->pos); | ||
526 | dMULTIPLY1_331(X1.pos,terrain->final_posr->R,pos0); | ||
527 | dMULTIPLY1_333(X1.R,terrain->final_posr->R,o2->final_posr->R); | ||
528 | bak = o2->final_posr; | ||
529 | o2->final_posr = &X1; | ||
530 | memcpy(aabbbak,o2->aabb,sizeof(dReal)*6); | ||
531 | gflagsbak = o2->gflags; | ||
532 | o2->computeAABB(); | ||
533 | } | ||
534 | |||
535 | int nMinX = int(floor(o2->aabb[0] / terrain->m_vNodeLength)); | ||
536 | int nMaxX = int(floor(o2->aabb[1] / terrain->m_vNodeLength)) + 1; | ||
537 | int nMinZ = int(floor(o2->aabb[4] / terrain->m_vNodeLength)); | ||
538 | int nMaxZ = int(floor(o2->aabb[5] / terrain->m_vNodeLength)) + 1; | ||
539 | |||
540 | if (terrain->m_bFinite) | ||
541 | { | ||
542 | nMinX = MAX(nMinX,0); | ||
543 | nMaxX = MIN(nMaxX,terrain->m_nNumNodesPerSide); | ||
544 | nMinZ = MAX(nMinZ,0); | ||
545 | nMaxZ = MIN(nMaxZ,terrain->m_nNumNodesPerSide); | ||
546 | |||
547 | if ((nMinX >= nMaxX) || (nMinZ >= nMaxZ)) | ||
548 | goto dCollideTerrainYExit; | ||
549 | } | ||
550 | |||
551 | dVector3 AabbTop; | ||
552 | AabbTop[0] = (o2->aabb[0]+o2->aabb[1]) / 2; | ||
553 | AabbTop[2] = (o2->aabb[4]+o2->aabb[5]) / 2; | ||
554 | AabbTop[1] = o2->aabb[3]; | ||
555 | if (o2->type != dRayClass) | ||
556 | { | ||
557 | dReal AabbTopDepth = terrain->GetHeight(AabbTop[0],AabbTop[2]) - AabbTop[1]; | ||
558 | if (AabbTopDepth > 0.f) | ||
559 | { | ||
560 | contact->depth = AabbTopDepth; | ||
561 | dReal MaxDepth = (o2->aabb[3]-o2->aabb[2]) / 2; | ||
562 | if (contact->depth > MaxDepth) | ||
563 | contact->depth = MaxDepth; | ||
564 | contact->g1 = o1; | ||
565 | contact->g2 = o2; | ||
566 | dOPE(contact->pos,=,AabbTop); | ||
567 | contact->normal[0] = 0.f; | ||
568 | contact->normal[1] = -1.f; | ||
569 | contact->normal[2] = 0.f; | ||
570 | |||
571 | numTerrainContacts = 1; | ||
572 | goto dCollideTerrainYExit; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | for (i=nMinX;i<nMaxX;i++) | ||
577 | { | ||
578 | for (j=nMinZ;j<nMaxZ;j++) | ||
579 | { | ||
580 | numTerrainContacts += terrain->dCollideTerrainUnit( | ||
581 | i,j,o2,numMaxTerrainContacts - numTerrainContacts, | ||
582 | flags,CONTACT(contact,numTerrainContacts*skip),skip ); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | dIASSERT(numTerrainContacts <= numMaxTerrainContacts); | ||
587 | |||
588 | for (i=0; i<numTerrainContacts; i++) | ||
589 | { | ||
590 | CONTACT(contact,i*skip)->g1 = o1; | ||
591 | CONTACT(contact,i*skip)->g2 = o2; | ||
592 | } | ||
593 | |||
594 | dCollideTerrainYExit: | ||
595 | |||
596 | if (terrain->gflags & GEOM_PLACEABLE) | ||
597 | { | ||
598 | o2->final_posr = bak; | ||
599 | memcpy(o2->aabb,aabbbak,sizeof(dReal)*6); | ||
600 | o2->gflags = gflagsbak; | ||
601 | |||
602 | for (i=0; i<numTerrainContacts; i++) | ||
603 | { | ||
604 | dOPE(pos0,=,CONTACT(contact,i*skip)->pos); | ||
605 | dMULTIPLY0_331(CONTACT(contact,i*skip)->pos,terrain->final_posr->R,pos0); | ||
606 | dOP(CONTACT(contact,i*skip)->pos,+,CONTACT(contact,i*skip)->pos,terrain->final_posr->pos); | ||
607 | |||
608 | dOPE(pos0,=,CONTACT(contact,i*skip)->normal); | ||
609 | dMULTIPLY0_331(CONTACT(contact,i*skip)->normal,terrain->final_posr->R,pos0); | ||
610 | } | ||
611 | } | ||
612 | |||
613 | return numTerrainContacts; | ||
614 | } | ||
615 | /* | ||
616 | void dsDrawTerrainY(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos) | ||
617 | { | ||
618 | float A[3],B[3],C[3],D[3]; | ||
619 | float R[12]; | ||
620 | float pos[3]; | ||
621 | if (pR) | ||
622 | memcpy(R,pR,sizeof(R)); | ||
623 | else | ||
624 | { | ||
625 | memset(R,0,sizeof(R)); | ||
626 | R[0] = 1.f; | ||
627 | R[5] = 1.f; | ||
628 | R[10] = 1.f; | ||
629 | } | ||
630 | |||
631 | if (ppos) | ||
632 | memcpy(pos,ppos,sizeof(pos)); | ||
633 | else | ||
634 | memset(pos,0,sizeof(pos)); | ||
635 | |||
636 | float vx,vz; | ||
637 | vx = vLength * x; | ||
638 | vz = vLength * z; | ||
639 | |||
640 | int i; | ||
641 | for (i=0;i<nNumNodesPerSide;i++) | ||
642 | { | ||
643 | for (int j=0;j<nNumNodesPerSide;j++) | ||
644 | { | ||
645 | A[0] = i * vNodeLength + vx; | ||
646 | A[2] = j * vNodeLength + vz; | ||
647 | A[1] = GetHeight(i,j,nNumNodesPerSide,pHeights); | ||
648 | B[0] = (i+1) * vNodeLength + vx; | ||
649 | B[2] = j * vNodeLength + vz; | ||
650 | B[1] = GetHeight(i+1,j,nNumNodesPerSide,pHeights); | ||
651 | C[0] = i * vNodeLength + vx; | ||
652 | C[2] = (j+1) * vNodeLength + vz; | ||
653 | C[1] = GetHeight(i,j+1,nNumNodesPerSide,pHeights); | ||
654 | D[0] = (i+1) * vNodeLength + vx; | ||
655 | D[2] = (j+1) * vNodeLength + vz; | ||
656 | D[1] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights); | ||
657 | dsDrawTriangle(pos,R,C,B,A,1); | ||
658 | dsDrawTriangle(pos,R,D,B,C,1); | ||
659 | } | ||
660 | } | ||
661 | } | ||
662 | */ | ||