| 1 | Benoit CHAPEROT 2003-2004 www.jstarlab.com |
|---|
| 2 | Support for terrain and cones, collision and drawing. |
|---|
| 3 | |
|---|
| 4 | Terrains can be with z up (dTerrainZ) or y up (dTerrainY). |
|---|
| 5 | Terrains are defined by a height field. |
|---|
| 6 | Terrains are now placeable. |
|---|
| 7 | Terrains can now be finite or infinite (repeat themselve in the x and (y or z) directions). |
|---|
| 8 | |
|---|
| 9 | Terrains can potentially collide with everything that collides with planes and rays; |
|---|
| 10 | see the switch statement. |
|---|
| 11 | |
|---|
| 12 | Cones currently collides only with terrain and planes and rays. |
|---|
| 13 | Cones, with high radius to height ratios are perfect to simulate vehicle wheels on terrains. |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | There was an error in the depths returned by dCollideTerrain. |
|---|
| 18 | Plus now contacts are not sorted according to their depths. |
|---|
| 19 | Contact sorting is now supposed to be done externally. |
|---|
| 20 | Not all dCollide functions seem to sort contacts according to depth. |
|---|
| 21 | Requesting a high number of contacts, sorting them and then considering only the most significant contacts |
|---|
| 22 | is a good way I think to improve stability. |
|---|
| 23 | * Cones Collisions with spheres, boxes, ccylinder and trimesh are now roughly approximated using sphere collisions. |
|---|
| 24 | |
|---|
| 25 | You will need to complete the following operations (with ODE 0.039): |
|---|
| 26 | |
|---|
| 27 | *** add to folder ode\src: |
|---|
| 28 | |
|---|
| 29 | dCone.cpp |
|---|
| 30 | dTerrainY.cpp |
|---|
| 31 | dTerrainZ.cpp |
|---|
| 32 | collision_std_internal.h |
|---|
| 33 | |
|---|
| 34 | On linux => edit each .cpp file and comment out #include "windows.h" & #include "ode\ode.h" |
|---|
| 35 | |
|---|
| 36 | |
|---|
| 37 | *** add to drawstuff\src\drawstuff.cpp: |
|---|
| 38 | |
|---|
| 39 | static void drawCone(float l, float r) |
|---|
| 40 | { |
|---|
| 41 | int i; |
|---|
| 42 | float tmp,ny,nz,a,ca,sa; |
|---|
| 43 | const int n = 24; // number of sides to the cone (divisible by 4) |
|---|
| 44 | |
|---|
| 45 | a = float(M_PI*2.0)/float(n); |
|---|
| 46 | sa = (float) sin(a); |
|---|
| 47 | ca = (float) cos(a); |
|---|
| 48 | |
|---|
| 49 | // draw top |
|---|
| 50 | glShadeModel (GL_FLAT); |
|---|
| 51 | ny=1; nz=0; // normal vector = (0,ny,nz) |
|---|
| 52 | glBegin (GL_TRIANGLE_FAN); |
|---|
| 53 | glNormal3d (0,0,1); |
|---|
| 54 | glVertex3d (0,0,l); |
|---|
| 55 | for (i=0; i<=n; i++) { |
|---|
| 56 | if (i==1 || i==n/2+1) |
|---|
| 57 | setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]); |
|---|
| 58 | glNormal3d (ny*r,nz*r,0); |
|---|
| 59 | glVertex3d (ny*r,nz*r,0); |
|---|
| 60 | if (i==1 || i==n/2+1) |
|---|
| 61 | setColor (color[0],color[1],color[2],color[3]); |
|---|
| 62 | |
|---|
| 63 | // rotate ny,nz |
|---|
| 64 | tmp = ca*ny - sa*nz; |
|---|
| 65 | nz = sa*ny + ca*nz; |
|---|
| 66 | ny = tmp; |
|---|
| 67 | } |
|---|
| 68 | glEnd(); |
|---|
| 69 | |
|---|
| 70 | // draw bottom |
|---|
| 71 | ny=1; nz=0; // normal vector = (0,ny,nz) |
|---|
| 72 | glBegin (GL_TRIANGLE_FAN); |
|---|
| 73 | glNormal3d (0,0,-1); |
|---|
| 74 | glVertex3d (0,0,0); |
|---|
| 75 | for (i=0; i<=n; i++) { |
|---|
| 76 | if (i==1 || i==n/2+1) |
|---|
| 77 | setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]); |
|---|
| 78 | glNormal3d (0,0,-1); |
|---|
| 79 | glVertex3d (ny*r,nz*r,0); |
|---|
| 80 | if (i==1 || i==n/2+1) |
|---|
| 81 | setColor (color[0],color[1],color[2],color[3]); |
|---|
| 82 | |
|---|
| 83 | // rotate ny,nz |
|---|
| 84 | tmp = ca*ny + sa*nz; |
|---|
| 85 | nz = -sa*ny + ca*nz; |
|---|
| 86 | ny = tmp; |
|---|
| 87 | } |
|---|
| 88 | glEnd(); |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | void dsDrawCone (const float pos[3], const float R[12], float length, float radius) |
|---|
| 92 | { |
|---|
| 93 | if (current_state != 2) dsError ("drawing function called outside simulation loop"); |
|---|
| 94 | setupDrawingMode(); |
|---|
| 95 | glShadeModel (GL_SMOOTH); |
|---|
| 96 | setTransform (pos,R); |
|---|
| 97 | drawCone (length,radius); |
|---|
| 98 | glPopMatrix(); |
|---|
| 99 | |
|---|
| 100 | if (use_shadows) { |
|---|
| 101 | setShadowDrawingMode(); |
|---|
| 102 | setShadowTransform(); |
|---|
| 103 | setTransform (pos,R); |
|---|
| 104 | drawCone (length,radius); |
|---|
| 105 | glPopMatrix(); |
|---|
| 106 | glPopMatrix(); |
|---|
| 107 | glDepthRange (0,1); |
|---|
| 108 | } |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | void dsDrawConeD (const double pos[3], const double R[12], float length, float radius) |
|---|
| 112 | { |
|---|
| 113 | int i; |
|---|
| 114 | float pos2[3],R2[12]; |
|---|
| 115 | for (i=0; i<3; i++) pos2[i]=(float)pos[i]; |
|---|
| 116 | for (i=0; i<12; i++) R2[i]=(float)R[i]; |
|---|
| 117 | dsDrawCone(pos2,R2,length,radius); |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | static float GetHeight(int x,int y,int nNumNodesPerSide,float *pHeights) |
|---|
| 121 | { |
|---|
| 122 | int nNumNodesPerSideMask = nNumNodesPerSide - 1; |
|---|
| 123 | return pHeights[ (((unsigned int)(y) & nNumNodesPerSideMask) * nNumNodesPerSide) |
|---|
| 124 | + ((unsigned int)(x) & nNumNodesPerSideMask)]; |
|---|
| 125 | } |
|---|
| 126 | |
|---|
| 127 | void dsDrawTerrainY(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos) |
|---|
| 128 | { |
|---|
| 129 | float A[3],B[3],C[3],D[3]; |
|---|
| 130 | float R[12]; |
|---|
| 131 | float pos[3]; |
|---|
| 132 | if (pR) |
|---|
| 133 | memcpy(R,pR,sizeof(R)); |
|---|
| 134 | else |
|---|
| 135 | { |
|---|
| 136 | memset(R,0,sizeof(R)); |
|---|
| 137 | R[0] = 1.f; |
|---|
| 138 | R[5] = 1.f; |
|---|
| 139 | R[10] = 1.f; |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | if (ppos) |
|---|
| 143 | memcpy(pos,ppos,sizeof(pos)); |
|---|
| 144 | else |
|---|
| 145 | memset(pos,0,sizeof(pos)); |
|---|
| 146 | |
|---|
| 147 | float vx,vz; |
|---|
| 148 | vx = vLength * x; |
|---|
| 149 | vz = vLength * z; |
|---|
| 150 | |
|---|
| 151 | int i; |
|---|
| 152 | for (i=0;i<nNumNodesPerSide;i++) |
|---|
| 153 | { |
|---|
| 154 | for (int j=0;j<nNumNodesPerSide;j++) |
|---|
| 155 | { |
|---|
| 156 | A[0] = i * vNodeLength + vx; |
|---|
| 157 | A[2] = j * vNodeLength + vz; |
|---|
| 158 | A[1] = GetHeight(i,j,nNumNodesPerSide,pHeights); |
|---|
| 159 | B[0] = (i+1) * vNodeLength + vx; |
|---|
| 160 | B[2] = j * vNodeLength + vz; |
|---|
| 161 | B[1] = GetHeight(i+1,j,nNumNodesPerSide,pHeights); |
|---|
| 162 | C[0] = i * vNodeLength + vx; |
|---|
| 163 | C[2] = (j+1) * vNodeLength + vz; |
|---|
| 164 | C[1] = GetHeight(i,j+1,nNumNodesPerSide,pHeights); |
|---|
| 165 | D[0] = (i+1) * vNodeLength + vx; |
|---|
| 166 | D[2] = (j+1) * vNodeLength + vz; |
|---|
| 167 | D[1] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights); |
|---|
| 168 | dsDrawTriangle(pos,R,C,B,A,1); |
|---|
| 169 | dsDrawTriangle(pos,R,D,B,C,1); |
|---|
| 170 | } |
|---|
| 171 | } |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | void dsDrawTerrainZ(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos) |
|---|
| 175 | { |
|---|
| 176 | float A[3],B[3],C[3],D[3]; |
|---|
| 177 | float R[12]; |
|---|
| 178 | float pos[3]; |
|---|
| 179 | if (pR) |
|---|
| 180 | memcpy(R,pR,sizeof(R)); |
|---|
| 181 | else |
|---|
| 182 | { |
|---|
| 183 | memset(R,0,sizeof(R)); |
|---|
| 184 | R[0] = 1.f; |
|---|
| 185 | R[5] = 1.f; |
|---|
| 186 | R[10] = 1.f; |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | if (ppos) |
|---|
| 190 | memcpy(pos,ppos,sizeof(pos)); |
|---|
| 191 | else |
|---|
| 192 | memset(pos,0,sizeof(pos)); |
|---|
| 193 | |
|---|
| 194 | float vx,vz; |
|---|
| 195 | vx = vLength * x; |
|---|
| 196 | vz = vLength * z; |
|---|
| 197 | |
|---|
| 198 | int i; |
|---|
| 199 | for (i=0;i<nNumNodesPerSide;i++) |
|---|
| 200 | { |
|---|
| 201 | for (int j=0;j<nNumNodesPerSide;j++) |
|---|
| 202 | { |
|---|
| 203 | A[0] = i * vNodeLength + vx; |
|---|
| 204 | A[1] = j * vNodeLength + vz; |
|---|
| 205 | A[2] = GetHeight(i,j,nNumNodesPerSide,pHeights); |
|---|
| 206 | B[0] = (i+1) * vNodeLength + vx; |
|---|
| 207 | B[1] = j * vNodeLength + vz; |
|---|
| 208 | B[2] = GetHeight(i+1,j,nNumNodesPerSide,pHeights); |
|---|
| 209 | C[0] = i * vNodeLength + vx; |
|---|
| 210 | C[1] = (j+1) * vNodeLength + vz; |
|---|
| 211 | C[2] = GetHeight(i,j+1,nNumNodesPerSide,pHeights); |
|---|
| 212 | D[0] = (i+1) * vNodeLength + vx; |
|---|
| 213 | D[1] = (j+1) * vNodeLength + vz; |
|---|
| 214 | D[2] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights); |
|---|
| 215 | dsDrawTriangle(pos,R,C,A,B,1); |
|---|
| 216 | dsDrawTriangle(pos,R,D,C,B,1); |
|---|
| 217 | } |
|---|
| 218 | } |
|---|
| 219 | } |
|---|
| 220 | |
|---|
| 221 | *** add to include\drawstuff\drawstuff.h: |
|---|
| 222 | void dsDrawCone (const float pos[3], const float R[12], float length, float radius); |
|---|
| 223 | void dsDrawConeD (const double pos[3], const double R[12], float length, float radius); |
|---|
| 224 | void dsDrawTerrainY(int x,int y,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos); |
|---|
| 225 | void dsDrawTerrainZ(int x,int y,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos); |
|---|
| 226 | |
|---|
| 227 | *** add in include\ode\collision.h line 77: |
|---|
| 228 | /* class numbers - each geometry object needs a unique number */ |
|---|
| 229 | enum { |
|---|
| 230 | dSphereClass = 0, |
|---|
| 231 | dBoxClass, |
|---|
| 232 | dCCylinderClass, |
|---|
| 233 | dCylinderClass, |
|---|
| 234 | dPlaneClass, |
|---|
| 235 | dRayClass, |
|---|
| 236 | dGeomTransformClass, |
|---|
| 237 | dTriMeshClass, |
|---|
| 238 | |
|---|
| 239 | dTerrainYClass, //here |
|---|
| 240 | dTerrainZClass, //here |
|---|
| 241 | dConeClass, //here |
|---|
| 242 | |
|---|
| 243 | dFirstSpaceClass, |
|---|
| 244 | dSimpleSpaceClass = dFirstSpaceClass, |
|---|
| 245 | dHashSpaceClass, |
|---|
| 246 | dQuadTreeSpaceClass, |
|---|
| 247 | |
|---|
| 248 | dLastSpaceClass = dQuadTreeSpaceClass, |
|---|
| 249 | |
|---|
| 250 | dFirstUserClass, |
|---|
| 251 | dLastUserClass = dFirstUserClass + dMaxUserClasses - 1, |
|---|
| 252 | dGeomNumClasses |
|---|
| 253 | }; |
|---|
| 254 | |
|---|
| 255 | dGeomID dCreateTerrainY (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable); |
|---|
| 256 | dReal dGeomTerrainYPointDepth (dGeomID g, dReal x, dReal y, dReal z); |
|---|
| 257 | dGeomID dCreateTerrainZ (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable); |
|---|
| 258 | dReal dGeomTerrainZPointDepth (dGeomID g, dReal x, dReal y, dReal z); |
|---|
| 259 | |
|---|
| 260 | dGeomID dCreateCone(dSpaceID space, dReal radius, dReal length); |
|---|
| 261 | void dGeomConeSetParams (dGeomID cone, dReal radius, dReal length); |
|---|
| 262 | void dGeomConeGetParams (dGeomID cone, dReal *radius, dReal *length); |
|---|
| 263 | dReal dGeomConePointDepth(dGeomID g, dReal x, dReal y, dReal z); |
|---|
| 264 | |
|---|
| 265 | *** add in include\ode\odemath.h: |
|---|
| 266 | #define dOP(a,op,b,c) \ |
|---|
| 267 | (a)[0] = ((b)[0]) op ((c)[0]); \ |
|---|
| 268 | (a)[1] = ((b)[1]) op ((c)[1]); \ |
|---|
| 269 | (a)[2] = ((b)[2]) op ((c)[2]); |
|---|
| 270 | #define dOPC(a,op,b,c) \ |
|---|
| 271 | (a)[0] = ((b)[0]) op (c); \ |
|---|
| 272 | (a)[1] = ((b)[1]) op (c); \ |
|---|
| 273 | (a)[2] = ((b)[2]) op (c); |
|---|
| 274 | #define dOPE(a,op,b) \ |
|---|
| 275 | (a)[0] op ((b)[0]); \ |
|---|
| 276 | (a)[1] op ((b)[1]); \ |
|---|
| 277 | (a)[2] op ((b)[2]); |
|---|
| 278 | #define dOPEC(a,op,c) \ |
|---|
| 279 | (a)[0] op (c); \ |
|---|
| 280 | (a)[1] op (c); \ |
|---|
| 281 | (a)[2] op (c); |
|---|
| 282 | #define dLENGTH(a) \ |
|---|
| 283 | (dSqrt( ((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]) )); |
|---|
| 284 | #define dLENGTHSQUARED(a) \ |
|---|
| 285 | (((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2])); |
|---|
| 286 | |
|---|
| 287 | *** add in ode\src\collision_kernel.cpp function 'static void initColliders()' next to other 'setCollider' calls: |
|---|
| 288 | setCollider (dTerrainYClass,dSphereClass,&dCollideTerrainY); |
|---|
| 289 | setCollider (dTerrainYClass,dBoxClass,&dCollideTerrainY); |
|---|
| 290 | setCollider (dTerrainYClass,dCCylinderClass,&dCollideTerrainY); |
|---|
| 291 | setCollider (dTerrainYClass,dRayClass,&dCollideTerrainY); |
|---|
| 292 | setCollider (dTerrainYClass,dConeClass,&dCollideTerrainY); |
|---|
| 293 | |
|---|
| 294 | setCollider (dTerrainZClass,dSphereClass,&dCollideTerrainZ); |
|---|
| 295 | setCollider (dTerrainZClass,dBoxClass,&dCollideTerrainZ); |
|---|
| 296 | setCollider (dTerrainZClass,dCCylinderClass,&dCollideTerrainZ); |
|---|
| 297 | setCollider (dTerrainZClass,dRayClass,&dCollideTerrainZ); |
|---|
| 298 | setCollider (dTerrainZClass,dConeClass,&dCollideTerrainZ); |
|---|
| 299 | |
|---|
| 300 | setCollider (dRayClass,dConeClass,&dCollideRayCone); |
|---|
| 301 | setCollider (dConeClass,dPlaneClass,&dCollideConePlane); |
|---|
| 302 | setCollider (dConeClass,dSphereClass,&dCollideConeSphere); |
|---|
| 303 | setCollider (dConeClass,dBoxClass,&dCollideConeBox); |
|---|
| 304 | setCollider (dCCylinderClass,dConeClass,&dCollideCCylinderCone); |
|---|
| 305 | setCollider (dTriMeshClass,dConeClass,&dCollideTriMeshCone); |
|---|
| 306 | |
|---|
| 307 | *** add in ode\src\collision_std.h: |
|---|
| 308 | int dCollideTerrainY(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip); |
|---|
| 309 | int dCollideTerrainZ(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip); |
|---|
| 310 | |
|---|
| 311 | int dCollideConePlane (dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip); |
|---|
| 312 | int dCollideRayCone (dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip); |
|---|
| 313 | int dCollideConeSphere(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); |
|---|
| 314 | int dCollideConeBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); |
|---|
| 315 | int dCollideCCylinderCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); |
|---|
| 316 | int dCollideTriMeshCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); |
|---|
| 317 | |
|---|
| 318 | *** add dCone.cpp, dTerrainY.cpp and dTerrainZ.cpp to the the ODE_SRC variable in the makefile |
|---|
| 319 | On Linux => add dCone.cpp, dTerrainY.cpp and dTerrainZ.cpp to the the libode_a_SOURCES variable in the ode/src/Makefile.am file. |
|---|
| 320 | |
|---|
| 321 | *** now you can now test using file test_boxstackb.cpp (to add in folder ode\test). |
|---|
| 322 | |
|---|