src/Collision.cpp

Go to the documentation of this file.
00001 
00002 #ifndef DOLOG
00003 //#define DOLOG
00004 #undef  DOLOG
00005 #endif
00006 
00007 
00008 #include "Collision.h"
00009 
00010 #include <sstream>
00011 #include <iomanip>
00012 
00013 
00016 std::string Collision::dump() const
00017 {
00018     std::stringstream s;
00019     s << "[" << std::setw(6) << std::setprecision(5) << time << " * " << first->name() << " vs " << second->name() << " ]";
00020     return s.str();
00021 }
00022 
00023 
00026 void BallCollision::collide()
00027 {/*{{{*/
00028     assert(first);
00029     assert(second);
00030     assert(first->applyPhysics());
00031     assert(second->applyPhysics());
00032 
00033     LLOG("colliding balls" << dump());
00034     if (first->velocity().length() < PHYS_EPS && second->velocity().length() < PHYS_EPS)
00035     {
00036         LOG("Zeroing");
00037         first->setVelocity(Vec3f(0, 0, 0));
00038         second->setVelocity(Vec3f(0, 0, 0));
00039         first->setAngularVelocity(Vec3f(0, 0, 0));
00040         second->setAngularVelocity(Vec3f(0, 0, 0));
00041 //        return;
00042     }
00043     first->updateProperties(time);
00044     second->updateProperties(time);
00045 
00046     // calculate velocity change
00047 
00048     // collision plane normal
00049     Vec3f n = (first->position() - second->position());
00050     LLOG("distance = " << std::setprecision(8) << n.length());
00051     Vec3f spreadV(0, 0, 0);
00052     if (n.length() < BALL_RADIUS*2 + EPSILON)
00053     {
00054         // avoid gluing
00055         LOG("avoid gluing");
00056         spreadV = n.normal() * powf(fabs(BALL_RADIUS*2 - n.length() + PHYS_EPS), SPREAD_POW) * SPREAD_MAX_V;
00057     }
00058     n.normalize();
00059 
00060     LLOG("plane normal : " << n);
00061     LLOG("spread velocity : " << spreadV);
00062 
00063     // normal and tangential components of the velocities
00064     Vec3f vn1 = -n * first->velocity().dot(-n);
00065     Vec3f vn2 = n * second->velocity().dot(n);
00066     Vec3f vt1 = first->velocity() - vn1;
00067     Vec3f vt2 = second->velocity() - vn2;
00068     LLOG("obj1 : vn1 = " << vn1 << " (" << vn1.length() << ")  vt1 = " << vt1 << " (" << vt1.length() << ")");
00069     LLOG("obj2 : vn2 = " << vn2 << " (" << vn2.length() << ")  vt2 = " << vt2 << " (" << vt2.length() << ")");
00070 
00071     // calculate new velocities using formulas obtained from
00072     // conservation of linear momentum and conservation of kinetic energy
00073     // assume equal masses -> most terms cancel out, normal velocities are exchanged
00074     assert(fabs(first->mass() - second->mass()) < EPSILON);
00075     Vec3f v1_new = vt1 + (vn2 * COLLISION_LOSS) + spreadV;
00076     Vec3f v2_new = vt2 + (vn1 * COLLISION_LOSS) - spreadV;
00077     LLOG("new velocities : v1_new = " << v1_new << " (" << v1_new.length() << ")");
00078     LLOG("                 v2_new = " << v2_new << " (" << v2_new.length() << ")");
00079 
00080     // calculate angular velocity change
00081 
00082     Vec3f r1 = -n * BALL_RADIUS;
00083     Vec3f r2 = n * BALL_RADIUS;
00084     
00085     // difference of perimeter velocities
00086     Vec3f vpr = r2.cross(second->angularVelocity()) - r1.cross(first->angularVelocity());
00087     Vec3f force1(0, 0, 0);
00088     if ((vpr + vt1).length() > EPSILON)
00089         force1 = (vpr + vt1).normal() * (- MUE_BALLS) * first->mass() * (vn2 - vn1 * COLLISION_LOSS).length() / T_IMPULSE;
00090     Vec3f force2(0, 0, 0);
00091     if ((- vpr + vt2).length() > EPSILON)
00092         force2 = (- vpr + vt2).normal() * (- MUE_BALLS) * second->mass() * (vn1 - vn2 * COLLISION_LOSS).length() / T_IMPULSE;
00093     // delta angular velocity
00094     Vec3f dw1 = r1.cross(force1) * 2.5f * T_IMPULSE / (first->mass() * BALL_RADIUS * BALL_RADIUS);
00095     Vec3f dw2 = r2.cross(force2) * 2.5f * T_IMPULSE / (second->mass() * BALL_RADIUS * BALL_RADIUS);
00096     // FIXME limit dw-s
00097     LLOG("vpr = " << vpr << " (" << vpr.length() << ")");
00098     LLOG("F1 = " << force1 << " (" << force1.length() << ")  F2 = " << force2 << " (" << force2.length() << ")");
00099     LLOG("dw1 = " << dw1 << " (" << dw1.length() << ")  dw2 = " << dw2 << " (" << dw2.length() << ")");
00100 
00101     first->setVelocity(v1_new);
00102     second->setVelocity(v2_new);
00103     first->setAngularVelocity(first->angularVelocity() + dw1);
00104     second->setAngularVelocity(second->angularVelocity() + dw2);
00105     LLOG("\n");
00106 }/*}}}*/
00107 
00108 
00111 void BorderCollision::collide()
00112 {/*{{{*/
00113     assert(first);
00114     assert(first->applyPhysics());
00115     assert(second);
00116     assert(!second->applyPhysics());
00117 
00118     LLOG("colliding with border " << dump());
00119     first->updateProperties(time);
00120     TableBorder * border = dynamic_cast<TableBorder *>(second);
00121     assert(border);
00122 
00123     LLOG("distance = " << (border->xAligned() ? first->position().z() : first->position().x()) - border->dist());
00124 
00125     // calculate velocity change
00126 
00127     // collision plane normal
00128     Vec3f n = border->normal();
00129     LLOG("plane normal : " << n);
00130 
00131     // normal and tangential components of the velocities
00132     Vec3f vn = -n * first->velocity().dot(-n);
00133     Vec3f vt = first->velocity() - vn;
00134     LLOG("obj : vn = " << vn << " (" << vn.length() << ")  vt = " << vt << " (" << vt.length() << ")");
00135 
00136     // calculate new velocities using formulas obtained from
00137     // conservation of linear momentum and conservation of kinetic energy
00138     // assume infinite mass of border -> normal velocity is reflected
00139     Vec3f v_new = vt - (vn * COLLISION_LOSS);
00140     LLOG("new velocity : v_new = " << v_new << " (" << v_new.length() << ")");
00141 
00142     // calculate angular velocity change
00143 
00144     Vec3f r = -n * BALL_RADIUS;
00145 
00146     // perimeter velocity
00147     Vec3f vpr = - r.cross(first->angularVelocity());
00148     Vec3f force(0, 0, 0);
00149     if ((vpr + vt).length() > EPSILON)
00150         force = (vpr + vt).normal() * (- MUE_SLIDING) * first->mass() * (vn + vn * COLLISION_LOSS).length() / T_IMPULSE;
00151     // delta angular velocity
00152     Vec3f dw = r.cross(force) * 2.5f * T_IMPULSE / (first->mass() * BALL_RADIUS * BALL_RADIUS);
00153     if (dw.length() > first->angularVelocity().length()*2*COLLISION_LOSS)
00154         dw = first->angularVelocity() * -2 * COLLISION_LOSS;
00155     LLOG("r   = " << r << " (" << r.length() << ")");
00156     LLOG("vpr = " << vpr << " (" << vpr.length() << ")");
00157     LLOG("F   = " << force << " (" << force.length() << ")");
00158     LLOG("dw  = " << dw << " (" << dw.length() << ")");
00159 
00160     first->setVelocity(v_new);
00161     first->setAngularVelocity(first->angularVelocity() + dw);
00162     LLOG("result");
00163 //    first->dump();  // FIXME DEBUG
00164     LLOG("\n");
00165 }/*}}}*/
00166 
00167 

Generated on Fri Feb 1 00:01:42 2008 for Grayfall by  doxygen 1.5.1