<repo_name>yorrickslr/guacamole<file_sep>/tutorial/beginner/0_window/main.cpp
/******************************************************************************
 * guacamole - delicious VR                                                   *
 *                                                                            *
 * Copyright: (c) 2011-2018 <NAME>                        *
 * Contact:   <EMAIL>                      *
 *            <EMAIL>                                   *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or (at your option)  *
 * any later version.                                                         *
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          *
 *                                                                            *
 * You should have received a copy of the GNU General Public License along    *
 * with this program. If not, see <http://www.gnu.org/licenses/>.             *
 *                                                                            *
 ******************************************************************************/

#include <functional>

#include <gua/guacamole.hpp>
#include <gua/renderer/TriMeshLoader.hpp>
#include <gua/utils/Trackball.hpp>

/* scenegraph overview for "main_scenegraph"
  /
  └ screen
    └ camera
*/

int main(int argc, char** argv) {
  // initialize guacamole
  gua::init(argc, argv);

  // initialize scenegraph
  gua::SceneGraph graph("main_scenegraph");

  auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen");
  screen->data.set_size(gua::math::vec2(1.28f, 0.72f));  // real world size of screen
  screen->translate(0, 0, 1.0);

  // resolution to be used for camera resolution and windows size
  auto resolution = gua::math::vec2ui(1280, 720);

  // set up camera and connect to screen in scenegraph
  auto camera = graph.add_node<gua::node::CameraNode>("/screen", "cam");
  camera->translate(0, 0, 2.0);
  camera->config.set_resolution(resolution);
  camera->config.set_screen_path("/screen");
  camera->config.set_scene_graph_name("main_scenegraph");
  camera->config.set_output_window_name("main_window");

  // set up window
  auto window = std::make_shared<gua::GlfwWindow>();
  gua::WindowDatabase::instance()->add("main_window", window);
  window->config.set_enable_vsync(false);
  window->config.set_size(resolution);
  window->config.set_resolution(resolution);
  window->config.set_stereo_mode(gua::StereoMode::MONO);
  window->on_resize.connect([&](gua::math::vec2ui const& new_size) {
    window->config.set_resolution(new_size);
    camera->config.set_resolution(new_size);
    screen->data.set_size(
        gua::math::vec2(0.001 * new_size.x, 0.001 * new_size.y));
  });
  window->open();

  gua::Renderer renderer;

  // application loop
  gua::events::MainLoop loop;
  
  // registers the function given in ticker.on_tick to
  // be called by the given loop in the given interval
  gua::events::Ticker ticker(loop, 1.0 / 500.0);

  // log fps and handle close events
  size_t ctr{};
  ticker.on_tick.connect([&]() {
    // log fps every 150th tick
    if (ctr++ % 150 == 0) {
      gua::Logger::LOG_WARNING
        << "Frame time: " << 1000.f / window->get_rendering_fps()
        << " ms, fps: " << window->get_rendering_fps() << std::endl;
    }
    window->process_events();
    if (window->should_close()) {
      // stop rendering and close the window
      renderer.stop();
      window->close();
      loop.stop();
    } else {
      // draw our scenegrapgh
      renderer.queue_draw({&graph});
    }
  });

  loop.start();

  return 0;
}
<file_sep>/plugins/guacamole-spoints/include/gua/spoints/SPointsSync.hpp
/******************************************************************************
 * guacamole - delicious VR                                                   *
 *                                                                            *
 * Copyright: (c) 2011-2013 <NAME>                        *
 * Contact:   <EMAIL> / <EMAIL>      *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or (at your option)  *
 * any later version.                                                         *
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          *
 *                                                                            *
 * You should have received a copy of the GNU General Public License along    *
 * with this program. If not, see <http://www.gnu.org/licenses/>.             *
 *                                                                            *
 ******************************************************************************/

#ifndef GUA_SPOINTS_SYNC_HPP
#define GUA_SPOINTS_SYNC_HPP

#include <gua/spoints/platform.hpp>

#include <memory>
#include <queue>

#include <gua/math/math.hpp>
#include <gua/utils.hpp>

#include <fstream>
#include <iostream>

namespace gua
{
class GUA_SPOINTS_DLL SPointsSync
{
  public:
    SPointsSync();
    ~SPointsSync(){};

    void set_sync_length(int new_sync_length);
    int get_sync_length();
    scm::math::mat<double, 4u, 4u> get_synchronized(scm::math::mat<double, 4u, 4u> const& matrix, bool is_left);
    scm::math::mat<double, 4u, 4u> get_synchronized(scm::math::mat<double, 4u, 4u> const& matrix);

    // unsigned long id = (unsigned long)this;
    // std::ofstream* file = new std::ofstream();

  private:
    std::shared_ptr<std::queue<scm::math::mat<double, 4u, 4u>>> sync_queue_l_ = std::make_shared<std::queue<scm::math::mat<double, 4u, 4u>>>(std::queue<scm::math::mat<double, 4u, 4u>>());
    std::shared_ptr<std::queue<scm::math::mat<double, 4u, 4u>>> sync_queue_r_ = std::make_shared<std::queue<scm::math::mat<double, 4u, 4u>>>(std::queue<scm::math::mat<double, 4u, 4u>>());
    int sync_length_;
};

} // namespace gua

#endif // GUA_SPOINTS_SYNC_HPP
<file_sep>/tutorial/beginner/4_lights/main.cpp
/******************************************************************************
 * guacamole - delicious VR                                                   *
 *                                                                            *
 * Copyright: (c) 2011-2018 <NAME>                        *
 * Contact:   <EMAIL>                      *
 *            <EMAIL>                                   *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or (at your option)  *
 * any later version.                                                         *
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          *
 *                                                                            *
 * You should have received a copy of the GNU General Public License along    *
 * with this program. If not, see <http://www.gnu.org/licenses/>.             *
 *                                                                            *
 ******************************************************************************/

#include <functional>

#include <gua/guacamole.hpp>
#include <gua/renderer/TriMeshLoader.hpp>

/* scenegraph overview for "main_scenegraph"
  /
  └ screen
    └ camera
  └ transform
    └ sphere_geometry
    └ monkey_geometry
    └ teapot_geometry
  └ light_transform
    case:1
    └ point_light_transform
      └ point_light0
      └ point_light1
      └ point_light2
    case:2
    └ spot_light_transform
      └ spot_light0
      └ spot_light1
      └ spot_light2  
    case:3
    └ sun_light_transform
      └ sun_light
*/

int main(int argc, char** argv) {
  // initialize guacamole
  gua::init(argc, argv);

  // initialize scenegraph
  gua::SceneGraph graph("main_scenegraph");

  // initialize trimeshloader for model loading
  gua::TriMeshLoader loader;

  // create a transform node
  // which will be attached to the scenegraph
  auto transform = graph.add_node<gua::node::TransformNode>("/", "transform");
  // the model will be attached to the transform node
  auto sphere_geometry(loader.create_geometry_from_file(
                          "sphere_geometry", "../data/objects/sphere.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE )
                      );
  sphere_geometry->scale(0.4);
  sphere_geometry->translate(0.6,0.0,0.0);
  auto monkey_geometry(loader.create_geometry_from_file(
                          "monkey_geometry", "../data/objects/monkey.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE )
                      );
  monkey_geometry->scale(0.5);
  auto teapot_geometry(loader.create_geometry_from_file(
                          "teapot_geometry", "../data/objects/teapot.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE )
                      );
  teapot_geometry->scale(0.5);
  teapot_geometry->translate(-0.6,0.0,0.0);
  auto plane_geometry(loader.create_geometry_from_file(
                          "plane_geometry", "../data/objects/plane.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE)
                      );
  plane_geometry->rotate(10.0f, gua::math::vec3(1.0f,0.0f,0.0f));
  plane_geometry->translate(0.0, -0.2, 0.0);
  // plane_geometry->scale(gua::math::vec3(2.0f,0.0f,0.0f));
  graph.add_node("/transform", sphere_geometry);
  graph.add_node("/transform", monkey_geometry);
  graph.add_node("/transform", teapot_geometry);
  graph.add_node("/transform", plane_geometry);

  /* LIGHTS */
  // create some transform nodes to append the different lights to
  // main light transform node
  auto light_transform = graph.add_node<gua::node::TransformNode>("/","light_transform");
  // one transform node for every type
  auto point_light_transform = std::make_shared<gua::node::TransformNode>();
  auto spot_light_transform = std::make_shared<gua::node::TransformNode>();
  auto sun_light_transform = std::make_shared<gua::node::TransformNode>();

  // create some point lights and configure them
  auto point_light0 = point_light_transform->add_child<gua::node::LightNode>("point_light0");
  point_light0->data.set_type(gua::node::LightNode::Type::POINT);
  point_light0->data.set_brightness(40.0f);
  point_light0->data.set_falloff(2.0f);
  point_light0->data.set_softness(1.5f);
  point_light0->data.set_enable_shadows(true);
  // float r = float(std::rand()) / float(RAND_MAX);
  // float g = float(std::rand()) / float(RAND_MAX);
  // float b = float(std::rand()) / float(RAND_MAX);
  // point_light0->data.set_color(gua::utils::Color3f(0.5f+r,g,b));
  point_light0->data.set_color(gua::utils::Color3f(1.0f,0.0f,0.0f));
  point_light0->scale(10.0f);
  point_light0->translate(2.0f,2.0f,2.0f);


  auto point_light1 = point_light_transform->add_child<gua::node::LightNode>("point_light1");
  point_light1->data.set_type(gua::node::LightNode::Type::POINT);
  point_light1->data.set_brightness(25.0f);
  point_light1->data.set_falloff(0.5f);
  point_light1->data.set_softness(2.0f);
  point_light1->data.set_enable_shadows(true);
  // r = float(std::rand()) / float(RAND_MAX);
  // g = float(std::rand()) / float(RAND_MAX);
  // b = float(std::rand()) / float(RAND_MAX);
  // point_light1->data.set_color(gua::utils::Color3f(r,0.5f+g,b));
  point_light1->data.set_color(gua::utils::Color3f(0.0f,1.0f,0.0f));
  point_light1->scale(4.0f);
  point_light1->translate(-1.5f,-2.0f,1.0f);

  auto point_light2 = point_light_transform->add_child<gua::node::LightNode>("point_light2");
  point_light2->data.set_type(gua::node::LightNode::Type::POINT);
  point_light2->data.set_brightness(110.0f);
  point_light2->data.set_falloff(1.0f);
  point_light2->data.set_softness(1.0f);
  point_light2->data.set_enable_shadows(true);
  // r = float(std::rand()) / float(RAND_MAX);
  // g = float(std::rand()) / float(RAND_MAX);
  // b = float(std::rand()) / float(RAND_MAX);
  // point_light2->data.set_color(gua::utils::Color3f(r,g,0.5f+b));
  point_light2->data.set_color(gua::utils::Color3f(0.0f,0.0f,1.0f));
  point_light2->scale(10.0f);
  point_light2->translate(-0.5f,5.0f,0.0f);

  // add the point lights to the scenegraph, you can later switch the light via keyboard input
  auto temp = graph.add_node<gua::node::TransformNode>(light_transform, point_light_transform);

  // create some spot lights and configure them
  auto spot_light0 = spot_light_transform->add_child<gua::node::LightNode>("spot_light0");
  spot_light0->data.set_type(gua::node::LightNode::Type::SPOT);
  spot_light0->data.set_brightness(50.0f);
  spot_light0->data.set_falloff(2.0f);
  spot_light0->data.set_softness(1.5f);
  spot_light0->data.set_enable_shadows(true);
  // r = float(std::rand()) / float(RAND_MAX);
  // g = float(std::rand()) / float(RAND_MAX);
  // b = float(std::rand()) / float(RAND_MAX);
  // spot_light0->data.set_color(gua::utils::Color3f(0.5f+r,g,b));
  spot_light0->data.set_color(gua::utils::Color3f(1.0f,0.0f,0.0f));
  spot_light0->scale(1.5f);
  spot_light0->rotate(45.0f, gua::math::vec3(0.0f,1.0f,0.0f));
  spot_light0->translate(1.0f,0.0f,1.0f);


  auto spot_light1 = spot_light_transform->add_child<gua::node::LightNode>("spot_light1");
  spot_light1->data.set_type(gua::node::LightNode::Type::SPOT);
  spot_light1->data.set_brightness(35.0f);
  spot_light1->data.set_falloff(0.5f);
  spot_light1->data.set_softness(2.0f);
  spot_light1->data.set_enable_shadows(true);
  // r = float(std::rand()) / float(RAND_MAX);
  // g = float(std::rand()) / float(RAND_MAX);
  // b = float(std::rand()) / float(RAND_MAX);
  // spot_light1->data.set_color(gua::utils::Color3f(r,0.5f+g,b));
  spot_light1->data.set_color(gua::utils::Color3f(0.0f,0.6f,0.2f));
  spot_light1->scale(2.0f);
  spot_light1->rotate(63.43f, gua::math::vec3(1.0f,0.0f,0.0f));  
  spot_light1->translate(-0.6f,-1.f,0.5f);

  auto spot_light2 = spot_light_transform->add_child<gua::node::LightNode>("spot_light2");
  spot_light2->data.set_type(gua::node::LightNode::Type::SPOT);
  spot_light2->data.set_brightness(120.0f);
  spot_light2->data.set_falloff(0.8f);
  spot_light2->data.set_softness(1.0f);
  spot_light2->data.set_enable_shadows(true);
  // r = float(std::rand()) / float(RAND_MAX);
  // g = float(std::rand()) / float(RAND_MAX);
  // b = float(std::rand()) / float(RAND_MAX);
  // spot_light2->data.set_color(gua::utils::Color3f(r,g,0.5f+b));
  spot_light2->data.set_color(gua::utils::Color3f(0.0f,0.0f,1.0f));
  spot_light2->scale(5.0f);
  spot_light2->rotate(-90.0f, gua::math::vec3(1.0f,0.0f,0.0f));
  spot_light2->translate(0.0f,5.0f,0.0f);

  // add a sun light
  auto sun_light = sun_light_transform->add_child<gua::node::LightNode>("sun_light");
  sun_light->data.set_type(gua::node::LightNode::Type::SUN);
  sun_light->data.set_brightness(3.0f);
  // sun_light->data.set_falloff(2.0f);
  // sun_light->data.set_softness(1.5f);
  sun_light->data.set_enable_shadows(true);
  sun_light->data.set_shadow_map_size(1024);
  // r = float(std::rand()) / float(RAND_MAX);
  // g = float(std::rand()) / float(RAND_MAX);
  // b = float(std::rand()) / float(RAND_MAX);
  // sun_light->data.set_color(gua::utils::Color3f(0.5f+r,g,b));
  sun_light->data.set_color(gua::utils::Color3f(1.0f,0.7f,0.07f));
  sun_light->scale(1.0f);
  sun_light->translate(70.0f,70.0f,1.0f);

  auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen");
  screen->data.set_size(gua::math::vec2(1.28f, 0.72f));  // real world size of screen
  screen->translate(0, 0, 1.0);

  // resolution to be used for camera resolution and windows size
  auto resolution = gua::math::vec2ui(1280, 720);

  // set up camera and connect to screen in scenegraph
  auto camera = graph.add_node<gua::node::CameraNode>("/screen", "cam");
  camera->translate(0, 0, 2.0);
  camera->config.set_resolution(resolution);
  camera->config.set_screen_path("/screen");
  camera->config.set_scene_graph_name("main_scenegraph");
  camera->config.set_output_window_name("main_window");

  // set up window
  auto window = std::make_shared<gua::GlfwWindow>();
  gua::WindowDatabase::instance()->add("main_window", window);
  window->config.set_enable_vsync(false);
  window->config.set_size(resolution);
  window->config.set_resolution(resolution);
  window->config.set_stereo_mode(gua::StereoMode::MONO);
  window->on_resize.connect([&](gua::math::vec2ui const& new_size) {
    window->config.set_resolution(new_size);
    camera->config.set_resolution(new_size);
    screen->data.set_size(
        gua::math::vec2(0.001 * new_size.x, 0.001 * new_size.y));
  });
  window->open();
  // add keyboard input
  window->on_key_press.connect([&](int key, int scancode, int action, int mods) {
    if(action == 0) return;

    switch(key) {
      case '1':
        std::cout << "SWITCHED TO POINT LIGHTS" << std::endl;
        light_transform->clear_children();
        graph.add_node<gua::node::TransformNode>(light_transform, point_light_transform);
        break;
      case '2':
        std::cout << "SWITCHED TO SPOT LIGHTS" << std::endl;
        light_transform->clear_children();
        graph.add_node<gua::node::TransformNode>(light_transform, spot_light_transform);
        break;
      case '3':
        std::cout << "SWITCHED TO SUN LIGHT" << std::endl;
        light_transform->clear_children();
        graph.add_node<gua::node::TransformNode>(light_transform, sun_light_transform);
        break;
    }
  });

  gua::Renderer renderer;

  // application loop
  gua::events::MainLoop loop;
  gua::events::Ticker ticker(loop, 1.0 / 500.0);

  // log fps and handle close events
  size_t ctr{};
  ticker.on_tick.connect([&]() {
    // use a timer for an ongoing transformation
	  auto time = gua::Timer::get_now()*0.0000000001;
	  auto trans = (std::cos(time*17000000000.0f)+1.0f)/2.0f;
    
    sun_light_transform->rotate(time, gua::math::vec3(-1.0f,1.0f,0.0f));
    sun_light->data.set_color(gua::utils::Color3f(1.0f,trans,0.07f));
    // log fps every 150th tick
    if (ctr++ % 150 == 0) {
      // change light color every 150th tick 
      // float r = float(std::rand()) / float(RAND_MAX);
      // float g = float(std::rand()) / float(RAND_MAX);
      // float b = float(std::rand()) / float(RAND_MAX);
      // point_light->data.color = gua::utils::Color3f(r,g,b);
      gua::Logger::LOG_WARNING
        << "Frame time: " << 1000.f / window->get_rendering_fps()
        << " ms, fps: " << window->get_rendering_fps() 
        << "\nCOS(TIME): " << trans << std::endl;
    }
	
    window->process_events();
    if (window->should_close()) {
      // stop rendering and close the window
      renderer.stop();
      window->close();
      loop.stop();
    } else {
      // draw our scenegrapgh
      renderer.queue_draw({&graph});
    }
  });

  loop.start();

  return 0;
}
<file_sep>/tutorial/beginner/3_input/main.cpp
/******************************************************************************
 * guacamole - delicious VR                                                   *
 *                                                                            *
 * Copyright: (c) 2011-2018 <NAME>                        *
 * Contact:   <EMAIL>                      *
 *            <EMAIL>                                   *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or (at your option)  *
 * any later version.                                                         *
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          *
 *                                                                            *
 * You should have received a copy of the GNU General Public License along    *
 * with this program. If not, see <http://www.gnu.org/licenses/>.             *
 *                                                                            *
 ******************************************************************************/

#include <functional>

#include <gua/guacamole.hpp>
#include <gua/renderer/TriMeshLoader.hpp>
#include <gua/utils/Trackball.hpp>

/* scenegraph overview for "main_scenegraph"
  /
  └ screen
    └ camera
  └ transform
    └ teapot_geometry
*/

/*  to use the mouse input for trackball navigation, 
    we need a callback to forward the interaction to the trackball */
void mouse_button(gua::utils::Trackball& trackball, int mousebutton, int action, int mods) {
  gua::utils::Trackball::button_type button;
  gua::utils::Trackball::state_type state;

  switch (mousebutton) {
    // left mb for rotation
    case 0: button = gua::utils::Trackball::left; break;
    // middle mb for translation (shift on x/y plane) on screen pane
    case 2: button = gua::utils::Trackball::middle; break;
    // right mb for zoom or shift on z axis
    case 1: button = gua::utils::Trackball::right; break;
  };

  switch (action) {
    case 0: state = gua::utils::Trackball::released; break;
    case 1: state = gua::utils::Trackball::pressed; break;
  };
  // forward button and state along with the mouse position to the trackball class
  trackball.mouse(button, state, trackball.posx(), trackball.posy());
}

int main(int argc, char** argv) {
  // initialize guacamole
  gua::init(argc, argv);

  // initialize scenegraph
  gua::SceneGraph graph("main_scenegraph");

  // initialize trimeshloader for model loading
  gua::TriMeshLoader loader;

  // create a transform node
  // which will be attached to the scenegraph
  auto transform = graph.add_node<gua::node::TransformNode>("/", "transform");
  // the model will be attached to the transform node
  auto teapot_geometry(loader.create_geometry_from_file(
                          "teapot_geometry", "../data/objects/teapot.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE )
                      );
  // teapot_geometry->scale(0.15);
  teapot_geometry->translate(-0.6,0.0,0.0);
  graph.add_node("/transform", teapot_geometry);


  auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen");
  screen->data.set_size(gua::math::vec2(1.28f, 0.72f));  // real world size of screen
  screen->translate(0, 0, 1.0);

  // initialize trackball for mouse interaction
  // trackball(zoom_factor, shift_factor, rotation_factor)
  gua::utils::Trackball trackball(0.01, 0.002, 0.2);

  // initialize navigator node for key input and keyboard navigation


  // resolution to be used for camera resolution and windows size
  auto resolution = gua::math::vec2ui(1280, 720);

  // set up camera and connect to screen in scenegraph
  auto camera = graph.add_node<gua::node::CameraNode>("/screen", "cam");
  camera->translate(0, 0, 2.0);
  camera->config.set_resolution(resolution);
  camera->config.set_screen_path("/screen");
  camera->config.set_scene_graph_name("main_scenegraph");
  camera->config.set_output_window_name("main_window");

  // set up window
  auto window = std::make_shared<gua::GlfwWindow>();
  gua::WindowDatabase::instance()->add("main_window", window);
  window->config.set_enable_vsync(false);
  window->config.set_size(resolution);
  window->config.set_resolution(resolution);
  window->config.set_stereo_mode(gua::StereoMode::MONO);
  window->on_resize.connect([&](gua::math::vec2ui const& new_size) {
    window->config.set_resolution(new_size);
    camera->config.set_resolution(new_size);
    screen->data.set_size(
        gua::math::vec2(0.001 * new_size.x, 0.001 * new_size.y));
  });
  // connect mouse movement in window to trackball motion
  window->on_move_cursor.connect(
      [&](gua::math::vec2 const& pos) { trackball.motion(pos.x, pos.y); });
  // connect mouse input to our mouse button callback.
  // the placeholders will be replaced by the mousebutton, 
  // action and mods arguments of the callback funktion
  window->on_button_press.connect(
      std::bind(mouse_button, std::ref(trackball), std::placeholders::_1,
                std::placeholders::_2, std::placeholders::_3));
  // add a simple keyboard movement;
  // as we need the camera, lambda function is good way to go
  window->on_key_press.connect([&](int key, int scancode, int action, int mods) {
    if(action == 0) return;

    switch(key) {
      case 'W':
        camera->translate(0.0,0.0,0.5);
        break;
      case 'S':
        camera->translate(0.0,0.0,-0.5);
        break;
      case 'A':
        camera->translate(0.5,0.0,0.0);
        break;
      case 'D':
        camera->translate(-0.5,0.0,0.0);
        break;
    }
  }); 
  window->open();

  gua::Renderer renderer;

  // application loop
  gua::events::MainLoop loop;
  gua::events::Ticker ticker(loop, 1.0 / 500.0);

  // log fps and handle close events
  size_t ctr{};
  ticker.on_tick.connect([&]() {
    // log fps every 150th tick
    if (ctr++ % 150 == 0) {
      gua::Logger::LOG_WARNING
        << "Frame time: " << 1000.f / window->get_rendering_fps()
        << " ms, fps: " << window->get_rendering_fps() << std::endl;
    }
    // apply trackball matrix to the object
    gua::math::mat4 modelmatrix =
        scm::math::make_translation(trackball.shiftx(), trackball.shifty(),
                                    trackball.distance()) *
        gua::math::mat4(trackball.rotation());

    transform->set_transform(modelmatrix);
	
    window->process_events();
    if (window->should_close()) {
      // stop rendering and close the window
      renderer.stop();
      window->close();
      loop.stop();
    } else {
      // draw our scenegrapgh
      renderer.queue_draw({&graph});
    }
  });

  loop.start();

  return 0;
}
<file_sep>/tutorial/intermediate/CMakeLists.txt
# guacamole tutorial
<file_sep>/tutorial/beginner/5_pipeline/main.cpp
/******************************************************************************
 * guacamole - delicious VR                                                   *
 *                                                                            *
 * Copyright: (c) 2011-2018 <NAME>                        *
 * Contact:   <EMAIL>                      *
 *            <EMAIL>                                   *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or (at your option)  *
 * any later version.                                                         *
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          *
 *                                                                            *
 * You should have received a copy of the GNU General Public License along    *
 * with this program. If not, see <http://www.gnu.org/licenses/>.             *
 *                                                                            *
 ******************************************************************************/

#include <functional>

#include <gua/guacamole.hpp>
#include <gua/renderer/TriMeshLoader.hpp>
#include <gua/utils/Trackball.hpp>
#include <gua/renderer/DebugViewPass.hpp>

/* scenegraph overview for "main_scenegraph"
  /
  └ screen
    └ camera
  └ transform
    └ sphere_geometry
    └ monkey_geometry
    └ teapot_geometry
  └ light_transform
    └ sun_light
*/

/*  to use the mouse input for trackball navigation, 
    we need a callback to forward the interaction to the trackball */
void mouse_button(gua::utils::Trackball& trackball, int mousebutton, int action, int mods) {
  gua::utils::Trackball::button_type button;
  gua::utils::Trackball::state_type state;

  switch (mousebutton) {
    // left mb for rotation
    case 0: button = gua::utils::Trackball::left; break;
    // middle mb for translation (shift on x/y plane) on screen pane
    case 2: button = gua::utils::Trackball::middle; break;
    // right mb for zoom or shift on z axis
    case 1: button = gua::utils::Trackball::right; break;
  };

  switch (action) {
    case 0: state = gua::utils::Trackball::released; break;
    case 1: state = gua::utils::Trackball::pressed; break;
  };
  // forward button and state along with the mouse position to the trackball class
  trackball.mouse(button, state, trackball.posx(), trackball.posy());
}

int main(int argc, char** argv) {
  // initialize guacamole
  gua::init(argc, argv);

  // initialize scenegraph
  gua::SceneGraph graph("main_scenegraph");

  // initialize trimeshloader for model loading
  gua::TriMeshLoader loader;

  // create a transform node
  // which will be attached to the scenegraph
  auto transform = graph.add_node<gua::node::TransformNode>("/", "transform");
  // the model will be attached to the transform node
  auto sphere_geometry(loader.create_geometry_from_file(
                          "sphere_geometry", "../data/objects/sphere.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE )
                      );
  sphere_geometry->scale(0.4);
  sphere_geometry->translate(0.6,0.0,0.0);
  auto monkey_geometry(loader.create_geometry_from_file(
                          "monkey_geometry", "../data/objects/monkey.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE )
                      );
  monkey_geometry->scale(0.5);
  auto teapot_geometry(loader.create_geometry_from_file(
                          "teapot_geometry", "../data/objects/teapot.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE )
                      );
  teapot_geometry->scale(0.5);
  teapot_geometry->translate(-0.6,0.0,0.0);
  auto plane_geometry(loader.create_geometry_from_file(
                          "plane_geometry", "../data/objects/plane.obj", 
                          gua::TriMeshLoader::OPTIMIZE_GEOMETRY | gua::TriMeshLoader::NORMALIZE_POSITION |
                          gua::TriMeshLoader::LOAD_MATERIALS | gua::TriMeshLoader::OPTIMIZE_MATERIALS |
                          gua::TriMeshLoader::NORMALIZE_SCALE)
                      );
  plane_geometry->rotate(10.0f, gua::math::vec3(1.0f,0.0f,0.0f));
  plane_geometry->translate(0.0, -0.2, 0.0);
  // plane_geometry->scale(gua::math::vec3(2.0f,0.0f,0.0f));
  graph.add_node("/transform", sphere_geometry);
  graph.add_node("/transform", monkey_geometry);
  graph.add_node("/transform", teapot_geometry);
  graph.add_node("/transform", plane_geometry);

  /* LIGHTS */
  // create some transform nodes to append the different lights to
  // main light transform node
  auto light_transform = graph.add_node<gua::node::TransformNode>("/","light_transform");

  // add a sun light
  auto sun_light = graph.add_node<gua::node::LightNode>("/light_transform", "sun_light");
  sun_light->data.set_type(gua::node::LightNode::Type::SUN);
  sun_light->data.set_color(gua::utils::Color3f(1.5f, 1.2f, 1.f));
  sun_light->data.set_shadow_cascaded_splits({0.1f, 1.5, 5.f, 10.f});
  sun_light->data.set_shadow_near_clipping_in_sun_direction(100.0f);
  sun_light->data.set_shadow_far_clipping_in_sun_direction(100.0f);
  sun_light->data.set_max_shadow_dist(30.0f);
  sun_light->data.set_shadow_offset(0.0004f);
  sun_light->data.set_enable_shadows(true);
  sun_light->data.set_shadow_map_size(512);
  sun_light->rotate(-65, 1, 0, 0);
  sun_light->rotate(-100, 0, 1, 0);
  
  // sun_light_transform->rotate(90.0f, gua::math::vec3(-1.0f,1.0f,0.0f));
  

  auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen");
  screen->data.set_size(gua::math::vec2(1.28f, 0.72f));  // real world size of screen
  screen->translate(0, 0, 1.0);

  // resolution to be used for camera resolution and windows size
  auto resolution = gua::math::vec2ui(1280, 720);

  // initialize trackball for mouse interaction
  // trackball(zoom_factor, shift_factor, rotation_factor)
  gua::utils::Trackball trackball(0.01, 0.002, 0.2);

  // set up camera and connect to screen in scenegraph
  auto camera = graph.add_node<gua::node::CameraNode>("/screen", "cam");
  camera->translate(0, 0, 2.0);
  camera->config.set_resolution(resolution);
  camera->config.set_screen_path("/screen");
  camera->config.set_scene_graph_name("main_scenegraph");
  camera->config.set_output_window_name("main_window");

  // Pipeline Description
  // The pipeline description is stored in the camera and later used for
  // pipeline creation When creating a camera, a default pipeline description is
  // set up It includes several passes affecting the pipeline layout and
  // functionality defalut pipeline description includes: TrimeMeshPass,
  // LineStripPass, TexturedQuadPassDescription, LightVisibilityPassDescription, 
  // BBoxPassDescription, ResolvePassDescription, TexturedScreenSpaceQuadPassDescription
  // You can create an own pipeline description from scratch or configure the existing description.

  auto pipe_desc = camera->get_pipeline_description();
  // Let's set a skymap as background for the scene
  // Those settings have to be configured in the resolve pass
  auto res_pass = pipe_desc->get_resolve_pass();
  res_pass->background_mode(gua::ResolvePassDescription::BackgroundMode::SKYMAP_TEXTURE);
  res_pass->background_texture("../data/textures/sphericalskymap.jpg");
  res_pass->background_color(gua::utils::Color3f(0,0,0));
  res_pass->environment_lighting_texture("../data/textures/sphericalskymap.jpg");
  res_pass->environment_lighting(gua::utils::Color3f(0.4, 0.4, 0.5));
  res_pass->environment_lighting_mode(gua::ResolvePassDescription::EnvironmentLightingMode::AMBIENT_COLOR);
  res_pass->ssao_enable(true);
  res_pass->tone_mapping_method(gua::ResolvePassDescription::ToneMappingMethod::HEJL);
  res_pass->tone_mapping_exposure(1.5f);
  res_pass->horizon_fade(0.2f);
  res_pass->ssao_intensity(1.5f);
  res_pass->ssao_radius(2.f);
  res_pass->vignette_coverage(0.2f);
  res_pass->vignette_softness(1.f);
  res_pass->vignette_color(gua::math::vec4f(0.5, 0.1, 0.3, 1.0));


  // adding a pipeline pass /!\ don't forget to include the pass /!\ 
  // for example add a debug view pass. 
  // Debug View will add overviews of normals, depth, color and position of the scene.
  pipe_desc->add_pass(std::make_shared<gua::DebugViewPassDescription>());

  // set up window
  auto window = std::make_shared<gua::GlfwWindow>();
  gua::WindowDatabase::instance()->add("main_window", window);
  window->config.set_enable_vsync(false);
  window->config.set_size(resolution);
  window->config.set_resolution(resolution);
  window->config.set_stereo_mode(gua::StereoMode::MONO);
  window->on_resize.connect([&](gua::math::vec2ui const& new_size) {
    window->config.set_resolution(new_size);
    camera->config.set_resolution(new_size);
    screen->data.set_size(
        gua::math::vec2(0.001 * new_size.x, 0.001 * new_size.y));
  });
  window->open();
  // connect mouse movement in window to trackball motion
  window->on_move_cursor.connect(
      [&](gua::math::vec2 const& pos) { trackball.motion(pos.x, pos.y); });
  // connect mouse input to our mouse button callback.
  // the placeholders will be replaced by the mousebutton, 
  // action and mods arguments of the callback funktion
  window->on_button_press.connect(
      std::bind(mouse_button, std::ref(trackball), std::placeholders::_1,
                std::placeholders::_2, std::placeholders::_3));
  // add a simple keyboard movement;
  // as we need the camera, lambda function is good way to go
  // add keyboard input
  window->on_key_press.connect([&](int key, int scancode, int action, int mods) { 
  });

  gua::Renderer renderer;

  // application loop
  gua::events::MainLoop loop;
  gua::events::Ticker ticker(loop, 1.0 / 500.0);

  // log fps and handle close events
  size_t ctr{};
  ticker.on_tick.connect([&]() {
    // use a timer for an ongoing transformation
	  auto time = gua::Timer::get_now()*0.0000000001;
	  auto trans = (std::cos(time*17000000000.0f)+1.0f)/2.0f;
    
    // sun_light_transform->rotate(time, gua::math::vec3(-1.0f,1.0f,0.0f));
    /* sun_light->data.set_color(gua::utils::Color3f(1.0f,trans,0.07f)); */
    // log fps every 150th tick
    if (ctr++ % 150 == 0) {
      // change light color every 150th tick 
      // float r = float(std::rand()) / float(RAND_MAX);
      // float g = float(std::rand()) / float(RAND_MAX);
      // float b = float(std::rand()) / float(RAND_MAX);
      // point_light->data.color = gua::utils::Color3f(r,g,b);
      gua::Logger::LOG_WARNING
        << "Frame time: " << 1000.f / window->get_rendering_fps()
        << " ms, fps: " << window->get_rendering_fps() << std::endl;
    }

    // apply trackball matrix to the object
    gua::math::mat4 modelmatrix =
        scm::math::make_translation(trackball.shiftx(), trackball.shifty(),
                                    trackball.distance()) *
        gua::math::mat4(trackball.rotation());

    transform->set_transform(modelmatrix);
	
    window->process_events();
    if (window->should_close()) {
      // stop rendering and close the window
      renderer.stop();
      window->close();
      loop.stop();
    } else {
      // draw our scenegrapgh
      renderer.queue_draw({&graph});
    }
  });

  loop.start();

  return 0;
}
<file_sep>/tutorial/beginner/CMakeLists.txt
# guacamole tutorial

# input requires GLFW3
IF (${GUACAMOLE_GLFW3})
  add_subdirectory(0_window)
  add_subdirectory(1_load_trimesh)
  add_subdirectory(2_transformations)
  add_subdirectory(3_input)
  add_subdirectory(4_lights)
  add_subdirectory(5_pipeline)
ENDIF (${GUACAMOLE_GLFW3})
<file_sep>/examples/0_getting_started/CMakeLists.txt
# guacamole examples
IF (GUACAMOLE_EXAMPLES)

  # input requires GLFW3
  IF (${GUACAMOLE_GLFW3})
    add_subdirectory(0_window)
  ENDIF (${GUACAMOLE_GLFW3})

ENDIF (GUACAMOLE_EXAMPLES)
<file_sep>/tutorial/CMakeLists.txt
# guacamole tutorial
IF (GUACAMOLE_TUTORIAL)

  add_subdirectory(beginner)
  add_subdirectory(intermediate)

ENDIF (GUACAMOLE_TUTORIAL)
<file_sep>/plugins/guacamole-spoints/src/gua/spoints/SPointsSync.cpp
/******************************************************************************
 * guacamole - delicious VR                                                   *
 *                                                                            *
 * Copyright: (c) 2011-2013 <NAME>                        *
 * Contact:   <EMAIL> / <EMAIL>      *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or (at your option)  *
 * any later version.                                                         *
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          *
 *                                                                            *
 * You should have received a copy of the GNU General Public License along    *
 * with this program. If not, see <http://www.gnu.org/licenses/>.             *
 *                                                                            *
 ******************************************************************************/
// class header

#include <gua/spoints/SPointsSync.hpp>

// guacamole headers
#include <gua/guacamole.hpp>
#include <gua/platform.hpp>

namespace gua
{
////////////////////////////////////////////////////////////////////////////////
SPointsSync::SPointsSync() : sync_length_{1}
{
    // file->open("C:/Users/HMDEyes/SPointsSync.log");
}

//////////////////////////////////////////////////////////////////////////////
scm::math::mat<double, 4u, 4u> SPointsSync::get_synchronized(scm::math::mat<double, 4u, 4u> const& matrix, bool is_left)
{
    // *file << "sync lenght is " << sync_length << std::endl;
    // *file << "pushing matrix to queue:" << std::endl;
    // *file << matrix << std::endl;
    if(sync_length_ == 0)
    {
        return matrix;
    }
    if(is_left)
    {
        sync_queue_l_->push(matrix);
        if(sync_queue_l_->size() > sync_length_)
        {
            sync_queue_l_->pop();
        }

        return sync_queue_l_->front();
    }
    else
    {
        sync_queue_r_->push(matrix);
        if(sync_queue_r_->size() > sync_length_)
        {
            sync_queue_r_->pop();
        }

        return sync_queue_r_->front();
    }
}

//////////////////////////////////////////////////////////////////////////////
scm::math::mat<double, 4u, 4u> SPointsSync::get_synchronized(scm::math::mat<double, 4u, 4u> const& matrix) { return get_synchronized(matrix, true); }

//////////////////////////////////////////////////////////////////////////////
void SPointsSync::set_sync_length(int new_sync_length)
{
    sync_length_ = new_sync_length;
    while(sync_length_ < sync_queue_l_->size())
    {
        sync_queue_l_->pop();
    }
    while(sync_length_ < sync_queue_r_->size())
    {
        sync_queue_r_->pop();
    }
}

//////////////////////////////////////////////////////////////////////////////
int SPointsSync::get_sync_length() { return sync_length_; }

} // namespace gua
