您的位置:首页 > 编程语言

(三)代码b.0:hellovr_opengl

2018-03-29 10:49 966 查看
    我主要也是看了各个主要函数调用关系,特别是和显示有关的,因为改代码基本就是在这些地方该。    https://github.com/ValveSoftware/openvr/blob/master/samples/hellovr_opengl/hellovr_opengl_main.cpp
//========= Copyright Valve Corporation ============//

#include <SDL.h>

#include <GL/glew.h>

#include <SDL_opengl.h>

#if defined( OSX )

#include <Foundation/Foundation.h>

#include <AppKit/AppKit.h>

#include <OpenGL/glu.h>

// Apple's version of glut.h #undef's APIENTRY, redefine it

#define APIENTRY

#else

#include <GL/glu.h>

#endif

#include <stdio.h>

#include <string>

#include <cstdlib>

#include <openvr.h>

#include "shared/lodepng.h"

#include "shared/Matrices.h"

#include "shared/pathtools.h"

#if defined(POSIX)

#include "unistd.h"

#endif

#ifndef _WIN32

#define APIENTRY

#endif

#ifndef _countof

#define _countof(x) (sizeof(x)/sizeof((x)[0]))

#endif

void ThreadSleep( unsigned long nMilliseconds )

{

#if defined(_WIN32)

::Sleep( nMilliseconds );

#elif defined(POSIX)

usleep( nMilliseconds * 1000 );

#endif

}

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();

bool SetupTexturemaps();

void SetupScene();

void AddCubeToScene( Matrix4 mat, std::vector<float> &vertdata );

void AddCubeVertex( float fl0, float fl1, float fl2, float fl3, float fl4, std::vector<float> &vertdata );

void RenderControllerAxes();

bool SetupStereoRenderTargets();

void SetupCompanionWindow();

void SetupCameras();

void RenderStereoTargets();

void RenderCompanionWindow();

void RenderScene( vr::Hmd_Eye nEye );

Matrix4 GetHMDMatrixProjectionEye( vr::Hmd_Eye nEye );

Matrix4 GetHMDMatrixPoseEye( vr::Hmd_Eye nEye );

Matrix4 GetCurrentViewProjectionMatrix( vr::Hmd_Eye nEye );

void UpdateHMDMatrixPose();

Matrix4 ConvertSteamVRMatrixToMatrix4( const vr::HmdMatrix34_t &matPose );

GLuint CompileGLShader( const char *pchShaderName, const char *pchVertexShader, const char *pchFragmentShader );

bool CreateAllShaders();

void SetupRenderModelForTrackedDevice( vr::TrackedDeviceIndex_t unTrackedDeviceIndex );

CGLRenderModel *FindOrLoadRenderModel( const char *pchRenderModelName );

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 ];

private: // SDL bookkeeping

SDL_Window *m_pCompanionWindow;

uint32_t m_nCompanionWindowWidth;

uint32_t m_nCompanionWindowHeight;

SDL_GLContext m_pContext;

private: // OpenGL bookkeeping

int m_iTrackedControllerCount;

int m_iTrackedControllerCount_Last;

int m_iValidPoseCount;

int m_iValidPoseCount_Last;

bool m_bShowCubes;

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;

GLuint m_iTexture;

unsigned int m_uiVertcount;

GLuint m_glSceneVertBuffer;

GLuint m_unSceneVAO;

GLuint m_unCompanionWindowVAO;

GLuint m_glCompanionWindowIDVertBuffer;

GLuint m_glCompanionWindowIDIndexBuffer;

unsigned int m_uiCompanionWindowIndexSize;

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;

struct VertexDataScene

{

Vector3 position;

Vector2 texCoord;

};

struct VertexDataWindow

{

Vector2 position;

Vector2 texCoord;

VertexDataWindow( const Vector2 & pos, const Vector2 tex ) :  position(pos), texCoord(tex) {	}

};

GLuint m_unSceneProgramID;

GLuint m_unCompanionWindowProgramID;

GLuint m_unControllerTransformProgramID;

GLuint m_unRenderModelProgramID;

GLint m_nSceneMatrixLocation;

GLint m_nControllerMatrixLocation;

GLint m_nRenderModelMatrixLocation;

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

uint32_t m_nRenderWidth;

uint32_t m_nRenderHeight;

std::vector< CGLRenderModel * > m_vecRenderModels;

CGLRenderModel *m_rTrackedDeviceToRenderModel[ vr::k_unMaxTrackedDeviceCount ];

};

//-----------------------------------------------------------------------------

// Purpose: Outputs a set of optional arguments to debugging output, using

//          the printf format setting specified in fmt*.

//-----------------------------------------------------------------------------

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

}

//-----------------------------------------------------------------------------

// Purpose: Constructor

//-----------------------------------------------------------------------------

CMainApplication::CMainApplication( int argc, char *argv[] )

: m_pCompanionWindow(NULL)

, m_pContext(NULL)

, m_nCompanionWindowWidth( 640 )

, m_nCompanionWindowHeight( 320 )

, m_unSceneProgramID( 0 )

, m_unCompanionWindowProgramID( 0 )

, m_unControllerTransformProgramID( 0 )

, m_unRenderModelProgramID( 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_unSceneVAO( 0 )

, m_nSceneMatrixLocation( -1 )

, m_nControllerMatrixLocation( -1 )

, m_nRenderModelMatrixLocation( -1 )

, m_iTrackedControllerCount( 0 )

, m_iTrackedControllerCount_Last( -1 )

, m_iValidPoseCount( 0 )

, m_iValidPoseCount_Last( -1 )

, m_iSceneVolumeInit( 20 )

, m_strPoseClasses("")

, m_bShowCubes( 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 cou
168b7
ld 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 = 700;

int nWindowPosY = 100;

Uint32 unWindowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;

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_pCompanionWindow = SDL_CreateWindow( "hellovr", nWindowPosX, nWindowPosY, m_nCompanionWindowWidth, m_nCompanionWindowHeight, unWindowFlags );

if (m_pCompanionWindow == NULL)

{

printf( "%s - Window could not be created! SDL Error: %s\n", __FUNCTION__, SDL_GetError() );

return false;

}

m_pContext = SDL_GL_CreateContext(m_pCompanionWindow);

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 = "hellovr - " + m_strDriver + " " + m_strDisplay;

SDL_SetWindowTitle( m_pCompanionWindow, strWindowTitle.c_str() );

// cube array

m_iSceneVolumeWidth = m_iSceneVolumeInit;

m_iSceneVolumeHeight = m_iSceneVolumeInit;

m_iSceneVolumeDepth = m_iSceneVolumeInit;

m_fScale = 0.3f;

m_fScaleSpacing = 4.0f;

m_fNearClip = 0.1f;

m_fFarClip = 30.0f;

m_iTexture = 0;

m_uiVertcount = 0;

// 		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: Outputs the string in message to debugging output.

//          All other parameters are ignored.

//          Does not return any meaningful value or reference.

//-----------------------------------------------------------------------------

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: Initialize OpenGL. Returns true if OpenGL has been successfully

//          initialized, false if shaders could not be created.

//          If failure occurred in a module other than shaders, the function

//          may return true or throw an error.

//-----------------------------------------------------------------------------

bool CMainApplication::BInitGL()

{

if( m_bDebugOpenGL )

{

glDebugMessageCallback( (GLDEBUGPROC)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;

SetupTexturemaps();

SetupScene();

SetupCameras();

SetupStereoRenderTargets();

SetupCompanionWindow();

SetupRenderModels();

return true;

}

//-----------------------------------------------------------------------------

// Purpose: Initialize Compositor. Returns true if the compositor was

//          successfully initialized, false otherwise.

//-----------------------------------------------------------------------------

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;

}

//-----------------------------------------------------------------------------

// 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( m_pContext )

{

if( m_bDebugOpenGL )

{

glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE );

glDebugMessageCallback(nullptr, nullptr);

}

glDeleteBuffers(1, &m_glSceneVertBuffer);

if ( m_unSceneProgramID )

{

glDeleteProgram( m_unSceneProgramID );

}

if ( m_unControllerTransformProgramID )

{

glDeleteProgram( m_unControllerTransformProgramID );

}

if ( m_unRenderModelProgramID )

{

glDeleteProgram( m_unRenderModelProgramID );

}

if ( m_unCompanionWindowProgramID )

{

glDeleteProgram( m_unCompanionWindowProgramID );

}

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_unCompanionWindowVAO != 0 )

{

glDeleteVertexArrays( 1, &m_unCompanionWindowVAO );

}

if( m_unSceneVAO != 0 )

{

glDeleteVertexArrays( 1, &m_unSceneVAO );

}

if( m_unControllerVAO != 0 )

{

glDeleteVertexArrays( 1, &m_unControllerVAO );

}

}

if( m_pCompanionWindow )

{

SDL_DestroyWindow(m_pCompanionWindow);

m_pCompanionWindow = NULL;

}

SDL_Quit();

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

bool CMainApplication::HandleInput()

{

SDL_Event sdlEvent;

bool bRet = false;

while ( SDL_PollEvent( &sdlEvent ) != 0 )

{

if ( sdlEvent.type == SDL_QUIT )

{

bRet = true;

}

else if ( sdlEvent.type == SDL_KEYDOWN )

{

if ( sdlEvent.key.keysym.sym == SDLK_ESCAPE

|| sdlEvent.key.keysym.sym == SDLK_q )

{

bRet = true;

}

if( sdlEvent.key.keysym.sym == SDLK_c )

{

m_bShowCubes = !m_bShowCubes;

}

}

}

// 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, sizeof(state) ) )

{

m_rbShowTrackedDevice[ unDevice ] = state.ulButtonPressed == 0;

}

}

return bRet;

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

void CMainApplication::RunMainLoop()

{

bool bQuit = false;

SDL_StartTextInput();

SDL_ShowCursor( SDL_DISABLE );

while ( !bQuit )

{

bQuit = HandleInput();

RenderFrame();

}

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;

}

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

void CMainApplication::RenderFrame()

{

// for now as fast as possible

if ( m_pHMD )

{

RenderControllerAxes();

RenderStereoTargets();

RenderCompanionWindow();

vr::Texture_t leftEyeTexture = {(void*)(uintptr_t)leftEyeDesc.m_nResolveTextureId, vr::TextureType_OpenGL, vr::ColorSpace_Gamma };

vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTexture );

vr::Texture_t rightEyeTexture = {(void*)(uintptr_t)rightEyeDesc.m_nResolveTextureId, vr::TextureType_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_pCompanionWindow );

}

// 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( 0, 0, 0, 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: Compiles a GL shader program and returns the handle. Returns 0 if

//			the shader couldn't be compiled for some reason.

//-----------------------------------------------------------------------------

GLuint CMainApplication::CompileGLShader( const char *pchShaderName, const char *pchVertexShader, const char *pchFragmentShader )

{

GLuint unProgramID = glCreateProgram();

GLuint nSceneVertexShader = glCreateShader(GL_VERTEX_SHADER);

glShaderSource( nSceneVertexShader, 1, &pchVertexShader, NULL);

glCompileShader( nSceneVertexShader );

GLint vShaderCompiled = GL_FALSE;

glGetShaderiv( nSceneVertexShader, GL_COMPILE_STATUS, &vShaderCompiled);

if ( vShaderCompiled != GL_TRUE)

{

dprintf("%s - Unable to compile vertex shader %d!\n", pchShaderName, nSceneVertexShader);

glDeleteProgram( unProgramID );

glDeleteShader( nSceneVertexShader );

return 0;

}

glAttachShader( unProgramID, nSceneVertexShader);

glDeleteShader( nSceneVertexShader ); // the program hangs onto this once it's attached

GLuint  nSceneFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

glShaderSource( nSceneFragmentShader, 1, &pchFragmentShader, NULL);

glCompileShader( nSceneFragmentShader );

GLint fShaderCompiled = GL_FALSE;

glGetShaderiv( nSceneFragmentShader, GL_COMPILE_STATUS, &fShaderCompiled);

if (fShaderCompiled != GL_TRUE)

{

dprintf("%s - Unable to compile fragment shader %d!\n", pchShaderName, nSceneFragmentShader );

glDeleteProgram( unProgramID );

glDeleteShader( nSceneFragmentShader );

return 0;

}

glAttachShader( unProgramID, nSceneFragmentShader );

glDeleteShader( nSceneFragmentShader ); // the program hangs onto this once it's attached

glLinkProgram( unProgramID );

GLint programSuccess = GL_TRUE;

glGetProgramiv( unProgramID, GL_LINK_STATUS, &programSuccess);

if ( programSuccess != GL_TRUE )

{

dprintf("%s - Error linking program %d!\n", pchShaderName, unProgramID);

glDeleteProgram( unProgramID );

return 0;

}

glUseProgram( unProgramID );

glUseProgram( 0 );

return unProgramID;

}

//-----------------------------------------------------------------------------

// Purpose: Creates all the shaders used by HelloVR SDL

//-----------------------------------------------------------------------------

bool CMainApplication::CreateAllShaders()

{

m_unSceneProgramID = CompileGLShader(

"Scene",

// Vertex Shader

"#version 410\n"

"uniform mat4 matrix;\n"

"layout(location = 0) in vec4 position;\n"

"layout(location = 1) in vec2 v2UVcoordsIn;\n"

"layout(location = 2) in vec3 v3NormalIn;\n"

"out vec2 v2UVcoords;\n"

"void main()\n"

"{\n"

"	v2UVcoords = v2UVcoordsIn;\n"

"	gl_Position = matrix * position;\n"

"}\n",

// Fragment Shader

"#version 410 core\n"

"uniform sampler2D mytexture;\n"

"in vec2 v2UVcoords;\n"

"out vec4 outputColor;\n"

"void main()\n"

"{\n"

"   outputColor = texture(mytexture, v2UVcoords);\n"

"}\n"

);

m_nSceneMatrixLocation = glGetUniformLocation( m_unSceneProgramID, "matrix" );

if( m_nSceneMatrixLocation == -1 )

{

dprintf( "Unable to find matrix 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;

}

m_unCompanionWindowProgramID = CompileGLShader(

"CompanionWindow",

// vertex shader

"#version 410 core\n"

"layout(location = 0) in vec4 position;\n"

"layout(location = 1) in vec2 v2UVIn;\n"

"noperspective out vec2 v2UV;\n"

"void main()\n"

"{\n"

"	v2UV = v2UVIn;\n"

"	gl_Position = position;\n"

"}\n",

// fragment shader

"#version 410 core\n"

"uniform sampler2D mytexture;\n"

"noperspective in vec2 v2UV;\n"

"out vec4 outputColor;\n"

"void main()\n"

"{\n"

"		outputColor = texture(mytexture, v2UV);\n"

"}\n"

);

return m_unSceneProgramID != 0

&& m_unControllerTransformProgramID != 0

&& m_unRenderModelProgramID != 0

&& m_unCompanionWindowProgramID != 0;

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

bool CMainApplication::SetupTexturemaps()

{

std::string sExecutableDirectory = Path_StripFilename( Path_GetExecutablePath() );

std::string strFullPath = Path_MakeAbsolute( "../cube_texture.png", sExecutableDirectory );

std::vector<unsigned char> imageRGBA;

unsigned nImageWidth, nImageHeight;

unsigned nError = lodepng::decode( imageRGBA, nImageWidth, nImageHeight, strFullPath.c_str() );

if ( nError != 0 )

return false;

glGenTextures(1, &m_iTexture );

glBindTexture( GL_TEXTURE_2D, m_iTexture );

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nImageWidth, nImageHeight,

0, GL_RGBA, GL_UNSIGNED_BYTE, &imageRGBA[0] );

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

return ( m_iTexture != 0 );

}

//-----------------------------------------------------------------------------

// Purpose: create a sea of cubes

//-----------------------------------------------------------------------------

void CMainApplication::SetupScene()

{

if ( !m_pHMD )

return;

std::vector<float> vertdataarray;

Matrix4 matScale;

matScale.scale( m_fScale, m_fScale, m_fScale );

Matrix4 matTransform;

matTransform.translate(

-( (float)m_iSceneVolumeWidth * m_fScaleSpacing ) / 2.f,

-( (float)m_iSceneVolumeHeight * m_fScaleSpacing ) / 2.f,

-( (float)m_iSceneVolumeDepth * m_fScaleSpacing ) / 2.f);

Matrix4 mat = matScale * matTransform;

for( int z = 0; z< m_iSceneVolumeDepth; z++ )

{

for( int y = 0; y< m_iSceneVolumeHeight; y++ )

{

for( int x = 0; x< m_iSceneVolumeWidth; x++ )

{

AddCubeToScene( mat, vertdataarray );

mat = mat * Matrix4().translate( m_fScaleSpacing, 0, 0 );

}

mat = mat * Matrix4().translate( -((float)m_iSceneVolumeWidth) * m_fScaleSpacing, m_fScaleSpacing, 0 );

}

mat = mat * Matrix4().translate( 0, -((float)m_iSceneVolumeHeight) * m_fScaleSpacing, m_fScaleSpacing );

}

m_uiVertcount = vertdataarray.size()/5;

glGenVertexArrays( 1, &m_unSceneVAO );

glBindVertexArray( m_unSceneVAO );

glGenBuffers( 1, &m_glSceneVertBuffer );

glBindBuffer( GL_ARRAY_BUFFER, m_glSceneVertBuffer );

glBufferData( GL_ARRAY_BUFFER, sizeof(float) * vertdataarray.size(), &vertdataarray[0], GL_STATIC_DRAW);

GLsizei stride = sizeof(VertexDataScene);

uintptr_t offset = 0;

glEnableVertexAttribArray( 0 );

glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride , (const void *)offset);

offset += sizeof(Vector3);

glEnableVertexAttribArray( 1 );

glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, stride, (const void *)offset);

glBindVertexArray( 0 );

glDisableVertexAttribArray(0);

glDisableVertexAttribArray(1);

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

void CMainApplication::AddCubeVertex( float fl0, float fl1, float fl2, float fl3, float fl4, std::vector<float> &vertdata )

{

vertdata.push_back( fl0 );

vertdata.push_back( fl1 );

vertdata.push_back( fl2 );

vertdata.push_back( fl3 );

vertdata.push_back( fl4 );

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

void CMainApplication::AddCubeToScene( Matrix4 mat, std::vector<float> &vertdata )

{

// Matrix4 mat( outermat.data() );

Vector4 A = mat * Vector4( 0, 0, 0, 1 );

Vector4 B = mat * Vector4( 1, 0, 0, 1 );

Vector4 C = mat * Vector4( 1, 1, 0, 1 );

Vector4 D = mat * Vector4( 0, 1, 0, 1 );

Vector4 E = mat * Vector4( 0, 0, 1, 1 );

Vector4 F = mat * Vector4( 1, 0, 1, 1 );

Vector4 G = mat * Vector4( 1, 1, 1, 1 );

Vector4 H = mat * Vector4( 0, 1, 1, 1 );

// triangles instead of quads

AddCubeVertex( E.x, E.y, E.z, 0, 1, vertdata ); //Front

AddCubeVertex( F.x, F.y, F.z, 1, 1, vertdata );

AddCubeVertex( G.x, G.y, G.z, 1, 0, vertdata );

AddCubeVertex( G.x, G.y, G.z, 1, 0, vertdata );

AddCubeVertex( H.x, H.y, H.z, 0, 0, vertdata );

AddCubeVertex( E.x, E.y, E.z, 0, 1, vertdata );

AddCubeVertex( B.x, B.y, B.z, 0, 1, vertdata ); //Back

AddCubeVertex( A.x, A.y, A.z, 1, 1, vertdata );

AddCubeVertex( D.x, D.y, D.z, 1, 0, vertdata );

AddCubeVertex( D.x, D.y, D.z, 1, 0, vertdata );

AddCubeVertex( C.x, C.y, C.z, 0, 0, vertdata );

AddCubeVertex( B.x, B.y, B.z, 0, 1, vertdata );

AddCubeVertex( H.x, H.y, H.z, 0, 1, vertdata ); //Top

AddCubeVertex( G.x, G.y, G.z, 1, 1, vertdata );

AddCubeVertex( C.x, C.y, C.z, 1, 0, vertdata );

AddCubeVertex( C.x, C.y, C.z, 1, 0, vertdata );

AddCubeVertex( D.x, D.y, D.z, 0, 0, vertdata );

AddCubeVertex( H.x, H.y, H.z, 0, 1, vertdata );

AddCubeVertex( A.x, A.y, A.z, 0, 1, vertdata ); //Bottom

AddCubeVertex( B.x, B.y, B.z, 1, 1, vertdata );

AddCubeVertex( F.x, F.y, F.z, 1, 0, vertdata );

AddCubeVertex( F.x, F.y, F.z, 1, 0, vertdata );

AddCubeVertex( E.x, E.y, E.z, 0, 0, vertdata );

AddCubeVertex( A.x, A.y, A.z, 0, 1, vertdata );

AddCubeVertex( A.x, A.y, A.z, 0, 1, vertdata ); //Left

AddCubeVertex( E.x, E.y, E.z, 1, 1, vertdata );

AddCubeVertex( H.x, H.y, H.z, 1, 0, vertdata );

AddCubeVertex( H.x, H.y, H.z, 1, 0, vertdata );

AddCubeVertex( D.x, D.y, D.z, 0, 0, vertdata );

AddCubeVertex( A.x, A.y, A.z, 0, 1, vertdata );

AddCubeVertex( F.x, F.y, F.z, 0, 1, vertdata ); //Right

AddCubeVertex( B.x, B.y, B.z, 1, 1, vertdata );

AddCubeVertex( C.x, C.y, C.z, 1, 0, vertdata );

AddCubeVertex( C.x, C.y, C.z, 1, 0, vertdata );

AddCubeVertex( G.x, G.y, G.z, 0, 0, vertdata );

AddCubeVertex( F.x, F.y, F.z, 0, 1, vertdata );

}

//-----------------------------------------------------------------------------

// Purpose: Draw all of the controllers as X/Y/Z lines

//-----------------------------------------------------------------------------

void CMainApplication::RenderControllerAxes()

{

// Don't attempt to update controllers if input is not available

if( !m_pHMD->IsInputAvailable() )

return;

std::vector<float> 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 );

uintptr_t 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: Creates a frame buffer. Returns true if the buffer was set up.

//          Returns false if the setup failed.

//-----------------------------------------------------------------------------

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

glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT, 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, 4, GL_RGBA8, nWidth, nHeight, true);

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

return true;

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

void CMainApplication::SetupCompanionWindow()

{

if ( !m_pHMD )

return;

std::vector<VertexDataWindow> vVerts;

// left eye verts

vVerts.push_back( VertexDataWindow( Vector2(-1, -1), Vector2(0, 1)) );

vVerts.push_back( VertexDataWindow( Vector2(0, -1), Vector2(1, 1)) );

vVerts.push_back( VertexDataWindow( Vector2(-1, 1), Vector2(0, 0)) );

vVerts.push_back( VertexDataWindow( Vector2(0, 1), Vector2(1, 0)) );

// right eye verts

vVerts.push_back( VertexDataWindow( Vector2(0, -1), Vector2(0, 1)) );

vVerts.push_back( VertexDataWindow( Vector2(1, -1), Vector2(1, 1)) );

vVerts.push_back( VertexDataWindow( Vector2(0, 1), Vector2(0, 0)) );

vVerts.push_back( VertexDataWindow( Vector2(1, 1), Vector2(1, 0)) );

GLushort vIndices[] = { 0, 1, 3,   0, 3, 2,   4, 5, 7,   4, 7, 6};

m_uiCompanionWindowIndexSize = _countof(vIndices);

glGenVertexArrays( 1, &m_unCompanionWindowVAO );

glBindVertexArray( m_unCompanionWindowVAO );

glGenBuffers( 1, &m_glCompanionWindowIDVertBuffer );

glBindBuffer( GL_ARRAY_BUFFER, m_glCompanionWindowIDVertBuffer );

glBufferData( GL_ARRAY_BUFFER, vVerts.size()*sizeof(VertexDataWindow), &vVerts[0], GL_STATIC_DRAW );

glGenBuffers( 1, &m_glCompanionWindowIDIndexBuffer );

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_glCompanionWindowIDIndexBuffer );

glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_uiCompanionWindowIndexSize*sizeof(GLushort), &vIndices[0], GL_STATIC_DRAW );

glEnableVertexAttribArray( 0 );

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexDataWindow), (void *)offsetof( VertexDataWindow, position ) );

glEnableVertexAttribArray( 1 );

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(VertexDataWindow), (void *)offsetof( VertexDataWindow, texCoord ) );

glBindVertexArray( 0 );

glDisableVertexAttribArray(0);

glDisableVertexAttribArray(1);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

void CMainApplication::RenderStereoTargets()

{

glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );

glEnable( GL_MULTISAMPLE );

// Left Eye

glBindFramebuffer( GL_FRAMEBUFFER, leftEyeDesc.m_nRenderFramebufferId );

glViewport(0, 0, m_nRenderWidth, m_nRenderHeight );

RenderScene( vr::Eye_Left );

glBindFramebuffer( GL_FRAMEBUFFER, 0 );

glDisable( GL_MULTISAMPLE );

glBindFramebuffer(GL_READ_FRAMEBUFFER, leftEyeDesc.m_nRenderFramebufferId);

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, leftEyeDesc.m_nResolveFramebufferId );

glBlitFramebuffer( 0, 0, m_nRenderWidth, m_nRenderHeight, 0, 0, m_nRenderWidth, m_nRenderHeight,

GL_COLOR_BUFFER_BIT,

GL_LINEAR );

glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0 );

glEnable( GL_MULTISAMPLE );

// Right Eye

glBindFramebuffer( GL_FRAMEBUFFER, rightEyeDesc.m_nRenderFramebufferId );

glViewport(0, 0, m_nRenderWidth, m_nRenderHeight );

RenderScene( vr::Eye_Right );

glBindFramebuffer( GL_FRAMEBUFFER, 0 );

glDisable( GL_MULTISAMPLE );

glBindFramebuffer(GL_READ_FRAMEBUFFER, rightEyeDesc.m_nRenderFramebufferId );

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rightEyeDesc.m_nResolveFramebufferId );

glBlitFramebuffer( 0, 0, m_nRenderWidth, m_nRenderHeight, 0, 0, m_nRenderWidth, m_nRenderHeight,

GL_COLOR_BUFFER_BIT,

GL_LINEAR  );

glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0 );

}

//-----------------------------------------------------------------------------

// Purpose: Renders a scene with respect to nEye.

//-----------------------------------------------------------------------------

void CMainApplication::RenderScene( vr::Hmd_Eye nEye )

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);

if( m_bShowCubes )

{

glUseProgram( m_unSceneProgramID );

glUniformMatrix4fv( m_nSceneMatrixLocation, 1, GL_FALSE, GetCurrentViewProjectionMatrix( nEye ).get() );

glBindVertexArray( m_unSceneVAO );

glBindTexture( GL_TEXTURE_2D, m_iTexture );

glDrawArrays( GL_TRIANGLES, 0, m_uiVertcount );

glBindVertexArray( 0 );

}

bool bIsInputAvailable = m_pHMD->IsInputAvailable();

if( bIsInputAvailable )

{

// draw the controller axis lines

glUseProgram( m_unControllerTransformProgramID );

glUniformMatrix4fv( m_nControllerMatrixLocation, 1, GL_FALSE, GetCurrentViewProjectionMatrix( nEye ).get() );

glBindVertexArray( m_unControllerVAO );

glDrawArrays( GL_LINES, 0, m_uiControllerVertcount );

glBindVertexArray( 0 );

}

// ----- 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 ];

if( !pose.bPoseIsValid )

continue;

if( !bIsInputAvailable && m_pHMD->GetTrackedDeviceClass( unTrackedDevice ) == vr::TrackedDeviceClass_Controller )

continue;

const Matrix4 & matDeviceToTracking = m_rmat4DevicePose[ unTrackedDevice ];

Matrix4 matMVP = GetCurrentViewProjectionMatrix( nEye ) * matDeviceToTracking;

glUniformMatrix4fv( m_nRenderModelMatrixLocation, 1, GL_FALSE, matMVP.get() );

m_rTrackedDeviceToRenderModel[ unTrackedDevice ]->Draw();

}

glUseProgram( 0 );

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

void CMainApplication::RenderCompanionWindow()

{

glDisable(GL_DEPTH_TEST);

glViewport( 0, 0, m_nCompanionWindowWidth, m_nCompanionWindowHeight );

glBindVertexArray( m_unCompanionWindowVAO );

glUseProgram( m_unCompanionWindowProgramID );

// render left eye (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 );

glDrawElements( GL_TRIANGLES, m_uiCompanionWindowIndexSize/2, GL_UNSIGNED_SHORT, 0 );

// render right eye (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 );

glDrawElements( GL_TRIANGLES, m_uiCompanionWindowIndexSize/2, GL_UNSIGNED_SHORT, (const void *)(uintptr_t)(m_uiCompanionWindowIndexSize) );

glBindVertexArray( 0 );

glUseProgram( 0 );

}

//-----------------------------------------------------------------------------

// Purpose: Gets a Matrix Projection Eye with respect to nEye.

//-----------------------------------------------------------------------------

Matrix4 CMainApplication::GetHMDMatrixProjectionEye( vr::Hmd_Eye nEye )

{

if ( !m_pHMD )

return Matrix4();

vr::HmdMatrix44_t mat = m_pHMD->GetProjectionMatrix( nEye, m_fNearClip, m_fFarClip );

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: Gets an HMDMatrixPoseEye with respect to nEye.

//-----------------------------------------------------------------------------

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: Gets a Current View Projection Matrix with respect to nEye,

//          which may be an Eye_Left or an Eye_Right.

//-----------------------------------------------------------------------------

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_GenericTracker:    m_rDevClassChar[nDevice] = 'G'; 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];

m_mat4HMDPose.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;

}

}

// load the model if we didn't find one

if( !pRenderModel )

{

vr::RenderModel_t *pModel;

vr::EVRRenderModelError error;

while ( 1 )

{

error = vr::VRRenderModels()->LoadRenderModel_Async( pchRenderModelName, &pModel );

if ( error != vr::VRRenderModelError_Loading )

break;

ThreadSleep( 1 );

}

if ( error != vr::VRRenderModelError_None )

{

dprintf( "Unable to load render model %s - %s\n", pchRenderModelName, vr::VRRenderModels()->GetRenderModelErrorNameFromEnum( error ) );

return NULL; // move on to the next tracked device

}

vr::RenderModel_TextureMap_t *pTexture;

while ( 1 )

{

error = vr::VRRenderModels()->LoadTexture_Async( pModel->diffuseTextureId, &pTexture );

if ( error != vr::VRRenderModelError_Loading )

break;

ThreadSleep( 1 );

}

if ( error != vr::VRRenderModelError_None )

{

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

glDeleteVertexArrays( 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 );

}

//-----------------------------------------------------------------------------

// Purpose:

//-----------------------------------------------------------------------------

int main(int argc, char *argv[])

{

CMainApplication *pMainApplication = new CMainApplication( argc, argv );

if (!pMainApplication->BInit())

{

pMainApplication->Shutdown();

return 1;

}

pMainApplication->RunMainLoop();

pMainApplication->Shutdown();

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hellovr_opengl