12#include <GLFW/glfw3.h>
15#include <glm/gtc/matrix_transform.hpp>
19#define GLFW_EXPOSE_NATIVE_WIN32
20#define GLFW_EXPOSE_NATIVE_WGL
21#include "glfw3native.h"
23#include <shellscalingapi.h>
42#define WEAVING_ENABLED
44using namespace std::chrono_literals;
47bool contextValid =
false;
49bool initializeSrObjects();
63 <<
"ContextInvalid event received: "
70 initializeSrObjects();
77 std::cout <<
"Unknown event type" << std::endl;
89 glm::vec3 left, right;
90 MyEyes(
SR::EyeTracker* tracker) : left(-30, 0, 600), right(30, 0, 600) {
124std::mutex constructNewContextMutex;
125MyEyes* eyes =
nullptr;
126SystemEventMonitor* listener =
nullptr;
128bool createSrContext() {
129 if (context !=
nullptr) {
133 while (context ==
nullptr && contextValid ==
false) {
139 std::cout <<
"Server not available, trying again in 0.5 second" << std::endl;
140 std::this_thread::sleep_for(500ms);
146bool initializeSrObjects() {
147 std::lock_guard<std::mutex> lock(constructNewContextMutex);
150 if (eyes !=
nullptr) {
154 if (listener !=
nullptr) {
159 while (weaver !=
nullptr) {
161 std::this_thread::sleep_for(10ms);
164 if (createSrContext() ==
false) {
171 listener =
new SystemEventMonitor();
180glm::mat4 CalculateModel()
182 const float size = 20.0;
183 using namespace std::chrono;
184 auto now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
185 const int ms_per_revolution = 5000;
186 float angle = float((2 * 3.1415 / ms_per_revolution) * (now % ms_per_revolution));
188 glm::mat4 Model = glm::mat4();
189 Model = scale(Model, glm::vec3(size, size, size));
190 Model = translate(Model, glm::vec3(0, 1, 0));
191 Model = rotate(Model, angle, glm::vec3(0, 1, 0));
196float screenWidth_mm = 697.0;
197float screenHeight_mm = 394.0;
199glm::mat4 CalculateProjection(glm::vec3 &eye)
203 const float near = 1.0;
204 const float far = 10000.0;
205 const glm::vec3 pa(-screenWidth_mm / 2, screenHeight_mm / 2, 0);
206 const glm::vec3 pb(screenWidth_mm / 2, screenHeight_mm / 2, 0);
207 const glm::vec3 pc(-screenWidth_mm / 2, -screenHeight_mm / 2, 0);
209 const glm::vec3 vr(1, 0, 0);
210 const glm::vec3 vu(0, 1, 0);
211 const glm::vec3 vn(0, 0, 1);
214 glm::vec3 va = pa - eye;
215 glm::vec3 vb = pb - eye;
216 glm::vec3 vc = pc - eye;
219 float distance = -dot(va, vn);
222 float l = dot(vr, va) * near / distance;
223 float r = dot(vr, vb) * near / distance;
224 float b = dot(vu, vc) * near / distance;
225 float t = dot(vu, va) * near / distance;
228 glm::mat4 _frustum = glm::frustum(l, r, b, t, near, far);
232 vr[0], vu[0], vn[0], 0,
233 vr[1], vu[1], vn[1], 0,
234 vr[2], vu[2], vn[2], 0,
239 glm::mat4 _translate = translate(glm::mat4(), -eye);
242 return _frustum * M * _translate;
245void RenderScene(
GLuint MatrixID,
const size_t renderWidth,
const size_t renderHeight, glm::vec3 leftEye, glm::vec3 rightEye, Pyramid& pyramid) {
248 glm::mat4 View = glm::mat4();
249 glm::mat4 Model = CalculateModel();
252 glm::mat4 Projection = CalculateProjection(leftEye);
253 glm::mat4 MVP = Projection * View * Model;
254 glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
257 glViewport(0, 0, renderWidth, renderHeight);
263 Projection = CalculateProjection(rightEye);
264 MVP = Projection * View * Model;
265 glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
268 glViewport(renderWidth, 0, renderWidth, renderHeight);
276bool ensureWindowFitsToMonitor() {
278 HMONITOR windowMonitor = MonitorFromWindow(glfwGetWin32Window(window), MONITOR_DEFAULTTONEAREST);
281 if (!windowMonitor) {
286 MONITORINFO monitorInfo;
287 ZeroMemory(&monitorInfo,
sizeof(monitorInfo));
288 monitorInfo.cbSize =
sizeof(monitorInfo);
289 GetMonitorInfoA(windowMonitor, &monitorInfo);
293 GetWindowRect(glfwGetWin32Window(window), &windowRect);
296 if (windowRect.left != monitorInfo.rcMonitor.left ||
297 windowRect.right != monitorInfo.rcMonitor.right ||
298 windowRect.top != monitorInfo.rcMonitor.top ||
299 windowRect.bottom != monitorInfo.rcMonitor.bottom) {
301 glfwSetWindowPos(window,
302 monitorInfo.rcMonitor.left,
303 monitorInfo.rcMonitor.top
305 glfwSetWindowSize(window,
306 monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
307 monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top
315bool windowFitsToMonitor =
false;
317void windowMoveCallback(GLFWwindow* window,
int xPos,
int yPos) {
318 windowFitsToMonitor =
false;
321void monitorConfigurationCallback(GLFWmonitor* monitor,
int event) {
322 windowFitsToMonitor =
false;
328 SetProcessDpiAwareness(PROCESS_DPI_AWARENESS::PROCESS_PER_MONITOR_DPI_AWARE);
333 fprintf(stderr,
"Failed to initialize GLFW\n");
337 glfwWindowHint(GLFW_SAMPLES, 4);
338 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
339 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
340 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
341 glfwWindowHint(GLFW_AUTO_ICONIFY, GL_FALSE);
342 glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
345 GLFWmonitor* monitor = glfwGetPrimaryMonitor();
346 const GLFWvidmode* mode = glfwGetVideoMode(monitor);
347 window = glfwCreateWindow(mode->width, mode->height,
"Simulated Reality - Cube demo", NULL, NULL);
348 if (window == NULL) {
349 fprintf(stderr,
"Failed to open GLFW window.\n");
353 windowFitsToMonitor =
true;
354 glfwMakeContextCurrent(window);
358 glewExperimental =
true;
359 if (glewInit() != GLEW_OK) {
360 fprintf(stderr,
"Failed to initialize GLEW\n");
366 glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
367 glfwSetWindowPosCallback(window, windowMoveCallback);
368 glfwSetMonitorCallback(monitorConfigurationCallback);
370 glClearColor(0.5f, 0.5f, 0.5f, 0.0);
371 glEnable(GL_DEPTH_TEST);
372 glDepthFunc(GL_LESS);
373 GLuint programID = loadBasicShaders();
374 GLuint MatrixID = glGetUniformLocation(programID,
"MVP");
377 initializeSrObjects();
382 glUseProgram(programID);
385 int screenWidth_mm_i, screenHeight_mm_i;
386 glfwGetMonitorPhysicalSize(monitor, &screenWidth_mm_i, &screenHeight_mm_i);
387 screenWidth_mm = screenWidth_mm_i;
388 screenHeight_mm = screenHeight_mm_i;
393#ifdef WEAVING_ENABLED
403 const size_t renderWidth = mode->width * 0.5f;
404 const size_t renderHeight = mode->height;
407#ifdef WEAVING_ENABLED
418#ifdef WEAVING_ENABLED
421 if (contextValid && weaver !=
nullptr) {
425 glBindFramebuffer(GL_FRAMEBUFFER, 0);
429 glUseProgram(programID);
430 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
432 RenderScene(MatrixID, renderWidth, renderHeight, eyes->left, eyes->right, pyramid);
435 RenderScene(MatrixID, renderWidth, renderHeight, { -30, 0, 600 }, { 30, 0, 600 }, pyramid);
438#ifdef WEAVING_ENABLED
439 int windowWidth, windowHeight;
440 glfwGetFramebufferSize(window, &windowWidth, &windowHeight);
442 glBindFramebuffer(GL_FRAMEBUFFER, 0);
444 glViewport(0, 0, windowWidth, windowHeight);
448 if (contextValid && weaver !=
nullptr) {
449 weaver->
weave((
unsigned int)windowWidth, (
unsigned int)windowHeight, 0, 0);
455 glfwSwapBuffers(window);
458 if (!windowFitsToMonitor) {
459 windowFitsToMonitor = ensureWindowFitsToMonitor();
462#ifdef WEAVING_ENABLED
464 if (contextValid && weaver ==
nullptr) {
475 if (contextValid ==
false && weaver !=
nullptr) {
482 glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS
483 && glfwWindowShouldClose(window) == 0
486#ifdef WEAVING_ENABLED
488 if (weaver !=
nullptr) {
494 glDeleteProgram(programID);
498 if (contextValid ==
false) {
500 std::this_thread::sleep_for(3000ms);
void * SRContext
Definition: admin_c.h:15
Interface for listening to SR_eyePair updates.
Definition: eyepairlistener.h:20
virtual void accept(const SR_eyePair &frame)=0
Accept an SR_eyePair frame.
Sense class which provides face tracking functionality to the SR system.
Definition: eyetracker.h:40
static EyeTracker * create(SRContext &context)
Creates a functional EyeTracker instance.
virtual std::shared_ptr< EyePairStream > openEyePairStream(EyePairListener *listener)=0
Creates a EyePairStream for listener to be connected to.
GLuint getFrameBuffer()
Returns the buffer that will be used to create a weaved imaged. This buffer expects a side-by-side im...
void weave(unsigned int width, unsigned int height)
Can be called to render a weaved image of a certain size to the currently bound framebuffer.
Interface for listening to SR_handPose updates.
Definition: handposelistener.h:39
virtual void accept(const SR_handPose &handPose)=0
Accept an SR_handPose frame.
Sense class which provides hand tracking functionality to the SR system.
Definition: handtracker.h:46
virtual std::shared_ptr< HandPoseStream > openHandPoseStream(HandPoseListener *listener)=0
Creates a HandPoseStream for listener to be connected to.
static HandTracker * create(SRContext &context)
Creates a functional HandTracker instance.
Definition: glweaver.h:152
void setLatencyInFrames(uint64_t latencyInFrames)
Set the latency to match the expected duration of the full rendering pipeline in number of frames....
Maintains WorldObject and Sense objects during the application lifetime.
Definition: srcontext.h:80
void initialize()
Initialize all senses.
Class of WorldObject representing the screen in real space.
Definition: screen.h:39
const int getPhysicalResolutionWidth()
Get the horizontal native resolution of the physical screen itself.
static Screen * create(SRContext &context)
Creates an instance of a Screen class.
const int getPhysicalResolutionHeight()
Get the vertical native resolution of the physical screen itself.
Class of Exception which indicates that a SR Service was not available to connect with.
Definition: exception.h:101
Interface for listening to SR_systemEvent updates.
Definition: systemeventlistener.h:30
virtual void accept(const SystemEvent &frame)=0
Accept an SR_systemEvent frame.
Class containing dynamic-length event messages.
Definition: systemevent.h:65
uint64_t time
Time since epoch in microseconds.
Definition: systemevent.h:67
SR_eventType eventType
Type of the event.
Definition: systemevent.h:68
std::string message
Full description of the event.
Definition: systemevent.h:69
Sense class which shares information about the SR system throughout the SR system and to applications...
Definition: systemsense.h:41
static SystemSense * create(SRContext &context)
Creates a functional SystemSense instance.
virtual std::shared_ptr< SystemEventStream > openSystemEventStream(SystemEventListener *listener)=0
Creates a SystemEventStream for listener to be connected to.
unsigned int GLuint
Definition: glweaver.h:28
C-compatible struct containing the position of two eyes.
Definition: eyepair.h:28
SR_point3d left
Absolute position of left eye in millimeter.
Definition: eyepair.h:34
SR_point3d right
Absolute position of right eye in millimeter.
Definition: eyepair.h:35
C-compatible struct containing the pose of a hand.
Definition: handpose.h:124
SR_finger index
Index finger.
Definition: handpose.h:136
@ ContextInvalid
Context needs to be re-initialized for the application to recover.
Definition: systemevent.h:19
SR_point3d tip
distal alias
Definition: handpose.h:64
double y
Second value in the 3d vector.
Definition: types.h:85
double z
Third value in the 3d vector.
Definition: types.h:86
double x
First value in the 3d vector.
Definition: types.h:84