Scene now rendered to separate widget.

RefactorUnifiedBlendTreeStateMachineHandling
Martin Felis 2023-04-14 17:21:53 +02:00
parent e8ef7924d2
commit 509f9616ad
1 changed files with 295 additions and 74 deletions

View File

@ -103,6 +103,61 @@ enum class ControlMode { ControlModeNone, ControlModeFPS };
ControlMode gControlMode = ControlMode::ControlModeNone;
struct Viewport {
sg_pass_action pass_action = {};
sg_pass pass = {};
sg_pipeline pip = {};
sg_bindings bind = {};
sg_image color_image = {};
sg_image depth_image = {};
int size[2] = {400, 400};
void Resize(int width, int height) {
width = width < 1 ? 1 : width;
height = height < 1 ? 1 : height;
this->pass_action.colors[0].action = SG_ACTION_CLEAR;
this->pass_action.colors[0].value = {0.1f, 0.1f, 0.1f, 1.0f};
if (this->size[0] == width && this->size[1] == height
&& this->pass.id != 0) {
return;
}
this->size[0] = width;
this->size[1] = height;
if (this->pass.id != 0) {
sg_destroy_pass(this->pass);
sg_destroy_image(this->depth_image);
sg_destroy_image(this->color_image);
}
sg_image_desc img_desc = {
.render_target = true,
.width = this->size[0],
.height = this->size[1],
.pixel_format = SG_PIXELFORMAT_RGBA8,
.sample_count = 4,
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_REPEAT,
.wrap_v = SG_WRAP_REPEAT,
.label = "color-image"};
this->color_image = sg_make_image(&img_desc);
img_desc.pixel_format = SG_PIXELFORMAT_DEPTH_STENCIL;
img_desc.label = "depth-image";
this->depth_image = sg_make_image(&img_desc);
sg_pass_desc offscreen_pass_desc{};
offscreen_pass_desc.color_attachments[0].image = this->color_image;
offscreen_pass_desc.depth_stencil_attachment.image = this->depth_image;
offscreen_pass_desc.label = "offscreen-pass";
this->pass = sg_make_pass(&offscreen_pass_desc);
}
};
struct ApplicationConfig {
int window_position[2] = {100, 30};
int window_size[2] = {1000, 600};
@ -128,6 +183,13 @@ struct ApplicationConfig {
};
AnimationPlayerWidget animation_player_widget;
struct ViewportWidget {
bool visible = false;
int position[2] = {20, 20};
int size[2] = {800, 500};
};
ViewportWidget viewport_widget;
bool show_imgui_demo_window = false;
bool show_another_window = false;
bool show_camera_widget = false;
@ -150,16 +212,29 @@ void to_json(nlohmann::json& j, const ApplicationConfig& config) {
j["graph_editor"]["size"][1] = config.graph_editor.size[1];
j["skinned_mesh_widget"]["visible"] = config.skinned_mesh_widget.visible;
j["skinned_mesh_widget"]["position"][0] = config.skinned_mesh_widget.position[0];
j["skinned_mesh_widget"]["position"][1] = config.skinned_mesh_widget.position[1];
j["skinned_mesh_widget"]["position"][0] =
config.skinned_mesh_widget.position[0];
j["skinned_mesh_widget"]["position"][1] =
config.skinned_mesh_widget.position[1];
j["skinned_mesh_widget"]["size"][0] = config.skinned_mesh_widget.size[0];
j["skinned_mesh_widget"]["size"][1] = config.skinned_mesh_widget.size[1];
j["animation_player_widget"]["visible"] = config.animation_player_widget.visible;
j["animation_player_widget"]["position"][0] = config.animation_player_widget.position[0];
j["animation_player_widget"]["position"][1] = config.animation_player_widget.position[1];
j["animation_player_widget"]["size"][0] = config.animation_player_widget.size[0];
j["animation_player_widget"]["size"][1] = config.animation_player_widget.size[1];
j["animation_player_widget"]["visible"] =
config.animation_player_widget.visible;
j["animation_player_widget"]["position"][0] =
config.animation_player_widget.position[0];
j["animation_player_widget"]["position"][1] =
config.animation_player_widget.position[1];
j["animation_player_widget"]["size"][0] =
config.animation_player_widget.size[0];
j["animation_player_widget"]["size"][1] =
config.animation_player_widget.size[1];
j["viewport_widget"]["visible"] = config.viewport_widget.visible;
j["viewport_widget"]["position"][0] = config.viewport_widget.position[0];
j["viewport_widget"]["position"][1] = config.viewport_widget.position[1];
j["viewport_widget"]["size"][0] = config.viewport_widget.size[0];
j["viewport_widget"]["size"][1] = config.viewport_widget.size[1];
j["camera_widget"]["visible"] = config.show_camera_widget;
}
@ -186,12 +261,14 @@ void from_json(const nlohmann::json& j, ApplicationConfig& config) {
config.graph_editor.visible = j["graph_editor"]["visible"];
}
if (j["graph_editor"].contains("position") and j["graph_editor"]["position"].size() == 2) {
if (j["graph_editor"].contains("position")
and j["graph_editor"]["position"].size() == 2) {
config.graph_editor.position[0] = j["graph_editor"]["position"].at(0);
config.graph_editor.position[1] = j["graph_editor"]["position"].at(1);
}
if (j["graph_editor"].contains("size") and j["graph_editor"]["size"].size() == 2) {
if (j["graph_editor"].contains("size")
and j["graph_editor"]["size"].size() == 2) {
config.graph_editor.size[0] = j["graph_editor"]["size"].at(0);
config.graph_editor.size[1] = j["graph_editor"]["size"].at(1);
}
@ -202,33 +279,66 @@ void from_json(const nlohmann::json& j, ApplicationConfig& config) {
config.skinned_mesh_widget.visible = j["skinned_mesh_widget"]["visible"];
}
if (j["skinned_mesh_widget"].contains("position") and j["skinned_mesh_widget"]["position"].size() == 2) {
config.skinned_mesh_widget.position[0] = j["skinned_mesh_widget"]["position"].at(0);
config.skinned_mesh_widget.position[1] = j["skinned_mesh_widget"]["position"].at(1);
if (j["skinned_mesh_widget"].contains("position")
and j["skinned_mesh_widget"]["position"].size() == 2) {
config.skinned_mesh_widget.position[0] =
j["skinned_mesh_widget"]["position"].at(0);
config.skinned_mesh_widget.position[1] =
j["skinned_mesh_widget"]["position"].at(1);
}
if (j["skinned_mesh_widget"].contains("size") and j["skinned_mesh_widget"]["size"].size() == 2) {
config.skinned_mesh_widget.size[0] = j["skinned_mesh_widget"]["size"].at(0);
config.skinned_mesh_widget.size[1] = j["skinned_mesh_widget"]["size"].at(1);
if (j["skinned_mesh_widget"].contains("size")
and j["skinned_mesh_widget"]["size"].size() == 2) {
config.skinned_mesh_widget.size[0] =
j["skinned_mesh_widget"]["size"].at(0);
config.skinned_mesh_widget.size[1] =
j["skinned_mesh_widget"]["size"].at(1);
}
}
if (j.contains("animation_player_widget")) {
if (j["animation_player_widget"].contains("visible")) {
config.animation_player_widget.visible =
j["animation_player_widget"]["visible"];
}
if (j.contains("animation_player_widget")) {
if (j["animation_player_widget"].contains("visible")) {
config.animation_player_widget.visible = j["animation_player_widget"]["visible"];
if (j["animation_player_widget"].contains("position")
and j["animation_player_widget"]["position"].size() == 2) {
config.animation_player_widget.position[0] =
j["animation_player_widget"]["position"].at(0);
config.animation_player_widget.position[1] =
j["animation_player_widget"]["position"].at(1);
}
if (j["animation_player_widget"].contains("size")
and j["animation_player_widget"]["size"].size() == 2) {
config.animation_player_widget.size[0] =
j["animation_player_widget"]["size"].at(0);
config.animation_player_widget.size[1] =
j["animation_player_widget"]["size"].at(1);
}
}
if (j["animation_player_widget"].contains("position") and j["animation_player_widget"]["position"].size() == 2) {
config.animation_player_widget.position[0] = j["animation_player_widget"]["position"].at(0);
config.animation_player_widget.position[1] = j["animation_player_widget"]["position"].at(1);
if (j.contains("viewport_widget")) {
if (j["viewport_widget"].contains("visible")) {
config.viewport_widget.visible = j["viewport_widget"]["visible"];
}
if (j["viewport_widget"].contains("position")
and j["viewport_widget"]["position"].size() == 2) {
config.viewport_widget.position[0] =
j["viewport_widget"]["position"].at(0);
config.viewport_widget.position[1] =
j["viewport_widget"]["position"].at(1);
}
if (j["viewport_widget"].contains("size")
and j["viewport_widget"]["size"].size() == 2) {
config.viewport_widget.size[0] = j["viewport_widget"]["size"].at(0);
config.viewport_widget.size[1] = j["viewport_widget"]["size"].at(1);
}
}
if (j["animation_player_widget"].contains("size") and j["animation_player_widget"]["size"].size() == 2) {
config.animation_player_widget.size[0] = j["animation_player_widget"]["size"].at(0);
config.animation_player_widget.size[1] = j["animation_player_widget"]["size"].at(1);
}
}
if (j.contains("camera_widget") and j["camera_widget"].contains("visible")) {
config.show_camera_widget = j["camera_widget"]["visible"];
}
@ -371,8 +481,9 @@ int main() {
assert(sg_isvalid());
// setup sokol-gl
sgl_desc_t sgldesc = {};
sgldesc.sample_count = 0;
sgl_desc_t sgldesc = {
.sample_count = 4
};
sgl_setup(&sgldesc);
SkinnedMeshResource skinned_mesh_resource;
@ -385,7 +496,8 @@ int main() {
AnimGraph anim_graph;
AnimGraphContext anim_graph_context;
AnimData anim_graph_output;
anim_graph_output.m_local_matrices.resize(skinned_mesh.m_skeleton.num_soa_joints());
anim_graph_output.m_local_matrices.resize(
skinned_mesh.m_skeleton.num_soa_joints());
state.time.factor = 1.0f;
@ -496,18 +608,11 @@ int main() {
pass_action.colors[0].action = SG_ACTION_CLEAR;
pass_action.colors[0].value = {0.1f, 0.1f, 0.1f, 1.0f};
Viewport offscreen_viewport;
// draw loop
while (!glfwWindowShouldClose(w)) {
glfwGetWindowPos(
w,
&gApplicationConfig.window_position[0],
&gApplicationConfig.window_position[1]);
glfwGetWindowSize(
w,
&gApplicationConfig.window_size[0],
&gApplicationConfig.window_size[1]);
// Update time
state.time.frame = stm_sec(
stm_round_to_common_refresh_rate(stm_laptime(&state.time.laptime)));
@ -519,9 +624,21 @@ int main() {
}
if (state.ozz.animation != nullptr) {
state.time.absolute = fmodf (state.time.absolute, state.ozz.animation->duration());
state.time.absolute =
fmodf(state.time.absolute, state.ozz.animation->duration());
}
// Update window state
glfwGetWindowPos(
w,
&gApplicationConfig.window_position[0],
&gApplicationConfig.window_position[1]);
glfwGetWindowSize(
w,
&gApplicationConfig.window_size[0],
&gApplicationConfig.window_size[1]);
int cur_width, cur_height;
glfwGetFramebufferSize(w, &cur_width, &cur_height);
@ -545,8 +662,8 @@ int main() {
glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
Camera_Update(
&state.camera,
cur_width,
cur_height,
offscreen_viewport.size[0],
offscreen_viewport.size[1],
state.time.frame,
0,
0,
@ -601,7 +718,12 @@ int main() {
}
if (ImGui::BeginMenu("View")) {
ImGui::Checkbox("Graph Editor", &gApplicationConfig.graph_editor.visible);
ImGui::Checkbox(
"Viewport",
&gApplicationConfig.viewport_widget.visible);
ImGui::Checkbox(
"Graph Editor",
&gApplicationConfig.graph_editor.visible);
ImGui::Checkbox(
"Camera Settings",
&gApplicationConfig.show_camera_widget);
@ -628,7 +750,8 @@ int main() {
anim_graph.init(anim_graph_context);
// For simplicity use first animation data output
const std::vector<Socket>& graph_output_sockets = anim_graph.getGraphOutputs();
const std::vector<Socket>& graph_output_sockets =
anim_graph.getGraphOutputs();
for (int i = 0; i < graph_output_sockets.size(); i++) {
const Socket& output = graph_output_sockets[i];
if (output.m_type == SocketType::SocketTypeAnimation) {
@ -642,6 +765,51 @@ int main() {
// Animation Runtime
{
// Viewport
if (gApplicationConfig.viewport_widget.visible) {
ImGui::SetNextWindowPos(
ImVec2(
gApplicationConfig.viewport_widget.position[0],
gApplicationConfig.viewport_widget.position[1]),
ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(
ImVec2(
gApplicationConfig.viewport_widget.size[0],
gApplicationConfig.viewport_widget.size[1]),
ImGuiCond_FirstUseEver);
ImGui::Begin("Viewport", &gApplicationConfig.viewport_widget.visible);
ImVec2 viewport_widget_size = ImGui::GetWindowSize();
gApplicationConfig.viewport_widget.size[0] =
viewport_widget_size.x;
gApplicationConfig.viewport_widget.size[1] =
viewport_widget_size.y;
ImGui::Text(
"Viewport size: %d, %d",
offscreen_viewport.size[0],
offscreen_viewport.size[1]);
ImVec2 content_size = ImGui::GetContentRegionAvail();
int* current_size = offscreen_viewport.size;
if (current_size[0] != content_size[0] || current_size[1] != content_size[1]) {
offscreen_viewport.Resize(content_size[0], content_size[1]);
}
ImGui::Image(
(ImTextureID)(uintptr_t)offscreen_viewport.color_image.id,
ImVec2(
offscreen_viewport.size[0],
offscreen_viewport.size[1]),
ImVec2(0.0f, 1.0f),
ImVec2(1.0f, 0.0f));
ImGui::End();
}
if (gApplicationConfig.show_camera_widget) {
ImGui::SetNextWindowPos(ImVec2(600, 30), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(300, 170), ImGuiCond_FirstUseEver);
@ -655,24 +823,33 @@ int main() {
ImGui::End();
}
ImGui::SetNextWindowPos(ImVec2(600, 60), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(300, 400), ImGuiCond_FirstUseEver);
draw_grid();
if (gApplicationConfig.skinned_mesh_widget.visible) {
ImGui::SetNextWindowPos(ImVec2(gApplicationConfig.skinned_mesh_widget.position[0], gApplicationConfig.skinned_mesh_widget.position[1]), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(gApplicationConfig.skinned_mesh_widget.size[0], gApplicationConfig.skinned_mesh_widget.size[1]), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(
ImVec2(
gApplicationConfig.skinned_mesh_widget.position[0],
gApplicationConfig.skinned_mesh_widget.position[1]),
ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(
ImVec2(
gApplicationConfig.skinned_mesh_widget.size[0],
gApplicationConfig.skinned_mesh_widget.size[1]),
ImGuiCond_FirstUseEver);
ImGui::Begin("SkinnedMesh", &gApplicationConfig.skinned_mesh_widget.visible);
ImGui::Begin(
"SkinnedMesh",
&gApplicationConfig.skinned_mesh_widget.visible);
ImVec2 skinned_mesh_widget_position = ImGui::GetWindowPos();
gApplicationConfig.skinned_mesh_widget.position[0] = skinned_mesh_widget_position.x;
gApplicationConfig.skinned_mesh_widget.position[1] = skinned_mesh_widget_position.y;
gApplicationConfig.skinned_mesh_widget.position[0] =
skinned_mesh_widget_position.x;
gApplicationConfig.skinned_mesh_widget.position[1] =
skinned_mesh_widget_position.y;
ImVec2 skinned_mesh_widget_size = ImGui::GetWindowSize();
gApplicationConfig.skinned_mesh_widget.size[0] = skinned_mesh_widget_size.x;
gApplicationConfig.skinned_mesh_widget.size[1] = skinned_mesh_widget_size.y;
gApplicationConfig.skinned_mesh_widget.size[0] =
skinned_mesh_widget_size.x;
gApplicationConfig.skinned_mesh_widget.size[1] =
skinned_mesh_widget_size.y;
SkinnedMeshWidget(&skinned_mesh);
@ -680,18 +857,32 @@ int main() {
}
if (gApplicationConfig.animation_player_widget.visible) {
ImGui::SetNextWindowPos(ImVec2(gApplicationConfig.animation_player_widget.position[0], gApplicationConfig.animation_player_widget.position[1]), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(gApplicationConfig.animation_player_widget.size[0], gApplicationConfig.animation_player_widget.size[1]), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(
ImVec2(
gApplicationConfig.animation_player_widget.position[0],
gApplicationConfig.animation_player_widget.position[1]),
ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(
ImVec2(
gApplicationConfig.animation_player_widget.size[0],
gApplicationConfig.animation_player_widget.size[1]),
ImGuiCond_FirstUseEver);
ImGui::Begin("Animation Player", &gApplicationConfig.animation_player_widget.visible);
ImGui::Begin(
"Animation Player",
&gApplicationConfig.animation_player_widget.visible);
ImVec2 animation_player_widget_position = ImGui::GetWindowPos();
gApplicationConfig.animation_player_widget.position[0] = animation_player_widget_position.x;
gApplicationConfig.animation_player_widget.position[1] = animation_player_widget_position.y;
gApplicationConfig.animation_player_widget.position[0] =
animation_player_widget_position.x;
gApplicationConfig.animation_player_widget.position[1] =
animation_player_widget_position.y;
ImVec2 animation_player_widget_size = ImGui::GetWindowSize();
gApplicationConfig.animation_player_widget.size[0] = animation_player_widget_size.x;
gApplicationConfig.animation_player_widget.size[1] = animation_player_widget_size.y;
gApplicationConfig.animation_player_widget.size[0] =
animation_player_widget_size.x;
gApplicationConfig.animation_player_widget.size[1] =
animation_player_widget_size.y;
if (anim_graph.m_nodes.size() > 0) {
ImGui::Checkbox("Use Graph", &state.time.use_graph);
@ -753,9 +944,10 @@ int main() {
state.ozz.sampling_job.ratio =
state.time.absolute / state.ozz.animation->duration();
state.ozz.sampling_job.context = &skinned_mesh.m_sampling_context;
state.ozz.sampling_job.output = ozz::make_span(skinned_mesh.m_local_matrices);
state.ozz.sampling_job.output =
ozz::make_span(skinned_mesh.m_local_matrices);
if(!state.ozz.sampling_job.Run()) {
if (!state.ozz.sampling_job.Run()) {
ozz::log::Err() << "Error sampling animation." << std::endl;
}
@ -763,7 +955,8 @@ int main() {
skinned_mesh.CalcModelMatrices();
}
if (state.time.use_graph && anim_graph.m_nodes.size() > 0 && state.time.anim_update_time > 0.) {
if (state.time.use_graph && anim_graph.m_nodes.size() > 0
&& state.time.anim_update_time > 0.) {
anim_graph.markActiveNodes();
anim_graph.updateTime(state.time.anim_update_time);
anim_graph.evaluate(anim_graph_context);
@ -777,13 +970,23 @@ int main() {
sgl_load_matrix((const float*)&state.camera.mtxProj);
sgl_matrix_mode_modelview();
sgl_load_matrix((const float*)&state.camera.mtxView);
draw_grid();
RenderSkinnedMesh(skinned_mesh);
}
// Animation Graph Editor
if (gApplicationConfig.graph_editor.visible) {
ImGui::SetNextWindowPos(ImVec2(gApplicationConfig.graph_editor.position[0], gApplicationConfig.graph_editor.position[1]), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(gApplicationConfig.graph_editor.size[0], gApplicationConfig.graph_editor.size[1]), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(
ImVec2(
gApplicationConfig.graph_editor.position[0],
gApplicationConfig.graph_editor.position[1]),
ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(
ImVec2(
gApplicationConfig.graph_editor.size[0],
gApplicationConfig.graph_editor.size[1]),
ImGuiCond_FirstUseEver);
ImGui::Begin(
"Graph Editor",
@ -809,12 +1012,17 @@ int main() {
ImGui::ShowDemoWindow();
}
// the sokol_gfx draw pass
sg_begin_default_pass(&pass_action, cur_width, cur_height);
// Rendering of the offscreen scene
sg_begin_pass(offscreen_viewport.pass, &offscreen_viewport.pass_action);
sgl_draw();
sg_end_pass();
// Rendering of the main gui
sg_begin_default_pass(&pass_action, cur_width, cur_height);
ImGui::Render();
draw_imgui(ImGui::GetDrawData());
sg_end_pass();
sg_commit();
glfwSwapBuffers(w);
glfwPollEvents();
@ -937,6 +1145,8 @@ void draw_imgui(ImDrawData* draw_data) {
return;
}
sg_image default_image = bind.fs_images[0];
// render the command list
sg_apply_pipeline(pip);
vs_params_t vs_params;
@ -972,12 +1182,23 @@ void draw_imgui(ImDrawData* draw_data) {
if (pcmd.UserCallback) {
pcmd.UserCallback(cl, &pcmd);
} else {
uint32_t prev_fs_image_id = bind.fs_images[0].id;
if (pcmd.TextureId != nullptr) {
bind.fs_images[0].id = (uint32_t)(uintptr_t)pcmd.TextureId;
sg_apply_bindings(&bind);
}
const int scissor_x = (int)(pcmd.ClipRect.x);
const int scissor_y = (int)(pcmd.ClipRect.y);
const int scissor_w = (int)(pcmd.ClipRect.z - pcmd.ClipRect.x);
const int scissor_h = (int)(pcmd.ClipRect.w - pcmd.ClipRect.y);
sg_apply_scissor_rect(scissor_x, scissor_y, scissor_w, scissor_h, true);
sg_draw(base_element, pcmd.ElemCount, 1);
if (pcmd.TextureId != nullptr) {
bind.fs_images[0].id = prev_fs_image_id;
sg_apply_bindings(&bind);
}
}
base_element += pcmd.ElemCount;
}