This commit is contained in:
Dmitry 2018-03-03 11:17:09 +03:00
parent 3a391f11f5
commit 9455594fb7
184 changed files with 18637 additions and 0 deletions

321
.gitignore vendored Normal file
View File

@ -0,0 +1,321 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog

View File

@ -0,0 +1,6 @@
// RendererDirect3D12.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{53923514-84B2-4B78-889A-8709C6BFA3A5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>RendererDirect3D12</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;RENDERERDIRECT3D12_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;RENDERERDIRECT3D12_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="RendererDirect3D12.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RendererDirect3D12.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,19 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@ -0,0 +1 @@
#include "stdafx.h"

View File

@ -0,0 +1,16 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
// reference additional headers your program requires here

View File

@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

View File

@ -0,0 +1,6 @@
// RendererVulkan.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>RendererVulkan</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;RENDERERVULKAN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;RENDERERVULKAN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="RendererVulkan.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RendererVulkan.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,19 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@ -0,0 +1 @@
#include "stdafx.h"

16
RendererVulkan/stdafx.h Normal file
View File

@ -0,0 +1,16 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
// reference additional headers your program requires here

View File

@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

43
Verus.sln Normal file
View File

@ -0,0 +1,43 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Verus", "Verus\Verus.vcxproj", "{B154D670-E4B1-4D8A-885C-69546A5BD833}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VerusTest", "VerusTest\VerusTest.vcxproj", "{D7085182-35B9-4689-ADBA-B77087AD16BF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererDirect3D12", "RendererDirect3D12\RendererDirect3D12.vcxproj", "{53923514-84B2-4B78-889A-8709C6BFA3A5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererVulkan", "RendererVulkan\RendererVulkan.vcxproj", "{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B154D670-E4B1-4D8A-885C-69546A5BD833}.Debug|x64.ActiveCfg = Debug|x64
{B154D670-E4B1-4D8A-885C-69546A5BD833}.Debug|x64.Build.0 = Debug|x64
{B154D670-E4B1-4D8A-885C-69546A5BD833}.Release|x64.ActiveCfg = Release|x64
{B154D670-E4B1-4D8A-885C-69546A5BD833}.Release|x64.Build.0 = Release|x64
{D7085182-35B9-4689-ADBA-B77087AD16BF}.Debug|x64.ActiveCfg = Debug|x64
{D7085182-35B9-4689-ADBA-B77087AD16BF}.Debug|x64.Build.0 = Debug|x64
{D7085182-35B9-4689-ADBA-B77087AD16BF}.Release|x64.ActiveCfg = Release|x64
{D7085182-35B9-4689-ADBA-B77087AD16BF}.Release|x64.Build.0 = Release|x64
{53923514-84B2-4B78-889A-8709C6BFA3A5}.Debug|x64.ActiveCfg = Debug|x64
{53923514-84B2-4B78-889A-8709C6BFA3A5}.Debug|x64.Build.0 = Debug|x64
{53923514-84B2-4B78-889A-8709C6BFA3A5}.Release|x64.ActiveCfg = Release|x64
{53923514-84B2-4B78-889A-8709C6BFA3A5}.Release|x64.Build.0 = Release|x64
{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}.Debug|x64.ActiveCfg = Debug|x64
{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}.Debug|x64.Build.0 = Debug|x64
{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}.Release|x64.ActiveCfg = Release|x64
{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0D2FFAEF-1E59-46F0-BDDF-1634F6790F83}
EndGlobalSection
EndGlobal

11
Verus/Verus.props Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\bullet3-2.88\src;C:\Home\Middleware\bullet3-2.88\Extras;C:\Home\Middleware\glm-0.9.9.3\glm;C:\Home\Middleware\json-3.5.0;C:\Home\Middleware\libogg-1.3.3\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\SDL2-2.0.9\include;C:\Home\Middleware\tinyxml2-7.0.1;C:\Home\Middleware\vectormath;C:\Home\Middleware\zlib-1.2.11;C:\Program Files %28x86%29\OpenAL 1.1 SDK\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Home\Middleware\bullet3-2.88\lib\Debug;C:\Home\Middleware\libogg-1.3.3\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\SDL2-2.0.9\lib\x64;C:\Home\Middleware\tinyxml2-7.0.1;C:\Home\Middleware\zlib-1.2.11;C:\Program Files %28x86%29\OpenAL 1.1 SDK\libs\Win64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />
</Project>

275
Verus/Verus.vcxproj Normal file
View File

@ -0,0 +1,275 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{B154D670-E4B1-4D8A-885C-69546A5BD833}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Verus</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="Verus.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="Verus.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>verus.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>verus.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="src\AI\AI.h" />
<ClInclude Include="src\AI\TaskDriver.h" />
<ClInclude Include="src\AI\Turret.h" />
<ClInclude Include="src\Anim\Anim.h" />
<ClInclude Include="src\Anim\Animation.h" />
<ClInclude Include="src\Anim\Motion.h" />
<ClInclude Include="src\Anim\Skeleton.h" />
<ClInclude Include="src\App\App.h" />
<ClInclude Include="src\App\Settings.h" />
<ClInclude Include="src\App\Window.h" />
<ClInclude Include="src\Audio\Audio.h" />
<ClInclude Include="src\Audio\AudioSystem.h" />
<ClInclude Include="src\Audio\OggCallbacks.h" />
<ClInclude Include="src\Audio\Sound.h" />
<ClInclude Include="src\Audio\Source.h" />
<ClInclude Include="src\Audio\StreamPlayer.h" />
<ClInclude Include="src\CGI\BaseGeometry.h" />
<ClInclude Include="src\CGI\BasePipeline.h" />
<ClInclude Include="src\CGI\BaseShader.h" />
<ClInclude Include="src\CGI\BaseTexture.h" />
<ClInclude Include="src\CGI\CGI.h" />
<ClInclude Include="src\D\AssertionCompileTime.h" />
<ClInclude Include="src\D\AssertionRunTime.h" />
<ClInclude Include="src\D\D.h" />
<ClInclude Include="src\D\Log.h" />
<ClInclude Include="src\D\Recoverable.h" />
<ClInclude Include="src\D\RuntimeError.h" />
<ClInclude Include="src\Game\BaseGame.h" />
<ClInclude Include="src\Game\Game.h" />
<ClInclude Include="src\Game\State.h" />
<ClInclude Include="src\Game\StateMachine.h" />
<ClInclude Include="src\Global\AlignedAllocator.h" />
<ClInclude Include="src\Global\AllocatorAware.h" />
<ClInclude Include="src\Global\BaseAllocator.h" />
<ClInclude Include="src\Global\Basic.h" />
<ClInclude Include="src\Global\Blob.h" />
<ClInclude Include="src\Global\Convert.h" />
<ClInclude Include="src\Global\EngineInit.h" />
<ClInclude Include="src\Global\Linear.h" />
<ClInclude Include="src\Global\Lockable.h" />
<ClInclude Include="src\Global\Object.h" />
<ClInclude Include="src\Global\Parallel.h" />
<ClInclude Include="src\Global\QuickRefs.h" />
<ClInclude Include="src\Global\Random.h" />
<ClInclude Include="src\Global\Range.h" />
<ClInclude Include="src\Global\Singleton.h" />
<ClInclude Include="src\Global\Store.h" />
<ClInclude Include="src\Global\Str.h" />
<ClInclude Include="src\Global\Timer.h" />
<ClInclude Include="src\Global\Utils.h" />
<ClInclude Include="src\Input\Input.h" />
<ClInclude Include="src\Input\KeyMapper.h" />
<ClInclude Include="src\IO\Async.h" />
<ClInclude Include="src\IO\DDSHeader.h" />
<ClInclude Include="src\IO\File.h" />
<ClInclude Include="src\IO\FileSystem.h" />
<ClInclude Include="src\IO\IO.h" />
<ClInclude Include="src\IO\Json.h" />
<ClInclude Include="src\IO\Stream.h" />
<ClInclude Include="src\Global\EnumClass.h" />
<ClInclude Include="src\Global\Macros.h" />
<ClInclude Include="src\Global\Global.h" />
<ClInclude Include="src\Global\STL.h" />
<ClInclude Include="src\Global\SyntaxHighlight.h" />
<ClInclude Include="src\Global\Typedef.h" />
<ClInclude Include="src\IO\StreamPtr.h" />
<ClInclude Include="src\IO\Xml.h" />
<ClInclude Include="src\Math\Bounds.h" />
<ClInclude Include="src\Math\Frustum.h" />
<ClInclude Include="src\Math\Math.h" />
<ClInclude Include="src\Math\Matrix.h" />
<ClInclude Include="src\Math\NormalComputer.h" />
<ClInclude Include="src\Math\Plane.h" />
<ClInclude Include="src\Math\Quat.h" />
<ClInclude Include="src\Math\Sphere.h" />
<ClInclude Include="src\Math\Vector.h" />
<ClInclude Include="src\Net\Addr.h" />
<ClInclude Include="src\Net\HttpFile.h" />
<ClInclude Include="src\Net\Net.h" />
<ClInclude Include="src\Net\Socket.h" />
<ClInclude Include="src\Scene\BaseMesh.h" />
<ClInclude Include="src\Scene\Camera.h" />
<ClInclude Include="src\Scene\Mesh.h" />
<ClInclude Include="src\Scene\Scene.h" />
<ClInclude Include="src\Security\CipherRC4.h" />
<ClInclude Include="src\Security\Security.h" />
<ClInclude Include="src\ThirdParty\libb64\cdecode.h" />
<ClInclude Include="src\ThirdParty\libb64\cencode.h" />
<ClInclude Include="src\ThirdParty\md5.h" />
<ClInclude Include="src\ThirdParty\ThirdParty.h" />
<ClInclude Include="src\ThirdParty\utf8.h" />
<ClInclude Include="src\ThirdParty\utf8\checked.h" />
<ClInclude Include="src\ThirdParty\utf8\core.h" />
<ClInclude Include="src\ThirdParty\utf8\unchecked.h" />
<ClInclude Include="src\verus.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\AI\AI.cpp" />
<ClCompile Include="src\AI\TaskDriver.cpp" />
<ClCompile Include="src\AI\Turret.cpp" />
<ClCompile Include="src\Anim\Anim.cpp" />
<ClCompile Include="src\Anim\Animation.cpp" />
<ClCompile Include="src\Anim\Motion.cpp" />
<ClCompile Include="src\Anim\Skeleton.cpp" />
<ClCompile Include="src\App\App.cpp" />
<ClCompile Include="src\App\Settings.cpp" />
<ClCompile Include="src\App\Window.cpp" />
<ClCompile Include="src\Audio\Audio.cpp" />
<ClCompile Include="src\Audio\AudioSystem.cpp" />
<ClCompile Include="src\Audio\OggCallbacks.cpp" />
<ClCompile Include="src\Audio\Sound.cpp" />
<ClCompile Include="src\Audio\Source.cpp" />
<ClCompile Include="src\Audio\StreamPlayer.cpp" />
<ClCompile Include="src\CGI\BaseGeometry.cpp" />
<ClCompile Include="src\CGI\BasePipeline.cpp" />
<ClCompile Include="src\CGI\BaseShader.cpp" />
<ClCompile Include="src\CGI\BaseTexture.cpp" />
<ClCompile Include="src\D\Log.cpp" />
<ClCompile Include="src\Game\BaseGame.cpp" />
<ClCompile Include="src\Game\State.cpp" />
<ClCompile Include="src\Game\StateMachine.cpp" />
<ClCompile Include="src\Global\AllocatorAware.cpp" />
<ClCompile Include="src\Global\Convert.cpp" />
<ClCompile Include="src\Global\EngineInit.cpp" />
<ClCompile Include="src\Global\Global.cpp" />
<ClCompile Include="src\Global\Object.cpp" />
<ClCompile Include="src\Global\Random.cpp" />
<ClCompile Include="src\Global\Str.cpp" />
<ClCompile Include="src\Global\Timer.cpp" />
<ClCompile Include="src\Global\Utils.cpp" />
<ClCompile Include="src\Input\Input.cpp" />
<ClCompile Include="src\Input\KeyMapper.cpp" />
<ClCompile Include="src\IO\Async.cpp" />
<ClCompile Include="src\IO\DDSHeader.cpp" />
<ClCompile Include="src\IO\File.cpp" />
<ClCompile Include="src\IO\FileSystem.cpp" />
<ClCompile Include="src\IO\IO.cpp" />
<ClCompile Include="src\IO\Json.cpp" />
<ClCompile Include="src\IO\Xml.cpp" />
<ClCompile Include="src\Math\Bounds.cpp" />
<ClCompile Include="src\Math\Frustum.cpp" />
<ClCompile Include="src\Math\Math.cpp" />
<ClCompile Include="src\Math\Matrix.cpp" />
<ClCompile Include="src\Math\NormalComputer.cpp" />
<ClCompile Include="src\Math\Plane.cpp" />
<ClCompile Include="src\Math\Quat.cpp" />
<ClCompile Include="src\Math\Sphere.cpp" />
<ClCompile Include="src\Math\Vector.cpp" />
<ClCompile Include="src\Net\Addr.cpp" />
<ClCompile Include="src\Net\HttpFile.cpp" />
<ClCompile Include="src\Net\Net.cpp" />
<ClCompile Include="src\Net\Socket.cpp" />
<ClCompile Include="src\Scene\BaseMesh.cpp" />
<ClCompile Include="src\Scene\Camera.cpp" />
<ClCompile Include="src\Scene\Mesh.cpp" />
<ClCompile Include="src\Scene\Scene.cpp" />
<ClCompile Include="src\ThirdParty\libb64\cdecode.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4244</DisableSpecificWarnings>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4244</DisableSpecificWarnings>
</ClCompile>
<ClCompile Include="src\ThirdParty\libb64\cencode.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4244</DisableSpecificWarnings>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4244</DisableSpecificWarnings>
</ClCompile>
<ClCompile Include="src\ThirdParty\md5.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4267</DisableSpecificWarnings>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4267</DisableSpecificWarnings>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="src\verus.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

549
Verus/Verus.vcxproj.filters Normal file
View File

@ -0,0 +1,549 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{6dd7f6ca-0929-4d46-9f6d-71ecf8c91abd}</UniqueIdentifier>
</Filter>
<Filter Include="src\CGI">
<UniqueIdentifier>{f756df7f-0ce7-4098-895a-2c1d03fe386b}</UniqueIdentifier>
</Filter>
<Filter Include="src\IO">
<UniqueIdentifier>{afbabad8-439c-4609-b622-a881c8d6d034}</UniqueIdentifier>
</Filter>
<Filter Include="src\D">
<UniqueIdentifier>{9c9fdfe5-4d92-491c-bff1-7442a538ac24}</UniqueIdentifier>
</Filter>
<Filter Include="src\Security">
<UniqueIdentifier>{d5e876a9-20a7-460a-89e4-c6b1cd902307}</UniqueIdentifier>
</Filter>
<Filter Include="src\Global">
<UniqueIdentifier>{d44bf87b-c74b-42a1-9b54-dfe744447364}</UniqueIdentifier>
</Filter>
<Filter Include="src\Math">
<UniqueIdentifier>{ebb05836-e3a7-452d-8e05-a9007ffe1320}</UniqueIdentifier>
</Filter>
<Filter Include="src\Game">
<UniqueIdentifier>{5ece1220-9707-4688-9429-dcde547cb05f}</UniqueIdentifier>
</Filter>
<Filter Include="src\Net">
<UniqueIdentifier>{bcb0dace-45fa-45b5-85d6-c80026a9577b}</UniqueIdentifier>
</Filter>
<Filter Include="src\Audio">
<UniqueIdentifier>{b02345a2-66ea-4995-8a5b-b7b6df5e4470}</UniqueIdentifier>
</Filter>
<Filter Include="src\ThirdParty">
<UniqueIdentifier>{779ebfcc-422d-4f9a-a3de-3d5d416612a0}</UniqueIdentifier>
</Filter>
<Filter Include="src\ThirdParty\utf8">
<UniqueIdentifier>{9026283b-bf5f-489c-9008-4093adeb4ce6}</UniqueIdentifier>
</Filter>
<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>
<Filter Include="src\Anim">
<UniqueIdentifier>{35c65d58-6412-4aa5-bb70-9f3ab9ee37a2}</UniqueIdentifier>
</Filter>
<Filter Include="src\Input">
<UniqueIdentifier>{b10e474d-ad34-4fb3-9a41-875a17a54d36}</UniqueIdentifier>
</Filter>
<Filter Include="src\App">
<UniqueIdentifier>{8487cc8d-90f6-4f48-83f8-433947c79c5c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CGI\BaseGeometry.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\CGI\BasePipeline.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\CGI\BaseShader.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\CGI\BaseTexture.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\CGI\CGI.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\IO\File.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\IO\IO.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\IO\Stream.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\verus.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="src\D\AssertionCompileTime.h">
<Filter>src\D</Filter>
</ClInclude>
<ClInclude Include="src\D\AssertionRunTime.h">
<Filter>src\D</Filter>
</ClInclude>
<ClInclude Include="src\D\Log.h">
<Filter>src\D</Filter>
</ClInclude>
<ClInclude Include="src\D\Recoverable.h">
<Filter>src\D</Filter>
</ClInclude>
<ClInclude Include="src\D\RuntimeError.h">
<Filter>src\D</Filter>
</ClInclude>
<ClInclude Include="src\D\D.h">
<Filter>src\D</Filter>
</ClInclude>
<ClInclude Include="src\Security\CipherRC4.h">
<Filter>src\Security</Filter>
</ClInclude>
<ClInclude Include="src\Security\Security.h">
<Filter>src\Security</Filter>
</ClInclude>
<ClInclude Include="src\Global\EnumClass.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Macros.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\STL.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\SyntaxHighlight.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Typedef.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Global.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Singleton.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Basic.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\AllocatorAware.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\AlignedAllocator.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\BaseAllocator.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Utils.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\QuickRefs.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Parallel.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Range.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Math\Math.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\Game\Game.h">
<Filter>src\Game</Filter>
</ClInclude>
<ClInclude Include="src\Game\State.h">
<Filter>src\Game</Filter>
</ClInclude>
<ClInclude Include="src\Game\StateMachine.h">
<Filter>src\Game</Filter>
</ClInclude>
<ClInclude Include="src\Global\Object.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Global\Random.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Net\Addr.h">
<Filter>src\Net</Filter>
</ClInclude>
<ClInclude Include="src\Net\Net.h">
<Filter>src\Net</Filter>
</ClInclude>
<ClInclude Include="src\Net\Socket.h">
<Filter>src\Net</Filter>
</ClInclude>
<ClInclude Include="src\Global\Lockable.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Audio\OggCallbacks.h">
<Filter>src\Audio</Filter>
</ClInclude>
<ClInclude Include="src\Audio\Sound.h">
<Filter>src\Audio</Filter>
</ClInclude>
<ClInclude Include="src\Audio\Source.h">
<Filter>src\Audio</Filter>
</ClInclude>
<ClInclude Include="src\Math\Matrix.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\Math\Quat.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\Math\Vector.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\Global\Store.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\IO\Async.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\Global\Blob.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Audio\StreamPlayer.h">
<Filter>src\Audio</Filter>
</ClInclude>
<ClInclude Include="src\Global\Linear.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Audio\AudioSystem.h">
<Filter>src\Audio</Filter>
</ClInclude>
<ClInclude Include="src\Global\Str.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Audio\Audio.h">
<Filter>src\Audio</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\ThirdParty.h">
<Filter>src\ThirdParty</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\utf8.h">
<Filter>src\ThirdParty</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\utf8\checked.h">
<Filter>src\ThirdParty\utf8</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\utf8\core.h">
<Filter>src\ThirdParty\utf8</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\utf8\unchecked.h">
<Filter>src\ThirdParty\utf8</Filter>
</ClInclude>
<ClInclude Include="src\Global\Convert.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\libb64\cdecode.h">
<Filter>src\ThirdParty\libb64</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\libb64\cencode.h">
<Filter>src\ThirdParty\libb64</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\md5.h">
<Filter>src\ThirdParty</Filter>
</ClInclude>
<ClInclude Include="src\IO\FileSystem.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\IO\DDSHeader.h">
<Filter>src\IO</Filter>
</ClInclude>
<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>
<ClInclude Include="src\Math\Plane.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\Math\Sphere.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\Math\Bounds.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\AI\AI.h">
<Filter>src\AI</Filter>
</ClInclude>
<ClInclude Include="src\AI\TaskDriver.h">
<Filter>src\AI</Filter>
</ClInclude>
<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>
<ClInclude Include="src\Math\NormalComputer.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="src\Anim\Anim.h">
<Filter>src\Anim</Filter>
</ClInclude>
<ClInclude Include="src\Anim\Animation.h">
<Filter>src\Anim</Filter>
</ClInclude>
<ClInclude Include="src\Anim\Motion.h">
<Filter>src\Anim</Filter>
</ClInclude>
<ClInclude Include="src\Anim\Skeleton.h">
<Filter>src\Anim</Filter>
</ClInclude>
<ClInclude Include="src\IO\Xml.h">
<Filter>src\IO</Filter>
</ClInclude>
<ClInclude Include="src\Net\HttpFile.h">
<Filter>src\Net</Filter>
</ClInclude>
<ClInclude Include="src\Game\BaseGame.h">
<Filter>src\Game</Filter>
</ClInclude>
<ClInclude Include="src\Global\EngineInit.h">
<Filter>src\Global</Filter>
</ClInclude>
<ClInclude Include="src\Input\Input.h">
<Filter>src\Input</Filter>
</ClInclude>
<ClInclude Include="src\Input\KeyMapper.h">
<Filter>src\Input</Filter>
</ClInclude>
<ClInclude Include="src\App\App.h">
<Filter>src\App</Filter>
</ClInclude>
<ClInclude Include="src\App\Settings.h">
<Filter>src\App</Filter>
</ClInclude>
<ClInclude Include="src\App\Window.h">
<Filter>src\App</Filter>
</ClInclude>
<ClInclude Include="src\IO\Json.h">
<Filter>src\IO</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\CGI\BaseGeometry.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
<ClCompile Include="src\CGI\BasePipeline.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
<ClCompile Include="src\CGI\BaseShader.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
<ClCompile Include="src\CGI\BaseTexture.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
<ClCompile Include="src\IO\File.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<ClCompile Include="src\IO\IO.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<ClCompile Include="src\verus.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="src\D\Log.cpp">
<Filter>src\D</Filter>
</ClCompile>
<ClCompile Include="src\Global\AllocatorAware.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Global\Utils.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Global\Global.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Math\Math.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\Game\State.cpp">
<Filter>src\Game</Filter>
</ClCompile>
<ClCompile Include="src\Game\StateMachine.cpp">
<Filter>src\Game</Filter>
</ClCompile>
<ClCompile Include="src\Global\Object.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Global\Random.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Net\Addr.cpp">
<Filter>src\Net</Filter>
</ClCompile>
<ClCompile Include="src\Net\Net.cpp">
<Filter>src\Net</Filter>
</ClCompile>
<ClCompile Include="src\Net\Socket.cpp">
<Filter>src\Net</Filter>
</ClCompile>
<ClCompile Include="src\Audio\OggCallbacks.cpp">
<Filter>src\Audio</Filter>
</ClCompile>
<ClCompile Include="src\Audio\Sound.cpp">
<Filter>src\Audio</Filter>
</ClCompile>
<ClCompile Include="src\Audio\Source.cpp">
<Filter>src\Audio</Filter>
</ClCompile>
<ClCompile Include="src\Math\Matrix.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\Math\Quat.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\Math\Vector.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\IO\Async.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<ClCompile Include="src\Audio\StreamPlayer.cpp">
<Filter>src\Audio</Filter>
</ClCompile>
<ClCompile Include="src\Audio\AudioSystem.cpp">
<Filter>src\Audio</Filter>
</ClCompile>
<ClCompile Include="src\Global\Str.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Audio\Audio.cpp">
<Filter>src\Audio</Filter>
</ClCompile>
<ClCompile Include="src\Global\Convert.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\ThirdParty\libb64\cdecode.c">
<Filter>src\ThirdParty\libb64</Filter>
</ClCompile>
<ClCompile Include="src\ThirdParty\libb64\cencode.c">
<Filter>src\ThirdParty\libb64</Filter>
</ClCompile>
<ClCompile Include="src\ThirdParty\md5.cpp">
<Filter>src\ThirdParty</Filter>
</ClCompile>
<ClCompile Include="src\IO\FileSystem.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<ClCompile Include="src\IO\DDSHeader.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<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>
<ClCompile Include="src\Math\Plane.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\Math\Sphere.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\Math\Bounds.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\AI\AI.cpp">
<Filter>src\AI</Filter>
</ClCompile>
<ClCompile Include="src\AI\TaskDriver.cpp">
<Filter>src\AI</Filter>
</ClCompile>
<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\NormalComputer.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="src\Anim\Anim.cpp">
<Filter>src\Anim</Filter>
</ClCompile>
<ClCompile Include="src\Anim\Animation.cpp">
<Filter>src\Anim</Filter>
</ClCompile>
<ClCompile Include="src\Anim\Motion.cpp">
<Filter>src\Anim</Filter>
</ClCompile>
<ClCompile Include="src\Anim\Skeleton.cpp">
<Filter>src\Anim</Filter>
</ClCompile>
<ClCompile Include="src\IO\Xml.cpp">
<Filter>src\IO</Filter>
</ClCompile>
<ClCompile Include="src\Net\HttpFile.cpp">
<Filter>src\Net</Filter>
</ClCompile>
<ClCompile Include="src\Game\BaseGame.cpp">
<Filter>src\Game</Filter>
</ClCompile>
<ClCompile Include="src\Global\EngineInit.cpp">
<Filter>src\Global</Filter>
</ClCompile>
<ClCompile Include="src\Input\Input.cpp">
<Filter>src\Input</Filter>
</ClCompile>
<ClCompile Include="src\Input\KeyMapper.cpp">
<Filter>src\Input</Filter>
</ClCompile>
<ClCompile Include="src\App\App.cpp">
<Filter>src\App</Filter>
</ClCompile>
<ClCompile Include="src\App\Settings.cpp">
<Filter>src\App</Filter>
</ClCompile>
<ClCompile Include="src\App\Window.cpp">
<Filter>src\App</Filter>
</ClCompile>
<ClCompile Include="src\IO\Json.cpp">
<Filter>src\IO</Filter>
</ClCompile>
</ItemGroup>
</Project>

1
Verus/src/AI/AI.cpp Normal file
View File

@ -0,0 +1 @@
#include "verus.h"

4
Verus/src/AI/AI.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
#include "TaskDriver.h"
#include "Turret.h"

View File

@ -0,0 +1,72 @@
#include "verus.h"
using namespace verus;
using namespace verus::AI;
TaskDriver::TaskDriver()
{
}
TaskDriver::~TaskDriver()
{
}
void TaskDriver::Update()
{
VERUS_QREF_TIMER;
VERUS_QREF_UTILS;
if (_cooldownTimer > 0)
{
_cooldownTimer -= dt;
if (_cooldownTimer < 0)
_cooldownTimer = 0;
else
return;
}
RMode mode = _mapModes.find(_currentMode)->second;
VERUS_FOREACH(TMapTasks, mode._mapTasks, it)
{
RTask task = it->second;
task._time += dt;
if (task._time >= task._deadline)
{
if (utils.GetRandom().NextFloat() * 100 < task._chance)
{
if (_pDelegate)
_pDelegate->TaskDriver_OnTask(_C(task._name), _C(_currentMode));
_cooldownTimer = _cooldown;
}
task._deadline = task._intervalMin + task._intervalSize*utils.GetRandom().NextFloat();
task._time = 0;
}
}
}
void TaskDriver::AddMode(CSZ name)
{
if (_mapModes.find(name) != _mapModes.end())
return;
Mode mode;
mode._name = name;
_mapModes[name] = mode;
_currentMode = name;
}
void TaskDriver::AddTask(CSZ name, float chance, float intervalMin, float intervalMax, CSZ mode)
{
VERUS_QREF_UTILS;
RMode thisMode = _mapModes.find(mode ? mode : _currentMode)->second;
Task task;
task._name = name;
task._chance = chance;
task._intervalMin = intervalMin;
task._intervalSize = intervalMax - intervalMin;
task._deadline = task._intervalMin + task._intervalSize*utils.GetRandom().NextFloat();
thisMode._mapTasks[name] = task;
}

58
Verus/src/AI/TaskDriver.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
namespace verus
{
namespace AI
{
struct TaskDriverDelegate
{
virtual void TaskDriver_OnTask(CSZ task, CSZ mode) = 0;
};
VERUS_TYPEDEFS(TaskDriverDelegate);
class TaskDriver
{
struct Task
{
String _name;
float _chance = 100;
float _time = 0;
float _deadline = 0;
float _intervalMin = 0;
float _intervalSize = 0;
};
VERUS_TYPEDEFS(Task);
typedef Map<String, Task> TMapTasks;
struct Mode
{
String _name;
TMapTasks _mapTasks;
};
VERUS_TYPEDEFS(Mode);
typedef Map<String, Mode> TMapModes;
TMapModes _mapModes;
String _currentMode;
PTaskDriverDelegate _pDelegate = nullptr;
float _cooldown = 1;
float _cooldownTimer = 0;
public:
TaskDriver();
~TaskDriver();
void Update();
Str GetCurrentMode() const { return _C(_currentMode); }
void SetCurrentMode(CSZ name) { _currentMode = name; }
void SetDelegate(PTaskDriverDelegate p) { _pDelegate = p; }
void AddMode(CSZ name);
void AddTask(CSZ name, float chance, float intervalMin, float intervalMax, CSZ mode = nullptr);
};
VERUS_TYPEDEFS(TaskDriver);
}
}

27
Verus/src/AI/Turret.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "verus.h"
using namespace verus;
using namespace verus::AI;
void Turret::Update()
{
VERUS_QREF_TIMER;
float delta = _targetYaw - _actualYaw;
if (delta <= -VERUS_PI) delta += VERUS_2PI;
if (delta >= +VERUS_PI) delta -= VERUS_2PI;
if (delta < 0)
_actualYaw -= Math::Max(_yawSpeed*dt, -delta);
else
_actualYaw += Math::Min(_yawSpeed*dt, delta);
_actualYaw = Math::WrapAngle(_actualYaw);
}
void Turret::LookAt(RcVector3 rayFromTurret, bool instantly)
{
_targetYaw = Math::WrapAngle(atan2(
static_cast<float>(rayFromTurret.getX()),
static_cast<float>(rayFromTurret.getZ())));
if (instantly)
_actualYaw = _targetYaw;
}

34
Verus/src/AI/Turret.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
namespace verus
{
namespace AI
{
class Turret
{
float _targetPitch = 0;
float _targetYaw = 0;
float _actualPitch = 0;
float _actualYaw = 0;
float _pitchSpeed = 1;
float _yawSpeed = 1;
public:
void Update();
float GetTargetPitch() const { return _targetPitch; }
float GetTargetYaw() const { return _targetYaw; }
float GetActualPitch() const { return _actualPitch; }
float GetActualYaw() const { return _actualYaw; }
// Speed:
float GetPitchSpeed() const { return _pitchSpeed; }
float GetYawSpeed() const { return _yawSpeed; }
void SetPitchSpeed(float x) { _pitchSpeed = x; }
void SetYawSpeed(float x) { _yawSpeed = x; }
void LookAt(RcVector3 rayFromTurret, bool instantly = false);
};
VERUS_TYPEDEFS(Turret);
}
}

11
Verus/src/Anim/Anim.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "verus.h"
namespace verus
{
void Make_Anim()
{
}
void Free_Anim()
{
}
}

11
Verus/src/Anim/Anim.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "Motion.h"
#include "Skeleton.h"
#include "Animation.h"
namespace verus
{
void Make_Anim();
void Free_Anim();
}

View File

@ -0,0 +1,309 @@
#include "verus.h"
using namespace verus;
using namespace verus::Anim;
// Collection:
Collection::Collection()
{
}
Collection::~Collection()
{
DeleteAll();
}
void Collection::Async_Run(CSZ url, RcBlob blob)
{
IO::StreamPtr sp(blob);
CSZ niceName = strrchr(url, '/');
niceName = niceName ? niceName + 1 : url;
RMotionData md = _map[niceName];
md._motion.Init();
md._motion.Deserialize(sp);
if (md._duration)
md._motion.ComputePlaybackSpeed(md._duration);
}
void Collection::AddMotion(CSZ name, bool loop, float duration)
{
CSZ niceName = strrchr(name, '/');
niceName = niceName ? niceName + 1 : name;
RMotionData md = _map[niceName];
md._duration = duration;
md._loop = loop;
IO::Async::I().Load(name, this);
}
void Collection::DeleteAll()
{
IO::Async::Cancel(this);
_map.clear();
}
PMotionData Collection::Find(CSZ name)
{
return TStoreMotions::Find(name);
}
int Collection::GetMaxBones()
{
int num = 0;
VERUS_FOREACH(TStoreMotions::TMap, _map, it)
num = Math::Max(num, it->second._motion.GetNumBones());
return num;
}
// Animation:
Animation::Animation()
{
}
Animation::~Animation()
{
}
void Animation::Update(int numAlphaTracks, PAlphaTrack pAlphaTracks)
{
VERUS_QREF_TIMER;
// Async BindCollection():
if (_vTriggerStates.size() != _pCollection->GetMaxBones())
_vTriggerStates.resize(_pCollection->GetMaxBones());
// Async BindSkeleton():
if (!_blendMotion.GetNumBones() && _pSkeleton->GetNumBones())
_pSkeleton->InsertBonesIntoMotion(_blendMotion);
if (_playing)
{
if (_blending)
{
_blendTimer += dt;
if (_blendTimer >= _blendDuration)
_blending = false;
}
else if (!_currentMotion.empty())
{
RMotionData md = *_pCollection->Find(_C(_currentMotion));
const float len = md._motion.GetDuration();
if (_time < len + 0.5f)
{
_time += dt;
md._motion.ProcessTriggers(_time, this, GetTriggerStatesArray());
if (_time >= len)
{
if (_pDelegate)
_pDelegate->Animation_OnEnd(_C(_currentMotion));
_time = md._loop ? fmod(_time, len) : len + 1;
md._motion.ResetTriggers(GetTriggerStatesArray()); // New loop, reset triggers.
}
}
}
}
if (!_currentMotion.empty() && numAlphaTracks >= 0) // Alpha track (-1) should not modify the skeleton.
{
RMotionData md = *_pCollection->Find(_C(_currentMotion));
int numAlphaMotions = 0;
Skeleton::AlphaMotion alphaMotions[4];
for (int i = 0; i < numAlphaTracks && i < 4; ++i)
{
alphaMotions[i]._pMotion = pAlphaTracks[i]._pAnimation->GetMotion(); // Can be in blend state.
alphaMotions[i]._rootBone = pAlphaTracks[i]._rootBone;
alphaMotions[i]._alpha = pAlphaTracks[i]._pAnimation->GetAlpha();
alphaMotions[i]._time = pAlphaTracks[i]._pAnimation->GetTime();
numAlphaMotions++;
}
if (_blending)
{
md._motion.BindBlendMotion(&_blendMotion, _blendTimer / _blendDuration);
_pSkeleton->ApplyMotion(md._motion, _time, numAlphaMotions, alphaMotions);
}
else
{
#ifdef VERUS_COMPARE_MODE
_pSkeleton->ApplyMotion(md._motion, 0, numAlphaMotions, alphaMotions);
#else
_pSkeleton->ApplyMotion(md._motion, _time, numAlphaMotions, alphaMotions);
#endif
}
}
}
void Animation::BindCollection(PCollection p)
{
_pCollection = p;
}
void Animation::BindSkeleton(PSkeleton p)
{
_pSkeleton = p;
}
void Animation::SetCurrentMotion(CSZ name)
{
// Reset triggers:
if (!_currentMotion.empty())
_pCollection->Find(_C(_currentMotion))->_motion.ResetTriggers(GetTriggerStatesArray());
if (name)
{
_pCollection->Find(name)->_motion.ResetTriggers(GetTriggerStatesArray());
_currentMotion = name;
}
else
_currentMotion.clear();
}
void Animation::Play()
{
_playing = true;
}
void Animation::Stop()
{
_playing = false;
_time = 0;
}
void Animation::Pause()
{
_playing = false;
}
void Animation::BlendTo(CSZ name, Range<float> duration, int randTime, PMotion pMotionFrom)
{
VERUS_QREF_UTILS;
PMotion pMotion = pMotionFrom;
if (!_currentMotion.empty() || pMotionFrom)
{
if (!pMotionFrom)
pMotion = &_pCollection->Find(_C(_currentMotion))->_motion;
if (_blending) // Already blending?
pMotion->BindBlendMotion(&_blendMotion, _blendTimer / _blendDuration);
pMotion->BakeMotionAt(_time, _blendMotion); // Capture current pose.
pMotion->BindBlendMotion(nullptr, 0);
}
if ((0 == duration._max) || (_currentMotion.empty() && name && _prevMotion == name && _blendTimer / _blendDuration < 0.5f))
{
_blending = false; // Special case for alpha tracks.
}
else
{
_blending = true;
_blendDuration = (_currentMotion == (name ? name : "")) ? duration._min : duration._max;
_blendTimer = 0;
}
_prevMotion = _currentMotion;
_currentMotion = name ? name : "";
// Reset triggers:
if (pMotion)
pMotion->ResetTriggers(GetTriggerStatesArray());
if (name)
{
pMotion = &_pCollection->Find(name)->_motion;
pMotion->ResetTriggers(GetTriggerStatesArray());
}
// Reset time:
_time = (randTime >= 0 && pMotion) ? (randTime / 255.f)*pMotion->GetDuration() : 0;
if (_time)
pMotion->SkipTriggers(_time, GetTriggerStatesArray());
}
bool Animation::BlendToNew(std::initializer_list<CSZ> names, Range<float> duration, int randTime, PMotion pMotionFrom)
{
for (auto name : names)
{
if (_currentMotion == name)
return false;
}
BlendTo(*names.begin(), duration, randTime, pMotionFrom);
return true;
}
void Animation::Motion_OnTrigger(CSZ name, int state)
{
if (_pDelegate)
_pDelegate->Animation_OnTrigger(name, state);
}
PMotion Animation::GetMotion()
{
PMotion p = nullptr;
if (_currentMotion.empty())
{
if (!_prevMotion.empty())
p = &_pCollection->Find(_C(_prevMotion))->_motion;
}
else
{
p = &_pCollection->Find(_C(_currentMotion))->_motion;
}
if (p && _blending)
p->BindBlendMotion(&_blendMotion, _blendTimer / _blendDuration);
return p;
}
float Animation::GetAlpha(CSZ name) const
{
bool matchCurrentMotion = false;
bool matchPrevMotion = false;
if (name)
{
matchCurrentMotion = Str::StartsWith(_C(_currentMotion), name);
matchPrevMotion = Str::StartsWith(_C(_prevMotion), name);
}
const bool doBlend = name ? (matchCurrentMotion || matchPrevMotion) : true;
if (_blending && doBlend)
{
bool fadeIn = _prevMotion.empty() && !_currentMotion.empty();
bool fadeOut = !_prevMotion.empty() && _currentMotion.empty();
if (name)
{
fadeIn = !matchPrevMotion && matchCurrentMotion;
fadeOut = matchPrevMotion && !matchCurrentMotion;
}
if (fadeIn)
return Math::SmoothStep(0, 1, _blendTimer / _blendDuration);
if (fadeOut)
return Math::SmoothStep(0, 1, 1 - _blendTimer / _blendDuration);
}
if (name)
return matchCurrentMotion ? 1.f : 0.f;
else
return _currentMotion.empty() ? 0.f : 1.f;
}
float Animation::GetTime()
{
if (_currentMotion.empty())
{
if (_prevMotion.empty())
return _time;
else // When alpha goes to zero, use last motion frame:
return _pCollection->Find(_C(_prevMotion))->_motion.GetDuration();
}
else
{
return _time;
}
}
bool Animation::IsNearEdge(float t, Edge edge)
{
PMotion pMotion = GetMotion();
if (!pMotion)
return false;
const float at = _time / pMotion->GetDuration();
return ((edge&Edge::begin) && at < t) || ((edge&Edge::end) && at >= 1 - t);
}

109
Verus/src/Anim/Animation.h Normal file
View File

@ -0,0 +1,109 @@
#pragma once
namespace verus
{
namespace Anim
{
struct AnimationDelegate
{
virtual void Animation_OnEnd(CSZ name) {}
virtual void Animation_OnTrigger(CSZ name, int state) {}
};
VERUS_TYPEDEFS(AnimationDelegate);
//! Objects of this type are stored in Collection.
struct MotionData
{
Motion _motion;
float _duration = 0;
bool _loop = true;
};
VERUS_TYPEDEFS(MotionData);
typedef StoreUnique<String, MotionData> TStoreMotions;
//! The collection of motion objects (Motion) that can be reused by multiple animation objects (Animation).
class Collection : private TStoreMotions, public IO::AsyncCallback
{
public:
Collection();
~Collection();
virtual void Async_Run(CSZ url, RcBlob blob) override;
void AddMotion(CSZ name, bool loop = true, float duration = 0);
void DeleteAll();
PMotionData Find(CSZ name);
int GetMaxBones();
};
VERUS_TYPEDEFS(Collection);
//! Holds the collection (Collection) of motion objects (Motion) and provides the ability to interpolate between them.
//! Note: triggers will work properly with 'multiple animations' + 'single
//! collection' only if you add motions before binding collection.
//!
class Animation : public MotionDelegate
{
public:
enum class Edge : int
{
begin = (1 << 0),
end = (1 << 1)
};
struct AlphaTrack
{
Animation* _pAnimation = nullptr;
CSZ _rootBone = nullptr;
};
VERUS_TYPEDEFS(AlphaTrack);
private:
PCollection _pCollection = nullptr;
PAnimationDelegate _pDelegate = nullptr;
PSkeleton _pSkeleton = nullptr;
Motion _blendMotion;
String _currentMotion;
String _prevMotion;
Vector<int> _vTriggerStates;
float _time = 0;
float _blendDuration = 0;
float _blendTimer = 0;
bool _blending = false;
bool _playing = false;
public:
Animation();
~Animation();
void Update(int numAlphaTracks = 0, PAlphaTrack pAlphaTracks = nullptr);
void BindCollection(PCollection p);
void BindSkeleton(PSkeleton p);
void SetCurrentMotion(CSZ name);
PAnimationDelegate SetDelegate(PAnimationDelegate p) { return Utils::Swap(_pDelegate, p); }
void Play();
void Stop();
void Pause();
Str GetCurrentMotionName() const { return _C(_currentMotion); }
void BlendTo(CSZ name,
Range<float> duration = 0.5f, int randTime = -1, PMotion pMotionFrom = nullptr);
bool BlendToNew(std::initializer_list<CSZ> names,
Range<float> duration = 0.5f, int randTime = -1, PMotion pMotionFrom = nullptr);
bool IsBlending() const { return _blending; }
virtual void Motion_OnTrigger(CSZ name, int state) override;
PMotion GetMotion();
float GetAlpha(CSZ name = nullptr) const;
float GetTime();
bool IsNearEdge(float t = 0.1f, Edge edge = Edge::begin | Edge::end);
int* GetTriggerStatesArray() { return _vTriggerStates.empty() ? nullptr : _vTriggerStates.data(); }
};
VERUS_TYPEDEFS(Animation);
}
}

972
Verus/src/Anim/Motion.cpp Normal file
View File

@ -0,0 +1,972 @@
#include "verus.h"
using namespace verus;
using namespace verus::Anim;
// Motion::Bone::Rotation:
Motion::Bone::Rotation::Rotation()
{
}
Motion::Bone::Rotation::Rotation(RcQuat q)
{
_q = q;
}
Motion::Bone::Rotation::Rotation(RcVector3 euler)
{
euler.EulerToQuaternion(_q);
}
// Motion::Bone:
Motion::Bone::Bone(PMotion pMotion) :
_pMotion(pMotion)
{
}
Motion::Bone::~Bone()
{
DeleteAll();
}
void Motion::Bone::DeleteAll()
{
_mapRot.clear();
_mapPos.clear();
_mapScale.clear();
_mapTrigger.clear();
}
// Insert:
void Motion::Bone::InsertKeyframeRotation(int frame, RcQuat q)
{
_mapRot[frame] = Rotation(q);
}
void Motion::Bone::InsertKeyframeRotation(int frame, RcVector3 euler)
{
_mapRot[frame] = Rotation(euler);
}
void Motion::Bone::InsertKeyframePosition(int frame, RcVector3 pos)
{
_mapPos[frame] = pos;
}
void Motion::Bone::InsertKeyframeScale(int frame, RcVector3 scale)
{
_mapScale[frame] = scale;
}
void Motion::Bone::InsertKeyframeTrigger(int frame, int state)
{
_mapTrigger[frame] = state;
}
// Delete:
void Motion::Bone::DeleteKeyframeRotation(int frame)
{
VERUS_IF_FOUND_IN(TMapRot, _mapRot, frame, it)
_mapRot.erase(it);
}
void Motion::Bone::DeleteKeyframePosition(int frame)
{
VERUS_IF_FOUND_IN(TMapPos, _mapPos, frame, it)
_mapPos.erase(it);
}
void Motion::Bone::DeleteKeyframeScale(int frame)
{
VERUS_IF_FOUND_IN(TMapScale, _mapScale, frame, it)
_mapScale.erase(it);
}
void Motion::Bone::DeleteKeyframeTrigger(int frame)
{
VERUS_IF_FOUND_IN(TMapTrigger, _mapTrigger, frame, it)
_mapTrigger.erase(it);
}
// Find:
bool Motion::Bone::FindKeyframeRotation(int frame, RVector3 euler, RQuat q) const
{
euler = Vector3(0);
q = Quat::identity();
VERUS_IF_FOUND_IN(TMapRot, _mapRot, frame, it)
{
euler.EulerFromQuaternion(it->second._q);
q = it->second._q;
return true;
}
return false;
}
bool Motion::Bone::FindKeyframePosition(int frame, RVector3 pos) const
{
pos = Vector3(0);
VERUS_IF_FOUND_IN(TMapPos, _mapPos, frame, it)
{
pos = it->second;
return true;
}
return false;
}
bool Motion::Bone::FindKeyframeScale(int frame, RVector3 scale) const
{
scale = Vector3(1, 1, 1);
VERUS_IF_FOUND_IN(TMapScale, _mapScale, frame, it)
{
scale = it->second;
return true;
}
return false;
}
bool Motion::Bone::FindKeyframeTrigger(int frame, int& state) const
{
state = 0;
VERUS_IF_FOUND_IN(TMapTrigger, _mapTrigger, frame, it)
{
state = it->second;
return true;
}
return false;
}
void Motion::Bone::ComputeRotationAt(float time, RVector3 euler, RQuat q) const
{
Rotation prev, next, null(Quat(0));
const float alpha = GetAlpha(_mapRot, prev, next, null, time);
q = VMath::slerp(alpha, prev._q, next._q);
PMotion pBlendMotion = _pMotion->GetBlendMotion();
if (pBlendMotion)
{
PBone pBone = pBlendMotion->FindBone(_C(_name));
if (pBone)
{
Vector3 eulerBlend;
Quat qBlend;
if (pBone->FindKeyframeRotation(0, eulerBlend, qBlend))
q = VMath::slerp(_pMotion->GetBlendAlpha(), qBlend, q);
}
}
euler.EulerFromQuaternion(q);
}
void Motion::Bone::ComputePositionAt(float time, RVector3 pos) const
{
Vector3 prev, next, null(0);
const float alpha = GetAlpha(_mapPos, prev, next, null, time);
pos = VMath::lerp(alpha, prev, next);
PMotion pBlendMotion = _pMotion->GetBlendMotion();
if (pBlendMotion)
{
PBone pBone = pBlendMotion->FindBone(_C(_name));
if (pBone)
{
Vector3 posBlend;
if (pBone->FindKeyframePosition(0, posBlend))
pos = VMath::lerp(_pMotion->GetBlendAlpha(), posBlend, pos);
}
}
}
void Motion::Bone::ComputeScaleAt(float time, RVector3 scale) const
{
Vector3 prev, next, null(1, 1, 1);
const float alpha = GetAlpha(_mapScale, prev, next, null, time);
scale = VMath::lerp(alpha, prev, next);
PMotion pBlendMotion = _pMotion->GetBlendMotion();
if (pBlendMotion)
{
PBone pBone = pBlendMotion->FindBone(_C(_name));
if (pBone)
{
Vector3 scaleBlend;
if (pBone->FindKeyframeScale(0, scaleBlend))
scale = VMath::lerp(_pMotion->GetBlendAlpha(), scaleBlend, scale);
}
}
}
void Motion::Bone::ComputeTriggerAt(float time, int& state) const
{
if (_mapTrigger.empty())
{
state = 0;
return;
}
const int frame = int(_pMotion->GetFps()*time);
TMapTrigger::const_iterator it = _mapTrigger.upper_bound(frame); // Find frame after 'time'.
if (it != _mapTrigger.begin())
{
it--;
state = it->second;
}
else // All keyframes are after 'time':
{
state = 0;
}
}
void Motion::Bone::ComputeMatrixAt(float time, RTransform3 mat)
{
Quat q;
Vector3 scale, euler, pos;
ComputeRotationAt(time, euler, q);
ComputePositionAt(time, pos);
ComputeScaleAt(time, scale);
mat = VMath::appendScale(Transform3(q, pos), scale);
}
void Motion::Bone::MoveKeyframe(int direction, Type type, int frame)
{
const int frameDest = (direction >= 0) ? frame + 1 : frame - 1;
if (frameDest < 0 || frameDest >= _pMotion->GetNumFrames())
return;
switch (type)
{
case Type::rotation:
{
VERUS_IF_FOUND_IN(TMapRot, _mapRot, frame, it)
{
if (_mapRot.find(frameDest) == _mapRot.end())
{
_mapRot[frameDest] = it->second;
_mapRot.erase(it);
}
}
}
break;
case Type::position:
{
VERUS_IF_FOUND_IN(TMapPos, _mapPos, frame, it)
{
if (_mapPos.find(frameDest) == _mapPos.end())
{
_mapPos[frameDest] = it->second;
_mapPos.erase(it);
}
}
}
break;
case Type::scale:
{
VERUS_IF_FOUND_IN(TMapScale, _mapScale, frame, it)
{
if (_mapScale.find(frameDest) == _mapScale.end())
{
_mapScale[frameDest] = it->second;
_mapScale.erase(it);
}
}
}
break;
case Type::trigger:
{
VERUS_IF_FOUND_IN(TMapTrigger, _mapTrigger, frame, it)
{
if (_mapTrigger.find(frameDest) == _mapTrigger.end())
{
_mapTrigger[frameDest] = it->second;
_mapTrigger.erase(it);
}
}
}
break;
}
}
void Motion::Bone::Serialize(IO::RStream stream)
{
const int numKeyframesRot = Utils::Cast32(_mapRot.size());
const int numKeyframesPos = Utils::Cast32(_mapPos.size());
const int numKeyframesScale = Utils::Cast32(_mapScale.size());
const int numKeyframesTrigger = Utils::Cast32(_mapTrigger.size());
stream << numKeyframesRot;
VERUS_FOREACH_CONST(TMapRot, _mapRot, it)
{
stream << it->first;
stream.Write(&it->second._q, 16);
}
stream << numKeyframesPos;
VERUS_FOREACH_CONST(TMapPos, _mapPos, it)
{
stream << it->first;
stream.Write(&it->second, 12);
}
stream << numKeyframesScale;
VERUS_FOREACH_CONST(TMapScale, _mapScale, it)
{
stream << it->first;
stream.Write(&it->second, 12);
}
stream << numKeyframesTrigger;
VERUS_FOREACH_CONST(TMapTrigger, _mapTrigger, it)
{
stream << it->first;
stream << it->second;
}
}
void Motion::Bone::Deserialize(IO::RStream stream)
{
int numKeyframesRot, numKeyframesPos, numKeyframesScale, numKeyframesTrigger, frame, state;
Vector3 temp;
Quat q;
stream >> numKeyframesRot;
VERUS_FOR(i, numKeyframesRot)
{
stream >> frame;
stream.Read(&q, 16);
InsertKeyframeRotation(frame, q);
}
stream >> numKeyframesPos;
VERUS_FOR(i, numKeyframesPos)
{
stream >> frame;
stream.Read(&temp, 12);
InsertKeyframePosition(frame, temp);
}
stream >> numKeyframesScale;
VERUS_FOR(i, numKeyframesScale)
{
stream >> frame;
stream.Read(&temp, 12);
InsertKeyframeScale(frame, temp);
}
stream >> numKeyframesTrigger;
VERUS_FOR(i, numKeyframesTrigger)
{
stream >> frame;
stream >> state;
InsertKeyframeTrigger(frame, state);
}
}
void Motion::Bone::DeleteRedundantKeyframes()
{
if (2 == _mapRot.size())
{
if (!memcmp(
&_mapRot.begin()->second,
&_mapRot.rbegin()->second,
16))
_mapRot.erase(--_mapRot.end());
}
if (1 == _mapRot.size())
{
RQuat q = _mapRot.begin()->second._q;
if (q.IsIdentity())
_mapRot.clear();
}
if (2 == _mapPos.size())
{
if (!memcmp(
&_mapPos.begin()->second,
&_mapPos.rbegin()->second,
12))
_mapPos.erase(--_mapPos.end());
}
if (2 == _mapScale.size())
{
if (!memcmp(
&_mapScale.begin()->second,
&_mapScale.rbegin()->second,
12))
_mapScale.erase(--_mapScale.end());
}
}
void Motion::Bone::DeleteOddKeyframes()
{
{
TMapRot::iterator it = _mapRot.begin();
while (it != _mapRot.end())
{
if (it->first & 0x1)
_mapRot.erase(it++);
else
++it;
}
}
{
TMapPos::iterator it = _mapPos.begin();
while (it != _mapPos.end())
{
if (it->first & 0x1)
_mapPos.erase(it++);
else
++it;
}
}
{
TMapScale::iterator it = _mapScale.begin();
while (it != _mapScale.end())
{
if (it->first & 0x1)
_mapScale.erase(it++);
else
++it;
}
}
}
void Motion::Bone::InsertLoopKeyframes()
{
if (!_mapRot.empty())
_mapRot[_pMotion->GetNumFrames()] = _mapRot.begin()->second;
if (!_mapPos.empty())
_mapPos[_pMotion->GetNumFrames()] = _mapPos.begin()->second;
if (!_mapScale.empty())
_mapScale[_pMotion->GetNumFrames()] = _mapScale.begin()->second;
}
void Motion::Bone::Cut(int frame, bool before)
{
if (before && !frame)
return;
{
TMapRot::iterator it = _mapRot.begin();
while (it != _mapRot.end())
{
if (before)
{
if (it->first >= frame)
_mapRot[it->first - frame] = it->second;
_mapRot.erase(it++);
}
else
{
if (it->first > frame)
_mapRot.erase(it++);
else
++it;
}
}
}
{
TMapPos::iterator it = _mapPos.begin();
while (it != _mapPos.end())
{
if (before)
{
if (it->first >= frame)
_mapPos[it->first - frame] = it->second;
_mapPos.erase(it++);
}
else
{
if (it->first > frame)
_mapPos.erase(it++);
else
++it;
}
}
}
{
TMapScale::iterator it = _mapScale.begin();
while (it != _mapScale.end())
{
if (before)
{
if (it->first >= frame)
_mapScale[it->first - frame] = it->second;
_mapScale.erase(it++);
}
else
{
if (it->first > frame)
_mapScale.erase(it++);
else
++it;
}
}
}
}
void Motion::Bone::Fix(bool speedLimit)
{
const float e = 0.02f;
// Remove rotation keyframes:
if (true)
{
Quat qBase(0);
TMapRot::iterator it = _mapRot.begin();
bool hasBroken = false;
while (it != _mapRot.end())
{
RcQuat q = it->second._q;
const bool broken =
Math::IsNaN(q.getX()) ||
Math::IsNaN(q.getY()) ||
Math::IsNaN(q.getZ()) ||
Math::IsNaN(q.getW());
if (broken)
hasBroken = true;
const bool same = qBase.IsEqual(q, e);
if (same || broken)
_mapRot.erase(it++);
else
{
qBase = q;
++it;
}
}
}
// Remove position keyframes:
if (true)
{
Vector3 base(0);
TMapPos::iterator it = _mapPos.begin();
while (it != _mapPos.end())
{
RcVector3 pos = it->second;
const bool broken =
Math::IsNaN(pos.getX()) ||
Math::IsNaN(pos.getY()) ||
Math::IsNaN(pos.getZ());
const bool same = base.IsEqual(pos, e);
if (same || broken)
_mapPos.erase(it++);
else
{
base = pos;
++it;
}
}
}
// Limit rotation speed:
if (speedLimit && Skeleton::IsKinectBone(_C(_name)))
{
VERUS_FOREACH(TMapRot, _mapRot, it)
{
RQuat q = it->second._q;
if (it->first >= 1)
{
Quat qPrev;
Vector3 euler;
ComputeRotationAt((it->first - 1)*_pMotion->GetFpsInv(), euler, qPrev);
const float threshold = 0.5f;
const Quat qPrevInv = VMath::inverse(Matrix3(qPrev));
const Quat qD = q * qPrevInv;
const float a = abs(glm::angle(qD.GLM()));
if (a > threshold)
{
const float back = Math::Clamp((a - threshold) / threshold, 0.f, 0.75f);
q = VMath::slerp(back, q, qPrev);
}
}
}
}
}
void Motion::Bone::ApplyScaleBias(RcVector3 scale, RcVector3 bias)
{
VERUS_FOREACH(TMapPos, _mapPos, it)
it->second = VMath::mulPerElem(it->second, scale) + bias;
}
void Motion::Bone::Scatter(int srcFrom, int srcTo, int dMin, int dMax)
{
VERUS_QREF_UTILS;
int start = srcFrom;
const int range = dMax - dMin;
while (true)
{
start += dMin + utils.GetRandom().Next() % range;
if (start >= _pMotion->GetNumFrames())
break;
for (int i = srcFrom; i < srcTo; ++i)
{
Quat q;
Vector3 euler, pos;
if (FindKeyframeRotation(i, euler, q))
InsertKeyframeRotation(i + start, q);
if (FindKeyframePosition(i, pos))
InsertKeyframePosition(i + start, pos);
}
}
}
int Motion::Bone::GetLastKeyframe() const
{
int frame = 0;
if (!_mapRot.empty())
frame = Math::Max(frame, _mapRot.rbegin()->first);
if (!_mapPos.empty())
frame = Math::Max(frame, _mapPos.rbegin()->first);
if (!_mapScale.empty())
frame = Math::Max(frame, _mapScale.rbegin()->first);
if (!_mapTrigger.empty())
frame = Math::Max(frame, _mapTrigger.rbegin()->first);
return frame;
}
// Motion:
Motion::Motion()
{
}
Motion::~Motion()
{
Done();
}
void Motion::Init()
{
VERUS_INIT();
}
void Motion::Done()
{
DeleteAllBones();
VERUS_DONE(Motion);
}
Motion::PBone Motion::GetBoneByIndex(int index)
{
int i = 0;
for (auto& kv : _mapBones)
{
if (i == index)
return &kv.second;
i++;
}
return nullptr;
}
int Motion::GetBoneIndex(CSZ name) const
{
int i = 0;
VERUS_FOREACH_CONST(TMapBones, _mapBones, it)
{
if (it->first == name)
return i;
i++;
}
return -1;
}
Motion::PBone Motion::InsertBone(CSZ name)
{
PBone pBone = FindBone(name);
if (pBone)
return pBone;
Bone bone(this);
bone.Rename(name);
_mapBones[name] = bone;
return &_mapBones[name];
}
void Motion::DeleteBone(CSZ name)
{
VERUS_IF_FOUND_IN(TMapBones, _mapBones, name, it)
_mapBones.erase(it);
}
void Motion::DeleteAllBones()
{
_mapBones.clear();
}
Motion::PBone Motion::FindBone(CSZ name)
{
VERUS_IF_FOUND_IN(TMapBones, _mapBones, name, it)
return &it->second;
return nullptr;
}
void Motion::Serialize(IO::RStream stream)
{
const UINT32 magic = '2NAX';
stream << magic;
const UINT16 version = xanVersion;
stream << version;
stream << _numFrames;
stream << _fps;
stream << GetNumBones();
for (auto& kv : _mapBones)
{
RBone bone = kv.second;
stream.WriteString(_C(bone.GetName()));
bone.Serialize(stream);
}
}
void Motion::Deserialize(IO::RStream stream)
{
UINT32 magic = 0;
stream >> magic;
if ('2NAX' != magic)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid XAN format";
UINT16 version = 0;
stream >> version;
if (xanVersion != version)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid XAN version";
stream >> _numFrames;
stream >> _fps;
if (_numFrames < 0 || _numFrames > maxNumFrames)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid number of frames in XAN";
if (_fps <= 0 || _fps > maxFps)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid FPS in XAN";
SetFps(_fps);
int numBones = 0;
stream >> numBones;
if (numBones < 0 || numBones > maxNumBones)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid number of bones in XAN";
char buffer[IO::Stream::bufferSize] = {};
VERUS_FOR(i, numBones)
{
stream.ReadString(buffer);
PBone pBone = InsertBone(buffer);
pBone->Deserialize(stream);
}
}
void Motion::BakeMotionAt(float time, Motion& dest) const
{
float nativeTime = time * _playbackSpeed;
if (_reversed)
nativeTime = GetNativeDuration() - nativeTime;
VERUS_FOREACH_CONST(TMapBones, _mapBones, it)
{
PcBone pBone = &it->second;
PBone pBoneDest = dest.FindBone(_C(it->first));
if (pBoneDest)
{
Vector3 rot, pos, scale;
Quat q;
pBone->ComputeRotationAt(nativeTime, rot, q);
pBone->ComputePositionAt(nativeTime, pos);
pBone->ComputeScaleAt(nativeTime, scale);
pBoneDest->InsertKeyframeRotation(0, q);
pBoneDest->InsertKeyframePosition(0, pos);
pBoneDest->InsertKeyframeScale(0, scale);
}
}
}
void Motion::BindBlendMotion(PMotion p, float alpha)
{
_pBlendMotion = p;
_blendAlpha = alpha;
}
void Motion::DeleteRedundantKeyframes()
{
for (auto& kv : _mapBones)
kv.second.DeleteRedundantKeyframes();
}
void Motion::DeleteOddKeyframes()
{
for (auto& kv : _mapBones)
kv.second.DeleteOddKeyframes();
}
void Motion::InsertLoopKeyframes()
{
for (auto& kv : _mapBones)
kv.second.InsertLoopKeyframes();
}
void Motion::Cut(int frame, bool before)
{
for (auto& kv : _mapBones)
kv.second.Cut(frame, before);
_numFrames = before ? _numFrames - frame : frame + 1;
}
void Motion::Fix(bool speedLimit)
{
for (auto& kv : _mapBones)
kv.second.Fix(speedLimit);
}
void Motion::ProcessTriggers(float time, PMotionDelegate p, int* pUserTriggerStates)
{
VERUS_RT_ASSERT(p);
float nativeTime = time * _playbackSpeed;
if (_reversed)
nativeTime = GetNativeDuration() - nativeTime;
int i = 0;
for (auto& kv : _mapBones)
{
PBone pBone = &kv.second;
int state = 0;
if (!(_reversed && nativeTime < _fpsInv*0.5f)) // Avoid edge case for the first frame in reverse.
pBone->ComputeTriggerAt(nativeTime, state);
const int last = pUserTriggerStates ? pUserTriggerStates[i] : pBone->GetLastTriggerState();
if (state != last)
{
p->Motion_OnTrigger(_C(pBone->GetName()), state);
if (pUserTriggerStates)
pUserTriggerStates[i] = state;
else
pBone->SetLastTriggerState(state);
}
i++;
}
}
void Motion::ResetTriggers(int* pUserTriggerStates)
{
int i = 0;
for (auto& kv : _mapBones)
{
PBone pBone = &kv.second;
int state = 0;
if (_reversed)
pBone->ComputeTriggerAt(GetNativeDuration(), state);
if (pUserTriggerStates)
pUserTriggerStates[i] = state;
else
pBone->SetLastTriggerState(state);
i++;
}
}
void Motion::SkipTriggers(float time, int* pUserTriggerStates)
{
float nativeTime = time * _playbackSpeed;
if (_reversed)
nativeTime = GetNativeDuration() - nativeTime;
int i = 0;
for (auto& kv : _mapBones)
{
PBone pBone = &kv.second;
int state;
pBone->ComputeTriggerAt(nativeTime, state);
if (pUserTriggerStates)
pUserTriggerStates[i] = state;
else
pBone->SetLastTriggerState(state);
i++;
}
}
void Motion::ApplyScaleBias(CSZ name, RcVector3 scale, RcVector3 bias)
{
PBone pBone = FindBone(name);
if (pBone)
pBone->ApplyScaleBias(scale, bias);
}
void Motion::SetPlaybackSpeed(float x)
{
VERUS_RT_ASSERT(x != 0);
_playbackSpeed = x;
_reversed = x < 0;
if (_reversed)
_playbackSpeed = -_playbackSpeed;
_playbackSpeedInv = 1 / _playbackSpeed;
}
void Motion::ComputePlaybackSpeed(float duration)
{
VERUS_RT_ASSERT(duration != 0);
_playbackSpeed = GetNativeDuration() / duration;
_reversed = duration < 0;
if (_reversed)
_playbackSpeed = -_playbackSpeed;
_playbackSpeedInv = 1 / _playbackSpeed;
}
void Motion::Exec(CSZ code)
{
if (Str::StartsWith(code, "copy "))
{
char boneSrc[80] = {};
char boneDst[80] = {};
sscanf(code, "%*s %s %s", boneSrc, boneDst);
PBone pSrc = FindBone(boneSrc);
PBone pDst = FindBone(boneDst);
pDst->_mapRot = pSrc->_mapRot;
pDst->_mapPos = pSrc->_mapPos;
}
if (Str::StartsWith(code, "scatter "))
{
int srcFrom = 0, srcTo = 0;
int dMin = 0, dMax = 0;
char bone[80] = {};
sscanf(code, "%*s %d %d %d %d %s", &srcFrom, &srcTo, &dMin, &dMax, bone);
const int srcSize = srcTo - srcFrom;
if (dMin < srcSize)
{
const int d = srcSize - dMin;
dMin += d;
dMax += d;
}
PBone p = FindBone(bone + 5);
if (p)
p->Scatter(srcFrom, srcTo, dMin, dMax);
}
if (Str::StartsWith(code, "delete "))
{
char what[80] = {};
char name[80] = {};
sscanf(code, "%*s %s %s", what, name);
if (strlen(name) > 5)
{
PBone p = FindBone(name + 5);
if (p)
{
if (!strcmp(what, "rot"))
p->_mapRot.clear();
if (!strcmp(what, "pos"))
p->_mapPos.clear();
if (!strcmp(what, "scale"))
p->_mapScale.clear();
}
}
else
{
for (auto& bone : _mapBones)
{
if (!strcmp(what, "rot"))
bone.second._mapRot.clear();
if (!strcmp(what, "pos"))
bone.second._mapPos.clear();
if (!strcmp(what, "scale"))
bone.second._mapScale.clear();
}
}
}
}
int Motion::GetLastKeyframe() const
{
int frame = 0;
VERUS_FOREACH_CONST(TMapBones, _mapBones, it)
frame = Math::Max(frame, it->second.GetLastKeyframe());
return frame;
}

237
Verus/src/Anim/Motion.h Normal file
View File

@ -0,0 +1,237 @@
#pragma once
namespace verus
{
namespace Anim
{
struct MotionDelegate
{
virtual void Motion_OnTrigger(CSZ name, int state) = 0;
};
VERUS_TYPEDEFS(MotionDelegate);
//! Motion holds a series of keyframes and provides the ability to interpolate between them.
//! Motion can be stored in XAN format. Motion's rate can be
//! scaled and even reversed. Animation object (Animation) can be used to
//! handle multiple motion objects.
//!
class Motion : public Object
{
public:
class Bone : public AllocatorAware
{
friend class Motion;
class Rotation
{
public:
Quat _q;
Rotation();
Rotation(RcQuat q);
Rotation(RcVector3 euler);
};
VERUS_TYPEDEFS(Rotation);
typedef Map<int, Rotation> TMapRot;
typedef Map<int, Vector3> TMapPos;
typedef Map<int, Vector3> TMapScale;
typedef Map<int, int> TMapTrigger;
String _name;
Motion* _pMotion = nullptr;
TMapRot _mapRot; //!< Rotation keyframes.
TMapPos _mapPos; //!< Position keyframes.
TMapScale _mapScale; //!< Scaling keyframes.
TMapTrigger _mapTrigger; //!< Trigger keyframes.
int _lastTriggerState = 0;
template<typename TMap, typename T>
float GetAlpha(const TMap& m, T& prev, T& next, const T& null, float time) const
{
if (m.empty()) // No frames at all, so return null.
{
prev = null;
next = null;
return 0;
}
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'.
if (it != m.end()) // There are frames greater (after 'time'):
{
if (it != m.begin()) // And there are less than (before 'time'), full interpolation:
{
typename TMap::const_iterator itPrev = it;
itPrev--;
const float prevTime = itPrev->first*_pMotion->GetFpsInv();
const float nextTime = it->first*_pMotion->GetFpsInv();
const float delta = nextTime - prevTime;
const float offset = nextTime - time;
alpha = 1 - offset / delta;
prev = itPrev->second;
next = it->second;
}
else // But there are no less than:
{
const float nextTime = it->first*_pMotion->GetFpsInv();
const float delta = nextTime;
const float offset = time;
alpha = offset / delta;
prev = null;
next = it->second;
}
}
else // There are no frames greater, but there are less than:
{
it--;
alpha = 0;
prev = it->second;
next = null;
}
return alpha;
}
public:
enum class Type : int
{
rotation,
position,
scale,
trigger
};
Bone(Motion* pMotion = nullptr);
~Bone();
Str GetName() const { return _C(_name); }
void Rename(CSZ name) { _name = name; }
int GetLastTriggerState() const { return _lastTriggerState; }
void SetLastTriggerState(int state) { _lastTriggerState = state; }
void DeleteAll();
void InsertKeyframeRotation(int frame, RcQuat q);
void InsertKeyframeRotation(int frame, RcVector3 euler);
void InsertKeyframePosition(int frame, RcVector3 pos);
void InsertKeyframeScale(int frame, RcVector3 scale);
void InsertKeyframeTrigger(int frame, int state);
void DeleteKeyframeRotation(int frame);
void DeleteKeyframePosition(int frame);
void DeleteKeyframeScale(int frame);
void DeleteKeyframeTrigger(int frame);
bool FindKeyframeRotation(int frame, RVector3 euler, RQuat q) const;
bool FindKeyframePosition(int frame, RVector3 pos) const;
bool FindKeyframeScale(int frame, RVector3 scale) const;
bool FindKeyframeTrigger(int frame, int& state) const;
void ComputeRotationAt(float time, RVector3 euler, RQuat q) const;
void ComputePositionAt(float time, RVector3 pos) const;
void ComputeScaleAt(float time, RVector3 scale) const;
void ComputeTriggerAt(float time, int& state) const;
void ComputeMatrixAt(float time, RTransform3 mat);
void MoveKeyframe(int direction, Type type, int frame);
int GetNumKeysRotation() const { return Utils::Cast32(_mapRot.size()); }
int GetNumKeysPosition() const { return Utils::Cast32(_mapPos.size()); }
int GetNumKeysScale() const { return Utils::Cast32(_mapScale.size()); }
int GetNumKeysTrigger() const { return Utils::Cast32(_mapTrigger.size()); }
VERUS_P(void Serialize(IO::RStream stream));
VERUS_P(void Deserialize(IO::RStream stream));
void DeleteRedundantKeyframes();
void DeleteOddKeyframes();
void InsertLoopKeyframes();
void Cut(int frame, bool before);
void Fix(bool speedLimit);
void ApplyScaleBias(RcVector3 scale, RcVector3 bias);
void Scatter(int srcFrom, int srcTo, int dMin, int dMax);
int GetLastKeyframe() const;
};
VERUS_TYPEDEFS(Bone);
private:
enum { xanVersion = 0x0101, maxFps = 10000, maxNumBones = 10000, maxNumFrames = 32 * 1024 * 1024 };
typedef Map<String, Bone> TMapBones;
TMapBones _mapBones;
Motion* _pBlendMotion = nullptr;
int _numFrames = 50;
int _fps = 10;
float _fpsInv = 0.1f;
float _blendAlpha = 0;
float _playbackSpeed = 1;
float _playbackSpeedInv = 1;
bool _reversed = false;
public:
Motion();
~Motion();
void Init();
void Done();
int GetFps() const { return _fps; }
float GetFpsInv() const { return _fpsInv; }
void SetFps(int fps) { _fps = fps; _fpsInv = 1.f / _fps; }
int GetNumFrames() const { return _numFrames; }
void SetNumFrames(int num) { _numFrames = num; }
int GetNumBones() const { return Utils::Cast32(_mapBones.size()); }
float GetDuration() const { return GetNativeDuration()*_playbackSpeedInv; }
float GetNativeDuration() const { return _numFrames * _fpsInv; }
PBone GetBoneByIndex(int index);
int GetBoneIndex(CSZ name) const;
PBone InsertBone(CSZ name);
void DeleteBone(CSZ name);
void DeleteAllBones();
PBone FindBone(CSZ name);
void Serialize(IO::RStream stream);
void Deserialize(IO::RStream stream);
void BakeMotionAt(float time, Motion& dest) const;
void BindBlendMotion(Motion* p, float alpha);
Motion* GetBlendMotion() const { return _pBlendMotion; }
float GetBlendAlpha() const { return _blendAlpha; }
void DeleteRedundantKeyframes();
void DeleteOddKeyframes();
void InsertLoopKeyframes();
void Cut(int frame, bool before = true);
void Fix(bool speedLimit);
// Triggers:
void ProcessTriggers(float time, PMotionDelegate p, int* pUserTriggerStates = nullptr);
void ResetTriggers(int* pUserTriggerStates = nullptr);
void SkipTriggers(float time, int* pUserTriggerStates = nullptr);
void ApplyScaleBias(CSZ name, RcVector3 scale, RcVector3 bias);
float GetPlaybackSpeed() const { return _playbackSpeed; }
float GetPlaybackSpeedInv() const { return _playbackSpeedInv; }
void SetPlaybackSpeed(float x);
void ComputePlaybackSpeed(float duration);
bool IsReversed() const { return _reversed; }
void Exec(CSZ code);
int GetLastKeyframe() const;
};
VERUS_TYPEDEFS(Motion);
}
}

1247
Verus/src/Anim/Skeleton.cpp Normal file

File diff suppressed because it is too large Load Diff

153
Verus/src/Anim/Skeleton.h Normal file
View File

@ -0,0 +1,153 @@
#pragma once
namespace verus
{
namespace Anim
{
//! Standard skeleton, which can be animated using motion object (Motion).
//! X3D format can support up to 256 bones, but the hardware has certain
//! limitations. With Shader Model 2.0 the shader can hold about 32 bone
//! matrices. Other bones must be remapped using Primary Bones concept.
//!
//! Alpha Motions (AlphaMotion) add the ability to mix multiple motions,
//! just like images are mixed with alpha channel. Alpha Motion affects
//! it's root bone and all descendants of that bone.
//!
//! A ragdoll can be created automatically or configured using XML .rig file.
//! Ragdoll's simulation can start from any motion frame and any simulated pose
//! can be baked back into motion object, allowing smooth transition to ragdoll
//! simulation and back to motion.
//!
class Skeleton : public Object
{
public:
struct AlphaMotion
{
PMotion _pMotion = nullptr;
CSZ _rootBone = nullptr;
float _alpha = 0;
float _time = 0;
};
VERUS_TYPEDEFS(AlphaMotion);
struct Bone : public AllocatorAware
{
Transform3 _matToBoneSpace = Transform3::identity();
Transform3 _matFromBoneSpace = Transform3::identity();
Transform3 _matFinal = Transform3::identity();
Transform3 _matFinalInv = Transform3::identity();
Transform3 _matExternal = Transform3::identity();
Transform3 _matAdapt = Transform3::identity();
Transform3 _matToActorSpace = Transform3::identity();
Vector3 _rigRot = Vector3(0); //!< Rotation angles of ragdoll's rigid component.
Vector3 _cRot = Vector3(0); //!< Constraint's rotation angles.
Vector3 _cLimits = Vector3(0); //!< Constraint's limits.
Vector3 _boxSize = Vector3(0); //!< For a box shape.
String _name;
String _parentName;
btCollisionShape* _pShape = nullptr;
btRigidBody* _pBody = nullptr;
btTypedConstraint* _pConstraint = nullptr;
float _width = 0;
float _length = 0;
float _mass = 0;
int _shaderIndex = 0; //!< Index of a matrix in the vertex shader.
bool _ready = false;
bool _rigBone = true;
bool _hinge = false; //!< btHingeConstraint vs btConeTwistConstraint.
bool _noCollision = false;
};
VERUS_TYPEDEFS(Bone);
private:
typedef Map<String, Bone> TMapBones;
typedef Map<int, int> TMapPrimary;
Transform3 _matParents = Transform3::identity();
Transform3 _matRagdollToWorld = Transform3::identity();
Transform3 _matRagdollToWorldInv = Transform3::identity();
TMapBones _mapBones;
TMapPrimary _mapPrimary;
PBone _pCurrentBone = nullptr;
PMotion _pCurrentMotion = nullptr;
PAlphaMotion _pAlphaMotions = nullptr;
float _currentTime = 0;
float _mass = 0;
int _numPrimaryBones = 0;
int _numAlphaMotions = 0;
bool _ragdollMode = false;
public:
Skeleton();
~Skeleton();
void operator=(const Skeleton& that);
void Init();
void Done();
void Draw(bool bindPose = true, int selected = -1);
static CSZ RootName() { return "$ROOT"; }
PBone InsertBone(RBone bone);
PBone FindBone(CSZ name);
PcBone FindBone(CSZ name) const;
//! Uses shader's array index to find a bone.
PBone FindBoneByIndex(int index);
//! Sets the current pose using motion object (Motion).
void ApplyMotion(RMotion motion, float time,
int numAlphaMotions = 0, PAlphaMotion pAlphaMotions = nullptr);
//! Fills the array of matrices that will be used by a shader.
void FillMatrixArray(mataff* p) const;
void ResetFinalPose();
VERUS_P(void ResetBones());
VERUS_P(void RecursiveBoneUpdate());
int GetNumBones() const { return _numPrimaryBones ? _numPrimaryBones : Utils::Cast32(_mapBones.size()); }
void VisitBones(std::function<Continue(RBone)> fn);
void VisitBones(std::function<Continue(RcBone)> fn) const;
//! Adds skeleton's bones to motion object (Motion).
void InsertBonesIntoMotion(RMotion motion) const;
//! Removes motion's bones, which are not skeleton's bones.
void DeleteOutsiders(RMotion motion) const;
void AdjustPrimaryBones(const Vector<String>& vPrimaryBones);
int RemapBoneIndex(int index) const;
bool IsParentOf(CSZ bone, CSZ parent) const;
void LoadRigInfo(CSZ url);
void LoadRigInfoFromPtr(const BYTE* p);
void BeginRagdoll(RcTransform3 matW, RcVector3 impulse = Vector3(0), CSZ bone = "Spine2");
void EndRagdoll();
bool IsRagdollMode() const { return _ragdollMode; }
RcTransform3 GetRagdollToWorldMatrix() { return _matRagdollToWorld; }
//! Saves the current pose into motion object (Motion) at some frame.
void BakeMotion(RMotion motion, int frame = 0, bool kinect = false);
void AdaptBindPoseOf(const Skeleton& that);
void SimpleIK(CSZ boneDriven, CSZ boneDriver, RcVector3 dirDriverSpace, RcVector3 dirDesiredMeshSpace, float limitDot, float alpha);
void ProcessKinectData(const BYTE* p, RMotion motion, int frame = 0);
void ProcessKinectJoint(const BYTE* p, CSZ name, RcVector3 skeletonPos);
void LoadKinectBindPose(CSZ xml);
static bool IsKinectBone(CSZ name);
static bool IsKinectLeafBone(CSZ name);
void FixateFeet(RMotion motion);
//! Tries to compute the highest speed at which a bone would move with this motion applied.
//! Can be used to sync animation and movement to fix the sliding feet problem.
Vector3 GetHighestSpeed(RMotion motion, CSZ name, RcVector3 scale = Vector3(1, 0, 1), bool positive = false);
};
VERUS_TYPEDEFS(Skeleton);
}
}

52
Verus/src/App/App.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "verus.h"
namespace verus
{
void Make_App()
{
}
void Free_App()
{
}
}
using namespace verus;
void App::RunEventLoop()
{
SDL_Event event = {};
bool done = false;
do
{
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
{
done = true;
}
break;
case SDL_WINDOWEVENT:
{
switch (event.window.event)
{
case SDL_WINDOWEVENT_MINIMIZED:
break;
case SDL_WINDOWEVENT_RESTORED:
break;
}
}
break;
case SDL_USEREVENT:
{
}
break;
}
}
if (done)
break;
} while (!done);
}

18
Verus/src/App/App.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "Settings.h"
#include "Window.h"
namespace verus
{
void Make_App();
void Free_App();
}
namespace verus
{
namespace App
{
void RunEventLoop();
}
}

272
Verus/src/App/Settings.cpp Normal file
View File

@ -0,0 +1,272 @@
#include "verus.h"
using namespace verus;
using namespace verus::App;
Settings::Settings()
{
VERUS_ZERO_MEM(_commandLine);
#ifdef _WIN32
if (0x419 == GetUserDefaultUILanguage())
_uiLang = "RU";
#endif
SetQuality(Quality::medium);
}
Settings::~Settings()
{
}
void Settings::LoadValidateSave()
{
Load();
Validate();
Save();
}
void Settings::Load()
{
Json::Load();
_quality = static_cast<Quality>(GetI("quality", +_quality));
_direct3D = GetI("direct3D", _direct3D);
_gpuAnisotropyLevel = GetI("gpuAnisotropyLevel", _gpuAnisotropyLevel);
_gpuAntialiasingLevel = GetI("gpuAntialiasingLevel", _gpuAntialiasingLevel);
_gpuDepthTexture = GetI("gpuDepthTexture", _gpuDepthTexture);
_gpuForcedProfile = GetS("gpuForcedProfile", _C(_gpuForcedProfile));
_gpuOffscreenRender = GetB("gpuOffscreenRender", _gpuOffscreenRender);
_gpuParallaxMapping = GetB("gpuParallaxMapping", _gpuParallaxMapping);
_gpuPerPixelLighting = GetB("gpuPerPixelLighting", _gpuPerPixelLighting);
_gpuTextureLodLevel = GetI("gpuTextureLodLevel", _gpuTextureLodLevel);
_gpuTrilinearFilter = GetB("gpuTrilinearFilter", _gpuTrilinearFilter);
_inputMouseSensitivity = GetF("inputMouseSensitivity", _inputMouseSensitivity);
_postProcessBloom = GetB("postProcessBloom", _postProcessBloom);
_postProcessCinema = GetB("postProcessCinema", _postProcessCinema);
_postProcessMotionBlur = GetB("postProcessMotionBlur", _postProcessMotionBlur);
_postProcessSSAO = GetB("postProcessSSAO", _postProcessSSAO);
_sceneGrassDensity = GetI("sceneGrassDensity", _sceneGrassDensity);
_sceneShadowQuality = static_cast<ShadowQuality>(GetI("sceneShadowQuality", +_sceneShadowQuality));
_sceneWaterQuality = static_cast<WaterQuality>(GetI("sceneWaterQuality", +_sceneWaterQuality));
_screenFOV = GetF("screenFOV", _screenFOV);
_screenSizeHeight = GetI("screenSizeHeight", _screenSizeHeight);
_screenSizeWidth = GetI("screenSizeWidth", _screenSizeWidth);
_screenVSync = GetB("screenVSync", _screenVSync);
_screenWindowed = GetB("screenWindowed", _screenWindowed);
_uiLang = GetS("uiLang", _C(_uiLang));
}
void Settings::Save()
{
Set("quality", +_quality);
Set("direct3D", _direct3D);
Set("gpuAnisotropyLevel", _gpuAnisotropyLevel);
Set("gpuAntialiasingLevel", _gpuAntialiasingLevel);
Set("gpuDepthTexture", _gpuDepthTexture);
Set("gpuForcedProfile", _C(_gpuForcedProfile));
Set("gpuOffscreenRender", _gpuOffscreenRender);
Set("gpuParallaxMapping", _gpuParallaxMapping);
Set("gpuPerPixelLighting", _gpuPerPixelLighting);
Set("gpuTextureLodLevel", _gpuTextureLodLevel);
Set("gpuTrilinearFilter", _gpuTrilinearFilter);
Set("inputMouseSensitivity", _inputMouseSensitivity);
Set("postProcessBloom", _postProcessBloom);
Set("postProcessCinema", _postProcessCinema);
Set("postProcessMotionBlur", _postProcessMotionBlur);
Set("postProcessSSAO", _postProcessSSAO);
Set("sceneGrassDensity", _sceneGrassDensity);
Set("sceneShadowQuality", +_sceneShadowQuality);
Set("sceneWaterQuality", +_sceneWaterQuality);
Set("screenFOV", _screenFOV);
Set("screenSizeHeight", _screenSizeHeight);
Set("screenSizeWidth", _screenSizeWidth);
Set("screenVSync", _screenVSync);
Set("screenWindowed", _screenWindowed);
Set("uiLang", _C(_uiLang));
Json::Save();
}
void Settings::Validate()
{
_quality = Math::Clamp(_quality, Quality::low, Quality::ultra);
_gpuAnisotropyLevel = Math::Clamp(_gpuAnisotropyLevel, 0, 16);
_gpuAntialiasingLevel = Math::Clamp(_gpuAntialiasingLevel, 0, 16);
_gpuTextureLodLevel = Math::Clamp(_gpuTextureLodLevel, 0, 4);
_screenFOV = Math::Clamp<float>(_screenFOV, 60, 90);
_screenSizeHeight = Math::Clamp(_screenSizeHeight, 270, 0x2000);
_screenSizeWidth = Math::Clamp(_screenSizeWidth, 480, 0x2000);
if (_gpuForcedProfile == "sm_2_0")
{
_postProcessMotionBlur = false;
_postProcessSSAO = false;
_sceneShadowQuality = Math::Min(_sceneShadowQuality, ShadowQuality::filtered);
}
if (!_gpuPerPixelLighting)
{
_gpuParallaxMapping = false;
_sceneWaterQuality = Math::Clamp(_sceneWaterQuality, WaterQuality::solidColor, WaterQuality::distortedReflection);
}
_postProcessBloom = _postProcessBloom && _gpuOffscreenRender;
_sceneGrassDensity = Math::Clamp(_sceneGrassDensity, 15, 1500);
_sceneShadowQuality = Math::Clamp(_sceneShadowQuality, ShadowQuality::none, ShadowQuality::cascaded);
_sceneWaterQuality = Math::Clamp(_sceneWaterQuality, WaterQuality::solidColor, WaterQuality::trueWavesRefraction);
if (_sceneShadowQuality >= ShadowQuality::cascaded)
_gpuDepthTexture = 1;
if (_uiLang != "RU" && _uiLang != "EN")
_uiLang = "EN";
}
void Settings::ParseCommandLineArgs(int argc, wchar_t* argv[])
{
Vector<String> v;
VERUS_FOR(i, argc)
v.push_back(Str::WideToUtf8(argv[i]));
Vector<SZ> vArgv;
VERUS_FOR(i, argc)
vArgv.push_back(const_cast<SZ>(_C(v[i])));
ParseCommandLineArgs(argc, vArgv.data());
}
void Settings::ParseCommandLineArgs(int argc, char* argv[])
{
auto IsArg = [&argv](int i, CSZ arg)
{
return !strcmp(argv[i], arg);
};
VERUS_FOR(i, argc)
{
_commandLine.normalMapOnlyLS = _commandLine.normalMapOnlyLS || IsArg(i, "--normal-map-only-ls");
_commandLine.physicsDebug = _commandLine.physicsDebug || IsArg(i, "--physics-debug");
_commandLine.physicsDebugFull = _commandLine.physicsDebugFull || IsArg(i, "--physics-debug-full");
_commandLine.profiler = _commandLine.profiler || IsArg(i, "--profiler");
_commandLine.testTexToPix = _commandLine.testTexToPix || IsArg(i, "--test-tex-to-pix");
}
VERUS_QREF_UTILS;
//utils.SetupPathsEx(); // Only now we can finally do this.
SetFilename("Settings.json");
const String pathName = _C(GetFilename());
VERUS_FOR(i, argc)
{
if (IsArg(i, "--q-low"))
{
const bool ret = IO::FileSystem::Delete(_C(pathName));
SetQuality(Quality::low);
}
if (IsArg(i, "--q-medium"))
{
const bool ret = IO::FileSystem::Delete(_C(pathName));
SetQuality(Quality::medium);
}
if (IsArg(i, "--q-high"))
{
const bool ret = IO::FileSystem::Delete(_C(pathName));
SetQuality(Quality::high);
}
if (IsArg(i, "--q-ultra"))
{
const bool ret = IO::FileSystem::Delete(_C(pathName));
SetQuality(Quality::ultra);
}
}
}
void Settings::SetQuality(Quality q)
{
_quality = q;
_direct3D = 9;
_gpuAnisotropyLevel = 0;
_gpuAntialiasingLevel = 0;
_gpuDepthTexture = 0;
_gpuForcedProfile = "";
_gpuOffscreenRender = true;
_gpuParallaxMapping = false;
_gpuPerPixelLighting = true;
_gpuTextureLodLevel = 0;
_gpuTrilinearFilter = false;
_postProcessBloom = false;
_postProcessCinema = false;
_postProcessMotionBlur = false;
_postProcessSSAO = false;
_sceneGrassDensity = 1000;
_sceneShadowQuality = ShadowQuality::sharp;
_sceneWaterQuality = WaterQuality::distortedReflection;
_screenVSync = false;
_screenWindowed = true;
switch (q)
{
case Quality::low:
_gpuDepthTexture = -1;
_gpuForcedProfile = "sm_3_0";
_sceneGrassDensity = 500;
_sceneShadowQuality = ShadowQuality::none;
_sceneWaterQuality = WaterQuality::solidColor;
_screenSizeHeight = 600;
_screenSizeWidth = 800;
break;
case Quality::medium:
_gpuAnisotropyLevel = 4;
_gpuForcedProfile = "sm_3_0";
_screenSizeHeight = 768;
_screenSizeWidth = 1024;
break;
case Quality::high:
_direct3D = 11;
_gpuAnisotropyLevel = 8;
_gpuTrilinearFilter = true;
_postProcessBloom = true;
_postProcessCinema = true;
_postProcessSSAO = true;
_sceneGrassDensity = 1500;
_sceneShadowQuality = ShadowQuality::filtered;
_sceneWaterQuality = WaterQuality::trueWavesReflection;
_screenSizeHeight = 720;
_screenSizeWidth = 1280;
break;
case Quality::ultra:
_direct3D = 11;
_gpuAnisotropyLevel = 16;
_gpuDepthTexture = 1;
_gpuTrilinearFilter = true;
_postProcessBloom = true;
_postProcessCinema = true;
_postProcessMotionBlur = true;
_postProcessSSAO = true;
_sceneGrassDensity = 1500;
_sceneShadowQuality = ShadowQuality::cascaded;
_sceneWaterQuality = WaterQuality::trueWavesRefraction;
_screenSizeHeight = 1080;
_screenSizeWidth = 1980;
break;
}
#ifdef _WIN32
# ifndef _DEBUG
_screenSizeHeight = GetSystemMetrics(SM_CYSCREEN);
_screenSizeWidth = GetSystemMetrics(SM_CXSCREEN);
_screenWindowed = false;
# endif
#else // Linux?
_direct3D = 0;
_gpuForcedProfile = "arb1";
#endif
}
void Settings::MatchScreen()
{
SDL_DisplayMode dm;
if (SDL_GetCurrentDisplayMode(0, &dm) < 0)
throw VERUS_RUNTIME_ERROR << "SDL_GetCurrentDisplayMode(), " << SDL_GetError();
_screenSizeWidth = dm.w;
_screenSizeHeight = dm.h;
}

86
Verus/src/App/Settings.h Normal file
View File

@ -0,0 +1,86 @@
#pragma once
namespace verus
{
namespace App
{
class Settings : public Singleton<Settings>, public IO::Json
{
public:
enum class Quality : int
{
low,
medium,
high,
ultra
};
enum class ShadowQuality : int
{
none,
sharp,
filtered,
cascaded
};
enum class WaterQuality : int
{
solidColor,
simpleReflection,
distortedReflection,
trueWavesReflection,
trueWavesRefraction
};
Quality _quality = Quality::medium;
int _direct3D = 9;
int _gpuAnisotropyLevel = 4;
int _gpuAntialiasingLevel = 0;
int _gpuDepthTexture = 0;
String _gpuForcedProfile = "sm_3_0";
bool _gpuOffscreenRender = false;
bool _gpuParallaxMapping = false;
bool _gpuPerPixelLighting = true;
int _gpuTextureLodLevel = 0;
bool _gpuTrilinearFilter = false;
float _inputMouseSensitivity = 1;
bool _postProcessBloom = false;
bool _postProcessCinema = false;
bool _postProcessMotionBlur = false;
bool _postProcessSSAO = false;
int _sceneGrassDensity = 1000;
ShadowQuality _sceneShadowQuality = ShadowQuality::sharp;
WaterQuality _sceneWaterQuality = WaterQuality::solidColor;
float _screenFOV = 70;
int _screenSizeHeight = 720;
int _screenSizeWidth = 1280;
bool _screenVSync = false;
bool _screenWindowed = true;
String _uiLang = "EN";
struct
{
bool normalMapOnlyLS;
bool physicsDebug;
bool physicsDebugFull;
bool profiler;
bool testTexToPix;
} _commandLine;
Settings();
~Settings();
void LoadValidateSave();
void Load();
void Save();
void Validate();
void ParseCommandLineArgs(int argc, wchar_t* argv[]);
void ParseCommandLineArgs(int argc, char* argv[]);
void SetQuality(Quality q);
void MatchScreen();
};
VERUS_TYPEDEFS(Settings);
}
}

58
Verus/src/App/Window.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "verus.h"
using namespace verus;
using namespace verus::App;
// Window::Desc:
void Window::Desc::ApplySettings()
{
VERUS_QREF_SETTINGS;
_width = settings._screenSizeWidth;
_height = settings._screenSizeHeight;
_fullscreen = !settings._screenWindowed;
}
// Window:
Window::Window()
{
}
Window::~Window()
{
Done();
}
void Window::Init(RcDesc descConst)
{
VERUS_INIT();
Desc desc = descConst;
if (desc._useSettings)
desc.ApplySettings();
Uint32 flags = 0;
if (desc._fullscreen)
flags |= SDL_WINDOW_FULLSCREEN;
_pWnd = SDL_CreateWindow(
desc._title ? desc._title : "",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
desc._width,
desc._height,
flags);
if (!_pWnd)
throw VERUS_RECOVERABLE << "SDL_CreateWindow(), " << SDL_GetError();
}
void Window::Done()
{
if (_pWnd)
{
SDL_DestroyWindow(_pWnd);
_pWnd = nullptr;
}
VERUS_DONE(Window);
}

31
Verus/src/App/Window.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
namespace verus
{
namespace App
{
class Window : public Object
{
SDL_Window* _pWnd = nullptr;
public:
struct Desc
{
CSZ _title = nullptr;
int _width = 0;
int _height = 0;
bool _fullscreen = false;
bool _useSettings = true;
void ApplySettings();
};
VERUS_TYPEDEFS(Desc);
Window();
~Window();
void Init(RcDesc desc = Desc());
void Done();
};
}
}

13
Verus/src/Audio/Audio.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "verus.h"
namespace verus
{
void Make_Audio()
{
Audio::AudioSystem::Make();
}
void Free_Audio()
{
Audio::AudioSystem::Free();
}
}

13
Verus/src/Audio/Audio.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "OggCallbacks.h"
#include "Source.h"
#include "Sound.h"
#include "StreamPlayer.h"
#include "AudioSystem.h"
namespace verus
{
void Make_Audio();
void Free_Audio();
}

View File

@ -0,0 +1,142 @@
#include "verus.h"
using namespace verus;
using namespace verus::Audio;
AudioSystem::AudioSystem()
{
}
AudioSystem::~AudioSystem()
{
Done();
}
void AudioSystem::Init()
{
VERUS_INIT();
const ALCchar* deviceName = nullptr;
#ifdef _WIN32
deviceName = "DirectSound3D";
#endif
if (!(_pDevice = alcOpenDevice(deviceName)))
throw VERUS_RUNTIME_ERROR << "alcOpenDevice()";
if (!(_pContext = alcCreateContext(_pDevice, nullptr)))
throw VERUS_RUNTIME_ERROR << "alcCreateContext(), " << alcGetError(_pDevice);
if (!alcMakeContextCurrent(_pContext))
throw VERUS_RUNTIME_ERROR << "alcMakeContextCurrent(), " << alcGetError(_pDevice);
int vMajor = 0, vMinor = 0;
alcGetIntegerv(_pDevice, ALC_MAJOR_VERSION, sizeof(vMajor), &vMajor);
alcGetIntegerv(_pDevice, ALC_MINOR_VERSION, sizeof(vMinor), &vMinor);
StringStream ss;
ss << vMajor << "." << vMinor;
_version = ss.str();
_deviceSpecifier = alcGetString(_pDevice, ALC_DEVICE_SPECIFIER);
}
void AudioSystem::Done()
{
DeleteAllStreams();
DeleteAllSounds();
alcMakeContextCurrent(0);
if (_pContext)
{
alcDestroyContext(_pContext);
_pContext = nullptr;
}
if (_pDevice)
{
alcCloseDevice(_pDevice);
_pDevice = nullptr;
}
VERUS_DONE(AudioSystem);
}
void AudioSystem::Update()
{
if (!IsInitialized())
return;
VERUS_UPDATE_ONCE_CHECK;
VERUS_QREF_TIMER;
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_streamPlayers))
_streamPlayers[i].Update();
// Update every frame:
for (auto& x : TStoreSounds::_map)
x.second.Update();
// Update ~15 times per second:
if (timer.IsEventEvery(67))
{
for (auto& x : TStoreSounds::_map)
x.second.UpdateHRTF();
if (VMath::lengthSqr(_listenerDirection) > 0.1f &&
VMath::lengthSqr(_listenerUp) > 0.1f)
{
const float orien[6] =
{
_listenerDirection.getX(),
_listenerDirection.getY(),
_listenerDirection.getZ(),
_listenerUp.getX(),
_listenerUp.getY(),
_listenerUp.getZ()
};
alListenerfv(AL_POSITION, _listenerPosition.ToPointer());
alListenerfv(AL_VELOCITY, _listenerVelocity.ToPointer());
alListenerfv(AL_ORIENTATION, orien); // Zero-length vectors can crash OpenAL!
}
}
}
void AudioSystem::DeleteAllStreams()
{
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_streamPlayers))
_streamPlayers[i].Done();
}
PSound AudioSystem::InsertSound(CSZ url)
{
return TStoreSounds::Insert(url);
}
PSound AudioSystem::FindSound(CSZ url)
{
return TStoreSounds::Find(url);
}
void AudioSystem::DeleteSound(CSZ url)
{
TStoreSounds::Delete(url);
}
void AudioSystem::DeleteAllSounds()
{
TStoreSounds::DeleteAll();
}
void AudioSystem::UpdateListener(RcPoint3 pos, RcVector3 dir, RcVector3 vel, RcVector3 up)
{
_listenerPosition = pos;
_listenerDirection = dir;
_listenerVelocity = vel;
_listenerUp = up;
}
float AudioSystem::ComputeTravelDelay(RcPoint3 pos) const
{
const float speed = alGetFloat(AL_SPEED_OF_SOUND);
const float dist = VMath::dist(pos, _listenerPosition);
return Math::Clamp<float>(dist / speed, 0, 3);
}

View File

@ -0,0 +1,44 @@
#pragma once
namespace verus
{
namespace Audio
{
typedef StoreUnique<String, Sound> TStoreSounds;
class AudioSystem : public Singleton<AudioSystem>, public Object, private TStoreSounds
{
Point3 _listenerPosition = Point3(0);
Vector3 _listenerDirection = Vector3(0, 0, 1);
Vector3 _listenerVelocity = Vector3(0);
Vector3 _listenerUp = Vector3(0, 1, 0);
ALCdevice* _pDevice = nullptr;
ALCcontext* _pContext = nullptr;
String _version;
String _deviceSpecifier;
StreamPlayer _streamPlayers[4];
public:
AudioSystem();
~AudioSystem();
void Init();
void Done();
void Update();
RStreamPlayer GetStreamPlayer(int index) { return _streamPlayers[index]; }
void DeleteAllStreams();
PSound InsertSound(CSZ url);
PSound FindSound(CSZ url);
void DeleteSound(CSZ url);
void DeleteAllSounds();
void UpdateListener(RcPoint3 pos, RcVector3 dir, RcVector3 vel, RcVector3 up);
float ComputeTravelDelay(RcPoint3 pos) const;
static CSZ GetSingletonFailMessage() { return "Make_Audio(); // FAIL.\r\n"; }
};
VERUS_TYPEDEFS(AudioSystem);
}
}

View File

@ -0,0 +1,46 @@
#include "verus.h"
namespace verus
{
namespace Audio
{
size_t read_func(void* ptr, size_t size, size_t nmemb, void* datasource)
{
POggDataSource pDS = static_cast<POggDataSource>(datasource);
INT64 readLen = size * nmemb;
const INT64 maxLen = pDS->_size - pDS->_cursor;
if (readLen > maxLen)
readLen = maxLen;
memcpy(ptr, pDS->_p + pDS->_cursor, size_t(readLen));
pDS->_cursor += readLen;
return size_t(readLen);
}
int seek_func(void* datasource, ogg_int64_t offset, int whence)
{
POggDataSource pDS = static_cast<POggDataSource>(datasource);
switch (whence)
{
case SEEK_SET: pDS->_cursor = offset; return 0;
case SEEK_CUR: pDS->_cursor += offset; return 0;
case SEEK_END: pDS->_cursor = pDS->_size - offset; return 0;
}
return -1;
}
int close_func(void* datasource)
{
POggDataSource pDS = static_cast<POggDataSource>(datasource);
pDS->_cursor = 0;
return 0;
}
long tell_func(void* datasource)
{
POggDataSource pDS = static_cast<POggDataSource>(datasource);
return long(pDS->_cursor);
}
const ov_callbacks g_oggCallbacks = { read_func, seek_func, close_func, tell_func };
}
}

View File

@ -0,0 +1,22 @@
#pragma once
namespace verus
{
namespace Audio
{
struct OggDataSource
{
const BYTE* _p = nullptr;
INT64 _size = 0;
INT64 _cursor = 0;
};
VERUS_TYPEDEFS(OggDataSource);
size_t read_func(void*, size_t, size_t, void*);
int seek_func(void*, ogg_int64_t, int);
int close_func(void*);
long tell_func(void*);
extern const ov_callbacks g_oggCallbacks;
}
}

183
Verus/src/Audio/Sound.cpp Normal file
View File

@ -0,0 +1,183 @@
#include "verus.h"
using namespace verus;
using namespace verus::Audio;
// Sound:
Sound::Sound()
{
}
Sound::~Sound()
{
Done();
}
void Sound::Init(RcDesc desc)
{
if (_refCount)
return;
VERUS_INIT();
_url = desc._url;
_refCount = 1;
if (desc._is3D) SetFlag(SoundFlags::is3D);
if (desc._loop) SetFlag(SoundFlags::loop);
_gain = desc._gain;
_pitch = desc._pitch;
_referenceDistance = desc._referenceDistance;
if (desc._randomOffset) SetFlag(SoundFlags::randOff);
IO::Async::I().Load(desc._url, this);
}
bool Sound::Done()
{
_refCount--;
if (_refCount <= 0)
{
IO::Async::Cancel(this);
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_sources))
_sources[i].Done();
if (_buffer)
alDeleteBuffers(1, &_buffer);
VERUS_DONE(Sound);
return true;
}
return false;
}
void Sound::Async_Run(CSZ url, RcBlob blob)
{
VERUS_RT_ASSERT(_url == url);
VERUS_RT_ASSERT(!_buffer);
VERUS_RT_ASSERT(blob._size);
OggDataSource oggds;
oggds._p = blob._p;
oggds._size = blob._size;
OggVorbis_File ovf;
vorbis_info* povi;
const int ret = ov_open_callbacks(&oggds, &ovf, 0, 0, g_oggCallbacks);
if (ret < 0)
throw VERUS_RUNTIME_ERROR << "ov_open_callbacks(), " << ret;
povi = ov_info(&ovf, -1);
const ALenum format = (povi->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
alGenBuffers(1, &_buffer);
_length = static_cast<float>(ov_time_total(&ovf, -1));
const INT64 pcmSize = ov_pcm_total(&ovf, -1) * 2 * povi->channels + 1;
Vector<BYTE> vRaw;
vRaw.resize(pcmSize);
int bitstream, offset = 0;
long num = ov_read(&ovf, reinterpret_cast<char*>(vRaw.data()), Utils::Cast32(vRaw.size()), 0, 2, 1, &bitstream);
do
{
offset += num;
num = ov_read(&ovf, reinterpret_cast<char*>(&vRaw[offset]), Utils::Cast32(vRaw.size()) - offset, 0, 2, 1, &bitstream);
} while (num > 0);
alBufferData(_buffer, format, vRaw.data(), offset, povi->rate);
ov_clear(&ovf);
SetFlag(SoundFlags::loaded);
}
void Sound::Update()
{
if (!IsLoaded())
return;
VERUS_UPDATE_ONCE_CHECK;
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_sources))
_sources[i].Update();
}
void Sound::UpdateHRTF()
{
if (!IsLoaded())
return;
const bool is3D = IsFlagSet(SoundFlags::is3D);
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_sources))
_sources[i].UpdateHRTF(is3D);
}
SourcePtr Sound::NewSource(PSourcePtr pID, Source::RcDesc desc)
{
SourcePtr source;
if (IsLoaded())
{
source.Attach(_sources + _next, this);
VERUS_CIRCULAR_ADD(_next, VERUS_ARRAY_LENGTH(_sources));
if (source->_sid) // Delete existing?
alDeleteSources(1, &source->_sid);
alGenSources(1, &source->_sid);
const ALuint sid = source->_sid;
if (IsFlagSet(SoundFlags::is3D))
{
alSourcef(sid, AL_REFERENCE_DISTANCE, _referenceDistance);
alSourcef(sid, AL_ROLLOFF_FACTOR, 4);
}
else // No 3D effect?
{
alSourcei(sid, AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(sid, AL_POSITION, 0, 0, 0);
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);
alSourcei(sid, AL_BUFFER, _buffer);
alSourcef(sid, AL_GAIN, _gain.GetRandomValue()*desc._gain);
if (desc._secOffset < 0)
{
VERUS_QREF_UTILS;
ALint size = 0;
alGetBufferi(_buffer, AL_SIZE, &size);
const ALint offset = utils.GetRandom().Next() % size;
alSourcei(sid, AL_BYTE_OFFSET, offset);
}
else if (desc._secOffset > 0)
{
alSourcef(sid, AL_SEC_OFFSET, desc._secOffset);
}
}
if (pID) // Adjust this source later?
{
if (desc._stopSource && *pID)
(*pID)->Stop();
*pID = source;
}
return source;
}
float Sound::GetRandomOffset() const
{
return _length * Utils::I().GetRandom().NextFloat();
}
// SoundPtr:
void SoundPtr::Init(Sound::RcDesc desc)
{
VERUS_QREF_ASYS;
VERUS_RT_ASSERT(!_p);
_p = asys.InsertSound(desc._url);
_p->Init(desc);
}
void SoundPwn::Done()
{
if (_p)
{
AudioSystem::I().DeleteSound(_C(_p->GetUrl()));
_p = nullptr;
}
}

141
Verus/src/Audio/Sound.h Normal file
View File

@ -0,0 +1,141 @@
#pragma once
namespace verus
{
namespace Audio
{
struct SoundFlags
{
enum
{
loaded = (ObjectFlags::user << 0),
is3D = (ObjectFlags::user << 1),
loop = (ObjectFlags::user << 2),
randOff = (ObjectFlags::user << 3),
user = (ObjectFlags::user << 4)
};
};
class Sound : public Object, public IO::AsyncCallback
{
Source _sources[8];
String _url;
ALuint _buffer = 0;
int _next = 0;
int _refCount = 0;
Range<float> _gain = 1;
Range<float> _pitch = 1;
float _length = 0;
float _referenceDistance = 4;
public:
struct Desc
{
CSZ _url = nullptr;
Range<float> _gain = 0.8f;
Range<float> _pitch = 1;
float _referenceDistance = 4;
bool _is3D = false;
bool _loop = false;
bool _randomOffset = 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& SetGain(const Range<float>& gain) { _gain = gain; return *this; }
Desc& SetPitch(const Range<float>& 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);
Sound();
~Sound();
void Init(RcDesc desc);
bool Done();
virtual void Async_Run(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();
SourcePtr NewSource(PSourcePtr pID = nullptr, Source::RcDesc desc = Source::Desc());
const Range<float>& GetGain() const { return _gain; }
const Range<float>& GetPitch() const { return _pitch; }
float GetLength() const { return _length; }
float GetRandomOffset() const;
void SetRandomOffset(bool b) { b ? SetFlag(SoundFlags::randOff) : ResetFlag(SoundFlags::randOff); }
bool HasRandomOffset() const { return IsFlagSet(SoundFlags::randOff); }
};
VERUS_TYPEDEFS(Sound);
class SoundPtr : public Ptr<Sound>
{
public:
void Init(Sound::RcDesc desc);
};
VERUS_TYPEDEFS(SoundPtr);
class SoundPwn : public SoundPtr
{
public:
~SoundPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(SoundPwn);
template<int NUM>
class SoundPwns
{
SoundPwn _sounds[NUM];
int _prev = 0;
public:
SoundPwns()
{
}
~SoundPwns()
{
Done();
}
void Init(Sound::RcDesc desc)
{
char buffer[200];
VERUS_FOR(i, NUM)
{
sprintf_s(buffer, desc._url, i);
Sound::Desc descs = desc;
descs._url = buffer;
_sounds[i].Init(descs);
}
}
void Done()
{
VERUS_FOR(i, NUM)
_sounds[i].Done();
}
RSoundPtr operator[](int i)
{
if (i < 0)
i = Utils::I().GetRandom().Next() & 0xFF; // Only positive.
i %= NUM;
if (i == _prev)
i = (i + 1) % NUM;
_prev = i;
return _sounds[i];
}
};
}
}

136
Verus/src/Audio/Source.cpp Normal file
View File

@ -0,0 +1,136 @@
#include "verus.h"
using namespace verus;
using namespace verus::Audio;
// Source:
Source::Source()
{
}
Source::~Source()
{
Done();
}
void Source::Done()
{
if (_sid)
{
alDeleteSources(1, &_sid);
_sid = 0;
_pSound = nullptr;
}
}
void Source::Update()
{
if (!_sid)
return;
VERUS_QREF_TIMER;
int state;
alGetSourcei(_sid, AL_SOURCE_STATE, &state);
if (AL_INITIAL == state)
{
_travelDelay -= dt;
if (_travelDelay <= 0)
{
if (_pSound->HasRandomOffset())
alSourcef(_sid, AL_SEC_OFFSET, _pSound->GetRandomOffset());
alSourcePlay(_sid);
}
}
}
void Source::UpdateHRTF(bool is3D)
{
if (!_sid)
return;
int state;
alGetSourcei(_sid, AL_SOURCE_STATE, &state);
if (AL_STOPPED == state)
{
alDeleteSources(1, &_sid);
_sid = 0;
}
else if (is3D)
{
alSourcefv(_sid, AL_POSITION, _position.ToPointer());
alSourcefv(_sid, AL_DIRECTION, _direction.ToPointer());
alSourcefv(_sid, AL_VELOCITY, _velocity.ToPointer());
}
}
void Source::Play()
{
if (!this)
return; // For NewSource()-> pattern.
if (_pSound && _pSound->IsLoaded())
{
if (_pSound->HasRandomOffset())
alSourcef(_sid, AL_SEC_OFFSET, _pSound->GetRandomOffset());
alSourcePlay(_sid);
}
}
void Source::PlayAt(RcPoint3 pos, RcVector3 dir, RcVector3 vel, float delay)
{
if (!this)
return; // For NewSource()-> pattern.
VERUS_QREF_ASYS;
if (_pSound && _pSound->IsLoaded())
{
_travelDelay = asys.ComputeTravelDelay(pos) + delay;
MoveTo(pos, dir, vel);
UpdateHRTF(_pSound->IsFlagSet(SoundFlags::is3D));
}
}
void Source::Stop()
{
if (_pSound && _pSound->IsLoaded())
alSourceStop(_sid);
}
void Source::MoveTo(RcPoint3 pos, RcVector3 dir, RcVector3 vel)
{
if (_pSound && _pSound->IsLoaded())
{
_position = pos;
_direction = dir;
_velocity = vel;
}
}
void Source::SetGain(float gain)
{
if (_pSound && _pSound->IsLoaded())
alSourcef(_sid, AL_GAIN, gain*_pSound->GetGain().GetRandomValue());
}
void Source::SetPitch(float pitch)
{
if (_pSound && _pSound->IsLoaded())
alSourcef(_sid, AL_PITCH, pitch*_pSound->GetPitch().GetRandomValue());
}
// SourcePtr:
void SourcePtr::Attach(Source* pSource, Sound* pSound)
{
_p = pSource;
_p->_pSound = pSound;
}
void SourcePtr::Done()
{
if (_p)
{
_p->Done();
_p = nullptr;
}
}

55
Verus/src/Audio/Source.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
namespace verus
{
namespace Audio
{
class Source
{
friend class SourcePtr; // _pSound @ Attach().
friend class Sound; // _sid @ NewSource().
Point3 _position = Point3(0);
Vector3 _direction = Vector3(0);
Vector3 _velocity = Vector3(0);
Sound* _pSound = nullptr;
ALuint _sid = 0;
float _travelDelay = 0;
public:
struct Desc
{
float _secOffset = 0;
float _gain = 1;
float _pitch = 1;
bool _stopSource = true;
};
VERUS_TYPEDEFS(Desc);
Source();
~Source();
void Done();
void Update();
void UpdateHRTF(bool is3D);
void Play();
void PlayAt(RcPoint3 pos, RcVector3 dir = Vector3(0), RcVector3 vel = Vector3(0), float delay = 0);
void Stop();
void MoveTo(RcPoint3 pos, RcVector3 dir = Vector3(0), RcVector3 vel = Vector3(0));
void SetGain(float gain);
void SetPitch(float pitch);
};
VERUS_TYPEDEFS(Source);
class SourcePtr : public Ptr<Source>
{
public:
void Attach(Source* pSource, Sound* pSound);
void Done();
};
VERUS_TYPEDEFS(SourcePtr);
}
}

View File

@ -0,0 +1,340 @@
#include "verus.h"
using namespace verus;
using namespace verus::Audio;
// Track:
Track::Track()
{
_loaded = false;
}
Track::~Track()
{
Done();
}
void Track::Init(CSZ url)
{
IO::Async::I().Load(url, this);
}
void Track::Done()
{
IO::Async::Cancel(this);
}
void Track::Async_Run(CSZ url, RcBlob blob)
{
_vOggEncodedTrack.assign(blob._p, blob._p + blob._size);
_ds._p = _vOggEncodedTrack.data();
_ds._size = _vOggEncodedTrack.size();
_ds._cursor = 0;
_loaded = true;
}
// StreamPlayer:
StreamPlayer::StreamPlayer()
{
VERUS_ZERO_MEM(_oggVorbisFile);
VERUS_ZERO_MEM(_buffers);
}
StreamPlayer::~StreamPlayer()
{
Done();
}
void StreamPlayer::Init()
{
VERUS_INIT();
_fade.Set(1, 0);
_fade.SetLimits(0, 1);
alGenBuffers(2, _buffers);
alGenSources(1, &_source);
alSourcei(_source, AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(_source, AL_POSITION, 0, 0, 0);
alSource3f(_source, AL_VELOCITY, 0, 0, 0);
alSourcef(_source, AL_GAIN, _gain);
alSourcef(_source, AL_ROLLOFF_FACTOR, 0);
_vSmallBuffer.resize(441 * 32);
_vMediumBuffer.resize(441 * 32 * 32);
_vTracks.reserve(8);
ResetFlag(StreamPlayerFlags::stopThread);
ResetFlag(StreamPlayerFlags::noLock);
_thread = std::thread(&StreamPlayer::ThreadProc, this);
}
void StreamPlayer::Done()
{
StopThread();
_nativeTrack.Done();
if (_source)
{
alDeleteSources(1, &_source);
_source = 0;
}
if (_buffers[0])
{
alDeleteBuffers(2, _buffers);
_buffers[0] = _buffers[1] = 0;
}
ov_clear(&_oggVorbisFile);
VERUS_DONE(StreamPlayer);
}
void StreamPlayer::Update()
{
if (!IsInitialized())
return;
VERUS_UPDATE_ONCE_CHECK;
VERUS_QREF_TIMER;
_fade.UpdateClamped(dt);
const float level = Math::SmoothStep(0.f, 1.f, _fade.GetValue());
alSourcef(_source, AL_GAIN, _gain*level);
}
void StreamPlayer::AddTrack(PTrack pTrack)
{
{
VERUS_LOCK(*this);
_vTracks.push_back(pTrack);
if (!_pTrack)
_pTrack = pTrack;
}
_cv.notify_one();
}
void StreamPlayer::DeleteTrack(PTrack pTrack)
{
{
VERUS_LOCK(*this);
VERUS_WHILE(Vector<PTrack>, _vTracks, it)
{
if (*it == pTrack)
it = _vTracks.erase(it);
else
it++;
}
if (_pTrack == pTrack)
{
SetFlag(StreamPlayerFlags::noLock);
SwitchToTrack(nullptr);
ResetFlag(StreamPlayerFlags::noLock);
}
}
_cv.notify_one();
}
void StreamPlayer::SwitchToTrack(PTrack pTrack)
{
VERUS_LOCK_EX(*this, IsFlagSet(StreamPlayerFlags::noLock));
VERUS_FOR(i, int(_vTracks.size()))
{
if (_vTracks[i] == pTrack)
{
_currentTrack = i;
break;
}
}
_pTrack = pTrack;
_pVorbisInfo = nullptr;
ov_clear(&_oggVorbisFile);
if (!_pTrack || !_pTrack->IsLoaded()) // Possible to start decoding?
return;
const int ret = ov_open_callbacks(_pTrack->GetOggDataSource(), &_oggVorbisFile, 0, 0, g_oggCallbacks);
if (ret < 0)
throw VERUS_RUNTIME_ERROR << "ov_open_callbacks(), " << ret;
_pVorbisInfo = ov_info(&_oggVorbisFile, -1);
_format = (_pVorbisInfo->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
}
void StreamPlayer::Play()
{
SetFlag(StreamPlayerFlags::play);
alSourcePlay(_source);
_cv.notify_one();
}
void StreamPlayer::Stop()
{
ResetFlag(StreamPlayerFlags::play);
alSourceStop(_source);
_cv.notify_one();
}
void StreamPlayer::Seek(int pos)
{
{
VERUS_LOCK(*this);
if (!_pVorbisInfo)
return;
int queued;
alGetSourcei(_source, AL_BUFFERS_QUEUED, &queued);
while (queued > 0)
{
ALuint buffer;
alSourceUnqueueBuffers(_source, 1, &buffer);
queued--;
}
ov_pcm_seek(&_oggVorbisFile, pos);
}
_cv.notify_one();
}
void StreamPlayer::ThreadProc()
{
VERUS_RT_ASSERT(IsInitialized());
try
{
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
while (!IsFlagSet(StreamPlayerFlags::stopThread))
{
VERUS_LOCK(*this);
_cv.wait_for(lock, std::chrono::milliseconds(530));
if (IsFlagSet(StreamPlayerFlags::play))
{
SetFlag(StreamPlayerFlags::noLock);
if (_pTrack)
{
if (_pTrack->IsLoaded() && !_pVorbisInfo) // Loaded but not started?
{
SwitchToTrack(_pTrack);
VERUS_RT_ASSERT(_pVorbisInfo);
}
if (_pVorbisInfo) // Can get the data?
{
int queued;
alGetSourcei(_source, AL_BUFFERS_QUEUED, &queued);
if (!queued)
{
FillBuffer(_buffers[0]);
FillBuffer(_buffers[1]);
alSourceQueueBuffers(_source, 2, _buffers);
alSourcePlay(_source);
}
int processed;
alGetSourcei(_source, AL_BUFFERS_PROCESSED, &processed);
#ifdef VERUS_DEBUG
char debug[80];
sprintf_s(debug, "ThreadProc() processed=%d", processed);
VERUS_LOG_DEBUG(debug);
#endif
while (processed > 0)
{
ALuint buffer;
alSourceUnqueueBuffers(_source, 1, &buffer);
FillBuffer(buffer);
alSourceQueueBuffers(_source, 1, &buffer);
processed--;
}
int state;
alGetSourcei(_source, AL_SOURCE_STATE, &state);
if (AL_STOPPED == state)
alSourcePlay(_source);
}
}
else // No track? Stop the music:
{
alSourceStop(_source);
}
ResetFlag(StreamPlayerFlags::noLock);
}
}
alSourceStop(_source);
}
catch (D::RcRuntimeError e)
{
//Utils::CLog::Error(e.what(), e.GetThreadID(), e.GetFile(), e.GetLine());
}
catch (const std::exception& e)
{
VERUS_LOG_ERROR(e.what());
}
}
void StreamPlayer::StopThread()
{
if (_thread.joinable())
{
SetFlag(StreamPlayerFlags::stopThread);
Stop();
_thread.join();
}
}
void StreamPlayer::FillBuffer(ALuint buffer)
{
VERUS_RT_ASSERT(IsInitialized());
int bitstream, oggCursor = 0, safeSize = Utils::Cast32(_vMediumBuffer.size() - _vSmallBuffer.size());
while (oggCursor < safeSize)
{
long num = -1;
if (_pTrack && _pTrack->IsLoaded())
num = ov_read(&_oggVorbisFile, reinterpret_cast<char*>(_vSmallBuffer.data()), Utils::Cast32(_vSmallBuffer.size()), 0, 2, 1, &bitstream);
if (num > 0)
{
memcpy(&_vMediumBuffer[oggCursor], _vSmallBuffer.data(), num);
oggCursor += num;
}
else if (0 == num) // No more data?
{
if (!_vTracks.empty()) // Next one in the playlist?
{
_currentTrack++;
_currentTrack %= _vTracks.size();
SwitchToTrack(_vTracks[_currentTrack]);
}
else
ov_raw_seek(&_oggVorbisFile, 0); // Start from the beginning.
}
else
safeSize = 0; // Still loading? Exit.
}
if (_pVorbisInfo)
alBufferData(buffer, _format, _vMediumBuffer.data(), oggCursor, _pVorbisInfo->rate);
}
void StreamPlayer::FadeIn(float time)
{
_fade.Plan(1, time);
}
void StreamPlayer::FadeOut(float time)
{
_fade.Plan(0, time);
}
void StreamPlayer::Mute()
{
_fade.Set(0, 0);
}

View File

@ -0,0 +1,81 @@
#pragma once
namespace verus
{
namespace Audio
{
class Track : public IO::AsyncCallback
{
Vector<BYTE> _vOggEncodedTrack;
OggDataSource _ds;
std::atomic_bool _loaded;
public:
Track();
~Track();
POggDataSource GetOggDataSource() { return &_ds; }
void Init(CSZ url);
void Done();
virtual void Async_Run(CSZ url, RcBlob blob) override;
bool IsLoaded() const { return _loaded; }
};
VERUS_TYPEDEFS(Track);
struct StreamPlayerFlags
{
enum
{
stopThread = (ObjectFlags::user << 0),
play = (ObjectFlags::user << 1),
noLock = (ObjectFlags::user << 2)
};
};
class StreamPlayer : public Object, public Lockable
{
Track _nativeTrack;
Vector<PTrack> _vTracks;
Vector<BYTE> _vSmallBuffer;
Vector<BYTE> _vMediumBuffer;
std::thread _thread;
std::condition_variable _cv;
vorbis_info* _pVorbisInfo = nullptr;
PTrack _pTrack = nullptr;
OggVorbis_File _oggVorbisFile;
ALuint _buffers[2];
ALuint _source = 0;
ALenum _format = 0;
Linear<float> _fade;
float _gain = 0.25f;
int _currentTrack = 0;
public:
StreamPlayer();
~StreamPlayer();
void Init();
void Done();
void Update();
void AddTrack(PTrack pTrack);
void DeleteTrack(PTrack pTrack);
void SwitchToTrack(PTrack pTrack);
void Play();
void Stop();
void Seek(int pos);
VERUS_P(void ThreadProc());
VERUS_P(void StopThread());
VERUS_P(void FillBuffer(ALuint buffer));
void FadeIn(float time);
void FadeOut(float time);
void Mute();
};
VERUS_TYPEDEFS(StreamPlayer);
}
}

View File

@ -0,0 +1,4 @@
#include "verus.h"
using namespace verus;
using namespace verus::CGI;

View File

@ -0,0 +1,11 @@
#pragma once
namespace verus
{
namespace CGI
{
class BaseGeometry
{
};
}
}

View File

@ -0,0 +1,4 @@
#include "verus.h"
using namespace verus;
using namespace verus::CGI;

View File

@ -0,0 +1,11 @@
#pragma once
namespace verus
{
namespace CGI
{
class BasePipeline
{
};
}
}

View File

@ -0,0 +1,4 @@
#include "verus.h"
using namespace verus;
using namespace verus::CGI;

View File

@ -0,0 +1,11 @@
#pragma once
namespace verus
{
namespace CGI
{
class BaseShader
{
};
}
}

View File

@ -0,0 +1,4 @@
#include "verus.h"
using namespace verus;
using namespace verus::CGI;

View File

@ -0,0 +1,11 @@
#pragma once
namespace verus
{
namespace CGI
{
class BaseTexture
{
};
}
}

6
Verus/src/CGI/CGI.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "BaseGeometry.h"
#include "BasePipeline.h"
#include "BaseShader.h"
#include "BaseTexture.h"

View File

@ -0,0 +1,3 @@
#pragma once
#define VERUS_CT_ASSERT(x) static_assert(x, "VERUS_CT_ASSERT")

View File

@ -0,0 +1,14 @@
#pragma once
#ifdef _DEBUG
# define VERUS_RT_ASSERT(x) assert(x)
# define VERUS_RT_FAIL(x) assert(!x)
#else
# ifdef VERUS_RELEASE_DEBUG
# define VERUS_RT_ASSERT(x) SDL_assert_release(x)
# define VERUS_RT_FAIL(x) SDL_assert_release(!x)
# else
# define VERUS_RT_ASSERT(x)
# define VERUS_RT_FAIL(x)
# endif
#endif

7
Verus/src/D/D.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include "AssertionRunTime.h"
#include "AssertionCompileTime.h"
#include "RuntimeError.h"
#include "Recoverable.h"
#include "Log.h"

134
Verus/src/D/Log.cpp Normal file
View File

@ -0,0 +1,134 @@
#include "verus.h"
using namespace verus;
using namespace verus::D;
std::mutex D::Log::s_mutex;
void Log::Error(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line)
{
std::lock_guard<std::mutex> lock(s_mutex);
const time_t t = time(0);
const tm* pTM = localtime(&t);
char timestamp[80];
strftime(timestamp, sizeof(timestamp), "%Y.%m.%d %H:%M:%S", pTM);
CSZ p = strrchr(filename, '/');
if (!p)
p = strrchr(filename, '\\');
filename = p ? p + 1 : filename;
String pathName;
//if (Global::IsValidSingleton())
//{
// pathName = Global::I().GetWritablePath() + "/Errors.txt";
//}
//else
{
String temp = getenv("TEMP");
pathName = temp + "/CorrErrors.txt";
}
IO::File file;
if (file.Open(_C(pathName), "a"))
{
if (file.GetSize() > 100 * 1024)
{
file.Close();
file.Open(_C(pathName), "w");
}
StringStream ss;
ss << timestamp << " " << tid << " " << filename << ":" << line << " ERROR: " << txt << "\n";
file.Write(_C(ss.str()), ss.str().length());
}
}
void Log::Session(CSZ txt)
{
/*
std::lock_guard<std::mutex> lock(s_mutex);
String pathName(Global::I().GetWritablePath());
pathName += "/SessionLog.txt";
IO::File file;
if (file.Create(_C(pathName), "a"))
{
StringStream ss;
ss.fill('0');
ss << '[';
ss.width(8);
ss << SDL_GetTicks() << "ms] " << txt << "\n";
file.Write(_C(ss.str()), ss.str().length());
}
*/
}
void Log::DebugString(CSZ txt)
{
/*
StringStream ss;
ss << verus::Global::GetNextCounterValue() << ": " << txt << "\n";
#ifdef _WIN32
OutputDebugStringA(_C(ss.str()));
#endif
*/
}
void Log::Write(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line, Severity severity)
{
char timestamp[40];
FormatTime(timestamp, sizeof(timestamp));
CSZ severityLetter = GetSeverityLetter(severity);
const String filenameEx = ExtractFilename(filename);
StringStream ss;
ss << timestamp << " [" << severityLetter << "] [" << tid << "] [" << filenameEx << ":" << line << "] " << txt << std::endl;
const String s = ss.str();
IO::File file;
if (file.Open("Log.txt", "a"))
{
if (file.GetSize() > 100 * 1024)
{
file.Close();
file.Open("Log.txt", "w");
}
file.Write(_C(s), s.length());
}
}
void Log::FormatTime(char* buffer, size_t size)
{
const auto now = std::chrono::system_clock::now();
const time_t tnow = std::chrono::system_clock::to_time_t(now);
const auto trimmed = std::chrono::system_clock::from_time_t(tnow);
const int ms = static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(now - trimmed).count());
char msText[16];
sprintf_s(msText, ".%06d", ms);
tm* pTM = localtime(&tnow);
strftime(buffer, size, "%Y-%m-%d %H:%M:%S", pTM);
strcat(buffer, msText);
}
CSZ Log::GetSeverityLetter(Severity severity)
{
switch (severity)
{
case Severity::error: return "E";
case Severity::warning: return "W";
case Severity::info: return "I";
case Severity::debug: return "D";
}
return "X";
}
String Log::ExtractFilename(CSZ filename)
{
CSZ p = strrchr(filename, '/');
if (!p)
p = strrchr(filename, '\\');
filename = p ? p + 1 : filename;
p = strrchr(filename, '.');
return p ? String(filename, p) : String(filename);
}

48
Verus/src/D/Log.h Normal file
View File

@ -0,0 +1,48 @@
#pragma once
//#define VERUS_LOG_ERROR(txt) {verus::D::Log::Error(txt, std::this_thread::get_id(), __FILE__, __LINE__);}
//#define VERUS_LOG_ERROR_STREAM(txt) {StringStream ss; ss << txt; verus::D::Log::Error(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__);}
//#define VERUS_LOG_SESSION(txt) {verus::D::Log::Session(txt);}
//#define VERUS_LOG_SESSION_STREAM(txt) {StringStream ss; ss << txt; verus::D::Log::Session(_C(ss.str()));}
//#ifdef _DEBUG
//# define VERUS_LOG_DEBUG(x) {verus::D::Log::DebugString(x);}
//#else
//# define VERUS_LOG_DEBUG(x) {}
//#endif
#define VERUS_LOG_ERROR(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::error);}
#define VERUS_LOG_WARN(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::warning);}
#define VERUS_LOG_INFO(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::info);}
#define VERUS_LOG_DEBUG(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::debug);}
namespace verus
{
namespace D
{
class Log : public Singleton<Log>
{
public:
enum class Severity : int
{
error,
warning,
info,
debug
};
private:
static std::mutex s_mutex;
public:
static void Error(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line);
static void Session(CSZ txt);
static void DebugString(CSZ txt);
void Write(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line, Severity severity);
static void FormatTime(char* buffer, size_t size);
static CSZ GetSeverityLetter(Severity severity);
static String ExtractFilename(CSZ filename);
};
}
}

32
Verus/src/D/Recoverable.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
namespace verus
{
namespace D
{
class Recoverable : public RuntimeError
{
public:
Recoverable(std::thread::id tid = std::this_thread::get_id(), CSZ file = __FILE__, UINT32 line = __LINE__) : RuntimeError(tid, file, line) {}
Recoverable(const Recoverable& that)
{
*this = that;
}
Recoverable& operator=(const Recoverable& that)
{
RuntimeError::operator=(that);
return *this;
}
template<typename T>
Recoverable& operator<<(const T& t)
{
RuntimeError::operator<<(t);
return *this;
}
};
VERUS_TYPEDEFS(Recoverable);
}
}
#define VERUS_RECOVERABLE verus::D::Recoverable(std::this_thread::get_id(), __FILE__, __LINE__)

View File

@ -0,0 +1,67 @@
#pragma once
namespace verus
{
namespace D
{
//! See: https://marknelson.us/posts/2007/11/13/no-exceptions.html
class RuntimeError : public std::exception
{
mutable StringStream _ss;
mutable String _what;
std::thread::id _tid;
String _file;
UINT32 _line = 0;
public:
RuntimeError(std::thread::id tid = std::this_thread::get_id(), CSZ file = __FILE__, UINT32 line = __LINE__) :
_tid(tid), _line(line)
{
CSZ p = strrchr(file, '/');
if (!p)
p = strrchr(file, '\\');
_file = p ? p + 1 : file;
}
RuntimeError(const RuntimeError& that)
{
*this = that;
}
RuntimeError& operator=(const RuntimeError& that)
{
_what += that._what;
_what += that._ss.str();
_tid = that._tid;
_file = that._file;
_line = that._line;
return *this;
}
virtual ~RuntimeError() throw() {}
virtual CSZ what() const throw()
{
if (_ss.str().size())
{
_what += _ss.str();
_ss.str("");
}
return _C(_what);
}
std::thread::id GetThreadID() const { return _tid; }
CSZ GetFile() const { return _C(_file); }
UINT32 GetLine() const { return _line; }
template<typename T>
RuntimeError& operator<<(const T& t)
{
_ss << t;
return *this;
}
bool IsRaised() const { return !!strlen(what()); }
};
VERUS_TYPEDEFS(RuntimeError);
}
}
#define VERUS_RUNTIME_ERROR verus::D::RuntimeError(std::this_thread::get_id(), __FILE__, __LINE__)

316
Verus/src/Game/BaseGame.cpp Normal file
View File

@ -0,0 +1,316 @@
#include "verus.h"
using namespace verus;
using namespace verus::Game;
#if 0
struct MyRenderDelegate : CGL::CRenderDelegate
{
PBaseGame _p = nullptr;
MyRenderDelegate(PBaseGame p) : _p(p) {}
~MyRenderDelegate() {}
virtual void Render_OnDraw() override
{
VERUS_QREF_RENDER;
render.BindOffscreenRT();
_p->BaseGame_Draw();
}
virtual void Render_OnDrawOverlay() override
{
_p->BaseGame_DrawOverlay();
}
virtual void Render_OnPresent() override
{
VERUS_QREF_RENDER;
render->Present();
}
virtual void Render_OnDrawCubeMap() override
{
}
};
VERUS_TYPEDEFS(MyRenderDelegate);
#endif
struct BaseGame::Pimpl : AllocatorAware
{
PBaseGame _p = nullptr;
Scene::MainCamera _camera;
//CCharacter _cameraCharacter;
bool _defaultCameraMovement = true;
bool _showFPS = true;
bool _debugBullet = false;
bool _exitOnEscape = true;
Pimpl(PBaseGame p) : _p(p)
{
}
~Pimpl()
{
}
bool HandleUserEvents(SDL_Event* pEvent)
{
switch (pEvent->user.code)
{
case 0: return true; // Exit.
}
return false;
}
};
BaseGame::BaseGame()
{
Utils::MakeEx(&_alloc);
_p = new Pimpl(this);
}
BaseGame::~BaseGame()
{
delete _p;
_engineInit.Free();
Utils::FreeEx(&_alloc);
SDL_Quit();
//CGL::CRender::DoneWin32();
}
void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
{
VERUS_SDL_CENTERED;
//Settings::Make();
//VERUS_QREF_SETTINGS;
//settings.ParseCommandLineArgs(argc, argv);
//settings.LoadValidateSave();
const int ret = SDL_Init(SDL_INIT_EVERYTHING);
if (ret)
throw VERUS_RUNTIME_ERROR << "SDL_Init(), " << ret;
// Allocate memory:
_engineInit.Make();
#ifdef _DEBUG
//Utils::TestAll();
#endif
// Initialization:
//_engineInit.Init(this, new MyRenderDelegate(this), true);
// Configure:
//VERUS_QREF_RENDER;
//VERUS_QREF_SM;
//_p->_camera.SetAspectRatio(render.GetWindowAspectRatio());
//sm.SetCamera(&_p->_camera);
BaseGame_LoadContent();
}
void BaseGame::Run()
{
VERUS_QREF_TIMER;
VERUS_QREF_KM;
//VERUS_QREF_BULLET;
//VERUS_QREF_RENDER;
VERUS_QREF_ASYNC;
VERUS_QREF_ASYS;
SDL_SetRelativeMouseMode(SDL_TRUE);
timer.Update();
SDL_Event event;
bool done = false;
do // The Game Loop.
{
if (_p->_exitOnEscape && km.IsKeyPressed(SDL_SCANCODE_ESCAPE))
Exit();
while (SDL_PollEvent(&event))
{
if (!km.HandleSdlEvent(event))
{
switch (event.type)
{
case SDL_QUIT:
{
done = true;
}
break;
case SDL_WINDOWEVENT:
{
switch (event.window.event)
{
case SDL_WINDOWEVENT_MINIMIZED:
BaseGame_OnDeactivated();
break;
case SDL_WINDOWEVENT_RESTORED:
BaseGame_OnActivated();
break;
}
}
break;
case SDL_USEREVENT:
{
if (_p->HandleUserEvents(&event))
{
SDL_Delay(100);
done = true;
}
}
break;
}
}
}
if (done)
break;
//
// UPDATE
// At this point the user sees a frame drawn some time ago.
//
async.Update();
timer.Update(); // Now we know how much time has passed. Maybe 1 hour!
// Process input for simulation:
if (_p->_defaultCameraMovement)
{
const float speed = km.IsKeyPressed(SDL_SCANCODE_SPACE) ? 20.f : 2.f;
//if (km.IsKeyPressed(SDL_SCANCODE_W))
// _p->_cameraCharacter.MoveFront(speed);
//if (km.IsKeyPressed(SDL_SCANCODE_S))
// _p->_cameraCharacter.MoveFront(-speed);
//if (km.IsKeyPressed(SDL_SCANCODE_A))
// _p->_cameraCharacter.MoveSide(-speed);
//if (km.IsKeyPressed(SDL_SCANCODE_D))
// _p->_cameraCharacter.MoveSide(speed);
}
BaseGame_HandleInput();
//bullet.Simulate(); // x += v*dt.
// Update game state after simulation:
if (_p->_defaultCameraMovement)
{
//_p->_cameraCharacter.Update(); // Get position from Bullet.
//_p->_camera.MoveEyeTo(_p->_cameraCharacter.GetPosition());
//_p->_camera.MoveAtTo(_p->_cameraCharacter.GetPosition() + _p->_cameraCharacter.GetDirectionFront());
//if (Scene::CWater::IsValidSingleton())
{
// VERUS_QREF_WATER;
// if (water.IsInitialized())
// _p->_camera.ExcludeWaterLine();
}
_p->_camera.Update();
}
BaseGame_Update();
asys.Update();
// Draw current frame:
//if (render.Draw())
{
#ifdef VERUS_DEBUG
if (_p->_debugBullet)
bullet.DebugDraw();
#endif
//render.DrawToScreen();
}
km.ResetClickState();
//render.Present(); // This can take a while.
// Show FPS:
if (_p->_showFPS && timer.IsEventEvery(500))
{
char title[64];
CSZ renderer = "";
//switch (render.GetRenderer())
{
//case CGL::RENDERER_OPENGL: renderer = "OpenGL"; break;
//case CGL::RENDERER_DIRECT3D9: renderer = "Direct3D 9"; break;
//case CGL::RENDERER_DIRECT3D11: renderer = "Direct3D 11"; break;
//case CGL::RENDERER_DIRECT3D12: renderer = "Direct3D 12"; break;
}
//sprintf_s(title, "[%s] - %.1f FPS", renderer, render.GetFps());
//SDL_SetWindowTitle(render.GetWindow(), title);
}
} while (!done); // The Game Loop.
BaseGame_UnloadContent();
SDL_SetRelativeMouseMode(SDL_FALSE);
}
void BaseGame::Exit()
{
Utils::ExitSdlLoop();
}
void BaseGame::KeyMapper_OnMouseMove(int x, int y)
{
//VERUS_QREF_CONST_SETTINGS;
//const float fx = x * 0.006f*settings.m_inputMouseSensitivity;
//const float fy = y * 0.006f*settings.m_inputMouseSensitivity;
if (_p->_defaultCameraMovement)
{
//_p->_cameraCharacter.TurnPitch(fy);
//_p->_cameraCharacter.TurnYaw(fx);
}
//BaseGame_OnMouseMove(fx, fy);
}
void BaseGame::KeyMapper_OnKey(int scancode)
{
BaseGame_OnKey(scancode);
}
void BaseGame::KeyMapper_OnChar(wchar_t c)
{
BaseGame_OnChar(c);
}
Scene::RCamera BaseGame::GetCamera()
{
return _p->_camera;
}
#if 0
RCharacter BaseGame::GetCameraCharacter()
{
return _p->_cameraCharacter;
}
#endif
void BaseGame::ActivateDefaultCameraMovement(bool b)
{
_p->_defaultCameraMovement = b;
}
void BaseGame::ShowFPS(bool b)
{
_p->_showFPS = b;
}
void BaseGame::DebugBullet(bool b)
{
_p->_debugBullet = b;
}
bool BaseGame::IsDebugBulletMode() const
{
return _p->_debugBullet;
}

50
Verus/src/Game/BaseGame.h Normal file
View File

@ -0,0 +1,50 @@
#pragma once
namespace verus
{
namespace Game
{
class BaseGame : public Input::KeyMapperDelegate
{
struct Pimpl;
Pimpl* _p = nullptr;
AlignedAllocator _alloc;
EngineInit _engineInit;
public:
BaseGame();
~BaseGame();
void Initialize(VERUS_MAIN_DEFAULT_ARGS);
void Run();
void Exit();
virtual void BaseGame_LoadContent() = 0;
virtual void BaseGame_UnloadContent() = 0;
virtual void BaseGame_HandleInput() = 0;
virtual void BaseGame_Update() = 0;
virtual void BaseGame_Draw() = 0;
virtual void BaseGame_DrawOverlay() = 0;
virtual void BaseGame_OnActivated() {}
virtual void BaseGame_OnDeactivated() {}
virtual void BaseGame_OnMouseMove(float x, float y) {}
virtual void BaseGame_OnKey(int scancode) {}
virtual void BaseGame_OnChar(wchar_t c) {}
virtual void KeyMapper_OnMouseMove(int x, int y) override;
virtual void KeyMapper_OnKey(int scancode) override;
virtual void KeyMapper_OnChar(wchar_t c) override;
// Internal objects:
Scene::RCamera GetCamera();
//RCharacter GetCameraCharacter();
// Configurations:
void ActivateDefaultCameraMovement(bool b);
void ShowFPS(bool b);
void DebugBullet(bool b);
bool IsDebugBulletMode() const;
};
VERUS_TYPEDEFS(BaseGame);
}
}

5
Verus/src/Game/Game.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "State.h"
#include "StateMachine.h"
#include "BaseGame.h"

25
Verus/src/Game/State.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "verus.h"
using namespace verus;
using namespace verus::Game;
bool State::IsValidNextState(PState p)
{
return true;
}
void State::OnEnter(PState pPrev)
{
}
void State::HandleInput()
{
}
void State::Update()
{
}
void State::OnExit(PState pNext)
{
}

21
Verus/src/Game/State.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
namespace verus
{
namespace Game
{
class StateMachine;
struct State
{
StateMachine* _pStateMachine = nullptr;
virtual bool IsValidNextState(State* p);
virtual void OnEnter(State* pPrev);
virtual void HandleInput();
virtual void Update();
virtual void OnExit(State* pNext);
};
VERUS_TYPEDEFS(State);
}
}

View File

@ -0,0 +1,100 @@
#include "verus.h"
using namespace verus;
using namespace verus::Game;
void StateMachine::HandleInput()
{
PcState pCheck = _pCurrentState;
_pCurrentState->_pStateMachine = this;
_pCurrentState->HandleInput();
_changed = (_pCurrentState != pCheck);
}
void StateMachine::Update()
{
VERUS_UPDATE_ONCE_CHECK;
PcState pCheck = _pCurrentState;
_pCurrentState->_pStateMachine = this;
_pCurrentState->Update();
_changed = (_pCurrentState != pCheck);
}
PState StateMachine::GetCurrentState() const
{
return _pCurrentState;
}
PState StateMachine::GetRequestedState() const
{
return _pRequestedState;
}
bool StateMachine::CanEnterState(RState state, bool allowSameState)
{
state._pStateMachine = this;
if (&state == _pCurrentState && !allowSameState)
return false;
return _pCurrentState ? _pCurrentState->IsValidNextState(&state) : true;
}
bool StateMachine::EnterState(RState state, bool allowSameState)
{
state._pStateMachine = this;
if (!CanEnterState(state, allowSameState))
return false;
const UINT32 frame = /*CGL::CRender::I().GetNumFrames();*/ 0;
VERUS_RT_ASSERT(frame != _prevFrame); // Don't change state multiple times per frame!
_prevFrame = frame;
PState pPrevState = _pCurrentState;
if (_pCurrentState)
{
PcState pCheck = _pCurrentState;
_pCurrentState->OnExit(&state);
VERUS_RT_ASSERT(pCheck == _pCurrentState); // Don't change state while changing state!
}
_pCurrentState = &state;
{
PcState pCheck = _pCurrentState;
_pCurrentState->OnEnter(pPrevState);
VERUS_RT_ASSERT(pCheck == _pCurrentState); // Don't change state while changing state!
}
_pRequestedState = nullptr;
return true;
}
bool StateMachine::EnterRequestedState()
{
if (_pRequestedState == _pCurrentState)
_pRequestedState = nullptr;
if (_pRequestedState)
return EnterState(*_pRequestedState);
else
return false;
}
void StateMachine::ReenterState()
{
if (_pCurrentState)
{
{
PcState pCheck = _pCurrentState;
_pCurrentState->OnExit(_pCurrentState);
VERUS_RT_ASSERT(pCheck == _pCurrentState);
}
{
PcState pCheck = _pCurrentState;
_pCurrentState->OnEnter(_pCurrentState);
VERUS_RT_ASSERT(pCheck == _pCurrentState);
}
}
}
void StateMachine::RequestState(RState state)
{
_pRequestedState = &state;
}

View File

@ -0,0 +1,28 @@
#pragma once
namespace verus
{
namespace Game
{
class StateMachine : public Object
{
PState _pCurrentState = nullptr;
PState _pRequestedState = nullptr;
UINT32 _prevFrame = -1;
bool _changed = false;
public:
void HandleInput();
void Update();
PState GetCurrentState() const;
PState GetRequestedState() const;
bool CanEnterState(RState state, bool allowSameState = false);
bool EnterState(RState state, bool allowSameState = false);
bool EnterRequestedState();
void ReenterState();
void RequestState(RState state);
bool IsStateChanged() const { return _changed; }
};
VERUS_TYPEDEFS(StateMachine);
}
}

View File

@ -0,0 +1,39 @@
#pragma once
namespace verus
{
//! This allocator will reserve aligned memory blocks.
class AlignedAllocator : public BaseAllocator
{
INT64 _memUsedTotal = 0;
int _numMalloc = 0;
int _numFree = 0;
int _mallocDelta = 0;
public:
AlignedAllocator() {}
virtual void* malloc(size_t size) override
{
_memUsedTotal += size;
_numMalloc++;
_mallocDelta++;
return _mm_malloc(size, VERUS_MEMORY_ALIGNMENT);
}
virtual void* realloc(void* memory, size_t size) override
{
void* p = _mm_malloc(size, VERUS_MEMORY_ALIGNMENT);
memcpy(p, memory, size);
_mm_free(memory);
return p;
}
virtual void free(void* memory) override
{
_numFree++;
_mallocDelta--;
_mm_free(memory);
}
};
}

View File

@ -0,0 +1,57 @@
#include "verus.h"
using namespace verus;
void* AllocatorAware::operator new(size_t size)
{
VERUS_QREF_UTILS;
return utils.GetAllocator()->malloc(size);
}
void* AllocatorAware::operator new[](size_t size)
{
VERUS_QREF_UTILS;
return utils.GetAllocator()->malloc(size);
}
void AllocatorAware::operator delete(void* p)
{
VERUS_QREF_UTILS;
utils.GetAllocator()->free(p);
}
void AllocatorAware::operator delete[](void* p)
{
VERUS_QREF_UTILS;
utils.GetAllocator()->free(p);
}
void* AllocatorAware::operator new(size_t size, void* place)
{
return place;
}
void AllocatorAware::operator delete(void* p, void* place)
{
}
void* AllocatorAware::UtilsMalloc(size_t size)
{
if (Utils::IsValidSingleton())
{
VERUS_QREF_UTILS;
return utils.GetAllocator()->malloc(size);
}
return nullptr;
}
bool AllocatorAware::UtilsFree(void* p)
{
if (Utils::IsValidSingleton())
{
VERUS_QREF_UTILS;
utils.GetAllocator()->free(p);
return true;
}
return false;
}

View File

@ -0,0 +1,20 @@
#pragma once
namespace verus
{
//! Objects of this class will use the allocator provided by Utils.
class AllocatorAware
{
public:
void* operator new(size_t size);
void* operator new[](size_t size);
void operator delete(void* p);
void operator delete[](void* p);
// Placement:
void* operator new(size_t size, void* place);
void operator delete(void* p, void* place);
static void* UtilsMalloc(size_t size);
static bool UtilsFree(void* p);
};
}

View File

@ -0,0 +1,13 @@
#pragma once
namespace verus
{
class BaseAllocator
{
public:
virtual void* malloc(size_t size) = 0;
virtual void* realloc(void* memory, size_t size) = 0;
virtual void free(void* memory) = 0;
};
VERUS_TYPEDEFS(BaseAllocator);
}

8
Verus/src/Global/Basic.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "Macros.h"
#include "Typedef.h"
#include "EnumClass.h"
#include "QuickRefs.h"
#include "AllocatorAware.h"
#include "Singleton.h"

13
Verus/src/Global/Blob.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
namespace verus
{
struct Blob
{
const BYTE* _p;
const INT64 _size;
Blob(const BYTE* p = nullptr, const INT64 size = 0) : _p(p), _size(size) {}
};
VERUS_TYPEDEFS(Blob);
}

View File

@ -0,0 +1,359 @@
#include "verus.h"
using namespace verus;
// F to I:
BYTE Convert::UnormToUint8(float x) { return BYTE(x*UCHAR_MAX + 0.5f); }
UINT16 Convert::UnormToUint16(float x) { return UINT16(x*USHRT_MAX + 0.5f); }
char Convert::SnormToSint8(float x) { return char((x >= 0) ? x * SCHAR_MAX + 0.5f : x * SCHAR_MAX - 0.5f); }
short Convert::SnormToSint16(float x) { return short((x >= 0) ? x * SHRT_MAX + 0.5f : x * SHRT_MAX - 0.5f); }
// I to F:
float Convert::Uint8ToUnorm(BYTE x) { return x * (1.f / UCHAR_MAX); }
float Convert::Uint16ToUnorm(UINT16 x) { return x * (1.f / USHRT_MAX); }
float Convert::Sint8ToSnorm(char x) { if (x == SCHAR_MIN) x = SCHAR_MIN + 1; return x * (1.f / SCHAR_MAX); }
float Convert::Sint16ToSnorm(short x) { if (x == SHRT_MIN) x = SHRT_MIN + 1; return x * (1.f / SHRT_MAX); }
// AoF to AoI:
void Convert::UnormToUint8(const float* pIn, BYTE* pOut, int num) { VERUS_FOR(i, num) pOut[i] = UnormToUint8(pIn[i]); }
void Convert::UnormToUint16(const float* pIn, UINT16* pOut, int num) { VERUS_FOR(i, num) pOut[i] = UnormToUint16(pIn[i]); }
void Convert::SnormToSint8(const float* pIn, char* pOut, int num) { VERUS_FOR(i, num) pOut[i] = SnormToSint8(pIn[i]); }
void Convert::SnormToSint16(const float* pIn, short* pOut, int num) { VERUS_FOR(i, num) pOut[i] = SnormToSint16(pIn[i]); }
// AoI to AoF:
void Convert::Uint8ToUnorm(const BYTE* pIn, float* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Uint8ToUnorm(pIn[i]); }
void Convert::Uint16ToUnorm(const UINT16* pIn, float* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Uint16ToUnorm(pIn[i]); }
void Convert::Sint8ToSnorm(const char* pIn, float* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Sint8ToSnorm(pIn[i]); }
void Convert::Sint16ToSnorm(const short* pIn, float* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Sint16ToSnorm(pIn[i]); }
// I to I:
short Convert::Sint8ToSint16(char x) { return x * SHRT_MAX / SCHAR_MAX; }
char Convert::Sint16ToSint8(short x) { return x * SCHAR_MAX / SHRT_MAX; }
void Convert::Sint8ToSint16(const char* pIn, short* pOut, int num) { VERUS_FOR(i, num) pOut[i] = Sint8ToSint16(pIn[i]); }
void Convert::Sint16ToSint8(const short* pIn, char* pOut, int num) { VERUS_FOR(i, num) 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] =
{
(in >> 28) & 0xF,
(in >> 20) & 0xF,
(in >> 12) & 0xF,
(in >> 4) & 0xF
};
return (x[0] << 12) | (x[1] << 8) | (x[2] << 4) | (x[3]);
}
UINT32 Convert::Uint4x4ToUint8x4(UINT16 in)
{
int x[4] =
{
(in >> 12) & 0xF,
(in >> 8) & 0xF,
(in >> 4) & 0xF,
(in >> 0) & 0xF
};
return (x[0] << 28) | (x[1] << 20) | (x[2] << 12) | (x[3] << 4);
}
UINT32 Convert::Color16To32(UINT16 in)
{
const int b = ((in >> 0) & 0x1F) << 3;
const int g = ((in >> 5) & 0x3F) << 2;
const int r = ((in >> 11) & 0x1F) << 3;
return VERUS_COLOR_RGBA(r, g, b, 255);
}
void Convert::ColorInt32ToFloat(UINT32 in, float* out, bool sRGB)
{
const float gamma = sRGB ? 2.2f : 1.f;
out[0] = pow(float(int((in >> 0) & 0xFF))*(1 / 255.f), gamma);
out[1] = pow(float(int((in >> 8) & 0xFF))*(1 / 255.f), gamma);
out[2] = pow(float(int((in >> 16) & 0xFF))*(1 / 255.f), gamma);
out[3] = float(int((in >> 24) & 0xFF))*(1 / 255.f);
}
UINT32 Convert::ColorFloatToInt32(const float* in, bool sRGB)
{
const float gamma = sRGB ? 1 / 2.2f : 1.f;
const int r = Math::Clamp(int(pow(in[0], gamma)*255.5f), 0, 255);
const int g = Math::Clamp(int(pow(in[1], gamma)*255.5f), 0, 255);
const int b = Math::Clamp(int(pow(in[2], gamma)*255.5f), 0, 255);
const int a = Math::Clamp(int(in[3] * 255.5f), 0, 255);
return VERUS_COLOR_RGBA(r, g, b, a);
}
void Convert::ColorTextToFloat4(CSZ sz, float* out, bool sRGB)
{
int color[4] = {};
if (!sz)
{
}
else if (6 == strlen(sz) && !strchr(sz, ' '))
{
color[0] = Str::ByteFromHex(sz + 0);
color[1] = Str::ByteFromHex(sz + 2);
color[2] = Str::ByteFromHex(sz + 4);
color[3] = 255;
}
else if (8 == strlen(sz) && !strchr(sz, ' '))
{
color[0] = Str::ByteFromHex(sz + 0);
color[1] = Str::ByteFromHex(sz + 2);
color[2] = Str::ByteFromHex(sz + 4);
color[3] = Str::ByteFromHex(sz + 6);
}
else
{
const int num = sscanf(sz, "%d %d %d %d",
color + 0,
color + 1,
color + 2,
color + 3);
if (3 == num)
color[3] = 255;
}
const float gamma = sRGB ? 2.2f : 1.f;
out[0] = pow(float(color[0])*(1 / 255.f), gamma);
out[1] = pow(float(color[1])*(1 / 255.f), gamma);
out[2] = pow(float(color[2])*(1 / 255.f), gamma);
out[3] = float(color[3])*(1 / 255.f);
}
UINT32 Convert::ColorTextToInt32(CSZ sz)
{
int color[4] = {};
if (6 == strlen(sz) && !strchr(sz, ' '))
{
color[0] = Str::ByteFromHex(sz + 0);
color[1] = Str::ByteFromHex(sz + 2);
color[2] = Str::ByteFromHex(sz + 4);
color[3] = 255;
}
else if (8 == strlen(sz) && !strchr(sz, ' '))
{
color[0] = Str::ByteFromHex(sz + 0);
color[1] = Str::ByteFromHex(sz + 2);
color[2] = Str::ByteFromHex(sz + 4);
color[3] = Str::ByteFromHex(sz + 6);
}
else
{
sscanf(sz, "%d %d %d %d",
color + 0,
color + 1,
color + 2,
color + 3);
}
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;
return UINT16(Math::Clamp((f - mn) / range * USHRT_MAX, 0.f, float(USHRT_MAX)));
}
float Convert::DequantizeFloat(UINT16 i, float mn, float mx)
{
const float range = mx - mn;
return float(i) / USHRT_MAX * range + mn;
}
BYTE Convert::QuantizeFloatToByte(float f, float mn, float mx)
{
const float range = mx - mn;
return BYTE(Math::Clamp((f - mn) / range * UCHAR_MAX, 0.f, float(UCHAR_MAX)));
}
float Convert::DequantizeFloatFromByte(BYTE i, float mn, float mx)
{
const float range = mx - mn;
return float(i) / UCHAR_MAX * range + mn;
}
String Convert::ToBase64(const Vector<BYTE>& vBin)
{
Vector<char> vBase64;
vBase64.resize(vBin.size() * 2);
base64_encodestate state;
base64_init_encodestate(&state);
const int len = base64_encode_block(reinterpret_cast<CSZ>(vBin.data()), Utils::Cast32(vBin.size()), vBase64.data(), &state);
const int len2 = base64_encode_blockend(&vBase64[len], &state);
vBase64.resize(len + len2);
return String(vBase64.begin(), vBase64.end());
}
Vector<BYTE> Convert::ToBinFromBase64(CSZ base64)
{
Vector<BYTE> vBin;
vBin.resize(strlen(base64));
base64_decodestate state;
base64_init_decodestate(&state);
const int len = base64_decode_block(base64, Utils::Cast32(strlen(base64)), reinterpret_cast<SZ>(vBin.data()), &state);
vBin.resize(len);
return vBin;
}
String Convert::ByteToHex(BYTE b)
{
static const char hexval[] = "0123456789ABCDEF";
char ret[3];
ret[0] = hexval[(b >> 4) & 0xF];
ret[1] = hexval[(b >> 0) & 0xF];
ret[2] = 0;
return ret;
}
String Convert::ToHex(const Vector<BYTE>& vBin)
{
static const char hexval[] = "0123456789ABCDEF";
const int num = Utils::Cast32(vBin.size());
Vector<char> vHex;
vHex.resize(num * 2);
VERUS_FOR(i, num)
{
vHex[(i << 1) + 0] = hexval[(vBin[i] >> 4) & 0xF];
vHex[(i << 1) + 1] = hexval[(vBin[i] >> 0) & 0xF];
}
return String(vHex.begin(), vHex.end());
}
Vector<BYTE> Convert::ToBinFromHex(CSZ hex)
{
Vector<BYTE> vBin;
const size_t len = strlen(hex);
if (0 == len || (len & 0x1))
return vBin;
const int lenBin = Utils::Cast32(len / 2);
vBin.resize(lenBin);
VERUS_FOR(i, lenBin)
{
const char hi = hex[(i << 1)];
const char lo = hex[(i << 1) + 1];
if /**/ (hi >= '0' && hi <= '9') vBin[i] = ((hi - '0')) << 4;
else if (hi >= 'a' && hi <= 'f') vBin[i] = ((hi - 'a') + 10) << 4;
else if (hi >= 'A' && hi <= 'F') vBin[i] = ((hi - 'A') + 10) << 4;
if /**/ (lo >= '0' && lo <= '9') vBin[i] |= (lo - '0');
else if (lo >= 'a' && lo <= 'f') vBin[i] |= (lo - 'a') + 10;
else if (lo >= 'A' && lo <= 'F') vBin[i] |= (lo - 'A') + 10;
}
return vBin;
}
Vector<BYTE> Convert::ToMd5(const Vector<BYTE>& vBin)
{
MD5Hash md5;
md5.update(vBin.data(), Utils::Cast32(vBin.size()));
md5.finalize();
Vector<BYTE> vOut = ToBinFromHex(_C(md5.hexdigest()));
return vOut;
}
String Convert::ToMd5String(const Vector<BYTE>& vBin)
{
return ToHex(ToMd5(vBin));
}
void Convert::Test()
{
BYTE dataUint8[] = { 0, 127, 255 };
UINT16 dataUint16[] = { 0, 127, 65535, 65534 };
char dataSint8[] = { 64, -127, -128 };
short dataSint16[] = { 32767, -32766, -32768, -32767 };
float dataFloat[4];
Uint8ToUnorm(dataUint8, dataFloat, 3);
UnormToUint8(dataFloat, dataUint8, 3);
Uint16ToUnorm(dataUint16, dataFloat, 4);
UnormToUint16(dataFloat, dataUint16, 4);
Sint8ToSnorm(dataSint8, dataFloat, 3);
SnormToSint8(dataFloat, dataSint8, 3);
Sint16ToSnorm(dataSint16, dataFloat, 4);
SnormToSint16(dataFloat, dataSint16, 4);
Vector<BYTE> vBin;
vBin.resize(16);
Random random;
random.NextArray(vBin);
const String base64 = ToBase64(vBin);
const Vector<BYTE> vBinBase64 = ToBinFromBase64(_C(base64));
const String hex = ToHex(vBin);
const Vector<BYTE> vBinHex = ToBinFromHex(_C(hex));
VERUS_RT_ASSERT(std::equal(vBin.begin(), vBin.end(), vBinHex.begin()));
VERUS_RT_ASSERT(std::equal(vBin.begin(), vBin.end(), vBinBase64.begin()));
CSZ txt = "Hello World 1! Hello World 2! Hello World 3!";
vBin.assign(txt, txt + strlen(txt));
const Vector<BYTE> vMd5 = ToMd5(vBin);
const String md5 = ToMd5String(vBin);
VERUS_RT_ASSERT(md5 == "C84AAFD3D09E719514977BF3624F4D85");
}

View File

@ -0,0 +1,82 @@
#pragma once
namespace verus
{
//! This class converts different data types.
class Convert
{
public:
// Single floating-point to integer:
static BYTE UnormToUint8(float x);
static UINT16 UnormToUint16(float x);
static char SnormToSint8(float x);
static short SnormToSint16(float x);
// Single integer to Floating-point:
static float Uint8ToUnorm(BYTE x);
static float Uint16ToUnorm(UINT16 x);
static float Sint8ToSnorm(char x);
static float Sint16ToSnorm(short x);
// Array of floating-points to integers:
static void UnormToUint8(const float* pIn, BYTE* pOut, int num);
static void UnormToUint16(const float* pIn, UINT16* pOut, int num);
static void SnormToSint8(const float* pIn, char* pOut, int num);
static void SnormToSint16(const float* pIn, short* pOut, int num);
// Array of integers to floating-points:
static void Uint8ToUnorm(const BYTE* pIn, float* pOut, int num);
static void Uint16ToUnorm(const UINT16* pIn, float* pOut, int num);
static void Sint8ToSnorm(const char* pIn, float* pOut, int num);
static void Sint16ToSnorm(const short* pIn, float* pOut, int num);
// Integers to integers:
static short Sint8ToSint16(char x);
static char Sint16ToSint8(short x);
static void Sint8ToSint16(const char* pIn, short* pOut, int num);
static void Sint16ToSint8(const short* pIn, char* pOut, int num);
/* ??? */ 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);
// Colors:
static UINT32 Color16To32(UINT16 in);
static void ColorInt32ToFloat(UINT32 in, float* out, bool sRGB = true);
static UINT32 ColorFloatToInt32(const float* in, bool sRGB = true);
static void ColorTextToFloat4(CSZ sz, float* out, bool sRGB = true);
static UINT32 ColorTextToInt32(CSZ sz);
// Floating-point quantization:
static UINT16 QuantizeFloat(float f, float mn, float mx);
static float DequantizeFloat(UINT16 i, float mn, float mx);
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);
// Hexadecimal:
static String ByteToHex(BYTE b);
static String ToHex(const Vector<BYTE>& vBin);
static Vector<BYTE> ToBinFromHex(CSZ hex);
// MD5:
static Vector<BYTE> ToMd5(const Vector<BYTE>& vBin);
static String ToMd5String(const Vector<BYTE>& vBin);
static void Test();
};
}

View File

@ -0,0 +1,122 @@
#include "verus.h"
using namespace verus;
void EngineInit::Make()
{
#if 0
if (_makeUtils)
Make_Utils();
if (_makeNet)
Make_Net();
if (_makeIO)
Make_IO();
if (_makeInput)
Make_Input();
if (_makeAudio)
Make_Audio();
if (_makeCGL)
Make_CGL();
if (_makePhysics)
Make_Physics();
if (_makeEffects)
Make_Effects();
if (_makeExtra)
Make_Extra();
if (_makeScene)
Make_Scene();
if (_makeGUI)
Make_GUI();
#endif
}
void EngineInit::Free()
{
#if 0
if (_makeGUI)
Free_GUI();
if (_makeScene)
Free_Scene();
if (_makeExtra)
Free_Extra();
if (_makeEffects)
Free_Effects();
if (_makePhysics)
Free_Physics();
if (_makeCGL)
Free_CGL();
if (_makeAudio)
Free_Audio();
if (_makeInput)
Free_Input();
if (_makeIO)
Free_IO();
if (_makeNet)
Free_Net();
if (_makeUtils)
Free_Utils();
#endif
}
void EngineInit::Init(Input::PKeyMapperDelegate pKeyMapperDelegate, CGI::RenderDelegate* pRenderDelegate, bool createWindow)
{
#if 0
if (_makeUtils)
Utils::CTimer::I().Init();
if (_makeIO)
IO::CAsync::I().Init();
// "A.P.I.":
if (_makeAudio)
Audio::CAudio::I().Init();
if (_makePhysics)
Physics::CBullet::I().Init();
if (_makeInput)
{
Input::CKeyMapper::I().Init();
Input::CKeyMapper::I().SetDelegate(pKeyMapperDelegate);
}
if (_makeCGL)
{
CGL::CRender::I().Init(pRenderDelegate, createWindow);
#ifdef _WIN32
CGL::CRender::InitWin32(_C(CUtils::I().GetWritablePath()), 101);
#endif
}
// Static init:
if (_makeEffects)
Effects::CParticles::InitStatic();
if (_makeGUI)
GUI::CFont::InitStatic();
if (_makeScene)
{
Scene::CMesh::InitStatic();
Scene::CTerrain::InitStatic();
Scene::CForest::InitStatic();
}
// Helpers:
if (_makeCGL)
CGL::CDebugRender::I().Init();
if (_makeScene)
Scene::CHelpers::I().Init();
// Effects:
if (_makeEffects)
{
Effects::CBlur::I().Init();
Effects::CBloom::I().Init();
Effects::CSsao::I().Init();
}
// Materials & textures:
if (_makeScene)
Scene::CMaterialManager::I().Init();
if (_makeGUI)
GUI::CGUI::I().Init();
#endif
}

View File

@ -0,0 +1,38 @@
#pragma once
namespace verus
{
namespace Input
{
struct KeyMapperDelegate;
}
namespace CGI
{
struct RenderDelegate;
}
}
namespace verus
{
class EngineInit
{
public:
bool _makeUtils = true;
bool _makeNet = true;
bool _makeIO = true;
bool _makeInput = true;
bool _makeAudio = true;
bool _makeCGL = true;
bool _makePhysics = true;
bool _makeEffects = true;
bool _makeExtra = false;
bool _makeScene = true;
bool _makeGUI = true;
void Make();
void Free();
void Init(Input::KeyMapperDelegate* pKeyMapperDelegate, CGI::RenderDelegate* pRenderDelegate, bool createWindow);
};
VERUS_TYPEDEFS(EngineInit);
}

View File

@ -0,0 +1,42 @@
#pragma once
namespace verus
{
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
inline U operator&(T a, T b)
{
return static_cast<U>(a)&static_cast<U>(b);
}
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
inline T operator|(T a, T b)
{
return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
}
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
inline T& operator&=(T& a, T b)
{
a = static_cast<T>(static_cast<U>(a)&static_cast<U>(b));
return a;
}
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
inline T& operator|=(T& a, T b)
{
a = static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
return a;
}
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
inline T operator~(T a)
{
return static_cast<T>(~static_cast<U>(a));
}
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>, typename U = std::underlying_type_t<T>>
inline U operator+(T a)
{
return static_cast<U>(a);
}
}

View File

@ -0,0 +1,15 @@
#include "verus.h"
int g_numSingletonAlloc;
namespace verus
{
void Make_Global()
{
Timer::Make();
}
void Free_Global()
{
Timer::Free();
}
}

26
Verus/src/Global/Global.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#define VERUS_MEMORY_ALIGNMENT 16
#include "BaseAllocator.h"
#include "AlignedAllocator.h"
#include "STL.h"
#include "Store.h"
#include "Blob.h"
#include "Random.h"
#include "Utils.h"
#include "Parallel.h"
#include "Range.h"
#include "Object.h"
#include "Lockable.h"
#include "Linear.h"
#include "Str.h"
#include "Convert.h"
#include "Timer.h"
#include "EngineInit.h"
namespace verus
{
void Make_Global();
void Free_Global();
}

103
Verus/src/Global/Linear.h Normal file
View File

@ -0,0 +1,103 @@
#pragma once
namespace verus
{
template<typename T>
class Linear
{
T _value;
T _speed;
T _min;
T _max;
public:
Linear() : _value(0), _speed(0), _min(0), _max(1) {}
T& GetValue() { return _value; }
const T& GetValue() const { return _value; }
T& GetSpeed() { return _speed; }
const T& GetSpeed() const { return _speed; }
void Set(const T& value, const T& speed)
{
_value = value;
_speed = speed;
}
void SetValue(const T& value)
{
_value = value;
}
void SetSpeed(const T& speed)
{
_speed = speed;
}
void SetLimits(const T& mn, const T& mx)
{
_min = mn;
_max = mx;
}
void Plan(const T& value, float time)
{
const T delta = value - _value;
_speed = delta / time;
}
void SpinTo(const T& value, float speed)
{
if (value >= _value)
{
_speed = speed;
_min = _value;
_max = value;
}
else
{
_speed = -speed;
_min = value;
_max = _value;
}
}
void Reverse()
{
_speed = -_speed;
if (_speed >= 0)
{
_max = -_min;
_min = _value;
}
else
{
_min = -_max;
_max = _value;
}
}
void UpdateUnlimited(float dt)
{
_value += _speed * dt;
}
void UpdateClamped(float dt)
{
_value += _speed * dt;
_value = Math::Clamp(_value, _min, _max);
}
void UpdateClampedV(float dt)
{
_value += _speed * dt;
_value = _value.Clamp(_min, _max);
}
void WrapFloatV()
{
_value = _value.Mod(1);
}
};
}

View File

@ -0,0 +1,17 @@
#pragma once
#define VERUS_LOCK(o) std::unique_lock<std::mutex> lock = std::unique_lock<std::mutex>((o).GetMutex())
#define VERUS_LOCK_EX(o, no) std::unique_lock<std::mutex> lock = no ?\
std::unique_lock<std::mutex>((o).GetMutex(), std::defer_lock) : std::unique_lock<std::mutex>((o).GetMutex())
namespace verus
{
class Lockable
{
std::mutex _mutex;
public:
std::mutex& GetMutex() { return _mutex; }
};
VERUS_TYPEDEFS(Lockable);
}

66
Verus/src/Global/Macros.h Normal file
View File

@ -0,0 +1,66 @@
#pragma once
#define VERUS_CRNL "\r\n"
#define VERUS_WHITESPACE " \t\r\n"
#define VERUS_ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
#define VERUS_LITERAL_LENGTH(x) (sizeof(x)-1)
#define VERUS_ZERO_MEM(x) memset(&x, 0, sizeof(x))
#define VERUS_BUFFER_OFFSET(x) ((char*)nullptr+(x))
#define VERUS_BITMASK_SET(flags, mask) ((flags) |= (mask))
#define VERUS_BITMASK_UNSET(flags, mask) ((flags) &= ~(mask))
#define VERUS_MAIN_DEFAULT_ARGS int argc, char* argv[]
#define VERUS_P(x) private: x; public:
#define VERUS_PD(x) protected: x; private:
#define VERUS_FRIEND(c, type) friend c type; type
#define VERUS_SMART_DELETE(p) {if(p) {delete p; p = nullptr;}}
#define VERUS_SMART_DELETE_ARRAY(p) {if(p) {delete [] p; p = nullptr;}}
#define _C(x) ((x).c_str())
#define VERUS_P_FOR(i, to) Parallel::For(0, to, [&](int i)
#define VERUS_FOR(i, to) for(int i = 0; i < to; ++i)
#define VERUS_FOREACH(T, v, it) for(T::iterator it=(v).begin(), itEnd=(v).end(); it!=itEnd; ++it)
#define VERUS_FOREACH_CONST(T, v, it) for(T::const_iterator it=(v).begin(), itEnd=(v).end(); it!=itEnd; ++it)
#define VERUS_FOREACH_REVERSE(T, v, it) for(T::reverse_iterator it=(v).rbegin(), itEnd=(v).rend(); it!=itEnd; ++it)
#define VERUS_FOREACH_REVERSE_CONST(T, v, it) for(T::const_reverse_iterator it=(v).rbegin(), itEnd=(v).rend(); it!=itEnd; ++it)
#define VERUS_FOREACH_X(T, v, it) for(T::iterator it=(v).begin(), itEnd=(v).end(); it!=itEnd;)
#define VERUS_FOREACH_X_CONST(T, v, it) for(T::const_iterator it=(v).begin(), itEnd=(v).end(); it!=itEnd;)
#define VERUS_FOREACH_X_REVERSE(T, v, it) for(T::reverse_iterator it=(v).rbegin(), itEnd=(v).rend(); it!=itEnd;)
#define VERUS_FOREACH_X_REVERSE_CONST(T, v, it) for(T::const_reverse_iterator it=(v).rbegin(), itEnd=(v).rend(); it!=itEnd;)
// For loops with erase() use this:
#define VERUS_WHILE(T, v, it) T::iterator it=(v).begin(); while(it!=(v).end())
#define VERUS_IF_FOUND_IN(T, map, x, it)\
auto it = map.find(x);\
if(it != map.end())
#define VERUS_TYPEDEFS(x)\
typedef x& R##x;\
typedef const x& Rc##x;\
typedef x* P##x;\
typedef const x* Pc##x
// Circular buffer's size must be power of two:
#define VERUS_CIRCULAR_ADD(x, mx)\
x++;\
x &= mx-1
#define VERUS_CIRCULAR_IS_FULL(r, w, mx)\
(((w+1)&(mx-1)) == r)
// Colors:
#define VERUS_COLOR_RGBA(r,g,b,a) ((UINT32)((((a)&0xFF)<<24)|(((b)&0xFF)<<16)|(((g)&0xFF)<<8)|((r)&0xFF)))
#define VERUS_COLOR_TO_D3D(color) (((color)&0xFF00FF00)|(((color)>>16)&0xFF)|(((color)&0xFF)<<16))
#define VERUS_COLOR_WHITE VERUS_COLOR_RGBA(255, 255, 255, 255)
#define VERUS_COLOR_BLACK VERUS_COLOR_RGBA(0, 0, 0, 255)
#ifdef _WIN32
# define VERUS_SDL_CENTERED _putenv("SDL_VIDEO_WINDOW_POS"); _putenv("SDL_VIDEO_CENTERED=1")
#else
# define VERUS_SDL_CENTERED putenv("SDL_VIDEO_WINDOW_POS"); putenv("SDL_VIDEO_CENTERED=1")
#endif

View File

@ -0,0 +1,39 @@
#include "verus.h"
using namespace verus;
Object::Object()
{
_flags = 0;
}
Object::~Object()
{
VERUS_RT_ASSERT(!IsInitialized());
}
void Object::Init()
{
VERUS_RT_ASSERT(!IsInitialized());
SetFlag(ObjectFlags::init);
}
void Object::Done()
{
_flags = 0;
}
#ifdef VERUS_DEBUG
void Object::UpdateOnceCheck()
{
const UINT32 numFrames = CGL::CRender::I().GetNumFrames();
VERUS_RT_ASSERT(_updateOnceFrame <= numFrames);
_updateOnceFrame = numFrames + 1;
}
void Object::UpdateOnceCheckDraw()
{
const UINT32 numFrames = CGL::CRender::I().GetNumFrames();
VERUS_RT_ASSERT(_updateOnceFrame > numFrames);
}
#endif

57
Verus/src/Global/Object.h Normal file
View File

@ -0,0 +1,57 @@
#pragma once
#ifdef VERUS_DEBUG
# define VERUS_UPDATE_ONCE_CHECK UpdateOnceCheck()
# define VERUS_UPDATE_ONCE_CHECK_DRAW UpdateOnceCheckDraw()
#else
# define VERUS_UPDATE_ONCE_CHECK
# define VERUS_UPDATE_ONCE_CHECK_DRAW
#endif
#define VERUS_INIT()\
Object::Init();
#define VERUS_DONE(x)\
if(Object::IsInitialized()) {\
Object::Done();\
this->~x();\
new(this) x();}
namespace verus
{
struct ObjectFlags
{
enum
{
init = (1 << 0),
user = (1 << 1)
};
};
class Object
{
std::atomic_uint _flags;
#ifdef VERUS_DEBUG
UINT32 _updateOnceFrame = 0;
#endif
protected:
Object();
virtual ~Object();
void Init();
void Done();
#ifdef VERUS_DEBUG
void UpdateOnceCheck();
void UpdateOnceCheckDraw();
#endif
public:
bool IsInitialized() const { return _flags & ObjectFlags::init; }
bool IsFlagSet(UINT32 mask) const { return !!(_flags&mask); }
void SetFlag(UINT32 mask) { _flags |= mask; }
void ResetFlag(UINT32 mask) { _flags &= ~mask; }
};
}

View File

@ -0,0 +1,44 @@
#pragma once
namespace verus
{
class Parallel
{
public:
template<typename TFunc>
static void For(int from, int to, TFunc func, int minTime = 10, int minShare = 1)
{
const int total = to - from;
VERUS_RT_ASSERT(minShare <= total);
const UINT32 numCoresLimit = total / minShare;
const int numCores = Math::Min(std::thread::hardware_concurrency(), numCoresLimit);
const int numExThreads = numCores - 1;
const int share = total / numCores;
const int extra = total - share * numExThreads;
std::vector<std::thread> v;
v.reserve(numExThreads);
const std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
VERUS_FOR(i, numExThreads)
{
v.push_back(std::thread([i, share, func]()
{
const int from = share * i;
const int to = from + share;
for (int j = from; j < to; ++j)
func(j);
}));
}
{
const int from = share * numExThreads;
const int to = from + extra;
for (int j = from; j < to; ++j)
func(j);
}
VERUS_FOREACH(std::vector<std::thread>, v, it)
it->join();
const std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
const std::chrono::milliseconds d = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
//VERUS_RT_ASSERT(d.count() >= minTime);
}
};
}

View File

@ -0,0 +1,29 @@
#pragma once
#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_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_CONST_SETTINGS RcSettings settings = CSettings::IConst()
#define VERUS_QREF_DEPTH Effects::RDepth depth = Effects::Depth::I()
#define VERUS_QREF_DR CGL::RDebugRender dr = CGL::DebugRender::I()
#define VERUS_QREF_FSYS IO::RFileSys fsys = IO::FileSys::I()
#define VERUS_QREF_GAME Game::RGame game = Game::Game::I()
#define VERUS_QREF_GRASS Scene::RGrass grass = Scene::Grass::I()
#define VERUS_QREF_GUI GUI::RGUI gui = GUI::GUI::I()
#define VERUS_QREF_HELPERS Scene::RHelpers helpers = Scene::Helpers::I()
#define VERUS_QREF_KM Input::RKeyMapper km = Input::KeyMapper::I()
#define VERUS_QREF_LS Scene::RLandscape ls = Scene::Landscape::I()
#define VERUS_QREF_MM Scene::RMaterialManager mm = Scene::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_RENDER CGL::RRender render = CGL::Render::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_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_WATER Scene::RWater water = Scene::Water::I()

View File

@ -0,0 +1,56 @@
#include "verus.h"
using namespace verus;
Random::Random()
{
std::random_device rd;
Seed(rd());
}
Random::Random(UINT32 seed) :
_mt(seed)
{
}
Random::~Random()
{
}
UINT32 Random::Next()
{
return _mt();
}
double Random::NextDouble()
{
return static_cast<double>(Next()) / std::numeric_limits<UINT32>::max();
}
float Random::NextFloat()
{
return static_cast<float>(Next()) / std::numeric_limits<UINT32>::max();
}
void Random::NextArray(UINT32* p, int num)
{
VERUS_FOR(i, num)
p[i] = Next();
}
void Random::NextArray(float* p, int num)
{
VERUS_FOR(i, num)
p[i] = NextFloat();
}
void Random::NextArray(Vector<BYTE>& v)
{
VERUS_FOREACH(Vector<BYTE>, v, it)
*it = Next();
}
void Random::Seed(UINT32 seed)
{
_mt.seed(seed);
}

27
Verus/src/Global/Random.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
namespace verus
{
class Random
{
std::mt19937 _mt;
public:
Random();
Random(UINT32 seed);
~Random();
UINT32 Next();
double NextDouble();
float NextFloat();
void NextArray(UINT32* p, int num);
void NextArray(float* p, int num);
void NextArray(Vector<BYTE>& v);
std::mt19937& GetGenerator() { return _mt; }
void Seed(UINT32 seed);
};
VERUS_TYPEDEFS(Random);
}

19
Verus/src/Global/Range.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
namespace verus
{
template<typename T>
class Range
{
public:
T _min;
T _max;
Range() : _min(0), _max(0) {}
Range(T x) : _min(x), _max(x) {}
Range(T mn, T mx) : _min(mn), _max(mx) { VERUS_RT_ASSERT(_min <= _max); }
T GetRange() const { return _max - _min; }
T GetRandomValue() const { return _min + Utils::I().GetRandom().NextFloat()*GetRange(); }
};
}

112
Verus/src/Global/STL.h Normal file
View File

@ -0,0 +1,112 @@
#pragma once
namespace verus
{
//! Custom allocator for the Standard Template Library. Will try to use the allocator provided by Utils.
template<typename T>
class AllocatorAwareSTL
{
void operator=(const AllocatorAwareSTL&);
public:
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
AllocatorAwareSTL() {}
AllocatorAwareSTL(const AllocatorAwareSTL&) {}
~AllocatorAwareSTL() {}
template<typename _Other>
AllocatorAwareSTL(const AllocatorAwareSTL<_Other>& other) {}
template<typename U>
struct rebind
{
typedef AllocatorAwareSTL<U> other;
};
pointer address(reference r) const
{
return &r;
}
const_pointer address(const_reference r) const
{
return &r;
}
pointer allocate(size_type n)
{
pointer p = static_cast<pointer>(AllocatorAware::UtilsMalloc(n * sizeof(value_type)));
if (p)
{
return p;
}
else
{
p = static_cast<pointer>(malloc(n * sizeof(value_type)));
char txt[80];
sprintf_s(txt, "allocate(), malloc() 0x%p", p);
VERUS_LOG_DEBUG(txt);
return p;
}
}
void deallocate(pointer p, size_type)
{
if (!AllocatorAware::UtilsFree(p))
{
char txt[80];
sprintf_s(txt, "deallocate(), free() 0x%p", p);
VERUS_LOG_DEBUG(txt);
free(p);
}
}
void construct(pointer p, const value_type& val)
{
new(p)value_type(val);
}
void destroy(pointer p)
{
p->~value_type();
}
size_type max_size() const
{
return ULONG_MAX / sizeof(value_type);
}
};
//! This function will compare two allocators.
template<typename T>
bool operator==(const AllocatorAwareSTL<T>& l, const AllocatorAwareSTL<T>& r)
{
return true;
}
//! This function will compare two allocators.
template<typename T>
bool operator!=(const AllocatorAwareSTL<T>& l, const AllocatorAwareSTL<T>& r)
{
return !(l == r);
}
}
namespace verus
{
template<typename T> using Vector = std::vector <T, AllocatorAwareSTL<T>>;
template<typename T> using List = std::list <T, AllocatorAwareSTL<T>>;
template<typename T> using Set = std::set <T, std::less<T>, AllocatorAwareSTL<T>>;
template<typename T> using MultiSet = std::multiset <T, std::less<T>, AllocatorAwareSTL<T>>;
template<typename T> using HashSet = std::unordered_set <T, std::hash<T>, std::equal_to<T>, AllocatorAwareSTL<T>>;
template<typename T, typename U> using Map = std::map <T, U, std::less<T>, AllocatorAwareSTL<T>>;
template<typename T, typename U> using MultiMap = std::multimap <T, U, std::less<T>, AllocatorAwareSTL<T>>;
template<typename T, typename U> using HashMap = std::unordered_map <T, U, std::hash<T>, std::equal_to<T>, AllocatorAwareSTL<T>>;
}

View File

@ -0,0 +1,74 @@
#pragma once
extern int g_numSingletonAlloc;
namespace verus
{
//! Restricts the instantiation of a class to one object.
template<typename T>
class Singleton : public AllocatorAware
{
static T* s_pSingleton;
Singleton(const Singleton& that);
Singleton& operator=(const Singleton& that);
public:
Singleton()
{
s_pSingleton = static_cast<T*>(this);
}
virtual ~Singleton()
{
}
static inline void Make()
{
if (s_pSingleton)
return;
new T();
g_numSingletonAlloc++;
}
static inline void Free()
{
if (s_pSingleton)
{
g_numSingletonAlloc--;
delete s_pSingleton;
}
s_pSingleton = nullptr;
}
static inline T& I() { Test(); return *s_pSingleton; }
static inline T* P() { Test(); return s_pSingleton; }
static inline const T& IConst() { Test(); return *s_pSingleton; }
static inline const T* PConst() { Test(); return s_pSingleton; }
static inline bool IsValidSingleton()
{
return s_pSingleton != nullptr;
}
static inline void Assign(T* p) { s_pSingleton = p; }
static inline void Test()
{
#ifdef _DEBUG
//if (!IsValidSingleton())
// VERUS_LOG_DEBUG(T::GetSingletonFailMessage());
//VERUS_RT_ASSERT(s_pSingleton);
#endif
};
static inline CSZ GetSingletonFailMessage() { return "Singleton FAIL.\r\n"; }
static inline void TestAllocCount()
{
//VERUS_RT_ASSERT(!g_numSingletonAlloc);
}
};
template<typename T> T* Singleton<T>::s_pSingleton = nullptr;
}

177
Verus/src/Global/Store.h Normal file
View File

@ -0,0 +1,177 @@
#pragma once
namespace verus
{
//! A convenient way to store a collection of objects.
//! It's a good idea not to use new/delete explicitly. Use STL allocator.
//! 'Unique' class uses map and supports reference counting.
//! The Insert method returns a raw pointer which should be wrapped inside a Ptr.
//!
//! Types of pointers:
//! - raw pointer - very dumb, no automatic initialization.
//! - Ptr wrapper - like a smart pointer, but even smarter.
//! - Pwn wrapper - owning Ptr, basically calls Done in destructor.
//! Use Ptr for function parameters. Use Pwn for class members.
//!
template<typename TValue>
class Store
{
protected:
typedef List<TValue> TList;
TList _list;
public:
TValue* Insert()
{
_list.emplace_back();
return &_list.back();
}
void Delete(TValue* p)
{
_list.remove_if([p](const TValue& v)
{
return p == &v;
});
}
void DeleteAll()
{
_list.clear();
}
TValue& GetStoredAt(int index)
{
auto it = _list.begin();
std::advance(it, index);
return *it;
}
int GetNumStored() const
{
return _list.size();
}
};
template<typename TKey, typename TValue>
class StoreUnique
{
protected:
typedef Map<TKey, TValue> TMap;
TMap _map;
public:
TValue* Insert(const TKey& key)
{
VERUS_IF_FOUND_IN(TMap, _map, key, it)
{
it->second.AddRef();
return &it->second;
}
return &_map[key];
}
TValue* Find(const TKey& key)
{
VERUS_IF_FOUND_IN(TMap, _map, key, it)
return &it->second;
return nullptr;
}
void Delete(const TKey& key)
{
VERUS_IF_FOUND_IN(TMap, _map, key, it)
{
if (it->second.Done())
_map.erase(it);
}
}
void DeleteAll()
{
for (auto& x : _map)
{
while (!x.second.Done());
}
_map.clear();
}
TValue& GetStoredAt(int index)
{
auto it = _map.begin();
std::advance(it, index);
return *it;
}
int GetNumStored() const
{
return _map.size();
}
};
template<typename T>
class Ptr
{
protected:
T* _p;
public:
Ptr(T* p = nullptr) : _p(p) {}
~Ptr() {}
T& operator*() const { return *_p; }
T* operator->() const { return _p; }
explicit operator bool() const { return !!_p; }
bool operator==(const Ptr<T>& that) const { return _p == that._p; }
bool operator!=(const Ptr<T>& that) const { return _p != that._p; }
bool operator<(const Ptr<T>& that) const { return _p < that._p; }
T* Attach(T* ptr)
{
T* p = _p;
_p = ptr;
return p;
}
T* Detach()
{
T* p = _p;
_p = nullptr;
return p;
}
};
template<typename T, int NUM>
class Pwns
{
T _t[NUM];
public:
Pwns()
{
}
~Pwns()
{
Done();
}
void Done()
{
VERUS_FOR(i, NUM)
_t[i].Done();
}
const T& operator[](int i) const
{
VERUS_RT_ASSERT(i >= 0 && i < NUM);
return _t[i];
}
T& operator[](int i)
{
VERUS_RT_ASSERT(i >= 0 && i < NUM);
return _t[i];
}
};
}

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