rbdlsim/src/vissim.cc

1078 lines
31 KiB
C++

// clang-format off
// glad must be included before any other OpenGL libraries
#include <glad/gl.h>
// clang-format on
#include <GLFW/glfw3.h>
#include <unistd.h>
#include <Tracy.hpp>
#include <csignal>
#include <cstdio>
#include <iostream>
// clang-format off
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include "ImGuizmo.h"
#include "imgui_internal.h"
#include "imgui.h"
// clang-format on
#include "render_utils.h"
#include "simulator.h"
#include "srender.h"
#include "utils.h"
#define SCONVCOL_IMPLEMENTATION
#include "sconvcol.h"
GLFWwindow* gWindow = nullptr;
GuiInputState* gGuiInputState = nullptr;
CameraState* gCameraState = nullptr;
// Rendering
srndr* gRndr = nullptr;
srview* gView = nullptr;
srcmdbuf* gRndrCmds = nullptr;
simd4x4f gProjMatrix{
simd4f_create(1.f, 0.f, 0.0, 0.f),
simd4f_create(0.f, 1.f, 0.f, 0.f),
simd4f_create(0.f, 0.f, 1.f, 0.f),
simd4f_create(0.f, 0.f, 0.f, 1.f)};
simd4x4f gTransformMatrix{
simd4f_create(1.0f, 0.f, 0.0, 0.f),
simd4f_create(0.f, 1.0f, 0.f, 0.f),
simd4f_create(0.f, 0.f, 1.0f, 0.f),
simd4f_create(0.f, 0.f, 0.f, 1.f)};
vectorial_inline simd4x4f simd4x4f_scale(simd4f s) {
return simd4x4f_create(
simd4f_create(simd4f_get_x(s), 0.f, 0.f, 0.f),
simd4f_create(0.f, simd4f_get_y(s), 0.f, 0.f),
simd4f_create(0.f, 0.f, simd4f_get_z(s), 0.f),
simd4f_create(0.f, 0.f, 0.f, simd4f_get_w(s)));
}
double mouse_scroll_x = 0.;
double mouse_scroll_y = 0.;
enum ViewMode { ViewModeSimulation = 0, ViewModeGuizmoTest = 1 };
ViewMode gViewMode = ViewModeSimulation;
bool gGizmoEnabled = true;
enum ControlMode { ControlModeNone = 0, ControlModeFirstPersonView = 1 };
ControlMode gControlMode = ControlModeNone;
struct Dialogs {
bool mCameraDialog = false;
bool mImGuiDemo = false;
bool mSimulator = false;
bool mImGuizmoTransform = false;
};
Dialogs* gDialogs = nullptr;
using namespace std;
static void error_callback(int error, const char* description) {
fprintf(stderr, "Error (%d): %s\n", error, description);
}
static void opengl_error_callback(
GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam) {
const char* source_str;
switch (source) {
case GL_DEBUG_SOURCE_API:
source_str = "API";
break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
source_str = "Window System";
break;
case GL_DEBUG_SOURCE_SHADER_COMPILER:
source_str = "Shader Compiler";
break;
case GL_DEBUG_SOURCE_THIRD_PARTY:
source_str = "3rd Party";
break;
case GL_DEBUG_SOURCE_APPLICATION:
source_str = "Application";
break;
default:
source_str = "Other";
break;
}
const char* type_str;
switch (type) {
case GL_DEBUG_TYPE_ERROR:
type_str = "Error";
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
type_str = "Deprecated Behaviour";
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
type_str = "Undefined Behaviour";
break;
case GL_DEBUG_TYPE_PORTABILITY:
type_str = "Portability";
break;
case GL_DEBUG_TYPE_PERFORMANCE:
type_str = "Performance";
break;
case GL_DEBUG_TYPE_MARKER:
type_str = "Marker";
break;
case GL_DEBUG_TYPE_PUSH_GROUP:
type_str = "Push Group";
break;
case GL_DEBUG_TYPE_POP_GROUP:
type_str = "Pop Group";
break;
default:
type_str = "Other";
break;
}
const char* severity_str;
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH:
severity_str = "high";
break;
case GL_DEBUG_SEVERITY_MEDIUM:
severity_str = "medium";
break;
case GL_DEBUG_SEVERITY_LOW:
severity_str = "low";
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
severity_str = "notification";
break;
default:
severity_str = "unknown";
}
gLog(
"OpenGL Error (%s, type %s, severity = %s): %s",
source_str,
type_str,
severity_str,
message);
}
static void
key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
void signal_handler(int signo) { gLog("Received signal %d", signo); }
void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
mouse_scroll_x += xoffset;
mouse_scroll_y += yoffset;
}
void handle_mouse() {
if (!glfwGetWindowAttrib(gWindow, GLFW_FOCUSED)) {
return;
}
double mouse_x, mouse_y;
glfwGetCursorPos(gWindow, &mouse_x, &mouse_y);
if (gGuiInputState->mouseButton) {
gGuiInputState->mousedX = int32_t(mouse_x) - gGuiInputState->mouseX;
gGuiInputState->mousedY = int32_t(mouse_y) - gGuiInputState->mouseY;
} else {
gGuiInputState->mousedX = 0;
gGuiInputState->mousedY = 0;
}
gGuiInputState->mouseX = int32_t(mouse_x);
gGuiInputState->mouseY = int32_t(mouse_y);
gGuiInputState->mouseScroll = int32_t(mouse_scroll_y);
gGuiInputState->mouseButton = glfwGetMouseButton(gWindow, 0)
+ (glfwGetMouseButton(gWindow, 1) << 1)
+ (glfwGetMouseButton(gWindow, 2) << 2);
}
void ShowDockspace(bool open) {
static bool opt_fullscreen = true;
static bool opt_padding = false;
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
ImGuiIO& io = ImGui::GetIO();
(void)io;
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
// because it would be confusing to have two docking targets within each others.
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking;
if (opt_fullscreen) {
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->GetWorkPos());
ImGui::SetNextWindowSize(viewport->GetWorkSize());
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse
| ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |=
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
} else {
dockspace_flags &= ~ImGuiDockNodeFlags_PassthruCentralNode;
}
// When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background
// and handle the pass-thru hole, so we ask Begin() to not render a background.
if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
window_flags |= ImGuiWindowFlags_NoBackground;
// Important: note that we proceed even if Begin() returns false (aka window is collapsed).
// This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
// all active windows docked into it will lose their parent and become undocked.
// We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
// any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
if (!opt_padding)
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace Demo", &open, window_flags);
if (!opt_padding) ImGui::PopStyleVar();
if (opt_fullscreen) ImGui::PopStyleVar(2);
// DockSpace
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) {
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
} else {
gLog("Error: no docking not enabled");
}
ImGui::End();
}
static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::TRANSLATE);
void RenderGuizmoTest(srcmdbuf* cmdbuf) {
srcmd rcmd;
srcmd_clear(&rcmd);
rcmd.type = SRndrCmdTypeGrid;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
simd4x4f_translation(&rcmd.mat, 0.0f, 0.0f, 0.0f);
srcmdbuf_add(cmdbuf, &rcmd);
}
}
rcmd.type = SRndrCmdTypeCube;
rcmd.mat = gTransformMatrix;
srcmdbuf_add(cmdbuf, &rcmd);
}
void ShowViewManip() {
const ImGuiStyle& imgui_style = ImGui::GetStyle();
ImGuizmo::SetDrawlist();
float windowWidth = (float)ImGui::GetWindowWidth();
float windowHeight = (float)ImGui::GetWindowHeight();
ImGuizmo::SetRect(
ImGui::GetWindowPos().x,
ImGui::GetWindowPos().y,
windowWidth,
windowHeight);
float viewManipulateRight = ImGui::GetWindowPos().x + windowWidth;
float title_height = ImGui::GetFontSize() + imgui_style.FramePadding.y * 2.f;
ImVec2 window_pos = ImGui::GetWindowPos();
ImVec2 view_manip_widget_size(128, 128);
ImVec2 view_manip_widget_pos(
viewManipulateRight - 128 - imgui_style.WindowPadding.x,
window_pos.y + title_height + imgui_style.WindowPadding.y);
ImGui::SetCursorPos(view_manip_widget_pos - ImGui::GetWindowPos());
ImGui::InvisibleButton("ViewManipulator", view_manip_widget_size);
ImGuizmo::ViewManipulate(
(float*)&(gCameraState->mtxView.x),
10.0f,
view_manip_widget_pos,
view_manip_widget_size,
0x40404040);
}
void ShowTransformManip(
float* cameraView,
float* cameraProjection,
float* matrix) {
static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::LOCAL);
static bool useSnap = false;
static float snap[3] = {1.f, 1.f, 1.f};
static float bounds[] = {-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f};
static float boundsSnap[] = {0.1f, 0.1f, 0.1f};
static bool boundSizing = false;
static bool boundSizingSnap = false;
bool useWindow = false;
bool editTransformDecomposition = true;
ImVec2 window_size = ImGui::GetWindowSize();
ImVec2 window_pos = ImGui::GetWindowPos();
ImGuiStyle imgui_style = ImGui::GetStyle();
float title_height = ImGui::GetFontSize() + imgui_style.FramePadding.y * 2.f;
window_pos.x += imgui_style.WindowPadding.x;
window_pos.y += imgui_style.WindowPadding.y + title_height;
window_size.x -= imgui_style.WindowPadding.x * 2;
window_size.y -= imgui_style.WindowPadding.y * 2 + title_height;
if (gDialogs->mImGuizmoTransform) {
ImGui::Begin("Guizmo", &gDialogs->mImGuizmoTransform);
if (editTransformDecomposition) {
if (ImGui::IsKeyPressed(90)) mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
if (ImGui::IsKeyPressed(69)) mCurrentGizmoOperation = ImGuizmo::ROTATE;
if (ImGui::IsKeyPressed(82)) // r Key
mCurrentGizmoOperation = ImGuizmo::SCALE;
if (ImGui::RadioButton(
"Translate",
mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
ImGui::SameLine();
if (ImGui::RadioButton(
"Rotate",
mCurrentGizmoOperation == ImGuizmo::ROTATE))
mCurrentGizmoOperation = ImGuizmo::ROTATE;
ImGui::SameLine();
if (ImGui::RadioButton(
"Scale",
mCurrentGizmoOperation == ImGuizmo::SCALE))
mCurrentGizmoOperation = ImGuizmo::SCALE;
if (ImGui::RadioButton(
"Universal",
mCurrentGizmoOperation == ImGuizmo::UNIVERSAL))
mCurrentGizmoOperation = ImGuizmo::UNIVERSAL;
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
ImGuizmo::DecomposeMatrixToComponents(
matrix,
matrixTranslation,
matrixRotation,
matrixScale);
ImGui::InputFloat3("Tr", matrixTranslation);
ImGui::InputFloat3("Rt", matrixRotation);
ImGui::InputFloat3("Sc", matrixScale);
ImGuizmo::RecomposeMatrixFromComponents(
matrixTranslation,
matrixRotation,
matrixScale,
matrix);
if (mCurrentGizmoOperation != ImGuizmo::SCALE) {
if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
mCurrentGizmoMode = ImGuizmo::LOCAL;
ImGui::SameLine();
if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
mCurrentGizmoMode = ImGuizmo::WORLD;
}
if (ImGui::IsKeyPressed(83)) useSnap = !useSnap;
ImGui::Checkbox("", &useSnap);
ImGui::SameLine();
switch (mCurrentGizmoOperation) {
case ImGuizmo::TRANSLATE:
ImGui::InputFloat3("Snap", &snap[0]);
break;
case ImGuizmo::ROTATE:
ImGui::InputFloat("Angle Snap", &snap[0]);
break;
case ImGuizmo::SCALE:
ImGui::InputFloat("Scale Snap", &snap[0]);
break;
default:
break;
}
ImGui::Checkbox("Bound Sizing", &boundSizing);
if (boundSizing) {
ImGui::PushID(3);
ImGui::Checkbox("", &boundSizingSnap);
ImGui::SameLine();
ImGui::InputFloat3("Snap", boundsSnap);
ImGui::PopID();
}
}
ImGui::End();
}
ImGuiIO& io = ImGui::GetIO();
float viewManipulateRight = io.DisplaySize.x;
float viewManipulateTop = 0;
if (useWindow) {
ImGui::SetNextWindowSize(ImVec2(800, 400));
ImGui::SetNextWindowPos(ImVec2(400, 20));
ImGui::PushStyleColor(
ImGuiCol_WindowBg,
(ImVec4)ImColor(0.35f, 0.3f, 0.3f));
ImGui::Begin("Gizmo", 0);
ImGuizmo::SetDrawlist();
float windowWidth = (float)ImGui::GetWindowWidth();
ImGuizmo::SetRect(window_pos.x, window_pos.y, window_size.x, window_size.y);
} else {
ImGuizmo::SetDrawlist();
ImGuizmo::SetRect(window_pos.x, window_pos.y, window_size.x, window_size.y);
}
simd4x4f identity_mat;
simd4x4f_identity(&identity_mat);
bool modified = ImGuizmo::Manipulate(
cameraView,
cameraProjection,
mCurrentGizmoOperation,
mCurrentGizmoMode,
matrix,
NULL,
useSnap ? &snap[0] : NULL,
boundSizing ? bounds : NULL,
boundSizingSnap ? boundsSnap : NULL);
if (useWindow) {
ImGui::End();
ImGui::PopStyleColor(1);
}
}
void SimulatorSceneRender(srcmdbuf* render_commands) {
// Populate render commands
srcmdbuf_clear(render_commands);
srcmd rcmd;
srcmd_clear(&rcmd);
rcmd.type = SRndrCmdTypeFrame;
srcmdbuf_add(render_commands, &rcmd);
simulator_draw(render_commands);
if (gDialogs->mSimulator) {
ImGui::Begin("Simulator", &gDialogs->mSimulator);
simulator_gui();
ImGui::End();
}
}
struct SceneHull {
sch_hull hull;
srmeshdata* mesh = nullptr;
simd4x4f transform = {
simd4f_create(1.f, 0.f, 0.0, 0.f),
simd4f_create(0.f, 1.f, 0.f, 0.f),
simd4f_create(0.f, 0.f, 1.f, 0.f),
simd4f_create(0.f, 0.f, 0.f, 1.f)};
~SceneHull() {
if (mesh != nullptr) {
destroy();
}
};
void destroy() {
srmesh_destroy(mesh);
mesh = nullptr;
}
void createMesh() {
assert(mesh == nullptr);
// create mesh for hull
static srvrtxdata mesh_buffer_data[1024];
static GLuint index_buffer_data[1024];
int vertex_index = -1;
int index_count = -1;
int triangle_count = 0;
int face_vert0_idx = 0;
for (int fi = 0; fi < hull.num_faces; fi++) {
sch_face* face = &hull.faces[fi];
sch_edge* edge0 = face->edge;
sch_vert* face_vert0 = edge0->vert;
sch_edge* cur_edge = edge0->next;
sch_vert* cur_vert = nullptr;
sch_edge* next_edge = nullptr;
sch_vert* next_vert = nullptr;
int tri_vert_0_idx = 0;
int tri_vert_1_idx = 0;
int tri_vert_2_idx = 0;
sch_plane plane;
sch_hull_calc_plane(&hull, fi, &plane);
// add face_vert0 (later used as tri_vert_0)
vertex_index++;
face_vert0_idx = vertex_index;
tri_vert_0_idx = face_vert0_idx;
srvrtxdata* mesh_vert = &mesh_buffer_data[tri_vert_0_idx];
mesh_vert->x = simd4f_get_x(face_vert0->p);
mesh_vert->y = simd4f_get_y(face_vert0->p);
mesh_vert->z = simd4f_get_z(face_vert0->p);
mesh_vert->w = 1.f;
mesh_vert->nx = simd4f_get_x(plane.n);
mesh_vert->ny = simd4f_get_y(plane.n);
mesh_vert->nz = simd4f_get_z(plane.n);
mesh_vert->color[0] = fabs(mesh_vert->nx) * 255;
mesh_vert->color[1] = fabs(mesh_vert->ny) * 255;
mesh_vert->color[2] = fabs(mesh_vert->nz) * 255;
mesh_vert->color[3] = 255;
// add tri_vert_1
cur_vert = cur_edge->vert;
tri_vert_1_idx = ++vertex_index;
mesh_vert = &mesh_buffer_data[tri_vert_1_idx];
mesh_vert->x = simd4f_get_x(cur_vert->p);
mesh_vert->y = simd4f_get_y(cur_vert->p);
mesh_vert->z = simd4f_get_z(cur_vert->p);
mesh_vert->w = 1.f;
mesh_vert->nx = simd4f_get_x(plane.n);
mesh_vert->ny = simd4f_get_y(plane.n);
mesh_vert->nz = simd4f_get_z(plane.n);
mesh_vert->color[0] = fabs(mesh_vert->nx) * 255;
mesh_vert->color[1] = fabs(mesh_vert->ny) * 255;
mesh_vert->color[2] = fabs(mesh_vert->nz) * 255;
mesh_vert->color[3] = 255;
do {
// add face_vert0
index_buffer_data[++index_count] = tri_vert_0_idx;
// add face_vert1
index_buffer_data[++index_count] = tri_vert_1_idx;
next_edge = cur_edge->next;
next_vert = next_edge->vert;
tri_vert_2_idx = ++vertex_index;
mesh_vert = &mesh_buffer_data[tri_vert_2_idx];
mesh_vert->x = simd4f_get_x(next_vert->p);
mesh_vert->y = simd4f_get_y(next_vert->p);
mesh_vert->z = simd4f_get_z(next_vert->p);
mesh_vert->w = 1.f;
mesh_vert->nx = simd4f_get_x(plane.n);
mesh_vert->ny = simd4f_get_y(plane.n);
mesh_vert->nz = simd4f_get_z(plane.n);
mesh_vert->color[0] = fabs(mesh_vert->nx) * 255;
mesh_vert->color[1] = fabs(mesh_vert->ny) * 255;
mesh_vert->color[2] = fabs(mesh_vert->nz) * 255;
mesh_vert->color[3] = 255;
index_buffer_data[++index_count] = tri_vert_2_idx;
triangle_count++;
cur_edge = next_edge;
tri_vert_1_idx = tri_vert_2_idx;
} while (next_edge->next != edge0);
}
mesh = srmesh_create(
mesh_buffer_data,
vertex_index + 1,
index_buffer_data,
index_count + 1,
GL_TRIANGLES,
index_count + 1);
}
};
struct SconvHullScene {
SceneHull mHullA;
SceneHull mHullB;
SceneHull* mCurrentHull;
void setupSceneRotTrans() {
simd4x4f rot;
simd4x4f_axis_rotation(&rot, 0.4f, simd4f_create (0.f, 1.f, 0.f, 1.f));
simd4x4f translation;
simd4x4f_translation(&translation, -0.5f - 0.51f * sqrtf(2.), 0.0f, 0.f);
simd4x4f_matrix_mul(&translation, &rot, &mHullB.transform);
}
void setupSceneEdgeCollision() {
simd4x4f rot_y;
simd4x4f_axis_rotation(&rot_y, 0.25f * M_PI, simd4f_create (0.f, 1.f, 0.f, 1.f));
simd4x4f rot_z;
simd4x4f_axis_rotation(&rot_z, 0.25f * M_PI, simd4f_create (0.f, 0.f, 1.f, 1.f));
simd4x4f rot;
simd4x4f_matrix_mul(&rot_y, &rot_z, &rot);
simd4x4f translation;
simd4x4f_translation(&translation, 0.98f, 0.f, -0.98f);
simd4x4f_matrix_mul(&translation, &rot, &mHullB.transform);
}
void setupRotatedBoxes () {
simd4x4f trans_A;
simd4x4f trans_B;
simd4x4f_axis_rotation (&trans_A, M_PI / 180.0f * 45.f, simd4f_create(0.f, 0.f, 1.f, 1.f));
simd4x4f rot_B;
simd4x4f_axis_rotation (&rot_B, M_PI / 180.0f * 45.f, simd4f_create(0.f, 1.f, 0.f, 1.f));
simd4x4f translation_B;
simd4x4f_translation (&translation_B, sqrt(2.f) + 0.001, 0.f, 0.f);
simd4x4f_matrix_mul (&translation_B, &rot_B, &trans_B);
mHullA.transform = trans_A;
mHullB.transform = trans_B;
}
void init() {
sch_create_unitbox(&mHullA.hull);
mHullA.createMesh();
sch_create_unitbox(&mHullB.hull);
mHullB.createMesh();
// setupSceneEdgeCollision();
setupRotatedBoxes();
mCurrentHull = &mHullA;
};
void destroy() {
mHullA.destroy();
mHullB.destroy();
}
void draw(srcmdbuf* render_commands) {
// Populate render commands
srcmdbuf_clear(render_commands);
srcmd rcmd;
srcmd_clear(&rcmd);
rcmd.type = SRndrCmdTypeFrame;
srcmdbuf_add(render_commands, &rcmd);
rcmd.type = SRndrCmdTypeGrid;
float origin[3] = {0.f, 0.f, 0.f};
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
simd4x4f_translation(
&rcmd.mat,
origin[0] + i * 10.0f,
origin[1],
origin[2] + j * 10.f);
srcmdbuf_add(render_commands, &rcmd);
}
}
ImGuizmo::Manipulate(
(float*)&(gCameraState->mtxView),
(float*)&(gProjMatrix),
ImGuizmo::TRANSLATE,
ImGuizmo::WORLD,
(float*)(&mCurrentHull->transform),
NULL);
// Render hulls
srcmd cmd;
cmd.type = SrndrCmdTypeMesh;
cmd.color = simd4f_create(1.f, 1.f, 1.f, 1.f);
cmd.mat = mHullA.transform;
cmd.meshdata = mHullA.mesh;
srcmdbuf_add(render_commands, &cmd);
cmd.type = SrndrCmdTypeMesh;
cmd.color = simd4f_create(1.f, 1.f, 1.f, 1.f);
cmd.mat = mHullB.transform;
cmd.meshdata = mHullB.mesh;
srcmdbuf_add(render_commands, &cmd);
}
};
SconvHullScene gHullScene;
void ImSRenderWidget(srndr* renderer, srview* view) {
ZoneScoped;
const ImGuiStyle& imgui_style = ImGui::GetStyle();
// Render Output
ImGui::Begin("Render Output", nullptr, ImGuiWindowFlags_NoScrollbar);
// Update the gCameraState->mtxView
const ImVec2 content_avail = ImGui::GetContentRegionAvail();
srview_set_size(view, int(content_avail.x), int(content_avail.y));
float view_width = content_avail.x / 50.f;
float view_height = content_avail.y / 50.f;
simd4x4f_ortho(
&gProjMatrix,
-0.5f * view_width,
0.5f * view_width,
-0.5f * view_height,
0.5f * view_height,
-50.0f,
50.0f);
simd4x4f_perspective(
&gProjMatrix,
70.f * (M_PI / 180.f),
view_width / view_height,
0.1f,
50.f);
srview_set_view(view, gCameraState->mtxView);
srview_set_proj(view, gProjMatrix);
// Perform the actual render
GLuint view_texture;
srview_get_output_texture(view, &view_texture);
ImGui::Image(
(void*)view_texture,
content_avail,
ImVec2(0.0f, 1.0f),
ImVec2(1.0f, 0.0f));
ImGuiIO& io = ImGui::GetIO();
ShowViewManip();
ShowTransformManip(
(float*)&(gCameraState->mtxView),
(float*)&(gProjMatrix),
(float*)(&gTransformMatrix));
ImGui::End();
};
int main() {
gTimerInit();
LoggingInit();
if (signal(SIGUSR1, signal_handler) == SIG_ERR) {
gLog("Error registering signal handler!");
}
// Initialize GLFW
glfwSetErrorCallback(error_callback);
glfwInit();
const char* glsl_version = "#version 130";
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_SAMPLES, 16);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#if __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
gWindow = glfwCreateWindow(800, 600, "ViSimir", NULL, NULL);
assert(gWindow != NULL);
glfwMakeContextCurrent(gWindow);
glfwSwapInterval(1);
// Initialize OpenGL loader
gladLoadGL(glfwGetProcAddress);
glfwSetKeyCallback(gWindow, key_callback);
glfwSetScrollCallback(gWindow, mouse_scroll_callback);
std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << endl;
std::cout << "GLSL Version : " << glGetString(GL_SHADING_LANGUAGE_VERSION)
<< endl;
glEnable(GL_DEBUG_OUTPUT);
// glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(opengl_error_callback, nullptr);
// During init, enable debug output
// glEnable ( GL_DEBUG_OUTPUT );
// glDebugMessageCallback( (GLDEBUGPROC) opengl_error_callback, 0 );
// imgui initialization.
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
(void)io;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
// io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
GuiInputState gui_input_state;
gGuiInputState = &gui_input_state;
ImGui_ImplGlfw_InitForOpenGL(gWindow, true);
ImGui_ImplOpenGL3_Init(glsl_version);
// Setup Style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
ImGuiStyle& style = ImGui::GetStyle();
style.WindowRounding =
0.0f; // When viewports are enabled it is preferable to disable WinodwRounding
style.Colors[ImGuiCol_WindowBg].w =
1.0f; // When viewports are enabled it is preferable to disable WindowBg alpha
double frame_time_last = glfwGetTime();
double frame_time_current = frame_time_last;
double frame_delta_time = 0.0;
uint64_t frame_counter = 0;
bool show_demo_window = true;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
CameraState camera_state;
CameraState_Init(&camera_state);
gCameraState = &camera_state;
Dialogs dialogs;
gDialogs = &dialogs;
gRndr = srndr_create();
gView = srview_create();
gRndrCmds = srcmdbuf_create(1024);
//
// Scene init
//
simulator_init();
gHullScene.init();
simd4x4f_translation(&gCameraState->mtxView, 0.1f, 0.1f, -0.5f);
simd4f eye = simd4f_create(5.f, 4.f, 5.f, 1.f);
simd4x4f_lookat(
&gCameraState->mtxView,
eye,
simd4f_create(0.f, 0.f, 0.f, 1.f),
simd4f_create(0.f, 1.f, 0.f, 1.f));
simd4x4f scale_mat = simd4x4f_scale(simd4f_create(1.f, 1.f, 1.f, 1.f));
simd4x4f_mul(&gTransformMatrix, &scale_mat, &gTransformMatrix);
CameraState_CalcFromMatrix(gCameraState, &gCameraState->mtxView);
while (!glfwWindowShouldClose(gWindow)) {
FrameMark;
frame_counter++;
{
ZoneNamedN(input_loop, "InputEvents", true);
// Start the imgui frame such that widgets can be submitted
handle_mouse();
glfwPollEvents();
}
{
ZoneNamedN(imgui_render, "ImGuiFrameStart", true);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ShowDockspace(true);
ImGuizmo::BeginFrame();
ImGuizmo::Enable(gGizmoEnabled);
}
frame_time_last = frame_time_current;
frame_time_current = glfwGetTime();
frame_delta_time = frame_time_current - frame_time_last;
gTimer->mFrameTime = (float)(frame_delta_time);
if (!gTimer->mPaused) {
gTimer->mDeltaTime = gTimer->mFrameTime;
gTimer->mCurrentTime = gTimer->mCurrentTime + gTimer->mDeltaTime;
} else {
gTimer->mDeltaTime = 0.0f;
}
{
ZoneNamedN(main_ui, "UpdateMainUI", true);
assert(gTimer->mDeltaTime >= 0.0f);
int width, height;
ImGui::BeginMainMenuBar();
if (ImGui::BeginMenu("Dialogs")) {
ImGui::Checkbox("Camera", &gDialogs->mCameraDialog);
ImGui::Checkbox("Simulator", &gDialogs->mSimulator);
ImGui::Checkbox("ImGuizmo Transform", &gDialogs->mImGuizmoTransform);
ImGui::Checkbox("ImGui Demo", &gDialogs->mImGuiDemo);
ImGui::EndMenu();
}
float menu_bar_height = ImGui::GetWindowHeight();
ImGui::EndMainMenuBar();
if (glfwGetMouseButton(gWindow, GLFW_MOUSE_BUTTON_RIGHT)) {
if (gControlMode == ControlModeNone) {
gControlMode = ControlModeFirstPersonView;
CameraState_CalcFromMatrix(gCameraState, &gCameraState->mtxView);
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
} else {
gControlMode = ControlModeNone;
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
if (gControlMode == ControlModeFirstPersonView) {
float camera_accel[3] = {0.f, 0.f, 0.f};
float accel_scale = 100.0;
if (glfwGetKey(gWindow, GLFW_KEY_LEFT_SHIFT)) {
accel_scale *= 3.;
} else if (glfwGetKey(gWindow, GLFW_KEY_LEFT_CONTROL)) {
accel_scale /= 3.;
}
if (glfwGetKey(gWindow, GLFW_KEY_W)) {
camera_accel[0] -= accel_scale;
}
if (glfwGetKey(gWindow, GLFW_KEY_S)) {
camera_accel[0] += accel_scale;
}
if (glfwGetKey(gWindow, GLFW_KEY_C)) {
camera_accel[1] -= accel_scale;
}
if (glfwGetKey(gWindow, GLFW_KEY_SPACE)) {
camera_accel[1] += accel_scale;
}
if (glfwGetKey(gWindow, GLFW_KEY_A)) {
camera_accel[2] -= accel_scale;
}
if (glfwGetKey(gWindow, GLFW_KEY_D)) {
camera_accel[2] += accel_scale;
}
CameraState_Update(
gCameraState,
frame_delta_time,
gGuiInputState->mousedX,
gGuiInputState->mousedY,
camera_accel);
}
if (gDialogs->mCameraDialog) {
ImGui::Begin("Camera Controls", &gDialogs->mCameraDialog);
bool changed = false;
changed = ImGui::SliderFloat(
"Heading",
&gCameraState->heading,
-M_PI * 0.98,
M_PI * 0.98);
changed = ImGui::SliderFloat(
"Pitch",
&gCameraState->pitch,
-M_PI * 0.49,
M_PI * 0.49)
|| changed;
changed =
ImGui::SliderFloat3("Forward", gCameraState->forward, -1.f, 1.f)
|| changed;
changed = ImGui::SliderFloat3("Right", gCameraState->right, -1.f, 1.f)
|| changed;
changed =
ImGui::SliderFloat3("Up", gCameraState->up, -1.f, 1.f) || changed;
changed = ImGui::SliderFloat3("Pos", gCameraState->pos, -100.f, 100.f)
|| changed;
if (changed) {
CameraState_CalcToMatrix(gCameraState, &gCameraState->mtxView);
}
if (gDialogs->mImGuiDemo) {
ImGui::ShowDemoWindow(&gDialogs->mImGuiDemo);
}
ImGui::End();
}
//gHullScene.draw(gRndrCmds);
SimulatorSceneRender(gRndrCmds);
srndr_render(gRndr, gView, gRndrCmds);
ImSRenderWidget(gRndr, gView);
}
simulator_update(gTimer->mDeltaTime);
{
ZoneNamedN(render_submit, "RenderSubmit", true);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
{
ZoneNamedN(imgui_render, "ImGuiRender", true);
// Rendering
ImGui::Render();
int display_w, display_h;
glfwMakeContextCurrent(gWindow);
glfwGetFramebufferSize(gWindow, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(
clear_color.x,
clear_color.y,
clear_color.z,
clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImDrawData* draw_data = ImGui::GetDrawData();
assert(draw_data != NULL);
ImGui_ImplOpenGL3_RenderDrawData(draw_data);
}
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
{
ZoneNamedN(gl_swap, "Swap", true);
glfwMakeContextCurrent(gWindow);
glfwSwapBuffers(gWindow);
}
{
ZoneNamedN(fps_limit, "FPS limit", true);
// Send the application to sleep if we have some time left for this frame
double frame_target_time = 1.0 / 60.0;
if (frame_delta_time < frame_target_time) {
usleep((frame_target_time - frame_delta_time) * 1000000 * 0.98);
}
}
}
}
gLog("Exiting application");
gHullScene.destroy();
srview_destroy(gView);
srndr_destroy(gRndr);
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwTerminate();
}