Skip to content

Commit

Permalink
ChainViewer (DX12): Update with accurate 3D capsules
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Nov 11, 2024
1 parent 5abf3c5 commit c92548f
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 3 deletions.
104 changes: 101 additions & 3 deletions src/mods/tools/ChainViewer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <optional>
#include <tuple>

#include <DirectxColors.h>

#include <imgui.h>
#include <ImGuizmo.h>

Expand Down Expand Up @@ -50,6 +52,7 @@

#endif

#include "../BackBufferRenderer.hpp"
#include "ObjectExplorer.hpp"
#include "ChainViewer.hpp"

Expand All @@ -59,6 +62,39 @@ std::optional<std::string> ChainViewer::on_initialize() {
return Mod::on_initialize();
}

std::optional<std::string> ChainViewer::on_initialize_d3d_thread() {
if (g_framework->is_dx12()) {
DirectX::EffectPipelineStateDescription psd(
&DirectX::DX12::GeometricPrimitive::VertexType::InputLayout,
DirectX::DX12::CommonStates::AlphaBlend,
DirectX::DX12::CommonStates::DepthNone,
DirectX::DX12::CommonStates::CullCounterClockwise,
BackBufferRenderer::get()->get_default_rt_state()
);

auto device = g_framework->get_d3d12_hook()->get_device();

m_d3d12.effect = std::make_unique<DirectX::DX12::BasicEffect>(device, DirectX::EffectFlags::None, psd);
m_d3d12.effect->SetWorld(DirectX::SimpleMath::Matrix::Identity);
m_d3d12.effect->SetView(DirectX::SimpleMath::Matrix::Identity);
m_d3d12.effect->SetProjection(DirectX::SimpleMath::Matrix::Identity);
m_d3d12.effect->SetDiffuseColor(DirectX::Colors::Blue);
m_d3d12.effect->SetAlpha(m_effect_alpha);

m_d3d12.cylinder = DirectX::GeometricPrimitive::CreateCylinder();
m_d3d12.sphere = DirectX::GeometricPrimitive::CreateSphere();

spdlog::info("ChainViewer D3D12 initialized");
} else {
// TODO
spdlog::info("ChainViewer D3D11 initialized");
}

// OK
return Mod::on_initialize();
}


void ChainViewer::on_config_load(const utility::Config& cfg) {
for (IModValue& option : m_options) {
option.config_load(cfg);
Expand All @@ -82,6 +118,21 @@ void ChainViewer::on_draw_dev_ui() {
if (m_enabled->draw("Enabled") && !m_enabled->value()) {
// todo
}

if (ImGui::SliderFloat("Effect Alpha", &m_effect_alpha, 0.0f, 1.0f)) {
m_effect_dirty = true;
}
}

void ChainViewer::on_present() {
if (g_framework->is_dx12()) {
if (m_effect_dirty) {
m_d3d12.effect->SetAlpha(m_effect_alpha);
m_effect_dirty = false;
}
} else {
// TODO
}
}

void ChainViewer::on_frame() {
Expand Down Expand Up @@ -145,13 +196,24 @@ void ChainViewer::on_frame() {
return;
}

Matrix4x4f proj{}, view{};
__declspec(align(16)) Matrix4x4f proj{}, view{};

const auto camera_origin = sdk::get_transform_position(camera_transform);

sdk::call_object_func<void*>(camera, "get_ProjectionMatrix", &proj, context, camera);
sdk::call_object_func<void*>(camera, "get_ViewMatrix", &view, context, camera);

auto proj_directx = DirectX::SimpleMath::Matrix{&proj[0][0]};
auto view_directx = DirectX::SimpleMath::Matrix{&view[0][0]};

std::vector<BackBufferRenderer::D3D12RenderWorkFn> d3d12_work{};

// Set the view and projection matrices for the effect once per frame
d3d12_work.emplace_back([this, proj_directx, view_directx](ID3D12GraphicsCommandList* cmd_list) {
m_d3d12.effect->SetProjection(proj_directx);
m_d3d12.effect->SetView(view_directx);
});

/*view = view * Matrix4x4f {
-1, 0, 0, 0,
0, 1, 0, 0,
Expand Down Expand Up @@ -256,11 +318,23 @@ void ChainViewer::on_frame() {

// Draw spheres/capsules and imguizmo widgets
if (collider.pair_joint == nullptr) {
imgui::draw_sphere(adjusted_pos1, collider.sphere.r, ImGui::GetColorU32(col), true);

Matrix4x4f mat = glm::scale(Vector3f{collider.sphere.r, collider.sphere.r, collider.sphere.r});
mat[3] = Vector4f{adjusted_pos1, 1.0f};

if (g_framework->is_dx12()) {
d3d12_work.emplace_back([this, adjusted_pos1, radius = collider.sphere.r](ID3D12GraphicsCommandList* cmd_list){
DirectX::SimpleMath::Matrix world = DirectX::SimpleMath::Matrix::CreateScale(radius) * DirectX::SimpleMath::Matrix::CreateTranslation(adjusted_pos1.x, adjusted_pos1.y, adjusted_pos1.z);
m_d3d12.effect->SetWorld(world);

m_d3d12.effect->Apply(cmd_list);
m_d3d12.sphere->Draw(cmd_list);
});
} else {
// TODO
imgui::draw_sphere(adjusted_pos1, collider.sphere.r, ImGui::GetColorU32(col), true);
}

const auto screen_pos1 = sdk::renderer::world_to_screen(adjusted_pos1);
const auto screen_pos1_top = sdk::renderer::world_to_screen(adjusted_pos1 + Vector3f{0.0f, collider.sphere.r, 0.0f});
const auto cursor_pos = *(Vector2f*)&ImGui::GetIO().MousePos;
Expand All @@ -278,7 +352,27 @@ void ChainViewer::on_frame() {
}
} else {
// Capsule
imgui::draw_capsule(adjusted_pos1, adjusted_pos2, collider.capsule.r, ImGui::GetColorU32(col), true);
if (g_framework->is_dx12()) {
d3d12_work.emplace_back([this, adjusted_pos1, adjusted_pos2, radius = collider.capsule.r](ID3D12GraphicsCommandList* cmd_list){
const auto delta = adjusted_pos2 - adjusted_pos1;
const auto dir = glm::normalize(delta);
const auto length = glm::length(delta) + (radius * 2.0f);
const auto center = (adjusted_pos1 + adjusted_pos2) * 0.5f;
DirectX::SimpleMath::Matrix world =
DirectX::SimpleMath::Matrix::CreateScale(radius * 2.0f, radius * 2.0f, length) *
DirectX::SimpleMath::Matrix::CreateLookAt(DirectX::SimpleMath::Vector3::Zero, DirectX::SimpleMath::Vector3(dir.x, dir.y, dir.z), DirectX::SimpleMath::Vector3::Up).Invert() *
DirectX::SimpleMath::Matrix::CreateTranslation(center.x, center.y, center.z);

m_d3d12.effect->SetWorld(world);

m_d3d12.effect->Apply(cmd_list);
m_d3d12.sphere->Draw(cmd_list);
});
} else {
// TODO
imgui::draw_capsule(adjusted_pos1, adjusted_pos2, collider.capsule.r, ImGui::GetColorU32(col), true);
}


const auto screen_pos1 = sdk::renderer::world_to_screen(adjusted_pos1);
const auto screen_pos1_top = sdk::renderer::world_to_screen(adjusted_pos1 + Vector3f{0.0f, collider.capsule.r, 0.0f});
Expand Down Expand Up @@ -428,5 +522,9 @@ void ChainViewer::on_frame() {
}

ImGui::End();

if (g_framework->is_dx12()) {
BackBufferRenderer::get()->submit_work_d3d12(std::move(d3d12_work));
}
}

21 changes: 21 additions & 0 deletions src/mods/tools/ChainViewer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

#include <chrono>

#include <../../directxtk12-src/Inc/SimpleMath.h>
#include <../../directxtk12-src/Inc/CommonStates.h>
#include <../../directxtk12-src/Inc/Effects.h>
#include <../../directxtk12-src/Inc/GeometricPrimitive.h>

#include "../mods/vr/d3d12/CommandContext.hpp"
#include "../mods/vr/d3d12/TextureContext.hpp"
#include "../mods/vr/d3d12/ComPtr.hpp"

#include "Tool.hpp"

class ChainViewer : public Tool {
Expand All @@ -11,11 +20,23 @@ class ChainViewer : public Tool {
}

std::optional<std::string> on_initialize() override;
std::optional<std::string> on_initialize_d3d_thread() override;
void on_config_load(const utility::Config& cfg) override;
void on_config_save(utility::Config& cfg) override;

void on_draw_dev_ui() override;
void on_frame() override;
void on_present() override;

private:
struct {
std::unique_ptr<DirectX::DX12::BasicEffect> effect{};
std::unique_ptr<DirectX::DX12::GeometricPrimitive> cylinder{};
std::unique_ptr<DirectX::DX12::GeometricPrimitive> sphere{};
} m_d3d12;

float m_effect_alpha{0.5f};
bool m_effect_dirty{false};

private:
const ModToggle::Ptr m_enabled{ ModToggle::create(generate_name("Enabled")) };
Expand Down

0 comments on commit c92548f

Please sign in to comment.