Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

Simulator.cpp

Go to the documentation of this file.
00001 #include "Simulator.h"
00002 #include "Border.h"
00003 #include "Circle.h"
00004 #include "SystemSolver.h"
00005 #include "purgeContainer.h"
00006 #include <algorithm>
00007 
00008 
00009 Simulator::Simulator() :
00010    integrator(dtDefault),
00011    draggedObject(NULL) {
00012       
00013    realTime=(real)0.0;
00014 
00015    isContact=0;
00016 
00017    contactSolver=new ContactSolver(&contacts);
00018 
00019    isRightMouseButtonPressed=false;
00020 
00021 }
00022 
00023 Simulator::~Simulator(){
00024    delete(contactSolver); 
00025    deleteObjects();
00026 }
00027 
00028 
00029 
00030 void Simulator::registerObject(PhysicalObject* object){
00031    objects.push_back(object);
00032    object->registerPrimitives(this); //register the object's primitives
00033    sortedObjects[0].push_back(object);
00034    sortedObjects[1].push_back(object);
00035 }
00036 
00037 void Simulator::registerPrimitive(PhysicalObject* object){
00038    primitives.push_back(object);
00039 }
00040 
00041 void Simulator::deleteObjects(){
00042    purgeContainer(objects);
00043 }
00044 
00045 void Simulator::controll(){
00046    PhysicalObjectPVector::iterator objectsI=objects.begin(), objectsEnd=objects.end();
00047    for(; objectsI!=objectsEnd; ++objectsI)
00048       (*objectsI)->controll();
00049 }
00050 
00051 void Simulator::advanceTime(){
00052    realTime += integrator.getDt();
00053    ++timeStep;
00054 
00055 
00056    PhysicalObjectPVector::iterator objectsI, objectsEnd;
00057 
00058    objectsEnd=objects.end();
00059 
00060    deleteContacts(); 
00061    //if we move contact deletion at the end of the cycle, there is no contact information to be drawn on the GUI
00062 
00063    detectContacts();
00064    
00065    isContact = !contacts.empty();
00066 
00067    if(isContact){ 
00068       indexContacts();     
00069    } //if is contact
00070 
00071    if(draggedObject){
00072       applyMouseForce();
00073    }
00074     
00075    for(objectsI=objects.begin(); objectsI!=objectsEnd; ++objectsI) {
00076       (*objectsI)->computeDerivativesWithoutContacts(contactSolver);
00077    }
00078 
00079    if(isContact){
00080       fillContactMatrix();
00081       contactSolver->computeContacts();
00082       contactSolver->uploadForces();
00083       for(objectsI=objects.begin(); objectsI!=objectsEnd; ++objectsI){
00084          (*objectsI)->computeDerivatives(&contacts);
00085       }        
00086    }
00087 
00088    //controll is called here because it may need information about derivatives, for example
00089    //proprioception of speed; it is also called before integration because it may need information
00090    //about the positions of objects
00091    controll();
00092 
00093    for(objectsI=objects.begin(); objectsI!=objectsEnd; objectsI++)
00094       (*objectsI)->integrate(integrator); 
00095 
00096    
00097 }
00098 
00099 /*
00100 void Simulator::detectContacts(){
00101    // basic method, inefficient: n^2 complexity
00102    PhysicalObjectPVector::iterator objectsI1, objectsI2, objectsEnd=objects.end();
00103    for(objectsI1=objects.begin(); objectsI1!=objectsEnd; ++objectsI1){
00104       for(objectsI2 = objectsI1, ++objectsI2; 
00105             objectsI2 != objectsEnd; ++objectsI2) {
00106          (*objectsI1)->detectContacts(*objectsI2, &contacts);
00107         }
00108       (*objectsI1)->detectInternalContacts(&contacts);
00109    }
00110 }
00111 */
00112 
00113 /*
00114 void Simulator::detectContacts(){
00115    // maintains a list of x-sorted objects
00116    sortObjects(0);
00117    PhysicalObjectPVector::iterator i1, i2, e=sortedObjects[0].end();
00118    for(i1=sortedObjects[0].begin(); i1!=e; ++i1){
00119       i2 = i1;
00120       ++i2;
00121       //we know that i2minx>=i1minx
00122       while(i2 != e && (*i2)->boxMin.x<=(*i1)->boxMax.x)  {
00123          if( ((*i1)->boxMin.y>=(*i2)->boxMin.y && (*i1)->boxMin.y<=(*i2)->boxMax.y) ||
00124                ((*i2)->boxMin.y>=(*i1)->boxMin.y && (*i2)->boxMin.y<=(*i1)->boxMax.y) ){
00125             (*i1)->detectContacts(*i2, &contacts);
00126          }
00127          ++i2;
00128       }
00129       (*i1)->detectInternalContacts(&contacts);
00130    }
00131 }
00132 */
00133 
00134 
00135 void Simulator::detectContacts(){
00136    // maintains 2 lists of x-sorted and y-sorted objects
00137    PhysicalObjectPVector::iterator i1, i2, e;
00138    ObjectPair o;
00139 
00140    sortObjects(0);
00141    xContacts.clear();
00142    e=sortedObjects[0].end();
00143    for(i1=sortedObjects[0].begin(); i1!=e; ++i1){
00144       i2 = i1;
00145       ++i2;
00146       while(i2 != e && (*i2)->boxMin[0]<=(*i1)->boxMax[0])  {
00147          xContacts.insert(ObjectPair(*i1, *i2));
00148          ++i2;
00149       }
00150       (*i1)->detectInternalContacts(&contacts);
00151    }
00152 
00153    sortObjects(1);
00154    xyContacts.clear();
00155    e=sortedObjects[1].end();
00156    for(i1=sortedObjects[1].begin(); i1!=e; ++i1){
00157       i2 = i1;
00158       ++i2;
00159       while(i2 != e && (*i2)->boxMin[1]<=(*i1)->boxMax[1])  {
00160          o=ObjectPair(*i1,*i2);
00161          if(xContacts.find(o)!=xContacts.end()) xyContacts.insert(o);
00162          ++i2;
00163       } 
00164    }
00165    
00166    std::set<ObjectPair>::iterator si=xyContacts.begin(),se=xyContacts.end();
00167    for(;si!=se;++si){
00168       (*si).o1->detectContacts((*si).o2,&contacts);
00169    }
00170 }
00171 
00172 
00173 void Simulator::sortObjects(int n){
00174    //insertion sort
00175    assert(n==0 || n==1);
00176    if(sortedObjects[n].size()>1){
00177       PhysicalObject* o;
00178       PhysicalObjectPVector::iterator ib=sortedObjects[n].begin(), ip=ib, i=ip, it, e=sortedObjects[n].end();
00179       PhysicalObjectPVector::reverse_iterator ir;
00180       ++i;
00181       while(i!=e){
00182          if((*i)->boxMin[n]<(*ip)->boxMin[n]){
00183             it=i;
00184             o=*i;
00185             do {
00186                *it=*(it-1);
00187                --it;
00188             }  while(it!=ib && o->boxMin[n]<(*(it-1))->boxMin[n]);
00189             *it=o;
00190          }
00191          ip=i;
00192          ++i;
00193       }
00194    }
00195 }
00196 
00197 
00198 void Simulator::indexContacts(){
00199    /* Set the indexes of contacts. */
00200    unsigned int k=0;
00201    for(GlobalContactInfoVector::iterator it = contacts.begin(), end = contacts.end(); it != end; ++it){
00202       it->contact1->alpha=it->alpha=k;
00203       if(it->contact2!=NULL)
00204          it->contact2->alpha=k;
00205       k++;
00206    }
00207 
00208    contactSolver->init();
00209 
00210 }
00211  
00212 void Simulator::fillContactMatrix(){
00213    for(GlobalContactInfoVector::iterator it = contacts.begin(), end = contacts.end(); 
00214         it != end; ++it){
00215       it->contact1->parentObject->fillContactMatrix(contactSolver, it->contact1);
00216       //contact2 is NULL for torque contacts
00217       if(it->contact2 != NULL) {
00218          it->contact2->parentObject->fillContactMatrix(contactSolver, it->contact2);
00219       }
00220    }
00221 }
00222 
00223 
00224 
00225 void Simulator::computeContacts(){
00226     contactSolver->computeContacts();
00227 }
00228 
00229 void Simulator::deleteContacts(){
00230    PhysicalObjectPVector::iterator objectsI, objectsEnd;
00231    for(objectsI=objects.begin(), objectsEnd=objects.end(); objectsI!=objectsEnd; ++objectsI)
00232       (*objectsI)->deleteContacts();
00233    contacts.clear();
00234 }
00235 
00236 void Simulator::setMouseForce(float x, float y){
00237    PhysicalObjectPVector::iterator objectsI, objectsEnd;
00238    bool objectFound=false;
00239    Vector2 r(x, y);
00240    Vector2 p;
00241    PhysicalObject* o;
00242    for(objectsI=objects.begin(), objectsEnd=objects.end(); objectsI!=objectsEnd && !objectFound; 
00243                         ++objectsI){
00244       objectFound=(*objectsI)->detectMouseContact(r, p, o);
00245       if(objectFound) {
00246          draggedObject=o;
00247          draggingPoint=p;
00248       }
00249    }
00250 }
00251 
00252 void Simulator::unsetMouseForce(){
00253    /*
00254    if(draggedObject){
00255       draggedObject->externalTorque=0;
00256       draggedObject->externalForce.setToZero();
00257    }
00258    */
00259    draggedObject=NULL;
00260 }
00261 
00262 void Simulator::applyMouseForce(){
00263    Vector2 p=draggingPoint;
00264    p.rotate(draggedObject->alpha);
00265    //p is the position of the dragging point relative to the object, 
00266    //expressed in the laboratory reference system
00267 
00268    Vector2 f=p;
00269    f+=draggedObject->r; //f is now the absolute position of the dragging point
00270    f.x=mouseX-f.x;
00271    f.y=mouseY-f.y; //f is now the position of the mouse relative to the dragging point
00272    f*=ThyrixParameters::kMouseForce; //f is now the force
00273 
00274    draggedObject->externalTorque+=p^f;
00275    draggedObject->externalForce+=f;
00276 }
00277 
00278 
00279 void Simulator::draw(GUI *gui){
00280    World::draw(gui);
00281 
00282    gui->setBrushColor(GUI::colorTransparent);    
00283    
00284    PhysicalObjectPVector::iterator it,end;
00285    for(it = objects.begin(), end = objects.end(); it != end; ++it) {
00286       (*it)->draw(gui);
00287 
00288       /*
00289       //draw bounding boxes
00290       gui->setBrushColor(GUI::colorTransparent);  
00291       gui->drawRectangle((*it)->boxMin.x,(*it)->boxMin.y,(*it)->boxMax.x-(*it)->boxMin.x,(*it)->boxMax.y-(*it)->boxMin.y);
00292       */
00293    }
00294 
00295    /*
00296    //draw primitives bounding boxes
00297    for(it = primitives.begin(), end = primitives.end(); it != end; ++it) {
00298       gui->drawRectangle((*it)->boxMin.x,(*it)->boxMin.y,(*it)->boxMax.x-(*it)->boxMin.x,(*it)->boxMax.y-(*it)->boxMin.y);
00299    }
00300    */
00301    
00302    
00303 
00304    /*
00305    //illustrate dragging action
00306    if(draggedObject){
00307       Vector2 r(draggingPoint);
00308       r.rotate(draggedObject->alpha);
00309       gui->drawLine(draggedObject->r+r,mouseX,mouseY);
00310    }
00311    */
00312 }

Thyrix homepageUsers' guide

(C) Arxia 2004-2005