1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
21 *************************************************************************/
23 // TriMesh collision demo.
24 // Serves as a test for the collision of trimesh geometries.
25 // By Davy (Dawei) Chen.
32 #include <drawstuff/drawstuff.h>
33 #include "texturepath.h"
36 #define dsDrawTriangle dsDrawTriangleD
38 #define dGeomTriMeshDataBuildReal dGeomTriMeshDataBuildSingle
41 # pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
45 static dWorldID world
;
46 static dSpaceID space
;
47 static dJointGroupID contactgroup
;
49 // 2D Convex hulls to create the TriMesh geometries
50 const float HULL1
[] = { -1.000000, -35.000000, 1.000000, -34.000000, 5.000000, -31.000000, 16.000000, -20.000000, 16.000000, -11.000000, 5.000000, 0.000000, -1.000000, 3.000000, -7.000000, 4.000000, -13.000000, 3.000000, -16.000000, 2.000000, -20.000000, 0.000000, -24.000000, -4.000000, -26.000000, -8.000000, -27.000000, -12.000000, -27.000000, -15.000000, -27.000000, -19.000000, -26.000000, -23.000000, -24.000000, -27.000000, -20.000000, -31.000000, -16.000000, -34.000000 };
51 const float HULL2
[] = { 23.000000, 28.000000, 28.000000, 29.000000, 30.000000, 30.000000, 34.000000, 33.000000, 35.000000, 34.000000, 38.000000, 39.000000, 39.000000, 42.000000, 40.000000, 48.000000, 39.000000, 53.000000, 38.000000, 56.000000, 35.000000, 61.000000, 34.000000, 62.000000, 30.000000, 65.000000, 28.000000, 66.000000, 25.000000, 67.000000, 20.000000, 68.000000, 19.000000, 68.000000, 14.000000, 67.000000, 11.000000, 66.000000, 9.000000, 65.000000, 5.000000, 62.000000, 4.000000, 61.000000, 1.000000, 56.000000, 0.000000, 53.000000, 0.000000, 48.000000, 0.000000, 42.000000, 1.000000, 39.000000, 4.000000, 34.000000, 5.000000, 33.000000, 9.000000, 30.000000, 11.000000, 29.000000 };
52 const float HULL3
[] = { -1.000000, -35.000000, 1.000000, -34.000000, 5.000000, -31.000000, 8.000000, -28.000000, 11.000000, -22.000000, 12.000000, -19.000000, 12.000000, -12.000000, 11.000000, -9.000000, 8.000000, -3.000000, 5.000000, 0.000000, -1.000000, 3.000000, -7.000000, 4.000000, -13.000000, 3.000000, -16.000000, 2.000000, -20.000000, 0.000000, -23.000000, -3.000000, -25.000000, -6.000000, -26.000000, -8.000000, -27.000000, -11.000000, -27.000000, -15.000000, -27.000000, -20.000000, -26.000000, -23.000000, -25.000000, -25.000000, -23.000000, -28.000000, -20.000000, -31.000000, -16.000000, -34.000000 };
53 const float HULL4
[] = { -2.000000, -35.000000, 6.000000, -31.000000, 9.000000, -27.000000, 10.000000, -25.000000, 11.000000, -22.000000, 11.000000, -9.000000, 10.000000, -6.000000, 9.000000, -4.000000, 6.000000, 0.000000, -2.000000, 3.000000, -7.000000, 4.000000, -19.000000, 3.000000, -20.000000, 2.000000, -25.000000, -6.000000, -26.000000, -8.000000, -27.000000, -11.000000, -27.000000, -15.000000, -27.000000, -20.000000, -26.000000, -23.000000, -25.000000, -25.000000, -20.000000, -34.000000 };
54 const float HULL5
[] = { -2.000000, -35.000000, 4.000000, -32.000000, 9.000000, -27.000000, 11.000000, -23.000000, 12.000000, -20.000000, 12.000000, -11.000000, 11.000000, -8.000000, 9.000000, -4.000000, 5.000000, 0.000000, -2.000000, 3.000000, -7.000000, 4.000000, -12.000000, 3.000000, -15.000000, 2.000000, -20.000000, 0.000000, -23.000000, -3.000000, -25.000000, -6.000000, -26.000000, -8.000000, -27.000000, -11.000000, -27.000000, -15.000000, -27.000000, -20.000000, -26.000000, -23.000000, -25.000000, -25.000000, -23.000000, -28.000000, -19.000000, -32.000000, -15.000000, -34.000000 };
55 const float HULL6
[] = { -1.000000, -35.000000, 25.000000, -29.000000, 26.000000, -28.000000, 30.000000, -18.000000, 30.000000, -14.000000, 26.000000, -6.000000, 25.000000, -5.000000, -1.000000, 3.000000, -7.000000, 4.000000, -13.000000, 3.000000, -20.000000, 0.000000, -23.000000, -3.000000, -25.000000, -6.000000, -26.000000, -8.000000, -27.000000, -12.000000, -27.000000, -15.000000, -27.000000, -19.000000, -26.000000, -23.000000, -25.000000, -25.000000, -23.000000, -28.000000, -20.000000, -31.000000, -17.000000, -33.000000 };
57 // Center points of the 2D Convex hulls
58 const float CENTER1
[] = { -5.500000, -15.500000 };
59 const float CENTER2
[] = { 20.000000, 48.000000 };
60 const float CENTER3
[] = { -7.500000, -15.500000 };
61 const float CENTER4
[] = { -8.000000, -15.500000 };
62 const float CENTER5
[] = { -7.500000, -15.500000 };
63 const float CENTER6
[] = { 1.500000, -15.500000 };
65 // Where to position the TriMeshes on the Ground plane
66 // In (X, Y) coordinates pairs
67 const float BODY_POSITIONS
[][2] = {
76 const float *HULLS
[] = { HULL1
, HULL2
, HULL3
, HULL4
, HULL5
, HULL6
};
77 const int HULL_SIZES
[] = {
78 sizeof(HULL1
) / sizeof(float) / 2,
79 sizeof(HULL2
) / sizeof(float) / 2,
80 sizeof(HULL3
) / sizeof(float) / 2,
81 sizeof(HULL4
) / sizeof(float) / 2,
82 sizeof(HULL5
) / sizeof(float) / 2,
83 sizeof(HULL6
) / sizeof(float) / 2
85 const float *CENTERS
[] = { CENTER1
, CENTER2
, CENTER3
, CENTER4
, CENTER5
, CENTER6
};
86 const int HULLS_COUNT
= sizeof(HULLS
) / sizeof(float *);
88 const float TRIMESH_HEIGHT
= 2.0f
;
90 static float *odeVerts
[HULLS_COUNT
];
91 static dTriIndex
*odeInds
[HULLS_COUNT
];
92 static int odeIndsCount
[HULLS_COUNT
];
94 static dTriMeshDataID triMeshDataId
[HULLS_COUNT
];
95 static dGeomID triMeshId
[HULLS_COUNT
];
96 static dBodyID bodyId
[HULLS_COUNT
];
98 // this is called by dSpaceCollide when two objects in space are
99 // potentially colliding.
101 static void nearCallback(void *data
, dGeomID o1
, dGeomID o2
)
105 if (dGeomIsSpace(o1
) || dGeomIsSpace(o2
))
107 // colliding a space with something
108 dSpaceCollide2(o1
, o2
, data
, &nearCallback
);
109 // Note we do not want to test intersections within a space,
110 // only between spaces.
116 int n
= dCollide(o1
, o2
, N
, &(contact
[0].geom
), sizeof(dContact
));
119 for (int i
= 0; i
<n
; i
++)
121 contact
[i
].surface
.slip1
= 0.7;
122 contact
[i
].surface
.slip2
= 0.7;
123 contact
[i
].surface
.mode
= dContactSoftERP
| dContactSoftCFM
| dContactApprox1
| dContactSlip1
| dContactSlip2
;
124 // Friction effect, if set to dInfinity, objects would be unmovable
125 contact
[i
].surface
.mu
= 0.0f
;
126 contact
[i
].surface
.soft_erp
= 0.50;
127 contact
[i
].surface
.soft_cfm
= 0.03;
128 dJointID c
= dJointCreateContact(world
, contactgroup
, &contact
[i
]);
132 dGeomGetBody(contact
[i
].geom
.g1
),
133 dGeomGetBody(contact
[i
].geom
.g2
)
139 // start simulation - set viewpoint
143 dAllocateODEDataForThread(dAllocateMaskAll
);
144 float xyz
[3] = { -8,0,5 };
145 float hpr
[3] = { 0.0f
,-29.5000f
,0.0000f
};
146 dsSetViewpoint(xyz
, hpr
);
147 fprintf(stderr
, "Press SPACE to reset the simulation1.\n");
152 for (int i
= 0; i
< HULLS_COUNT
; i
++)
154 dBodySetPosition(bodyId
[i
],
155 BODY_POSITIONS
[i
][0] * 0.05,
156 BODY_POSITIONS
[i
][1] * 0.05,
160 dRFromAxisAndAngle(R
,
165 dBodySetRotation(bodyId
[i
], R
);
167 // Enable the body as it might have been auto-disabled
168 dBodyEnable(bodyId
[i
]);
172 // called when a key pressed
174 static void command(int cmd
)
186 static void simLoop(int pause
)
188 double simstep
= 1/240.0;
189 double dt
= dsElapsedTime();
191 int nrofsteps
= (int)ceilf(dt
/simstep
);
192 nrofsteps
= nrofsteps
> 8 ? 8 : nrofsteps
;
194 for (int i
= 0; i
<nrofsteps
&& !pause
; i
++)
196 // Add force to TriMesh bodies, and make them gather towards world center
197 for (int j
= 0; j
< HULLS_COUNT
; j
++)
199 const dReal
*pos
= dBodyGetPosition(bodyId
[j
]);
200 // Calculate force tensity according to distance from world center
201 float length
= dCalcVectorLengthSquare3(pos
);
203 dCopyVector3(pos1
, pos
);
204 dNegateVector3(pos1
);
206 dScaleVector3(pos1
, 5.0f
* length
);
208 dBodyAddForce(bodyId
[j
], pos1
[0], pos1
[1], pos1
[2]);
211 dSpaceCollide(space
, 0, &nearCallback
);
212 dWorldQuickStep(world
, simstep
);
213 dJointGroupEmpty(contactgroup
);
217 for (int i
= 0; i
< HULLS_COUNT
; i
++)
219 const dReal
*Pos
= dBodyGetPosition(bodyId
[i
]);
220 const dReal
*Rot
= dBodyGetRotation(bodyId
[i
]);
225 for (int j
= 0; j
< odeIndsCount
[i
] / 3; j
++)
227 const dVector3 v0
= {
228 odeVerts
[i
][odeInds
[i
][j
* 3 + 0] * 3],
229 odeVerts
[i
][odeInds
[i
][j
* 3 + 0] * 3 + 1],
230 odeVerts
[i
][odeInds
[i
][j
* 3 + 0] * 3 + 2]
232 const dVector3 v1
= {
233 odeVerts
[i
][odeInds
[i
][j
* 3 + 1] * 3],
234 odeVerts
[i
][odeInds
[i
][j
* 3 + 1] * 3 + 1],
235 odeVerts
[i
][odeInds
[i
][j
* 3 + 1] * 3 + 2]
237 const dVector3 v2
= {
238 odeVerts
[i
][odeInds
[i
][j
* 3 + 2] * 3],
239 odeVerts
[i
][odeInds
[i
][j
* 3 + 2] * 3 + 1],
240 odeVerts
[i
][odeInds
[i
][j
* 3 + 2] * 3 + 2]
242 dsDrawTriangle(Pos
, Rot
, v0
, v1
, v2
, 1);
248 int main(int argc
, char **argv
)
252 // setup pointers to drawstuff callback functions
254 fn
.version
= DS_VERSION
;
257 fn
.command
= &command
;
259 fn
.path_to_textures
= DRAWSTUFF_TEXTURE_PATH
;
263 world
= dWorldCreate();
264 space
= dHashSpaceCreate(0);
265 dHashSpaceSetLevels(space
, -3, 5);
266 dCreatePlane(space
, 0, 0, 1, 0); // Add a ground plane.
268 contactgroup
= dJointGroupCreate(0);
269 dWorldSetGravity(world
, 0, 0, -1);
270 dWorldSetQuickStepNumIterations(world
, 32);
271 dWorldSetContactMaxCorrectingVel(world
, 40);
272 dWorldSetMaxAngularSpeed(world
, 62.8);
273 dWorldSetERP(world
, 0.7);
274 dWorldSetQuickStepW(world
, 0.75); // For increased stability.
276 dWorldSetAutoDisableFlag(world
, true);
277 dWorldSetAutoDisableLinearThreshold(world
, 0.01);
278 dWorldSetAutoDisableAngularThreshold(world
, 0.03);
279 dWorldSetAutoDisableTime(world
, 0.15f
);
281 // Generate TriMesh geometries and bodies
282 for (int i
= 0; i
< HULLS_COUNT
; i
++)
284 int hullSize
= HULL_SIZES
[i
];
286 int odeVertsCount1
= hullSize
* 3 * 2;
287 int odeVertsCount
= odeVertsCount1
+ 2 * 3;
288 odeVerts
[i
] = new float[odeVertsCount
];
289 for (int j
= 0; j
< hullSize
; j
++)
292 odeVerts
[i
][j
* 3] = (HULLS
[i
][j
* 2] - CENTERS
[i
][0]) * 0.05f
;
293 odeVerts
[i
][j
* 3 + 1] = (HULLS
[i
][j
* 2 + 1] - CENTERS
[i
][1]) * 0.05f
;
294 odeVerts
[i
][j
* 3 + 2] = 0.0f
;
296 odeVerts
[i
][(hullSize
+ j
) * 3] = (HULLS
[i
][j
* 2] - CENTERS
[i
][0]) * 0.05f
;
297 odeVerts
[i
][(hullSize
+ j
) * 3 + 1] = (HULLS
[i
][j
* 2 + 1] - CENTERS
[i
][1]) * 0.05f
;
298 odeVerts
[i
][(hullSize
+ j
) * 3 + 2] = TRIMESH_HEIGHT
;
300 // Center vertex on bottom plane
301 odeVerts
[i
][odeVertsCount1
] = 0.0f
;
302 odeVerts
[i
][odeVertsCount1
+ 1] = 0.0f
;
303 odeVerts
[i
][odeVertsCount1
+ 2] = 0.0f
;
304 // Center vertex on top plane
305 odeVerts
[i
][odeVertsCount1
+ 3] = 0.0f
;
306 odeVerts
[i
][odeVertsCount1
+ 3 + 1] = 0.0f
;
307 odeVerts
[i
][odeVertsCount1
+ 3 + 2] = TRIMESH_HEIGHT
;
309 int odeIndsCount1
= hullSize
* 6;
310 odeIndsCount
[i
] = odeIndsCount1
* 2;
311 odeInds
[i
] = new dTriIndex
[odeIndsCount
[i
]];
312 for (int j
= 0; j
< hullSize
; j
++)
316 int n1
= j
+ 1 < hullSize
? j
+ 1 : 0;
317 int n2
= hullSize
+ n1
;
318 odeInds
[i
][j
* 6] = j
;
319 odeInds
[i
][j
* 6 + 1] = n1
;
320 odeInds
[i
][j
* 6 + 2] = hullSize
+ j
;
321 odeInds
[i
][j
* 6 + 3] = hullSize
+ j
;
322 odeInds
[i
][j
* 6 + 4] = n1
;
323 odeInds
[i
][j
* 6 + 5] = n2
;
324 // Bottom and Top triangles
325 odeInds
[i
][odeIndsCount1
+ j
* 6] = j
;
326 odeInds
[i
][odeIndsCount1
+ j
* 6 + 1] = n1
;
327 odeInds
[i
][odeIndsCount1
+ j
* 6 + 2] = hullSize
* 2;
328 odeInds
[i
][odeIndsCount1
+ j
* 6 + 3] = hullSize
+ j
;
329 odeInds
[i
][odeIndsCount1
+ j
* 6 + 4] = n2
;
330 odeInds
[i
][odeIndsCount1
+ j
* 6 + 5] = hullSize
* 2 + 1;
333 bodyId
[i
] = dBodyCreate(world
);
334 dBodySetPosition(bodyId
[i
],
335 BODY_POSITIONS
[i
][0] * 0.05,
336 BODY_POSITIONS
[i
][1] * 0.05,
340 dRFromAxisAndAngle(R
,
345 dBodySetRotation(bodyId
[i
], R
);
348 dBodySetData(bodyId
[i
], (void *)index
);
355 const float DENSITY
= 1.0f
;
356 dMassSetBox(&m1
, DENSITY
, sides
[0], sides
[1], sides
[2]);
358 dBodySetMass(bodyId
[i
], &m1
);
359 // Make bodies less bouncy
360 dBodySetLinearDamping(bodyId
[i
], 0.1);
361 dBodySetAngularDamping(bodyId
[i
], 0.1);
363 triMeshDataId
[i
] = dGeomTriMeshDataCreate();
364 dGeomTriMeshDataBuildReal(triMeshDataId
[i
], odeVerts
[i
], 3 * sizeof(float), odeVertsCount
, odeInds
[i
], odeIndsCount
[i
], 3 * sizeof(dTriIndex
));
365 dGeomTriMeshDataPreprocess2(triMeshDataId
[i
], (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES
), NULL
);
367 triMeshId
[i
] = dCreateTriMesh(space
, triMeshDataId
[i
], 0, 0, 0);
368 dGeomSetBody(triMeshId
[i
], bodyId
[i
]);
372 dsSimulationLoop(argc
, argv
, DS_SIMULATION_DEFAULT_WIDTH
, DS_SIMULATION_DEFAULT_HEIGHT
, &fn
);
374 for (int i
= 0; i
< HULLS_COUNT
; i
++)
376 dGeomTriMeshDataDestroy(triMeshDataId
[i
]);
377 dGeomDestroy(triMeshId
[i
]);
378 dBodyDestroy(bodyId
[i
]);
380 delete[] odeVerts
[i
];
386 dJointGroupEmpty(contactgroup
);
387 dJointGroupDestroy(contactgroup
);
388 dSpaceDestroy(space
);
389 dWorldDestroy(world
);