void ARVRController::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { set_process_internal(true); }; break; case NOTIFICATION_EXIT_TREE: { set_process_internal(false); }; break; case NOTIFICATION_INTERNAL_PROCESS: { // get our ARVRServer ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL(arvr_server); // find the tracker for our controller ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, controller_id); if (tracker == NULL) { // this controller is currently turned off is_active = false; button_states = 0; } else { is_active = true; set_transform(tracker->get_transform(true)); int joy_id = tracker->get_joy_id(); if (joy_id >= 0) { int mask = 1; // check button states for (int i = 0; i < 16; i++) { bool was_pressed = (button_states & mask) == mask; bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, i); if (!was_pressed && is_pressed) { emit_signal("button_pressed", i); button_states += mask; } else if (was_pressed && !is_pressed) { emit_signal("button_release", i); button_states -= mask; }; mask = mask << 1; }; } else { button_states = 0; }; }; }; break; default: break; }; };
void ARVRAnchor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { set_process_internal(true); }; break; case NOTIFICATION_EXIT_TREE: { set_process_internal(false); }; break; case NOTIFICATION_INTERNAL_PROCESS: { // get our ARVRServer ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL(arvr_server); // find the tracker for our anchor ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_ANCHOR, anchor_id); if (tracker == NULL) { // this anchor is currently not available is_active = false; } else { is_active = true; Transform transform; // we'll need our world_scale real_t world_scale = arvr_server->get_world_scale(); // get our info from our tracker transform.basis = tracker->get_orientation(); transform.origin = tracker->get_position(); // <-- already adjusted to world scale // our basis is scaled to the size of the plane the anchor is tracking // extract the size from our basis and reset the scale size = transform.basis.get_scale() * world_scale; transform.basis.orthonormalize(); // apply our reference frame and set our transform set_transform(arvr_server->get_reference_frame() * transform); }; }; break; default: break; }; };
void RigidBodyBullet::set_state(PhysicsServer::BodyState p_state, const Variant &p_variant) { switch (p_state) { case PhysicsServer::BODY_STATE_TRANSFORM: set_transform(p_variant); break; case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: set_linear_velocity(p_variant); break; case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: set_angular_velocity(p_variant); break; case PhysicsServer::BODY_STATE_SLEEPING: set_activation_state(!bool(p_variant)); break; case PhysicsServer::BODY_STATE_CAN_SLEEP: can_sleep = bool(p_variant); if (!can_sleep) { // Can't sleep btBody->forceActivationState(DISABLE_DEACTIVATION); } break; } }
void Object3D::set_look_at(const glm::vec3 &theLookAt, const glm::vec3 &theUp) { set_transform(glm::inverse(glm::lookAt(position(), theLookAt, theUp)) * glm::scale(mat4(), scale())); }
void SceneNode::rotate(double angle, const QVector3D& axis) { QMatrix4x4 m; m.rotate(angle, axis); set_transform(get_transform() * m); }
void Spatial::rotate(const Vector3 &p_axis, float p_angle) { Transform t = get_transform(); t.basis.rotate(p_axis, p_angle); set_transform(t); }
void Spatial::scale_object_local(const Vector3 &p_scale) { Transform t = get_transform(); t.basis.scale_local(p_scale); set_transform(t); }
void Spatial::set_identity() { set_transform(Transform()); }
void Spatial::scale(const Vector3 &p_ratio) { Transform t = get_transform(); t.basis.scale(p_ratio); set_transform(t); }
void Spatial::rotate_z(float p_radians) { Transform t = get_transform(); t.basis.rotate(Vector3(0, 0, 1), p_radians); set_transform(t); }
void SceneNode::scale(const Vector3D& amount) { set_transform(m_trans*scaling(amount)); }
void SceneNode::rotate(char axis, double angle) { set_transform(m_trans*rotation(angle, axis)); }
shooting(main_window *w): window(*w), config(keyconfig::get_instance()), holder(std::make_shared<resource_holder>()), player_(holder) { register_resource(holder.get()); register_object(&dialog); dialog.set_button_text(0, L"はい"); dialog.set_button_handler(0, [this](){ this->dialog.hide(); on_hide(); on_show(); }); dialog.set_button_text(1, L"いいえ"); dialog.set_button_handler(1, [this](){ this->dialog.hide(); this->window.select_scene(main_window::scene::title); }); dialog.set_size(paint::size(300, 200)); dialog.set_position(paint::point(250, 200)); add_keyboard_handler([this](unsigned keycode, bool push){ config->set_keyboard_state(keycode, push); }, keycode_range(0, 255)); add_timer_handler([this](...){ if(pause) return; auto state = config->get_state(); vector v; const float velocity = 7.f; if(state.up){ v[1][0] -= velocity; } if(state.down){ v[1][0] += velocity; } if(state.left){ v[0][0] -= velocity; } if(state.right){ v[0][0] += velocity; } player_.set_vector(v); auto now = std::chrono::system_clock::now(); if(state.b && now - bullet_time >= std::chrono::milliseconds(192)){ auto it = std::find(bullets.begin(), bullets.end(), false); if(it != bullets.end()){ float r = it->get_radius(); it->set_position(player_.get_center()); it->set_vector(vector(0, -10)); it->set_active(); auto trans = transform::scale(1.f, 1.01f); if(state.a){ trans = transform::rotation(to_rad(-0.5)) * trans; } if(state.c){ trans = transform::rotation(to_rad(0.5)) * trans; } it->set_transform(trans); } bullet_time = now; } if(now - enemy_time >= enemy_duration){ enemy_duration = std::chrono::milliseconds(this->rand() % 750 + 250); enemy_time = now; enemies.push_back(new enemy1(holder)); enemies.back()->set_position(paint::point(static_cast<float>(this->rand() % 800), -50)); } move(); this->window.repaint(); }, timer_id); }
void SceneNode::rotate(char axis, double angle) { set_transform(m_trans.rotate(angle, (tolower(axis) == 'x') ? 1.0 : 0.0, (tolower(axis) == 'y') ? 1.0 : 0.0, (tolower(axis) == 'z') ? 1.0 : 0.0)); }
void PathFollow::_update_transform() { if (!path) return; Ref<Curve3D> c = path->get_curve(); if (!c.is_valid()) return; if (delta_offset == 0) { return; } float o = offset; if (loop) { o = Math::fposmod(o, c->get_baked_length()); } Vector3 pos = c->interpolate_baked(o, cubic); Transform t = get_transform(); t.origin = pos; Vector3 pos_offset = Vector3(h_offset, v_offset, 0); if (rotation_mode != ROTATION_NONE) { // perform parallel transport // // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example // for a discussion about why not Frenet frame. Vector3 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized(); Vector3 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized(); Vector3 axis = t_prev.cross(t_cur); float dot = t_prev.dot(t_cur); float angle = Math::acos(CLAMP(dot, -1, 1)); if (likely(Math::abs(angle) > CMP_EPSILON)) { if (rotation_mode == ROTATION_Y) { // assuming we're referring to global Y-axis. is this correct? axis.x = 0; axis.z = 0; } else if (rotation_mode == ROTATION_XY) { axis.z = 0; } else if (rotation_mode == ROTATION_XYZ) { // all components are allowed } if (likely(axis.length() > CMP_EPSILON)) { t.rotate_basis(axis.normalized(), angle); } } // do the additional tilting float tilt_angle = c->interpolate_baked_tilt(o); Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct?? if (likely(Math::abs(tilt_angle) > CMP_EPSILON)) { if (rotation_mode == ROTATION_Y) { tilt_axis.x = 0; tilt_axis.z = 0; } else if (rotation_mode == ROTATION_XY) { tilt_axis.z = 0; } else if (rotation_mode == ROTATION_XYZ) { // all components are allowed } if (likely(tilt_axis.length() > CMP_EPSILON)) { t.rotate_basis(tilt_axis.normalized(), tilt_angle); } } t.translate(pos_offset); } else { t.origin += pos_offset; } set_transform(t); }
void OrientedPathFollow::_update_transform() { if (!path) return; Ref<Curve3D> c = path->get_curve(); if (!c.is_valid()) return; int count = c->get_point_count(); if (count < 2) return; if (delta_offset == 0) { return; } float offset = get_offset(); float bl = c->get_baked_length(); float bi = c->get_bake_interval(); float o = offset; float o_next = offset + bi; if (has_loop()) { o = Math::fposmod(o, bl); o_next = Math::fposmod(o_next, bl); } else if (o_next >= bl) { o = bl - bi; o_next = bl; } bool cubic = get_cubic_interpolation(); Vector3 pos = c->interpolate_baked(o, cubic); Vector3 forward = c->interpolate_baked(o_next, cubic) - pos; if (forward.length_squared() < CMP_EPSILON2) forward = Vector3(0, 0, 1); else forward.normalize(); Vector3 up = c->interpolate_baked_up_vector(o, true); if (o_next < o) { Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); Vector3 axis = up.cross(up1); if (axis.length_squared() < CMP_EPSILON2) axis = forward; else axis.normalize(); up.rotate(axis, up.angle_to(up1) * 0.5f); } Transform t = get_transform(); Vector3 scale = t.basis.get_scale(); Vector3 sideways = up.cross(forward).normalized(); up = forward.cross(sideways).normalized(); t.basis.set(sideways, up, forward); t.basis.scale_local(scale); t.origin = pos + sideways * get_h_offset() + up * get_v_offset(); set_transform(t); }
void PathFollow::_update_transform() { if (!path) return; Ref<Curve3D> c = path->get_curve(); if (!c.is_valid()) return; if (delta_offset == 0) { return; } float bl = c->get_baked_length(); if (bl == 0.0) { return; } float bi = c->get_bake_interval(); float o = offset; float o_next = offset + bi; if (loop) { o = Math::fposmod(o, bl); o_next = Math::fposmod(o_next, bl); } else if (rotation_mode == ROTATION_ORIENTED && o_next >= bl) { o = bl - bi; o_next = bl; } Vector3 pos = c->interpolate_baked(o, cubic); Transform t = get_transform(); // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used if (rotation_mode == ROTATION_ORIENTED) { Vector3 forward = c->interpolate_baked(o_next, cubic) - pos; if (forward.length_squared() < CMP_EPSILON2) forward = Vector3(0, 0, 1); else forward.normalize(); Vector3 up = c->interpolate_baked_up_vector(o, true); if (o_next < o) { Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); Vector3 axis = up.cross(up1); if (axis.length_squared() < CMP_EPSILON2) axis = forward; else axis.normalize(); up.rotate(axis, up.angle_to(up1) * 0.5f); } Vector3 scale = t.basis.get_scale(); Vector3 sideways = up.cross(forward).normalized(); up = forward.cross(sideways).normalized(); t.basis.set(sideways, up, forward); t.basis.scale_local(scale); t.origin = pos + sideways * h_offset + up * v_offset; } else if (rotation_mode != ROTATION_NONE) { // perform parallel transport // // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example // for a discussion about why not Frenet frame. t.origin = pos; Vector3 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized(); Vector3 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized(); Vector3 axis = t_prev.cross(t_cur); float dot = t_prev.dot(t_cur); float angle = Math::acos(CLAMP(dot, -1, 1)); if (likely(Math::abs(angle) > CMP_EPSILON)) { if (rotation_mode == ROTATION_Y) { // assuming we're referring to global Y-axis. is this correct? axis.x = 0; axis.z = 0; } else if (rotation_mode == ROTATION_XY) { axis.z = 0; } else if (rotation_mode == ROTATION_XYZ) { // all components are allowed } if (likely(axis.length() > CMP_EPSILON)) { t.rotate_basis(axis.normalized(), angle); } } // do the additional tilting float tilt_angle = c->interpolate_baked_tilt(o); Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct?? if (likely(Math::abs(tilt_angle) > CMP_EPSILON)) { if (rotation_mode == ROTATION_Y) { tilt_axis.x = 0; tilt_axis.z = 0; } else if (rotation_mode == ROTATION_XY) { tilt_axis.z = 0; } else if (rotation_mode == ROTATION_XYZ) { // all components are allowed } if (likely(tilt_axis.length() > CMP_EPSILON)) { t.rotate_basis(tilt_axis.normalized(), tilt_angle); } } t.translate(Vector3(h_offset, v_offset, 0)); } else { t.origin = pos + Vector3(h_offset, v_offset, 0); } set_transform(t); }
int main(int argc, char** argv) { // initialize guacamole gua::init(argc, argv); gua::ShadingModelDatabase::load_shading_models_from("data/materials/"); gua::MaterialDatabase::load_materials_from("data/materials/"); // initialize Oculus SDK OVR::SensorFusion* oculus_sensor = init_oculus(); if (!oculus_sensor) return 1; // no oculus sensor found // setup scene gua::SceneGraph graph("main_scenegraph"); gua::TriMeshLoader loader; auto monkey_geometry(loader.create_geometry_from_file( "root_ape", geometry, "data/materials/Stones.gmd" )); auto root_monkey = graph.add_node("/", monkey_geometry); root_monkey->scale(0.5, 0.5, 0.5); // depth monkey cube car // 1 14.084 56 3.619.000 Vertices / 7 draw calls // 2 74.444 296 19.129.000 Vertices / 37 draw calls // 3 436.604 1.736 112.189.000 Vertices / 217 draw calls // 4 2.609.564 10.376 Vertices / 1.297 draw calls // 5 15.647.324 62.216 Vertices / 7.777 draw calls // 6 93.873.884 373.256 Vertices / 46.657 draw calls setup_scene(graph, root_monkey, 4); auto lights = add_lights(graph, 50); auto pos = graph.add_node<gua::node::TransformNode>("/", "pos"); pos->translate(0, 0, 2); auto nav = graph.add_node<gua::node::TransformNode>("/pos", "nav"); auto screen = graph.add_node<gua::node::ScreenNode>("/pos/nav", "screen_l"); screen->data.set_size(gua::math::vec2(0.08, 0.1)); screen->translate(-0.04, 0, -0.05f); screen = graph.add_node<gua::node::ScreenNode>("/pos/nav", "screen_r"); screen->data.set_size(gua::math::vec2(0.08, 0.1)); screen->translate(0.04, 0, -0.05f); auto eye = graph.add_node<gua::node::TransformNode>("/pos/nav", "eye_l"); eye->translate(-0.032, 0, 0); eye = graph.add_node<gua::node::TransformNode>("/pos/nav", "eye_r"); eye->translate(0.032, 0, 0); unsigned width = 1280/2; unsigned height = 800; auto pipe = new gua::Pipeline(); pipe->config.set_camera(gua::Camera("/pos/nav/eye_l", "/pos/nav/eye_r", "/pos/nav/screen_l", "/pos/nav/screen_r", "main_scenegraph")); pipe->config.set_left_resolution(gua::math::vec2ui(width, height)); pipe->config.set_right_resolution(gua::math::vec2ui(width, height)); pipe->config.set_enable_fps_display(true); pipe->config.set_enable_frustum_culling(true); pipe->config.set_enable_stereo(true); pipe->config.set_enable_ssao(true); pipe->config.set_ssao_intensity(2.f); pipe->config.set_enable_fxaa(true); pipe->config.set_enable_hdr(true); pipe->config.set_hdr_key(5.f); pipe->config.set_enable_bloom(true); pipe->config.set_bloom_radius(10.f); pipe->config.set_bloom_threshold(0.8f); pipe->config.set_bloom_intensity(0.8f); #if WIN32 auto oculus_window(new gua::OculusWindow("\\\\.\\DISPLAY1")); #else auto oculus_window(new gua::OculusWindow(":0.0")); #endif pipe->set_window(oculus_window); gua::Renderer renderer({ pipe }); gua::Timer timer; timer.start(); double time(0); float desired_frame_time(1.0 / 60.0); gua::events::MainLoop loop; // application loop gua::events::Ticker ticker(loop, desired_frame_time); ticker.on_tick.connect([&]() { double frame_time(timer.get_elapsed()); time += frame_time; timer.reset(); std::function<void (std::shared_ptr<gua::node::Node>, int)> rotate; rotate = [&](std::shared_ptr<gua::node::Node> node, int depth) { node->rotate(frame_time * (1+depth) * 0.5, 1, 1, 0); for (auto child: node->get_children()) { rotate(child, ++depth); } }; rotate(graph["/root_ape"], 1); for (int i = 0; i < lights.size(); ++i) { lights[i]->rotate( std::sin(time * (i * 0.1 + 0.5)) * frame_time * 2.5, 0, 1, 0); } graph["/root_ape"]->rotate(15 * frame_time, 0, 1, 0); //graph["/screen"]->rotate(20*frame_time, 0, 1, 0); nav->set_transform(get_oculus_transform(oculus_sensor)); renderer.queue_draw({&graph}); }); loop.start(); return 0; }
void Spatial::rotate(const Vector3 &p_normal, float p_radians) { Transform t = get_transform(); t.basis.rotate(p_normal, p_radians); set_transform(t); }
void SceneNode::translate(const Vector3D& amount) { set_transform(m_trans*translation(amount)); }
void Spatial::translate(const Vector3 &p_offset) { Transform t = get_transform(); t.translate(p_offset); set_transform(t); }
int main(int argc, char** argv) { // initialize guacamole gua::init(argc, argv); // setup scene gua::SceneGraph graph("main_scenegraph"); gua::math::vec4 iron(0.560, 0.570, 0.580, 1); gua::math::vec4 silver(0.972, 0.960, 0.915, 1); gua::math::vec4 aluminium(0.913, 0.921, 0.925, 1); gua::math::vec4 gold(1.000, 0.766, 0.336, 1); gua::math::vec4 copper(0.955, 0.637, 0.538, 1); gua::math::vec4 chromium(0.550, 0.556, 0.554, 1); gua::math::vec4 nickel(0.660, 0.609, 0.526, 1); gua::math::vec4 titanium(0.542, 0.497, 0.449, 1); gua::math::vec4 cobalt(0.662, 0.655, 0.634, 1); gua::math::vec4 platinum(0.672, 0.637, 0.585, 1); auto pbrMat(gua::MaterialShaderDatabase::instance()->lookup("gua_default_material")->make_new_material()); // pbrMat.set_uniform("Color", chromium); // pbrMat.set_uniform("Roughness", 0.2f); // pbrMat.set_uniform("Metalness", 1.0f); std::string directory("/opt/3d_models/Cerberus_by_Andrew_Maximov/Textures/"); pbrMat->set_uniform("ColorMap", directory + "Cerberus_A.tga"); pbrMat->set_uniform("MetalnessMap", directory + "Cerberus_M.tga"); pbrMat->set_uniform("RoughnessMap", directory + "Cerberus_R.tga"); pbrMat->set_uniform("NormalMap", directory + "Cerberus_N.negated_green.tga"); gua::TriMeshLoader loader; auto transform = graph.add_node<gua::node::TransformNode>("/", "transform"); auto cerberus(loader.create_geometry_from_file( "cerberus", "/opt/3d_models/Cerberus_by_Andrew_Maximov/Cerberus_LP.3ds", pbrMat, gua::TriMeshLoader::NORMALIZE_POSITION | gua::TriMeshLoader::NORMALIZE_SCALE)); graph.add_node("/transform", cerberus); cerberus->set_draw_bounding_box(true); cerberus->rotate(90, 0.f, 1.f, 0.f); cerberus->rotate(90, 0.f, 0.f, 1.f); auto pointLight = graph.add_node<gua::node::LightNode>("/", "pointLight"); pointLight->data.set_type(gua::node::LightNode::Type::POINT); pointLight->data.color = gua::utils::Color3f(1.0f, 1.0f, 1.0f); pointLight->data.brightness = 150.0f; // lm pointLight->scale(9.f); pointLight->translate(-2.f, 3.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 resolution = gua::math::vec2ui(2560, 1440); std::string skymaps_dir("/opt/guacamole/resources/skymaps/"); for(auto const& file : {std::string(directory + "Cerberus_A.tga"), std::string(directory + "Cerberus_M.tga"), std::string(directory + "Cerberus_R.tga"), std::string(directory + "Cerberus_N.negated_green.tga"), std::string(skymaps_dir + "skymap.jpg")}) { gua::TextureDatabase::instance()->load(file); } auto tiledPipe(std::make_shared<gua::PipelineDescription>()); tiledPipe->add_pass(std::make_shared<gua::TriMeshPassDescription>()); tiledPipe->add_pass(std::make_shared<gua::LightVisibilityPassDescription>()); tiledPipe->add_pass(std::make_shared<gua::ResolvePassDescription>()); 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_pipeline_description(tiledPipe); 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); size_t ctr{}; 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()); transform->set_transform(modelmatrix); 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()) { renderer.stop(); window->close(); loop.stop(); } else { renderer.queue_draw({&graph}); } }); loop.start(); return 0; }
void Spatial::orthonormalize() { Transform t = get_transform(); t.orthonormalize(); set_transform(t); }
int main(int argc, char** argv) { // initialize guacamole gua::init(argc, argv); ///////////////////////////////////////////////////////////////////////////// // create a set of materials ///////////////////////////////////////////////////////////////////////////// // create simple untextured material shader auto pbr_keep_input_desc = std::make_shared<gua::MaterialShaderDescription>("./data/materials/PBR_use_input_color.gmd"); auto pbr_uniform_color_desc = std::make_shared<gua::MaterialShaderDescription>("./data/materials/PBR_uniform_color.gmd"); //use this material for models where shading does not make sense auto pbr_keep_color_shader(std::make_shared<gua::MaterialShader>("PBR_pass_input_color", pbr_keep_input_desc)); auto pbr_overwrite_color_shader(std::make_shared<gua::MaterialShader>("PBR_overwrite_input_color", pbr_uniform_color_desc)); gua::MaterialShaderDatabase::instance()->add(pbr_keep_color_shader); gua::MaterialShaderDatabase::instance()->add(pbr_overwrite_color_shader); // create different materials for point-based input auto plod_glossy = pbr_keep_color_shader->make_new_material(); auto plod_rough = pbr_keep_color_shader->make_new_material(); auto plod_passthrough = pbr_keep_color_shader->make_new_material(); // glossy has high metalness, low roughness and no emissivity (=no passthrough) plod_glossy->set_uniform("metalness", 1.0f); plod_glossy->set_uniform("roughness", 0.3f); plod_glossy->set_uniform("emissivity", 0.0f); // rough has no metalness, high roughness and no emissivity (=no passthrough) plod_rough->set_uniform("metalness", 0.0f); plod_rough->set_uniform("roughness", 0.8f); plod_rough->set_uniform("emissivity", 1.0f); // passthrough has emissivity of 1.0 plod_passthrough->set_uniform("emissivity", 1.0f); auto rough_white = pbr_overwrite_color_shader->make_new_material(); rough_white->set_uniform("color", gua::math::vec3f(1.0f, 1.0f, 1.0f)); rough_white->set_uniform("metalness", 0.0f); rough_white->set_uniform("roughness", 0.8f); rough_white->set_uniform("emissivity", 0.0f); auto rough_red = pbr_overwrite_color_shader->make_new_material(); rough_red->set_uniform("color", gua::math::vec3f(0.8f, 0.0f, 0.0f)); rough_red->set_uniform("metalness", 0.0f); rough_red->set_uniform("roughness", 0.8f); rough_red->set_uniform("emissivity", 0.0f); // setup scene gua::SceneGraph graph("main_scenegraph"); gua::LodLoader plodLoader; plodLoader.set_upload_budget_in_mb(32); plodLoader.set_render_budget_in_mb(2048); plodLoader.set_out_of_core_budget_in_mb(4096); auto transform = graph.add_node<gua::node::TransformNode>("/", "transform"); auto model_xf = graph.add_node<gua::node::TransformNode>("/transform", "model_xf"); auto setup_plod_node = [](std::shared_ptr<gua::node::PLodNode> const& node) { node->set_radius_scale(1.0f); node->set_enable_backface_culling_by_normal(false); node->set_draw_bounding_box(true); }; #if WIN32 auto plod_pig_node = plodLoader.load_lod_pointcloud("plod_pig", "data/objects/Area_4_hunter_with_bow_knn.bvh", plod_rough, gua::LodLoader::NORMALIZE_POSITION | gua::LodLoader::NORMALIZE_SCALE | gua::LodLoader::MAKE_PICKABLE); #else auto plod_pig_node = plodLoader.load_lod_pointcloud("plod_pig", "/mnt/pitoti/3d_pitoti/groundtruth_data/rocks/seradina12c/areas/objects/Area_4_hunter_with_bow_knn.bvh", plod_rough, gua::LodLoader::NORMALIZE_POSITION | gua::LodLoader::NORMALIZE_SCALE | gua::LodLoader::MAKE_PICKABLE); #endif plod_pig_node->scale(5.0, 5.0, 5.0); plod_pig_node->rotate(269, gua::math::vec3(0.0, 0.0, 1.0)); gua::TriMeshLoader loader; auto root_plod_pig_model = graph.add_node("/", plod_pig_node); auto nav = graph.add_node<gua::node::TransformNode>("/", "nav"); nav->translate(0.0, 0.0, 1.0); #if WIN32 auto window = std::make_shared<gua::OculusWindow>(":0.0"); gua::WindowDatabase::instance()->add("main_window", window); window->config.set_enable_vsync(false); window->config.set_fullscreen_mode(false); window->open(); #else auto window = std::make_shared<gua::OculusWindow>(":0.0"); gua::WindowDatabase::instance()->add("main_window", window); window->config.set_enable_vsync(false); window->config.set_fullscreen_mode(true); window->config.set_size(window->get_window_resolution()); window->config.set_resolution(window->get_window_resolution()); window->open(); #endif //get the resolution from the oculus window gua::math::vec2ui res(window->get_window_resolution()); auto resolve_pass = std::make_shared<gua::ResolvePassDescription>(); resolve_pass->background_mode(gua::ResolvePassDescription::BackgroundMode::QUAD_TEXTURE); resolve_pass->tone_mapping_exposure(1.0f); auto neck = graph.add_node<gua::node::TransformNode>("/nav", "neck"); auto camera = graph.add_node<gua::node::CameraNode>("/nav/neck", "cam"); float camera_trans_y = 0.0; float camera_trans_z = 0.0; camera->translate(0.0, camera_trans_y, camera_trans_z); camera->config.set_resolution( res ); camera->config.set_left_screen_path("/nav/neck/cam/left_screen"); camera->config.set_right_screen_path("/nav/neck/cam/right_screen"); camera->config.set_scene_graph_name("main_scenegraph"); camera->config.set_output_window_name("main_window"); camera->config.set_enable_stereo(true); camera->config.set_eye_dist(window->get_IPD()); auto pipe = std::make_shared<gua::PipelineDescription>(); pipe->add_pass(std::make_shared<gua::PLodPassDescription>()); pipe->add_pass(std::make_shared<gua::LightVisibilityPassDescription>()); pipe->add_pass(std::make_shared<gua::ResolvePassDescription>()); camera->set_pipeline_description(pipe); // retreive the complete viewing setup from the oculus window //************** auto left_screen = graph.add_node<gua::node::ScreenNode>("/nav/neck/cam", "left_screen"); left_screen->data.set_size(window->get_left_screen_size()); left_screen->translate(window->get_left_screen_translation()); auto right_screen = graph.add_node<gua::node::ScreenNode>("/nav/neck/cam", "right_screen"); right_screen->data.set_size(window->get_right_screen_size()); right_screen->translate(window->get_right_screen_translation()); //****************/ gua::Renderer renderer; gua::Timer timer; timer.start(); double time(0); float desired_frame_time(1.0 / 60.0); gua::events::MainLoop loop; // application loop gua::events::Ticker ticker(loop, desired_frame_time); ticker.on_tick.connect([&]() { double frame_time(timer.get_elapsed()); time += frame_time; timer.reset(); window->process_events(); std::function<void (std::shared_ptr<gua::node::Node>, int)> rotate; rotate = [&](std::shared_ptr<gua::node::Node> node, int depth) { node->rotate(frame_time * (1+depth) * 0.5, 1, 1, 0); for (auto child: node->get_children()) { rotate(child, ++depth); } }; float frame_offset = 1.0 * frame_time; camera->set_transform(window->get_oculus_sensor_orientation()); //neck->set_transform(window->get_oculus_sensor_orientation()); renderer.queue_draw({&graph}); }); loop.start(); return 0; }
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; }
void Spatial::rotate_y(float p_angle) { Transform t = get_transform(); t.basis.rotate(Vector3(0, 1, 0), p_angle); set_transform(t); }
void SoftBody::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_WORLD: { if (Engine::get_singleton()->is_editor_hint()) { add_change_receptor(this); } RID space = get_world()->get_space(); PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space); update_physics_server(); } break; case NOTIFICATION_READY: { if (!parent_collision_ignore.is_empty()) add_collision_exception_with(get_node(parent_collision_ignore)); } break; case NOTIFICATION_TRANSFORM_CHANGED: { if (Engine::get_singleton()->is_editor_hint()) { _reset_points_offsets(); return; } PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform()); set_notify_transform(false); // Required to be top level with Transform at center of world in order to modify VisualServer only to support custom Transform set_as_toplevel(true); set_transform(Transform()); set_notify_transform(true); } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (!simulation_started) return; _update_cache_pin_points_datas(); // Submit bone attachment const int pinned_points_indices_size = pinned_points.size(); PoolVector<PinnedPoint>::Read r = pinned_points.read(); for (int i = 0; i < pinned_points_indices_size; ++i) { if (r[i].spatial_attachment) { PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); } } } break; case NOTIFICATION_VISIBILITY_CHANGED: { _update_pickable(); } break; case NOTIFICATION_EXIT_WORLD: { PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, RID()); } break; } #ifdef TOOLS_ENABLED if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { if (Engine::get_singleton()->is_editor_hint()) { update_configuration_warning(); } } #endif }
void SceneNode::translate(const QVector3D& amount) { QMatrix4x4 m; m.translate(amount); set_transform(get_transform() * m); }
int main(int argc, char** argv) { unsigned width = 800; unsigned height = 600; // initialize guacamole int argc_d = 0; char** argv_d = {}; gua::init(argc_d, argv_d); //gua::ShadingModelDatabase::load_shading_models_from("data/materials/"); //gua::MaterialDatabase::load_materials_from("data/materials/"); //gua::TextureDatabase::instance()->load("data/textures/0001MM_diff.jpg"); // setup scene gua::SceneGraph graph("main_scenegraph"); gua::TriMeshLoader trimeshloader; gua::NURBSLoader nurbsloader; // gua::Video3DLoader videoloader; // auto video_geode(videoloader.create_geometry_from_file("video_geode", argv[1])); auto teapot_geode(trimeshloader.create_geometry_from_file("teapot_geode", "data/objects/teapot.obj", "data/materials/Red.gmd", gua::TriMeshLoader::DEFAULTS)); auto plate_geode(trimeshloader.create_geometry_from_file("plate_geode", "data/objects/plate.obj", "data/materials/White.gmd", gua::TriMeshLoader::DEFAULTS)); auto nurbs_geode(nurbsloader.create_geometry_from_file("nurbs_geode", "data/objects/teapot.igs", "data/materials/Orange.gmd", gua::NURBSLoader::DEFAULTS)); auto video = graph.add_node<gua::node::TransformNode>("/", "video"); auto teapot = graph.add_node<gua::node::TransformNode>("/", "teapot"); auto nurbs = graph.add_node<gua::node::TransformNode>("/", "nurbs"); auto plate = graph.add_node<gua::node::TransformNode>("/", "plate"); // graph.add_node("/video", video_geode); graph.add_node("/teapot", teapot_geode); graph.add_node("/nurbs", nurbs_geode); graph.add_node("/plate", plate_geode); const float aspect = width * 1.0f/height; auto screen = graph.add_node<gua::node::ScreenNode>("/", "screen"); //screen->data.set_size(gua::math::vec2(aspect*0.05, 0.05)); screen->data.set_size(gua::math::vec2(aspect*2.0, 2.0)); screen->translate(0, 0, 6.f); auto screen2 = graph.add_node<gua::node::ScreenNode>("/", "screen2"); //screen2->data.set_size(gua::math::vec2(aspect*0.05, 0.05)); screen2->data.set_size(gua::math::vec2(aspect*2.0, 2.0)); screen2->translate(0, 0, 6.f); auto eye = graph.add_node<gua::node::TransformNode>("/screen", "eye"); //eye->translate(0.0, 0.0, 0.025); eye->translate(0.0, 0.0, 1.0); auto eye2 = graph.add_node<gua::node::TransformNode>("/screen2", "eye2"); //eye2->translate(0.0, 0.0, 0.025); eye2->translate(0.0, 0.0, 1.0); auto eye3 = graph.add_node<gua::node::TransformNode>("/", "eye3"); eye3->translate(-0.05, 0, 7.5); auto eye4 = graph.add_node<gua::node::TransformNode>("/", "eye4"); eye4->translate(0.05, 0, 7.5); auto eye5 = graph.add_node<gua::node::TransformNode>("/", "eye5"); eye5->translate(-0.05, 0, 6.5); auto eye6 = graph.add_node<gua::node::TransformNode>("/", "eye6"); eye6->translate(0.05, 0, 6.5); auto eye7 = graph.add_node<gua::node::TransformNode>("/", "eye7"); eye7->translate(-0.05, 0, 8.5); auto eye8 = graph.add_node<gua::node::TransformNode>("/", "eye8"); eye8->translate(0.05, 0, 8.5); #if 0 auto sunlight = graph.add_node<gua::node::SunLightNode>("/", "sunlight"); sunlight->data.set_shadow_map_size(1024); sunlight->data.set_shadow_offset(0.005f); sunlight->data.set_enable_shadows(true); sunlight->rotate(-90, 1, 0, 0); sunlight->translate(0, 0, -5); #endif #if 1 auto spotlight = graph.add_node<gua::node::SpotLightNode>("/", "spotlight"); spotlight->scale(30.0f); spotlight->rotate(-90, 1, 0, 0); spotlight->translate(1.0, 18.0, 1.0); spotlight->data.set_shadow_map_size(1024); spotlight->data.set_falloff(0.1f); spotlight->data.set_shadow_offset(0.005f); spotlight->data.set_color({ 1.0f, 1.0f, 1.0f }); //spotlight->data.set_enable_shadows(true); spotlight->data.set_enable_shadows(true); spotlight->data.set_enable_specular_shading(true); spotlight->data.set_enable_diffuse_shading(true); #endif auto pipe = new gua::Pipeline(); auto pipe2 = new gua::Pipeline(); auto pipe3 = new gua::Pipeline(); auto pipe4 = new gua::Pipeline(); pipe->config.set_camera(gua::Camera("/screen/eye", "/screen2/eye2", "/screen", "/screen2", "main_scenegraph")); pipe2->config.set_camera(gua::Camera("/eye3", "/eye4", "/screen", "/screen", "main_scenegraph")); pipe3->config.set_camera(gua::Camera("/eye5", "/eye6", "/screen", "/screen", "main_scenegraph")); pipe4->config.set_camera(gua::Camera("/eye7", "/eye8", "/screen", "/screen", "main_scenegraph")); set_pipe_defaults(pipe , width, height); set_pipe_defaults(pipe2, width, height); set_pipe_defaults(pipe3, width, height); set_pipe_defaults(pipe4, width, height); auto window (new gua::Window); auto window2(new gua::Window); auto window3(new gua::Window); auto window4(new gua::Window); #if WIN32 window->config.set_display_name("\\\\.\\DISPLAY1"); window2->config.set_display_name("\\\\.\\DISPLAY1"); window3->config.set_display_name("\\\\.\\DISPLAY1"); window4->config.set_display_name("\\\\.\\DISPLAY1"); #else window->config.set_display_name(":0.0"); window2->config.set_display_name(":0.0"); window3->config.set_display_name(":0.0"); window4->config.set_display_name(":0.0"); #endif set_window_default(window, width, height); set_window_default(window2, width, height); set_window_default(window3, width, height); set_window_default(window4, width, height); #if 0 //pipe->config.set_enable_stereo(true); pipe->config.set_enable_ssao(true); pipe->config.set_ssao_intensity(2.f); window->config.set_stereo_mode(gua::StereoMode::SIDE_BY_SIDE); window->config.set_size(gua::math::vec2ui(2 * width, height)); window->config.set_left_position(gua::math::vec2ui(0, 0)); window->config.set_right_position(gua::math::vec2ui(width, 0)); #endif pipe->set_window(window); pipe2->set_window(window2); pipe3->set_window(window3); pipe4->set_window(window4); #if 1 gua::Renderer renderer({ pipe, pipe2, pipe3, pipe4 }); #else gua::Renderer renderer({ pipe }); #endif // transform teapot auto bbox = teapot_geode->get_bounding_box(); teapot->translate(-bbox.center()); teapot->scale(5.0f / std::sqrt(bbox.size(0)*bbox.size(0) + bbox.size(1)*bbox.size(1) + bbox.size(2)*bbox.size(2))); teapot->translate(gua::math::vec3{ -2.0f, -1.5f, -4.0f }); // tranform nurbs bbox = nurbs_geode->get_bounding_box(); nurbs->translate(-bbox.center()); nurbs->scale(5.0f / std::sqrt(bbox.size(0)*bbox.size(0) + bbox.size(1)*bbox.size(1) + bbox.size(2)*bbox.size(2))); nurbs->rotate(-90, 1, 0, 0); nurbs->translate(gua::math::vec3{ 3.0f, -1.5f, -4.0f }); // transform plate plate->scale(0.07); plate->translate(0.0f, -4.0f, -4.0f); float time_value = 0; //nurbs_geode->translate(0.0f, 0.0f, 0.0f); // application loop while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); scm::math::mat4f ident; scm::math::set_identity(ident); video->set_transform(ident); video->scale(2.0f + std::sin(time_value)); //video->rotate(10.0f*time_value, 0, 1, 0); //video->translate(0, -2.0, -2.0); time_value += 0.01f; //video_geode->rotate(0.1, 0, 1, 0); teapot_geode->rotate(0.3, 0, 1, 0); nurbs_geode->rotate(0.3, 0, 0, 1); plate->translate(-plate->get_bounding_box().center()); plate->rotate(0.04f, 0, 1, 0); plate->translate(plate->get_bounding_box().center()); renderer.queue_draw({ &graph }); } return 0; }
SceneGraph::Iterator& SceneGraph::Iterator:: operator << (math::mat4 const& transform) { set_transform(transform); return *this; }