10#include <glm/gtc/matrix_transform.hpp>
14#define GLFW_EXPOSE_NATIVE_WIN32
15#define GLFW_EXPOSE_NATIVE_WGL
16#include "glfw3native.h"
18#include <shellscalingapi.h>
37#define WEAVING_ENABLED
39using namespace std::chrono_literals;
42bool contextValid =
false;
44bool initializeSrObjects();
58 <<
"ContextInvalid event received: "
65 initializeSrObjects();
72 std::cout <<
"Unknown event type" << std::endl;
84 glm::vec3 left, right;
85 MyEyes(
SR::EyeTracker* tracker) : left(-30, 0, 600), right(30, 0, 600) {
119std::mutex constructNewContextMutex;
120MyEyes* eyes =
nullptr;
121SystemEventMonitor* listener =
nullptr;
123bool createSrContext() {
124 if (context !=
nullptr) {
128 while (context ==
nullptr && contextValid ==
false) {
134 std::cout <<
"Server not available, trying again in 0.5 second" << std::endl;
135 std::this_thread::sleep_for(500ms);
141bool initializeSrObjects() {
142 std::lock_guard<std::mutex> lock(constructNewContextMutex);
145 if (eyes !=
nullptr) {
149 if (listener !=
nullptr) {
154 while (weaver !=
nullptr) {
156 std::this_thread::sleep_for(10ms);
159 if (createSrContext() ==
false) {
166 listener =
new SystemEventMonitor();
175glm::mat4 CalculateModel()
177 const float size = 20.0;
178 using namespace std::chrono;
179 auto now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
180 const int ms_per_revolution = 5000;
181 float angle = float((2 * 3.1415 / ms_per_revolution) * (now % ms_per_revolution));
183 glm::mat4 Model = glm::mat4();
184 Model = scale(Model, glm::vec3(size, size, size));
185 Model = translate(Model, glm::vec3(0, 1, 0));
186 Model = rotate(Model, angle, glm::vec3(0, 1, 0));
191float screenWidth_mm = 697.0;
192float screenHeight_mm = 394.0;
194glm::mat4 CalculateProjection(glm::vec3 &eye)
198 const float near = 1.0;
199 const float far = 10000.0;
200 const glm::vec3 pa(-screenWidth_mm / 2, screenHeight_mm / 2, 0);
201 const glm::vec3 pb(screenWidth_mm / 2, screenHeight_mm / 2, 0);
202 const glm::vec3 pc(-screenWidth_mm / 2, -screenHeight_mm / 2, 0);
204 const glm::vec3 vr(1, 0, 0);
205 const glm::vec3 vu(0, 1, 0);
206 const glm::vec3 vn(0, 0, 1);
209 glm::vec3 va = pa - eye;
210 glm::vec3 vb = pb - eye;
211 glm::vec3 vc = pc - eye;
214 float distance = -dot(va, vn);
217 float l = dot(vr, va) * near / distance;
218 float r = dot(vr, vb) * near / distance;
219 float b = dot(vu, vc) * near / distance;
220 float t = dot(vu, va) * near / distance;
223 glm::mat4 _frustum = glm::frustum(l, r, b, t, near, far);
227 vr[0], vu[0], vn[0], 0,
228 vr[1], vu[1], vn[1], 0,
229 vr[2], vu[2], vn[2], 0,
234 glm::mat4 _translate = translate(glm::mat4(), -eye);
237 return _frustum * M * _translate;
240void RenderScene(
GLuint MatrixID,
const size_t renderWidth,
const size_t renderHeight, glm::vec3 leftEye, glm::vec3 rightEye, Pyramid& pyramid) {
243 glm::mat4 View = glm::mat4();
244 glm::mat4 Model = CalculateModel();
247 glm::mat4 Projection = CalculateProjection(leftEye);
248 glm::mat4 MVP = Projection * View * Model;
249 glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
252 glViewport(0, 0, renderWidth, renderHeight);
258 Projection = CalculateProjection(rightEye);
259 MVP = Projection * View * Model;
260 glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
263 glViewport(renderWidth, 0, renderWidth, renderHeight);
271bool ensureWindowFitsToMonitor() {
273 HMONITOR windowMonitor = MonitorFromWindow(glfwGetWin32Window(window), MONITOR_DEFAULTTONEAREST);
276 if (!windowMonitor) {
281 MONITORINFO monitorInfo;
282 ZeroMemory(&monitorInfo,
sizeof(monitorInfo));
283 monitorInfo.cbSize =
sizeof(monitorInfo);
284 GetMonitorInfoA(windowMonitor, &monitorInfo);
288 GetWindowRect(glfwGetWin32Window(window), &windowRect);
291 if (windowRect.left != monitorInfo.rcMonitor.left ||
292 windowRect.right != monitorInfo.rcMonitor.right ||
293 windowRect.top != monitorInfo.rcMonitor.top ||
294 windowRect.bottom != monitorInfo.rcMonitor.bottom) {
296 glfwSetWindowPos(window,
297 monitorInfo.rcMonitor.left,
298 monitorInfo.rcMonitor.top
300 glfwSetWindowSize(window,
301 monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
302 monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top
310bool windowFitsToMonitor =
false;
312void windowMoveCallback(GLFWwindow* window,
int xPos,
int yPos) {
313 windowFitsToMonitor =
false;
316void monitorConfigurationCallback(GLFWmonitor* monitor,
int event) {
317 windowFitsToMonitor =
false;
323 SetProcessDpiAwareness(PROCESS_DPI_AWARENESS::PROCESS_PER_MONITOR_DPI_AWARE);
328 fprintf(stderr,
"Failed to initialize GLFW\n");
332 glfwWindowHint(GLFW_SAMPLES, 4);
333 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
334 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
335 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
336 glfwWindowHint(GLFW_AUTO_ICONIFY, GL_FALSE);
337 glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
340 GLFWmonitor* monitor = glfwGetPrimaryMonitor();
341 const GLFWvidmode* mode = glfwGetVideoMode(monitor);
342 window = glfwCreateWindow(mode->width, mode->height,
"Simulated Reality - Cube demo", NULL, NULL);
343 if (window == NULL) {
344 fprintf(stderr,
"Failed to open GLFW window.\n");
348 windowFitsToMonitor =
true;
349 glfwMakeContextCurrent(window);
353 glewExperimental =
true;
354 if (glewInit() != GLEW_OK) {
355 fprintf(stderr,
"Failed to initialize GLEW\n");
361 glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
362 glfwSetWindowPosCallback(window, windowMoveCallback);
363 glfwSetMonitorCallback(monitorConfigurationCallback);
365 glClearColor(0.5f, 0.5f, 0.5f, 0.0);
366 glEnable(GL_DEPTH_TEST);
367 glDepthFunc(GL_LESS);
368 GLuint programID = loadBasicShaders();
369 GLuint MatrixID = glGetUniformLocation(programID,
"MVP");
372 initializeSrObjects();
377 glUseProgram(programID);
380 int screenWidth_mm_i, screenHeight_mm_i;
381 glfwGetMonitorPhysicalSize(monitor, &screenWidth_mm_i, &screenHeight_mm_i);
382 screenWidth_mm = screenWidth_mm_i;
383 screenHeight_mm = screenHeight_mm_i;
388#ifdef WEAVING_ENABLED
398 const size_t renderWidth = mode->width * 0.5f;
399 const size_t renderHeight = mode->height;
402#ifdef WEAVING_ENABLED
410 bool lKeyPressed =
false;
415 bool prevLKeyPressed = lKeyPressed;
416 lKeyPressed = glfwGetKey(window, GLFW_KEY_L) == GLFW_PRESS;
417 if (lKeyPressed && !prevLKeyPressed)
420#ifdef WEAVING_ENABLED
423 if (contextValid && weaver !=
nullptr) {
427 glBindFramebuffer(GL_FRAMEBUFFER, 0);
431 glUseProgram(programID);
432 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
434 RenderScene(MatrixID, renderWidth, renderHeight, eyes->left, eyes->right, pyramid);
437 RenderScene(MatrixID, renderWidth, renderHeight, { -30, 0, 600 }, { 30, 0, 600 }, pyramid);
440#ifdef WEAVING_ENABLED
441 int windowWidth, windowHeight;
442 glfwGetFramebufferSize(window, &windowWidth, &windowHeight);
444 glBindFramebuffer(GL_FRAMEBUFFER, 0);
446 glViewport(0, 0, windowWidth, windowHeight);
450 if (contextValid && weaver !=
nullptr) {
451 weaver->
weave((
unsigned int)windowWidth, (
unsigned int)windowHeight, 0, 0);
457 glfwSwapBuffers(window);
460 if (!windowFitsToMonitor) {
461 windowFitsToMonitor = ensureWindowFitsToMonitor();
464#ifdef WEAVING_ENABLED
466 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:10
Interface for listening to SR_eyePair updates.
Definition: eyepairlistener.h:15
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:35
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 enableLateLatching(bool enable)
Enables late latching. Note that late latching requires applications to call weave() once per frame,...
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.
bool isLateLatchingEnabled() const
Determines if late latching is enabled.
Interface for listening to SR_handPose updates.
Definition: handposelistener.h:34
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:41
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:216
Maintains WorldObject and Sense objects during the application lifetime.
Definition: srcontext.h:75
void initialize()
Initialize all senses.
Class of WorldObject representing the screen in real space.
Definition: screen.h:34
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:96
Interface for listening to SR_systemEvent updates.
Definition: systemeventlistener.h:25
virtual void accept(const SystemEvent &frame)=0
Accept an SR_systemEvent frame.
Class containing dynamic-length event messages.
Definition: systemevent.h:60
uint64_t time
Time since epoch in microseconds.
Definition: systemevent.h:62
SR_eventType eventType
Type of the event.
Definition: systemevent.h:63
std::string message
Full description of the event.
Definition: systemevent.h:64
Sense class which shares information about the SR system throughout the SR system and to applications...
Definition: systemsense.h:36
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:23
C-compatible struct containing the position of two eyes.
Definition: eyepair.h:23
SR_point3d left
Absolute position of left eye in millimeter.
Definition: eyepair.h:29
SR_point3d right
Absolute position of right eye in millimeter.
Definition: eyepair.h:30
C-compatible struct containing the pose of a hand.
Definition: handpose.h:119
SR_finger index
Index finger.
Definition: handpose.h:131
@ ContextInvalid
Context needs to be re-initialized for the application to recover.
Definition: systemevent.h:14
SR_point3d tip
distal alias
Definition: handpose.h:59
double y
Second value in the 3d vector.
Definition: types.h:77
double z
Third value in the 3d vector.
Definition: types.h:78
double x
First value in the 3d vector.
Definition: types.h:76