/************************************************************************* * * * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * * All rights reserved. Email: russ@q12.org Web: www.q12.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of EITHER: * * (1) The GNU Lesser General Public License as published by the Free * * Software Foundation; either version 2.1 of the License, or (at * * your option) any later version. The text of the GNU Lesser * * General Public License is included with this library in the * * file LICENSE.TXT. * * (2) The BSD-style license that is included with this library in * * the file LICENSE-BSD.TXT. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * * LICENSE.TXT and LICENSE-BSD.TXT for more details. * * * *************************************************************************/ //#include #include #include #include "texturepath.h" #ifdef dDOUBLE #define dsDrawSphere dsDrawSphereD #define dsDrawBox dsDrawBoxD #define dsDrawTriangle dsDrawTriangleD #define dsDrawLine dsDrawLineD #endif const dReal ball_radius = 0.4; const dReal balls_sep = 2; // separation between the balls /* Choose one test case */ #define TEST_CASE 0 #if TEST_CASE == 0 const dReal track_len = 10; const dReal track_height = 1; const dReal track_width = 0.1; const dReal track_gauge = 1; const dReal track_elevation = 2; const dReal track_angle = 80 * M_PI/180.; const dReal track_incl = 10 * M_PI/180.; #elif TEST_CASE == 1 const dReal track_len = 10; const dReal track_height = 1; const dReal track_width = 0.1; const dReal track_gauge = 1.9*ball_radius; const dReal track_elevation = 2; const dReal track_angle = 0 * M_PI/180.; const dReal track_incl = 10 * M_PI/180.; #elif TEST_CASE == 2 const dReal track_len = 10; const dReal track_height = 1; const dReal track_width = 0.1; const dReal track_gauge = 1.9*ball_radius; const dReal track_elevation = 2; const dReal track_angle = 15 * M_PI/180.; const dReal track_incl = 10 * M_PI/180.; #elif TEST_CASE == 3 const dReal track_len = 10; const dReal track_height = .7; const dReal track_width = 0.1; const dReal track_gauge = track_height*1.1; const dReal track_elevation = 2; const dReal track_angle = 90 * M_PI/180.; const dReal track_incl = 10 * M_PI/180.; #else #error "TEST_CAST to a valid value!" #endif dWorldID world; dSpaceID space; dJointGroupID contact_group; dGeomID ground; dGeomID ball1_geom, ball2_geom; dTriMeshDataID mesh_data; dGeomID mesh_geom; dBodyID ball1_body, ball2_body; const unsigned n_box_verts = 8; dVector3 box_verts[n_box_verts] = { {-track_len/2, -track_width/2, track_height/2}, // 0 { track_len/2, -track_width/2, track_height/2}, // 1 { track_len/2, track_width/2, track_height/2}, // 2 {-track_len/2, track_width/2, track_height/2}, // 3 { track_len/2, -track_width/2, -track_height/2}, // 4 {-track_len/2, -track_width/2, -track_height/2}, // 5 {-track_len/2, track_width/2, -track_height/2}, // 6 { track_len/2, track_width/2, -track_height/2} // 7 }; const unsigned n_box_faces = 12; dTriIndex box_faces[n_box_faces * 3] = { 0, 1, 2, 0, 2, 3, 1, 4, 7, 1, 7, 2, 4, 5, 6, 4, 6, 7, 5, 0, 3, 5, 3, 6, 3, 2, 7, 3, 7, 6, 0, 5, 4, 0, 4, 1 }; const unsigned n_track_verts = n_box_verts * 2; const unsigned n_track_faces = n_box_faces * 2; dVector3 track_verts[n_track_verts]; dTriIndex track_faces[n_track_faces * 3]; void resetBall(dBodyID b, unsigned idx) { dBodySetPosition(b, 0.5*track_len*cos(track_incl) // Z - 0.5*track_height*sin(track_incl) - ball_radius, // X balls_sep*idx, // Y track_elevation + ball_radius// Z + 0.5*track_len*sin(track_incl) + 0.5*track_height*cos(track_incl)); dMatrix3 r = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0}; dBodySetRotation(b, r); dBodySetLinearVel(b, 0, 0, 0); dBodySetAngularVel(b, 0, 0, 0); } void resetSim() { resetBall(ball1_body, 0); resetBall(ball2_body, 1); } void start() { dAllocateODEDataForThread(dAllocateMaskAll); world = dWorldCreate(); dWorldSetGravity (world,0,0,-9.8); contact_group = dJointGroupCreate(0); space = dSimpleSpaceCreate (0); // first, the ground plane // it has to coincide with the plane we have in drawstuff ground = dCreatePlane(space, 0, 0, 1, 0); // now a ball dMass m; dMassSetSphere(&m, 0.1, ball_radius); ball1_geom = dCreateSphere(space, ball_radius); ball1_body = dBodyCreate(world); dGeomSetBody(ball1_geom, ball1_body); dBodySetMass(ball1_body, &m); ball2_geom = dCreateSphere(space, ball_radius); ball2_body = dBodyCreate(world); dGeomSetBody(ball2_geom, ball2_body); dBodySetMass(ball2_body, &m); // tracks made out of boxes dGeomID trk; dMatrix3 r1, r2, r3; dVector3 ro = {0, -(0.5*track_gauge + 0.5*track_width), track_elevation}; dMatrix3 s1, s2, s3; dVector3 so = {0, 0.5*track_gauge + 0.5*track_width, track_elevation}; dRFromAxisAndAngle(r1, 1, 0, 0, track_angle); dRFromAxisAndAngle(r2, 0, 1, 0, -track_incl); dMultiply0_333(r3, r2, r1); dRFromAxisAndAngle(s1, 1, 0, 0, -track_angle); dRFromAxisAndAngle(s2, 0, 1, 0, -track_incl); dMultiply0_333(s3, s2, s1); trk = dCreateBox(space, track_len, track_width, track_height); dGeomSetPosition(trk, ro[0], ro[1] + balls_sep, ro[2]); dGeomSetRotation(trk, r3); trk = dCreateBox(space, track_len, track_width, track_height); dGeomSetPosition(trk, so[0], so[1] + balls_sep, so[2]); dGeomSetRotation(trk, s3); // tracks made out of trimesh for (unsigned i=0; i 0.99 // about 8 degrees of difference && dCalcPointsDistance3(contacts[i].geom.pos, contacts[j].geom.pos) < epsilon) { // they are too close closest_point = j; //clog << "found close points: " << j << " and " << i << endl; break; } } if (closest_point != i) { // we discard one of the points if (contacts[i].geom.depth > contacts[closest_point].geom.depth) // the new point is deeper, copy it over closest_point contacts[closest_point] = contacts[i]; } else contacts[new_n++] = contacts[i]; // the point is preserved } //clog << "reduced from " << n << " to " << new_n << endl; n = new_n; for (int i=0; i