diff --git a/components/streams/CMakeLists.txt b/components/streams/CMakeLists.txt index 877940ec26dfbfede03c664933dace46c21a23ee..7bb5dc6ac6dda4b07fa9bfa13eed1a3fb56e0379 100644 --- a/components/streams/CMakeLists.txt +++ b/components/streams/CMakeLists.txt @@ -18,6 +18,7 @@ set(STREAMSRC src/renderer.cpp src/renderers/screen_render.cpp src/renderers/openvr_render.cpp + src/renderers/collisions.cpp ) add_library(ftlstreams ${STREAMSRC}) diff --git a/components/streams/src/renderers/collisions.cpp b/components/streams/src/renderers/collisions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca4262e750f15eef3dbff9a305595b31f8681a24 --- /dev/null +++ b/components/streams/src/renderers/collisions.cpp @@ -0,0 +1,67 @@ +#include "collisions.hpp" +#include <ftl/codecs/touch.hpp> +#include <ftl/utility/matrix_conversion.hpp> +#include <ftl/rgbd/capabilities.hpp> +#include <ftl/algorithms/dbscan.hpp> + +using ftl::codecs::Channel; +using ftl::rgbd::Capability; + +void ftl::render::collision2touch(const ftl::rgbd::Frame &rgbdframe, const std::vector<float4> &collisions, const std::list<ftl::data::FrameSetPtr> &sets, uint32_t myid) { + std::vector<float4> clusters; + std::vector<short> labels; + ftl::dbscan<float4>(collisions, [](const std::vector<float4> &pts, size_t idx, float radius) { + std::vector<size_t> neighbors; + for (auto i = 0u; i < pts.size(); i++) { + if (i == idx) { + continue; + } + float dx = pts[idx].x - pts[i].x; + float dy = pts[idx].y - pts[i].y; + + if (dx*dx+dy*dy < radius*radius) { + neighbors.push_back(i); + } + } + return neighbors; + }, 5, 16.0f, labels, clusters); + + // TODO: Support multi-touch + if (clusters.size() == 1) { + //LOG(INFO) << "Found " << clusters.size() << " collisions"; + //LOG(INFO) << " -- " << clusters[0].x << "," << clusters[0].y << " " << clusters[0].z; + + // Find all frames that support touch + for (auto &s : sets) { + if (s->frameset() == myid) continue; + + for (const auto &f : s->frames) { + if (f.has(Channel::Capabilities)) { + const auto &cap = f.get<std::unordered_set<Capability>>(Channel::Capabilities); + + // If it supports touch, calculate the touch points in screen coordinates + if (cap.count(Capability::TOUCH)){ + const auto &rgbdf = f.cast<ftl::rgbd::Frame>(); + auto pose = MatrixConversion::toCUDA((rgbdf.getPose().inverse() * rgbdframe.getPose()).cast<float>()); + float3 campos = pose * rgbdframe.getLeft().screenToCam(clusters[0].x, clusters[0].y, clusters[0].z); + int2 pt = rgbdf.getLeft().camToScreen<int2>(campos); + //LOG(INFO) << "TOUCH AT " << pt.x << "," << pt.y << " - " << campos.z; + + { + // Send the touch data + auto response = f.response(); + auto &touches = response.create<std::vector<ftl::codecs::Touch>>(Channel::Touch); + auto &touch = touches.emplace_back(); + touch.id = 0; + touch.x = pt.x; + touch.y = pt.y; + touch.type = ftl::codecs::TouchType::COLLISION; + touch.strength = 255; + touch.d = campos.z; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/components/streams/src/renderers/collisions.hpp b/components/streams/src/renderers/collisions.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a605759b8ab008cc6d9dc6865c0ec29b5469bfab --- /dev/null +++ b/components/streams/src/renderers/collisions.hpp @@ -0,0 +1,15 @@ +#ifndef _FTL_RENDER_COLLISIONS_HPP_ +#define _FTL_RENDER_COLLISIONS_HPP_ + +#include <ftl/data/new_frameset.hpp> +#include <ftl/rgbd/frame.hpp> + +namespace ftl { +namespace render { + +void collision2touch(const ftl::rgbd::Frame &rgbdframe, const std::vector<float4> &collisions, const std::list<ftl::data::FrameSetPtr> &sets, uint32_t myid); + +} +} + +#endif \ No newline at end of file diff --git a/components/streams/src/renderers/screen_render.cpp b/components/streams/src/renderers/screen_render.cpp index 580ebb84a1a67a15c774300b0dd6aa8f975c93db..a18b92c9f8af4ea5158a9555728f0b158a28108b 100644 --- a/components/streams/src/renderers/screen_render.cpp +++ b/components/streams/src/renderers/screen_render.cpp @@ -4,13 +4,12 @@ #include <ftl/rgbd/capabilities.hpp> #include <ftl/operators/antialiasing.hpp> #include <ftl/operators/gt_analysis.hpp> -#include <ftl/algorithms/dbscan.hpp> #include <ftl/utility/matrix_conversion.hpp> -#include <ftl/codecs/touch.hpp> #include <loguru.hpp> #include "screen_render.hpp" +#include "collisions.hpp" using ftl::render::Source; using ftl::render::ScreenRender; @@ -139,65 +138,9 @@ bool ScreenRender::retrieve(ftl::data::Frame &frame_out) { post_pipe_->apply(rgbdframe, rgbdframe, 0); - - const auto &collisions = renderer_->getCollisions(); - std::vector<float4> clusters; - std::vector<short> labels; - ftl::dbscan<float4>(collisions, [](const std::vector<float4> &pts, size_t idx, float radius) { - std::vector<size_t> neighbors; - for (auto i = 0u; i < pts.size(); i++) { - if (i == idx) { - continue; - } - float dx = pts[idx].x - pts[i].x; - float dy = pts[idx].y - pts[i].y; - - if (dx*dx+dy*dy < radius*radius) { - neighbors.push_back(i); - } - } - return neighbors; - }, 5, 16.0f, labels, clusters); - - // TODO: Support multi-touch - if (clusters.size() == 1) { - //LOG(INFO) << "Found " << clusters.size() << " collisions"; - //LOG(INFO) << " -- " << clusters[0].x << "," << clusters[0].y << " " << clusters[0].z; - - // Find all frames that support touch - for (auto &s : sets) { - if (s->frameset() == my_id_) continue; - - for (const auto &f : s->frames) { - if (f.has(Channel::Capabilities)) { - const auto &cap = f.get<std::unordered_set<Capability>>(Channel::Capabilities); - - // If it supports touch, calculate the touch points - if (cap.count(Capability::TOUCH)){ - const auto &rgbdf = f.cast<ftl::rgbd::Frame>(); - auto pose = MatrixConversion::toCUDA((rgbdf.getPose().inverse() * rgbdframe.getPose()).cast<float>()); - float3 campos = pose * rgbdframe.getLeft().screenToCam(clusters[0].x, clusters[0].y, clusters[0].z); - int2 pt = rgbdf.getLeft().camToScreen<int2>(campos); - //LOG(INFO) << "TOUCH AT " << pt.x << "," << pt.y << " - " << campos.z; - - { - // Send the touch data - auto response = f.response(); - auto &touches = response.create<std::vector<ftl::codecs::Touch>>(Channel::Touch); - auto &touch = touches.emplace_back(); - touch.id = 0; - touch.x = pt.x; - touch.y = pt.y; - touch.type = ftl::codecs::TouchType::COLLISION; - touch.strength = 255; - touch.d = campos.z; - } - } - } - } - } + if (host_->value("enable_touch", false)) { + ftl::render::collision2touch(rgbdframe, renderer_->getCollisions(), sets, my_id_); } - return true; } else { //LOG(INFO) << "Render fail";