Skip to content

Commit c92548f

Browse files
committed
ChainViewer (DX12): Update with accurate 3D capsules
1 parent 5abf3c5 commit c92548f

File tree

2 files changed

+122
-3
lines changed

2 files changed

+122
-3
lines changed

src/mods/tools/ChainViewer.cpp

+101-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include <optional>
22
#include <tuple>
33

4+
#include <DirectxColors.h>
5+
46
#include <imgui.h>
57
#include <ImGuizmo.h>
68

@@ -50,6 +52,7 @@
5052

5153
#endif
5254

55+
#include "../BackBufferRenderer.hpp"
5356
#include "ObjectExplorer.hpp"
5457
#include "ChainViewer.hpp"
5558

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

65+
std::optional<std::string> ChainViewer::on_initialize_d3d_thread() {
66+
if (g_framework->is_dx12()) {
67+
DirectX::EffectPipelineStateDescription psd(
68+
&DirectX::DX12::GeometricPrimitive::VertexType::InputLayout,
69+
DirectX::DX12::CommonStates::AlphaBlend,
70+
DirectX::DX12::CommonStates::DepthNone,
71+
DirectX::DX12::CommonStates::CullCounterClockwise,
72+
BackBufferRenderer::get()->get_default_rt_state()
73+
);
74+
75+
auto device = g_framework->get_d3d12_hook()->get_device();
76+
77+
m_d3d12.effect = std::make_unique<DirectX::DX12::BasicEffect>(device, DirectX::EffectFlags::None, psd);
78+
m_d3d12.effect->SetWorld(DirectX::SimpleMath::Matrix::Identity);
79+
m_d3d12.effect->SetView(DirectX::SimpleMath::Matrix::Identity);
80+
m_d3d12.effect->SetProjection(DirectX::SimpleMath::Matrix::Identity);
81+
m_d3d12.effect->SetDiffuseColor(DirectX::Colors::Blue);
82+
m_d3d12.effect->SetAlpha(m_effect_alpha);
83+
84+
m_d3d12.cylinder = DirectX::GeometricPrimitive::CreateCylinder();
85+
m_d3d12.sphere = DirectX::GeometricPrimitive::CreateSphere();
86+
87+
spdlog::info("ChainViewer D3D12 initialized");
88+
} else {
89+
// TODO
90+
spdlog::info("ChainViewer D3D11 initialized");
91+
}
92+
93+
// OK
94+
return Mod::on_initialize();
95+
}
96+
97+
6298
void ChainViewer::on_config_load(const utility::Config& cfg) {
6399
for (IModValue& option : m_options) {
64100
option.config_load(cfg);
@@ -82,6 +118,21 @@ void ChainViewer::on_draw_dev_ui() {
82118
if (m_enabled->draw("Enabled") && !m_enabled->value()) {
83119
// todo
84120
}
121+
122+
if (ImGui::SliderFloat("Effect Alpha", &m_effect_alpha, 0.0f, 1.0f)) {
123+
m_effect_dirty = true;
124+
}
125+
}
126+
127+
void ChainViewer::on_present() {
128+
if (g_framework->is_dx12()) {
129+
if (m_effect_dirty) {
130+
m_d3d12.effect->SetAlpha(m_effect_alpha);
131+
m_effect_dirty = false;
132+
}
133+
} else {
134+
// TODO
135+
}
85136
}
86137

87138
void ChainViewer::on_frame() {
@@ -145,13 +196,24 @@ void ChainViewer::on_frame() {
145196
return;
146197
}
147198

148-
Matrix4x4f proj{}, view{};
199+
__declspec(align(16)) Matrix4x4f proj{}, view{};
149200

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

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

206+
auto proj_directx = DirectX::SimpleMath::Matrix{&proj[0][0]};
207+
auto view_directx = DirectX::SimpleMath::Matrix{&view[0][0]};
208+
209+
std::vector<BackBufferRenderer::D3D12RenderWorkFn> d3d12_work{};
210+
211+
// Set the view and projection matrices for the effect once per frame
212+
d3d12_work.emplace_back([this, proj_directx, view_directx](ID3D12GraphicsCommandList* cmd_list) {
213+
m_d3d12.effect->SetProjection(proj_directx);
214+
m_d3d12.effect->SetView(view_directx);
215+
});
216+
155217
/*view = view * Matrix4x4f {
156218
-1, 0, 0, 0,
157219
0, 1, 0, 0,
@@ -256,11 +318,23 @@ void ChainViewer::on_frame() {
256318

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

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

325+
if (g_framework->is_dx12()) {
326+
d3d12_work.emplace_back([this, adjusted_pos1, radius = collider.sphere.r](ID3D12GraphicsCommandList* cmd_list){
327+
DirectX::SimpleMath::Matrix world = DirectX::SimpleMath::Matrix::CreateScale(radius) * DirectX::SimpleMath::Matrix::CreateTranslation(adjusted_pos1.x, adjusted_pos1.y, adjusted_pos1.z);
328+
m_d3d12.effect->SetWorld(world);
329+
330+
m_d3d12.effect->Apply(cmd_list);
331+
m_d3d12.sphere->Draw(cmd_list);
332+
});
333+
} else {
334+
// TODO
335+
imgui::draw_sphere(adjusted_pos1, collider.sphere.r, ImGui::GetColorU32(col), true);
336+
}
337+
264338
const auto screen_pos1 = sdk::renderer::world_to_screen(adjusted_pos1);
265339
const auto screen_pos1_top = sdk::renderer::world_to_screen(adjusted_pos1 + Vector3f{0.0f, collider.sphere.r, 0.0f});
266340
const auto cursor_pos = *(Vector2f*)&ImGui::GetIO().MousePos;
@@ -278,7 +352,27 @@ void ChainViewer::on_frame() {
278352
}
279353
} else {
280354
// Capsule
281-
imgui::draw_capsule(adjusted_pos1, adjusted_pos2, collider.capsule.r, ImGui::GetColorU32(col), true);
355+
if (g_framework->is_dx12()) {
356+
d3d12_work.emplace_back([this, adjusted_pos1, adjusted_pos2, radius = collider.capsule.r](ID3D12GraphicsCommandList* cmd_list){
357+
const auto delta = adjusted_pos2 - adjusted_pos1;
358+
const auto dir = glm::normalize(delta);
359+
const auto length = glm::length(delta) + (radius * 2.0f);
360+
const auto center = (adjusted_pos1 + adjusted_pos2) * 0.5f;
361+
DirectX::SimpleMath::Matrix world =
362+
DirectX::SimpleMath::Matrix::CreateScale(radius * 2.0f, radius * 2.0f, length) *
363+
DirectX::SimpleMath::Matrix::CreateLookAt(DirectX::SimpleMath::Vector3::Zero, DirectX::SimpleMath::Vector3(dir.x, dir.y, dir.z), DirectX::SimpleMath::Vector3::Up).Invert() *
364+
DirectX::SimpleMath::Matrix::CreateTranslation(center.x, center.y, center.z);
365+
366+
m_d3d12.effect->SetWorld(world);
367+
368+
m_d3d12.effect->Apply(cmd_list);
369+
m_d3d12.sphere->Draw(cmd_list);
370+
});
371+
} else {
372+
// TODO
373+
imgui::draw_capsule(adjusted_pos1, adjusted_pos2, collider.capsule.r, ImGui::GetColorU32(col), true);
374+
}
375+
282376

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

430524
ImGui::End();
525+
526+
if (g_framework->is_dx12()) {
527+
BackBufferRenderer::get()->submit_work_d3d12(std::move(d3d12_work));
528+
}
431529
}
432530

src/mods/tools/ChainViewer.hpp

+21
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
#include <chrono>
44

5+
#include <../../directxtk12-src/Inc/SimpleMath.h>
6+
#include <../../directxtk12-src/Inc/CommonStates.h>
7+
#include <../../directxtk12-src/Inc/Effects.h>
8+
#include <../../directxtk12-src/Inc/GeometricPrimitive.h>
9+
10+
#include "../mods/vr/d3d12/CommandContext.hpp"
11+
#include "../mods/vr/d3d12/TextureContext.hpp"
12+
#include "../mods/vr/d3d12/ComPtr.hpp"
13+
514
#include "Tool.hpp"
615

716
class ChainViewer : public Tool {
@@ -11,11 +20,23 @@ class ChainViewer : public Tool {
1120
}
1221

1322
std::optional<std::string> on_initialize() override;
23+
std::optional<std::string> on_initialize_d3d_thread() override;
1424
void on_config_load(const utility::Config& cfg) override;
1525
void on_config_save(utility::Config& cfg) override;
1626

1727
void on_draw_dev_ui() override;
1828
void on_frame() override;
29+
void on_present() override;
30+
31+
private:
32+
struct {
33+
std::unique_ptr<DirectX::DX12::BasicEffect> effect{};
34+
std::unique_ptr<DirectX::DX12::GeometricPrimitive> cylinder{};
35+
std::unique_ptr<DirectX::DX12::GeometricPrimitive> sphere{};
36+
} m_d3d12;
37+
38+
float m_effect_alpha{0.5f};
39+
bool m_effect_dirty{false};
1940

2041
private:
2142
const ModToggle::Ptr m_enabled{ ModToggle::create(generate_name("Enabled")) };

0 commit comments

Comments
 (0)