00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <thread.h>
00024 #include <math.h>
00025 #include "collision.h"
00026 #include "world.h"
00027 #include "log.h"
00028 #include "agent.h"
00029
00030
00031
00032
00033
00034 Collision::Collision(){
00035 type=noCollision;
00036 }
00037
00038
00039
00040
00041
00042 Collision::Collision(Cylinder *_cyl1, const Point3d &_pt1, Cylinder *_cyl2, const Point3d &_pt2, Vector3d &_normal, collisionType _type){
00043 cyl1=_cyl1;
00044 cyl2=_cyl2;
00045 pt1=_pt1;
00046 pt2=_pt2;
00047 normal=_normal;
00048 type=_type;
00049 }
00050
00051
00052
00053
00054
00055 Collision::Collision(Cylinder *_cyl, const Point3d &_pt, collisionType _type){
00056 cyl1=_cyl;
00057 cyl2=NULL;
00058 pt1=_pt;
00059 type=_type;
00060 normal=Vector3d(0,0,1);
00061 }
00062
00063
00064
00065
00066
00067 Collision::Collision(Cylinder *_cyl, const Point3d &_pt1, const Point3d &_pt2, collisionType _type){
00068 cyl1=_cyl;
00069 cyl2=NULL;
00070 pt1=_pt1;
00071 pt2=_pt2;
00072 type=_type;
00073 normal=Vector3d(0,0,1);
00074 }
00075
00076
00077
00078 Collision::~Collision(){
00079 }
00080
00081
00082
00083
00084 void Collision::resolve(){
00085 if (type==noCollision)
00086 return;
00087
00088 if (cyl2==NULL)
00089 resolveGroundCollision();
00090 else
00091 resolveCylinderCollision();
00092 }
00093
00094 void Collision::resolveGroundCollision(){
00095 Quaternion base=cyl1->orientationBase;
00096
00097 Vector3d relativeVelocity=cyl1->velocity
00098 +(base.toWorld(cyl1->angularVelocity^pt1));
00099
00100 Vector3d tangent(0,0,0);
00101 if ((relativeVelocity.X()!=0)&&(0!=relativeVelocity.Y())){
00102 tangent=Vector3d(relativeVelocity.X(), relativeVelocity.Y(),0);
00103 tangent.normalize();
00104 }
00105
00106 if (type==contact){
00107 Vector3d contactForce=Vector3d(0,0,0);
00108 Vector3d frictionForce=Vector3d(0,0,0);
00109
00110 Vector3d A=cyl1->inertiaInverse*(cyl1->moment - (cyl1->angularVelocity^(cyl1->inertia*cyl1->angularVelocity)));
00111 Vector3d relativeAcceleration=(cyl1->force/cyl1->mass) +
00112 base.toWorld((cyl1->angularVelocity^(cyl1->angularVelocity^pt1)) +
00113 (A^pt1));
00114
00115 if (relativeAcceleration.Z()<0)
00116 contactForce=cyl1->mass*((-relativeAcceleration*normal)*normal);
00117 if (tangent!=Vector3d(0,0,0)){
00118 frictionForce=(contactForce.module()*World::getGroundFrictionCoefficient())*tangent;
00119 }
00120
00121
00122
00123 cyl1->force+=contactForce+frictionForce;
00124
00125
00126 contactForce=base.toBody(contactForce);
00127 frictionForce=base.toBody(frictionForce);
00128
00129 cyl1->moment+=pt1^(contactForce+frictionForce);
00130 }
00131
00132 if (relativeVelocity.Z()<COLLISION_VELOCITY_EPSILUM){
00133 #define mu World::getGroundFrictionCoefficient()
00134 #define Cr World::getGroundRestitutionCoefficient()
00135 Point3d pt1w=base.toWorld(pt1);
00136
00137
00138 double j=(-(1+Cr)*(relativeVelocity.Z())) /
00139 ( (1/cyl1->mass) + (normal*(((pt1w^normal)*cyl1->inertiaInverse)^pt1w)) );
00140
00141 j=fabs(j);
00142
00143 if (j<0){
00144 log <<"J LESS THAN 0!!!"<<j<<endl;
00145 log <<relativeVelocity.toString()<<endl;
00146 log <<cyl1->velocity.toString()<<endl;
00147 cyl1->velocity=Vector3d(0,0,0);
00148 cyl1->angularVelocity=Vector3d(0,0,0);
00149 return;
00150 }
00151 if ((j>1e3)||(j<0))
00152 j=1e3;
00153
00154 Vector3d impulse;
00155 if (fabs(relativeVelocity*tangent) > 0.0)
00156 impulse=(j*normal) + ((mu*j)*tangent);
00157 else
00158 impulse=j*normal;
00159
00160 cyl1->velocity+=impulse/cyl1->mass;
00161 cyl1->angularVelocity+=( pt1^base.toBody(impulse) ) * cyl1->inertiaInverse;
00162 }
00163 }
00164
00165
00166
00167
00168
00169
00170
00171 void Collision::resolveCylinderCollision(){
00172
00173 }