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 "cylinder.h"
00026 #include "log.h"
00027 #include "world.h"
00028 #include "agent.h"
00029 #include "collision.h"
00030
00031
00032
00033
00034 void Cylinder::updateMomentOfInertia(){
00035 double xxyy=((1.0/12.0)*mass*height*height) + ((1.0/4.0)*mass*width*width);
00036 double zz=(1.0/2.0)*mass*width*width;
00037
00038 inertia=Matrix3x3(xxyy,0,0,
00039 0,xxyy,0,
00040 0,0,zz);
00041 inertiaInverse=inertia.Inverse();
00042 }
00043
00044
00045
00046
00047
00048
00049
00050 void Cylinder::newCycle(){
00051 unsigned int i;
00052 updateMomentOfInertia();
00053
00054 if (fabs(velocity.X())<COLLISION_VELOCITY_EPSILUM) velocity=Vector3d(0,velocity.Y(),velocity.Z());
00055 if (fabs(velocity.Y())<COLLISION_VELOCITY_EPSILUM) velocity=Vector3d(velocity.X(),0,velocity.Z());
00056 if (fabs(velocity.Z())<COLLISION_VELOCITY_EPSILUM) velocity=Vector3d(velocity.X(),velocity.Y(),0);
00057
00058 if (fabs(angularVelocity.X())<COLLISION_ANGULARVELOCITY_EPSILUM) angularVelocity=Vector3d(0,angularVelocity.Y(),angularVelocity.Z());
00059 if (fabs(angularVelocity.Y())<COLLISION_ANGULARVELOCITY_EPSILUM) angularVelocity=Vector3d(angularVelocity.X(),0,angularVelocity.Z());
00060 if (fabs(angularVelocity.Z())<COLLISION_ANGULARVELOCITY_EPSILUM) angularVelocity=Vector3d(angularVelocity.X(),angularVelocity.Y(),0);
00061
00062
00063 for(i=son.size();i--;){
00064 son[i]->gluePosition=(orientationWorld*son[i]->gluePositionBody.X()*height) +
00065 (son[i]->orientationWorld*radius);
00066 }
00067
00068 force=Vector3d(0,0,0);
00069 oldForce=force;
00070 moment=Vector3d(0,0,0);
00071 oldMoment=moment;
00072
00073
00074 force+=Vector3d(0,0,1)*mass*World::getGravity();
00075
00076
00077
00078
00079 double speed=velocity.module();
00080 if (speed!=0.0)
00081 force+=((-velocity).normalized())*(speed*speed*World::getLinearDragCoefficient()*width*height);
00082
00083
00084 double aspeed=angularVelocity.module();
00085 if (aspeed!=0.0)
00086 moment+=((-angularVelocity).normalized())*(aspeed*aspeed*World::getAngularDragCoefficient()*width*height);
00087
00088
00089 double f;
00090 double l;
00091 Vector3d L,V;
00092 Vector3d O;
00093
00094 for (i=son.size();i--;){
00095 L=son[i]->gluePosition-son[i]->position;
00096 l=L.module();
00097 if (l==0)
00098 continue;
00099 if (l>length){
00100 drop(son[i]->getId(),NULL,0);
00101 continue;
00102 }
00103 V=-(velocity-son[i]->velocity);
00104 f=(World::getSpringCoefficient()*l+
00105 World::getDamperCoefficient()*(V*L)/l);
00106
00107 O=Vector3d(sin(son[i]->gluePositionBody.Y()),
00108 cos(son[i]->gluePositionBody.Y()),0);
00109
00110
00111
00112
00113
00114 moment+=(O*f)^((O*radius)+Vector3d(0,0,(son[i]->gluePositionBody.X()-0.5)*son[i]->length));
00115
00116
00117
00118 son[i]->moment+=Vector3d(0,0,-f)^(Vector3d(0,0,-length/2));
00119
00120 son[i]->setToGluePosition();
00121 }
00122
00123
00124 Collision *col=checkGroundCollision();
00125 if (NULL!=col){
00126 if (col->getType()==contact)
00127 col->resolve();
00128 delete col;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 }
00138
00139
00140
00141
00142 void Cylinder::setToGluePosition(void){
00143 if (NULL!=father)
00144 position=gluePosition;
00145 }
00146
00147
00148
00149
00150
00151
00152 void Cylinder::movePosition(const Vector3d &ammount){
00153
00154
00155
00156
00157
00158 position+=ammount;
00159 }
00160
00161
00162
00163
00164
00165
00166
00167 void Cylinder::applyForce(const Vector3d &_force, const Point3d &where){
00168 log <<"Do not use this force!"<<endl;
00169 force+=_force;
00170
00171 }
00172
00173
00174
00175
00176
00177
00178 void Cylinder::applyForceOnBody(const Vector3d &_force, const Point3d &where){
00179 force+=orientationBase.toWorld(_force);
00180 moment+= _force^where;
00181 }
00182
00183
00184
00185
00186
00187
00188 void Cylinder::applyVelocity(double dtime){
00189
00190 oldPosition=position;
00191 oldOrientationBase=orientationBase;
00192 oldVelocity=velocity;
00193 oldAngularVelocity=angularVelocity;
00194 oldForce=force;
00195 oldMoment=moment;
00196
00197
00198
00199 Vector3d A=force/mass;
00200 velocity+=A*dtime;
00201 position+=velocity*dtime;
00202
00203
00204 A=inertiaInverse*(moment - (angularVelocity^(inertia*angularVelocity)));
00205
00206 angularVelocity+=A*dtime;
00207 orientationBase+=(orientationBase*angularVelocity) * (0.5 *dtime);
00208 orientationBase.normalize();
00209
00210 position+=orientationWorld*(length/2);
00211
00212 orientationWorld=orientationBase.toWorld(Vector3d(0,0,1));
00213 orientationWorld.normalize();
00214
00215 position-=orientationWorld*(length/2);
00216
00217
00218
00219
00220
00221
00222
00223 }
00224
00225
00226
00227
00228 void Cylinder::undoVelocity(void){
00229 position=oldPosition;
00230
00231 orientationBase=oldOrientationBase;
00232 orientationWorld=orientationBase.toWorld(Vector3d(0,0,1));
00233 orientationWorld.normalize();
00234
00235 velocity=oldVelocity;
00236 angularVelocity=oldAngularVelocity;
00237 force=oldForce;
00238 moment=oldMoment;
00239 }
00240
00241
00242
00243
00244
00245 vector<Collision *> Cylinder::checkCollisions(){
00246 Collision *coll;
00247 vector<Collision *> ret;
00248
00249
00250 coll=checkGroundCollision();
00251 if (NULL!=coll)
00252 ret.push_back(coll);
00253
00254
00255 unsigned int i;
00256 Cylinder *c;
00257 for (i=world->getNumCylinders();i--;){
00258 c=world->getCylinder(i);
00259 if (c!=this)
00260 if ((coll=checkCylinderCollision(c))!=NULL)
00261 ret.push_back(coll);
00262 }
00263
00264 return ret;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 Collision *Cylinder::checkGroundCollision(){
00285 Point3d p1,p2, p0, pb1, pb2,pb0;
00286 Vector3d o=orientationWorld;
00287
00288
00289 p1=getPosition();
00290 p2=p1+(o*height);
00291 p0=p1+(o*(height/2));
00292
00293 pb1=Vector3d(0,0,-length/2);
00294 pb2=Vector3d(0,0,+length/2);
00295 pb0=Vector3d(0,0,0);
00296
00297
00298
00299 if ((p1.Z()<-COLLISION_SPACE_EPSILUM)&&(p2.Z()<-COLLISION_SPACE_EPSILUM)){
00300 if (p1.Z()<p2.Z()){
00301 if ((velocity.Z()+orientationBase.toWorld(angularVelocity^pb1).Z())<COLLISION_VELOCITY_EPSILUM)
00302 return new Collision(this, pb1, penetrating);
00303 }
00304 else{
00305 if ((velocity.Z()+orientationBase.toWorld(angularVelocity^pb2).Z())<COLLISION_VELOCITY_EPSILUM)
00306 return new Collision(this, pb2, penetrating);
00307 }
00308 }
00309 if (p0.Z()<-COLLISION_SPACE_EPSILUM)
00310 if (velocity.Z()<COLLISION_VELOCITY_EPSILUM)
00311 return new Collision(this, pb0, penetrating);
00312 if (p1.Z()<-COLLISION_SPACE_EPSILUM)
00313 if ((velocity.Z()+orientationBase.toWorld(angularVelocity^pb1).Z())<COLLISION_VELOCITY_EPSILUM)
00314 return new Collision(this, pb1, penetrating);
00315 if (p2.Z()<-COLLISION_SPACE_EPSILUM)
00316 if ((velocity.Z()+orientationBase.toWorld(angularVelocity^pb2).Z())<COLLISION_VELOCITY_EPSILUM)
00317 return new Collision(this, pb2, penetrating);
00318
00319
00320
00321 if (force.Z()<0){
00322
00323 if ((p1.Z()<COLLISION_SPACE_EPSILUM)&&(p2.Z()<COLLISION_SPACE_EPSILUM)){
00324 if (p1.Z()<p2.Z())
00325 return new Collision(this, pb1, contact);
00326 else
00327 return new Collision(this, pb2, contact);
00328 }
00329 if (p0.Z()<COLLISION_SPACE_EPSILUM)
00330 return new Collision(this, pb0, contact);
00331 if (p1.Z()<COLLISION_SPACE_EPSILUM)
00332 return new Collision(this, pb1, contact);
00333 if (p2.Z()<COLLISION_SPACE_EPSILUM)
00334 return new Collision(this, pb2, contact);
00335 }
00336
00337
00338 return NULL;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 Collision *Cylinder::checkCylinderCollision(Cylinder *other){
00351 return NULL;
00352
00353
00354 double srr=(other->length+length);
00355 if ( dcc > srr+2*COLLISION_SPACE_EPSILUM)
00356 return NULL;
00357
00358 if ((orientationWorld^other->orientationWorld).module()==0){ // Parallel lines... just check distance...
00359 double d=(orientationWorld^(position-other->position)).module();
00360 d=(d-srr)/2;
00361 if (d<-COLLISION_SPACE_EPSILUM)
00362 return new Collision(this, other, other->getCentreOfGravity()+getCentreOfGravity()/2, penetrating);
00363 else if (d<COLLISION_SPACE_EPSILUM)
00364 return new Collision(this, other, other->getCentreOfGravity()+getCentreOfGravity()/2, contact);
00365 else
00366 return NULL;
00367 }
00368 // Not parallel...
00369
00370
00371
00372
00373 //new Collision(this, other, other->getCentreOfGravity()+getCentreOfGravity()/2, contact);
00374
00375
00376 return NULL;*/
00377 }