00001 #include "statemachine.h"
00002 #include "debug.h"
00003 #include "random.h"
00004 #include "fast_atof.h"
00005 #include "flock.h"
00006 #include "boid.h"
00007 #include "flockanimatordefault.h"
00008 #include "gui.h"
00009 #include "terrain.h"
00010 #include "stateflocksimulation.h"
00011
00012 using namespace irr;
00013 using namespace core;
00014 using namespace scene;
00015 using namespace video;
00016 using namespace gui;
00017
00018 extern StateMachine* sm;
00019 extern Debug* dbg;
00020 extern ITimer* timer;
00021
00022 StateFlockSimulation::StateFlockSimulation(c8* n, IrrlichtDevice* d) : State(n, d)
00023 {
00024
00025 }
00026
00027 StateFlockSimulation::~StateFlockSimulation()
00028 {
00029
00030 }
00031
00032 bool StateFlockSimulation::OnEvent(SEvent event)
00033 {
00034 if (event.EventType == EET_KEY_INPUT_EVENT)
00035 {
00036 if (event.KeyInput.PressedDown)
00037 {
00038 switch(event.KeyInput.Key)
00039 {
00040 case KEY_ESCAPE:
00041 {
00042 if (guiMesh->isVisible())
00043 {
00044 guiMesh->setVisible(false);
00045 guiFlock->setVisible(false);
00046 }
00047 else
00048 {
00049 guiMesh->setVisible(true);
00050 guiFlock->setVisible(true);
00051 }
00052 return true;
00053 }
00054 }
00055 }
00056 }
00057
00058 if (event.EventType == EET_GUI_EVENT)
00059 {
00060 s32 id = event.GUIEvent.Caller->getID();
00061
00062 switch(event.GUIEvent.EventType)
00063 {
00064 case EGET_BUTTON_CLICKED:
00065 {
00066 switch (id)
00067 {
00068 case 101:
00069 {
00070 if (! device->getGUIEnvironment()->addFileOpenDialog(L"open file"))
00071 {
00072 dbg->log("openFileDialog() cannot create dialog");
00073 }
00074 return true;
00075 }
00076 case 102:
00077 {
00078
00079 addFlock();
00080
00081 s32 meshScale = guiMesh->getSliderValue(111);
00082
00083 for (u32 i=0; i<flocks.size(); i++)
00084 {
00085
00086 list<Boid*>::Iterator it = flocks[i]->getBoidList().begin();
00087 for (; it != flocks[i]->getBoidList().end(); ++it)
00088 {
00089
00090 (*it)->setScale(meshScale / 100.0f);
00091 }
00092 }
00093 return true;
00094 }
00095 case 109:
00096 {
00097
00098 for (u32 i=0; i<flocks.size(); i++)
00099 {
00100 flocks[i]->remove();
00101 flocks[i]->drop();
00102 }
00103 flocks.clear();
00104 return true;
00105 }
00106 case 199:
00107 {
00108 sm->pushEvent("STATE_MENU");
00109 return true;
00110 }
00111 default:
00112 {
00113 dbg->log("StateFlockSimulation::OnEvent() unhandelt event from id", id);
00114 return false;
00115 }
00116 }
00117 }
00118
00119 case EGET_FILE_SELECTED:
00120 {
00121
00122 IGUIFileOpenDialog* dialog = (IGUIFileOpenDialog*)event.GUIEvent.Caller;
00123 stringw path(dialog->getFilename());
00124 guiMesh->setTextFromID(100, path);
00125 addFlock();
00126 return true;
00127 }
00128
00129 case EGET_SCROLL_BAR_CHANGED:
00130 {
00131 switch (id)
00132 {
00133 case 104:
00134 {
00135
00136 s32 separation = guiFlock->getSliderValue(104);
00137 for (u32 i=0; i<flocks.size(); i++)
00138 {
00139 flocks[i]->setSeparationWeight(separation);
00140 }
00141 break;
00142 }
00143 case 106:
00144 {
00145
00146 s32 alignment = guiFlock->getSliderValue(106);
00147 for (u32 i=0; i<flocks.size(); i++)
00148 {
00149 flocks[i]->setAlignmentWeight(alignment);
00150 }
00151 break;
00152 }
00153 case 108:
00154 {
00155
00156 s32 cohesion = guiFlock->getSliderValue(108);
00157 for (u32 i=0; i<flocks.size(); i++)
00158 {
00159 flocks[i]->setCohesionWeight(cohesion);
00160 }
00161 break;
00162 }
00163 case 113:
00164 {
00165
00166 s32 radius = guiFlock->getSliderValue(113);
00167 for (u32 i=0; i<flocks.size(); i++)
00168 {
00169 flocks[i]->setNeighborRadius(radius * 10);
00170 }
00171 break;
00172 }
00173 case 115:
00174 {
00175
00176 s32 seekness = guiFlock->getSliderValue(115);
00177 for (u32 i=0; i<flocks.size(); i++)
00178 {
00179 flocks[i]->setSeekTargetWeight(seekness);
00180 }
00181 break;
00182 }
00183 case 111:
00184 {
00185
00186 s32 meshScale = guiMesh->getSliderValue(111);
00187 for (u32 i=0; i<flocks.size(); i++)
00188 {
00189 list<Boid*>::Iterator it = flocks[i]->getBoidList().begin();
00190 for (; it != flocks[i]->getBoidList().end(); ++it)
00191 {
00192 (*it)->setScale(meshScale / 100.0f);
00193 }
00194 }
00195 break;
00196 }
00197 default:
00198 {
00199 dbg->log("StateFlockSimulation::OnEvent() unhandelt event from id", id);
00200 return false;
00201 }
00202 }
00203 return true;
00204 }
00205 }
00206 }
00207
00208 if (event.EventType == EET_MOUSE_INPUT_EVENT)
00209 {
00210 switch(event.MouseInput.Event)
00211 {
00212 case EMIE_LMOUSE_PRESSED_DOWN:
00213 {
00214 return false;
00215 }
00216 case EMIE_RMOUSE_PRESSED_DOWN:
00217 {
00218 return false;
00219 }
00220 case EMIE_MOUSE_WHEEL:
00221 {
00222 f32 speed = event.MouseInput.Wheel;
00223 moveCamera(speed * 100.0f);
00224 return true;
00225 }
00226 }
00227 }
00228
00229 return false;
00230 }
00231
00232 void StateFlockSimulation::render(u32 deltaTime)
00233 {
00234 device->getVideoDriver()->beginScene(true, true, video::SColor(0,0,150,150));
00235 device->getSceneManager()->drawAll();
00236
00237 dbg->show("this is FlockSimulationState");
00238 dbg->show("roll WHEEL to zoom");
00239 dbg->show("polyCount", device->getVideoDriver()->getPrimitiveCountDrawn());
00240 dbg->show("fps", device->getVideoDriver()->getFPS());
00241
00242
00243 s32 sum = 0;
00244 for (u32 i=0; i<flocks.size(); i++)
00245 {
00246 flocks[i]->update(deltaTime);
00247 sum += flocks[i]->getBoidCount();
00248 }
00249 dbg->show("boidsCount", sum);
00250
00251 device->getGUIEnvironment()->drawAll();
00252 device->getVideoDriver()->endScene();
00253
00254
00255 if (!flocks.empty())
00256 {
00257 vector3df flockCenter = flocks.getLast()->getBoundingBox().getCenter();
00258 camera->setTarget(flockCenter);
00259 }
00260 }
00261
00262 void StateFlockSimulation::entry()
00263 {
00264 dbg->log("State", name, "entry");
00265
00266
00267
00268
00269 guiMesh = new Gui(device, stringc("Mesh"), rect<s32>(20, 220, 200, 430));
00270 guiMesh->addText(100, "media/fly/satelite40Faces1Texture.3DS");
00271 guiMesh->addButton(101, "Open mesh file");
00272 guiMesh->addButton(102, "Create flock");
00273 guiMesh->addButton(109, "Clear scene");
00274 guiMesh->addSlider(111, "Meshscale", 16);
00275 guiMesh->addButton(199, "Exit");
00276
00277 guiFlock = new Gui(device, stringc("Flock behavior mixer"), rect<s32>(600, 20, 780, 120));
00278 guiFlock->addSlider(104, "Separation", 36);
00279 guiFlock->addSlider(106, "Alignment", 0);
00280 guiFlock->addSlider(108, "Cohesion", 35);
00281 guiFlock->addSlider(113, "Neighbor_Radius", 10);
00282 guiFlock->addSlider(115, "Seek_Target", 8);
00283
00284
00285 terrain = new Terrain(device, "media/terrain/terrain97_128.bmp", "media/terrain/textur99.bmp", "");
00286
00287
00288 camera = device->getSceneManager()->addCameraSceneNode();
00289 camera->setPosition(terrain->getCenter() + vector3df(500, 1500, 500) );
00290 camera->setRotation(vector3df(60,20,0));
00291
00292
00293 ILightSceneNode* light = device->getSceneManager()->addLightSceneNode(camera);
00294 light->getLightData().Radius *= 40;
00295
00296
00297 device->getSceneManager()->getActiveCamera()->setFarValue(5000);
00298 }
00299
00300 void StateFlockSimulation::exit()
00301 {
00302 dbg->log("State", name, "exit");
00303
00304
00305 for (u32 i=0; i<flocks.size(); i++)
00306 {
00307 flocks[i]->remove();
00308 flocks[i]->drop();
00309 }
00310 flocks.clear();
00311
00312 delete guiMesh;
00313 delete guiFlock;
00314 delete terrain;
00315
00316 device->getSceneManager()->clear();
00317 }
00318
00319 void StateFlockSimulation::moveCamera(f32 speed)
00320 {
00321 vector3df start = camera->getPosition();
00322 vector3df target = camera->getTarget() - start;
00323 target.normalize();
00324 camera->setPosition(start + target * speed);
00325 }
00326
00327 void StateFlockSimulation::addFlock()
00328 {
00329 stringc filePath = guiMesh->getTextFromID(100);
00330 Flock* f = new Flock(device, 50, filePath.c_str(),
00331 device->getSceneManager()->getRootSceneNode() );
00332
00333
00334 f->setSeparationWeight(guiFlock->getSliderValue(104));
00335 f->setAlignmentWeight(guiFlock->getSliderValue(106));
00336 f->setCohesionWeight(guiFlock->getSliderValue(108));
00337 f->setNeighborRadius(guiFlock->getSliderValue(113) * 10);
00338 f->setTarget(terrain->getCenter() + vector3df(0, 1000, 0) );
00339 f->setSeekTargetWeight(guiFlock->getSliderValue(115));
00340
00341 f->setTornadoWeight(1);
00342
00343 flocks.push_back(f);
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 FlockAnimatorDefault* flockAnimDefault = new FlockAnimatorDefault(device);
00355 f->addAnimator(flockAnimDefault);
00356 flockAnimDefault->drop();
00357 }