File plugin.cpp
File List > debugview > plugin.cpp
Go to the documentation of this file
#include "plugin.hpp"
#include "illixr/data_format/imu.hpp"
#include "illixr/data_format/opencv_data_types.hpp"
#include "illixr/error_util.hpp"
#include "illixr/global_module_defs.hpp"
#include "illixr/imgui/backends/imgui_impl_glfw.h"
#include "illixr/imgui/backends/imgui_impl_opengl3.h"
#include "illixr/imgui/imgui.h"
#include "illixr/math_util.hpp"
#include "illixr/shader_util.hpp"
#include "illixr/shaders/demo_shader.hpp"
#include "illixr/switchboard.hpp"
#include "illixr/threadloop.hpp"
using namespace ILLIXR;
using namespace ILLIXR::data_format;
// Loosely inspired by
// http://spointeau.blogspot.com/2013/12/hello-i-am-looking-at-opengl-3.html
Eigen::Matrix4f look_at(const Eigen::Vector3f& eye, const Eigen::Vector3f& target, const Eigen::Vector3f& up) {
using namespace Eigen;
Vector3f look_dir = (target - eye).normalized();
Vector3f up_dir = up.normalized();
Vector3f side_dir = look_dir.cross(up_dir).normalized();
up_dir = side_dir.cross(look_dir);
Matrix4f result;
result << side_dir.x(), side_dir.y(), side_dir.z(), -side_dir.dot(eye), up_dir.x(), up_dir.y(), up_dir.z(),
-up_dir.dot(eye), -look_dir.x(), -look_dir.y(), -look_dir.z(), look_dir.dot(eye), 0, 0, 0, 1;
return result;
}
static void glfw_error_callback(int error, const char* description) {
spdlog::get("illixr")->error("|| glfw error_callback: {}\n|> {}", error, description);
ILLIXR::abort();
}
[[maybe_unused]] debugview::debugview(const std::string& name, phonebook* pb)
: threadloop{name, pb}
, switchboard_{phonebook_->lookup_impl<switchboard>()}
, pose_prediction_{phonebook_->lookup_impl<pose_prediction>()}
, slow_pose_reader_{switchboard_->get_reader<pose::head_pose_type>("slow_pose")}
, fast_pose_reader_{switchboard_->get_reader<imu_raw_type>("imu_raw")}
, rgb_depth_reader_(switchboard_->get_reader<rgb_depth_type>("rgb_depth"))
, cam_reader_{switchboard_->get_buffered_reader<data_format::binocular_cam_type>("cam")}
, display_backend_manages_glfw_{strcmp(switchboard_->get_env_char("ILLIXR_DISPLAY_MODE"), "glfw") == 0} {
spdlogger(switchboard_->get_env_char("DEBUGVIEW_LOG_LEVEL"));
}
void debugview::draw_GUI() {
RAC_ERRNO_MSG("debugview at start of draw_GUI");
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
// Calls glfw within source code which sets errno
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Init the window docked to the bottom left corner.
ImGui::SetNextWindowPos(ImVec2(0.0f, ImGui::GetIO().DisplaySize.y), ImGuiCond_Once, ImVec2(0.0f, 1.0f));
ImGui::Begin("ILLIXR Debug View");
ImGui::Text("Adjust options for the runtime debug view.");
ImGui::Spacing();
if (ImGui::CollapsingHeader("Headset visualization options", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::Checkbox("Follow headset position", &follow_headset_);
ImGui::SliderFloat("View distance ", &view_distance_, 0.1f, 10.0f);
ImGui::SliderFloat3("Tracking \"offset\"", tracking_position_offset_.data(), -10.0f, 10.0f);
if (ImGui::Button("Reset")) {
tracking_position_offset_ = Eigen::Vector3f{5.0f, 2.0f, -3.0f};
}
ImGui::SameLine();
ImGui::Text("Resets to default tracking universe");
if (ImGui::Button("Zero")) {
tracking_position_offset_ = Eigen::Vector3f{0.0f, 0.0f, 0.0f};
}
ImGui::SameLine();
ImGui::Text("Resets to zeroed out tracking universe");
if (ImGui::Button("Zero orientation")) {
const pose::head_pose_type predicted_pose = pose_prediction_->get_fast_pose().pose;
if (pose_prediction_->fast_pose_reliable()) {
// Can only zero if predicted_pose is valid
pose_prediction_->set_offset(predicted_pose.orientation);
}
}
ImGui::SameLine();
ImGui::Text("Resets to zeroed out tracking universe");
}
ImGui::Spacing();
ImGui::Text("Switchboard connection status:");
ImGui::Text("Predicted pose topic:");
ImGui::SameLine();
if (pose_prediction_->fast_pose_reliable()) {
const pose::head_pose_type predicted_pose = pose_prediction_->get_fast_pose().pose;
ImGui::TextColored(ImVec4(0.0, 1.0, 0.0, 1.0), "Valid predicted pose pointer");
ImGui::Text("Predicted pose position (XYZ):\n (%f, %f, %f)", predicted_pose.position.x(), predicted_pose.position.y(),
predicted_pose.position.z());
ImGui::Text("Predicted pose quaternion (XYZW):\n (%f, %f, %f, %f)", predicted_pose.orientation.x(),
predicted_pose.orientation.y(), predicted_pose.orientation.z(), predicted_pose.orientation.w());
} else {
ImGui::TextColored(ImVec4(1.0, 0.0, 0.0, 1.0), "Invalid predicted pose pointer");
}
ImGui::Text("Fast pose topic:");
ImGui::SameLine();
switchboard::ptr<const imu_raw_type> raw_imu = fast_pose_reader_.get_ro_nullable();
if (raw_imu) {
pose::head_pose_type raw_pose;
raw_pose.position = Eigen::Vector3f{float(raw_imu->pos(0)), float(raw_imu->pos(1)), float(raw_imu->pos(2))};
raw_pose.orientation = Eigen::Quaternionf{float(raw_imu->quat.w()), float(raw_imu->quat.x()), float(raw_imu->quat.y()),
float(raw_imu->quat.z())};
pose::head_pose_type swapped_pose = pose_prediction_->correct_pose(raw_pose);
ImGui::TextColored(ImVec4(0.0, 1.0, 0.0, 1.0), "Valid fast pose pointer");
ImGui::Text("Fast pose position (XYZ):\n (%f, %f, %f)", swapped_pose.position.x(), swapped_pose.position.y(),
swapped_pose.position.z());
ImGui::Text("Fast pose quaternion (XYZW):\n (%f, %f, %f, %f)", swapped_pose.orientation.x(),
swapped_pose.orientation.y(), swapped_pose.orientation.z(), swapped_pose.orientation.w());
} else {
ImGui::TextColored(ImVec4(1.0, 0.0, 0.0, 1.0), "Invalid fast pose pointer");
}
ImGui::Text("Slow pose topic:");
ImGui::SameLine();
switchboard::ptr<const pose::head_pose_type> slow_pose_ptr = slow_pose_reader_.get_ro_nullable();
if (slow_pose_ptr) {
pose::head_pose_type swapped_pose = pose_prediction_->correct_pose(*slow_pose_ptr);
ImGui::TextColored(ImVec4(0.0, 1.0, 0.0, 1.0), "Valid slow pose pointer");
ImGui::Text("Slow pose position (XYZ):\n (%f, %f, %f)", swapped_pose.position.x(), swapped_pose.position.y(),
swapped_pose.position.z());
ImGui::Text("Slow pose quaternion (XYZW):\n (%f, %f, %f, %f)", swapped_pose.orientation.x(),
swapped_pose.orientation.y(), swapped_pose.orientation.z(), swapped_pose.orientation.w());
} else {
ImGui::TextColored(ImVec4(1.0, 0.0, 0.0, 1.0), "Invalid slow pose pointer");
}
ImGui::Text("Ground truth pose topic:");
ImGui::SameLine();
if (pose_prediction_->true_pose_reliable()) {
const pose::head_pose_type true_pose = pose_prediction_->get_true_pose();
ImGui::TextColored(ImVec4(0.0, 1.0, 0.0, 1.0), "Valid ground truth pose pointer");
ImGui::Text("Ground truth position (XYZ):\n (%f, %f, %f)", true_pose.position.x(), true_pose.position.y(),
true_pose.position.z());
ImGui::Text("Ground truth quaternion (XYZW):\n (%f, %f, %f, %f)", true_pose.orientation.x(), true_pose.orientation.y(),
true_pose.orientation.z(), true_pose.orientation.w());
} else {
ImGui::TextColored(ImVec4(1.0, 0.0, 0.0, 1.0), "Invalid ground truth pose pointer");
}
ImGui::Text("Debug view Eulers:");
ImGui::Text(" (%f, %f)", view_euler_.x(), view_euler_.y());
ImGui::End();
ImGui::Begin("Camera + IMU");
ImGui::Text("Camera view buffers: ");
ImGui::Text(" Camera0: (%d, %d) \n GL texture handle: %d", camera_texture_size_[0].x(),
camera_texture_size_[0].y(), camera_texture_[0]);
ImGui::Text(" Camera1: (%d, %d) \n GL texture handle: %d", camera_texture_size_[1].x(),
camera_texture_size_[1].y(), camera_texture_[1]);
ImGui::End();
if (use_cam_) {
ImGui::SetNextWindowSize(ImVec2(700, 350), ImGuiCond_Once);
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y), ImGuiCond_Once,
ImVec2(1.0f, 1.0f));
ImGui::Begin("Onboard camera views");
auto window_size = ImGui::GetWindowSize();
auto vertical_offset = ImGui::GetCursorPos().y;
ImGui::Image((void*) (intptr_t) camera_texture_[0], ImVec2(window_size.x / 2, window_size.y - vertical_offset * 2));
ImGui::SameLine();
ImGui::Image((void*) (intptr_t) camera_texture_[1], ImVec2(window_size.x / 2, window_size.y - vertical_offset * 2));
ImGui::End();
}
if (use_rgb_depth_) {
ImGui::SetNextWindowSize(ImVec2(700, 350), ImGuiCond_Once);
// if there are RGBD stream and Stereo images stream, then move the RGBD display window up
// essentially making the display images of RGBD on top of stereo
if (use_cam_)
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y - 350), ImGuiCond_Once,
ImVec2(1.0f, 1.0f));
else
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y), ImGuiCond_Once,
ImVec2(1.0f, 1.0f));
ImGui::Begin("Onboard RGBD views");
auto window_size = ImGui::GetWindowSize();
auto vertical_offset = ImGui::GetCursorPos().y;
ImGui::Image((void*) (intptr_t) rgb_depth_texture_[0], ImVec2(window_size.x / 2, window_size.y - vertical_offset * 2));
ImGui::SameLine();
ImGui::Image((void*) (intptr_t) rgb_depth_texture_[1], ImVec2(window_size.x / 2, window_size.y - vertical_offset * 2));
ImGui::End();
}
ImGui::Render();
RAC_ERRNO_MSG("debugview after ImGui render");
}
bool debugview::load_camera_images() {
RAC_ERRNO_MSG("debugview at start of load_camera_images");
cam_ = cam_reader_.size() == 0 ? nullptr : cam_reader_.dequeue();
if (cam_ == nullptr) {
return false;
}
if (!use_cam_)
use_cam_ = true;
glBindTexture(GL_TEXTURE_2D, camera_texture_[0]);
cv::Mat img0{cam_->at(image::LEFT_EYE).clone()};
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, img0.cols, img0.rows, 0, GL_RED, GL_UNSIGNED_BYTE, img0.ptr());
camera_texture_size_[0] = Eigen::Vector2i(img0.cols, img0.rows);
GLint swizzle_mask[] = {GL_RED, GL_RED, GL_RED, GL_RED};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
glBindTexture(GL_TEXTURE_2D, camera_texture_[1]);
cv::Mat img1{cam_->at(image::RIGHT_EYE).clone()};
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, img1.cols, img1.rows, 0, GL_RED, GL_UNSIGNED_BYTE, img1.ptr());
camera_texture_size_[1] = Eigen::Vector2i(img1.cols, img1.rows);
GLint swizzle_mask1[] = {GL_RED, GL_RED, GL_RED, GL_RED};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask1);
RAC_ERRNO_MSG("debugview at end of load_camera_images");
return true;
}
bool debugview::load_rgb_depth() {
RAC_ERRNO_MSG("debugview at start of load_rgb_depth");
rgb_depth_ = rgb_depth_reader_.get_ro_nullable();
if (rgb_depth_ == nullptr) {
return false;
}
if (!use_rgb_depth_)
use_rgb_depth_ = true;
glBindTexture(GL_TEXTURE_2D, rgb_depth_texture_[0]);
cv::Mat rgb{rgb_depth_->at(image::RGB).clone()};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rgb.cols, rgb.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgb.ptr());
rgbd_texture_size_[0] = Eigen::Vector2i(rgb.cols, rgb.rows);
glBindTexture(GL_TEXTURE_2D, rgb_depth_texture_[1]);
cv::Mat depth{rgb_depth_->at(image::DEPTH).clone()};
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depth.cols, depth.rows, 0, GL_DEPTH_COMPONENT, GL_SHORT, depth.ptr());
rgbd_texture_size_[1] = Eigen::Vector2i(depth.cols, depth.rows);
GLint swizzle_mask[] = {GL_RED, GL_RED, GL_RED, 1};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
RAC_ERRNO_MSG("debugview at end of load_rgb_depth");
return true;
}
Eigen::Matrix4f debugview::generate_headset_transform(const Eigen::Vector3f& position, const Eigen::Quaternionf& rotation,
const Eigen::Vector3f& position_offset) {
Eigen::Matrix4f headset_position;
headset_position << 1, 0, 0, position.x() + position_offset.x(), 0, 1, 0, position.y() + position_offset.y(), 0, 0, 1,
position.z() + position_offset.z(), 0, 0, 0, 1;
// We need to convert the headset rotation quaternion to a 4x4 homogenous matrix.
// First of all, we convert to 3x3 matrix, then extend to 4x4 by augmenting.
Eigen::Matrix3f rotation_matrix = rotation.toRotationMatrix();
Eigen::Matrix4f rotation_matrix_homogeneous = Eigen::Matrix4f::Identity();
rotation_matrix_homogeneous.block(0, 0, 3, 3) = rotation_matrix;
// Then we apply the headset rotation.
return headset_position * rotation_matrix_homogeneous;
}
void debugview::_p_thread_setup() {
RAC_ERRNO_MSG("debugview at start of _p_thread_setup");
// Note: glfwMakeContextCurrent must be called from the thread which will be using it.
glfwMakeContextCurrent(gui_window_);
}
void debugview::_p_one_iteration() {
RAC_ERRNO_MSG("debugview at stat of _p_one_iteration");
RAC_ERRNO_MSG("debugview before glfwPollEvents");
glfwPollEvents();
RAC_ERRNO_MSG("debugview after glfwPollEvents");
if (glfwGetMouseButton(gui_window_, GLFW_MOUSE_BUTTON_LEFT)) {
double xpos, ypos;
glfwGetCursorPos(gui_window_, &xpos, &ypos);
Eigen::Vector2d new_pos = Eigen::Vector2d{xpos, ypos};
if (!being_dragged_) {
last_mouse_position_ = new_pos;
being_dragged_ = true;
}
mouse_velocity_ = new_pos - last_mouse_position_;
last_mouse_position_ = new_pos;
} else {
being_dragged_ = false;
}
view_euler_.y() += mouse_velocity_.x() * 0.002f;
view_euler_.x() += mouse_velocity_.y() * 0.002f;
mouse_velocity_ = mouse_velocity_ * 0.95;
load_camera_images();
load_rgb_depth();
glUseProgram(demo_shader_program_);
Eigen::Matrix4f headset_pose = Eigen::Matrix4f::Identity();
const pose::fast_head_pose_type predicted_pose = pose_prediction_->get_fast_pose();
if (pose_prediction_->fast_pose_reliable()) {
const pose::head_pose_type pose = predicted_pose.pose;
Eigen::Quaternionf combined_quat = pose.orientation;
headset_pose = generate_headset_transform(pose.position, combined_quat, tracking_position_offset_);
}
Eigen::Matrix4f model_matrix = Eigen::Matrix4f::Identity();
// If we are following the headset, and have a valid pose, apply the optional offset.
Eigen::Vector3f optional_offset = (follow_headset_ && pose_prediction_->fast_pose_reliable())
? (predicted_pose.pose.position + tracking_position_offset_)
: Eigen::Vector3f{0.0f, 0.0f, 0.0f};
Eigen::Matrix4f user_view = look_at(Eigen::Vector3f{(float) (view_distance_ * cos(view_euler_.y())),
(float) (view_distance_ * sin(view_euler_.x())),
(float) (view_distance_ * sin(view_euler_.y()))} +
optional_offset,
optional_offset, Eigen::Vector3f::UnitY());
Eigen::Matrix4f model_view = user_view * model_matrix;
glUseProgram(demo_shader_program_);
// Size viewport to window size.
int display_w, display_h;
glfwGetFramebufferSize(gui_window_, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
float ratio = (float) display_h / (float) display_w;
// Construct a basic perspective projection
RAC_ERRNO_MSG("debugview before projection_fov");
math_util::projection_fov(&basic_projection_, 40.0f, 40.0f, 40.0f * ratio, 40.0f * ratio, 0.03f, 20.0f);
RAC_ERRNO_MSG("debugview after projection_fov");
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glClearDepth(1);
glUniformMatrix4fv(static_cast<GLint>(model_view_attr_), 1, GL_FALSE, (GLfloat*) model_view.data());
glUniformMatrix4fv(static_cast<GLint>(projection_attr_), 1, GL_FALSE, (GLfloat*) (basic_projection_.data()));
glBindVertexArray(demo_vao_);
// Draw things
glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
RAC_ERRNO_MSG("debugview before glClear");
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RAC_ERRNO_MSG("debugview after glClear");
demo_scene_.Draw();
model_view = user_view * headset_pose;
glUniformMatrix4fv(static_cast<GLint>(model_view_attr_), 1, GL_FALSE, (GLfloat*) model_view.data());
headset_.Draw();
draw_GUI();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
RAC_ERRNO_MSG("debugview before glfwSwapBuffers");
glfwSwapBuffers(gui_window_);
RAC_ERRNO_MSG("debugview after glfwSwapBuffers");
}
void debugview::start() {
RAC_ERRNO_MSG("debugview at the top of start()");
// If the display backend already initialized GLFW, then we shouldn't try to do it again.
// Otherwise, GLFW should be initialized here.
if (!display_backend_manages_glfw_) {
if (!glfwInit()) {
ILLIXR::abort("[debugview] Failed to initialize glfw");
}
RAC_ERRNO_MSG("debugview after glfwInit");
}
glfwSetErrorCallback(glfw_error_callback);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
glfwWindowHint(GLFW_VISIBLE, GL_TRUE);
constexpr std::string_view glsl_version{"#version 330 core"};
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
gui_window_ = glfwCreateWindow(1600, 1000, "ILLIXR Debug View", nullptr, nullptr);
if (gui_window_ == nullptr) {
spdlog::get(name_)->error("couldn't create window {}:{}", __FILE__, __LINE__);
ILLIXR::abort();
}
glfwSetWindowSize(gui_window_, 1600, 1000);
glfwMakeContextCurrent(gui_window_);
RAC_ERRNO_MSG("debuview before vsync");
glfwSwapInterval(1); // Enable vsync!
RAC_ERRNO_MSG("debugview after vysnc");
// glEnable(GL_DEBUG_OUTPUT);
// glDebugMessageCallback(MessageCallback, 0);
// Init and verify GLEW
const GLenum glew_err = glewInit();
if (glew_err != GLEW_OK) {
spdlog::get(name_)->error("GLEW Error: {}", reinterpret_cast<const char*>(glewGetErrorString(glew_err)));
glfwDestroyWindow(gui_window_);
ILLIXR::abort("[debugview] Failed to initialize GLEW");
}
RAC_ERRNO_MSG("debugview after glewInit");
// Initialize IMGUI context.
IMGUI_CHECKVERSION();
ImGui::CreateContext();
// Dark theme, of course.
ImGui::StyleColorsDark();
// Init IMGUI for OpenGL
ImGui_ImplGlfw_InitForOpenGL(gui_window_, true);
ImGui_ImplOpenGL3_Init(glsl_version.data());
// Create and bind global VAO object
glGenVertexArrays(1, &demo_vao_);
glBindVertexArray(demo_vao_);
demo_shader_program_ = init_and_link(demo_vertex_shader, demo_fragment_shader);
#ifndef NDEBUG
spdlog::get(name_)->debug("Demo app shader program is program {}", demo_shader_program_);
#endif
vertex_pos_attr = glGetAttribLocation(demo_shader_program_, "vertexPosition");
vertex_normal_attr_ = glGetAttribLocation(demo_shader_program_, "vertexNormal");
model_view_attr_ = glGetUniformLocation(demo_shader_program_, "u_modelview");
projection_attr_ = glGetUniformLocation(demo_shader_program_, "u_projection");
color_uniform_ = glGetUniformLocation(demo_shader_program_, "u_color");
RAC_ERRNO_MSG("debugview after glGetUniformLocation");
// Load/initialize the demo scene.
const std::string obj_dir = switchboard_->get_env("ILLIXR_DEMO_DATA");
if (obj_dir.empty()) {
ILLIXR::abort("Please define ILLIXR_DEMO_DATA.");
}
demo_scene_ = ObjScene(std::string(obj_dir), "scene.obj");
headset_ = ObjScene(std::string(obj_dir), "headset.obj");
// Generate fun test pattern for missing camera images.
for (unsigned x = 0; x < TEST_PATTERN_WIDTH; x++) {
for (unsigned y = 0; y < TEST_PATTERN_HEIGHT; y++) {
test_pattern_[x][y] = ((x + y) % 6 == 0) ? 255 : 0;
}
}
glGenTextures(2, &(camera_texture_[0]));
glBindTexture(GL_TEXTURE_2D, camera_texture_[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, camera_texture_[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenTextures(2, &(rgb_depth_texture_[0]));
glBindTexture(GL_TEXTURE_2D, rgb_depth_texture_[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, rgb_depth_texture_[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Construct a basic perspective projection
math_util::projection_fov(&basic_projection_, 40.0f, 40.0f, 40.0f, 40.0f, 0.03f, 20.0f);
glfwMakeContextCurrent(nullptr);
threadloop::start();
RAC_ERRNO_MSG("debuview at bottom of start()");
}
debugview::~debugview() {
RAC_ERRNO_MSG("debugview at start of destructor");
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(gui_window_);
RAC_ERRNO_MSG("debugview during destructor");
// If the display backend is GLFW, it will terminate the GLFW context.
// Otherwise, GLFW should be terminated here.
if (!display_backend_manages_glfw_) {
glfwTerminate();
}
}
PLUGIN_MAIN(debugview)