/*************************************************************************** File: SimScene.cpp Created: 02/04/2002 Author: Maxim Garber Computer Science Department University of North Carolina - Chapel Hill garber@cs.unc.edu Description: Simulation scene file. ----------------------------------------------------------------------------. Copyright 2002 Maxim Garber *****************************************************************************/ #include "SimScene.h" #include /**************************************************************************** Function : SimScene Description: Constructor ****************************************************************************/ SimScene::SimScene(char* fileName) { FILE* fp = fopen(fileName,"r"); if (fp==NULL) { printf("ERROR: unable to open SceneFile [%s]!\n",fileName); exit(1); } char string[50]; /////////////////////////////////////////////////////////////////////////// // Read Object Names fscanf(fp, "%s", &string); if(strcmp(string, "[scene]") != 0) { printf("ERROR: invalid ObjFile format [%s]!\n",fileName); exit(1); } // read next attribute fscanf(fp, "%s", &string); while(strcmp(string, "[end]") != 0) { if(strcmp(string, "cloth:") == 0) { char clothfile[50]; fscanf(fp, "%s", &clothfile); SimCloth* cloth = new SimCloth(clothfile); _cloths.push_back(cloth); } if(strcmp(string, "sphere:") == 0) { char spherefile[50]; fscanf(fp, "%s", &spherefile); SimSphere* sphere = new SimSphere(spherefile); _spheres.push_back(sphere); } // read next item fscanf(fp, "%s", &string); } // link clothes to collision spheres std::list::iterator s = _spheres.begin(); for(; s!= _spheres.end(); s++) { std::list::iterator c = _cloths.begin(); for(; c!= _cloths.end(); c++) (*c)->AddSphere(*s); } } /**************************************************************************** Function : ~SimScene Description: Destructor ****************************************************************************/ SimScene::~SimScene() { std::list::iterator i = _cloths.begin(); for(; i!= _cloths.end(); i++) delete(*i); _cloths.clear(); std::list::iterator j = _spheres.begin(); for(; j!= _spheres.end(); j++) delete(*j); _spheres.clear(); } /**************************************************************************** Function : Update Description: Updates the objects in the scene ****************************************************************************/ void SimScene::Update(float timeStep) { // update all spheres std::list::iterator j = _spheres.begin(); for(; j!= _spheres.end(); j++) { (*j)->Update(timeStep); // handle intersphere collisions std::list::iterator s = j; s++; float difference, delta[3]; for(; s!= _spheres.end(); s++) { Subtract3fv(delta, (*j)->GetCenter(), (*s)->GetCenter()); difference = (*j)->GetRadius() + (*s)->GetRadius() - Length3fv(delta); if(difference > 0) { // we have a collision project objects to resolve collision float massFactor = (*j)->GetInverseMass();+(*s)->GetInverseMass(); Normalize3fv(delta); float sDelta[3], jDelta[3]; // move sphere s ScalarMult3fv(sDelta, delta, -difference*(*s)->GetInverseMass()/massFactor); (*s)->MoveCenter(sDelta); // move sphere j ScalarMult3fv(jDelta, delta, difference*(*j)->GetInverseMass()/massFactor); (*j)->MoveCenter(jDelta); break; } } } // update all cloths std::list::iterator i = _cloths.begin(); for(; i!= _cloths.end(); i++) (*i)->Update(timeStep); // cull inactive spheres std::list::iterator newEnd = std::stable_partition(_spheres.begin(), _spheres.end(), SimSphereActive); for(j = newEnd; j != _spheres.end(); j++) { SimSphere *sphere = *j; // remove sphere from cloth list std::list::iterator i = _cloths.begin(); for(; i!= _cloths.end(); i++) (*i)->RemoveSphere(sphere); delete sphere; } if (newEnd != _spheres.end()) _spheres.erase(newEnd, _spheres.end()); } /**************************************************************************** Function : Draw Description: Draws all of the objects in the scene ****************************************************************************/ void SimScene::Draw() { // draw all spheres std::list::iterator j = _spheres.begin(); for(; j!= _spheres.end(); j++) (*j)->Draw(); // draw all cloths std::list::iterator i = _cloths.begin(); for(; i!= _cloths.end(); i++) (*i)->Draw(); } /**************************************************************************** Function : AddSphere Description: Adds a sphere to the scene ****************************************************************************/ void SimScene::AddSphere(SimSphere* sphere) { _spheres.push_back(sphere); std::list::iterator c = _cloths.begin(); for(; c!= _cloths.end(); c++) (*c)->AddSphere(sphere); }