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 homepage Users' guide
(C) Arxia 2004-2005