2019.12
This commit is contained in:
parent
a692b08930
commit
75be504c1f
|
@ -15,7 +15,7 @@
|
|||
<ProjectGuid>{53923514-84B2-4B78-889A-8709C6BFA3A5}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>RendererDirect3D12</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
|
|
|
@ -34,12 +34,12 @@ CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::AtGPU(INT index) const
|
|||
|
||||
// DynamicDescriptorHeap:
|
||||
|
||||
void DynamicDescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, bool shaderVisible)
|
||||
void DynamicDescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, UINT numStatic, bool shaderVisible)
|
||||
{
|
||||
VERUS_CT_ASSERT(sizeof(*this) == 56);
|
||||
_capacity = num;
|
||||
_offset = 0;
|
||||
DescriptorHeap::Create(pDevice, type, _capacity * BaseRenderer::s_ringBufferSize, shaderVisible);
|
||||
DescriptorHeap::Create(pDevice, type, _capacity * BaseRenderer::s_ringBufferSize + numStatic, shaderVisible);
|
||||
}
|
||||
|
||||
HandlePair DynamicDescriptorHeap::GetNextHandlePair(int num)
|
||||
|
@ -63,3 +63,9 @@ HandlePair DynamicDescriptorHeap::GetNextHandlePair(int num)
|
|||
VERUS_RT_FAIL("DynamicDescriptorHeap is full.");
|
||||
return HandlePair();
|
||||
}
|
||||
|
||||
HandlePair DynamicDescriptorHeap::GetStaticHandlePair(int index)
|
||||
{
|
||||
const INT indexAt = _capacity * BaseRenderer::s_ringBufferSize + index;
|
||||
return HandlePair(AtCPU(indexAt), AtGPU(indexAt));
|
||||
}
|
||||
|
|
|
@ -43,9 +43,10 @@ namespace verus
|
|||
UINT64 _peakLoad = 0;
|
||||
|
||||
public:
|
||||
void Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, bool shaderVisible = false);
|
||||
void Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, UINT numStatic = 0, bool shaderVisible = false);
|
||||
|
||||
HandlePair GetNextHandlePair(int num = 1);
|
||||
HandlePair GetStaticHandlePair(int index);
|
||||
|
||||
UINT GetCapacity() const { return _capacity; }
|
||||
UINT GetOffset() const { return _offset; }
|
||||
|
|
|
@ -17,8 +17,8 @@ void GeometryD3D12::Init(RcGeometryDesc desc)
|
|||
{
|
||||
VERUS_INIT();
|
||||
|
||||
_dynBindingsMask = desc._dynBindingsMask;
|
||||
_32BitIndices = desc._32BitIndices;
|
||||
_dynamic = desc._dynamic;
|
||||
|
||||
_vInputElementDesc.reserve(GetNumInputElementDesc(desc._pInputElementDesc));
|
||||
int i = 0;
|
||||
|
@ -30,7 +30,7 @@ void GeometryD3D12::Init(RcGeometryDesc desc)
|
|||
if (binding < 0)
|
||||
{
|
||||
binding = -binding;
|
||||
_bindingInstMask |= (1 << binding);
|
||||
_instBindingsMask |= (1 << binding);
|
||||
inputClassification = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
|
||||
instanceDataStepRate = 1;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ void GeometryD3D12::CreateVertexBuffer(int num, int binding)
|
|||
const int elementSize = _vStrides[binding];
|
||||
vb._bufferSize = num * elementSize;
|
||||
|
||||
if (((_bindingInstMask >> binding) & 0x1) || _dynamic)
|
||||
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
|
||||
{
|
||||
D3D12MA::ALLOCATION_DESC allocDesc = {};
|
||||
allocDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
|
||||
|
@ -136,7 +136,7 @@ void GeometryD3D12::UpdateVertexBuffer(const void* p, int binding, BaseCommandBu
|
|||
VERUS_QREF_RENDERER_D3D12;
|
||||
HRESULT hr = 0;
|
||||
|
||||
if (((_bindingInstMask >> binding) & 0x1) || _dynamic)
|
||||
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
|
||||
{
|
||||
auto& vb = _vVertexBuffers[binding];
|
||||
CD3DX12_RANGE readRange(0, 0);
|
||||
|
@ -289,7 +289,7 @@ D3D12_INPUT_LAYOUT_DESC GeometryD3D12::GetD3DInputLayoutDesc(UINT32 bindingsFilt
|
|||
|
||||
const D3D12_VERTEX_BUFFER_VIEW* GeometryD3D12::GetD3DVertexBufferView(int binding) const
|
||||
{
|
||||
if ((_bindingInstMask >> binding) & 0x1)
|
||||
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
|
||||
{
|
||||
VERUS_QREF_RENDERER_D3D12;
|
||||
return &_vVertexBuffers[binding]._bufferView[pRendererD3D12->GetRingBufferIndex()];
|
||||
|
|
|
@ -141,7 +141,7 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
|
|||
gpsDesc.RasterizerState.SlopeScaledDepthBias = desc._rasterizationState._depthBiasSlopeFactor;
|
||||
gpsDesc.RasterizerState.DepthClipEnable = desc._rasterizationState._depthClampEnable;
|
||||
gpsDesc.RasterizerState.MultisampleEnable = FALSE;
|
||||
gpsDesc.RasterizerState.AntialiasedLineEnable = FALSE;
|
||||
gpsDesc.RasterizerState.AntialiasedLineEnable = TRUE;
|
||||
gpsDesc.RasterizerState.ForcedSampleCount = 0;
|
||||
gpsDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
|
||||
|
|
|
@ -31,6 +31,15 @@ void RendererD3D12::Init()
|
|||
void RendererD3D12::Done()
|
||||
{
|
||||
WaitIdle();
|
||||
|
||||
if (ImGui::GetCurrentContext())
|
||||
{
|
||||
ImGui_ImplDX12_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
Renderer::I().ImGuiSetCurrentContext(nullptr);
|
||||
}
|
||||
|
||||
DeleteFramebuffer(-1);
|
||||
DeleteRenderPass(-1);
|
||||
|
||||
|
@ -190,8 +199,8 @@ void RendererD3D12::InitD3D()
|
|||
_pFence = CreateFence();
|
||||
_hFence = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
_dhCbvSrvUav.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, settings.GetLimits()._d3d12_dhCbvSrvUavCapacity, true);
|
||||
_dhSamplers.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, settings.GetLimits()._d3d12_dhSamplersCapacity, true);
|
||||
_dhCbvSrvUav.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, settings.GetLimits()._d3d12_dhCbvSrvUavCapacity, 16, true);
|
||||
_dhSamplers.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, settings.GetLimits()._d3d12_dhSamplersCapacity, 0, true);
|
||||
|
||||
CreateSamplers();
|
||||
}
|
||||
|
@ -350,10 +359,63 @@ D3D12_STATIC_SAMPLER_DESC RendererD3D12::GetStaticSamplerDesc(Sampler s) const
|
|||
|
||||
void RendererD3D12::ImGuiInit(int renderPassID)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGuiContext* pContext = ImGui::CreateContext();
|
||||
renderer.ImGuiSetCurrentContext(pContext);
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigWindowsMoveFromTitleBarOnly = true;
|
||||
if (!settings._imguiFont.empty())
|
||||
{
|
||||
Vector<BYTE> vData;
|
||||
IO::FileSystem::LoadResource(_C(settings._imguiFont), vData);
|
||||
void* pFontData = IM_ALLOC(vData.size());
|
||||
memcpy(pFontData, vData.data(), vData.size());
|
||||
io.Fonts->AddFontFromMemoryTTF(pFontData, Utils::Cast32(vData.size()), 15);
|
||||
}
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplSDL2_InitForD3D(renderer.GetMainWindow()->GetSDL());
|
||||
auto hp = _dhCbvSrvUav.GetStaticHandlePair(0);
|
||||
ImGui_ImplDX12_Init(
|
||||
_pDevice.Get(),
|
||||
s_ringBufferSize,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
_dhCbvSrvUav.GetD3DDescriptorHeap(),
|
||||
hp._hCPU,
|
||||
hp._hGPU);
|
||||
}
|
||||
|
||||
void RendererD3D12::ImGuiRenderDrawData()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
ImGui::Render();
|
||||
auto pCmdList = static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList();
|
||||
if (ImGui::GetDrawData())
|
||||
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), pCmdList);
|
||||
}
|
||||
|
||||
void RendererD3D12::ResizeSwapChain()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
_dhSwapChainBuffersRTVs.Reset();
|
||||
_vSwapChainBuffers.clear();
|
||||
|
||||
_pSwapChain->ResizeBuffers(
|
||||
_swapChainDesc.BufferCount,
|
||||
renderer.GetSwapChainWidth(),
|
||||
renderer.GetSwapChainHeight(),
|
||||
_swapChainDesc.Format,
|
||||
_swapChainDesc.Flags);
|
||||
|
||||
_swapChainBufferIndex = _pSwapChain->GetCurrentBackBufferIndex();
|
||||
|
||||
CreateSwapChainBuffersRTVs();
|
||||
}
|
||||
|
||||
void RendererD3D12::BeginFrame(bool present)
|
||||
|
@ -361,6 +423,10 @@ void RendererD3D12::BeginFrame(bool present)
|
|||
VERUS_QREF_RENDERER;
|
||||
HRESULT hr = 0;
|
||||
|
||||
ImGui_ImplDX12_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame(renderer.GetMainWindow()->GetSDL());
|
||||
ImGui::NewFrame();
|
||||
|
||||
WaitForFenceValue(_fenceValues[_ringBufferIndex]);
|
||||
|
||||
if (present)
|
||||
|
@ -391,6 +457,8 @@ void RendererD3D12::EndFrame(bool present)
|
|||
_fenceValues[_ringBufferIndex] = QueueSignal();
|
||||
_ringBufferIndex = (_ringBufferIndex + 1) % s_ringBufferSize;
|
||||
}
|
||||
|
||||
ImGui::EndFrame();
|
||||
}
|
||||
|
||||
void RendererD3D12::Present()
|
||||
|
@ -495,7 +563,7 @@ int RendererD3D12::CreateRenderPass(std::initializer_list<RP::Attachment> ilA, s
|
|||
return index;
|
||||
index++;
|
||||
}
|
||||
throw VERUS_RECOVERABLE << "CreateRenderPass(), Attachment not found";
|
||||
throw VERUS_RECOVERABLE << "CreateRenderPass(), attachment not found";
|
||||
};
|
||||
|
||||
renderPass._vSubpasses.reserve(ilS.size());
|
||||
|
|
|
@ -67,6 +67,8 @@ namespace verus
|
|||
virtual void ImGuiInit(int renderPassID) override;
|
||||
virtual void ImGuiRenderDrawData() override;
|
||||
|
||||
virtual void ResizeSwapChain() override;
|
||||
|
||||
// Which graphics API?
|
||||
virtual Gapi GetGapi() override { return Gapi::direct3D12; }
|
||||
|
||||
|
@ -74,7 +76,6 @@ namespace verus
|
|||
virtual void BeginFrame(bool present) override;
|
||||
virtual void EndFrame(bool present) override;
|
||||
virtual void Present() override;
|
||||
|
||||
virtual void WaitIdle() override;
|
||||
|
||||
// Resources:
|
||||
|
|
|
@ -436,6 +436,16 @@ int ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_list<
|
|||
return complexSetID;
|
||||
}
|
||||
|
||||
void ShaderD3D12::FreeDescriptorSet(int complexSetID)
|
||||
{
|
||||
if (complexSetID >= 0 && complexSetID < _vComplexSets.size())
|
||||
{
|
||||
_vComplexSets[complexSetID]._vTextures.clear();
|
||||
_vComplexSets[complexSetID]._dhSrvUav.Reset();
|
||||
_vComplexSets[complexSetID]._dhSamplers.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderD3D12::BeginBindDescriptors()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
|
|
@ -70,6 +70,7 @@ namespace verus
|
|||
virtual void CreateDescriptorSet(int setNumber, const void* pSrc, int size, int capacity, std::initializer_list<Sampler> il, ShaderStageFlags stageFlags) override;
|
||||
virtual void CreatePipelineLayout() override;
|
||||
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips) override;
|
||||
virtual void FreeDescriptorSet(int complexSetID) override;
|
||||
|
||||
virtual void BeginBindDescriptors() override;
|
||||
virtual void EndBindDescriptors() override;
|
||||
|
|
|
@ -24,7 +24,7 @@ extern "C"
|
|||
|
||||
if (VERUS_SDK_VERSION != version)
|
||||
{
|
||||
VERUS_RT_FAIL("VerusCreateRenderer(), Wrong version");
|
||||
VERUS_RT_FAIL("VerusCreateRenderer(), Wrong version.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<ProjectGuid>{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>RendererVulkan</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
|
|
|
@ -31,7 +31,8 @@ void CommandBufferVulkan::Begin()
|
|||
VkResult res = VK_SUCCESS;
|
||||
VkCommandBufferBeginInfo vkcbbi = {};
|
||||
vkcbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
vkcbbi.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
||||
if (_oneTimeSubmit)
|
||||
vkcbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
if (VK_SUCCESS != (res = vkBeginCommandBuffer(GetVkCommandBuffer(), &vkcbbi)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkBeginCommandBuffer(), res=" << res;
|
||||
}
|
||||
|
@ -324,10 +325,11 @@ VkCommandBuffer CommandBufferVulkan::GetVkCommandBuffer() const
|
|||
return _commandBuffers[renderer->GetRingBufferIndex()];
|
||||
}
|
||||
|
||||
void CommandBufferVulkan::InitSingleTimeCommands()
|
||||
void CommandBufferVulkan::InitOneTimeSubmit()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_RENDERER_VULKAN;
|
||||
_oneTimeSubmit = true;
|
||||
auto commandPool = pRendererVulkan->GetVkCommandPool(renderer->GetRingBufferIndex());
|
||||
auto commandBuffer = pRendererVulkan->CreateCommandBuffer(commandPool);
|
||||
VERUS_FOR(i, BaseRenderer::s_ringBufferSize)
|
||||
|
@ -335,7 +337,7 @@ void CommandBufferVulkan::InitSingleTimeCommands()
|
|||
Begin();
|
||||
}
|
||||
|
||||
void CommandBufferVulkan::DoneSingleTimeCommands()
|
||||
void CommandBufferVulkan::DoneOneTimeSubmit()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_RENDERER_VULKAN;
|
||||
|
@ -348,4 +350,5 @@ void CommandBufferVulkan::DoneSingleTimeCommands()
|
|||
vkQueueWaitIdle(pRendererVulkan->GetVkGraphicsQueue());
|
||||
auto commandPool = pRendererVulkan->GetVkCommandPool(renderer->GetRingBufferIndex());
|
||||
vkFreeCommandBuffers(pRendererVulkan->GetVkDevice(), commandPool, 1, _commandBuffers);
|
||||
_oneTimeSubmit = false;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace verus
|
|||
class CommandBufferVulkan : public BaseCommandBuffer
|
||||
{
|
||||
VkCommandBuffer _commandBuffers[BaseRenderer::s_ringBufferSize] = {};
|
||||
bool _oneTimeSubmit = false;
|
||||
|
||||
public:
|
||||
CommandBufferVulkan();
|
||||
|
@ -46,8 +47,8 @@ namespace verus
|
|||
|
||||
VkCommandBuffer GetVkCommandBuffer() const;
|
||||
|
||||
void InitSingleTimeCommands();
|
||||
void DoneSingleTimeCommands();
|
||||
void InitOneTimeSubmit();
|
||||
void DoneOneTimeSubmit();
|
||||
};
|
||||
VERUS_TYPEDEFS(CommandBufferVulkan);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ void GeometryVulkan::Init(RcGeometryDesc desc)
|
|||
{
|
||||
VERUS_INIT();
|
||||
|
||||
_dynBindingsMask = desc._dynBindingsMask;
|
||||
_32BitIndices = desc._32BitIndices;
|
||||
_dynamic = desc._dynamic;
|
||||
|
||||
const int numBindings = GetNumBindings(desc._pInputElementDesc);
|
||||
_vVertexInputBindingDesc.reserve(numBindings);
|
||||
|
@ -30,7 +30,7 @@ void GeometryVulkan::Init(RcGeometryDesc desc)
|
|||
if (binding < 0)
|
||||
{
|
||||
binding = -binding;
|
||||
_bindingInstMask |= (1 << binding);
|
||||
_instBindingsMask |= (1 << binding);
|
||||
inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ void GeometryVulkan::CreateVertexBuffer(int num, int binding)
|
|||
const int elementSize = _vStrides[binding];
|
||||
vb._bufferSize = num * elementSize;
|
||||
|
||||
if (((_bindingInstMask >> binding) & 0x1) || _dynamic)
|
||||
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
|
||||
{
|
||||
pRendererVulkan->CreateBuffer(vb._bufferSize * BaseRenderer::s_ringBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU,
|
||||
vb._buffer, vb._vmaAllocation);
|
||||
|
@ -114,7 +114,7 @@ void GeometryVulkan::UpdateVertexBuffer(const void* p, int binding, BaseCommandB
|
|||
VERUS_QREF_RENDERER_VULKAN;
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
if (((_bindingInstMask >> binding) & 0x1) || _dynamic)
|
||||
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
|
||||
{
|
||||
auto& vb = _vVertexBuffers[binding];
|
||||
void* pData = nullptr;
|
||||
|
@ -240,7 +240,7 @@ VkPipelineVertexInputStateCreateInfo GeometryVulkan::GetVkPipelineVertexInputSta
|
|||
|
||||
VkDeviceSize GeometryVulkan::GetVkVertexBufferOffset(int binding) const
|
||||
{
|
||||
if ((_bindingInstMask >> binding) & 0x1)
|
||||
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
|
||||
{
|
||||
VERUS_QREF_RENDERER_VULKAN;
|
||||
auto& vb = _vVertexBuffers[binding];
|
||||
|
|
|
@ -75,8 +75,12 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
viewportState.viewportCount = desc._multiViewport;
|
||||
viewportState.scissorCount = desc._multiViewport;
|
||||
|
||||
VkPipelineRasterizationLineStateCreateInfoEXT rasterizationLineState = {};
|
||||
rasterizationLineState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
|
||||
rasterizationLineState.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
|
||||
VkPipelineRasterizationStateCreateInfo rasterizationState = {};
|
||||
rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
rasterizationState.pNext = &rasterizationLineState;
|
||||
rasterizationState.depthClampEnable = desc._rasterizationState._depthClampEnable;
|
||||
rasterizationState.rasterizerDiscardEnable = desc._rasterizationState._rasterizerDiscardEnable;
|
||||
rasterizationState.polygonMode = ToNativePolygonMode(desc._rasterizationState._polygonMode);
|
||||
|
@ -86,7 +90,7 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
|
|||
rasterizationState.depthBiasConstantFactor = desc._rasterizationState._depthBiasConstantFactor * 0.5f; // Magic value to match D3D12.
|
||||
rasterizationState.depthBiasClamp = desc._rasterizationState._depthBiasClamp;
|
||||
rasterizationState.depthBiasSlopeFactor = desc._rasterizationState._depthBiasSlopeFactor;
|
||||
rasterizationState.lineWidth = desc._rasterizationState._lineWidth;
|
||||
rasterizationState.lineWidth = 1;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisampleState = {};
|
||||
multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
|
|
|
@ -91,12 +91,22 @@ void RendererVulkan::Init()
|
|||
void RendererVulkan::Done()
|
||||
{
|
||||
WaitIdle();
|
||||
|
||||
if (ImGui::GetCurrentContext())
|
||||
{
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
Renderer::I().ImGuiSetCurrentContext(nullptr);
|
||||
}
|
||||
|
||||
DeleteFramebuffer(-1);
|
||||
DeleteRenderPass(-1);
|
||||
|
||||
for (auto sampler : _vSamplers)
|
||||
VERUS_VULKAN_DESTROY(sampler, vkDestroySampler(_device, sampler, GetAllocator()));
|
||||
_vSamplers.clear();
|
||||
VERUS_VULKAN_DESTROY(_descriptorPoolImGui, vkDestroyDescriptorPool(_device, _descriptorPoolImGui, GetAllocator()));
|
||||
VERUS_FOR(i, s_ringBufferSize)
|
||||
{
|
||||
VERUS_VULKAN_DESTROY(_acquireNextImageSemaphores[i], vkDestroySemaphore(_device, _acquireNextImageSemaphores[i], GetAllocator()));
|
||||
|
@ -378,6 +388,10 @@ void RendererVulkan::CreateDevice()
|
|||
{
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
VkPhysicalDeviceLineRasterizationFeaturesEXT lineRasterizationFeatures = {};
|
||||
lineRasterizationFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
|
||||
lineRasterizationFeatures.smoothLines = VK_TRUE;
|
||||
|
||||
_queueFamilyIndices = FindQueueFamilyIndices(_physicalDevice);
|
||||
VERUS_RT_ASSERT(_queueFamilyIndices.IsComplete());
|
||||
Set<int> setUniqueQueueFamilies = { _queueFamilyIndices._graphicsFamilyIndex, _queueFamilyIndices._presentFamilyIndex };
|
||||
|
@ -400,6 +414,7 @@ void RendererVulkan::CreateDevice()
|
|||
physicalDeviceFeatures.shaderImageGatherExtended = VK_TRUE;
|
||||
VkDeviceCreateInfo vkdci = {};
|
||||
vkdci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
vkdci.pNext = &lineRasterizationFeatures;
|
||||
vkdci.queueCreateInfoCount = Utils::Cast32(vDeviceQueueCreateInfos.size());
|
||||
vkdci.pQueueCreateInfos = vDeviceQueueCreateInfos.data();
|
||||
#if defined(_DEBUG) || defined(VERUS_DEBUG)
|
||||
|
@ -441,8 +456,9 @@ RendererVulkan::SwapChainInfo RendererVulkan::GetSwapChainInfo(VkPhysicalDevice
|
|||
return swapChainInfo;
|
||||
}
|
||||
|
||||
void RendererVulkan::CreateSwapChain()
|
||||
void RendererVulkan::CreateSwapChain(VkSwapchainKHR oldSwapchain)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
@ -457,15 +473,15 @@ void RendererVulkan::CreateSwapChain()
|
|||
vksci.minImageCount = _numSwapChainBuffers;
|
||||
vksci.imageFormat = VK_FORMAT_B8G8R8A8_SRGB;
|
||||
vksci.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
vksci.imageExtent.width = settings._screenSizeWidth;
|
||||
vksci.imageExtent.height = settings._screenSizeHeight;
|
||||
vksci.imageExtent.width = renderer.GetSwapChainWidth();
|
||||
vksci.imageExtent.height = renderer.GetSwapChainHeight();
|
||||
vksci.imageArrayLayers = 1;
|
||||
vksci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
vksci.preTransform = swapChainInfo._surfaceCapabilities.currentTransform;
|
||||
vksci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
vksci.presentMode = settings._screenVSync ? VK_PRESENT_MODE_MAILBOX_KHR : VK_PRESENT_MODE_FIFO_KHR;
|
||||
vksci.clipped = VK_TRUE;
|
||||
vksci.oldSwapchain = VK_NULL_HANDLE;
|
||||
vksci.oldSwapchain = oldSwapchain;
|
||||
const uint32_t queueFamilyIndicesArray[] =
|
||||
{
|
||||
static_cast<uint32_t>(_queueFamilyIndices._graphicsFamilyIndex),
|
||||
|
@ -662,44 +678,45 @@ const VkSampler* RendererVulkan::GetImmutableSampler(Sampler s) const
|
|||
return &_vSamplers[+s];
|
||||
}
|
||||
|
||||
void RendererVulkan::ImGuiCheckVkResultFn(VkResult res)
|
||||
{
|
||||
if (VK_SUCCESS != res)
|
||||
throw VERUS_RUNTIME_ERROR << "ImGuiCheckVkResultFn(), res=" << res;
|
||||
}
|
||||
|
||||
void RendererVulkan::ImGuiInit(int renderPassID)
|
||||
{
|
||||
VkResult res = VK_SUCCESS;
|
||||
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
|
||||
{
|
||||
VkDescriptorPoolSize pool_sizes[] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
|
||||
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
|
||||
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
|
||||
pool_info.pPoolSizes = pool_sizes;
|
||||
res = vkCreateDescriptorPool(_device, &pool_info, GetAllocator(), &descriptorPool);
|
||||
}
|
||||
VkDescriptorPoolSize vkdps = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 };
|
||||
VkDescriptorPoolCreateInfo vkdpci = {};
|
||||
vkdpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
vkdpci.maxSets = 1;
|
||||
vkdpci.poolSizeCount = 1;
|
||||
vkdpci.pPoolSizes = &vkdps;
|
||||
if (VK_SUCCESS != (res = vkCreateDescriptorPool(_device, &vkdpci, GetAllocator(), &_descriptorPoolImGui)))
|
||||
throw VERUS_RUNTIME_ERROR << "vkCreateDescriptorPool(), res=" << res;
|
||||
|
||||
VERUS_QREF_RENDERER;
|
||||
SDL_Window* pWnd = renderer.GetMainWindow()->GetSDL();
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGuiContext* pContext = ImGui::CreateContext();
|
||||
renderer.ImGuiSetCurrentContext(pContext);
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigWindowsMoveFromTitleBarOnly = true;
|
||||
if (!settings._imguiFont.empty())
|
||||
{
|
||||
Vector<BYTE> vData;
|
||||
IO::FileSystem::LoadResource(_C(settings._imguiFont), vData);
|
||||
void* pFontData = IM_ALLOC(vData.size());
|
||||
memcpy(pFontData, vData.data(), vData.size());
|
||||
io.Fonts->AddFontFromMemoryTTF(pFontData, Utils::Cast32(vData.size()), 15);
|
||||
}
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplSDL2_InitForVulkan(pWnd);
|
||||
ImGui_ImplSDL2_InitForVulkan(renderer.GetMainWindow()->GetSDL());
|
||||
ImGui_ImplVulkan_InitInfo info = {};
|
||||
info.Instance = _instance;
|
||||
info.PhysicalDevice = _physicalDevice;
|
||||
|
@ -707,49 +724,40 @@ void RendererVulkan::ImGuiInit(int renderPassID)
|
|||
info.QueueFamily = _queueFamilyIndices._graphicsFamilyIndex;
|
||||
info.Queue = _graphicsQueue;
|
||||
info.PipelineCache = nullptr;
|
||||
info.DescriptorPool = descriptorPool;
|
||||
info.DescriptorPool = _descriptorPoolImGui;
|
||||
info.Allocator = GetAllocator();
|
||||
info.MinImageCount = 2;
|
||||
info.ImageCount = 2;
|
||||
info.CheckVkResultFn = nullptr;
|
||||
info.MinImageCount = settings._screenVSync ? 3 : 2;;
|
||||
info.ImageCount = s_ringBufferSize;
|
||||
info.CheckVkResultFn = ImGuiCheckVkResultFn;
|
||||
ImGui_ImplVulkan_Init(&info, _vRenderPasses[renderPassID]);
|
||||
|
||||
{
|
||||
// Use any command queue
|
||||
VkCommandPool command_pool = _commandPools[_ringBufferIndex];
|
||||
VkCommandBuffer command_buffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
|
||||
|
||||
res = vkResetCommandPool(_device, command_pool, 0);
|
||||
|
||||
VkCommandBufferBeginInfo begin_info = {};
|
||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
res = vkBeginCommandBuffer(command_buffer, &begin_info);
|
||||
|
||||
|
||||
ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
|
||||
|
||||
VkSubmitInfo end_info = {};
|
||||
end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
end_info.commandBufferCount = 1;
|
||||
end_info.pCommandBuffers = &command_buffer;
|
||||
res = vkEndCommandBuffer(command_buffer);
|
||||
|
||||
res = vkQueueSubmit(_graphicsQueue, 1, &end_info, VK_NULL_HANDLE);
|
||||
|
||||
|
||||
res = vkDeviceWaitIdle(_device);
|
||||
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
}
|
||||
CommandBufferVulkan commandBuffer;
|
||||
commandBuffer.InitOneTimeSubmit();
|
||||
ImGui_ImplVulkan_CreateFontsTexture(commandBuffer.GetVkCommandBuffer());
|
||||
commandBuffer.DoneOneTimeSubmit();
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
}
|
||||
|
||||
void RendererVulkan::ImGuiRenderDrawData()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VkCommandBuffer command_buffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
|
||||
ImGui::Render();
|
||||
VkCommandBuffer commandBuffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
|
||||
if (ImGui::GetDrawData())
|
||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), command_buffer);
|
||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer);
|
||||
}
|
||||
|
||||
void RendererVulkan::ResizeSwapChain()
|
||||
{
|
||||
for (auto swapChainImageViews : _vSwapChainImageViews)
|
||||
vkDestroyImageView(_device, swapChainImageViews, GetAllocator());
|
||||
_vSwapChainImageViews.clear();
|
||||
_vSwapChainImages.clear();
|
||||
|
||||
VkSwapchainKHR oldSwapchain = _swapChain;
|
||||
CreateSwapChain(oldSwapchain);
|
||||
CreateImageViews();
|
||||
VERUS_VULKAN_DESTROY(oldSwapchain, vkDestroySwapchainKHR(_device, oldSwapchain, GetAllocator()));
|
||||
}
|
||||
|
||||
void RendererVulkan::BeginFrame(bool present)
|
||||
|
@ -944,7 +952,7 @@ int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA,
|
|||
return index;
|
||||
index++;
|
||||
}
|
||||
throw VERUS_RECOVERABLE << "CreateRenderPass(), Attachment not found";
|
||||
throw VERUS_RECOVERABLE << "CreateRenderPass(), attachment not found";
|
||||
};
|
||||
|
||||
struct SubpassMetadata
|
||||
|
@ -1014,7 +1022,7 @@ int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA,
|
|||
|
||||
// vAttachmentRef is ready, convert indices to actual pointers:
|
||||
if (vAttachmentRef.empty())
|
||||
throw VERUS_RECOVERABLE << "CreateRenderPass(), No attachment references";
|
||||
throw VERUS_RECOVERABLE << "CreateRenderPass(), no attachment references";
|
||||
int index = 0;
|
||||
for (auto& sd : vSubpassDesc)
|
||||
{
|
||||
|
@ -1041,7 +1049,7 @@ int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA,
|
|||
return index;
|
||||
index++;
|
||||
}
|
||||
throw VERUS_RECOVERABLE << "CreateRenderPass(), Subpass not found";
|
||||
throw VERUS_RECOVERABLE << "CreateRenderPass(), subpass not found";
|
||||
};
|
||||
|
||||
Vector<VkSubpassDependency> vSubpassDependency;
|
||||
|
|
|
@ -74,6 +74,7 @@ namespace verus
|
|||
VkSemaphore _queueSubmitSemaphore = VK_NULL_HANDLE;
|
||||
VkFence _queueSubmitFences[s_ringBufferSize] = {};
|
||||
QueueFamilyIndices _queueFamilyIndices;
|
||||
VkDescriptorPool _descriptorPoolImGui = VK_NULL_HANDLE;
|
||||
Vector<VkSampler> _vSamplers;
|
||||
Vector<VkRenderPass> _vRenderPasses;
|
||||
Vector<Framebuffer> _vFramebuffers;
|
||||
|
@ -109,7 +110,7 @@ namespace verus
|
|||
void PickPhysicalDevice();
|
||||
void CreateDevice();
|
||||
SwapChainInfo GetSwapChainInfo(VkPhysicalDevice device);
|
||||
void CreateSwapChain();
|
||||
void CreateSwapChain(VkSwapchainKHR oldSwapchain = VK_NULL_HANDLE);
|
||||
void CreateImageViews();
|
||||
void CreateCommandPools();
|
||||
void CreateSyncObjects();
|
||||
|
@ -125,9 +126,12 @@ namespace verus
|
|||
VkCommandPool GetVkCommandPool(int ringBufferIndex) const { return _commandPools[ringBufferIndex]; }
|
||||
const VkSampler* GetImmutableSampler(Sampler s) const;
|
||||
|
||||
static void ImGuiCheckVkResultFn(VkResult res);
|
||||
virtual void ImGuiInit(int renderPassID) override;
|
||||
virtual void ImGuiRenderDrawData() override;
|
||||
|
||||
virtual void ResizeSwapChain() override;
|
||||
|
||||
// Which graphics API?
|
||||
virtual Gapi GetGapi() override { return Gapi::vulkan; }
|
||||
|
||||
|
@ -135,7 +139,6 @@ namespace verus
|
|||
virtual void BeginFrame(bool present) override;
|
||||
virtual void EndFrame(bool present) override;
|
||||
virtual void Present() override;
|
||||
|
||||
virtual void WaitIdle() override;
|
||||
|
||||
// Resources:
|
||||
|
|
|
@ -451,6 +451,19 @@ int ShaderVulkan::BindDescriptorSetTextures(int setNumber, std::initializer_list
|
|||
return complexSetID;
|
||||
}
|
||||
|
||||
void ShaderVulkan::FreeDescriptorSet(int complexSetID)
|
||||
{
|
||||
VERUS_QREF_RENDERER_VULKAN;
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
if (complexSetID >= 0 && complexSetID < _vComplexDescriptorSets.size() && _vComplexDescriptorSets[complexSetID] != VK_NULL_HANDLE)
|
||||
{
|
||||
if (VK_SUCCESS != (res = vkFreeDescriptorSets(pRendererVulkan->GetVkDevice(), _descriptorPool, 1, &_vComplexDescriptorSets[complexSetID])))
|
||||
throw VERUS_RUNTIME_ERROR << "vkFreeDescriptorSets(), res=" << res;
|
||||
_vComplexDescriptorSets[complexSetID] = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderVulkan::BeginBindDescriptors()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
@ -496,32 +509,26 @@ void ShaderVulkan::CreateDescriptorPool()
|
|||
|
||||
VkDescriptorPoolCreateInfo vkdpci = {};
|
||||
vkdpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
vkdpci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
vkdpci.poolSizeCount = 1;
|
||||
VkDescriptorPoolSize vkdps[4] = {};
|
||||
vkdps[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||
vkdps[0].descriptorCount = _poolComplexUniformBuffers + Utils::Cast32(_vDescriptorSetLayouts.size());
|
||||
vkdps[0] = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, _poolComplexUniformBuffers + Utils::Cast32(_vDescriptorSetLayouts.size()) };
|
||||
vkdpci.maxSets = vkdps[0].descriptorCount;
|
||||
int index = 1;
|
||||
if (_poolComplexImageSamplers > 0)
|
||||
{
|
||||
vkdps[index].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
vkdps[index].descriptorCount = _poolComplexImageSamplers;
|
||||
vkdps[index++] = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, _poolComplexImageSamplers };
|
||||
vkdpci.poolSizeCount++;
|
||||
index++;
|
||||
}
|
||||
if (_poolComplexStorageImages > 0)
|
||||
{
|
||||
vkdps[index].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
vkdps[index].descriptorCount = _poolComplexStorageImages;
|
||||
vkdps[index++] = { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, _poolComplexStorageImages };
|
||||
vkdpci.poolSizeCount++;
|
||||
index++;
|
||||
}
|
||||
if (_poolComplexInputAttachments > 0)
|
||||
{
|
||||
vkdps[index].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||
vkdps[index].descriptorCount = _poolComplexInputAttachments;
|
||||
vkdps[index++] = { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, _poolComplexInputAttachments };
|
||||
vkdpci.poolSizeCount++;
|
||||
index++;
|
||||
}
|
||||
vkdpci.pPoolSizes = vkdps;
|
||||
if (VK_SUCCESS != (res = vkCreateDescriptorPool(pRendererVulkan->GetVkDevice(), &vkdpci, pRendererVulkan->GetAllocator(), &_descriptorPool)))
|
||||
|
|
|
@ -37,10 +37,10 @@ namespace verus
|
|||
VkDescriptorPool _descriptorPool = VK_NULL_HANDLE;
|
||||
VkPipelineLayout _pipelineLayout = VK_NULL_HANDLE;
|
||||
UINT64 _currentFrame = UINT64_MAX;
|
||||
int _poolComplexUniformBuffers = 0;
|
||||
int _poolComplexImageSamplers = 0;
|
||||
int _poolComplexStorageImages = 0;
|
||||
int _poolComplexInputAttachments = 0;
|
||||
uint32_t _poolComplexUniformBuffers = 0;
|
||||
uint32_t _poolComplexImageSamplers = 0;
|
||||
uint32_t _poolComplexStorageImages = 0;
|
||||
uint32_t _poolComplexInputAttachments = 0;
|
||||
bool _compute = false;
|
||||
|
||||
public:
|
||||
|
@ -53,6 +53,7 @@ namespace verus
|
|||
virtual void CreateDescriptorSet(int setNumber, const void* pSrc, int size, int capacity, std::initializer_list<Sampler> il, ShaderStageFlags stageFlags) override;
|
||||
virtual void CreatePipelineLayout() override;
|
||||
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips) override;
|
||||
virtual void FreeDescriptorSet(int complexSetID) override;
|
||||
|
||||
virtual void BeginBindDescriptors() override;
|
||||
virtual void EndBindDescriptors() override;
|
||||
|
|
|
@ -101,9 +101,9 @@ void TextureVulkan::Init(RcTextureDesc desc)
|
|||
if (renderTarget)
|
||||
{
|
||||
CommandBufferVulkan commandBuffer;
|
||||
commandBuffer.InitSingleTimeCommands();
|
||||
commandBuffer.InitOneTimeSubmit();
|
||||
commandBuffer.PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::undefined, ImageLayout::fsReadOnly, 0, 0);
|
||||
commandBuffer.DoneSingleTimeCommands();
|
||||
commandBuffer.DoneOneTimeSubmit();
|
||||
}
|
||||
if (depthFormat)
|
||||
{
|
||||
|
@ -111,9 +111,9 @@ void TextureVulkan::Init(RcTextureDesc desc)
|
|||
ImageLayout::depthStencilReadOnly :
|
||||
ImageLayout::depthStencilAttachment;
|
||||
CommandBufferVulkan commandBuffer;
|
||||
commandBuffer.InitSingleTimeCommands();
|
||||
commandBuffer.InitOneTimeSubmit();
|
||||
commandBuffer.PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::undefined, layout, 0, 0);
|
||||
commandBuffer.DoneSingleTimeCommands();
|
||||
commandBuffer.DoneOneTimeSubmit();
|
||||
}
|
||||
|
||||
_vStagingBuffers.reserve(_desc._mipLevels * _desc._arrayLayers);
|
||||
|
@ -328,7 +328,7 @@ void TextureVulkan::CreateSampler()
|
|||
}
|
||||
}
|
||||
vksci.mipLodBias = _desc._pSamplerDesc->_mipLodBias;
|
||||
vksci.maxAnisotropy = settings._gpuAnisotropyLevel;
|
||||
vksci.maxAnisotropy = static_cast<float>(settings._gpuAnisotropyLevel);
|
||||
vksci.minLod = _desc._pSamplerDesc->_minLod;
|
||||
vksci.maxLod = _desc._pSamplerDesc->_maxLod;
|
||||
if (_desc._pSamplerDesc->_borderColor.getX() < 0.5f)
|
||||
|
|
|
@ -24,7 +24,7 @@ extern "C"
|
|||
|
||||
if (VERUS_SDK_VERSION != version)
|
||||
{
|
||||
VERUS_RT_FAIL("VerusCreateRenderer(), Wrong version");
|
||||
VERUS_RT_FAIL("VerusCreateRenderer(), Wrong version.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IncludePath>C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\bullet3-2.88\src;C:\Home\Middleware\bullet3-2.88\Extras;C:\Home\Middleware\libogg-1.3.3\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\SDL2-2.0.9\include;C:\Program Files %28x86%29\OpenAL 1.1 SDK\include;C:\VulkanSDK\1.1.126.0\Include;C:\VulkanSDK\1.1.126.0\glslang;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Home\Middleware\bullet3-2.88\bin;C:\Home\Middleware\libogg-1.3.3\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\SDL2-2.0.9\lib\x64;C:\Program Files %28x86%29\OpenAL 1.1 SDK\libs\Win64;C:\VulkanSDK\1.1.126.0\Lib;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.88\src;C:\Home\Middleware\bullet3-2.88\Extras;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\SDL2-2.0.10\include;C:\Program Files %28x86%29\OpenAL 1.1 SDK\include;C:\VulkanSDK\1.1.126.0\Include;C:\VulkanSDK\1.1.126.0\glslang;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Home\Middleware\bullet3-2.88\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\SDL2-2.0.10\lib\x64;C:\Program Files %28x86%29\OpenAL 1.1 SDK\libs\Win64;C:\VulkanSDK\1.1.126.0\Lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup />
|
||||
<ItemGroup />
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<ProjectGuid>{B154D670-E4B1-4D8A-885C-69546A5BD833}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>Verus</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
|
@ -126,6 +126,8 @@
|
|||
<ClInclude Include="src\D\Log.h" />
|
||||
<ClInclude Include="src\D\Recoverable.h" />
|
||||
<ClInclude Include="src\D\RuntimeError.h" />
|
||||
<ClInclude Include="src\Extra\Extra.h" />
|
||||
<ClInclude Include="src\Extra\FileParser.h" />
|
||||
<ClInclude Include="src\Game\BaseGame.h" />
|
||||
<ClInclude Include="src\Game\Spirit.h" />
|
||||
<ClInclude Include="src\Game\Game.h" />
|
||||
|
@ -153,6 +155,7 @@
|
|||
<ClInclude Include="src\Global\Utils.h" />
|
||||
<ClInclude Include="src\Input\Input.h" />
|
||||
<ClInclude Include="src\Input\KeyMapper.h" />
|
||||
<ClInclude Include="src\Input\DragController.h" />
|
||||
<ClInclude Include="src\IO\Async.h" />
|
||||
<ClInclude Include="src\IO\DDSHeader.h" />
|
||||
<ClInclude Include="src\IO\File.h" />
|
||||
|
@ -186,12 +189,16 @@
|
|||
<ClInclude Include="src\Net\Net.h" />
|
||||
<ClInclude Include="src\Net\Socket.h" />
|
||||
<ClInclude Include="src\Physics\Bullet.h" />
|
||||
<ClInclude Include="src\Physics\BulletDebugDraw.h" />
|
||||
<ClInclude Include="src\Physics\CharacterController.h" />
|
||||
<ClInclude Include="src\Physics\Groups.h" />
|
||||
<ClInclude Include="src\Physics\KinematicCharacterController.h" />
|
||||
<ClInclude Include="src\Physics\Physics.h" />
|
||||
<ClInclude Include="src\Physics\UserPtr.h" />
|
||||
<ClInclude Include="src\Scene\Atmosphere.h" />
|
||||
<ClInclude Include="src\Scene\BaseMesh.h" />
|
||||
<ClInclude Include="src\Scene\Camera.h" />
|
||||
<ClInclude Include="src\Scene\CameraOrbit.h" />
|
||||
<ClInclude Include="src\Scene\EditorTerrain.h" />
|
||||
<ClInclude Include="src\Scene\Helpers.h" />
|
||||
<ClInclude Include="src\Scene\MaterialManager.h" />
|
||||
|
@ -213,6 +220,7 @@
|
|||
<ClInclude Include="src\ThirdParty\libb64\cdecode.h" />
|
||||
<ClInclude Include="src\ThirdParty\libb64\cencode.h" />
|
||||
<ClInclude Include="src\ThirdParty\md5.h" />
|
||||
<ClInclude Include="src\ThirdParty\nativefiledialog\nfd.h" />
|
||||
<ClInclude Include="src\ThirdParty\pugixml-1.10\pugiconfig.hpp" />
|
||||
<ClInclude Include="src\ThirdParty\pugixml-1.10\pugixml.hpp" />
|
||||
<ClInclude Include="src\ThirdParty\ThirdParty.h" />
|
||||
|
@ -263,6 +271,8 @@
|
|||
<ClCompile Include="src\CGI\RendererParser.cpp" />
|
||||
<ClCompile Include="src\CGI\RenderPass.cpp" />
|
||||
<ClCompile Include="src\D\Log.cpp" />
|
||||
<ClCompile Include="src\Extra\Extra.cpp" />
|
||||
<ClCompile Include="src\Extra\FileParser.cpp" />
|
||||
<ClCompile Include="src\Game\BaseGame.cpp" />
|
||||
<ClCompile Include="src\Game\Spirit.cpp" />
|
||||
<ClCompile Include="src\Game\State.cpp" />
|
||||
|
@ -279,6 +289,7 @@
|
|||
<ClCompile Include="src\Global\Utils.cpp" />
|
||||
<ClCompile Include="src\Input\Input.cpp" />
|
||||
<ClCompile Include="src\Input\KeyMapper.cpp" />
|
||||
<ClCompile Include="src\Input\DragController.cpp" />
|
||||
<ClCompile Include="src\IO\Async.cpp" />
|
||||
<ClCompile Include="src\IO\DDSHeader.cpp" />
|
||||
<ClCompile Include="src\IO\File.cpp" />
|
||||
|
@ -304,10 +315,17 @@
|
|||
<ClCompile Include="src\Net\Net.cpp" />
|
||||
<ClCompile Include="src\Net\Socket.cpp" />
|
||||
<ClCompile Include="src\Physics\Bullet.cpp" />
|
||||
<ClCompile Include="src\Physics\BulletDebugDraw.cpp" />
|
||||
<ClCompile Include="src\Physics\CharacterController.cpp" />
|
||||
<ClCompile Include="src\Physics\KinematicCharacterController.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Physics\Physics.cpp" />
|
||||
<ClCompile Include="src\Scene\Atmosphere.cpp" />
|
||||
<ClCompile Include="src\Scene\BaseMesh.cpp" />
|
||||
<ClCompile Include="src\Scene\Camera.cpp" />
|
||||
<ClCompile Include="src\Scene\CameraOrbit.cpp" />
|
||||
<ClCompile Include="src\Scene\EditorTerrain.cpp" />
|
||||
<ClCompile Include="src\Scene\Helpers.cpp" />
|
||||
<ClCompile Include="src\Scene\MaterialManager.cpp" />
|
||||
|
@ -316,6 +334,10 @@
|
|||
<ClCompile Include="src\Scene\SceneManager.cpp" />
|
||||
<ClCompile Include="src\Scene\ShadowMap.cpp" />
|
||||
<ClCompile Include="src\Scene\Terrain.cpp" />
|
||||
<ClCompile Include="src\ThirdParty\fast_atof.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ThirdParty\imgui\imgui.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
|
@ -356,6 +378,14 @@
|
|||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ThirdParty\nativefiledialog\nfd_common.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ThirdParty\nativefiledialog\nfd_win.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ThirdParty\pugixml-1.10\pugixml.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
|
|
|
@ -82,6 +82,12 @@
|
|||
<Filter Include="src\ThirdParty\imgui">
|
||||
<UniqueIdentifier>{3ee2005e-b456-4f4f-95cd-ad3ac11aaccb}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="src\ThirdParty\nativefiledialog">
|
||||
<UniqueIdentifier>{91530a5d-5ad0-4b0a-b2af-b48fa807a91d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="src\Extra">
|
||||
<UniqueIdentifier>{a3579964-dc6d-460a-82fb-b3b35746fcf1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\CGI\BaseGeometry.h">
|
||||
|
@ -516,6 +522,30 @@
|
|||
<ClInclude Include="src\ThirdParty\imgui\imgui_impl_sdl.h">
|
||||
<Filter>src\ThirdParty\imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Physics\BulletDebugDraw.h">
|
||||
<Filter>src\Physics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Physics\CharacterController.h">
|
||||
<Filter>src\Physics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Physics\KinematicCharacterController.h">
|
||||
<Filter>src\Physics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Scene\CameraOrbit.h">
|
||||
<Filter>src\Scene</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Input\DragController.h">
|
||||
<Filter>src\Input</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ThirdParty\nativefiledialog\nfd.h">
|
||||
<Filter>src\ThirdParty\nativefiledialog</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Extra\Extra.h">
|
||||
<Filter>src\Extra</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Extra\FileParser.h">
|
||||
<Filter>src\Extra</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\CGI\BaseGeometry.cpp">
|
||||
|
@ -839,6 +869,36 @@
|
|||
<ClCompile Include="src\ThirdParty\imgui\imgui_impl_sdl.cpp">
|
||||
<Filter>src\ThirdParty\imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Physics\BulletDebugDraw.cpp">
|
||||
<Filter>src\Physics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Physics\CharacterController.cpp">
|
||||
<Filter>src\Physics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Physics\KinematicCharacterController.cpp">
|
||||
<Filter>src\Physics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Scene\CameraOrbit.cpp">
|
||||
<Filter>src\Scene</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Input\DragController.cpp">
|
||||
<Filter>src\Input</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ThirdParty\nativefiledialog\nfd_win.cpp">
|
||||
<Filter>src\ThirdParty\nativefiledialog</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ThirdParty\nativefiledialog\nfd_common.c">
|
||||
<Filter>src\ThirdParty\nativefiledialog</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Extra\Extra.cpp">
|
||||
<Filter>src\Extra</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Extra\FileParser.cpp">
|
||||
<Filter>src\Extra</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ThirdParty\fast_atof.c">
|
||||
<Filter>src\ThirdParty</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\Lib.hlsl">
|
||||
|
|
|
@ -716,26 +716,26 @@ void Motion::Deserialize(IO::RStream stream)
|
|||
UINT32 magic = 0;
|
||||
stream >> magic;
|
||||
if ('2NAX' != magic)
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), Invalid XAN format";
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), invalid XAN format";
|
||||
|
||||
UINT16 version = 0;
|
||||
stream >> version;
|
||||
if (s_xanVersion != version)
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), Invalid XAN version";
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), invalid XAN version";
|
||||
|
||||
stream >> _numFrames;
|
||||
stream >> _fps;
|
||||
if (_numFrames < 0 || _numFrames > s_maxNumFrames)
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), Invalid number of frames in XAN";
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), invalid number of frames in XAN";
|
||||
if (_fps <= 0 || _fps > s_maxFps)
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), Invalid FPS in XAN";
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), invalid FPS in XAN";
|
||||
|
||||
SetFps(_fps);
|
||||
|
||||
int numBones = 0;
|
||||
stream >> numBones;
|
||||
if (numBones < 0 || numBones > s_maxNumBones)
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), Invalid number of bones in XAN";
|
||||
throw VERUS_RECOVERABLE << "Deserialize(), invalid number of bones in XAN";
|
||||
|
||||
char buffer[IO::Stream::s_bufferSize] = {};
|
||||
VERUS_FOR(i, numBones)
|
||||
|
|
|
@ -295,20 +295,6 @@ void Skeleton::RecursiveBoneUpdate()
|
|||
pCurrentBone->_ready = true;
|
||||
}
|
||||
|
||||
void Skeleton::VisitBones(std::function<Continue(RBone)> fn)
|
||||
{
|
||||
for (auto& kv : _mapBones)
|
||||
if (Continue::yes != fn(kv.second))
|
||||
return;
|
||||
}
|
||||
|
||||
void Skeleton::VisitBones(std::function<Continue(RcBone)> fn) const
|
||||
{
|
||||
for (const auto& kv : _mapBones)
|
||||
if (Continue::yes != fn(kv.second))
|
||||
return;
|
||||
}
|
||||
|
||||
void Skeleton::InsertBonesIntoMotion(RMotion motion) const
|
||||
{
|
||||
for (const auto& kv : _mapBones)
|
||||
|
|
|
@ -111,8 +111,20 @@ namespace verus
|
|||
|
||||
int GetNumBones() const { return _numPrimaryBones ? _numPrimaryBones : Utils::Cast32(_mapBones.size()); }
|
||||
|
||||
void VisitBones(std::function<Continue(RBone)> fn);
|
||||
void VisitBones(std::function<Continue(RcBone)> fn) const;
|
||||
template<typename F>
|
||||
void VisitBones(const F& fn)
|
||||
{
|
||||
for (auto& kv : _mapBones)
|
||||
if (Continue::yes != fn(kv.second))
|
||||
return;
|
||||
}
|
||||
template<typename F>
|
||||
void VisitBones(const F& fn) const
|
||||
{
|
||||
for (const auto& kv : _mapBones)
|
||||
if (Continue::yes != fn(kv.second))
|
||||
return;
|
||||
}
|
||||
|
||||
//! Adds skeleton's bones to motion object (Motion).
|
||||
void InsertBonesIntoMotion(RMotion motion) const;
|
||||
|
|
|
@ -82,6 +82,7 @@ namespace verus
|
|||
String _uiLang = "EN";
|
||||
CommandLine _commandLine;
|
||||
Limits _limits;
|
||||
String _imguiFont;
|
||||
|
||||
Settings();
|
||||
~Settings();
|
||||
|
|
|
@ -33,9 +33,11 @@ void Window::Init(RcDesc descConst)
|
|||
if (desc._useSettings)
|
||||
desc.ApplySettings();
|
||||
|
||||
Uint32 flags = 0;
|
||||
Uint32 flags = desc._flags;
|
||||
if (desc._fullscreen)
|
||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
if (desc._resizable)
|
||||
flags |= SDL_WINDOW_RESIZABLE;
|
||||
if (0 == settings._gapi)
|
||||
flags |= SDL_WINDOW_VULKAN;
|
||||
|
||||
|
|
|
@ -11,11 +11,13 @@ namespace verus
|
|||
public:
|
||||
struct Desc
|
||||
{
|
||||
CSZ _title = nullptr;
|
||||
int _width = 0;
|
||||
int _height = 0;
|
||||
bool _fullscreen = false;
|
||||
bool _useSettings = true;
|
||||
CSZ _title = nullptr;
|
||||
int _width = 0;
|
||||
int _height = 0;
|
||||
Uint32 _flags = 0;
|
||||
bool _fullscreen = false;
|
||||
bool _resizable = false;
|
||||
bool _useSettings = true;
|
||||
|
||||
void ApplySettings();
|
||||
};
|
||||
|
@ -27,7 +29,7 @@ namespace verus
|
|||
void Init(RcDesc desc = Desc());
|
||||
void Done();
|
||||
|
||||
SDL_Window* GetSDL() { return _pWnd; }
|
||||
SDL_Window* GetSDL() const { return _pWnd; }
|
||||
};
|
||||
VERUS_TYPEDEFS(Window);
|
||||
}
|
||||
|
|
|
@ -274,7 +274,7 @@ void StreamPlayer::ThreadProc()
|
|||
}
|
||||
catch (D::RcRuntimeError e)
|
||||
{
|
||||
//Utils::CLog::Error(e.what(), e.GetThreadID(), e.GetFile(), e.GetLine());
|
||||
D::Log::I().Write(e.what(), e.GetThreadID(), e.GetFile(), e.GetLine(), D::Log::Severity::error);
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
|
|
|
@ -10,17 +10,17 @@ namespace verus
|
|||
{
|
||||
PcInputElementDesc _pInputElementDesc;
|
||||
const int* _pStrides = nullptr;
|
||||
UINT32 _dynBindingsMask = 0;
|
||||
bool _32BitIndices = false;
|
||||
bool _dynamic = false;
|
||||
};
|
||||
VERUS_TYPEDEFS(GeometryDesc);
|
||||
|
||||
class BaseGeometry : public Object
|
||||
{
|
||||
protected:
|
||||
int _bindingInstMask = 0;
|
||||
bool _32BitIndices = false;
|
||||
bool _dynamic = false;
|
||||
UINT32 _instBindingsMask = 0;
|
||||
UINT32 _dynBindingsMask = 0;
|
||||
bool _32BitIndices = false;
|
||||
|
||||
BaseGeometry() = default;
|
||||
virtual ~BaseGeometry() = default;
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace verus
|
|||
bool _primitiveRestartEnable = false; // Special index value is 0xFFFFFFFF for 32-bit and 0xFFFF for 16-bit indices.
|
||||
bool _compute = false; // Compute pipeline, use PipelineDesc(ShaderPtr, CSZ) to set this to true.
|
||||
|
||||
// What to draw (geo)? How to draw (shader)? Where to draw (render pass)?
|
||||
PipelineDesc(GeometryPtr geo, ShaderPtr shader, CSZ branch, int renderPassID, int subpass = 0) :
|
||||
_geometry(geo), _shader(shader), _shaderBranch(branch), _renderPassID(renderPassID), _subpass(subpass)
|
||||
{
|
||||
|
|
|
@ -67,7 +67,7 @@ void BaseRenderer::SetAlphaBlendHelper(
|
|||
{
|
||||
case 0: break;
|
||||
case 1: colorBlendOp = BLENDOP_REVSUBTRACT; break;
|
||||
default: VERUS_RT_FAIL("FAIL: color s/d not found.");
|
||||
default: VERUS_RT_FAIL("Color s/d not found.");
|
||||
}
|
||||
srcColorBlendFactor = RendererParser::ExpectBlendOp(p);
|
||||
p += VERUS_LITERAL_LENGTH(")");
|
||||
|
@ -77,7 +77,7 @@ void BaseRenderer::SetAlphaBlendHelper(
|
|||
case 0: if (-1 == colorBlendOp) colorBlendOp = BLENDOP_ADD; break;
|
||||
case 1: if (-1 == colorBlendOp) colorBlendOp = BLENDOP_SUBTRACT; break;
|
||||
case 2: break;
|
||||
default: VERUS_RT_FAIL("FAIL: invalid color op.");
|
||||
default: VERUS_RT_FAIL("Invalid color op.");
|
||||
}
|
||||
p += VERUS_LITERAL_LENGTH("d*(");
|
||||
dstColorBlendFactor = RendererParser::ExpectBlendOp(p);
|
||||
|
@ -99,7 +99,7 @@ void BaseRenderer::SetAlphaBlendHelper(
|
|||
{
|
||||
case 0: break;
|
||||
case 1: alphaBlendOp = BLENDOP_REVSUBTRACT; break;
|
||||
default: VERUS_RT_FAIL("FAIL: alpha s/d not found.");
|
||||
default: VERUS_RT_FAIL("Alpha s/d not found.");
|
||||
}
|
||||
srcAlphaBlendFactor = RendererParser::ExpectBlendOp(p);
|
||||
p += VERUS_LITERAL_LENGTH(")");
|
||||
|
@ -108,7 +108,7 @@ void BaseRenderer::SetAlphaBlendHelper(
|
|||
case 0: if (-1 == alphaBlendOp) alphaBlendOp = BLENDOP_ADD; break;
|
||||
case 1: if (-1 == alphaBlendOp) alphaBlendOp = BLENDOP_SUBTRACT; break;
|
||||
case 2: break;
|
||||
default: VERUS_RT_FAIL("FAIL: invalid alpha op.");
|
||||
default: VERUS_RT_FAIL("Invalid alpha op.");
|
||||
}
|
||||
p += VERUS_LITERAL_LENGTH("d*(");
|
||||
dstAlphaBlendFactor = RendererParser::ExpectBlendOp(p);
|
||||
|
|
|
@ -25,10 +25,10 @@ namespace verus
|
|||
class BaseRenderer : public Object
|
||||
{
|
||||
protected:
|
||||
BaseRendererDesc _desc;
|
||||
UINT32 _numSwapChainBuffers = 0;
|
||||
UINT32 _swapChainBufferIndex = 0;
|
||||
UINT32 _ringBufferIndex = 0;
|
||||
BaseRendererDesc _desc;
|
||||
UINT32 _numSwapChainBuffers = 0;
|
||||
UINT32 _swapChainBufferIndex = 0;
|
||||
UINT32 _ringBufferIndex = 0;
|
||||
|
||||
BaseRenderer();
|
||||
virtual ~BaseRenderer();
|
||||
|
@ -37,7 +37,6 @@ namespace verus
|
|||
static const int s_ringBufferSize = 3;
|
||||
|
||||
static BaseRenderer* Load(CSZ dll, RBaseRendererDesc desc);
|
||||
|
||||
virtual void ReleaseMe() = 0;
|
||||
|
||||
void SetDesc(RBaseRendererDesc desc) { _desc = desc; }
|
||||
|
@ -49,6 +48,8 @@ namespace verus
|
|||
virtual void ImGuiInit(int renderPassID) = 0;
|
||||
virtual void ImGuiRenderDrawData() = 0;
|
||||
|
||||
virtual void ResizeSwapChain() = 0;
|
||||
|
||||
// Which graphics API?
|
||||
virtual Gapi GetGapi() = 0;
|
||||
|
||||
|
@ -56,7 +57,6 @@ namespace verus
|
|||
virtual void BeginFrame(bool present = true) = 0;
|
||||
virtual void EndFrame(bool present = true) = 0;
|
||||
virtual void Present() = 0;
|
||||
|
||||
virtual void WaitIdle() = 0;
|
||||
|
||||
// Resources:
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace verus
|
|||
int capacity = 1, std::initializer_list<Sampler> il = {}, ShaderStageFlags stageFlags = ShaderStageFlags::vs_fs) = 0;
|
||||
virtual void CreatePipelineLayout() = 0;
|
||||
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips = nullptr) = 0;
|
||||
virtual void FreeDescriptorSet(int complexSetID) = 0;
|
||||
|
||||
virtual void BeginBindDescriptors() = 0;
|
||||
virtual void EndBindDescriptors() = 0;
|
||||
|
|
|
@ -34,7 +34,7 @@ void DebugDraw::Init()
|
|||
geoDesc._pInputElementDesc = ied;
|
||||
const int strides[] = { sizeof(Vertex), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
geoDesc._dynamic = true;
|
||||
geoDesc._dynBindingsMask = 0x1;
|
||||
_geo.Init(geoDesc);
|
||||
_geo->CreateVertexBuffer(_maxNumVert, 0);
|
||||
|
||||
|
@ -44,7 +44,7 @@ void DebugDraw::Init()
|
|||
|
||||
{
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
|
||||
pipeDesc._rasterizationState._polygonMode = PolygonMode::line;
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
|
||||
pipeDesc._topology = PrimitiveTopology::pointList;
|
||||
_pipe[PIPE_POINTS].Init(pipeDesc);
|
||||
pipeDesc._depthTestEnable = false;
|
||||
|
@ -52,7 +52,7 @@ void DebugDraw::Init()
|
|||
}
|
||||
{
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
|
||||
pipeDesc._rasterizationState._polygonMode = PolygonMode::line;
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
|
||||
pipeDesc._topology = PrimitiveTopology::lineList;
|
||||
_pipe[PIPE_LINES].Init(pipeDesc);
|
||||
pipeDesc._depthTestEnable = false;
|
||||
|
@ -60,6 +60,7 @@ void DebugDraw::Init()
|
|||
}
|
||||
{
|
||||
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
|
||||
pipeDesc._rasterizationState._polygonMode = PolygonMode::line;
|
||||
pipeDesc._topology = PrimitiveTopology::triangleList;
|
||||
_pipe[PIPE_POLY].Init(pipeDesc);
|
||||
|
@ -114,11 +115,13 @@ void DebugDraw::Begin(Type type, PcTransform3 pMat, bool zEnable)
|
|||
|
||||
void DebugDraw::End()
|
||||
{
|
||||
if (!_numVert)
|
||||
return;
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
_geo->UpdateVertexBuffer(_vDynamicBuffer.data(), 0);
|
||||
renderer.GetCommandBuffer()->Draw(_numVert, 1, _offset);
|
||||
_offset = _numVert;
|
||||
_offset += _numVert;
|
||||
_numVert = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace verus
|
|||
PipelinePwns<PIPE_MAX> _pipe;
|
||||
Vector<Vertex> _vDynamicBuffer;
|
||||
UINT64 _currentFrame = UINT64_MAX;
|
||||
const int _maxNumVert = 4096;
|
||||
const int _maxNumVert = 0x10000;
|
||||
int _numVert = 0;
|
||||
int _offset = 0;
|
||||
int _peakLoad = 0;
|
||||
|
|
|
@ -103,100 +103,59 @@ void DeferredShading::Init()
|
|||
_pipe[PIPE_QUAD].Init(pipeDesc);
|
||||
}
|
||||
|
||||
InitGBuffers(settings._screenSizeWidth, settings._screenSizeHeight);
|
||||
|
||||
TextureDesc texDesc;
|
||||
|
||||
// Light accumulation buffers:
|
||||
texDesc._format = Format::unormR10G10B10A2;
|
||||
texDesc._width = settings._screenSizeWidth;
|
||||
texDesc._height = settings._screenSizeHeight;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment;
|
||||
_tex[TEX_LIGHT_ACC_DIFF].Init(texDesc);
|
||||
texDesc._format = Format::unormR10G10B10A2;
|
||||
texDesc._width = settings._screenSizeWidth;
|
||||
texDesc._height = settings._screenSizeHeight;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment;
|
||||
_tex[TEX_LIGHT_ACC_SPEC].Init(texDesc);
|
||||
|
||||
_fb = renderer->CreateFramebuffer(_rp,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_3],
|
||||
_tex[TEX_LIGHT_ACC_DIFF],
|
||||
_tex[TEX_LIGHT_ACC_SPEC],
|
||||
renderer.GetTexDepthStencil()
|
||||
},
|
||||
settings._screenSizeWidth,
|
||||
settings._screenSizeHeight);
|
||||
|
||||
_csidCompose = _shader[S_COMPOSE]->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_3],
|
||||
_tex[TEX_LIGHT_ACC_DIFF],
|
||||
_tex[TEX_LIGHT_ACC_SPEC]
|
||||
});
|
||||
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_csidQuad))
|
||||
_csidQuad[i] = renderer.GetShaderQuad()->BindDescriptorSetTextures(1, { _tex[TEX_GBUFFER_0 + i] });
|
||||
OnSwapChainResized(true, false);
|
||||
|
||||
VERUS_LOG_INFO("</DeferredShadingInit>");
|
||||
}
|
||||
|
||||
void DeferredShading::InitGBuffers(int w, int h)
|
||||
{
|
||||
_width = w;
|
||||
_height = h;
|
||||
|
||||
TextureDesc texDesc;
|
||||
|
||||
// GB0:
|
||||
texDesc._clearValue = Vector4(0, 0, 0, 1);
|
||||
texDesc._format = Format::srgbR8G8B8A8;
|
||||
texDesc._width = _width;
|
||||
texDesc._height = _height;
|
||||
texDesc._width = w;
|
||||
texDesc._height = h;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
|
||||
_tex[TEX_GBUFFER_0].Init(texDesc);
|
||||
|
||||
// GB1:
|
||||
texDesc._clearValue = Vector4(1);
|
||||
texDesc._format = Format::floatR32;
|
||||
texDesc._width = _width;
|
||||
texDesc._height = _height;
|
||||
texDesc._width = w;
|
||||
texDesc._height = h;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
|
||||
_tex[TEX_GBUFFER_1].Init(texDesc);
|
||||
|
||||
// GB2:
|
||||
texDesc._clearValue = Vector4(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
texDesc._clearValue = Vector4(0.5f, 0.5f, 0.25f, 0.5f);
|
||||
texDesc._format = Format::unormR10G10B10A2;
|
||||
texDesc._width = _width;
|
||||
texDesc._height = _height;
|
||||
texDesc._width = w;
|
||||
texDesc._height = h;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
|
||||
_tex[TEX_GBUFFER_2].Init(texDesc);
|
||||
|
||||
// GB3:
|
||||
texDesc._clearValue = Vector4(1, 1, 1, 1);
|
||||
texDesc._format = Format::unormR8G8B8A8;
|
||||
texDesc._width = _width;
|
||||
texDesc._height = _height;
|
||||
texDesc._width = w;
|
||||
texDesc._height = h;
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
|
||||
_tex[TEX_GBUFFER_3].Init(texDesc);
|
||||
}
|
||||
|
||||
void DeferredShading::InitByAtmosphere(TexturePtr texShadow)
|
||||
{
|
||||
_texShadowAtmo = texShadow;
|
||||
_csidLight = _shader[S_LIGHT]->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_3],
|
||||
texShadow,
|
||||
texShadow
|
||||
_texShadowAtmo,
|
||||
_texShadowAtmo
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -205,6 +164,76 @@ void DeferredShading::Done()
|
|||
VERUS_DONE(DeferredShading);
|
||||
}
|
||||
|
||||
void DeferredShading::OnSwapChainResized(bool init, bool done)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
if (done)
|
||||
{
|
||||
_shader[S_LIGHT]->FreeDescriptorSet(_csidLight);
|
||||
|
||||
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_csidQuad))
|
||||
renderer.GetShaderQuad()->FreeDescriptorSet(_csidQuad[i]);
|
||||
_shader[S_COMPOSE]->FreeDescriptorSet(_csidCompose);
|
||||
|
||||
renderer->DeleteFramebuffer(_fb);
|
||||
|
||||
_tex[TEX_LIGHT_ACC_SPEC].Done();
|
||||
_tex[TEX_LIGHT_ACC_DIFF].Done();
|
||||
_tex[TEX_GBUFFER_3].Done();
|
||||
_tex[TEX_GBUFFER_2].Done();
|
||||
_tex[TEX_GBUFFER_1].Done();
|
||||
_tex[TEX_GBUFFER_0].Done();
|
||||
}
|
||||
|
||||
if (init)
|
||||
{
|
||||
InitGBuffers(renderer.GetSwapChainWidth(), renderer.GetSwapChainHeight());
|
||||
|
||||
TextureDesc texDesc;
|
||||
|
||||
// Light accumulation buffers:
|
||||
texDesc._format = Format::unormR10G10B10A2;
|
||||
texDesc._width = renderer.GetSwapChainWidth();
|
||||
texDesc._height = renderer.GetSwapChainHeight();
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment;
|
||||
_tex[TEX_LIGHT_ACC_DIFF].Init(texDesc);
|
||||
texDesc._format = Format::unormR10G10B10A2;
|
||||
texDesc._width = renderer.GetSwapChainWidth();
|
||||
texDesc._height = renderer.GetSwapChainHeight();
|
||||
texDesc._flags = TextureDesc::Flags::colorAttachment;
|
||||
_tex[TEX_LIGHT_ACC_SPEC].Init(texDesc);
|
||||
|
||||
_fb = renderer->CreateFramebuffer(_rp,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_3],
|
||||
_tex[TEX_LIGHT_ACC_DIFF],
|
||||
_tex[TEX_LIGHT_ACC_SPEC],
|
||||
renderer.GetTexDepthStencil()
|
||||
},
|
||||
renderer.GetSwapChainWidth(),
|
||||
renderer.GetSwapChainHeight());
|
||||
|
||||
_csidCompose = _shader[S_COMPOSE]->BindDescriptorSetTextures(1,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0],
|
||||
_tex[TEX_GBUFFER_1],
|
||||
_tex[TEX_GBUFFER_2],
|
||||
_tex[TEX_GBUFFER_3],
|
||||
_tex[TEX_LIGHT_ACC_DIFF],
|
||||
_tex[TEX_LIGHT_ACC_SPEC]
|
||||
});
|
||||
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_csidQuad))
|
||||
_csidQuad[i] = renderer.GetShaderQuad()->BindDescriptorSetTextures(1, { _tex[TEX_GBUFFER_0 + i] });
|
||||
|
||||
if (_texShadowAtmo)
|
||||
InitByAtmosphere(_texShadowAtmo);
|
||||
}
|
||||
}
|
||||
|
||||
bool DeferredShading::IsLoaded()
|
||||
{
|
||||
VERUS_QREF_HELPERS;
|
||||
|
@ -308,6 +337,14 @@ void DeferredShading::EndGeometryPass(bool resetRT)
|
|||
|
||||
bool DeferredShading::BeginLightingPass()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_RT_ASSERT(renderer.GetNumFrames() == _frame);
|
||||
VERUS_RT_ASSERT(!_activeGeometryPass && !_activeLightingPass);
|
||||
_activeLightingPass = true;
|
||||
|
||||
renderer.GetCommandBuffer()->NextSubpass();
|
||||
_shader[S_LIGHT]->BeginBindDescriptors();
|
||||
|
||||
if (!IsLoaded())
|
||||
return false;
|
||||
|
||||
|
@ -348,15 +385,6 @@ bool DeferredShading::BeginLightingPass()
|
|||
}
|
||||
}
|
||||
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_RT_ASSERT(renderer.GetNumFrames() == _frame);
|
||||
VERUS_RT_ASSERT(!_activeGeometryPass && !_activeLightingPass);
|
||||
_activeLightingPass = true;
|
||||
|
||||
renderer.GetCommandBuffer()->NextSubpass();
|
||||
|
||||
_shader[S_LIGHT]->BeginBindDescriptors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -371,7 +399,7 @@ void DeferredShading::EndLightingPass()
|
|||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
}
|
||||
|
||||
void DeferredShading::Compose()
|
||||
void DeferredShading::Compose(RcVector4 bgColor)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
|
@ -383,6 +411,7 @@ void DeferredShading::Compose()
|
|||
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubComposeFS._matInvV = sm.GetCamera()->GetMatrixVi().UniformBufferFormat();
|
||||
s_ubComposeFS._colorAmbient = Vector4(0.1f, 0.1f, 0.2f, 1).GLM();
|
||||
s_ubComposeFS._colorBackground = bgColor.GLM();
|
||||
s_ubComposeFS._fogColor = Vector4(0.5f, 0.5f, 0.5f, 0.002f).GLM();
|
||||
s_ubComposeFS._zNearFarEx = sm.GetCamera()->GetZNearFarEx().GLM();
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_COMPOSE], 0);
|
||||
|
@ -432,13 +461,12 @@ void DeferredShading::OnNewLightType(LightType type, bool wireframe)
|
|||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_LIGHT], 1, _csidLight);
|
||||
|
||||
// Shadow:
|
||||
if (atmo.GetSunShadowTexture())
|
||||
s_ubShadowFS._shadowTexSize = atmo.GetSunShadowTexture()->GetSize().GLM();
|
||||
s_ubShadowFS._matSunShadow = atmo.GetSunShadowMatrixDS(0).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM1 = atmo.GetSunShadowMatrixDS(1).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM2 = atmo.GetSunShadowMatrixDS(2).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM3 = atmo.GetSunShadowMatrixDS(3).UniformBufferFormat();
|
||||
s_ubShadowFS._splitRanges = atmo.GetSunShadowSplitRanges().GLM();
|
||||
s_ubShadowFS._matSunShadow = atmo.GetShadowMap().GetShadowMatrixDS(0).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM1 = atmo.GetShadowMap().GetShadowMatrixDS(1).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM2 = atmo.GetShadowMap().GetShadowMatrixDS(2).UniformBufferFormat();
|
||||
s_ubShadowFS._matSunShadowCSM3 = atmo.GetShadowMap().GetShadowMatrixDS(3).UniformBufferFormat();
|
||||
s_ubShadowFS._shadowConfig = atmo.GetShadowMap().GetConfig().GLM();
|
||||
s_ubShadowFS._splitRanges = atmo.GetShadowMap().GetSplitRanges().GLM();
|
||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_LIGHT], 3);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,9 +56,8 @@ namespace verus
|
|||
ShaderPwns<S_MAX> _shader;
|
||||
PipelinePwns<PIPE_MAX> _pipe;
|
||||
TexturePwns<TEX_MAX> _tex;
|
||||
TexturePtr _texShadowAtmo;
|
||||
UINT64 _frame = 0;
|
||||
int _width = 0;
|
||||
int _height = 0;
|
||||
int _rp = -1;
|
||||
int _fb = -1;
|
||||
int _csidLight = -1;
|
||||
|
@ -77,13 +76,12 @@ namespace verus
|
|||
void InitByAtmosphere(TexturePtr texShadow);
|
||||
void Done();
|
||||
|
||||
void OnSwapChainResized(bool init, bool done);
|
||||
|
||||
static bool IsLoaded();
|
||||
|
||||
void Draw(int gbuffer);
|
||||
|
||||
int GetWidth() const { return _width; }
|
||||
int GetHeight() const { return _height; }
|
||||
|
||||
bool IsActiveGeometryPass() const { return _activeGeometryPass; }
|
||||
bool IsActiveLightingPass() const { return _activeLightingPass; }
|
||||
|
||||
|
@ -93,7 +91,7 @@ namespace verus
|
|||
void EndGeometryPass(bool resetRT = false);
|
||||
bool BeginLightingPass();
|
||||
void EndLightingPass();
|
||||
void Compose();
|
||||
void Compose(RcVector4 bgColor = Vector4(0));
|
||||
void AntiAliasing();
|
||||
|
||||
static bool IsLightUrl(CSZ url);
|
||||
|
|
|
@ -28,6 +28,9 @@ void Renderer::Init(PRendererDelegate pDelegate)
|
|||
VERUS_INIT();
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
_swapChainWidth = settings._screenSizeWidth;
|
||||
_swapChainHeight = settings._screenSizeHeight;
|
||||
|
||||
_pRendererDelegate = pDelegate;
|
||||
|
||||
CSZ dll = "RendererVulkan.dll";
|
||||
|
@ -73,13 +76,6 @@ void Renderer::Init(PRendererDelegate pDelegate)
|
|||
PipelineDesc pipeDesc(_shader[S_GENERATE_MIPS], "#");
|
||||
_pipeGenerateMips.Init(pipeDesc);
|
||||
|
||||
TextureDesc texDesc;
|
||||
texDesc._clearValue = Vector4(1);
|
||||
texDesc._format = Format::unormD24uintS8;
|
||||
texDesc._width = settings._screenSizeWidth;
|
||||
texDesc._height = settings._screenSizeHeight;
|
||||
_texDepthStencil.Init(texDesc);
|
||||
|
||||
_rpSwapChain = _pBaseRenderer->CreateRenderPass(
|
||||
{ RP::Attachment("Color", Format::srgbB8G8R8A8).LoadOpClear().Layout(ImageLayout::undefined, ImageLayout::presentSrc) },
|
||||
{ RP::Subpass("Sp0").Color({RP::Ref("Color", ImageLayout::colorAttachment)}) },
|
||||
|
@ -96,14 +92,11 @@ void Renderer::Init(PRendererDelegate pDelegate)
|
|||
}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilAttachment)),
|
||||
},
|
||||
{});
|
||||
_fbSwapChain.resize(_pBaseRenderer->GetNumSwapChainBuffers());
|
||||
VERUS_FOR(i, _fbSwapChain.size())
|
||||
_fbSwapChain[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChain, {}, settings._screenSizeWidth, settings._screenSizeHeight, i);
|
||||
_fbSwapChainDepth.resize(_pBaseRenderer->GetNumSwapChainBuffers());
|
||||
VERUS_FOR(i, _fbSwapChainDepth.size())
|
||||
_fbSwapChainDepth[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChainDepth, { _texDepthStencil }, settings._screenSizeWidth, settings._screenSizeHeight, i);
|
||||
|
||||
OnSwapChainResized(true, false);
|
||||
|
||||
_pBaseRenderer->ImGuiInit(_rpSwapChainDepth);
|
||||
ImGuiUpdateStyle();
|
||||
|
||||
_ds.Init();
|
||||
}
|
||||
|
@ -161,6 +154,48 @@ void Renderer::Present()
|
|||
_fps = _fps * 0.75f + timer.GetDeltaTimeInv() * 0.25f;
|
||||
}
|
||||
|
||||
void Renderer::OnWindowResized(int w, int h)
|
||||
{
|
||||
_pBaseRenderer->WaitIdle();
|
||||
|
||||
_swapChainWidth = w;
|
||||
_swapChainHeight = h;
|
||||
_pBaseRenderer->ResizeSwapChain();
|
||||
|
||||
OnSwapChainResized(true, true);
|
||||
_ds.OnSwapChainResized(true, true);
|
||||
}
|
||||
|
||||
void Renderer::OnSwapChainResized(bool init, bool done)
|
||||
{
|
||||
if (done)
|
||||
{
|
||||
VERUS_FOR(i, _fbSwapChainDepth.size())
|
||||
_pBaseRenderer->DeleteFramebuffer(_fbSwapChainDepth[i]);
|
||||
VERUS_FOR(i, _fbSwapChain.size())
|
||||
_pBaseRenderer->DeleteFramebuffer(_fbSwapChain[i]);
|
||||
|
||||
_texDepthStencil.Done();
|
||||
}
|
||||
|
||||
if (init)
|
||||
{
|
||||
TextureDesc texDesc;
|
||||
texDesc._clearValue = Vector4(1);
|
||||
texDesc._format = Format::unormD24uintS8;
|
||||
texDesc._width = _swapChainWidth;
|
||||
texDesc._height = _swapChainHeight;
|
||||
_texDepthStencil.Init(texDesc);
|
||||
|
||||
_fbSwapChain.resize(_pBaseRenderer->GetNumSwapChainBuffers());
|
||||
VERUS_FOR(i, _fbSwapChain.size())
|
||||
_fbSwapChain[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChain, {}, _swapChainWidth, _swapChainHeight, i);
|
||||
_fbSwapChainDepth.resize(_pBaseRenderer->GetNumSwapChainBuffers());
|
||||
VERUS_FOR(i, _fbSwapChainDepth.size())
|
||||
_fbSwapChainDepth[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChainDepth, { _texDepthStencil }, _swapChainWidth, _swapChainHeight, i);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::DrawQuad(PBaseCommandBuffer pCB)
|
||||
{
|
||||
if (!pCB)
|
||||
|
@ -182,10 +217,79 @@ void Renderer::OnShaderWarning(CSZ s)
|
|||
float Renderer::GetWindowAspectRatio() const
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
return static_cast<float>(settings._screenSizeWidth) / static_cast<float>(settings._screenSizeHeight);
|
||||
return static_cast<float>(_swapChainWidth) / static_cast<float>(_swapChainHeight);
|
||||
}
|
||||
|
||||
void Renderer::ImGuiSetCurrentContext(ImGuiContext* pContext)
|
||||
{
|
||||
ImGui::SetCurrentContext(pContext);
|
||||
}
|
||||
|
||||
void Renderer::ImGuiUpdateStyle()
|
||||
{
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
||||
style.WindowRounding = 4;
|
||||
style.WindowTitleAlign.x = 0.5f;
|
||||
style.ChildRounding = 2;
|
||||
style.PopupRounding = 2;
|
||||
style.FramePadding.y = 4;
|
||||
style.FrameRounding = 2;
|
||||
style.FrameBorderSize = 1;
|
||||
style.ScrollbarSize = 16;
|
||||
style.ScrollbarRounding = 2;
|
||||
style.GrabMinSize = 12;
|
||||
style.GrabRounding = 2;
|
||||
style.TabRounding = 0;
|
||||
style.TabBorderSize = 1;
|
||||
|
||||
ImVec4* colors = style.Colors;
|
||||
colors[ImGuiCol_Text] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f);
|
||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.99f);
|
||||
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.99f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
|
||||
colors[ImGuiCol_BorderShadow] = ImVec4(0.05f, 0.05f, 0.05f, 0.08f);
|
||||
colors[ImGuiCol_FrameBg] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.02f, 0.02f, 0.02f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgActive] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
|
||||
colors[ImGuiCol_TitleBg] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgActive] = ImVec4(0.19f, 0.03f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
|
||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.92f, 0.43f, 0.02f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.92f, 0.43f, 0.02f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.92f, 0.43f, 0.02f, 1.00f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
|
||||
colors[ImGuiCol_ButtonHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.13f);
|
||||
colors[ImGuiCol_ButtonActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.25f);
|
||||
colors[ImGuiCol_Header] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
|
||||
colors[ImGuiCol_HeaderHovered] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
|
||||
colors[ImGuiCol_HeaderActive] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
|
||||
colors[ImGuiCol_Separator] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorActive] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_Tab] = ImVec4(0.02f, 0.02f, 0.02f, 1.00f);
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.19f, 0.03f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
|
||||
colors[ImGuiCol_DragDropTarget] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_NavHighlight] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);
|
||||
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ namespace verus
|
|||
DeferredShading _ds;
|
||||
UINT64 _numFrames = 0;
|
||||
Gapi _gapi = Gapi::unknown;
|
||||
int _swapChainWidth = 0;
|
||||
int _swapChainHeight = 0;
|
||||
float _fps = 30;
|
||||
int _rpSwapChain = 0;
|
||||
int _rpSwapChainDepth = 0;
|
||||
|
@ -66,6 +68,11 @@ namespace verus
|
|||
void Draw();
|
||||
void Present();
|
||||
|
||||
void OnWindowResized(int w, int h);
|
||||
VERUS_P(void OnSwapChainResized(bool init, bool done));
|
||||
int GetSwapChainWidth() const { return _swapChainWidth; }
|
||||
int GetSwapChainHeight() const { return _swapChainHeight; }
|
||||
|
||||
// Simple (fullscreen) quad:
|
||||
void DrawQuad(PBaseCommandBuffer pCB = nullptr);
|
||||
|
||||
|
@ -82,6 +89,7 @@ namespace verus
|
|||
float GetWindowAspectRatio() const;
|
||||
|
||||
virtual void ImGuiSetCurrentContext(ImGuiContext* pContext);
|
||||
void ImGuiUpdateStyle();
|
||||
|
||||
// Frame rate:
|
||||
float GetFps() const { return _fps; }
|
||||
|
|
|
@ -16,7 +16,7 @@ int RendererParser::Expect(CSZ& p, CSZ* ppOptions)
|
|||
CSZ option = ppOptions[index];
|
||||
while (option)
|
||||
{
|
||||
size_t len = strlen(option);
|
||||
const size_t len = strlen(option);
|
||||
if (!strncmp(p, option, len))
|
||||
{
|
||||
p += len;
|
||||
|
|
|
@ -47,7 +47,6 @@ namespace verus
|
|||
float _depthBiasConstantFactor = 0;
|
||||
float _depthBiasClamp = 0;
|
||||
float _depthBiasSlopeFactor = 0;
|
||||
float _lineWidth = 1;
|
||||
bool _depthClampEnable = false;
|
||||
bool _depthBiasEnable = false;
|
||||
bool _rasterizerDiscardEnable = false;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#define VERUS_DEBUG
|
||||
|
||||
#include "AssertionRunTime.h"
|
||||
#include "AssertionCompileTime.h"
|
||||
#include "RuntimeError.h"
|
||||
|
|
|
@ -5,79 +5,14 @@ using namespace verus::D;
|
|||
|
||||
std::mutex D::Log::s_mutex;
|
||||
|
||||
void Log::Error(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_mutex);
|
||||
|
||||
const time_t t = time(0);
|
||||
const tm* pTM = localtime(&t);
|
||||
char timestamp[80];
|
||||
strftime(timestamp, sizeof(timestamp), "%Y.%m.%d %H:%M:%S", pTM);
|
||||
|
||||
CSZ p = strrchr(filename, '/');
|
||||
if (!p)
|
||||
p = strrchr(filename, '\\');
|
||||
filename = p ? p + 1 : filename;
|
||||
|
||||
String pathName;
|
||||
//if (Global::IsValidSingleton())
|
||||
//{
|
||||
// pathName = Global::I().GetWritablePath() + "/Errors.txt";
|
||||
//}
|
||||
//else
|
||||
{
|
||||
String temp = getenv("TEMP");
|
||||
pathName = temp + "/CorrErrors.txt";
|
||||
}
|
||||
|
||||
IO::File file;
|
||||
if (file.Open(_C(pathName), "a"))
|
||||
{
|
||||
if (file.GetSize() > 100 * 1024)
|
||||
{
|
||||
file.Close();
|
||||
file.Open(_C(pathName), "w");
|
||||
}
|
||||
StringStream ss;
|
||||
ss << timestamp << " " << tid << " " << filename << ":" << line << " ERROR: " << txt << "\n";
|
||||
file.Write(_C(ss.str()), ss.str().length());
|
||||
}
|
||||
}
|
||||
|
||||
void Log::Session(CSZ txt)
|
||||
{
|
||||
/*
|
||||
std::lock_guard<std::mutex> lock(s_mutex);
|
||||
|
||||
String pathName(Global::I().GetWritablePath());
|
||||
pathName += "/SessionLog.txt";
|
||||
IO::File file;
|
||||
if (file.Create(_C(pathName), "a"))
|
||||
{
|
||||
StringStream ss;
|
||||
ss.fill('0');
|
||||
ss << '[';
|
||||
ss.width(8);
|
||||
ss << SDL_GetTicks() << "ms] " << txt << "\n";
|
||||
file.Write(_C(ss.str()), ss.str().length());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Log::DebugString(CSZ txt)
|
||||
{
|
||||
/*
|
||||
StringStream ss;
|
||||
ss << verus::Global::GetNextCounterValue() << ": " << txt << "\n";
|
||||
|
||||
#ifdef _WIN32
|
||||
OutputDebugStringA(_C(ss.str()));
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
void Log::Write(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line, Severity severity)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (severity <= Severity::error)
|
||||
{
|
||||
SDL_TriggerBreakpoint();
|
||||
}
|
||||
#endif
|
||||
char timestamp[40];
|
||||
FormatTime(timestamp, sizeof(timestamp));
|
||||
CSZ severityLetter = GetSeverityLetter(severity);
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
//#define VERUS_LOG_ERROR(txt) {verus::D::Log::Error(txt, std::this_thread::get_id(), __FILE__, __LINE__);}
|
||||
//#define VERUS_LOG_ERROR_STREAM(txt) {StringStream ss; ss << txt; verus::D::Log::Error(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__);}
|
||||
//#define VERUS_LOG_SESSION(txt) {verus::D::Log::Session(txt);}
|
||||
//#define VERUS_LOG_SESSION_STREAM(txt) {StringStream ss; ss << txt; verus::D::Log::Session(_C(ss.str()));}
|
||||
//#ifdef _DEBUG
|
||||
//# define VERUS_LOG_DEBUG(x) {verus::D::Log::DebugString(x);}
|
||||
//#else
|
||||
//# define VERUS_LOG_DEBUG(x) {}
|
||||
//#endif
|
||||
|
||||
#define VERUS_LOG_ERROR(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::error);}
|
||||
#define VERUS_LOG_WARN(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::warning);}
|
||||
#define VERUS_LOG_INFO(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::info);}
|
||||
|
@ -34,10 +24,6 @@ namespace verus
|
|||
static std::mutex s_mutex;
|
||||
|
||||
public:
|
||||
static void Error(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line);
|
||||
static void Session(CSZ txt);
|
||||
static void DebugString(CSZ txt);
|
||||
|
||||
void Write(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line, Severity severity);
|
||||
|
||||
static void FormatTime(char* buffer, size_t size);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#include "verus.h"
|
||||
|
||||
namespace verus
|
||||
{
|
||||
void Make_Extra()
|
||||
{
|
||||
Extra::FileParser::Make();
|
||||
}
|
||||
void Free_Extra()
|
||||
{
|
||||
Extra::FileParser::Free();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "FileParser.h"
|
||||
|
||||
namespace verus
|
||||
{
|
||||
void Make_Extra();
|
||||
void Free_Extra();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,332 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace Extra
|
||||
{
|
||||
struct FileParserDelegate;
|
||||
|
||||
class FileParser : public Singleton<FileParser>, public Object
|
||||
{
|
||||
public:
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
enum class Found : int
|
||||
{
|
||||
null = 0,
|
||||
faces = (1 << 0),
|
||||
vertsAndUVs = (1 << 1),
|
||||
normals = (1 << 2),
|
||||
boneHierarchy = (1 << 3),
|
||||
skinning = (1 << 4),
|
||||
tangentSpace = (1 << 5),
|
||||
texcoordExtra = (1 << 6)
|
||||
};
|
||||
|
||||
struct UberVertex
|
||||
{
|
||||
glm::vec3 _pos;
|
||||
glm::vec3 _nrm;
|
||||
glm::vec2 _tc0;
|
||||
glm::vec2 _tc1;
|
||||
glm::vec3 _tan;
|
||||
glm::vec3 _bin;
|
||||
float _bw[4];
|
||||
UINT32 _bi[4];
|
||||
int _currentWeight = 0;
|
||||
|
||||
UberVertex();
|
||||
bool operator==(const UberVertex& that) const;
|
||||
void Add(float weight, UINT32 index);
|
||||
void CompileBits(UINT32& ww, UINT32& ii) const;
|
||||
UINT32 GetDominantIndex();
|
||||
};
|
||||
VERUS_TYPEDEFS(UberVertex);
|
||||
|
||||
struct Face
|
||||
{
|
||||
UINT16 _indices[3];
|
||||
};
|
||||
VERUS_TYPEDEFS(Face);
|
||||
|
||||
struct Bone
|
||||
{
|
||||
String _name;
|
||||
String _parentName;
|
||||
glm::mat4 _matOffset;
|
||||
glm::mat4 _matFrame;
|
||||
glm::mat4 _matFrameAcc;
|
||||
};
|
||||
VERUS_TYPEDEFS(Bone);
|
||||
|
||||
private:
|
||||
struct Vec3Short
|
||||
{
|
||||
short _x;
|
||||
short _y;
|
||||
short _z;
|
||||
};
|
||||
|
||||
struct Vec2Short
|
||||
{
|
||||
short _u;
|
||||
short _v;
|
||||
};
|
||||
|
||||
struct Vec3Char
|
||||
{
|
||||
char _x;
|
||||
char _y;
|
||||
char _z;
|
||||
};
|
||||
|
||||
struct Aabb
|
||||
{
|
||||
glm::vec3 _mn = glm::vec3(+FLT_MAX);
|
||||
glm::vec3 _mx = glm::vec3(-FLT_MAX);
|
||||
|
||||
void Reset();
|
||||
void Include(const glm::vec3& point);
|
||||
glm::vec3 GetExtents() const;
|
||||
};
|
||||
|
||||
String _name;
|
||||
String _copyOf;
|
||||
Vector<UberVertex> _vUberVerts;
|
||||
Vector<Face> _vFaces;
|
||||
Vector<Vec3Short> _vZipPos;
|
||||
Vector<Vec3Char> _vZipNormal;
|
||||
Vector<Vec3Char> _vZipTan;
|
||||
Vector<Vec3Char> _vZipBin;
|
||||
Vector<Vec2Short> _vZipTc0;
|
||||
Vector<Vec2Short> _vZipTc1;
|
||||
Vector<Bone> _vBones;
|
||||
int _numVerts = 0;
|
||||
int _numFaces = 0;
|
||||
int _numBones = 0;
|
||||
glm::vec3 _posScale;
|
||||
glm::vec3 _posBias;
|
||||
glm::vec2 _tc0Scale;
|
||||
glm::vec2 _tc0Bias;
|
||||
glm::vec2 _tc1Scale;
|
||||
glm::vec2 _tc1Bias;
|
||||
glm::mat4 _matBoneAxis;
|
||||
glm::mat4 _matCombined;
|
||||
glm::mat4 _worldSpace;
|
||||
Found _found = Found::null;
|
||||
int _materialIndex = 0;
|
||||
|
||||
public:
|
||||
Mesh();
|
||||
~Mesh();
|
||||
|
||||
PBone FindBone(CSZ name);
|
||||
|
||||
VERUS_P(void Optimize());
|
||||
VERUS_P(void ComputeTangentSpace());
|
||||
VERUS_P(void Compress());
|
||||
void SerializeX3D3(IO::RFile file);
|
||||
|
||||
RcString GetName() const { return _name; }
|
||||
void SetName(CSZ name) { _name = name; }
|
||||
|
||||
const glm::mat4& GetBoneAxisMatrix() const { return _matBoneAxis; }
|
||||
|
||||
const glm::mat4& GetCombinedMatrix() const { return _matCombined; }
|
||||
void SetCombinedMatrix(const glm::mat4& mat) { _matCombined = mat; }
|
||||
|
||||
const glm::mat4& GetWorldSpaceMatrix() const { return _worldSpace; }
|
||||
void SetWorldSpaceMatrix(const glm::mat4& mat) { _worldSpace = mat; }
|
||||
|
||||
int GetNumVerts() const { return _numVerts; }
|
||||
int GetNumFaces() const { return _numFaces; }
|
||||
int GetNumBones() const { return _numBones; }
|
||||
void SetNumVerts(int num) { _numVerts = num; }
|
||||
void SetNumFaces(int num) { _numFaces = num; }
|
||||
void SetNumBones(int num) { _numBones = num; }
|
||||
|
||||
void ResizeVertsArray(int size) { _vUberVerts.resize(size); }
|
||||
void ResizeFacesArray(int size) { _vFaces.resize(size); }
|
||||
|
||||
RUberVertex GetSetVertexAt(int index) { return _vUberVerts[index]; }
|
||||
RFace GetSetFaceAt(int index) { return _vFaces[index]; }
|
||||
|
||||
void AddFoundFlag(Found flag) { _found |= flag; }
|
||||
|
||||
int GetNextBoneIndex() const { return _vBones.size(); }
|
||||
void AddBone(RcBone bone) { _vBones.push_back(bone); }
|
||||
|
||||
bool IsCopyOf(Mesh& that);
|
||||
bool IsCopy() const { return !_copyOf.empty(); }
|
||||
RcString GetCopyOfName() const { return _copyOf; }
|
||||
|
||||
int GetMaterialIndex() const { return _materialIndex; }
|
||||
void SetMaterialIndex(int index) { _materialIndex = index; }
|
||||
};
|
||||
VERUS_TYPEDEFS(Mesh);
|
||||
|
||||
struct Desc
|
||||
{
|
||||
glm::vec3 _bias = glm::vec3(0);
|
||||
float _scaleFactor = 1;
|
||||
float _angle = 0;
|
||||
float _areaBasedNormals = 0;
|
||||
bool _useRigidBones = false;
|
||||
bool _convertAsLevel = false;
|
||||
bool _useDefaultMaterial = false;
|
||||
bool _rightHanded = true;
|
||||
};
|
||||
VERUS_TYPEDEFS(Desc);
|
||||
|
||||
private:
|
||||
struct Frame
|
||||
{
|
||||
String _name;
|
||||
String _parent;
|
||||
glm::mat4 _mat;
|
||||
glm::mat4 _matAcc;
|
||||
};
|
||||
VERUS_TYPEDEFS(Frame);
|
||||
|
||||
struct SubKey
|
||||
{
|
||||
Quat _q;
|
||||
bool _redundant = false;
|
||||
};
|
||||
|
||||
struct AnimationKey
|
||||
{
|
||||
Vector<SubKey> _vFrame;
|
||||
int _type = 0;
|
||||
int _numLogicFrames = 0;
|
||||
|
||||
void DetectRedundantFrames(float threshold = 0.001f);
|
||||
};
|
||||
|
||||
struct Animation
|
||||
{
|
||||
String _name;
|
||||
Vector<AnimationKey> _vAnimKeys;
|
||||
};
|
||||
|
||||
struct AnimationSet
|
||||
{
|
||||
String _name;
|
||||
Vector<Animation> _vAnimations;
|
||||
|
||||
void CleanUp();
|
||||
};
|
||||
|
||||
struct Material
|
||||
{
|
||||
String _name;
|
||||
String _copyOf;
|
||||
String _textureFilename;
|
||||
glm::vec4 _faceColor;
|
||||
glm::vec3 _specularColor;
|
||||
glm::vec3 _emissiveColor;
|
||||
float _power = 1;
|
||||
|
||||
bool IsCopyOf(const Material& that)
|
||||
{
|
||||
const float e = 0.01f;
|
||||
return
|
||||
_textureFilename == that._textureFilename &&
|
||||
glm::all(glm::epsilonEqual(_faceColor, that._faceColor, e)) &&
|
||||
glm::all(glm::epsilonEqual(_specularColor, that._specularColor, e)) &&
|
||||
glm::all(glm::epsilonEqual(_emissiveColor, that._emissiveColor, e)) &&
|
||||
glm::epsilonEqual(_power, that._power, e);
|
||||
}
|
||||
};
|
||||
VERUS_TYPEDEFS(Material);
|
||||
|
||||
typedef Map<String, String> TMapBoneNames;
|
||||
typedef Map<String, Frame> TMapFrames;
|
||||
|
||||
Transform3 _matRoot;
|
||||
TMapBoneNames _mapBoneNames;
|
||||
String _currentMesh;
|
||||
String _pathName;
|
||||
Vector<char> _vData;
|
||||
const char* _pData;
|
||||
const char* _pDataBegin;
|
||||
Vector<PMesh> _vMesh;
|
||||
std::unique_ptr<Mesh> _pCurrentMesh;
|
||||
TMapFrames _mapFrames;
|
||||
Vector<Frame> _stackFrames;
|
||||
Vector<AnimationSet> _vAnimSets;
|
||||
Vector<Material> _vMaterials;
|
||||
FileParserDelegate* _pDelegate;
|
||||
std::future<void> _future;
|
||||
Desc _desc;
|
||||
int _depth = 0;
|
||||
StringStream _ssDebug;
|
||||
|
||||
public:
|
||||
FileParser();
|
||||
~FileParser();
|
||||
|
||||
void Init(FileParserDelegate* p, RcDesc desc);
|
||||
void Done();
|
||||
|
||||
void LoadBoneNames(CSZ pathName);
|
||||
void ParseData(CSZ pathName);
|
||||
void SerializeAll(CSZ pathName);
|
||||
|
||||
void AsyncRun(CSZ pathName);
|
||||
void AsyncJoin();
|
||||
bool IsAsyncStarted() const;
|
||||
bool IsAsyncFinished() const;
|
||||
|
||||
private:
|
||||
void LoadFromFile(CSZ pathName);
|
||||
|
||||
void StreamReadUntil(SZ dest, int destSize, CSZ separator);
|
||||
void StreamSkipWhitespace();
|
||||
void StreamSkipUntil(char c);
|
||||
|
||||
void FixBones();
|
||||
|
||||
void ParseBlockRecursive(CSZ type, CSZ blockName);
|
||||
void ParseBlockData_Mesh();
|
||||
void ParseBlockData_MeshTextureCoords();
|
||||
void ParseBlockData_MeshNormals();
|
||||
void ParseBlockData_FVFData(bool declData);
|
||||
void ParseBlockData_XSkinMeshHeader();
|
||||
void ParseBlockData_SkinWeights();
|
||||
void ParseBlockData_Frame(CSZ blockName);
|
||||
void ParseBlockData_FrameTransformMatrix();
|
||||
void ParseBlockData_AnimationSet(CSZ blockName);
|
||||
void ParseBlockData_Animation(CSZ blockName);
|
||||
void ParseBlockData_AnimationKey();
|
||||
void ParseBlockData_Material();
|
||||
void ParseBlockData_TextureFilename();
|
||||
void ParseBlockData_MeshMaterialList();
|
||||
|
||||
PMesh AddMesh(PMesh pMesh);
|
||||
PMesh FindMesh(CSZ name);
|
||||
void DeleteAll();
|
||||
|
||||
void OnProgress(float percent);
|
||||
void OnProgressText(CSZ txt);
|
||||
|
||||
void Debug(CSZ txt);
|
||||
|
||||
void DetectMaterialCopies();
|
||||
String GetXmlMaterial(int i);
|
||||
String RenameBone(CSZ name);
|
||||
};
|
||||
VERUS_TYPEDEFS(FileParser);
|
||||
|
||||
struct FileParserDelegate
|
||||
{
|
||||
virtual void FileParser_OnProgress(float percent) = 0;
|
||||
virtual void FileParser_OnProgressText(CSZ txt) = 0;
|
||||
virtual void FileParser_Optimize(
|
||||
Vector<FileParser::Mesh::UberVertex>& vVb,
|
||||
Vector<FileParser::Mesh::Face>& vIb) = 0;
|
||||
virtual bool FileParser_CanOverwriteFile(CSZ filename) { return true; }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -12,11 +12,6 @@ struct MyRendererDelegate : CGI::RendererDelegate
|
|||
|
||||
virtual void Renderer_OnDraw() override
|
||||
{
|
||||
//VERUS_QREF_RENDERER;
|
||||
//VERUS_QREF_TIMER;
|
||||
//const float x = fmod(timer.GetTime(), 1.f);
|
||||
//renderer.SetClearColor(Vector4(x, 0.5f, 0.25f, 1.f));
|
||||
//renderer->Clear(0);
|
||||
_p->BaseGame_Draw();
|
||||
}
|
||||
|
||||
|
@ -42,11 +37,12 @@ struct BaseGame::Pimpl : AllocatorAware
|
|||
PBaseGame _p = nullptr;
|
||||
Scene::MainCamera _camera;
|
||||
Spirit _cameraSpirit;
|
||||
bool _bulletDebugDrawEnabled = false;
|
||||
bool _defaultCameraMovement = true;
|
||||
bool _showFPS = true;
|
||||
bool _debugBullet = false;
|
||||
bool _escapeKeyExitGame = true;
|
||||
bool _minimized = false;
|
||||
bool _rawInputEvents = false;
|
||||
bool _showFPS = true;
|
||||
|
||||
Pimpl(PBaseGame p) : _p(p)
|
||||
{
|
||||
|
@ -55,15 +51,6 @@ struct BaseGame::Pimpl : AllocatorAware
|
|||
~Pimpl()
|
||||
{
|
||||
}
|
||||
|
||||
bool HandleUserEvents(SDL_Event* pEvent)
|
||||
{
|
||||
switch (pEvent->user.code)
|
||||
{
|
||||
case 0: return true; // Exit.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
BaseGame::BaseGame()
|
||||
|
@ -83,7 +70,7 @@ BaseGame::~BaseGame()
|
|||
//CGL::CRender::DoneWin32();
|
||||
}
|
||||
|
||||
void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
|
||||
void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS, App::Window::RcDesc desc)
|
||||
{
|
||||
VERUS_SDL_CENTERED;
|
||||
|
||||
|
@ -91,6 +78,7 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
|
|||
VERUS_QREF_SETTINGS;
|
||||
settings.ParseCommandLineArgs(argc, argv);
|
||||
//settings.LoadValidateSave();
|
||||
BaseGame_UpdateSettings();
|
||||
|
||||
const int ret = SDL_Init(SDL_INIT_EVERYTHING);
|
||||
if (ret)
|
||||
|
@ -103,15 +91,16 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
|
|||
//Utils::TestAll();
|
||||
#endif
|
||||
|
||||
_window.Init();
|
||||
_window.Init(desc);
|
||||
CGI::Renderer::I().SetMainWindow(&_window);
|
||||
_engineInit.Init(this, new MyRendererDelegate(this));
|
||||
|
||||
// Configure:
|
||||
VERUS_QREF_RENDERER;
|
||||
//VERUS_QREF_SM;
|
||||
VERUS_QREF_SM;
|
||||
_p->_camera.SetAspectRatio(renderer.GetWindowAspectRatio());
|
||||
//sm.SetCamera(&_p->_camera);
|
||||
_p->_camera.Update();
|
||||
sm.SetCamera(&_p->_camera);
|
||||
|
||||
renderer->BeginFrame(false); // Begin recording a command buffer.
|
||||
renderer.InitCmd();
|
||||
|
@ -119,22 +108,23 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
|
|||
renderer->EndFrame(false); // End recording a command buffer.
|
||||
}
|
||||
|
||||
void BaseGame::Run()
|
||||
void BaseGame::Run(bool relativeMouseMode)
|
||||
{
|
||||
VERUS_QREF_TIMER;
|
||||
VERUS_QREF_KM;
|
||||
VERUS_QREF_BULLET;
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_ASYNC;
|
||||
VERUS_QREF_ASYS;
|
||||
VERUS_QREF_BULLET;
|
||||
VERUS_QREF_KM;
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_SM;
|
||||
VERUS_QREF_TIMER;
|
||||
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
if (relativeMouseMode)
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
|
||||
timer.Update();
|
||||
|
||||
SDL_Event event;
|
||||
bool done = false;
|
||||
bool quit = false;
|
||||
|
||||
do // The Game Loop.
|
||||
{
|
||||
|
@ -144,37 +134,73 @@ void BaseGame::Run()
|
|||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
|
||||
if (_p->_rawInputEvents && !ImGui::GetIO().WantCaptureMouse)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_MOUSEMOTION:
|
||||
{
|
||||
BaseGame_SDL_OnMouseMotion(event.motion.xrel, event.motion.yrel);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
{
|
||||
if (1 == event.button.clicks)
|
||||
BaseGame_SDL_OnMouseButtonDown(event.button.button);
|
||||
else if (2 == event.button.clicks)
|
||||
BaseGame_SDL_OnMouseDoubleClick(event.button.button);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
if (1 == event.button.clicks)
|
||||
BaseGame_SDL_OnMouseButtonUp(event.button.button);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
BaseGame_SDL_OnMouseWheel(event.wheel.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!km.HandleSdlEvent(event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
{
|
||||
done = true;
|
||||
if (BaseGame_CanQuitEventLoop())
|
||||
quit = true;
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
{
|
||||
switch (event.window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
{
|
||||
renderer.OnWindowResized(event.window.data1, event.window.data2);
|
||||
sm.GetCamera()->SetAspectRatio(renderer.GetWindowAspectRatio());
|
||||
sm.GetCamera()->Update();
|
||||
BaseGame_OnWindowResized();
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
{
|
||||
_p->_minimized = true;
|
||||
BaseGame_OnDeactivated();
|
||||
renderer->WaitIdle();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
{
|
||||
_p->_minimized = false;
|
||||
BaseGame_OnActivated();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_USEREVENT:
|
||||
{
|
||||
if (_p->HandleUserEvents(&event))
|
||||
{
|
||||
SDL_Delay(100);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -185,7 +211,7 @@ void BaseGame::Run()
|
|||
if (_p->_minimized)
|
||||
continue;
|
||||
|
||||
if (done)
|
||||
if (quit)
|
||||
break;
|
||||
|
||||
//
|
||||
|
@ -227,8 +253,8 @@ void BaseGame::Run()
|
|||
// _p->_camera.ExcludeWaterLine();
|
||||
}
|
||||
_p->_camera.Update();
|
||||
sm.SetCamera(&_p->_camera);
|
||||
}
|
||||
sm.SetCamera(&_p->_camera);
|
||||
|
||||
BaseGame_Update();
|
||||
|
||||
|
@ -253,20 +279,24 @@ void BaseGame::Run()
|
|||
sprintf_s(title, "[%s] - %.1f FPS", gapi, renderer.GetFps());
|
||||
SDL_SetWindowTitle(renderer.GetMainWindow()->GetSDL(), title);
|
||||
}
|
||||
} while (!done); // The Game Loop.
|
||||
} while (!quit); // The Game Loop.
|
||||
|
||||
BaseGame_UnloadContent();
|
||||
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
if (relativeMouseMode)
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
}
|
||||
|
||||
void BaseGame::Exit()
|
||||
{
|
||||
Utils::ExitSdlLoop();
|
||||
Utils::PushQuitEvent();
|
||||
}
|
||||
|
||||
void BaseGame::KeyMapper_OnMouseMove(int x, int y)
|
||||
{
|
||||
if (!SDL_GetRelativeMouseMode())
|
||||
return;
|
||||
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
const float rad = (VERUS_2PI / 360.f) / 3.f; // 3 pixels = 1 degree.
|
||||
|
@ -303,22 +333,43 @@ RSpirit BaseGame::GetCameraSpirit()
|
|||
return _p->_cameraSpirit;
|
||||
}
|
||||
|
||||
void BaseGame::ActivateDefaultCameraMovement(bool b)
|
||||
void BaseGame::EnableBulletDebugDraw(bool b)
|
||||
{
|
||||
_p->_bulletDebugDrawEnabled = b;
|
||||
}
|
||||
|
||||
void BaseGame::EnableDefaultCameraMovement(bool b)
|
||||
{
|
||||
_p->_defaultCameraMovement = b;
|
||||
}
|
||||
|
||||
void BaseGame::EnableEscapeKeyExitGame(bool b)
|
||||
{
|
||||
_p->_escapeKeyExitGame = b;
|
||||
}
|
||||
|
||||
void BaseGame::EnableRawInputEvents(bool b)
|
||||
{
|
||||
_p->_rawInputEvents = b;
|
||||
}
|
||||
|
||||
void BaseGame::ShowFPS(bool b)
|
||||
{
|
||||
_p->_showFPS = b;
|
||||
}
|
||||
|
||||
void BaseGame::DebugBullet(bool b)
|
||||
bool BaseGame::IsBulletDebugDrawEnabled() const
|
||||
{
|
||||
_p->_debugBullet = b;
|
||||
return _p->_bulletDebugDrawEnabled;
|
||||
}
|
||||
|
||||
bool BaseGame::IsDebugBulletMode() const
|
||||
void BaseGame::BulletDebugDraw()
|
||||
{
|
||||
return _p->_debugBullet;
|
||||
#ifdef VERUS_DEBUG
|
||||
if (_p->_bulletDebugDrawEnabled)
|
||||
{
|
||||
VERUS_QREF_BULLET;
|
||||
bullet.DebugDraw();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -16,35 +16,53 @@ namespace verus
|
|||
BaseGame();
|
||||
~BaseGame();
|
||||
|
||||
void Initialize(VERUS_MAIN_DEFAULT_ARGS);
|
||||
void Run();
|
||||
void Initialize(VERUS_MAIN_DEFAULT_ARGS, App::Window::RcDesc desc = App::Window::Desc());
|
||||
void Run(bool relativeMouseMode = true);
|
||||
void Exit();
|
||||
|
||||
virtual void BaseGame_UpdateSettings() {};
|
||||
virtual void BaseGame_LoadContent() = 0;
|
||||
virtual void BaseGame_UnloadContent() = 0;
|
||||
virtual void BaseGame_HandleInput() = 0;
|
||||
virtual void BaseGame_Update() = 0;
|
||||
virtual void BaseGame_Draw() = 0;
|
||||
virtual void BaseGame_DrawOverlay() = 0;
|
||||
virtual void BaseGame_OnWindowResized() {}
|
||||
virtual void BaseGame_OnActivated() {}
|
||||
virtual void BaseGame_OnDeactivated() {}
|
||||
virtual void BaseGame_OnMouseMove(float x, float y) {}
|
||||
virtual void BaseGame_OnKey(int scancode) {}
|
||||
virtual void BaseGame_OnChar(wchar_t c) {}
|
||||
virtual bool BaseGame_CanQuitEventLoop() { return true; }
|
||||
|
||||
// Raw SDL events, for editor:
|
||||
virtual void BaseGame_SDL_OnMouseMotion(int x, int y) {}
|
||||
virtual void BaseGame_SDL_OnMouseButtonDown(int button) {}
|
||||
virtual void BaseGame_SDL_OnMouseDoubleClick(int button) {}
|
||||
virtual void BaseGame_SDL_OnMouseButtonUp(int button) {}
|
||||
virtual void BaseGame_SDL_OnMouseWheel(int delta) {}
|
||||
|
||||
virtual void KeyMapper_OnMouseMove(int x, int y) override;
|
||||
virtual void KeyMapper_OnKey(int scancode) override;
|
||||
virtual void KeyMapper_OnChar(wchar_t c) override;
|
||||
|
||||
// Internal objects:
|
||||
REngineInit GetEngineInit() { return _engineInit; }
|
||||
|
||||
App::RcWindow GetWindow() const { return _window; }
|
||||
|
||||
// Camera:
|
||||
Scene::RCamera GetCamera();
|
||||
RSpirit GetCameraSpirit();
|
||||
|
||||
// Configurations:
|
||||
void ActivateDefaultCameraMovement(bool b);
|
||||
// Configuration:
|
||||
void EnableBulletDebugDraw(bool b);
|
||||
void EnableDefaultCameraMovement(bool b);
|
||||
void EnableEscapeKeyExitGame(bool b);
|
||||
void EnableRawInputEvents(bool b);
|
||||
void ShowFPS(bool b);
|
||||
void DebugBullet(bool b);
|
||||
bool IsDebugBulletMode() const;
|
||||
|
||||
bool IsBulletDebugDrawEnabled() const;
|
||||
void BulletDebugDraw();
|
||||
};
|
||||
VERUS_TYPEDEFS(BaseGame);
|
||||
}
|
||||
|
|
|
@ -6,3 +6,49 @@
|
|||
#include "QuickRefs.h"
|
||||
#include "AllocatorAware.h"
|
||||
#include "Singleton.h"
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace Math
|
||||
{
|
||||
// Clamp:
|
||||
template<typename T>
|
||||
T Clamp(T x, T mn, T mx)
|
||||
{
|
||||
if (x <= mn)
|
||||
return mn;
|
||||
else if (x >= mx)
|
||||
return mx;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Minimum & maximum:
|
||||
template<typename T>
|
||||
T Min(T a, T b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
template<typename T>
|
||||
T Max(T a, T b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
// Memory alignment:
|
||||
template<typename T>
|
||||
T AlignUp(T val, T align)
|
||||
{
|
||||
return (val + align - 1) / align * align;
|
||||
}
|
||||
template<typename T>
|
||||
T AlignDown(T val, T align)
|
||||
{
|
||||
return val / align * align;
|
||||
}
|
||||
template<typename T>
|
||||
T DivideByMultiple(T value, T alignment)
|
||||
{
|
||||
return (value + alignment - 1) / alignment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ void EngineInit::Make()
|
|||
Make_Physics();
|
||||
//if (_makeEffects)
|
||||
// Make_Effects();
|
||||
//if (_makeExtra)
|
||||
// Make_Extra();
|
||||
if (_makeExtra)
|
||||
Make_Extra();
|
||||
if (_makeScene)
|
||||
Make_Scene();
|
||||
//if (_makeGUI)
|
||||
|
@ -34,8 +34,8 @@ void EngineInit::Free()
|
|||
// Free_GUI();
|
||||
if (_makeScene)
|
||||
Free_Scene();
|
||||
//if (_makeExtra)
|
||||
// Free_Extra();
|
||||
if (_makeExtra)
|
||||
Free_Extra();
|
||||
//if (_makeEffects)
|
||||
// Free_Effects();
|
||||
if (_makePhysics)
|
||||
|
|
|
@ -26,14 +26,14 @@ void Object::Done()
|
|||
#ifdef VERUS_DEBUG
|
||||
void Object::UpdateOnceCheck()
|
||||
{
|
||||
const UINT32 numFrames = CGL::CRender::I().GetNumFrames();
|
||||
const UINT64 numFrames = CGI::Renderer::I().GetNumFrames();
|
||||
VERUS_RT_ASSERT(_updateOnceFrame <= numFrames);
|
||||
_updateOnceFrame = numFrames + 1;
|
||||
}
|
||||
|
||||
void Object::UpdateOnceCheckDraw()
|
||||
{
|
||||
const UINT32 numFrames = CGL::CRender::I().GetNumFrames();
|
||||
const UINT64 numFrames = CGI::Renderer::I().GetNumFrames();
|
||||
VERUS_RT_ASSERT(_updateOnceFrame > numFrames);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,14 +8,8 @@
|
|||
# define VERUS_UPDATE_ONCE_CHECK_DRAW
|
||||
#endif
|
||||
|
||||
#define VERUS_INIT()\
|
||||
Object::Init();
|
||||
|
||||
#define VERUS_DONE(x)\
|
||||
if(Object::IsInitialized()) {\
|
||||
Object::Done();\
|
||||
this->~x();\
|
||||
new(this) x();}
|
||||
#define VERUS_INIT() Object::Init();
|
||||
#define VERUS_DONE(x) if (Object::IsInitialized()) { Object::Done(); this->~x(); new(this) x(); }
|
||||
|
||||
namespace verus
|
||||
{
|
||||
|
@ -32,7 +26,7 @@ namespace verus
|
|||
{
|
||||
std::atomic_uint _flags;
|
||||
#ifdef VERUS_DEBUG
|
||||
UINT32 _updateOnceFrame = 0;
|
||||
UINT64 _updateOnceFrame = 0;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
namespace verus
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
inline auto Async(F&& f, Ts&&... params)
|
||||
{
|
||||
return std::async(std::launch::async, std::forward<F>(f), std::forward<Ts>(params)...);
|
||||
}
|
||||
|
||||
class Parallel
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace verus
|
|||
|
||||
int GetNumStored() const
|
||||
{
|
||||
return _list.size();
|
||||
return static_cast<int>(_list.size());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -108,7 +108,7 @@ namespace verus
|
|||
|
||||
int GetNumStored() const
|
||||
{
|
||||
return _map.size();
|
||||
return static_cast<int>(_map.size());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -55,10 +55,10 @@ void Utils::InitPaths()
|
|||
VERUS_LOG_INFO("Writable path: " << _writablePath);
|
||||
}
|
||||
|
||||
void Utils::ExitSdlLoop()
|
||||
void Utils::PushQuitEvent()
|
||||
{
|
||||
SDL_Event event = {};
|
||||
event.type = SDL_USEREVENT;
|
||||
event.type = SDL_QUIT;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace verus
|
|||
String _modulePath;
|
||||
String _shaderPath;
|
||||
String _writablePath;
|
||||
String _projectPath;
|
||||
PBaseAllocator _pAllocator;
|
||||
|
||||
public:
|
||||
|
@ -26,6 +27,8 @@ namespace verus
|
|||
void SetShaderPath(CSZ path) { _shaderPath = path; }
|
||||
Str GetWritablePath() const { return _C(_writablePath); }
|
||||
void SetWritablePath(CSZ path) { _writablePath = path; }
|
||||
Str GetProjectPath() const { return _C(_projectPath); }
|
||||
void SetProjectPath(CSZ path) { _projectPath = path; }
|
||||
|
||||
RRandom GetRandom() { return _random; }
|
||||
|
||||
|
@ -33,7 +36,7 @@ namespace verus
|
|||
PBaseAllocator GetAllocator() { return _pAllocator; }
|
||||
void SetAllocator(PBaseAllocator p) { _pAllocator = p; }
|
||||
|
||||
static void ExitSdlLoop();
|
||||
static void PushQuitEvent();
|
||||
|
||||
static INT32 Cast32(INT64 x);
|
||||
static UINT32 Cast32(UINT64 x);
|
||||
|
|
|
@ -146,6 +146,7 @@ void FileSystem::LoadResourceFromFile(CSZ url, Vector<BYTE>& vData, RcLoadDesc d
|
|||
if (shader)
|
||||
{
|
||||
strUrl.replace(0, strlen(s_shaderPAK), "/");
|
||||
pathNameProject = String(_C(Utils::I().GetProjectPath())) + strUrl;
|
||||
StringStream ss;
|
||||
ss << _C(Utils::I().GetShaderPath()) << strUrl;
|
||||
strUrl = ss.str();
|
||||
|
@ -154,6 +155,7 @@ void FileSystem::LoadResourceFromFile(CSZ url, Vector<BYTE>& vData, RcLoadDesc d
|
|||
{
|
||||
String folder = strUrl.substr(1, pakPos - 1);
|
||||
const String name = strUrl.substr(pakPos + 2);
|
||||
pathNameProject = String(_C(Utils::I().GetProjectPath())) + s_dataFolder + folder + "/" + name;
|
||||
StringStream ss;
|
||||
ss << _C(Utils::I().GetModulePath()) << s_dataFolder << folder << "/" << name;
|
||||
strUrl = ss.str();
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::Input;
|
||||
|
||||
void DragController::SetDelegate(PDragControllerDelegate p)
|
||||
{
|
||||
_pDelegate = p;
|
||||
if (_pDelegate)
|
||||
_pDelegate->DragController_GetRatio(_ratioX, _ratioY);
|
||||
}
|
||||
|
||||
void DragController::Begin(int x, int y)
|
||||
{
|
||||
if (!_pDelegate)
|
||||
return;
|
||||
_active = true;
|
||||
_originCoordX = x;
|
||||
_originCoordY = y;
|
||||
_pDelegate->DragController_Begin();
|
||||
_pDelegate->DragController_GetParams(_originX, _originY);
|
||||
}
|
||||
|
||||
bool DragController::DragTo(int x, int y)
|
||||
{
|
||||
if (!_pDelegate || !_active)
|
||||
return false;
|
||||
const float newX = _originX + (x - _originCoordX) * _ratioX;
|
||||
const float newY = _originY + (y - _originCoordY) * _ratioY;
|
||||
_pDelegate->DragController_SetParams(newX, newY);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DragController::DragBy(int x, int y)
|
||||
{
|
||||
if (!_pDelegate || !_active)
|
||||
return false;
|
||||
_originX += x * _ratioX;
|
||||
_originY += y * _ratioY;
|
||||
_pDelegate->DragController_SetParams(_originX, _originY);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DragController::End()
|
||||
{
|
||||
if (_pDelegate)
|
||||
_pDelegate->DragController_End();
|
||||
_active = false;
|
||||
}
|
||||
|
||||
void DragController::SetScale(float s)
|
||||
{
|
||||
if (_pDelegate)
|
||||
_pDelegate->DragController_SetScale(s);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
struct DragControllerDelegate
|
||||
{
|
||||
virtual void DragController_GetParams(float& x, float& y) = 0;
|
||||
virtual void DragController_SetParams(float x, float y) = 0;
|
||||
virtual void DragController_GetRatio(float& x, float& y) = 0;
|
||||
virtual void DragController_Begin() {}
|
||||
virtual void DragController_End() {}
|
||||
virtual void DragController_SetScale(float s) {}
|
||||
};
|
||||
VERUS_TYPEDEFS(DragControllerDelegate);
|
||||
|
||||
class DragController
|
||||
{
|
||||
PDragControllerDelegate _pDelegate = nullptr;
|
||||
float _originX = 0;
|
||||
float _originY = 0;
|
||||
int _originCoordX = 0;
|
||||
int _originCoordY = 0;
|
||||
float _ratioX = 1;
|
||||
float _ratioY = 1;
|
||||
bool _active = false;
|
||||
|
||||
public:
|
||||
void SetDelegate(PDragControllerDelegate p);
|
||||
|
||||
void Begin(int x, int y);
|
||||
bool DragTo(int x, int y);
|
||||
bool DragBy(int x, int y);
|
||||
void End();
|
||||
|
||||
void SetScale(float s);
|
||||
};
|
||||
VERUS_TYPEDEFS(DragController);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "KeyMapper.h"
|
||||
#include "DragController.h"
|
||||
|
||||
namespace verus
|
||||
{
|
||||
|
|
|
@ -58,21 +58,29 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
|
|||
// Keyboard:
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
if (ImGui::GetIO().WantCaptureKeyboard)
|
||||
return false;
|
||||
#if defined(_DEBUG) || defined(VERUS_DEBUG)
|
||||
if (settings._screenWindowed && SDL_SCANCODE_KP_ENTER == event.key.keysym.scancode)
|
||||
{
|
||||
const SDL_bool rel = SDL_GetRelativeMouseMode();
|
||||
SDL_SetRelativeMouseMode(rel ? SDL_FALSE : SDL_TRUE);
|
||||
}
|
||||
#endif
|
||||
OnKeyDown(event.key.keysym.scancode);
|
||||
}
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
if (ImGui::GetIO().WantCaptureKeyboard)
|
||||
return false;
|
||||
OnKeyUp(event.key.keysym.scancode);
|
||||
}
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
if (ImGui::GetIO().WantCaptureKeyboard)
|
||||
return false;
|
||||
wchar_t wide[4];
|
||||
Str::Utf8ToWide(event.text.text, wide, 4);
|
||||
OnChar(wide[0]);
|
||||
|
@ -90,6 +98,8 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
|
|||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
{
|
||||
if (ImGui::GetIO().WantCaptureMouse)
|
||||
return false;
|
||||
if (1 == event.button.clicks)
|
||||
{
|
||||
if (event.button.button < VERUS_BUTTON_WHEELUP)
|
||||
|
@ -104,6 +114,8 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
|
|||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
if (ImGui::GetIO().WantCaptureMouse)
|
||||
return false;
|
||||
if (1 == event.button.clicks)
|
||||
{
|
||||
if (event.button.button < VERUS_BUTTON_WHEELUP)
|
||||
|
@ -113,6 +125,8 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
|
|||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
if (ImGui::GetIO().WantCaptureMouse)
|
||||
return false;
|
||||
if (event.wheel.y >= 0)
|
||||
{
|
||||
OnMouseDown(VERUS_BUTTON_WHEELUP);
|
||||
|
|
|
@ -81,45 +81,5 @@ namespace verus
|
|||
// Matrices:
|
||||
Transform3 QuadMatrix(float x = 0, float y = 0, float w = 1, float h = 1);
|
||||
Transform3 ToUVMatrix(float zOffset = 0, RcVector4 texSize = Vector4(0), PcVector4 pTileSize = nullptr);
|
||||
|
||||
// Clamp:
|
||||
template<typename T>
|
||||
T Clamp(T x, T mn, T mx)
|
||||
{
|
||||
if (x <= mn)
|
||||
return mn;
|
||||
else if (x >= mx)
|
||||
return mx;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Minimum & maximum:
|
||||
template<typename T>
|
||||
T Min(T a, T b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
template<typename T>
|
||||
T Max(T a, T b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
// Memory alignment:
|
||||
template<typename T>
|
||||
T AlignUp(T val, T align)
|
||||
{
|
||||
return (val + align - 1) / align * align;
|
||||
}
|
||||
template<typename T>
|
||||
T AlignDown(T val, T align)
|
||||
{
|
||||
return val / align * align;
|
||||
}
|
||||
template<typename T>
|
||||
T DivideByMultiple(T value, T alignment)
|
||||
{
|
||||
return (value + alignment - 1) / alignment;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ void Bullet::Init()
|
|||
_pBroadphaseInterface = new btDbvtBroadphase();
|
||||
_pConstraintSolver = new btSequentialImpulseConstraintSolver();
|
||||
|
||||
//_pBroadphaseInterface->getOverlappingPairCache()->setInternalGhostPairCallback(&m_ghostPairCallback);
|
||||
_pBroadphaseInterface->getOverlappingPairCache()->setInternalGhostPairCallback(&_ghostPairCallback);
|
||||
|
||||
_pDiscreteDynamicsWorld = new btDiscreteDynamicsWorld(
|
||||
_pDispatcher,
|
||||
|
@ -31,7 +31,7 @@ void Bullet::Init()
|
|||
|
||||
#ifdef VERUS_DEBUG
|
||||
_pDiscreteDynamicsWorld->setDebugDrawer(&_debugDraw);
|
||||
_pDiscreteDynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_NoDebug);
|
||||
EnableDebugDraw(true);
|
||||
#endif
|
||||
|
||||
// See: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6773:
|
||||
|
@ -131,13 +131,15 @@ void Bullet::Simulate()
|
|||
|
||||
void Bullet::DebugDraw()
|
||||
{
|
||||
#ifdef VERUS_DEBUG
|
||||
if (!_pDiscreteDynamicsWorld)
|
||||
return;
|
||||
|
||||
//VERUS_QREF_DR;
|
||||
//dr.Begin(CGL::CDebugRender::T_LINES, nullptr, false);
|
||||
//_pDiscreteDynamicsWorld->debugDrawWorld();
|
||||
//dr.End();
|
||||
VERUS_QREF_DD;
|
||||
dd.Begin(CGI::DebugDraw::Type::lines, nullptr, false);
|
||||
_pDiscreteDynamicsWorld->debugDrawWorld();
|
||||
dd.End();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Bullet::EnableDebugDraw(bool b)
|
||||
|
|
|
@ -26,6 +26,8 @@ namespace verus
|
|||
btConstraintSolver* _pConstraintSolver = nullptr;
|
||||
btCollisionConfiguration* _pCollisionConfiguration = nullptr;
|
||||
btDiscreteDynamicsWorld* _pDiscreteDynamicsWorld = nullptr;
|
||||
btGhostPairCallback _ghostPairCallback;
|
||||
BulletDebugDraw _debugDraw;
|
||||
|
||||
public:
|
||||
Bullet();
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::Physics;
|
||||
|
||||
void BulletDebugDraw::drawLine(const btVector3& from, const btVector3& to,
|
||||
const btVector3& color)
|
||||
{
|
||||
VERUS_QREF_SM;
|
||||
const float maxDistSq = s_maxDrawDist * s_maxDrawDist;
|
||||
const Point3 posEye = sm.GetCamera()->GetPositionEye();
|
||||
if (VMath::distSqr(posEye, Point3(from)) >= maxDistSq &&
|
||||
VMath::distSqr(posEye, Point3(to)) >= maxDistSq)
|
||||
return;
|
||||
|
||||
VERUS_QREF_DD;
|
||||
dd.AddLine(from, to, Convert::ColorFloatToInt32(color) | VERUS_COLOR_BLACK);
|
||||
}
|
||||
|
||||
void BulletDebugDraw::drawLine(const btVector3& from, const btVector3& to,
|
||||
const btVector3& fromColor, const btVector3& toColor)
|
||||
{
|
||||
VERUS_QREF_SM;
|
||||
const float maxDistSq = s_maxDrawDist * s_maxDrawDist;
|
||||
const Point3 posEye = sm.GetCamera()->GetPositionEye();
|
||||
if (VMath::distSqr(posEye, Point3(from)) >= maxDistSq &&
|
||||
VMath::distSqr(posEye, Point3(to)) >= maxDistSq)
|
||||
return;
|
||||
|
||||
VERUS_QREF_DD;
|
||||
dd.AddLine(from, to, Convert::ColorFloatToInt32(fromColor) | VERUS_COLOR_BLACK);
|
||||
}
|
||||
|
||||
void BulletDebugDraw::drawSphere(const btVector3& p, btScalar radius, const btVector3& color)
|
||||
{
|
||||
}
|
||||
|
||||
void BulletDebugDraw::drawBox(const btVector3& boxMin, const btVector3& boxMax,
|
||||
const btVector3& color)
|
||||
{
|
||||
}
|
||||
|
||||
void BulletDebugDraw::drawTriangle(const btVector3& a, const btVector3& b, const btVector3& c,
|
||||
const btVector3& color, btScalar alpha)
|
||||
{
|
||||
VERUS_QREF_DD;
|
||||
Vector4 colorEx = color;
|
||||
colorEx.setW(alpha);
|
||||
const UINT32 color32 = Convert::ColorFloatToInt32(colorEx.ToPointer());
|
||||
dd.AddLine(a, b, color32);
|
||||
dd.AddLine(b, c, color32);
|
||||
dd.AddLine(c, a, color32);
|
||||
}
|
||||
|
||||
void BulletDebugDraw::drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB,
|
||||
btScalar distance, int lifeTime, const btVector3& color)
|
||||
{
|
||||
}
|
||||
|
||||
void BulletDebugDraw::reportErrorWarning(const char* warningString)
|
||||
{
|
||||
}
|
||||
|
||||
void BulletDebugDraw::draw3dText(const btVector3& location, const char* textString)
|
||||
{
|
||||
}
|
||||
|
||||
void BulletDebugDraw::drawTransform(const btTransform& transform, btScalar orthoLen)
|
||||
{
|
||||
btIDebugDraw::drawTransform(transform, 0.1f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace Physics
|
||||
{
|
||||
class BulletDebugDraw : public btIDebugDraw
|
||||
{
|
||||
static const int s_maxDrawDist = 30;
|
||||
|
||||
int _debugMode = 0;
|
||||
|
||||
public:
|
||||
BulletDebugDraw() : _debugMode(btIDebugDraw::DBG_DrawWireframe) {}
|
||||
~BulletDebugDraw() {}
|
||||
|
||||
virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override;
|
||||
virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor) override;
|
||||
|
||||
virtual void drawSphere(const btVector3& p, btScalar radius, const btVector3& color) override;
|
||||
virtual void drawBox(const btVector3& boxMin, const btVector3& boxMax, const btVector3& color) override;
|
||||
|
||||
virtual void drawTriangle(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& color, btScalar alpha) override;
|
||||
|
||||
virtual void drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override;
|
||||
|
||||
virtual void reportErrorWarning(const char* warningString) override;
|
||||
|
||||
virtual void draw3dText(const btVector3& location, const char* textString) override;
|
||||
|
||||
virtual void drawTransform(const btTransform& transform, btScalar orthoLen) override;
|
||||
|
||||
virtual void setDebugMode(int debugMode) override { _debugMode = debugMode; }
|
||||
virtual int getDebugMode() const override { return _debugMode; }
|
||||
};
|
||||
VERUS_TYPEDEFS(BulletDebugDraw);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::Physics;
|
||||
|
||||
CharacterController::CharacterController()
|
||||
{
|
||||
}
|
||||
|
||||
CharacterController::~CharacterController()
|
||||
{
|
||||
Done();
|
||||
}
|
||||
|
||||
void CharacterController::Init(RcPoint3 pos, RcDesc desc)
|
||||
{
|
||||
VERUS_INIT();
|
||||
|
||||
VERUS_QREF_BULLET;
|
||||
|
||||
if (desc._radius >= 1e-4f)
|
||||
_radius = desc._radius;
|
||||
if (desc._height >= 1e-4f)
|
||||
_height = desc._height;
|
||||
float stepHeight = _radius;
|
||||
if (desc._stepHeight >= 0)
|
||||
stepHeight = desc._stepHeight;
|
||||
|
||||
_offset = _radius + _height * 0.5f;
|
||||
|
||||
btTransform t;
|
||||
t.setIdentity();
|
||||
t.setOrigin(pos.Bullet() + btVector3(0, _offset, 0));
|
||||
_pCapsule = new btCapsuleShape(1, 1);
|
||||
_pGhostObject = new btPairCachingGhostObject();
|
||||
_pGhostObject->setWorldTransform(t);
|
||||
_pGhostObject->setCollisionShape(_pCapsule);
|
||||
_pGhostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
|
||||
_pGhostObject->setUserPointer(this);
|
||||
_pKCC = new KinematicCharacterController(_pGhostObject, _pCapsule, stepHeight);
|
||||
_pKCC->setGravity(-bullet.GetWorld()->getGravity().getY());
|
||||
_pKCC->setMaxSlope(btRadians(48));
|
||||
bullet.GetWorld()->addCollisionObject(_pGhostObject, +Group::character, -1);
|
||||
bullet.GetWorld()->addAction(_pKCC);
|
||||
UpdateScaling();
|
||||
}
|
||||
|
||||
void CharacterController::Done()
|
||||
{
|
||||
VERUS_QREF_BULLET;
|
||||
|
||||
if (_pKCC)
|
||||
{
|
||||
bullet.GetWorld()->removeAction(_pKCC);
|
||||
delete _pKCC;
|
||||
_pKCC = nullptr;
|
||||
}
|
||||
|
||||
if (_pGhostObject)
|
||||
{
|
||||
bullet.GetWorld()->removeCollisionObject(_pGhostObject);
|
||||
delete _pGhostObject;
|
||||
_pGhostObject = nullptr;
|
||||
}
|
||||
|
||||
if (_pCapsule)
|
||||
{
|
||||
delete _pCapsule;
|
||||
_pCapsule = nullptr;
|
||||
}
|
||||
|
||||
VERUS_DONE(CharacterController);
|
||||
}
|
||||
|
||||
int CharacterController::UserPtr_GetType()
|
||||
{
|
||||
return 0;
|
||||
//return +Scene::NodeType::character;
|
||||
}
|
||||
|
||||
void CharacterController::SetRadius(float r)
|
||||
{
|
||||
const bool update = (r != _radius);
|
||||
_radius = r;
|
||||
if (update)
|
||||
UpdateScaling();
|
||||
}
|
||||
|
||||
void CharacterController::SetHeight(float h)
|
||||
{
|
||||
const Point3 pos = GetPosition();
|
||||
const bool update = (h != _height);
|
||||
_height = h;
|
||||
if (update)
|
||||
{
|
||||
UpdateScaling();
|
||||
MoveTo(pos);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::UpdateScaling()
|
||||
{
|
||||
_offset = _radius + _height * 0.5f;
|
||||
if (_pCapsule)
|
||||
_pCapsule->setLocalScaling(btVector3(_radius, _height, _radius));
|
||||
}
|
||||
|
||||
void CharacterController::Move(RcVector3 velocity)
|
||||
{
|
||||
VERUS_QREF_TIMER;
|
||||
if (_pKCC)
|
||||
_pKCC->setVelocityForTimeInterval(velocity.Bullet(), dt);
|
||||
}
|
||||
|
||||
Point3 CharacterController::GetPosition()
|
||||
{
|
||||
if (_pGhostObject)
|
||||
return _pGhostObject->getWorldTransform().getOrigin() - btVector3(0, _offset, 0);
|
||||
return Point3(0);
|
||||
}
|
||||
|
||||
void CharacterController::MoveTo(RcPoint3 pos)
|
||||
{
|
||||
if (_pKCC)
|
||||
_pKCC->warp(pos.Bullet() + btVector3(0, _offset, 0));
|
||||
}
|
||||
|
||||
void CharacterController::Visualize(bool b)
|
||||
{
|
||||
const int f = _pGhostObject->getCollisionFlags();
|
||||
if (b)
|
||||
_pGhostObject->setCollisionFlags(f & ~btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
|
||||
else
|
||||
_pGhostObject->setCollisionFlags(f | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace Physics
|
||||
{
|
||||
class CharacterController : public Object, public UserPtr
|
||||
{
|
||||
btCapsuleShape* _pCapsule = nullptr;
|
||||
KinematicCharacterController* _pKCC = nullptr; // Action.
|
||||
btPairCachingGhostObject* _pGhostObject = nullptr; // CollisionObject.
|
||||
float _radius = 1;
|
||||
float _height = 1;
|
||||
float _offset = 0;
|
||||
|
||||
public:
|
||||
class Desc
|
||||
{
|
||||
public:
|
||||
float _radius = -1;
|
||||
float _height = -1;
|
||||
float _stepHeight = -1;
|
||||
};
|
||||
VERUS_TYPEDEFS(Desc);
|
||||
|
||||
CharacterController();
|
||||
~CharacterController();
|
||||
|
||||
void Init(RcPoint3 pos, RcDesc desc);
|
||||
void Done();
|
||||
|
||||
virtual int UserPtr_GetType() override;
|
||||
|
||||
float GetRadius() const { return _radius; }
|
||||
float GetHeight() const { return _height; }
|
||||
float GetOffset() const { return _offset; }
|
||||
void SetRadius(float r);
|
||||
void SetHeight(float h);
|
||||
VERUS_P(void UpdateScaling());
|
||||
|
||||
KinematicCharacterController* GetKCC() { return _pKCC; }
|
||||
const KinematicCharacterController* GetKCC() const { return _pKCC; }
|
||||
|
||||
void Move(RcVector3 velocity);
|
||||
|
||||
Point3 GetPosition();
|
||||
void MoveTo(RcPoint3 pos);
|
||||
|
||||
void Visualize(bool b);
|
||||
|
||||
bool Is(const void* p) const { return p == this; }
|
||||
};
|
||||
VERUS_TYPEDEFS(CharacterController);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,791 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include <verus.h>
|
||||
#include <LinearMath/btIDebugDraw.h>
|
||||
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||
#include <BulletCollision/CollisionShapes/btMultiSphereShape.h>
|
||||
#include <BulletCollision/BroadphaseCollision/btOverlappingPairCache.h>
|
||||
#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
|
||||
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
||||
#include <LinearMath/btDefaultMotionState.h>
|
||||
#include "KinematicCharacterController.h"
|
||||
|
||||
|
||||
// static helper method
|
||||
static btVector3
|
||||
getNormalizedVector(const btVector3& v)
|
||||
{
|
||||
btVector3 n(0, 0, 0);
|
||||
|
||||
if (v.length() > SIMD_EPSILON) {
|
||||
n = v.normalized();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
///@todo Interact with dynamic objects,
|
||||
///Ride kinematicly animated platforms properly
|
||||
///More realistic (or maybe just a config option) falling
|
||||
/// -> Should integrate falling velocity manually and use that in stepDown()
|
||||
///Support jumping
|
||||
///Support ducking
|
||||
class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
|
||||
{
|
||||
public:
|
||||
btKinematicClosestNotMeRayResultCallback(btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
|
||||
{
|
||||
m_me = me;
|
||||
}
|
||||
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
|
||||
{
|
||||
if (rayResult.m_collisionObject == m_me)
|
||||
return 1.0;
|
||||
|
||||
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
|
||||
}
|
||||
protected:
|
||||
btCollisionObject* m_me;
|
||||
};
|
||||
|
||||
class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
|
||||
{
|
||||
public:
|
||||
btKinematicClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
|
||||
: btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
|
||||
, m_me(me)
|
||||
, m_up(up)
|
||||
, m_minSlopeDot(minSlopeDot)
|
||||
{
|
||||
}
|
||||
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
|
||||
{
|
||||
if (convexResult.m_hitCollisionObject == m_me)
|
||||
return btScalar(1.0);
|
||||
|
||||
if (!convexResult.m_hitCollisionObject->hasContactResponse())
|
||||
return btScalar(1.0);
|
||||
|
||||
btVector3 hitNormalWorld;
|
||||
if (normalInWorldSpace)
|
||||
{
|
||||
hitNormalWorld = convexResult.m_hitNormalLocal;
|
||||
}
|
||||
else
|
||||
{
|
||||
///need to transform normal into worldspace
|
||||
hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
|
||||
}
|
||||
|
||||
btScalar dotUp = m_up.dot(hitNormalWorld);
|
||||
if (dotUp < m_minSlopeDot) {
|
||||
return btScalar(1.0);
|
||||
}
|
||||
|
||||
return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
|
||||
}
|
||||
protected:
|
||||
btCollisionObject* m_me;
|
||||
const btVector3 m_up;
|
||||
btScalar m_minSlopeDot;
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
|
||||
*
|
||||
* from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
|
||||
*/
|
||||
btVector3 KinematicCharacterController::computeReflectionDirection(const btVector3& direction, const btVector3& normal)
|
||||
{
|
||||
return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the portion of 'direction' that is parallel to 'normal'
|
||||
*/
|
||||
btVector3 KinematicCharacterController::parallelComponent(const btVector3& direction, const btVector3& normal)
|
||||
{
|
||||
btScalar magnitude = direction.dot(normal);
|
||||
return normal * magnitude;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the portion of 'direction' that is perpindicular to 'normal'
|
||||
*/
|
||||
btVector3 KinematicCharacterController::perpindicularComponent(const btVector3& direction, const btVector3& normal)
|
||||
{
|
||||
return direction - parallelComponent(direction, normal);
|
||||
}
|
||||
|
||||
KinematicCharacterController::KinematicCharacterController(btPairCachingGhostObject* ghostObject, btConvexShape* convexShape, btScalar stepHeight, int upAxis)
|
||||
{
|
||||
m_upAxis = upAxis;
|
||||
m_addedMargin = 0.02f;
|
||||
m_walkDirection.setValue(0, 0, 0);
|
||||
m_useGhostObjectSweepTest = true;
|
||||
m_ghostObject = ghostObject;
|
||||
m_stepHeight = stepHeight;
|
||||
m_turnAngle = btScalar(0.0);
|
||||
m_convexShape = convexShape;
|
||||
m_useWalkDirection = true; // use walk direction by default, legacy behavior
|
||||
m_velocityTimeInterval = 0.0;
|
||||
m_verticalVelocity = 0.0;
|
||||
m_verticalOffset = 0.0;
|
||||
m_gravity = 9.8f * 3; // 3G acceleration.
|
||||
m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
|
||||
m_jumpSpeed = 10.0; // ?
|
||||
m_wasOnGround = false;
|
||||
m_wasJumping = false;
|
||||
m_interpolateUp = true;
|
||||
setMaxSlope(btRadians(45.0));
|
||||
m_currentStepOffset = 0;
|
||||
full_drop = false;
|
||||
bounce_fix = false;
|
||||
}
|
||||
|
||||
KinematicCharacterController::~KinematicCharacterController()
|
||||
{
|
||||
}
|
||||
|
||||
btPairCachingGhostObject* KinematicCharacterController::getGhostObject()
|
||||
{
|
||||
return m_ghostObject;
|
||||
}
|
||||
|
||||
bool KinematicCharacterController::recoverFromPenetration(btCollisionWorld* collisionWorld)
|
||||
{
|
||||
// Here we must refresh the overlapping paircache as the penetrating movement itself or the
|
||||
// previous recovery iteration might have used setWorldTransform and pushed us into an object
|
||||
// that is not in the previous cache contents from the last timestep, as will happen if we
|
||||
// are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
|
||||
//
|
||||
// Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
|
||||
// paircache and the ghostobject's internal paircache at the same time. /BW
|
||||
|
||||
btVector3 minAabb, maxAabb;
|
||||
m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb, maxAabb);
|
||||
collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
|
||||
minAabb,
|
||||
maxAabb,
|
||||
collisionWorld->getDispatcher());
|
||||
|
||||
bool penetration = false;
|
||||
|
||||
collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
|
||||
|
||||
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
|
||||
|
||||
btScalar maxPen = btScalar(0.0);
|
||||
for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
|
||||
{
|
||||
m_manifoldArray.resize(0);
|
||||
|
||||
btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
|
||||
|
||||
btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
|
||||
btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
|
||||
|
||||
if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
|
||||
continue;
|
||||
|
||||
if (collisionPair->m_algorithm)
|
||||
collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
|
||||
|
||||
|
||||
for (int j = 0; j < m_manifoldArray.size(); j++)
|
||||
{
|
||||
btPersistentManifold* manifold = m_manifoldArray[j];
|
||||
btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
|
||||
for (int p = 0; p < manifold->getNumContacts(); p++)
|
||||
{
|
||||
const btManifoldPoint& pt = manifold->getContactPoint(p);
|
||||
|
||||
btScalar dist = pt.getDistance();
|
||||
|
||||
if (dist < 0.0)
|
||||
{
|
||||
if (dist < maxPen)
|
||||
{
|
||||
maxPen = dist;
|
||||
m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
|
||||
|
||||
}
|
||||
m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
|
||||
penetration = true;
|
||||
}
|
||||
else {
|
||||
//printf("touching %f\n", dist);
|
||||
}
|
||||
}
|
||||
|
||||
//manifold->clearManifold();
|
||||
}
|
||||
}
|
||||
btTransform newTrans = m_ghostObject->getWorldTransform();
|
||||
newTrans.setOrigin(m_currentPosition);
|
||||
m_ghostObject->setWorldTransform(newTrans);
|
||||
// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
|
||||
return penetration;
|
||||
}
|
||||
|
||||
void KinematicCharacterController::stepUp(btCollisionWorld* world)
|
||||
{
|
||||
// phase 1: up
|
||||
btTransform start, end;
|
||||
m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f ? m_verticalOffset : 0.f));
|
||||
|
||||
start.setIdentity();
|
||||
end.setIdentity();
|
||||
|
||||
/* FIXME: Handle penetration properly */
|
||||
start.setOrigin(m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin));
|
||||
end.setOrigin(m_targetPosition);
|
||||
|
||||
btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, -getUpAxisDirections()[m_upAxis], btScalar(0.7071));
|
||||
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
if (m_useGhostObjectSweepTest)
|
||||
{
|
||||
m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
|
||||
}
|
||||
else
|
||||
{
|
||||
world->convexSweepTest(m_convexShape, start, end, callback);
|
||||
}
|
||||
|
||||
if (callback.hasHit())
|
||||
{
|
||||
// Only modify the position if the hit was a slope and not a wall or ceiling.
|
||||
if (callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > 0.0)
|
||||
{
|
||||
// we moved up only a fraction of the step height
|
||||
m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction;
|
||||
if (m_interpolateUp == true)
|
||||
m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
||||
else
|
||||
m_currentPosition = m_targetPosition;
|
||||
}
|
||||
m_verticalVelocity = 0.0;
|
||||
m_verticalOffset = 0.0;
|
||||
}
|
||||
else {
|
||||
m_currentStepOffset = m_stepHeight;
|
||||
m_currentPosition = m_targetPosition;
|
||||
}
|
||||
}
|
||||
|
||||
void KinematicCharacterController::updateTargetPositionBasedOnCollision(const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
|
||||
{
|
||||
btVector3 movementDirection = m_targetPosition - m_currentPosition;
|
||||
btScalar movementLength = movementDirection.length();
|
||||
if (movementLength > SIMD_EPSILON)
|
||||
{
|
||||
movementDirection.normalize();
|
||||
|
||||
btVector3 reflectDir = computeReflectionDirection(movementDirection, hitNormal);
|
||||
reflectDir.normalize();
|
||||
|
||||
btVector3 parallelDir, perpindicularDir;
|
||||
|
||||
parallelDir = parallelComponent(reflectDir, hitNormal);
|
||||
perpindicularDir = perpindicularComponent(reflectDir, hitNormal);
|
||||
|
||||
m_targetPosition = m_currentPosition;
|
||||
if (0)//tangentMag != 0.0)
|
||||
{
|
||||
btVector3 parComponent = parallelDir * btScalar(tangentMag * movementLength);
|
||||
// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
|
||||
m_targetPosition += parComponent;
|
||||
}
|
||||
|
||||
if (normalMag != 0.0)
|
||||
{
|
||||
btVector3 perpComponent = perpindicularDir * btScalar(normalMag * movementLength);
|
||||
// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
|
||||
m_targetPosition += perpComponent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("movementLength don't normalize a zero vector\n");
|
||||
}
|
||||
}
|
||||
|
||||
void KinematicCharacterController::stepForwardAndStrafe(btCollisionWorld* collisionWorld, const btVector3& walkMove)
|
||||
{
|
||||
// printf("m_normalizedDirection=%f,%f,%f\n",
|
||||
// m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
|
||||
// phase 2: forward and strafe
|
||||
btTransform start, end;
|
||||
m_targetPosition = m_currentPosition + walkMove;
|
||||
|
||||
start.setIdentity();
|
||||
end.setIdentity();
|
||||
|
||||
btScalar fraction = 1.0;
|
||||
btScalar distance2 = (m_currentPosition - m_targetPosition).length2();
|
||||
// printf("distance2=%f\n",distance2);
|
||||
|
||||
if (m_touchingContact)
|
||||
{
|
||||
if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0))
|
||||
{
|
||||
//interferes with step movement
|
||||
//updateTargetPositionBasedOnCollision (m_touchingNormal);
|
||||
}
|
||||
}
|
||||
|
||||
int maxIter = 10;
|
||||
|
||||
while (fraction > btScalar(0.01) && maxIter-- > 0)
|
||||
{
|
||||
start.setOrigin(m_currentPosition);
|
||||
end.setOrigin(m_targetPosition);
|
||||
btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
|
||||
|
||||
btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, sweepDirNegative, btScalar(0.0));
|
||||
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
|
||||
btScalar margin = m_convexShape->getMargin();
|
||||
m_convexShape->setMargin(margin + m_addedMargin);
|
||||
|
||||
|
||||
if (m_useGhostObjectSweepTest)
|
||||
{
|
||||
m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||
}
|
||||
else
|
||||
{
|
||||
collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||
}
|
||||
|
||||
m_convexShape->setMargin(margin);
|
||||
|
||||
|
||||
fraction -= callback.m_closestHitFraction;
|
||||
|
||||
if (callback.hasHit())
|
||||
{
|
||||
// we moved only a fraction
|
||||
//btScalar hitDistance;
|
||||
//hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
|
||||
|
||||
// m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
||||
|
||||
updateTargetPositionBasedOnCollision(callback.m_hitNormalWorld);
|
||||
btVector3 currentDir = m_targetPosition - m_currentPosition;
|
||||
distance2 = currentDir.length2();
|
||||
if (distance2 > SIMD_EPSILON)
|
||||
{
|
||||
currentDir.normalize();
|
||||
/* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
|
||||
if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("currentDir: don't normalize a zero vector\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// we moved whole way
|
||||
m_currentPosition = m_targetPosition;
|
||||
}
|
||||
|
||||
// if (callback.m_closestHitFraction == 0.f)
|
||||
// break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KinematicCharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt)
|
||||
{
|
||||
btTransform start, end, end_double;
|
||||
bool runonce = false;
|
||||
|
||||
// phase 3: down
|
||||
/*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
|
||||
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep);
|
||||
btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
|
||||
btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity;
|
||||
m_targetPosition -= (step_drop + gravity_drop);*/
|
||||
|
||||
btVector3 orig_position = m_targetPosition;
|
||||
|
||||
btScalar downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
|
||||
|
||||
if (downVelocity > 0.0 && downVelocity > m_fallSpeed
|
||||
&& (m_wasOnGround || !m_wasJumping))
|
||||
downVelocity = m_fallSpeed;
|
||||
|
||||
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
|
||||
m_targetPosition -= step_drop;
|
||||
|
||||
btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
|
||||
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
btKinematicClosestNotMeConvexResultCallback callback2(m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
|
||||
callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
while (1)
|
||||
{
|
||||
start.setIdentity();
|
||||
end.setIdentity();
|
||||
|
||||
end_double.setIdentity();
|
||||
|
||||
start.setOrigin(m_currentPosition);
|
||||
end.setOrigin(m_targetPosition);
|
||||
|
||||
//set double test for 2x the step drop, to check for a large drop vs small drop
|
||||
end_double.setOrigin(m_targetPosition - step_drop);
|
||||
|
||||
if (m_useGhostObjectSweepTest)
|
||||
{
|
||||
m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||
|
||||
if (!callback.hasHit())
|
||||
{
|
||||
//test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
|
||||
m_ghostObject->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||
|
||||
if (!callback.hasHit())
|
||||
{
|
||||
//test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
|
||||
collisionWorld->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||
}
|
||||
}
|
||||
|
||||
btScalar downVelocity2 = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
|
||||
bool has_hit = false;
|
||||
if (bounce_fix == true)
|
||||
has_hit = callback.hasHit() || callback2.hasHit();
|
||||
else
|
||||
has_hit = callback2.hasHit();
|
||||
|
||||
if (downVelocity2 > 0.0 && downVelocity2 < m_stepHeight && has_hit == true && runonce == false
|
||||
&& (m_wasOnGround || !m_wasJumping))
|
||||
{
|
||||
//redo the velocity calculation when falling a small amount, for fast stairs motion
|
||||
//for larger falls, use the smoother/slower interpolated movement by not touching the target position
|
||||
|
||||
m_targetPosition = orig_position;
|
||||
downVelocity = m_stepHeight;
|
||||
|
||||
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
|
||||
m_targetPosition -= step_drop;
|
||||
runonce = true;
|
||||
continue; //re-run previous tests
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (callback.hasHit() || runonce == true)
|
||||
{
|
||||
// we dropped a fraction of the height -> hit floor
|
||||
|
||||
btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
|
||||
|
||||
//printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY());
|
||||
|
||||
if (bounce_fix == true)
|
||||
{
|
||||
if (full_drop == true)
|
||||
m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
||||
else
|
||||
//due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
|
||||
m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, fraction);
|
||||
}
|
||||
else
|
||||
m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
||||
|
||||
full_drop = false;
|
||||
|
||||
m_verticalVelocity = 0.0;
|
||||
m_verticalOffset = 0.0;
|
||||
m_wasJumping = false;
|
||||
}
|
||||
else {
|
||||
// we dropped the full height
|
||||
|
||||
full_drop = true;
|
||||
|
||||
if (bounce_fix == true)
|
||||
{
|
||||
downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
|
||||
if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
|
||||
{
|
||||
m_targetPosition += step_drop; //undo previous target change
|
||||
downVelocity = m_fallSpeed;
|
||||
step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
|
||||
m_targetPosition -= step_drop;
|
||||
}
|
||||
}
|
||||
//printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY());
|
||||
|
||||
m_currentPosition = m_targetPosition;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KinematicCharacterController::setWalkDirection
|
||||
(
|
||||
const btVector3& walkDirection
|
||||
)
|
||||
{
|
||||
m_useWalkDirection = true;
|
||||
m_walkDirection = walkDirection;
|
||||
m_normalizedDirection = getNormalizedVector(m_walkDirection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KinematicCharacterController::setVelocityForTimeInterval
|
||||
(
|
||||
const btVector3& velocity,
|
||||
btScalar timeInterval
|
||||
)
|
||||
{
|
||||
// printf("setVelocity!\n");
|
||||
// printf(" interval: %f\n", timeInterval);
|
||||
// printf(" velocity: (%f, %f, %f)\n",
|
||||
// velocity.x(), velocity.y(), velocity.z());
|
||||
|
||||
m_useWalkDirection = false;
|
||||
m_walkDirection = velocity;
|
||||
m_normalizedDirection = getNormalizedVector(m_walkDirection);
|
||||
m_velocityTimeInterval += timeInterval;
|
||||
}
|
||||
|
||||
void KinematicCharacterController::reset(btCollisionWorld* collisionWorld)
|
||||
{
|
||||
m_verticalVelocity = 0.0;
|
||||
m_verticalOffset = 0.0;
|
||||
m_wasOnGround = false;
|
||||
m_wasJumping = false;
|
||||
m_walkDirection.setValue(0, 0, 0);
|
||||
m_velocityTimeInterval = 0.0;
|
||||
|
||||
//clear pair cache
|
||||
btHashedOverlappingPairCache* cache = m_ghostObject->getOverlappingPairCache();
|
||||
while (cache->getOverlappingPairArray().size() > 0)
|
||||
{
|
||||
cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
|
||||
}
|
||||
}
|
||||
|
||||
void KinematicCharacterController::warp(const btVector3& origin)
|
||||
{
|
||||
btTransform xform;
|
||||
xform.setIdentity();
|
||||
xform.setOrigin(origin);
|
||||
m_ghostObject->setWorldTransform(xform);
|
||||
}
|
||||
|
||||
|
||||
void KinematicCharacterController::preStep(btCollisionWorld* collisionWorld)
|
||||
{
|
||||
|
||||
int numPenetrationLoops = 0;
|
||||
m_touchingContact = false;
|
||||
while (recoverFromPenetration(collisionWorld))
|
||||
{
|
||||
numPenetrationLoops++;
|
||||
m_touchingContact = true;
|
||||
if (numPenetrationLoops > 4)
|
||||
{
|
||||
//printf("character could not recover from penetration = %d\n", numPenetrationLoops);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
|
||||
m_targetPosition = m_currentPosition;
|
||||
// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void KinematicCharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar dt)
|
||||
{
|
||||
// printf("playerStep(): ");
|
||||
// printf(" dt = %f", dt);
|
||||
|
||||
// quick check...
|
||||
if (!m_useWalkDirection && m_velocityTimeInterval <= 0.0) {
|
||||
// printf("\n");
|
||||
return; // no motion
|
||||
}
|
||||
|
||||
m_wasOnGround = onGround();
|
||||
|
||||
// Update fall velocity.
|
||||
m_verticalVelocity -= m_gravity * dt;
|
||||
if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
|
||||
{
|
||||
m_verticalVelocity = m_jumpSpeed;
|
||||
}
|
||||
if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
|
||||
{
|
||||
m_verticalVelocity = -btFabs(m_fallSpeed);
|
||||
}
|
||||
m_verticalOffset = m_verticalVelocity * dt;
|
||||
|
||||
|
||||
btTransform xform;
|
||||
xform = m_ghostObject->getWorldTransform();
|
||||
|
||||
// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
|
||||
// printf("walkSpeed=%f\n",walkSpeed);
|
||||
|
||||
stepUp(collisionWorld);
|
||||
if (m_useWalkDirection) {
|
||||
stepForwardAndStrafe(collisionWorld, m_walkDirection);
|
||||
}
|
||||
else {
|
||||
//printf(" time: %f", m_velocityTimeInterval);
|
||||
// still have some time left for moving!
|
||||
if (m_velocityTimeInterval >= dt)
|
||||
{
|
||||
m_velocityTimeInterval -= dt;
|
||||
btVector3 move = m_walkDirection * dt;
|
||||
stepForwardAndStrafe(collisionWorld, move);
|
||||
}
|
||||
#if 0
|
||||
btScalar dtMoving =
|
||||
(dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
|
||||
m_velocityTimeInterval -= dt;
|
||||
|
||||
// how far will we move while we are moving?
|
||||
btVector3 move = m_walkDirection * dtMoving;
|
||||
|
||||
//printf(" dtMoving: %f", dtMoving);
|
||||
|
||||
// okay, step
|
||||
stepForwardAndStrafe(collisionWorld, move);
|
||||
#endif
|
||||
}
|
||||
stepDown(collisionWorld, dt);
|
||||
|
||||
// printf("\n");
|
||||
|
||||
xform.setOrigin(m_currentPosition);
|
||||
m_ghostObject->setWorldTransform(xform);
|
||||
}
|
||||
|
||||
void KinematicCharacterController::setFallSpeed(btScalar fallSpeed)
|
||||
{
|
||||
m_fallSpeed = fallSpeed;
|
||||
}
|
||||
|
||||
void KinematicCharacterController::setJumpSpeed(btScalar jumpSpeed)
|
||||
{
|
||||
m_jumpSpeed = jumpSpeed;
|
||||
}
|
||||
|
||||
void KinematicCharacterController::setMaxJumpHeight(btScalar maxJumpHeight)
|
||||
{
|
||||
m_maxJumpHeight = maxJumpHeight;
|
||||
}
|
||||
|
||||
bool KinematicCharacterController::canJump() const
|
||||
{
|
||||
//return onGround();
|
||||
return true; // Can jump even in the air!
|
||||
}
|
||||
|
||||
void KinematicCharacterController::jump(const btVector3& v)
|
||||
{
|
||||
if (!canJump())
|
||||
return;
|
||||
|
||||
// Add jump impulse:
|
||||
m_verticalVelocity += m_jumpSpeed;
|
||||
m_wasJumping = true;
|
||||
|
||||
#if 0
|
||||
currently no jumping.
|
||||
btTransform xform;
|
||||
m_rigidBody->getMotionState()->getWorldTransform(xform);
|
||||
btVector3 up = xform.getBasis()[1];
|
||||
up.normalize();
|
||||
btScalar magnitude = (btScalar(1.0) / m_rigidBody->getInvMass()) * btScalar(8.0);
|
||||
m_rigidBody->applyCentralImpulse(up * magnitude);
|
||||
#endif
|
||||
}
|
||||
|
||||
void KinematicCharacterController::setGravity(btScalar gravity)
|
||||
{
|
||||
m_gravity = gravity;
|
||||
}
|
||||
|
||||
btScalar KinematicCharacterController::getGravity() const
|
||||
{
|
||||
return m_gravity;
|
||||
}
|
||||
|
||||
void KinematicCharacterController::setMaxSlope(btScalar slopeRadians)
|
||||
{
|
||||
m_maxSlopeRadians = slopeRadians;
|
||||
m_maxSlopeCosine = btCos(slopeRadians);
|
||||
}
|
||||
|
||||
btScalar KinematicCharacterController::getMaxSlope() const
|
||||
{
|
||||
return m_maxSlopeRadians;
|
||||
}
|
||||
|
||||
bool KinematicCharacterController::onGround() const
|
||||
{
|
||||
return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0;
|
||||
}
|
||||
|
||||
|
||||
btVector3* KinematicCharacterController::getUpAxisDirections()
|
||||
{
|
||||
static btVector3 sUpAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
|
||||
|
||||
return sUpAxisDirection;
|
||||
}
|
||||
|
||||
void KinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
|
||||
{
|
||||
}
|
||||
|
||||
void KinematicCharacterController::setUpInterpolate(bool value)
|
||||
{
|
||||
m_interpolateUp = value;
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef KINEMATIC_CHARACTER_CONTROLLER_H
|
||||
#define KINEMATIC_CHARACTER_CONTROLLER_H
|
||||
|
||||
#include <LinearMath/btVector3.h>
|
||||
#include <BulletDynamics/Character/btCharacterControllerInterface.h>
|
||||
#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
|
||||
|
||||
|
||||
class btCollisionShape;
|
||||
class btConvexShape;
|
||||
class btRigidBody;
|
||||
class btCollisionWorld;
|
||||
class btCollisionDispatcher;
|
||||
class btPairCachingGhostObject;
|
||||
|
||||
///btKinematicCharacterController is an object that supports a sliding motion in a world.
|
||||
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
|
||||
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
|
||||
ATTRIBUTE_ALIGNED16(class) KinematicCharacterController : public btCharacterControllerInterface
|
||||
{
|
||||
protected:
|
||||
|
||||
btScalar m_halfHeight;
|
||||
|
||||
btPairCachingGhostObject* m_ghostObject;
|
||||
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
|
||||
|
||||
btScalar m_verticalVelocity;
|
||||
btScalar m_verticalOffset;
|
||||
btScalar m_fallSpeed;
|
||||
btScalar m_jumpSpeed;
|
||||
btScalar m_maxJumpHeight;
|
||||
btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
|
||||
btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
|
||||
btScalar m_gravity;
|
||||
|
||||
btScalar m_turnAngle;
|
||||
|
||||
btScalar m_stepHeight;
|
||||
|
||||
btScalar m_addedMargin;//@todo: remove this and fix the code
|
||||
|
||||
///this is the desired walk direction, set by the user
|
||||
btVector3 m_walkDirection;
|
||||
btVector3 m_normalizedDirection;
|
||||
|
||||
//some internal variables
|
||||
btVector3 m_currentPosition;
|
||||
btScalar m_currentStepOffset;
|
||||
btVector3 m_targetPosition;
|
||||
|
||||
///keep track of the contact manifolds
|
||||
btManifoldArray m_manifoldArray;
|
||||
|
||||
bool m_touchingContact;
|
||||
btVector3 m_touchingNormal;
|
||||
|
||||
bool m_wasOnGround;
|
||||
bool m_wasJumping;
|
||||
bool m_useGhostObjectSweepTest;
|
||||
bool m_useWalkDirection;
|
||||
btScalar m_velocityTimeInterval;
|
||||
int m_upAxis;
|
||||
|
||||
static btVector3* getUpAxisDirections();
|
||||
bool m_interpolateUp;
|
||||
bool full_drop;
|
||||
bool bounce_fix;
|
||||
|
||||
btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
|
||||
btVector3 parallelComponent(const btVector3& direction, const btVector3& normal);
|
||||
btVector3 perpindicularComponent(const btVector3& direction, const btVector3& normal);
|
||||
|
||||
bool recoverFromPenetration(btCollisionWorld* collisionWorld);
|
||||
void stepUp(btCollisionWorld* collisionWorld);
|
||||
void updateTargetPositionBasedOnCollision(const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
|
||||
void stepForwardAndStrafe(btCollisionWorld* collisionWorld, const btVector3& walkMove);
|
||||
void stepDown(btCollisionWorld* collisionWorld, btScalar dt);
|
||||
public:
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
KinematicCharacterController(btPairCachingGhostObject* ghostObject, btConvexShape* convexShape, btScalar stepHeight, int upAxis = 1);
|
||||
~KinematicCharacterController();
|
||||
|
||||
|
||||
///btActionInterface interface
|
||||
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime)
|
||||
{
|
||||
preStep(collisionWorld);
|
||||
playerStep(collisionWorld, deltaTime);
|
||||
}
|
||||
|
||||
///btActionInterface interface
|
||||
void debugDraw(btIDebugDraw* debugDrawer);
|
||||
|
||||
void setUpAxis(int axis)
|
||||
{
|
||||
if (axis < 0)
|
||||
axis = 0;
|
||||
if (axis > 2)
|
||||
axis = 2;
|
||||
m_upAxis = axis;
|
||||
}
|
||||
|
||||
/// This should probably be called setPositionIncrementPerSimulatorStep.
|
||||
/// This is neither a direction nor a velocity, but the amount to
|
||||
/// increment the position each simulation iteration, regardless
|
||||
/// of dt.
|
||||
/// This call will reset any velocity set by setVelocityForTimeInterval().
|
||||
virtual void setWalkDirection(const btVector3& walkDirection);
|
||||
|
||||
/// Caller provides a velocity with which the character should move for
|
||||
/// the given time period. After the time period, velocity is reset
|
||||
/// to zero.
|
||||
/// This call will reset any walk direction set by setWalkDirection().
|
||||
/// Negative time intervals will result in no motion.
|
||||
virtual void setVelocityForTimeInterval(const btVector3& velocity,
|
||||
btScalar timeInterval);
|
||||
|
||||
void reset(btCollisionWorld* collisionWorld);
|
||||
void warp(const btVector3& origin);
|
||||
|
||||
void preStep(btCollisionWorld* collisionWorld);
|
||||
void playerStep(btCollisionWorld* collisionWorld, btScalar dt);
|
||||
|
||||
void setFallSpeed(btScalar fallSpeed);
|
||||
void setJumpSpeed(btScalar jumpSpeed);
|
||||
void setMaxJumpHeight(btScalar maxJumpHeight);
|
||||
bool canJump() const;
|
||||
|
||||
void jump(const btVector3& v = btVector3());
|
||||
|
||||
void setGravity(btScalar gravity);
|
||||
btScalar getGravity() const;
|
||||
|
||||
/// The max slope determines the maximum angle that the controller can walk up.
|
||||
/// The slope angle is measured in radians.
|
||||
void setMaxSlope(btScalar slopeRadians);
|
||||
btScalar getMaxSlope() const;
|
||||
|
||||
btPairCachingGhostObject* getGhostObject();
|
||||
void setUseGhostSweepTest(bool useGhostObjectSweepTest)
|
||||
{
|
||||
m_useGhostObjectSweepTest = useGhostObjectSweepTest;
|
||||
}
|
||||
|
||||
bool onGround() const;
|
||||
void setUpInterpolate(bool value);
|
||||
|
||||
void reset() {}
|
||||
};
|
||||
|
||||
#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
#include "Groups.h"
|
||||
#include "UserPtr.h"
|
||||
#include "BulletDebugDraw.h"
|
||||
#include "Bullet.h"
|
||||
#include "KinematicCharacterController.h" // Improved btKinematicCharacterController.
|
||||
#include "CharacterController.h"
|
||||
|
||||
namespace verus
|
||||
{
|
||||
|
|
|
@ -53,14 +53,7 @@ namespace verus
|
|||
// Shadow:
|
||||
void BeginShadow(int split);
|
||||
void EndShadow(int split);
|
||||
RShadowMap GetShadowMap() { return _shadowMap; }
|
||||
bool IsRenderingShadow() const { return _shadowMap.IsRendering(); }
|
||||
int GetCurrentSplit() const { return _shadowMap.GetCurrentSplit(); }
|
||||
PCamera GetSunCameraCSM() { return _shadowMap.GetCameraCSM(); }
|
||||
RcVector4 GetSunShadowSplitRanges() const { return _shadowMap.GetSplitRanges(); }
|
||||
RcMatrix4 GetSunShadowMatrix(int split) const { return _shadowMap.GetShadowMatrix(split); }
|
||||
RcMatrix4 GetSunShadowMatrixDS(int split) const { return _shadowMap.GetShadowMatrixDS(split); }
|
||||
CGI::TexturePtr GetSunShadowTexture() const { return _shadowMap.GetTexture(); }
|
||||
RCascadedShadowMap GetShadowMap() { return _shadowMap; }
|
||||
|
||||
RcPoint3 GetEyePosition(PVector3 pDirFront = nullptr);
|
||||
};
|
||||
|
|
|
@ -57,7 +57,7 @@ void BaseMesh::Load(RcBlob blob)
|
|||
}
|
||||
else
|
||||
{
|
||||
throw VERUS_RECOVERABLE << "Load(), Invalid magic number";
|
||||
throw VERUS_RECOVERABLE << "Load(), invalid magic number";
|
||||
}
|
||||
}
|
||||
VERUS_LOG_WARN("Load(), Old X3D version");
|
||||
|
@ -90,6 +90,7 @@ void BaseMesh::LoadX3D3(RcBlob blob)
|
|||
{
|
||||
sp.ReadString(buffer);
|
||||
_numFaces = atoi(buffer);
|
||||
_indexCount = _numFaces * 3;
|
||||
VERUS_RT_ASSERT(_vIndices.empty());
|
||||
_vIndices.resize(_numFaces * 3);
|
||||
UINT16* pIB = _vIndices.data();
|
||||
|
@ -113,22 +114,18 @@ void BaseMesh::LoadX3D3(RcBlob blob)
|
|||
vPolyCheck.push_back(tag);
|
||||
}
|
||||
std::sort(vPolyCheck.begin(), vPolyCheck.end());
|
||||
if (std::adjacent_find(vPolyCheck.begin(), vPolyCheck.end()) != vPolyCheck.end())
|
||||
VERUS_LOG_SESSION(_C("WARNING: Duplicate triangle in " + _url));
|
||||
if (vPolyCheck.end() != std::adjacent_find(vPolyCheck.begin(), vPolyCheck.end()))
|
||||
VERUS_LOG_WARN("Duplicate triangle in " << _url);
|
||||
Vector<UINT16> vSorted;
|
||||
vSorted.assign(_vIndices.begin(), _vIndices.end());
|
||||
std::sort(vSorted.begin(), vSorted.end());
|
||||
bool isolatedVertex = false;
|
||||
std::adjacent_find(vSorted.begin(), vSorted.end(), [&isolatedVertex](const UINT16& a, const UINT16& b)
|
||||
{
|
||||
if (b - a > 1)
|
||||
isolatedVertex = true;
|
||||
return false;
|
||||
});
|
||||
if (vSorted.end() != std::adjacent_find(vSorted.begin(), vSorted.end(), [](const UINT16& a, const UINT16& b) {return b - a > 1; }))
|
||||
isolatedVertex = true;
|
||||
if (isolatedVertex)
|
||||
VERUS_LOG_SESSION(_C("WARNING: Isolated vertex in " + _url));
|
||||
VERUS_LOG_WARN("Isolated vertex in " << _url);
|
||||
if (_numVerts <= vSorted.back())
|
||||
VERUS_LOG_SESSION(_C("WARNING: Index out of bounds in " + _url));
|
||||
VERUS_LOG_WARN("Index out of bounds in " << _url);
|
||||
#endif
|
||||
sp.Read(&_posDeq[0], 12);
|
||||
sp.Read(&_posDeq[3], 12);
|
||||
|
@ -142,8 +139,8 @@ void BaseMesh::LoadX3D3(RcBlob blob)
|
|||
#ifdef VERUS_DEBUG
|
||||
const short* pMin = std::min_element(pVB[i]._pos, pVB[i]._pos + 3);
|
||||
const short* pMax = std::max_element(pVB[i]._pos, pVB[i]._pos + 3);
|
||||
mn = CMath::Min(mn, *pMin);
|
||||
mx = CMath::Max(mx, *pMax);
|
||||
mn = Math::Min(mn, *pMin);
|
||||
mx = Math::Max(mx, *pMax);
|
||||
#endif
|
||||
}
|
||||
#ifdef VERUS_DEBUG
|
||||
|
@ -210,8 +207,8 @@ void BaseMesh::LoadX3D3(RcBlob blob)
|
|||
#ifdef VERUS_DEBUG
|
||||
const short* pMin = std::min_element(pVB[i]._tc0, pVB[i]._tc0 + 2);
|
||||
const short* pMax = std::max_element(pVB[i]._tc0, pVB[i]._tc0 + 2);
|
||||
mn = CMath::Min(mn, *pMin);
|
||||
mx = CMath::Max(mx, *pMax);
|
||||
mn = Math::Min(mn, *pMin);
|
||||
mx = Math::Max(mx, *pMax);
|
||||
#endif
|
||||
}
|
||||
#ifdef VERUS_DEBUG
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace verus
|
|||
int _numVerts = 0;
|
||||
int _numFaces = 0;
|
||||
int _numBones = 0;
|
||||
int _indexCount = 0;
|
||||
float _posDeq[6];
|
||||
float _tc0Deq[4];
|
||||
float _tc1Deq[4];
|
||||
|
@ -61,6 +62,7 @@ namespace verus
|
|||
int GetNumVerts() const { return _numVerts; }
|
||||
int GetNumFaces() const { return _numFaces; }
|
||||
int GetNumBones() const { return _numBones; }
|
||||
int GetIndexCount() const { return _indexCount; }
|
||||
|
||||
virtual void Async_Run(CSZ url, RcBlob blob) override;
|
||||
|
||||
|
@ -101,6 +103,7 @@ namespace verus
|
|||
void VisitVertices(std::function<Continue(RcPoint3, int)> fn);
|
||||
|
||||
Anim::RSkeleton GetSkeleton() { return _skeleton; }
|
||||
Anim::RcSkeleton GetSkeleton() const { return _skeleton; }
|
||||
|
||||
String ToXmlString() const;
|
||||
String ToObjString() const;
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::Scene;
|
||||
|
||||
void CameraOrbit::Update()
|
||||
{
|
||||
const Vector3 toEye = Matrix3::rotationZYX(Vector3(_pitch, _yaw, 0)) * Vector3(0, 0, _radius);
|
||||
MoveEyeTo(_posAt + toEye);
|
||||
MainCamera::Update();
|
||||
}
|
||||
|
||||
void CameraOrbit::DragController_GetParams(float& x, float& y)
|
||||
{
|
||||
x = _yaw;
|
||||
y = _pitch;
|
||||
}
|
||||
|
||||
void CameraOrbit::DragController_SetParams(float x, float y)
|
||||
{
|
||||
_yaw = fmod(x, VERUS_2PI);
|
||||
_pitch = Math::Clamp(y, -VERUS_PI * 0.49f, VERUS_PI * 0.49f);
|
||||
Update();
|
||||
}
|
||||
|
||||
void CameraOrbit::DragController_GetRatio(float& x, float& y)
|
||||
{
|
||||
x = -VERUS_2PI / 1440.f;
|
||||
y = -VERUS_2PI / 1440.f;
|
||||
}
|
||||
|
||||
void CameraOrbit::MulRadiusBy(float a)
|
||||
{
|
||||
_radius *= a;
|
||||
Update();
|
||||
}
|
||||
|
||||
void CameraOrbit::SaveState(int slot)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << _C(Utils::I().GetWritablePath()) << "/CameraState.xml";
|
||||
IO::Xml xml;
|
||||
xml.SetFilename(_C(ss.str()));
|
||||
xml.Load();
|
||||
char txt[16];
|
||||
sprintf_s(txt, "slot%d", slot);
|
||||
char params[40];
|
||||
sprintf_s(params, "|%f %f %f", _pitch, _yaw, _radius);
|
||||
xml.Set(txt, _C(_posAt.ToString() + params));
|
||||
}
|
||||
|
||||
void CameraOrbit::LoadState(int slot)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << _C(Utils::I().GetWritablePath()) << "/CameraState.xml";
|
||||
IO::Xml xml;
|
||||
xml.SetFilename(_C(ss.str()));
|
||||
xml.Load();
|
||||
char txt[16];
|
||||
sprintf_s(txt, "slot%d", slot);
|
||||
CSZ v = xml.GetS(txt);
|
||||
if (v)
|
||||
{
|
||||
CSZ p = strchr(v, '|');
|
||||
_posAt.FromString(v);
|
||||
sscanf(p + 1, "%f %f %f", &_pitch, &_yaw, &_radius);
|
||||
_update |= Update::v;
|
||||
Update();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace Scene
|
||||
{
|
||||
class CameraOrbit : public MainCamera, public Input::DragControllerDelegate
|
||||
{
|
||||
float _pitch = 0;
|
||||
float _yaw = 0;
|
||||
float _radius = 10;
|
||||
|
||||
public:
|
||||
virtual void Update() override;
|
||||
|
||||
virtual void DragController_GetParams(float& x, float& y) override;
|
||||
virtual void DragController_SetParams(float x, float y) override;
|
||||
virtual void DragController_GetRatio(float& x, float& y) override;
|
||||
|
||||
float GetRadius() const { return _radius; }
|
||||
void MulRadiusBy(float a);
|
||||
|
||||
float GetPitch() const { return _pitch; }
|
||||
float GetYaw() const { return _yaw; }
|
||||
void SetPitch(float a) { _pitch = a; }
|
||||
void SetYaw(float a) { _yaw = a; }
|
||||
|
||||
virtual void SaveState(int slot) override;
|
||||
virtual void LoadState(int slot) override;
|
||||
};
|
||||
VERUS_TYPEDEFS(CameraOrbit);
|
||||
}
|
||||
}
|
|
@ -20,8 +20,8 @@ void Helpers::Init()
|
|||
|
||||
// Grid:
|
||||
_vGrid.reserve(92);
|
||||
const UINT32 colorMain = VERUS_COLOR_RGBA(0, 0, 0, 255);
|
||||
const UINT32 colorExtra = VERUS_COLOR_RGBA(80, 80, 80, 255);
|
||||
const UINT32 colorMain = VERUS_COLOR_RGBA(32, 32, 32, 255);
|
||||
const UINT32 colorExtra = VERUS_COLOR_RGBA(64, 64, 64, 255);
|
||||
const int edgeMin = 5, edgeMax = 55;
|
||||
for (int i = -edgeMin; i <= edgeMin; ++i)
|
||||
{
|
||||
|
@ -157,7 +157,7 @@ void Helpers::Done()
|
|||
void Helpers::DrawGrid()
|
||||
{
|
||||
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines);
|
||||
const int numLines = _vGrid.size() >> 1;
|
||||
const int numLines = Utils::Cast32(_vGrid.size() >> 1);
|
||||
VERUS_FOR(i, numLines)
|
||||
{
|
||||
CGI::DebugDraw::I().AddLine(
|
||||
|
@ -177,7 +177,7 @@ void Helpers::DrawBasis(PcTransform3 pMat, int axis, bool overlay)
|
|||
axis = 2;
|
||||
const UINT32 hover = VERUS_COLOR_RGBA(200, 200, 0, 255);
|
||||
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines, pMat, !overlay);
|
||||
const int numLines = (int)_vBasis.size() >> 1;
|
||||
const int numLines = Utils::Cast32(_vBasis.size() >> 1);
|
||||
VERUS_FOR(i, numLines)
|
||||
{
|
||||
const bool isHover = (i / 5 == axis);
|
||||
|
@ -192,7 +192,7 @@ void Helpers::DrawBasis(PcTransform3 pMat, int axis, bool overlay)
|
|||
void Helpers::DrawCircle(RcPoint3 pos, float radius, UINT32 color, Scene::RTerrain terrain)
|
||||
{
|
||||
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines, nullptr, false);
|
||||
const int numLines = _vCircle.size() >> 1;
|
||||
const int numLines = Utils::Cast32(_vCircle.size() >> 1);
|
||||
Point3 a = VMath::scale(_vCircle[0]._pos, radius) + Vector3(pos);
|
||||
float xz[2] = { a.getX(), a.getZ() };
|
||||
a.setY(terrain.GetHeightAt(xz));
|
||||
|
@ -211,7 +211,7 @@ void Helpers::DrawCircle(RcPoint3 pos, float radius, UINT32 color, Scene::RTerra
|
|||
void Helpers::DrawBox(PcTransform3 pMat, UINT32 color)
|
||||
{
|
||||
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines, pMat);
|
||||
const int numLines = _vBox.size() >> 1;
|
||||
const int numLines = Utils::Cast32(_vBox.size() >> 1);
|
||||
VERUS_FOR(i, numLines)
|
||||
{
|
||||
CGI::DebugDraw::I().AddLine(
|
||||
|
@ -226,7 +226,7 @@ void Helpers::DrawLight(RcPoint3 pos, UINT32 color, PcPoint3 pTarget)
|
|||
{
|
||||
Transform3 matW = Transform3::translation(Vector3(pos));
|
||||
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines, &matW);
|
||||
const int numLines = _vLight.size() >> 1;
|
||||
const int numLines = Utils::Cast32(_vLight.size() >> 1);
|
||||
VERUS_FOR(i, numLines)
|
||||
{
|
||||
CGI::DebugDraw::I().AddLine(
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
using namespace verus;
|
||||
using namespace verus::Scene;
|
||||
|
||||
CGI::ShaderPwn Mesh::s_shader;
|
||||
CGI::PipelinePwns<1> Mesh::s_pipe;
|
||||
CGI::ShaderPwn Mesh::s_shader;
|
||||
CGI::PipelinePwns<Mesh::PIPE_MAX> Mesh::s_pipe;
|
||||
|
||||
Mesh::UB_PerFrame Mesh::s_ubPerFrame;
|
||||
Mesh::UB_PerMaterialFS Mesh::s_ubPerMaterialFS;
|
||||
|
@ -42,6 +42,7 @@ void Mesh::InitStatic()
|
|||
|
||||
void Mesh::DoneStatic()
|
||||
{
|
||||
s_pipe.Done();
|
||||
s_shader.Done();
|
||||
}
|
||||
|
||||
|
@ -56,10 +57,48 @@ void Mesh::Init(RcDesc desc)
|
|||
|
||||
void Mesh::Done()
|
||||
{
|
||||
BaseMesh::Done();
|
||||
VERUS_DONE(Mesh);
|
||||
}
|
||||
|
||||
void Mesh::Bind(CGI::CommandBufferPtr cb, UINT32 bindingsFilter)
|
||||
void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
if (!s_pipe[pipe])
|
||||
{
|
||||
static CSZ branches[] =
|
||||
{
|
||||
"#",
|
||||
"#DepthRobotic",
|
||||
"#DepthSkinned",
|
||||
"#Instanced",
|
||||
"#Robotic",
|
||||
"#Skinned"
|
||||
};
|
||||
CGI::PipelineDesc pipeDesc(_geo, s_shader, branches[pipe], renderer.GetDS().GetRenderPassID());
|
||||
switch (pipe)
|
||||
{
|
||||
case PIPE_DEPTH_ROBOTIC:
|
||||
case PIPE_DEPTH_SKINNED:
|
||||
pipeDesc._colorAttachBlendEqs[0] = "";
|
||||
pipeDesc.DepthBiasEnable();
|
||||
default:
|
||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||
pipeDesc._colorAttachBlendEqs[3] = VERUS_COLOR_BLEND_OFF;
|
||||
}
|
||||
pipeDesc._vertexInputBindingsFilter = _bindingsMask;
|
||||
s_pipe[pipe].Init(pipeDesc);
|
||||
}
|
||||
cb->BindPipeline(s_pipe[pipe]);
|
||||
}
|
||||
|
||||
void Mesh::BindGeo(CGI::CommandBufferPtr cb)
|
||||
{
|
||||
BindGeo(cb, _bindingsMask);
|
||||
}
|
||||
|
||||
void Mesh::BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter)
|
||||
{
|
||||
cb->BindVertexBuffers(_geo, bindingsFilter);
|
||||
cb->BindIndexBuffer(_geo);
|
||||
|
@ -90,6 +129,12 @@ void Mesh::UpdateUniformBufferSkeletonVS()
|
|||
_skeleton.UpdateUniformBufferArray(s_ubSkeletonVS._vMatBones);
|
||||
}
|
||||
|
||||
void Mesh::UpdateUniformBufferPerObject(RcTransform3 tr)
|
||||
{
|
||||
s_ubPerObject._matW = tr.UniformBufferFormat();
|
||||
s_ubPerObject._userColor = Vector4(1, 0, 0, 1).GLM();
|
||||
}
|
||||
|
||||
void Mesh::UpdateUniformBufferPerObject(Point3 pos)
|
||||
{
|
||||
const Transform3 matT = Transform3::translation(Vector3(pos));
|
||||
|
|
|
@ -9,6 +9,17 @@ namespace verus
|
|||
public:
|
||||
#include "../Shaders/DS_Mesh.inc.hlsl"
|
||||
|
||||
enum PIPE
|
||||
{
|
||||
PIPE_MAIN,
|
||||
PIPE_DEPTH_ROBOTIC,
|
||||
PIPE_DEPTH_SKINNED,
|
||||
PIPE_INSTANCED,
|
||||
PIPE_ROBOTIC,
|
||||
PIPE_SKINNED,
|
||||
PIPE_MAX
|
||||
};
|
||||
|
||||
struct PerInstanceData
|
||||
{
|
||||
Vector4 _matPart0 = Vector4(0);
|
||||
|
@ -18,13 +29,13 @@ namespace verus
|
|||
};
|
||||
|
||||
private:
|
||||
static CGI::ShaderPwn s_shader;
|
||||
static CGI::PipelinePwns<1> s_pipe;
|
||||
static UB_PerFrame s_ubPerFrame;
|
||||
static UB_PerMaterialFS s_ubPerMaterialFS;
|
||||
static UB_PerMeshVS s_ubPerMeshVS;
|
||||
static UB_SkeletonVS s_ubSkeletonVS;
|
||||
static UB_PerObject s_ubPerObject;
|
||||
static CGI::ShaderPwn s_shader;
|
||||
static CGI::PipelinePwns<PIPE_MAX> s_pipe;
|
||||
static UB_PerFrame s_ubPerFrame;
|
||||
static UB_PerMaterialFS s_ubPerMaterialFS;
|
||||
static UB_PerMeshVS s_ubPerMeshVS;
|
||||
static UB_SkeletonVS s_ubSkeletonVS;
|
||||
static UB_PerObject s_ubPerObject;
|
||||
|
||||
CGI::GeometryPwn _geo;
|
||||
Vector<PerInstanceData> _vInstanceBuffer;
|
||||
|
@ -51,7 +62,9 @@ namespace verus
|
|||
void Init(RcDesc desc = Desc());
|
||||
void Done();
|
||||
|
||||
void Bind(CGI::CommandBufferPtr cb, UINT32 bindingsFilter);
|
||||
void BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb);
|
||||
void BindGeo(CGI::CommandBufferPtr cb);
|
||||
void BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter);
|
||||
|
||||
static CGI::ShaderPtr GetShader() { return s_shader; }
|
||||
static UB_PerMaterialFS& GetUbPerMaterialFS() { return s_ubPerMaterialFS; }
|
||||
|
@ -59,6 +72,7 @@ namespace verus
|
|||
void UpdateUniformBufferPerMaterialFS();
|
||||
void UpdateUniformBufferPerMeshVS();
|
||||
void UpdateUniformBufferSkeletonVS();
|
||||
void UpdateUniformBufferPerObject(RcTransform3 tr);
|
||||
void UpdateUniformBufferPerObject(Point3 pos);
|
||||
|
||||
CGI::GeometryPtr GetGeometry() const { return _geo; }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Camera.h"
|
||||
#include "CameraOrbit.h"
|
||||
#include "BaseMesh.h"
|
||||
#include "Mesh.h"
|
||||
#include "Terrain.h"
|
||||
|
|
|
@ -27,7 +27,7 @@ bool SceneManager::IsDrawingDepth(DrawDepth dd)
|
|||
if (DrawDepth::automatic == dd)
|
||||
{
|
||||
VERUS_QREF_ATMO;
|
||||
return atmo.IsRenderingShadow();
|
||||
return atmo.GetShadowMap().IsRendering();
|
||||
}
|
||||
else
|
||||
return DrawDepth::yes == dd;
|
||||
|
|
|
@ -91,6 +91,8 @@ void ShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar)
|
|||
_camera.Update();
|
||||
_pSceneCamera = sm.SetCamera(&_camera);
|
||||
|
||||
_config.setX((zFar - zNear) * 2);
|
||||
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rp, _fb,
|
||||
{
|
||||
_tex->GetClearValue()
|
||||
|
@ -355,6 +357,8 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
|||
_camera.Update();
|
||||
_pSceneCamera = sm.SetCamera(&_camera);
|
||||
|
||||
_config.setX((zFar - zNear) * 2);
|
||||
|
||||
if (0 == _currentSplit)
|
||||
{
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rp, _fb,
|
||||
|
@ -363,7 +367,7 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
|||
});
|
||||
}
|
||||
|
||||
const int s = _side / 2;
|
||||
const float s = static_cast<float>(_side / 2);
|
||||
switch (_currentSplit)
|
||||
{
|
||||
case 0: renderer.GetCommandBuffer()->SetViewport({ Vector4(0, 0, s, s) }); break;
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace verus
|
|||
protected:
|
||||
Matrix4 _matShadow;
|
||||
Matrix4 _matShadowDS;
|
||||
Vector4 _config = Vector4(0);
|
||||
CGI::TexturePwn _tex;
|
||||
Camera _camera;
|
||||
PCamera _pSceneCamera = nullptr;
|
||||
|
@ -37,6 +38,8 @@ namespace verus
|
|||
RcMatrix4 GetShadowMatrix() const;
|
||||
RcMatrix4 GetShadowMatrixDS() const;
|
||||
|
||||
RcVector4 GetConfig() { return _config; }
|
||||
|
||||
CGI::TexturePtr GetTexture() const;
|
||||
|
||||
PCamera GetSceneCamera() { return _pSceneCamera; }
|
||||
|
|
|
@ -43,8 +43,13 @@ void TerrainPhysics::Init(Physics::PUserPtr p, int w, int h, float heightScale)
|
|||
pBody->setFriction(Physics::Bullet::GetFriction(Physics::Material::wood));
|
||||
pBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::wood));
|
||||
pBody->setUserPointer(p);
|
||||
const int f = pBody->getCollisionFlags();
|
||||
pBody->setCollisionFlags(f | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
|
||||
#ifndef _DEBUG
|
||||
if (w >= 128 || h >= 128)
|
||||
#endif
|
||||
{
|
||||
const int f = pBody->getCollisionFlags();
|
||||
pBody->setCollisionFlags(f | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainPhysics::Done()
|
||||
|
@ -432,6 +437,7 @@ void Terrain::Init(RcDesc desc)
|
|||
_csidVS = s_shader->BindDescriptorSetTextures(0, { _tex[TEX_HEIGHTMAP] });
|
||||
|
||||
OnHeightModified();
|
||||
AddNewRigidBody();
|
||||
|
||||
_vLayerUrls.reserve(s_maxNumLayers);
|
||||
}
|
||||
|
@ -470,9 +476,9 @@ void Terrain::Layout()
|
|||
PCamera pPrevCamera = nullptr;
|
||||
Camera cam;
|
||||
// For CSM we need to create geometry beyond the view frustum (1st slice):
|
||||
if (settings._sceneShadowQuality >= App::Settings::ShadowQuality::cascaded && atmo.IsRenderingShadow())
|
||||
if (settings._sceneShadowQuality >= App::Settings::ShadowQuality::cascaded && atmo.GetShadowMap().IsRendering())
|
||||
{
|
||||
PCamera pCameraCSM = atmo.GetSunCameraCSM();
|
||||
PCamera pCameraCSM = atmo.GetShadowMap().GetCameraCSM();
|
||||
if (pCameraCSM)
|
||||
pPrevCamera = sm.SetCamera(pCameraCSM);
|
||||
}
|
||||
|
@ -905,16 +911,15 @@ void Terrain::OnHeightModified()
|
|||
UpdateHeightmapTexture();
|
||||
UpdateNormalsTexture();
|
||||
//UpdateLandTexture();
|
||||
//UpdateRigidBody();
|
||||
UpdateRigidBodyData();
|
||||
}
|
||||
|
||||
void Terrain::AddNewRigidBody()
|
||||
{
|
||||
UpdateRigidBody();
|
||||
_physics.Init(this, _mapSide, _mapSide, ConvertHeight(static_cast<short>(1)));
|
||||
}
|
||||
|
||||
void Terrain::UpdateRigidBody()
|
||||
void Terrain::UpdateRigidBodyData()
|
||||
{
|
||||
auto& v = _physics.GetData();
|
||||
v.resize(_mapSide * _mapSide);
|
||||
|
|
|
@ -208,7 +208,7 @@ namespace verus
|
|||
|
||||
// Physics:
|
||||
void AddNewRigidBody();
|
||||
void UpdateRigidBody();
|
||||
void UpdateRigidBodyData();
|
||||
};
|
||||
VERUS_TYPEDEFS(Terrain);
|
||||
}
|
||||
|
|
|
@ -236,6 +236,7 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
g_texShadow,
|
||||
g_samShadow,
|
||||
tcShadow,
|
||||
g_ubShadowFS._shadowConfig,
|
||||
g_ubShadowFS._splitRanges,
|
||||
g_ubShadowFS._matSunShadow,
|
||||
g_ubShadowFS._matSunShadowCSM1,
|
||||
|
@ -277,10 +278,12 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
so.target0.rgb = maxDiff * litRet.y; // Lambert's cosine law.
|
||||
so.target1.rgb = maxSpec * saturate(litRet.z * intensitySpec) + diffBoost;
|
||||
#endif
|
||||
so.target0.rgb = max(so.target0.rgb, emission.x * GetEmissionScale());
|
||||
so.target1.rgb = min(so.target1.rgb, 1.0 - emission.x * GetEmissionScale());
|
||||
so.target0.rgb = max(so.target0.rgb, emission.x);
|
||||
so.target1.rgb = min(so.target1.rgb, 1.0 - emission.x);
|
||||
so.target0.a = 1.0;
|
||||
so.target1.a = 1.0;
|
||||
so.target0 = HDRColorToSRGB(so.target0);
|
||||
so.target1 = HDRColorToSRGB(so.target1);
|
||||
}
|
||||
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
||||
else
|
||||
|
|
|
@ -21,11 +21,11 @@ VERUS_UBUFFER UB_PerMeshVS
|
|||
|
||||
VERUS_UBUFFER UB_ShadowFS
|
||||
{
|
||||
float4 _shadowTexSize;
|
||||
matrix _matSunShadow;
|
||||
matrix _matSunShadowCSM1;
|
||||
matrix _matSunShadowCSM2;
|
||||
matrix _matSunShadowCSM3;
|
||||
float4 _shadowConfig;
|
||||
float4 _splitRanges;
|
||||
};
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ FSO mainFS(VSO si)
|
|||
|
||||
const float4 rawAccDiff = g_texAccDiff.Sample(g_samAccDiff, si.tc0);
|
||||
const float4 rawAccSpec = g_texAccSpec.Sample(g_samAccSpec, si.tc0);
|
||||
const float4 accDiff = HDRColorToLinear(rawAccDiff);
|
||||
const float4 accSpec = HDRColorToLinear(rawAccSpec);
|
||||
|
||||
const float ssaoDiff = 1.0;
|
||||
const float ssaoSpec = 1.0;
|
||||
|
@ -79,12 +81,15 @@ FSO mainFS(VSO si)
|
|||
const float gray = Grayscale(colorAmbient);
|
||||
const float3 colorGround = lerp(colorAmbient, float3(1, 0.88, 0.47) * gray, saturate(gray * 14.0));
|
||||
const float3 colorAmbientFinal = lerp(colorGround, colorAmbient, saturate(normalW.y * 2.0 + 0.5));
|
||||
const float3 color = lerp(
|
||||
ApplyEmission(albedo, emission.x) * saturate(rawAccDiff.rgb * ssaoDiff + colorAmbientFinal * ssaoAmb) + rawAccSpec.rgb * ssaoSpec,
|
||||
g_ubComposeFS._fogColor.rgb,
|
||||
fog);
|
||||
|
||||
so.color.rgb = color;
|
||||
const float3 color =
|
||||
albedo * saturate(accDiff.rgb * ssaoDiff + colorAmbientFinal * ssaoAmb) +
|
||||
accSpec.rgb * ssaoSpec +
|
||||
albedo * emission.x;
|
||||
|
||||
const float3 colorWithFog = lerp(color, g_ubComposeFS._fogColor.rgb, fog);
|
||||
|
||||
so.color.rgb = lerp(colorWithFog, g_ubComposeFS._colorBackground.rgb, floor(rawGBuffer1) * g_ubComposeFS._colorBackground.a);
|
||||
so.color.a = 1.0;
|
||||
|
||||
return so;
|
||||
|
|
|
@ -8,6 +8,7 @@ VERUS_UBUFFER UB_ComposeFS
|
|||
{
|
||||
mataff _matInvV;
|
||||
float4 _colorAmbient;
|
||||
float4 _colorBackground;
|
||||
float4 _fogColor;
|
||||
float4 _zNearFarEx;
|
||||
};
|
||||
|
|
|
@ -155,9 +155,9 @@ void mainFS(VSO si)
|
|||
}
|
||||
#endif
|
||||
#else
|
||||
_DS_FSO mainFS(VSO si)
|
||||
DS_FSO mainFS(VSO si)
|
||||
{
|
||||
_DS_FSO so;
|
||||
DS_FSO so;
|
||||
|
||||
#ifdef DEF_SOLID
|
||||
DS_Reset(so);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "Lib.hlsl"
|
||||
#include "LibColor.hlsl"
|
||||
#include "LibDeferredShading.hlsl"
|
||||
#include "DS_Terrain.inc.hlsl"
|
||||
|
||||
|
|
|
@ -10,6 +10,27 @@ float4 ColorToSRGB(float4 x)
|
|||
return float4(rgb, x.a);
|
||||
}
|
||||
|
||||
// HDR from 0.0 to 12.0, where 1.0 - night, 10.0 - bright daylight, 11.0 - sky, 12.0 - ultra bright sun:
|
||||
float4 HDRColorToLinear(float4 x)
|
||||
{
|
||||
return float4(x.rgb * x.rgb * 12.0, x.a);
|
||||
}
|
||||
float4 HDRColorToSRGB(float4 x)
|
||||
{
|
||||
return float4(sqrt(saturate(x.rgb * (1.0 / 12.0))), x.a);
|
||||
}
|
||||
|
||||
// See: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||
float3 ToneMappingACES(float3 x)
|
||||
{
|
||||
const float a = 2.51f;
|
||||
const float b = 0.03f;
|
||||
const float c = 2.43f;
|
||||
const float d = 0.59f;
|
||||
const float e = 0.14f;
|
||||
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
|
||||
}
|
||||
|
||||
// See: https://en.wikipedia.org/wiki/Grayscale
|
||||
float Grayscale(float3 color)
|
||||
{
|
||||
|
@ -22,6 +43,12 @@ float3 Desaturate(float3 color, float alpha, float lum = 1.0)
|
|||
return lerp(color, gray, alpha);
|
||||
}
|
||||
|
||||
float3 DesaturateFilmic(float3 color)
|
||||
{
|
||||
const float gray = Grayscale(color);
|
||||
return lerp(color, gray, saturate(gray * gray * gray));
|
||||
}
|
||||
|
||||
// See: http://www.chilliant.com/rgb2hsv.html
|
||||
float3 ConvertRGBtoHCV(float3 color)
|
||||
{
|
||||
|
|
|
@ -5,15 +5,6 @@ struct DS_FSO
|
|||
float4 target2 : SV_Target2; // {normal, emission, motion}
|
||||
float4 target3 : SV_Target3; // {lam, metal, gloss}
|
||||
};
|
||||
struct DS_FSO_DEPTH
|
||||
{
|
||||
float4 color : SV_Target0;
|
||||
};
|
||||
#ifdef DEF_DEPTH
|
||||
# define _DS_FSO DS_FSO_DEPTH
|
||||
#else
|
||||
# define _DS_FSO DS_FSO
|
||||
#endif
|
||||
|
||||
struct DS_ACC_FSO
|
||||
{
|
||||
|
@ -37,16 +28,6 @@ float3 DecodeNormal(float2 enc)
|
|||
return float3(fenc * g, f2.y);
|
||||
}
|
||||
|
||||
float GetEmissionScale()
|
||||
{
|
||||
return 4.0;
|
||||
}
|
||||
|
||||
float3 ApplyEmission(float3 color, float emission)
|
||||
{
|
||||
return color * (1.0 + emission * GetEmissionScale());
|
||||
}
|
||||
|
||||
void DS_Reset(out DS_FSO so)
|
||||
{
|
||||
so.target0 = 0.0;
|
||||
|
@ -59,7 +40,7 @@ void DS_Test(out DS_FSO so, float3 normal, float spec, float gloss)
|
|||
{
|
||||
so.target0 = float4(0.5, 0.5, 0.5, spec);
|
||||
so.target1 = 0.0;
|
||||
so.target2 = float4(EncodeNormal(normal), 0.5, 0.5);
|
||||
so.target2 = float4(EncodeNormal(normal), 0.25, 0.5);
|
||||
so.target3 = float4(1.0 / 8.0, 0.5, 0.5, gloss * (1.0 / 64.0));
|
||||
}
|
||||
|
||||
|
@ -90,15 +71,14 @@ void DS_SetNormal(inout DS_FSO so, float3 normal)
|
|||
|
||||
float2 DS_GetEmission(float4 gbuffer)
|
||||
{
|
||||
const float x2 = gbuffer.b * 2.0;
|
||||
return float2(
|
||||
saturate(x2 - 1.0),
|
||||
saturate(1.0 - x2));
|
||||
const float2 em_skin = saturate((gbuffer.b - 0.25) * float2(1.0 / 0.75, -1.0 / 0.25));
|
||||
return float2(HDRColorToLinear(em_skin.x).r, em_skin.y);
|
||||
}
|
||||
|
||||
void DS_SetEmission(inout DS_FSO so, float emission, float skin)
|
||||
{
|
||||
so.target2.b = (emission - skin) * 0.5 + 0.5;
|
||||
const float em = HDRColorToSRGB(emission).r;
|
||||
so.target2.b = (3.0 * em - skin) * 0.25 + 0.25;
|
||||
}
|
||||
|
||||
float2 DS_GetLamScaleBias(float4 gbuffer)
|
||||
|
|
|
@ -44,7 +44,8 @@ float PCF(
|
|||
SamplerComparisonState samCmp,
|
||||
Texture2D tex,
|
||||
SamplerState sam,
|
||||
float3 tc)
|
||||
float3 tc,
|
||||
float4 config)
|
||||
{
|
||||
#if _SHADOW_QUALITY <= 2
|
||||
return texCmp.SampleCmpLevelZero(samCmp, tc.xy, tc.z).r;
|
||||
|
@ -72,14 +73,10 @@ float PCF(
|
|||
const float ret = sum * (1.0 / num);
|
||||
if (dzBlockers_numBlockers.y > 0.0)
|
||||
{
|
||||
#if _SHADOW_QUALITY <= 3
|
||||
const float scale = 655.36;
|
||||
#else
|
||||
const float scale = 20000.0;
|
||||
#endif
|
||||
const float penumbraScale = config.x;
|
||||
const float dzBlockers = dzBlockers_numBlockers.x / dzBlockers_numBlockers.y;
|
||||
const float penumbra = saturate(dzFrag - dzBlockers);
|
||||
const float contrast = 1.0 + max(0.0, 3.0 - penumbra * scale);
|
||||
const float contrast = 1.0 + max(0.0, 3.0 - penumbra * penumbraScale);
|
||||
return saturate((ret - 0.5) * contrast + 0.5);
|
||||
}
|
||||
else
|
||||
|
@ -94,12 +91,13 @@ float ShadowMap(
|
|||
SamplerComparisonState samCmp,
|
||||
Texture2D tex,
|
||||
SamplerState sam,
|
||||
float4 tc)
|
||||
float4 tc,
|
||||
float4 config)
|
||||
{
|
||||
#if _SHADOW_QUALITY <= 0
|
||||
return 1.0;
|
||||
#else
|
||||
const float ret = PCF(texCmp, samCmp, tex, sam, tc.xyz);
|
||||
const float ret = PCF(texCmp, samCmp, tex, sam, tc.xyz, config);
|
||||
const float2 center = tc.xy * 2.0 - 1.0;
|
||||
return max(ret, saturate(dot(center, center) * (9.0 / 4.0) - 1.0));
|
||||
#endif
|
||||
|
@ -111,6 +109,7 @@ float ShadowMapCSM(
|
|||
Texture2D tex,
|
||||
SamplerState sam,
|
||||
float4 pos,
|
||||
float4 config,
|
||||
float4 ranges,
|
||||
matrix mat0,
|
||||
matrix mat1,
|
||||
|
@ -130,28 +129,28 @@ float ShadowMapCSM(
|
|||
|
||||
contrast = contrastScale * contrastScale * contrastScale;
|
||||
const float3 tc = mul(p, mat0).xyz;
|
||||
ret = max(PCF(texCmp, samCmp, tex, sam, tc), fade);
|
||||
ret = max(PCF(texCmp, samCmp, tex, sam, tc, config), fade);
|
||||
}
|
||||
else if (pos.w > ranges.y)
|
||||
{
|
||||
contrast = contrastScale * contrastScale;
|
||||
const float3 tc = mul(p, mat1).xyz;
|
||||
ret = PCF(texCmp, samCmp, tex, sam, tc);
|
||||
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
|
||||
}
|
||||
else if (pos.w > ranges.z)
|
||||
{
|
||||
contrast = contrastScale;
|
||||
const float3 tc = mul(p, mat2).xyz;
|
||||
ret = PCF(texCmp, samCmp, tex, sam, tc);
|
||||
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float3 tc = mul(p, mat3).xyz;
|
||||
ret = PCF(texCmp, samCmp, tex, sam, tc);
|
||||
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
|
||||
}
|
||||
|
||||
return saturate((ret - 0.5) * contrast + 0.5);
|
||||
#else
|
||||
return ShadowMap(texCmp, samCmp, tex, sam, pos);
|
||||
return ShadowMap(texCmp, samCmp, tex, sam, pos, config);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -12,8 +12,14 @@ extern "C"
|
|||
# include "libb64/cdecode.h"
|
||||
#endif
|
||||
|
||||
// fast_atof (http://www.leapsecond.com/tools/fast_atof.c)
|
||||
extern "C"
|
||||
{
|
||||
double fast_atof(const char* p);
|
||||
}
|
||||
|
||||
// GLM (https://github.com/g-truc/glm):
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#define GLM_FORCE_CTOR_INIT
|
||||
#include "glm-0.9.9.6/glm/glm/glm.hpp"
|
||||
#include "glm-0.9.9.6/glm/glm/gtc/packing.hpp"
|
||||
#include "glm-0.9.9.6/glm/glm/gtc/quaternion.hpp"
|
||||
|
@ -33,6 +39,9 @@ extern "C"
|
|||
// MD5:
|
||||
#include "md5.h"
|
||||
|
||||
// Native File Dialog (https://github.com/mlabbe/nativefiledialog):
|
||||
#include "nativefiledialog/nfd.h"
|
||||
|
||||
// pugixml (https://pugixml.org/):
|
||||
#include "pugixml-1.10/pugixml.hpp"
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue