int main(int argc, char** argv) { gua::init(argc, argv); //create simple untextured material shader auto lod_keep_input_desc = std::make_shared<gua::MaterialShaderDescription>("./data/materials/PLOD_use_input_color.gmd"); auto lod_keep_color_shader(std::make_shared<gua::MaterialShader>("PLOD_pass_input_color", lod_keep_input_desc)); gua::MaterialShaderDatabase::instance()->add(lod_keep_color_shader); //create material for pointcloud auto lod_rough = lod_keep_color_shader->make_new_material(); lod_rough->set_uniform("metalness", 0.2f); lod_rough->set_uniform("roughness", 0.4f); lod_rough->set_uniform("emissivity", 0.8f); //configure lod backend gua::LodLoader lod_loader; lod_loader.set_out_of_core_budget_in_mb(512); lod_loader.set_render_budget_in_mb(512); lod_loader.set_upload_budget_in_mb(20); //load a sample pointcloud auto plod_node = lod_loader.load_lod_pointcloud( "pointcloud", "/opt/3d_models/lamure/plod/pig_pr.bvh", lod_rough, gua::LodLoader::NORMALIZE_POSITION | gua::LodLoader::NORMALIZE_SCALE | gua::LodLoader::MAKE_PICKABLE); //load a sample mesh-based lod model auto mlod_node = lod_loader.load_lod_trimesh( //"tri_mesh", "/opt/3d_models/lamure/mlod/xyzrgb_dragon_7219k.bvh", //plod_rough, gua::LodLoader::NORMALIZE_POSITION | gua::LodLoader::NORMALIZE_SCALE/* | gua::LodLoader::MAKE_PICKABLE*/ ); mlod_node->set_error_threshold(0.25); //setup scenegraph gua::SceneGraph graph("main_scenegraph"); auto scene_transform = graph.add_node<gua::node::TransformNode>("/", "transform"); auto mlod_transform = graph.add_node<gua::node::TransformNode>("/transform", "mlod_transform"); auto plod_transform = graph.add_node<gua::node::TransformNode>("/transform", "plod_transform"); graph.add_node("/transform/mlod_transform", mlod_node); graph.add_node("/transform/plod_transform", plod_node); mlod_transform->translate(-0.4, 0.0, 0.0); plod_transform->rotate(180.0, 0.0, 1.0, 0.0); plod_transform->translate(0.3, 0.08, 0.0); //create a lightsource auto light_transform = graph.add_node<gua::node::TransformNode>("/transform", "light_transform"); auto light = graph.add_node<gua::node::LightNode>("/transform/light_transform", "light"); light->data.set_type(gua::node::LightNode::Type::POINT); light->data.set_enable_shadows(false); light->data.set_shadow_map_size(4096); light->data.brightness = 5.0f; light->translate(0.f, 0.2f, 0.f); light->scale(4.f); light->translate(0.f, 0.f, 1.f); auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen"); screen->data.set_size(gua::math::vec2(1.92f, 1.08f)); screen->translate(0, 0, 1.0); //add mouse interaction scm::gl::trackball_manipulator trackball; trackball.transform_matrix()*scm::math::make_translation(0.01f, 0.002f, 0.2f); trackball.dolly(0.2f); float dolly_sens = 1.5f; gua::math::vec2 trackball_init_pos(0.f); gua::math::vec2 last_mouse_pos(0.f); int button_state = -1; //setup rendering pipeline and window auto resolution = gua::math::vec2ui(1920, 1080); auto camera = graph.add_node<gua::node::CameraNode>("/screen", "cam"); camera->translate(0.0f, 0, 2.5f); camera->config.set_resolution(resolution); //use close near plane to allow inspection of details //camera->config.set_near_clip(0.01f); //camera->config.set_far_clip(200.0f); camera->config.set_screen_path("/screen"); camera->config.set_scene_graph_name("main_scenegraph"); camera->config.set_output_window_name("main_window"); camera->config.set_enable_stereo(true); auto PLod_Pass = std::make_shared<gua::PLodPassDescription>(); auto pipe = std::make_shared<gua::PipelineDescription>(); pipe->add_pass(std::make_shared<gua::MLodPassDescription>()); pipe->add_pass(PLod_Pass); pipe->add_pass(std::make_shared<gua::BBoxPassDescription>()); pipe->add_pass(std::make_shared<gua::LightVisibilityPassDescription>()); pipe->add_pass(std::make_shared<gua::ResolvePassDescription>()); pipe->add_pass(std::make_shared<gua::DebugViewPassDescription>()); camera->set_pipeline_description(pipe); pipe->get_resolve_pass()->tone_mapping_exposure(1.f); pipe->get_resolve_pass()->tone_mapping_method(gua::ResolvePassDescription::ToneMappingMethod::UNCHARTED); pipe->get_resolve_pass()->background_mode(gua::ResolvePassDescription::BackgroundMode::SKYMAP_TEXTURE); pipe->get_resolve_pass()->background_texture("data/textures/envlightmap.jpg"); //init window and window behaviour 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)); }); //trackball controls bool drag_mode = false; window->on_move_cursor.connect([&](gua::math::vec2 const& pos) { float nx = 2.f * float(pos.x - (resolution.x/2))/float(resolution.x); float ny = -2.f * float(resolution.y - pos.y - (resolution.y/2))/float(resolution.y); if (button_state != -1) { if (drag_mode) { auto ssize = screen->data.get_size(); gua::math::vec3 trans = gua::math::vec3(ssize.x *(nx - last_mouse_pos.x), ssize.y * (ny - last_mouse_pos.y), 0.f); auto object_trans = scm::math::inverse(screen->get_world_transform()) * mlod_transform->get_world_transform(); mlod_transform->set_world_transform(screen->get_world_transform() * scm::math::make_translation(trans) * object_trans); } else { if (button_state == 0) { // left trackball.rotation(trackball_init_pos.x, trackball_init_pos.y, nx, ny); } if (button_state == 1) { // right trackball.dolly(dolly_sens*0.5f * (ny - trackball_init_pos.y)); } if (button_state == 2) { // middle float f = dolly_sens < 1.0f ? 0.02f : 0.3f; trackball.translation(f*(nx - trackball_init_pos.x), f*(ny - trackball_init_pos.y)); } trackball_init_pos.x = nx; trackball_init_pos.y = ny; } } last_mouse_pos.x = nx; last_mouse_pos.y = ny; }); window->on_button_press.connect([&](int mousebutton, int action, int mods) { if (action == 1) { drag_mode = mods == 1; trackball_init_pos = last_mouse_pos; button_state = mousebutton; } else button_state = -1; }); window->on_key_press.connect(std::bind([&](gua::PipelineDescription& pipe, gua::SceneGraph& graph, int key, int scancode, int action, int mods) { if (action == 0) return; switch (std::tolower(key)) { case '1': PLod_Pass->mode(gua::PLodPassDescription::SurfelRenderMode::HQ_TWO_PASS); PLod_Pass->touch(); break; case '2': PLod_Pass->mode(gua::PLodPassDescription::SurfelRenderMode::HQ_LINKED_LIST); PLod_Pass->touch(); break; default: break; } }, std::ref(*(camera->get_pipeline_description())), std::ref(graph), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); window->open(); gua::Renderer renderer; //application loop gua::events::MainLoop loop; gua::events::Ticker ticker(loop, 1.0 / 500.0); ticker.on_tick.connect([&]() { screen->set_transform(scm::math::inverse(gua::math::mat4(trackball.transform_matrix()))); light->rotate(0.1, 0.f, 1.f, 0.f); window->process_events(); if (window->should_close()) { renderer.stop(); window->close(); loop.stop(); } else { renderer.queue_draw({ &graph }); std::cout << "FPS: " << window->get_rendering_fps() << " Frametime: " << 1000.f / window->get_rendering_fps() << std::endl; } }); loop.start(); return 0; }
int main(int argc, char** argv) { // initialize guacamole gua::init(argc, argv); // setup scene gua::SceneGraph graph("main_scenegraph"); gua::TriMeshLoader loader; auto teapot_mat(gua::MaterialShaderDatabase::instance() ->lookup("gua_default_material") ->make_new_material()); teapot_mat->set_render_wireframe(false); teapot_mat->set_show_back_faces(false); auto transform = graph.add_node<gua::node::TransformNode>("/", "transform"); auto teapot(loader.create_geometry_from_file( "teapot", "data/objects/teapot.obj", teapot_mat, gua::TriMeshLoader::NORMALIZE_POSITION | gua::TriMeshLoader::NORMALIZE_SCALE) ); graph.add_node("/transform", teapot); teapot->set_draw_bounding_box(true); auto portal = graph.add_node<gua::node::TexturedQuadNode>("/", "portal"); portal->data.set_size(gua::math::vec2(1.2f, 0.8f)); portal->data.set_texture("portal"); portal->translate(0.5f, 0.f, -0.2f); portal->rotate(-30, 0.f, 1.f, 0.f); auto light2 = graph.add_node<gua::node::LightNode>("/", "light2"); light2->data.set_type(gua::node::LightNode::Type::POINT); light2->data.brightness = 150.0f; light2->scale(12.f); light2->translate(-3.f, 5.f, 5.f); auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen"); screen->data.set_size(gua::math::vec2(1.92f, 1.08f)); screen->translate(0, 0, 1.0); auto portal_screen = graph.add_node<gua::node::ScreenNode>("/", "portal_screen"); portal_screen->translate(0.0, 0.0, 5.0); portal_screen->rotate(90, 0.0, 1.0, 0.0); portal_screen->data.set_size(gua::math::vec2(1.2f, 0.8f)); // add mouse interaction gua::utils::Trackball trackball(0.01, 0.002, 0.2); // setup rendering pipeline and window auto resolution = gua::math::vec2ui(1920, 1080); auto portal_camera = graph.add_node<gua::node::CameraNode>("/portal_screen", "portal_cam"); portal_camera->translate(0, 0, 2.0); portal_camera->config.set_resolution(gua::math::vec2ui(1200, 800)); portal_camera->config.set_screen_path("/portal_screen"); portal_camera->config.set_scene_graph_name("main_scenegraph"); portal_camera->config.set_output_texture_name("portal"); portal_camera->config.set_enable_stereo(false); auto portal_pipe = std::make_shared<gua::PipelineDescription>(); portal_pipe->add_pass(std::make_shared<gua::TriMeshPassDescription>()); portal_pipe->add_pass( std::make_shared<gua::LightVisibilityPassDescription>()); auto resolve_pass = std::make_shared<gua::ResolvePassDescription>(); resolve_pass->background_mode( gua::ResolvePassDescription::BackgroundMode::QUAD_TEXTURE); resolve_pass->tone_mapping_exposure(1.0f); portal_pipe->add_pass(resolve_pass); portal_pipe->add_pass(std::make_shared<gua::DebugViewPassDescription>()); portal_camera->set_pipeline_description(portal_pipe); 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"); camera->config.set_enable_stereo(false); camera->set_pre_render_cameras({portal_camera}); camera->get_pipeline_description()->get_resolve_pass()->tone_mapping_exposure( 1.0f); camera->get_pipeline_description()->add_pass( std::make_shared<gua::DebugViewPassDescription>()); 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->on_move_cursor.connect( [&](gua::math::vec2 const& pos) { trackball.motion(pos.x, pos.y); }); window->on_button_press.connect( std::bind(mouse_button, std::ref(trackball), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); gua::Renderer renderer; // application loop gua::events::MainLoop loop; gua::events::Ticker ticker(loop, 1.0 / 500.0); ticker.on_tick.connect([&]() { // apply trackball matrix to object gua::math::mat4 modelmatrix = scm::math::make_translation(trackball.shiftx(), trackball.shifty(), trackball.distance()) * gua::math::mat4(trackball.rotation()); transform->set_transform(modelmatrix); if (window->should_close()) { renderer.stop(); window->close(); loop.stop(); } else { renderer.queue_draw({&graph}); } }); loop.start(); return 0; }
int main(int argc, char** argv) { // initialize guacamole gua::init(argc, argv); // setup scene gua::SceneGraph graph("main_scenegraph"); gua::TriMeshLoader loader; auto transform = graph.add_node<gua::node::TransformNode>("/", "transform"); auto cube(loader.create_geometry_from_file( "cube", "data/objects/cube.obj", gua::TriMeshLoader::NORMALIZE_POSITION | gua::TriMeshLoader::NORMALIZE_SCALE | gua::TriMeshLoader::MAKE_PICKABLE) ); graph.add_node("/transform", cube); scm::math::vec3d cube_translation(0.0, 0.0, -3.0); cube->set_draw_bounding_box(true); auto ray_geometry(loader.create_geometry_from_file( "ray_geometry", "data/objects/cylinder.obj", gua::TriMeshLoader::NORMALIZE_POSITION | gua::TriMeshLoader::NORMALIZE_SCALE) ); graph.add_node("/", ray_geometry); ray_geometry->scale(0.02, 0.02, 0.1); auto light2 = graph.add_node<gua::node::LightNode>("/", "light2"); light2->data.set_type(gua::node::LightNode::Type::POINT); light2->data.brightness = 150.0f; light2->scale(12.f); light2->translate(-3.f, 5.f, 5.f); auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen"); screen->data.set_size(gua::math::vec2(1.92f, 1.08f)); screen->translate(0, 0, 1.0); // add mouse interaction gua::utils::Trackball trackball(0.01, 0.002, 0.2); // setup rendering pipeline and window auto resolution = gua::math::vec2ui(1920, 1080); 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("Picking Example"); camera->config.set_enable_stereo(false); camera->get_pipeline_description()->get_resolve_pass()->tone_mapping_exposure( 1.0f); camera->get_pipeline_description()->add_pass( std::make_shared<gua::DebugViewPassDescription>()); auto window = std::make_shared<gua::GlfwWindow>(); gua::WindowDatabase::instance()->add("Picking Example", 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->on_move_cursor.connect( [&](gua::math::vec2 const& pos) { trackball.motion(pos.x, pos.y); }); window->on_button_press.connect( std::bind(mouse_button, std::ref(trackball), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); gua::Renderer renderer; // application loop gua::events::MainLoop loop; gua::events::Ticker ticker(loop, 1.0 / 500.0); scm::math::vec3d camera_positon(0.0, 0.0, 2.0); scm::math::vec3d negative_z_viewing_direction(0.0, 0.0, -100.0); scm::math::vec3d::value_type t_max(200.0); //create ray that is located in the origin of the current screen and looks along the negative z-axis (pick ray is seen as circle) gua::Ray ray_from_camera_position(camera_positon, negative_z_viewing_direction, t_max); size_t frame_count = 0; ticker.on_tick.connect([&]() { // apply trackball matrix to object gua::math::mat4 modelmatrix = scm::math::make_translation(cube_translation[0], cube_translation[1], cube_translation[2]) * scm::math::make_translation(trackball.shiftx(), trackball.shifty(), trackball.distance()) * gua::math::mat4(trackball.rotation()); transform->set_transform(modelmatrix); if (window->should_close()) { renderer.stop(); window->close(); loop.stop(); } else { //std::set<gua::PickResult> pick_results; //cube->ray_test_impl(ray_from_camera_position, gua::PickResult::Options::PICK_ONLY_FIRST_FACE, gua::Mask(), pick_results); auto pick_results = graph.ray_test(ray_from_camera_position, gua::PickResult::Options::PICK_ONLY_FIRST_FACE | gua::PickResult::Options::GET_WORLD_POSITIONS); if(0 == (++frame_count) % 100) { if(pick_results.size()) { //print first picked face world position result std::cout << "World space intersection position: " << pick_results.begin()->world_position << "\n"; } } renderer.queue_draw({&graph}); } }); loop.start(); return 0; }
int main(int argc, char** argv) { // initialize guacamole gua::init(argc, argv); // setup scene gua::SceneGraph graph("main_scenegraph"); gua::TriMeshLoader loader; auto add_mesh = [&](int x, int y, int z) { auto t = graph.add_node<gua::node::TransformNode>("/", "mesh_" + std::to_string(x) + "_" + std::to_string(y)); t->scale(0.5); t->translate((x - COUNT * 0.5 + 0.5) / 2, (y - COUNT * 0.5 + 0.5) / 2, (z - COUNT * 0.5 + 0.5) / 2); auto mesh(loader.create_geometry_from_file("teapot", "data/objects/teapot.obj", gua::TriMeshLoader::NORMALIZE_POSITION | gua::TriMeshLoader::NORMALIZE_SCALE)); t->add_child(mesh); }; for(int x(0); x < COUNT; ++x) { for(int y(0); y < COUNT; ++y) { for(int z(0); z < COUNT; ++z) { add_mesh(x, y, z); } } } auto resolution = gua::math::vec2ui(1920, 1080); auto light = graph.add_node<gua::node::LightNode>("/", "light"); light->data.set_type(gua::node::LightNode::Type::POINT); light->scale(4.4f); light->translate(1.f, 0.f, 2.f); auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen"); screen->data.set_size(gua::math::vec2(0.001 * resolution.x, 0.001 * resolution.y)); screen->translate(0, 0, 1.0); 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"); camera->get_pipeline_description()->get_resolve_pass()->tone_mapping_exposure(0.8f); auto plane_transform = graph.add_node<gua::node::TransformNode>("/", "plane_transform"); auto add_clipping_plane = [&](gua::math::vec3 const& pos, gua::math::vec4 const& rot) { auto clipping_plane = graph.add_node<gua::node::ClippingPlaneNode>("/plane_transform", "clipping_plane"); clipping_plane->rotate(rot.x, rot.y, rot.z, rot.w); clipping_plane->translate(pos); auto plane(loader.create_geometry_from_file("plane", "data/objects/plane.obj", gua::TriMeshLoader::NORMALIZE_POSITION | gua::TriMeshLoader::NORMALIZE_SCALE)); plane->rotate(-90, 1, 0, 0); // clipping_plane->add_child(plane); }; add_clipping_plane(gua::math::vec3(0, 0, -0.5), gua::math::vec4(180, 1, 0, 0)); add_clipping_plane(gua::math::vec3(0, 0, 0.5), gua::math::vec4(0, 0, 0, 0)); add_clipping_plane(gua::math::vec3(0, 0.5, 0), gua::math::vec4(-90, 1, 0, 0)); add_clipping_plane(gua::math::vec3(0, -0.5, 0), gua::math::vec4(90, 1, 0, 0)); add_clipping_plane(gua::math::vec3(-0.5, 0, 0), gua::math::vec4(-90, 0, 1, 0)); add_clipping_plane(gua::math::vec3(0.5, 0, 0), gua::math::vec4(90, 0, 1, 0)); // auto clipping_plane_2 = graph.add_node<gua::node::ClippingPlaneNode>("/plane_transform", "clipping_plane_2"); // clipping_plane_2->rotate(90, 1, 0, 0); // clipping_plane_2->translate(0, 0.5, 0); // add mouse interaction gua::utils::Trackball trackball(0.01, 0.002, 0.2); auto window = std::make_shared<gua::GlfwWindow>(); gua::WindowDatabase::instance()->add("main_window", window); window->config.set_enable_vsync(true); window->config.set_size(resolution); window->config.set_resolution(resolution); 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->on_move_cursor.connect([&](gua::math::vec2 const& pos) { trackball.motion(pos.x, pos.y); }); window->on_button_press.connect(std::bind(mouse_button, std::ref(trackball), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); window->open(); gua::Renderer renderer; // application loop gua::events::MainLoop loop; gua::events::Ticker ticker(loop, 1.0 / 500.0); ticker.on_tick.connect([&]() { // apply trackball matrix to object gua::math::mat4 modelmatrix = scm::math::make_translation(gua::math::float_t(trackball.shiftx()), gua::math::float_t(trackball.shifty()), gua::math::float_t(trackball.distance())) * gua::math::mat4(trackball.rotation()); plane_transform->set_transform(modelmatrix); window->process_events(); if(window->should_close()) { renderer.stop(); window->close(); loop.stop(); } else { renderer.queue_draw({&graph}); } }); loop.start(); return 0; }
int main(int argc, char** argv) { // initialize guacamole gua::init(argc, argv); auto load_mat = [](std::string const& file){ gua::MaterialShaderDescription desc; desc.load_from_file(file); auto shader(std::make_shared<gua::MaterialShader>(file, std::make_shared<gua::MaterialShaderDescription>(desc))); gua::MaterialShaderDatabase::instance()->add(shader); return shader->make_new_material(); }; // setup scene gua::SceneGraph graph("main_scenegraph"); gua::TriMeshLoader loader; auto transform = graph.add_node<gua::node::TransformNode>("/", "transform"); // load material and create monkey geometry auto projective_material(load_mat("data/materials/Projective_Texture_Material.gmd")); projective_material->set_uniform("projective_texture", std::string("data/textures/smiley.jpg")); auto monkey(loader.create_geometry_from_file("monkey", "data/objects/monkey.obj", projective_material, gua::TriMeshLoader::NORMALIZE_POSITION | gua::TriMeshLoader::NORMALIZE_SCALE)); monkey->scale(3); monkey->translate(0.0, 0.0, -1.0); graph.add_node("/transform", monkey); auto light2 = graph.add_node<gua::node::LightNode>("/", "light2"); light2->data.set_type(gua::node::LightNode::Type::POINT); light2->data.brightness = 150.0f; light2->scale(12.f); light2->translate(-3.f, 5.f, 5.f); auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen"); screen->data.set_size(gua::math::vec2(1.92f, 1.08f)); screen->translate(0, 0, 1.0); // add mouse interaction gua::utils::Trackball trackball(0.01, 0.002, 0.2); // setup rendering pipeline and window auto resolution = gua::math::vec2ui(1920, 1080); 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"); camera->config.set_enable_stereo(false); camera->get_pipeline_description()->add_pass(std::make_shared<gua::DebugViewPassDescription>()); // projector transform node, screen and transform node auto projector_transform = graph.add_node<gua::node::TransformNode>("/", "projector_transform"); projector_transform->translate(0.7, 0.0, 0.7); projector_transform->rotate(45.0, 0.0, 1.0, 0.0); graph.add_node("/", projector_transform); auto projector_screen = graph.add_node<gua::node::ScreenNode>("/projector_transform", "projector_screen"); projector_screen->data.set_size(gua::math::vec2(0.5f, 0.5f)); projector_screen->translate(0.0, 0.0, -1.0); graph.add_node("/projector_transform", projector_screen); auto projector_geometry(loader.create_geometry_from_file("projector_geometry", "data/objects/projector.obj", gua::TriMeshLoader::NORMALIZE_POSITION | gua::TriMeshLoader::LOAD_MATERIALS)); projector_geometry->scale(0.1); graph.add_node("/projector_transform", projector_geometry); 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->on_move_cursor.connect([&](gua::math::vec2 const& pos) { trackball.motion(pos.x, pos.y); }); window->on_button_press.connect(std::bind(mouse_button, std::ref(trackball), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); window->open(); gua::Renderer renderer; // application loop gua::events::MainLoop loop; gua::events::Ticker ticker(loop, 1.0/500.0); ticker.on_tick.connect([&]() { // apply trackball matrix to object gua::math::mat4 modelmatrix = scm::math::make_translation(gua::math::float_t(trackball.shiftx()), gua::math::float_t(trackball.shifty()), gua::math::float_t(trackball.distance())) * gua::math::mat4(trackball.rotation()); projector_transform->set_transform(modelmatrix); // use the guacamole frustum to calculate a view mat and projection mat for the projection auto projection_frustum = gua::Frustum::perspective(projector_transform->get_world_transform(), projector_screen->get_scaled_world_transform(), 0.1f, 1000.0f); auto projection_mat = projection_frustum.get_projection(); auto view_mat = projection_frustum.get_view(); // set these matrices as uniforms for the projection material projective_material->set_uniform("projective_texture_matrix", gua::math::mat4f(projection_mat * view_mat)); projective_material->set_uniform("view_texture_matrix", gua::math::mat4f(view_mat)); window->process_events(); if (window->should_close()) { renderer.stop(); window->close(); loop.stop(); } else { renderer.queue_draw({&graph}); } }); loop.start(); return 0; }