00001
00002 #ifndef DOLOG
00003
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
00042 }
00043 first->updateProperties(time);
00044 second->updateProperties(time);
00045
00046
00047
00048
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
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
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
00072
00073
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
00081
00082 Vec3f r1 = -n * BALL_RADIUS;
00083 Vec3f r2 = n * BALL_RADIUS;
00084
00085
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
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
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
00126
00127
00128 Vec3f n = border->normal();
00129 LLOG("plane normal : " << n);
00130
00131
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
00137
00138
00139 Vec3f v_new = vt - (vn * COLLISION_LOSS);
00140 LLOG("new velocity : v_new = " << v_new << " (" << v_new.length() << ")");
00141
00142
00143
00144 Vec3f r = -n * BALL_RADIUS;
00145
00146
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
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
00164 LLOG("\n");
00165 }
00166
00167