//========= Copyright Valve Corporaion ============// #define NOMINMAX #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_NEW #include #include #include #include //#include #include #include #include #include #include #include #include "shared/lodepng.h" #include "shared/Matrices.h" #include "shared/pathtools.h" #include "rply/rply.h" #include "NOMADVRLib/ConfigFile.h" #include "NOMADVRLib/atoms.hpp" #include "NOMADVRLib/atomsGL.h" #include "NOMADVRLib/TessShaders.h" #include "NOMADVRLib/UnitCellShaders.h" #include "NOMADVRLib/IsoShaders.h" #include "NOMADVRLib/CompileGLShader.h" #include "NOMADVRLib/polyhedron.h" #include "NOMADVRLib/IsosurfacesGL.h" #define TESSSUB 16 //TTF_Font* font; //#define LOCALTEST /*#ifdef LOCALTEST #define PATH "Y:\\v2t\\datasets\\mpcdf_CO2_CaO\\cubes-bigger\\IsosurfacesFixed\\" #else #define PATH "data\\CO2-CaO-B\\" //#define PATH "C:\\Users\\mobile\\Desktop\\openvrDemos\\win64\\data\\CO2-CaO-B\\" #endif */ #define ZLAYERS 12 #define MAXGPU 300 //shown on https://www.vbw-bayern.de/vbw/Aktionsfelder/Innovation-F-T/Forschung-und-Technologie/Zukunft-digital-Big-Data.jsp #define GRID 1 #define NUMLODS 1 #define NUMPLY (TIMESTEPS * ISOS) class CGLRenderModel { public: CGLRenderModel( const std::string & sRenderModelName ); ~CGLRenderModel(); bool BInit( const vr::RenderModel_t & vrModel, const vr::RenderModel_TextureMap_t & vrDiffuseTexture ); void Cleanup(); void Draw(); const std::string & GetName() const { return m_sModelName; } private: GLuint m_glVertBuffer; GLuint m_glIndexBuffer; GLuint m_glVertArray; GLuint m_glTexture; GLsizei m_unVertexCount; std::string m_sModelName; }; static bool g_bPrintf = true; //----------------------------------------------------------------------------- // Purpose: //------------------------------------------------------------------------------ class CMainApplication { public: CMainApplication(int argc, char *argv[]); virtual ~CMainApplication(); bool BInit(); bool BInitGL(); bool BInitCompositor(); void SetupRenderModels(); void Shutdown(); void RunMainLoop(); bool HandleInput(); void ProcessVREvent(const vr::VREvent_t & event); void RenderFrame(); void HapticFeedback(); void HapticFeedback(int device); bool SetupTexturemaps(); bool SetupDepthPeeling(); void SetupScene(); void SetupIsosurfaces(); void SetupAtoms(); void SetupUnitCell(); void SetupMarker(); void DrawControllers(); bool SetupStereoRenderTargets(); void SetupDistortion(); void SetupCameras(); void RenderStereoTargets(); void RenderDistortion(); void RenderScene(vr::Hmd_Eye nEye); void RenderAtoms(const vr::Hmd_Eye &nEye); void RenderAtomsUnitCell(const vr::Hmd_Eye &nEye, int p[3]); void RenderUnitCell(const vr::Hmd_Eye &nEye); //Vector3 GetDisplacement(int p[3]); Matrix4 GetHMDMatrixProjectionEye(vr::Hmd_Eye nEye); Matrix4 GetHMDMatrixPoseEye(vr::Hmd_Eye nEye); Matrix4 GetCurrentViewProjectionMatrix(vr::Hmd_Eye nEye); Matrix4 GetCurrentViewMatrix( vr::Hmd_Eye nEye ); void UpdateHMDMatrixPose(); Matrix4 ConvertSteamVRMatrixToMatrix4(const vr::HmdMatrix34_t &matPose); bool CreateAllShaders(); void SetupRenderModelForTrackedDevice(vr::TrackedDeviceIndex_t unTrackedDeviceIndex); CGLRenderModel *FindOrLoadRenderModel(const char *pchRenderModelName); void RenderAllTrackedRenderModels(vr::Hmd_Eye nEye); private: bool m_bDebugOpenGL; bool m_bVerbose; bool m_bPerf; bool m_bVblank; bool m_bGlFinishHack; vr::IVRSystem *m_pHMD; vr::IVRRenderModels *m_pRenderModels; std::string m_strDriver; std::string m_strDisplay; vr::TrackedDevicePose_t m_rTrackedDevicePose[vr::k_unMaxTrackedDeviceCount]; Matrix4 m_rmat4DevicePose[vr::k_unMaxTrackedDeviceCount]; bool m_rbShowTrackedDevice[vr::k_unMaxTrackedDeviceCount]; std::vector **vertdataarray; //[LOD][PLY] #ifndef INDICESGL32 std::vector **vertindicesarray;//[LOD][PLY] #else std::vector **vertindicesarray;//[LOD][PLY] #endif private: // SDL bookkeeping SDL_Window *m_pWindow; uint32_t m_nWindowWidth; uint32_t m_nWindowHeight; SDL_GLContext m_pContext; void PaintGrid(const vr::Hmd_Eye &nEye, const int iso); bool PaintBox(); private: // OpenGL bookkeeping int m_iTrackedControllerCount; int m_iTrackedControllerCount_Last; int m_iValidPoseCount; 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 int m_iSceneVolumeWidth; int m_iSceneVolumeHeight; int m_iSceneVolumeDepth; float m_fScaleSpacing; float m_fScale; int m_iSceneVolumeInit; // if you want something other than the default 20x20x20 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; unsigned int **m_uiVertcount;// [LODS][NUMPLY]; //for isos GLuint **m_glSceneVertBuffer; // [LODS][NUMPLY]; GLuint **m_unSceneVAO; //[LODS][NUMPLY]; GLuint **m_unSceneVAOIndices; //[LODS][NUMPLY]; //for atoms GLuint *m_glAtomVertBuffer; // [TIMESTEPS]; GLuint *m_unAtomVAO; //[3]; //atoms, cloned atoms, bonds GLuint BondIndices; //for unit cells GLuint m_glUnitCellVertBuffer; // primitive, possibly non-primitive in further. Deformed cube GLuint m_glUnitCellIndexBuffer; // GLuint m_unUnitCellVAO; // //for markers GLuint m_glMarkerVertBuffer; GLuint m_unMarkerVAO; int currentset; float elapsedtime; static const float videospeed; int currentiso; int firstdevice, seconddevice; GLuint m_unLensVAO; GLuint m_glIDVertBuffer; GLuint m_glIDIndexBuffer; unsigned int m_uiIndexSize; GLuint m_glControllerVertBuffer; GLuint m_unControllerVAO; unsigned int m_uiControllerVertcount; Matrix4 m_mat4HMDPose; Matrix4 m_mat4eyePosLeft; Matrix4 m_mat4eyePosRight; Matrix4 m_mat4ProjectionCenter; Matrix4 m_mat4ProjectionLeft; Matrix4 m_mat4ProjectionRight; Vector3 UserPosition; struct VertexDataScene { Vector3 position; Vector2 texCoord; }; struct VertexDataLens { Vector2 position; Vector2 texCoordRed; Vector2 texCoordGreen; Vector2 texCoordBlue; }; GLuint m_unSceneProgramID; GLuint m_unLensProgramID; GLuint m_unControllerTransformProgramID; GLuint m_unRenderModelProgramID; GLuint m_unAtomsProgramID; GLuint m_unUnitCellProgramID; GLuint m_unBlendingProgramID; GLuint m_unMarkerProgramID; GLint m_nSceneMatrixLocation; GLint m_nBlendingIntLocation; GLint m_nControllerMatrixLocation; GLint m_nRenderModelMatrixLocation; GLint m_nAtomMatrixLocation; GLint m_nAtomMVLocation; GLint m_nUnitCellMatrixLocation, m_nUnitCellColourLocation; GLint m_nMarkerMatrixLocation; struct FramebufferDesc { GLuint m_nDepthBufferId; GLuint m_nRenderTextureId; GLuint m_nRenderFramebufferId; GLuint m_nResolveTextureId; GLuint m_nResolveFramebufferId; }; FramebufferDesc leftEyeDesc; FramebufferDesc rightEyeDesc; bool CreateFrameBuffer( int nWidth, int nHeight, FramebufferDesc &framebufferDesc ); void CleanDepthTexture(); uint32_t m_nRenderWidth; uint32_t m_nRenderHeight; std::vector< CGLRenderModel * > m_vecRenderModels; CGLRenderModel *m_rTrackedDeviceToRenderModel[ vr::k_unMaxTrackedDeviceCount ]; char *pixels, *pixels2; //for saving screenshots to disk int framecounter; bool savetodisk; }; const float CMainApplication::videospeed = 0.01f; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void dprintf( const char *fmt, ... ) { va_list args; char buffer[ 2048 ]; va_start( args, fmt ); vsprintf_s( buffer, fmt, args ); va_end( args ); if ( g_bPrintf ) printf( "%s", buffer ); OutputDebugStringA( buffer ); if (strncmp(buffer, "PoseCount", 9) && strncmp (buffer, "Device", 6)) SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Warning", buffer, 0); } //pure windows, no sdl void eprintf( const char *fmt, ... ) { static int numerrors=0; numerrors++; if (numerrors==25) { MessageBoxA(0, "Max messages reached, no further reporting", "Warning", 0); } if (numerrors>15) { return; } va_list args; char buffer[ 2048 ]; va_start( args, fmt ); vsprintf_s( buffer, fmt, args ); va_end( args ); if ( g_bPrintf ) printf( "%s", buffer ); MessageBoxA(0, buffer, "Warning", 0); } //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CMainApplication::CMainApplication(int argc, char *argv[]) : m_pWindow(NULL) , m_pContext(NULL) , m_nWindowWidth(1920) , m_nWindowHeight(1080) , m_unSceneProgramID(0) , m_unLensProgramID(0) , m_unControllerTransformProgramID(0) , m_unRenderModelProgramID(0) , m_unAtomsProgramID(0) , m_unUnitCellProgramID(0) , m_pHMD(NULL) , m_pRenderModels(NULL) , m_bDebugOpenGL(false) , m_bVerbose(false) , m_bPerf(false) , m_bVblank(false) , m_bGlFinishHack(true) , m_glControllerVertBuffer(0) , m_unControllerVAO(0) , m_unLensVAO(0) , m_unSceneVAO(0) , m_unSceneVAOIndices(0) , m_unAtomVAO(0) , m_glAtomVertBuffer(0) , m_glUnitCellVertBuffer(-1) , m_glUnitCellIndexBuffer(-1) , m_unUnitCellVAO(0) , m_nSceneMatrixLocation(-1) , m_nBlendingIntLocation(-1) , m_nControllerMatrixLocation(-1) , m_nRenderModelMatrixLocation(-1) , m_nAtomMatrixLocation(-1) , m_nAtomMVLocation(-1) , m_nUnitCellMatrixLocation(-1) , m_nUnitCellColourLocation(-1) , m_iTrackedControllerCount(0) , m_iTrackedControllerCount_Last(-1) , m_iValidPoseCount(0) , m_iValidPoseCount_Last(-1) , m_iSceneVolumeInit(20) , m_strPoseClasses("") , m_bShowCubes(true) , currentset(0) , elapsedtime(videospeed*float(SDL_GetTicks())) , currentiso(ISOS) , firstdevice(-1) , seconddevice(-1) , m_iTexture(0) , axisTextures(0) , peelingFramebuffer(0) , m_uiVertcount(0) , m_glSceneVertBuffer(0) //, UserPosition(Vector3(-101.0f * 0.15f*0.5f*GRID + 12.5f, -15.0f, -101.0f * 0.15f*0.5f*GRID + 101.0f * 0.15f*0.25f)) , UserPosition(Vector3(-userpos[0] /** 0.04f*/, -userpos[1] /** 0.04f*/, -userpos[2] /** 0.04f*/)) , vertdataarray(0) , vertindicesarray(0) , pixels(0) , framecounter(0) , savetodisk(false) { for (int j=0;j<2;j++) 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" ) ) { m_bDebugOpenGL = true; } else if( !stricmp( argv[i], "-verbose" ) ) { m_bVerbose = true; } else if( !stricmp( argv[i], "-novblank" ) ) { m_bVblank = false; } else if( !stricmp( argv[i], "-noglfinishhack" ) ) { m_bGlFinishHack = false; } else if( !stricmp( argv[i], "-noprintf" ) ) { g_bPrintf = false; } else if ( !stricmp( argv[i], "-cubevolume" ) && ( argc > i + 1 ) && ( *argv[ i + 1 ] != '-' ) ) { m_iSceneVolumeInit = atoi( argv[ i + 1 ] ); i++; } } // other initialization tasks are done in BInit memset(m_rDevClassChar, 0, sizeof(m_rDevClassChar)); }; //----------------------------------------------------------------------------- // Purpose: Destructor //----------------------------------------------------------------------------- CMainApplication::~CMainApplication() { // work is done in Shutdown dprintf( "Shutdown" ); } //----------------------------------------------------------------------------- // Purpose: Helper to get a string from a tracked device property and turn it // into a std::string //----------------------------------------------------------------------------- std::string GetTrackedDeviceString( vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *peError = NULL ) { uint32_t unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty( unDevice, prop, NULL, 0, peError ); if( unRequiredBufferLen == 0 ) return ""; char *pchBuffer = new char[ unRequiredBufferLen ]; unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty( unDevice, prop, pchBuffer, unRequiredBufferLen, peError ); std::string sResult = pchBuffer; delete [] pchBuffer; return sResult; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CMainApplication::BInit() { if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 ) { printf("%s - SDL could not initialize! SDL Error: %s\n", __FUNCTION__, SDL_GetError()); return false; } // Loading the SteamVR Runtime vr::EVRInitError eError = vr::VRInitError_None; m_pHMD = vr::VR_Init( &eError, vr::VRApplication_Scene ); if ( eError != vr::VRInitError_None ) { m_pHMD = NULL; char buf[1024]; sprintf_s( buf, sizeof( buf ), "Unable to init VR runtime: %s", vr::VR_GetVRInitErrorAsEnglishDescription( eError ) ); SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "VR_Init Failed", buf, NULL ); return false; } m_pRenderModels = (vr::IVRRenderModels *)vr::VR_GetGenericInterface( vr::IVRRenderModels_Version, &eError ); if( !m_pRenderModels ) { m_pHMD = NULL; vr::VR_Shutdown(); char buf[1024]; sprintf_s( buf, sizeof( buf ), "Unable to get render model interface: %s", vr::VR_GetVRInitErrorAsEnglishDescription( eError ) ); SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "VR_Init Failed", buf, NULL ); return false; } int nWindowPosX = 0; int nWindowPosY = 0; m_nWindowWidth = 1920; m_nWindowHeight = 1080; Uint32 unWindowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN /*| SDL_WINDOW_FULLSCREEN_DESKTOP*/; //rgh: interferes with mode change to 100Hz refresh SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 4 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 ); //SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 0 ); if( m_bDebugOpenGL ) SDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG ); m_pWindow = SDL_CreateWindow( "Geophysics OpenVR SDL", nWindowPosX, nWindowPosY, m_nWindowWidth, m_nWindowHeight, unWindowFlags ); if (m_pWindow == NULL) { printf( "%s - Window could not be created! SDL Error: %s\n", __FUNCTION__, SDL_GetError() ); return false; } m_pContext = SDL_GL_CreateContext(m_pWindow); if (m_pContext == NULL) { printf( "%s - OpenGL context could not be created! SDL Error: %s\n", __FUNCTION__, SDL_GetError() ); return false; } glewExperimental = GL_TRUE; GLenum nGlewError = glewInit(); if (nGlewError != GLEW_OK) { printf( "%s - Error initializing GLEW! %s\n", __FUNCTION__, glewGetErrorString( nGlewError ) ); return false; } glGetError(); // to clear the error caused deep in GLEW if ( SDL_GL_SetSwapInterval( m_bVblank ? 1 : 0 ) < 0 ) { printf( "%s - Warning: Unable to set VSync! SDL Error: %s\n", __FUNCTION__, SDL_GetError() ); return false; } m_strDriver = "No Driver"; m_strDisplay = "No Display"; m_strDriver = GetTrackedDeviceString( m_pHMD, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String ); m_strDisplay = GetTrackedDeviceString( m_pHMD, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String ); std::string strWindowTitle = "Geophysics OpenVR - " + m_strDriver + " " + m_strDisplay; SDL_SetWindowTitle( m_pWindow, strWindowTitle.c_str() ); // cube array m_iSceneVolumeWidth = m_iSceneVolumeInit; m_iSceneVolumeHeight = m_iSceneVolumeInit; m_iSceneVolumeDepth = m_iSceneVolumeInit; m_fScale = 0.04f; //0.15f; //rgh: original too big for room m_fScaleSpacing = 4.0f; m_fNearClip = 0.2f; m_fFarClip = 200.0f;//rgh: original 30 too small for our skymap // m_MillisecondsTimer.start(1, this); // m_SecondsTimer.start(1000, this); if (!BInitGL()) { printf("%s - Unable to initialize OpenGL!\n", __FUNCTION__); return false; } if (!BInitCompositor()) { printf("%s - Failed to initialize VR Compositor!\n", __FUNCTION__); return false; } return true; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void APIENTRY DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const void* userParam) { dprintf( "GL Error: %s\n", message ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CMainApplication::BInitGL() { if( m_bDebugOpenGL ) { glDebugMessageCallback(DebugCallback, nullptr); glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE ); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); } if( !CreateAllShaders() ) return false; GLenum e; SetupTexturemaps(); e=glGetError(); if (e!=GL_NO_ERROR) eprintf ("gl error %d, %s %d", e, __FILE__, __LINE__); SetupScene(); e=glGetError(); if (e!=GL_NO_ERROR) eprintf ("gl error %d, %s %d", e, __FILE__, __LINE__); SetupCameras(); e=glGetError(); if (e!=GL_NO_ERROR) eprintf ("gl error %d, %s %d", e, __FILE__, __LINE__); SetupStereoRenderTargets(); e=glGetError(); if (e!=GL_NO_ERROR) eprintf ("gl error %d, %s %d", e, __FILE__, __LINE__); SetupDistortion(); e=glGetError(); if (e!=GL_NO_ERROR) eprintf ("gl error %d, %s %d", e, __FILE__, __LINE__); SetupDepthPeeling(); SetupRenderModels(); return true; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CMainApplication::BInitCompositor() { vr::EVRInitError peError = vr::VRInitError_None; if ( !vr::VRCompositor() ) { printf( "Compositor initialization failed. See log file for details\n" ); return false; } return true; } void deleteVaos (GLuint *** vaos, int numlods, int numply) { if( *vaos != 0 ) { for (int i = 0; i < numlods; i++) { glDeleteVertexArrays(numply, (*vaos)[i]); delete[] (*vaos)[i]; } delete[] (*vaos); *vaos = 0; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMainApplication::Shutdown() { if( m_pHMD ) { vr::VR_Shutdown(); m_pHMD = NULL; } for( std::vector< CGLRenderModel * >::iterator i = m_vecRenderModels.begin(); i != m_vecRenderModels.end(); i++ ) { delete (*i); } m_vecRenderModels.clear(); if (vertdataarray) { for (int i = 0; i < NUMLODS; i++) if (vertdataarray[i]) delete[] vertdataarray[i]; delete[]vertdataarray; vertdataarray = 0; } if (vertindicesarray){ for (int i = 0; i < NUMLODS; i++) if (vertindicesarray[i]) delete[] vertindicesarray[i]; delete[] vertindicesarray; vertindicesarray = 0; } if (m_pContext) { glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE); glDebugMessageCallback(nullptr, nullptr); if (m_glSceneVertBuffer) { for (int i = 0; i < NUMLODS; i++) { glDeleteBuffers(NUMPLY, m_glSceneVertBuffer[i]); delete[] (m_glSceneVertBuffer[i]); } delete[] m_glSceneVertBuffer; m_glSceneVertBuffer = nullptr; } glDeleteBuffers(1, &m_glIDVertBuffer); glDeleteBuffers(1, &m_glIDIndexBuffer); if ( m_unSceneProgramID ) { glDeleteProgram( m_unSceneProgramID ); } if ( m_unControllerTransformProgramID ) { glDeleteProgram( m_unControllerTransformProgramID ); } if ( m_unRenderModelProgramID ) { glDeleteProgram( m_unRenderModelProgramID ); } if ( m_unLensProgramID ) { glDeleteProgram( m_unLensProgramID ); } if ( m_unAtomsProgramID ) { glDeleteProgram( m_unAtomsProgramID ); } if (m_unUnitCellProgramID) glDeleteProgram(m_unUnitCellProgramID); glDeleteRenderbuffers( 1, &leftEyeDesc.m_nDepthBufferId ); glDeleteTextures( 1, &leftEyeDesc.m_nRenderTextureId ); glDeleteFramebuffers( 1, &leftEyeDesc.m_nRenderFramebufferId ); glDeleteTextures( 1, &leftEyeDesc.m_nResolveTextureId ); glDeleteFramebuffers( 1, &leftEyeDesc.m_nResolveFramebufferId ); glDeleteRenderbuffers( 1, &rightEyeDesc.m_nDepthBufferId ); glDeleteTextures( 1, &rightEyeDesc.m_nRenderTextureId ); glDeleteFramebuffers( 1, &rightEyeDesc.m_nRenderFramebufferId ); glDeleteTextures( 1, &rightEyeDesc.m_nResolveTextureId ); glDeleteFramebuffers( 1, &rightEyeDesc.m_nResolveFramebufferId ); if( m_unLensVAO != 0 ) { glDeleteVertexArrays( 1, &m_unLensVAO ); } deleteVaos(&m_unSceneVAO, NUMLODS, NUMPLY); if( m_unAtomVAO != 0 ) { glDeleteVertexArrays(1, m_unAtomVAO); delete[] m_unAtomVAO; m_unAtomVAO = 0; } if (m_glAtomVertBuffer!=0) { glDeleteBuffers(1, m_glAtomVertBuffer); delete[] m_glAtomVertBuffer; m_glAtomVertBuffer=0; } if (m_unUnitCellVAO!=0) { glDeleteVertexArrays(1, &m_unUnitCellVAO); } if (m_glUnitCellVertBuffer!=-1) { glDeleteBuffers(1, &m_glUnitCellVertBuffer); m_glUnitCellVertBuffer=-1; } if (m_glUnitCellIndexBuffer!=-1) { glDeleteBuffers(1, &m_glUnitCellIndexBuffer); m_glUnitCellIndexBuffer=-1; } if( m_unControllerVAO != 0 ) { glDeleteVertexArrays( 1, &m_unControllerVAO ); } if (m_unSceneVAOIndices!=0) { for (int i=0;i= TIMESTEPS) currentset = 0; } if (sdlEvent.key.keysym.sym == SDLK_2) { currentset--; if (currentset < 0) currentset = TIMESTEPS -1; } if (sdlEvent.key.keysym.sym == SDLK_0) { currentiso++; if (currentiso > ISOS) currentiso = 0; } if (sdlEvent.key.keysym.sym == SDLK_a) { Matrix4 tmp = m_mat4HMDPose; UserPosition += tmp.invert()*Vector3(0, 0, speed); //UserPosition.x += speed; } if (sdlEvent.key.keysym.sym == SDLK_y) { //UserPosition.x -= speed; Matrix4 tmp = m_mat4HMDPose; UserPosition -= tmp.invert()*Vector3(0, 0, speed); } if (sdlEvent.key.keysym.sym == SDLK_o) { UserPosition[2] -= 0.1f; dprintf("%f %f\n", UserPosition[0], UserPosition[2]); } if (sdlEvent.key.keysym.sym == SDLK_p) { UserPosition[2] += 0.1f; dprintf("%f %f\n", UserPosition[0], UserPosition[2]); } } } // Process SteamVR events vr::VREvent_t event; while (m_pHMD->PollNextEvent(&event, sizeof(event))) { ProcessVREvent(event); } // Process SteamVR controller state for (vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; unDevice++) { vr::VRControllerState_t state; if (m_pHMD->GetControllerState(unDevice, &state)) { //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; else if(seconddevice==-1) seconddevice=unDevice; 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; if (firstdevice == -1) firstdevice = unDevice; else if(seconddevice==-1) seconddevice=unDevice; if (unDevice == firstdevice) { currentset--; if (currentset < 0) currentset = TIMESTEPS - 1; } else { currentiso++; if (currentiso > ISOS) currentiso = 0; } } else if (buttonPressed[0][unDevice] && (state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_Grip)) == 0) buttonPressed[0][unDevice] = false; if (state.rAxis[1].x >0.1) { if (firstdevice == -1) firstdevice = unDevice; if (unDevice == firstdevice) { Matrix4 tmp = m_mat4HMDPose; UserPosition += tmp.invert()*Vector3(0, 0, speed); } else { float newtime = videospeed*float(SDL_GetTicks());; if (newtime-elapsedtime > 1) { elapsedtime = newtime; currentset++; if (currentset >= TIMESTEPS) currentset = 0; } } } } } return bRet; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMainApplication::RunMainLoop() { bool bQuit = false; SDL_StartTextInput(); SDL_ShowCursor( SDL_DISABLE ); while ( !bQuit ) { bQuit = HandleInput(); RenderFrame(); HapticFeedback(); } SDL_StopTextInput(); } //----------------------------------------------------------------------------- // Purpose: Processes a single VR event //----------------------------------------------------------------------------- void CMainApplication::ProcessVREvent( const vr::VREvent_t & event ) { switch (event.eventType) { case vr::VREvent_TrackedDeviceActivated: { SetupRenderModelForTrackedDevice(event.trackedDeviceIndex); dprintf("Device %u attached. Setting up render model.\n", event.trackedDeviceIndex); } break; case vr::VREvent_TrackedDeviceDeactivated: { dprintf("Device %u detached.\n", event.trackedDeviceIndex); } break; case vr::VREvent_TrackedDeviceUpdated: { dprintf("Device %u updated.\n", event.trackedDeviceIndex); } break; /* case vr::VREvent_ButtonTouch: { buttonPressed = true; } break; case vr::VREvent_ButtonUntouch: { buttonPressed = false; } break;*/ /*case vr::VREvent_ButtonPress: { m_bShowCubes = ~m_bShowCubes; }*/ } } void CMainApplication::HapticFeedback(){ HapticFeedback(firstdevice); HapticFeedback(seconddevice); } //----------------------------------------------------------------------------- // Purpose: Haptic feedback if controller near an atom //----------------------------------------------------------------------------- void CMainApplication::HapticFeedback(int device) { if (device!=-1) { vr::VRControllerState_t cs; vr::TrackedDevicePose_t dp; m_pHMD->GetControllerStateWithPose( vr::TrackingUniverseStanding, device, &cs, &dp ); if (dp.bPoseIsValid) { vr::HmdMatrix34_t mat=dp.mDeviceToAbsoluteTracking; Vector3 controllerPos(mat.m[0][3], mat.m[1][3],mat.m[2][3]); for (int i=0;iTriggerHapticPulse(device, 0, 3000); return; } } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMainApplication::RenderFrame() { // for now as fast as possible if ( m_pHMD ) { DrawControllers(); RenderStereoTargets(); RenderDistortion(); vr::Texture_t leftEyeTexture = {(void*)leftEyeDesc.m_nResolveTextureId, vr::API_OpenGL, vr::ColorSpace_Gamma }; vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTexture ); vr::Texture_t rightEyeTexture = {(void*)rightEyeDesc.m_nResolveTextureId, vr::API_OpenGL, vr::ColorSpace_Gamma }; vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTexture ); } if ( m_bVblank && m_bGlFinishHack ) { //$ HACKHACK. From gpuview profiling, it looks like there is a bug where two renders and a present // happen right before and after the vsync causing all kinds of jittering issues. This glFinish() // appears to clear that up. Temporary fix while I try to get nvidia to investigate this problem. // 1/29/2014 mikesart glFinish(); } // SwapWindow { SDL_GL_SwapWindow( m_pWindow ); } // Clear { // We want to make sure the glFinish waits for the entire present to complete, not just the submission // of the command. So, we do a clear here right here so the glFinish will wait fully for the swap. glClearColor(BACKGROUND[0], BACKGROUND[1], BACKGROUND[2], 1); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } // Flush and wait for swap. if ( m_bVblank ) { glFlush(); glFinish(); } // Spew out the controller and pose count whenever they change. if ( m_iTrackedControllerCount != m_iTrackedControllerCount_Last || m_iValidPoseCount != m_iValidPoseCount_Last ) { m_iValidPoseCount_Last = m_iValidPoseCount; m_iTrackedControllerCount_Last = m_iTrackedControllerCount; dprintf( "PoseCount:%d(%s) Controllers:%d\n", m_iValidPoseCount, m_strPoseClasses.c_str(), m_iTrackedControllerCount ); } UpdateHMDMatrixPose(); } //----------------------------------------------------------------------------- // Purpose: Creates all the shaders used by HelloVR SDL //----------------------------------------------------------------------------- bool CMainApplication::CreateAllShaders() { if (GL_NO_ERROR!=PrepareISOTransShader (&m_unSceneProgramID, &m_nSceneMatrixLocation, &m_unBlendingProgramID)) { dprintf( "Error Preparing Transparency shader\n" ); return false; } /*m_nBlendingIntLocation = glGetUniformLocation(m_unSceneProgramID, "blending"); if (m_nBlendingIntLocation == -1) { dprintf("Unable to find blending uniform in scene shader\n"); return false; }*/ m_unControllerTransformProgramID = CompileGLShader( "Controller", // vertex shader "#version 410\n" "uniform mat4 matrix;\n" "layout(location = 0) in vec4 position;\n" "layout(location = 1) in vec3 v3ColorIn;\n" "out vec4 v4Color;\n" "void main()\n" "{\n" " v4Color.xyz = v3ColorIn; v4Color.a = 1.0;\n" " gl_Position = matrix * position;\n" "}\n", // fragment shader "#version 410\n" "in vec4 v4Color;\n" "out vec4 outputColor;\n" "void main()\n" "{\n" " outputColor = v4Color;\n" "}\n" ); m_nControllerMatrixLocation = glGetUniformLocation( m_unControllerTransformProgramID, "matrix" ); if( m_nControllerMatrixLocation == -1 ) { dprintf( "Unable to find matrix uniform in controller shader\n" ); return false; } m_unRenderModelProgramID = CompileGLShader( "render model", // vertex shader "#version 410\n" "uniform mat4 matrix;\n" "layout(location = 0) in vec4 position;\n" "layout(location = 1) in vec3 v3NormalIn;\n" "layout(location = 2) in vec2 v2TexCoordsIn;\n" "out vec2 v2TexCoord;\n" "void main()\n" "{\n" " v2TexCoord = v2TexCoordsIn;\n" " gl_Position = matrix * vec4(position.xyz, 1);\n" "}\n", //fragment shader "#version 410 core\n" "uniform sampler2D diffuse;\n" "in vec2 v2TexCoord;\n" "out vec4 outputColor;\n" "void main()\n" "{\n" " outputColor = texture( diffuse, v2TexCoord);\n" "}\n" ); m_nRenderModelMatrixLocation = glGetUniformLocation( m_unRenderModelProgramID, "matrix" ); if( m_nRenderModelMatrixLocation == -1 ) { dprintf( "Unable to find matrix uniform in render model shader\n" ); return false; } if (!PrepareUnitCellAtomShader (&m_unAtomsProgramID, &m_unUnitCellProgramID, &m_unMarkerProgramID, &m_nAtomMatrixLocation, &m_nUnitCellMatrixLocation, &m_nUnitCellColourLocation, &m_nMarkerMatrixLocation)) return false; m_unLensProgramID = CompileGLShader( "Distortion", // vertex shader "#version 410 core\n" "layout(location = 0) in vec4 position;\n" "layout(location = 1) in vec2 v2UVredIn;\n" "layout(location = 2) in vec2 v2UVGreenIn;\n" "layout(location = 3) in vec2 v2UVblueIn;\n" "noperspective out vec2 v2UVred;\n" "noperspective out vec2 v2UVgreen;\n" "noperspective out vec2 v2UVblue;\n" "void main()\n" "{\n" " v2UVred = v2UVredIn;\n" " v2UVgreen = v2UVGreenIn;\n" " v2UVblue = v2UVblueIn;\n" " gl_Position = position;\n" "}\n", // fragment shader "#version 410 core\n" "uniform sampler2D mytexture;\n" "noperspective in vec2 v2UVred;\n" "noperspective in vec2 v2UVgreen;\n" "noperspective in vec2 v2UVblue;\n" "out vec4 outputColor;\n" "void main()\n" "{\n" " float fBoundsCheck = ( (dot( vec2( lessThan( v2UVgreen.xy, vec2(0.05, 0.05)) ), vec2(1.0, 1.0))+dot( vec2( greaterThan( v2UVgreen.xy, vec2( 0.95, 0.95)) ), vec2(1.0, 1.0))) );\n" " if( fBoundsCheck > 1.0 )\n" " { outputColor = vec4( 0, 0, 0, 1.0 ); }\n" " else\n" " {\n" " float red = texture(mytexture, v2UVred).x;\n" " float green = texture(mytexture, v2UVgreen).y;\n" " float blue = texture(mytexture, v2UVblue).z;\n" " outputColor = vec4( red, green, blue, 1.0 ); }\n" "}\n" ); return m_unSceneProgramID != 0 && m_unControllerTransformProgramID != 0 && m_unRenderModelProgramID != 0 && m_unLensProgramID != 0; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CMainApplication::SetupTexturemaps() { //rgh: textures: [0] White texture for textureless meshes // [1,2] Depth texture for depth peeling ping pong (needs to be initialized after SetupStereoRenderTargets) // [3..ZLAYERS+2] Colour textures for transparency //sdl_textures: 6 [0..5] a b c alpha beta gamma text for axis labels //std::string sExecutableDirectory = Path_StripFilename(Path_GetExecutablePath()); //std::string strFullPath = Path_MakeAbsolute("../cube_texture.png", sExecutableDirectory); m_iTexture = new GLuint[3+ZLAYERS+1]; // white, depth1, depth2, color[ZLAYERS], atomtexture glGenTextures(3+ZLAYERS+1, m_iTexture); //white unsigned char data2[4] = { 255, 255, 255, 255 }; //white texture for non-textured meshes glBindTexture(GL_TEXTURE_2D, m_iTexture[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); GLenum e; if ((e = glGetError()) != GL_NO_ERROR) dprintf("opengl error %d, SetupTextureMaps 1\n", e); e=atomTexture( m_iTexture[3+ZLAYERS]); glBindTexture( GL_TEXTURE_2D, 0 ); if ((e = glGetError()) != GL_NO_ERROR) dprintf("opengl error %d, SetupTextureMaps 2\n", e); //sdl text http://stackoverflow.com/questions/5289447/using-sdl-ttf-with-opengl/5289823#5289823 //http://stackoverflow.com/questions/28880562/rendering-text-with-sdl2-and-opengl //FIXME TODO /*int size=10; =TTF_OpenFont("", size); axisTextures=new SDL_Texture*[6]; const wchar_t axis[6]={'a', 'b', 'c', '\u03B1', '\u03B2', '\u03B3'}; for (int i=0;i<6;i++) { axisTextures[i]=TTF_RenderUTF8_Blended(); } */ return ( m_iTexture != 0 && e==GL_NO_ERROR); } bool CMainApplication::SetupDepthPeeling() { bool e; e=::SetupDepthPeeling(m_nRenderWidth, m_nRenderHeight, ZLAYERS, m_iTexture+1, &peelingFramebuffer); if (!e) dprintf("Errir setting up DepthPeeling\n"); return (e); } //----------------------------------------------------------------------------- // Purpose: Load the scene into OpenGL //----------------------------------------------------------------------------- void CMainApplication::SetupScene() { SetupIsosurfaces(); SetupAtoms(); delete[] clonedAtoms; clonedAtoms=0; SetupUnitCell(); SetupMarker(); } void CMainApplication::SetupMarker() { GLenum e; e=::SetupMarker(&m_unMarkerVAO, &m_glMarkerVertBuffer); } void CMainApplication::SetupUnitCell() { GLenum e; e=::SetupUnitCell(&m_unUnitCellVAO, &m_glUnitCellVertBuffer, &m_glUnitCellIndexBuffer); if (e!=GL_NO_ERROR) dprintf("opengl error %d, SetupUnitCell, l %d\n", e, __LINE__); } //----------------------------------------------------------------------------- // Purpose: Load the atoms into OpenGL //----------------------------------------------------------------------------- void CMainApplication::SetupAtoms() { GLenum e; e=::SetupAtoms(&m_unAtomVAO, &m_glAtomVertBuffer, &BondIndices); // GLuint *vao, *buffer, *index; // e=::SetupAtomsNoTess(&vao, &buffer, &index); if (e!=GL_NO_ERROR) dprintf("opengl error %d, SetupAtoms, l %d\n", e, __LINE__); } //----------------------------------------------------------------------------- // Purpose: Load the isosurfaces into OpenGL //----------------------------------------------------------------------------- void CMainApplication::SetupIsosurfaces() { if (!m_pHMD) return; //rgh: add scene loading here vertdataarray = new std::vector*[NUMLODS]; #ifndef INDICESGL32 vertindicesarray = new std::vector*[NUMLODS]; #else vertindicesarray = new std::vector*[NUMLODS]; #endif for (int i = 0; i < NUMLODS; i++) {//LODS 100%, 25%, 6%, 2% vertdataarray[i] = new std::vector[NUMPLY]; #ifndef INDICESGL32 vertindicesarray[i] = new std::vector[NUMPLY]; #else vertindicesarray[i] = new std::vector[NUMPLY]; #endif } Matrix4 matScale; matScale.scale(m_fScale, m_fScale, m_fScale); Matrix4 matTransform; /*matTransform.translate( -((float)m_iSceneVolumeWidth * m_fScaleSpacing) / 1.f, -((float)m_iSceneVolumeHeight * m_fScaleSpacing) / 1.f, -((float)m_iSceneVolumeDepth * m_fScaleSpacing) / 1.f);*/ matTransform.rotateX(-90); Matrix4 mat = matScale * matTransform; const char *lods[] = {""}; m_glSceneVertBuffer = new GLuint*[NUMLODS]; m_uiVertcount = new unsigned int*[NUMLODS]; m_unSceneVAO = new unsigned int*[NUMLODS]; m_unSceneVAOIndices = new unsigned int*[NUMLODS]; GLenum e; glClearColor(0,0,0, 1); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glUseProgram(m_unControllerTransformProgramID); float loadingmat[] = { 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, -1, -1, 0, 1 }; if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s\n", e, gluErrorString(e)); //glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_iTexture[1]); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s\n", e, gluErrorString(e)); glDisable(GL_CULL_FACE); float z = 0.0f; float points[] = {//pos [4], color [3] 0, 0, z, 1, 1,1,1, 0, 1, z, 1, 1, 1, 1, 1, 1, z, 1, 1, 1, 1, 1, 0, z, 1, 1, 1, 1, }; //http://stackoverflow.com/questions/21767467/glvertexattribpointer-raising-impossible-gl-invalid-operation GLuint myvao; glGenVertexArrays(1, &myvao); glBindVertexArray(myvao); GLuint testBuf; glGenBuffers(1, &testBuf); glBindBuffer(GL_ARRAY_BUFFER, testBuf); glBufferData(GL_ARRAY_BUFFER, 4 * 7 * sizeof(GLfloat), points, GL_STATIC_DRAW); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glDisableVertexAttribArray(2); glDisableVertexAttribArray(3); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(4 * sizeof(float))); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); GLuint iData[] = { 0, 1, 2, 2, 3, 0 }; GLuint indexBufferID; glGenBuffers(1, &indexBufferID); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(iData), iData, GL_STATIC_DRAW); for (int i = 0; i < NUMLODS; i++) { m_glSceneVertBuffer[i] = new GLuint[NUMPLY]; m_uiVertcount[i] = new unsigned int[NUMPLY]; m_unSceneVAO[i] = new unsigned int[NUMPLY]; m_unSceneVAOIndices[i] = new unsigned int[NUMPLY]; glGenBuffers(NUMPLY, m_glSceneVertBuffer[i]); glGenVertexArrays(NUMPLY, m_unSceneVAO[i]); if ((e = glGetError()) != GL_NO_ERROR) dprintf("opengl error %d, glGenVertexArrays\n", e); // Create and populate the index buffer glGenBuffers(NUMPLY, m_unSceneVAOIndices[i]); if ((e = glGetError()) != GL_NO_ERROR) dprintf("opengl error %d, glGenBuffers\n", e); } char tmpname[250]; for (int currentlod = 0; currentlod < NUMLODS; currentlod++) { int time = 1; for (int p = 0; p < NUMPLY; p++) { glBindVertexArray(myvao); if ((e = glGetError()) != GL_NO_ERROR) dprintf("opengl error %d, l %d\n", e, __LINE__); //loadingmat[0]=(float)currentlod/NUMLODS; //xscaling loadingmat[0]=2*(float)p/NUMPLY; //yscaling glUniformMatrix4fv(m_nControllerMatrixLocation, 1, GL_FALSE, loadingmat); if ((e = glGetError()) != GL_NO_ERROR) dprintf("opengl error %d, l %d\n", e, __LINE__); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); if ((e = glGetError()) != GL_NO_ERROR) dprintf("opengl error %d, l %d\n", e, __LINE__); SDL_GL_SwapWindow(m_pWindow); //http://stackoverflow.com/questions/9052224/error4error-c3861-snprintf-identifier-not-found sprintf(tmpname, "%s%s%d-%s.ply", PATH, lods[currentlod], time, plyfiles[p % ISOS]); vertdataarray[currentlod][p].clear(); vertindicesarray[currentlod][p].clear(); Matrix4 matFinal; //matFinal.translate(translations[p%ISOS][0]+cubetrans[0], translations[p%ISOS][1]+cubetrans[1], translations[p%ISOS][2]+cubetrans[2]); Matrix4 matcubetrans, mvs; if (voxelSize[0]!=-1) { mvs.scale(1.0 / (double)voxelSize[0], 1.0 / (double)voxelSize[1], 1.0 / (double)voxelSize[2]); matcubetrans.translate(cubetrans[0], cubetrans[1], cubetrans[2]); //angstrom //if abc, in abc coordinates /*Matrix4 abcm (abc[0][0], abc[1][0], abc[2][0], 0, abc[0][1], abc[1][1], abc[2][1], 0, abc[0][2], abc[1][2], abc[2][2], 0, 0, 0, 0, 1);*/ Matrix4 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); Matrix4 rot; rot.rotateX(-90); Matrix4 sc; sc.scale(supercell[0], supercell[1], supercell[2]); Matrix4 sctrans; sctrans.translate(-translations[p%ISOS][2], -translations[p%ISOS][1], -translations[p%ISOS][0]); matFinal = rot*abcm*sctrans*sc*mvs; } else { matFinal.translate(translations[p%ISOS][0], translations[p%ISOS][1], translations[p%ISOS][2]); matFinal=mat*matFinal; } if (!AddModelToScene(matFinal.get(), vertdataarray[currentlod][p], vertindicesarray[currentlod][p], tmpname, false, isocolours[p%ISOS][0]<0, p%ISOS)) { dprintf("Error loading ply file %s\n", tmpname); //m_bShowCubes = false; //return; } #ifndef INDICESGL32 if (vertdataarray[currentlod][p].size() > 65535 * numComponents) { dprintf("Mesh has more than 64k vertices (%d), unsupported\n", vertdataarray[currentlod][p].size() / numComponents); m_bShowCubes = false; return; } #endif m_uiVertcount[currentlod][p] = vertindicesarray[currentlod][p].size(); //rgh: now pos, normal, color if (GL_NO_ERROR!=PrepareGLiso(m_unSceneVAO[currentlod][p], m_glSceneVertBuffer[currentlod][p], vertdataarray[currentlod][p], m_unSceneVAOIndices[currentlod][p], vertindicesarray[currentlod][p])) eprintf ("PrepareGLiso, GL error"); //FIXME: after we go to 64 bits, keep the data in ram vertdataarray[currentlod][p].clear(); vertindicesarray[currentlod][p].clear(); vertdataarray[currentlod][p].resize(0); vertindicesarray[currentlod][p].resize(0); if (p % ISOS == ISOS - 1) time++; } delete[] vertdataarray[currentlod]; delete[] vertindicesarray[currentlod]; vertdataarray[currentlod] = nullptr; vertindicesarray[currentlod] = nullptr; } // for each lod //glEnable(GL_DEPTH_TEST); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glDeleteBuffers(1, &testBuf); glDeleteBuffers(1, &indexBufferID); glDeleteVertexArrays(1, &myvao); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glUseProgram(0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); } //----------------------------------------------------------------------------- // Purpose: Draw all of the controllers as X/Y/Z lines //----------------------------------------------------------------------------- void CMainApplication::DrawControllers() { //rgh: the format for the vertarray has changed, now xyz, nxnynz, rgba, uv. Cancel this function until needed. Needs to fix fill of points down return; // don't draw controllers if somebody else has input focus if( m_pHMD->IsInputFocusCapturedByAnotherProcess() ) return; std::vector vertdataarray; m_uiControllerVertcount = 0; m_iTrackedControllerCount = 0; for ( vr::TrackedDeviceIndex_t unTrackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; ++unTrackedDevice ) { if ( !m_pHMD->IsTrackedDeviceConnected( unTrackedDevice ) ) continue; if( m_pHMD->GetTrackedDeviceClass( unTrackedDevice ) != vr::TrackedDeviceClass_Controller ) continue; m_iTrackedControllerCount += 1; if( !m_rTrackedDevicePose[ unTrackedDevice ].bPoseIsValid ) continue; const Matrix4 & mat = m_rmat4DevicePose[unTrackedDevice]; Vector4 center = mat * Vector4( 0, 0, 0, 1 ); for ( int i = 0; i < 3; ++i ) { Vector3 color( 0, 0, 0 ); Vector4 point( 0, 0, 0, 1 ); point[i] += 0.05f; // offset in X, Y, Z color[i] = 1.0; // R, G, B point = mat * point; vertdataarray.push_back( center.x ); vertdataarray.push_back( center.y ); vertdataarray.push_back( center.z ); vertdataarray.push_back( color.x ); vertdataarray.push_back( color.y ); vertdataarray.push_back( color.z ); vertdataarray.push_back( point.x ); vertdataarray.push_back( point.y ); vertdataarray.push_back( point.z ); vertdataarray.push_back( color.x ); vertdataarray.push_back( color.y ); vertdataarray.push_back( color.z ); m_uiControllerVertcount += 2; } Vector4 start = mat * Vector4( 0, 0, -0.02f, 1 ); Vector4 end = mat * Vector4( 0, 0, -39.f, 1 ); Vector3 color( .92f, .92f, .71f ); vertdataarray.push_back( start.x );vertdataarray.push_back( start.y );vertdataarray.push_back( start.z ); vertdataarray.push_back( color.x );vertdataarray.push_back( color.y );vertdataarray.push_back( color.z ); vertdataarray.push_back( end.x );vertdataarray.push_back( end.y );vertdataarray.push_back( end.z ); vertdataarray.push_back( color.x );vertdataarray.push_back( color.y );vertdataarray.push_back( color.z ); m_uiControllerVertcount += 2; } // Setup the VAO the first time through. if ( m_unControllerVAO == 0 ) { glGenVertexArrays( 1, &m_unControllerVAO ); glBindVertexArray( m_unControllerVAO ); glGenBuffers( 1, &m_glControllerVertBuffer ); glBindBuffer( GL_ARRAY_BUFFER, m_glControllerVertBuffer ); GLuint stride = 2 * 3 * sizeof( float ); GLuint offset = 0; glEnableVertexAttribArray( 0 ); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset); offset += sizeof( Vector3 ); glEnableVertexAttribArray( 1 ); glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset); glBindVertexArray( 0 ); } glBindBuffer( GL_ARRAY_BUFFER, m_glControllerVertBuffer ); // set vertex data if we have some if( vertdataarray.size() > 0 ) { //$ TODO: Use glBufferSubData for this... glBufferData( GL_ARRAY_BUFFER, sizeof(float) * vertdataarray.size(), &vertdataarray[0], GL_STREAM_DRAW ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMainApplication::SetupCameras() { m_mat4ProjectionLeft = GetHMDMatrixProjectionEye( vr::Eye_Left ); m_mat4ProjectionRight = GetHMDMatrixProjectionEye( vr::Eye_Right ); m_mat4eyePosLeft = GetHMDMatrixPoseEye( vr::Eye_Left ); m_mat4eyePosRight = GetHMDMatrixPoseEye( vr::Eye_Right ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CMainApplication::CreateFrameBuffer( int nWidth, int nHeight, FramebufferDesc &framebufferDesc ) { glGenFramebuffers(1, &framebufferDesc.m_nRenderFramebufferId ); glBindFramebuffer(GL_FRAMEBUFFER, framebufferDesc.m_nRenderFramebufferId); glGenRenderbuffers(1, &framebufferDesc.m_nDepthBufferId); glBindRenderbuffer(GL_RENDERBUFFER, framebufferDesc.m_nDepthBufferId); glRenderbufferStorage/*Multisample*/(GL_RENDERBUFFER,/* 1, */GL_DEPTH_COMPONENT32, nWidth, nHeight ); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, framebufferDesc.m_nDepthBufferId ); glGenTextures(1, &framebufferDesc.m_nRenderTextureId ); glBindTexture(GL_TEXTURE_2D/*_MULTISAMPLE*/, framebufferDesc.m_nRenderTextureId ); //glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, nWidth, nHeight, true); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D/*_MULTISAMPLE*/, framebufferDesc.m_nRenderTextureId, 0); glGenFramebuffers(1, &framebufferDesc.m_nResolveFramebufferId ); glBindFramebuffer(GL_FRAMEBUFFER, framebufferDesc.m_nResolveFramebufferId); glGenTextures(1, &framebufferDesc.m_nResolveTextureId ); glBindTexture(GL_TEXTURE_2D, framebufferDesc.m_nResolveTextureId ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferDesc.m_nResolveTextureId, 0); // check FBO status GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { return false; } glBindFramebuffer( GL_FRAMEBUFFER, 0 ); return true; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CMainApplication::SetupStereoRenderTargets() { if ( !m_pHMD ) return false; m_pHMD->GetRecommendedRenderTargetSize( &m_nRenderWidth, &m_nRenderHeight ); CreateFrameBuffer( m_nRenderWidth, m_nRenderHeight, leftEyeDesc ); 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; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMainApplication::SetupDistortion() { if ( !m_pHMD ) return; GLushort m_iLensGridSegmentCountH = 43; GLushort m_iLensGridSegmentCountV = 43; float w = (float)( 1.0/float(m_iLensGridSegmentCountH-1)); float h = (float)( 1.0/float(m_iLensGridSegmentCountV-1)); float u, v = 0; std::vector vVerts(0); VertexDataLens vert; //left eye distortion verts float Xoffset = -1; for( int y=0; yComputeDistortion(vr::Eye_Left, u, v); vert.texCoordRed = Vector2(dc0.rfRed[0], 1 - dc0.rfRed[1]); vert.texCoordGreen = Vector2(dc0.rfGreen[0], 1 - dc0.rfGreen[1]); vert.texCoordBlue = Vector2(dc0.rfBlue[0], 1 - dc0.rfBlue[1]); vVerts.push_back( vert ); } } //right eye distortion verts Xoffset = 0; for( int y=0; yComputeDistortion( vr::Eye_Right, u, v ); vert.texCoordRed = Vector2(dc0.rfRed[0], 1 - dc0.rfRed[1]); vert.texCoordGreen = Vector2(dc0.rfGreen[0], 1 - dc0.rfGreen[1]); vert.texCoordBlue = Vector2(dc0.rfBlue[0], 1 - dc0.rfBlue[1]); vVerts.push_back( vert ); } } std::vector vIndices; GLushort a,b,c,d; GLushort offset = 0; for( GLushort y=0; y= 0; i--) { PaintGrid(nEye, i); } //for all isos in descending order if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after paintgrid: %d, %s\n", e, gluErrorString(e)); if (numAtoms!=0) { RenderAtoms(nEye); RenderUnitCell(nEye); } RenderAllTrackedRenderModels(nEye); } // for zl glBindFramebuffer(GL_FRAMEBUFFER, dfb); //now blend all together, back to front glDisable(GL_DEPTH_TEST); glUseProgram(m_unRenderModelProgramID); const float mat[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; glUniformMatrix4fv(m_nRenderModelMatrixLocation, 1, GL_FALSE, mat); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s\n", e, gluErrorString(e)); glBindTexture(GL_TEXTURE_2D, m_iTexture[1]); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s\n", e, gluErrorString(e)); glDisable(GL_CULL_FACE); float z = 0.0f; //(m_fNearClip + m_fFarClip) / 2.0f; const float points[] = { -1, -1, z, 1, 0, 0, -1, 0, 0, -1, 1, z, 1, 0, 0, -1, 0, 1, 1, 1, z, 1, 0, 0, -1, 1, 1, 1, -1, z, 1, 0, 0, -1, 1, 0, }; GLuint myvao; glGenVertexArrays(1, &myvao); glBindVertexArray(myvao); GLuint testBuf; glGenBuffers(1, &testBuf); glBindBuffer(GL_ARRAY_BUFFER, testBuf); glBufferData(GL_ARRAY_BUFFER, 4 * 9 * sizeof(GLfloat), points, GL_STATIC_DRAW); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glDisableVertexAttribArray(3); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)0); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); //<- fails ?! glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(4 * sizeof(float))); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(7 * sizeof(float))); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); GLuint iData[] = { 0, 1, 2, 2, 3, 0 }; GLuint indexBufferID; glGenBuffers(1, &indexBufferID); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(iData), iData, GL_STATIC_DRAW); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); BlendTextures(m_iTexture + 1, ZLAYERS); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); DeleteBlendingBuffers(&myvao, &testBuf, &indexBufferID); if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after zlayer: %d, %s, l %d\n", e, gluErrorString(e), __LINE__); glUseProgram(0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); } // if currentiso else { glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); if (numAtoms!=0) { RenderAtoms(nEye); RenderUnitCell(nEye); } CleanDepthTexture(); glBindTexture(GL_TEXTURE_2D, 0); glUseProgram(m_unSceneProgramID); PaintGrid(nEye, currentiso); RenderAllTrackedRenderModels(nEye); } //else currentiso =isos if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error after rendering: %d, %s\n", e, gluErrorString(e)); } //show cubes } void CMainApplication::RenderAllTrackedRenderModels(vr::Hmd_Eye nEye) { // ----- Render Model rendering ----- glUseProgram(m_unRenderModelProgramID); for (uint32_t unTrackedDevice = 0; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; unTrackedDevice++) { if (!m_rTrackedDeviceToRenderModel[unTrackedDevice] || !m_rbShowTrackedDevice[unTrackedDevice]) continue; const vr::TrackedDevicePose_t & pose = m_rTrackedDevicePose[unTrackedDevice]; const Matrix4 & matDeviceToTracking = m_rmat4DevicePose[unTrackedDevice]; Matrix4 matMVP = GetCurrentViewProjectionMatrix(nEye) * matDeviceToTracking; glUniformMatrix4fv(m_nRenderModelMatrixLocation, 1, GL_FALSE, matMVP.get()); m_rTrackedDeviceToRenderModel[unTrackedDevice]->Draw(); } GLuint e; if ((e = glGetError()) != GL_NO_ERROR) dprintf("Gl error marker 2: %d, %s\n", e, gluErrorString(e)); //glUseProgram(0); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMainApplication::RenderDistortion() { glDisable(GL_DEPTH_TEST); glViewport( 0, 0, m_nWindowWidth, m_nWindowHeight ); glBindVertexArray( m_unLensVAO ); glUseProgram( m_unLensProgramID ); //render left lens (first half of index array ) glBindTexture(GL_TEXTURE_2D, leftEyeDesc.m_nResolveTextureId ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glDrawElements( GL_TRIANGLES, m_uiIndexSize/2, GL_UNSIGNED_SHORT, 0 ); //render right lens (second half of index array ) glBindTexture(GL_TEXTURE_2D, rightEyeDesc.m_nResolveTextureId ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glDrawElements( GL_TRIANGLES, m_uiIndexSize/2, GL_UNSIGNED_SHORT, (const void *)(m_uiIndexSize) ); glBindVertexArray( 0 ); glUseProgram( 0 ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- Matrix4 CMainApplication::GetHMDMatrixProjectionEye( vr::Hmd_Eye nEye ) { if ( !m_pHMD ) return Matrix4(); vr::HmdMatrix44_t mat = m_pHMD->GetProjectionMatrix( nEye, m_fNearClip, m_fFarClip, vr::API_OpenGL); return Matrix4( mat.m[0][0], mat.m[1][0], mat.m[2][0], mat.m[3][0], mat.m[0][1], mat.m[1][1], mat.m[2][1], mat.m[3][1], mat.m[0][2], mat.m[1][2], mat.m[2][2], mat.m[3][2], mat.m[0][3], mat.m[1][3], mat.m[2][3], mat.m[3][3] ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- Matrix4 CMainApplication::GetHMDMatrixPoseEye( vr::Hmd_Eye nEye ) { if ( !m_pHMD ) return Matrix4(); vr::HmdMatrix34_t matEyeRight = m_pHMD->GetEyeToHeadTransform( nEye ); Matrix4 matrixObj( matEyeRight.m[0][0], matEyeRight.m[1][0], matEyeRight.m[2][0], 0.0, matEyeRight.m[0][1], matEyeRight.m[1][1], matEyeRight.m[2][1], 0.0, matEyeRight.m[0][2], matEyeRight.m[1][2], matEyeRight.m[2][2], 0.0, matEyeRight.m[0][3], matEyeRight.m[1][3], matEyeRight.m[2][3], 1.0f ); return matrixObj.invert(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- Matrix4 CMainApplication::GetCurrentViewMatrix( vr::Hmd_Eye nEye ) { Matrix4 matMV; if( nEye == vr::Eye_Left ) { matMV = m_mat4eyePosLeft * m_mat4HMDPose; } else if( nEye == vr::Eye_Right ) { matMV = m_mat4eyePosRight * m_mat4HMDPose; } return matMV; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- Matrix4 CMainApplication::GetCurrentViewProjectionMatrix( vr::Hmd_Eye nEye ) { Matrix4 matMVP; if( nEye == vr::Eye_Left ) { matMVP = m_mat4ProjectionLeft * m_mat4eyePosLeft * m_mat4HMDPose; } else if( nEye == vr::Eye_Right ) { matMVP = m_mat4ProjectionRight * m_mat4eyePosRight * m_mat4HMDPose; } return matMVP; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMainApplication::UpdateHMDMatrixPose() { if ( !m_pHMD ) return; vr::VRCompositor()->WaitGetPoses(m_rTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0 ); m_iValidPoseCount = 0; m_strPoseClasses = ""; for ( int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice ) { if ( m_rTrackedDevicePose[nDevice].bPoseIsValid ) { m_iValidPoseCount++; m_rmat4DevicePose[nDevice] = ConvertSteamVRMatrixToMatrix4( m_rTrackedDevicePose[nDevice].mDeviceToAbsoluteTracking ); if (m_rDevClassChar[nDevice]==0) { switch (m_pHMD->GetTrackedDeviceClass(nDevice)) { case vr::TrackedDeviceClass_Controller: m_rDevClassChar[nDevice] = 'C'; break; case vr::TrackedDeviceClass_HMD: m_rDevClassChar[nDevice] = 'H'; break; case vr::TrackedDeviceClass_Invalid: m_rDevClassChar[nDevice] = 'I'; break; case vr::TrackedDeviceClass_Other: m_rDevClassChar[nDevice] = 'O'; break; case vr::TrackedDeviceClass_TrackingReference: m_rDevClassChar[nDevice] = 'T'; break; default: m_rDevClassChar[nDevice] = '?'; break; } } m_strPoseClasses += m_rDevClassChar[nDevice]; } } if ( m_rTrackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid ) { m_mat4HMDPose = m_rmat4DevicePose[vr::k_unTrackedDeviceIndex_Hmd].invert(); } } //----------------------------------------------------------------------------- // Purpose: Finds a render model we've already loaded or loads a new one //----------------------------------------------------------------------------- CGLRenderModel *CMainApplication::FindOrLoadRenderModel( const char *pchRenderModelName ) { CGLRenderModel *pRenderModel = NULL; for( std::vector< CGLRenderModel * >::iterator i = m_vecRenderModels.begin(); i != m_vecRenderModels.end(); i++ ) { if( !stricmp( (*i)->GetName().c_str(), pchRenderModelName ) ) { pRenderModel = *i; break; } } //http://steamcommunity.com/app/358720/discussions/0/357284131801141236/ // load the model if we didn't find one if (!pRenderModel) { // Mesh laden vr::RenderModel_t *pModel = NULL; while (vr::VRRenderModels()->LoadRenderModel_Async(pchRenderModelName, &pModel) == vr::VRRenderModelError_Loading) { //std::this_thread::sleep_for(std::chrono::milliseconds(50)); Sleep(50); } if (vr::VRRenderModels()->LoadRenderModel_Async(pchRenderModelName, &pModel) || pModel == NULL) { dprintf(" Unable to load render model %s\n", pchRenderModelName); return NULL; // move on to the next tracked device } vr::RenderModel_TextureMap_t *pTexture = NULL; while (vr::VRRenderModels()->LoadTexture_Async(pModel->diffuseTextureId, &pTexture) == vr::VRRenderModelError_Loading) { //std::this_thread::sleep_for(std::chrono::milliseconds(50)); Sleep(50); } if (vr::VRRenderModels()->LoadTexture_Async(pModel->diffuseTextureId, &pTexture) || pTexture == NULL) { dprintf("Unable to load render texture id:%d for render model %s\n", pModel->diffuseTextureId, pchRenderModelName); vr::VRRenderModels()->FreeRenderModel(pModel); return NULL; // move on to the next tracked device } pRenderModel = new CGLRenderModel( pchRenderModelName ); if ( !pRenderModel->BInit( *pModel, *pTexture ) ) { dprintf( "Unable to create GL model from render model %s\n", pchRenderModelName ); delete pRenderModel; pRenderModel = NULL; } else { m_vecRenderModels.push_back( pRenderModel ); } vr::VRRenderModels()->FreeRenderModel( pModel ); vr::VRRenderModels()->FreeTexture( pTexture ); } return pRenderModel; } //----------------------------------------------------------------------------- // Purpose: Create/destroy GL a Render Model for a single tracked device //----------------------------------------------------------------------------- void CMainApplication::SetupRenderModelForTrackedDevice( vr::TrackedDeviceIndex_t unTrackedDeviceIndex ) { if( unTrackedDeviceIndex >= vr::k_unMaxTrackedDeviceCount ) return; // try to find a model we've already set up std::string sRenderModelName = GetTrackedDeviceString( m_pHMD, unTrackedDeviceIndex, vr::Prop_RenderModelName_String ); CGLRenderModel *pRenderModel = FindOrLoadRenderModel( sRenderModelName.c_str() ); if( !pRenderModel ) { std::string sTrackingSystemName = GetTrackedDeviceString( m_pHMD, unTrackedDeviceIndex, vr::Prop_TrackingSystemName_String ); dprintf( "Unable to load render model for tracked device %d (%s.%s)\n", unTrackedDeviceIndex, sTrackingSystemName.c_str(), sRenderModelName.c_str() ); } else { m_rTrackedDeviceToRenderModel[ unTrackedDeviceIndex ] = pRenderModel; m_rbShowTrackedDevice[ unTrackedDeviceIndex ] = true; } } //----------------------------------------------------------------------------- // Purpose: Create/destroy GL Render Models //----------------------------------------------------------------------------- void CMainApplication::SetupRenderModels() { memset( m_rTrackedDeviceToRenderModel, 0, sizeof( m_rTrackedDeviceToRenderModel ) ); if( !m_pHMD ) return; for( uint32_t unTrackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; unTrackedDevice++ ) { if( !m_pHMD->IsTrackedDeviceConnected( unTrackedDevice ) ) continue; SetupRenderModelForTrackedDevice( unTrackedDevice ); } } //----------------------------------------------------------------------------- // Purpose: Converts a SteamVR matrix to our local matrix class //----------------------------------------------------------------------------- Matrix4 CMainApplication::ConvertSteamVRMatrixToMatrix4( const vr::HmdMatrix34_t &matPose ) { Matrix4 matrixObj( matPose.m[0][0], matPose.m[1][0], matPose.m[2][0], 0.0, matPose.m[0][1], matPose.m[1][1], matPose.m[2][1], 0.0, matPose.m[0][2], matPose.m[1][2], matPose.m[2][2], 0.0, matPose.m[0][3], matPose.m[1][3], matPose.m[2][3], 1.0f ); return matrixObj; } //----------------------------------------------------------------------------- // Purpose: Create/destroy GL Render Models //----------------------------------------------------------------------------- CGLRenderModel::CGLRenderModel( const std::string & sRenderModelName ) : m_sModelName( sRenderModelName ) { m_glIndexBuffer = 0; m_glVertArray = 0; m_glVertBuffer = 0; m_glTexture = 0; } CGLRenderModel::~CGLRenderModel() { Cleanup(); } //----------------------------------------------------------------------------- // Purpose: Allocates and populates the GL resources for a render model //----------------------------------------------------------------------------- bool CGLRenderModel::BInit( const vr::RenderModel_t & vrModel, const vr::RenderModel_TextureMap_t & vrDiffuseTexture ) { // create and bind a VAO to hold state for this model glGenVertexArrays( 1, &m_glVertArray ); glBindVertexArray( m_glVertArray ); // Populate a vertex buffer glGenBuffers( 1, &m_glVertBuffer ); glBindBuffer( GL_ARRAY_BUFFER, m_glVertBuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof( vr::RenderModel_Vertex_t ) * vrModel.unVertexCount, vrModel.rVertexData, GL_STATIC_DRAW ); // Identify the components in the vertex buffer glEnableVertexAttribArray( 0 ); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( vr::RenderModel_Vertex_t ), (void *)offsetof( vr::RenderModel_Vertex_t, vPosition ) ); glEnableVertexAttribArray( 1 ); glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof( vr::RenderModel_Vertex_t ), (void *)offsetof( vr::RenderModel_Vertex_t, vNormal ) ); glEnableVertexAttribArray( 2 ); glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, sizeof( vr::RenderModel_Vertex_t ), (void *)offsetof( vr::RenderModel_Vertex_t, rfTextureCoord ) ); // Create and populate the index buffer glGenBuffers( 1, &m_glIndexBuffer ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_glIndexBuffer ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( uint16_t ) * vrModel.unTriangleCount * 3, vrModel.rIndexData, GL_STATIC_DRAW ); glBindVertexArray( 0 ); // create and populate the texture glGenTextures(1, &m_glTexture ); glBindTexture( GL_TEXTURE_2D, m_glTexture ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, vrDiffuseTexture.unWidth, vrDiffuseTexture.unHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, vrDiffuseTexture.rubTextureMapData ); // If this renders black ask McJohn what's wrong. glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); GLfloat fLargest; glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest ); glBindTexture( GL_TEXTURE_2D, 0 ); m_unVertexCount = vrModel.unTriangleCount * 3; return true; } //----------------------------------------------------------------------------- // Purpose: Frees the GL resources for a render model //----------------------------------------------------------------------------- void CGLRenderModel::Cleanup() { if( m_glVertBuffer ) { glDeleteBuffers(1, &m_glIndexBuffer); glDeleteBuffers(1, &m_glVertArray); glDeleteBuffers(1, &m_glVertBuffer); m_glIndexBuffer = 0; m_glVertArray = 0; m_glVertBuffer = 0; } } //----------------------------------------------------------------------------- // Purpose: Draws the render model //----------------------------------------------------------------------------- void CGLRenderModel::Draw() { glBindVertexArray( m_glVertArray ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, m_glTexture ); glDrawElements( GL_TRIANGLES, m_unVertexCount, GL_UNSIGNED_SHORT, 0 ); glBindVertexArray( 0 ); } void cleanConfig() { for (int i = 0; i < ISOS; i++) { delete[] isocolours[i]; delete[] translations[i]; } delete[] isocolours; delete[] translations; if (plyfiles) { for (int i=0;i\n", argv[0]); MessageBoxA(0, MainErrors[1], nullptr, 0); return -1; } { //change cwd so that relative paths work std::string s(argv[1]); SetCurrentDirectoryA(s.substr(0, s.find_last_of("\\/")).c_str()); } int r; if ((r=loadConfigFile(argv[1]))<0) { if (-100BInit()) { pMainApplication->Shutdown(); MessageBoxA(0, MainErrors[3], nullptr, 0); return -3; } pMainApplication->RunMainLoop(); pMainApplication->Shutdown(); delete pMainApplication; cleanConfig(); _CrtDumpMemoryLeaks(); return 0; }