void LodResource::ray_test(Ray const& ray, int options, node::Node* owner, std::set<PickResult>& hits) { if (!is_pickable_) return; bool has_hit = false; PickResult pick = PickResult( 0.f, owner, ray.origin_, math::vec3(0.f, 0.f, 0.f), math::vec3(0.f, 1.f, 0.f), math::vec3(0.f, 1.f, 0.f), math::vec2(0.f, 0.f)); const auto model_transform = owner->get_cached_world_transform(); const auto world_origin = ray.origin_; const auto world_direction = scm::math::normalize(ray.direction_); lamure::ren::ray lod_ray(math::vec3f(world_origin), math::vec3f(world_direction), scm::math::length(ray.direction_)); lamure::ren::ray::intersection intersection; auto lod_node = reinterpret_cast<node::PLodNode*>(owner); float aabb_scale = 9.0f; unsigned int max_depth = 255; unsigned int surfel_skip = 1; bool wysiwyg = true; lamure::ren::controller* controller = lamure::ren::controller::get_instance(); lamure::model_t model_id = controller->deduce_model_id(lod_node->get_geometry_description()); if (lod_ray.intersect_model(model_id, math::mat4f(model_transform), aabb_scale, max_depth, surfel_skip, wysiwyg, intersection)) { has_hit = true; pick.distance = intersection.distance_; pick.world_position = intersection.position_; auto object_position = scm::math::inverse(model_transform) * gua::math::vec4(intersection.position_.x, intersection.position_.y, intersection.position_.z, 1.0); pick.position = math::vec3(object_position.x, object_position.y, object_position.z); pick.normal = intersection.normal_; } if (has_hit) { if (hits.empty()) { hits.insert(pick); } else if (pick.distance < hits.begin()->distance) { hits.insert(pick); } } }
void PLodNode::ray_test_impl(Ray const& ray, int options, Mask const& mask, std::set<PickResult>& hits) { // first of all, check bbox auto box_hits(::gua::intersect(ray, bounding_box_)); // ray did not intersect bbox -- therefore it wont intersect if (box_hits.first == Ray::END && box_hits.second == Ray::END) { return; } // return if only first object shall be returned and the current first hit // is in front of the bbox entry point and the ray does not start inside // the bbox if (options & PickResult::PICK_ONLY_FIRST_OBJECT && hits.size() > 0 && hits.begin()->distance < box_hits.first && box_hits.first != Ray::END) { return; } // bbox is intersected, but check geometry only if mask tells us to check if (get_geometry_description() != "" && mask.check(get_tags())) { auto geometry( GeometryDatabase::instance()->lookup(get_geometry_description())); if (geometry) { Ray world_ray(ray); geometry->ray_test(world_ray, options, this, hits); } } for (auto child : get_children()) { child->ray_test_impl(ray, options, mask, hits); } }
void LowQualitySplattingSubRenderer:: render_sub_pass(Pipeline& pipe, PipelinePassDescription const& desc, gua::plod_shared_resources& shared_resources, std::vector<node::Node*>& sorted_models, std::unordered_map<node::PLodNode*, std::unordered_set<lamure::node_t> >& nodes_in_frustum_per_model, lamure::context_t context_id, lamure::view_t lamure_view_id ) { auto const& camera = pipe.current_viewstate().camera; RenderContext const& ctx(pipe.get_context()); auto& target = *pipe.current_viewstate().target; scm::gl::context_all_guard context_guard(ctx.render_context); ctx.render_context->set_rasterizer_state(no_backface_culling_rasterizer_state_); bool write_depth = true; target.bind(ctx, write_depth); target.set_viewport(ctx); MaterialShader* current_material(nullptr); std::shared_ptr<ShaderProgram> current_material_program; bool program_changed = false; std::string const gpu_query_name_depth_pass = "******" + std::to_string(pipe.current_viewstate().viewpoint_uuid) + " / PLodRenderer::DepthPass"; pipe.begin_gpu_query(ctx, gpu_query_name_depth_pass); int view_id(camera.config.get_view_id()); //loop through all models and render depth pass for (auto const& object : sorted_models) { auto plod_node(reinterpret_cast<node::PLodNode*>(object)); current_material = plod_node->get_material()->get_shader(); current_material_program = _get_material_dependent_shader_program(current_material, current_material_program, program_changed); lamure::ren::controller* controller = lamure::ren::controller::get_instance(); lamure::model_t model_id = controller->deduce_model_id(plod_node->get_geometry_description()); std::unordered_set<lamure::node_t>& nodes_in_frustum = nodes_in_frustum_per_model[plod_node]; auto const& plod_resource = plod_node->get_geometry(); if (plod_resource && current_material_program) { if (program_changed) { current_material_program->unuse(ctx); current_material_program->use(ctx); current_material_program->set_uniform(ctx, target.get_depth_buffer()->get_handle(ctx), "gua_gbuffer_depth"); } plod_node->get_material()->apply_uniforms(ctx, current_material_program.get(), view_id); _upload_model_dependent_uniforms(current_material_program, ctx, plod_node, pipe); ctx.render_context->apply(); plod_resource->draw(ctx, context_id, lamure_view_id, model_id, controller->get_context_memory(context_id, lamure::ren::bvh::primitive_type::POINTCLOUD, ctx.render_device), nodes_in_frustum, scm::gl::primitive_topology::PRIMITIVE_POINT_LIST); program_changed = false; } else { Logger::LOG_WARNING << "PLodRenderer::render(): Cannot find ressources for node: " << plod_node->get_name() << std::endl; } } target.unbind(ctx); pipe.end_gpu_query(ctx, gpu_query_name_depth_pass); }