This commit is contained in:
Dmitry 2020-12-02 20:00:15 +03:00
parent 487312f38f
commit 2cbe3aa503
78 changed files with 976 additions and 410 deletions

View File

@ -82,6 +82,12 @@ void RendererD3D12::EnableDebugLayer()
ComPtr<ID3D12Debug> pDebug;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pDebug))))
pDebug->EnableDebugLayer();
#if 0
ComPtr<ID3D12Debug1> pDebug1;
if (SUCCEEDED(pDebug->QueryInterface(IID_PPV_ARGS(&pDebug1))))
pDebug1->SetEnableGPUBasedValidation(TRUE);
#endif
}
ComPtr<IDXGIFactory7> RendererD3D12::CreateDXGIFactory()

View File

@ -104,7 +104,7 @@ void TextureD3D12::Init(RcTextureDesc desc)
if (FAILED(hr = pRendererD3D12->GetMaAllocator()->CreateResource(
&allocDesc,
&resDescUAV,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
nullptr,
&_uaResource._pMaAllocation,
IID_PPV_ARGS(&_uaResource._pResource))))
@ -400,7 +400,7 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
{
const int subUAV = srcMip + mip;
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(_uaResource._pResource.Get(),
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE, subUAV);
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE, subUAV);
}
pCmdList->ResourceBarrier(barrierCount, barriers);
@ -426,7 +426,7 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
{
const int subUAV = srcMip + mip;
barriers[barrierCount++] = CD3DX12_RESOURCE_BARRIER::Transition(_uaResource._pResource.Get(),
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, subUAV);
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, subUAV);
}
pCmdList->ResourceBarrier(barrierCount, barriers);

View File

@ -2008,12 +2008,12 @@ inline void MemcpySubresource(
_In_ const D3D12_SUBRESOURCE_INFO* pSrc,
SIZE_T RowSizeInBytes,
UINT NumRows,
UINT NumSlices)
UINT NumSlices) noexcept
{
for (UINT z = 0; z < NumSlices; ++z)
{
auto pDestSlice = reinterpret_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;
auto pSrcSlice = (reinterpret_cast<const BYTE*>(pResourceData) + pSrc->Offset) + pSrc->DepthPitch * LONG_PTR(z);
auto pDestSlice = static_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;
auto pSrcSlice = (static_cast<const BYTE*>(pResourceData) + pSrc->Offset) + pSrc->DepthPitch * LONG_PTR(z);
for (UINT y = 0; y < NumRows; ++y)
{
memcpy(pDestSlice + pDest->RowPitch * y,
@ -2105,14 +2105,14 @@ inline UINT64 UpdateSubresources(
_In_ ID3D12GraphicsCommandList* pCmdList,
_In_ ID3D12Resource* pDestinationResource,
_In_ ID3D12Resource* pIntermediate,
_In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
_In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
UINT64 RequiredSize,
_In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
_In_reads_(NumSubresources) const UINT* pNumRows,
_In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,
_In_ const void* pResourceData,
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData)
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept
{
// Minor validation
auto IntermediateDesc = pIntermediate->GetDesc();
@ -2170,7 +2170,7 @@ inline UINT64 UpdateSubresources(
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept
{
UINT64 RequiredSize = 0;
UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
auto MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
if (MemToAlloc > SIZE_MAX)
{
return 0;
@ -2181,8 +2181,8 @@ inline UINT64 UpdateSubresources(
return 0;
}
auto pLayouts = static_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
auto pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
auto pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
auto Desc = pDestinationResource->GetDesc();
ID3D12Device* pDevice = nullptr;
@ -2202,13 +2202,13 @@ inline UINT64 UpdateSubresources(
_In_ ID3D12Resource* pDestinationResource,
_In_ ID3D12Resource* pIntermediate,
UINT64 IntermediateOffset,
_In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
_In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
_In_ const void* pResourceData,
_In_reads_(NumSubresources) D3D12_SUBRESOURCE_INFO* pSrcData)
_In_reads_(NumSubresources) D3D12_SUBRESOURCE_INFO* pSrcData) noexcept
{
UINT64 RequiredSize = 0;
UINT64 MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
auto MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
if (MemToAlloc > SIZE_MAX)
{
return 0;
@ -2219,8 +2219,8 @@ inline UINT64 UpdateSubresources(
return 0;
}
auto pLayouts = reinterpret_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
UINT64* pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
UINT* pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
auto pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
auto pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
auto Desc = pDestinationResource->GetDesc();
ID3D12Device* pDevice = nullptr;
@ -2241,8 +2241,8 @@ inline UINT64 UpdateSubresources(
_In_ ID3D12Resource* pDestinationResource,
_In_ ID3D12Resource* pIntermediate,
UINT64 IntermediateOffset,
_In_range_(0, MaxSubresources) UINT FirstSubresource,
_In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,
_In_range_(0,MaxSubresources) UINT FirstSubresource,
_In_range_(1,MaxSubresources-FirstSubresource) UINT NumSubresources,
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept
{
UINT64 RequiredSize = 0;
@ -2267,10 +2267,10 @@ inline UINT64 UpdateSubresources(
_In_ ID3D12Resource* pDestinationResource,
_In_ ID3D12Resource* pIntermediate,
UINT64 IntermediateOffset,
_In_range_(0, MaxSubresources) UINT FirstSubresource,
_In_range_(1, MaxSubresources - FirstSubresource) UINT NumSubresources,
_In_range_(0,MaxSubresources) UINT FirstSubresource,
_In_range_(1,MaxSubresources-FirstSubresource) UINT NumSubresources,
_In_ const void* pResourceData,
_In_reads_(NumSubresources) D3D12_SUBRESOURCE_INFO* pSrcData)
_In_reads_(NumSubresources) D3D12_SUBRESOURCE_INFO* pSrcData) noexcept
{
UINT64 RequiredSize = 0;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];

View File

@ -3,8 +3,8 @@
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>C:\Compressonator_3.2.4691\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\DevIL-Windows-SDK-1.8.0\include;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.7\include;C:\Home\Middleware\openal-soft-1.20.1-bin\include;C:\Home\Middleware\SDL2-2.0.12\include;C:\VulkanSDK\1.2.154.1\Include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Compressonator_3.2.4691\lib\VS2017\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\lib\x64\Release;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.7\lib2;C:\Home\Middleware\openal-soft-1.20.1-bin\libs\Win64;C:\Home\Middleware\SDL2-2.0.12\lib\x64;C:\VulkanSDK\1.2.154.1\Lib;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Compressonator_3.2.4691\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\DevIL-Windows-SDK-1.8.0\include;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.7\include;C:\Home\Middleware\openal-soft-1.20.1-bin\include;C:\Home\Middleware\SDL2-2.0.12\include;C:\VulkanSDK\1.2.162.0\Include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Compressonator_3.2.4691\lib\VS2017\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\lib\x64\Release;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.7\lib2;C:\Home\Middleware\openal-soft-1.20.1-bin\libs\Win64;C:\Home\Middleware\SDL2-2.0.12\lib\x64;C:\VulkanSDK\1.2.162.0\Lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />

View File

@ -140,6 +140,7 @@
<ClInclude Include="src\Extra\FileParser.h" />
<ClInclude Include="src\Game\BaseGame.h" />
<ClInclude Include="src\Game\BaseCharacter.h" />
<ClInclude Include="src\Game\ChainAward.h" />
<ClInclude Include="src\Game\Spirit.h" />
<ClInclude Include="src\Game\Game.h" />
<ClInclude Include="src\Game\State.h" />
@ -171,6 +172,7 @@
<ClInclude Include="src\Global\Utils.h" />
<ClInclude Include="src\GUI\Animator.h" />
<ClInclude Include="src\GUI\Button.h" />
<ClInclude Include="src\GUI\Chat.h" />
<ClInclude Include="src\GUI\Container.h" />
<ClInclude Include="src\GUI\Cursor.h" />
<ClInclude Include="src\GUI\Font.h" />
@ -335,6 +337,7 @@
<ClCompile Include="src\Extra\FileParser.cpp" />
<ClCompile Include="src\Game\BaseGame.cpp" />
<ClCompile Include="src\Game\BaseCharacter.cpp" />
<ClCompile Include="src\Game\ChainAward.cpp" />
<ClCompile Include="src\Game\Spirit.cpp" />
<ClCompile Include="src\Game\State.cpp" />
<ClCompile Include="src\Game\StateMachine.cpp" />
@ -351,6 +354,7 @@
<ClCompile Include="src\Global\Utils.cpp" />
<ClCompile Include="src\GUI\Animator.cpp" />
<ClCompile Include="src\GUI\Button.cpp" />
<ClCompile Include="src\GUI\Chat.cpp" />
<ClCompile Include="src\GUI\Container.cpp" />
<ClCompile Include="src\GUI\Cursor.cpp" />
<ClCompile Include="src\GUI\Font.cpp" />

View File

@ -702,6 +702,12 @@
<ClInclude Include="src\Global\BaseCircularBuffer.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\GUI\Chat.h">
<Filter>src\GUI</Filter>
</ClInclude>
<ClInclude Include="src\Game\ChainAward.h">
<Filter>src\Game</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\CGI\BaseGeometry.cpp">
@ -1190,6 +1196,12 @@
<ClCompile Include="src\Net\Multiplayer.cpp">
<Filter>src\Net</Filter>
</ClCompile>
<ClCompile Include="src\GUI\Chat.cpp">
<Filter>src\GUI</Filter>
</ClCompile>
<ClCompile Include="src\Game\ChainAward.cpp">
<Filter>src\Game</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="src\Shaders\Lib.hlsl">

View File

@ -57,6 +57,7 @@ namespace verus
next = null;
return 0;
}
time = Math::Max(0.f, time); // Negative time is not allowed.
float alpha;
const int frame = static_cast<int>(_pMotion->GetFps() * time); // Frame is before or at 'time'.
typename TMap::const_iterator it = m.upper_bound(frame); // Find frame after 'time'.

View File

@ -642,9 +642,9 @@ void Skeleton::BeginRagdoll(RcTransform3 matW, RcVector3 impulse, CSZ bone)
{
btConeTwistConstraint* pConeC = new btConeTwistConstraint(*pBone->_pBody, *pParent->_pBody, localA, localB);
if (!pBone->_cLimits.IsZero())
pConeC->setLimit(pBone->_cLimits.getX(), pBone->_cLimits.getY(), pBone->_cLimits.getZ(), 0.9f, 0.1f);
pConeC->setLimit(pBone->_cLimits.getX(), pBone->_cLimits.getY(), pBone->_cLimits.getZ(), 0.9f);
else
pConeC->setLimit(VERUS_PI / 4, VERUS_PI / 4, VERUS_PI / 4, 0.9f, 0.1f);
pConeC->setLimit(VERUS_PI / 4, VERUS_PI / 4, VERUS_PI / 4, 0.9f);
if (!isLeaf)
pConeC->setFixThresh(1);
pBone->_pConstraint = pConeC;
@ -1172,6 +1172,8 @@ void Skeleton::FixateFeet(RMotion motion)
Vector3 Skeleton::GetHighestSpeed(RMotion motion, CSZ name, RcVector3 scale, bool positive)
{
VERUS_RT_ASSERT(!_ragdollMode);
const int frameCount = motion.GetFrameCount();
const float dt = motion.GetFpsInv();
const float dti = float(motion.GetFps());

View File

@ -43,7 +43,7 @@ void Settings::ParseCommandLineArgs(int argc, char* argv[])
_commandLine._gapi = atoi(argv[i + 1]);
if (IsArg(i, "--efs") || IsArg(i, "--fullscreen"))
_commandLine._exclusiveFullscreen = true;
if (IsArg(i, "--windowed"))
if (IsArg(i, "--wnd") || IsArg(i, "--windowed"))
_commandLine._windowed = true;
if (IsArg(i, "--bwnd"))
_commandLine._borderlessWindowed = true;

View File

@ -26,10 +26,12 @@ namespace verus
int _ds_ubAOTexturesFSCapacity = 1;
int _ds_ubAOPerMeshVSCapacity = 10;
int _generateMips_ubCapacity = 100;
int _mesh_ubPerFrameCapacity = 100;
int _mesh_ubPerFrameCapacity = 1000;
int _mesh_ubPerMaterialFSCapacity = 1000;
int _mesh_ubPerMeshVSCapacity = 10000;
int _mesh_ubSkinningVSCapacity = 5000;
int _particles_ubVSCapacity = 100;
int _particles_ubFSCapacity = 100;
int _quad_ubVSCapacity = 100;
int _quad_ubFSCapacity = 100;
int _terrain_ubDrawDepthCapacity = 100;

View File

@ -65,6 +65,14 @@ void Window::Init(RcDesc constDesc)
if (DisplayMode::borderlessWindowed == desc._displayMode)
VERUS_LOG_INFO("Window is using Borderless Windowed display mode");
}
SDL_Surface* pSurface = SDL_GetWindowSurface(_pWnd);
const Uint32 color = SDL_MapRGB(pSurface->format,
(desc._color >> 0) & 0xFF,
(desc._color >> 8) & 0xFF,
(desc._color >> 16) & 0xFF);
SDL_FillRect(pSurface, nullptr, color);
SDL_UpdateWindowSurface(_pWnd);
}
void Window::Done()

View File

@ -17,6 +17,7 @@ namespace verus
int _height = 0;
Uint32 _flags = 0;
DisplayMode _displayMode = DisplayMode::windowed;
UINT32 _color = VERUS_COLOR_BLACK;
bool _resizable = false;
bool _maximized = false;
bool _useSettings = true;

View File

@ -134,10 +134,11 @@ namespace verus
RSoundPtr operator[](int i)
{
if (i < 0)
const bool useRand = i < 0;
if (useRand)
i = Utils::I().GetRandom().Next() & 0xFF; // Only positive.
i %= COUNT;
if (i == _prev)
if (useRand && (i == _prev))
i = (i + 1) % COUNT;
_prev = i;
return _sounds[i];

View File

@ -212,7 +212,7 @@ void Renderer::Update()
const float target = -0.3f + 0.6f * expScale * expScale; // Dark scene exposure compensation.
const float important = (actual - 0.5f * (1 - alpha)) / alpha;
const float delta = abs(target - important);
const float speed = delta * sqrt(delta) * 20;
const float speed = delta * sqrt(delta) * 15;
if (important < target * 0.95f)
_exposure[1] -= speed * dt;

View File

@ -21,9 +21,11 @@ Particles::~Particles()
void Particles::InitStatic()
{
VERUS_QREF_CONST_SETTINGS;
s_shader.Init("[Shaders]:Particles.hlsl");
s_shader->CreateDescriptorSet(0, &s_ubParticlesVS, sizeof(s_ubParticlesVS), 100, {}, CGI::ShaderStageFlags::vs);
s_shader->CreateDescriptorSet(1, &s_ubParticlesFS, sizeof(s_ubParticlesFS), 100,
s_shader->CreateDescriptorSet(0, &s_ubParticlesVS, sizeof(s_ubParticlesVS), settings.GetLimits()._particles_ubVSCapacity, {}, CGI::ShaderStageFlags::vs);
s_shader->CreateDescriptorSet(1, &s_ubParticlesFS, sizeof(s_ubParticlesFS), settings.GetLimits()._particles_ubFSCapacity,
{
CGI::Sampler::aniso
}, CGI::ShaderStageFlags::fs);
@ -240,13 +242,8 @@ void Particles::Update()
_drawCount = 0;
if (!_csh.IsSet())
{
if (_tex->IsLoaded())
_csh = s_shader->BindDescriptorSetTextures(1, { _tex });
else
return;
}
if (!_csh.IsSet() && _tex->IsLoaded())
_csh = s_shader->BindDescriptorSetTextures(1, { _tex });
VERUS_QREF_TIMER;
@ -375,16 +372,24 @@ void Particles::Draw()
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_ATMO;
if (!_drawCount)
if (!_drawCount || !_csh.IsSet())
return;
float brightness = _brightness;
if (brightness < 0)
{
const glm::vec3 gray = glm::saturation(0.f, atmo.GetSunColor().GLM() + atmo.GetAmbientColor().GLM());
brightness = gray.x * abs(brightness);
}
auto cb = renderer.GetCommandBuffer();
s_ubParticlesVS._matP = sm.GetCamera()->GetMatrixP().UniformBufferFormat();
s_ubParticlesVS._matWVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
s_ubParticlesVS._viewportSize = cb->GetViewportSize().GLM();
s_ubParticlesVS._brightness.x = _brightness;
s_ubParticlesVS._brightness.x = brightness;
s_ubParticlesFS._tilesetSize = _tilesetSize.GLM();
switch (_billboardType)
@ -585,8 +590,8 @@ int Particles::Add(RcPoint3 pos, RcVector3 dir, float scale, PcVector4 pUserColo
particle._beginSize = scale * (_beginSizeRange.getX() + _beginSizeRange.getZ() * random.NextFloat());
particle._endSize = scale * (_endSizeRange.getX() + _endSizeRange.getZ() * random.NextFloat());
particle._beginSpin = scale * (_beginSpinRange.getX() + _beginSpinRange.getZ() * random.NextFloat());
particle._endSpin = scale * (_endSpinRange.getX() + _endSpinRange.getZ() * random.NextFloat());
particle._beginSpin = _beginSpinRange.getX() + _beginSpinRange.getZ() * random.NextFloat();
particle._endSpin = _endSpinRange.getX() + _endSpinRange.getZ() * random.NextFloat();
if (_decal)
particle._endSpin = particle._beginSpin;
@ -628,20 +633,32 @@ bool Particles::TimeCorrectedVerletIntegration(RParticle particle, RPoint3 point
}
const Vector3 accel = _gravity * _gravityStrength + wind * _windStrength;
const Point3 posCurrent = particle._position;
particle._position += (posCurrent - particle._prevPosition) * timer.GetVerletValue() + accel * timer.GetDeltaTimeSq();
particle._prevPosition = posCurrent;
particle._velocity = (particle._position - posCurrent) * timer.GetDeltaTimeInv();
const Point3 currentPos = particle._position;
particle._position += (currentPos - particle._prevPosition) * timer.GetVerletValue() + accel * timer.GetDeltaTimeSq();
particle._prevPosition = currentPos;
particle._velocity = (particle._position - currentPos) * timer.GetDeltaTimeInv();
if (_collide)
{
VERUS_QREF_SM;
if (sm.RayCastingTest(particle._prevPosition, particle._position, nullptr, &point, &normal))
if (particle._inContact && VMath::lengthSqr(particle._velocity) < 0.15 * 0.15f)
{
hit = true;
particle._velocity = particle._velocity.Reflect(normal) * _bounceStrength;
particle._prevPosition = point;
particle._position = point + particle._velocity * timer.GetDeltaTime();
particle._velocity = Vector3(0);
particle._position = currentPos;
particle._prevPosition = currentPos;
}
else
{
VERUS_QREF_SM;
if (sm.RayCastingTest(particle._prevPosition, particle._position, nullptr, &point, &normal))
{
hit = true;
particle._inContact = normal.getY() > 0.7071f;
particle._velocity = particle._velocity.Reflect(normal) * _bounceStrength;
particle._prevPosition = point;
particle._position = point + particle._velocity * timer.GetDeltaTime();
}
else
particle._inContact = false;
}
}

View File

@ -34,6 +34,7 @@ namespace verus
float _endSize = 0;
float _beginSpin = 0;
float _endSpin = 0;
bool _inContact = false;
};
VERUS_TYPEDEFS(Particle);
@ -61,8 +62,8 @@ namespace verus
{
glm::vec4 pos;
glm::vec2 tc0;
UINT32 color;
float psize;
UINT32 color;
float psize;
};
VERUS_TYPEDEFS(Vertex);

View File

@ -85,24 +85,6 @@ void Animator::Parse(pugi::xml_node node, PcWidget pWidget)
_angle = Math::ToRadians(node.attribute("angle").as_float());
_postAngle = Math::ToRadians(node.attribute("postAngle").as_float());
auto ParseEasing = [](CSZ txt)
{
if (!txt || !strlen(txt))
return Easing::linear;
if (!strcmp(txt, "linear"))
return Easing::linear;
if (!strcmp(txt, "accel"))
return Easing::accel;
if (!strcmp(txt, "decel"))
return Easing::decel;
if (!strcmp(txt, "swing"))
return Easing::swing;
if (!strcmp(txt, "blink"))
return Easing::blink;
VERUS_RT_FAIL("Easing FAIL.");
return Easing::linear;
};
for (auto fxNode : node.children("fx"))
{
if (!strcmp(fxNode.attribute("mode").value(), "color"))
@ -112,7 +94,7 @@ void Animator::Parse(pugi::xml_node node, PcWidget pWidget)
_animatedColor._current = _animatedColor._from;
_animatedColor._invDuration = fxNode.attribute("duration").as_float();
_animatedColor._delay = fxNode.attribute("delay").as_float();
_animatedColor._easing = ParseEasing(fxNode.attribute("easing").value());
_animatedColor._easing = Math::EasingFromString(fxNode.attribute("easing").value());
if (_animatedColor._invDuration)
_animatedColor._invDuration = 1 / _animatedColor._invDuration;
}
@ -145,7 +127,7 @@ void Animator::Parse(pugi::xml_node node, PcWidget pWidget)
_animatedRect._current = _animatedRect._from;
_animatedRect._invDuration = fxNode.attribute("duration").as_float();
_animatedRect._delay = fxNode.attribute("delay").as_float();
_animatedRect._easing = ParseEasing(fxNode.attribute("easing").value());
_animatedRect._easing = Math::EasingFromString(fxNode.attribute("easing").value());
if (_animatedRect._invDuration)
_animatedRect._invDuration = 1 / _animatedRect._invDuration;
}

View File

@ -5,15 +5,6 @@ namespace verus
{
namespace GUI
{
enum class Easing : int
{
linear,
accel,
decel,
swing,
blink
};
template<typename T>
struct Animated
{
@ -23,34 +14,7 @@ namespace verus
float _time = 0;
float _invDuration = 0;
float _delay = 0;
Easing _easing = Easing::linear;
float GetRatioWithEasing(float ratio)
{
switch (_easing)
{
case Easing::accel:
{
return ratio * ratio;
}
case Easing::decel:
{
const float anti = 1 - ratio;
return 1 - anti * anti;
}
case Easing::swing:
{
return ratio * ratio * (3 - (ratio + ratio));
}
case Easing::blink:
{
const float scale = 0.148148148f;
const float anti = 1 - ratio;
return 1 - (ratio * anti * anti) / scale;
}
}
return ratio;
}
Easing _easing = Easing::none;
T Lerp(const T& a, const T& b, float ratio)
{
@ -64,7 +28,7 @@ namespace verus
if (_time >= 0)
_time += dt;
const float ratio = Math::Clamp<float>((_time - _delay) * _invDuration, 0, 1);
const float ratioWithEasing = GetRatioWithEasing(ratio);
const float ratioWithEasing = Math::ApplyEasing(_easing, ratio);
_current = Lerp(_from, _to, ratioWithEasing);
if (dt > 0 && ratio >= 1)
_invDuration = -_invDuration;

153
Verus/src/GUI/Chat.cpp Normal file
View File

@ -0,0 +1,153 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::GUI;
Chat::Chat()
{
}
Chat::~Chat()
{
Done();
}
void Chat::Init(int keepCount, float keepFor)
{
VERUS_INIT();
_keepFor = keepFor;
_vMessages.resize(keepCount);
}
void Chat::Done()
{
VERUS_DONE(Chat);
}
void Chat::AddMessage(CSZ txt, CSZ name, ChatMessageType type)
{
if (!strlen(txt))
return;
VERUS_QREF_TIMER_GUI;
String str;
if (name)
{
str.reserve(strlen(txt) + strlen(name) + 2 + 11 + 11);
if (!_nameColor.empty())
str += _nameColor;
str += name;
str += ": ";
if (!_nameColor.empty())
str += _normalMsgColor.empty() ? "\\RGB=X" : _normalMsgColor;
str += txt;
txt = _C(str);
}
RMessage msg = _vMessages[_writeAt];
msg._text = txt;
msg._time = timer.GetTime();
msg._type = type;
_writeAt = VERUS_CIRCULAR_ADD(_writeAt, _vMessages.size());
}
CSZ Chat::GetText()
{
VERUS_QREF_TIMER_GUI;
const float minTime = timer.GetTime() - _keepFor;
// Detect if we need a new string:
int index = _writeAt;
int count = static_cast<int>(_vMessages.size());
do
{
index--;
if (index < 0)
index = static_cast<int>(_vMessages.size()) - 1;
RMessage msg = _vMessages[index];
if (msg._time < minTime)
break;
count--;
} while (count);
if (index == _oldMsgIndex && _writeAt == _oldWriteAt)
return _C(_compiled);
_oldWriteAt = _writeAt; // Confirm new messages.
_oldMsgIndex = index; // Confirm messages getting old.
// Build a new string:
_compiled.clear();
index = _writeAt;
count = static_cast<int>(_vMessages.size());
do
{
index--;
if (index < 0)
index = static_cast<int>(_vMessages.size()) - 1;
RMessage msg = _vMessages[index];
if (msg._time < minTime)
break;
if (ChatMessageType::normal == msg._type && !_normalMsgColor.empty())
_compiled += _normalMsgColor;
if (ChatMessageType::system == msg._type && !_systemMsgColor.empty())
_compiled += _systemMsgColor;
_compiled += msg._text;
if (ChatMessageType::normal == msg._type && !_normalMsgColor.empty())
_compiled += "\\RGB=X";
if (ChatMessageType::system == msg._type && !_systemMsgColor.empty())
_compiled += "\\RGB=X";
_compiled += "\n";
count--;
} while (count);
_compiledW = Str::Utf8ToWide(_compiled);
return _C(_compiled);
}
CWSZ Chat::GetTextW()
{
GetText();
return _C(_compiledW);
}
void Chat::SetNormalMessageColor(UINT32 color)
{
if (color)
{
_normalMsgColor = "\\RGB=";
_normalMsgColor += Convert::ToHex(color).substr(0, 6);
}
else
_normalMsgColor.clear();
}
void Chat::SetSystemMessageColor(UINT32 color)
{
if (color)
{
_systemMsgColor = "\\RGB=";
_systemMsgColor += Convert::ToHex(color).substr(0, 6);
}
else
_systemMsgColor.clear();
}
void Chat::SetNameColor(UINT32 color)
{
if (color)
{
_nameColor = "\\RGB=";
_nameColor += Convert::ToHex(color).substr(0, 6);
}
else
_nameColor.clear();
}

52
Verus/src/GUI/Chat.h Normal file
View File

@ -0,0 +1,52 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace GUI
{
enum class ChatMessageType : int
{
normal,
system
};
class Chat : public Object
{
struct Message
{
String _text;
float _time = -FLT_MAX;
ChatMessageType _type = ChatMessageType::normal;
};
VERUS_TYPEDEFS(Message);
Vector<Message> _vMessages;
String _normalMsgColor;
String _systemMsgColor;
String _nameColor;
String _compiled;
WideString _compiledW;
float _keepFor = 0;
int _writeAt = 0;
int _oldWriteAt = -1;
int _oldMsgIndex = -1;
public:
Chat();
~Chat();
void Init(int keepCount = 4, float keepFor = 20);
void Done();
void AddMessage(CSZ txt, CSZ name, ChatMessageType type = ChatMessageType::normal);
CSZ GetText();
CWSZ GetTextW();
void SetNormalMessageColor(UINT32 color);
void SetSystemMessageColor(UINT32 color);
void SetNameColor(UINT32 color);
};
VERUS_TYPEDEFS(Chat);
}
}

View File

@ -73,7 +73,7 @@ void Container::ParseWidgets(pugi::xml_node node, CSZ sizerID)
if (pWidget->AsInputFocus())
vm.GetCurrentParseView()->AddControlToTabList(pWidget);
}
else if (strcmp(type, "fx"))
else if (strcmp(type, "fx") && strcmp(type, "string"))
{
VERUS_RT_FAIL("Unknown widget type");
}
@ -108,7 +108,7 @@ PWidget Container::GetHovered(float x, float y)
return pChild;
}
if (p->IsHovered(x, y))
if ((!pContainer || !pContainer->IsSizer()) && p->IsHovered(x, y))
return p;
}
return nullptr;

View File

@ -22,6 +22,8 @@ void Cursor::Init()
void Cursor::Done()
{
if (ViewManager::I().GetShader())
ViewManager::I().GetShader()->FreeDescriptorSet(_csh);
VERUS_DONE(Cursor);
}
@ -30,21 +32,36 @@ void Cursor::Draw()
if (!IsInitialized())
return;
VERUS_QREF_RENDERER;
VERUS_QREF_VM;
//VERUS_QREF_RENDER;
//
//gui.GetStateBlockAlphaBlend()->Apply();
//
//const CVector3 scale(512 / 1920.f, 512 / 1080.f);
//
//render->SetTextures({ _tex->GetTex(), _tex->GetTex() });
//gui.GetCbPerObject().matW = Math::QuadMatrix(m_x - _hotspotX, _y - _hotspotY, scale.getX(), scale.getY()).ConstBufferFormat();
//gui.GetCbPerObject().matV = Math::ToUVMatrix(0, 0).ConstBufferFormat();
//gui.GetCbPerObject().colorAmbient = Vector4(1, 1, 1, 1);
//gui.GetCbPerObject().tcScaleBias = Vector4(1, 1, 0, 0);
//gui.GetShader()->Bind("T");
//gui.GetShader()->UpdateBuffer(0);
//render.DrawQuad();
if (!_csh.IsSet())
{
if (_tex->GetTex()->IsLoaded())
_csh = vm.GetShader()->BindDescriptorSetTextures(1, { _tex->GetTex() });
else
return;
}
const Vector3 scale(512 / 1920.f, 512 / 1080.f);
auto cb = renderer.GetCommandBuffer();
auto shader = vm.GetShader();
auto& ubGui = vm.GetUbGui();
auto& ubGuiFS = vm.GetUbGuiFS();
ubGui._matW = Math::QuadMatrix(_x - _hotspotX, _y - _hotspotY, scale.getX(), scale.getY()).UniformBufferFormat();
ubGui._matV = Math::ToUVMatrix(0, 0).UniformBufferFormat();
ubGui._tcScaleBias = Vector4(1, 1, 0, 0).GLM();
ubGui._tcMaskScaleBias = Vector4(1, 1, 0, 0).GLM();
ubGuiFS._color = Vector4::Replicate(1).GLM();
vm.BindPipeline(ViewManager::PIPE_MAIN, cb);
shader->BeginBindDescriptors();
cb->BindDescriptors(shader, 0);
cb->BindDescriptors(shader, 1, _csh);
shader->EndBindDescriptors();
renderer.DrawQuad(cb.Get());
}
void Cursor::MoveHotspotTo(float x, float y)
@ -59,6 +76,9 @@ void Cursor::MoveBy(float x, float y)
return;
VERUS_QREF_CONST_SETTINGS;
_x = Math::Clamp<float>(_x + x * (100.f / settings._displaySizeWidth), 0, 1);
_y = Math::Clamp<float>(_y + y * (100.f / settings._displaySizeHeight), 0, 1);
const float scale = Game::BaseGame::GetMouseScale();
const float invScale = 1 / scale;
_x = Math::Clamp<float>(_x + x * (invScale / settings._displaySizeWidth), 0, 1);
_y = Math::Clamp<float>(_y + y * (invScale / settings._displaySizeHeight), 0, 1);
}

View File

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

View File

@ -139,7 +139,8 @@ void Font::Draw(RcDrawDesc dd)
return;
}
const wchar_t wrapChars[] = L" \t\r\n-";
_overrideColor = 0;
const wchar_t wrapChars[] = L" \t\r\n-\\";
CWSZ text = dd._text;
int lineCount = -dd._skippedLineCount;
const float lineHeight = ToFloatY(_lineHeight, dd._scale);
@ -171,7 +172,34 @@ void Font::Draw(RcDrawDesc dd)
int wordLen = static_cast<int>(wcscspn(text, wrapChars)); // First occurrence of wrap chars.
if (!wordLen && L'-' == *text)
{
wordLen = 1; // Don't throw away hyphen.
}
else if (!wordLen && L'\\' == *text)
{
CWSZ token = L"\\RGB=";
const size_t len = wcslen(token);
if (!wcsncmp(text, L"\\RGB=", len))
{
char buffer[7] = {};
text += len;
VERUS_FOR(i, 6)
{
if (!(*text) || !isxdigit(*text))
break;
buffer[i] = static_cast<char>(*text);
text++;
}
_overrideColor = Convert::ColorTextToInt32(buffer);
if (!_overrideColor && *text)
text++;
wordLen = -1;
}
else
{
wordLen = 1;
}
}
if (wordLen > 0) // Add word:
{
@ -191,17 +219,17 @@ void Font::Draw(RcDrawDesc dd)
break; // No more vertical space.
// 2) draw the word:
xoffset += DrawWord(text, wordLen, xoffset, yoffset, lineCount < 0, dd._colorFont, dd._scale);
xoffset += DrawWord(text, wordLen, xoffset, yoffset, lineCount < 0, _overrideColor ? _overrideColor : dd._colorFont, dd._scale);
}
else // Word fits in:
{
// Draw the word:
xoffset += DrawWord(text, wordLen, xoffset, yoffset, lineCount < 0, dd._colorFont, dd._scale);
xoffset += DrawWord(text, wordLen, xoffset, yoffset, lineCount < 0, _overrideColor ? _overrideColor : dd._colorFont, dd._scale);
}
text += wordLen; // Next char.
}
else // Deal with wrap char:
else if (!wordLen) // Deal with wrap char:
{
if (L'\n' == *text) // New line:
{

View File

@ -58,6 +58,7 @@ namespace verus
TMapKerning _mapKerning;
int _lineHeight = 0;
int _texSize = 0;
UINT32 _overrideColor = 0;
public:
struct DrawDesc

View File

@ -15,6 +15,7 @@
#include "Cursor.h"
#include "ViewManager.h"
#include "ViewController.h"
#include "Chat.h"
namespace verus
{

View File

@ -22,29 +22,28 @@ void Image::Update()
{
Widget::Update();
VERUS_QREF_VM;
if (!_solidColor && !_csh.IsSet() && _tex->GetTex()->IsLoaded())
_csh = vm.GetShader()->BindDescriptorSetTextures(1, { _tex->GetTex() });
VERUS_QREF_TIMER_GUI;
_tcBias.UpdateUnlimited(dt);
//_tcBias.WrapFloat4();
_tcBias.WrapFloatV();
}
void Image::Draw()
{
VERUS_QREF_RENDERER;
VERUS_QREF_VM;
auto cb = renderer.GetCommandBuffer();
auto shader = vm.GetShader();
if (!GetColor().getW())
Widget::DrawDebug();
if (!GetColor().getW())
return;
if (!_solidColor && !_csh.IsSet())
{
if (_tex->GetTex()->IsLoaded())
_csh = shader->BindDescriptorSetTextures(1, { _tex->GetTex() });
else
return;
}
return;
VERUS_QREF_RENDERER;
VERUS_QREF_VM;
const float pulseScale = GetAnimator().GetPulseScale();
const float angle = GetAnimator().GetAngle();
@ -58,16 +57,14 @@ void Image::Draw()
const Transform3 matW = Transform3(matPostR, Vector3(0)) *
VMath::appendScale(Math::QuadMatrix(x, y, GetW(), GetH()) * Transform3(matPreR, Vector3(0)), scale);
auto cb = renderer.GetCommandBuffer();
auto shader = vm.GetShader();
auto& ubGui = vm.GetUbGui();
auto& ubGuiFS = vm.GetUbGuiFS();
ubGui._matW = matW.UniformBufferFormat();
ubGuiFS._color = Vector4::Replicate(1).GLM();
if (_solidColor)
{
ubGuiFS._color = GetColor().GLM();
}
else
ubGuiFS._color = GetColor().GLM();
if (!_solidColor)
{
const Transform3 matV = Math::ToUVMatrix(0, 0);
ubGui._matV = matV.UniformBufferFormat();
@ -87,7 +84,7 @@ void Image::Draw()
ubGui._tcMaskScaleBias.y = _tcScaleMask.getY();
ubGui._tcMaskScaleBias.z = _tcBiasMask.getX();
ubGui._tcMaskScaleBias.w = _tcBiasMask.getY();
vm.BindPipeline(ViewManager::PIPE_MASK, cb);
vm.BindPipeline(_add ? ViewManager::PIPE_MASK_ADD : ViewManager::PIPE_MASK, cb);
}
else if (_solidColor)
{
@ -95,12 +92,12 @@ void Image::Draw()
}
else
{
vm.BindPipeline(ViewManager::PIPE_MAIN, cb);
vm.BindPipeline(_add ? ViewManager::PIPE_MAIN_ADD : ViewManager::PIPE_MAIN, cb);
}
shader->BeginBindDescriptors();
cb->BindDescriptors(shader, 0);
cb->BindDescriptors(shader, 1, _solidColor ? CGI::CSHandle() : _csh);
cb->BindDescriptors(shader, 1, _solidColor ? vm.GetDefaultComplexSetHandle() : _csh);
shader->EndBindDescriptors();
renderer.DrawQuad();
}
@ -132,7 +129,7 @@ void Image::Parse(pugi::xml_node node)
}
_tcScale.setX(ViewManager::ParseCoordX(node.attribute("us").value(), 1));
_tcScale.setX(ViewManager::ParseCoordY(node.attribute("vs").value(), 1));
_tcScale.setY(ViewManager::ParseCoordY(node.attribute("vs").value(), 1));
_tcBias.GetValue().setX(ViewManager::ParseCoordX(node.attribute("ub").value()));
_tcBias.GetValue().setY(ViewManager::ParseCoordY(node.attribute("vb").value()));
_tcBias.GetSpeed().setX(ViewManager::ParseCoordX(node.attribute("ubSpeed").value()));

View File

@ -54,7 +54,7 @@ void Table::Draw()
}
// Draw rows:
for (int row = _offset; row < int(_vRows.size()); ++row)
for (int row = _offset; row < _vRows.size(); ++row)
{
if (row == _selectedRow)
{
@ -67,7 +67,7 @@ void Table::Draw()
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
shader->BeginBindDescriptors();
cb->BindDescriptors(shader, 0);
cb->BindDescriptors(shader, 1);
cb->BindDescriptors(shader, 1, vm.GetDefaultComplexSetHandle());
shader->EndBindDescriptors();
renderer.DrawQuad();
}
@ -137,7 +137,7 @@ void Table::Clear()
void Table::SelectNextRow()
{
if (_selectedRow >= 0 && _selectedRow < int(_vRows.size()) - 1)
if (_selectedRow >= 0 && _selectedRow < static_cast<int>(_vRows.size()) - 1)
_selectedRow++;
}
@ -165,7 +165,7 @@ void Table::UpdateRow(int index, int col, CSZ txt, UINT32 color, const void* pUs
{
if (index < 0)
index = _selectedRow;
if (index >= int(_vRows.size()))
if (index >= _vRows.size())
return;
if (col >= _cols)
return;
@ -212,7 +212,7 @@ bool Table::InvokeOnClick(float x, float y)
const bool ret = Label::InvokeOnClick(x, y);
const float xLocal = x - GetX();
const float yLocal = y - GetY();
const int row = int(yLocal / _rowHeight) + _offset - (_header._vCells.empty() ? 0 : 1);
const int row = static_cast<int>(yLocal / _rowHeight) + _offset - (_header._vCells.empty() ? 0 : 1);
_selectedRow = -1;
if (row >= 0 && row < GetRowCount())
_selectedRow = row;

View File

@ -26,7 +26,7 @@ namespace verus
int _offset = 0;
int _selectedRow = -1;
int _cols = 0;
float _rowHeight = 0;
float _rowHeight = 0.1f;
public:
Table();

View File

@ -55,7 +55,7 @@ void TextBox::Draw()
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
shader->BeginBindDescriptors();
cb->BindDescriptors(shader, 0);
cb->BindDescriptors(shader, 1);
cb->BindDescriptors(shader, 1, vm.GetDefaultComplexSetHandle());
shader->EndBindDescriptors();
renderer.DrawQuad();
}

View File

@ -77,11 +77,8 @@ void View::Draw()
if (_tex)
{
if (!_csh.IsSet())
{
if (_tex->GetTex()->IsLoaded())
_csh = shader->BindDescriptorSetTextures(1, { _tex->GetTex() });
}
if (!_csh.IsSet() && _tex->GetTex()->IsLoaded())
_csh = shader->BindDescriptorSetTextures(1, { _tex->GetTex() });
if (_csh.IsSet())
{
@ -152,7 +149,7 @@ void View::Parse(pugi::xml_node node)
for (auto stringNode : node.children("string"))
{
int id = stringNode.attribute("id").as_int(-1);
const int id = stringNode.attribute("id").as_int(-1);
VERUS_RT_ASSERT(id >= 0);
String s, textAttr = String("text") + _locale;
if (auto attr = stringNode.attribute(_C(textAttr)))
@ -211,7 +208,8 @@ void View::OnDoubleClick() // Gets called by ViewManager::Update().
_pInputFocus = pHovered->AsInputFocus();
if (_pInputFocus)
_pInputFocus->InputFocus_OnFocus();
pHovered->InvokeOnDoubleClick(cursor.GetX(), cursor.GetY());
if (!pHovered->InvokeOnDoubleClick(cursor.GetX(), cursor.GetY()))
pHovered->InvokeOnClick(cursor.GetX(), cursor.GetY());
}
else
{

View File

@ -33,6 +33,9 @@ void ViewController::Done()
void ViewController::Reload()
{
VERUS_QREF_RENDERER;
renderer->WaitIdle();
const String url = _C(_pView->GetUrl());
Done();
Init(_C(url));

View File

@ -49,6 +49,8 @@ void ViewManager::Init(bool hasCursor, bool canDebug)
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
pipeDesc.DisableDepthTest();
_pipe[PIPE_MAIN].Init(pipeDesc);
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
_pipe[PIPE_MAIN_ADD].Init(pipeDesc);
}
{
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader, "#Mask", renderer.GetRenderPassHandle_AutoWithDepth());
@ -56,6 +58,8 @@ void ViewManager::Init(bool hasCursor, bool canDebug)
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
pipeDesc.DisableDepthTest();
_pipe[PIPE_MASK].Init(pipeDesc);
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
_pipe[PIPE_MASK_ADD].Init(pipeDesc);
}
{
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader, "#SolidColor", renderer.GetRenderPassHandle_AutoWithDepth());
@ -73,6 +77,7 @@ void ViewManager::Done()
_cursor.Done();
_shader->FreeDescriptorSet(_cshDebug);
_shader->FreeDescriptorSet(_cshDefault);
VERUS_DONE(ViewManager);
@ -94,6 +99,9 @@ bool ViewManager::Update()
{
VERUS_UPDATE_ONCE_CHECK;
if (!_cshDebug.IsSet() && _tex[TEX_DEBUG]->IsLoaded())
_cshDebug = _shader->BindDescriptorSetTextures(1, { _tex[TEX_DEBUG] });
for (auto& x : TStoreFonts::_map)
x.second.ResetDynamicBuffer();
@ -159,8 +167,8 @@ void ViewManager::DeleteView(PView pView)
void ViewManager::DeleteAllViews()
{
for (const auto& p : _vViews)
delete p;
for (const auto& x : _vViews)
delete x;
_vViews.clear();
}
@ -204,23 +212,23 @@ void ViewManager::MsgBox(CSZ txt, int data)
{
if (txt) // Display MessageBox:
{
PView pView = GetViewByName("Menu/MsgBox.xml");
PView pView = GetViewByName("UI/MsgBox.xml");
pView->Disable(false);
pView->Hide(false);
pView->SetData();
pView->ResetAnimators();
pView->SetState(View::State::active);
MoveToFront("Menu/MsgBox.xml");
MoveToFront("UI/MsgBox.xml");
PLabel pLabel = static_cast<PLabel>(pView->GetWidgetById("MsgBoxText"));
pLabel->SetText(txt);
}
else // Restore original view:
{
PView pView = GetViewByName("Menu/MsgBox.xml");
PView pView = GetViewByName("UI/MsgBox.xml");
pView->Disable();
pView->Hide();
pView->SetState(View::State::done);
MoveToBack("Menu/MsgBox.xml");
MoveToBack("UI/MsgBox.xml");
}
}

View File

@ -18,7 +18,9 @@ namespace verus
enum PIPE
{
PIPE_MAIN,
PIPE_MAIN_ADD,
PIPE_MASK,
PIPE_MASK_ADD,
PIPE_SOLID_COLOR,
PIPE_COUNT
};
@ -38,6 +40,7 @@ namespace verus
CGI::PipelinePwns<PIPE_COUNT> _pipe;
CGI::TexturePwns<TEX_COUNT> _tex;
CGI::CSHandle _cshDefault;
CGI::CSHandle _cshDebug;
String _fadeToView;
UB_Gui _ubGui;
UB_GuiFS _ubGuiFS;
@ -84,6 +87,7 @@ namespace verus
UB_GuiFS& GetUbGuiFS() { return _ubGuiFS; }
CGI::TexturePtr GetDebugTexture();
CGI::CSHandle GetDefaultComplexSetHandle() const { return _cshDefault; }
CGI::CSHandle GetDebugComplexSetHandle() const { return _cshDebug; }
PView GetCurrentParseView() { return _pCurrentParseView; }

View File

@ -35,27 +35,33 @@ void Widget::SetText(CSZ text)
void Widget::DrawDebug()
{
//VERUS_QREF_VM;
//VERUS_QREF_RENDER;
//
//PView pOwnerView = GetOwnerView();
//
//if (!pOwnerView->IsDebug())
// return;
//
//gui.GetStateBlockAlphaBlend()->Apply();
//
//float x, y;
//GetAbsolutePosition(x, y);
//
//render->SetTextures({ gui.GetDebugTexture(), gui.GetDebugTexture() });
//gui.GetCbPerObject().matW = Math::QuadMatrix(x, y, GetW(), GetH()).ConstBufferFormat();
//gui.GetCbPerObject().matV = Math::ToUVMatrix(0, 0).ConstBufferFormat();
//gui.GetCbPerObject().colorAmbient = Vector4(1, 1, 1, 1);
//gui.GetCbPerObject().tcScaleBias = Vector4(1, 1, 0, 0);
//gui.GetShader()->Bind("T");
//gui.GetShader()->UpdateBuffer(0);
//render.DrawQuad();
PView pOwnerView = GetOwnerView();
if (!pOwnerView->IsDebug())
return;
VERUS_QREF_RENDERER;
VERUS_QREF_VM;
float x, y;
GetAbsolutePosition(x, y);
auto cb = renderer.GetCommandBuffer();
auto shader = vm.GetShader();
auto& ubGui = vm.GetUbGui();
auto& ubGuiFS = vm.GetUbGuiFS();
ubGui._matW = Math::QuadMatrix(x, y, GetW(), GetH()).UniformBufferFormat();
ubGui._matV = Math::ToUVMatrix(0, 0).UniformBufferFormat();
ubGui._tcScaleBias = Vector4(1, 1, 0, 0).GLM();
ubGui._tcMaskScaleBias = Vector4(1, 1, 0, 0).GLM();
ubGuiFS._color = Vector4::Replicate(1).GLM();
vm.BindPipeline(ViewManager::PIPE_MAIN, cb);
shader->BeginBindDescriptors();
cb->BindDescriptors(shader, 0);
cb->BindDescriptors(shader, 1, vm.GetDebugComplexSetHandle());
shader->EndBindDescriptors();
renderer.DrawQuad(cb.Get());
}
void Widget::DrawInputStyle()
@ -75,7 +81,7 @@ void Widget::DrawInputStyle()
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
shader->BeginBindDescriptors();
cb->BindDescriptors(shader, 0);
cb->BindDescriptors(shader, 1);
cb->BindDescriptors(shader, 1, vm.GetDefaultComplexSetHandle());
shader->EndBindDescriptors();
renderer.DrawQuad();
}
@ -109,8 +115,8 @@ void Widget::GetAbsolutePosition(float& x, float& y)
PSizer pSizer = static_cast<PSizer>(pView->GetWidgetById(_C(_sizer)));
float xFromSizer = 0, yFromSizer = 0;
pSizer->GetWidgetAbsolutePosition(this, xFromSizer, yFromSizer);
x = xFromSizer;
y = yFromSizer;
x = GetX() + xFromSizer;
y = GetY() + yFromSizer;
}
}

View File

@ -171,6 +171,16 @@ void BaseCharacter::MoveTo(RcPoint3 pos)
_cc.MoveTo(_position);
}
bool BaseCharacter::FitRemotePosition()
{
const bool warp = Spirit::FitRemotePosition();
if (warp)
_fallSpeed.ForceTarget(0);
if (_cc.IsInitialized())
_cc.MoveTo(_position);
return warp;
}
bool BaseCharacter::IsOnGround() const
{
if (_cc.IsInitialized())
@ -250,39 +260,6 @@ void BaseCharacter::EndRagdoll()
InitController();
}
void BaseCharacter::ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVector3 offset)
{
VERUS_QREF_SM;
const float r = 0.1f;
Point3 point;
Vector3 norm;
// From unit's origin to it's head:
const Point3 pos = _smoothPosition;
const float startAt = _cc.GetRadius() + _cc.GetHeight() * 0.5f;
Point3 origin = pos + Vector3(0, startAt, 0);
Point3 at = pos + GetYawMatrix() * offset;
if (sm.RayCastingTest(origin, at, nullptr, &point, &norm, &r))
at = point + norm * r;
Point3 eye = at - GetFrontDirection() * _cameraRadius.GetValue();
if (sm.RayCastingTest(at, eye, nullptr, &point, &norm, &r)) // Hitting the wall?
{
eye = point + norm * r;
}
else // No collision?
{
}
if (VMath::distSqr(at, eye) < r * r) // Extremely close?
{
eye = at - GetFrontDirection() * r;
}
aimPos = eye;
aimDir = VMath::normalizeApprox(at - eye);
}
void BaseCharacter::ComputeThirdPersonCameraArgs(RcVector3 offset, RPoint3 eye, RPoint3 at)
{
VERUS_QREF_SM;
@ -346,6 +323,33 @@ float BaseCharacter::ComputeThirdPersonCamera(Scene::RCamera camera, Anim::RcOrb
return ret;
}
void BaseCharacter::ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVector3 offset)
{
VERUS_QREF_SM;
const float r = 0.1f;
Point3 point;
Vector3 norm;
Point3 eye, at;
ComputeThirdPersonCameraArgs(offset, eye, at);
if (sm.RayCastingTest(at, eye, nullptr, &point, &norm, &r)) // Hitting the wall?
{
eye = point + norm * r;
}
else // No collision?
{
}
if (VMath::distSqr(at, eye) < r * r) // Extremely close?
{
eye = at - GetFrontDirection() * r;
}
aimPos = eye;
aimDir = VMath::normalizeApprox(at - eye);
}
void BaseCharacter::SetMaxCameraRadius(float r)
{
_maxCameraRadius = r;

View File

@ -39,6 +39,7 @@ namespace verus
Physics::RCharacterController GetController() { return _cc; }
virtual void MoveTo(RcPoint3 pos) override;
virtual bool FitRemotePosition() override;
// Dimensions:
float GetIdleRadius() const { return _idleRadius; }
@ -75,9 +76,9 @@ namespace verus
virtual void BaseCharacter_OnInitRagdoll(RcTransform3 matW) {}
virtual void BaseCharacter_OnDoneRagdoll() {}
void ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVector3 offset = Vector3(0));
virtual void ComputeThirdPersonCameraArgs(RcVector3 offset, RPoint3 eye, RPoint3 at);
float ComputeThirdPersonCamera(Scene::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

@ -309,10 +309,7 @@ void BaseGame::KeyMapper_OnMouseMove(int x, int y)
if (!SDL_GetRelativeMouseMode())
return;
VERUS_QREF_CONST_SETTINGS;
const float rad = (VERUS_2PI / 360.f) / 3.f; // 3 pixels = 1 degree.
const float scale = rad * settings._inputMouseSensitivity;
const float scale = GetMouseScale();
const float fx = x * scale;
const float fy = y * scale;
@ -370,3 +367,10 @@ void BaseGame::BulletDebugDraw()
VERUS_QREF_BULLET;
bullet.DebugDraw();
}
float BaseGame::GetMouseScale()
{
VERUS_QREF_CONST_SETTINGS;
const float rad = (VERUS_2PI / 360.f) / 3.f; // 3 pixels = 1 degree.
return rad * settings._inputMouseSensitivity;
}

View File

@ -62,6 +62,8 @@ namespace verus
void ShowFPS(bool b);
void BulletDebugDraw();
static float GetMouseScale();
};
VERUS_TYPEDEFS(BaseGame);
}

View File

@ -0,0 +1,40 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#include "verus.h"
using namespace verus;
using namespace verus::Game;
ChainAward::ChainAward(float maxInterval, int maxLevel) :
_maxInterval(maxInterval),
_maxLevel(maxLevel)
{
Reset();
}
ChainAward::~ChainAward()
{
}
int ChainAward::Score()
{
VERUS_QREF_TIMER;
const float now = timer.GetTime();
if (now - _lastTime < _maxInterval)
{
_lastLevel++;
if (_lastLevel > _maxLevel)
_lastLevel = _maxLevel;
}
else
{
_lastLevel = 0;
}
_lastTime = now;
return _lastLevel;
}
void ChainAward::Reset()
{
_lastTime = -_maxInterval;
_lastLevel = 0;
}

View File

@ -0,0 +1,24 @@
// Copyright (C) 2021, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus
{
namespace Game
{
class ChainAward
{
float _lastTime = 0;
float _maxInterval = 0;
int _lastLevel = 0;
int _maxLevel = 0;
public:
ChainAward(float maxInterval = 1, int maxLevel = 10);
~ChainAward();
int Score();
void Reset();
};
VERUS_TYPEDEFS(ChainAward);
}
}

View File

@ -6,3 +6,4 @@
#include "Spirit.h"
#include "BaseCharacter.h"
#include "BaseGame.h"
#include "ChainAward.h"

View File

@ -75,13 +75,15 @@ namespace verus
RcPoint3 GetJerkyPosition() const { return _dv._jerkyPosition; }
virtual void MoveTo(RcPoint3 pos);
void SetRemotePosition(RcPoint3 pos);
bool FitRemotePosition();
virtual bool FitRemotePosition();
RcVector3 GetVelocity() const { return _velocity; }
void SetVelocity(RcVector3 v) { _velocity = v; }
RcVector3 GetFrontDirection() const { return _dv._frontDir; }
RcVector3 GetFrontDirection2D() const { return _dv._frontDir2D; }
RcVector3 GetSideDirection() const { return _dv._sideDir; }
RcVector3 GetSideDirection2D() const { return _dv._sideDir2D; }
//! Rotates smoothly across multiple frames.
void Rotate(RcVector3 front, float speed);

View File

@ -33,33 +33,6 @@ char Convert::Sint16ToSint8(short x) { return x * SCHAR_MAX / SHRT_MAX; }
void Convert::Sint8ToSint16(const char* pIn, short* pOut, int count) { VERUS_FOR(i, count) pOut[i] = Sint8ToSint16(pIn[i]); }
void Convert::Sint16ToSint8(const short* pIn, char* pOut, int count) { VERUS_FOR(i, count) pOut[i] = Sint16ToSint8(pIn[i]); }
void Convert::ToDeviceNormal(const char* pIn, char* pOut)
{
// For UBYTE4 type normal:
// OpenGL glNormalPointer() only accepts signed bytes (GL_BYTE)
// Direct3D 9 only accepts unsigned bytes (D3DDECLTYPE_UBYTE4) So it goes.
//VERUS_QREF_RENDER;
//if (CGL::RENDERER_DIRECT3D9 == render.GetRenderer())
//{
// VERUS_FOR(i, 3)
// pOut[i] = pIn[i] + 127;
//}
}
UINT32 Convert::ToDeviceColor(UINT32 color)
{
// OpenGL stores color as RGBA. Direct3D 9 as BGRA.
// See also GL_EXT_vertex_array_bgra.
//VERUS_QREF_RENDER;
//return (CGL::RENDERER_DIRECT3D9 == render.GetRenderer()) ? VERUS_COLOR_TO_D3D(color) : color;
return 0;
}
float Convert::Byte256ToSFloat(BYTE in)
{
return float(in) * (1 / 128.f) - 1;
}
UINT16 Convert::Uint8x4ToUint4x4(UINT32 in)
{
int x[4] =
@ -223,40 +196,6 @@ UINT32 Convert::ColorTextToInt32(CSZ sz)
return VERUS_COLOR_RGBA(color[0], color[1], color[2], color[3]);
}
void Convert::ToCorrectNormal(const char* in, char* out)
{
// For UBYTE4 type normal:
// OpenGL glNormalPointer() only accepts signed bytes (GL_BYTE)
// Direct3D only accepts unsigned bytes (D3DDECLTYPE_UBYTE4) So it goes.
//VERUS_QREF_RENDER;
//if (CGL::RENDERER_OPENGL != render.GetRenderer())
//{
// VERUS_FOR(i, 3)
// out[i] = in[i] + 125;
//}
}
UINT32 Convert::ToCorrectColor(UINT32 in)
{
// OpenGL stores color as RGBA. Direct3D 9 as BGRA.
// See also GL_EXT_vertex_array_bgra.
//VERUS_QREF_RENDER;
//return (CGL::RENDERER_DIRECT3D9 == render.GetRenderer()) ? VERUS_COLOR_TO_D3D(in) : in;
return 0;
}
void Convert::ByteToChar3(const BYTE* in, char* out)
{
VERUS_FOR(i, 3)
out[i] = int(in[i]) - 125;
}
void Convert::ByteToShort3(const BYTE* in, short* out)
{
VERUS_FOR(i, 3)
out[i] = (int(in[i]) << 8) - 32000;
}
UINT16 Convert::QuantizeFloat(float f, float mn, float mx)
{
const float range = mx - mn;
@ -328,6 +267,18 @@ String Convert::ToHex(const Vector<BYTE>& vBin)
return String(vHex.begin(), vHex.end());
}
String Convert::ToHex(UINT32 color)
{
static const char hexval[] = "0123456789ABCDEF";
char hex[8];
VERUS_FOR(i, 4)
{
hex[(i << 1) + 0] = hexval[((color >> (i << 3)) >> 4) & 0xF];
hex[(i << 1) + 1] = hexval[((color >> (i << 3)) >> 0) & 0xF];
}
return String(hex, hex + 8);
}
Vector<BYTE> Convert::ToBinFromHex(CSZ hex)
{
Vector<BYTE> vBin;

View File

@ -37,11 +37,6 @@ namespace verus
static void Sint8ToSint16(const char* pIn, short* pOut, int count);
static void Sint16ToSint8(const short* pIn, char* pOut, int count);
/* ??? */ static void ToDeviceNormal(const char* pIn, char* pOut);
/* ??? */ static UINT32 ToDeviceColor(UINT32 color);
/* ??? */ static float Byte256ToSFloat(BYTE in);
// 4 bits per channel:
static UINT16 Uint8x4ToUint4x4(UINT32 in);
static UINT32 Uint4x4ToUint8x4(UINT16 in, bool scaleTo255 = false);
@ -63,12 +58,6 @@ namespace verus
static BYTE QuantizeFloatToByte(float f, float mn, float mx);
static float DequantizeFloatFromByte(BYTE i, float mn, float mx);
/* ??? */ static void ToCorrectNormal(const char* in, char* out);
/* ??? */ static UINT32 ToCorrectColor(UINT32 in);
/* ??? */ static void ByteToChar3(const BYTE* in, char* out);
/* ??? */ static void ByteToShort3(const BYTE* in, short* out);
// Base64:
static String ToBase64(const Vector<BYTE>& vBin);
static Vector<BYTE> ToBinFromBase64(CSZ base64);
@ -76,6 +65,7 @@ namespace verus
// Hexadecimal:
static String ByteToHex(BYTE b);
static String ToHex(const Vector<BYTE>& vBin);
static String ToHex(UINT32 color);
static Vector<BYTE> ToBinFromHex(CSZ hex);
// MD5:

View File

@ -14,7 +14,7 @@ bool Cooldown::IsFinished(float after) const
return _deadline <= timer.GetTime() + after;
}
bool Cooldown::IsInProgress(float partComplete) const
bool Cooldown::IsInProgress(float partFinished) const
{
VERUS_QREF_TIMER;
const float t = timer.GetTime();
@ -22,7 +22,7 @@ bool Cooldown::IsInProgress(float partComplete) const
if (t >= startTime && t < _deadline)
{
const float part = (t - startTime) / _actualInterval;
return part >= partComplete;
return part >= partFinished;
}
return false;
}
@ -33,3 +33,11 @@ void Cooldown::Start(float interval)
_actualInterval = (interval >= 0) ? interval : _baseInterval;
_deadline = timer.GetTime() + _actualInterval;
}
float Cooldown::GetFinishedRatio() const
{
VERUS_QREF_TIMER;
const float t = timer.GetTime();
const float startTime = _deadline - _actualInterval;
return Math::Clamp<float>((t - startTime) / _actualInterval, 0, 1);
}

View File

@ -13,10 +13,11 @@ namespace verus
Cooldown(float interval);
bool IsFinished(float after = 0) const;
bool IsInProgress(float partComplete = 1) const;
bool IsInProgress(float partFinished = 1) const;
void Start(float interval = -1);
void Reset() { _deadline = 0; }
void SetBaseInterval(float x) { _baseInterval = x; }
float GetFinishedRatio() const;
};
VERUS_TYPEDEFS(Cooldown);
}

View File

@ -76,6 +76,12 @@ void Utils::PushQuitEvent()
SDL_PushEvent(&event);
}
void Utils::OpenUrl(CSZ url)
{
const WideString urlW = Str::Utf8ToWide(url);
ShellExecute(0, L"open", _C(urlW), 0, 0, SW_SHOWNORMAL);
}
INT32 Utils::Cast32(INT64 x)
{
if (x < std::numeric_limits<INT32>::min() || x > std::numeric_limits<INT32>::max())

View File

@ -47,6 +47,8 @@ namespace verus
static void PushQuitEvent();
static void OpenUrl(CSZ url);
static INT32 Cast32(INT64 x);
static UINT32 Cast32(UINT64 x);

View File

@ -51,7 +51,7 @@ namespace verus
std::thread _thread;
std::condition_variable _cv;
D::RuntimeError _ex;
CSZ _queue[64];
CSZ _queue[256];
int _cursorRead = 0;
int _cursorWrite = 0;
UINT32 _order = 0;

View File

@ -101,27 +101,24 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
{
if (ImGui::GetIO().WantCaptureMouse)
return false;
if (1 == event.button.clicks)
{
if (event.button.button < VERUS_BUTTON_WHEELUP)
OnMouseDown(event.button.button);
}
else if (2 == event.button.clicks)
if (2 == event.button.clicks)
{
if (event.button.button < VERUS_BUTTON_WHEELUP)
OnMouseDoubleClick(event.button.button);
}
else
{
if (event.button.button < VERUS_BUTTON_WHEELUP)
OnMouseDown(event.button.button);
}
}
break;
case SDL_MOUSEBUTTONUP:
{
if (ImGui::GetIO().WantCaptureMouse)
return false;
if (1 == event.button.clicks)
{
if (event.button.button < VERUS_BUTTON_WHEELUP)
OnMouseUp(event.button.button);
}
if (event.button.button < VERUS_BUTTON_WHEELUP)
OnMouseUp(event.button.button);
}
break;
case SDL_MOUSEWHEEL:

View File

@ -9,6 +9,51 @@ VERUS_CT_ASSERT(sizeof(glm::mat4x3) == 48);
using namespace verus;
static CSZ g_easings[] =
{
"",
"sineIn",
"sineOut",
"sineInOut",
"quadIn",
"quadOut",
"quadInOut",
"cubicIn",
"cubicOut",
"cubicInOut",
"quartIn",
"quartOut",
"quartInOut",
"quintIn",
"quintOut",
"quintInOut",
"expoIn",
"expoOut",
"expoInOut",
"circIn",
"circOut",
"circInOut",
"backIn",
"backOut",
"backInOut",
"elasticIn",
"elasticOut",
"elasticInOut",
"bounceIn",
"bounceOut",
"bounceInOut"
};
bool Math::IsPowerOfTwo(int x)
{
if (x <= 0)
@ -81,6 +126,73 @@ float Math::SmoothStep(float a, float b, float t)
return x * x * (3 - (x + x));
}
float Math::ApplyEasing(Easing easing, float x)
{
switch (easing)
{
case Easing::none: return x;
case Easing::sineIn: return glm::sineEaseIn(x);
case Easing::sineOut: return glm::sineEaseOut(x);
case Easing::sineInOut: return glm::sineEaseInOut(x);
case Easing::quadIn: return glm::quadraticEaseIn(x);
case Easing::quadOut: return glm::quadraticEaseOut(x);
case Easing::quadInOut: return glm::quadraticEaseInOut(x);
case Easing::cubicIn: return glm::cubicEaseIn(x);
case Easing::cubicOut: return glm::cubicEaseOut(x);
case Easing::cubicInOut: return glm::cubicEaseInOut(x);
case Easing::quartIn: return glm::quarticEaseIn(x);
case Easing::quartOut: return glm::quarticEaseOut(x);
case Easing::quartInOut: return glm::quarticEaseInOut(x);
case Easing::quintIn: return glm::quinticEaseIn(x);
case Easing::quintOut: return glm::quinticEaseOut(x);
case Easing::quintInOut: return glm::quinticEaseInOut(x);
case Easing::expoIn: return glm::exponentialEaseIn(x);
case Easing::expoOut: return glm::exponentialEaseOut(x);
case Easing::expoInOut: return glm::exponentialEaseInOut(x);
case Easing::circIn: return glm::circularEaseIn(x);
case Easing::circOut: return glm::circularEaseOut(x);
case Easing::circInOut: return glm::circularEaseInOut(x);
case Easing::backIn: return glm::backEaseIn(x);
case Easing::backOut: return glm::backEaseOut(x);
case Easing::backInOut: return glm::backEaseInOut(x);
case Easing::elasticIn: return glm::elasticEaseIn(x);
case Easing::elasticOut: return glm::elasticEaseOut(x);
case Easing::elasticInOut: return glm::elasticEaseInOut(x);
case Easing::bounceIn: return glm::bounceEaseIn(x);
case Easing::bounceOut: return glm::bounceEaseOut(x);
case Easing::bounceInOut: return glm::bounceEaseInOut(x);
}
VERUS_RT_FAIL("Unknown easing.");
return x;
}
Easing Math::EasingFromString(CSZ s)
{
const int count = VERUS_COUNT_OF(g_easings);
VERUS_FOR(i, count)
{
if (!strcmp(s, g_easings[i]))
return static_cast<Easing>(i);
}
throw VERUS_RECOVERABLE << "Unknown easing string: " << s;
}
CSZ Math::EasingToString(Easing easing)
{
VERUS_RT_ASSERT(easing >= Easing::none && easing < Easing::count);
return g_easings[+easing];
}
Vector3 Math::TriangleNormal(RcPoint3 a, RcPoint3 b, RcPoint3 c)
{
return VMath::normalize(VMath::cross(a - b, a - c));

View File

@ -16,12 +16,60 @@ namespace verus
inside,
intersect
};
enum class Continue : int
{
no,
yes
};
enum class Easing : int
{
none,
sineIn,
sineOut,
sineInOut,
quadIn,
quadOut,
quadInOut,
cubicIn,
cubicOut,
cubicInOut,
quartIn,
quartOut,
quartInOut,
quintIn,
quintOut,
quintInOut,
expoIn,
expoOut,
expoInOut,
circIn,
circOut,
circInOut,
backIn,
backOut,
backInOut,
elasticIn,
elasticOut,
elasticInOut,
bounceIn,
bounceOut,
bounceInOut,
count
};
typedef glm::vec2 float2;
typedef glm::vec3 float3;
typedef glm::vec4 float4;
@ -62,6 +110,9 @@ namespace verus
// Interpolation, splines:
float Lerp(float a, float b, float t);
float SmoothStep(float a, float b, float t);
float ApplyEasing(Easing easing, float x);
Easing EasingFromString(CSZ s);
CSZ EasingToString(Easing easing);
// Shapes:
Vector3 TriangleNormal(RcPoint3 a, RcPoint3 b, RcPoint3 c);

View File

@ -41,6 +41,13 @@ bool Addr::IsLocalhost() const
void Addr::FromString(CSZ addr)
{
if (!addr || !(*addr))
{
_addr = 0;
_port = 0;
return;
}
char addrBuff[40];
CSZ pColon = strchr(addr, ':');
if (pColon) // "IP:Port" format?
@ -52,6 +59,7 @@ void Addr::FromString(CSZ addr)
addr = addrBuff;
}
_addr = 0;
const int ret = inet_pton(AF_INET, addr, &_addr);
if (1 != ret)
{

View File

@ -12,7 +12,7 @@ namespace verus
union
{
UINT32 _addr = 0;
BYTE _a[4];
BYTE _a[4];
};
UINT16 _port = 0;
@ -25,7 +25,7 @@ namespace verus
//! Returns localhost address 127.0.0.1.
static Addr Localhost(int port = 0);
bool IsNull() const { return !_port; }
bool IsNull() const { return !_addr || !_port; }
bool IsLocalhost() const;
//! Accepts IP:Port or URL, which is resolved using getaddrinfo().

View File

@ -393,7 +393,7 @@ void Multiplayer::ThreadProc()
std::chrono::steady_clock::time_point tpNat = std::chrono::steady_clock::now();
while (true)
{
_cv.wait_for(lock, std::chrono::milliseconds(20)); // ~50 times per second.
_cv.wait_for(lock, std::chrono::milliseconds(10)); // ~100 times per second.
bool resend = false;
if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - tpResend).count() >= 3)
@ -506,7 +506,7 @@ void Multiplayer::ThreadProc()
}
// Receive reports from the net?
while ((res = _socket.RecvFrom(_vReportBuffer.data(), _vReportBuffer.size(), addr)) > 0)
while ((res = _socket.RecvFrom(_vReportBuffer.data(), static_cast<int>(_vReportBuffer.size()), addr)) > 0)
{
// Start analyzing incoming traffic...
@ -717,33 +717,32 @@ void Multiplayer::ThreadProcWeb()
} while (ret > 0);
CSZ p = strstr(_C(data), "\r\n\r\n");
//tinyxml2::XMLDocument doc;
//doc.Parse(p);
//if (doc.Error())
// return;
//
//tinyxml2::XMLElement* pElem = nullptr;
//tinyxml2::XMLElement* pRoot = doc.FirstChildElement(); // <games>.
//if (!pRoot)
// return;
//
//{
// VERUS_LOCK(*this);
// _vGameDesc.clear();
// if (_vGameDesc.capacity() < 16)
// _vGameDesc.reserve(16);
// for (pElem = pRoot->FirstChildElement("game"); pElem; pElem = pElem->NextSiblingElement("game"))
// {
// GameDesc gd;
// gd._addr.FromString(pElem->Attribute("ip"));
// gd._version = atoi(pElem->Attribute("ver"));
// gd._num = atoi(pElem->Attribute("p"));
// gd._map = pElem->Attribute("map");
// gd._name = pElem->GetText();
// _vGameDesc.push_back(gd);
// }
// SetFlag(MultiplayerFlags::activeGamesReady);
//}
pugi::xml_document doc;
const pugi::xml_parse_result result = doc.load_buffer(p, strlen(p));
if (!result)
return;
pugi::xml_node root = doc.first_child();
if (!root)
return;
{
VERUS_LOCK(*this);
_vGameDesc.clear();
if (_vGameDesc.capacity() < 16)
_vGameDesc.reserve(16);
for (auto node : root.children("game"))
{
GameDesc gameDesc;
gameDesc._name = node.text().as_string();
gameDesc._map = node.attribute("map").value();
gameDesc._addr.FromString(node.attribute("ip").value());
gameDesc._version = node.attribute("var").as_int();
gameDesc._count = node.attribute("p").as_int();
_vGameDesc.push_back(gameDesc);
}
SetFlag(MultiplayerFlags::activeGamesReady);
}
}
else
{

View File

@ -6,9 +6,11 @@ namespace verus
void Make_Net()
{
Net::Socket::Startup();
Net::Multiplayer::Make();
}
void Free_Net()
{
Net::Multiplayer::Free();
Net::Socket::Cleanup();
}
}

View File

@ -486,3 +486,17 @@ void Atmosphere::CreateCelestialBodyMesh()
_geo->CreateVertexBuffer(4, 0);
_geo->UpdateVertexBuffer(skyBody, 0);
}
void Atmosphere::GetReport(RReport report)
{
report._time = _time;
report._speed = _timeSpeed;
report._cloudiness = _clouds._cloudiness.GetTarget();
}
void Atmosphere::SetReport(RcReport report)
{
_time = report._time;
_timeSpeed = report._speed;
_clouds._cloudiness = report._cloudiness;
}

View File

@ -101,6 +101,14 @@ namespace verus
bool _async_loaded = false;
public:
struct Report
{
float _time;
float _speed;
float _cloudiness;
};
VERUS_TYPEDEFS(Report);
Atmosphere();
virtual ~Atmosphere();
@ -153,6 +161,9 @@ namespace verus
RCascadedShadowMap GetShadowMap() { return _shadowMap; }
void CreateCelestialBodyMesh();
void GetReport(RReport report);
void SetReport(RcReport report);
};
VERUS_TYPEDEFS(Atmosphere);
}

View File

@ -165,7 +165,6 @@ void BaseMesh::LoadX3D3(RcBlob blob)
pVB[i]._nrm[2] * pVB[i]._nrm[2];
VERUS_RT_ASSERT(len > 125 * 125);
#endif
Convert::ToDeviceNormal(pVB[i]._nrm, pVB[i]._nrm);
}
}
break;

View File

@ -58,7 +58,7 @@ void Grass::DoneStatic()
s_shader.Done();
}
void Grass::Init(RTerrain terrain)
void Grass::Init(RTerrain terrain, CSZ atlasUrl)
{
VERUS_INIT();
VERUS_QREF_RENDERER;
@ -120,21 +120,28 @@ void Grass::Init(RTerrain terrain)
_pipe[PIPE_BILLBOARDS].Init(pipeDesc);
}
const int texW = 1024;
const int texH = 1024;
_vTextureSubresData.clear();
_vTextureSubresData.resize(texW * texH);
if (atlasUrl)
{
_tex.Init(atlasUrl);
}
else
{
const int texW = 1024;
const int texH = 1024;
_vTextureSubresData.clear();
_vTextureSubresData.resize(texW * texH);
CGI::TextureDesc texDesc;
texDesc._name = "Grass.Tex";
texDesc._format = CGI::Format::srgbR8G8B8A8;
texDesc._width = texW;
texDesc._height = texH;
texDesc._mipLevels = 0;
texDesc._flags = CGI::TextureDesc::Flags::generateMips;
_tex.Init(texDesc);
_tex->UpdateSubresource(_vTextureSubresData.data());
_tex->GenerateMips();
CGI::TextureDesc texDesc;
texDesc._name = "Grass.Tex";
texDesc._format = CGI::Format::srgbR8G8B8A8;
texDesc._width = texW;
texDesc._height = texH;
texDesc._mipLevels = 0;
texDesc._flags = CGI::TextureDesc::Flags::generateMips;
_tex.Init(texDesc);
_tex->UpdateSubresource(_vTextureSubresData.data());
_tex->GenerateMips();
}
s_shader->FreeDescriptorSet(_cshVS);
_cshVS = s_shader->BindDescriptorSetTextures(0,
@ -143,11 +150,6 @@ void Grass::Init(RTerrain terrain)
_pTerrain->GetNormalsTexture(),
_pTerrain->GetMainLayerTexture(),
});
s_shader->FreeDescriptorSet(_cshFS);
_cshFS = s_shader->BindDescriptorSetTextures(1,
{
_tex
});
_vMagnets.resize(16);
std::fill(_vMagnets.begin(), _vMagnets.end(), Magnet());
@ -172,6 +174,9 @@ void Grass::Update()
VERUS_QREF_ATMO;
VERUS_QREF_TIMER;
if (!_cshFS.IsSet() && _tex->IsLoaded())
_cshFS = s_shader->BindDescriptorSetTextures(1, { _tex });
_phase = glm::fract(_phase + dt * 2.3f);
const float windSpeed = atmo.GetWindSpeed();
@ -182,10 +187,13 @@ void Grass::Update()
_turbulence = turbulence * turbulence;
// Async texture loading:
VERUS_FOR(i, s_maxBushTypes)
if (!_vTextureSubresData.empty())
{
if (_texLoaded[i].IsInitialized() && _texLoaded[i].IsLoaded())
OnTextureLoaded(i);
VERUS_FOR(i, s_maxBushTypes)
{
if (_texLoaded[i].IsInitialized() && _texLoaded[i].IsLoaded())
OnTextureLoaded(i);
}
}
}
@ -211,6 +219,8 @@ void Grass::Draw()
{
if (!_visiblePatchCount)
return;
if (!_cshFS.IsSet())
return;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
@ -432,12 +442,25 @@ void Grass::ResetAllTextures()
void Grass::SetTexture(int layer, CSZ url, CSZ url2)
{
if (_vTextureSubresData.empty()) // Using DDS?
{
_bushMask |= (1 << layer);
if (layer < 8)
_bushMask |= (1 << (layer + 8));
return;
}
VERUS_RT_ASSERT(url);
_texLoaded[layer].LoadDDS(url);
if (layer < 8)
SetTexture(layer + 8, url2 ? url2 : url);
}
void Grass::SaveTexture(CSZ url)
{
IO::FileSystem::SaveImage(url, _vTextureSubresData.data(), 1024, 1024);
}
void Grass::OnTextureLoaded(int layer)
{
VERUS_QREF_RENDERER;

View File

@ -90,7 +90,7 @@ namespace verus
static void InitStatic();
static void DoneStatic();
void Init(RTerrain terrain);
void Init(RTerrain terrain, CSZ atlasUrl = nullptr);
void Done();
void ResetInstanceCount();
@ -106,6 +106,7 @@ namespace verus
void ResetAllTextures();
void SetTexture(int layer, CSZ url, CSZ url2 = nullptr);
VERUS_P(void OnTextureLoaded(int layer));
void SaveTexture(CSZ url);
int BeginMagnet(RcPoint3 pos, float radius);
void EndMagnet(int index);

View File

@ -201,13 +201,29 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
"#SolidColorRobotic",
"#SolidColorSkinned",
// Simple:
"#",
"#Instanced",
"#Robotic",
"#Skinned"
"#Skinned",
"#Texture",
"#TextureInstanced",
"#TextureRobotic",
"#TextureSkinned"
};
if (pipe >= PIPE_SIMPLE_REF)
if (pipe >= PIPE_SIMPLE_TEX_ADD)
{
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_SIMPLE], branches[pipe], renderer.GetDS().GetRenderPassHandle_ExtraCompose());
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
pipeDesc._rasterizationState._cullMode = CGI::CullMode::none;
pipeDesc._vertexInputBindingsFilter = _bindingsMask;
pipeDesc._depthWriteEnable = false;
s_pipe[pipe].Init(pipeDesc);
}
else if (pipe >= PIPE_SIMPLE_WATER_REF)
{
VERUS_QREF_WATER;
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_SIMPLE], branches[pipe], water.GetRenderPassHandle());

View File

@ -49,10 +49,15 @@ namespace verus
PIPE_WIREFRAME_ROBOTIC,
PIPE_WIREFRAME_SKINNED,
PIPE_SIMPLE_REF,
PIPE_SIMPLE_REF_INSTANCED,
PIPE_SIMPLE_REF_ROBOTIC,
PIPE_SIMPLE_REF_SKINNED,
PIPE_SIMPLE_WATER_REF,
PIPE_SIMPLE_WATER_REF_INSTANCED,
PIPE_SIMPLE_WATER_REF_ROBOTIC,
PIPE_SIMPLE_WATER_REF_SKINNED,
PIPE_SIMPLE_TEX_ADD,
PIPE_SIMPLE_TEX_ADD_INSTANCED,
PIPE_SIMPLE_TEX_ADD_ROBOTIC,
PIPE_SIMPLE_TEX_ADD_SKINNED,
PIPE_COUNT
};

View File

@ -604,6 +604,8 @@ bool SceneManager::RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, PBlockPtr pB
{
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)
{

View File

@ -131,13 +131,6 @@ void Block::Update()
}
}
void Block::SetDynamic(bool mode)
{
SceneNode::SetDynamic(mode);
_octreeBindOnce = false;
_async_loadedModel = false;
}
MaterialPtr Block::GetMaterial(bool orModelMat)
{
if (!_material && orModelMat)

View File

@ -61,8 +61,6 @@ namespace verus
bool IsLoadedModel() const { return _model->IsLoaded(); }
virtual void SetDynamic(bool mode) override;
virtual void SetColor(RcVector4 color) override { _userColor = color; }
virtual Vector4 GetColor() override { return _userColor; }
ModelPtr GetModel() { return _model; }

View File

@ -21,6 +21,7 @@ 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);

View File

@ -33,6 +33,7 @@ namespace verus
CSZ _urlIntShaker = nullptr;
float _intShakerScale = 0.25f;
LightData _data;
bool _dynamic = false;
};
VERUS_TYPEDEFS(Desc);

View File

@ -68,7 +68,7 @@ void Model::BindPipeline(CGI::CommandBufferPtr cb)
void Model::BindPipelineReflection(CGI::CommandBufferPtr cb)
{
_mesh.BindPipeline(Mesh::PIPE_SIMPLE_REF_INSTANCED, cb);
_mesh.BindPipeline(Mesh::PIPE_SIMPLE_WATER_REF_INSTANCED, cb);
_mesh.UpdateUniformBufferSimplePerFrame();
}

View File

@ -42,6 +42,13 @@ void SceneNode::Rename(CSZ name)
_name = sm.EnsureUniqueName(name);
}
void SceneNode::SetDynamic(bool mode)
{
_dynamic = mode;
_octreeBindOnce = false;
UpdateBounds();
}
void SceneNode::SetTransform(RcTransform3 tr)
{
_tr = tr;

View File

@ -48,7 +48,7 @@ namespace verus
IO::RDictionary GetDictionary() { return _dict; }
bool IsDynamic() const { return _dynamic; }
virtual void SetDynamic(bool mode) { _dynamic = mode; }
void SetDynamic(bool mode);
bool IsHidden() const { return _hidden; }
void Hide(bool hide = true) { _hidden = hide; }

View File

@ -14,6 +14,8 @@ namespace verus
struct Desc
{
CSZ _url = nullptr;
Desc(CSZ url = nullptr) : _url(url) {}
};
VERUS_TYPEDEFS(Desc);

View File

@ -1266,7 +1266,7 @@ void Terrain::UpdateHeightmapTexture()
const int ij[] = { i * step, j * step };
short h;
GetHeightAt(ij, 0, &h);
_vHeightmapSubresData[offset + j] = glm::packHalf1x16(h);
_vHeightmapSubresData[offset + j] = glm::packHalf1x16(static_cast<float>(h - 3));
}
});
_tex[TEX_HEIGHTMAP]->UpdateSubresource(_vHeightmapSubresData.data(), lod);

View File

@ -52,7 +52,7 @@ FSO mainFS(VSO si)
const float4 rawColor = g_tex.SampleLevel(g_sam, si.tc0, 0.0);
const float3 color = rawColor.rgb * g_ubBloomFS._exposure.x;
const float3 bloom = saturate((color - 1.0) * 0.3);
const float3 bloom = saturate((color - 0.95) * 0.6);
#ifdef DEF_GOD_RAYS
const float2 ndcPos = ToNdcPos(si.tc0);

View File

@ -218,7 +218,7 @@ FSO mainMotionFS(VSO si)
FSO so;
const float3 rand = Rand(si.pos.xy);
const float offsetScale = 0.5 + 0.3 * rand.x; // Blur 50% - 80% of frame time.
const float offsetScale = 0.3 + 0.2 * rand.x; // Blur 30% - 50% of frame time.
const int sampleCount = max(4, _ANISOTROPY_LEVEL);
@ -237,7 +237,7 @@ FSO mainMotionFS(VSO si)
}
const float2 stride = (si.tc0 - tcFrom) * offsetScale / (sampleCount - 1);
const float2 tcOrigin = lerp(tcFrom, si.tc0, 0.7);
const float2 tcOrigin = lerp(tcFrom, si.tc0, 0.8);
float4 acc = float4(g_tex.SampleLevel(g_sam, si.tc0, 0.0).rgb, 1);
[unroll] for (int i = 0; i < sampleCount; i++)

View File

@ -95,5 +95,5 @@ float3 VerusToneMapping(float3 hdr, float filmicLook = 1.0)
const float desatMask = saturate(maxValue * 0.15);
hdr = lerp(hdr, maxValue, desatMask * desatMask); // Color crosstalk.
const float3 ldr = lerp(1.0 - exp(-hdr), ToneMappingACES(hdr), filmicLook);
return saturate(ldr);
return saturate(ldr * 1.2 - 0.002); // Add some clipping.
}

View File

@ -36,11 +36,13 @@ struct VSI
struct VSO
{
float4 pos : SV_Position;
float4 color0 : COLOR0;
float2 tc0 : TEXCOORD0;
float4 posW_depth : TEXCOORD1;
#if !defined(DEF_TEXTURE)
float3 nrmW : TEXCOORD2;
float3 dirToEye : TEXCOORD3;
float4 color0 : COLOR0;
#endif
float clipDistance : SV_ClipDistance;
};
@ -113,10 +115,12 @@ VSO mainVS(VSI si)
so.pos = mul(float4(posW, 1), g_ubSimplePerFrame._matVP);
so.posW_depth = float4(posW, so.pos.z);
so.color0 = userColor;
so.tc0 = intactTc0;
#if !defined(DEF_TEXTURE)
so.nrmW = nrmW;
so.dirToEye = eyePos - posW;
so.color0 = userColor;
#endif
so.clipDistance = posW.y + clipDistanceOffset;
return so;
@ -128,6 +132,11 @@ FSO mainFS(VSO si)
{
FSO so;
#ifdef DEF_TEXTURE
const float4 rawAlbedo = g_texAlbedo.Sample(g_samAlbedo, si.tc0);
so.color.rgb = rawAlbedo.rgb * si.color0.rgb;
so.color.a = 1.0;
#else
// <Material>
const float2 mm_alphaSwitch = g_ubSimplePerMaterialFS._alphaSwitch_anisoSpecDir.xy;
const float mm_emission = g_ubSimplePerMaterialFS._detail_emission_gloss_hairDesat.y;
@ -227,6 +236,7 @@ FSO mainFS(VSO si)
so.color.rgb = lerp(so.color.rgb, g_ubSimplePerFrame._fogColor.rgb, fog);
clip(alpha_spec.x - 0.5);
#endif
return so;
}
@ -236,3 +246,8 @@ FSO mainFS(VSO si)
//@main:#Instanced INSTANCED
//@main:#Robotic ROBOTIC
//@main:#Skinned SKINNED
//@main:#Texture TEXTURE
//@main:#TextureInstanced TEXTURE INSTANCED
//@main:#TextureRobotic TEXTURE ROBOTIC
//@main:#TextureSkinned TEXTURE SKINNED