|
|
@@ -1,10 +1,13 @@
|
|
|
+#include "core/local_connection.h"
|
|
|
+#include "core/timestamp_helper.hpp"
|
|
|
#include "cuda_helper.hpp"
|
|
|
#include "frame_sender.h"
|
|
|
#include "image_process.h"
|
|
|
#include "mvs_camera.h"
|
|
|
#include "simple_mq.h"
|
|
|
#include "simple_opengl.h"
|
|
|
-#include "third_party/timestamp_helper.hpp"
|
|
|
+#include "third_party/scope_guard.hpp"
|
|
|
+#include "utility.hpp"
|
|
|
#include "variable_defs.h"
|
|
|
#include "video_encoder.h"
|
|
|
#include "vtk_viewer.h"
|
|
|
@@ -19,19 +22,25 @@
|
|
|
#include <opencv2/core/mat.hpp>
|
|
|
#include <opencv2/core/cuda.hpp>
|
|
|
|
|
|
+#include <vtkProperty.h>
|
|
|
+
|
|
|
#include <imgui.h>
|
|
|
#include <imgui_impl_glfw.h>
|
|
|
#include <imgui_impl_opengl3.h>
|
|
|
|
|
|
+#include <boost/iostreams/device/mapped_file.hpp>
|
|
|
+
|
|
|
#include <cassert>
|
|
|
#include <thread>
|
|
|
#include <queue>
|
|
|
+#include <vector>
|
|
|
|
|
|
using namespace simple_mq_singleton;
|
|
|
using namespace sophiar;
|
|
|
|
|
|
-// make sophiar happy
|
|
|
-local_time_type sophiar::program_start_time;
|
|
|
+using boost::iostreams::mapped_file;
|
|
|
+
|
|
|
+log_timer global_timer;
|
|
|
|
|
|
// global variable definition
|
|
|
CUcontext cuda_ctx = nullptr;
|
|
|
@@ -41,14 +50,13 @@ std::string left_camera_name, right_camera_name;
|
|
|
std::unique_ptr<mvs::camera> left_camera, right_camera;
|
|
|
mvs::capture_config capture_conf = {};
|
|
|
int preview_camera_index = 0; // 0 for left, 1 for right
|
|
|
-uint64_t left_raw_cnt = 0, right_raw_cnt = 0;
|
|
|
-std::unique_ptr<cv::cuda::GpuMat> left_img_dev, right_img_dev;
|
|
|
-std::unique_ptr<cv::cuda::Stream> left_stream, right_stream;
|
|
|
-cudaStream_t left_cuda_stream = nullptr, right_cuda_stream = nullptr;
|
|
|
-std::unique_ptr<monocular_processor> left_processor, right_processor;
|
|
|
std::unique_ptr<simple_render> opengl_render;
|
|
|
float process_frame_rate = 0;
|
|
|
bool enhance_image = false;
|
|
|
+bool augment_enable = false;
|
|
|
+cv::Size augment_render_size;
|
|
|
+double augment_render_angle = 0;
|
|
|
+std::unique_ptr<vtk_viewer> augment_viewer;
|
|
|
|
|
|
std::unique_ptr<std::thread> encoder_thread;
|
|
|
bool output_full_frame = false;
|
|
|
@@ -64,8 +72,89 @@ int sender_listen_port;
|
|
|
sender_config main_sender_conf;
|
|
|
std::unique_ptr<frame_sender> sender;
|
|
|
|
|
|
+std::string sophiar_config_path;
|
|
|
+std::unique_ptr<std::thread> sophiar_thread;
|
|
|
+local_connection sophiar_conn;
|
|
|
+bool last_command_success = true;
|
|
|
+
|
|
|
+bool show_vtk_debug = false;
|
|
|
+bool show_imgui_demo = false;
|
|
|
+std::unique_ptr<vtk_viewer> vtk_test1, vtk_test2;
|
|
|
+
|
|
|
+struct augment_store_type {
|
|
|
+ std::string name, trans_var;
|
|
|
+ vtkSmartPointer<vtkActor> actor;
|
|
|
+ int opacity = 100;
|
|
|
+};
|
|
|
+
|
|
|
+std::vector<augment_store_type> augment_items;
|
|
|
+
|
|
|
std::queue<void (*)()> simple_eq;
|
|
|
|
|
|
+struct camera_related {
|
|
|
+ uint64_t raw_cnt = 0;
|
|
|
+ std::unique_ptr<cv::cuda::GpuMat> img_dev;
|
|
|
+ std::unique_ptr<cv::cuda::Stream> stream;
|
|
|
+ cudaStream_t cuda_stream = nullptr;
|
|
|
+ std::unique_ptr<monocular_processor> processor;
|
|
|
+ std::string trans_var;
|
|
|
+
|
|
|
+ // remap related
|
|
|
+ std::string remap_data_path;
|
|
|
+ std::unique_ptr<smart_texture> remap_tex;
|
|
|
+ bool augment_available = false;
|
|
|
+ std::unique_ptr<smart_texture> augment_tex;
|
|
|
+
|
|
|
+ void wait_frame(simple_mq::index_type index) const {
|
|
|
+ uint64_t cur_cnt;
|
|
|
+ if (auto ptr = mq().query_variable_ptr<cv::Mat>(index, &cur_cnt);
|
|
|
+ ptr == nullptr || cur_cnt <= raw_cnt) {
|
|
|
+ mq().wait_variable(index, raw_cnt);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void process_frame(simple_mq::index_type index) {
|
|
|
+ uint64_t cur_cnt;
|
|
|
+ auto raw_ptr = mq().query_variable_ptr<cv::Mat>(index, &cur_cnt);
|
|
|
+ assert(cur_cnt > raw_cnt);
|
|
|
+ raw_cnt = cur_cnt;
|
|
|
+ processor->process(*raw_ptr, img_dev.get(), enhance_image, *stream);
|
|
|
+
|
|
|
+ if (augment_enable) {
|
|
|
+ auto trans = sophiar_conn.query_transform_variable(trans_var);
|
|
|
+ augment_available = trans.has_value();
|
|
|
+ if (augment_available) {
|
|
|
+ augment_viewer->set_camera_pose(trans.value());
|
|
|
+ augment_viewer->render(augment_render_size);
|
|
|
+
|
|
|
+ // copy rendered image
|
|
|
+ augment_tex->create(GL_RGBA8, img_dev->size());
|
|
|
+ glCopyImageSubData(augment_viewer->get_tex(), GL_TEXTURE_2D, 0, 0, 0, 0,
|
|
|
+ augment_tex->id, GL_TEXTURE_2D, 0, 0, 0, 0, img_dev->cols, img_dev->rows, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void render(const simple_rect &rect) {
|
|
|
+ assert(img_dev != nullptr);
|
|
|
+ opengl_render->render_rect(*img_dev, rect, false, cuda_stream);
|
|
|
+ if (augment_available) {
|
|
|
+ // create remap file if needed
|
|
|
+ if (remap_tex == nullptr) [[unlikely]] {
|
|
|
+ auto remap_file = mapped_file{remap_data_path, mapped_file::readonly};
|
|
|
+ auto size = img_dev->size();
|
|
|
+ assert(remap_file.size() == size.area() * CV_ELEM_SIZE(CV_32FC2));
|
|
|
+ auto remap_data = cv::Mat{size, CV_32FC2, (void *) remap_file.const_data()};
|
|
|
+ remap_tex = std::make_unique<smart_texture>();
|
|
|
+ upload_remap_data(remap_tex.get(), remap_data);
|
|
|
+ }
|
|
|
+ opengl_render->render_rect(augment_tex->id, rect, remap_tex->id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+camera_related left, right;
|
|
|
+
|
|
|
constexpr auto config_path = "./config.yaml";
|
|
|
|
|
|
void initialize_mq() {
|
|
|
@@ -90,14 +179,14 @@ void initialize_cuda() {
|
|
|
});
|
|
|
|
|
|
// create some cuda objects
|
|
|
- left_img_dev = std::make_unique<cv::cuda::GpuMat>();
|
|
|
- right_img_dev = std::make_unique<cv::cuda::GpuMat>();
|
|
|
- left_stream = std::make_unique<cv::cuda::Stream>();
|
|
|
- right_stream = std::make_unique<cv::cuda::Stream>();
|
|
|
- left_cuda_stream = (cudaStream_t) left_stream->cudaPtr();
|
|
|
- right_cuda_stream = (cudaStream_t) right_stream->cudaPtr();
|
|
|
- left_processor = std::make_unique<monocular_processor>();
|
|
|
- right_processor = std::make_unique<monocular_processor>();
|
|
|
+ left.img_dev = std::make_unique<cv::cuda::GpuMat>();
|
|
|
+ right.img_dev = std::make_unique<cv::cuda::GpuMat>();
|
|
|
+ left.stream = std::make_unique<cv::cuda::Stream>();
|
|
|
+ right.stream = std::make_unique<cv::cuda::Stream>();
|
|
|
+ left.cuda_stream = (cudaStream_t) left.stream->cudaPtr();
|
|
|
+ right.cuda_stream = (cudaStream_t) right.stream->cudaPtr();
|
|
|
+ left.processor = std::make_unique<monocular_processor>();
|
|
|
+ right.processor = std::make_unique<monocular_processor>();
|
|
|
output_stream = std::make_unique<cv::cuda::Stream>();
|
|
|
output_cuda_stream = (cudaStream_t) output_stream->cudaPtr();
|
|
|
output_frame_dev = std::make_shared<cv::cuda::GpuMat>();
|
|
|
@@ -116,6 +205,13 @@ void load_config() {
|
|
|
main_encoder_conf.frame_rate = capture_conf.frame_rate;
|
|
|
capture_conf.expo_time_ms = capture_param["expo_time_ms"].as<float>();
|
|
|
capture_conf.gain_db = capture_param["gain_db"].as<float>();
|
|
|
+ auto remap_conf = camera_conf["remap"];
|
|
|
+ augment_render_size = {remap_conf["width"].as<int>(),
|
|
|
+ remap_conf["height"].as<int>()};
|
|
|
+ augment_render_angle = remap_conf["angle"].as<double>();
|
|
|
+ auto remap_data_conf = remap_conf["data"];
|
|
|
+ left.remap_data_path = remap_data_conf["left"].as<std::string>();
|
|
|
+ right.remap_data_path = remap_data_conf["right"].as<std::string>();
|
|
|
|
|
|
// load main window config
|
|
|
auto window_conf = conf["main_window"];
|
|
|
@@ -134,6 +230,20 @@ void load_config() {
|
|
|
main_sender_conf.parity_rate = sender_conf["parity"].as<float>();
|
|
|
sender_listen_port = sender_conf["port"].as<int>();
|
|
|
|
|
|
+ // load sophiar config
|
|
|
+ auto sophiar_conf = conf["sophiar"];
|
|
|
+ sophiar_config_path = sophiar_conf["config"].as<std::string>();
|
|
|
+ left.trans_var = sophiar_conf["left_camera_trans_var"].as<std::string>();
|
|
|
+ right.trans_var = sophiar_conf["right_camera_trans_var"].as<std::string>();
|
|
|
+
|
|
|
+ // load augment items
|
|
|
+ for (auto item: sophiar_conf["augment"]) {
|
|
|
+ augment_items.emplace_back(
|
|
|
+ item["name"].as<std::string>(),
|
|
|
+ item["trans_var"].as<std::string>(),
|
|
|
+ load_stl(item["stl_file"].as<std::string>()));
|
|
|
+ }
|
|
|
+
|
|
|
// make variables exist
|
|
|
mq().update_variable(SENDER_CONNECTED, false);
|
|
|
mq().update_variable(REQUEST_IDR, false);
|
|
|
@@ -155,6 +265,7 @@ void initialize_main_window() {
|
|
|
"RemoteAR V3.-1", nullptr, nullptr);
|
|
|
assert(main_window != nullptr);
|
|
|
glfwMakeContextCurrent(main_window);
|
|
|
+ glfwSwapInterval(0);
|
|
|
|
|
|
// load opengl functions
|
|
|
auto version = gladLoadGL(glfwGetProcAddress);
|
|
|
@@ -189,6 +300,8 @@ void initialize_main_window() {
|
|
|
// initialize OpenGL objects
|
|
|
opengl_render = std::make_unique<simple_render>();
|
|
|
output_fbo = std::make_unique<smart_frame_buffer>();
|
|
|
+ left.augment_tex = std::make_unique<smart_texture>();
|
|
|
+ right.augment_tex = std::make_unique<smart_texture>();
|
|
|
|
|
|
// elegant cleanup
|
|
|
std::atexit([] {
|
|
|
@@ -199,6 +312,25 @@ void initialize_main_window() {
|
|
|
glfwDestroyWindow(main_window);
|
|
|
glfwTerminate();
|
|
|
});
|
|
|
+
|
|
|
+ // start sophiar
|
|
|
+ assert(sophiar_thread == nullptr);
|
|
|
+ sophiar_thread = std::make_unique<std::thread>([=] {
|
|
|
+ run_sophiar(sophiar_config_path);
|
|
|
+ });
|
|
|
+
|
|
|
+ // initialize vtk viewers
|
|
|
+ augment_viewer = std::make_unique<vtk_viewer>();
|
|
|
+ augment_viewer->set_camera_view_angle(augment_render_angle);
|
|
|
+ for (auto &item: augment_items) {
|
|
|
+ augment_viewer->add_actor(item.actor);
|
|
|
+ }
|
|
|
+
|
|
|
+ // initialize vtk test viewer
|
|
|
+ vtk_test1 = std::make_unique<vtk_viewer>();
|
|
|
+ vtk_test2 = std::make_unique<vtk_viewer>();
|
|
|
+ vtk_test1->add_actor(load_stl("/home/tpx/data/stls/GlassProbe_4Ball_3.STL"));
|
|
|
+ vtk_test2->add_actor(load_stl("/home/tpx/data/stls/HeadModelDrill.stl"));
|
|
|
}
|
|
|
|
|
|
bool is_camera_opened() {
|
|
|
@@ -349,11 +481,11 @@ void upload_encoder_config() {
|
|
|
|
|
|
void start_encoder() {
|
|
|
if (output_full_frame) {
|
|
|
- assert(!left_img_dev->empty() && !right_img_dev->empty());
|
|
|
- assert(left_img_dev->size() == right_img_dev->size());
|
|
|
+ assert(!left.img_dev->empty() && !right.img_dev->empty());
|
|
|
+ assert(left.img_dev->size() == right.img_dev->size());
|
|
|
main_encoder_conf.frame_size = cv::Size{
|
|
|
- left_img_dev->size().width * 2,
|
|
|
- left_img_dev->size().height};
|
|
|
+ left.img_dev->size().width * 2,
|
|
|
+ left.img_dev->size().height};
|
|
|
output_fbo->create(main_encoder_conf.frame_size);
|
|
|
} else {
|
|
|
main_encoder_conf.frame_size = cv::Size{output_width, output_height};
|
|
|
@@ -373,6 +505,10 @@ void stop_encoder() {
|
|
|
encoder_thread.reset();
|
|
|
}
|
|
|
|
|
|
+void start_tracking() {
|
|
|
+ last_command_success = sophiar_conn.start_object("tracker_all");
|
|
|
+}
|
|
|
+
|
|
|
void cleanup() {
|
|
|
close_cameras();
|
|
|
stop_encoder();
|
|
|
@@ -381,8 +517,14 @@ void cleanup() {
|
|
|
// avoid cudaErrorCudartUnloading
|
|
|
opengl_render.reset();
|
|
|
output_fbo.reset();
|
|
|
- left_processor.reset();
|
|
|
- right_processor.reset();
|
|
|
+ left.processor.reset();
|
|
|
+ right.processor.reset();
|
|
|
+
|
|
|
+ // stop sophiar
|
|
|
+ assert(sophiar_thread != nullptr);
|
|
|
+ stop_sophiar();
|
|
|
+ sophiar_thread->join();
|
|
|
+ sophiar_thread.reset();
|
|
|
}
|
|
|
|
|
|
void prepare_imgui_frame() {
|
|
|
@@ -392,7 +534,9 @@ void prepare_imgui_frame() {
|
|
|
ImGui_ImplGlfw_NewFrame();
|
|
|
ImGui::NewFrame();
|
|
|
|
|
|
- ImGui::ShowDemoWindow();
|
|
|
+ if (show_imgui_demo) {
|
|
|
+ ImGui::ShowDemoWindow();
|
|
|
+ }
|
|
|
|
|
|
if (ImGui::Begin("Remote AR Control")) {
|
|
|
ImGui::PushItemWidth(200);
|
|
|
@@ -494,6 +638,65 @@ void prepare_imgui_frame() {
|
|
|
ImGui::PopID();
|
|
|
}
|
|
|
|
|
|
+ if (ImGui::CollapsingHeader("Navigation")) {
|
|
|
+ ImGui::PushID("Encoder");
|
|
|
+
|
|
|
+ ImGui::SeparatorText("Actions");
|
|
|
+ if (ImGui::Button("Start Tracking")) {
|
|
|
+ simple_eq.push(start_tracking);
|
|
|
+ }
|
|
|
+
|
|
|
+ ImGui::SeparatorText("Infos");
|
|
|
+ if (last_command_success) {
|
|
|
+ ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4) ImColor(0, 255, 0));
|
|
|
+ } else {
|
|
|
+ ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4) ImColor(255, 0, 0));
|
|
|
+ }
|
|
|
+ ImGui::LabelText("Last Command", last_command_success ? "Success" : "Failed");
|
|
|
+ ImGui::PopStyleColor();
|
|
|
+
|
|
|
+ auto helper_func = [&](const std::string &var_name, const std::string &show_name, bool last = false) {
|
|
|
+ auto var = sophiar_conn.query_transform_variable(var_name);
|
|
|
+ bool var_ok = var.has_value();
|
|
|
+ if (var_ok) {
|
|
|
+ ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4) ImColor(0, 255, 0));
|
|
|
+ } else {
|
|
|
+ ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4) ImColor(255, 0, 0));
|
|
|
+ }
|
|
|
+ ImGui::Checkbox(show_name.c_str(), &var_ok);
|
|
|
+ ImGui::PopStyleColor();
|
|
|
+ if (!last) {
|
|
|
+ ImGui::SameLine();
|
|
|
+ }
|
|
|
+ };
|
|
|
+// ImGui::BeginDisabled();
|
|
|
+ helper_func("camera_ref_in_tracker", "Camera");
|
|
|
+ helper_func("probe_in_tracker", "Probe");
|
|
|
+ helper_func("femur_in_tracker", "Femur");
|
|
|
+ helper_func("tibia_in_tracker", "Tibia", true);
|
|
|
+// ImGui::EndDisabled();
|
|
|
+
|
|
|
+ ImGui::PopID();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ImGui::CollapsingHeader("Augment Render")) {
|
|
|
+ ImGui::PushID("Augment");
|
|
|
+
|
|
|
+ ImGui::SeparatorText("Configs");
|
|
|
+ ImGui::Checkbox("Enable", &augment_enable);
|
|
|
+
|
|
|
+ if (augment_enable) {
|
|
|
+ for (auto &item: augment_items) {
|
|
|
+ auto opacity_name = fmt::format("{} Opacity (%)", item.name);
|
|
|
+ if (ImGui::DragInt(opacity_name.c_str(), &item.opacity, 1, 0, 100)) {
|
|
|
+ item.actor->GetProperty()->SetOpacity(0.01 * item.opacity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ImGui::PopID();
|
|
|
+ }
|
|
|
+
|
|
|
// if (is_capturing() && ImGui::CollapsingHeader("Video Encoder")) {
|
|
|
if (ImGui::CollapsingHeader("Video Encoder")) {
|
|
|
ImGui::PushID("Encoder");
|
|
|
@@ -560,10 +763,28 @@ void prepare_imgui_frame() {
|
|
|
ImGui::PopID();
|
|
|
}
|
|
|
|
|
|
+ if (ImGui::CollapsingHeader("Debug")) {
|
|
|
+ ImGui::PushID("Debug");
|
|
|
+ ImGui::Checkbox("Debug VTK Viewer", &show_vtk_debug);
|
|
|
+ ImGui::Checkbox("Show ImGui Demo", &show_imgui_demo);
|
|
|
+ ImGui::PopID();
|
|
|
+ }
|
|
|
+
|
|
|
ImGui::PopItemWidth();
|
|
|
}
|
|
|
ImGui::End();
|
|
|
|
|
|
+ if (show_vtk_debug) {
|
|
|
+ if (ImGui::Begin("VTK Test A", nullptr, vtk_viewer::no_scroll_flag)) {
|
|
|
+ vtk_test1->show();
|
|
|
+ }
|
|
|
+ ImGui::End();
|
|
|
+ if (ImGui::Begin("VTK Test B", nullptr, vtk_viewer::no_scroll_flag)) {
|
|
|
+ vtk_test2->show();
|
|
|
+ }
|
|
|
+ ImGui::End();
|
|
|
+ }
|
|
|
+
|
|
|
ImGui::Render();
|
|
|
}
|
|
|
|
|
|
@@ -576,30 +797,21 @@ void handle_imgui_events() {
|
|
|
|
|
|
void wait_camera_frames() {
|
|
|
assert(is_capturing());
|
|
|
- uint64_t cur_cnt;
|
|
|
- if (auto ptr = mq().query_variable_ptr<cv::Mat>(IMG_RAW_HOST_LEFT, &cur_cnt);
|
|
|
- ptr == nullptr || cur_cnt <= left_raw_cnt) {
|
|
|
- mq().wait_variable(IMG_RAW_HOST_LEFT, left_raw_cnt);
|
|
|
- }
|
|
|
- if (auto ptr = mq().query_variable_ptr<cv::Mat>(IMG_RAW_HOST_RIGHT, &cur_cnt);
|
|
|
- ptr == nullptr || cur_cnt <= right_raw_cnt) {
|
|
|
- mq().wait_variable(IMG_RAW_HOST_RIGHT, right_raw_cnt);
|
|
|
- }
|
|
|
+ left.wait_frame(IMG_RAW_HOST_LEFT);
|
|
|
+ right.wait_frame(IMG_RAW_HOST_RIGHT);
|
|
|
}
|
|
|
|
|
|
void process_camera_frames() {
|
|
|
- // retrieve new frames
|
|
|
- uint64_t cur_cnt;
|
|
|
- auto left_raw_ptr = mq().query_variable_ptr<cv::Mat>(IMG_RAW_HOST_LEFT, &cur_cnt);
|
|
|
- assert(cur_cnt > left_raw_cnt);
|
|
|
- left_raw_cnt = cur_cnt;
|
|
|
- auto right_raw_ptr = mq().query_variable_ptr<cv::Mat>(IMG_RAW_HOST_RIGHT, &cur_cnt);
|
|
|
- assert(cur_cnt > right_raw_cnt);
|
|
|
- right_raw_cnt = cur_cnt;
|
|
|
-
|
|
|
- // process images
|
|
|
- left_processor->process(*left_raw_ptr, left_img_dev.get(), enhance_image, *left_stream);
|
|
|
- right_processor->process(*right_raw_ptr, right_img_dev.get(), enhance_image, *right_stream);
|
|
|
+ // update augment items' position
|
|
|
+ for (auto &item: augment_items) {
|
|
|
+ auto trans = sophiar_conn.query_transform_variable(item.trans_var);
|
|
|
+ if (trans.has_value()) {
|
|
|
+ update_actor_pose(item.actor, trans.value());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ left.process_frame(IMG_RAW_HOST_LEFT);
|
|
|
+ right.process_frame(IMG_RAW_HOST_RIGHT);
|
|
|
}
|
|
|
|
|
|
void render_main_window() {
|
|
|
@@ -611,19 +823,19 @@ void render_main_window() {
|
|
|
|
|
|
if (is_capturing()) {
|
|
|
// draw preview camera frame
|
|
|
- assert(left_img_dev->size() == right_img_dev->size());
|
|
|
- float width_normal = left_img_dev->size().aspectRatio() / frame_size.aspectRatio();
|
|
|
+ assert(left.img_dev->size() == right.img_dev->size());
|
|
|
+ float width_normal = left.img_dev->size().aspectRatio() / frame_size.aspectRatio();
|
|
|
auto render_rect = simple_rect{
|
|
|
-width_normal, 1, 2 * width_normal, -2
|
|
|
};
|
|
|
if (preview_camera_index == 0) { // left camera
|
|
|
- if (!left_img_dev->empty()) {
|
|
|
- opengl_render->render_rect(*left_img_dev, render_rect, false, left_cuda_stream);
|
|
|
+ if (!left.img_dev->empty()) {
|
|
|
+ left.render(render_rect);
|
|
|
}
|
|
|
} else { // right camera
|
|
|
assert(preview_camera_index == 1);
|
|
|
- if (!right_img_dev->empty()) {
|
|
|
- opengl_render->render_rect(*right_img_dev, render_rect, false, right_cuda_stream);
|
|
|
+ if (!right.img_dev->empty()) {
|
|
|
+ right.render(render_rect);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -640,21 +852,20 @@ void render_main_window() {
|
|
|
|
|
|
void generate_output_frame() {
|
|
|
// offline drawing
|
|
|
- assert(output_fbo->id != 0);
|
|
|
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, output_fbo->id);
|
|
|
- glViewport(0, 0, output_fbo->size().width, output_fbo->size().height);
|
|
|
+ output_fbo->bind();
|
|
|
+ auto closer = sg::make_scope_guard([&] { output_fbo->unbind(); });
|
|
|
simple_rect left_rect, right_rect;
|
|
|
if (output_full_frame) {
|
|
|
left_rect = simple_rect{-1, -1, 1, 2};
|
|
|
right_rect = simple_rect{0, -1, 1, 2};
|
|
|
} else {
|
|
|
- float width_normal = left_img_dev->size().aspectRatio() /
|
|
|
+ float width_normal = left.img_dev->size().aspectRatio() /
|
|
|
output_fbo->size().aspectRatio();
|
|
|
left_rect = simple_rect{-0.5f - width_normal / 2, -1, width_normal, 2};
|
|
|
right_rect = simple_rect{0.5f - width_normal / 2, -1, width_normal, 2};
|
|
|
}
|
|
|
- opengl_render->render_rect(*left_img_dev, left_rect, false, left_cuda_stream);
|
|
|
- opengl_render->render_rect(*right_img_dev, right_rect, false, right_cuda_stream);
|
|
|
+ left.render(left_rect);
|
|
|
+ right.render(right_rect);
|
|
|
|
|
|
// wait encoder idle
|
|
|
for (uint64_t cur_cnt = 0;;) {
|