This commit is contained in:
Dmitry 2022-10-01 02:21:30 +03:00
parent 134983b861
commit b8941ef04e
187 changed files with 13593 additions and 8418 deletions

View File

@ -147,7 +147,7 @@ void HelloTexturedCubeGame::BaseGame_DrawView(CGI::RcViewDesc viewDesc)
renderer.GetFramebufferHandle_AutoWithDepth(renderer->GetSwapChainBufferIndex()),
{ Vector4(0), Vector4(1) });
Scene::RCamera camera = GetDefaultCamera();
World::RCamera camera = GetDefaultCamera();
camera.SetAspectRatio(renderer.GetCurrentViewAspectRatio());
camera.Update();
Transform3 matW = Transform3::rotationZYX(_rotation);

View File

@ -3,7 +3,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@ -12,6 +12,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
@ -72,7 +73,7 @@ struct VERTEX_CONSTANT_BUFFER_DX11
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
// Functions
@ -97,14 +98,14 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC
ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->VSSetShader(bd->pVertexShader, NULL, 0);
ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
ctx->PSSetShader(bd->pPixelShader, NULL, 0);
ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
ctx->GSSetShader(NULL, NULL, 0);
ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->GSSetShader(nullptr, nullptr, 0);
ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
// Setup blend state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
@ -126,7 +127,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
// Create and grow vertex/index buffers if needed
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
{
if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
@ -135,12 +136,12 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVB) < 0)
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
return;
}
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
{
if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
@ -148,7 +149,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pIB) < 0)
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
return;
}
@ -252,7 +253,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != NULL)
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
@ -326,13 +327,13 @@ static void ImGui_ImplDX11_CreateFontsTexture()
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
ID3D11Texture2D* pTexture = NULL;
ID3D11Texture2D* pTexture = nullptr;
D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
IM_ASSERT(pTexture != NULL);
IM_ASSERT(pTexture != nullptr);
// Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
@ -410,9 +411,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
}";
ID3DBlob* vertexShaderBlob;
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr)))
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &bd->pVertexShader) != S_OK)
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &bd->pVertexShader) != S_OK)
{
vertexShaderBlob->Release();
return false;
@ -440,7 +441,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVertexConstantBuffer);
bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer);
}
}
@ -463,9 +464,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
}";
ID3DBlob* pixelShaderBlob;
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr)))
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &bd->pPixelShader) != S_OK)
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &bd->pPixelShader) != S_OK)
{
pixelShaderBlob->Release();
return false;
@ -525,23 +526,23 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
if (!bd->pd3dDevice)
return;
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = NULL; }
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = NULL; }
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = NULL; }
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = NULL; }
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = NULL; }
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = NULL; }
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = NULL; }
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = NULL; }
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; }
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; }
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; }
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; }
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; }
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; }
}
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
@ -550,9 +551,9 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
// Get factory from device
IDXGIDevice* pDXGIDevice = NULL;
IDXGIAdapter* pDXGIAdapter = NULL;
IDXGIFactory* pFactory = NULL;
IDXGIDevice* pDXGIDevice = nullptr;
IDXGIAdapter* pDXGIAdapter = nullptr;
IDXGIFactory* pFactory = nullptr;
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
@ -573,22 +574,22 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
void ImGui_ImplDX11_Shutdown()
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplDX11_InvalidateDeviceObjects();
if (bd->pFactory) { bd->pFactory->Release(); }
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
io.BackendRendererName = NULL;
io.BackendRendererUserData = NULL;
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
IM_DELETE(bd);
}
void ImGui_ImplDX11_NewFrame()
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX11_Init()?");
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX11_Init()?");
if (!bd->pFontSampler)
ImGui_ImplDX11_CreateDeviceObjects();

View File

@ -3,7 +3,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.

View File

@ -3,7 +3,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
@ -20,6 +20,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer.
@ -49,6 +50,33 @@
#endif
// DirectX data
struct ImGui_ImplDX12_RenderBuffers;
struct ImGui_ImplDX12_Data
{
ID3D12Device* pd3dDevice;
ID3D12RootSignature* pRootSignature;
ID3D12PipelineState* pPipelineState;
DXGI_FORMAT RTVFormat;
ID3D12Resource* pFontTextureResource;
D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle;
D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle;
ID3D12DescriptorHeap* pd3dSrvDescHeap;
UINT numFramesInFlight;
ImGui_ImplDX12_RenderBuffers* pFrameResources;
UINT frameIndex;
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
// Buffers used during the rendering of a frame
struct ImGui_ImplDX12_RenderBuffers
{
ID3D12Resource* IndexBuffer;
@ -57,35 +85,11 @@ struct ImGui_ImplDX12_RenderBuffers
int VertexBufferSize;
};
struct ImGui_ImplDX12_Data
{
ID3D12Device* pd3dDevice;
ID3D12RootSignature* pRootSignature;
ID3D12PipelineState* pPipelineState;
DXGI_FORMAT RTVFormat;
ID3D12Resource* pFontTextureResource;
D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle;
D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle;
ImGui_ImplDX12_RenderBuffers* pFrameResources;
UINT numFramesInFlight;
UINT frameIndex;
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
};
struct VERTEX_CONSTANT_BUFFER_DX12
{
float mvp[4][4];
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
}
// Functions
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, ImGui_ImplDX12_RenderBuffers* fr)
{
@ -149,7 +153,7 @@ static inline void SafeRelease(T*& res)
{
if (res)
res->Release();
res = NULL;
res = nullptr;
}
// Render function
@ -166,7 +170,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[bd->frameIndex % bd->numFramesInFlight];
// Create and grow vertex/index buffers if needed
if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
if (fr->VertexBuffer == nullptr || fr->VertexBufferSize < draw_data->TotalVtxCount)
{
SafeRelease(fr->VertexBuffer);
fr->VertexBufferSize = draw_data->TotalVtxCount + 5000;
@ -186,10 +190,10 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
desc.SampleDesc.Count = 1;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->VertexBuffer)) < 0)
if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&fr->VertexBuffer)) < 0)
return;
}
if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount)
if (fr->IndexBuffer == nullptr || fr->IndexBufferSize < draw_data->TotalIdxCount)
{
SafeRelease(fr->IndexBuffer);
fr->IndexBufferSize = draw_data->TotalIdxCount + 10000;
@ -209,7 +213,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
desc.SampleDesc.Count = 1;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->IndexBuffer)) < 0)
if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&fr->IndexBuffer)) < 0)
return;
}
@ -248,7 +252,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != NULL)
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
@ -310,9 +314,9 @@ static void ImGui_ImplDX12_CreateFontsTexture()
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
ID3D12Resource* pTexture = NULL;
ID3D12Resource* pTexture = nullptr;
bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture));
D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&pTexture));
UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
UINT uploadSize = height * uploadPitch;
@ -332,12 +336,12 @@ static void ImGui_ImplDX12_CreateFontsTexture()
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
ID3D12Resource* uploadBuffer = NULL;
ID3D12Resource* uploadBuffer = nullptr;
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer));
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer));
IM_ASSERT(SUCCEEDED(hr));
void* mapped = NULL;
void* mapped = nullptr;
D3D12_RANGE range = { 0, uploadSize };
hr = uploadBuffer->Map(0, &range, &mapped);
IM_ASSERT(SUCCEEDED(hr));
@ -367,31 +371,31 @@ static void ImGui_ImplDX12_CreateFontsTexture()
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
ID3D12Fence* fence = NULL;
ID3D12Fence* fence = nullptr;
hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
IM_ASSERT(SUCCEEDED(hr));
HANDLE event = CreateEvent(0, 0, 0, 0);
IM_ASSERT(event != NULL);
IM_ASSERT(event != nullptr);
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queueDesc.NodeMask = 1;
ID3D12CommandQueue* cmdQueue = NULL;
ID3D12CommandQueue* cmdQueue = nullptr;
hr = bd->pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue));
IM_ASSERT(SUCCEEDED(hr));
ID3D12CommandAllocator* cmdAlloc = NULL;
ID3D12CommandAllocator* cmdAlloc = nullptr;
hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
IM_ASSERT(SUCCEEDED(hr));
ID3D12GraphicsCommandList* cmdList = NULL;
hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList));
ID3D12GraphicsCommandList* cmdList = nullptr;
hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, nullptr, IID_PPV_ARGS(&cmdList));
IM_ASSERT(SUCCEEDED(hr));
cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL);
cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, nullptr);
cmdList->ResourceBarrier(1, &barrier);
hr = cmdList->Close();
@ -496,7 +500,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
// Load d3d12.dll and D3D12SerializeRootSignature() function address dynamically to facilitate using with D3D12On7.
// See if any version of d3d12.dll is already loaded in the process. If so, give preference to that.
static HINSTANCE d3d12_dll = ::GetModuleHandleA("d3d12.dll");
if (d3d12_dll == NULL)
if (d3d12_dll == nullptr)
{
// Attempt to load d3d12.dll from local directories. This will only succeed if
// (1) the current OS is Windows 7, and
@ -504,23 +508,23 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
// See https://github.com/ocornut/imgui/pull/3696 for details.
const char* localD3d12Paths[] = { ".\\d3d12.dll", ".\\d3d12on7\\d3d12.dll", ".\\12on7\\d3d12.dll" }; // A. current directory, B. used by some games, C. used in Microsoft D3D12On7 sample
for (int i = 0; i < IM_ARRAYSIZE(localD3d12Paths); i++)
if ((d3d12_dll = ::LoadLibraryA(localD3d12Paths[i])) != NULL)
if ((d3d12_dll = ::LoadLibraryA(localD3d12Paths[i])) != nullptr)
break;
// If failed, we are on Windows >= 10.
if (d3d12_dll == NULL)
if (d3d12_dll == nullptr)
d3d12_dll = ::LoadLibraryA("d3d12.dll");
if (d3d12_dll == NULL)
if (d3d12_dll == nullptr)
return false;
}
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFn = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)::GetProcAddress(d3d12_dll, "D3D12SerializeRootSignature");
if (D3D12SerializeRootSignatureFn == NULL)
if (D3D12SerializeRootSignatureFn == nullptr)
return false;
ID3DBlob* blob = NULL;
if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK)
ID3DBlob* blob = nullptr;
if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, nullptr) != S_OK)
return false;
bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature));
@ -529,7 +533,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
// If you would like to use this DX12 sample code but remove this dependency you can:
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
// 1) compile once, save the compiled shader blobs into a file or source code and assign them to psoDesc.VS/PS [preferred solution]
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
@ -577,8 +581,8 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
return output;\
}";
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &vertexShaderBlob, NULL)))
return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_5_0", 0, 0, &vertexShaderBlob, nullptr)))
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
psoDesc.VS = { vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() };
// Create the input layout
@ -609,10 +613,10 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
return out_col; \
}";
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &pixelShaderBlob, NULL)))
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_5_0", 0, 0, &pixelShaderBlob, nullptr)))
{
vertexShaderBlob->Release();
return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
}
psoDesc.PS = { pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() };
}
@ -675,12 +679,12 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
if (!bd || !bd->pd3dDevice)
return;
ImGuiIO& io = ImGui::GetIO();
ImGuiIO& io = ImGui::GetIO();
SafeRelease(bd->pRootSignature);
SafeRelease(bd->pPipelineState);
SafeRelease(bd->pFontTextureResource);
io.Fonts->SetTexID(NULL); // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
io.Fonts->SetTexID(0); // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
for (UINT i = 0; i < bd->numFramesInFlight; i++)
{
@ -694,7 +698,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplDX12_Data* bd = IM_NEW(ImGui_ImplDX12_Data)();
@ -708,15 +712,15 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
bd->hFontSrvGpuDescHandle = font_srv_gpu_desc_handle;
bd->pFrameResources = new ImGui_ImplDX12_RenderBuffers[num_frames_in_flight];
bd->numFramesInFlight = num_frames_in_flight;
bd->pd3dSrvDescHeap = cbv_srv_heap;
bd->frameIndex = UINT_MAX;
IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports)
// Create buffers with a default size (they will later be grown as needed)
for (int i = 0; i < num_frames_in_flight; i++)
{
ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[i];
fr->IndexBuffer = NULL;
fr->VertexBuffer = NULL;
fr->IndexBuffer = nullptr;
fr->VertexBuffer = nullptr;
fr->IndexBufferSize = 10000;
fr->VertexBufferSize = 5000;
}
@ -727,20 +731,21 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
void ImGui_ImplDX12_Shutdown()
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
// Clean up windows and device objects
ImGui_ImplDX12_InvalidateDeviceObjects();
delete[] bd->pFrameResources;
io.BackendRendererName = NULL;
io.BackendRendererUserData = NULL;
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
IM_DELETE(bd);
}
void ImGui_ImplDX12_NewFrame()
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX12_Init()?");
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX12_Init()?");
if (!bd->pPipelineState)
ImGui_ImplDX12_CreateDeviceObjects();

View File

@ -3,7 +3,7 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
// See imgui_impl_dx12.cpp file for details.

View File

@ -2,8 +2,8 @@
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
@ -30,6 +30,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-01-02: Vulkan: Fixed sampler passed to ImGui_ImplVulkan_AddTexture() not being honored + removed a bunch of duplicate code.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symetry. (#914, #5738).
// 2022-01-20: Vulkan: Added support for ImTextureID as VkDescriptorSet. User need to call ImGui_ImplVulkan_AddTexture(). Building for 32-bit targets requires '#define ImTextureID ImU64'. (#914).
// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
@ -114,7 +118,7 @@ struct ImGui_ImplVulkan_Data
VkDeviceMemory UploadBufferMemory;
VkBuffer UploadBuffer;
// Render buffers
// Render buffers for main window
ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers;
ImGui_ImplVulkan_Data()
@ -190,6 +194,7 @@ static bool g_FunctionsLoaded = true;
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDeviceWaitIdle) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFlushMappedMemoryRanges) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeDescriptorSets) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetBufferMemoryRequirements) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetImageMemoryRequirements) \
@ -326,7 +331,7 @@ static uint32_t __glsl_shader_frag_spv[] =
// FIXME: multi-context support is not tested and probably dysfunctional in this backend.
static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
@ -445,7 +450,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Allocate array to store enough vertex/index buffers
ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers;
if (wrb->FrameRenderBuffers == NULL)
if (wrb->FrameRenderBuffers == nullptr)
{
wrb->Index = 0;
wrb->Count = v->ImageCount;
@ -467,8 +472,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
CreateOrResizeBuffer(rb->IndexBuffer, rb->IndexBufferMemory, rb->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
// Upload vertex/index data into a single contiguous GPU buffer
ImDrawVert* vtx_dst = NULL;
ImDrawIdx* idx_dst = NULL;
ImDrawVert* vtx_dst = nullptr;
ImDrawIdx* idx_dst = nullptr;
VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)(&vtx_dst));
check_vk_result(err);
err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)(&idx_dst));
@ -511,7 +516,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != NULL)
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
@ -550,7 +555,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->FontDescriptorSet);
desc_set[0] = bd->FontDescriptorSet;
}
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, NULL);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, nullptr);
// Draw
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
@ -563,7 +568,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
// Our last values will leak into user/application rendering IF:
// - Your app uses a pipeline with VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR dynamic state
// - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitely set that state.
// - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitly set that state.
// If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.
// In theory we should aim to backup/restore those values but I am not sure this is possible.
// We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
@ -655,7 +660,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
// Upload to Buffer:
{
char* map = NULL;
char* map = nullptr;
err = vkMapMemory(v->Device, bd->UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
check_vk_result(err);
memcpy(map, pixels, upload_size);
@ -681,7 +686,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy_barrier[0].subresourceRange.levelCount = 1;
copy_barrier[0].subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier);
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, copy_barrier);
VkBufferImageCopy region = {};
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@ -703,7 +708,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
use_barrier[0].subresourceRange.levelCount = 1;
use_barrier[0].subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier);
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier);
}
// Store our identifier
@ -736,72 +741,6 @@ static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAlloca
}
}
static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
if (bd->FontSampler)
return;
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
VkSamplerCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
VkResult err = vkCreateSampler(device, &info, allocator, &bd->FontSampler);
check_vk_result(err);
}
static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
if (bd->DescriptorSetLayout)
return;
ImGui_ImplVulkan_CreateFontSampler(device, allocator);
VkSampler sampler[1] = { bd->FontSampler };
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding[0].descriptorCount = 1;
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
binding[0].pImmutableSamplers = sampler;
VkDescriptorSetLayoutCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
info.pBindings = binding;
VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &bd->DescriptorSetLayout);
check_vk_result(err);
}
static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
if (bd->PipelineLayout)
return;
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
ImGui_ImplVulkan_CreateDescriptorSetLayout(device, allocator);
VkPushConstantRange push_constants[1] = {};
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_constants[0].offset = sizeof(float) * 0;
push_constants[0].size = sizeof(float) * 4;
VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = 1;
layout_info.pSetLayouts = set_layout;
layout_info.pushConstantRangeCount = 1;
layout_info.pPushConstantRanges = push_constants;
VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &bd->PipelineLayout);
check_vk_result(err);
}
static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
@ -886,8 +825,6 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states);
dynamic_state.pDynamicStates = dynamic_states;
ImGui_ImplVulkan_CreatePipelineLayout(device, allocator);
VkGraphicsPipelineCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.flags = bd->PipelineCreateFlags;
@ -916,6 +853,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
if (!bd->FontSampler)
{
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
VkSamplerCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
info.magFilter = VK_FILTER_LINEAR;
@ -933,12 +871,10 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
if (!bd->DescriptorSetLayout)
{
VkSampler sampler[1] = {bd->FontSampler};
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding[0].descriptorCount = 1;
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
binding[0].pImmutableSamplers = sampler;
VkDescriptorSetLayoutCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
@ -1013,7 +949,7 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch
#ifdef VK_NO_PROTOTYPES
#define IMGUI_VULKAN_FUNC_LOAD(func) \
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
if (func == NULL) \
if (func == nullptr) \
return false;
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD)
#undef IMGUI_VULKAN_FUNC_LOAD
@ -1030,7 +966,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplVulkan_Data* bd = IM_NEW(ImGui_ImplVulkan_Data)();
@ -1059,19 +995,19 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
void ImGui_ImplVulkan_Shutdown()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplVulkan_DestroyDeviceObjects();
io.BackendRendererName = NULL;
io.BackendRendererUserData = NULL;
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
IM_DELETE(bd);
}
void ImGui_ImplVulkan_NewFrame()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplVulkan_Init()?");
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplVulkan_Init()?");
IM_UNUSED(bd);
}
@ -1120,11 +1056,18 @@ VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image
write_desc[0].descriptorCount = 1;
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
write_desc[0].pImageInfo = desc_image;
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, NULL);
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, nullptr);
}
return descriptor_set;
}
void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
vkFreeDescriptorSets(v->Device, v->DescriptorPool, 1, &descriptor_set);
}
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
@ -1144,7 +1087,7 @@ VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image
VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
IM_ASSERT(request_formats != NULL);
IM_ASSERT(request_formats != nullptr);
IM_ASSERT(request_formats_count > 0);
// Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
@ -1152,7 +1095,7 @@ VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physic
// Additionally several new color spaces were introduced with Vulkan Spec v1.0.40,
// hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used.
uint32_t avail_count;
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, NULL);
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, nullptr);
ImVector<VkSurfaceFormatKHR> avail_format;
avail_format.resize((int)avail_count);
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, avail_format.Data);
@ -1189,12 +1132,12 @@ VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physic
VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
IM_ASSERT(request_modes != NULL);
IM_ASSERT(request_modes != nullptr);
IM_ASSERT(request_modes_count > 0);
// Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
uint32_t avail_count = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, NULL);
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, nullptr);
ImVector<VkPresentModeKHR> avail_modes;
avail_modes.resize((int)avail_count);
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, avail_modes.Data);
@ -1286,8 +1229,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
}
IM_FREE(wd->Frames);
IM_FREE(wd->FrameSemaphores);
wd->Frames = NULL;
wd->FrameSemaphores = NULL;
wd->Frames = nullptr;
wd->FrameSemaphores = nullptr;
wd->ImageCount = 0;
if (wd->RenderPass)
vkDestroyRenderPass(device, wd->RenderPass, allocator);
@ -1334,7 +1277,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
}
err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain);
check_vk_result(err);
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, NULL);
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, nullptr);
check_vk_result(err);
VkImage backbuffers[16] = {};
IM_ASSERT(wd->ImageCount >= min_image_count);
@ -1342,7 +1285,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
check_vk_result(err);
IM_ASSERT(wd->Frames == NULL);
IM_ASSERT(wd->Frames == nullptr);
wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount);
wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount);
memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);
@ -1457,8 +1400,8 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
}
IM_FREE(wd->Frames);
IM_FREE(wd->FrameSemaphores);
wd->Frames = NULL;
wd->FrameSemaphores = NULL;
wd->Frames = nullptr;
wd->FrameSemaphores = nullptr;
vkDestroyPipeline(device, wd->Pipeline, allocator);
vkDestroyRenderPass(device, wd->RenderPass, allocator);
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
@ -1502,7 +1445,7 @@ void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVul
for (uint32_t n = 0; n < buffers->Count; n++)
ImGui_ImplVulkanH_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator);
IM_FREE(buffers->FrameRenderBuffers);
buffers->FrameRenderBuffers = NULL;
buffers->FrameRenderBuffers = nullptr;
buffers->Index = 0;
buffers->Count = 0;
}

View File

@ -2,8 +2,8 @@
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
// See imgui_impl_vulkan.cpp file for details.
@ -72,12 +72,14 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
// Register a texture (VkDescriptorSet == ImTextureID)
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem, please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem
// Please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout);
IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);
// Optional: load Vulkan functions with a custom function loader
// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = NULL);
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
@ -86,8 +88,8 @@ IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*l
// You probably do NOT need to use or care about those functions.
// Those functions only exist because:
// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
// 2) the upcoming multi-viewport feature will need them internally.
// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,
// 2) the multi-viewport / platform window implementation needs them internally.
// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
// but it is too much code to duplicate everywhere so we exceptionally expose them.
//
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).

View File

@ -57,15 +57,20 @@ public:
CMP_BOOL TextureTool::FeedbackProc(CMP_FLOAT progress, CMP_DWORD_PTR pUser1, CMP_DWORD_PTR pUser2)
{
const int edge = static_cast<int>(progress * 0.5f + 0.5f);
std::wcout << _T("\rCompressing [");
wchar_t buffer[80];
wcscpy(buffer, _T("\rCompressing ["));
size_t offset = wcslen(buffer);
VERUS_FOR(i, 50)
{
if (i < edge)
std::wcout << _T("=");
buffer[i + offset] = _T('=');
else
std::wcout << _T(" ");
buffer[i + offset] = _T(' ');
}
std::wcout << _T("] ") << std::setw(3) << static_cast<int>(progress + 0.5f) << _T("%") << std::flush;
buffer[offset + 50] = 0;
wsprintf(buffer + wcslen(buffer), _T("] %3d%%"), static_cast<int>(progress + 0.5f));
wprintf(buffer);
fflush(stdout);
return false;
}

View File

@ -3,8 +3,8 @@
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>C:\Compressonator_4.2.5185\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.89\src;C:\Home\Middleware\bullet3-2.89\Extras;C:\Home\Middleware\libogg-1.3.5\include;C:\Home\Middleware\libvorbis-1.3.7\include;C:\Home\Middleware\openal-soft-1.22.0-bin\include;C:\Home\Middleware\OpenXR-SDK-release-1.0.25\include;C:\Home\Middleware\SDL2-2.0.22\include;C:\VulkanSDK\1.3.216.0\Include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Compressonator_4.2.5185\lib\VS2017\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\libogg-1.3.5\lib;C:\Home\Middleware\libvorbis-1.3.7\lib2;C:\Home\Middleware\openal-soft-1.22.0-bin\libs\Win64;C:\Home\Middleware\OpenXR-SDK-release-1.0.25\lib;C:\Home\Middleware\SDL2-2.0.22\lib\x64;C:\VulkanSDK\1.3.216.0\Lib;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Compressonator_4.3.206\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.89\src;C:\Home\Middleware\bullet3-2.89\Extras;C:\Home\Middleware\libogg-1.3.5\include;C:\Home\Middleware\libvorbis-1.3.7\include;C:\Home\Middleware\openal-soft-1.22.0-bin\include;C:\Home\Middleware\OpenXR-SDK-release-1.0.25\include;C:\Home\Middleware\SDL2-2.0.22\include;C:\VulkanSDK\1.3.239.0\Include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Compressonator_4.3.206\lib\VS2019\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\libogg-1.3.5\lib;C:\Home\Middleware\libvorbis-1.3.7\lib2;C:\Home\Middleware\openal-soft-1.22.0-bin\libs\Win64;C:\Home\Middleware\OpenXR-SDK-release-1.0.25\lib;C:\Home\Middleware\SDL2-2.0.22\lib\x64;C:\VulkanSDK\1.3.239.0\Lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />

View File

@ -222,8 +222,8 @@
<ClInclude Include="src\Global\SyntaxHighlight.h" />
<ClInclude Include="src\Global\Typedef.h" />
<ClInclude Include="src\IO\StreamPtr.h" />
<ClInclude Include="src\IO\Vwx.h" />
<ClInclude Include="src\IO\Xml.h" />
<ClInclude Include="src\IO\Xxx.h" />
<ClInclude Include="src\Math\Bounds.h" />
<ClInclude Include="src\Math\Frustum.h" />
<ClInclude Include="src\Math\Math.h" />
@ -250,40 +250,11 @@
<ClInclude Include="src\Physics\Spring.h" />
<ClInclude Include="src\Physics\UserPtr.h" />
<ClInclude Include="src\Physics\Vehicle.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\CubeMapBaker.h" />
<ClInclude Include="src\Scene\EditorTerrain.h" />
<ClInclude Include="src\Scene\Forest.h" />
<ClInclude Include="src\Scene\Grass.h" />
<ClInclude Include="src\Scene\Helpers.h" />
<ClInclude Include="src\Scene\LightMapBaker.h" />
<ClInclude Include="src\Scene\MaterialManager.h" />
<ClInclude Include="src\Scene\Mesh.h" />
<ClInclude Include="src\Scene\Scatter.h" />
<ClInclude Include="src\Scene\Scene.h" />
<ClInclude Include="src\Scene\SceneManager.h" />
<ClInclude Include="src\Scene\SceneNodes\Block.h" />
<ClInclude Include="src\Scene\SceneNodes\Emitter.h" />
<ClInclude Include="src\Scene\SceneNodes\Light.h" />
<ClInclude Include="src\Scene\SceneNodes\Model.h" />
<ClInclude Include="src\Scene\SceneNodes\Prefab.h" />
<ClInclude Include="src\Scene\SceneNodes\SceneNode.h" />
<ClInclude Include="src\Scene\SceneNodes\SceneNodes.h" />
<ClInclude Include="src\Scene\SceneNodes\SceneParticles.h" />
<ClInclude Include="src\Scene\SceneNodes\Site.h" />
<ClInclude Include="src\Scene\SceneNodes\Trigger.h" />
<ClInclude Include="src\Scene\SceneNodes\Types.h" />
<ClInclude Include="src\Scene\ShadowMapBaker.h" />
<ClInclude Include="src\Scene\Terrain.h" />
<ClInclude Include="src\Scene\Water.h" />
<ClInclude Include="src\Security\CipherRC4.h" />
<ClInclude Include="src\Security\Security.h" />
<ClInclude Include="src\ThirdParty\imgui\imconfig.h" />
<ClInclude Include="src\ThirdParty\imgui\imgui.h" />
<ClInclude Include="src\ThirdParty\imgui\imgui_impl_sdl.h" />
<ClInclude Include="src\ThirdParty\imgui\imgui_impl_sdl2.h" />
<ClInclude Include="src\ThirdParty\imgui\imgui_internal.h" />
<ClInclude Include="src\ThirdParty\imgui\imstb_rectpack.h" />
<ClInclude Include="src\ThirdParty\imgui\imstb_textedit.h" />
@ -316,6 +287,41 @@
<ClInclude Include="src\ThirdParty\zlib-1.2.12\zlib.h" />
<ClInclude Include="src\ThirdParty\zlib-1.2.12\zutil.h" />
<ClInclude Include="src\verus.h" />
<ClInclude Include="src\World\Atmosphere.h" />
<ClInclude Include="src\World\CubeMapBaker.h" />
<ClInclude Include="src\World\EditorOverlays.h" />
<ClInclude Include="src\World\EditorTerrain.h" />
<ClInclude Include="src\World\Forest.h" />
<ClInclude Include="src\World\Grass.h" />
<ClInclude Include="src\World\LightMapBaker.h" />
<ClInclude Include="src\World\BaseMesh.h" />
<ClInclude Include="src\World\Camera.h" />
<ClInclude Include="src\World\Scatter.h" />
<ClInclude Include="src\World\ShadowMapBaker.h" />
<ClInclude Include="src\World\Terrain.h" />
<ClInclude Include="src\World\Water.h" />
<ClInclude Include="src\World\World.h" />
<ClInclude Include="src\World\WorldManager.h" />
<ClInclude Include="src\World\MaterialManager.h" />
<ClInclude Include="src\World\Mesh.h" />
<ClInclude Include="src\World\WorldNodes\BlockNode.h" />
<ClInclude Include="src\World\WorldNodes\ControlPointNode.h" />
<ClInclude Include="src\World\WorldNodes\EmitterNode.h" />
<ClInclude Include="src\World\WorldNodes\InstanceNode.h" />
<ClInclude Include="src\World\WorldNodes\LightNode.h" />
<ClInclude Include="src\World\WorldNodes\ModelNode.h" />
<ClInclude Include="src\World\WorldNodes\ParticlesNode.h" />
<ClInclude Include="src\World\WorldNodes\PathNode.h" />
<ClInclude Include="src\World\WorldNodes\PhysicsNode.h" />
<ClInclude Include="src\World\WorldNodes\PrefabNode.h" />
<ClInclude Include="src\World\WorldNodes\ShakerNode.h" />
<ClInclude Include="src\World\WorldNodes\SoundNode.h" />
<ClInclude Include="src\World\WorldNodes\TerrainNode.h" />
<ClInclude Include="src\World\WorldNodes\Types.h" />
<ClInclude Include="src\World\WorldNodes\BaseNode.h" />
<ClInclude Include="src\World\WorldNodes\WorldNodes.h" />
<ClInclude Include="src\World\OrbitingCamera.h" />
<ClInclude Include="src\World\WorldUtils.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\AI\AI.cpp" />
@ -422,8 +428,8 @@
<ClCompile Include="src\IO\IO.cpp" />
<ClCompile Include="src\IO\Json.cpp" />
<ClCompile Include="src\IO\Dictionary.cpp" />
<ClCompile Include="src\IO\Vwx.cpp" />
<ClCompile Include="src\IO\Xml.cpp" />
<ClCompile Include="src\IO\Xxx.cpp" />
<ClCompile Include="src\Math\Bounds.cpp" />
<ClCompile Include="src\Math\Frustum.cpp" />
<ClCompile Include="src\Math\Math.cpp" />
@ -451,34 +457,6 @@
<ClCompile Include="src\Physics\Physics.cpp" />
<ClCompile Include="src\Physics\Spring.cpp" />
<ClCompile Include="src\Physics\Vehicle.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\CubeMapBaker.cpp" />
<ClCompile Include="src\Scene\EditorTerrain.cpp" />
<ClCompile Include="src\Scene\Forest.cpp" />
<ClCompile Include="src\Scene\Grass.cpp" />
<ClCompile Include="src\Scene\Helpers.cpp" />
<ClCompile Include="src\Scene\LightMapBaker.cpp" />
<ClCompile Include="src\Scene\MaterialManager.cpp" />
<ClCompile Include="src\Scene\Mesh.cpp" />
<ClCompile Include="src\Scene\Scatter.cpp" />
<ClCompile Include="src\Scene\Scene.cpp" />
<ClCompile Include="src\Scene\SceneManager.cpp" />
<ClCompile Include="src\Scene\SceneNodes\Block.cpp" />
<ClCompile Include="src\Scene\SceneNodes\Emitter.cpp" />
<ClCompile Include="src\Scene\SceneNodes\Light.cpp" />
<ClCompile Include="src\Scene\SceneNodes\Model.cpp" />
<ClCompile Include="src\Scene\SceneNodes\Prefab.cpp" />
<ClCompile Include="src\Scene\SceneNodes\SceneNode.cpp" />
<ClCompile Include="src\Scene\SceneNodes\SceneNodes.cpp" />
<ClCompile Include="src\Scene\SceneNodes\SceneParticles.cpp" />
<ClCompile Include="src\Scene\SceneNodes\Site.cpp" />
<ClCompile Include="src\Scene\SceneNodes\Trigger.cpp" />
<ClCompile Include="src\Scene\ShadowMapBaker.cpp" />
<ClCompile Include="src\Scene\Terrain.cpp" />
<ClCompile Include="src\Scene\Water.cpp" />
<ClCompile Include="src\ThirdParty\fast_atof.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
@ -495,7 +473,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\ThirdParty\imgui\imgui_impl_sdl.cpp">
<ClCompile Include="src\ThirdParty\imgui\imgui_impl_sdl2.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
@ -641,6 +619,40 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\World\Atmosphere.cpp" />
<ClCompile Include="src\World\CubeMapBaker.cpp" />
<ClCompile Include="src\World\EditorOverlays.cpp" />
<ClCompile Include="src\World\EditorTerrain.cpp" />
<ClCompile Include="src\World\Forest.cpp" />
<ClCompile Include="src\World\Grass.cpp" />
<ClCompile Include="src\World\LightMapBaker.cpp" />
<ClCompile Include="src\World\BaseMesh.cpp" />
<ClCompile Include="src\World\Camera.cpp" />
<ClCompile Include="src\World\Scatter.cpp" />
<ClCompile Include="src\World\ShadowMapBaker.cpp" />
<ClCompile Include="src\World\Terrain.cpp" />
<ClCompile Include="src\World\Water.cpp" />
<ClCompile Include="src\World\World.cpp" />
<ClCompile Include="src\World\WorldManager.cpp" />
<ClCompile Include="src\World\MaterialManager.cpp" />
<ClCompile Include="src\World\Mesh.cpp" />
<ClCompile Include="src\World\WorldNodes\BlockNode.cpp" />
<ClCompile Include="src\World\WorldNodes\ControlPointNode.cpp" />
<ClCompile Include="src\World\WorldNodes\EmitterNode.cpp" />
<ClCompile Include="src\World\WorldNodes\InstanceNode.cpp" />
<ClCompile Include="src\World\WorldNodes\LightNode.cpp" />
<ClCompile Include="src\World\WorldNodes\ModelNode.cpp" />
<ClCompile Include="src\World\WorldNodes\ParticlesNode.cpp" />
<ClCompile Include="src\World\WorldNodes\PathNode.cpp" />
<ClCompile Include="src\World\WorldNodes\PhysicsNode.cpp" />
<ClCompile Include="src\World\WorldNodes\BaseNode.cpp" />
<ClCompile Include="src\World\WorldNodes\PrefabNode.cpp" />
<ClCompile Include="src\World\WorldNodes\ShakerNode.cpp" />
<ClCompile Include="src\World\WorldNodes\SoundNode.cpp" />
<ClCompile Include="src\World\WorldNodes\TerrainNode.cpp" />
<ClCompile Include="src\World\WorldNodes\WorldNodes.cpp" />
<ClCompile Include="src\World\OrbitingCamera.cpp" />
<ClCompile Include="src\World\WorldUtils.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="src\Shaders\DS_Mesh.hlsl">

View File

@ -52,9 +52,6 @@
<Filter Include="src\ThirdParty\libb64">
<UniqueIdentifier>{2c793d5f-0a67-4166-8490-3ef154bdb4fc}</UniqueIdentifier>
</Filter>
<Filter Include="src\Scene">
<UniqueIdentifier>{28848bdf-d48d-40a2-92a2-6946c609e14e}</UniqueIdentifier>
</Filter>
<Filter Include="src\AI">
<UniqueIdentifier>{6c75fda0-ca2a-4925-9260-1d069a48b1b7}</UniqueIdentifier>
</Filter>
@ -85,9 +82,6 @@
<Filter Include="src\Effects">
<UniqueIdentifier>{5ea015f8-8b97-4159-ad67-d71abdba3c91}</UniqueIdentifier>
</Filter>
<Filter Include="src\Scene\SceneNodes">
<UniqueIdentifier>{07af1a9e-5cdc-4264-811b-d958ec70a709}</UniqueIdentifier>
</Filter>
<Filter Include="src\ThirdParty\tinygltf-2.5.0">
<UniqueIdentifier>{54a71e7f-5bcd-480d-990e-0d5e79d7ded9}</UniqueIdentifier>
</Filter>
@ -106,6 +100,12 @@
<Filter Include="src\ThirdParty\zlib-1.2.12">
<UniqueIdentifier>{8b9c1325-e416-4e6f-8277-1d5e18f9122f}</UniqueIdentifier>
</Filter>
<Filter Include="src\World">
<UniqueIdentifier>{aa98d856-89ce-4d9d-af82-94b6f935fc27}</UniqueIdentifier>
</Filter>
<Filter Include="src\World\WorldNodes">
<UniqueIdentifier>{3b005273-c21c-493a-a7e2-c5e41cbbc66a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CGI\BaseGeometry.h">
@ -312,12 +312,6 @@
<ClInclude Include="src\Global\Timer.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Camera.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Scene.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Math\Frustum.h">
<Filter>src\Math</Filter>
</ClInclude>
@ -339,12 +333,6 @@
<ClInclude Include="src\AI\Turret.h">
<Filter>src\AI</Filter>
</ClInclude>
<ClInclude Include="src\Scene\BaseMesh.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Mesh.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\IO\StreamPtr.h">
<Filter>src\IO</Filter>
</ClInclude>
@ -420,12 +408,6 @@
<ClInclude Include="src\ThirdParty\json.hpp">
<Filter>src\ThirdParty</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Terrain.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Atmosphere.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Physics\Bullet.h">
<Filter>src\Physics</Filter>
</ClInclude>
@ -444,21 +426,9 @@
<ClInclude Include="src\Math\Quadtree.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\Scene\MaterialManager.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneManager.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Physics\UserPtr.h">
<Filter>src\Physics</Filter>
</ClInclude>
<ClInclude Include="src\Scene\EditorTerrain.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Helpers.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\CGI\DebugDraw.h">
<Filter>src\CGI</Filter>
</ClInclude>
@ -468,9 +438,6 @@
<ClInclude Include="src\IO\Dictionary.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\Scene\ShadowMapBaker.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Physics\BulletDebugDraw.h">
<Filter>src\Physics</Filter>
</ClInclude>
@ -480,9 +447,6 @@
<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>
@ -498,18 +462,9 @@
<ClInclude Include="src\CGI\Scheduled.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\IO\Xxx.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Grass.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\CGI\TextureRAM.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Water.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Global\Cooldown.h">
<Filter>src\Global</Filter>
</ClInclude>
@ -585,30 +540,6 @@
<ClInclude Include="src\Effects\Bloom.h">
<Filter>src\Effects</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Forest.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Scene\Scatter.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\Block.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\Light.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\Model.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\SceneNode.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\SceneNodes.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\Types.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Effects\Particles.h">
<Filter>src\Effects</Filter>
</ClInclude>
@ -621,18 +552,6 @@
<ClInclude Include="src\Global\LocalPtr.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\Site.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\Prefab.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\Emitter.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\SceneParticles.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\Anim\Shaker.h">
<Filter>src\Anim</Filter>
</ClInclude>
@ -672,9 +591,6 @@
<ClInclude Include="src\Effects\Ssr.h">
<Filter>src\Effects</Filter>
</ClInclude>
<ClInclude Include="src\Scene\CubeMapBaker.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Game\QuestSystem.h">
<Filter>src\Game</Filter>
</ClInclude>
@ -687,7 +603,7 @@
<ClInclude Include="src\ThirdParty\imgui\imgui.h">
<Filter>src\ThirdParty\imgui</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\imgui\imgui_impl_sdl.h">
<ClInclude Include="src\ThirdParty\imgui\imgui_impl_sdl2.h">
<Filter>src\ThirdParty\imgui</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\imgui\imgui_internal.h">
@ -702,9 +618,6 @@
<ClInclude Include="src\ThirdParty\imgui\imstb_truetype.h">
<Filter>src\ThirdParty\imgui</Filter>
</ClInclude>
<ClInclude Include="src\Scene\SceneNodes\Trigger.h">
<Filter>src\Scene\SceneNodes</Filter>
</ClInclude>
<ClInclude Include="src\App\UndoManager.h">
<Filter>src\App</Filter>
</ClInclude>
@ -741,9 +654,6 @@
<ClInclude Include="src\Global\Interval.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Scene\LightMapBaker.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\CGI\DeferredShading.h">
<Filter>src\CGI</Filter>
</ClInclude>
@ -792,6 +702,114 @@
<ClInclude Include="src\CGI\BaseExtReality.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\World\World.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldManager.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\BlockNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\LightNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\ModelNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\BaseNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\WorldNodes.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\Types.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\Camera.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\BaseMesh.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\MaterialManager.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\Mesh.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\OrbitingCamera.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\PhysicsNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\EditorOverlays.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\EmitterNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\ParticlesNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\SoundNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\IO\Vwx.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\TerrainNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\PrefabNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\InstanceNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\CubeMapBaker.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\LightMapBaker.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\ShadowMapBaker.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\Water.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\Atmosphere.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\Forest.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\Scatter.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\EditorTerrain.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\Terrain.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\Grass.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldUtils.h">
<Filter>src\World</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\ShakerNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\ControlPointNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
<ClInclude Include="src\World\WorldNodes\PathNode.h">
<Filter>src\World\WorldNodes</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\CGI\BaseGeometry.cpp">
@ -905,12 +923,6 @@
<ClCompile Include="src\Global\Timer.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Camera.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Scene.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Math\Frustum.cpp">
<Filter>src\Math</Filter>
</ClCompile>
@ -932,12 +944,6 @@
<ClCompile Include="src\AI\Turret.cpp">
<Filter>src\AI</Filter>
</ClCompile>
<ClCompile Include="src\Scene\BaseMesh.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Mesh.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Math\TangentSpaceTools.cpp">
<Filter>src\Math</Filter>
</ClCompile>
@ -1004,12 +1010,6 @@
<ClCompile Include="src\Game\Spirit.cpp">
<Filter>src\Game</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Terrain.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Atmosphere.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Physics\Bullet.cpp">
<Filter>src\Physics</Filter>
</ClCompile>
@ -1025,18 +1025,6 @@
<ClCompile Include="src\Math\Quadtree.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\Scene\MaterialManager.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneManager.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Scene\EditorTerrain.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Helpers.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\CGI\DebugDraw.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
@ -1046,9 +1034,6 @@
<ClCompile Include="src\IO\Dictionary.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<ClCompile Include="src\Scene\ShadowMapBaker.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Physics\BulletDebugDraw.cpp">
<Filter>src\Physics</Filter>
</ClCompile>
@ -1058,9 +1043,6 @@
<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>
@ -1085,18 +1067,9 @@
<ClCompile Include="src\CGI\Scheduled.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
<ClCompile Include="src\IO\Xxx.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Grass.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\CGI\TextureRAM.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Water.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Global\Cooldown.cpp">
<Filter>src\Global</Filter>
</ClCompile>
@ -1166,42 +1139,9 @@
<ClCompile Include="src\Effects\Bloom.cpp">
<Filter>src\Effects</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Forest.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Scene\Scatter.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\Block.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\Light.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\Model.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\SceneNode.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\SceneNodes.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Effects\Particles.cpp">
<Filter>src\Effects</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\Site.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\Prefab.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\Emitter.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\SceneParticles.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\Anim\Shaker.cpp">
<Filter>src\Anim</Filter>
</ClCompile>
@ -1232,9 +1172,6 @@
<ClCompile Include="src\Effects\Ssr.cpp">
<Filter>src\Effects</Filter>
</ClCompile>
<ClCompile Include="src\Scene\CubeMapBaker.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Game\QuestSystem.cpp">
<Filter>src\Game</Filter>
</ClCompile>
@ -1250,7 +1187,7 @@
<ClCompile Include="src\ThirdParty\imgui\imgui_draw.cpp">
<Filter>src\ThirdParty\imgui</Filter>
</ClCompile>
<ClCompile Include="src\ThirdParty\imgui\imgui_impl_sdl.cpp">
<ClCompile Include="src\ThirdParty\imgui\imgui_impl_sdl2.cpp">
<Filter>src\ThirdParty\imgui</Filter>
</ClCompile>
<ClCompile Include="src\ThirdParty\imgui\imgui_tables.cpp">
@ -1259,9 +1196,6 @@
<ClCompile Include="src\ThirdParty\imgui\imgui_widgets.cpp">
<Filter>src\ThirdParty\imgui</Filter>
</ClCompile>
<ClCompile Include="src\Scene\SceneNodes\Trigger.cpp">
<Filter>src\Scene\SceneNodes</Filter>
</ClCompile>
<ClCompile Include="src\App\UndoManager.cpp">
<Filter>src\App</Filter>
</ClCompile>
@ -1301,9 +1235,6 @@
<ClCompile Include="src\Global\Range.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Scene\LightMapBaker.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\CGI\DeferredShading.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
@ -1361,6 +1292,111 @@
<ClCompile Include="src\CGI\BaseExtReality.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
<ClCompile Include="src\World\World.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldManager.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\BlockNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\LightNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\ModelNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\BaseNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\WorldNodes.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\Camera.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\BaseMesh.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\MaterialManager.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\Mesh.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\OrbitingCamera.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\PhysicsNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\EditorOverlays.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\EmitterNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\ParticlesNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\SoundNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\IO\Vwx.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\TerrainNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\PrefabNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\InstanceNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\CubeMapBaker.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\LightMapBaker.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\ShadowMapBaker.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\Water.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\Atmosphere.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\Forest.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\Scatter.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\EditorTerrain.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\Terrain.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\Grass.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldUtils.cpp">
<Filter>src\World</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\ShakerNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\ControlPointNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
<ClCompile Include="src\World\WorldNodes\PathNode.cpp">
<Filter>src\World\WorldNodes</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="src\Shaders\Lib.hlsl">

View File

@ -32,8 +32,8 @@ namespace verus
const T d = _target - _actual;
if (angle)
{
VERUS_RT_ASSERT(_target >= T(-VERUS_PI) && _target < T(VERUS_PI));
VERUS_RT_ASSERT(_actual >= T(-VERUS_PI) && _actual < T(VERUS_PI));
VERUS_RT_ASSERT(_target >= T(-4) && _target < T(4));
VERUS_RT_ASSERT(_actual >= T(-4) && _actual < T(4));
if (d > T(VERUS_PI))
_actual += VERUS_2PI;
else if (d < T(-VERUS_PI))

View File

@ -4,8 +4,6 @@
using namespace verus;
using namespace verus::Anim;
const float Motion::Bone::s_magicValueForCircle = 0.825f * 0.7071f * 4; // Octagon vertices will form a perfect circle.
// Motion::Bone::Rotation:
Motion::Bone::Rotation::Rotation()
@ -24,6 +22,8 @@ Motion::Bone::Rotation::Rotation(RcVector3 euler)
// Motion::Bone:
const float Motion::Bone::s_magicValueForCircle = 0.825f * 0.7071f * 4; // Octagon vertices will form a perfect circle.
Motion::Bone::Bone(PMotion pMotion) :
_pMotion(pMotion)
{

View File

@ -6,6 +6,8 @@ using namespace verus::Anim;
void Shaker::Load(CSZ url)
{
_url = url;
Vector<BYTE> v;
IO::FileSystem::LoadResource(url, v);
@ -29,7 +31,7 @@ void Shaker::Load(CSZ url)
const float val = v[chunkOffset + i] * (1 / 128.f) - 1;
_vData[i] = val;
}
if (!_loop)
if (!_looping)
_offset = static_cast<float>(chunkSize);
}
@ -39,7 +41,7 @@ void Shaker::Update()
_offset += dt * _speed;
if (_offset >= _vData.size())
{
if (_loop)
if (_looping)
{
_offset = fmod(_offset, static_cast<float>(_vData.size()));
}
@ -68,9 +70,3 @@ float Shaker::Get()
{
return _value;
}
void Shaker::SetScaleBias(float s, float b)
{
_scale = s;
_bias = b;
}

View File

@ -9,24 +9,40 @@ namespace verus
// Works well for camera's shaking effects.
class Shaker
{
String _url;
Vector<float> _vData;
float _speed = 0;
float _offset = 0;
float _value = 0;
float _scale = 1;
float _bias = 0;
bool _loop = false;
bool _looping = false;
public:
Shaker(float speed = 400, bool loop = true) : _speed(speed), _loop(loop) {}
Shaker(float speed = 400, bool looping = true) : _speed(speed), _looping(looping) {}
bool IsLoaded() const { return !_vData.empty(); }
void Load(CSZ url);
Str GetURL() const { return _C(_url); }
void Update();
void Reset() { _offset = 0; }
void Randomize();
// Returns the current value in the range [-1 to 1].
float Get();
void SetScaleBias(float s, float b);
float GetSpeed() const { return _speed; }
void SetSpeed(float speed) { _speed = speed; }
float GetScale() const { return _scale; }
void SetScale(float scale) { _scale = scale; }
float GetBias() const { return _bias; }
void SetBias(float bias) { _bias = bias; }
bool IsLooping() const { return _looping; }
void SetLooping(float looping) { _looping = looping; }
};
VERUS_TYPEDEFS(Shaker);
}

View File

@ -137,9 +137,11 @@ void Skeleton::ApplyMotion(RMotion motion, float time, int layeredMotionCount, P
for (auto& kv : _mapBones)
{
RBone bone = kv.second;
if (bone._pBody)
if (bone._pRigidBody)
{
bone._matFinal = _matRagdollToWorldInv * Transform3(bone._pBody->getWorldTransform()) * bone._matToActorSpace;
btTransform btr;
bone._pRigidBody->getMotionState()->getWorldTransform(btr);
bone._matFinal = _matRagdollToWorldInv * Transform3(btr) * bone._matToActorSpace;
}
else
{
@ -149,9 +151,11 @@ void Skeleton::ApplyMotion(RMotion motion, float time, int layeredMotionCount, P
PBone pParent = FindBone(_C(bone._parentName));
while (pParent)
{
if (pParent->_pBody)
if (pParent->_pRigidBody)
{
bone._matFinal = _matRagdollToWorldInv * Transform3(pParent->_pBody->getWorldTransform()) * pParent->_matToActorSpace;
btTransform btr;
pParent->_pRigidBody->getMotionState()->getWorldTransform(btr);
bone._matFinal = _matRagdollToWorldInv * Transform3(btr) * pParent->_matToActorSpace;
break;
}
pParent = FindBone(_C(pParent->_parentName));
@ -553,16 +557,16 @@ void Skeleton::BeginRagdoll(RcTransform3 matW, RcVector3 impulse, CSZ bone)
pParent->_matToActorSpace = VMath::inverse(matBody);
matBody = _matRagdollToWorld * pParent->_matFinal * matBody;
Physics::Group group = Physics::Group::general, mask = Physics::Group::all;
Physics::Group group = Physics::Group::ragdoll, mask = Physics::Group::all;
if (pParent->_noCollision)
group = mask = Physics::Group::none;
const btTransform tr = matBody.Bullet();
pParent->_pBody = bullet.AddNewRigidBody(pParent->_mass, tr, pParent->_pShape, group, mask);
pParent->_pBody->setFriction(pParent->_friction);
pParent->_pBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::leather) * 0.5f);
pParent->_pBody->setDamping(dampL, dampA);
pParent->_pBody->setDeactivationTime(daTime);
pParent->_pBody->setSleepingThresholds(sleepL, sleepA);
pParent->_pRigidBody = bullet.AddNewRigidBody(pParent->_mass, tr, pParent->_pShape, +group, +mask);
pParent->_pRigidBody->setFriction(pParent->_friction);
pParent->_pRigidBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::leather) * 0.5f);
pParent->_pRigidBody->setDamping(dampL, dampA);
pParent->_pRigidBody->setDeactivationTime(daTime);
pParent->_pRigidBody->setSleepingThresholds(sleepL, sleepA);
}
}
@ -604,16 +608,16 @@ void Skeleton::BeginRagdoll(RcTransform3 matW, RcVector3 impulse, CSZ bone)
pBone->_matToActorSpace = VMath::inverse(matBody);
matBody = _matRagdollToWorld * pBone->_matFinal * matBody;
Physics::Group group = Physics::Group::general, mask = Physics::Group::all;
Physics::Group group = Physics::Group::ragdoll, mask = Physics::Group::all;
if (pBone->_noCollision)
group = mask = Physics::Group::none;
const btTransform tr = matBody.Bullet();
pBone->_pBody = bullet.AddNewRigidBody(pBone->_mass, tr, pBone->_pShape, group, mask);
pBone->_pBody->setFriction(pBone->_friction);
pBone->_pBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::leather) * 0.5f);
pBone->_pBody->setDamping(dampL, dampA);
pBone->_pBody->setDeactivationTime(daTime);
pBone->_pBody->setSleepingThresholds(sleepL, sleepA);
pBone->_pRigidBody = bullet.AddNewRigidBody(pBone->_mass, tr, pBone->_pShape, +group, +mask);
pBone->_pRigidBody->setFriction(pBone->_friction);
pBone->_pRigidBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::leather) * 0.5f);
pBone->_pRigidBody->setDamping(dampL, dampA);
pBone->_pRigidBody->setDeactivationTime(daTime);
pBone->_pRigidBody->setSleepingThresholds(sleepL, sleepA);
isLeaf = true;
}
@ -630,7 +634,7 @@ void Skeleton::BeginRagdoll(RcTransform3 matW, RcVector3 impulse, CSZ bone)
if (pBone->_hinge)
{
btHingeConstraint* pHingeC = new btHingeConstraint(*pBone->_pBody, *pParent->_pBody, localA, localB);
btHingeConstraint* pHingeC = new btHingeConstraint(*pBone->_pRigidBody, *pParent->_pRigidBody, localA, localB);
if (!pBone->_cLimits.IsZero())
pHingeC->setLimit(pBone->_cLimits.getX(), pBone->_cLimits.getY());
else
@ -640,7 +644,7 @@ void Skeleton::BeginRagdoll(RcTransform3 matW, RcVector3 impulse, CSZ bone)
}
else
{
btConeTwistConstraint* pConeC = new btConeTwistConstraint(*pBone->_pBody, *pParent->_pBody, localA, localB);
btConeTwistConstraint* pConeC = new btConeTwistConstraint(*pBone->_pRigidBody, *pParent->_pRigidBody, localA, localB);
if (!pBone->_cLimits.IsZero())
pConeC->setLimit(pBone->_cLimits.getX(), pBone->_cLimits.getY(), pBone->_cLimits.getZ(), 0.9f);
else
@ -652,8 +656,8 @@ void Skeleton::BeginRagdoll(RcTransform3 matW, RcVector3 impulse, CSZ bone)
}
}
if (pBone->_name == bone && pBone->_pBody)
pBone->_pBody->applyCentralImpulse(impulse.Bullet());
if (pBone->_name == bone && pBone->_pRigidBody)
pBone->_pRigidBody->applyCentralImpulse(impulse.Bullet());
}
_ragdollMode = true;
@ -677,12 +681,12 @@ void Skeleton::EndRagdoll()
for (auto& kv : _mapBones)
{
RBone bone = kv.second;
if (bone._pBody)
if (bone._pRigidBody)
{
bullet.GetWorld()->removeRigidBody(bone._pBody);
delete bone._pBody->getMotionState();
delete bone._pBody;
bone._pBody = nullptr;
bullet.GetWorld()->removeRigidBody(bone._pRigidBody);
delete bone._pRigidBody->getMotionState();
delete bone._pRigidBody;
bone._pRigidBody = nullptr;
}
if (bone._pShape)
{

View File

@ -42,7 +42,7 @@ namespace verus
String _name;
String _parentName;
btCollisionShape* _pShape = nullptr;
btRigidBody* _pBody = nullptr;
btRigidBody* _pRigidBody = nullptr;
btTypedConstraint* _pConstraint = nullptr;
float _width = 0;
float _length = 0;

View File

@ -82,7 +82,7 @@ void Warp::DrawLines() const
void Warp::DrawZones() const
{
VERUS_QREF_HELPERS;
VERUS_QREF_EO;
VERUS_QREF_RENDERER;
for (const auto& zone : _vZones)
@ -94,7 +94,7 @@ void Warp::DrawZones() const
case 'g': color = VERUS_COLOR_RGBA(0, 255, 0, 255); break;
case 'b': color = VERUS_COLOR_RGBA(0, 0, 255, 255); break;
}
helpers.DrawSphere(zone._pos, zone._radius, color, renderer.GetCommandBuffer());
eo.DrawSphere(zone._pos, zone._radius, color, renderer.GetCommandBuffer());
}
}

View File

@ -54,12 +54,12 @@ void UndoManager::Redo()
bool UndoManager::CanUndo() const
{
return _nextUndo < _vCommands.size() && _vCommands[_nextUndo]->HasRedo();
return _nextUndo < _vCommands.size() && _vCommands[_nextUndo]->IsValid() && _vCommands[_nextUndo]->HasRedo();
}
bool UndoManager::CanRedo() const
{
return _nextUndo && _vCommands[_nextUndo - 1]->HasRedo();
return _nextUndo && _vCommands[_nextUndo - 1]->IsValid() && _vCommands[_nextUndo - 1]->HasRedo();
}
UndoManager::PCommand UndoManager::BeginChange(PCommand pCommand)

View File

@ -25,12 +25,12 @@ void Sound::Init(RcDesc desc)
_url = desc._url;
_refCount = 1;
if (desc._is3D) SetFlag(SoundFlags::is3D);
if (desc._loop) SetFlag(SoundFlags::loop);
if (desc._looping) SetFlag(SoundFlags::looping);
if (desc._randomOffset) SetFlag(SoundFlags::randOff);
if (desc._keepPcmBuffer) SetFlag(SoundFlags::keepPcmBuffer);
_gain = desc._gain;
_pitch = desc._pitch;
_referenceDistance = desc._referenceDistance;
if (desc._randomOffset) SetFlag(SoundFlags::randOff);
if (desc._keepPcmBuffer) SetFlag(SoundFlags::keepPcmBuffer);
IO::Async::I().Load(desc._url, this);
}
@ -51,6 +51,25 @@ bool Sound::Done()
return false;
}
void Sound::Update()
{
if (!IsLoaded())
return;
VERUS_UPDATE_ONCE_CHECK;
VERUS_FOR(i, VERUS_COUNT_OF(_sources))
_sources[i].Update();
}
void Sound::UpdateHRTF()
{
if (!IsLoaded())
return;
const bool is3D = IsFlagSet(SoundFlags::is3D);
VERUS_FOR(i, VERUS_COUNT_OF(_sources))
_sources[i].UpdateHRTF(is3D);
}
void Sound::Async_WhenLoaded(CSZ url, RcBlob blob)
{
VERUS_RT_ASSERT(_url == url);
@ -94,25 +113,6 @@ void Sound::Async_WhenLoaded(CSZ url, RcBlob blob)
SetFlag(SoundFlags::loaded);
}
void Sound::Update()
{
if (!IsLoaded())
return;
VERUS_UPDATE_ONCE_CHECK;
VERUS_FOR(i, VERUS_COUNT_OF(_sources))
_sources[i].Update();
}
void Sound::UpdateHRTF()
{
if (!IsLoaded())
return;
const bool is3D = IsFlagSet(SoundFlags::is3D);
VERUS_FOR(i, VERUS_COUNT_OF(_sources))
_sources[i].UpdateHRTF(is3D);
}
SourcePtr Sound::NewSource(PSourcePtr pID, Source::RcDesc desc)
{
SourcePtr source;
@ -138,10 +138,10 @@ SourcePtr Sound::NewSource(PSourcePtr pID, Source::RcDesc desc)
alSource3f(sid, AL_VELOCITY, 0, 0, 0);
alSourcef(sid, AL_ROLLOFF_FACTOR, 0);
}
alSourcef(sid, AL_PITCH, _pitch.GetRandomValue() * desc._pitch);
alSourcei(sid, AL_LOOPING, IsFlagSet(SoundFlags::loop) ? 1 : 0);
alSourcef(sid, AL_PITCH, Math::Clamp<float>(_pitch.GetRandomValue() * desc._pitch, 0.5f, 2));
alSourcei(sid, AL_LOOPING, IsFlagSet(SoundFlags::looping) ? 1 : 0);
alSourcei(sid, AL_BUFFER, _buffer);
alSourcef(sid, AL_GAIN, _gain.GetRandomValue() * desc._gain);
alSourcef(sid, AL_GAIN, Math::Clamp<float>(_gain.GetRandomValue() * desc._gain, 0, 1));
if (desc._secOffset < 0)
{
@ -189,7 +189,7 @@ void SoundPwn::Done()
{
if (_p)
{
AudioSystem::I().DeleteSound(_C(_p->GetUrl()));
AudioSystem::I().DeleteSound(_C(_p->GetURL()));
_p = nullptr;
}
}

View File

@ -11,7 +11,7 @@ namespace verus
{
loaded = (ObjectFlags::user << 0),
is3D = (ObjectFlags::user << 1),
loop = (ObjectFlags::user << 2),
looping = (ObjectFlags::user << 2),
randOff = (ObjectFlags::user << 3),
keepPcmBuffer = (ObjectFlags::user << 4),
user = (ObjectFlags::user << 5)
@ -24,14 +24,15 @@ namespace verus
String _url;
Vector<BYTE> _vPcmBuffer;
ALuint _buffer = 0;
int _next = 0;
int _refCount = 0;
int _next = 0;
Interval _gain = 1;
Interval _pitch = 1;
float _length = 0;
float _referenceDistance = 4;
float _length = 0;
public:
// Note that this structure contains some default values for new sources, which can be changed per source.
struct Desc
{
CSZ _url = nullptr;
@ -39,16 +40,16 @@ namespace verus
Interval _pitch = 1;
float _referenceDistance = 4;
bool _is3D = false;
bool _loop = false;
bool _looping = false;
bool _randomOffset = false;
bool _keepPcmBuffer = false;
Desc(CSZ url) : _url(url) {}
Desc& Set3D(bool b = true) { _is3D = b; return *this; }
Desc& SetLoop(bool b = true) { _loop = b; return *this; }
Desc& SetLooping(bool b = true) { _looping = b; return *this; }
Desc& SetRandomOffset(bool b = true) { _randomOffset = b; return *this; }
Desc& SetGain(Interval gain) { _gain = gain; return *this; }
Desc& SetPitch(Interval pitch) { _pitch = pitch; return *this; }
Desc& SetRandomOffset(bool b = true) { _randomOffset = b; return *this; }
Desc& SetReferenceDistance(float rd) { _referenceDistance = rd; return *this; }
};
VERUS_TYPEDEFS(Desc);
@ -56,18 +57,21 @@ namespace verus
Sound();
~Sound();
void AddRef() { _refCount++; }
int GetRefCount() const { return _refCount; }
void Init(RcDesc desc);
bool Done();
virtual void Async_WhenLoaded(CSZ url, RcBlob blob) override;
bool IsLoaded() const { return IsFlagSet(SoundFlags::loaded); }
void AddRef() { _refCount++; }
Str GetUrl() const { return _C(_url); }
void Update();
void UpdateHRTF();
// <Resources>
virtual void Async_WhenLoaded(CSZ url, RcBlob blob) override;
bool IsLoaded() const { return IsFlagSet(SoundFlags::loaded); }
Str GetURL() const { return _C(_url); }
// </Resources>
SourcePtr NewSource(PSourcePtr pID = nullptr, Source::RcDesc desc = Source::Desc());
Interval GetGain() const { return _gain; }

View File

@ -110,13 +110,19 @@ void Source::MoveTo(RcPoint3 pos, RcVector3 dir, RcVector3 vel)
void Source::SetGain(float gain)
{
if (_pSound && _pSound->IsLoaded())
alSourcef(_sid, AL_GAIN, gain * _pSound->GetGain().GetRandomValue());
alSourcef(_sid, AL_GAIN, Math::Clamp<float>(gain * _pSound->GetGain().GetRandomValue(), 0, 1));
}
void Source::SetPitch(float pitch)
{
if (_pSound && _pSound->IsLoaded())
alSourcef(_sid, AL_PITCH, pitch * _pSound->GetPitch().GetRandomValue());
alSourcef(_sid, AL_PITCH, Math::Clamp<float>(pitch * _pSound->GetPitch().GetRandomValue(), 0.5f, 2));
}
void Source::SetLooping(bool loop)
{
if (_pSound && _pSound->IsLoaded())
alSourcei(_sid, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
}
// SourcePtr:

View File

@ -42,6 +42,7 @@ namespace verus
void SetGain(float gain);
void SetPitch(float pitch);
void SetLooping(bool loop);
};
VERUS_TYPEDEFS(Source);

View File

@ -78,7 +78,7 @@ void DebugDraw::Done()
void DebugDraw::Begin(Type type, PcTransform3 pMat, bool zEnable)
{
VERUS_QREF_SM;
VERUS_QREF_WM;
VERUS_QREF_RENDERER;
auto cb = renderer.GetCommandBuffer();
@ -92,8 +92,8 @@ void DebugDraw::Begin(Type type, PcTransform3 pMat, bool zEnable)
}
Matrix4 matWVP;
if (sm.GetPassCamera())
matWVP = sm.GetPassCamera()->GetMatrixVP();
if (wm.GetPassCamera())
matWVP = wm.GetPassCamera()->GetMatrixVP();
else
matWVP = Matrix4::identity();
s_ubDebugDraw._matWVP = pMat ? Matrix4(matWVP * *pMat).UniformBufferFormat() : matWVP.UniformBufferFormat();

View File

@ -469,8 +469,8 @@ void DeferredShading::OnSwapChainResized(bool init, bool done)
bool DeferredShading::IsLoaded()
{
VERUS_QREF_HELPERS;
Scene::RDeferredLights dl = helpers.GetDeferredLights();
VERUS_QREF_WU;
World::RDeferredLights dl = wu.GetDeferredLights();
return
dl.Get(LightType::dir).IsLoaded() &&
dl.Get(LightType::omni).IsLoaded() &&
@ -479,8 +479,8 @@ bool DeferredShading::IsLoaded()
void DeferredShading::ResetInstanceCount()
{
VERUS_QREF_HELPERS;
Scene::RDeferredLights dl = helpers.GetDeferredLights();
VERUS_QREF_WU;
World::RDeferredLights dl = wu.GetDeferredLights();
dl.Get(LightType::dir).ResetInstanceCount();
dl.Get(LightType::omni).ResetInstanceCount();
dl.Get(LightType::spot).ResetInstanceCount();
@ -599,13 +599,13 @@ bool DeferredShading::BeginLightingPass(bool ambient, bool terrainOcclusion)
if (ambient)
{
VERUS_QREF_ATMO;
VERUS_QREF_SM;
VERUS_QREF_WM;
s_ubAmbientVS._matW = Math::QuadMatrix().UniformBufferFormat();
s_ubAmbientVS._matV = Math::ToUVMatrix().UniformBufferFormat();
s_ubAmbientVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
s_ubAmbientFS._matInvV = sm.GetPassCamera()->GetMatrixInvV().UniformBufferFormat();
s_ubAmbientFS._matInvP = sm.GetPassCamera()->GetMatrixInvP().UniformBufferFormat();
s_ubAmbientFS._matInvV = wm.GetPassCamera()->GetMatrixInvV().UniformBufferFormat();
s_ubAmbientFS._matInvP = wm.GetPassCamera()->GetMatrixInvP().UniformBufferFormat();
s_ubAmbientFS._ambientColorY0 = float4(atmo.GetAmbientColorY0().GLM(), 0);
s_ubAmbientFS._ambientColorY1 = float4(atmo.GetAmbientColorY1().GLM(), 0);
s_ubAmbientFS._invMapSide_minOcclusion.x = 1.f / _terrainMapSide;
@ -628,8 +628,8 @@ bool DeferredShading::BeginLightingPass(bool ambient, bool terrainOcclusion)
{
_async_initPipe = true;
VERUS_QREF_HELPERS;
Scene::RDeferredLights dl = helpers.GetDeferredLights();
VERUS_QREF_WU;
World::RDeferredLights dl = wu.GetDeferredLights();
{
PipelineDesc pipeDesc(dl.Get(LightType::dir).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedDir", _rph, 1);
@ -690,7 +690,7 @@ void DeferredShading::EndLightingPass()
void DeferredShading::BeginComposeAndForwardRendering(bool underwaterMask)
{
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_WM;
VERUS_QREF_ATMO;
VERUS_QREF_WATER;
VERUS_RT_ASSERT(renderer.GetFrameCount() == _frame);
@ -707,7 +707,7 @@ void DeferredShading::BeginComposeAndForwardRendering(bool underwaterMask)
_tex[TEX_GBUFFER_3]->GetClearValue()
});
const Matrix4 matInvVP = VMath::inverse(sm.GetPassCamera()->GetMatrixVP());
const Matrix4 matInvVP = VMath::inverse(wm.GetPassCamera()->GetMatrixVP());
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
@ -717,7 +717,7 @@ void DeferredShading::BeginComposeAndForwardRendering(bool underwaterMask)
s_ubComposeFS._exposure_underwaterMask.y = underwaterMask ? 1.f : 0.f;
s_ubComposeFS._backgroundColor = _backgroundColor.GLM();
s_ubComposeFS._fogColor = Vector4(atmo.GetFogColor(), atmo.GetFogDensity()).GLM();
s_ubComposeFS._zNearFarEx = sm.GetPassCamera()->GetZNearFarEx().GLM();
s_ubComposeFS._zNearFarEx = wm.GetPassCamera()->GetZNearFarEx().GLM();
s_ubComposeFS._waterDiffColorShallow = float4(water.GetDiffuseColorShallow().GLM(), water.GetFogDensity());
s_ubComposeFS._waterDiffColorDeep = float4(water.GetDiffuseColorDeep().GLM(), water.IsUnderwater() ? 1.f : 0.f);
@ -802,13 +802,13 @@ bool DeferredShading::IsLightUrl(CSZ url)
void DeferredShading::OnNewLightType(CommandBufferPtr cb, LightType type, bool wireframe)
{
VERUS_QREF_ATMO;
VERUS_QREF_SM;
VERUS_QREF_WM;
s_ubPerFrame._matToUV = Math::ToUVMatrix().UniformBufferFormat();
s_ubPerFrame._matV = sm.GetPassCamera()->GetMatrixV().UniformBufferFormat();
s_ubPerFrame._matInvV = sm.GetPassCamera()->GetMatrixInvV().UniformBufferFormat();
s_ubPerFrame._matVP = sm.GetPassCamera()->GetMatrixVP().UniformBufferFormat();
s_ubPerFrame._matInvP = sm.GetPassCamera()->GetMatrixInvP().UniformBufferFormat();
s_ubPerFrame._matV = wm.GetPassCamera()->GetMatrixV().UniformBufferFormat();
s_ubPerFrame._matInvV = wm.GetPassCamera()->GetMatrixInvV().UniformBufferFormat();
s_ubPerFrame._matVP = wm.GetPassCamera()->GetMatrixVP().UniformBufferFormat();
s_ubPerFrame._matInvP = wm.GetPassCamera()->GetMatrixInvP().UniformBufferFormat();
s_ubPerFrame._tcViewScaleBias = cb->GetViewScaleBias().GLM();
switch (type)
@ -851,10 +851,10 @@ void DeferredShading::BindDescriptorsPerMeshVS(CommandBufferPtr cb)
void DeferredShading::Load()
{
VERUS_QREF_HELPERS;
Scene::RDeferredLights dl = helpers.GetDeferredLights();
VERUS_QREF_WU;
World::RDeferredLights dl = wu.GetDeferredLights();
Scene::Mesh::Desc meshDesc;
World::Mesh::Desc meshDesc;
meshDesc._instanceCapacity = 10000;
meshDesc._url = "[Models]:DS/Dir.x3d";

View File

@ -242,10 +242,10 @@ void Renderer::Done()
_commandBuffer.Done();
Effects::Particles::DoneStatic();
Scene::Forest::DoneStatic();
Scene::Grass::DoneStatic();
Scene::Terrain::DoneStatic();
Scene::Mesh::DoneStatic();
World::Forest::DoneStatic();
World::Grass::DoneStatic();
World::Terrain::DoneStatic();
World::Mesh::DoneStatic();
GUI::Font::DoneStatic();
_pBaseRenderer->ReleaseMe();
@ -279,7 +279,7 @@ void Renderer::Update()
const float alpha = Math::Max(0.001f, floatColor[3]);
const float actual = gray.r;
const float expScale = Math::Clamp(_exposure[1] * (1 / 16.f), 0.f, 1.f);
const float target = -0.2f + 0.6f * expScale * expScale; // Dark scene exposure compensation.
const float target = -0.1f + 0.5f * expScale * expScale; // Dark scene exposure compensation.
const float important = (actual - 0.5f * (1 - alpha)) / alpha;
const float delta = target - important;
const float speed = (delta * delta) * ((delta > 0) ? 5.f : 15.f);
@ -406,8 +406,8 @@ bool Renderer::OnWindowSizeChanged(int w, int h)
OnScreenSwapChainResized(true, true);
if (_ds.IsInitialized())
_ds.OnSwapChainResized(true, true);
if (Scene::Water::IsValidSingleton())
Scene::Water::I().OnSwapChainResized();
if (World::Water::IsValidSingleton())
World::Water::I().OnSwapChainResized();
if (Effects::Bloom::IsValidSingleton())
Effects::Bloom::I().OnSwapChainResized();
if (Effects::Ssao::IsValidSingleton())
@ -704,6 +704,12 @@ void Renderer::ImGuiUpdateStyle()
colors[ImGuiCol_PlotHistogram] = disabledColor;
colors[ImGuiCol_PlotHistogramHovered] = satColorB;
colors[ImGuiCol_TableHeaderBg] = borderColor;
colors[ImGuiCol_TableBorderStrong] = borderColor;
colors[ImGuiCol_TableBorderLight] = borderColor;
colors[ImGuiCol_TableRowBg] = frameBgColor;
colors[ImGuiCol_TableRowBgAlt] = frameBgColor;
colors[ImGuiCol_TextSelectedBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_DragDropTarget] = satColorB;
colors[ImGuiCol_NavHighlight] = satColorB;

View File

@ -129,7 +129,7 @@ void Bloom::Generate()
VERUS_QREF_ATMO;
VERUS_QREF_CONST_SETTINGS;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_WM;
if (!settings._postProcessBloom)
return;
@ -176,10 +176,10 @@ void Bloom::Generate()
cb->BeginRenderPass(_rphLightShafts, _fbh, { _tex[TEX_PING]->GetClearValue() },
CGI::ViewportScissorFlags::setAllForCurrentViewScaled | CGI::ViewportScissorFlags::applyHalfScale);
s_ubBloomLightShaftsFS._matInvVP = Matrix4(VMath::inverse(sm.GetPassCamera()->GetMatrixVP())).UniformBufferFormat();
s_ubBloomLightShaftsFS._matInvVP = Matrix4(VMath::inverse(wm.GetPassCamera()->GetMatrixVP())).UniformBufferFormat();
s_ubBloomLightShaftsFS._dirToSun = float4(atmo.GetDirToSun().GLM(), 0);
s_ubBloomLightShaftsFS._sunColor = float4(atmo.GetSunColor().GLM(), 0);
s_ubBloomLightShaftsFS._eyePos = float4(sm.GetPassCamera()->GetEyePosition().GLM(), 0);
s_ubBloomLightShaftsFS._eyePos = float4(wm.GetPassCamera()->GetEyePosition().GLM(), 0);
s_ubBloomLightShaftsFS._maxDist_sunGloss_wideStrength_sunStrength.x = _maxDist;
s_ubBloomLightShaftsFS._maxDist_sunGloss_wideStrength_sunStrength.y = _sunGloss;
s_ubBloomLightShaftsFS._maxDist_sunGloss_wideStrength_sunStrength.z = _wideStrength;

View File

@ -40,8 +40,8 @@ namespace verus
float _colorBias = 1.4f;
float _maxDist = 20;
float _sunGloss = 128;
float _wideStrength = 0.2f;
float _sunStrength = 0.3f;
float _wideStrength = 0.15f;
float _sunStrength = 0.35f;
bool _blur = true;
bool _blurLightShafts = true;
bool _editMode = false;

View File

@ -349,7 +349,7 @@ void Blur::GenerateForDepthOfField()
VERUS_QREF_CONST_SETTINGS;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_WM;
const float radius = 0.02f;
const Matrix3 matR = Matrix3::rotationZ(Math::ToRadians(45));
@ -394,7 +394,7 @@ void Blur::GenerateForDepthOfField()
s_ubBlurVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
s_ubBlurFS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
UpdateUniformBuffer(radius, 0, renderer.GetCurrentViewWidth(), samplesPerPixel, maxSamples);
s_ubExtraBlurFS._zNearFarEx = sm.GetPassCamera()->GetZNearFarEx().GLM();
s_ubExtraBlurFS._zNearFarEx = wm.GetPassCamera()->GetZNearFarEx().GLM();
s_ubExtraBlurFS._textureSize = cb->GetViewportSize().GLM();
s_ubExtraBlurFS._focusDist_blurStrength.x = _dofFocusDist;
s_ubExtraBlurFS._focusDist_blurStrength.y = _dofBlurStrength;
@ -505,7 +505,7 @@ void Blur::GenerateForAntiAliasing()
{
VERUS_QREF_CONST_SETTINGS;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_WM;
auto cb = renderer.GetCommandBuffer();
@ -516,7 +516,7 @@ void Blur::GenerateForAntiAliasing()
s_ubBlurVS._matV = Math::ToUVMatrix().UniformBufferFormat();
s_ubBlurVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
s_ubBlurFS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
s_ubExtraBlurFS._zNearFarEx = sm.GetPassCamera()->GetZNearFarEx().GLM();
s_ubExtraBlurFS._zNearFarEx = wm.GetPassCamera()->GetZNearFarEx().GLM();
s_ubExtraBlurFS._textureSize = cb->GetViewportSize().GLM();
cb->BindPipeline(_pipe[settings._postProcessAntiAliasing ? PIPE_AA : PIPE_AA_OFF]);
@ -535,7 +535,7 @@ void Blur::GenerateForMotionBlur()
{
VERUS_QREF_CONST_SETTINGS;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_WM;
auto cb = renderer.GetCommandBuffer();
@ -546,9 +546,9 @@ void Blur::GenerateForMotionBlur()
s_ubBlurVS._matV = Math::ToUVMatrix().UniformBufferFormat();
s_ubBlurVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
s_ubBlurFS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
s_ubExtraBlurFS._matInvVP = Matrix4(VMath::inverse(sm.GetViewCamera()->GetMatrixVP())).UniformBufferFormat();
s_ubExtraBlurFS._matPrevVP = sm.GetViewCamera()->GetMatrixPrevVP().UniformBufferFormat();
s_ubExtraBlurFS._zNearFarEx = sm.GetViewCamera()->GetZNearFarEx().GLM();
s_ubExtraBlurFS._matInvVP = Matrix4(VMath::inverse(wm.GetViewCamera()->GetMatrixVP())).UniformBufferFormat();
s_ubExtraBlurFS._matPrevVP = wm.GetViewCamera()->GetMatrixPrevVP().UniformBufferFormat();
s_ubExtraBlurFS._zNearFarEx = wm.GetViewCamera()->GetZNearFarEx().GLM();
cb->BindPipeline(_pipe[settings._postProcessMotionBlur ? PIPE_MOTION_BLUR : PIPE_MOTION_BLUR_OFF]);
_shader->BeginBindDescriptors();

View File

@ -248,7 +248,7 @@ void Particles::Update()
VERUS_QREF_TIMER;
Vector3 wind = Vector3(0);
if (Scene::Atmosphere::IsValidSingleton())
if (World::Atmosphere::IsValidSingleton())
{
VERUS_QREF_ATMO;
wind = atmo.GetWindVelocity();
@ -293,8 +293,8 @@ void Particles::Update()
}
else // Billboards:
{
VERUS_QREF_SM;
Scene::PCamera pHeadCamera = sm.GetHeadCamera();
VERUS_QREF_WM;
World::PCamera pHeadCamera = wm.GetHeadCamera();
Vector3 normal = pHeadCamera->GetFrontDirection();
Vector3 up(0, 1, 0);
switch (_billboardType)
@ -371,7 +371,7 @@ void Particles::Draw()
VERUS_UPDATE_ONCE_CHECK_DRAW;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_WM;
VERUS_QREF_ATMO;
if (!_drawCount || !_csh.IsSet())
@ -386,8 +386,8 @@ void Particles::Draw()
brightness = gray.x * abs(brightness);
}
s_ubParticlesVS._matP = sm.GetPassCamera()->GetMatrixP().UniformBufferFormat();
s_ubParticlesVS._matWVP = sm.GetPassCamera()->GetMatrixVP().UniformBufferFormat();
s_ubParticlesVS._matP = wm.GetPassCamera()->GetMatrixP().UniformBufferFormat();
s_ubParticlesVS._matWVP = wm.GetPassCamera()->GetMatrixVP().UniformBufferFormat();
s_ubParticlesVS._viewportSize = cb->GetViewportSize().GLM();
s_ubParticlesVS._brightness.x = brightness;
s_ubParticlesFS._tilesetSize = _tilesetSize.GLM();
@ -539,7 +539,7 @@ int Particles::Add(RcPoint3 pos, RcVector3 dir, float scale, PcVector4 pUserColo
VERUS_QREF_TIMER;
Vector3 wind = Vector3(0);
if (Scene::Atmosphere::IsValidSingleton())
if (World::Atmosphere::IsValidSingleton())
{
VERUS_QREF_ATMO;
wind = atmo.GetWindVelocity();
@ -626,7 +626,7 @@ bool Particles::TimeCorrectedVerletIntegration(RParticle particle, RPoint3 point
bool hit = false;
Vector3 wind = Vector3(0);
if (Scene::Atmosphere::IsValidSingleton())
if (World::Atmosphere::IsValidSingleton())
{
VERUS_QREF_ATMO;
wind = atmo.GetWindVelocity();
@ -648,8 +648,8 @@ bool Particles::TimeCorrectedVerletIntegration(RParticle particle, RPoint3 point
}
else
{
VERUS_QREF_SM;
if (sm.RayCastingTest(particle._prevPosition, particle._position, nullptr, &point, &normal))
VERUS_QREF_WM;
if (wm.RayTestEx(particle._prevPosition, particle._position, nullptr, &point, &normal, nullptr, Physics::Bullet::I().GetMainMask()))
{
hit = true;
particle._inContact = normal.getY() > 0.7071f;

View File

@ -127,7 +127,7 @@ namespace verus
void Update(); // Call this after adding particles!
void Draw();
Str GetUrl() const { return _C(_url); }
Str GetURL() const { return _C(_url); }
int GetTilesetX() const { return _tilesetX; }
int GetTilesetY() const { return _tilesetY; }
int GetCapacity() const { return _capacity; }

View File

@ -109,7 +109,7 @@ void Ssao::Generate()
{
VERUS_QREF_CONST_SETTINGS;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_WM;
if (!settings._postProcessSSAO)
return;
@ -127,7 +127,7 @@ void Ssao::Generate()
cb->BeginRenderPass(_rph, _fbh, { renderer.GetDS().GetGBuffer(3)->GetClearValue() });
Scene::RCamera passCamera = *sm.GetPassCamera();
World::RCamera passCamera = *wm.GetPassCamera();
s_ubSsaoVS._matW = Math::QuadMatrix().UniformBufferFormat();
s_ubSsaoVS._matV = Math::ToUVMatrix().UniformBufferFormat();

View File

@ -116,7 +116,7 @@ void Ssr::Generate()
{
VERUS_QREF_ATMO;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_WM;
if (!_csh.IsSet())
{
@ -137,7 +137,7 @@ void Ssr::Generate()
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly, 0);
cb->BeginRenderPass(_rph, _fbh, { renderer.GetDS().GetLightAccSpecularTexture()->GetClearValue() });
Scene::RCamera passCamera = *sm.GetPassCamera();
World::RCamera passCamera = *wm.GetPassCamera();
const Matrix4 matPTex = Matrix4(Math::ToUVMatrix()) * passCamera.GetMatrixP();

View File

@ -317,13 +317,13 @@ void BaseConvert::Mesh::Compress()
VERUS_FOR(i, _vertCount)
aabb.Include(_vUberVerts[i]._pos);
extents = aabb.GetExtents();
Scene::BaseMesh::ComputeDeq(_posScale, _posBias, extents, aabb._mn);
World::BaseMesh::ComputeDeq(_posScale, _posBias, extents, aabb._mn);
_vZipPos.reserve(_vertCount);
VERUS_FOR(i, _vertCount)
{
Mesh::Vec3Short pos;
glm::vec3 v(_vUberVerts[i]._pos);
Scene::BaseMesh::QuantizeV(v, extents, aabb._mn);
World::BaseMesh::QuantizeV(v, extents, aabb._mn);
pos._x = short(v.x);
pos._y = short(v.y);
pos._z = short(v.z);
@ -336,7 +336,7 @@ void BaseConvert::Mesh::Compress()
VERUS_FOR(i, _vertCount)
aabb.Include(glm::vec3(_vUberVerts[i]._tc0, 0));
extents = aabb.GetExtents();
Scene::BaseMesh::ComputeDeq(scale, bias, extents, aabb._mn);
World::BaseMesh::ComputeDeq(scale, bias, extents, aabb._mn);
_tc0Scale = glm::vec2(scale);
_tc0Bias = glm::vec2(bias);
_vZipTc0.reserve(_vertCount);
@ -344,7 +344,7 @@ void BaseConvert::Mesh::Compress()
{
Mesh::Vec2Short tc;
glm::vec3 v(_vUberVerts[i]._tc0, 0);
Scene::BaseMesh::QuantizeV(v, extents, aabb._mn);
World::BaseMesh::QuantizeV(v, extents, aabb._mn);
tc._u = short(v.x);
tc._v = short(v.y);
_vZipTc0.push_back(tc);
@ -369,7 +369,7 @@ void BaseConvert::Mesh::Compress()
aabb.Include(glm::vec3(_vUberVerts[i]._tc1, 0));
}
extents = aabb.GetExtents();
Scene::BaseMesh::ComputeDeq(scale, bias, extents, aabb._mn);
World::BaseMesh::ComputeDeq(scale, bias, extents, aabb._mn);
_tc1Scale = glm::vec2(scale);
_tc1Bias = glm::vec2(bias);
_vZipTc1.reserve(_vertCount);
@ -377,7 +377,7 @@ void BaseConvert::Mesh::Compress()
{
Mesh::Vec2Short tc;
glm::vec3 v((_vUberVerts[i]._tc1), 0);
Scene::BaseMesh::QuantizeV(v, extents, aabb._mn);
World::BaseMesh::QuantizeV(v, extents, aabb._mn);
tc._u = short(v.x);
tc._v = short(v.y);
_vZipTc1.push_back(tc);

View File

@ -7,7 +7,7 @@ namespace verus
{
class Cursor : public Object
{
Scene::TexturePwn _tex;
World::TexturePwn _tex;
CGI::CSHandle _csh;
float _x = 0.5f;
float _y = 0.5f;

View File

@ -7,7 +7,7 @@ namespace verus
{
class Image : public Widget
{
Scene::TexturePwn _tex;
World::TexturePwn _tex;
CGI::CSHandle _csh;
Vector4 _tcScale = Vector4(1, 1);
Linear<Vector4> _tcBias;

View File

@ -51,7 +51,7 @@ namespace verus
String _locale = "RU";
TMapStrings _mapStrings;
Vector<PWidget> _vTabList;
Scene::TexturePwn _tex;
World::TexturePwn _tex;
PWidget _pLastHovered = nullptr;
PInputFocus _pInputFocus = nullptr;
State _state = State::done;

View File

@ -436,8 +436,8 @@ Matrix4 ViewManager::GetXrMatrix() const
if (CGI::ViewType::openXR != renderer.GetCurrentViewType())
return Matrix4::identity();
VERUS_QREF_SM;
return (_xrMatrixEnabled && sm.GetHeadCamera() && sm.GetPassCamera()) ?
sm.GetPassCamera()->GetMatrixVP() * sm.GetHeadCamera()->GetMatrixInvV() *
VERUS_QREF_WM;
return (_xrMatrixEnabled && wm.GetHeadCamera() && wm.GetPassCamera()) ?
wm.GetPassCamera()->GetMatrixVP() * wm.GetHeadCamera()->GetMatrixInvV() *
Transform3(Matrix3::scale(Vector3(0.25f * (16 / 9.f), 0.25f)), Vector3(0, 0, -1)) : Matrix4::identity();
}

View File

@ -251,7 +251,7 @@ void BaseCharacter::EndRagdoll()
void BaseCharacter::ComputeThirdPersonCameraArgs(RcVector3 offset, RPoint3 eye, RPoint3 at)
{
VERUS_QREF_SM;
VERUS_QREF_WM;
const float r = 0.1f;
Point3 point;
@ -262,14 +262,14 @@ void BaseCharacter::ComputeThirdPersonCameraArgs(RcVector3 offset, RPoint3 eye,
const float startAt = _cc.GetRadius() + _cc.GetHeight() * 0.5f; // Inside capsule.
const Point3 origin = pos + Vector3(0, startAt, 0);
at = pos + offsetW;
if (sm.RayCastingTest(origin, at, nullptr, &point, &norm, &r))
if (wm.RayTestEx(origin, at, nullptr, &point, &norm, &r, Physics::Bullet::I().GetMainMask()))
at = point + norm * r;
eye = at - GetFrontDirection() * _cameraRadius.GetValue() + offsetW * 0.05f;
}
float BaseCharacter::ComputeThirdPersonCamera(Scene::RCamera camera, Anim::RcOrbit orbit, RcVector3 offset)
float BaseCharacter::ComputeThirdPersonCamera(World::RCamera camera, Anim::RcOrbit orbit, RcVector3 offset)
{
VERUS_QREF_SM;
VERUS_QREF_WM;
const float r = 0.1f;
Point3 point;
@ -288,7 +288,7 @@ float BaseCharacter::ComputeThirdPersonCamera(Scene::RCamera camera, Anim::RcOrb
eye = at + Vector3(toEye);
float ret = 0;
if (sm.RayCastingTest(at, eye, nullptr, &point, &norm, &r)) // Hitting the wall?
if (wm.RayTestEx(at, eye, nullptr, &point, &norm, &r, Physics::Bullet::I().GetMainMask())) // Hitting the wall?
{
eye = point + norm * r;
const float maxCameraRadius = VMath::dist(at, eye) + r;
@ -315,7 +315,7 @@ float BaseCharacter::ComputeThirdPersonCamera(Scene::RCamera camera, Anim::RcOrb
void BaseCharacter::ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVector3 offset)
{
VERUS_QREF_SM;
VERUS_QREF_WM;
const float r = 0.1f;
Point3 point;
@ -324,7 +324,7 @@ void BaseCharacter::ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVec
Point3 eye, at;
ComputeThirdPersonCameraArgs(offset, eye, at);
if (sm.RayCastingTest(at, eye, nullptr, &point, &norm, &r)) // Hitting the wall?
if (wm.RayTestEx(at, eye, nullptr, &point, &norm, &r, Physics::Bullet::I().GetMainMask())) // Hitting the wall?
{
eye = point + norm * r;
}

View File

@ -77,7 +77,7 @@ namespace verus
virtual void BaseCharacter_OnDoneRagdoll() {}
virtual void ComputeThirdPersonCameraArgs(RcVector3 offset, RPoint3 eye, RPoint3 at);
float ComputeThirdPersonCamera(Scene::RCamera camera, Anim::RcOrbit orbit, RcVector3 offset = Vector3(0));
float ComputeThirdPersonCamera(World::RCamera camera, Anim::RcOrbit orbit, RcVector3 offset = Vector3(0));
void ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVector3 offset = Vector3(0));
void SetMaxCameraRadius(float r);
float GetCameraRadius() const { return _cameraRadius.GetValue(); }

View File

@ -26,7 +26,7 @@ VERUS_TYPEDEFS(MyRendererDelegate);
struct BaseGame::Pimpl : AllocatorAware
{
PBaseGame _p = nullptr;
Scene::MainCamera _camera;
World::MainCamera _camera;
Spirit _cameraSpirit;
bool _defaultCameraMovement = true;
bool _escapeKeyExitGame = true;
@ -107,14 +107,14 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS, App::Window::RcDesc windowDes
// Configure:
VERUS_QREF_RENDERER;
_p->_camera.Update();
if (Scene::SceneManager::IsValidSingleton())
Scene::SceneManager::I().SetAllCameras(&_p->_camera);
if (World::WorldManager::IsValidSingleton())
World::WorldManager::I().SetAllCameras(&_p->_camera);
renderer.BeginFrame(); // Begin recording a command buffer.
renderer.InitCmd();
_engineInit.InitCmd();
if (Scene::MaterialManager::IsValidSingleton())
Scene::MaterialManager::I().InitCmd();
if (World::MaterialManager::IsValidSingleton())
World::MaterialManager::I().InitCmd();
BaseGame_LoadContent();
renderer.EndFrame(); // End recording a command buffer.
@ -161,8 +161,7 @@ void BaseGame::Loop(bool relativeMouseMode)
{
case SDL_KEYDOWN:
{
if (event.key.keysym.mod & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT))
keyboardShortcut = BaseGame_SDL_OnKeyboardShortcut(event.key.keysym.sym, event.key.keysym.mod);
keyboardShortcut = BaseGame_SDL_OnKeyboardShortcut(event.key.keysym.sym, event.key.keysym.mod);
}
break;
case SDL_MOUSEMOTION:
@ -298,20 +297,20 @@ void BaseGame::Loop(bool relativeMouseMode)
_p->_cameraSpirit.Update();
_p->_camera.MoveEyeTo(_p->_cameraSpirit.GetPosition());
_p->_camera.MoveAtTo(_p->_cameraSpirit.GetPosition() + _p->_cameraSpirit.GetFrontDirection());
if (Scene::Water::IsValidSingleton())
if (World::Water::IsValidSingleton())
{
VERUS_QREF_WATER;
if (water.IsInitialized())
_p->_camera.ExcludeWaterLine();
}
_p->_camera.Update();
if (Scene::SceneManager::IsValidSingleton())
Scene::SceneManager::I().SetAllCameras(&_p->_camera);
if (World::WorldManager::IsValidSingleton())
World::WorldManager::I().SetAllCameras(&_p->_camera);
}
else
{
if (Scene::SceneManager::IsValidSingleton())
Scene::SceneManager::I().SetAllCameras(nullptr);
if (World::WorldManager::IsValidSingleton())
World::WorldManager::I().SetAllCameras(nullptr);
}
BaseGame_Update(); // Between physics and audio update.
@ -379,7 +378,7 @@ void BaseGame::ToggleFullscreen()
throw VERUS_RUNTIME_ERROR << "SDL_SetWindowFullscreen()";
}
Scene::RCamera BaseGame::GetDefaultCamera()
World::RCamera BaseGame::GetDefaultCamera()
{
return _p->_camera;
}

View File

@ -52,7 +52,7 @@ namespace verus
void ToggleFullscreen();
// Camera:
Scene::RCamera GetDefaultCamera();
World::RCamera GetDefaultCamera();
RSpirit GetCameraSpirit();
// Configuration:

View File

@ -183,11 +183,11 @@ bool ActiveMechanics::UpdateMultiplayer()
return false;
}
Scene::PMainCamera ActiveMechanics::GetScreenCamera()
World::PMainCamera ActiveMechanics::GetScreenCamera()
{
for (auto p : _vStack)
{
Scene::PMainCamera pCamera = p->GetScreenCamera();
World::PMainCamera pCamera = p->GetScreenCamera();
if (pCamera)
return pCamera;
}

View File

@ -32,7 +32,7 @@ namespace verus
bool OnTakeDamage(int id, float amount);
void OnViewChanged(CGI::RcViewDesc viewDesc);
bool UpdateMultiplayer();
Scene::PMainCamera GetScreenCamera();
World::PMainCamera GetScreenCamera();
void Reset();
bool Push(RMechanics mech);

View File

@ -571,7 +571,7 @@ void Cutscene::OnViewChanged(CGI::RcViewDesc viewDesc)
}
}
Scene::PMainCamera Cutscene::GetScreenCamera()
World::PMainCamera Cutscene::GetScreenCamera()
{
return _pCurrentCameraCommand ? &_screenCamera : nullptr;
}

View File

@ -131,7 +131,7 @@ namespace verus
Vector<PCommand> _vCommands;
std::function<void(int)> _fnOnEnd;
PCameraCommand _pCurrentCameraCommand = nullptr;
Scene::MainCamera _screenCamera;
World::MainCamera _screenCamera;
int _beginIndex = 0;
int _endIndex = 0;
float _timeSinceBarrier = 0;
@ -166,7 +166,7 @@ namespace verus
virtual bool IsDefaultInputEnabled() override;
virtual Continue OnMouseMove(float x, float y) override;
virtual void OnViewChanged(CGI::RcViewDesc viewDesc) override;
virtual Scene::PMainCamera GetScreenCamera() override;
virtual World::PMainCamera GetScreenCamera() override;
void SetOnEndCallback(std::function<void(int)> fn) { _fnOnEnd = fn; }

View File

@ -31,7 +31,7 @@ namespace verus
virtual Continue OnTakeDamage(int id, float amount) { return Continue::yes; }
virtual void OnViewChanged(CGI::RcViewDesc viewDesc) {}
virtual Continue UpdateMultiplayer() { return Continue::yes; }
virtual Scene::PMainCamera GetScreenCamera() { return nullptr; }
virtual World::PMainCamera GetScreenCamera() { return nullptr; }
};
VERUS_TYPEDEFS(Mechanics);
}

View File

@ -250,7 +250,7 @@ Transform3 Spirit::GetUprightWithLeanMatrix() const
float Spirit::GetMotionBlur() const
{
VERUS_QREF_SM;
Scene::PMainCamera pViewCamera = sm.GetViewCamera();
VERUS_QREF_WM;
World::PMainCamera pViewCamera = wm.GetViewCamera();
return pViewCamera ? pViewCamera->ComputeMotionBlur(_smoothPosition, _smoothPrevPosition) : 1;
}

View File

@ -23,8 +23,8 @@ void EngineInit::Make()
Make_Effects();
if (_makeExtra)
Make_Extra();
if (_makeScene)
Make_Scene();
if (_makeWorld)
Make_World();
if (_makeGUI)
Make_GUI();
}
@ -34,8 +34,8 @@ void EngineInit::Free()
// Some object must outlive others, so the order is important:
if (_makeGUI)
Free_GUI();
if (_makeScene)
Free_Scene();
if (_makeWorld)
Free_World();
if (_makeExtra)
Free_Extra();
if (_makeEffects)
@ -79,19 +79,22 @@ void EngineInit::Init(CGI::RendererDelegate* pRendererDelegate)
Effects::Particles::InitStatic();
if (_makeGUI)
GUI::Font::InitStatic();
if (_makeScene)
if (_makeWorld)
{
Scene::Mesh::InitStatic();
Scene::Terrain::InitStatic();
Scene::Grass::InitStatic();
Scene::Forest::InitStatic();
World::Mesh::InitStatic();
World::Terrain::InitStatic();
World::Grass::InitStatic();
World::Forest::InitStatic();
}
// Helpers:
if (_makeCGI && _allowInitShaders)
CGI::DebugDraw::I().Init();
if (_makeScene)
Scene::Helpers::I().Init();
if (_makeWorld)
{
World::WorldUtils::I().Init();
World::EditorOverlays::I().Init();
}
// Effects:
if (_makeEffects)
@ -104,8 +107,8 @@ void EngineInit::Init(CGI::RendererDelegate* pRendererDelegate)
}
// Materials & textures:
if (_makeScene)
Scene::MaterialManager::I().Init();
if (_makeWorld)
World::MaterialManager::I().Init();
if (_makeGUI)
GUI::ViewManager::I().Init();
@ -125,6 +128,6 @@ void EngineInit::ReducedFeatureSet()
_makeGUI = false;
_makeNet = false;
_makePhysics = false;
_makeScene = false;
_makeWorld = false;
_allowInitShaders = false;
}

View File

@ -24,7 +24,7 @@ namespace verus
bool _makeIO = true;
bool _makeNet = true;
bool _makePhysics = true;
bool _makeScene = true;
bool _makeWorld = true;
bool _allowInitShaders = true;
void Make();

View File

@ -25,6 +25,8 @@
#define _C(x) ((x).c_str())
#define VERUS_MAKE_VERSION(major, minor, patch) (((major)<<24)|((minor)<<12)|(patch))
#define VERUS_P_FOR(i, to) Parallel::For(0, to, [&](int i)
#define VERUS_U_FOR(i, to) for(UINT32 i = 0; i < to; ++i)
#define VERUS_FOR(i, to) for(int i = 0; i < to; ++i)

View File

@ -3,28 +3,28 @@
#define VERUS_QREF_ASYNC IO::RAsync async = IO::Async::I()
#define VERUS_QREF_ASYS Audio::RAudioSystem asys = Audio::AudioSystem::I()
#define VERUS_QREF_ATMO Scene::RAtmosphere atmo = Scene::Atmosphere::I()
#define VERUS_QREF_ATMO World::RAtmosphere atmo = World::Atmosphere::I()
#define VERUS_QREF_BLOOM Effects::RBloom bloom = Effects::Bloom::I()
#define VERUS_QREF_BLUR Effects::RBlur blur = Effects::Blur::I()
#define VERUS_QREF_BULLET Physics::RBullet bullet = Physics::Bullet::I()
#define VERUS_QREF_CINEMA Effects::RCinema cinema = Effects::Cinema::I()
#define VERUS_QREF_CONST_SETTINGS App::RcSettings settings = App::Settings::IConst()
#define VERUS_QREF_DD CGI::RDebugDraw dd = CGI::DebugDraw::I()
#define VERUS_QREF_EO World::REditorOverlays eo = World::EditorOverlays::I()
#define VERUS_QREF_FSYS IO::RFileSystem fsys = IO::FileSystem::I()
#define VERUS_QREF_GRASS Scene::RGrass grass = Scene::Grass::I()
#define VERUS_QREF_HELPERS Scene::RHelpers helpers = Scene::Helpers::I()
#define VERUS_QREF_GRASS World::RGrass grass = World::Grass::I()
#define VERUS_QREF_IM Input::RInputManager im = Input::InputManager::I()
#define VERUS_QREF_LMB Scene::RLightMapBaker lmb = Scene::LightMapBaker::I()
#define VERUS_QREF_MM Scene::RMaterialManager mm = Scene::MaterialManager::I()
#define VERUS_QREF_LMB World::RLightMapBaker lmb = World::LightMapBaker::I()
#define VERUS_QREF_MM World::RMaterialManager mm = World::MaterialManager::I()
#define VERUS_QREF_MP Net::RMultiplayer mp = Net::Multiplayer::I()
#define VERUS_QREF_PHYSICS Physics::RPhysics physics = Physics::Physics::I()
#define VERUS_QREF_RENDERER CGI::RRenderer renderer = CGI::Renderer::I()
#define VERUS_QREF_SETTINGS App::RSettings settings = App::Settings::I()
#define VERUS_QREF_SM Scene::RSceneManager sm = Scene::SceneManager::I()
#define VERUS_QREF_SSAO Effects::RSsao ssao = Effects::Ssao::I()
#define VERUS_QREF_SSR Effects::RSsr ssr = Effects::Ssr::I()
#define VERUS_QREF_TIMER RTimer timer = Timer::I(); const float dt = timer.GetDeltaTime()
#define VERUS_QREF_TIMER_GUI RTimer timer = Timer::I(); const float dt = timer.GetDeltaTime(Timer::Type::gui)
#define VERUS_QREF_UTILS RUtils utils = Utils::I()
#define VERUS_QREF_VM GUI::RViewManager vm = GUI::ViewManager::I()
#define VERUS_QREF_WATER Scene::RWater water = Scene::Water::I()
#define VERUS_QREF_WATER World::RWater water = World::Water::I()
#define VERUS_QREF_WM World::RWorldManager wm = World::WorldManager::I()
#define VERUS_QREF_WU World::RWorldUtils wu = World::WorldUtils::I()

View File

@ -113,13 +113,17 @@ namespace verus
return nullptr;
}
void Delete(const TKey& key)
bool Delete(const TKey& key)
{
VERUS_IF_FOUND_IN(TMap, _map, key, it)
{
if (it->second.Done())
{
_map.erase(it);
return true;
}
}
return false;
}
void DeleteAll()

View File

@ -13,6 +13,7 @@ namespace verus
bool operator==(const Str& that) const { return !strcmp(_sz, that._sz); }
bool operator!=(const Str& that) const { return 0 != strcmp(_sz, that._sz); }
bool operator<(const Str& that) const { return strcmp(_sz, that._sz) < 0; }
size_t Size() const { return strlen(_sz) + 1; }
size_t Length() const { return strlen(_sz); }

View File

@ -407,7 +407,7 @@ bool FileSystem::FileExist(CSZ url)
File file;
if (file.Open(_C(pathname))) // Normal filename:
return true;
if (file.Open(_C(pakPathname))) // PAK filename:
if (file.Open(_C(pakPathname))) // PAK filename (don't check contents, just assume that it's there):
return true;
if (file.Open(_C(projectPathname))) // File in another project dir:
return true;

View File

@ -10,7 +10,7 @@
#include "Json.h"
#include "Xml.h"
#include "Dictionary.h"
#include "Xxx.h"
#include "Vwx.h"
namespace verus
{

147
Verus/src/IO/Vwx.cpp Normal file
View File

@ -0,0 +1,147 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::IO;
Vwx::Vwx()
{
}
Vwx::~Vwx()
{
Async::I().Cancel(this);
}
void Vwx::Async_WhenLoaded(CSZ url, RcBlob blob)
{
if (Str::EndsWith(url, ".xxx", false))
{
Deserialize_LegacyXXX(url, blob);
return;
}
VERUS_QREF_WM;
IO::StreamPtr sp(blob);
UINT32 temp;
UINT32 blockType = 0;
INT64 blockSize = 0;
char buffer[IO::Stream::s_bufferSize] = {};
sp.Read(buffer, 5);
VERUS_RT_ASSERT(!strcmp(buffer, "<VWX>"));
sp >> temp;
sp >> temp;
sp.ReadString(buffer);
VERUS_RT_ASSERT(!strcmp(buffer, "1.0.0"));
UINT32 verMajor = 0, verMinor = 0, verPatch = 0;
sscanf(buffer, "%d.%d.%d", &verMajor, &verMinor, &verPatch);
sp.SetVersion(VERUS_MAKE_VERSION(verMajor, verMinor, verPatch));
while (!sp.IsEnd())
{
sp >> temp;
sp >> blockType;
sp >> blockSize;
switch (blockType)
{
case '>MW<':
{
wm.Deserialize(sp);
}
break;
default:
{
sp.Advance(blockSize);
}
}
}
}
void Vwx::Serialize(CSZ url)
{
File file;
if (!file.Open(url, "wb"))
return;
VERUS_QREF_WM;
file.WriteText("<VWX>");
file.WriteText(VERUS_CRNL VERUS_CRNL "<VN>");
file.WriteString("1.0.0");
wm.Serialize(file);
}
void Vwx::Deserialize(CSZ url, bool sync)
{
if (sync)
{
Vector<BYTE> vData;
IO::FileSystem::LoadResource(url, vData);
Async_WhenLoaded(url, Blob(vData.data(), vData.size()));
}
else
Async::I().Load(url, this);
}
void Vwx::Deserialize_LegacyXXX(CSZ url, RcBlob blob)
{
VERUS_QREF_WM;
IO::StreamPtr sp(blob);
UINT32 temp;
UINT32 blockType = 0;
INT64 blockSize = 0;
char buffer[IO::Stream::s_bufferSize] = {};
sp.Read(buffer, 5);
VERUS_RT_ASSERT(!strcmp(buffer, "<XXX>"));
sp >> temp;
sp >> temp;
sp.ReadString(buffer);
VERUS_RT_ASSERT(!strcmp(buffer, "3.0"));
UINT32 verMajor = 0, verMinor = 0;
sscanf(buffer, "%d.%d", &verMajor, &verMinor);
sp.SetVersion(VERUS_MAKE_VERSION(1, 0, 0));
Vector<BYTE> vTerrain;
while (!sp.IsEnd())
{
sp >> temp;
sp >> blockType;
sp >> blockSize;
switch (blockType)
{
case '>RT<':
{
vTerrain.resize(blockSize);
sp.Read(vTerrain.data(), blockSize);
}
break;
case '>MS<':
{
wm.Deserialize_LegacyXXX(sp);
}
break;
default:
{
sp.Advance(blockSize);
}
}
}
if (!vTerrain.empty() && wm.IsInitialized())
{
IO::StreamPtr sp(Blob(vTerrain.data(), vTerrain.size()));
World::TerrainNode::Desc desc;
desc._terrainDesc._mapSide = 0;
World::TerrainNodePtr terrainNode;
terrainNode.Init(desc);
terrainNode->GetTerrain().Deserialize(sp);
}
}

22
Verus/src/IO/Vwx.h Normal file
View File

@ -0,0 +1,22 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace IO
{
class Vwx : public AsyncDelegate
{
public:
Vwx();
~Vwx();
virtual void Async_WhenLoaded(CSZ url, RcBlob blob) override;
void Serialize(CSZ url);
void Deserialize(CSZ url, bool sync);
void Deserialize_LegacyXXX(CSZ url, RcBlob blob);
};
}
}

View File

@ -1,330 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::IO;
void Xxx::Serialize(CSZ path)
{
VERUS_QREF_SM;
VERUS_QREF_MM;
File file;
if (!file.Open(path, "wb"))
return;
const UINT32 magic = '2XXX';
file << magic;
const UINT16 version = 0x0105;
file << version;
mm.Serialize(file);
sm.Serialize(file);
}
void Xxx::Deserialize(CSZ path, RString error, bool keepExisting)
{
#if 0
VERUS_QREF_SM;
VERUS_QREF_MM;
if (!IO::CFileSys::FileExist(path))
{
error = "File not found.";
return;
}
CVector<BYTE> vData;
IO::CFileSys::LoadResource(path, vData);
if (vData.size() < 4)
{
error = "Invalid file size.";
return;
}
if (CStr::EndsWith(path, ".xml", false))
{
tinyxml2::XMLDocument doc;
doc.Parse(reinterpret_cast<CSZ>(&vData.front()));
if (doc.Error())
{
error = "Invalid XML.";
return;
}
tinyxml2::XMLHandle hDoc(&doc);
tinyxml2::XMLHandle hRoot = hDoc.FirstChildElement();
// Restart material manager:
if (!keepExisting)
{
mm.Done();
mm.Init();
}
CString levelName = strrchr(path, '\\') + 1;
levelName = levelName.substr(0, levelName.length() - 4);
tinyxml2::XMLElement* pElemPath = hRoot.FirstChildElement("path").ToElement();
if (pElemPath && pElemPath->GetText())
levelName = pElemPath->GetText();
CStringStream ssMissingTextures;
for (tinyxml2::XMLElement* pElem = hRoot.FirstChildElement("material").ToElement(); pElem; pElem = pElem->NextSiblingElement("material"))
{
CSZ name = pElem->GetText();
if (!name)
continue;
CString nameEx = strchr(name, '\\') ? CStr::FixCyrillicX(name, false) : name;
CString nameEx2 = strchr(name, '\\') ? CStr::FixCyrillicX(name, true) : name;
CString textureUrl = CString("Textures:") + levelName + "/" + nameEx;
textureUrl = textureUrl.substr(0, textureUrl.length() - 4) + ".dds";
if (!IO::CFileSys::FileExist(textureUrl.c_str()))
{
ssMissingTextures << textureUrl << VERUS_CRNL;
textureUrl = CString("Textures:") + levelName + "/" + nameEx2;
textureUrl = textureUrl.substr(0, textureUrl.length() - 4) + ".dds";
}
if (IO::CFileSys::FileExist(textureUrl.c_str()))
{
Scene::PMaterial pMat = new Scene::CMaterial(pElem->Attribute("name"));
pMat->m_texAlbedoID = mm.Texture_Add(textureUrl.c_str());
pMat->m_colorDiffuse.FromString4(pElem->Attribute("faceColor"));
pMat->m_colorSpec.FromString3(pElem->Attribute("specularColor"));
pMat->m_colorEmission.FromString3(pElem->Attribute("emissiveColor"));
pElem->QueryFloatAttribute("power", &pMat->m_specPower);
mm.Material_Add(pMat, false);
}
else
{
ssMissingTextures << textureUrl << VERUS_CRNL;
}
}
if (!ssMissingTextures.str().empty())
{
IO::CFileSys::SaveString(IO::CFileSys::ReplaceFilename(path, "MissingTextures.txt").c_str(), ssMissingTextures.str().c_str());
}
if (!keepExisting)
sm.DeleteAll();
CStringStream ssMissingObjects;
for (tinyxml2::XMLElement* pElem = hRoot.FirstChildElement("object").ToElement(); pElem; pElem = pElem->NextSiblingElement("object"))
{
CSZ name = pElem->GetText();
if (!name)
continue;
CSZ copyOf = pElem->Attribute("copyOf");
float4x4 initialMatrix;
initialMatrix.FromString(pElem->Attribute("matrix"));
CSZ material = pElem->Attribute("mat");
if (copyOf && strlen(copyOf) > 0)
{
Scene::PUnit pu = static_cast<Scene::PUnit>(sm.GetObjectByID(sm.FindUnitID(copyOf)));
Scene::PModel pModel = sm.FindModel(pu->GetModelID());
Math::CBounds modelBounds;
modelBounds.FromOrientedBox(pModel->GetMesh().GetBounds(), initialMatrix);
const float size = modelBounds.GetSmartSize();
Scene::CUnit::CInitParams ip;
ip.m_initialMatrix = initialMatrix;
ip.m_url = name;
ip.m_urlModel = pu->GetModelName().c_str();
ip.m_material = material;
sm.AddUnit(ip);
pu = static_cast<Scene::PUnit>(sm.GetObjectByID(sm.FindUnitID(name)));
if (size > 20)
{
char scale[16];
sprintf_s(scale, "%g", 20 / size);
pu->GetParamList().Add("$LM_SCALE", scale);
}
}
else
{
CString modelUrl = CString("Geometry:") + levelName + "/" + name + ".x3d";
if (IO::CFileSys::FileExist(modelUrl.c_str()))
{
sm.InsertModel(modelUrl.c_str(), false, material);
Scene::PModel pModel = sm.FindModel(sm.FindModelID(modelUrl.c_str()));
Math::CBounds modelBounds;
modelBounds.FromOrientedBox(pModel->GetMesh().GetBounds(), initialMatrix);
const float size = modelBounds.GetSmartSize();
Scene::CUnit::CInitParams ip;
ip.m_initialMatrix = initialMatrix;
ip.m_url = name;
ip.m_urlModel = modelUrl.c_str();
ip.m_material = material;
sm.AddUnit(ip);
Scene::PUnit pu = static_cast<Scene::PUnit>(sm.GetObjectByID(sm.FindUnitID(name)));
if (size > 20)
{
char scale[16];
sprintf_s(scale, "%g", 20 / size);
pu->GetParamList().Add("$LM_SCALE", scale);
}
}
else
{
ssMissingObjects << modelUrl << VERUS_CRNL;
}
}
}
if (!ssMissingObjects.str().empty())
{
IO::CFileSys::SaveString(IO::CFileSys::ReplaceFilename(path, "MissingObjects.txt").c_str(), ssMissingObjects.str().c_str());
}
}
else
{
IO::StreamPtr sp(&vData.front(), vData.size());
UINT32 magic = 0;
sp >> magic;
if (magic != '2XXX')
{
error = "File format is not XXX2.";
return;
}
UINT16 version = 0;
sp >> version;
if (version != 0x0105)
{
CStringStream ss;
ss << "Invalid file version (0x" << std::hex << version << ").";
error = ss.str();
return;
}
UINT16 chunkID = 0;
int blockSize, blockBegin, blockEnd;
while (sp.GetOffset() < sp.GetSize())
{
sp >> chunkID;
sp >> blockSize;
blockBegin = sp.GetOffset();
switch (chunkID)
{
case VERUS_XXX_MATERIALMANAGER:
mm.Deserialize(sp);
break;
case VERUS_XXX_LANDSCAPE:
break;
case VERUS_XXX_SCENEMANAGER:
sm.Deserialize(sp);
break;
default:
{
sp.Advance(blockSize);
}
}
blockEnd = sp.GetOffset();
if (blockEnd - blockBegin != blockSize)
{
error = "File is corrupted.";
return;
}
}
}
#endif
}
Xxx::Xxx(Scene::Terrain* pTerrain) :
_pTerrain(pTerrain)
{
}
Xxx::~Xxx()
{
Async::I().Cancel(this);
}
void Xxx::Async_WhenLoaded(CSZ url, RcBlob blob)
{
VERUS_QREF_SM;
IO::StreamPtr sp(blob);
UINT32 temp;
UINT32 blockType = 0;
INT64 blockSize = 0;
char buffer[IO::Stream::s_bufferSize] = {};
sp.Read(buffer, 5);
sp >> temp;
sp >> temp;
sp.ReadString(buffer);
VERUS_RT_ASSERT(!strcmp(buffer, "3.0"));
UINT32 verMajor = 0, verMinor = 0;
sscanf(buffer, "%d.%d", &verMajor, &verMinor);
sp.SetVersion(MakeVersion(verMajor, verMinor));
while (!sp.IsEnd())
{
sp >> temp;
sp >> blockType;
sp >> blockSize;
switch (blockType)
{
case '>RT<':
{
if (_pTerrain)
_pTerrain->Deserialize(sp);
else
sp.Advance(blockSize);
}
break;
case '>MS<':
{
sm.Deserialize(sp);
}
break;
default:
{
sp.Advance(blockSize);
}
}
}
}
void Xxx::SerializeXXX3(CSZ url)
{
File file;
if (!file.Open(url, "wb"))
return;
VERUS_QREF_SM;
file.WriteText("<XXX>");
file.WriteText(VERUS_CRNL VERUS_CRNL "<VN>");
file.WriteString("3.0");
if (_pTerrain)
_pTerrain->Serialize(file);
sm.Serialize(file);
}
void Xxx::DeserializeXXX3(CSZ url, bool sync)
{
if (sync)
{
Vector<BYTE> vData;
IO::FileSystem::LoadResource(url, vData);
Async_WhenLoaded(url, Blob(vData.data(), vData.size()));
}
else
Async::I().Load(url, this);
}
UINT32 Xxx::MakeVersion(UINT32 verMajor, UINT32 verMinor)
{
return (verMajor << 16) | (verMinor & 0xFFFF);
}

View File

@ -1,35 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
class Terrain;
}
}
namespace verus
{
namespace IO
{
class Xxx : public AsyncDelegate
{
Scene::Terrain* _pTerrain = nullptr;
public:
static void Serialize(CSZ path);
static void Deserialize(CSZ path, RString error, bool keepExisting = false);
Xxx(Scene::Terrain* pTerrain = nullptr);
~Xxx();
virtual void Async_WhenLoaded(CSZ url, RcBlob blob) override;
void SerializeXXX3(CSZ url);
void DeserializeXXX3(CSZ url, bool sync);
static UINT32 MakeVersion(UINT32 verMajor, UINT32 verMinor);
};
}
}

View File

@ -194,6 +194,11 @@ Transform3 Bounds::GetDrawTransform() const
return Math::BoundsDrawMatrix(_min, _max);
}
Transform3 Bounds::GetBoxTransform() const
{
return Math::BoundsBoxMatrix(_min, _max);
}
RBounds Bounds::MirrorY()
{
const float miny = _min.getY();

View File

@ -48,6 +48,7 @@ namespace verus
Sphere GetSphere() const;
Matrix4 GetMatrix() const;
Transform3 GetDrawTransform() const;
Transform3 GetBoxTransform() const;
Bounds& MirrorY();
Bounds& Wrap();

View File

@ -130,27 +130,15 @@ void Frustum::Draw()
dd.End();
}
Vector4 Frustum::GetBounds(RcMatrix4 m, float& zNear, float& zFar) const
Bounds Frustum::GetBounds(RcTransform3 tr, PPoint3 pFocusedCenterPos) const
{
Vector4 ret(
+FLT_MAX,
+FLT_MAX,
-FLT_MAX,
-FLT_MAX);
zNear = -FLT_MAX;
zFar = FLT_MAX;
Bounds ret;
VERUS_FOR(i, 8)
ret.Include(tr * _corners[i]);
if (pFocusedCenterPos)
{
const Vector4 matSpace = m * _corners[i];
ret = Vector4(
Math::Min<float>(ret.getX(), matSpace.getX()),
Math::Min<float>(ret.getY(), matSpace.getY()),
Math::Max<float>(ret.getZ(), matSpace.getX()),
Math::Max<float>(ret.getW(), matSpace.getY()));
// In RH-system closer objects have larger z values!
zNear = Math::Max<float>(zNear, matSpace.getZ());
zFar = Math::Min<float>(zFar, matSpace.getZ());
*pFocusedCenterPos = ret.GetCenter();
pFocusedCenterPos->setZ((tr * _corners[8]).getZ());
}
return ret;
}

View File

@ -36,7 +36,7 @@ namespace verus
RcPoint3 GetZNearPosition() const { return _corners[8]; }
RcPoint3 GetZFarPosition() const { return _corners[9]; }
Vector4 GetBounds(RcMatrix4 m, float& zNear, float& zFar) const;
Bounds GetBounds(RcTransform3 tr, PPoint3 pFocusedCenterPos = nullptr) const;
Frustum& SetNearPlane(RcPoint3 eye, RcVector3 front, float zNear);
Frustum& SetFarPlane(RcPoint3 eye, RcVector3 front, float zFar);

View File

@ -379,6 +379,13 @@ Transform3 Math::BoundsDrawMatrix(RcPoint3 mn, RcPoint3 mx)
return VMath::appendScale(Transform3::translation(c - Point3(0, d.getY() * 0.5f, 0)), d);
}
Transform3 Math::BoundsBoxMatrix(RcPoint3 mn, RcPoint3 mx)
{
const Vector3 d = mx - mn;
const Vector3 c = VMath::lerp(0.5f, mn, mx);
return VMath::appendScale(Transform3::translation(c), d);
}
float Math::ComputeOnePixelDistance(float objectSize, float viewportHeightInPixels, float fovY)
{
// Assume that object occupies one pixel, then the whole viewport height will be:
@ -474,6 +481,20 @@ float Math::Reduce(float val, float reduction)
return val - glm::sign(val) * reduction;
}
Point3 Math::ClosestPointOnSegment(RcPoint3 segA, RcPoint3 segB, RcPoint3 point)
{
const float lenSq = VMath::distSqr(segA, segB);
if (lenSq < VERUS_FLOAT_THRESHOLD)
return segA;
const float t = Math::Clamp<float>(VMath::dot(point - segA, segB - segA) / lenSq, 0, 1);
return VMath::lerp(t, segA, segB);
}
float Math::SegmentToPointDistance(RcPoint3 segA, RcPoint3 segB, RcPoint3 point)
{
return VMath::dist(point, ClosestPointOnSegment(segA, segB, point));
}
void Math::Test()
{
const float e = 1e-6f;
@ -655,11 +676,11 @@ void Math::Test()
}
{
//const Point3 a(1, 0, 0), b(3, 0, 0), p(1.25f, 3, 0), p2(10, 10, 0);
//Point3 res = ClosestPointOnLineSegment(a, b, p);
//VERUS_RT_ASSERT(glm::all(glm::epsilonEqual(res.GLM(), glm::vec3(1.25f, 0, 0), eps)));
//Point3 res2 = ClosestPointOnLineSegment(a, b, p2);
//VERUS_RT_ASSERT(glm::all(glm::epsilonEqual(res2.GLM(), glm::vec3(3, 0, 0), eps)));
const Point3 a(1, 0, 0), b(3, 0, 0), p(1.25f, 3, 0), p2(10, 10, 0);
Point3 res = ClosestPointOnSegment(a, b, p);
VERUS_RT_ASSERT(glm::all(glm::epsilonEqual(res.GLM(), glm::vec3(1.25f, 0, 0), eps)));
Point3 res2 = ClosestPointOnSegment(a, b, p2);
VERUS_RT_ASSERT(glm::all(glm::epsilonEqual(res2.GLM(), glm::vec3(3, 0, 0), eps)));
}
{
@ -693,7 +714,7 @@ void Math::Test()
{
// Right-handed mode (default):
Scene::Camera camera;
World::Camera camera;
camera.MoveEyeTo(Point3(0, 0, 3));
camera.MoveAtTo(Point3(0, 0, 4));
camera.SetYFov(VERUS_PI * 0.25f);

View File

@ -6,6 +6,8 @@
#define VERUS_E 2.718281828f
#define VERUS_GR 1.618034f
#define VERUS_HERMITE_CIRCLE ((0.707107f-0.5f)*8.f)
#define VERUS_FLOAT_THRESHOLD 1e-4f
namespace verus
@ -151,6 +153,7 @@ namespace verus
// Scene:
Transform3 BoundsDrawMatrix(RcPoint3 mn, RcPoint3 mx);
Transform3 BoundsBoxMatrix(RcPoint3 mn, RcPoint3 mx);
float ComputeOnePixelDistance(float objectSize, float viewportHeightInPixels = 135, float fovY = VERUS_PI / 4);
float ComputeDistToMipScale(float texHeight, float viewportHeightInPixels, float objectSize, float fovY);
void Quadrant(const int** ppSrcMinMax, int** ppDestMinMax, int half, int id);
@ -165,6 +168,9 @@ namespace verus
float Reduce(float val, float reduction);
Point3 ClosestPointOnSegment(RcPoint3 segA, RcPoint3 segB, RcPoint3 point);
float SegmentToPointDistance(RcPoint3 segA, RcPoint3 segB, RcPoint3 point);
void Test();
};
}

View File

@ -214,7 +214,7 @@ Continue Octree::TraverseVisible(RcFrustum frustum, PResult pResult, int current
pResult->_testCount = 0;
pResult->_passedTestCount = 0;
pResult->_pLastFoundToken = nullptr;
pResult->_depth = Scene::SceneManager::IsDrawingDepth(Scene::DrawDepth::automatic);
pResult->_depth = World::WorldManager::IsDrawingDepth(World::DrawDepth::automatic);
}
pResult->_testCount++;

View File

@ -153,7 +153,7 @@ void QuadtreeIntegral::InitNodes(int currentNode, int depth)
void QuadtreeIntegral::TraverseVisible(int currentNode, int depth)
{
VERUS_QREF_SM;
VERUS_QREF_WM;
if (!currentNode)
{
@ -166,7 +166,7 @@ void QuadtreeIntegral::TraverseVisible(int currentNode, int depth)
bool testFrustum = true;
if (_distCoarseMode && depth + 2 >= _maxDepth)
{
RcPoint3 headPos = sm.GetHeadCamera()->GetEyePosition();
RcPoint3 headPos = wm.GetHeadCamera()->GetEyePosition();
RcPoint3 nodePos = _vNodes[currentNode].GetSphere().GetCenter();
const float distSq = VMath::distSqr(headPos, nodePos);
if (_maxDepth == depth && distSq >= 500 * 500.f)
@ -177,7 +177,7 @@ void QuadtreeIntegral::TraverseVisible(int currentNode, int depth)
testFrustum = false;
}
RFrustum frustum = sm.GetPassCamera()->GetFrustum();
RFrustum frustum = wm.GetPassCamera()->GetFrustum();
if (testFrustum && Relation::outside == frustum.ContainsAabb(_vNodes[currentNode].GetBounds()))
return;

View File

@ -62,8 +62,8 @@ btRigidBody* Bullet::AddNewRigidBody(
float mass,
const btTransform& startTransform,
btCollisionShape* pShape,
Group group,
Group mask,
int group,
int mask,
const btTransform* pCenterOfMassOffset,
void* pPlacementMotionState,
void* pPlacementRigidBody)
@ -82,16 +82,12 @@ btRigidBody* Bullet::AddNewRigidBody(
else
pMotionState = new btDefaultMotionState(startTransform, pCenterOfMassOffset ? *pCenterOfMassOffset : btTransform::getIdentity());
btRigidBody::btRigidBodyConstructionInfo rbci(mass, pMotionState, pShape, localInertia);
rbci.m_linearDamping = 0.01f;
rbci.m_angularDamping = 0.01f;
rbci.m_rollingFriction = 0.001f;
rbci.m_spinningFriction = 0.001f;
btRigidBody* pRigidBody = nullptr;
if (pPlacementRigidBody)
pRigidBody = new(pPlacementRigidBody) btRigidBody(rbci);
else
pRigidBody = new btRigidBody(rbci);
_pDiscreteDynamicsWorld->addRigidBody(pRigidBody, +group, +mask);
_pDiscreteDynamicsWorld->addRigidBody(pRigidBody, group, mask);
return pRigidBody;
}
@ -101,8 +97,8 @@ btRigidBody* Bullet::AddNewRigidBody(
float mass,
const btTransform& startTransform,
btCollisionShape* pShape,
Group group,
Group mask,
int group,
int mask,
const btTransform* pCenterOfMassOffset)
{
btAssert(!pShape || pShape->getShapeType() != INVALID_SHAPE_PROXYTYPE);
@ -116,12 +112,8 @@ btRigidBody* Bullet::AddNewRigidBody(
btDefaultMotionState* pMotionState = new(localRigidBody.GetDefaultMotionStateData())
btDefaultMotionState(startTransform, pCenterOfMassOffset ? *pCenterOfMassOffset : btTransform::getIdentity());
btRigidBody::btRigidBodyConstructionInfo rbci(mass, pMotionState, pShape, localInertia);
rbci.m_linearDamping = 0.01f;
rbci.m_angularDamping = 0.01f;
rbci.m_rollingFriction = 0.001f;
rbci.m_spinningFriction = 0.001f;
btRigidBody* pRigidBody = new(localRigidBody.GetRigidBodyData()) btRigidBody(rbci);
_pDiscreteDynamicsWorld->addRigidBody(pRigidBody, +group, +mask);
_pDiscreteDynamicsWorld->addRigidBody(pRigidBody, group, mask);
return pRigidBody;
}
@ -134,9 +126,9 @@ void Bullet::DeleteAllCollisionObjects()
for (int i = _pDiscreteDynamicsWorld->getNumCollisionObjects() - 1; i >= 0; --i)
{
btCollisionObject* pObject = _pDiscreteDynamicsWorld->getCollisionObjectArray()[i];
btRigidBody* pBody = btRigidBody::upcast(pObject);
if (pBody && pBody->getMotionState())
delete pBody->getMotionState();
btRigidBody* pRigidBody = btRigidBody::upcast(pObject);
if (pRigidBody && pRigidBody->getMotionState())
delete pRigidBody->getMotionState();
_pDiscreteDynamicsWorld->removeCollisionObject(pObject);
delete pObject;
}
@ -196,7 +188,7 @@ void Bullet::EnableDebugPlane(bool b)
{
btTransform tr;
tr.setIdentity();
_pStaticPlaneRigidBody = AddNewRigidBody(_pStaticPlaneRigidBody, 0, tr, _pStaticPlaneShape.Get(), Group::sceneBounds);
_pStaticPlaneRigidBody = AddNewRigidBody(_pStaticPlaneRigidBody, 0, tr, _pStaticPlaneShape.Get(), +Group::wall);
_pStaticPlaneRigidBody->setFriction(GetFriction(Material::wood));
_pStaticPlaneRigidBody->setRestitution(GetRestitution(Material::wood));
}
@ -242,3 +234,28 @@ float Bullet::GetRestitution(Material m)
}
return 0;
}
CSZ Bullet::GroupToString(int index)
{
CSZ text[] =
{
"General",
"Immovable",
"Kinematic",
"Debris",
"Sensor",
"Character",
"Ragdoll",
"Ray",
"Node",
"Dynamic",
"Gizmo",
"Particle",
"Terrain",
"Transport",
"Wall"
};
if (index >= 0 && index < VERUS_COUNT_OF(text))
return text[index];
return nullptr;
}

View File

@ -56,7 +56,8 @@ namespace verus
rubber,
sand,
stone,
wood
wood,
count
};
enum class DebugDrawMode : int
@ -78,6 +79,7 @@ namespace verus
LocalRigidBody _pStaticPlaneRigidBody;
btGhostPairCallback _ghostPairCallback;
BulletDebugDraw _debugDraw;
Group _mainMask = Group::immovable | Group::terrain;
bool _pauseSimulation = false;
public:
@ -93,8 +95,8 @@ namespace verus
float mass,
const btTransform& startTransform,
btCollisionShape* pShape,
Group group = Group::general,
Group mask = Group::all,
int group = +Group::general,
int mask = +Group::all,
const btTransform* pCenterOfMassOffset = nullptr,
void* pPlacementMotionState = nullptr,
void* pPlacementRigidBody = nullptr);
@ -103,8 +105,8 @@ namespace verus
float mass,
const btTransform& startTransform,
btCollisionShape* pShape,
Group group = Group::general,
Group mask = Group::all,
int group = +Group::general,
int mask = +Group::all,
const btTransform* pCenterOfMassOffset = nullptr);
void DeleteAllCollisionObjects();
@ -119,6 +121,11 @@ namespace verus
static float GetFriction(Material m);
static float GetRestitution(Material m);
static CSZ GroupToString(int index);
Group GetMainMask() const { return _mainMask; }
void SetMainMask(Group mask) { _mainMask = mask; }
};
VERUS_TYPEDEFS(Bullet);
}

View File

@ -7,9 +7,9 @@ using namespace verus::Physics;
void BulletDebugDraw::drawLine(const btVector3& from, const btVector3& to,
const btVector3& color)
{
VERUS_QREF_SM;
VERUS_QREF_WM;
const float maxDistSq = s_maxDrawDist * s_maxDrawDist;
const Point3 headPos = sm.GetHeadCamera()->GetEyePosition();
const Point3 headPos = wm.GetHeadCamera()->GetEyePosition();
if (VMath::distSqr(headPos, Point3(from)) >= maxDistSq &&
VMath::distSqr(headPos, Point3(to)) >= maxDistSq)
return;
@ -21,9 +21,9 @@ void BulletDebugDraw::drawLine(const btVector3& from, const btVector3& to,
void BulletDebugDraw::drawLine(const btVector3& from, const btVector3& to,
const btVector3& fromColor, const btVector3& toColor)
{
VERUS_QREF_SM;
VERUS_QREF_WM;
const float maxDistSq = s_maxDrawDist * s_maxDrawDist;
const Point3 headPos = sm.GetHeadCamera()->GetEyePosition();
const Point3 headPos = wm.GetHeadCamera()->GetEyePosition();
if (VMath::distSqr(headPos, Point3(from)) >= maxDistSq &&
VMath::distSqr(headPos, Point3(to)) >= maxDistSq)
return;

View File

@ -7,7 +7,7 @@ namespace verus
{
class BulletDebugDraw : public btIDebugDraw
{
static const int s_maxDrawDist = 30;
static const int s_maxDrawDist = 25;
int _debugMode = 0;

View File

@ -67,7 +67,7 @@ void CharacterController::Done()
int CharacterController::UserPtr_GetType()
{
return +Scene::NodeType::character;
return +World::NodeType::character;
}
void CharacterController::SetRadius(float r)

View File

@ -5,7 +5,7 @@ namespace verus
{
namespace Physics
{
enum class Group : short
enum class Group : UINT32
{
none = 0,
general = (1 << 0),
@ -14,13 +14,16 @@ namespace verus
debris = (1 << 3),
sensor = (1 << 4),
character = (1 << 5),
terrain = (1 << 6),
sceneBounds = (1 << 7),
gizmo = (1 << 8),
pickable = (1 << 9),
particle = (1 << 10),
vehicle = (1 << 11),
all = -1
ragdoll = (1 << 6),
ray = (1 << 7), // rayTest
node = (1 << 8), // World::PBaseNode
dynamic = (1 << 9),
gizmo = (1 << 10), // Editor::PGizmoTool
particle = (1 << 11),
terrain = (1 << 12),
transport = (1 << 13),
wall = (1 << 14),
all = UINT32_MAX
};
}
}

View File

@ -24,34 +24,42 @@ void Vehicle::Init(RcDesc desc)
_wheelCount = leftWheelCount + rightWheelCount;
_invWheelCount = 1.f / _wheelCount;
float maxHeight = -FLT_MAX;
// <Clearance>
float maxWheelY = -FLT_MAX;
Vector3 averageWheelPos(0);
VERUS_FOR(i, leftWheelCount)
{
averageWheelPos += Vector3(desc._vLeftWheels[i].GetCenter());
maxHeight = Math::Max<float>(maxHeight, desc._vLeftWheels[i].GetCenter().getY());
maxWheelY = Math::Max<float>(maxWheelY, desc._vLeftWheels[i].GetCenter().getY());
}
VERUS_FOR(i, rightWheelCount)
{
averageWheelPos += Vector3(desc._vRightWheels[i].GetCenter());
maxHeight = Math::Max<float>(maxHeight, desc._vRightWheels[i].GetCenter().getY());
maxWheelY = Math::Max<float>(maxWheelY, desc._vRightWheels[i].GetCenter().getY());
}
// </Clearance>
averageWheelPos *= _invWheelCount;
Math::Bounds chassis = desc._chassis;
chassis.Set(maxHeight - 0.05f, chassis.GetMax().getY(), 1);
chassis.Set(maxWheelY - 0.05f, chassis.GetMax().getY(), 1); // Adjust clearance.
chassis.Set(
chassis.GetMin().getZ() + chassis.GetExtents().getY(),
chassis.GetMax().getZ() - chassis.GetExtents().getY(),
2); // Make space for bumpers.
const Vector3 centerOfMassOffset = chassis.GetCenter() - Vector3(0, chassis.GetExtents().getY() * 0.7f, 0);
// Lower the center of gravity:
const Vector3 centerOfMassOffset = chassis.GetCenter() - Vector3(0, chassis.GetExtents().getY() * 0.8f, 0);
const Transform3 transformCoM = Transform3::translation(-centerOfMassOffset);
const btTransform trCoM = transformCoM.Bullet();
const float g = bullet.GetWorld()->getGravity().length();
const float forcePerWheel = (desc._mass * g) * _invWheelCount;
const float k = forcePerWheel / desc._suspensionRestLength; // Hooke's law.
const float forcePerWheel = (desc._mass * g) * _invWheelCount; // Newton's law (F = m * a).
const float k = forcePerWheel / desc._suspensionRestLength; // Hooke's law (F = k * x).
_vehicleTuning.m_suspensionStiffness = k / desc._mass;
_vehicleTuning.m_suspensionStiffness = k / desc._mass; // Per 1 kg.
_vehicleTuning.m_suspensionCompression = _vehicleTuning.m_suspensionStiffness * 0.15f;
_vehicleTuning.m_suspensionDamping = _vehicleTuning.m_suspensionStiffness * 0.3f;
_vehicleTuning.m_suspensionDamping = _vehicleTuning.m_suspensionStiffness * 0.2f;
_vehicleTuning.m_maxSuspensionTravelCm = 100 * 2 * desc._suspensionRestLength;
_vehicleTuning.m_frictionSlip = 1.75f;
_vehicleTuning.m_frictionSlip = 1.5f;
_vehicleTuning.m_maxSuspensionForce = forcePerWheel * 3;
averageWheelPos -= centerOfMassOffset;
@ -59,20 +67,31 @@ void Vehicle::Init(RcDesc desc)
if (!desc._vRightWheels.empty())
_frontRightWheelIndex = leftWheelCount;
const float bumperR = chassis.GetExtents().getY();
const float bumperH = Math::Max(VERUS_FLOAT_THRESHOLD, chassis.GetDimensions().getX() - bumperR * 2);
_pChassisShape = new(_pChassisShape.GetData()) btBoxShape(chassis.GetExtents().Bullet());
_pBumperShape = new(_pBumperShape.GetData()) btCapsuleShape(bumperR, bumperH);
_pCompoundShape = new(_pCompoundShape.GetData()) btCompoundShape();
btTransform tr;
tr.setIdentity();
tr.setOrigin(chassis.GetCenter().Bullet() - centerOfMassOffset.Bullet());
const btTransform trCoM = transformCoM.Bullet();
_pCompoundShape->addChildShape(tr, _pChassisShape.Get());
tr.setIdentity();
tr.getBasis().setEulerZYX(0, 0, VERUS_PI * 0.5f);
tr.setOrigin(chassis.GetCenter().Bullet() - centerOfMassOffset.Bullet() + btVector3(0, 0, chassis.GetExtents().getZ()));
_pCompoundShape->addChildShape(tr, _pBumperShape.Get());
tr.setIdentity();
tr.getBasis().setEulerZYX(0, 0, VERUS_PI * 0.5f);
tr.setOrigin(chassis.GetCenter().Bullet() - centerOfMassOffset.Bullet() - btVector3(0, 0, chassis.GetExtents().getZ()));
_pCompoundShape->addChildShape(tr, _pBumperShape.Get());
_pChassis = bullet.AddNewRigidBody(_pChassis, desc._mass, desc._tr.Bullet(), _pCompoundShape.Get(),
Group::vehicle, Group::all, &trCoM);
_pChassis->setFriction(0);
_pChassis->setRestitution(0);
+Group::transport, +Group::all, &trCoM);
_pChassis->setFriction(Bullet::GetFriction(Material::metal));
_pChassis->setRestitution(Bullet::GetRestitution(Material::metal) * 0.25f); // Energy-absorbing deformation.
_pChassis->setUserPointer(this);
_pChassis->setActivationState(DISABLE_DEACTIVATION);
_pChassis->setAngularFactor(btVector3(0.5f, 1, 0.5f)); // For stability.
_pVehicleRaycaster = new(_pVehicleRaycaster.GetData()) btDefaultVehicleRaycaster(bullet.GetWorld());
_pRaycastVehicle = new(_pRaycastVehicle.GetData()) btRaycastVehicle(_vehicleTuning, _pChassis.Get(), _pVehicleRaycaster.Get());
_pRaycastVehicle->setCoordinateSystem(0, 1, 2);
@ -90,7 +109,7 @@ void Vehicle::Init(RcDesc desc)
btRaycastVehicle::btVehicleTuning vehicleTuning(_vehicleTuning);
const Point3 pos = wheel.GetCenter() - centerOfMassOffset;
const float ratio = VMath::dist(pos, Point3(averageWheelPos)) / VMath::length(Vector3(pos));
const float scale = ratio * ratio;
const float scale = ratio * ratio; // Try to level out the car.
vehicleTuning.m_suspensionStiffness *= scale;
vehicleTuning.m_suspensionCompression *= scale;
vehicleTuning.m_suspensionDamping *= scale;
@ -131,6 +150,7 @@ void Vehicle::Done()
_pChassis.Delete();
}
_pCompoundShape.Delete();
_pBumperShape.Delete();
_pChassisShape.Delete();
VERUS_DONE(Vehicle);
@ -138,17 +158,6 @@ void Vehicle::Done()
void Vehicle::Update()
{
const Transform3 tr = GetTransform();
if (tr.getCol1().getY() > 0.25f)
{
_pChassis->setFriction(0);
_pChassis->setRestitution(0);
}
else // Rollover?
{
_pChassis->setFriction(Bullet::GetFriction(Material::metal) * 0.5f);
_pChassis->setRestitution(Bullet::GetRestitution(Material::metal) * 0.25f);
}
}
Transform3 Vehicle::GetTransform() const
@ -160,11 +169,11 @@ void Vehicle::ApplyAirForce(float scale)
{
btVector3 v = _pChassis->getLinearVelocity();
const float speedSq = v.length2();
if (speedSq >= 1e-4f)
if (speedSq >= VERUS_FLOAT_THRESHOLD)
{
const float speed = sqrt(speedSq);
v /= speed;
const float force = speed * speed * scale;
const float force = speed * speed * scale * 2;
_pChassis->applyCentralForce(-v * force); // Drag.
const Transform3 tr = GetTransform();
const Vector3 down = -tr.getCol1();
@ -187,7 +196,7 @@ void Vehicle::SetBrake(float brake, float handBrake, int index)
if (_frontRightWheelIndex > 0)
_pRaycastVehicle->setBrake(perWheel, _frontRightWheelIndex);
}
else
else // All wheel drive?
{
const float perWheel = brake * _invWheelCount;
VERUS_FOR(i, _wheelCount)
@ -218,7 +227,7 @@ void Vehicle::SetEngineForce(float force, int index)
if (_frontRightWheelIndex > 0)
_pRaycastVehicle->applyEngineForce(perWheel, _frontRightWheelIndex);
}
else
else // All wheel drive?
{
const float perWheel = force * _invWheelCount;
VERUS_FOR(i, _wheelCount)
@ -235,7 +244,7 @@ void Vehicle::SetSteeringAngle(float angle)
int Vehicle::UserPtr_GetType()
{
return +Scene::NodeType::vehicle;
return +World::NodeType::vehicle;
}
float Vehicle::ComputeEnginePitch() const
@ -250,12 +259,14 @@ float Vehicle::ComputeEnginePitch() const
}
}
if (!contact)
return 1.8f;
return 1.5f;
const float speedKmHourSigned = _pRaycastVehicle->getCurrentSpeedKmHour();
const float speedKmHour = abs(speedKmHourSigned);
const float base = 1.6f;
const float first = base * 10;
const float gear = (speedKmHourSigned < first) ? Math::Clamp<float>(speedKmHour / first, 0, 0.99f) : log(speedKmHour * 0.1f) / log(base);
const float power = 1 / 2.5f;
const float first = 15.588f; // 3^2.5
const float gear = (speedKmHourSigned < first) ?
Math::Clamp<float>(speedKmHour / first, 0, 0.99f) :
Math::Clamp<float>(pow(speedKmHour, power) - 1, 2, 5.99f);
return 0.8f + Math::Min(0.2f, speedKmHour * 0.004f) + 0.6f * fmod(gear, 1.f);
}

View File

@ -8,6 +8,7 @@ namespace verus
class Vehicle : public Object, public UserPtr
{
LocalPtr<btBoxShape> _pChassisShape;
LocalPtr<btCapsuleShape> _pBumperShape;
LocalPtr<btCompoundShape> _pCompoundShape;
LocalRigidBody _pChassis;
LocalPtr<btDefaultVehicleRaycaster> _pVehicleRaycaster;
@ -23,7 +24,7 @@ namespace verus
{
float _angle = 0;
float _speed = 1;
float _maxAngle = Math::ToRadians(36);
float _maxAngle = Math::ToRadians(40);
void Update(float stiffness)
{
@ -54,7 +55,7 @@ namespace verus
Vector<Math::Sphere> _vLeftWheels;
Vector<Math::Sphere> _vRightWheels;
float _mass = 1200;
float _suspensionRestLength = 0.2f;
float _suspensionRestLength = 0.15f; // 0.25 for buggy, 0.05 for sports car.
};
VERUS_TYPEDEFS(Desc);
@ -80,7 +81,7 @@ namespace verus
btRaycastVehicle* GetRaycastVehicle() { return _pRaycastVehicle.Get(); }
void ApplyAirForce(float scale = 2);
void ApplyAirForce(float scale = 1);
void SetBrake(float brake, float handBrake = 0, int index = -1);
void SetEngineForce(float force, int index = -1);
void SetSteeringAngle(float angle);

View File

@ -1,74 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
// Managed by DeferredShading:
class DeferredLights
{
Mesh _meshDir;
Mesh _meshOmni;
Mesh _meshSpot;
public:
RMesh Get(CGI::LightType type)
{
switch (type)
{
case CGI::LightType::omni: return _meshOmni;
case CGI::LightType::spot: return _meshSpot;
}
return _meshDir;
}
};
VERUS_TYPEDEFS(DeferredLights);
class Helpers : public Singleton<Helpers>, public Object
{
private:
struct Vertex
{
Point3 _pos;
UINT32 _color;
Vertex() {}
Vertex(RcPoint3 pos, UINT32 color)
{
_pos = pos;
_color = color;
}
};
Vector<Vertex> _vGrid;
Vector<Vertex> _vBasis;
Vector<Vertex> _vCircle;
Vector<Vertex> _vBox;
Vector<Vertex> _vLight;
Mesh _sphere;
DeferredLights _deferredLights;
public:
Helpers();
~Helpers();
void Init();
void Done();
void DrawGrid();
void DrawBasis(PcTransform3 pMat = nullptr, int axis = -1, bool overlay = false);
void DrawCircle(RcPoint3 pos, float radius, UINT32 color, RTerrain terrain);
void DrawBox(PcTransform3 pMat = nullptr, UINT32 color = 0);
void DrawLight(RcPoint3 pos, UINT32 color = 0, PcPoint3 pTarget = nullptr);
void DrawSphere(RcPoint3 pos, float r, UINT32 color, CGI::CommandBufferPtr cb);
static UINT32 GetBasisColorX(bool linear = false, int alpha = 255);
static UINT32 GetBasisColorY(bool linear = false, int alpha = 255);
static UINT32 GetBasisColorZ(bool linear = false, int alpha = 255);
RDeferredLights GetDeferredLights() { return _deferredLights; }
};
VERUS_TYPEDEFS(Helpers);
}
}

View File

@ -1,24 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
namespace verus
{
void Make_Scene()
{
Scene::Helpers::Make();
Scene::MaterialManager::Make();
Scene::SceneManager::Make();
Scene::Atmosphere::Make();
Scene::Water::Make();
Scene::LightMapBaker::Make();
}
void Free_Scene()
{
Scene::LightMapBaker::Free();
Scene::Water::Free();
Scene::Atmosphere::Free();
Scene::SceneManager::Free();
Scene::MaterialManager::Free();
Scene::Helpers::Free();
}
}

View File

@ -1,891 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
SceneManager::SceneManager()
{
VERUS_ZERO_MEM(_visibleCountPerType);
}
SceneManager::~SceneManager()
{
Done();
}
void SceneManager::Init(RcDesc desc)
{
VERUS_INIT();
SetAllCameras(desc._pCamera);
_mapSide = desc._mapSide;
const float sideHalf = desc._mapSide * 0.5f;
Math::Bounds bounds;
bounds.Set(
Vector3(-sideHalf, -sideHalf, -sideHalf),
Vector3(+sideHalf, +sideHalf, +sideHalf));
const Vector3 limit(sideHalf / 14, sideHalf / 14, sideHalf / 14);
_octree.Done();
_octree.Init(bounds, limit);
_octree.SetDelegate(this);
}
void SceneManager::Done()
{
DeleteAllTriggers();
DeleteAllPrefabs();
DeleteAllLights();
DeleteAllEmitters();
DeleteAllBlocks();
DeleteAllSites();
DeleteAllSceneParticles();
DeleteAllModels();
VERUS_DONE(SceneManager);
}
void SceneManager::ResetInstanceCount()
{
for (auto& x : TStoreModels::_map)
x.second.GetMesh().ResetInstanceCount();
}
void SceneManager::Update()
{
VERUS_UPDATE_ONCE_CHECK;
for (auto& x : TStoreSceneParticles::_map)
x.second.Update();
for (auto& x : TStoreSites::_map)
x.second.Update();
for (auto& x : TStoreBlocks::_list)
x.Update();
for (auto& x : TStoreEmitters::_list)
x.Update();
for (auto& x : TStoreLights::_list)
x.Update();
for (auto& x : TStorePrefabs::_list)
x.Update();
for (auto& x : TStoreTriggers::_list)
x.Update();
}
void SceneManager::UpdateParts()
{
const RcPoint3 headPos = _pHeadCamera->GetEyePosition();
for (auto& block : TStoreBlocks::_list)
{
const float distSq = VMath::distSqr(block.GetPosition(), headPos);
const float part = MaterialManager::ComputePart(distSq, block.GetBounds().GetAverageSize() * 0.5f);
block.GetMaterial()->IncludePart(part);
}
}
void SceneManager::Layout()
{
VERUS_QREF_ATMO;
VERUS_QREF_CONST_SETTINGS;
VERUS_QREF_SM;
// Allocate enough space:
int countAll = 0;
countAll += Utils::Cast32(TStoreSites::_map.size());
countAll += Utils::Cast32(TStoreBlocks::_list.size());
countAll += Utils::Cast32(TStoreLights::_list.size());
countAll += Utils::Cast32(TStorePrefabs::_list.size());
if (_vVisibleNodes.size() != countAll)
_vVisibleNodes.resize(countAll);
_visibleCount = 0;
VERUS_ZERO_MEM(_visibleCountPerType);
// <Traverse>
PCamera pPrevPassCamera = nullptr;
// For CSM we need to create geometry beyond the view frustum (1st slice):
if (settings._sceneShadowQuality >= App::Settings::Quality::high && atmo.GetShadowMapBaker().IsBaking())
{
PCamera pPassCameraCSM = atmo.GetShadowMapBaker().GetPassCameraCSM();
if (pPassCameraCSM)
pPrevPassCamera = sm.SetPassCamera(pPassCameraCSM);
}
_octree.TraverseVisible(_pPassCamera->GetFrustum());
// Back to original camera:
if (pPrevPassCamera)
SetPassCamera(pPrevPassCamera);
// </Traverse>
VERUS_RT_ASSERT(!_visibleCountPerType[+NodeType::unknown]);
std::sort(_vVisibleNodes.begin(), _vVisibleNodes.begin() + _visibleCount, [](PSceneNode pA, PSceneNode pB)
{
// Sort by node type?
const NodeType typeA = pA->GetType();
const NodeType typeB = pB->GetType();
if (typeA != typeB)
return typeA < typeB;
// Both are blocks?
if (NodeType::block == typeA)
{
PBlock pBlockA = static_cast<PBlock>(pA);
PBlock pBlockB = static_cast<PBlock>(pB);
MaterialPtr materialA = pBlockA->GetMaterial();
MaterialPtr materialB = pBlockB->GetMaterial();
if (materialA && materialB) // A and B have materials, compare them.
{
const bool ab = *materialA < *materialB;
const bool ba = *materialB < *materialA;
if (ab || ba)
return ab;
}
else if (materialA) // A is with material, B is without, so A goes first.
{
return true;
}
else if (materialB) // A is without material, B is with, so B goes first.
{
return false;
}
// Equal materials or none have any material, compare models used:
ModelPtr modelA = pBlockA->GetModel();
ModelPtr modelB = pBlockB->GetModel();
if (modelA != modelB)
return modelA < modelB;
}
// Both are lights?
if (NodeType::light == typeA)
{
PLight pLightA = static_cast<PLight>(pA);
PLight pLightB = static_cast<PLight>(pB);
const CGI::LightType lightTypeA = pLightA->GetLightType();
const CGI::LightType lightTypeB = pLightB->GetLightType();
if (lightTypeA != lightTypeB)
return lightTypeA < lightTypeB;
}
// Draw same node types front-to-back:
return pA->GetDistToHeadSq() < pB->GetDistToHeadSq();
});
}
void SceneManager::Draw()
{
if (!_visibleCountPerType[+NodeType::block])
return;
VERUS_QREF_RENDERER;
ModelPtr model;
MaterialPtr material;
bool bindPipeline = true;
auto cb = renderer.GetCommandBuffer();
auto shader = Mesh::GetShader();
const int begin = FindOffsetFor(NodeType::block);
const int end = begin + _visibleCountPerType[+NodeType::block];
shader->BeginBindDescriptors();
for (int i = begin; i <= end; ++i)
{
if (i == end)
{
if (model)
model->Draw(cb);
break;
}
PSceneNode pSN = _vVisibleNodes[i];
PBlock pBlock = static_cast<PBlock>(pSN);
ModelPtr nextModel = pBlock->GetModel();
MaterialPtr nextMaterial = pBlock->GetMaterial();
if (!nextModel->IsLoaded() || !nextMaterial->IsLoaded())
continue;
const bool changeModel = nextModel != model;
const bool changeMaterial = nextMaterial != material;
if (changeModel || changeMaterial)
{
if (model)
model->Draw(cb);
}
if (changeModel)
{
model = nextModel;
model->MarkFirstInstance();
if (bindPipeline)
{
bindPipeline = false;
model->BindPipeline(cb);
cb->BindDescriptors(shader, 0);
}
model->BindGeo(cb);
cb->BindDescriptors(shader, 2);
}
if (changeMaterial)
{
model->MarkFirstInstance();
material = nextMaterial;
material->UpdateMeshUniformBuffer();
cb->BindDescriptors(shader, 1, material->GetComplexSetHandle());
}
if (model)
model->PushInstance(pBlock->GetTransform(), pBlock->GetColor());
}
shader->EndBindDescriptors();
}
void SceneManager::DrawSimple(DrawSimpleMode mode)
{
if (!_visibleCountPerType[+NodeType::block])
return;
VERUS_QREF_RENDERER;
ModelPtr model;
MaterialPtr material;
bool bindPipeline = true;
auto cb = renderer.GetCommandBuffer();
auto shader = Mesh::GetSimpleShader();
const int begin = FindOffsetFor(NodeType::block);
const int end = begin + _visibleCountPerType[+NodeType::block];
shader->BeginBindDescriptors();
for (int i = begin; i <= end; ++i)
{
if (i == end)
{
if (model)
model->Draw(cb);
break;
}
PSceneNode pSN = _vVisibleNodes[i];
PBlock pBlock = static_cast<PBlock>(pSN);
ModelPtr nextModel = pBlock->GetModel();
MaterialPtr nextMaterial = pBlock->GetMaterial();
if (!nextModel->IsLoaded() || !nextMaterial->IsLoaded())
continue;
const bool changeModel = nextModel != model;
const bool changeMaterial = nextMaterial != material;
if (changeModel || changeMaterial)
{
if (model)
model->Draw(cb);
}
if (changeModel)
{
model = nextModel;
model->MarkFirstInstance();
if (bindPipeline)
{
bindPipeline = false;
model->BindPipelineSimple(mode, cb);
cb->BindDescriptors(shader, 0);
}
model->BindGeo(cb);
cb->BindDescriptors(shader, 2);
}
if (changeMaterial)
{
model->MarkFirstInstance();
material = nextMaterial;
material->UpdateMeshUniformBufferSimple();
cb->BindDescriptors(shader, 1, material->GetComplexSetHandleSimple());
}
if (model)
model->PushInstance(pBlock->GetTransform(), pBlock->GetColor());
}
shader->EndBindDescriptors();
}
void SceneManager::DrawTransparent()
{
for (auto& x : TStoreSceneParticles::_map)
x.second.Draw();
}
void SceneManager::DrawLights()
{
if (!_visibleCountPerType[+NodeType::light])
return;
VERUS_QREF_HELPERS;
VERUS_QREF_RENDERER;
CGI::LightType type = CGI::LightType::none;
PMesh pMesh = nullptr;
bool bindPipeline = true;
auto& ds = renderer.GetDS();
auto cb = renderer.GetCommandBuffer();
auto DrawMesh = [cb](PMesh pMesh)
{
if (pMesh && !pMesh->IsInstanceBufferEmpty(true))
{
pMesh->UpdateInstanceBuffer();
cb->DrawIndexed(pMesh->GetIndexCount(), pMesh->GetInstanceCount(true), 0, 0, pMesh->GetFirstInstance());
}
};
const int begin = FindOffsetFor(NodeType::light);
const int end = begin + _visibleCountPerType[+NodeType::light];
for (int i = begin; i <= end; ++i)
{
if (i == end)
{
DrawMesh(pMesh);
break;
}
PSceneNode pSN = _vVisibleNodes[i];
PLight pLight = static_cast<PLight>(pSN);
const CGI::LightType nextType = pLight->GetLightType();
if (nextType != type)
{
DrawMesh(pMesh);
type = nextType;
ds.OnNewLightType(cb, type);
pMesh = (type != CGI::LightType::none) ? &helpers.GetDeferredLights().Get(type) : nullptr;
if (pMesh)
{
pMesh->MarkFirstInstance();
pMesh->BindGeo(cb, (1 << 0) | (1 << 4));
pMesh->CopyPosDeqScale(&ds.GetUbPerMeshVS()._posDeqScale.x);
pMesh->CopyPosDeqBias(&ds.GetUbPerMeshVS()._posDeqBias.x);
ds.BindDescriptorsPerMeshVS(cb);
}
}
#ifdef VERUS_RELEASE_DEBUG
if (CGI::LightType::dir == type) // Must not be scaled!
{
RcTransform3 matW = pLight->GetTransform();
const Vector3 s = matW.GetScale();
VERUS_RT_ASSERT(glm::all(glm::epsilonEqual(s.GLM(), glm::vec3(1), glm::vec3(VERUS_FLOAT_THRESHOLD))));
}
#endif
if (pMesh)
pMesh->PushInstance(pLight->GetTransform(), pLight->GetInstData());
}
}
void SceneManager::DrawBounds()
{
VERUS_FOR(i, _visibleCount)
{
PSceneNode pSN = _vVisibleNodes[i];
if (pSN->IsSelected())
pSN->DrawBounds();
}
}
bool SceneManager::IsDrawingDepth(DrawDepth dd)
{
if (DrawDepth::automatic == dd)
{
VERUS_QREF_ATMO;
return atmo.GetShadowMapBaker().IsBaking();
}
else
return DrawDepth::yes == dd;
}
int SceneManager::FindOffsetFor(NodeType type) const
{
int ret = 0;
VERUS_FOR(i, +type)
ret += _visibleCountPerType[i];
return ret;
}
String SceneManager::EnsureUniqueName(CSZ name)
{
// Compact name:
const char* s = strrchr(name, ':');
s = s ? s + 1 : name;
const char* e = strrchr(name, '.');
if (!e)
e = name + strlen(name);
// Unique name:
int id = -1;
String test;
do
{
test = (id < 0) ? String(s, e) : String(s, e) + "_" + std::to_string(id);
for (auto& it : TStoreBlocks::_list) if (it.GetName() == _C(test)) test.clear();
for (auto& it : TStoreEmitters::_list) if (it.GetName() == _C(test)) test.clear();
for (auto& it : TStoreLights::_list) if (it.GetName() == _C(test)) test.clear();
for (auto& it : TStorePrefabs::_list) if (it.GetName() == _C(test)) test.clear();
for (auto& it : TStoreTriggers::_list) if (it.GetName() == _C(test)) test.clear();
id++;
} while (test.empty());
return test;
}
PModel SceneManager::InsertModel(CSZ url)
{
return TStoreModels::Insert(url);
}
PModel SceneManager::FindModel(CSZ url)
{
return TStoreModels::Find(url);
}
void SceneManager::DeleteModel(CSZ url)
{
TStoreModels::Delete(url);
}
void SceneManager::DeleteAllModels()
{
TStoreModels::DeleteAll();
}
PSceneParticles SceneManager::InsertSceneParticles(CSZ url)
{
return TStoreSceneParticles::Insert(url);
}
PSceneParticles SceneManager::FindSceneParticles(CSZ url)
{
return TStoreSceneParticles::Find(url);
}
void SceneManager::DeleteSceneParticles(CSZ url)
{
TStoreSceneParticles::Delete(url);
}
void SceneManager::DeleteAllSceneParticles()
{
TStoreSceneParticles::DeleteAll();
}
PSite SceneManager::InsertSite(CSZ name)
{
return TStoreSites::Insert(name);
}
PSite SceneManager::FindSite(CSZ name)
{
return TStoreSites::Find(name);
}
void SceneManager::DeleteSite(CSZ name)
{
TStoreSites::Delete(name);
}
void SceneManager::DeleteAllSites()
{
TStoreSites::DeleteAll();
}
PBlock SceneManager::InsertBlock()
{
return TStoreBlocks::Insert();
}
void SceneManager::DeleteBlock(PBlock p)
{
TStoreBlocks::Delete(p);
}
void SceneManager::DeleteAllBlocks()
{
TStoreBlocks::DeleteAll();
}
PEmitter SceneManager::InsertEmitter()
{
return TStoreEmitters::Insert();
}
void SceneManager::DeleteEmitter(PEmitter p)
{
TStoreEmitters::Delete(p);
}
void SceneManager::DeleteAllEmitters()
{
TStoreEmitters::DeleteAll();
}
PLight SceneManager::InsertLight()
{
return TStoreLights::Insert();
}
void SceneManager::DeleteLight(PLight p)
{
TStoreLights::Delete(p);
}
void SceneManager::DeleteAllLights()
{
TStoreLights::DeleteAll();
}
PPrefab SceneManager::InsertPrefab()
{
return TStorePrefabs::Insert();
}
void SceneManager::DeletePrefab(PPrefab p)
{
TStorePrefabs::Delete(p);
}
void SceneManager::DeleteAllPrefabs()
{
TStorePrefabs::DeleteAll();
}
PTrigger SceneManager::InsertTrigger()
{
return TStoreTriggers::Insert();
}
void SceneManager::DeleteTrigger(PTrigger p)
{
TStoreTriggers::Delete(p);
}
void SceneManager::DeleteAllTriggers()
{
TStoreTriggers::DeleteAll();
}
void SceneManager::DeleteNode(NodeType type, CSZ name)
{
Query query;
query._name = name;
query._type = type;
ForEachNode(query, [this, type](RSceneNode node)
{
switch (type)
{
case NodeType::block: DeleteBlock(static_cast<PBlock>(&node)); break;
case NodeType::light: DeleteLight(static_cast<PLight>(&node)); break;
case NodeType::prefab: DeletePrefab(static_cast<PPrefab>(&node)); break;
}
return Continue::yes;
});
}
bool SceneManager::IsValidNode(PSceneNode pSceneNode)
{
bool ret = false;
Query query;
ForEachNode(query, [pSceneNode, &ret](RSceneNode node)
{
if (&node == pSceneNode)
{
ret = true;
return Continue::no;
}
return Continue::yes;
});
return ret;
}
void SceneManager::ClearSelection()
{
Query query;
query._selected = 1;
ForEachNode(query, [](RSceneNode node)
{
node.Select(false);
return Continue::yes;
});
}
int SceneManager::GetSelectedCount()
{
int ret = 0;
Query query;
query._selected = 1;
ForEachNode(query, [&ret](RSceneNode node)
{
ret++;
return Continue::yes;
});
return ret;
}
Continue SceneManager::Octree_ProcessNode(void* pToken, void* pUser)
{
PSceneNode pSN = static_cast<PSceneNode>(pToken);
if (pSN->IsHidden())
return Continue::yes;
_vVisibleNodes[_visibleCount++] = pSN;
_visibleCountPerType[+pSN->GetType()]++;
return Continue::yes;
}
bool SceneManager::RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, PBlockPtr pBlock,
PPoint3 pPoint, PVector3 pNormal, const float* pRadius, Physics::Group mask)
{
VERUS_RT_ASSERT(!pBlock || *pBlock);
VERUS_QREF_BULLET;
if (!memcmp(pointA.ToPointer(), pointB.ToPointer(), sizeof(float) * 3))
return false;
btVector3 from(pointA.Bullet()), to(pointB.Bullet());
if (pPoint || pNormal)
{
if (pRadius)
{
btSphereShape sphere(*pRadius);
btTransform trA, trB;
trA.setIdentity();
trB.setIdentity();
trA.setOrigin(pointA.Bullet());
trB.setOrigin(pointB.Bullet());
btCollisionWorld::ClosestConvexResultCallback ccrc(from, to);
ccrc.m_collisionFilterMask = +mask;
bullet.GetWorld()->convexSweepTest(&sphere, trA, trB, ccrc);
if (ccrc.hasHit())
{
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(ccrc.m_hitCollisionObject->getUserPointer());
if (pBlock && p->UserPtr_GetType() == +NodeType::block)
pBlock->Attach(static_cast<PBlock>(p));
if (pPoint)
*pPoint = ccrc.m_hitPointWorld;
if (pNormal)
*pNormal = ccrc.m_hitNormalWorld;
return true;
}
else
return false;
}
else
{
btCollisionWorld::ClosestRayResultCallback crrc(from, to);
crrc.m_collisionFilterMask = +mask;
bullet.GetWorld()->rayTest(from, to, crrc);
if (crrc.hasHit())
{
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(crrc.m_collisionObject->getUserPointer());
if (pBlock && p->UserPtr_GetType() == +NodeType::block)
pBlock->Attach(static_cast<PBlock>(p));
if (pPoint)
*pPoint = crrc.m_hitPointWorld;
if (pNormal)
*pNormal = crrc.m_hitNormalWorld;
return true;
}
else
return false;
}
}
else // Point/normal not required?
{
struct AnyRayResultCallback : public btCollisionWorld::RayResultCallback
{
btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
m_closestHitFraction = 0;
m_collisionObject = rayResult.m_collisionObject;
return 0;
}
} arrc;
arrc.m_collisionFilterMask = +mask;
bullet.GetWorld()->rayTest(from, to, arrc);
if (arrc.hasHit())
{
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(arrc.m_collisionObject->getUserPointer());
if (pBlock && p->UserPtr_GetType() == +NodeType::block)
pBlock->Attach(static_cast<PBlock>(p));
return true;
}
else
return false;
}
return false;
}
Matrix3 SceneManager::GetBasisAt(RcPoint3 point, Physics::Group mask) const
{
VERUS_QREF_BULLET;
const btVector3 from = point.Bullet();
const btVector3 to = from - btVector3(0, 100, 0);
btCollisionWorld::ClosestRayResultCallback crrc(from, to);
crrc.m_collisionFilterMask = +mask;
bullet.GetWorld()->rayTest(from, to, crrc);
if (crrc.hasHit())
{
glm::vec3 nreal = Vector3(crrc.m_hitNormalWorld).GLM(), nrm(0, 1, 0), tan(1, 0, 0), bin(0, 0, 1);
const float angle = glm::angle(nrm, nreal);
VERUS_RT_ASSERT(angle <= VERUS_PI * 0.5f);
if (angle >= Math::ToRadians(1))
{
const glm::vec3 axis = glm::normalize(glm::cross(nrm, nreal));
const glm::quat q = glm::angleAxis(angle, axis);
const glm::mat3 mat = glm::mat3_cast(q);
tan = mat * tan;
bin = mat * bin;
}
return Matrix3(Vector3(tan), Vector3(nreal), Vector3(bin));
}
else
return Matrix3::identity();
}
void SceneManager::Serialize(IO::RSeekableStream stream)
{
stream.WriteText(VERUS_CRNL VERUS_CRNL "<SM>");
stream.BeginBlock();
stream.WriteString(_C(std::to_string(_mapSide)));
stream.WriteString(_C(std::to_string(TStoreModels::GetStoredCount())));
for (auto& x : TStoreModels::_map)
{
stream.WriteString(_C(x.first));
x.second.Serialize(stream);
}
auto GetPersistentCount = [this](NodeType type)
{
int count = 0;
Query query;
query._type = type;
ForEachNode(query, [&count](RSceneNode node)
{
if (!node.IsTransient())
count++;
return Continue::yes;
});
return count;
};
stream.WriteString(_C(std::to_string(GetPersistentCount(NodeType::block))));
for (auto& x : TStoreBlocks::_list)
{
if (!x.IsTransient())
x.Serialize(stream);
}
stream.WriteString(_C(std::to_string(GetPersistentCount(NodeType::emitter))));
for (auto& x : TStoreEmitters::_list)
{
if (!x.IsTransient())
x.Serialize(stream);
}
stream.WriteString(_C(std::to_string(GetPersistentCount(NodeType::light))));
for (auto& x : TStoreLights::_list)
{
if (!x.IsTransient())
x.Serialize(stream);
}
stream.WriteString(_C(std::to_string(GetPersistentCount(NodeType::prefab))));
for (auto& x : TStorePrefabs::_list)
{
if (!x.IsTransient())
x.Serialize(stream);
}
stream.WriteString(_C(std::to_string(GetPersistentCount(NodeType::trigger))));
for (auto& x : TStoreTriggers::_list)
{
if (!x.IsTransient())
x.Serialize(stream);
}
stream.EndBlock();
}
void SceneManager::Deserialize(IO::RStream stream)
{
char buffer[IO::Stream::s_bufferSize] = {};
int count = 0;
if (stream.GetVersion() >= IO::Xxx::MakeVersion(3, 0))
{
stream.ReadString(buffer);
const int mapSide = atoi(buffer);
Desc desc;
desc._mapSide = mapSide;
PCamera pPassCamera = _pPassCamera;
PMainCamera pHeadCamera = _pHeadCamera;
PMainCamera pViewCamera = _pViewCamera;
Done();
Init(desc);
_pPassCamera = pPassCamera;
_pHeadCamera = pHeadCamera;
_pViewCamera = pViewCamera;
stream.ReadString(buffer);
count = atoi(buffer);
VERUS_FOR(i, count)
{
stream.ReadString(buffer);
PModel p = InsertModel(buffer);
p->Deserialize(stream, buffer);
}
stream.ReadString(buffer);
count = atoi(buffer);
VERUS_FOR(i, count)
{
PBlock p = InsertBlock();
p->Deserialize(stream);
}
stream.ReadString(buffer);
count = atoi(buffer);
VERUS_FOR(i, count)
{
PEmitter p = InsertEmitter();
p->Deserialize(stream);
}
stream.ReadString(buffer);
count = atoi(buffer);
VERUS_FOR(i, count)
{
PLight p = InsertLight();
p->Deserialize(stream);
}
stream.ReadString(buffer);
count = atoi(buffer);
VERUS_FOR(i, count)
{
PPrefab p = InsertPrefab();
p->Deserialize(stream);
}
stream.ReadString(buffer);
count = atoi(buffer);
VERUS_FOR(i, count)
{
PTrigger p = InsertTrigger();
p->Deserialize(stream);
}
}
}

View File

@ -1,257 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
typedef StoreUnique<String, Model> TStoreModels;
typedef StoreUnique<String, SceneParticles> TStoreSceneParticles;
typedef StoreUnique<String, Site> TStoreSites;
typedef Store<Block> TStoreBlocks;
typedef Store<Emitter> TStoreEmitters;
typedef Store<Light> TStoreLights;
typedef Store<Prefab> TStorePrefabs;
typedef Store<Trigger> TStoreTriggers;
class SceneManager : public Singleton<SceneManager>, public Object, public Math::OctreeDelegate,
private TStoreModels, private TStoreSceneParticles, private TStoreSites,
private TStoreBlocks, private TStoreEmitters, private TStoreLights, private TStorePrefabs, private TStoreTriggers
{
Math::Octree _octree;
PCamera _pPassCamera = nullptr; // Render pass camera for getting view and projection matrices.
PMainCamera _pHeadCamera = nullptr; // Head camera which is located between the eyes.
PMainCamera _pViewCamera = nullptr; // Current view camera which is valid only inside DrawView method (eye camera).
Vector<PSceneNode> _vVisibleNodes;
int _visibleCount = 0;
int _visibleCountPerType[+NodeType::count];
int _mapSide = 0;
public:
struct Desc
{
PMainCamera _pCamera = nullptr;
int _mapSide = 256;
Desc() {}
};
VERUS_TYPEDEFS(Desc);
struct Query
{
CSZ _name = nullptr;
CSZ _blockMesh = nullptr;
CSZ _blockMaterial = nullptr;
CSZ _particlesUrl = nullptr;
NodeType _type = NodeType::unknown;
int _selected = -1;
void Reset() { *this = Query(); }
};
VERUS_TYPEDEFS(Query);
SceneManager();
virtual ~SceneManager();
void Init(RcDesc desc = Desc());
void Done();
void ResetInstanceCount();
void Update();
void UpdateParts();
void Layout();
void Draw();
void DrawSimple(DrawSimpleMode mode);
void DrawTransparent();
void DrawLights();
void DrawBounds();
// Cameras:
PCamera GetPassCamera() const { return _pPassCamera; }
PMainCamera GetHeadCamera() const { return _pHeadCamera; }
PMainCamera GetViewCamera() const { return _pViewCamera; }
PCamera SetPassCamera(PCamera p) { return Utils::Swap(_pPassCamera, p); }
PMainCamera SetHeadCamera(PMainCamera p) { return Utils::Swap(_pHeadCamera, p); }
PMainCamera SetViewCamera(PMainCamera p) { return Utils::Swap(_pViewCamera, p); }
void SetAllCameras(PMainCamera p) { _pPassCamera = _pHeadCamera = _pViewCamera = p; }
static bool IsDrawingDepth(DrawDepth dd);
int FindOffsetFor(NodeType type) const;
String EnsureUniqueName(CSZ name);
// Models:
PModel InsertModel(CSZ url);
PModel FindModel(CSZ url);
void DeleteModel(CSZ url);
void DeleteAllModels();
template<typename T>
void ForEachModel(const T& fn)
{
VERUS_FOREACH_X(TStoreModels::TMap, TStoreModels::_map, it)
{
auto& model = *it++;
if (Continue::no == fn(model.second))
return;
}
}
// SceneParticles:
PSceneParticles InsertSceneParticles(CSZ url);
PSceneParticles FindSceneParticles(CSZ url);
void DeleteSceneParticles(CSZ url);
void DeleteAllSceneParticles();
template<typename T>
void ForEachParticles(const T& fn)
{
VERUS_FOREACH_X(TStoreSceneParticles::TMap, TStoreSceneParticles::_map, it)
{
auto& particles = *it++;
if (Continue::no == fn(particles.second))
return;
}
}
// Sites:
PSite InsertSite(CSZ name);
PSite FindSite(CSZ name);
void DeleteSite(CSZ name);
void DeleteAllSites();
template<typename T>
void ForEachSite(const T& fn)
{
VERUS_FOREACH_X(TStoreSites::TMap, TStoreSites::_map, it)
{
auto& site = *it++;
if (Continue::no == fn(site.second))
return;
}
}
// Blocks:
PBlock InsertBlock();
void DeleteBlock(PBlock p);
void DeleteAllBlocks();
// Emitters:
PEmitter InsertEmitter();
void DeleteEmitter(PEmitter p);
void DeleteAllEmitters();
// Lights (and Shadows):
PLight InsertLight();
void DeleteLight(PLight p);
void DeleteAllLights();
// Prefabs:
PPrefab InsertPrefab();
void DeletePrefab(PPrefab p);
void DeleteAllPrefabs();
// Triggers:
PTrigger InsertTrigger();
void DeleteTrigger(PTrigger p);
void DeleteAllTriggers();
template<typename T>
void ForEachNode(RcQuery query, const T& fn)
{
auto MatchName = [&query](RSceneNode node)
{
return !query._name || node.GetName() == query._name;
};
auto MatchSelected = [&query](RSceneNode node)
{
return -1 == query._selected || !!query._selected == node.IsSelected();
};
if (NodeType::unknown == query._type || NodeType::block == query._type)
{
VERUS_FOREACH_X(TStoreBlocks::TList, TStoreBlocks::_list, it)
{
auto& block = *it++;
if (
MatchName(block) &&
MatchSelected(block) &&
(!query._blockMesh || block.GetUrl() == query._blockMesh) &&
(!query._blockMaterial || block.GetMaterial()->_name == query._blockMaterial))
if (Continue::no == fn(block))
return;
}
}
if (query._blockMesh || query._blockMaterial)
return;
if (NodeType::unknown == query._type || NodeType::emitter == query._type)
{
VERUS_FOREACH_X(TStoreEmitters::TList, TStoreEmitters::_list, it)
{
auto& emitter = *it++;
if (
MatchName(emitter) &&
MatchSelected(emitter) &&
(!query._particlesUrl || emitter.GetUrl() == query._particlesUrl))
if (Continue::no == fn(emitter))
return;
}
}
if (NodeType::unknown == query._type || NodeType::light == query._type)
{
VERUS_FOREACH_X(TStoreLights::TList, TStoreLights::_list, it)
{
auto& light = *it++;
if (
MatchName(light) &&
MatchSelected(light))
if (Continue::no == fn(light))
return;
}
}
if (NodeType::unknown == query._type || NodeType::prefab == query._type)
{
VERUS_FOREACH_X(TStorePrefabs::TList, TStorePrefabs::_list, it)
{
auto& prefab = *it++;
if (
MatchName(prefab) &&
MatchSelected(prefab))
if (Continue::no == fn(prefab))
return;
}
}
if (NodeType::unknown == query._type || NodeType::trigger == query._type)
{
VERUS_FOREACH_X(TStoreTriggers::TList, TStoreTriggers::_list, it)
{
auto& trigger = *it++;
if (
MatchName(trigger) &&
MatchSelected(trigger))
if (Continue::no == fn(trigger))
return;
}
}
}
void DeleteNode(NodeType type, CSZ name);
bool IsValidNode(PSceneNode pSceneNode);
void ClearSelection();
int GetSelectedCount();
// Octree (Acceleration Structure):
Math::ROctree GetOctree() { return _octree; }
virtual Continue Octree_ProcessNode(void* pToken, void* pUser) override;
bool RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, PBlockPtr pBlock = nullptr,
PPoint3 pPoint = nullptr, PVector3 pNormal = nullptr, const float* pRadius = nullptr,
Physics::Group mask = Physics::Group::immovable | Physics::Group::terrain);
Matrix3 GetBasisAt(RcPoint3 point, Physics::Group mask = Physics::Group::immovable | Physics::Group::terrain) const;
void Serialize(IO::RSeekableStream stream);
void Deserialize(IO::RStream stream);
};
VERUS_TYPEDEFS(SceneManager);
}
}

View File

@ -1,250 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// Block:
Block::Block()
{
_type = NodeType::block;
}
Block::~Block()
{
Done();
}
void Block::Init(RcDesc desc)
{
VERUS_QREF_SM;
_name = sm.EnsureUniqueName(desc._name ? desc._name : desc._model);
_matIndex = desc._matIndex;
_collide = desc._collide;
Model::Desc modelDesc;
modelDesc._url = desc._model;
modelDesc._mat = desc._modelMat;
_model.Init(modelDesc);
if (1 == _model->GetRefCount())
_model->AddRef(); // Models must be owned by blocks and scene manager.
if (desc._blockMat)
{
Material::Desc matDesc;
matDesc._name = desc._blockMat;
matDesc._load = true;
_material.Init(matDesc);
}
String url = desc._model;
Str::ReplaceExtension(url, ".Extra.xml");
Vector<BYTE> vData;
IO::FileSystem::I().LoadResourceFromCache(_C(url), vData, false);
if (vData.size() > 1)
LoadExtra(reinterpret_cast<SZ>(vData.data()));
}
void Block::Done()
{
RemoveRigidBody();
_material.Done();
_model.Done();
SceneManager::I().GetOctree().UnbindElement(this);
_vLights.clear();
_vEmitters.clear();
}
void Block::LoadExtra(SZ xml)
{
pugi::xml_document doc;
const pugi::xml_parse_result result = doc.load_buffer_inplace(xml, strlen(xml));
if (!result)
throw VERUS_RECOVERABLE << "load_buffer_inplace(); " << result.description();
pugi::xml_node root = doc.first_child();
int lightCount = 0;
for (auto node : root.children("light"))
{
auto matAttr = node.attribute("mat");
if (!matAttr || matAttr.as_int() == _matIndex)
lightCount++;
}
int emitterCount = 0;
for (auto node : root.children("emit"))
emitterCount++;
_vLights.resize(lightCount);
_vEmitters.resize(emitterCount);
int i = 0;
for (auto node : root.children("light"))
{
auto matAttr = node.attribute("mat");
if (!matAttr || matAttr.as_int() == _matIndex)
{
RLightPwn light = _vLights[i]._light;
Light::Desc desc;
desc._node = node;
light.Init(desc);
light->SetTransient();
_vLights[i]._tr = light->GetTransform();
light->SetTransform(GetTransform() * _vLights[i]._tr);
i++;
}
}
i = 0;
for (auto node : root.children("emit"))
{
REmitterPwn emitter = _vEmitters[i]._emitter;
Emitter::Desc desc;
desc._node = node;
emitter.Init(desc);
emitter->SetTransient();
_vEmitters[i]._tr = emitter->GetTransform();
emitter->SetTransform(GetTransform() * _vEmitters[i]._tr);
i++;
}
}
void Block::Update()
{
if (!_async_loadedModel && _model->IsLoaded())
{
_async_loadedModel = true;
if (!_dynamic)
{
VERUS_QREF_BULLET;
const btTransform tr = GetTransform().Bullet();
_pBody = bullet.AddNewRigidBody(0, tr, _model->GetMesh().GetShape(), Physics::Group::immovable);
_pBody->setFriction(Physics::Bullet::GetFriction(Physics::Material::stone));
_pBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::stone));
_pBody->setUserPointer(this);
SetCollisionGroup(_collide ? Physics::Group::immovable : Physics::Group::general);
}
UpdateBounds();
}
}
MaterialPtr Block::GetMaterial(bool orModelMat)
{
if (!_material && orModelMat)
return _model->GetMaterial();
return _material;
}
void Block::UpdateBounds()
{
if (_model->IsLoaded())
{
if (!_octreeBindOnce)
{
_bounds = Math::Bounds::MakeFromOrientedBox(_model->GetMesh().GetBounds(), _tr);
SceneManager::I().GetOctree().BindElement(Math::Octree::Element(_bounds, this), _dynamic);
_octreeBindOnce = _dynamic;
}
if (_dynamic)
{
_bounds = Math::Bounds::MakeFromOrientedBox(_model->GetMesh().GetBounds(), _tr);
SceneManager::I().GetOctree().UpdateDynamicBounds(Math::Octree::Element(_bounds, this));
}
}
for (auto& x : _vLights)
x._light->SetTransform(GetTransform() * x._tr);
for (auto& x : _vEmitters)
x._emitter->SetTransform(GetTransform() * x._tr);
}
void Block::Serialize(IO::RSeekableStream stream)
{
SceneNode::Serialize(stream);
stream.WriteString(_C(GetUrl()));
stream.WriteString(_material ? _C(_material->_name) : "");
stream << _userColor.GLM();
}
void Block::Deserialize(IO::RStream stream)
{
SceneNode::Deserialize(stream);
const String savedName = _C(GetName());
PreventNameCollision();
if (stream.GetVersion() >= IO::Xxx::MakeVersion(3, 0))
{
char url[IO::Stream::s_bufferSize] = {};
char material[IO::Stream::s_bufferSize] = {};
glm::vec4 userColor;
stream.ReadString(url);
stream.ReadString(material);
stream >> userColor;
_userColor = userColor;
Desc desc;
desc._name = _C(savedName);
desc._model = url;
desc._blockMat = (strlen(material) > 0) ? material : nullptr;
if (desc._blockMat)
desc._matIndex = atoi(strrchr(desc._blockMat, '.') - 1);
Init(desc);
}
}
void Block::SaveXML(pugi::xml_node node)
{
SceneNode::SaveXML(node);
node.append_attribute("url") = _C(GetUrl());
if (_material)
node.append_attribute("mat") = _C(_material->_name);
if (!_userColor.IsZero())
node.append_attribute("color") = _C(_userColor.ToColorString());
}
void Block::LoadXML(pugi::xml_node node)
{
SceneNode::LoadXML(node);
PreventNameCollision();
_userColor = Vector4(0);
if (auto attr = node.attribute("color"))
_userColor.FromColorString(attr.value());
Desc desc;
desc._name = node.attribute("name").value();
desc._model = node.attribute("url").value();
if (auto attr = node.attribute("mat"))
desc._blockMat = attr.value();
if (desc._blockMat)
desc._matIndex = atoi(strrchr(desc._blockMat, '.') - 1);
Init(desc);
}
// BlockPtr:
void BlockPtr::Init(Block::RcDesc desc)
{
VERUS_QREF_SM;
VERUS_RT_ASSERT(!_p);
_p = sm.InsertBlock();
if (desc._node)
_p->LoadXML(desc._node);
else
_p->Init(desc);
}
void BlockPwn::Done()
{
if (_p)
{
SceneManager::I().DeleteBlock(_p);
_p = nullptr;
}
}

View File

@ -1,95 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
class BlockLight
{
public:
Transform3 _tr = Transform3::identity();
LightPwn _light;
};
VERUS_TYPEDEFS(BlockLight);
class BlockEmitter
{
public:
Transform3 _tr = Transform3::identity();
EmitterPwn _emitter;
};
VERUS_TYPEDEFS(BlockEmitter);
// Block is a scene node which has a model and material info.
// Most blocks form the scene's so called static or immovable geometry.
class Block : public SceneNode
{
Vector4 _userColor = Vector4(0);
Vector<BlockLight> _vLights;
Vector<BlockEmitter> _vEmitters;
ModelPwn _model;
MaterialPwn _material;
int _matIndex = 0;
bool _collide = true;
bool _async_loadedModel = false;
public:
struct Desc
{
pugi::xml_node _node;
CSZ _name = nullptr;
CSZ _model = nullptr;
CSZ _modelMat = nullptr;
CSZ _blockMat = nullptr;
int _matIndex = 0;
bool _collide = true;
};
VERUS_TYPEDEFS(Desc);
Block();
~Block();
void Init(RcDesc desc);
void Done();
VERUS_P(void LoadExtra(SZ xml));
virtual void Update() override;
virtual String GetUrl() override { return _C(_model->GetMesh().GetUrl()); }
bool IsLoadedModel() const { return _model->IsLoaded(); }
virtual void SetColor(RcVector4 color) override { _userColor = color; }
virtual Vector4 GetColor() override { return _userColor; }
ModelPtr GetModel() { return _model; }
MaterialPtr GetMaterial(bool orModelMat = true);
int GetMaterialIndex() const { return _matIndex; }
virtual void UpdateBounds() override;
// Serialization:
virtual void Serialize(IO::RSeekableStream stream) override;
virtual void Deserialize(IO::RStream stream) override;
virtual void SaveXML(pugi::xml_node node) override;
virtual void LoadXML(pugi::xml_node node) override;
};
VERUS_TYPEDEFS(Block);
class BlockPtr : public Ptr<Block>
{
public:
void Init(Block::RcDesc desc);
};
VERUS_TYPEDEFS(BlockPtr);
class BlockPwn : public BlockPtr
{
public:
~BlockPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(BlockPwn);
}
}

View File

@ -1,153 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// Emitter:
Emitter::Emitter()
{
_type = NodeType::emitter;
}
Emitter::~Emitter()
{
Done();
}
void Emitter::Init(RcDesc desc)
{
VERUS_QREF_SM;
_name = sm.EnsureUniqueName(desc._name ? desc._name : "Emitter");
if (desc._urlParticles)
{
SceneParticles::Desc spDesc;
spDesc._url = desc._urlParticles;
_particles.Init(spDesc);
_flow = 0;
}
if (desc._urlSound)
_sound.Init(Audio::Sound::Desc(desc._urlSound).Set3D().SetLoop());
}
void Emitter::Done()
{
_particles.Done();
_sound.Done();
}
void Emitter::Update()
{
VERUS_QREF_SM;
const Point3 headPos = sm.GetHeadCamera()->GetEyePosition();
if (_particles && VMath::distSqr(GetPosition(), headPos) < 50 * 50.f)
_particles->GetParticles().AddFlow(GetPosition(), _flowOffset, _flowScale, &_flowColor, &_flow);
if (_sound)
{
const bool inRange = VMath::distSqr(GetPosition(), headPos) < 15 * 15.f;
if (inRange && !_src)
{
Audio::Source::Desc desc;
desc._secOffset = -1;
_sound->NewSource(&_src, desc)->PlayAt(GetPosition());
}
if (!inRange && _src)
_src.Done();
}
}
void Emitter::Serialize(IO::RSeekableStream stream)
{
SceneNode::Serialize(stream);
stream.WriteString(_C(_particles->GetParticles().GetUrl()));
stream.WriteString(_C(_sound->GetUrl()));
stream << _flowColor.GLM();
stream << _flowOffset.GLM();
stream << _flowScale;
}
void Emitter::Deserialize(IO::RStream stream)
{
SceneNode::Deserialize(stream);
const String savedName = _C(GetName());
PreventNameCollision();
if (stream.GetVersion() >= IO::Xxx::MakeVersion(3, 0))
{
char urlParticles[IO::Stream::s_bufferSize] = {};
char urlAudio[IO::Stream::s_bufferSize] = {};
glm::vec4 flowColor;
glm::vec3 flowOffset;
stream.ReadString(urlParticles);
stream.ReadString(urlAudio);
stream >> flowColor;
stream >> flowOffset;
stream >> _flowScale;
_flowColor = flowColor;
_flowOffset = flowOffset;
Desc desc;
desc._urlParticles = urlParticles;
desc._urlSound = urlAudio;
Init(desc);
}
}
void Emitter::SaveXML(pugi::xml_node node)
{
SceneNode::SaveXML(node);
node.append_attribute("color") = _C(_flowColor.ToColorString());
node.append_attribute("offset") = _C(_flowOffset.ToString(true));
node.append_attribute("scale") = _flowScale;
if (_particles)
node.append_attribute("urlParticles") = _C(_particles->GetParticles().GetUrl());
if (_sound)
node.append_attribute("urlAudio") = _C(_sound->GetUrl());
}
void Emitter::LoadXML(pugi::xml_node node)
{
SceneNode::LoadXML(node);
PreventNameCollision();
_flowColor = Vector4::Replicate(1);
if (auto attr = node.attribute("color"))
_flowColor.FromColorString(attr.value());
_flowOffset = Vector3(0);
if (auto attr = node.attribute("offset"))
_flowOffset.FromString(attr.value());
_flowScale = node.attribute("scale").as_float(_flowScale);
Desc desc;
if (auto attr = node.attribute("name"))
desc._name = attr.value();
desc._urlParticles = node.attribute("urlParticles").value();
desc._urlSound = node.attribute("urlAudio").value();
Init(desc);
}
// EmitterPtr:
void EmitterPtr::Init(Emitter::RcDesc desc)
{
VERUS_QREF_SM;
VERUS_RT_ASSERT(!_p);
_p = sm.InsertEmitter();
if (desc._node)
_p->LoadXML(desc._node);
else
_p->Init(desc);
}
void EmitterPwn::Done()
{
if (_p)
{
SceneManager::I().DeleteEmitter(_p);
_p = nullptr;
}
}

View File

@ -1,63 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
class Emitter : public SceneNode
{
Vector4 _flowColor = Vector4::Replicate(1);
Vector3 _flowOffset = Vector3(0);
SceneParticlesPwn _particles;
Audio::SoundPwn _sound;
Audio::SourcePtr _src;
float _flow = 0;
float _flowScale = 1;
public:
struct Desc
{
pugi::xml_node _node;
CSZ _name = nullptr;
CSZ _urlParticles = nullptr;
CSZ _urlSound = nullptr;
};
VERUS_TYPEDEFS(Desc);
Emitter();
~Emitter();
void Init(RcDesc desc);
void Done();
virtual void Update() override;
virtual String GetUrl() override { return _C(_particles->GetParticles().GetUrl()); }
SceneParticlesPtr GetParticles() { return _particles; }
// Serialization:
virtual void Serialize(IO::RSeekableStream stream) override;
virtual void Deserialize(IO::RStream stream) override;
virtual void SaveXML(pugi::xml_node node) override;
virtual void LoadXML(pugi::xml_node node) override;
};
VERUS_TYPEDEFS(Emitter);
class EmitterPtr : public Ptr<Emitter>
{
public:
void Init(Emitter::RcDesc desc);
};
VERUS_TYPEDEFS(EmitterPtr);
class EmitterPwn : public EmitterPtr
{
public:
~EmitterPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(EmitterPwn);
}
}

View File

@ -1,335 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// Light:
Light::Light()
{
_type = NodeType::light;
}
Light::~Light()
{
Done();
}
void Light::Init(RcDesc desc)
{
VERUS_QREF_SM;
_name = sm.EnsureUniqueName(desc._name ? desc._name : "Light");
_data = desc._data;
_dynamic = desc._dynamic;
if (desc._urlIntShaker)
{
_shaker.Load(desc._urlIntShaker);
_shaker.Randomize();
_shaker.SetScaleBias(0.5f * desc._intShakerScale, 1 - 0.5f * desc._intShakerScale);
_baseIntensity = GetIntensity();
}
}
void Light::Done()
{
SceneManager::I().GetOctree().UnbindElement(this);
}
void Light::Update()
{
if (!_async_loadedMesh)
{
VERUS_QREF_HELPERS;
RMesh mesh = helpers.GetDeferredLights().Get(_data._lightType);
if (mesh.IsLoaded())
{
_async_loadedMesh = true;
UpdateBounds();
}
}
if (_shaker.IsLoaded())
{
_shaker.Update();
SetIntensity(_shaker.Get() * _baseIntensity);
}
}
void Light::SetLightType(CGI::LightType type)
{
_data._lightType = type;
ComputeTransform();
}
CGI::LightType Light::GetLightType() const
{
return _data._lightType;
}
void Light::SetColor(RcVector4 color)
{
_data._color = color;
}
Vector4 Light::GetColor()
{
return _data._color;
}
void Light::SetIntensity(float i)
{
_data._color.setW(i);
}
float Light::GetIntensity() const
{
return _data._color.getW();
}
void Light::SetDirection(RcVector3 dir)
{
_data._dir = dir;
ComputeTransform();
}
RcVector3 Light::GetDirection() const
{
return _data._dir;
}
void Light::SetRadius(float r)
{
_data._radius = r;
ComputeTransform();
}
float Light::GetRadius() const
{
return _data._radius;
}
void Light::SetCone(float coneIn, float coneOut)
{
if (coneIn)
_data._coneIn = coneIn;
if (coneOut)
_data._coneOut = coneOut;
VERUS_RT_ASSERT(_data._coneIn >= _data._coneOut);
ComputeTransform();
}
float Light::GetConeIn() const
{
return _data._coneIn;
}
float Light::GetConeOut() const
{
return _data._coneOut;
}
Vector4 Light::GetInstData() const
{
return Vector4(_data._color.getXYZ() * _data._color.getW(), _data._coneIn);
}
void Light::DirFromPoint(RcPoint3 point, float radiusScale)
{
const Vector3 to = point - GetPosition();
const float len = VMath::length(to);
if (len > VERUS_FLOAT_THRESHOLD)
{
_data._dir = to / len;
if (radiusScale > 0)
_data._radius = len * radiusScale;
}
ComputeTransform();
}
void Light::ConeFromPoint(RcPoint3 point, bool coneIn)
{
const Vector3 to = point - GetPosition();
const Vector3 dir = VMath::normalize(to);
const float d = VMath::dot(dir, _data._dir);
if (coneIn)
_data._coneIn = d;
else
_data._coneIn = _data._coneOut = Math::Clamp<float>(d, cos(Math::ToRadians(80)), cos(Math::ToRadians(10)));
const float angle = acos(_data._coneOut);
const float minIn = cos(angle - Math::ToRadians(10));
_data._coneIn = Math::Clamp<float>(_data._coneIn, minIn, 1);
SetCone(_data._coneIn, _data._coneOut);
}
Transform3 Light::GetTransformNoScale() const
{
const Matrix3 matR = Matrix3::MakeTrackToZ(_data._dir);
return Transform3(matR, Vector3(GetPosition()));
}
void Light::SetTransform(RcTransform3 mat)
{
_data._dir = VMath::normalize(mat.getCol2());
const Transform3 tr = VMath::appendScale(mat, ComputeScale());
SceneNode::SetTransform(tr);
}
void Light::RestoreTransform(RcTransform3 tr, RcVector3 rot, RcVector3 scale)
{
_data._dir = VMath::normalize(tr.getCol2());
SceneNode::RestoreTransform(tr, rot, scale);
}
Vector3 Light::ComputeScale()
{
switch (_data._lightType)
{
case CGI::LightType::dir:
return Vector3::Replicate(1);
case CGI::LightType::omni:
return Vector3::Replicate(_data._radius);
case CGI::LightType::spot:
const float angle = acos(_data._coneOut);
const float scaleXY = tan(angle);
return Vector3(_data._radius * scaleXY, _data._radius * scaleXY, _data._radius);
}
return Vector3::Replicate(_data._radius);
}
void Light::ComputeTransform()
{
const Matrix3 matR = Matrix3::MakeTrackToZ(_data._dir);
const Transform3 tr = VMath::appendScale(Transform3(matR, Vector3(GetPosition())), ComputeScale());
SceneNode::SetTransform(tr);
}
void Light::UpdateBounds()
{
const bool dir = (CGI::LightType::dir == _data._lightType);
const bool octreeRoot = (_dynamic || dir);
VERUS_QREF_HELPERS;
RMesh mesh = helpers.GetDeferredLights().Get(_data._lightType);
if (mesh.IsLoaded())
{
if (!_octreeBindOnce)
{
_bounds = Math::Bounds::MakeFromOrientedBox(mesh.GetBounds(), _tr);
SceneManager::I().GetOctree().BindElement(Math::Octree::Element(_bounds, this), octreeRoot);
_octreeBindOnce = octreeRoot;
}
if (_dynamic)
{
_bounds = Math::Bounds::MakeFromOrientedBox(mesh.GetBounds(), _tr);
SceneManager::I().GetOctree().UpdateDynamicBounds(Math::Octree::Element(_bounds, this));
}
}
}
void Light::Serialize(IO::RSeekableStream stream)
{
SceneNode::Serialize(stream);
stream << _data._lightType;
stream << _data._color;
stream << _data._dir;
stream << _data._radius;
stream << _data._coneIn;
stream << _data._coneOut;
}
void Light::Deserialize(IO::RStream stream)
{
SceneNode::Deserialize(stream);
const String savedName = _C(GetName());
PreventNameCollision();
if (stream.GetVersion() >= IO::Xxx::MakeVersion(3, 0))
{
Desc desc;
desc._name = _C(savedName);
stream >> desc._data._lightType;
stream >> desc._data._color;
stream >> desc._data._dir;
stream >> desc._data._radius;
stream >> desc._data._coneIn;
stream >> desc._data._coneOut;
Init(desc);
}
}
void Light::SaveXML(pugi::xml_node node)
{
SceneNode::SaveXML(node);
switch (_data._lightType)
{
case CGI::LightType::dir: node.append_attribute("url") = "DIR"; break;
case CGI::LightType::omni: node.append_attribute("url") = "OMNI"; break;
case CGI::LightType::spot: node.append_attribute("url") = "SPOT"; break;
}
node.append_attribute("type") = +_data._lightType;
node.append_attribute("color") = _C(_data._color.ToString(true));
node.append_attribute("dir") = _C(_data._dir.ToString(true));
node.append_attribute("radius") = _data._radius;
node.append_attribute("coneIn") = _data._coneIn;
node.append_attribute("coneOut") = _data._coneOut;
}
void Light::LoadXML(pugi::xml_node node)
{
SceneNode::LoadXML(node);
PreventNameCollision();
Desc desc;
if (auto attr = node.attribute("name"))
desc._name = attr.value();
const int type = node.attribute("type").as_int(+CGI::LightType::omni);
desc._data._lightType = static_cast<CGI::LightType>(type);
if (auto attr = node.attribute("color"))
desc._data._color.FromString(attr.value());
if (auto attr = node.attribute("dir"))
desc._data._dir.FromString(attr.value());
desc._data._radius = node.attribute("radius").as_float(desc._data._radius);
desc._data._coneIn = node.attribute("coneIn").as_float(desc._data._coneIn);
desc._data._coneOut = node.attribute("coneOut").as_float(desc._data._coneOut);
desc._intShakerScale = node.attribute("intShakerScale").as_float(desc._intShakerScale);
if (auto attr = node.attribute("urlIntShaker"))
desc._urlIntShaker = attr.value();
// Normalize:
desc._data._dir = VMath::normalize(desc._data._dir);
// Convert degrees to cosine:
if (desc._data._coneIn > 1)
desc._data._coneIn = cos(Math::ToRadians(desc._data._coneIn));
if (desc._data._coneOut > 1)
desc._data._coneOut = cos(Math::ToRadians(desc._data._coneOut));
Init(desc);
}
// LightPtr:
void LightPtr::Init(Light::RcDesc desc)
{
VERUS_QREF_SM;
VERUS_RT_ASSERT(!_p);
_p = sm.InsertLight();
if (desc._node)
_p->LoadXML(desc._node);
else
{
_p->Init(desc);
_p->SetLightType(desc._data._lightType); // Call ComputeTransform().
}
}
void LightPwn::Done()
{
if (_p)
{
SceneManager::I().DeleteLight(_p);
_p = nullptr;
}
}

View File

@ -1,97 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
class LightData
{
public:
Vector4 _color = Vector4::Replicate(1);
Vector3 _dir = Vector3(0, 0, 1);
CGI::LightType _lightType = CGI::LightType::omni;
float _radius = 10;
float _coneIn = cos(Math::ToRadians(35)); // [0, coneOut-10] angle cosine.
float _coneOut = cos(Math::ToRadians(45)); // [10, 80] angle cosine.
};
VERUS_TYPEDEFS(LightData);
// Light is a scene node with light's info.
class Light : public SceneNode
{
LightData _data;
Anim::Shaker _shaker;
float _baseIntensity = 1;
bool _async_loadedMesh = false;
public:
struct Desc
{
pugi::xml_node _node;
CSZ _name = nullptr;
CSZ _urlIntShaker = nullptr;
float _intShakerScale = 0.25f;
LightData _data;
bool _dynamic = false;
};
VERUS_TYPEDEFS(Desc);
Light();
~Light();
void Init(RcDesc desc);
void Done();
virtual void Update() override;
void SetLightType(CGI::LightType type);
CGI::LightType GetLightType() const;
virtual void SetColor(RcVector4 color) override;
virtual Vector4 GetColor() override;
void SetIntensity(float i);
float GetIntensity() const;
void SetDirection(RcVector3 dir);
RcVector3 GetDirection() const;
void SetRadius(float r);
float GetRadius() const;
void SetCone(float coneIn = 0, float coneOut = 0);
float GetConeIn() const;
float GetConeOut() const;
Vector4 GetInstData() const;
void DirFromPoint(RcPoint3 point, float radiusScale = 0);
void ConeFromPoint(RcPoint3 point, bool coneIn = false);
Transform3 GetTransformNoScale() const;
virtual void SetTransform(RcTransform3 mat) override;
virtual void RestoreTransform(RcTransform3 tr, RcVector3 rot, RcVector3 scale) override;
Vector3 ComputeScale();
void ComputeTransform();
virtual void UpdateBounds() override;
// Serialization:
virtual void Serialize(IO::RSeekableStream stream) override;
virtual void Deserialize(IO::RStream stream) override;
virtual void SaveXML(pugi::xml_node node) override;
virtual void LoadXML(pugi::xml_node node) override;
};
VERUS_TYPEDEFS(Light);
class LightPtr : public Ptr<Light>
{
public:
void Init(Light::RcDesc desc);
};
VERUS_TYPEDEFS(LightPtr);
class LightPwn : public LightPtr
{
public:
~LightPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(LightPwn);
}
}

View File

@ -1,128 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// Model:
Model::Model()
{
}
Model::~Model()
{
Done();
}
void Model::Init(RcDesc desc)
{
if (_refCount)
return;
VERUS_INIT();
_refCount = 1;
Mesh::Desc meshDesc;
meshDesc._url = desc._url;
meshDesc._instanceCapacity = 1000;
meshDesc._initShape = true;
_mesh.Init(meshDesc);
Material::Desc matDesc;
matDesc._name = desc._mat ? desc._mat : desc._url;
matDesc._load = true;
_material.Init(matDesc);
}
bool Model::Done()
{
_refCount--;
if (_refCount <= 0)
{
VERUS_DONE(Model);
return true;
}
return false;
}
void Model::MarkFirstInstance()
{
_mesh.MarkFirstInstance();
}
void Model::Draw(CGI::CommandBufferPtr cb)
{
if (!_mesh.IsInstanceBufferEmpty(true))
{
_mesh.UpdateInstanceBuffer();
cb->DrawIndexed(_mesh.GetIndexCount(), _mesh.GetInstanceCount(true), 0, 0, _mesh.GetFirstInstance());
}
}
void Model::BindPipeline(CGI::CommandBufferPtr cb)
{
_mesh.BindPipelineInstanced(cb, false);
_mesh.UpdateUniformBufferPerFrame();
}
void Model::BindPipelineSimple(DrawSimpleMode mode, CGI::CommandBufferPtr cb)
{
switch (mode)
{
case DrawSimpleMode::envMap: _mesh.BindPipeline(Mesh::PIPE_SIMPLE_ENV_MAP_INSTANCED, cb); break;
case DrawSimpleMode::planarReflection: _mesh.BindPipeline(Mesh::PIPE_SIMPLE_PLANAR_REF_INSTANCED, cb); break;
}
_mesh.UpdateUniformBufferSimplePerFrame(mode);
}
void Model::BindGeo(CGI::CommandBufferPtr cb)
{
_mesh.BindGeo(cb);
_mesh.UpdateUniformBufferPerMeshVS();
}
void Model::PushInstance(RcTransform3 matW, RcVector4 instData)
{
_mesh.PushInstance(matW, instData);
}
void Model::Serialize(IO::RSeekableStream stream)
{
stream.WriteString(_C(_material->_name));
}
void Model::Deserialize(IO::RStream stream, CSZ url)
{
char mat[IO::Stream::s_bufferSize] = {};
stream.ReadString(mat);
// TODO: handle old names, remove later:
char* pOldExt = strstr(mat, ".xmt");
if (pOldExt)
strncpy(pOldExt, ".vml", 4);
Desc desc;
desc._url = url;
desc._mat = mat;
Init(desc);
}
// ModelPtr:
void ModelPtr::Init(Model::RcDesc desc)
{
VERUS_QREF_SM;
VERUS_RT_ASSERT(!_p);
_p = sm.InsertModel(desc._url);
_p->Init(desc);
}
void ModelPwn::Done()
{
if (_p)
{
SceneManager::I().DeleteModel(_C(_p->GetMesh().GetUrl()));
_p = nullptr;
}
}

View File

@ -1,70 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
// Model is an element of the scene manager container
// * has a mesh
// * has a material
// * has generic parameters
class Model : public Object
{
Mesh _mesh;
MaterialPwn _material;
IO::Dictionary _dict;
int _refCount = 0;
public:
struct Desc
{
CSZ _url = nullptr;
CSZ _mat = nullptr;
Desc(CSZ url = nullptr) : _url(url) {}
};
VERUS_TYPEDEFS(Desc);
Model();
~Model();
void Init(RcDesc desc);
bool Done();
bool IsLoaded() const { return _mesh.IsLoaded(); }
void AddRef() { _refCount++; }
int GetRefCount() const { return _refCount; }
void MarkFirstInstance();
void Draw(CGI::CommandBufferPtr cb);
void BindPipeline(CGI::CommandBufferPtr cb);
void BindPipelineSimple(DrawSimpleMode mode, CGI::CommandBufferPtr cb);
void BindGeo(CGI::CommandBufferPtr cb);
void PushInstance(RcTransform3 matW, RcVector4 instData);
RMesh GetMesh() { return _mesh; }
MaterialPtr GetMaterial() { return _material; }
void Serialize(IO::RSeekableStream stream);
void Deserialize(IO::RStream stream, CSZ url);
};
VERUS_TYPEDEFS(Model);
class ModelPtr : public Ptr<Model>
{
public:
void Init(Model::RcDesc desc);
};
VERUS_TYPEDEFS(ModelPtr);
class ModelPwn : public ModelPtr
{
public:
~ModelPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(ModelPwn);
}
}

View File

@ -1,232 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// Prefab:
Prefab::Prefab()
{
_type = NodeType::prefab;
}
Prefab::~Prefab()
{
Done();
}
void Prefab::Init(RcDesc desc)
{
VERUS_QREF_SM;
_name = sm.EnsureUniqueName(desc._url);
_url = desc._url;
_collide = desc._collide;
Vector<BYTE> vData;
IO::FileSystem::I().LoadResourceFromCache(_C(_url), vData);
LoadPrefab(reinterpret_cast<SZ>(vData.data()));
}
void Prefab::Done()
{
for (auto& f : _vFragments)
f._block.Done();
SceneManager::I().GetOctree().UnbindElement(this);
}
void Prefab::LoadPrefab(SZ xml)
{
pugi::xml_document doc;
const pugi::xml_parse_result result = doc.load_buffer_inplace(xml, strlen(xml));
if (!result)
throw VERUS_RECOVERABLE << "load_buffer_inplace(); " << result.description();
pugi::xml_node root = doc.first_child();
int fragCount = 0;
for (auto node : root.children("frag"))
fragCount++;
_vFragments.resize(fragCount);
int i = 0;
for (auto node : root.children("frag"))
{
RFragment f = _vFragments[i];
CSZ txt = node.text().as_string();
CSZ mat = node.attribute("mat").value();
String urlFrag = _url;
String matFrag;
Str::ReplaceFilename(urlFrag, txt);
urlFrag += ".x3d";
if (strchr(mat, ':'))
{
matFrag = mat;
}
else
{
matFrag = _url;
Str::ReplaceFilename(matFrag, mat);
matFrag += ".vml";
}
Block::Desc desc;
desc._model = _C(urlFrag);
desc._modelMat = _C(matFrag);
desc._collide = _collide;
f._block.Init(desc);
f._block->SetLinkedNode(this);
f._block->SetTransient();
CSZ tr = node.attribute("tr").value();
f._tr.FromString(tr);
i++;
}
UpdateBounds();
}
void Prefab::Update()
{
if (!_async_loadedAllBlocks)
{
bool all = true;
for (auto& f : _vFragments)
{
if (!f._block->IsLoadedModel())
{
all = false;
break;
}
}
if (all)
{
_async_loadedAllBlocks = true;
UpdateBounds();
}
}
}
void Prefab::Draw()
{
}
Vector4 Prefab::GetColor()
{
if (_vFragments[0]._block)
return _vFragments[0]._block->GetColor();
return Vector4(0);
}
void Prefab::SetColor(RcVector4 color)
{
for (auto& f : _vFragments)
{
if (f._block) // Async loaded?
f._block->SetColor(color);
}
}
void Prefab::UpdateBounds()
{
for (auto& f : _vFragments)
{
if (f._block) // Async loaded?
{
const Transform3 tr = GetTransform() * f._tr;
f._block->SetTransform(tr);
}
}
if (_async_loadedAllBlocks)
{
_bounds.Reset();
for (auto& f : _vFragments)
_bounds.CombineWith(f._block->GetBounds());
if (!_octreeBindOnce)
{
SceneManager::I().GetOctree().BindElement(Math::Octree::Element(_bounds, this), _dynamic);
_octreeBindOnce = _dynamic;
}
if (_dynamic)
{
SceneManager::I().GetOctree().UpdateDynamicBounds(Math::Octree::Element(_bounds, this));
}
}
}
void Prefab::SetCollisionGroup(Physics::Group g)
{
for (auto& f : _vFragments)
f._block->SetCollisionGroup(g);
}
void Prefab::MoveRigidBody()
{
for (auto& f : _vFragments)
f._block->MoveRigidBody();
}
void Prefab::Serialize(IO::RSeekableStream stream)
{
SceneNode::Serialize(stream);
stream.WriteString(_C(GetUrl()));
}
void Prefab::Deserialize(IO::RStream stream)
{
SceneNode::Deserialize(stream);
const String savedName = _C(GetName());
PreventNameCollision();
if (stream.GetVersion() >= IO::Xxx::MakeVersion(3, 0))
{
char url[IO::Stream::s_bufferSize] = {};
stream.ReadString(url);
Desc desc;
desc._url = url;
Init(desc);
}
}
void Prefab::SaveXML(pugi::xml_node node)
{
SceneNode::SaveXML(node);
node.attribute("url").set_value(_C(GetUrl()));
}
void Prefab::LoadXML(pugi::xml_node node)
{
SceneNode::LoadXML(node);
PreventNameCollision();
Desc desc;
desc._url = node.attribute("url").value();
Init(desc);
}
// PrefabPtr:
void PrefabPtr::Init(Prefab::RcDesc desc)
{
VERUS_QREF_SM;
VERUS_RT_ASSERT(!_p);
_p = sm.InsertPrefab();
if (desc._node)
_p->LoadXML(desc._node);
else
_p->Init(desc);
}
void PrefabPwn::Done()
{
if (_p)
{
SceneManager::I().DeletePrefab(_p);
_p = nullptr;
}
}

View File

@ -1,77 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
class Fragment
{
public:
Transform3 _tr = Transform3::identity();
BlockPwn _block;
};
VERUS_TYPEDEFS(Fragment);
class Prefab : public SceneNode
{
Vector<Fragment> _vFragments;
String _url;
bool _collide = true;
bool _async_loadedAllBlocks = false;
public:
struct Desc
{
pugi::xml_node _node;
CSZ _url = nullptr;
bool _collide = true;
};
VERUS_TYPEDEFS(Desc);
Prefab();
~Prefab();
void Init(RcDesc desc);
void Done();
VERUS_P(void LoadPrefab(SZ xml));
virtual void Update() override;
virtual void Draw() override;
virtual String GetUrl() override { return _url; }
virtual Vector4 GetColor() override;
virtual void SetColor(RcVector4 color) override;
virtual void UpdateBounds() override;
// Physics engine:
virtual void SetCollisionGroup(Physics::Group g = Physics::Group::immovable) override;
virtual void MoveRigidBody() override;
// Serialization:
virtual void Serialize(IO::RSeekableStream stream) override;
virtual void Deserialize(IO::RStream stream) override;
virtual void SaveXML(pugi::xml_node node) override;
virtual void LoadXML(pugi::xml_node node) override;
};
VERUS_TYPEDEFS(Prefab);
class PrefabPtr : public Ptr<Prefab>
{
public:
void Init(Prefab::RcDesc desc);
};
VERUS_TYPEDEFS(PrefabPtr);
class PrefabPwn : public PrefabPtr
{
public:
~PrefabPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(PrefabPwn);
}
}

View File

@ -1,198 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// SceneNode:
void SceneNode::PreventNameCollision()
{
_name.clear();
}
SceneNode::SceneNode()
{
}
SceneNode::~SceneNode()
{
}
int SceneNode::UserPtr_GetType()
{
return +_type;
}
void SceneNode::DrawBounds()
{
if (!_bounds.IsNull())
{
VERUS_QREF_HELPERS;
const Transform3 tr = _bounds.GetDrawTransform();
helpers.DrawBox(&tr);
}
}
void SceneNode::Rename(CSZ name)
{
if (_name == name)
return;
VERUS_QREF_SM;
_name = sm.EnsureUniqueName(name);
}
void SceneNode::SetDynamic(bool mode)
{
_dynamic = mode;
_octreeBindOnce = false;
UpdateBounds();
}
void SceneNode::SetTransform(RcTransform3 tr)
{
_tr = tr;
// Also update the UI values and bounds:
const Quat q(_tr.getUpper3x3());
_uiRotation.EulerFromQuaternion(q);
_uiScale = _tr.GetScale();
UpdateBounds();
}
void SceneNode::RestoreTransform(RcTransform3 tr, RcVector3 rot, RcVector3 scale)
{
_tr = tr;
_uiRotation = rot;
_uiScale = scale;
UpdateBounds();
}
void SceneNode::ComputeTransform()
{
Quat q;
_uiRotation.EulerToQuaternion(q);
_tr = VMath::appendScale(Transform3(q, _tr.getTranslation()), _uiScale);
}
Point3 SceneNode::GetPosition() const
{
return _tr.getTranslation();
}
Vector3 SceneNode::GetRotation() const
{
return _uiRotation;
}
Vector3 SceneNode::GetScale() const
{
return _uiScale;
}
void SceneNode::MoveTo(RcPoint3 pos)
{
_tr.setTranslation(Vector3(pos));
UpdateBounds();
}
void SceneNode::RotateTo(RcVector3 v)
{
_uiRotation = v;
ComputeTransform();
UpdateBounds();
}
void SceneNode::ScaleTo(RcVector3 v)
{
_uiScale = v;
ComputeTransform();
UpdateBounds();
}
void SceneNode::RemoveRigidBody()
{
if (_pBody)
{
VERUS_QREF_BULLET;
bullet.GetWorld()->removeRigidBody(_pBody);
delete _pBody->getMotionState();
delete _pBody;
_pBody = nullptr;
}
}
void SceneNode::SetCollisionGroup(Physics::Group g)
{
if (_pBody && _pBody->getBroadphaseHandle()->m_collisionFilterGroup != +g)
{
// https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=7538
VERUS_QREF_BULLET;
bullet.GetWorld()->removeRigidBody(_pBody);
bullet.GetWorld()->addRigidBody(_pBody, +g, -1);
}
}
void SceneNode::MoveRigidBody()
{
if (_pBody)
{
// https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=6729
VERUS_QREF_BULLET;
_pBody->setWorldTransform(_tr.Bullet());
bullet.GetWorld()->updateSingleAabb(_pBody);
}
}
void SceneNode::Serialize(IO::RSeekableStream stream)
{
stream.WriteString(_C(_name));
stream << _uiRotation.GLM();
stream << _uiScale.GLM();
stream << _tr.GLM4x3();
_dict.Serialize(stream);
}
void SceneNode::Deserialize(IO::RStream stream)
{
if (stream.GetVersion() >= IO::Xxx::MakeVersion(3, 0))
{
char name[IO::Stream::s_bufferSize] = {};
glm::vec3 uiRotation;
glm::vec3 uiScale;
glm::mat4x3 tr;
stream.ReadString(name);
stream >> uiRotation;
stream >> uiScale;
stream >> tr;
_dict.Deserialize(stream);
_name = name;
_uiRotation = uiRotation;
_uiScale = uiScale;
_tr = tr;
}
}
void SceneNode::SaveXML(pugi::xml_node node)
{
node.append_attribute("name") = _C(_name);
node.append_attribute("uiR") = _C(_uiRotation.ToString(true));
node.append_attribute("uiS") = _C(_uiScale.ToString(true));
node.append_attribute("tr") = _C(_tr.ToString());
}
void SceneNode::LoadXML(pugi::xml_node node)
{
if (auto attr = node.attribute("name"))
_name = attr.value();
_uiRotation.FromString(node.attribute("uiR").value());
_uiScale.FromString(node.attribute("uiS").value());
_tr.FromString(node.attribute("tr").value());
}
float SceneNode::GetDistToHeadSq() const
{
VERUS_QREF_SM;
return VMath::distSqr(sm.GetHeadCamera()->GetEyePosition(), GetPosition());
}

View File

@ -1,100 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
// SceneNode is an element of the scene manager container.
// * has a name
// * can be parent or child
// * has generic parameters
// * has bounds
class SceneNode : public AllocatorAware, public Physics::UserPtr
{
protected:
Transform3 _tr = Transform3::identity(); // Main transformation matrix.
Vector3 _uiRotation = Vector3(0); // User-friendly rotation used in editor's UI.
Vector3 _uiScale = Vector3(1, 1, 1); // User-friendly scale used in editor's UI.
Math::Bounds _bounds;
IO::Dictionary _dict;
String _name;
SceneNode* _pLinkedNode = nullptr;
btRigidBody* _pBody = nullptr;
NodeType _type = NodeType::unknown;
bool _dynamic = false;
bool _hidden = false;
bool _octreeBindOnce = false; // Don't rebind this node after every bounds change.
bool _selected = false;
bool _transient = false;
void PreventNameCollision();
public:
SceneNode();
virtual ~SceneNode();
virtual int UserPtr_GetType() override;
virtual void Update() {}
virtual void Draw() {}
virtual void DrawImmediate() {}
void DrawBounds();
Str GetName() const { return _C(_name); }
void Rename(CSZ name);
NodeType GetType() const { return _type; }
virtual String GetUrl() { return ""; }
IO::RDictionary GetDictionary() { return _dict; }
void SetDictionary(IO::RcDictionary dict) { _dict = dict; };
SceneNode* GetLinkedNode() const { return _pLinkedNode; }
void SetLinkedNode(SceneNode* p) { _pLinkedNode = p; }
bool IsDynamic() const { return _dynamic; }
void SetDynamic(bool mode);
bool IsHidden() const { return _hidden; }
void Hide(bool hide = true) { _hidden = hide; }
bool IsSelected() const { return _selected; }
void Select(bool select = true) { _selected = select; }
bool IsTransient() const { return _transient; }
void SetTransient(bool transient = true) { _transient = transient; }
virtual Vector4 GetColor() { return Vector4(0); }
virtual void SetColor(RcVector4 color) {}
RcTransform3 GetTransform() const { return _tr; }
virtual void SetTransform(RcTransform3 tr);
virtual void RestoreTransform(RcTransform3 tr, RcVector3 rot, RcVector3 scale);
VERUS_P(void ComputeTransform());
Point3 GetPosition() const; // Gets the position from the main transformation matrix.
Vector3 GetRotation() const; // Gets the user-friendly rotation.
Vector3 GetScale() const; // Gets the user-friendly scale.
virtual void MoveTo(RcPoint3 pos);
virtual void RotateTo(RcVector3 v);
virtual void ScaleTo(RcVector3 v);
// Bounds:
Math::RcBounds GetBounds() const { return _bounds; }
virtual void UpdateBounds() {}
// Physics engine:
void RemoveRigidBody();
virtual void SetCollisionGroup(Physics::Group g = Physics::Group::immovable);
virtual void MoveRigidBody();
// Serialization:
virtual void Serialize(IO::RSeekableStream stream);
virtual void Deserialize(IO::RStream stream);
virtual void SaveXML(pugi::xml_node node);
virtual void LoadXML(pugi::xml_node node);
float GetDistToHeadSq() const;
};
VERUS_TYPEDEFS(SceneNode);
}
}

View File

@ -1,16 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
#include "Types.h"
#include "SceneNode.h"
#include "Model.h"
#include "SceneParticles.h"
#include "Light.h"
#include "Emitter.h"
#include "Block.h"
#include "Prefab.h"
#include "Trigger.h"
#include "Site.h"

View File

@ -1,67 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// SceneParticles:
SceneParticles::SceneParticles()
{
}
SceneParticles::~SceneParticles()
{
Done();
}
void SceneParticles::Init(RcDesc desc)
{
if (_refCount)
return;
VERUS_INIT();
_refCount = 1;
_particles.Init(desc._url);
}
bool SceneParticles::Done()
{
_refCount--;
if (_refCount <= 0)
{
VERUS_DONE(SceneParticles);
return true;
}
return false;
}
void SceneParticles::Update()
{
_particles.Update();
}
void SceneParticles::Draw()
{
_particles.Draw();
}
// SceneParticlesPtr:
void SceneParticlesPtr::Init(SceneParticles::RcDesc desc)
{
VERUS_QREF_SM;
VERUS_RT_ASSERT(!_p);
_p = sm.InsertSceneParticles(desc._url);
_p->Init(desc);
}
void SceneParticlesPwn::Done()
{
if (_p)
{
SceneManager::I().DeleteSceneParticles(_C(_p->GetParticles().GetUrl()));
_p = nullptr;
}
}

View File

@ -1,51 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
class SceneParticles : public Object
{
Effects::Particles _particles;
int _refCount = 0;
public:
struct Desc
{
CSZ _url = nullptr;
Desc(CSZ url = nullptr) : _url(url) {}
};
VERUS_TYPEDEFS(Desc);
SceneParticles();
~SceneParticles();
void Init(RcDesc desc);
bool Done();
void AddRef() { _refCount++; }
Effects::RParticles GetParticles() { return _particles; }
void Update();
void Draw();
};
VERUS_TYPEDEFS(SceneParticles);
class SceneParticlesPtr : public Ptr<SceneParticles>
{
public:
void Init(SceneParticles::RcDesc desc);
};
VERUS_TYPEDEFS(SceneParticlesPtr);
class SceneParticlesPwn : public SceneParticlesPtr
{
public:
~SceneParticlesPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(SceneParticlesPwn);
}
}

View File

@ -1,398 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// Draft:
Draft::Draft()
{
}
Draft::~Draft()
{
Done();
}
void Draft::Init(Site* p, RcDesc desc)
{
_pParent = desc._pParent;
CGI::LightType type = CGI::LightType::none;
if (!strcmp(desc._url, "OMNI"))
type = CGI::LightType::omni;
if (!strcmp(desc._url, "SPOT"))
type = CGI::LightType::spot;
if (type != CGI::LightType::none)
{
Light::Desc lightDesc;
lightDesc._node = desc._node;
lightDesc._data._lightType = type;
if (p->GetRadius())
lightDesc._data._radius = p->GetRadius();
_light.Init(lightDesc);
_p = _light.Get();
}
else if (Str::EndsWith(desc._url, ".Prefab.xml"))
{
Prefab::Desc prefabDesc;
prefabDesc._node = desc._node;
prefabDesc._url = desc._url;
prefabDesc._collide = desc._collide;
_prefab.Init(prefabDesc);
_p = _prefab.Get();
}
else
{
Block::Desc blockDesc;
blockDesc._node = desc._node;
blockDesc._model = desc._url;
blockDesc._matIndex = desc._matIndex;
blockDesc._collide = desc._collide;
String mat;
if (desc._matIndex)
{
mat = desc._url;
Str::ReplaceExtension(mat, _C(std::to_string(desc._matIndex) + ".xmt"));
blockDesc._blockMat = _C(mat);
}
_block.Init(blockDesc);
_p = _block.Get();
}
_p->GetDictionary().Insert("Site", _C(p->GetName()));
}
void Draft::Done()
{
_block.Done();
_light.Done();
_prefab.Done();
}
// DraftPtr:
void DraftPtr::Init(Site* p, Draft::RcDesc desc)
{
VERUS_RT_ASSERT(!_p);
_p = p->InsertDraft();
_p->Init(p, desc);
}
void DraftPtr::Done(Site* p)
{
if (_p)
{
p->DeleteDraft(_p);
_p = nullptr;
}
};
// Site:
Site::Site()
{
_type = NodeType::site;
}
Site::~Site()
{
Done();
}
void Site::Init(RcDesc desc)
{
if (_refCount)
return;
_name = desc._name;
_refCount = 1;
}
bool Site::Done()
{
return true;
}
void Site::Update()
{
if (_activeDraft)
{
if (_activeDraft->GetLight() && _params._radius)
_activeDraft->GetLight()->SetRadius(_params._radius);
const Transform3 mat = Transform3::translation(_pDelegate->Site_TransformOffset(_params._offset)) *
_pDelegate->Site_GetTransform(_params);
_activeDraft->Get()->SetTransform(mat);
}
}
void Site::Draw()
{
}
void Site::DrawImmediate()
{
if (!_pDelegate)
return;
VERUS_QREF_DD;
VERUS_QREF_HELPERS;
const Transform3 mat = _pDelegate->Site_GetTransform(_params);
const Point3 at = mat.getTranslation();
const Point3 to = at + _pDelegate->Site_TransformOffset(_params._offset);
if (_activeDraft)
{
_activeDraft->Get()->DrawBounds();
helpers.DrawBasis(&_activeDraft->Get()->GetTransform(), -1, true);
}
if (!_params._offset.IsZero())
{
//dr.Begin(CGI::CDebugRender::T_LINES, nullptr, false);
//dr.AddLine(at, to, VERUS_COLOR_RGBA(0, 255, 0, 255));
//dr.End();
}
if (_params._radius)
{
helpers.DrawCircle(at, _params._radius, VERUS_COLOR_WHITE, *_params._pTerrain);
}
if (_linkedDraft)
{
const Point3 from = _linkedDraft->Get()->GetPosition();
//dr.Begin(CGI::CDebugRender::T_LINES, nullptr, false);
//dr.AddLine(from, to, VERUS_COLOR_RGBA(255, 0, 255, 255));
//dr.End();
}
for (auto& draft : TStoreDrafts::_list)
{
if (draft.GetLight())
{
LightPtr light = draft.GetLight();
if (CGI::LightType::spot == light->GetLightType())
{
const Point3 target = light->GetPosition() + light->GetDirection() * light->GetRadius();
helpers.DrawLight(light->GetPosition(), 0, &target);
}
else
helpers.DrawLight(light->GetPosition());
}
}
}
PDraft Site::InsertDraft()
{
return TStoreDrafts::Insert();
}
void Site::DeleteDraft(PDraft p)
{
TStoreDrafts::Delete(p);
}
void Site::DeleteAllDrafts()
{
TStoreDrafts::DeleteAll();
}
void Site::Save()
{
IO::Xml xml;
xml.SetFilename(_C("Site_" + _name + ".xml"));
for (auto& draft : TStoreDrafts::_list)
{
pugi::xml_node node = xml.AddElement("draft");
draft.Get()->SaveXML(node);
if (draft.GetParent() && draft.GetLight())
{
const Transform3 tr = VMath::inverse(draft.GetParent()->Get()->GetTransform()) * draft.GetLight()->GetTransformNoScale();
node.attribute("relative").set_value("1");
node.attribute("m").set_value(_C(tr.ToString()));
}
}
xml.Save();
}
void Site::Load(CSZ pathname)
{
IO::Xml xml;
if (pathname)
{
xml.SetFilename(pathname);
}
else if (String::npos != _name.find(':'))
{
const String path = IO::FileSystem::ConvertRelativePathToAbsolute(_name, true);
xml.SetFilename(_C(path));
}
else
xml.SetFilename(_C("Site_" + _name + ".xml"));
StringStream ss;
ss << "Site::Load(), url = " << _C(xml.GetFilename());
xml.Load();
int draftCount = 0;
auto root = xml.GetRoot();
for (auto node : root.children("draft"))
{
DraftPtr draft;
Draft::Desc draftDesc;
draftDesc._node = node;
draftDesc._url = node.attribute("url").value();
draftDesc._collide = true;
draft.Init(this, draftDesc);
draftCount++;
}
ss << ", draftCount = " << draftCount;
VERUS_LOG_INFO(ss.str());
}
void Site::Add(CSZ url, int matIndex)
{
if (!_activeDraft)
{
_prevUrl = url;
_prevMatIndex = matIndex;
Draft::Desc draftDesc;
draftDesc._url = url;
draftDesc._matIndex = matIndex;
if (_linkedDraft)
draftDesc._pParent = _linkedDraft.Get();
_activeDraft.Init(this, draftDesc);
}
}
void Site::Delete()
{
if (_activeDraft)
{
if (_linkedDraft == _activeDraft)
_linkedDraft.Detach();
_prevUrl = _activeDraft->Get()->GetUrl();
_prevMatIndex = 0;
_activeDraft.Done(this);
Save();
}
}
void Site::Edit(bool link)
{
RDraftPtr draft = link ? _linkedDraft : _activeDraft;
if (!draft) // Find the nearest block?
{
FindNearest(&draft);
if (draft && !link)
{
draft->Get()->SetCollisionGroup(Physics::Group::general);
_prevUrl = draft->Get()->GetUrl();
_prevMatIndex = 0;
}
}
else // Reset block's matrix:
{
if (link)
_linkedDraft.Detach();
}
}
void Site::Duplicate()
{
if (!_prevUrl.empty())
Add(_C(_prevUrl), _prevMatIndex);
}
void Site::Put()
{
if (_activeDraft)
{
_activeDraft->Get()->MoveRigidBody();
_activeDraft->Get()->SetCollisionGroup(Physics::Group::immovable);
_activeDraft.Detach();
Save();
}
}
PSceneNode Site::FindNearest(PDraftPtr pAttach)
{
PSceneNode p = nullptr;
const Transform3 mat = Transform3::translation(_pDelegate->Site_TransformOffset(_params._offset)) *
_pDelegate->Site_GetTransform(_params);
const Point3 at = mat.getTranslation();
float minDist = FLT_MAX;
for (auto& d : TStoreDrafts::_list)
{
const float dist = VMath::dist(at, d.Get()->GetPosition());
if (dist < minDist)
{
minDist = dist;
if (pAttach)
pAttach->Attach(&d);
p = d.Get();
}
}
return p;
}
void Site::Dir(RcVector3 dir)
{
if (_linkedDraft && _linkedDraft->GetLight())
{
_linkedDraft->GetLight()->SetDirection(dir);
Save();
}
}
void Site::DirFromPoint(float radiusScale)
{
if (_linkedDraft && _linkedDraft->GetLight())
{
const Transform3 mat = Transform3::translation(_pDelegate->Site_TransformOffset(_params._offset)) *
_pDelegate->Site_GetTransform(_params);
const Point3 at = mat.getTranslation();
_linkedDraft->GetLight()->DirFromPoint(at, radiusScale);
Save();
}
}
void Site::ConeFromPoint(bool coneIn)
{
if (_linkedDraft && _linkedDraft->GetLight())
{
const Transform3 mat = Transform3::translation(_pDelegate->Site_TransformOffset(_params._offset)) *
_pDelegate->Site_GetTransform(_params);
const Point3 at = mat.getTranslation();
_linkedDraft->GetLight()->ConeFromPoint(at, coneIn);
Save();
}
}
void Site::Commit()
{
}
PSiteDelegate Site::SetDelegate(PSiteDelegate p)
{
return Utils::Swap(_pDelegate, p);
}
// SitePtr:
void SitePtr::Init(Site::RcDesc desc)
{
VERUS_QREF_SM;
VERUS_RT_ASSERT(!_p);
_p = sm.InsertSite(desc._name);
_p->Init(desc);
}
void SitePwn::Done()
{
if (_p)
{
SceneManager::I().DeleteSite(_C(_p->GetName()));
_p = nullptr;
}
}

View File

@ -1,157 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
class Site;
class Draft
{
Draft* _pParent = nullptr;
PSceneNode _p = nullptr;
BlockPwn _block;
LightPwn _light;
PrefabPwn _prefab;
public:
struct Desc
{
pugi::xml_node _node;
Draft* _pParent = nullptr;
CSZ _url = nullptr;
int _matIndex = 0;
bool _collide = false;
};
VERUS_TYPEDEFS(Desc);
Draft();
~Draft();
void Init(Site* p, RcDesc desc);
void Done();
Draft* GetParent() { return _pParent; }
PSceneNode Get() { return _p; }
BlockPtr GetBlock() { return _block; }
LightPtr GetLight() { return _light; }
PrefabPtr GetPrefab() { return _prefab; }
};
VERUS_TYPEDEFS(Draft);
class DraftPtr : public Ptr<Draft>
{
public:
void Init(Site* p, Draft::RcDesc desc);
void Done(Site* p);
};
VERUS_TYPEDEFS(DraftPtr);
class SiteParams
{
public:
Vector3 _offset = Vector3(0);
PTerrain _pTerrain = nullptr;
float _radius = 0;
float _turn = 0;
bool _align = true;
bool _tilt = false;
};
VERUS_TYPEDEFS(SiteParams);
class SiteDelegate
{
public:
virtual Transform3 Site_GetTransform(RcSiteParams params) = 0;
virtual Vector3 Site_TransformOffset(RcVector3 offset) = 0;
};
VERUS_TYPEDEFS(SiteDelegate);
typedef Store<Draft> TStoreDrafts;
class Site : public SceneNode, private TStoreDrafts
{
PSiteDelegate _pDelegate = nullptr;
DraftPtr _activeDraft;
DraftPtr _linkedDraft;
String _prevUrl;
int _prevMatIndex = 0;
int _refCount = 0;
SiteParams _params;
public:
struct Desc
{
CSZ _name = nullptr;
};
VERUS_TYPEDEFS(Desc);
Site();
~Site();
void Init(RcDesc desc);
bool Done();
void AddRef() { _refCount++; }
virtual void Update() override;
virtual void Draw() override;
virtual void DrawImmediate() override;
// Drafts:
PDraft InsertDraft();
void DeleteDraft(PDraft p);
void DeleteAllDrafts();
DraftPtr GetActiveDraft() const { return _activeDraft; }
DraftPtr GetLinkedDraft() const { return _linkedDraft; }
void Save();
void Load(CSZ pathname = nullptr);
// Commands:
void Add(CSZ url, int matIndex); // +
void Delete(); // -
void Edit(bool link = false); // !
void Duplicate(); // *
void Put(); // =
PSceneNode FindNearest(PDraftPtr pAttach = nullptr);
void Dir(RcVector3 dir);
void DirFromPoint(float radiusScale = 0);
void ConeFromPoint(bool coneIn = false);
void Commit();
PSiteDelegate SetDelegate(PSiteDelegate p);
// Parameters:
void SetTerrain(PTerrain p) { _params._pTerrain = p; }
RcVector3 GetOffset() const { return _params._offset; }
void SetOffset(RcVector3 v) { _params._offset = v; }
float GetRadius() const { return _params._radius; }
void SetRadius(float x) { _params._radius = x; }
float GetTurn() const { return _params._turn; }
void SetTurn(float x) { _params._turn = x; }
bool GetAlign() const { return _params._align; }
void SetAlign(bool b) { _params._align = b; }
bool GetTilt() const { return _params._tilt; }
void SetTilt(bool b) { _params._tilt = b; }
};
VERUS_TYPEDEFS(Site);
class SitePtr : public Ptr<Site>
{
public:
void Init(Site::RcDesc desc);
};
VERUS_TYPEDEFS(SitePtr);
class SitePwn : public SitePtr
{
public:
~SitePwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(SitePwn);
}
}

View File

@ -1,47 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
// Trigger:
Trigger::Trigger()
{
_type = NodeType::trigger;
}
Trigger::~Trigger()
{
Done();
}
void Trigger::Init(RcDesc desc)
{
}
void Trigger::Done()
{
}
// TriggerPtr:
void TriggerPtr::Init(Trigger::RcDesc desc)
{
VERUS_QREF_SM;
VERUS_RT_ASSERT(!_p);
_p = sm.InsertTrigger();
if (desc._node)
_p->LoadXML(desc._node);
else
_p->Init(desc);
}
void TriggerPwn::Done()
{
if (_p)
{
SceneManager::I().DeleteTrigger(_p);
_p = nullptr;
}
}

View File

@ -1,40 +0,0 @@
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Scene
{
class Trigger : public SceneNode
{
public:
struct Desc
{
pugi::xml_node _node;
};
VERUS_TYPEDEFS(Desc);
Trigger();
~Trigger();
void Init(RcDesc desc);
void Done();
};
VERUS_TYPEDEFS(Trigger);
class TriggerPtr : public Ptr<Trigger>
{
public:
void Init(Trigger::RcDesc desc);
};
VERUS_TYPEDEFS(TriggerPtr);
class TriggerPwn : public TriggerPtr
{
public:
~TriggerPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(TriggerPwn);
}
}

View File

@ -199,7 +199,7 @@ DS_ACC_FSO mainFS(VSO si)
#ifdef DEF_DIR
float4 shadowConfig = g_ubShadowFS._shadowConfig;
shadowConfig.y = 1.0 - saturate(wrapDiffuse * shadowConfig.y);
const float3 posForShadow = AdjustPosForShadow(posWV, normalWV, dirToLightWV, -posWV.z);
const float3 posForShadow = AdjustPosForShadow(posWV, normalWV, dirToLightWV, -posWV.z, shadowConfig.z);
shadowMask = ShadowMapCSM(
g_texShadowCmp,
g_samShadowCmp,

Some files were not shown because too many files have changed in this diff Show More