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

world.cc

Go to the documentation of this file.
00001 /*
00002   svas_server -- virtual World Server of Svas
00003   Copyright (c) 2001, 2002 David Moreno Montero
00004  
00005  
00006   This program is free software; you can redistribute it and/or modify
00007   it under the terms of the GNU General Public License as published by
00008   the Free Software Foundation; either version 2 of the License, or
00009   (at your option) any later version.
00010  
00011   This program is distributed in the hope that it will be useful, but
00012   WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   General Public License for more details.
00015  
00016   You should have received a copy of the GNU General Public License
00017   along with this program; if not, write to the Free Software
00018   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00019   02111-1307, USA.  
00020 
00021 */
00022 
00023 #include <thread.h>
00024 #include <math.h>
00025 #include "world.h"
00026 #include "client.h"
00027 #include "log.h"
00028 #include "cylinder.h"
00029 #include "agent.h"
00030 #include "collision.h"
00031 #include "commcenter.h"
00032 
00033 /// The gravity constant of this world 
00034 double World::gravity=-0.0005;//-0.5;
00035 /// Linear drag coefficient
00036 double World::linearDragCoefficient=0.20;
00037 /// Angular drag coefficient
00038 double World::angularDragCoefficient=0.20;
00039 /// Ground restitution coefficient
00040 double World::groundRestitutionCoefficient=0.02;
00041 /// Ground friction coefficient
00042 double World::groundFrictionCoefficient=0.09;
00043 /// Spring coefficient (glue)
00044 double World::springCoefficient=10;
00045 /// Damper coefficient (resistance to union/separation in glue)
00046 double World::damperCoefficient=2;
00047 
00048 
00049 /**
00050  * creates a world that comprehen this bounding box
00051  */
00052 World::World(CommCenter *_commCenter, BoundingBox _bbox){
00053   commCenter=_commCenter;
00054 
00055   bbox=_bbox;
00056   log <<"New World. "<<bbox.toString()<<endl;
00057 
00058   quit=false;
00059 }
00060 
00061 /**
00062  * Is simply adds the agent to the list of agents
00063  */
00064 void World::newAgent(Agent *agent){
00065   log <<"Create new agent"<<endl;
00066   agents.push_back(agent);
00067 }
00068 
00069 /**
00070  * It searchs for a suitable client and creates the agent for that
00071  * client
00072  */
00073 void World::newAgent(Cylinder *cyl, const char *creationMessage, unsigned long int messageSize){
00074   log <<"Create NEW Agent!"<<endl;
00075 
00076   Agent *ag=cyl->getAgent();
00077   if (NULL==ag)
00078     return;
00079   Client *cl=ag->getClient();
00080   if (NULL==cl)
00081     return;
00082   string clientName=cl->getName();
00083 
00084   Client *newClient=commCenter->getClientForMigration(clientName);
00085   if (NULL==newClient){
00086     log <<"Can not find a suitable client for migration, agent not created; cylinder droped to the world"<<endl;
00087     cyl->setNewAgent(NULL);
00088     return;
00089   }
00090   Agent *newAgent=new Agent(newClient, cyl, creationMessage, messageSize);
00091 
00092   agents.push_back(newAgent);
00093 }
00094 
00095 
00096 /**
00097  * When a client go out it's agents are deleted. 
00098  *
00099  * They should be drop to the world. FIXME
00100  */
00101 void World::clientOut(Client *client){
00102   unsigned int i;
00103   for (i=agents.size();i--;)
00104     if (agents[i]->getClient()==client){  /// FIXME! Agents should not be deleted, but let them without an agent.
00105       delete agents[i];
00106       agents.erase(&agents[i]);
00107     }
00108 }
00109 
00110 /**
00111  * Gets and agents given a agentId. If none is found returns a NULL
00112  * pointer.
00113  */
00114 
00115 Agent *World::getAgent(unsigned long int agentId){
00116   unsigned int i;
00117   for (i=agents.size();i--;)
00118     if (agents[i]->getId()==agentId){
00119       return agents[i];
00120     }
00121   return NULL;
00122 }
00123 
00124 /**
00125  * Get a vector of agents that it's center is into the bounding box
00126  */
00127 vector<Agent*> World::getAgents(BoundingBox box){
00128   vector<Agent*> agentList;
00129   unsigned int i;
00130 
00131   for (i=agents.size();i--;){
00132     if (agents[i]->into(box))
00133       agentList.push_back(agents[i]);
00134   }
00135 
00136   return agentList;
00137 }
00138 
00139 
00140 /**
00141  * Prints several stats about the world. Each one is a variable with
00142  * an equal (=) between the variable and the value. Semicolon (;) is
00143  * used as separator.
00144  */
00145 string World::getStats(){
00146   string a; char s[256];
00147 
00148   sprintf(s,"numAgents=%d;",agents.size()); a+=s;
00149   sprintf(s,"numCylinders=%d;",cylinders.size()); a+=s;
00150   sprintf(s,"time=%ld;",sTime()); a+=s;
00151 
00152   return a;
00153 }
00154 
00155 /**
00156  * Runs a time step; first tell all cylinders to acomplish intentions,
00157  * and later move according to forces, velocities and collisions.
00158  */
00159 void World::step(){
00160   unsigned int i;
00161 
00162   /// First signal that we begin a new cycle, so they can reset forces
00163   /// and moments. It also adds some forces as gravity and drags.
00164   /*
00165   /// We HAVE TO make it in this order to correctly apply spring forces
00166   unsigned int j=cylinders.size();
00167   for (i=0;i<j;i++)
00168     cylinders[i]->newCycle();
00169   */
00170   for (i=cylinders.size();i--;){
00171     //log <<"-----+ "<<i<<endl;
00172     cylinders[i]->newCycle();
00173   }
00174 
00175 
00176   /// Then we perform actions
00177   for (i=agents.size();i--;){
00178     vector<Cylinder *> newCyls;
00179     newCyls=agents[i]->performActions();
00180   }
00181 
00182   step(0,1); // one time unit step
00183 
00184   messages.clear();
00185 }
00186 
00187 /**
00188  * Runs a collision detection/reponse step of upper-lower time
00189  * units. This is so to detect correctly all collisions.
00190  */
00191 void World::step(double lowerLimit, double upperLimit){
00192   //log <<"step"<<lowerLimit<<" to "<<upperLimit<<endl;
00193   unsigned int i;
00194 
00195   /// Now apply forces
00196   for (i=cylinders.size();i--;){
00197     //log <<"------ "<<i<<endl;
00198     cylinders[i]->applyVelocity(upperLimit-lowerLimit);
00199   }
00200 
00201   // The last oportunity cames when you've checked too many times
00202   bool lastOportunity=(upperLimit-lowerLimit)<COLLISION_TIME_EPSILUM;
00203 
00204   /// Now check collisions
00205   vector<Collision *> coll;
00206   vector<Collision *> contacts;
00207   bool penetrate=false;
00208   for (i=cylinders.size();(i--)&&(!penetrate);){
00209     coll=cylinders[i]->checkCollisions(); /// Returns all collisions of all it's cylinders
00210     unsigned int j;
00211     for (j=coll.size();j--;){  /// For each, 
00212       contacts.push_back(coll[j]); // add to contacts vector
00213       if ((coll[j]->getType()==penetrating)&&(!lastOportunity)) // Check if penetrating
00214         penetrate=true;
00215     }
00216   }
00217 
00218   // If there is penetration (and I wanna check more times)
00219   if (penetrate&&(!lastOportunity)){ 
00220     for (i=cylinders.size();i--;){ // undo the velocity
00221       cylinders[i]->undoVelocity();
00222     }
00223     step(lowerLimit, (lowerLimit+upperLimit)/2); // repeat in the lower part
00224     step((lowerLimit+upperLimit)/2, upperLimit); // and upper
00225   }
00226   else{ // Only contact, or nothing, or lastOportunity
00227     //    log <<lowerLimit<<" "<<upperLimit<<endl;
00228     for (i=contacts.size();i--;)
00229       contacts[i]->resolve();
00230   }
00231   
00232   for (i=contacts.size();i--;){
00233     delete contacts[i];
00234   }
00235 }
00236 
00237 /**
00238  * Add a new cylinder. All cylinders are in this vector, and are
00239  * here until they finally dissapear.
00240  */
00241 void World::addCylinder(Cylinder *c){
00242   cylinders.push_back(c);
00243 }
00244 
00245 /**
00246  * Add a new cylinder. All cylinders are in this vector, and are
00247  * here until they finally dissapear.
00248  */
00249 void World::delCylinder(Cylinder *c){
00250   unsigned int i;
00251   for (i=cylinders.size();i--;)
00252     if (c==cylinders[i])
00253       cylinders.erase(&cylinders[i]);
00254 }

Generated on Mon Jun 17 19:53:44 2002 for Svas Server by doxygen1.2.16