Commit fd3a262c authored by Ruben Garcia Hernndez's avatar Ruben Garcia Hernndez

Added CAVE-like environment demo

Bugfix: double fclose
Bugfix: missing includes
parent 4692c8ca
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# Project Name
PROJECT(NOMADCaveT)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else()
MESSAGE(FATAL_ERROR "C++ 11 is required")
endif()
set(project_LIBRARIES)
set(project_INCLUDES)
set(project_DEFINITIONS -DCAVE -DINDICESGL32)
#########################################################
# ADD PTHREAD
#########################################################
list(APPEND project_LIBRARIES pthread)
find_package(synch REQUIRED)
#list(APPEND project_INCLUDES ${SYNCH_INCLUDE_DIRS})
list(APPEND project_LIBRARIES synch)
find_package(screen REQUIRED )
#plib
#find_library (PLIB_UL plibul HINTS $ENV{PLIBDIR} PATH_SUFFIXES lib REQUIRED)
#find_library (PLIB_FNT plibfnt HINTS $ENV{PLIBDIR} PATH_SUFFIXES lib REQUIRED)
#set (PLIB_LIBRARIES ${PLIB_FNT} ${PLIB_UL})
#message ("plib_libraries = ${PLIB_LIBRARIES} ")
#find_path (PLIB_INCLUDE_DIR plib/fnt.h HINTS $ENV{PLIBDIR} PATH_SUFFIXES include REQUIRED)
#message ("plib_include = ${PLIB_INCLUDE_DIR} ")
#freetype2
INCLUDE (FindPkgConfig)
pkg_search_module(FREETYPE REQUIRED freetype2)
message ("freetype LDFLAGS ${FREETYPE_LDFLAGS}")
message ("freetype CFLAGS ${FREETYPE_CFLAGS}")
#target_link_libraries(demoCO2CaO PUBLIC screen)
#target_link_libraries(demoCO2CaO_server PUBLIC screen)
#list(APPEND project_INCLUDES ${SCREEN_INCLUDE_DIRS})
list(APPEND project_LIBRARIES screen)
#########################################################
# Include Files
#########################################################
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src)
include_directories(${project_INCLUDES})
include_directories(${FREETYPE_INCLUDE_DIRS})
set(HEADERS
)
set(SOURCES
src/main.cpp src/textRendering.cpp
src/NOMADVRLib/atoms.cpp src/NOMADVRLib/CompileGLShader.cpp
src/NOMADVRLib/polyhedron.cpp src/NOMADVRLib/UnitCellShaders.cpp
src/NOMADVRLib/atomsGL.cpp src/NOMADVRLib/ConfigFile.cpp
src/NOMADVRLib/TessShaders.cpp
src/happyhttp/happyhttp.cpp
)
set(HEADERS_SERVER
)
set(SOURCES_SERVER
src/main_server.cpp src/textRendering.cpp
)
########################################################
# Add definitions
#########################################################
add_definitions(${project_DEFINITIONS})
########################################################
# Linking & stuff
#########################################################
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
target_link_libraries(${PROJECT_NAME} ${project_LIBRARIES} ${FREETYPE_LDFLAGS})
add_executable(${PROJECT_NAME}_server ${SOURCES_SERVER} ${HEADERS_SERVER})
target_link_libraries(${PROJECT_NAME}_server ${project_LIBRARIES} ${FREETYPE_LIBRARIES})
for i in `seq -w 1 10`; do ssh caverender${i}-lnx killall demoCO2CaO; done
This demo is based on
https://svn.lrz.de/repos/v2t/projects/demos/demoBunge/
Revision 1538
For use in LRZ CAVE and Powerwall.
Use in suse:
Run once:
/sw/bin/remove_cursor
On CAVE Master 1 (linux)
/sw/DTrack2/2.8.1/bin/DTrack2.bin
(connect, activate, close, do not stop measurement)
/sw/equalizer/1.8.0/bin/vrpn_server -v -f /sw/config/vrpn-lrz-cave.cfg
On CAVE Master 1 (windows)
Dtrack2 icon on the desktop
(connect, activate, close, do not stop measurement)
vrpn: startvrpn in the desktop complains that vrpn_server.exe does not exist. Check this.
use in ubuntu:
/sw/vrpn/latest/bin/vrpn_server -v -f /sw/config/vrpn/lrz_cave.cfg
Run demo (on cavemaster 2):
./demoBunge_server /sw/config/mlib/cave_2.conf
Run demo (on cavemaster 1):
./demoBunge_server /sw/config/mlib/cave_1.conf
WAIT 5 minutes
#ifndef __DEFINES_H
#define __DEFINES_H
#define FONT "/usr/share/fonts/truetype/freefont/FreeSans.ttf"
//#define FONT "/usr/share/fonts/truetype/DejaVuSans.ttf"
#define SHADERPATH "/home/demos/nomad_rgarcia/m3d/"
#define PATHSIZE 256
#endif
#include <string>
#include <m3drenderer.h>
#include <functional>
#include <iostream>
#include <m3dtextureHandler.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtx/matrix_decompose.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <m3dnode.h>
#include <chrono>
#include <renderNode.h>
#include <synchObject.h>
#include <m3dFileIO.h>
#include <m3dtextureHandler.h>
#include <m3dmeshHandler.h>
#include <m3duploadingInterface.h>
#include <m3ddefaultShader.h>
#include "textRendering.hpp"
#include "selectedPoints.hpp"
#include "NOMADVRLib/ConfigFile.h"
#include "NOMADVRLib/atoms.hpp"
#include "NOMADVRLib/atomsGL.h"
#include "NOMADVRLib/TessShaders.h"
#include "NOMADVRLib/UnitCellShaders.h"
#include "NOMADVRLib/CompileGLShader.h"
#include "defines.h"
#define TESSSUB 16
void eprintf( const char *fmt, ... )
{
va_list args;
char buffer[ 2048 ];
va_start( args, fmt );
vsprintf( buffer, fmt, args );
va_end( args );
fprintf(stderr, "%s\n", buffer );
}
typedef std::chrono::high_resolution_clock Clock;
using namespace m3d;
class sceneManager{
public:
sceneManager(m3d::Renderer* ren, synchlib::renderNode* node, const char *NOMADconfigFile);
~sceneManager();
void displayFunction();
void keyboardFunction(char key, int x, int y);
void keyReleaseFunction(char key, int x, int y);
void setCDPSyncher(std::shared_ptr<synchlib::SynchObject<int> > sy){m_pCurrentDataPosSyncher = sy; m_pCurrentDataPosSyncher->setData(0);}
void setCDTPSyncher(std::shared_ptr<synchlib::SynchObject<int> > sy){m_pCurrentDataTimeSyncher = sy; m_pCurrentDataTimeSyncher->setData(0);}
void setCDPtSyncher(std::shared_ptr<synchlib::SynchObject<SelectedPoints> > sy)
{
m_pCurrentDataPointSyncher = sy;
SelectedPoints p={0};
m_pCurrentDataPointSyncher->setData(p);
}
private:
m3d::Renderer* m_ren;
synchlib::renderNode* m_node;
int counter = 0;
Clock::time_point t1 = Clock::now();
glm::mat4 m_preMat;
glm::mat4 m_scalemat;
glm::mat4 m_scalematSky;
std::shared_ptr<UploadingInterface> m_uploading;
TextRendering::Text text;
GLuint PointVAO, PointVBO;
std::shared_ptr<synchlib::SynchObject<int> > m_pCurrentDataPosSyncher;
std::shared_ptr<synchlib::SynchObject<int> > m_pCurrentDataTimeSyncher;
std::shared_ptr<synchlib::SynchObject<SelectedPoints> > m_pCurrentDataPointSyncher;
int m_oldDataPos = 0;
int m_oldTime = 0;
void glDraw(glm::mat4 pvmat, glm::mat4 viewmat, int curDataPos,
const SelectedPoints& sp);
const char * configFile="/home/demos/nomad_rgarcia-ubuntu/shell.ncfg";
void SetConfigFile (const char * f) {
configFile=f;
}
int error=0;
GLuint textures[2]; // white, atoms
//if no tesselation is available, we still need the tess atoms for the trajectories!
GLuint *AtomTVAO=0, *AtomTBuffer=0, *AtomVAO=0, *AtomBuffer=0, *AtomIndices=0,//[2], atoms, extraatoms
UnitCellVAO, UnitCellBuffer, UnitCellIndexBuffer;
GLuint AtomsP, UnitCellP; // framework does not provide support for tesselation and provides many things we don't need.
GLint AtomMatrixLoc, UnitCellMatrixLoc, UnitCellColourLoc;
bool hasTess=true;
void RenderAtoms(const float *m);
void RenderUnitCell(const glm::mat4 eyeViewProjection);
void RenderAtomTrajectoriesUnitCell();
void RenderAtomTrajectories(const glm::mat4 eyeViewProjection);
};
sceneManager::sceneManager(m3d::Renderer* ren, synchlib::renderNode* node,
const char *c){
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "construktor 0: "<<__FUNCTION__<<" OpenGL error " << err << std::endl;
}
m_ren = ren;// m_th = th;
m_node = node;
if (c)
SetConfigFile (c);
m_preMat = glm::mat4_cast(glm::rotation(glm::vec3(0.,0.,1.),glm::vec3(0.,1.,0.)));
m_scalemat = glm::scale(m_scalemat,glm::vec3(0.1,0.1,0.1));
m_scalematSky = glm::scale(m_scalematSky,glm::vec3(0.05,0.05,0.05));
std::string s(configFile);
chdir(s.substr(0, s.find_last_of("\\/")).c_str());
if ((error=loadConfigFile(configFile))<0) {
if (-100<error) {
fprintf (stderr, "%s", loadConfigFileErrors[-error]);
fprintf (stderr, "Config file reading error");
}else if (-200<error) {
fprintf (stderr, "%s", readAtomsXYZErrors[-error-100]);
fprintf (stderr, "XYZ file reading error");
}else if (-300<error) {
fprintf (stderr, "%s", readAtomsCubeErrors[-error-200]);
fprintf (stderr, "Cube file reading error");
}else {fprintf (stderr, "%s", readAtomsJsonErrors[-error-300]);
fprintf (stderr, "Json reading error");
}
}
glGenTextures(2, textures);
//white
unsigned char data2[4]={255,255,255,255}; //white texture for non-textured meshes
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
// Create the programs
if (!PrepareUnitCellShader (&UnitCellP, &UnitCellMatrixLoc, &UnitCellColourLoc)) {
eprintf("OneTimeInit, failure compiling Unit Cell Shader");
error=-401;
return ;
}
if (!PrepareAtomShader(&AtomsP, &AtomMatrixLoc)) {
hasTess=false;
if (!solid)
solid=new Solid(Solid::Type::Icosahedron);
if (!PrepareAtomShaderNoTess(&AtomsP, &AtomMatrixLoc)) {
error=-402;
eprintf ("PrepareAtomShaderNoTess failed");
}
};
//atom texture
int e;
e=atomTexture(textures[1]);
if (e!=GL_NO_ERROR) {
eprintf ("atomTexture error %d", e);
error=-403;
}
e=SetupAtoms(&AtomTVAO, &AtomTBuffer);
if (e!=GL_NO_ERROR) {
eprintf ("SetupAtoms error %d", e);
error=-404;
}
if (!hasTess)
e=SetupAtomsNoTess(&AtomVAO, &AtomBuffer, &AtomIndices);
if (e!=GL_NO_ERROR) {
eprintf ("SetupAtomsNoTess error %d, tess=%d", e, hasTess);
error=-405;
}
e=SetupUnitCell(&UnitCellVAO, &UnitCellBuffer, &UnitCellIndexBuffer);
if (e!=GL_NO_ERROR) {
eprintf ("SetupUnitCell error %d", e);
error=-406;
}
//for painting selected points
glGenVertexArrays(1, &PointVAO);
glGenBuffers(1, &PointVBO);
glBindVertexArray(PointVAO);
glBindBuffer(GL_ARRAY_BUFFER, PointVBO);
//x y z r g b (6), 5 points (wand + 4 selected points)
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 5, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
(char*)0+3*sizeof(float));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//end for painting selected points
M3DFileIO fileio;
std::shared_ptr<Node> UploadingRoot = Node::create();
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "construktor 1: "<<__FUNCTION__<<" OpenGL error " << err << std::endl;
}
if (!text.init(FONT))
std::cerr << "Font loading error " << FONT << std::endl;
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "construktor nach shader zeug: "<<__FUNCTION__<<
" OpenGL error" << err << std::endl;
}
std::shared_ptr<m3d::MeshHandler> mHandler = std::make_shared<MeshHandler>(ren->getDisplay(),*(ren->getContext()),true,false);
std::shared_ptr<TextureHandler> tHandler = std::make_shared<TextureHandler>((ren->getDisplay()),*(ren->getContext()),true);
mHandler->start();
tHandler->start();
m_uploading = std::make_shared<UploadingInterface>(mHandler,tHandler);
m_uploading->setRootNode(UploadingRoot);
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "construktor nach set root: "<<__FUNCTION__<<" OpenGL error " << err << std::endl;
}
std::cout<<"start"<<std::endl;
m_uploading->start();
std::cout<<"started"<<std::endl;
sleep(2);
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "construktor nach start: "<<__FUNCTION__<<" OpenGL error " << err << std::endl;
}
}
sceneManager::~sceneManager(){
m_uploading->quit();
}
void sceneManager::glDraw(glm::mat4 pvmat, glm::mat4 viewMat, int curDataPos,
const SelectedPoints& selectedPoints) {
GLenum err;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "disp vor draw: "<<__FUNCTION__<<" OpenGL error " << err << std::endl;
}
//here the low-level gl code can be added
glm::mat4 wand;
m_node->getWandTrafo(wand);
//rgh FIXME this should be done only once.
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(wand, scale, rotation, translation, skew, perspective);
glm::mat4 st;
m_node->getSceneTrafo(st);
//fprintf (stderr, "st = ");
//for (int i=0;i<4;i++)
// for (int j=0;j<4;j++)
// fprintf (stderr, "%f ", st[i][j]);
//fprintf(stderr, "\n");
//rgh FIXME: cache these numbers, do not calculate twice per frame
if(error)
return;
if (has_abc) {
RenderUnitCell(pvmat*st);
} else {
//atom trajectories
RenderAtomTrajectories(pvmat*st);
}
}
void sceneManager::displayFunction(){
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
std::cerr << "disp 1: "<<__FUNCTION__<<" OpenGL error" << err << std::endl;
}
bool ttt = false;
glm::mat4 pvmatL, pvmatR;
m_node->getProjectionMatrices(pvmatL,pvmatR);
glm::mat4 viewMat;
m_node->getSceneTrafo(viewMat);
int curDataPos;
m_pCurrentDataPosSyncher->getData(curDataPos);
int timePos;
m_pCurrentDataTimeSyncher->getData(timePos);
if(m_oldTime != timePos){
m_oldTime = timePos%TIMESTEPS;
if (m_oldTime<0)
m_oldTime+=TIMESTEPS;
//eprintf ("m_oldtime=%d", m_oldTime);
}
SelectedPoints selectedPoints;
m_pCurrentDataPointSyncher->getData(selectedPoints);
auto t2 = Clock::now();
auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
if(dur > 1000){
std::cout<<"################################ fps: "<<(double)counter/((double) dur / (double) 1000)<<std::endl;
counter = 0;
t1 = Clock::now();
std::cout<<"time: "<<timePos<<" iso: "<<curDataPos<<std::endl;
}
if(m_oldDataPos != curDataPos){
//rgh: no lods in this demo //m_posData->setLOD(curDataPos[0]);
m_oldDataPos = curDataPos;
}
glm::mat4 user; m_node->getUserTrafo(user);
//rgh: parameter not needed in this demo
// m_posData->getShader()->setUserPos(glm::vec3(user[3]));
// m_NegData->getShader()->setUserPos(glm::vec3(user[3]));
glm::mat4 viewRotOnly = viewMat;
viewRotOnly[3] = glm::vec4(0.,0.,0.,1.);
glDrawBuffer(GL_BACK_LEFT);
{
glDraw(pvmatL, viewMat, curDataPos, selectedPoints);
}
glDrawBuffer(GL_BACK_RIGHT);
{
glDraw(pvmatR, viewMat, curDataPos, selectedPoints);
}
GLsync fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE,0);
glClientWaitSync(fence,GL_SYNC_FLUSH_COMMANDS_BIT,GL_TIMEOUT_IGNORED);
if(!m_node->synchFrame()){
m_ren->stopMainLoop();
return;
}
m_ren->swapBuffer();
++counter;
}
void sceneManager::keyboardFunction(char key, int x, int y){
switch(key){
case 27:
m_ren->stopMainLoop();
break;
}
}
void sceneManager::keyReleaseFunction(char key, int x, int y){
switch(key){
}
}
void InitGraphics(void)
{
glClearColor (BACKGROUND[0], BACKGROUND[1], BACKGROUND[2], 1.0);
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
glDisable(GL_BLEND);
}
int main(int argc, char** argv){
if(argc < 4){
std::cout<<"Not enough arguments! Start with "<<argv[0]<<" <own hostname/IP> <path to mlib configfile> <path to ncfg configfile>"<<std::endl;
exit(0);
}
TMPDIR="/tmp/"; //needs to be a non-shared directory, as we have
//concurrent loading from the web
bool stereo = true;
bool debug = true;
m3d::Renderer* ren = new m3d::Renderer(stereo,debug);
std::string file =argv[2];
synchlib::caveConfig conf(file);
std::stringstream ownIP;
ownIP<< argv[1];
if(argc > 3){
ownIP<<"_"<<argv[3];
}
synchlib::renderNode* node = new synchlib::renderNode(file,argc, argv);
std::cout<<conf.m_wall_conf[ownIP.str()].wall_geo[0]<<" "<<conf.m_wall_conf[ownIP.str()].wall_geo[1]<<std::endl;
ren->createWindow("NOMADCaveT",conf.m_wall_conf[ownIP.str()].wall_geo[0],conf.m_wall_conf[ownIP.str()].wall_geo[1]);
//http://stackoverflow.com/questions/8302625/segmentation-fault-at-glgenvertexarrays-1-vao
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
{
sceneManager sceneM(ren,node, argv[4]);
std::shared_ptr<synchlib::SynchObject<int> > currentDataPosSyncher = synchlib::SynchObject<int>::create();
sceneM.setCDPSyncher(currentDataPosSyncher);
node->addSynchObject(currentDataPosSyncher,synchlib::renderNode::RECEIVER,0);
std::shared_ptr<synchlib::SynchObject<int> > currentDataTimeSyncher = synchlib::SynchObject<int>::create();
sceneM.setCDTPSyncher(currentDataTimeSyncher);
node->addSynchObject(currentDataTimeSyncher,synchlib::renderNode::RECEIVER,0);
std::shared_ptr<synchlib::SynchObject<SelectedPoints> >
currentDataPointsSyncher = synchlib::SynchObject<SelectedPoints>::create();
sceneM.setCDPtSyncher(currentDataPointsSyncher);
node->add