main.cpp 37.1 KB
Newer Older
1
#define GLM_SWIZZLE
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
#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"

35 36
#include "NOMADVRLib/IsosurfacesGL.h"

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#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 );
}

53 54
float globalscaling=10.0f;

55 56 57 58 59
typedef std::chrono::high_resolution_clock Clock;
 using namespace m3d;

class sceneManager{
public:
60 61
    sceneManager(m3d::Renderer* ren, synchlib::renderNode* node, 
	const char *NOMADconfigFile, const unsigned int geo[2]);
62 63 64 65
    ~sceneManager();
    void displayFunction();
    void keyboardFunction(char key, int x, int y);
    void keyReleaseFunction(char key, int x, int y);
66
    void setCDPSyncher(std::shared_ptr<synchlib::SynchObject<int> > sy){m_pCurrentDataPosSyncher = sy; m_pCurrentDataPosSyncher->setData(-1);}
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    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;
    std::shared_ptr<UploadingInterface> m_uploading;

TextRendering::Text text;

GLuint PointVAO, PointVBO;
92 93
m3d::ShaderLoader sPoint;
bool initGLSelectedPoints();
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

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
111 112
GLuint textDepthPeeling[ZLAYERS+2]; 
GLuint peelingFramebuffer;
113
unsigned int geo[2]; //window width, height
114
	//if no tesselation is available, we still need the tess atoms for the trajectories!
115
GLuint *AtomTVAO=nullptr, *AtomTBuffer=nullptr, BondIndices=0,
116 117 118
	*AtomVAO=nullptr, *AtomBuffer=nullptr, *AtomIndices=nullptr,//[2], atoms, extraatoms
	UnitCellVAO, UnitCellBuffer, UnitCellIndexBuffer;
GLuint	AtomsP, UnitCellP; 
119
GLint	AtomMatrixLoc, totalatomsLocation, UnitCellMatrixLoc, UnitCellColourLoc;
120 121
GLuint	TransP=0, BlendP=0;
GLint	TransMatrixLoc=-1;
122 123
bool hasTess=true;

124 125 126 127
GLuint *ISOVAO=nullptr/*[ISOS*TIMESTEPS]*/, *ISOBuffer=nullptr/*[ISOS*TIMESTEPS]*/,
	*ISOIndices=nullptr/*[ISOS*TIMESTEPS]*/;
GLuint ISOP;
GLint ISOMatrixLoc;
128
GLuint BlendVAO=0, BlendBuffer=0, BlendIndices=0;
129 130
int *numISOIndices=nullptr/*[ISOS*TIMESTEPS]*/;

131
void RenderAtoms(const float *m);
132
void RenderAtomBonds(const float *m);
133 134 135
void RenderUnitCell(const glm::mat4 eyeViewProjection);
void RenderAtomTrajectoriesUnitCell();
void RenderAtomTrajectories(const glm::mat4 eyeViewProjection);
136 137
void RenderIsos(const glm::mat4 eyeViewProjection, int curDataPos,
	const glm::mat4 pvmat, const SelectedPoints& selectedPoints);
138 139 140 141
void RenderText(const glm::mat4 pvmat, int curDataPos, int timestep,
	const SelectedPoints& selectedPoints);
void RenderPoints(const glm::mat4 pvmat, const glm::vec3 translation, 
	const SelectedPoints& selectedPoints);
142 143 144
};


145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
bool sceneManager::initGLSelectedPoints() {
//for painting selected points 

GLenum e;

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);    
e = glGetError();
return (e==GL_NO_ERROR); 
}


168
sceneManager::sceneManager(m3d::Renderer* ren, synchlib::renderNode* node,
169
	const char *c, const unsigned int geometry[2]):m_scalemat(1.0){
170 171 172 173 174 175
GLenum err;

	while ((err = glGetError()) != GL_NO_ERROR) {
		std::cerr << "construktor 0: "<<__FUNCTION__<<" OpenGL error " << err << std::endl;
	}

176 177 178
	geo[0]=geometry[0];
	geo[1]=geometry[1];

179 180 181 182 183 184 185 186 187
     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));
	
	std::string s(configFile);
188 189 190 191 192 193
   int e;
	e=chdir(s.substr(0, s.find_last_of("\\/")).c_str());
	if (e!=0) {
		fprintf (stderr, "Could not change to directory of config "
			"file, relative paths may fail\n");
	}
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209

	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");
		}
	}

210 211 212 213 214
e=glGetError();
if (e!=GL_NO_ERROR) {
	eprintf ("OpenGL error after loading config file %d", e);
	error=-409;
}
215
glGenTextures(2, textures);
216 217 218 219 220
e=glGetError();
if (e!=GL_NO_ERROR) {
	eprintf ("Depth-peeling, glGenTextures 1 OpenGL error %d", e);
	error=-410;
}
221
glGenTextures(2+ZLAYERS, textDepthPeeling);
222 223 224 225 226
e=glGetError();
if (e!=GL_NO_ERROR) {
	eprintf ("Depth-peeling, glGenTextures 2 OpenGL error %d", e);
	error=-411;
}
227

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
    //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 ;
	}
	
244
	if (!PrepareAtomShader(&AtomsP, &AtomMatrixLoc, &totalatomsLocation)) {
245 246 247
		hasTess=false;
		if (!solid)
			solid=new Solid(Solid::Type::Icosahedron);
248 249
		if (!PrepareAtomShaderNoTess(&AtomsP, &AtomMatrixLoc, 
			&totalatomsLocation)) {
250 251 252 253 254 255
			error=-402;
			eprintf ("PrepareAtomShaderNoTess failed");
		}
	};

	//atom texture
256

257 258 259 260 261 262
	e=atomTexture(textures[1]);
	if (e!=GL_NO_ERROR) {
		eprintf ("atomTexture error %d", e);
		error=-403;
	}

263 264
bool er;

265
	e=SetupAtoms(&AtomTVAO, &AtomTBuffer, &BondIndices);
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
	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;
	}
282 283
//now isosurfaces
	if (ISOS) {
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
		er=::SetupDepthPeeling(geo[0], geo[1], ZLAYERS, 
			textDepthPeeling, &peelingFramebuffer);
		if (!er) {
			eprintf("Error setting up DepthPeeling\n");
			error=-407;
		}


		if (GL_NO_ERROR!=(e=PrepareISOTransShader (&TransP, 
			&TransMatrixLoc, &BlendP)))
		{
			eprintf( "Error Preparing Transparency shader, %d\n", e );
			error=-408;
		}
		SetupBlending(&BlendVAO, &BlendBuffer, &BlendIndices);
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
		PrepareISOShader(&ISOP, &ISOMatrixLoc);

		std::vector<float> vertices;
#ifndef INDICESGL32
		std::vector<short> indices;
#else
		std::vector<GLuint> indices;
#endif
		numISOIndices=new int[TIMESTEPS*ISOS];
		ISOVAO=new GLuint[TIMESTEPS*ISOS];
		ISOBuffer=new GLuint[TIMESTEPS*ISOS];
		ISOIndices=new GLuint[TIMESTEPS*ISOS];

		glGenBuffers(TIMESTEPS*ISOS, ISOBuffer);
		glGenVertexArrays(TIMESTEPS*ISOS, ISOVAO);
		glGenBuffers(TIMESTEPS*ISOS, ISOIndices);

		if ((e = glGetError()) != GL_NO_ERROR)
			eprintf("opengl error %d, glGenBuffers\n", e);

		char tmpname[250];
		int timestep=1;
		for (int p = 0; p < TIMESTEPS*ISOS; p++) {
			sprintf(tmpname, "%s%d-%s.ply", PATH, timestep, 
				plyfiles[p % ISOS]);
			float mat[16];
325 326
			glm::mat4 matFinal, matcubetrans, mvs, sc, sctrans;
			if (voxelSize[0]!=-1) {
327
//We scale in RenderUnitCell by globalscaling so that atoms look large enough on the cave. 
328
//So we need to scale here as well.
329 330 331
				mvs=glm::scale(mvs, glm::vec3(globalscaling*scaling / (float)voxelSize[0], 
						globalscaling*scaling / (float)voxelSize[1], 
						globalscaling*scaling / (float)voxelSize[2]));
332 333 334 335 336 337 338 339 340 341 342
				matcubetrans=glm::translate(matcubetrans,glm::vec3(cubetrans[0], 
					cubetrans[1], cubetrans[2]));
				glm::mat4 abcm (abc[0][0], abc[0][1], abc[0][2], 0,
					abc[1][0], abc[1][1], abc[1][2], 0,
					abc[2][0], abc[2][1], abc[2][2], 0,
					0, 0, 0, 1);

				sc=glm::scale(sc, glm::vec3(supercell[0], supercell[1], supercell[2]));
				
				sctrans=glm::translate(sctrans, glm::vec3(-translations[p%ISOS][2], 
					-translations[p%ISOS][1], -translations[p%ISOS][0]));
343 344 345
				glm::mat4 trans(1.0);
				trans=glm::rotate(trans, (float)-M_PI_2, glm::vec3(1.f,0.f,0.f));
				matFinal = abcm*sctrans*sc*mvs*trans;
346 347 348 349
				for (int i=0;i<4;i++)
					for (int j=0;j<4;j++)
						mat[j*4+i]=matFinal[j][i];
			} else {
350 351 352 353
				mvs=glm::scale(mvs, glm::vec3(globalscaling*scaling, 
						globalscaling*scaling , 
						globalscaling*scaling));
				glm::mat4 trans(1.0);
354
				trans=glm::rotate(trans, (float)-M_PI_2, glm::vec3(1.f,0.f,0.f));
355
				glm::mat4 matFinal(1.0);
356
				matFinal=glm::translate(matFinal, 
357 358 359 360
					glm::vec3(translations[p%ISOS][0]*globalscaling*scaling,
						translations[p%ISOS][1]*globalscaling*scaling,
						translations[p%ISOS][2]*globalscaling*scaling));
				matFinal=trans*matFinal*mvs;
361 362 363 364 365 366
				
				for (int i=0;i<4;i++)
					for (int j=0;j<4;j++)
						mat[j*4+i]=matFinal[j][i];			
			}

367 368 369 370
			if (!AddModelToScene(mat, vertices, indices,
				tmpname, false, isocolours[p%ISOS][0]<0, p%ISOS))
			{
				eprintf("Error loading ply file %s\n", tmpname);
371
				//return; //rgh: files may be missing if no isos are available
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
			}
#ifndef INDICESGL32
			if (vertices.size() > 65535 * numComponents)
			{
				eprintf("Mesh has more than 64k vertices (%d), unsupported\n", vertdataarray[currentlod][p].size() / numComponents);
				return;
			}
#endif
			numISOIndices[p] = indices.size();
			if (GL_NO_ERROR!=PrepareGLiso(ISOVAO[p], ISOBuffer[p], 
				vertices, ISOIndices[p], indices))
				eprintf ("PrepareGLiso, GL error");
			
			vertices.clear();
			indices.clear();

			if (p % ISOS == ISOS - 1) {
				eprintf ("timestep %d", timestep);
				timestep++;
			}
		}
	}
394

395 396 397 398 399 400
	if (!initGLSelectedPoints())
		std::cout<< "initGLSelectedPoints failed" << std::endl;

	if (!sPoint.loadShadersFromFiles(SHADERPATH "points.vert", SHADERPATH "points.frag"))
	std::cerr << __FUNCTION__<<
			"Loading of points shader failed" << std::endl;
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449

	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;
450 451 452 453

if ((err = glGetError()) != GL_NO_ERROR) 
	eprintf ("begin of glDraw, error %d\n", err);

454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
       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;
481 482

if (ISOS) {
483
	RenderIsos(pvmat*st, curDataPos, pvmat, selectedPoints);
484
} else if (has_abc) {
485 486 487
	glm::mat4 trans(1.0);
	trans=glm::rotate(trans, (float)-M_PI_2, glm::vec3(1.f,0.f,0.f));	
	RenderUnitCell(pvmat*st*trans);
488 489
} else {
	//atom trajectories
490 491 492
	glm::mat4 trans(1.0);
	trans=glm::rotate(trans, (float)-M_PI_2, glm::vec3(1.f,0.f,0.f));
	RenderAtomTrajectories(pvmat*st*trans);
493 494
}

495

496 497
if (!ISOS)
	RenderText(pvmat, curDataPos, m_oldTime, selectedPoints);
498

499 500 501
if ((err = glGetError()) != GL_NO_ERROR) 
	eprintf ("end of glDraw, error %d\n", err);

502 503
}

504 505


506 507 508 509 510 511 512 513 514 515 516 517 518
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);
519 520 521
    curDataPos=curDataPos%(ISOS+1);
    if (curDataPos<0)
	curDataPos+=ISOS+1;
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
    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);

642 643 644 645 646 647
const unsigned int geo[2]={static_cast<unsigned int>(conf.m_wall_conf[ownIP.str()].wall_geo[0]),
	static_cast<unsigned int>(conf.m_wall_conf[ownIP.str()].wall_geo[1])};

    std::cout<<geo[0]<<"    "<<geo[1]<<std::endl;

    ren->createWindow("NOMADCaveT",geo[0],geo[1]);
648 649 650 651 652 653 654 655 656 657 658 659 660
//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));

    }



	{
661
		sceneManager sceneM(ren,node, argv[4], geo);
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717


		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->addSynchObject(currentDataPointsSyncher,synchlib::renderNode::RECEIVER,0);

		std::function<void(void)> dispFunc = std::bind(&sceneManager::displayFunction,&sceneM);
		std::function<void(char,int,int)>  keyFunc = std::bind(&sceneManager::keyboardFunction,&sceneM,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3);
		std::function<void(char,int,int)>  keyRFunc = std::bind(&sceneManager::keyReleaseFunction,&sceneM,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3);
		ren->setDisplayFunction(dispFunc);
		ren->setIdleFunction(dispFunc);
		ren->setKeyPressFunction(keyFunc);
		ren->setAllowKeyboardAutoRepressing(false);
		ren->setKeyReleaseFunction(keyRFunc);
//		ren->toggleFullscreen();
		node->init();

		node->startSynching();
		while ((err = glGetError()) != GL_NO_ERROR) {
			std::cerr <<" vor init: "<<__FUNCTION__<<" OpenGL error" << err << std::endl;
		}
		InitGraphics();
		while ((err = glGetError()) != GL_NO_ERROR) {
			std::cerr << "initGraphics: "<<__FUNCTION__<<" OpenGL error" << err << std::endl;
		}
		ren->mainLoop();
	}
    delete ren;

    node->stopSynching();
    delete node;

}

void sceneManager::RenderAtoms(const float *m) //m[16]
{
	//return;
	//eprintf ("RenderAtoms start numatoms %d, timestep %d", numAtoms[m_oldTime], m_oldTime);
	if (solid)
		eprintf ("solid nfaces %d", solid->nFaces);
	int e;
	if (numAtoms==0)
		return;
	
	if (hasTess) {
		glBindTexture(GL_TEXTURE_2D, textures[1]);
		glUseProgram(AtomsP);
718 719
		glUniform1f(totalatomsLocation, (float)getTotalAtomsInTexture());

720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
		//eprintf ("1");
		float levelso[4] = { TESSSUB, TESSSUB, TESSSUB, TESSSUB };
		float levelsi[2] = { TESSSUB, TESSSUB};
		//eprintf ("2");
		glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL,levelso);
		glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL,levelsi);
		glPatchParameteri(GL_PATCH_VERTICES, 1);
		//eprintf ("3");
		glBindVertexArray(AtomTVAO[0]);
		glEnableVertexAttribArray(0);
		glEnableVertexAttribArray(1);
		//eprintf ("4");
		glBindBuffer(GL_ARRAY_BUFFER, AtomTBuffer[0]);
		//eprintf ("5");
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 
			4 * sizeof(float), (const void *)(0));
		//eprintf ("6");
		glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 
			4 * sizeof(float), (const void *)(3 * sizeof(float)));
		//eprintf ("7");
		//trans.translate(iPos).rotateX(-90).translate(UserPosition);
		//Matrix4 transform = GetCurrentViewProjectionMatrix(nEye)*trans;
		//Matrix4 mv=GetCurrentViewMatrix(nEye)*trans;

		glUniformMatrix4fv(AtomMatrixLoc, 1, GL_FALSE, m);

		//glUniformMatrix4fv(m_nAtomMVLocation, 1, GL_FALSE, mv.get());
		if ((e = glGetError()) != GL_NO_ERROR)
			eprintf("Gl error 4 timestep =%d: %d, %s\n", m_oldTime, 
				e, gluErrorString(e));
		//eprintf ("8");
751
		if (m_oldTime==0 || fixedAtoms)
752 753 754 755 756 757 758 759 760 761 762
			glDrawArrays(GL_PATCHES, 0, numAtoms[0]);
		else
			glDrawArrays(GL_PATCHES, numAtoms[m_oldTime-1], 
				numAtoms[m_oldTime]-numAtoms[m_oldTime-1]);
		//eprintf ("9");
	
		if ((e = glGetError()) != GL_NO_ERROR)
			eprintf("Gl error after RenderAtoms timestep =%d: %d, %s\n", 
				m_oldTime, e, gluErrorString(e));

		//now cloned atoms
763
		if (numClonedAtoms!=0 && (m_oldTime==0 || fixedAtoms)) {
764 765 766 767 768 769 770 771 772 773
			//eprintf ("10");
			glBindVertexArray(AtomTVAO[1]);
			//eprintf ("11");
			glDrawArrays(GL_PATCHES, 0, numClonedAtoms);
			//eprintf ("12");
			if ((e = glGetError()) != GL_NO_ERROR)
				eprintf("Gl error after Render cloned Atom timestep =%d: %d, %s\n", 
					m_oldTime, e, gluErrorString(e));
		}

774 775


776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803
	} else { //no tess
		glBindVertexArray(AtomVAO[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, AtomIndices[0]);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("1 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);
	glBindBuffer(GL_ARRAY_BUFFER, AtomBuffer[0]);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("2 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7*sizeof(float), (const void *)0);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("3 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);

	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (const void *)(3*sizeof(float)));
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("4 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);

	glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (const void *)(6 * sizeof(float)));
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("5 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);

		glBindTexture(GL_TEXTURE_2D, textures[1]);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("6 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);

		glUseProgram(AtomsP);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("7 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);
804
		glUniform1f(totalatomsLocation, (float)getTotalAtomsInTexture());
805 806 807 808
		glUniformMatrix4fv(AtomMatrixLoc, 1, GL_FALSE, m);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("8 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);

809 810
		if (m_oldTime==0 || fixedAtoms) {
			glDrawElements(GL_TRIANGLES, numAtoms[0]* 3 * solid->nFaces, 
811 812 813 814 815 816 817 818 819 820
#ifndef INDICESGL32				
				GL_UNSIGNED_SHORT,
#else
				GL_UNSIGNED_INT,
#endif	
				0);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("9 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);

		} else {
821 822
			glDrawElements(GL_TRIANGLES, (numAtoms[m_oldTime]-
				numAtoms[m_oldTime-1]) * 3 * solid->nFaces,
823
#ifndef INDICESGL32				
824 825
				GL_UNSIGNED_SHORT, (void*)(numAtoms[m_oldTime-1]
					*sizeof(unsigned short)*3*solid->nFaces)
826
#else
827 828
				GL_UNSIGNED_INT, (void*)(numAtoms[m_oldTime-1]
					*sizeof(unsigned int)*3*solid->nFaces)
829 830 831 832 833 834 835
#endif
				);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("10 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);

		} //if (m_oldTime==0) 
		if ((e = glGetError()) != GL_NO_ERROR)
836 837
			eprintf("Gl error after Render Atom timestep =%d: %d\n",
				m_oldTime, e);
838 839 840 841 842
		//now cloned atoms
		if (numClonedAtoms!=0 && m_oldTime==0) {
			glBindVertexArray(AtomVAO[1]);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, AtomIndices[1]);
			glBindBuffer(GL_ARRAY_BUFFER, AtomBuffer[1]);
843 844 845 846 847 848 849 850
			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 
				7*sizeof(float), (const void *)0);
			glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 
				7 * sizeof(float), 
				(const void *)(3*sizeof(float)));
			glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 
				7 * sizeof(float), 
				(const void *)(6 * sizeof(float)));
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870

	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("5 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);
			glDrawElements(GL_TRIANGLES, numClonedAtoms* 3 * solid->nFaces, 
#ifndef INDICESGL32				
				GL_UNSIGNED_SHORT,
#else
				GL_UNSIGNED_INT,
#endif	
				0);			
			
			
			if ((e = glGetError()) != GL_NO_ERROR)
				eprintf("Gl error after Render cloned Atom timestep =%d: %d\n", m_oldTime, e);
		} // painting cloned atoms
	} // no tess

//eprintf ("RenderAtoms, end");
} // render atoms

871 872 873 874 875 876 877 878 879 880 881
void sceneManager::RenderAtomBonds(const float *t)
{
GLenum e;
if (numBonds) {
	glBindVertexArray(AtomTVAO[2]);
	if ((e = glGetError()) != GL_NO_ERROR)
			eprintf("Gl error after Render Atom bonds glBindVertexArray timestep =%d: %d, %s\n", m_oldTime, e, gluErrorString(e));
	glUseProgram(UnitCellP);
	if ((e = glGetError()) != GL_NO_ERROR)
			eprintf("Gl error after Render Atom bonds glUseProgram timestep =%d: %d, %s\n", m_oldTime, e, gluErrorString(e));
	glUniformMatrix4fv(UnitCellMatrixLoc, 1, GL_FALSE, t);
882
	glUniform4fv(UnitCellColourLoc, 1, bondscolours);
883 884 885 886 887 888 889 890 891 892 893 894 895

	if (m_oldTime==0||fixedAtoms)
		glDrawElements(GL_LINES, numBonds[0],  GL_UNSIGNED_INT, (void*)0);
	else
		glDrawElements(GL_LINES, numBonds[m_oldTime]-numBonds[m_oldTime-1], GL_UNSIGNED_INT, 
			(void*)(sizeof(int)*numBonds[m_oldTime-1]) );

	if ((e = glGetError()) != GL_NO_ERROR)
			eprintf("Gl error after Render Atom bonds timestep =%d: %d, %s\n", m_oldTime, e, gluErrorString(e));
}
glBindVertexArray(0);
}

896 897 898 899 900
void sceneManager::RenderAtomTrajectories(const glm::mat4 eyeViewProjection)
{
int e;
if (!numAtoms)
	return;
901
//eprintf ("RenderAtomTrajectories start");
902 903 904 905 906 907
/*glm::mat4 trans={1,0,0,UserTranslation[0],
		0,1,0,UserTranslation[1],
		0,0,1,UserTranslation[2],
		0,0,0,1};
*/					
//trans.translate(iPos).rotateX(-90).translate(UserPosition);
908 909 910
glm::mat4 scale={globalscaling*scaling,0,0,0,  
		0,globalscaling*scaling,0,0,
		0,0,globalscaling*scaling,0,
911 912
		0,0,0,1};
glm::mat4 transform =  eyeViewProjection*scale; //MatrixMul(eyeViewProjection,trans);
913 914 915 916 917 918 919 920 921 922 923
//gvr::Mat4f transform=eyeViewProjection;					
float t[16];
for (int i=0;i<4;i++)
	for (int j=0;j<4;j++)
		t[j*4+i]=transform[j][i];
glUseProgram(UnitCellP);
glUniformMatrix4fv(UnitCellMatrixLoc, 1, GL_FALSE, t);
if ((e = glGetError()) != GL_NO_ERROR)
	eprintf("Gl error after glUniform4fv 1 RenderAtomTrajectories: %d\n", e);
RenderAtomTrajectoriesUnitCell();
RenderAtoms(t);
924 925
//now bonds
//return;
926
RenderAtomBonds(t);
927

928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
} //RenderAtomTrajectories

void sceneManager::RenderAtomTrajectoriesUnitCell()
{
//eprintf ("RenderAtomTrajectoriesUnitCell start");
	//now trajectories
if (!showTrajectories)
	return;

int e;
if (!AtomTVAO) {
	eprintf("RenderAtomTrajectoriesUnitCell, no atoms");
	return;
}
glBindVertexArray(AtomTVAO[0]);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("1 Gl error RenderAtomTrajectoriesUnitCell: %d\n", e);
945 946

glUniform4fv(UnitCellColourLoc, 1, atomtrajectorycolour);
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978
if ((e = glGetError()) != GL_NO_ERROR)
	eprintf("Gl error after glUniform4fv 2 RenderAtomTrajectoriesUnitCell: %d\n", e);
//glEnableVertexAttribArray(0);
//glDisableVertexAttribArray(1);

//LOG("atomtrajectories.size()=%d", atomtrajectories.size());
glBindBuffer(GL_ARRAY_BUFFER, AtomTBuffer[0]);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("3 Gl error RenderAtomTrajectoriesUnitCell: %d\n", e);

for (unsigned int i=0;i<atomtrajectories.size();i++) {
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float)*numAtoms[0], 
		(const void *)(0+4*sizeof(float)*atomtrajectories[i]));
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("4 Gl error RenderAtomTrajectoriesUnitCell: %d\n", e);

		//LOG("atomtrajectoryrestarts[%d].size()=%d", i, atomtrajectoryrestarts[i].size());
	for (unsigned int j=1;j<atomtrajectoryrestarts[i].size();j++) {
		int orig=atomtrajectoryrestarts[i][j-1];
		int count=atomtrajectoryrestarts[i][j]-atomtrajectoryrestarts[i][j-1];
		glDrawArrays(GL_LINE_STRIP, orig, count);
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("5 Gl error RenderAtomTrajectoriesUnitCell: %d, orig=%d, count=%d\n", e, orig, count);

	} //j
	if ((e = glGetError()) != GL_NO_ERROR)
		eprintf("Gl error after Render Atom trajectories: %d\n", e);
} //i

} //sceneManager::RenderAtomTrajectoriesUnitCell()


979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
void sceneManager::RenderText(const glm::mat4 pvmat, int curDataPos, int timestep,
	const SelectedPoints& selectedPoints)
{
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);

//rgh FIXME: cache these numbers, do not calculate twice per frame

glm::vec3 b1, b2, b3, n1, n2;

if (selectedPoints.number>=2)
	b1=selectedPoints.p[1]-selectedPoints.p[0];

if (selectedPoints.number>=3) {
	b2=selectedPoints.p[1]-selectedPoints.p[2];
	n1=glm::normalize(b1*b2);
}

if (selectedPoints.number==4) {
	b3=selectedPoints.p[3]-selectedPoints.p[2];
	n2=glm::normalize(b2*b3);
}



std::string mystring=std::string("Timestep ")+std::to_string(timestep)+
	"\nIso "+std::to_string(curDataPos)+"\n";

1014 1015 1016 1017 1018 1019
if (selectedPoints.number==2) {
	float l=glm::length(b1)/globalscaling/scaling;
	char text[200];
	sprintf (text, "Distance: %0.2f Angstrom (%0.2f Bohr)\n", l, l*1.88973);
	mystring+=text;
} else if (selectedPoints.number==3)
1020 1021 1022 1023 1024
	mystring+="Angle: "+
		std::to_string(glm::degrees(glm::angle(glm::normalize(b1), glm::normalize(b2))))+"°";
//http://chemistry.stackexchange.com/questions/40181/when-calculating-a-dihedral-angle-for-a-chemical-bond-how-is-the-direction-defi
else if (selectedPoints.number==4)
	mystring+="Dihedral angle: "+		
1025
		std::to_string(glm::degrees(glm::angle(n1, n2)))+"°";
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056

text.render (mystring, 0,0, 0.02, glm::vec3(0,0,1), 
	pvmat*glm::translate(translation));

RenderPoints(pvmat, translation, selectedPoints);
}

void sceneManager::RenderPoints(const glm::mat4 pvmat, const glm::vec3 translation,
	const SelectedPoints& selectedPoints)
{
glm::mat4 st;
m_node->getSceneTrafo(st);
glm::mat4 stinv=glm::inverse(st);
glm::vec3 finalTranslation=(stinv*glm::vec4(translation, 1)).xyz();

sPoint.begin();
sPoint.setUniformMatrix("projection", false, pvmat*st);
glBindVertexArray(PointVAO);
glBindBuffer(GL_ARRAY_BUFFER, PointVBO);
float verts[(1+selectedPoints.number)*6];
float *vp=verts;
for (int j=0;j<selectedPoints.number;j++) {
	for(int i=0;i<3;i++)
		*vp++=selectedPoints.p[j][i];
	*vp++=0; *vp++=1; *vp++=0; //selected points colour
}
for (int i=0;i<3;i++)
	*vp++=finalTranslation[i];
*vp++=1; *vp++=0; *vp++=0; //wand point colour
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts); 

1057
if (selectedPoints.number > 0) {
1058
	glPointSize(2);
1059
	glDrawArrays(GL_LINE_STRIP, 0, 1+selectedPoints.number);
1060
	glPointSize(1);
1061 1062 1063 1064 1065
} else {
	glPointSize(4);
	glDrawArrays(GL_POINTS, 0, 1);
	glPointSize(1);
}
1066 1067 1068
sPoint.end();
}

1069 1070
void sceneManager::RenderIsos(const glm::mat4 eyeViewProjection, int curDataPos,
	const glm::mat4 pvmat, const SelectedPoints& selectedPoints)
1071 1072 1073 1074 1075 1076
{
GLenum e;
float t[16];
for (int i=0;i<4;i++)
	for (int j=0;j<4;j++)
		t[j*4+i]=eyeViewProjection[j][i];
1077

1078 1079

if (curDataPos!=ISOS) {
1080 1081 1082 1083
	glDisable(GL_BLEND);
	glUseProgram(ISOP);
	glUniformMatrix4fv(ISOMatrixLoc, 1, GL_FALSE, t);
	if ((e = glGetError()) != GL_NO_ERROR)
1084
		eprintf("Gl error after glUniform4fv 1 RenderIsos: %d\n", e);
1085 1086
	glBindVertexArray(ISOVAO[m_oldTime*ISOS+curDataPos]);
	glDrawElements(GL_TRIANGLES,numISOIndices[m_oldTime*ISOS+curDataPos] , GL_UNSIGNED_INT, 0);
1087
		if (has_abc) {
1088 1089 1090
			glm::mat4 trans(1.0);
			trans=glm::rotate(trans, (float)-M_PI_2, glm::vec3(1.f,0.f,0.f));
			RenderUnitCell(eyeViewProjection*trans);
1091 1092
		} else {
			//atom trajectories
1093 1094 1095
			glm::mat4 trans(1.0);
			trans=glm::rotate(trans, (float)-M_PI_2, glm::vec3(1.f,0.f,0.f));
			RenderAtomTrajectories(eyeViewProjection*trans);
1096
		}
1097
		RenderText(pvmat, curDataPos, m_oldTime, selectedPoints);
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
} else {//transparency
	glDisable(GL_BLEND);
	glDepthMask(GL_TRUE);
	//do depth peeling
	CleanDepthTexture(textDepthPeeling[0]);
	GLint dfb;
	glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &dfb);
if ((e = glGetError()) != GL_NO_ERROR)
	eprintf("Gl error RenderIsos, before zl loop: %d\n", e);
	for (int zl = 0; zl < ZLAYERS; zl++) {
		EnableDepthFB(zl, TransP, 
			peelingFramebuffer, textDepthPeeling);
		glUniformMatrix4fv(TransMatrixLoc, 1, GL_FALSE, t);
		for (int i=0;i<ISOS;i++) {
			glBindVertexArray(ISOVAO[m_oldTime*ISOS+i]);
1113 1114 1115 1116
			glDrawElements(GL_TRIANGLES,numISOIndices[m_oldTime*ISOS+i], 
				GL_UNSIGNED_INT, 0);	
		}
		if (has_abc) {
1117 1118 1119 1120
			glm::mat4 trans(1.0);
			trans=glm::rotate(trans, (float)-M_PI_2, 
				glm::vec3(1.f,0.f,0.f));
			RenderUnitCell(eyeViewProjection*trans);
1121 1122
		} else {
			//atom trajectories
1123 1124 1125 1126
			glm::mat4 trans(1.0);
			trans=glm::rotate(trans, (float)-M_PI_2, 
				glm::vec3(1.f,0.f,0.f));
			RenderAtomTrajectories(eyeViewProjection*trans);
1127
		}
1128
		RenderText(pvmat, curDataPos, m_oldTime, selectedPoints);
1129
	}
1130 1131 1132 1133
	glUseProgram(BlendP);
	glBindFramebuffer(GL_FRAMEBUFFER, dfb);
	glBindVertexArray(BlendVAO);
	BlendTextures(textDepthPeeling, ZLAYERS);
1134
}
1135 1136
if ((e = glGetError()) != GL_NO_ERROR)
	eprintf("Gl error after RenderIsos: %d\n", e);
1137 1138
}

1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
void sceneManager::RenderUnitCell(const glm::mat4 eyeViewProjection)
{
	//eprintf ("eyeViewProjection");
	//for (int i=0;i<4;i++)
	//	for (int j=0;j<4;j++)
	//		eprintf ("%d %d = %f", i, j, eyeViewProjection.m[i][j]);
	//eprintf ("RenderUnitCell, has_abc=%d", has_abc);
	if (!has_abc)
		return;
	if (UnitCellVAO==0)
		eprintf ("Error, Unit Cell VAO not loaded");
	int e;
	
	int p[3];

	for (p[0]=0;p[0]<repetitions[0];(p[0])++)
		for (p[1]=0;p[1]<repetitions[1];(p[1])++)
			for (p[2]=0;p[2]<repetitions[2];(p[2])++)
				{
					float delta[3];
					GetDisplacement(p, delta);
1160

1161 1162
					glm::mat4 trans= glm::mat4(1.0f);
					trans=glm::translate(trans,glm::vec3(delta[0]*5, delta[1]*5, delta[2]*5));
1163 1164 1165 1166
					trans=glm::scale(trans, glm::vec3
						(globalscaling*scaling ,
						globalscaling*scaling,
						globalscaling*scaling));
1167 1168 1169 1170 1171 1172 1173
//						={1,0,0,delta[0]/*+UserTranslation[0]*/,
//						0,1,0,delta[1]/*+UserTranslation[1]*/,
//						0,0,1,delta[2]/*+UserTranslation[2]*/,
//						0,0,0,1};
					
					//trans.translate(iPos).rotateX(-90).translate(UserPosition);
					glm::mat4 transform = eyeViewProjection*trans;
1174

1175 1176 1177 1178
					float t[16];
					for (int i=0;i<4;i++)
						for (int j=0;j<4;j++)
							t[j*4+i]=transform[j][i];
1179 1180
					
					
1181 1182 1183 1184
					glUseProgram(UnitCellP);
					glUniformMatrix4fv(UnitCellMatrixLoc, 1, GL_FALSE, t);
					if ((e = glGetError()) != GL_NO_ERROR)
						eprintf("Gl error after glUniform4fv 1 RenderUnitCell: %d\n", e);
1185
					if (displayunitcell) {
1186
						glUniform4fv(UnitCellColourLoc, 1, unitcellcolour);
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
						if ((e = glGetError()) != GL_NO_ERROR)
							eprintf("Gl error after glUniform4fv 2 RenderUnitCell: %d\n", e);
						glBindVertexArray(UnitCellVAO);
						glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, UnitCellIndexBuffer);
						if ((e = glGetError()) != GL_NO_ERROR)
							eprintf("1 Gl error RenderAtom timestep =%d: %d\n", m_oldTime, e);
						glBindBuffer(GL_ARRAY_BUFFER, UnitCellBuffer);
						glVertexAttribPointer(0, 3, GL_FLOAT, 
							GL_FALSE, 3 * sizeof(float), (const void *)(0));
						glEnableVertexAttribArray(0);
						glDisableVertexAttribArray(1);
						glDisableVertexAttribArray(2);
						glDisableVertexAttribArray(3);
						if ((e = glGetError()) != GL_NO_ERROR)
							eprintf("Gl error after glBindVertexArray RenderUnitCell: %d\n", e);
						glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0);
						//glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_INT, 0);
						if ((e = glGetError()) != GL_NO_ERROR)
							eprintf("Gl error after RenderUnitCell: %d\n", e);
					}	
1207 1208 1209 1210
					//atom trajectories
					//rgh: disable for now
					RenderAtomTrajectoriesUnitCell();
					RenderAtoms(t);
1211 1212
					RenderAtomBonds(t);
					
1213 1214
				}
}