diff --git a/src/objectPhysics.cpp b/src/objectPhysics.cpp new file mode 100644 index 0000000..b31f5f1 --- /dev/null +++ b/src/objectPhysics.cpp @@ -0,0 +1,337 @@ +// +// objectPhysics.cpp +// particle_combined +// +// Created by Sebastian Holzki on 11.06.19. +// + +#include "objectPhysics.hpp" + + + +ObjectPhysics::ObjectPhysics(){ + + emitting = 0; + attracting = 0; + isAVisitorObject = false; + age = 0; + +}; + + +// ----------------------------------- + +ObjectPhysics::~ObjectPhysics() +{ + + +}; + + +// ----------------------------------- + + +void ObjectPhysics::update(float deltaT){ + + aging(deltaT); + +} + + + +// ----------------------------------- + + +void ObjectPhysics::setPosition(float x, float y){ + + position.set(x,y); + +} + +// ----------------------------------- + +void ObjectPhysics::setPosition(ofVec2f _position){ + + position = _position; + +} + +// ----------------------------------- + + +ofVec2f ObjectPhysics::getPosition(){ + + return position; + +} + +// ----------------------------------- + + +float ObjectPhysics::getAge(){ + + return age; + +} + + +// ----------------------------------- + +void ObjectPhysics::setIsVisitor(bool isVisitor){ + + isAVisitorObject = isVisitor; + +} + +// ----------------------------------- + +bool ObjectPhysics::getIsVisitorObject(){ + + return isAVisitorObject; + +} + +// ----------------------------------- + +void ObjectPhysics::setEmitting(bool _emitting){ + + emitting = _emitting; + +} + +// ----------------------------------- + +void ObjectPhysics::setAttracting(bool _attracting){ + + attracting = _attracting; + +} + +// ----------------------------------- + + +void ObjectPhysics::aging(float deltaT){ + + if(agingEnabled){ + age += deltaT; + } + +} + +// ---------------------------------------------------------------------- +// *** ATTRAKTORS *** ATTRAKTORS *** ATTRAKTORS *** ATTRAKTORS *** +// ---------------------------------------------------------------------- + +Attraktor::Attraktor(){ + + emitting = false; + attracting = true; + agingEnabled = false; + + type = "attraktor"; + + cout << "Attraktor Konstruktor" << endl; + +}; + +// ----------------------------------- + +Attraktor::Attraktor(float x, float y){ + + emitting = false; + attracting = true; + + type = "attraktor"; + + position.set(x,y); + + cout << "Attraktor Konstruktor überladen" << endl; + }; + +// ----------------------------------- + +Attraktor::Attraktor(ofVec2f _position){ + + emitting = false; + attracting = true; + + type = "attraktor"; + + position.set(_position); + + // cout << "Attraktor Konstruktor überladen (ofVec2f position)" << endl; +}; + +// ----------------------------------- + +Attraktor::~Attraktor(){ + + cout << "Attraktor Destruktor" << endl; + +}; + +// ---------------------------------------------------------------------- +// *** EMITTERS *** EMITTERS *** EMITTERS *** EMITTERS *** +// ---------------------------------------------------------------------- + +Emitter::Emitter(){ + + emitting = true; + attracting = false; + + type = "emitter"; + +}; + +// ----------------------------------- + + +Emitter::Emitter(float _x, float _y){ + + emitting = true; + attracting = false; + + type = "emitter"; + + position.set(_x,_y); + + +}; + +// ----------------------------------- + +Emitter::Emitter(ofVec2f _position){ + + emitting = true; + attracting = false; + + type = "emitter"; + + position.set(_position); + + +}; + +// ----------------------------------- + +Emitter::~Emitter(){ + + +}; + +// ------------------------------------------------------------------ +// *** EMITTER ON STELE *** EMITTER ON STELE *** EMITTER ON STELE *** +// ------------------------------------------------------------------ + + +EmitterOnStele::EmitterOnStele(){ + + emitting = true; + attracting = false; + agingEnabled = true; + + type = "emitterOnStele"; + +}; + +// ----------------------------------- + + +EmitterOnStele::EmitterOnStele(float _x, float _y, bool _aging){ + + emitting = true; + attracting = false; + agingEnabled = _aging; + + type = "emitterOnStele"; + + position.set(_x,_y); + + +}; + +// ----------------------------------- + +EmitterOnStele::EmitterOnStele(ofVec2f _position, bool _aging){ + + emitting = true; + attracting = false; + agingEnabled = _aging; + + type = "emitterOnStele"; + + position.set(_position); + + +}; + +// ----------------------------------- + +EmitterOnStele::~EmitterOnStele(){ + + +}; + + +// ----------------------------------- +// *** ATTRAKTOR ON STELE *** +// ----------------------------------- + +AttraktorOnStele::AttraktorOnStele(){ + + emitting = false; + attracting = true; + + type = "attraktorStele"; + + +}; + +// ----------------------------------- + +AttraktorOnStele::AttraktorOnStele(float x, float y){ + + emitting = false; + attracting = true; + + type = "attraktorStele"; + + position.set(x,y); + +// cout << "AttraktorStele Konstruktor überladen" << endl; +}; + +// ----------------------------------- + +AttraktorOnStele::AttraktorOnStele(ofVec2f _position){ + + emitting = false; + attracting = true; + + type = "attraktorStele"; + + position.set(_position); + + // cout << "Attraktor Konstruktor überladen (ofVec2f position)" << endl; +}; + +// ----------------------------------- + +AttraktorOnStele::~AttraktorOnStele(){ + + cout << "AttraktorStelen Destruktor" << endl; + +}; + +// ----------------------------------- + + + + + + + + + + + diff --git a/src/objectPhysics.hpp b/src/objectPhysics.hpp new file mode 100644 index 0000000..46760ad --- /dev/null +++ b/src/objectPhysics.hpp @@ -0,0 +1,139 @@ +// +// objectPhysics.hpp +// emptyExample +// +// Created by Sebastian Holzki on 01.05.19. +// +#pragma once + + +#include +#include "ofMain.h" + + + + + +class ObjectPhysics { + +public: + + ObjectPhysics(); + ~ObjectPhysics(); + + void update(float deltaT); + + void setPosition(float x, float y); + void setPosition(ofVec2f position); + ofVec2f getPosition(); + + void setEmitting(bool emitting); + void setAttracting(bool attracting); + + void setIsVisitor(bool isVisitor); + bool getIsVisitorObject(); + bool isAVisitorObject; + + void aging(float deltaT); + + string type; + + ofVec2f position; + bool emitting; //if true: Particles will emit from the position + bool attracting; //if true: Particles will be attracted to the position + bool repell; //if true: Particles will be repelled from the position + bool agingEnabled; + + + float getAge(); + float age; + + +protected: + + float force; + float vel; + + + + + +}; + +// ******* ATTRAKTOR ******* ATTRAKTOR ******* ATTRAKTOR ******* ATTRAKTOR ******* ATTRAKTOR ******* + +class Attraktor: public ObjectPhysics { + + +public: + + Attraktor(); + Attraktor(float x, float y); + Attraktor(ofVec2f position); + + ~Attraktor(); + + + + +private: + + +}; + +// ******* EMITTER ******* EMITTER ******* EMITTER ******* EMITTER ******* EMITTER ******* EMITTER ******* + +class Emitter: public ObjectPhysics { + + +public: + + + Emitter(); + Emitter(float x, float y); + Emitter(ofVec2f position); + ~Emitter(); + +private: + +}; + +// *** EMITTER ON STELE *** EMITTER ON STELE *** EMITTER ON STELE *** + + +class EmitterOnStele: public ObjectPhysics { + + +public: + + EmitterOnStele(); + EmitterOnStele(float x, float y, bool aging); + EmitterOnStele(ofVec2f position, bool aging); + ~EmitterOnStele(); + +private: + +}; + + +// ******* ATTRAKTOR STELEN ******* ATTRAKTOR STELEN ******* ATTRAKTOR STELEN ******* ATTRAKTOR STELEN ******* ATTRAKTOR STELEN ******* + +class AttraktorOnStele: public ObjectPhysics { + + +public: + + AttraktorOnStele(); + AttraktorOnStele(float x, float y); + AttraktorOnStele(ofVec2f position); + + ~AttraktorOnStele(); + + + + +private: + + +}; + diff --git a/src/ofApp.cpp b/src/ofApp.cpp index 218b3c2..10c2c10 100644 --- a/src/ofApp.cpp +++ b/src/ofApp.cpp @@ -1,151 +1,1281 @@ + #include "ofApp.h" -//-------------------------------------------------------------- -void ofApp::setup() { - //Initialize 8 empty attractrs - for (int i = 0; i < 8; i++) +// *** GLOBALS DEFINITION *** GLOBALS DEFINITION *** GLOBALS DEFINITION *** GLOBALS DEFINITION **** + + +//-------------------------------------------------------------- +void ofApp::setup(){ + + + // *** SETUP STUFF FOR MAPPING *** + + setupWarpStuff(); + + + + + // *** SETUP STUFF FOR PROGRAM *** + + sceneHeight = ofGetHeight(); + sceneWidth = ofGetWidth(); + + + ofSetBackgroundColor(0,0,0); + + COUNT_VISITORS = 0; + COUNT_VISITORS_LASTFRAME = 0; + COUNT_PARTICLES = 0; + COUNT_PARTICLESYSTEMS = 0; + COUNT_OBJECTPHYSICS = 0; + COUNT_CHECKEDINVISITORS = 0; + + activeTypeOfView = LOGIC; + + currentMode = PARTICLE_MODE_DEFAULT; + currentModeHasChanged = false; + + deltaT = ofGetLastFrameTime(); + + logicalBackground.load("images/logicalBackground2.png"); + + + + + + // *** OBJECT PHYSICS SETUP *** OBJECT PHYSICS SETUP *** OBJECT PHYSICS SETUP *** OBJECT PHYSICS SETUP *** + + //maybe xml default load? + //we can generate all the fix emitters. + //1 in the center + //6 at the "stelen"-bottoms + //6 at the "stelen"-tops + +// *** VERSUCH MIT ofxXmlSettings *** + +// cout << xmlForSetup.load("xml/setup.xml") << endl; + + xmlForSetup.loadFile("xml/setup.xml"); + + centerOfScene.x = xmlForSetup.getValue("setup:center:x" , 0.0) * ofGetHeight(); + centerOfScene.y = xmlForSetup.getValue("setup:center:y" , 0.0) * ofGetHeight(); + + stele1_bottom.x = xmlForSetup.getValue("setup:stele1:x" , 0.0 ) * ofGetHeight(); + stele1_bottom.y = xmlForSetup.getValue("setup:stele1:y" , 0.0 ) * ofGetHeight(); + + stele2_bottom.x = xmlForSetup.getValue("setup:stele2:x" , 0.0 ) * ofGetHeight(); + stele2_bottom.y = xmlForSetup.getValue("setup:stele2:y" , 0.0 ) * ofGetHeight(); + + stele3_bottom.x = xmlForSetup.getValue("setup:stele3:x" , 0.0 ) * ofGetHeight(); + stele3_bottom.y = xmlForSetup.getValue("setup:stele3:y" , 0.0 ) * ofGetHeight(); + + stele4_bottom.x = xmlForSetup.getValue("setup:stele4:x" , 0.0 ) * ofGetHeight(); + stele4_bottom.y = xmlForSetup.getValue("setup:stele4:y" , 0.0 ) * ofGetHeight(); + + stele5_bottom.x = xmlForSetup.getValue("setup:stele5:x" , 0.0 ) * ofGetHeight(); + stele5_bottom.y = xmlForSetup.getValue("setup:stele5:y" , 0.0 ) * ofGetHeight(); + + stele6_bottom.x = xmlForSetup.getValue("setup:stele6:x" , 0.0 ) * ofGetHeight(); + stele6_bottom.y = xmlForSetup.getValue("setup:stele6:y" , 0.0 ) * ofGetHeight(); + +// visitors.emplace_back(new Visitor); +// visitors.emplace_back(new Visitor); + + + +// objectPhysics.emplace_back(new Attraktor(visitors.at(0)->getPosition())); +// objectPhysics.emplace_back(new Attraktor(visitors.at(1)->getPosition())); + + + objectPhysics.emplace_back(new Emitter(centerOfScene)); +// objectPhysics.emplace_back(new Emitter(stele1_bottom)); +//// objectPhysics.emplace_back(new Emitter(stele1_top)); +// objectPhysics.emplace_back(new Emitter(stele2_bottom)); +//// objectPhysics.emplace_back(new Emitter(stele2_top)); +// objectPhysics.emplace_back(new Emitter(stele3_bottom)); +//// objectPhysics.emplace_back(new Emitter(stele3_top)); +// objectPhysics.emplace_back(new Emitter(stele4_bottom)); +//// objectPhysics.emplace_back(new Emitter(stele4_top)); +// objectPhysics.emplace_back(new Emitter(stele5_bottom)); +//// objectPhysics.emplace_back(new Emitter(stele5_top)); +// objectPhysics.emplace_back(new Emitter(stele6_bottom)); +//// objectPhysics.emplace_back(new Emitter(stele6_top)); +//// + + + + + + + for (int i = 0; i < particleSystems.size(); i++){ + + + + } + + + // *** OSC Setup *** OSC Setup *** OSC Setup *** + + receiver.setup(PORT); +// std::cout << "breakpoint ofApp_1 erreicht" << std::endl; + + + + + + + // *** TESTINGAREA *** TESTINGAREA *** TESTINGAREA *** TESTINGAREA *** TESTINGAREA *** + +// objectPhysics.emplace_back(new Emitter(150, 150)); +// objectPhysics.emplace_back(new Emitter(400, 200)); +// +// + + particleSystems.emplace_back(new ParticleSystem); + particleSystems.back()->setup(); + + + +// objectPhysics.emplace_back(new AttraktorAufStelen( 1200 , 500)); + + + +// std::cout << "breakpoint ofApp_2, ofApp setup beendet" << std::endl; + +} + +//-------------------------------------------------------------- +void ofApp::update(){ + +// sceneHeight = ofGetHeight(); +// if(sceneHeight != sceneHeightLastFrame){ +// // refreshXML +// } + + if(currentMode == PARTICLE_MODE_POLYMESH){ + timerAfterCheckin += deltaT; + if(timerAfterCheckin >= 7){ + currentMode = PARTICLE_MODE_DEFAULT; + timerAfterCheckin = 0; + } + } + + deltaT = ofGetLastFrameTime(); + + // *** TESTING AREA *** +// objectPhysics.front()->setPosition(visitors.at(0)->getPosition()); +// objectPhysics.at(1)->setPosition(visitors.at(1)->getPosition()); + + +// for(int i = 0; i < objectPhysics.size(); i++){ +// +// objectPhysics.at(i)->update(deltaT); +// if(objectPhysics.at(i)->getAge() > 4){ +// +// delete objectPhysics.at(i); +// objectPhysics.erase(objectPhysics.begin() + i); +// +// } +// } + + // *** READ ATTRAKTORS FROM CHECKEDINVISITORS *** + + + + + // *** OSC RECEIVER *** OSC RECEIVER *** OSC RECEIVER *** + + + /* + + Here the program will read and convert the information from the tracking, count them & put coordinates of people entering the ground. + We have to define, how this information will affect the particleSystems! + + -Create message, put the stuff from the received OSC in it + -duplicate the msg as string to enable onscreen supervision + -There will be a global visitor count called VISITOR_COUNT + -Use VISITOR_COUNT to correctly update the size of the visitors vector + -Iterate trough Message-values and put information in the visitors vector + + */ + + COUNT_VISITORS_LASTFRAME = visitors.size(); + + if(receiver.hasWaitingMessages() == false){ + COUNT_VISITORS = 0; + } + + while(receiver.hasWaitingMessages()){ + + ofxOscMessage checkinInformations; + receiver.getNextMessage(&checkinInformations); + + oscMsg = ofToString(checkinInformations); + + + cout << "tracking message incoming" << endl; + + + COUNT_VISITORS = checkinInformations.getArgAsInt(0); + + + cout << COUNT_VISITORS << endl; + + + //Größe des visitor-vectors wird festgelegt und auf die größe der ankommenden Trackingdaten angepasst + if(checkinInformations.getAddress() == "/centroidsOfBlob") { + if(COUNT_VISITORS_LASTFRAME != COUNT_VISITORS){ + + if(COUNT_VISITORS_LASTFRAME < COUNT_VISITORS){ + + for(int i = 0; i < COUNT_VISITORS - COUNT_VISITORS_LASTFRAME; i++){ + + visitors.emplace_back(new Visitor); + objectPhysics.emplace_back(new Attraktor(visitors.back()->getPosition())); + objectPhysics.back()->setIsVisitor(true); + + } + + }else{ + + for(int i = 0; i < COUNT_VISITORS_LASTFRAME - COUNT_VISITORS; i++){ + + delete visitors.back(); + visitors.pop_back(); + delete objectPhysics.back(); + objectPhysics.pop_back(); + + } + } + } + + //Fill the visitors vector with the OSC data! + for(int i = 1; i < visitors.size() +1; i++){ + + //put Information into visitors + + float xOfVisitor = checkinInformations.getArgAsFloat(i * 2 - 1); + float yOfVisitor = checkinInformations.getArgAsFloat(i * 2) ; + + visitors.at( i - 1 )->setPosition(xOfVisitor, yOfVisitor); + + } + } + + + + if(checkinInformations.getAddress() == "/players"){ + + stele = getSteleForCheckin(checkinInformations.getArgAsFloat(0)) + 2; + playerType = getTypeForCheckin(checkinInformations.getArgAsFloat(1)); +// cout << oscMsg << endl; + + } + + if(checkinInformations.getAddress() == "/go"){ + + checkedInVisitors.emplace_back(new CheckedInVisitor()); + checkedInVisitors.back()->setup(playerType , stele , sceneWidth, sceneHeight); + + if (currentMode != PARTICLE_MODE_POLYMESH){ + + std::cout << "change of mode to DEFAULT" << std::endl; + currentMode = PARTICLE_MODE_POLYMESH; + currentModeHasChanged = true; + + } + } + + } + + +// +// while(receiver.hasWaitingMessages()){ +// +// ofxOscMessage visitorInformations; +// receiver.getNextMessage(&visitorInformations); +// +// oscMsg = ofToString(visitorInformations); +// +// if(visitorInformations.getAddress() == "/centroidsOfBlob") { +// +// cout << "tracking message incoming" << endl; +// COUNT_VISITORS_LASTFRAME = COUNT_VISITORS; +// COUNT_VISITORS = visitorInformations.getArgAsInt(0); //first Arg of OSC-Message is number of Blobs +// +// +// +//// *** CHECK FOR CHANGES IN THE NUMBER OF VISITORS *** CHECK FOR CHANGES IN THE NUMBER OF VISITORS *** CHECK FOR CHANGES IN THE NUMBER OF VISITORS *** +// +// +//// If there are MORE visitors now, add the difference to the visitors vector +// +// +// if(COUNT_VISITORS > COUNT_VISITORS_LASTFRAME){ +// +// for(int i = 0; i < (COUNT_VISITORS - COUNT_VISITORS_LASTFRAME); i++){ +// +// visitors.emplace_back(new Visitor); +// COUNT_VISITORS++; +// +// +// +// } +// } +// +// +//// If there are LESS visitors now, delete the difference from the visitors vector +// +// +// if(COUNT_VISITORS < COUNT_VISITORS_LASTFRAME){ +// +// for(int i = 0; i < (COUNT_VISITORS_LASTFRAME - COUNT_VISITORS); i++){ +// +// delete visitors.at(visitors.size()); //maybe nicht zulässig, weil fehleranfällig??? +// //erase ergänzen! +// COUNT_VISITORS--; +// } +// +// } +// +// +//// *** TRANSFER TRACKING-INFORMATION INTO VISITOR-CLASS *** TRANSFER TRACKING-INFORMATION INTO VISITOR-CLASS *** +// +// +// for(int i = 1; i <= COUNT_VISITORS; i++){ +// +// //put Information into visitors +// +// float xOfVisitor = visitorInformations.getArgAsFloat(i * 2 - 1) * sceneWidth; +// float yOfVisitor = visitorInformations.getArgAsFloat(i * 2) * sceneHeight; +// +// visitors.at( i - 1 )->setPosition(xOfVisitor, yOfVisitor); +// +// } +// +// } //end of .getAddress() == "/centroidsOfBlob") +// +// } //end of receiver.hasWaitingMessages +// + +// std::cout << "breakpoint ofApp_3 erreicht, OSC-Datenverarbeitung beendet" << std::endl; + + // *** RFID Input *** RFID Input *** RFID Input *** RFID Input *** RFID Input *** + + + // *** GENERATE CHECKED IN VISITOR *** GENERATE CHECKED IN VISITOR *** GENERATE CHECKED IN VISITOR *** + + //if key 'v' is pressed, a new checkedInVisitor will be generated + + + /* + + + + Here we have to define, how the particleSystems react to RFID input. + Read ID of a visitor and let the particlesystems react to it. + + !!! Here in ofApp.cpp there will only be the transfer of incoming information + //about IDs, playertypes, etc. into the update-methods of the particleSystems. !!! + + For example: + + - Tell all particleSystems about a new checkedIn-Visitor + - Set the playerType of one particular particleSystem to the checked in. + + */ + + // *** OBJECT PHYSICS UPDATE *** OBJECT PHYSICS UPDATE *** OBJECT PHYSICS UPDATE *** OBJECT PHYSICS UPDATE *** + + //update the objectPhysics, like creating Attractors for visitors in the default mode + +//get the begin in the object physics vector with visitor information, then set all remaining objectphysics + int beginOfVisitorsInObjectPhysics = getBeginOfVisitorsInObjectPhysics(); + if(visitors.size()){ + refreshCoordinatesOfVisitorAttraktors(beginOfVisitorsInObjectPhysics, sceneHeight); + } + +// int visitorIterator = 0; +// for(beginOfVisitorsInObjectPhysics; beginOfVisitorsInObjectPhysics < (visitors.size()+beginOfVisitorsInObjectPhysics); beginOfVisitorsInObjectPhysics++){ +// +// objectPhysics.at(beginOfVisitorsInObjectPhysics)->setPosition(visitors.at(visitorIterator)->getPosition()); +// visitorIterator++; +// } + +// if(COUNT_VISITORS > visitors.size()){ +// for(int i = 0; i < (COUNT_VISITORS - COUNT_VISITORS_LASTFRAME); i++){ +// +// objectPhysics.emplace_back(new Attraktor(visitors.at(i)->getPosition())); +// objectPhysics.at(i)->setIsVisitor(true); +// +// } +// } +// +// if(COUNT_VISITORS < COUNT_VISITORS_LASTFRAME){ +// for(int i = 0; i < (COUNT_VISITORS_LASTFRAME - COUNT_VISITORS); i++){ +// +// +// // delete objectPhysics.at(i); +// +// } +// } + + + + //adding/killing/modifying of emitters/attractors (objectPhysics) + //Following "if" will guarantee, that we only go into the switch once, if the currentModeHasChanged = true + //Like this we can setup stuff in the update method, without doing it every update + + if(currentMode != lastMode){ + currentModeHasChanged = true; + } + + if(currentModeHasChanged == true){ + + switch (currentMode){ + +// *** DEFAULT OBJECTPHYSICS *** DEFAULT OBJECTPHYSICS *** + + case PARTICLE_MODE_DEFAULT: { + + for(int i = 0; i < objectPhysics.size(); i++){ + + if( (objectPhysics).at(i)->type == "emitter" ){ + + (objectPhysics).at(i)->setEmitting(true); + + } + } + + currentModeHasChanged = false; + + break; + + } + +// *** POLYMESH OBJECTPHYSICS *** POLYMESH OBJECTPHYSICS *** + + case PARTICLE_MODE_POLYMESH: { + + for(int i = 0; i < objectPhysics.size(); i++){ + + if( (objectPhysics).at(i)->type == "emitter" ){ + + (objectPhysics).at(i)->setEmitting(false); + + } + } + + + /* + + implement here: Visitors are Attraktors + implement here: Visitors are Attraktors + implement here: Visitors are Attraktors + + set every visitorrelated ObjectPhysics to attracting = true + + for(int i = 0; i < objectPhysics.size(); i++){ + + if( (objectPhysics).at(i)->type == "attraktor" && objectPhysics).at(i)->isAVisitorObject == true ){ + + (objectPhysics).at(i)->setAttracting(true); + + } + } + + + + + */ + + currentModeHasChanged = false; + + break; + + } + +// *** RFID OBJECTPHYSICS & GENERATING CHECKEDINVISITORS *** + + case PARTICLE_MODE_RFID: { + + for(int i = 0; i < objectPhysics.size(); i++){ + + if( (objectPhysics).at(i)->type == "emitter" ){ + + (objectPhysics).at(i)->setEmitting(false); + + } + } + +// checkedInVisitors.emplace_back(new CheckedInVisitor); + + //5 is the stele where it will be displayed, in the future this number will + //depend on the input, maybe the position ! (check position.distance(stele1-stele6) and + //do the setup for the closest stele, maybe this can be implemented in the setup + +// checkedInVisitors.back->setStele(5); +// checkedInVisitors.back->setup(playerType that is transmitted by RFID); + + + + + + currentModeHasChanged = false; + + break; + } + + + + + + default: + int a = 0; + + + } + } + + + + // *** UPDATE THE CHECKEDINVISITORS *** UPDATE THE CHECKEDINVISITORS *** + +// int beginOfCheckedInVisitors; //returns the position in the objectPhysics-vector that is an checkedInVisitorEmitter +// for(int i = 0; i < objectPhysics.size(); i++){ +// if(objectPhysics.at(i)->type == "emitterOnStele"){ +// +// beginOfCheckedInVisitors = i; +// break; +// } +// } + + + for(int i = 0; i < checkedInVisitors.size(); i++){ + + checkedInVisitors.at(i)->update(deltaT, sceneWidth, sceneHeight); + +// //delete the Emitter on the visitors bottom if the visitor gets older than 3 (number can be replaced later) + if(checkedInVisitors.at(i)->getAge() > 50){ + + delete checkedInVisitors.at(i); + checkedInVisitors.erase(checkedInVisitors.begin() + i); + + } + } + +// if(checkedInVisitors.at(i)->getStateOfSetup()==false){ +// +// objectPhysics.emplace_back(new AttraktorOnStele(checkedInVisitors.at(i)->getPosition())); +// checkedInVisitors.at(i)->setStateOfSetup(true); +// } +// else if(checkedInVisitors.at(i)->getStateOfSetup()==true){ +// +// objectPhysics.back()->setPosition(checkedInVisitors.at(i)->getPosition()); +// +// } +// + +// if(checkedInVisitors.at(i)->getStateOfSetup()==false){ +// +// for(int cv = 0; cv < checkedInVisitors.at(i)->attractingPixelsOfHexagon.size(); cv++){ +// +// objectPhysics.emplace_back(new AttraktorOnStele(checkedInVisitors.at(i)->getPositionsOfAttractingPixels().at(cv))); +// checkedInVisitors.at(i)->setStateOfSetup(true); +// +// } +// } + + + + // *** MAIN UPDATE PARTICLE SYSTEMS *** MAIN UPDATE PARTICLE SYSTEMS *** MAIN UPDATE PARTICLE SYSTEMS *** + + //Trigger the TORNADO if there are more then 4 visitors and then make the effect sleep for a while + tornadoTimer += deltaT; + if(tornadoTimer > 30000){ + tornadoIsPossible = true; + } + if(tornadoIsPossible == true){ + if(COUNT_VISITORS > 4){ + + currentMode = PARTICLE_MODE_TORNADO; + tornadoIsPossible = false; + tornadoTimer = 0; + + } + } + + + for (int p = 0; p < particleSystems.size(); p++){ + + // Update particle systems + + //How to modify a specific particleSystem? + //Scenario: ParticleSystem 5 should become a dot connecting system + + // if p=5 dann particleMode = PARTICLE_MODE_POLYMESH + + particleSystems.at(p)->update(deltaT, currentMode, &objectPhysics, &checkedInVisitors, sceneWidth, sceneHeight); + +// if( neues xml soll übergeben werden, zB taste/zeit) +// particleSystems.at(p)->loadXML(&xml); + + } +// std::cout << "breakpoint ofApp_4 erreicht, particleSystem.update beendet" << std::endl; + + + //Zähle alle Partikel + COUNT_PARTICLES = 0; + for(int i = 0; i < particleSystems.size(); i++) + { + int particlesInThisSystem = particleSystems.at(i)->particles.size(); + COUNT_PARTICLES += particlesInThisSystem; + } + + lastMode = currentMode; + sceneHeightLastFrame = sceneHeight; + +} //end of update() + + + + +//-------------------------------------------------------------- +void ofApp::draw(){ + + fbo_warp.begin(); + ofClear(0, 0, 0); + + //draw all ParticleSystems that are in the particleSystems vector + + for(int p = 0; p < particleSystems.size(); p++) + { + particleSystems.at(p)->draw(activeTypeOfView); + + } + + +// *** TESTING AREA DRAW *** TESTING AREA DRAW *** + + for(int i = 0; i < checkedInVisitors.size() ; i++){ + + checkedInVisitors.at(i)->draw(); + + } + // drawStelen(sceneWidth, sceneHeight); + + +// --------------------------- + + //Which view is active and how it will look can be found and modified here: + + if(activeTypeOfView == LOGIC){ + + drawLogicalScene(ofGetWidth(), ofGetHeight()); + + } + + if(activeTypeOfView == MAPPED){ + +// drawMappedScene(ofGetWidth(), ofGetHeight()); + + } + + + fbo_warp.end(); + + // FIRST WARP + warpControllerCircle.getWarp(0)->begin(); + fbo_warp.getTexture().drawSubsection(0, 0, 3840, 1200, 0, 0, 1200, 1200); + //fbo_circle.draw(0, 0); + warpControllerCircle.getWarp(0)->end(); + + // SECOND WARP + warpControllerStele1.getWarp(0)->begin(); + fbo_warp.getTexture().drawSubsection(0, 0, 3840, 1200, 2204.444, 0, 293.3333, 1200); + warpControllerStele1.getWarp(0)->end(); + + + // THIRD WARP + warpControllerStele2.getWarp(0)->begin(); + fbo_warp.getTexture().drawSubsection(0, 0, 3840, 1200, 2631.1111, 0, 293.3333, 1200); + warpControllerStele2.getWarp(0)->end(); + + // FOURTH WARP + warpControllerStele3.getWarp(0)->begin(); + fbo_warp.getTexture().drawSubsection(0, 0, 3840, 1200, 3057.7773, 0, 293.3333, 1200); + warpControllerStele3.getWarp(0)->end(); + + + //Supervision of globals + + string countVisitors = ofToString(visitors.size()); + string countParticles = ofToString(COUNT_PARTICLES); + string countParticleSystems = ofToString(particleSystems.size()); + string countObjectPhysics = ofToString(objectPhysics.size()); + string countCheckedInVisitors = ofToString(checkedInVisitors.size()); + + ofSetColor(255,255,255); + + ofDrawBitmapString("framerate: " + ofToString(ofGetFrameRate()), sceneWidth*0.05, sceneHeight*0.70); + ofDrawBitmapString("windowWidth: " + ofToString(ofGetWidth()), sceneWidth*0.05, sceneHeight*0.72); + ofDrawBitmapString("windowHeight: " + ofToString(ofGetHeight()), sceneWidth*0.05, sceneHeight*0.74); + ofDrawBitmapString("currentMode: " + ofToString(getCurrentModeAsString()), sceneWidth*0.05, sceneHeight*0.76 ); + + ofDrawBitmapString("visitors: " + countVisitors, sceneWidth*0.05, sceneHeight*0.80); + ofDrawBitmapString("checkedInVisitors: " + countCheckedInVisitors, sceneWidth*0.05, sceneHeight*0.82); + ofDrawBitmapString("particleSystems: " + countParticleSystems, sceneWidth*0.05, sceneHeight*0.86); + ofDrawBitmapString("particles: " + countParticles, sceneWidth*0.05, sceneHeight*0.88); + ofDrawBitmapString("objectphysics: " + countObjectPhysics, sceneWidth*0.05, sceneHeight*0.9); + + + // ofDrawBitmapString(ofToString(objectPhysics.at(0)->getPosition()), 100, 500); + if(checkedInVisitors.size()){ + ofDrawBitmapString("oldest Visitor: " + ofToString(checkedInVisitors.at(0)->getAge()), sceneWidth*0.05, sceneHeight*0.94); + } +// std::cout << "breakpoint ofApp_5 erreicht, supervision globals beendet" << std::endl; + + + + + //Supervision of visitors + + for (int i = 0; i < visitors.size(); i++) { + + string x = ofToString(visitors.at(i)->getX()); + string y = ofToString(visitors.at(i)->getY()); + + ofDrawBitmapString("x: " + x + " y: " + y, 100, 100 + i * 20); + } + +// std::cout << "breakpoint ofApp_6 erreicht, supervision visitors beendet" << std::endl; + + + + +// std::cout << "breakpoint ofApp_7 erreicht, drawing_ofApp beendet" << std::endl; + + +} + +//-------------------------------------------------------------- + +void ofApp::drawMappedScene(float sceneWidth, float sceneHeight){ + + float xToDrawNextRect = - (sceneWidth / 18); + + for(int i = 0; i < 7; i++){ + + //draw 40/360 noFill rect and then increase the x for the next + ofNoFill(); + ofDrawRectangle(xToDrawNextRect, 0.5*sceneHeight, sceneWidth/9, 0.5*sceneHeight); + xToDrawNextRect += sceneWidth/9; + + ofFill(); + //draw 20/360 black rect and then increase the x for the next + ofDrawRectangle(xToDrawNextRect, 0.5*sceneHeight, sceneWidth/18, 0.5*sceneHeight); + xToDrawNextRect += sceneWidth/18; + } + + + +} + +//-------------------------------------------------------------- + + +void ofApp::drawGrid(float sceneWidth, float sceneHeight, int rows, int columns){ + + ofSetColor(50,50,50); + + //draw columns + for(int i = 0; i < columns-1; i++){ + float xStart = (sceneWidth/columns) * (i+1); + float xEnd = xStart; + float yStart = 0; + float yEnd = sceneHeight; + ofDrawLine(xStart, yStart, xEnd, yEnd); + } + + //draw rows + for(int i = 0; i < rows-1; i++){ + float yStart = (sceneHeight/rows) * (i+1); + float yEnd = yStart; + float xStart = 0; + float xEnd = sceneWidth; + ofDrawLine(xStart, yStart, xEnd, yEnd); + + } + + + +} + +//-------------------------------------------------------------- + +void ofApp::drawStelen(float sceneWidth, float sceneHeight){ + + ofSetColor(60,60,60); + float widthStele = (sceneWidth - sceneHeight) / 9; + float heightStele = widthStele*3.5; + float yToDraw = sceneHeight - heightStele; + float xBegin = sceneHeight; + + //draw rectangles + +// for(int i = 0; i < 6; i++){ +// +// float xToDraw = sceneHeight*0.5 + i * 1.5 * widthStele; +// +// ofDrawRectangle(xToDraw, 0 , widthStele, sceneHeight); +// +// } + + //draw schwarzzonen + + ofDrawRectangle(xBegin, 0, widthStele*0.25, sceneHeight); + xBegin += 0.25*widthStele; + + for(int i = 0; i < 5; i++){ + + xBegin += widthStele; + ofDrawRectangle(xBegin, 0, widthStele*0.5, sceneHeight); + xBegin += 0.5*widthStele; + + } + xBegin += widthStele; + ofDrawRectangle(xBegin, 0, widthStele*0.25, sceneHeight); + + + + +} + +//-------------------------------------------------------------- + + + +void ofApp::drawLogicalScene(float sceneWidth, float sceneHeight){ + + + ofNoFill(); + ofDrawCircle(sceneHeight/2, sceneHeight/2, sceneHeight/2); + ofFill(); + + +} + +//-------------------------------------------------------------- + + +string ofApp::getCurrentModeAsString(){ + + string currentModeAsString = ""; + + if(currentMode == PARTICLE_MODE_POLYMESH){ + currentModeAsString = "POLYMESH"; + } + else if(currentMode == PARTICLE_MODE_DEFAULT){ + currentModeAsString = "DEFAULT"; + } + else if(currentMode == PARTICLE_MODE_RFID){ + currentModeAsString = "RFID"; + } + + + return currentModeAsString; + + +} + +//-------------------------------------------------------------- + + +int ofApp::getTypeForCheckin(float x){ + + int numberBetween1and4; + + if(x < 0.25){ + return 1; + }else if(x >= 0.25 && x < 0.5){ + return 2; + }else if(x >= 0.5 && x < 0.75){ + return 3; + }else{ + return 4; + } + +} + + +//-------------------------------------------------------------- + + +int ofApp::getSteleForCheckin(float x){ + + int numberBetween1and3; + + if(x < 0.334){ + return 1; + }else if(x >= 0.334 && x < 0.667){ + return 2; + } + else{ + return 3; + } + +} + +//-------------------------------------------------------------- + +int ofApp::getBeginOfVisitorsInObjectPhysics(){ + + for(int i = 0; i < objectPhysics.size(); i++){ + + if(objectPhysics.at(i)->getIsVisitorObject() == true){ + return i; + } +} +} + +//-------------------------------------------------------------- + + +void ofApp::refreshCoordinatesOfVisitorAttraktors(int beginOfVisitorsInObjectPhysicsVector, float sceneHeight){ + + for(int i = 0; i < visitors.size(); i++){ + + float x = visitors.at(i)->getPosition().x * sceneHeight; + float y = visitors.at(i)->getPosition().y * sceneHeight; + + objectPhysics.at(beginOfVisitorsInObjectPhysicsVector + i)->setPosition(x,y); + + } + + + +} + +//-------------------------------------------------------------- + + +void ofApp::keyPressed(int key){ + + +} + +//-------------------------------------------------------------- +void ofApp::keyReleased(int key){ + + if (key == '1') { + + + checkedInVisitors.emplace_back(new CheckedInVisitor()); + checkedInVisitors.back()->setup(1, 1, ofGetWidth(), ofGetHeight()); + + if (currentMode != PARTICLE_MODE_DEFAULT){ + + std::cout << "change of mode to DEFAULT" << std::endl; + currentMode = PARTICLE_MODE_DEFAULT; + currentModeHasChanged = true; + + } + } + + + // Here the "RFID"-Effect will be faked! + // For example, pressing '1' will trigger the animation for one of the playertypes. + + if ( key == '2') { + + + + int randomStele = ofRandom(3,6); + + checkedInVisitors.emplace_back(new CheckedInVisitor()); + checkedInVisitors.back()->setup(2, randomStele, ofGetWidth(), ofGetHeight()); + + + if(currentMode != PARTICLE_MODE_POLYMESH){ + + std::cout << "change of mode to POLYMESH" << std::endl; + currentMode = PARTICLE_MODE_POLYMESH; + currentModeHasChanged = true; + timerAfterCheckin = 0; + + } + } + + if (key == '3') { + + + + int randomStele = ofRandom(3,6); + + checkedInVisitors.emplace_back(new CheckedInVisitor()); + checkedInVisitors.back()->setup(1, randomStele, ofGetWidth(), ofGetHeight()); + + if(currentMode != PARTICLE_MODE_RFID){ + + std::cout << "change of mode to RFID" << std::endl; + currentMode = PARTICLE_MODE_RFID; + currentModeHasChanged = true; + timerAfterCheckin = 0; + //implement starting a timer here, to trigger DEFAULT_MODE after a specific time + } + } + + if (key == '4') { + + if(listeningForStelenInput == true){ + + int randomStele = ofRandom(3,6); + + checkedInVisitors.emplace_back(new CheckedInVisitor()); + checkedInVisitors.back()->setup(2, randomStele, ofGetWidth(), ofGetHeight()); + + + } + } + + if (key == '5') { + + if(listeningForStelenInput == true){ + + int randomStele = ofRandom(3,6); + + checkedInVisitors.emplace_back(new CheckedInVisitor()); + checkedInVisitors.back()->setup(3, randomStele, ofGetWidth(), ofGetHeight()); + + + } + } + + if (key == '6') { + + if(listeningForStelenInput == true){ + + int randomStele = ofRandom(3,6); + + checkedInVisitors.emplace_back(new CheckedInVisitor()); + checkedInVisitors.back()->setup(4, randomStele, ofGetWidth(), ofGetHeight()); + + + } + } + + + if ( key == '7') { + + if( activeTypeOfView == LOGIC){ + + activeTypeOfView = MAPPED; + + }else if(activeTypeOfView == MAPPED){ + + activeTypeOfView = LOGIC; + } + } + + if ( key == 'q') { + + + } + + if (key == 's') { //SAVE MAYBE warpControllerStelen + warpControllerCircle.getWarp(0)->setEditing(false); + warpControllerStele1.getWarp(0)->setEditing(false); + warpControllerStele2.getWarp(0)->setEditing(false); + warpControllerStele3.getWarp(0)->setEditing(false); + + } + + if (key == 'x') { //Mapping + // editingWarp = !editingWarp; + warpControllerCircle.getWarp(0)->setEditing(true); + } + + + if (key == 'c') { //Mapping + // editingWarp = !editingWarp; + warpControllerStele1.getWarp(0)->setEditing(true); + } + + if (key == 'v') { //Mapping + // editingWarp = !editingWarp; + warpControllerStele2.getWarp(0)->setEditing(true); + } + + if (key == 'b') { //Mapping + // editingWarp = !editingWarp; + warpControllerStele3.getWarp(0)->setEditing(true); + } + + if (key == 'l') { + // secondWindow.toggleHidden(); + } + + if ( key == 'w') { + + + ofToggleFullscreen(); + } + + + + if ( key == 'r') { + + //So we can use the keys 1-6 for different functionalities. + //If listeningForStelenInput == true there cannot be changes in the mode, + //but it is possible to generate checkedInVisitors + + if( listeningForStelenInput == true){ + + listeningForStelenInput = false; + + }else if(listeningForStelenInput == false){ + + listeningForStelenInput = true; + + } + } + + +} + +//-------------------------------------------------------------- +void ofApp::mouseMoved(int x, int y){ + +// if(visitors.size()){ +// visitors.at(0)->setup(x, y); +// visitors.at(1)->setup(x + 200, y + 200); +// } + +} + +//-------------------------------------------------------------- +void ofApp::mouseDragged(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void ofApp::mousePressed(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseReleased(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseEntered(int x, int y){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseExited(int x, int y){ + +} + +//-------------------------------------------------------------- +void ofApp::windowResized(int w, int h){ + +} + +//-------------------------------------------------------------- +void ofApp::gotMessage(ofMessage msg){ + +} + +//-------------------------------------------------------------- +void ofApp::dragEvent(ofDragInfo dragInfo){ + +} + +//-------------------------------------------------------------- + +void ofApp::setupWarpStuff() { + + ofDisableArbTex(); + sceneSizeWarp.set(3840, 1200); + + fbo_warp.allocate(sceneSizeWarp.x, sceneSizeWarp.y, GL_RGB); + + fbo_warp.begin(); + ofClear(0); + fbo_warp.end(); + + // * WARP CONTROLLING * * WARP CONTROLLING * * WARP CONTROLLING * * WARP CONTROLLING * * WARP CONTROLLING * + //load warp settings from file if present + //this->warpController.loadSettings("settings.json"); + + //if there is no file, generate warp + + if (this->warpControllerCircle.getWarps().empty()) { - attractors.push_back(new Attractor); + std::shared_ptr warpCircle; + + warpCircle = this->warpControllerCircle.buildWarp(); + warpCircle->setSize(sceneSizeWarp.x, sceneSizeWarp.y); + // warp->setEdges(0.0f, 0.0f, 1.0f, 1.0f); + warpCircle->setControlPoint(0, glm::vec2(0.0f, 0.0f)); + warpCircle->setControlPoint(1, glm::vec2(0.333f, 0.0f)); + warpCircle->setControlPoint(2, glm::vec2(0.333f, 1.0f)); + warpCircle->setControlPoint(3, glm::vec2(0.0f, 1.0f)); + } - //OSC reciever port setup - receiver.setup(PORT); + // SECOND WARP - //Black background - ofSetBackgroundColor(0, 0, 0); - - ofSetFrameRate(60); - - birthCount = 0; - - //attractors.at(0)->setup(200, 200); -} - -//-------------------------------------------------------------- -void ofApp::update() { - - // *** OSC RECEIVER *** - while (receiver.hasWaitingMessages()) { - - ofxOscMessage contourCentroids; - receiver.getNextMessage(&contourCentroids); - oscMsg = ofToString(contourCentroids); - - //Get active ammount of attractors (nBlobs) and their x & y coordinates - //Exp. OSC Message: " /centroidsOfBlob ammount xValue, yValue" - if (contourCentroids.getAddress() == "/centroidsOfBlob") { - nBlobs = contourCentroids.getArgAsInt(0); - for (int i = 1; i <= nBlobs; i++) { - xOfCentroid = contourCentroids.getArgAsFloat(i * 2 - 1) * ofGetWindowWidth(); - yOfCentroid = contourCentroids.getArgAsFloat(i * 2) * ofGetWindowHeight(); - - attractors.at(i - 1)->setup(xOfCentroid, yOfCentroid); - } - } - //Delete all Attractors on command - if (contourCentroids.getAddress() == "/checkin") { - for (int i = 0; i < 8; i++) { - attractors.at(i)->setup(0, 0); - } - } - } - - // *** PARTICLE EMITTER *** - - //Capture time based on FrameTime - double deltaT = ofGetLastFrameTime(); - birthCount += deltaT; - - //Birth control for new particles - if (birthCount > 0.001) { - for (int i = 0;i < 4;i++) { - system.push_back(new thParticle); - system.back()->setup(ofVec2f(ofGetWidth()*.5, ofGetHeight()*.5)); - } - birthCount = 0; - } - - - for (int p = 0; p < system.size();) + if (this->warpControllerStele1.getWarps().empty()) { - //Upate particle system /w all active attractors - system.at(p)->update(deltaT, &attractors); + std::shared_ptr warpStele1; + + warpStele1 = this->warpControllerStele1.buildWarp(); + warpStele1->setSize(sceneSizeWarp.x, sceneSizeWarp.y); + // warp_stelen->setEdges(0.0f, 0.0f, 1.0f, 1.0f); + warpStele1->setControlPoint(0, glm::vec2(0.57193f, 0.0f)); + warpStele1->setControlPoint(1, glm::vec2(0.64637f, 0.0f)); + warpStele1->setControlPoint(2, glm::vec2(0.64637f, 1.0f)); + warpStele1->setControlPoint(3, glm::vec2(0.57193f, 1.0f)); - //Delete particles, that reached max Age - if (system.at(p)->getAgeNorm() > 4) { - delete system.at(p); - system.erase(system.begin() + p); - } - else { - p++; - } } -} + // THIRD WARP + if (this->warpControllerStele2.getWarps().empty()) + { + std::shared_ptr warpStele2; + warpStele2 = this->warpControllerStele2.buildWarp(); + warpStele2->setSize(sceneSizeWarp.x, sceneSizeWarp.y); + // warp_stelen->setEdges(0.0f, 0.0f, 1.0f, 1.0f); + warpStele2->setControlPoint(0, glm::vec2(0.68359f, 0.0f)); + warpStele2->setControlPoint(1, glm::vec2(0.75803f, 0.0f)); + warpStele2->setControlPoint(2, glm::vec2(0.75803f, 1.0f)); + warpStele2->setControlPoint(3, glm::vec2(0.68359f, 1.0f)); -//-------------------------------------------------------------- -void ofApp::draw() { - - //Draw particle system - for (int p = 0; p < system.size(); p++) { - system.at(p)->draw(); } + // FORTH WARP - //Capture time based on FrameTime - double deltaT = ofGetLastFrameTime(); - time += deltaT; + if (this->warpControllerStele3.getWarps().empty()) + { + std::shared_ptr warpStele3; + + warpStele3 = this->warpControllerStele3.buildWarp(); + warpStele3->setSize(sceneSizeWarp.x, sceneSizeWarp.y); + // warp_stelen->setEdges(0.0f, 0.0f, 1.0f, 1.0f); + warpStele3->setControlPoint(0, glm::vec2(0.79525f, 0.0f)); + warpStele3->setControlPoint(1, glm::vec2(0.86969f, 0.0f)); + warpStele3->setControlPoint(2, glm::vec2(0.86969f, 1.0f)); + warpStele3->setControlPoint(3, glm::vec2(0.79525f, 1.0f)); - // Delete inactive attractors after 4 seconds based on Frametime - if (time > 2) { - for (int i = 0; i < 8; i++) { - //attractors.at(i)->setup(0, 0); - time = 0; - } } - // *** DEBUG INFO *** - - //All 8 Attractors with x | y coordinates - for (int i = 0; i < 8; i++) { - - //string x = ofToString(attractors.at(i)->getX()); - //string y = ofToString(attractors.at(i)->getY()); - - //ofDrawBitmapString("x: " + x + " y: " + y, 100, 100 + i * 20); - } - //Recieved OSC messages - //ofDrawBitmapString("OSC: " + ofToString(oscMsg),100, 275); - //Elapsed time since last clear of attractors - //ofDrawBitmapString("Time: " + ofToString(time),100, 300); - //Current FPS - //ofDrawBitmapString("FPS: " + ofToString(ofGetFrameRate()), 100, 325); } //-------------------------------------------------------------- -void ofApp::keyPressed(int key) { -} - -//-------------------------------------------------------------- -void ofApp::keyReleased(int key) { - -} - -//-------------------------------------------------------------- -void ofApp::mouseMoved(int x, int y) { - -} - -//-------------------------------------------------------------- -void ofApp::mousePressed(int x, int y, int button) { - -} - -//-------------------------------------------------------------- -void ofApp::mouseReleased(int x, int y, int button) { - -} diff --git a/src/ofApp.h b/src/ofApp.h index 8997ec3..0a4629e 100644 --- a/src/ofApp.h +++ b/src/ofApp.h @@ -1,44 +1,199 @@ #pragma once -#include "ofMain.h" -#include "particle.h" +//addons #include "ofxOsc.h" -#include "ofxGui.h" +#include "ofxWarp.h" + +//headers +//#include "ofMain.h" +#include "particleSystem.hpp" +#include "greatWhole.hpp" +#include "visitor.hpp" +#include "objectPhysics.hpp" +// #include "particle.hpp" + + + + + + + +// *** SETUP OSC INFORMATION *** SETUP OSC INFORMATION *** -//OSC Reciever PORT & HOST IP #define PORT 12345 -#define HOST "172.20.10.2" +//#define HOST "192.168.178.52" -class ofApp : public ofBaseApp { -public: - void setup(); - void update(); - void draw(); +//typeOfView will be used, to toggle between the views of the logical scene and the scene after all the particles have been mapped +//enum typeOfView{ +// LOGIC, +// MAPPED +//}; +// - void keyPressed(int key); - void keyReleased(int key); - void mouseMoved(int x, int y); - void mousePressed(int x, int y, int button); - void mouseReleased(int x, int y, int button); +class ofApp : public ofBaseApp{ + + public: + + void setup(); + void setupWarpStuff(); + void update(); + void draw(); + + void keyPressed(int key); + void keyReleased(int key); + void mouseMoved(int x, int y); + void mouseDragged(int x, int y, int button); + void mousePressed(int x, int y, int button); + void mouseReleased(int x, int y, int button); + void mouseEntered(int x, int y); + void mouseExited(int x, int y); + void windowResized(int w, int h); + void dragEvent(ofDragInfo dragInfo); + void gotMessage(ofMessage msg); + + + + + void drawMappedScene(float x, float y); + void drawLogicalScene(float x, float y); + + int getTypeForCheckin(float x); + int getSteleForCheckin(float x); + + void drawGrid(float sceneWidth, float sceneHeight, int columns, int rows); + void drawStelen(float sceneWidth, float sceneHeight); + + int getBeginOfVisitorsInObjectPhysics(); + + void refreshCoordinatesOfVisitorAttraktors(int beginOfVisitorsInObjectPhysicsVector, float sceneHeight); + + ofImage logicalBackground; + + typeOfView activeTypeOfView; + bool listeningForStelenInput; + + CheckedInVisitor checkedInVisitor; + + //global mode for the whole scene; particles & particlesystem & objectPhysics will know about this! + particleMode currentMode; + + //shall be used for checking if there has be a Change in the mode, + //to be able to generate stuff in the update method without generating it in every iteration + particleMode lastMode; + + //mode for setting a Mode only for one or more particular system(s) + particleMode particularMode; + + string getCurrentModeAsString(); + bool currentModeHasChanged; + + ofxXmlSettings xmlForSetup; + ofxXmlSettings xmlSettings; + + // *** MAGIC INSIDE *** MAGIC INSIDE *** MAGIC INSIDE *** + + vector objectPhysics; + + vector particleSystems; + + vector visitors; + + vector checkedInVisitors; + + + //important stuff that regulates, whether a tornado can be triggered or not. + //tornadoIsPossible will be set false after the tornado has been triggered + //tornadoIsPossible will be set true after some time has passed + bool tornadoIsPossible; + float tornadoTimer; + + // *** GLOBALS *** GLOBALS *** GLOBALS *** GLOBALS **** + + //Changes in the scene can done with these + //We should load these coordinates in the ofApp/setup() depending on the rendered scene, maybe via xml? + + ofVec2f centerOfScene; + ofVec2f stele1_bottom; + ofVec2f stele1_top; + ofVec2f stele2_bottom; + ofVec2f stele2_top; + ofVec2f stele3_bottom; + ofVec2f stele3_top; + ofVec2f stele4_bottom; + ofVec2f stele4_top; + ofVec2f stele5_bottom; + ofVec2f stele5_top; + ofVec2f stele6_bottom; + ofVec2f stele6_top; + + + + //Supervision can be done with these + + int COUNT_PARTICLES; + //+1 for every new Particle, -1 for every Particle that gets older than the defined maxLife + + int COUNT_VISITORS; + //the visitor count will be fed with the nBlobs-value from incoming OSC messages + + int COUNT_VISITORS_LASTFRAME; + + int COUNT_PARTICLESYSTEMS; + + int COUNT_OBJECTPHYSICS; + + int COUNT_CHECKEDINVISITORS; + + //OSC Buffer (we will store the information here and wait for the "go" (checkin) message to use it) + int stele; + int playerType; + + + float timerAfterCheckin; + + + + string oscMsg; + ofxOscReceiver receiver; + + private: - - // OSC Receiver - string oscMsg; - ofxOscReceiver receiver; - float timeSent, timeReceived; + // *** MAPPING *** MAPPING *** MAPPING *** MAPPING *** MAPPING *** - int nBlobs; - int blobCount; + ofxWarpController warpControllerCircle; + ofxWarpController warpControllerStele1; + ofxWarpController warpControllerStele2; + ofxWarpController warpControllerStele3; - float xOfCentroid; - float yOfCentroid; + ofFbo fbo_warp; + ofVec2f sceneSizeWarp; - vector system; - vector attractors; - float birthCount; - double time; + + + int sceneWidth; + int sceneHeight; + int sceneHeightLastFrame; + + // *** OSC *** OSC *** OSC *** OSC *** OSC *** + + + float timeSent, timeReceived; + + + float deltaT; + + + GreatWhole dasGrosseGanze; + + int WINDOWSIZE_WIDTH = 1000; + int WINDOWSIZE_HEIGHT = 1000; + + }; + + + diff --git a/src/particle.cpp b/src/particle.cpp index 4c30988..7837884 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -1,148 +1,555 @@ - +// // particle.cpp -// particleSystem +// emptyExample +// +// Created by Sebastian Holzki on 16.04.19. // -#include "particle.h" -#include "ofApp.h" +#include "particle.hpp" + + + Particle::Particle() { - + +// std::cout << "partikel konstruktor" << std::endl; } -//-------------------------------------------------------------------------------------- +// ----------------------------------- + + +Particle::Particle(ofVec2f _position) +{ + + position = _position; + + + +// std::cout << "partikel konstruktor überladen" << std::endl; +} + +// ----------------------------------- Particle::~Particle() { + + + + +} + +// ----------------------------------- + + + +void Particle::setup(ofVec2f _position, float sceneHeight){ + + this->position = _position; + + velocity.set(0,0); + age = 0.0; + maxLife = 25.0; + + color.set(ofRandom(100,150),ofRandom(100,150),ofRandom(20,255)); + size = 1.5; + mass = 100; + + activeSlowingDown = 0; + factorOfSlowingDown = 0.3; + + activeSpeedingUp = factorOfSlowingDown; + factorOfSpeedingUp = 1; + + scaleFactorPerDeltaT = 0.002; + + distanceToCenter = 0; + angleToCenter = 0; + + aging = true; + + particleIsOnGround = isTheSetupPositionOnTheGround(position, sceneHeight); + + + +} + +// ----------------------------------- + +void Particle::update(float deltaT, particleMode currentMode, vector* objectPhysics, vector* checkedInVisitors, float _sceneWidth, float _sceneHeight){ + + + sceneWidth = _sceneWidth; + sceneHeight = _sceneHeight; + + + //angle and distance calculation to be able to map later + updateAngleToCenter(sceneHeight/2, sceneHeight/2); //updates the angle of the particle in relation to the center of the logical scene + updateDistanceToCenter(sceneHeight/2, sceneHeight/2, sceneHeight); //needs the center of the LED-Floor as reference + + + switch ( currentMode ) { + + + case PARTICLE_MODE_DEFAULT: { + + + //what does the PARTICLE do if the mode is 'PARTICLE_MODE_DEFAULT' + + if(currentMode != lastMode && lastMode == PARTICLE_MODE_POLYMESH){ + activeSpeedingUp = factorOfSlowingDown; + } + + if(activeSpeedingUp < factorOfSpeedingUp){ + //This is helping to make the transition from faster to slower a little smoother + //The particle will be slowed down in every iteration until the "destination"-speed is reached + activeSpeedingUp = activeSpeedingUp + deltaT; + } + + + attractParticle(objectPhysics, checkedInVisitors); + + + position += activeSpeedingUp * (velocity * deltaT) ; + + aging = true; + + if(aging == true){ + age += deltaT; + + + + } + + + + + + break; + } + + //------------------------ + + + case PARTICLE_MODE_POLYMESH: { + + //what does the PARTICLE do if its mode is 'PARTICLE_MODE_POLYMESH' + if(currentMode != lastMode){ + activeSlowingDown = 1; + } + + if(activeSlowingDown > factorOfSlowingDown){ + //This is helping to make the transition from faster to slower a little smoother + //The particle will be slowed down in every iteration until the "destination"-speed is reached + activeSlowingDown = activeSlowingDown - deltaT; + } + + + position += activeSlowingDown * (velocity * deltaT) ; + + aging = true; + + if(aging == true){ + age += deltaT; + } + + break; + + } + + //------------------------ + + + case PARTICLE_MODE_TORNADO: { + + + //what does the PARTICLE do if the mode is 'PARTICLE_MODE_TORNADO' + + + break; + } + + //------------------------ + + case PARTICLE_MODE_RFID: { + + //what does the PARTICLE do if its mode is 'PARTICLE_MODE_RFID' + + if(currentMode != lastMode && lastMode == PARTICLE_MODE_POLYMESH){ + activeSpeedingUp = factorOfSlowingDown; + } + + if(activeSpeedingUp < factorOfSpeedingUp){ + //This is helping to make the transition from faster to slower a little smoother + //The particle will be slowed down in every iteration until the "destination"-speed is reached + activeSpeedingUp = activeSpeedingUp + deltaT; + } + + position += activeSpeedingUp * (velocity * deltaT) ; + + size += scaleFactorPerDeltaT * deltaT ; + + aging = true; + + if(aging == true){ + age += deltaT; + } + + + + break; + } + + //------------------------ + + default: {} + + } //end of switch + + + // *** PARTICLE MOVEMENT CONTROL AREA *** PARTICLE MOVEMENT CONTROL AREA *** + + + //first we slow down the particle in their y-direction, + if(particleIsOnGround == false){ + if(velocity.y < 0 && velocity.y > -0.4){ + velocity.y *= 0.995; + } + } + if(distanceToCenter > sceneHeight/4*3){ + + } + + if(particleIsOnGround == false){ + if(position.x < (sceneHeight)){ + position.x = sceneWidth; + } + else if(position.x >= sceneWidth){ + position.x = sceneHeight; + } + } + + size += scaleFactorPerDeltaT * age ; + + lastMode = currentMode; } -//-------------------------------------------------------------------------------------- +// ----------------------------------- + +void Particle::draw(typeOfView activeTypeOfView){ + + updateColor(); + ofSetColor(color); + + ofSetCircleResolution(10); + mapParticle(sceneWidth, sceneHeight); + ofDrawCircle(position, size); + + if(activeTypeOfView == MAPPED){ + ofDrawBitmapString(distanceToCenter, position); + } + ofSetCircleResolution(35); + + +} -void Particle::setup(ofVec2f _position) { +//----------------------------------- - this->position = _position; - vel.set(ofRandom(-3.0, 3.0), ofRandom(-3.0, 3.0)); +float Particle::getMaxLife(){ + + return maxLife; + +} - age = 0.0; - maxLife = 12.0; - color.set(250, 250, 250); +//----------------------------------- - size = ofRandom(4.0, 0.01); +float Particle::getAngle(){ + + return angleToCenter; + +} - mass = ofRandom(100, 250); +//----------------------------------- - tex.load("img/overlay.png"); +ofVec2f Particle::getPosition(){ + + return position; + +} +//----------------------------------- + +void Particle::setRandomVelocity(){ + + velocity.set(ofRandom(-50,50), ofRandom(-50,50)); + +} + +//----------------------------------- + +void Particle::setRandomVelocityOnlyGoingUp(){ + + velocity.set(ofRandom(-50,50), ofRandom(-50,-1)); + +} + +//----------------------------------- + + +void Particle::updateColor(){ + + if(getAgeNorm() >= 1){ + color.set(69 + getAgeNorm() * 104, 164 - getAgeNorm() * 95 , 220, (color , 0)); + } + else{ + color.set(69 + getAgeNorm() * 104, 164 - getAgeNorm() * 95 , 220, (color, (1 - getAgeNorm()) * 255 )); + } +} + +//----------------------------------- + +void Particle::attractParticle(vector* objectPhysics, vector* checkedInVisitors){ + + if(particleIsOnGround == true){ + + for(int i = 0; i < objectPhysics->size(); i++){ + + if(( (*objectPhysics).at(i)->type == "attraktor" ) && (objectPhysics->at(i)->attracting == true)){ + + ofVec2f force; + + force.set(objectPhysics->at(i)->getPosition() - position); + + if(force.length() < 150){ + velocity += force.getNormalized() * 40; + } + if(force.length() < 50){ + velocity -= force.getNormalized() * 20; + } + + } + } + + } + + if(particleIsOnGround == false){ + + for(int i = 0; i < checkedInVisitors->size(); i++){ + + float ageOfCheckedInVisitor = checkedInVisitors->at(i)->getAge(); + + if(( ageOfCheckedInVisitor < 30.0 )){ + + ofVec2f force; + force.set(checkedInVisitors->at(i)->getBottom() - position); + float forceLength = force.length(); + + if(forceLength < 250){ + force = force.getNormalized()* 30 * 4/checkedInVisitors->at(i)->getAge(); + velocity += force; + } + + + } + } + + } + +} + +//----------------------------------- + + +float Particle::getAgeNorm(){ + + return age/maxLife; + +} + +//----------------------------------- + + +void Particle::updateAngleToCenter(float centerX, float centerY){ + + + //case 1 ( distance =< radius ) + ofVec2f center(centerX, centerY); + + ofVec2f particleToCenter = position - center; + //Subtraction: (position of particle) - (position of floor center) = vector between center and particle + + ofVec2f referenceVector(0, 0.5); + + angleToCenter = particleToCenter.getNormalized().angle(referenceVector.getNormalized()); + angleToCenter = angleToCenter + 180; + + //case 2 ( distance > radius + + } -//-------------------------------------------------------------------------------------- - -void Particle::update(float deltaT, vector* attractors) { - - ofVec2f force; - counterOfActiveAttractors = 0; - for (int i = 0; i < attractors->size(); i++) { - if (attractors->at(i)->getX() == 0 && attractors->at(i)->getY() == 0) { - force = 0 * force.getNormalized(); - vel += force; - vel = mass * vel.getNormalized(); - break; - } - - counterOfActiveAttractors++; - force.set(attractors->at(i)->getX() - position.x, attractors->at(i)->getY() - position.y); - - if (force.length() < 150) { - force = 60 * force.getNormalized(); - size = size + ofRandom(.01, 0.01); - - vel += force; - vel = mass * vel.getNormalized(); - } - else { - force = 0 * force.getNormalized(); - vel += force; - vel = mass * vel.getNormalized(); - } - } - - age += deltaT * .5; - position += (vel * deltaT); - - // *** COLLISION *** COLLISION *** COLLISION *** COLLISION *** COLLISION *** COLLISION - - //if (position.x <= 0 || position.x >= ofGetWidth()) { - //vel.x = -vel.x; - //position += (vel * deltaT); - //} - //else if (position.y <= 0 || position.y >= ofGetHeight()) { - //vel.y = -vel.y; - //position += (vel * deltaT); - //} - //else { - //position += (vel * deltaT); - //} +//----------------------------------- - //void thParticle::update(float deltaT, ofVec2f attractor){ - // - // - // age += deltaT; - // - // ofVec2f force = attractor - position; - // color.set(250,250, 250, (1 - age / maxLife) * 255); - // - // if( force.length() < 40 && force.length() > 11 ){ - // velocity = velocity.getNormalized() * mass; - // velocity += 0.01 * force ; - // - // }else if(force.length() < 12){ - // velocity = velocity.getNormalized() * mass; - // velocity += 5 * force ; - // - // }else{ - // - // velocity = velocity.getNormalized() * mass; - // velocity += 0.12 * force ; - // } - // position += velocity * deltaT; - //} +void Particle::updateDistanceToCenter(float centerX, float centerY, float sceneHeight){ + + distanceToCenterLastFrame = distanceToCenter; + + if(particleIsOnGround == true){ + + ofVec2f centerOfFloor(centerX, centerY); + distanceToCenter = position.distance(centerOfFloor); + + } + + if(particleIsOnGround == false){ + + distanceToCenter = sceneHeight/2 + sceneHeight - position.y; + + } + + if(distanceToCenterLastFrame >= sceneHeight/2 && distanceToCenter < sceneHeight/2){ + + //was passiert wenn es vorher größer als radius war, dann kleiner + particleJumpedOnGround = true; + + } + + if(distanceToCenterLastFrame <= sceneHeight/2 && distanceToCenter > sceneHeight/2){ + + //was passiert wenn es vorher kleiner als radius war, dann größer + particleJumpedOffGround = true; + + } + + } -//-------------------------------------------------------------------------------------- +//----------------------------------- -void Particle::draw() { - - color.set(getAgeNorm() * 241,241/ getAgeNorm() ,219); - - ofSetColor(color, (1 - getAgeNorm()) * 255); - //tex.setColor(color); - //tex.draw(position, size, size); - - ofDrawCircle(position, size); +bool Particle::isTheSetupPositionOnTheGround(ofVec2f _position, float sceneHeight){ + + + + ofVec2f centerOfFloor(sceneHeight/2, sceneHeight/2); + distanceToCenter = _position.distance(centerOfFloor); + + if(distanceToCenter > (sceneHeight/2)){ + + return false; + + }else{ + + return true; + + } + } -//-------------------------------------------------------------------------------------- +//----------------------------------- -float Particle::getAgeNorm() { - return age / maxLife; +void Particle::mapParticle(float sceneWidth, float sceneHeight){ + + //The mapping works with the information about the particle's distance to the center and its angle to the center (distanceToCenter, angleToCenter). + //if the particle gets too far away from the center, it will leave the LED-Floor. Then there is a small black gap. + //After that it will hit the "Stelen". The Stelen are represented by a 360degree circle, 40deg for every Stele, 20deg for every black gap in between. + + + if(particleJumpedOffGround == true){ + + position.y = sceneHeight - 20; + //sceneWidth noch ändern damit es sich am kreisumfang orientiert + position.x = (sceneHeight + angleToCenter/360 * (sceneWidth - sceneHeight)); + position.x += (sceneWidth - sceneHeight)/12 ; //so we dont have 0 deg exactly at the first pixel of the stelen + if(position.x > sceneWidth){ + + float difference = position.x - sceneWidth; + position.x = sceneHeight + difference; + + } + + ofVec2f referenceVector(0.0, 1.0); //will be used to get an angle of the velocityvector + referenceVector.getNormalized(); + + float lotAmKreisZuAustrittspunkt; + + if(angleToCenter < 90){ + + lotAmKreisZuAustrittspunkt = 270 - angleToCenter; + + } + if(angleToCenter >= 90){ + + lotAmKreisZuAustrittspunkt = angleToCenter - 90; + + } + + float velocityAngleZuReference = velocity.angle(referenceVector); +// velocity = velocity.rotate(270 - lotAmKreisZuAustrittspunkt); + float k = velocity.length(); + velocity.set(0, -k); + particleJumpedOffGround = false; + + + +// cout << "particleJumpedOffGround" << endl; + } + + if(particleJumpedOnGround == true){ + + + //Vorerst nicht implementiert +// particleJumpedOnGround = false; + + } + + + if(distanceToCenter > sceneHeight/2){ + + particleIsOnGround = false; + + }else if(distanceToCenter <= sceneHeight/2){ + + particleIsOnGround = true; + + } + + + + //setze bei übertritt einmal y auf sceneHeight + //setze x genau auf angle/360 * sceneWidth + //setze velocity neu mit weg über gedrehtes lot (siehe blatt) + //führe berechnung normal weiter aus + + + //correcting the velocity to the new way it is going to be displayed + + + } -//-------------------------------------------------------------------------------------- -float Particle::getMaxLife() { - return 1; -} -//-------------------------------------------------------------------------------------- \ No newline at end of file + + + + + + + + + + + + +