/*************************************************************************** * Reveal.cpp * Part of Revil * 2015- Florent Berthaut * hitmuri.net ****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "Reveal.hpp" #include <iostream> #include <unistd.h> #include <FL/filename.H> #include <OpenNI.h> #include "geoms/BoxGeometry.hpp" #include "geoms/CamGeometry.hpp" #include "geoms/QuadGeometry.hpp" #include "geoms/SphereGeometry.hpp" #include "geoms/TubeGeometry.hpp" #include "geoms/ConeGeometry.hpp" #include "geoms/FrameGeometry.hpp" #include "modules/RevealedShapeModule.hpp" #include "modules/RevealedPathModule.hpp" #include "modules/RevealedTextModule.hpp" #include "modules/RevealedCutModule.hpp" #include "modules/RevealedArrowModule.hpp" #include "modules/RevealedGridModule.hpp" #include "modules/RevealedModelModule.hpp" #include "modules/GroupModule.hpp" #include "modules/SpaceModule.hpp" #include "modules/PreviewModule.hpp" #include "modules/ProjectorModule.hpp" #include "modules/DepthCamModule.hpp" #include "modules/DepthShapeModule.hpp" #include "modules/DepthMeshModule.hpp" #include "modules/DepthGroupModule.hpp" #include "modules/RootSceneGroupModule.hpp" #include "modules/SceneGroupModule.hpp" #include "modules/OutputManagerModule.hpp" #include "gui/MainWindow.hpp" #include "gui/GuiListener.hpp" #include "osc/OscManager.hpp" #include "osc/OscListener.hpp" #include "audio/AudioManager.hpp" using namespace std; Reveal* Reveal::getInstance() { static Reveal rev; return &rev; } Reveal::~Reveal(){} Reveal::Reveal() : GroupModule() { m_type="Rivill"; m_name="rivill"; addAttribute(new Attribute("open", Attribute::FILE_OPEN_ATTRIBUTE, openCallback, this, Attribute::LOCAL, false)); addAttribute(new Attribute("save", Attribute::FILE_SAVE_ATTRIBUTE, saveCallback, this, Attribute::LOCAL, false)); addAttribute(new Attribute("quit", Attribute::ACTION_ATTRIBUTE, quitCallback, this, Attribute::LOCAL, false)); addAttribute(new Attribute("audio_output", Attribute::BOOL_ATTRIBUTE, audioOutputCallback,this,1,Attribute::GLOBAL)); m_audioOut=false; /* addAttribute(new Attribute("ressources_folder", Attribute::FOLDER_OPEN_ATTRIBUTE, ressourcesCallback, this, Attribute::LOCAL, false)); addAttribute(new Attribute("ressource_upload", Attribute::ACTION_STRING_ATTRIBUTE, uploadCallback,this,2,Attribute::GLOBAL,false)); */ addAttribute(new Attribute("debug_osc_input", Attribute::BOOL_ATTRIBUTE, debugOscCallback,this,1,Attribute::GLOBAL)); m_debugOSC=false; } void idleFunc(void* data) { Reveal::getInstance()->update(); usleep(1000); } void Reveal::init() { m_openPlanned=0; //initialize osc input OscManager::getInstance()->init(); //initialize depth cameras openni::OpenNI::initialize(); openni::OpenNI::setLogConsoleOutput(false); cout<<"Initialized OpenNI "<<openni::OpenNI::getExtendedError()<<endl; //initialize observers counter m_upObsIdCounter=0; //create all scene geometries m_geomsMap[GEOM_BOX] = new BoxGeometry(); m_geomsMap[GEOM_QUAD] = new QuadGeometry(); m_geomsMap[GEOM_SPHERE] = new SphereGeometry(); m_geomsMap[GEOM_TUBE] = new TubeGeometry(); m_geomsMap[GEOM_CONE] = new ConeGeometry(); m_geomsMap[GEOM_FRAME] = new FrameGeometry(); map<GEOM_ID, Geometry*>::iterator itGeom = m_geomsMap.begin(); for(; itGeom!=m_geomsMap.end(); ++itGeom) { itGeom->second->setGeomID(itGeom->first); m_geoms.push_back(itGeom->second); } m_contextHandlersCounter=0; m_maxNbRevealed=502; m_maxNbDepthCams=10; //add the outputs module m_output = new OutputManagerModule(); addChild(m_output); //add spaces module m_spaces = new SpacesModule(); addChild(m_spaces); //create scene module m_scene = new RootSceneGroupModule(); m_scene->addGroupAttributes(); addChild(m_scene); //Initialize main window fl_register_images(); MainWindow::getInstance()->init(); Fl::add_idle(idleFunc, MainWindow::getInstance()); //Initialize glfw for preview and projector windows glewExperimental = GL_TRUE; if(!glfwInit()) { exit(EXIT_FAILURE); } glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); //FIXME GLFW 3.3 glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); glfwWindowHint(GLFW_AUTO_ICONIFY, GL_FALSE); #ifdef GL43 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); #else glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); #endif #ifdef OSX glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); #endif //add preview module m_preview = new PreviewModule(); m_spaces->addChild(m_preview); refreshModules(); //Show main window MainWindow::getInstance()->show(); //start timer gettimeofday(&m_prevTime, NULL); } GLFWwindow* Reveal::getPreviewWindow() { return m_preview->getWindow(); } void Reveal::setAudioOutput(const bool& aud) { if(aud) { AudioManager::getInstance()->init(); } } void Reveal::planOpen(std::string opSt) { //FIXME find better strategy for delaying text m_openPlanned=10; m_openPlannedName=opSt; } void Reveal::update() { //delete listeners, attributes and modules testDelete(); //update osc manager OscManager::getInstance()->update(); //FIXME distinguish between anim and update (cam) //update observers every 50ms timeval curTime, timeDiff; gettimeofday(&curTime,NULL); timersub(&curTime, &m_prevTime, &timeDiff); int timeDiffMs = timeDiff.tv_sec*1000.0+timeDiff.tv_usec/1000.0; m_prevTime=curTime; vector<Module*>::iterator itUp = m_updateObservers.begin(); for(; itUp!=m_updateObservers.end(); ++itUp) { (*itUp)->update(timeDiffMs); } //draw all spaces m_spaces->draw(); //delayed open to fix text rendering issues ... if(m_openPlanned>0) { m_openPlanned--; if(m_openPlanned==0) { open(m_openPlannedName); } } glfwPollEvents(); } int Reveal::run() { return Fl::run(); } void Reveal::askQuit() { MainWindow::getInstance()->cbQuit(); } void Reveal::quit() { glfwTerminate(); exit(0); } void Reveal::open(const std::string& fileName) { cout<<"Opening "<<fileName<<endl; bool open=true; xmlDocPtr doc = xmlReadFile(fileName.c_str(), NULL, 0); xmlNodePtr rootNode = xmlDocGetRootElement(doc); if(doc==NULL || rootNode==NULL) { DEBUG("Could not open file "<<fileName); open=false; } else if(xmlStrcmp(rootNode->name, (const xmlChar*)"Rivill")) { xmlFreeDoc(doc); DEBUG("Could not open file "<<fileName); open=false; } if(open) { //if the file is valid m_currentFile=fileName; //clear the scene and spaces m_scene->deleteChildren(); m_spaces->removeChild(m_preview); m_spaces->deleteChildren(); m_spaces->addChild(m_preview); m_revealedMap.clear(); m_registeredOutputRevealed.clear(); m_registeredOutputDepthCams.clear(); m_upObsIdCounter=0; m_updateObservers.clear(); //and load load(rootNode); m_attributesMap["save"]->initFile(m_currentFile); MainWindow::getInstance()->refreshModules(); DEBUG("Opened file "<<fileName); } } void Reveal::save(const std::string& fileName) { cout<<"Saving to "<<fileName<<endl; m_currentFile=fileName; xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); xmlNodePtr rootNode = GroupModule::save(NULL); xmlDocSetRootElement(doc, rootNode); xmlSaveFormatFileEnc(fileName.c_str(), doc, "UTF-8", 1); xmlFreeDoc(doc); xmlCleanupParser(); } void Reveal::setRessourcesFolder(const std::string& f) { } void Reveal::uploadRessource(const std::vector<std::string>& vf) { } void Reveal::load(xmlNodePtr node) { Module::load(node); xmlNodePtr modsNode; for(modsNode=node->children; modsNode; modsNode=modsNode->next){ if(modsNode->type == XML_ELEMENT_NODE && !xmlStrcmp(modsNode->name, (const xmlChar *) "Modules")) { xmlNodePtr modNode; for(modNode=modsNode->children; modNode; modNode=modNode->next){ if(modNode->type == XML_ELEMENT_NODE) { if(!xmlStrcmp(modNode->name,(const xmlChar *)"Scene")) { m_scene->load(modNode); } else if(!xmlStrcmp(modNode->name,(const xmlChar*)"Spaces")){ m_spaces->load(modNode); } } } } } } Module* Reveal::createModule(const std::string& typeStr) { Module* mod=NULL; if(typeStr.compare("Projector")==0) { mod=new ProjectorModule(); } else if(typeStr.compare("Space")==0) { mod=new SpaceModule(); } else if(typeStr.compare("DepthGroup")==0) { mod=new DepthGroupModule(); } else if(typeStr.compare("DepthCam")==0) { mod=new DepthCamModule(); } else if(typeStr.compare("DepthShape")==0) { mod=new DepthShapeModule(); } else if(typeStr.compare("DepthMesh")==0) { mod=new DepthMeshModule(); } else if(typeStr.compare("SceneGroup")==0) { mod=new SceneGroupModule(); } else if(typeStr.compare("Shape")==0) { mod=new RevealedShapeModule(); } else if(typeStr.compare("Model")==0) { mod=new RevealedModelModule(); } else if(typeStr.compare("Path")==0) { mod=new RevealedPathModule(); } else if(typeStr.compare("Text")==0) { mod=new RevealedTextModule(); } else if(typeStr.compare("Cut")==0) { mod=new RevealedCutModule(); } else if(typeStr.compare("Arrow")==0) { mod=new RevealedArrowModule(); } else if(typeStr.compare("Grid")==0) { mod=new RevealedGridModule(); } return mod; } Listener* Reveal::createListener(const std::string& typeStr) { Listener* lis=NULL; if(typeStr.compare("OscListener")==0) { lis=new OscListener(); } return lis; } int Reveal::getVisibilityMask(const std::string& visibleFrom) { int res=0; map<string, int>::iterator itVis = m_visibleFromMap.find(visibleFrom); if(itVis!=m_visibleFromMap.end()) { res=itVis->second; } return res; } void Reveal::addUpdateObserver(Module* upObs) { m_updateObservers.push_back(upObs); upObs->setUpID(m_upObsIdCounter); m_upObsIdCounter++; } void Reveal::removeUpdateObserver(Module* upObs) { vector<Module*>::iterator itObs = m_updateObservers.begin(); for(; itObs!=m_updateObservers.end(); ) { if((*itObs)->getUpID()==upObs->getUpID()) { itObs = m_updateObservers.erase(itObs); } else { itObs++; } } } void Reveal::addModuleListObserver(ModuleListObserver* obs) { unsigned int obsID=0; while(m_moduleListObservers.find(obsID)!=m_moduleListObservers.end()) { obsID++; } m_moduleListObservers[obsID]=obs; obs->setModuleListObsID(obsID); } void Reveal::removeModuleListObserver(ModuleListObserver* obs) { m_moduleListObservers.erase(obs->getModuleListObsID()); } void Reveal::addContextHandler(ContextHandler* cont) { m_contextHandlers[m_contextHandlersCounter]=cont; cont->setContextHandlerID(m_contextHandlersCounter); m_contextHandlersCounter++; } void Reveal::removeContextHandler(ContextHandler* cont) { m_contextHandlers.erase(cont->getContextHandlerID()); } void Reveal::registerGeom(Geometry* geom) { GEOM_ID newID = GEOM_MODEL; while(m_geomsMap.find(newID)!=m_geomsMap.end()) { newID = GEOM_ID(int(newID)+1); } geom->setGeomID(newID); m_geomsMap[newID]=geom; m_geoms.push_back(geom); } void Reveal::unregisterGeom(Geometry* geom) { m_geomsMap.erase(geom->getGeomID()); vector<Geometry*>::iterator itGeom = m_geoms.begin(); for(; itGeom!=m_geoms.end(); ) { if((*itGeom)->getGeomID()==geom->getGeomID()) { itGeom = m_geoms.erase(itGeom); } else { ++itGeom; } } } void Reveal::registerRevealed(RevealedModule* rev) { m_revealedVec.push_back(rev); updateRevealed(); } void Reveal::unregisterRevealed(RevealedModule* rev) { vector<RevealedModule*>::iterator itRev=m_revealedVec.begin(); for(; itRev!=m_revealedVec.end();) { if((*itRev)->getRevID()==rev->getRevID()) { itRev=m_revealedVec.erase(itRev); } else { ++itRev; } } updateRevealed(); unregisterOutputRevealed(rev); } void Reveal::updateRevealed() { m_revealedMap.clear(); vector<RevealedModule*>::iterator itRev=m_revealedVec.begin(); unsigned int id=1; for(; itRev!=m_revealedVec.end(); ++itRev, ++id) { (*itRev)->setRevID(id); m_revealedMap[id]=*itRev; } } void Reveal::refreshModules() { //recreate map of modules and attributes m_modulesMap.clear(); m_fullAttributesMap.clear(); GroupModule::listModulesAndAttributes("", m_modulesMap, m_fullAttributesMap); //inform observers of the new module list map<unsigned int, ModuleListObserver*>::iterator itObs = m_moduleListObservers.begin(); for(; itObs!=m_moduleListObservers.end(); ++itObs) { itObs->second->updateModulesList(m_modulesMap); } //refresh space/projectors list m_visibleFromVec.clear(); m_visibleFromMap.clear(); m_visibleFromVec.push_back("none"); m_visibleFromMap[m_visibleFromVec.back()]=VISIBLE_FROM_NONE; m_visibleFromVec.push_back("all"); m_visibleFromMap[m_visibleFromVec.back()]=VISIBLE_FROM_ALL; m_spaces->getVisibleFromList(m_visibleFromVec, m_visibleFromMap); map<unsigned int, RevealedModule*>::iterator itMod = m_revealedMap.begin(); for(; itMod!=m_revealedMap.end(); ++itMod) { itMod->second->setVisibleFromList(m_visibleFromVec); } //refresh display MainWindow::getInstance()->refreshModules(); /* //TEMP list all attributes of all modules map<string, Attribute*>::iterator itAtt = m_attributesMap.begin(); for(;itAtt!=m_attributesMap.end(); ++itAtt) { cout<<itAtt->first<<endl; } */ } Attribute* Reveal::findAttribute(const std::string& fullName) { map<string,Attribute*>::iterator itAtt = m_fullAttributesMap.find(fullName); if(itAtt!=m_fullAttributesMap.end()) { return itAtt->second; } return NULL; } Module* Reveal::findModule(const std::string& fullName) { map<string, Module*>::iterator itMod = m_modulesMap.find(fullName); if(itMod!=m_modulesMap.end()) { return itMod->second; } return NULL; } void Reveal::registerOutputRevealed(RevealedModule* rev) { bool found=false; vector<RevealedModule*>::iterator itSh=m_registeredOutputRevealed.begin(); for(; itSh!=m_registeredOutputRevealed.end(); ++itSh) { if((*itSh)->getRevID()==rev->getRevID()) { found=true; } } if(!found) { m_registeredOutputRevealed.push_back(rev); } updateOutputRevealed(); } void Reveal::unregisterOutputRevealed(RevealedModule* rev) { //remove it from list vector<RevealedModule*>::iterator itSh=m_registeredOutputRevealed.begin(); for(; itSh!=m_registeredOutputRevealed.end(); ) { if((*itSh)->getRevID()==rev->getRevID()) { itSh=m_registeredOutputRevealed.erase(itSh); } else { ++itSh; } } //reset offsets updateOutputRevealed(); } void Reveal::updateOutputRevealed() { vector<RevealedModule*>::iterator itSh=m_registeredOutputRevealed.begin(); unsigned int offset=0; for(; itSh!=m_registeredOutputRevealed.end(); ++itSh) { (*itSh)->updateRevOffset(offset); } } void Reveal::registerOutputDepthCam(DepthCamModule* cam) { bool found=false; vector<DepthCamModule*>::iterator itCa=m_registeredOutputDepthCams.begin(); for(; itCa!=m_registeredOutputDepthCams.end(); ++itCa) { if((*itCa)->getDepthID()==cam->getDepthID()) { found=true; } } if(!found) { m_registeredOutputDepthCams.push_back(cam); } } void Reveal::unregisterOutputDepthCam(DepthCamModule* cam) { vector<DepthCamModule*>::iterator itCa=m_registeredOutputDepthCams.begin(); for(; itCa!=m_registeredOutputDepthCams.end(); ) { if((*itCa)->getDepthID()==cam->getDepthID()) { itCa=m_registeredOutputDepthCams.erase(itCa); } else { ++itCa; } } } void Reveal::deleteListener(Listener* lis) { m_listenersDeleteVec.push_back(lis); } void Reveal::deleteModule(Module* mod) { m_modulesDeleteVec.push_back(mod); refreshModules(); } void Reveal::testDelete() { bool erasedListeners=false; vector<Listener*>::iterator itLis = m_listenersDeleteVec.begin(); for(; itLis!=m_listenersDeleteVec.end(); ++itLis) { delete (*itLis); erasedListeners=true; } m_listenersDeleteVec.clear(); if(m_modulesDeleteVec.size()>0) { MainWindow::getInstance()->refreshModules(true, erasedListeners); } vector<Module*>::iterator itMod = m_modulesDeleteVec.begin(); for(; itMod!=m_modulesDeleteVec.end(); ++itMod) { delete (*itMod); } m_modulesDeleteVec.clear(); } GLuint Reveal::createProgram(const char* vertSource, const char* fragSource) { GLint compile_ok = GL_FALSE, link_ok = GL_FALSE; GLuint vertexShader, fragmentShader; vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertSource, NULL); glCompileShader(vertexShader); glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compile_ok); if(!compile_ok) { cout << "Error in vertex shader" << endl; GLint maxLength = 0; glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength); std::vector<GLchar> errorLog(maxLength); glGetShaderInfoLog(vertexShader,maxLength,&maxLength, &errorLog[0]); vector<GLchar>::iterator itC=errorLog.begin(); for(; itC!=errorLog.end(); ++itC) { cout<<*itC; } cout<<endl; } fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragSource, NULL); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compile_ok); if(!compile_ok) { cout << "Error in fragment shader" << endl; GLint maxLength = 0; glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength); std::vector<GLchar> errorLog(maxLength); glGetShaderInfoLog(fragmentShader,maxLength,&maxLength, &errorLog[0]); vector<GLchar>::iterator itC=errorLog.begin(); for(; itC!=errorLog.end(); ++itC) { cout<<*itC; } cout<<endl; } GLuint program = glCreateProgram(); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &link_ok); if(!link_ok) { cout<<"Error linking glsl program "<<program<<" "<<endl; GLint maxLength = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); std::vector<GLchar> errorLog(maxLength); glGetProgramInfoLog(program,maxLength,&maxLength, &errorLog[0]); vector<GLchar>::iterator itC=errorLog.begin(); for(; itC!=errorLog.end(); ++itC) { cout<<*itC; } cout<<endl; } return program; } void Reveal::measureStart() { gettimeofday(&m_measureTime, NULL); m_measuring=true; } void Reveal::measureStore(const int& nbPixels) { if(m_measuring) { timeval curTime, timeDiff; gettimeofday(&curTime, NULL); timersub(&curTime, &m_measureTime, &timeDiff); int timeDiffMs=int(timeDiff.tv_sec)*1000000 + int(timeDiff.tv_usec); if(m_measurePixelNb.find(nbPixels)==m_measurePixelNb.end()) { m_measurePixelTimes[nbPixels]=0; m_measurePixelNb[nbPixels]=0; } m_measurePixelNb[nbPixels]++; m_measurePixelTimes[nbPixels]+=timeDiffMs; cout<<nbPixels<<" " <<float(m_measurePixelTimes[nbPixels]) / float(m_measurePixelNb[nbPixels])<<endl; m_measuring=false; } } //MAIN int main( int argc, char **argv ) { Reveal::getInstance()->init(); if(argc>1) { char* abs = new char[200]; fl_filename_absolute(abs, 200, argv[1]); Reveal::getInstance()->planOpen(string(abs)); } return Reveal::getInstance()->run(); }