1 #ifdef BT_ENABLE_VR
2 #ifdef BT_USE_CUSTOM_PROFILER
3 #endif
4 
5 //========= Copyright Valve Corporation ============//
6 
7 #include "../OpenGLWindow/SimpleOpenGL3App.h"
8 #include "../OpenGLWindow/OpenGLInclude.h"
9 #include "Bullet3Common/b3Quaternion.h"
10 #include "Bullet3Common/b3Transform.h"
11 #include "Bullet3Common/b3CommandLineArgs.h"
12 
13 #include "../Utils/b3Clock.h"
14 #include "../Utils/ChromeTraceUtil.h"
15 #include "../ExampleBrowser/OpenGLGuiHelper.h"
16 #include "../CommonInterfaces/CommonExampleInterface.h"
17 #include "../CommonInterfaces/CommonGUIHelperInterface.h"
18 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
19 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
20 #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
21 
22 #ifdef __APPLE__
23 #define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
24 #import <Cocoa/Cocoa.h>
25 #endif  //__APPLE__
26 
27 #include "LinearMath/btIDebugDraw.h"
28 int gSharedMemoryKey = -1;
29 static int gDebugDrawFlags = 0;
30 static bool gDisplayDistortion = false;
31 static bool gDisableDesktopGL = false;
32 
33 static int maxNumObjectCapacity = 128 * 1024;
34 static int maxShapeCapacityInBytes = 128 * 1024 * 1024;
35 
36 #include <stdio.h>
37 #include <string>
38 #include <cstdlib>
39 
40 #include <openvr.h>
41 #include "strtools.h"
42 #include "compat.h"
43 #include "lodepng.h"
44 #include "Matrices.h"
45 #include "pathtools.h"
46 
47 CommonExampleInterface *sExample;
48 
49 int sPrevPacketNum = 0;
50 OpenGLGuiHelper *sGuiPtr = 0;
51 
52 static vr::VRControllerState_t sPrevStates[vr::k_unMaxTrackedDeviceCount] = {0};
53 
54 #if defined(POSIX)
55 #include "unistd.h"
56 #endif
57 #ifdef _WIN32
58 #include <Windows.h>
59 #endif
60 #ifdef __linux__
61 #define APIENTRY
62 #endif
63 
ThreadSleep(unsigned long nMilliseconds)64 void ThreadSleep(unsigned long nMilliseconds)
65 {
66 #if defined(_WIN32)
67 	::Sleep(nMilliseconds);
68 #elif defined(POSIX)
69 	usleep(nMilliseconds * 1000);
70 #endif
71 }
72 
73 class CGLRenderModel
74 {
75 public:
76 	CGLRenderModel(const std::string &sRenderModelName);
77 	~CGLRenderModel();
78 
79 	bool BInit(const vr::RenderModel_t &vrModel, const vr::RenderModel_TextureMap_t &vrDiffuseTexture);
80 	void Cleanup();
81 	void Draw();
GetName() const82 	const std::string &GetName() const { return m_sModelName; }
83 
84 private:
85 	GLuint m_glVertBuffer;
86 	GLuint m_glIndexBuffer;
87 	GLuint m_glVertArray;
88 	GLuint m_glTexture;
89 	GLsizei m_unVertexCount;
90 	std::string m_sModelName;
91 };
92 
93 static bool g_bPrintf = true;
94 
95 //-----------------------------------------------------------------------------
96 // Purpose:
97 //------------------------------------------------------------------------------
98 class CMainApplication
99 {
100 public:
101 	CMainApplication(int argc, char *argv[]);
102 	virtual ~CMainApplication();
103 
104 	bool BInit();
105 	bool BInitGL();
106 	bool BInitCompositor();
107 	void getControllerTransform(int unDevice, b3Transform &tr);
108 	void SetupRenderModels();
109 
110 	void Shutdown();
111 
112 	void RunMainLoop();
113 	bool HandleInput();
114 	void ProcessVREvent(const vr::VREvent_t &event);
115 	void RenderFrame();
116 
117 	bool SetupTexturemaps();
118 
119 	void SetupScene();
120 	void AddCubeToScene(Matrix4 mat, std::vector<float> &vertdata);
121 	void AddCubeVertex(float fl0, float fl1, float fl2, float fl3, float fl4, std::vector<float> &vertdata);
122 
123 	void DrawControllers();
124 
125 	bool SetupStereoRenderTargets();
126 	void SetupDistortion();
127 	void SetupCameras();
128 
129 	void RenderStereoTargets();
130 	void RenderDistortion();
131 	void RenderScene(vr::Hmd_Eye nEye);
132 
133 	Matrix4 GetHMDMatrixProjectionEye(vr::Hmd_Eye nEye);
134 	Matrix4 GetHMDMatrixPoseEye(vr::Hmd_Eye nEye);
135 	Matrix4 GetCurrentViewProjectionMatrix(vr::Hmd_Eye nEye);
136 	void UpdateHMDMatrixPose();
137 
138 	Matrix4 ConvertSteamVRMatrixToMatrix4(const vr::HmdMatrix34_t &matPose);
139 
140 	GLuint CompileGLShader(const char *pchShaderName, const char *pchVertexShader, const char *pchFragmentShader);
141 	bool CreateAllShaders();
142 
143 	void SetupRenderModelForTrackedDevice(vr::TrackedDeviceIndex_t unTrackedDeviceIndex);
144 	CGLRenderModel *FindOrLoadRenderModel(const char *pchRenderModelName);
145 
getApp()146 	SimpleOpenGL3App *getApp() { return m_app; }
147 
148 private:
149 	bool m_bDebugOpenGL;
150 	bool m_bVerbose;
151 	bool m_bPerf;
152 	bool m_bVblank;
153 	bool m_bGlFinishHack;
154 
155 	vr::IVRSystem *m_pHMD;
156 	vr::IVRRenderModels *m_pRenderModels;
157 	std::string m_strDriver;
158 	std::string m_strDisplay;
159 	vr::TrackedDevicePose_t m_rTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
160 	Matrix4 m_rmat4DevicePose[vr::k_unMaxTrackedDeviceCount];
161 	bool m_rbShowTrackedDevice[vr::k_unMaxTrackedDeviceCount];
162 
163 private:
164 	SimpleOpenGL3App *m_app;
165 	uint32_t m_nWindowWidth;
166 	uint32_t m_nWindowHeight;
167 	bool m_hasContext;
168 	b3Clock m_clock;
169 
170 private:  // OpenGL bookkeeping
171 	int m_iTrackedControllerCount;
172 	int m_iTrackedControllerCount_Last;
173 	int m_iValidPoseCount;
174 	int m_iValidPoseCount_Last;
175 	bool m_bShowCubes;
176 
177 	std::string m_strPoseClasses;                         // what classes we saw poses for this frame
178 	char m_rDevClassChar[vr::k_unMaxTrackedDeviceCount];  // for each device, a character representing its class
179 
180 	int m_iSceneVolumeWidth;
181 	int m_iSceneVolumeHeight;
182 	int m_iSceneVolumeDepth;
183 	float m_fScaleSpacing;
184 	float m_fScale;
185 
186 	int m_iSceneVolumeInit;  // if you want something other than the default 20x20x20
187 
188 	float m_fNearClip;
189 	float m_fFarClip;
190 
191 	GLuint m_iTexture;
192 
193 	unsigned int m_uiVertcount;
194 
195 	GLuint m_glSceneVertBuffer;
196 	GLuint m_unSceneVAO;
197 	GLuint m_unLensVAO;
198 	GLuint m_glIDVertBuffer;
199 	GLuint m_glIDIndexBuffer;
200 	unsigned int m_uiIndexSize;
201 
202 	GLuint m_glControllerVertBuffer;
203 	GLuint m_unControllerVAO;
204 	unsigned int m_uiControllerVertcount;
205 
206 	Matrix4 m_mat4HMDPose;
207 	Matrix4 m_mat4eyePosLeft;
208 	Matrix4 m_mat4eyePosRight;
209 
210 	Matrix4 m_mat4ProjectionCenter;
211 	Matrix4 m_mat4ProjectionLeft;
212 	Matrix4 m_mat4ProjectionRight;
213 
214 	struct VertexDataScene
215 	{
216 		Vector3 position;
217 		Vector2 texCoord;
218 	};
219 
220 	struct VertexDataLens
221 	{
222 		Vector2 position;
223 		Vector2 texCoordRed;
224 		Vector2 texCoordGreen;
225 		Vector2 texCoordBlue;
226 	};
227 
228 	GLuint m_unSceneProgramID;
229 	GLuint m_unLensProgramID;
230 	GLuint m_unControllerTransformProgramID;
231 	GLuint m_unRenderModelProgramID;
232 
233 	GLint m_nSceneMatrixLocation;
234 	GLint m_nControllerMatrixLocation;
235 	GLint m_nRenderModelMatrixLocation;
236 
237 	struct FramebufferDesc
238 	{
239 		GLuint m_nDepthBufferId;
240 		GLuint m_nRenderTextureId;
241 		GLuint m_nRenderFramebufferId;
242 		GLuint m_nResolveTextureId;
243 		GLuint m_nResolveFramebufferId;
244 	};
245 	FramebufferDesc leftEyeDesc;
246 	FramebufferDesc rightEyeDesc;
247 
248 	bool CreateFrameBuffer(int nWidth, int nHeight, FramebufferDesc &framebufferDesc);
249 
250 	uint32_t m_nRenderWidth;
251 	uint32_t m_nRenderHeight;
252 
253 	std::vector<CGLRenderModel *> m_vecRenderModels;
254 	CGLRenderModel *m_rTrackedDeviceToRenderModel[vr::k_unMaxTrackedDeviceCount];
255 };
256 
257 //-----------------------------------------------------------------------------
258 // Purpose: Constructor
259 //-----------------------------------------------------------------------------
CMainApplication(int argc,char * argv[])260 CMainApplication::CMainApplication(int argc, char *argv[])
261 	: m_app(NULL), m_hasContext(false), m_nWindowWidth(1280), m_nWindowHeight(720), m_unSceneProgramID(0), m_unLensProgramID(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_unLensVAO(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(false)
262 {
263 	for (int i = 1; i < argc; i++)
264 	{
265 		if (!stricmp(argv[i], "-gldebug"))
266 		{
267 			m_bDebugOpenGL = true;
268 		}
269 		else if (!stricmp(argv[i], "-verbose"))
270 		{
271 			m_bVerbose = true;
272 		}
273 		else if (!stricmp(argv[i], "-novblank"))
274 		{
275 			m_bVblank = false;
276 		}
277 		else if (!stricmp(argv[i], "-noglfinishhack"))
278 		{
279 			m_bGlFinishHack = false;
280 		}
281 		else if (!stricmp(argv[i], "-noprintf"))
282 		{
283 			g_bPrintf = false;
284 		}
285 		else if (!stricmp(argv[i], "-cubevolume") && (argc > i + 1) && (*argv[i + 1] != '-'))
286 		{
287 			m_iSceneVolumeInit = atoi(argv[i + 1]);
288 			i++;
289 		}
290 	}
291 	// other initialization tasks are done in BInit
292 	memset(m_rDevClassChar, 0, sizeof(m_rDevClassChar));
293 };
294 
295 //-----------------------------------------------------------------------------
296 // Purpose: Destructor
297 //-----------------------------------------------------------------------------
~CMainApplication()298 CMainApplication::~CMainApplication()
299 {
300 	// work is done in Shutdown
301 	b3Printf("Shutdown");
302 }
303 
304 //-----------------------------------------------------------------------------
305 // Purpose: Helper to get a string from a tracked device property and turn it
306 //			into a std::string
307 //-----------------------------------------------------------------------------
GetTrackedDeviceString(vr::IVRSystem * pHmd,vr::TrackedDeviceIndex_t unDevice,vr::TrackedDeviceProperty prop,vr::TrackedPropertyError * peError=NULL)308 std::string GetTrackedDeviceString(vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *peError = NULL)
309 {
310 	uint32_t unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty(unDevice, prop, NULL, 0, peError);
311 	if (unRequiredBufferLen == 0)
312 		return "";
313 
314 	char *pchBuffer = new char[unRequiredBufferLen];
315 	unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty(unDevice, prop, pchBuffer, unRequiredBufferLen, peError);
316 	std::string sResult = pchBuffer;
317 	delete[] pchBuffer;
318 	return sResult;
319 }
320 
321 b3KeyboardCallback prevKeyboardCallback = 0;
322 
MyKeyboardCallback(int key,int state)323 void MyKeyboardCallback(int key, int state)
324 {
325 	if (key == 'p')
326 	{
327 		if (state)
328 		{
329 			b3ChromeUtilsStartTimings();
330 		}
331 		else
332 		{
333 			b3ChromeUtilsStopTimingsAndWriteJsonFile("timings");
334 		}
335 	}
336 	if (sExample)
337 	{
338 		sExample->keyboardCallback(key, state);
339 	}
340 
341 	if (prevKeyboardCallback)
342 		prevKeyboardCallback(key, state);
343 }
344 
345 #include "../SharedMemory/SharedMemoryPublic.h"
346 extern bool useShadowMap;
347 static bool gEnableVRRenderControllers = true;
348 static bool gEnableVRRendering = true;
349 static int gUpAxis = 2;
350 
VRPhysicsServerVisualizerFlagCallback(int flag,bool enable)351 void VRPhysicsServerVisualizerFlagCallback(int flag, bool enable)
352 {
353 	if (flag == COV_ENABLE_Y_AXIS_UP)
354 	{
355 		//either Y = up or Z
356 		gUpAxis = enable ? 1 : 2;
357 	}
358 
359 	if (flag == COV_ENABLE_SHADOWS)
360 	{
361 		useShadowMap = enable;
362 	}
363 	if (flag == COV_ENABLE_GUI)
364 	{
365 		//there is no regular GUI here, but disable the
366 	}
367 	if (flag == COV_ENABLE_VR_RENDER_CONTROLLERS)
368 	{
369 		gEnableVRRenderControllers = enable;
370 	}
371 	if (flag == COV_ENABLE_RENDERING)
372 	{
373 		gEnableVRRendering = enable;
374 	}
375 
376 	if (flag == COV_ENABLE_WIREFRAME)
377 	{
378 		if (enable)
379 		{
380 			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
381 			//gDebugDrawFlags |= btIDebugDraw::DBG_DrawWireframe;
382 		}
383 		else
384 		{
385 			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
386 			//gDebugDrawFlags &= ~btIDebugDraw::DBG_DrawWireframe;
387 		}
388 	}
389 }
390 
391 //-----------------------------------------------------------------------------
392 // Purpose:
393 //-----------------------------------------------------------------------------
BInit()394 bool CMainApplication::BInit()
395 {
396 	// Loading the SteamVR Runtime
397 	vr::EVRInitError eError = vr::VRInitError_None;
398 	m_pHMD = vr::VR_Init(&eError, vr::VRApplication_Scene);
399 
400 	if (eError != vr::VRInitError_None)
401 	{
402 		m_pHMD = NULL;
403 		char buf[1024];
404 		sprintf_s(buf, sizeof(buf), "Unable to init VR runtime: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError));
405 		b3Warning("VR_Init Failed %s", buf);
406 		return false;
407 	}
408 
409 	m_pRenderModels = (vr::IVRRenderModels *)vr::VR_GetGenericInterface(vr::IVRRenderModels_Version, &eError);
410 	if (!m_pRenderModels)
411 	{
412 		m_pHMD = NULL;
413 		vr::VR_Shutdown();
414 
415 		char buf[1024];
416 		sprintf_s(buf, sizeof(buf), "Unable to get render model interface: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError));
417 		b3Warning("VR_Init Failed %s", buf);
418 		return false;
419 	}
420 
421 	//	int nWindowPosX = 700;
422 	//	int nWindowPosY = 100;
423 	m_nWindowWidth = 1280;
424 	m_nWindowHeight = 720;
425 
426 	/*
427 
428 	//SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY );
429 	SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
430 	SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 0 );
431 	SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 0 );
432 	if( m_bDebugOpenGL )
433 		SDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG );
434 
435 	*/
436 
437 	m_app = new SimpleOpenGL3App("SimpleOpenGL3App", m_nWindowWidth, m_nWindowHeight, true, maxNumObjectCapacity, maxShapeCapacityInBytes);
438 
439 	sGuiPtr = new OpenGLGuiHelper(m_app, false);
440 	sGuiPtr->setVisualizerFlagCallback(VRPhysicsServerVisualizerFlagCallback);
441 	sGuiPtr->setVRMode(true);
442 
443 	//sGuiPtr = new DummyGUIHelper;
444 
445 	prevKeyboardCallback = m_app->m_window->getKeyboardCallback();
446 	m_app->m_window->setKeyboardCallback(MyKeyboardCallback);
447 
448 	CommonExampleOptions options(sGuiPtr);
449 
450 	sExample = StandaloneExampleCreateFunc(options);
451 	sExample->initPhysics();
452 	sExample->resetCamera();
453 
454 #if 0
455 	int cubeIndex = m_app->registerCubeShape(1,1,1);
456 
457     b3Quaternion orn(0,0,0,1);
458 
459 	{
460 		b3Vector3 color=b3MakeVector3(0.3,0.3,0.6);
461 		b3Vector3 pos = b3MakeVector3(0,0,0);
462 		b3Vector3 scaling=b3MakeVector3 (1,.1,1);
463 		m_app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling);
464 	}
465 	{
466 		b3Vector3 color=b3MakeVector3(0.3,0.6,0.3);
467 		b3Vector3 pos = b3MakeVector3(0,0.3,0);
468 		b3Vector3 scaling=b3MakeVector3 (.1,.1,.1);
469 		m_app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling);
470 	}
471 #endif
472 
473 	m_app->m_renderer->writeTransforms();
474 
475 	/*	if (m_pWindow == NULL)
476 	{
477 		printf( "%s - Window could not be created! SDL Error: %s\n", __FUNCTION__, SDL_GetError() );
478 		return false;
479 	}
480 	*/
481 
482 	/*m_pContext = SDL_GL_CreateContext(m_pWindow);
483 	if (m_pContext == NULL)
484 	{
485 		printf( "%s - OpenGL context could not be created! SDL Error: %s\n", __FUNCTION__, SDL_GetError() );
486 		return false;
487 	}
488 
489 
490 
491 	if ( SDL_GL_SetSwapInterval( m_bVblank ? 1 : 0 ) < 0 )
492 	{
493 		printf( "%s - Warning: Unable to set VSync! SDL Error: %s\n", __FUNCTION__, SDL_GetError() );
494 		return false;
495 	}
496 
497 		*/
498 	m_strDriver = "No Driver";
499 	m_strDisplay = "No Display";
500 
501 	m_strDriver = GetTrackedDeviceString(m_pHMD, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String);
502 	m_strDisplay = GetTrackedDeviceString(m_pHMD, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String);
503 
504 	std::string strWindowTitle = "hellovr_bullet - " + m_strDriver + " " + m_strDisplay;
505 	m_app->m_window->setWindowTitle(strWindowTitle.c_str());
506 
507 	// cube array
508 	m_iSceneVolumeWidth = m_iSceneVolumeInit;
509 	m_iSceneVolumeHeight = m_iSceneVolumeInit;
510 	m_iSceneVolumeDepth = m_iSceneVolumeInit;
511 
512 	m_fScale = 0.3f;
513 	m_fScaleSpacing = 4.0f;
514 
515 	m_fNearClip = 0.1f;
516 	m_fFarClip = 3000.0f;
517 
518 	m_iTexture = 0;
519 	m_uiVertcount = 0;
520 
521 	// 		m_MillisecondsTimer.start(1, this);
522 	// 		m_SecondsTimer.start(1000, this);
523 
524 	if (!BInitGL())
525 	{
526 		printf("%s - Unable to initialize OpenGL!\n", __FUNCTION__);
527 		return false;
528 	}
529 
530 	if (!BInitCompositor())
531 	{
532 		printf("%s - Failed to initialize VR Compositor!\n", __FUNCTION__);
533 		return false;
534 	}
535 
536 	return true;
537 }
538 
539 //-----------------------------------------------------------------------------
540 // Purpose:
541 //-----------------------------------------------------------------------------
542 /*void APIENTRY DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const void* userParam)
543 {
544 	b3Printf( "GL Error: %s\n", message );
545 }
546 
547 static void APIENTRY DebugCallback (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam)
548 {
549 	b3Printf( "GL Error: %s\n", message );
550 }
551 */
552 
553 //-----------------------------------------------------------------------------
554 // Purpose:
555 //-----------------------------------------------------------------------------
BInitGL()556 bool CMainApplication::BInitGL()
557 {
558 	if (m_bDebugOpenGL)
559 	{
560 		//const GLvoid *userParam=0;
561 		//glDebugMessageCallback(DebugCallback,  userParam);
562 		//glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE );
563 		//glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
564 	}
565 
566 	if (!CreateAllShaders())
567 		return false;
568 
569 	SetupTexturemaps();
570 	SetupScene();
571 	SetupCameras();
572 	SetupStereoRenderTargets();
573 	SetupDistortion();
574 
575 	SetupRenderModels();
576 
577 	return true;
578 }
579 
580 //-----------------------------------------------------------------------------
581 // Purpose:
582 //-----------------------------------------------------------------------------
BInitCompositor()583 bool CMainApplication::BInitCompositor()
584 {
585 	vr::EVRInitError peError = vr::VRInitError_None;
586 
587 	if (!vr::VRCompositor())
588 	{
589 		printf("Compositor initialization failed. See log file for details\n");
590 		return false;
591 	}
592 
593 	return true;
594 }
595 
596 //-----------------------------------------------------------------------------
597 // Purpose:
598 //-----------------------------------------------------------------------------
Shutdown()599 void CMainApplication::Shutdown()
600 {
601 	if (m_pHMD)
602 	{
603 		vr::VR_Shutdown();
604 		m_pHMD = NULL;
605 	}
606 
607 	for (std::vector<CGLRenderModel *>::iterator i = m_vecRenderModels.begin(); i != m_vecRenderModels.end(); i++)
608 	{
609 		delete (*i);
610 	}
611 	m_vecRenderModels.clear();
612 
613 	if (m_hasContext)
614 	{
615 		if (m_glSceneVertBuffer)
616 		{
617 			//glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE );
618 			//glDebugMessageCallback(nullptr, nullptr);
619 			glDeleteBuffers(1, &m_glSceneVertBuffer);
620 			glDeleteBuffers(1, &m_glIDVertBuffer);
621 			glDeleteBuffers(1, &m_glIDIndexBuffer);
622 		}
623 
624 		if (m_unSceneProgramID)
625 		{
626 			glDeleteProgram(m_unSceneProgramID);
627 		}
628 		if (m_unControllerTransformProgramID)
629 		{
630 			glDeleteProgram(m_unControllerTransformProgramID);
631 		}
632 		if (m_unRenderModelProgramID)
633 		{
634 			glDeleteProgram(m_unRenderModelProgramID);
635 		}
636 		if (m_unLensProgramID)
637 		{
638 			glDeleteProgram(m_unLensProgramID);
639 		}
640 
641 		glDeleteRenderbuffers(1, &leftEyeDesc.m_nDepthBufferId);
642 		glDeleteTextures(1, &leftEyeDesc.m_nRenderTextureId);
643 		glDeleteFramebuffers(1, &leftEyeDesc.m_nRenderFramebufferId);
644 		glDeleteTextures(1, &leftEyeDesc.m_nResolveTextureId);
645 		glDeleteFramebuffers(1, &leftEyeDesc.m_nResolveFramebufferId);
646 
647 		glDeleteRenderbuffers(1, &rightEyeDesc.m_nDepthBufferId);
648 		glDeleteTextures(1, &rightEyeDesc.m_nRenderTextureId);
649 		glDeleteFramebuffers(1, &rightEyeDesc.m_nRenderFramebufferId);
650 		glDeleteTextures(1, &rightEyeDesc.m_nResolveTextureId);
651 		glDeleteFramebuffers(1, &rightEyeDesc.m_nResolveFramebufferId);
652 
653 		if (m_unLensVAO != 0)
654 		{
655 			glDeleteVertexArrays(1, &m_unLensVAO);
656 		}
657 		if (m_unSceneVAO != 0)
658 		{
659 			glDeleteVertexArrays(1, &m_unSceneVAO);
660 		}
661 		if (m_unControllerVAO != 0)
662 		{
663 			glDeleteVertexArrays(1, &m_unControllerVAO);
664 		}
665 	}
666 
667 	if (sExample)
668 	{
669 		sExample->exitPhysics();
670 		delete sExample;
671 	}
672 	delete m_app;
673 	m_app = 0;
674 }
675 
getControllerTransform(int unDevice,b3Transform & tr)676 void CMainApplication::getControllerTransform(int unDevice, b3Transform &tr)
677 {
678 	const Matrix4 &matOrg = m_rmat4DevicePose[unDevice];
679 	tr.setIdentity();
680 	tr.setOrigin(b3MakeVector3(matOrg[12], matOrg[13], matOrg[14]));  //pos[1]));
681 	b3Matrix3x3 bmat;
682 	for (int i = 0; i < 3; i++)
683 	{
684 		for (int j = 0; j < 3; j++)
685 		{
686 			bmat[i][j] = matOrg[i + 4 * j];
687 		}
688 	}
689 	tr.setBasis(bmat);
690 	b3Transform y2z;
691 	y2z.setIdentity();
692 	y2z.setRotation(b3Quaternion(0, B3_HALF_PI, 0));
693 	tr = y2z * tr;
694 }
695 //-----------------------------------------------------------------------------
696 // Purpose:
697 //-----------------------------------------------------------------------------
HandleInput()698 bool CMainApplication::HandleInput()
699 {
700 	bool bRet = false;
701 
702 	// Process SteamVR events
703 	vr::VREvent_t event;
704 	while (m_pHMD->PollNextEvent(&event, sizeof(event)))
705 	{
706 		ProcessVREvent(event);
707 	}
708 
709 	// Process SteamVR controller state
710 	for (vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; unDevice++)
711 	{
712 		vr::VRControllerState_t state;
713 		if (m_pHMD->GetControllerState(unDevice, &state, sizeof(vr::VRControllerState_t)))
714 		{
715 			b3Transform tr;
716 			getControllerTransform(unDevice, tr);
717 			float pos[3] = {tr.getOrigin()[0], tr.getOrigin()[1], tr.getOrigin()[2]};
718 			b3Quaternion born = tr.getRotation();
719 			float orn[4] = {born[0], born[1], born[2], born[3]};
720 
721 			//we need to have the 'move' events, so no early out here
722 			//if (sPrevStates[unDevice].unPacketNum != state.unPacketNum)
723 			if (m_pHMD->GetTrackedDeviceClass(unDevice) == vr::TrackedDeviceClass_HMD)
724 			{
725 				Matrix4 rotYtoZ = rotYtoZ.identity();
726 				//some Bullet apps (especially robotics related) require Z as up-axis)
727 				if (m_app->getUpAxis() == 2)
728 				{
729 					rotYtoZ.rotateX(-90);
730 				}
731 				Matrix4 viewMatCenter = m_mat4HMDPose * rotYtoZ;
732 				const float *mat = viewMatCenter.invertAffine().get();
733 				pos[0] = mat[12];
734 				pos[1] = mat[13];
735 				pos[2] = mat[14];
736 
737 				b3Matrix3x3 bmat;
738 				for (int i = 0; i < 3; i++)
739 				{
740 					for (int j = 0; j < 3; j++)
741 					{
742 						bmat[i][j] = mat[i + 4 * j];
743 					}
744 				}
745 				b3Quaternion orn2;
746 				bmat.getRotation(orn2);
747 				orn[0] = orn2[0];
748 				orn[1] = orn2[1];
749 				orn[2] = orn2[2];
750 				orn[3] = orn2[3];
751 				sExample->vrHMDMoveCallback(unDevice, pos, orn);
752 			}
753 
754 			if (m_pHMD->GetTrackedDeviceClass(unDevice) == vr::TrackedDeviceClass_GenericTracker)
755 			{
756 				sExample->vrGenericTrackerMoveCallback(unDevice, pos, orn);
757 			}
758 
759 			if (m_pHMD->GetTrackedDeviceClass(unDevice) == vr::TrackedDeviceClass_Controller)
760 			{
761 				sPrevStates[unDevice].unPacketNum = state.unPacketNum;
762 
763 				for (int button = 0; button < vr::k_EButton_Max; button++)
764 				{
765 					uint64_t trigger = vr::ButtonMaskFromId((vr::EVRButtonId)button);
766 
767 					btAssert(vr::k_unControllerStateAxisCount >= 5);
768 					float allAxis[10];  //store x,y times 5 controllers
769 					int index = 0;
770 					for (int i = 0; i < 5; i++)
771 					{
772 						allAxis[index++] = state.rAxis[i].x;
773 						allAxis[index++] = state.rAxis[i].y;
774 					}
775 					bool isTrigger = (state.ulButtonPressed & trigger) != 0;
776 					if (isTrigger)
777 					{
778 						//pressed now, not pressed before -> raise a button down event
779 						if ((sPrevStates[unDevice].ulButtonPressed & trigger) == 0)
780 						{
781 							//							printf("Device PRESSED: %d, button %d\n", unDevice, button);
782 							sExample->vrControllerButtonCallback(unDevice, button, 1, pos, orn);
783 						}
784 						else
785 						{
786 							//							printf("Device MOVED: %d\n", unDevice);
787 							sExample->vrControllerMoveCallback(unDevice, pos, orn, state.rAxis[1].x, allAxis);
788 						}
789 					}
790 					else
791 					{
792 						if (m_pHMD->GetTrackedDeviceClass(unDevice) == vr::TrackedDeviceClass_Controller)
793 						{
794 							//							printf("Device RELEASED: %d, button %d\n", unDevice,button);
795 
796 							//not pressed now, but pressed before -> raise a button up event
797 							if ((sPrevStates[unDevice].ulButtonPressed & trigger) != 0)
798 							{
799 								if (button == 2)
800 								{
801 									gDebugDrawFlags = 0;
802 								}
803 
804 								sExample->vrControllerButtonCallback(unDevice, button, 0, pos, orn);
805 							}
806 							else
807 							{
808 								sExample->vrControllerMoveCallback(unDevice, pos, orn, state.rAxis[1].x, allAxis);
809 							}
810 						}
811 					}
812 				}
813 			}
814 
815 			//			m_rbShowTrackedDevice[ unDevice ] = state.ulButtonPressed == 0;
816 		}
817 		sPrevStates[unDevice] = state;
818 	}
819 
820 	return bRet;
821 }
822 
823 //-----------------------------------------------------------------------------
824 // Purpose:
825 //-----------------------------------------------------------------------------
826 
RunMainLoop()827 void CMainApplication::RunMainLoop()
828 {
829 	bool bQuit = false;
830 
831 	while (!bQuit && !m_app->m_window->requestedExit())
832 	{
833 		this->m_app->setUpAxis(gUpAxis);
834 		b3ChromeUtilsEnableProfiling();
835 		if (gEnableVRRendering)
836 		{
837 			B3_PROFILE("main");
838 
839 			bQuit = HandleInput();
840 
841 			RenderFrame();
842 		}
843 		else
844 		{
845 			b3Clock::usleep(0);
846 			sExample->updateGraphics();
847 		}
848 	}
849 }
850 
851 //-----------------------------------------------------------------------------
852 // Purpose: Processes a single VR event
853 //-----------------------------------------------------------------------------
ProcessVREvent(const vr::VREvent_t & event)854 void CMainApplication::ProcessVREvent(const vr::VREvent_t &event)
855 {
856 	switch (event.eventType)
857 	{
858 		case vr::VREvent_TrackedDeviceActivated:
859 		{
860 			SetupRenderModelForTrackedDevice(event.trackedDeviceIndex);
861 			b3Printf("Device %u attached. Setting up render model.\n", event.trackedDeviceIndex);
862 		}
863 		break;
864 		case vr::VREvent_TrackedDeviceDeactivated:
865 		{
866 			b3Printf("Device %u detached.\n", event.trackedDeviceIndex);
867 		}
868 		break;
869 		case vr::VREvent_TrackedDeviceUpdated:
870 		{
871 			b3Printf("Device %u updated.\n", event.trackedDeviceIndex);
872 		}
873 		break;
874 	}
875 }
876 
877 //-----------------------------------------------------------------------------
878 // Purpose:
879 //-----------------------------------------------------------------------------
RenderFrame()880 void CMainApplication::RenderFrame()
881 {
882 	// for now as fast as possible
883 	if (m_pHMD)
884 	{
885 		{
886 			B3_PROFILE("DrawControllers");
887 			DrawControllers();
888 		}
889 		RenderStereoTargets();
890 
891 		if (!gDisableDesktopGL)
892 		{
893 			if (gDisplayDistortion)
894 			{
895 				B3_PROFILE("RenderDistortion");
896 				RenderDistortion();
897 			}
898 			else
899 			{
900 				//todo: should use framebuffer_multisample_blit_scaled
901 				//See https://twitter.com/id_aa_carmack/status/268488838425481217?lang=en
902 				glBindFramebuffer(GL_FRAMEBUFFER, 0);
903 				glDisable(GL_MULTISAMPLE);
904 				glBindFramebuffer(GL_READ_FRAMEBUFFER, rightEyeDesc.m_nRenderFramebufferId);
905 				glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
906 
907 				glBlitFramebuffer(0, 0, m_nRenderWidth, m_nRenderHeight, 0, 0, m_nRenderWidth, m_nRenderHeight,
908 								  GL_COLOR_BUFFER_BIT,
909 								  GL_LINEAR);
910 
911 				glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
912 				glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
913 			}
914 		}
915 
916 		vr::Texture_t leftEyeTexture = {(void *)leftEyeDesc.m_nResolveTextureId, vr::TextureType_OpenGL, vr::ColorSpace_Gamma};
917 		vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTexture);
918 		vr::Texture_t rightEyeTexture = {(void *)rightEyeDesc.m_nResolveTextureId, vr::TextureType_OpenGL, vr::ColorSpace_Gamma};
919 		vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTexture);
920 	}
921 
922 	if (m_bVblank && m_bGlFinishHack)
923 	{
924 		B3_PROFILE("bGlFinishHack");
925 		//$ HACKHACK. From gpuview profiling, it looks like there is a bug where two renders and a present
926 		// happen right before and after the vsync causing all kinds of jittering issues. This glFinish()
927 		// appears to clear that up. Temporary fix while I try to get nvidia to investigate this problem.
928 		// 1/29/2014 mikesart
929 		//glFinish();
930 	}
931 
932 	// SwapWindow
933 	{
934 		B3_PROFILE("m_app->swapBuffer");
935 		if (!gDisableDesktopGL)
936 		{
937 			m_app->swapBuffer();
938 		}
939 		//SDL_GL_SwapWindow( m_pWindow );
940 	}
941 
942 	// Clear
943 	{
944 		B3_PROFILE("glClearColor");
945 		// We want to make sure the glFinish waits for the entire present to complete, not just the submission
946 		// of the command. So, we do a clear here right here so the glFinish will wait fully for the swap.
947 		glClearColor(0, 0, 0, 1);
948 		//glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
949 	}
950 
951 	// Flush and wait for swap.
952 	if (m_bVblank)
953 	{
954 		B3_PROFILE("glFlushglFinish");
955 
956 		glFlush();
957 		glFinish();
958 	}
959 
960 	// Spew out the controller and pose count whenever they change.
961 	if (m_iTrackedControllerCount != m_iTrackedControllerCount_Last || m_iValidPoseCount != m_iValidPoseCount_Last)
962 	{
963 		B3_PROFILE("debug pose");
964 
965 		m_iValidPoseCount_Last = m_iValidPoseCount;
966 		m_iTrackedControllerCount_Last = m_iTrackedControllerCount;
967 
968 		b3Printf("PoseCount:%d(%s) Controllers:%d\n", m_iValidPoseCount, m_strPoseClasses.c_str(), m_iTrackedControllerCount);
969 	}
970 
971 	{
972 		B3_PROFILE("UpdateHMDMatrixPose");
973 		UpdateHMDMatrixPose();
974 	}
975 }
976 
977 //-----------------------------------------------------------------------------
978 // Purpose: Compiles a GL shader program and returns the handle. Returns 0 if
979 //			the shader couldn't be compiled for some reason.
980 //-----------------------------------------------------------------------------
CompileGLShader(const char * pchShaderName,const char * pchVertexShader,const char * pchFragmentShader)981 GLuint CMainApplication::CompileGLShader(const char *pchShaderName, const char *pchVertexShader, const char *pchFragmentShader)
982 {
983 	GLuint unProgramID = glCreateProgram();
984 
985 	GLuint nSceneVertexShader = glCreateShader(GL_VERTEX_SHADER);
986 	glShaderSource(nSceneVertexShader, 1, &pchVertexShader, NULL);
987 	glCompileShader(nSceneVertexShader);
988 
989 	GLint vShaderCompiled = GL_FALSE;
990 	glGetShaderiv(nSceneVertexShader, GL_COMPILE_STATUS, &vShaderCompiled);
991 	if (vShaderCompiled != GL_TRUE)
992 	{
993 		b3Printf("%s - Unable to compile vertex shader %d!\n", pchShaderName, nSceneVertexShader);
994 		glDeleteProgram(unProgramID);
995 		glDeleteShader(nSceneVertexShader);
996 		return 0;
997 	}
998 	glAttachShader(unProgramID, nSceneVertexShader);
999 	glDeleteShader(nSceneVertexShader);  // the program hangs onto this once it's attached
1000 
1001 	GLuint nSceneFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
1002 	glShaderSource(nSceneFragmentShader, 1, &pchFragmentShader, NULL);
1003 	glCompileShader(nSceneFragmentShader);
1004 
1005 	GLint fShaderCompiled = GL_FALSE;
1006 	glGetShaderiv(nSceneFragmentShader, GL_COMPILE_STATUS, &fShaderCompiled);
1007 	if (fShaderCompiled != GL_TRUE)
1008 	{
1009 		b3Printf("%s - Unable to compile fragment shader %d!\n", pchShaderName, nSceneFragmentShader);
1010 		glDeleteProgram(unProgramID);
1011 		glDeleteShader(nSceneFragmentShader);
1012 		return 0;
1013 	}
1014 
1015 	glAttachShader(unProgramID, nSceneFragmentShader);
1016 	glDeleteShader(nSceneFragmentShader);  // the program hangs onto this once it's attached
1017 
1018 	glLinkProgram(unProgramID);
1019 
1020 	GLint programSuccess = GL_TRUE;
1021 	glGetProgramiv(unProgramID, GL_LINK_STATUS, &programSuccess);
1022 	if (programSuccess != GL_TRUE)
1023 	{
1024 		b3Printf("%s - Error linking program %d!\n", pchShaderName, unProgramID);
1025 		glDeleteProgram(unProgramID);
1026 		return 0;
1027 	}
1028 
1029 	glUseProgram(unProgramID);
1030 	glUseProgram(0);
1031 
1032 	return unProgramID;
1033 }
1034 
1035 //-----------------------------------------------------------------------------
1036 // Purpose: Creates all the shaders used by HelloVR SDL
1037 //-----------------------------------------------------------------------------
CreateAllShaders()1038 bool CMainApplication::CreateAllShaders()
1039 {
1040 	m_unSceneProgramID = CompileGLShader(
1041 		"Scene",
1042 
1043 		// Vertex Shader
1044 		"#version 410\n"
1045 		"uniform mat4 matrix;\n"
1046 		"layout(location = 0) in vec4 position;\n"
1047 		"layout(location = 1) in vec2 v2UVcoordsIn;\n"
1048 		"layout(location = 2) in vec3 v3NormalIn;\n"
1049 		"out vec2 v2UVcoords;\n"
1050 		"void main()\n"
1051 		"{\n"
1052 		"	v2UVcoords = v2UVcoordsIn;\n"
1053 		"	gl_Position = matrix * position;\n"
1054 		"}\n",
1055 
1056 		// Fragment Shader
1057 		"#version 410 core\n"
1058 		"uniform sampler2D mytexture;\n"
1059 		"in vec2 v2UVcoords;\n"
1060 		"out vec4 outputColor;\n"
1061 		"void main()\n"
1062 		"{\n"
1063 		"   outputColor = texture(mytexture, v2UVcoords);\n"
1064 		"}\n");
1065 	m_nSceneMatrixLocation = glGetUniformLocation(m_unSceneProgramID, "matrix");
1066 	if (m_nSceneMatrixLocation == -1)
1067 	{
1068 		b3Printf("Unable to find matrix uniform in scene shader\n");
1069 		return false;
1070 	}
1071 
1072 	m_unControllerTransformProgramID = CompileGLShader(
1073 		"Controller",
1074 
1075 		// vertex shader
1076 		"#version 410\n"
1077 		"uniform mat4 matrix;\n"
1078 		"layout(location = 0) in vec4 position;\n"
1079 		"layout(location = 1) in vec3 v3ColorIn;\n"
1080 		"out vec4 v4Color;\n"
1081 		"void main()\n"
1082 		"{\n"
1083 		"	v4Color.xyz = v3ColorIn; v4Color.a = 1.0;\n"
1084 		"	gl_Position = matrix * position;\n"
1085 		"}\n",
1086 
1087 		// fragment shader
1088 		"#version 410\n"
1089 		"in vec4 v4Color;\n"
1090 		"out vec4 outputColor;\n"
1091 		"void main()\n"
1092 		"{\n"
1093 		"   outputColor = v4Color;\n"
1094 		"}\n");
1095 	m_nControllerMatrixLocation = glGetUniformLocation(m_unControllerTransformProgramID, "matrix");
1096 	if (m_nControllerMatrixLocation == -1)
1097 	{
1098 		b3Printf("Unable to find matrix uniform in controller shader\n");
1099 		return false;
1100 	}
1101 
1102 	m_unRenderModelProgramID = CompileGLShader(
1103 		"render model",
1104 
1105 		// vertex shader
1106 		"#version 410\n"
1107 		"uniform mat4 matrix;\n"
1108 		"layout(location = 0) in vec4 position;\n"
1109 		"layout(location = 1) in vec3 v3NormalIn;\n"
1110 		"layout(location = 2) in vec2 v2TexCoordsIn;\n"
1111 		"out vec2 v2TexCoord;\n"
1112 		"void main()\n"
1113 		"{\n"
1114 		"	v2TexCoord = v2TexCoordsIn;\n"
1115 		"	gl_Position = matrix * vec4(position.xyz, 1);\n"
1116 		"}\n",
1117 
1118 		//fragment shader
1119 		"#version 410 core\n"
1120 		"uniform sampler2D diffuse;\n"
1121 		"in vec2 v2TexCoord;\n"
1122 		"out vec4 outputColor;\n"
1123 		"void main()\n"
1124 		"{\n"
1125 		"   outputColor = texture( diffuse, v2TexCoord);\n"
1126 		"}\n"
1127 
1128 	);
1129 	m_nRenderModelMatrixLocation = glGetUniformLocation(m_unRenderModelProgramID, "matrix");
1130 	if (m_nRenderModelMatrixLocation == -1)
1131 	{
1132 		b3Printf("Unable to find matrix uniform in render model shader\n");
1133 		return false;
1134 	}
1135 
1136 	m_unLensProgramID = CompileGLShader(
1137 		"Distortion",
1138 
1139 		// vertex shader
1140 		"#version 410 core\n"
1141 		"layout(location = 0) in vec4 position;\n"
1142 		"layout(location = 1) in vec2 v2UVredIn;\n"
1143 		"layout(location = 2) in vec2 v2UVGreenIn;\n"
1144 		"layout(location = 3) in vec2 v2UVblueIn;\n"
1145 		"noperspective  out vec2 v2UVred;\n"
1146 		"noperspective  out vec2 v2UVgreen;\n"
1147 		"noperspective  out vec2 v2UVblue;\n"
1148 		"void main()\n"
1149 		"{\n"
1150 		"	v2UVred = v2UVredIn;\n"
1151 		"	v2UVgreen = v2UVGreenIn;\n"
1152 		"	v2UVblue = v2UVblueIn;\n"
1153 		"	gl_Position = position;\n"
1154 		"}\n",
1155 
1156 		// fragment shader
1157 		"#version 410 core\n"
1158 		"uniform sampler2D mytexture;\n"
1159 
1160 		"noperspective  in vec2 v2UVred;\n"
1161 		"noperspective  in vec2 v2UVgreen;\n"
1162 		"noperspective  in vec2 v2UVblue;\n"
1163 
1164 		"out vec4 outputColor;\n"
1165 
1166 		"void main()\n"
1167 		"{\n"
1168 		"	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"
1169 		"	if( fBoundsCheck > 1.0 )\n"
1170 		"	{ outputColor = vec4( 0, 0, 0, 1.0 ); }\n"
1171 		"	else\n"
1172 		"	{\n"
1173 		"		float red = texture(mytexture, v2UVred).x;\n"
1174 		"		float green = texture(mytexture, v2UVgreen).y;\n"
1175 		"		float blue = texture(mytexture, v2UVblue).z;\n"
1176 		"		outputColor = vec4( red, green, blue, 1.0  ); }\n"
1177 		"}\n");
1178 
1179 	return m_unSceneProgramID != 0 && m_unControllerTransformProgramID != 0 && m_unRenderModelProgramID != 0 && m_unLensProgramID != 0;
1180 }
1181 
1182 //-----------------------------------------------------------------------------
1183 // Purpose:
1184 //-----------------------------------------------------------------------------
SetupTexturemaps()1185 bool CMainApplication::SetupTexturemaps()
1186 {
1187 	std::string sExecutableDirectory = Path_StripFilename(Path_GetExecutablePath());
1188 	std::string strFullPath = Path_MakeAbsolute("../cube_texture.png", sExecutableDirectory);
1189 
1190 	std::vector<unsigned char> imageRGBA;
1191 	unsigned nImageWidth, nImageHeight;
1192 	unsigned nError = lodepng::decode(imageRGBA, nImageWidth, nImageHeight, strFullPath.c_str());
1193 
1194 	if (nError != 0)
1195 		return false;
1196 
1197 	glGenTextures(1, &m_iTexture);
1198 	glBindTexture(GL_TEXTURE_2D, m_iTexture);
1199 
1200 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nImageWidth, nImageHeight,
1201 				 0, GL_RGBA, GL_UNSIGNED_BYTE, &imageRGBA[0]);
1202 
1203 	glGenerateMipmap(GL_TEXTURE_2D);
1204 
1205 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1206 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1207 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1208 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1209 
1210 	GLfloat fLargest;
1211 	glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &fLargest);
1212 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, fLargest);
1213 	glBindTexture(GL_TEXTURE_2D, 0);
1214 
1215 	return (m_iTexture != 0);
1216 }
1217 
1218 //-----------------------------------------------------------------------------
1219 // Purpose: create a sea of cubes
1220 //-----------------------------------------------------------------------------
SetupScene()1221 void CMainApplication::SetupScene()
1222 {
1223 	if (!m_pHMD)
1224 		return;
1225 
1226 	std::vector<float> vertdataarray;
1227 
1228 	Matrix4 matScale;
1229 	matScale.scale(m_fScale, m_fScale, m_fScale);
1230 	Matrix4 matTransform;
1231 	matTransform.translate(
1232 		-((float)m_iSceneVolumeWidth * m_fScaleSpacing) / 2.f,
1233 		-((float)m_iSceneVolumeHeight * m_fScaleSpacing) / 2.f,
1234 		-((float)m_iSceneVolumeDepth * m_fScaleSpacing) / 2.f);
1235 
1236 	Matrix4 mat = matScale * matTransform;
1237 
1238 	for (int z = 0; z < m_iSceneVolumeDepth; z++)
1239 	{
1240 		for (int y = 0; y < m_iSceneVolumeHeight; y++)
1241 		{
1242 			for (int x = 0; x < m_iSceneVolumeWidth; x++)
1243 			{
1244 				AddCubeToScene(mat, vertdataarray);
1245 				mat = mat * Matrix4().translate(m_fScaleSpacing, 0, 0);
1246 			}
1247 			mat = mat * Matrix4().translate(-((float)m_iSceneVolumeWidth) * m_fScaleSpacing, m_fScaleSpacing, 0);
1248 		}
1249 		mat = mat * Matrix4().translate(0, -((float)m_iSceneVolumeHeight) * m_fScaleSpacing, m_fScaleSpacing);
1250 	}
1251 	m_uiVertcount = vertdataarray.size() / 5;
1252 
1253 	glGenVertexArrays(1, &m_unSceneVAO);
1254 	glBindVertexArray(m_unSceneVAO);
1255 
1256 	glGenBuffers(1, &m_glSceneVertBuffer);
1257 	glBindBuffer(GL_ARRAY_BUFFER, m_glSceneVertBuffer);
1258 	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertdataarray.size(), &vertdataarray[0], GL_STATIC_DRAW);
1259 
1260 	glBindBuffer(GL_ARRAY_BUFFER, m_glSceneVertBuffer);
1261 
1262 	GLsizei stride = sizeof(VertexDataScene);
1263 	uintptr_t offset = 0;
1264 
1265 	glEnableVertexAttribArray(0);
1266 	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
1267 
1268 	offset += sizeof(Vector3);
1269 	glEnableVertexAttribArray(1);
1270 	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
1271 
1272 	glBindVertexArray(0);
1273 	glDisableVertexAttribArray(0);
1274 	glDisableVertexAttribArray(1);
1275 
1276 	m_hasContext = true;
1277 }
1278 
1279 //-----------------------------------------------------------------------------
1280 // Purpose:
1281 //-----------------------------------------------------------------------------
AddCubeVertex(float fl0,float fl1,float fl2,float fl3,float fl4,std::vector<float> & vertdata)1282 void CMainApplication::AddCubeVertex(float fl0, float fl1, float fl2, float fl3, float fl4, std::vector<float> &vertdata)
1283 {
1284 	vertdata.push_back(fl0);
1285 	vertdata.push_back(fl1);
1286 	vertdata.push_back(fl2);
1287 	vertdata.push_back(fl3);
1288 	vertdata.push_back(fl4);
1289 }
1290 
1291 //-----------------------------------------------------------------------------
1292 // Purpose:
1293 //-----------------------------------------------------------------------------
AddCubeToScene(Matrix4 mat,std::vector<float> & vertdata)1294 void CMainApplication::AddCubeToScene(Matrix4 mat, std::vector<float> &vertdata)
1295 {
1296 	// Matrix4 mat( outermat.data() );
1297 
1298 	Vector4 A = mat * Vector4(0, 0, 0, 1);
1299 	Vector4 B = mat * Vector4(1, 0, 0, 1);
1300 	Vector4 C = mat * Vector4(1, 1, 0, 1);
1301 	Vector4 D = mat * Vector4(0, 1, 0, 1);
1302 	Vector4 E = mat * Vector4(0, 0, 1, 1);
1303 	Vector4 F = mat * Vector4(1, 0, 1, 1);
1304 	Vector4 G = mat * Vector4(1, 1, 1, 1);
1305 	Vector4 H = mat * Vector4(0, 1, 1, 1);
1306 
1307 	// triangles instead of quads
1308 	AddCubeVertex(E.x, E.y, E.z, 0, 1, vertdata);  //Front
1309 	AddCubeVertex(F.x, F.y, F.z, 1, 1, vertdata);
1310 	AddCubeVertex(G.x, G.y, G.z, 1, 0, vertdata);
1311 	AddCubeVertex(G.x, G.y, G.z, 1, 0, vertdata);
1312 	AddCubeVertex(H.x, H.y, H.z, 0, 0, vertdata);
1313 	AddCubeVertex(E.x, E.y, E.z, 0, 1, vertdata);
1314 
1315 	AddCubeVertex(B.x, B.y, B.z, 0, 1, vertdata);  //Back
1316 	AddCubeVertex(A.x, A.y, A.z, 1, 1, vertdata);
1317 	AddCubeVertex(D.x, D.y, D.z, 1, 0, vertdata);
1318 	AddCubeVertex(D.x, D.y, D.z, 1, 0, vertdata);
1319 	AddCubeVertex(C.x, C.y, C.z, 0, 0, vertdata);
1320 	AddCubeVertex(B.x, B.y, B.z, 0, 1, vertdata);
1321 
1322 	AddCubeVertex(H.x, H.y, H.z, 0, 1, vertdata);  //Top
1323 	AddCubeVertex(G.x, G.y, G.z, 1, 1, vertdata);
1324 	AddCubeVertex(C.x, C.y, C.z, 1, 0, vertdata);
1325 	AddCubeVertex(C.x, C.y, C.z, 1, 0, vertdata);
1326 	AddCubeVertex(D.x, D.y, D.z, 0, 0, vertdata);
1327 	AddCubeVertex(H.x, H.y, H.z, 0, 1, vertdata);
1328 
1329 	AddCubeVertex(A.x, A.y, A.z, 0, 1, vertdata);  //Bottom
1330 	AddCubeVertex(B.x, B.y, B.z, 1, 1, vertdata);
1331 	AddCubeVertex(F.x, F.y, F.z, 1, 0, vertdata);
1332 	AddCubeVertex(F.x, F.y, F.z, 1, 0, vertdata);
1333 	AddCubeVertex(E.x, E.y, E.z, 0, 0, vertdata);
1334 	AddCubeVertex(A.x, A.y, A.z, 0, 1, vertdata);
1335 
1336 	AddCubeVertex(A.x, A.y, A.z, 0, 1, vertdata);  //Left
1337 	AddCubeVertex(E.x, E.y, E.z, 1, 1, vertdata);
1338 	AddCubeVertex(H.x, H.y, H.z, 1, 0, vertdata);
1339 	AddCubeVertex(H.x, H.y, H.z, 1, 0, vertdata);
1340 	AddCubeVertex(D.x, D.y, D.z, 0, 0, vertdata);
1341 	AddCubeVertex(A.x, A.y, A.z, 0, 1, vertdata);
1342 
1343 	AddCubeVertex(F.x, F.y, F.z, 0, 1, vertdata);  //Right
1344 	AddCubeVertex(B.x, B.y, B.z, 1, 1, vertdata);
1345 	AddCubeVertex(C.x, C.y, C.z, 1, 0, vertdata);
1346 	AddCubeVertex(C.x, C.y, C.z, 1, 0, vertdata);
1347 	AddCubeVertex(G.x, G.y, G.z, 0, 0, vertdata);
1348 	AddCubeVertex(F.x, F.y, F.z, 0, 1, vertdata);
1349 }
1350 
1351 //-----------------------------------------------------------------------------
1352 // Purpose: Draw all of the controllers as X/Y/Z lines
1353 //-----------------------------------------------------------------------------
1354 extern int gGraspingController;
1355 
DrawControllers()1356 void CMainApplication::DrawControllers()
1357 {
1358 	// don't draw controllers if somebody else has input focus
1359 	if (m_pHMD->IsInputFocusCapturedByAnotherProcess())
1360 		return;
1361 
1362 	std::vector<float> vertdataarray;
1363 
1364 	m_uiControllerVertcount = 0;
1365 	m_iTrackedControllerCount = 0;
1366 
1367 	for (vr::TrackedDeviceIndex_t unTrackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; ++unTrackedDevice)
1368 	{
1369 		if (!m_pHMD->IsTrackedDeviceConnected(unTrackedDevice))
1370 			continue;
1371 
1372 		if (m_pHMD->GetTrackedDeviceClass(unTrackedDevice) != vr::TrackedDeviceClass_Controller)
1373 			continue;
1374 
1375 		m_iTrackedControllerCount += 1;
1376 
1377 		if (!m_rTrackedDevicePose[unTrackedDevice].bPoseIsValid)
1378 			continue;
1379 
1380 		const Matrix4 &mat = m_rmat4DevicePose[unTrackedDevice];
1381 
1382 		Vector4 center = mat * Vector4(0, 0, 0, 1);
1383 
1384 		for (int i = 0; i < 3; ++i)
1385 		{
1386 			Vector3 color(0, 0, 0);
1387 			Vector4 point(0, 0, 0, 1);
1388 			point[i] += 0.05f;  // offset in X, Y, Z
1389 			color[i] = 1.0;     // R, G, B
1390 			point = mat * point;
1391 			vertdataarray.push_back(center.x);
1392 			vertdataarray.push_back(center.y);
1393 			vertdataarray.push_back(center.z);
1394 
1395 			vertdataarray.push_back(color.x);
1396 			vertdataarray.push_back(color.y);
1397 			vertdataarray.push_back(color.z);
1398 
1399 			vertdataarray.push_back(point.x);
1400 			vertdataarray.push_back(point.y);
1401 			vertdataarray.push_back(point.z);
1402 
1403 			vertdataarray.push_back(color.x);
1404 			vertdataarray.push_back(color.y);
1405 			vertdataarray.push_back(color.z);
1406 
1407 			m_uiControllerVertcount += 2;
1408 		}
1409 
1410 		Vector4 start = mat * Vector4(0, 0, -0.02f, 1);
1411 		Vector4 end = mat * Vector4(0, 0, -39.f, 1);
1412 		Vector3 color(.92f, .92f, .71f);
1413 
1414 		vertdataarray.push_back(start.x);
1415 		vertdataarray.push_back(start.y);
1416 		vertdataarray.push_back(start.z);
1417 		vertdataarray.push_back(color.x);
1418 		vertdataarray.push_back(color.y);
1419 		vertdataarray.push_back(color.z);
1420 
1421 		vertdataarray.push_back(end.x);
1422 		vertdataarray.push_back(end.y);
1423 		vertdataarray.push_back(end.z);
1424 		vertdataarray.push_back(color.x);
1425 		vertdataarray.push_back(color.y);
1426 		vertdataarray.push_back(color.z);
1427 		m_uiControllerVertcount += 2;
1428 	}
1429 
1430 	// Setup the VAO the first time through.
1431 	if (m_unControllerVAO == 0)
1432 	{
1433 		glGenVertexArrays(1, &m_unControllerVAO);
1434 		glBindVertexArray(m_unControllerVAO);
1435 
1436 		glGenBuffers(1, &m_glControllerVertBuffer);
1437 		glBindBuffer(GL_ARRAY_BUFFER, m_glControllerVertBuffer);
1438 
1439 		GLuint stride = 2 * 3 * sizeof(float);
1440 		GLuint offset = 0;
1441 
1442 		glEnableVertexAttribArray(0);
1443 		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
1444 
1445 		offset += sizeof(Vector3);
1446 		glEnableVertexAttribArray(1);
1447 		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (const void *)offset);
1448 
1449 		glBindVertexArray(0);
1450 	}
1451 
1452 	glBindBuffer(GL_ARRAY_BUFFER, m_glControllerVertBuffer);
1453 
1454 	// set vertex data if we have some
1455 	if (vertdataarray.size() > 0)
1456 	{
1457 		//$ TODO: Use glBufferSubData for this...
1458 		glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertdataarray.size(), &vertdataarray[0], GL_STREAM_DRAW);
1459 	}
1460 }
1461 
1462 //-----------------------------------------------------------------------------
1463 // Purpose:
1464 //-----------------------------------------------------------------------------
SetupCameras()1465 void CMainApplication::SetupCameras()
1466 {
1467 	m_mat4ProjectionLeft = GetHMDMatrixProjectionEye(vr::Eye_Left);
1468 	m_mat4ProjectionRight = GetHMDMatrixProjectionEye(vr::Eye_Right);
1469 	m_mat4eyePosLeft = GetHMDMatrixPoseEye(vr::Eye_Left);
1470 	m_mat4eyePosRight = GetHMDMatrixPoseEye(vr::Eye_Right);
1471 }
1472 
1473 //-----------------------------------------------------------------------------
1474 // Purpose:
1475 //-----------------------------------------------------------------------------
CreateFrameBuffer(int nWidth,int nHeight,FramebufferDesc & framebufferDesc)1476 bool CMainApplication::CreateFrameBuffer(int nWidth, int nHeight, FramebufferDesc &framebufferDesc)
1477 {
1478 	glGenFramebuffers(1, &framebufferDesc.m_nRenderFramebufferId);
1479 	glBindFramebuffer(GL_FRAMEBUFFER, framebufferDesc.m_nRenderFramebufferId);
1480 
1481 	glGenRenderbuffers(1, &framebufferDesc.m_nDepthBufferId);
1482 	glBindRenderbuffer(GL_RENDERBUFFER, framebufferDesc.m_nDepthBufferId);
1483 	glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT, nWidth, nHeight);
1484 	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, framebufferDesc.m_nDepthBufferId);
1485 
1486 	glGenTextures(1, &framebufferDesc.m_nRenderTextureId);
1487 	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, framebufferDesc.m_nRenderTextureId);
1488 	glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, nWidth, nHeight, true);
1489 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, framebufferDesc.m_nRenderTextureId, 0);
1490 
1491 	glGenFramebuffers(1, &framebufferDesc.m_nResolveFramebufferId);
1492 	glBindFramebuffer(GL_FRAMEBUFFER, framebufferDesc.m_nResolveFramebufferId);
1493 
1494 	glGenTextures(1, &framebufferDesc.m_nResolveTextureId);
1495 	glBindTexture(GL_TEXTURE_2D, framebufferDesc.m_nResolveTextureId);
1496 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1497 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1498 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1499 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferDesc.m_nResolveTextureId, 0);
1500 
1501 	// check FBO status
1502 	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1503 	if (status != GL_FRAMEBUFFER_COMPLETE)
1504 	{
1505 		return false;
1506 	}
1507 
1508 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
1509 
1510 	return true;
1511 }
1512 
1513 //-----------------------------------------------------------------------------
1514 // Purpose:
1515 //-----------------------------------------------------------------------------
SetupStereoRenderTargets()1516 bool CMainApplication::SetupStereoRenderTargets()
1517 {
1518 	if (!m_pHMD)
1519 		return false;
1520 
1521 	m_pHMD->GetRecommendedRenderTargetSize(&m_nRenderWidth, &m_nRenderHeight);
1522 
1523 	CreateFrameBuffer(m_nRenderWidth, m_nRenderHeight, leftEyeDesc);
1524 	CreateFrameBuffer(m_nRenderWidth, m_nRenderHeight, rightEyeDesc);
1525 
1526 	return true;
1527 }
1528 
1529 //-----------------------------------------------------------------------------
1530 // Purpose:
1531 //-----------------------------------------------------------------------------
SetupDistortion()1532 void CMainApplication::SetupDistortion()
1533 {
1534 	if (!m_pHMD)
1535 		return;
1536 
1537 	GLushort m_iLensGridSegmentCountH = 43;
1538 	GLushort m_iLensGridSegmentCountV = 43;
1539 
1540 	float w = (float)(1.0 / float(m_iLensGridSegmentCountH - 1));
1541 	float h = (float)(1.0 / float(m_iLensGridSegmentCountV - 1));
1542 
1543 	float u, v = 0;
1544 
1545 	std::vector<VertexDataLens> vVerts(0);
1546 	VertexDataLens vert;
1547 
1548 	//left eye distortion verts
1549 	float Xoffset = -1;
1550 	for (int y = 0; y < m_iLensGridSegmentCountV; y++)
1551 	{
1552 		for (int x = 0; x < m_iLensGridSegmentCountH; x++)
1553 		{
1554 			u = x * w;
1555 			v = 1 - y * h;
1556 			vert.position = Vector2(Xoffset + u, -1 + 2 * y * h);
1557 
1558 			vr::DistortionCoordinates_t dc0;
1559 			bool result = m_pHMD->ComputeDistortion(vr::Eye_Left, u, v, &dc0);
1560 			btAssert(result);
1561 			vert.texCoordRed = Vector2(dc0.rfRed[0], 1 - dc0.rfRed[1]);
1562 			vert.texCoordGreen = Vector2(dc0.rfGreen[0], 1 - dc0.rfGreen[1]);
1563 			vert.texCoordBlue = Vector2(dc0.rfBlue[0], 1 - dc0.rfBlue[1]);
1564 
1565 			vVerts.push_back(vert);
1566 		}
1567 	}
1568 
1569 	//right eye distortion verts
1570 	Xoffset = 0;
1571 	for (int y = 0; y < m_iLensGridSegmentCountV; y++)
1572 	{
1573 		for (int x = 0; x < m_iLensGridSegmentCountH; x++)
1574 		{
1575 			u = x * w;
1576 			v = 1 - y * h;
1577 			vert.position = Vector2(Xoffset + u, -1 + 2 * y * h);
1578 
1579 			vr::DistortionCoordinates_t dc0;
1580 			bool result = m_pHMD->ComputeDistortion(vr::Eye_Right, u, v, &dc0);
1581 			btAssert(result);
1582 			vert.texCoordRed = Vector2(dc0.rfRed[0], 1 - dc0.rfRed[1]);
1583 			vert.texCoordGreen = Vector2(dc0.rfGreen[0], 1 - dc0.rfGreen[1]);
1584 			vert.texCoordBlue = Vector2(dc0.rfBlue[0], 1 - dc0.rfBlue[1]);
1585 
1586 			vVerts.push_back(vert);
1587 		}
1588 	}
1589 
1590 	std::vector<GLushort> vIndices;
1591 	GLushort a, b, c, d;
1592 
1593 	GLushort offset = 0;
1594 	for (GLushort y = 0; y < m_iLensGridSegmentCountV - 1; y++)
1595 	{
1596 		for (GLushort x = 0; x < m_iLensGridSegmentCountH - 1; x++)
1597 		{
1598 			a = m_iLensGridSegmentCountH * y + x + offset;
1599 			b = m_iLensGridSegmentCountH * y + x + 1 + offset;
1600 			c = (y + 1) * m_iLensGridSegmentCountH + x + 1 + offset;
1601 			d = (y + 1) * m_iLensGridSegmentCountH + x + offset;
1602 			vIndices.push_back(a);
1603 			vIndices.push_back(b);
1604 			vIndices.push_back(c);
1605 
1606 			vIndices.push_back(a);
1607 			vIndices.push_back(c);
1608 			vIndices.push_back(d);
1609 		}
1610 	}
1611 
1612 	offset = (m_iLensGridSegmentCountH) * (m_iLensGridSegmentCountV);
1613 	for (GLushort y = 0; y < m_iLensGridSegmentCountV - 1; y++)
1614 	{
1615 		for (GLushort x = 0; x < m_iLensGridSegmentCountH - 1; x++)
1616 		{
1617 			a = m_iLensGridSegmentCountH * y + x + offset;
1618 			b = m_iLensGridSegmentCountH * y + x + 1 + offset;
1619 			c = (y + 1) * m_iLensGridSegmentCountH + x + 1 + offset;
1620 			d = (y + 1) * m_iLensGridSegmentCountH + x + offset;
1621 			vIndices.push_back(a);
1622 			vIndices.push_back(b);
1623 			vIndices.push_back(c);
1624 
1625 			vIndices.push_back(a);
1626 			vIndices.push_back(c);
1627 			vIndices.push_back(d);
1628 		}
1629 	}
1630 	m_uiIndexSize = vIndices.size();
1631 
1632 	glGenVertexArrays(1, &m_unLensVAO);
1633 	glBindVertexArray(m_unLensVAO);
1634 
1635 	glGenBuffers(1, &m_glIDVertBuffer);
1636 	glBindBuffer(GL_ARRAY_BUFFER, m_glIDVertBuffer);
1637 	glBufferData(GL_ARRAY_BUFFER, vVerts.size() * sizeof(VertexDataLens), &vVerts[0], GL_STATIC_DRAW);
1638 
1639 	glGenBuffers(1, &m_glIDIndexBuffer);
1640 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glIDIndexBuffer);
1641 	glBufferData(GL_ELEMENT_ARRAY_BUFFER, vIndices.size() * sizeof(GLushort), &vIndices[0], GL_STATIC_DRAW);
1642 
1643 	glEnableVertexAttribArray(0);
1644 	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexDataLens), (void *)offsetof(VertexDataLens, position));
1645 
1646 	glEnableVertexAttribArray(1);
1647 	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(VertexDataLens), (void *)offsetof(VertexDataLens, texCoordRed));
1648 
1649 	glEnableVertexAttribArray(2);
1650 	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexDataLens), (void *)offsetof(VertexDataLens, texCoordGreen));
1651 
1652 	glEnableVertexAttribArray(3);
1653 	glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexDataLens), (void *)offsetof(VertexDataLens, texCoordBlue));
1654 
1655 	glBindVertexArray(0);
1656 
1657 	glDisableVertexAttribArray(0);
1658 	glDisableVertexAttribArray(1);
1659 	glDisableVertexAttribArray(2);
1660 	glDisableVertexAttribArray(3);
1661 
1662 	glBindBuffer(GL_ARRAY_BUFFER, 0);
1663 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1664 }
1665 
1666 //-----------------------------------------------------------------------------
1667 // Purpose:
1668 //-----------------------------------------------------------------------------
RenderStereoTargets()1669 void CMainApplication::RenderStereoTargets()
1670 {
1671 	B3_PROFILE("CMainApplication::RenderStereoTargets");
1672 
1673 	btScalar dtSec = btScalar(m_clock.getTimeInSeconds());
1674 	dtSec = btMin(dtSec, btScalar(0.1));
1675 	sExample->stepSimulation(dtSec);
1676 	m_clock.reset();
1677 
1678 	glClearColor(0.15f, 0.15f, 0.18f, 1.0f);  // nice background color, but not black
1679 	glEnable(GL_MULTISAMPLE);
1680 
1681 	m_app->m_instancingRenderer->init();
1682 
1683 	Matrix4 rotYtoZ = rotYtoZ.identity();
1684 
1685 	//some Bullet apps (especially robotics related) require Z as up-axis)
1686 	if (m_app->getUpAxis() == 2)
1687 	{
1688 		rotYtoZ.rotateX(-90);
1689 	}
1690 
1691 	// Left Eye
1692 	{
1693 		Matrix4 viewMatLeft = m_mat4eyePosLeft * m_mat4HMDPose * rotYtoZ;
1694 		Matrix4 viewMatCenter = m_mat4HMDPose * rotYtoZ;
1695 		//0,1,2,3
1696 		//4,5,6,7,
1697 		//8,9,10,11
1698 		//12,13,14,15
1699 
1700 		//m_mat4eyePosLeft.get()[10]
1701 		//m_app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(
1702 		//	m_mat4eyePosLeft.get()[3],
1703 		//	m_mat4eyePosLeft.get()[7],
1704 		//	m_mat4eyePosLeft.get()[11]);
1705 		Matrix4 m;
1706 		m = viewMatCenter;
1707 		const float *mat = m.invertAffine().get();
1708 
1709 		/*printf("camera:\n,%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f",
1710 			mat[0],mat[1],mat[2],mat[3],
1711 			mat[4],mat[5],mat[6],mat[7],
1712 			mat[8],mat[9],mat[10],mat[11],
1713 			mat[12],mat[13],mat[14],mat[15]);
1714 			*/
1715 		float dist = 1;
1716 		m_app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(
1717 			mat[12] - dist * mat[8],
1718 			mat[13] - dist * mat[9],
1719 			mat[14] - dist * mat[10]);
1720 		m_app->m_instancingRenderer->getActiveCamera()->setCameraUpVector(mat[0], mat[1], mat[2]);
1721 		m_app->m_instancingRenderer->getActiveCamera()->setVRCamera(viewMatLeft.get(), m_mat4ProjectionLeft.get());
1722 		m_app->m_instancingRenderer->updateCamera(m_app->getUpAxis());
1723 		m_app->m_instancingRenderer->getActiveCamera()->setVRCamera(viewMatLeft.get(), m_mat4ProjectionLeft.get());
1724 	}
1725 
1726 	glBindFramebuffer(GL_FRAMEBUFFER, leftEyeDesc.m_nRenderFramebufferId);
1727 
1728 	m_app->m_window->startRendering();
1729 	glViewport(0, 0, m_nRenderWidth, m_nRenderHeight);
1730 
1731 	RenderScene(vr::Eye_Left);
1732 
1733 	m_app->m_instancingRenderer->setRenderFrameBuffer((unsigned int)leftEyeDesc.m_nRenderFramebufferId);
1734 
1735 	if (gDebugDrawFlags)
1736 	{
1737 		sExample->physicsDebugDraw(gDebugDrawFlags);
1738 	}
1739 	//else
1740 	{
1741 		sExample->renderScene();
1742 	}
1743 
1744 	//m_app->m_instancingRenderer->renderScene();
1745 	DrawGridData gridUp;
1746 	gridUp.upAxis = m_app->getUpAxis();
1747 	//	m_app->drawGrid(gridUp);
1748 
1749 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
1750 
1751 	glDisable(GL_MULTISAMPLE);
1752 
1753 	glBindFramebuffer(GL_READ_FRAMEBUFFER, leftEyeDesc.m_nRenderFramebufferId);
1754 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, leftEyeDesc.m_nResolveFramebufferId);
1755 
1756 	glBlitFramebuffer(0, 0, m_nRenderWidth, m_nRenderHeight, 0, 0, m_nRenderWidth, m_nRenderHeight,
1757 					  GL_COLOR_BUFFER_BIT,
1758 					  GL_LINEAR);
1759 
1760 	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1761 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1762 
1763 	glEnable(GL_MULTISAMPLE);
1764 
1765 	// Right Eye
1766 
1767 	{
1768 		Matrix4 viewMatRight = m_mat4eyePosRight * m_mat4HMDPose * rotYtoZ;
1769 		m_app->m_instancingRenderer->getActiveCamera()->setVRCamera(viewMatRight.get(), m_mat4ProjectionRight.get());
1770 		m_app->m_instancingRenderer->updateCamera(m_app->getUpAxis());
1771 		m_app->m_instancingRenderer->getActiveCamera()->setVRCamera(viewMatRight.get(), m_mat4ProjectionRight.get());
1772 	}
1773 
1774 	glBindFramebuffer(GL_FRAMEBUFFER, rightEyeDesc.m_nRenderFramebufferId);
1775 
1776 	m_app->m_window->startRendering();
1777 	glViewport(0, 0, m_nRenderWidth, m_nRenderHeight);
1778 
1779 	RenderScene(vr::Eye_Right);
1780 
1781 	m_app->m_instancingRenderer->setRenderFrameBuffer((unsigned int)rightEyeDesc.m_nRenderFramebufferId);
1782 	//m_app->m_renderer->renderScene();
1783 
1784 	if (gDebugDrawFlags)
1785 	{
1786 		sExample->physicsDebugDraw(gDebugDrawFlags);
1787 	}
1788 	//else
1789 	{
1790 		sExample->renderScene();
1791 	}
1792 
1793 	//m_app->drawGrid(gridUp);
1794 
1795 	m_app->m_instancingRenderer->setRenderFrameBuffer(0);
1796 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
1797 
1798 	glDisable(GL_MULTISAMPLE);
1799 
1800 	glBindFramebuffer(GL_READ_FRAMEBUFFER, rightEyeDesc.m_nRenderFramebufferId);
1801 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rightEyeDesc.m_nResolveFramebufferId);
1802 
1803 	glBlitFramebuffer(0, 0, m_nRenderWidth, m_nRenderHeight, 0, 0, m_nRenderWidth, m_nRenderHeight,
1804 					  GL_COLOR_BUFFER_BIT,
1805 					  GL_LINEAR);
1806 
1807 	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1808 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1809 }
1810 
1811 //-----------------------------------------------------------------------------
1812 // Purpose:
1813 //-----------------------------------------------------------------------------
RenderScene(vr::Hmd_Eye nEye)1814 void CMainApplication::RenderScene(vr::Hmd_Eye nEye)
1815 {
1816 	B3_PROFILE("RenderScene");
1817 
1818 	//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1819 	glEnable(GL_DEPTH_TEST);
1820 
1821 	if (m_bShowCubes)
1822 	{
1823 		glUseProgram(m_unSceneProgramID);
1824 		glUniformMatrix4fv(m_nSceneMatrixLocation, 1, GL_FALSE, GetCurrentViewProjectionMatrix(nEye).get());
1825 		glBindVertexArray(m_unSceneVAO);
1826 		glBindTexture(GL_TEXTURE_2D, m_iTexture);
1827 		glDrawArrays(GL_TRIANGLES, 0, m_uiVertcount);
1828 		glBindVertexArray(0);
1829 	}
1830 
1831 	bool bIsInputCapturedByAnotherProcess = m_pHMD->IsInputFocusCapturedByAnotherProcess();
1832 
1833 	if (gEnableVRRenderControllers)
1834 	{
1835 		if (!bIsInputCapturedByAnotherProcess)
1836 		{
1837 			// draw the controller axis lines
1838 			glUseProgram(m_unControllerTransformProgramID);
1839 			glUniformMatrix4fv(m_nControllerMatrixLocation, 1, GL_FALSE, GetCurrentViewProjectionMatrix(nEye).get());
1840 			glBindVertexArray(m_unControllerVAO);
1841 			glDrawArrays(GL_LINES, 0, m_uiControllerVertcount);
1842 			glBindVertexArray(0);
1843 		}
1844 
1845 		// ----- Render Model rendering -----
1846 		glUseProgram(m_unRenderModelProgramID);
1847 
1848 		for (uint32_t unTrackedDevice = 0; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; unTrackedDevice++)
1849 		{
1850 			if (!m_rTrackedDeviceToRenderModel[unTrackedDevice] || !m_rbShowTrackedDevice[unTrackedDevice])
1851 				continue;
1852 
1853 			const vr::TrackedDevicePose_t &pose = m_rTrackedDevicePose[unTrackedDevice];
1854 			if (!pose.bPoseIsValid)
1855 				continue;
1856 
1857 			if (bIsInputCapturedByAnotherProcess && m_pHMD->GetTrackedDeviceClass(unTrackedDevice) == vr::TrackedDeviceClass_Controller)
1858 				continue;
1859 
1860 			const Matrix4 &matDeviceToTracking = m_rmat4DevicePose[unTrackedDevice];
1861 			Matrix4 matMVP = GetCurrentViewProjectionMatrix(nEye) * matDeviceToTracking;
1862 			glUniformMatrix4fv(m_nRenderModelMatrixLocation, 1, GL_FALSE, matMVP.get());
1863 
1864 			m_rTrackedDeviceToRenderModel[unTrackedDevice]->Draw();
1865 		}
1866 	}
1867 	glUseProgram(0);
1868 }
1869 
1870 //-----------------------------------------------------------------------------
1871 // Purpose:
1872 //-----------------------------------------------------------------------------
RenderDistortion()1873 void CMainApplication::RenderDistortion()
1874 {
1875 	glDisable(GL_DEPTH_TEST);
1876 	glViewport(0, 0, m_nWindowWidth, m_nWindowHeight);
1877 
1878 	glBindVertexArray(m_unLensVAO);
1879 	glUseProgram(m_unLensProgramID);
1880 
1881 	//render left lens (first half of index array )
1882 	glBindTexture(GL_TEXTURE_2D, leftEyeDesc.m_nResolveTextureId);
1883 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1884 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1885 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1886 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1887 	glDrawElements(GL_TRIANGLES, m_uiIndexSize / 2, GL_UNSIGNED_SHORT, 0);
1888 
1889 	//render right lens (second half of index array )
1890 	glBindTexture(GL_TEXTURE_2D, rightEyeDesc.m_nResolveTextureId);
1891 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1892 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1893 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1894 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1895 	glDrawElements(GL_TRIANGLES, m_uiIndexSize / 2, GL_UNSIGNED_SHORT, (const void *)(m_uiIndexSize));
1896 
1897 	glBindVertexArray(0);
1898 	glUseProgram(0);
1899 }
1900 
1901 //-----------------------------------------------------------------------------
1902 // Purpose:
1903 //-----------------------------------------------------------------------------
GetHMDMatrixProjectionEye(vr::Hmd_Eye nEye)1904 Matrix4 CMainApplication::GetHMDMatrixProjectionEye(vr::Hmd_Eye nEye)
1905 {
1906 	if (!m_pHMD)
1907 		return Matrix4();
1908 
1909 	vr::HmdMatrix44_t mat = m_pHMD->GetProjectionMatrix(nEye, m_fNearClip, m_fFarClip);
1910 
1911 	return Matrix4(
1912 		mat.m[0][0], mat.m[1][0], mat.m[2][0], mat.m[3][0],
1913 		mat.m[0][1], mat.m[1][1], mat.m[2][1], mat.m[3][1],
1914 		mat.m[0][2], mat.m[1][2], mat.m[2][2], mat.m[3][2],
1915 		mat.m[0][3], mat.m[1][3], mat.m[2][3], mat.m[3][3]);
1916 }
1917 
1918 //-----------------------------------------------------------------------------
1919 // Purpose:
1920 //-----------------------------------------------------------------------------
GetHMDMatrixPoseEye(vr::Hmd_Eye nEye)1921 Matrix4 CMainApplication::GetHMDMatrixPoseEye(vr::Hmd_Eye nEye)
1922 {
1923 	if (!m_pHMD)
1924 		return Matrix4();
1925 
1926 	vr::HmdMatrix34_t matEyeRight = m_pHMD->GetEyeToHeadTransform(nEye);
1927 	Matrix4 matrixObj(
1928 		matEyeRight.m[0][0], matEyeRight.m[1][0], matEyeRight.m[2][0], 0.0,
1929 		matEyeRight.m[0][1], matEyeRight.m[1][1], matEyeRight.m[2][1], 0.0,
1930 		matEyeRight.m[0][2], matEyeRight.m[1][2], matEyeRight.m[2][2], 0.0,
1931 		matEyeRight.m[0][3], matEyeRight.m[1][3], matEyeRight.m[2][3], 1.0f);
1932 
1933 	return matrixObj.invert();
1934 }
1935 
1936 //-----------------------------------------------------------------------------
1937 // Purpose:
1938 //-----------------------------------------------------------------------------
GetCurrentViewProjectionMatrix(vr::Hmd_Eye nEye)1939 Matrix4 CMainApplication::GetCurrentViewProjectionMatrix(vr::Hmd_Eye nEye)
1940 {
1941 	Matrix4 matMVP;
1942 	if (nEye == vr::Eye_Left)
1943 	{
1944 		matMVP = m_mat4ProjectionLeft * m_mat4eyePosLeft * m_mat4HMDPose;
1945 	}
1946 	else if (nEye == vr::Eye_Right)
1947 	{
1948 		matMVP = m_mat4ProjectionRight * m_mat4eyePosRight * m_mat4HMDPose;
1949 	}
1950 
1951 	return matMVP;
1952 }
1953 
1954 //-----------------------------------------------------------------------------
1955 // Purpose:
1956 //-----------------------------------------------------------------------------
UpdateHMDMatrixPose()1957 void CMainApplication::UpdateHMDMatrixPose()
1958 {
1959 	if (!m_pHMD)
1960 		return;
1961 	{
1962 		B3_PROFILE("WaitGetPoses");
1963 		vr::VRCompositor()->WaitGetPoses(m_rTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0);
1964 	}
1965 
1966 	m_iValidPoseCount = 0;
1967 	m_strPoseClasses = "";
1968 	{
1969 		B3_PROFILE("for loop");
1970 
1971 		for (int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice)
1972 		{
1973 			if (m_rTrackedDevicePose[nDevice].bPoseIsValid)
1974 			{
1975 				m_iValidPoseCount++;
1976 				m_rmat4DevicePose[nDevice] = ConvertSteamVRMatrixToMatrix4(m_rTrackedDevicePose[nDevice].mDeviceToAbsoluteTracking);
1977 				if (m_rDevClassChar[nDevice] == 0)
1978 				{
1979 					switch (m_pHMD->GetTrackedDeviceClass(nDevice))
1980 					{
1981 						case vr::TrackedDeviceClass_Controller:
1982 							m_rDevClassChar[nDevice] = 'C';
1983 							break;
1984 						case vr::TrackedDeviceClass_HMD:
1985 							m_rDevClassChar[nDevice] = 'H';
1986 							break;
1987 						case vr::TrackedDeviceClass_Invalid:
1988 							m_rDevClassChar[nDevice] = 'I';
1989 							break;
1990 						case vr::TrackedDeviceClass_TrackingReference:
1991 							m_rDevClassChar[nDevice] = 'T';
1992 							break;
1993 						case vr::TrackedDeviceClass_GenericTracker:
1994 							m_rDevClassChar[nDevice] = 'G';
1995 							break;
1996 						default:
1997 							m_rDevClassChar[nDevice] = '?';
1998 							break;
1999 					}
2000 				}
2001 				m_strPoseClasses += m_rDevClassChar[nDevice];
2002 			}
2003 		}
2004 	}
2005 	{
2006 		B3_PROFILE("m_mat4HMDPose invert");
2007 
2008 		if (m_rTrackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid)
2009 		{
2010 			m_mat4HMDPose = m_rmat4DevicePose[vr::k_unTrackedDeviceIndex_Hmd].invert();
2011 		}
2012 	}
2013 }
2014 
2015 //-----------------------------------------------------------------------------
2016 // Purpose: Finds a render model we've already loaded or loads a new one
2017 //-----------------------------------------------------------------------------
FindOrLoadRenderModel(const char * pchRenderModelName)2018 CGLRenderModel *CMainApplication::FindOrLoadRenderModel(const char *pchRenderModelName)
2019 {
2020 	CGLRenderModel *pRenderModel = NULL;
2021 	for (std::vector<CGLRenderModel *>::iterator i = m_vecRenderModels.begin(); i != m_vecRenderModels.end(); i++)
2022 	{
2023 		if (!stricmp((*i)->GetName().c_str(), pchRenderModelName))
2024 		{
2025 			pRenderModel = *i;
2026 			break;
2027 		}
2028 	}
2029 
2030 	// load the model if we didn't find one
2031 	if (!pRenderModel)
2032 	{
2033 		vr::RenderModel_t *pModel;
2034 		vr::EVRRenderModelError error;
2035 		while (1)
2036 		{
2037 			error = vr::VRRenderModels()->LoadRenderModel_Async(pchRenderModelName, &pModel);
2038 			if (error != vr::VRRenderModelError_Loading)
2039 				break;
2040 
2041 			ThreadSleep(1);
2042 		}
2043 
2044 		if (error != vr::VRRenderModelError_None)
2045 		{
2046 			b3Printf("Unable to load render model %s - %s\n", pchRenderModelName, vr::VRRenderModels()->GetRenderModelErrorNameFromEnum(error));
2047 			return NULL;  // move on to the next tracked device
2048 		}
2049 
2050 		vr::RenderModel_TextureMap_t *pTexture;
2051 		while (1)
2052 		{
2053 			error = vr::VRRenderModels()->LoadTexture_Async(pModel->diffuseTextureId, &pTexture);
2054 			if (error != vr::VRRenderModelError_Loading)
2055 				break;
2056 
2057 			ThreadSleep(1);
2058 		}
2059 
2060 		if (error != vr::VRRenderModelError_None)
2061 		{
2062 			b3Printf("Unable to load render texture id:%d for render model %s\n", pModel->diffuseTextureId, pchRenderModelName);
2063 			vr::VRRenderModels()->FreeRenderModel(pModel);
2064 			return NULL;  // move on to the next tracked device
2065 		}
2066 
2067 		pRenderModel = new CGLRenderModel(pchRenderModelName);
2068 		if (!pRenderModel->BInit(*pModel, *pTexture))
2069 		{
2070 			b3Printf("Unable to create GL model from render model %s\n", pchRenderModelName);
2071 			delete pRenderModel;
2072 			pRenderModel = NULL;
2073 		}
2074 		else
2075 		{
2076 			m_vecRenderModels.push_back(pRenderModel);
2077 		}
2078 		vr::VRRenderModels()->FreeRenderModel(pModel);
2079 		vr::VRRenderModels()->FreeTexture(pTexture);
2080 	}
2081 	return pRenderModel;
2082 }
2083 
2084 //-----------------------------------------------------------------------------
2085 // Purpose: Create/destroy GL a Render Model for a single tracked device
2086 //-----------------------------------------------------------------------------
SetupRenderModelForTrackedDevice(vr::TrackedDeviceIndex_t unTrackedDeviceIndex)2087 void CMainApplication::SetupRenderModelForTrackedDevice(vr::TrackedDeviceIndex_t unTrackedDeviceIndex)
2088 {
2089 	if (unTrackedDeviceIndex >= vr::k_unMaxTrackedDeviceCount)
2090 		return;
2091 
2092 	// try to find a model we've already set up
2093 	std::string sRenderModelName = GetTrackedDeviceString(m_pHMD, unTrackedDeviceIndex, vr::Prop_RenderModelName_String);
2094 	CGLRenderModel *pRenderModel = FindOrLoadRenderModel(sRenderModelName.c_str());
2095 	if (!pRenderModel)
2096 	{
2097 		std::string sTrackingSystemName = GetTrackedDeviceString(m_pHMD, unTrackedDeviceIndex, vr::Prop_TrackingSystemName_String);
2098 		b3Printf("Unable to load render model for tracked device %d (%s.%s)", unTrackedDeviceIndex, sTrackingSystemName.c_str(), sRenderModelName.c_str());
2099 	}
2100 	else
2101 	{
2102 		m_rTrackedDeviceToRenderModel[unTrackedDeviceIndex] = pRenderModel;
2103 		m_rbShowTrackedDevice[unTrackedDeviceIndex] = true;
2104 	}
2105 }
2106 
2107 //-----------------------------------------------------------------------------
2108 // Purpose: Create/destroy GL Render Models
2109 //-----------------------------------------------------------------------------
SetupRenderModels()2110 void CMainApplication::SetupRenderModels()
2111 {
2112 	memset(m_rTrackedDeviceToRenderModel, 0, sizeof(m_rTrackedDeviceToRenderModel));
2113 
2114 	if (!m_pHMD)
2115 		return;
2116 
2117 	for (uint32_t unTrackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; unTrackedDevice++)
2118 	{
2119 		if (!m_pHMD->IsTrackedDeviceConnected(unTrackedDevice))
2120 			continue;
2121 
2122 		SetupRenderModelForTrackedDevice(unTrackedDevice);
2123 	}
2124 }
2125 
2126 //-----------------------------------------------------------------------------
2127 // Purpose: Converts a SteamVR matrix to our local matrix class
2128 //-----------------------------------------------------------------------------
ConvertSteamVRMatrixToMatrix4(const vr::HmdMatrix34_t & matPose)2129 Matrix4 CMainApplication::ConvertSteamVRMatrixToMatrix4(const vr::HmdMatrix34_t &matPose)
2130 {
2131 	Matrix4 matrixObj(
2132 		matPose.m[0][0], matPose.m[1][0], matPose.m[2][0], 0.0,
2133 		matPose.m[0][1], matPose.m[1][1], matPose.m[2][1], 0.0,
2134 		matPose.m[0][2], matPose.m[1][2], matPose.m[2][2], 0.0,
2135 		matPose.m[0][3], matPose.m[1][3], matPose.m[2][3], 1.0f);
2136 	return matrixObj;
2137 }
2138 
2139 //-----------------------------------------------------------------------------
2140 // Purpose: Create/destroy GL Render Models
2141 //-----------------------------------------------------------------------------
CGLRenderModel(const std::string & sRenderModelName)2142 CGLRenderModel::CGLRenderModel(const std::string &sRenderModelName)
2143 	: m_sModelName(sRenderModelName)
2144 {
2145 	m_glIndexBuffer = 0;
2146 	m_glVertArray = 0;
2147 	m_glVertBuffer = 0;
2148 	m_glTexture = 0;
2149 }
2150 
~CGLRenderModel()2151 CGLRenderModel::~CGLRenderModel()
2152 {
2153 	Cleanup();
2154 }
2155 
2156 //-----------------------------------------------------------------------------
2157 // Purpose: Allocates and populates the GL resources for a render model
2158 //-----------------------------------------------------------------------------
BInit(const vr::RenderModel_t & vrModel,const vr::RenderModel_TextureMap_t & vrDiffuseTexture)2159 bool CGLRenderModel::BInit(const vr::RenderModel_t &vrModel, const vr::RenderModel_TextureMap_t &vrDiffuseTexture)
2160 {
2161 	// create and bind a VAO to hold state for this model
2162 	glGenVertexArrays(1, &m_glVertArray);
2163 	glBindVertexArray(m_glVertArray);
2164 
2165 	// Populate a vertex buffer
2166 	glGenBuffers(1, &m_glVertBuffer);
2167 	glBindBuffer(GL_ARRAY_BUFFER, m_glVertBuffer);
2168 	glBufferData(GL_ARRAY_BUFFER, sizeof(vr::RenderModel_Vertex_t) * vrModel.unVertexCount, vrModel.rVertexData, GL_STATIC_DRAW);
2169 
2170 	// Identify the components in the vertex buffer
2171 	glEnableVertexAttribArray(0);
2172 	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vr::RenderModel_Vertex_t), (void *)offsetof(vr::RenderModel_Vertex_t, vPosition));
2173 	glEnableVertexAttribArray(1);
2174 	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vr::RenderModel_Vertex_t), (void *)offsetof(vr::RenderModel_Vertex_t, vNormal));
2175 	glEnableVertexAttribArray(2);
2176 	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vr::RenderModel_Vertex_t), (void *)offsetof(vr::RenderModel_Vertex_t, rfTextureCoord));
2177 
2178 	// Create and populate the index buffer
2179 	glGenBuffers(1, &m_glIndexBuffer);
2180 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glIndexBuffer);
2181 	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint16_t) * vrModel.unTriangleCount * 3, vrModel.rIndexData, GL_STATIC_DRAW);
2182 
2183 	glBindVertexArray(0);
2184 
2185 	// create and populate the texture
2186 	glGenTextures(1, &m_glTexture);
2187 	glBindTexture(GL_TEXTURE_2D, m_glTexture);
2188 
2189 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vrDiffuseTexture.unWidth, vrDiffuseTexture.unHeight,
2190 				 0, GL_RGBA, GL_UNSIGNED_BYTE, vrDiffuseTexture.rubTextureMapData);
2191 
2192 	// If this renders black ask McJohn what's wrong.
2193 	glGenerateMipmap(GL_TEXTURE_2D);
2194 
2195 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2196 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2197 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2198 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
2199 	GLfloat fLargest;
2200 	glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &fLargest);
2201 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, fLargest);
2202 	glBindTexture(GL_TEXTURE_2D, 0);
2203 
2204 	m_unVertexCount = vrModel.unTriangleCount * 3;
2205 
2206 	return true;
2207 }
2208 
2209 //-----------------------------------------------------------------------------
2210 // Purpose: Frees the GL resources for a render model
2211 //-----------------------------------------------------------------------------
Cleanup()2212 void CGLRenderModel::Cleanup()
2213 {
2214 	if (m_glVertBuffer)
2215 	{
2216 		glDeleteBuffers(1, &m_glIndexBuffer);
2217 		glDeleteVertexArrays(1, &m_glVertArray);
2218 		glDeleteBuffers(1, &m_glVertBuffer);
2219 		m_glIndexBuffer = 0;
2220 		m_glVertArray = 0;
2221 		m_glVertBuffer = 0;
2222 	}
2223 }
2224 
2225 //-----------------------------------------------------------------------------
2226 // Purpose: Draws the render model
2227 //-----------------------------------------------------------------------------
Draw()2228 void CGLRenderModel::Draw()
2229 {
2230 	glBindVertexArray(m_glVertArray);
2231 
2232 	glActiveTexture(GL_TEXTURE0);
2233 	glBindTexture(GL_TEXTURE_2D, m_glTexture);
2234 
2235 	glDrawElements(GL_TRIANGLES, m_unVertexCount, GL_UNSIGNED_SHORT, 0);
2236 
2237 	glBindVertexArray(0);
2238 }
2239 
2240 //-----------------------------------------------------------------------------
2241 // Purpose:
2242 //-----------------------------------------------------------------------------
main(int argc,char * argv[])2243 int main(int argc, char *argv[])
2244 {
2245 	b3CommandLineArgs args(argc, argv);
2246 	if (args.CheckCmdLineFlag("disable_desktop_gl"))
2247 	{
2248 		gDisableDesktopGL = true;
2249 	}
2250 	if (args.CheckCmdLineFlag("tracing"))
2251 	{
2252 		b3ChromeUtilsStartTimings();
2253 		b3ChromeUtilsEnableProfiling();
2254 	}
2255 
2256 	args.GetCmdLineArgument("max_num_object_capacity", maxNumObjectCapacity);
2257 	args.GetCmdLineArgument("max_shape_capacity_in_bytes", maxShapeCapacityInBytes);
2258 	args.GetCmdLineArgument("shared_memory_key", gSharedMemoryKey);
2259 
2260 #ifdef BT_USE_CUSTOM_PROFILER
2261 	b3SetCustomEnterProfileZoneFunc(dcEnter);
2262 	b3SetCustomLeaveProfileZoneFunc(dcLeave);
2263 #endif
2264 
2265 	CMainApplication *pMainApplication = new CMainApplication(argc, argv);
2266 
2267 	if (!pMainApplication->BInit())
2268 	{
2269 		pMainApplication->Shutdown();
2270 		return 1;
2271 	}
2272 
2273 	if (sExample)
2274 	{
2275 		//until we have a proper VR gui, always assume we want the hard-coded default robot assets
2276 		char *newargv[2];
2277 		char *t0 = (char *)"--robotassets";
2278 		newargv[0] = t0;
2279 		newargv[1] = t0;
2280 		sExample->processCommandLineArgs(2, newargv);
2281 		sExample->processCommandLineArgs(argc, argv);
2282 	}
2283 
2284 	char *gVideoFileName = 0;
2285 	args.GetCmdLineArgument("mp4", gVideoFileName);
2286 	if (gVideoFileName)
2287 		pMainApplication->getApp()->dumpFramesToVideo(gVideoFileName);
2288 
2289 #ifndef B3_USE_GLFW
2290 #ifdef _WIN32
2291 	//request disable VSYNC
2292 	typedef bool(APIENTRY * PFNWGLSWAPINTERVALFARPROC)(int);
2293 	PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;
2294 	wglSwapIntervalEXT =
2295 		(PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT");
2296 	if (wglSwapIntervalEXT)
2297 		wglSwapIntervalEXT(0);
2298 #endif
2299 #endif
2300 #ifdef __APPLE__
2301 	GLint sync = 0;
2302 	CGLContextObj ctx = CGLGetCurrentContext();
2303 	CGLSetParameter(ctx, kCGLCPSwapInterval, &sync);
2304 #endif
2305 
2306 	pMainApplication->RunMainLoop();
2307 
2308 	pMainApplication->Shutdown();
2309 
2310 	if (args.CheckCmdLineFlag("tracing"))
2311 	{
2312 		b3ChromeUtilsStopTimingsAndWriteJsonFile("timings");
2313 	}
2314 
2315 	return 0;
2316 }
2317 #endif  //BT_ENABLE_VR
2318