From 85c755ae0c58df0b37a7e32aa43f9c75ee0100a7 Mon Sep 17 00:00:00 2001
From: "Garcia-Hernandez, Ruben Jesus (rgarcia)" <garcia@lrz.de>
Date: Wed, 12 Jul 2017 15:16:18 +0200
Subject: [PATCH] bond calculation fix stereo screenshot option (vive)
 configurable atom colours downsampling of screenshots option

---
 NOMADVRLib/ConfigFile.cpp                   | 29 +++++++++
 NOMADVRLib/ConfigFile.h                     |  3 +
 NOMADVRLib/atoms.cpp                        |  4 ++
 NOMADVRLib/atoms.hpp                        |  1 +
 NOMADVRLib/atomsGL.cpp                      |  5 +-
 OpenVR/TimestepData/hellovr_opengl_main.cpp | 72 +++++++++++++++++----
 6 files changed, 99 insertions(+), 15 deletions(-)

diff --git a/NOMADVRLib/ConfigFile.cpp b/NOMADVRLib/ConfigFile.cpp
index 612f9f5..10ff95a 100644
--- a/NOMADVRLib/ConfigFile.cpp
+++ b/NOMADVRLib/ConfigFile.cpp
@@ -44,10 +44,15 @@ int voxelSize[3];
 int repetitions[3];
 Solid *solid;
 
+bool saveStereo;
+int screenshotdownscaling;
+
 //markers such as hole positions and electron positions
 float ** markers;
 float ** markercolours;
 float cubetrans[3];
+
+
 const char * loadConfigFileErrors[] =
 {
 	"All Ok",//0
@@ -69,6 +74,7 @@ const char * loadConfigFileErrors[] =
 	"Error reading token", //-16
 	"markers with no previous correct timesteps parameter", //-17
 	"markercolours with no previous correct timesteps parameter", //-18
+	"Error reading atomcolour", // -19
 	"Error loading xyz file, add 100 to see the error",//<-100
 	"Error loading cube file, add 100 to see the error",//<-200
 	"Error loading json file, add 200 to see the error",//<-300
@@ -168,6 +174,8 @@ int loadConfigFile(const char * f)
 	translations=nullptr;
 	for (int i=0;i<3;i++)
 		voxelSize[i]=-1;
+	saveStereo=false;
+	screenshotdownscaling=1;
 	//
 	FILE *F = fopen(f, "r");
 	if (F == 0)
@@ -439,10 +447,31 @@ int loadConfigFile(const char * f)
 		}
 		} else if (!strcmp (s, "displaybonds")) {
 			displaybonds=true;
+		} else if (!strcmp (s, "atomcolour")) {
+			char atom [100];
+			float rgb[3];
+			r = fscanf(F, "%s %f", atom, rgb, rgb + 1, rgb + 2);
+			if (r!=4) {
+				eprintf ("Error loading atom colour");
+				return -19;
+			}
+			int a=findAtom(atom);
+			if (a==-1) {
+				eprintf ("atomcolour, unknown atom type %s", atom);
+				return -19;
+			}
+			for (int i=0;i<3;i++)
+				atomColours[a][i]=rgb[i];
 		} else if (!strcmp (s, "markerscaling")) {
 			r = fscanf(F, "%f", &markerscaling);
 		} else if (!strcmp (s, "displayunitcell")) {
 			displayunitcell=true;
+		} else if (!strcmp (s, "stereoscreenshot")) {
+			saveStereo=true;
+		} else if (!strcmp (s, "screenshotdownscaling")) {
+			r= fscanf(F, "%d", &screenshotdownscaling);
+			if (r<1)
+				eprintf ("Error reading screenshotdownscaling value");
 		} else if (!strcmp (s, "supercell")) {
 			r=fscanf (F, "%f %f %f", supercell, supercell+1, supercell+2);
 		} else if (!strcmp (s, "\x0d")) { //discard windows newline (problem in Sebastian Kokott's phone (?!)
diff --git a/NOMADVRLib/ConfigFile.h b/NOMADVRLib/ConfigFile.h
index 84c5827..690d90a 100644
--- a/NOMADVRLib/ConfigFile.h
+++ b/NOMADVRLib/ConfigFile.h
@@ -39,6 +39,9 @@ extern int repetitions[3];
 
 extern Solid *solid;
 
+extern bool saveStereo;
+extern int screenshotdownscaling;
+
 //markers such as hole positions and electron positions
 extern float ** markers;
 extern float ** markercolours;
diff --git a/NOMADVRLib/atoms.cpp b/NOMADVRLib/atoms.cpp
index 1496bc2..8a8f1b6 100644
--- a/NOMADVRLib/atoms.cpp
+++ b/NOMADVRLib/atoms.cpp
@@ -73,7 +73,11 @@ float atomColours[][4] =
 {0.941000f, 0.565000f, 0.627000f, 1.260000f},//Co
 {0.314000f, 0.816000f, 0.314000f, 1.240000f},//Ni
 {0.784000f, 0.502000f, 0.200000f, 1.320000f},//Cu
+// This is the standard colour
 {0.490000f, 0.502000f, 0.690000f, 1.220000f},//Zn
+// This is Andris's colour
+//{0.625f,0.125f,0.9375f, 1.220000f},//Zn
+
 {0.761000f, 0.561000f, 0.561000f, 1.220000f},//Ga
 {0.400000f, 0.561000f, 0.561000f, 1.200000f},//Ge
 {0.741000f, 0.502000f, 0.890000f, 1.190000f},//As
diff --git a/NOMADVRLib/atoms.hpp b/NOMADVRLib/atoms.hpp
index ea634c0..7c6a743 100644
--- a/NOMADVRLib/atoms.hpp
+++ b/NOMADVRLib/atoms.hpp
@@ -30,6 +30,7 @@ extern const char * readAtomsCubeErrors[];
 extern const char * readAtomsJsonErrors[];
 
 float atomRadius (int i);
+int findAtom(const char *const s);
 
 //internal functions
 void discardline (FILE *F);
diff --git a/NOMADVRLib/atomsGL.cpp b/NOMADVRLib/atomsGL.cpp
index 82d1fb6..a238715 100644
--- a/NOMADVRLib/atomsGL.cpp
+++ b/NOMADVRLib/atomsGL.cpp
@@ -256,6 +256,7 @@ GLenum SetupAtoms(GLuint **AtomVAO /*[3]*/, GLuint **AtomVertBuffer /*[2]*/, GLu
 	float *current=tmp;
 	
 	const int atomlimit=30;
+	const float bondscaling=0.7f;
 
 	numBonds=new int[getAtomTimesteps() ];
 	for (int p=0;p<getAtomTimesteps() ;p++) {
@@ -278,7 +279,7 @@ GLenum SetupAtoms(GLuint **AtomVAO /*[3]*/, GLuint **AtomVertBuffer /*[2]*/, GLu
 						}
 						r=atomRadius(static_cast<int>(atoms[p][4 * a1 + 3]))+
 							atomRadius(static_cast<int>(atoms[p][4 * a2 + 3]));
-						if (d*0.9f<r*r) {// bond
+						if (d*bondscaling<r*r) {// bond
 							bonds.push_back(a1+(p==0?0:numAtoms[p-1]));
 							bonds.push_back(a2+(p==0?0:numAtoms[p-1]));
 						}
@@ -300,7 +301,7 @@ GLenum SetupAtoms(GLuint **AtomVAO /*[3]*/, GLuint **AtomVertBuffer /*[2]*/, GLu
 						M[k]=atoms[p][4*a+k];
 				}
 			}
-			grid g(m, M, pow(numAtoms[p], 1.0/3), 0.9f);
+			grid g(m, M, pow(numAtoms[p], 1.0/3), bondscaling);
 			for (int a = 1; a < numAtoms[p]; a++) 
 				g.add(atoms[p]+4*a);
 			for (int a = 0; a < numAtoms[p]; a++) {
diff --git a/OpenVR/TimestepData/hellovr_opengl_main.cpp b/OpenVR/TimestepData/hellovr_opengl_main.cpp
index 18cc781..19450c8 100644
--- a/OpenVR/TimestepData/hellovr_opengl_main.cpp
+++ b/OpenVR/TimestepData/hellovr_opengl_main.cpp
@@ -191,6 +191,8 @@ private: // OpenGL bookkeeping
 	int m_iValidPoseCount_Last;
 	bool m_bShowCubes;
 	bool buttonPressed[2][vr::k_unMaxTrackedDeviceCount]; //grip, application menu
+	bool AtomsButtonPressed[2];
+	bool showAtoms;
 	std::string m_strPoseClasses;                            // what classes we saw poses for this frame
 	char m_rDevClassChar[vr::k_unMaxTrackedDeviceCount];   // for each device, a character representing its class
 
@@ -205,6 +207,8 @@ private: // OpenGL bookkeeping
 	float m_fNearClip;
 	float m_fFarClip;
 
+	void SaveScreenshot (char *name);
+
 	GLuint *m_iTexture; //[3+ZLAYERS+1] // white, depth1, depth2, color[ZLAYERS], atomtexture
 	SDL_Texture **axisTextures; //[6]
 	GLuint peelingFramebuffer;
@@ -303,7 +307,7 @@ private: // OpenGL bookkeeping
 	std::vector< CGLRenderModel * > m_vecRenderModels;
 	CGLRenderModel *m_rTrackedDeviceToRenderModel[ vr::k_unMaxTrackedDeviceCount ];
 
-	char * pixels; //for saving screenshots to disk
+	char *pixels, *pixels2; //for saving screenshots to disk
 	int framecounter;
 	bool savetodisk;
 };
@@ -423,7 +427,7 @@ CMainApplication::CMainApplication(int argc, char *argv[])
 		for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
 			buttonPressed[j][i] = false;
 		}
-
+	showAtoms=true;
 	for( int i = 1; i < argc; i++ )
 	{
 		if( !stricmp( argv[i], "-gldebug" ) )
@@ -939,19 +943,26 @@ bool CMainApplication::HandleInput()
 		vr::VRControllerState_t state;
 		if (m_pHMD->GetControllerState(unDevice, &state))
 		{
-			m_rbShowTrackedDevice[unDevice] = state.ulButtonPressed == 0;
+			//this hides the controllers when buttons are pressed. Why?! -> 
+			//rgh: the name of the variable seems to make it so :o) Possibly so that a different model can be used with the correct deformation
+			//m_rbShowTrackedDevice[unDevice] = state.ulButtonPressed == 0;
 
 			if (!buttonPressed[1][unDevice] && state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu)) {
 				buttonPressed[1][unDevice] = true;
 				if (firstdevice == -1)
 					firstdevice = unDevice;
-				savetodisk = !savetodisk;
+
+				if (firstdevice==unDevice)
+					savetodisk = !savetodisk;
+				else
+					showAtoms= !showAtoms;
 			}
 			else if (buttonPressed[1][unDevice] && 0 == (state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu)))
 			{
 				buttonPressed[1][unDevice] = false;
 			}
 
+			
 			if (!buttonPressed[0][unDevice] && state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_Grip))
 			{
 				buttonPressed[0][unDevice] = true;
@@ -1761,7 +1772,12 @@ bool CMainApplication::SetupStereoRenderTargets()
 	CreateFrameBuffer( m_nRenderWidth, m_nRenderHeight, rightEyeDesc );
 	
 	pixels = new char [m_nRenderWidth*m_nRenderHeight*3];
-
+	if (m_nRenderHeight%screenshotdownscaling!=0)
+		dprintf("Height not multiple of screenshot scale");
+	if (m_nRenderWidth%screenshotdownscaling!=0)
+		dprintf("Width not multiple of screenshot scale");
+	if (screenshotdownscaling!=1)
+		pixels2= new char[m_nRenderWidth*m_nRenderHeight*3/screenshotdownscaling/screenshotdownscaling];
 	return true;
 }
 
@@ -1902,6 +1918,34 @@ void CMainApplication::SetupDistortion()
 }
 
 
+void CMainApplication::SaveScreenshot (char *name)
+{
+SDL_Surface *s;
+int x=m_nRenderWidth/screenshotdownscaling;
+int y=m_nRenderHeight/screenshotdownscaling;
+glPixelStorei(GL_PACK_ALIGNMENT, 1);
+glReadPixels(0, 0, m_nRenderWidth, m_nRenderHeight, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+
+	//little endian machine, R and B are flipped
+	if (screenshotdownscaling==1) {
+		s = SDL_CreateRGBSurfaceFrom(pixels, x, y, 24, 3 * y, 0xff, 0xff00, 0xff0000, 0);
+	} else {
+		for (int i=0;i<x;i++)
+			for (int j=0;j<y;j++) {
+				short rgb[3]={0,0,0};
+				for (int k=0;k<screenshotdownscaling;k++) //horiz
+					for (int l=0;l<screenshotdownscaling;l++) //vert
+						for (int m=0;m<3;m++)
+							rgb[m]+=pixels[j*3*m_nRenderWidth*screenshotdownscaling+i*3*screenshotdownscaling	+l*3*m_nRenderWidth+k*3	+m];
+				for (int m=0;m<3;m++)
+					pixels2[i*3+j*3*m_nRenderWidth/screenshotdownscaling+m]=rgb[m]/screenshotdownscaling/screenshotdownscaling;
+			}
+		s = SDL_CreateRGBSurfaceFrom(pixels2, x, y, 24, 3 * y, 0xff, 0xff00, 0xff0000, 0);
+	}
+		SDL_SaveBMP(s, name);
+
+}
+
 //-----------------------------------------------------------------------------
 // Purpose:
 //-----------------------------------------------------------------------------
@@ -1921,11 +1965,7 @@ void CMainApplication::RenderStereoTargets()
 
 	if (savetodisk) {
 		sprintf(name, "%sL%05d.bmp", SCREENSHOT, framecounter);
-		glPixelStorei(GL_PACK_ALIGNMENT, 1);
-		glReadPixels(0, 0, m_nRenderWidth, m_nRenderHeight, GL_RGB, GL_UNSIGNED_BYTE, pixels);
-		//little endian machine, R and B are flipped
-		SDL_Surface *s = SDL_CreateRGBSurfaceFrom(pixels, m_nRenderWidth, m_nRenderHeight, 24, 3 * m_nRenderWidth, 0xff, 0xff00, 0xff0000, 0);
-		SDL_SaveBMP(s, name);
+		SaveScreenshot(name);
 	}
 
  	glBindFramebuffer( GL_FRAMEBUFFER, 0 );
@@ -1948,6 +1988,12 @@ void CMainApplication::RenderStereoTargets()
 	glBindFramebuffer( GL_FRAMEBUFFER, rightEyeDesc.m_nRenderFramebufferId );
  	glViewport(0, 0, m_nRenderWidth, m_nRenderHeight );
  	RenderScene( vr::Eye_Right );
+
+	if (savetodisk && saveStereo) {
+		sprintf(name, "%sR%05d.bmp", SCREENSHOT, framecounter);
+		SaveScreenshot(name);
+	}
+
  	glBindFramebuffer( GL_FRAMEBUFFER, 0 );
  	
 	glDisable( GL_MULTISAMPLE );
@@ -2073,7 +2119,7 @@ glPatchParameteri(GL_PATCH_VERTICES, 1);
 trans.translate(iPos).rotateX(-90).translate(UserPosition);
 Matrix4 transform = GetCurrentViewProjectionMatrix(nEye)*trans;
 
-if (numAtoms) {
+if (numAtoms && showAtoms) {
 	glBindVertexArray(m_unAtomVAO[0]);
 	glEnableVertexAttribArray(0);
 	glEnableVertexAttribArray(1);
@@ -2095,7 +2141,7 @@ if (numAtoms) {
 		dprintf("Gl error after RenderAtoms timestep =%d: %d, %s\n", currentset, e, gluErrorString(e));
 }
 //now cloned atoms
-if (numClonedAtoms!=0 && (currentset==0||fixedAtoms)) {
+if (numClonedAtoms!=0 && (currentset==0||fixedAtoms) && showAtoms) {
 	glBindVertexArray(m_unAtomVAO[1]);
 	glDrawArrays(GL_PATCHES, 0, numClonedAtoms);
 	if ((e = glGetError()) != GL_NO_ERROR)
@@ -2103,7 +2149,7 @@ if (numClonedAtoms!=0 && (currentset==0||fixedAtoms)) {
 }
 
 //now bonds
-if (numBonds && displaybonds) {
+if (numBonds && displaybonds && showAtoms) {
 	glBindVertexArray(m_unAtomVAO[2]);
 	glUseProgram(m_unUnitCellProgramID);
 	glUniformMatrix4fv(m_nUnitCellMatrixLocation, 1, GL_FALSE, transform.get());
-- 
GitLab