2019.2
This commit is contained in:
parent
3a391f11f5
commit
9455594fb7
|
@ -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
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// RendererDirect3D12.cpp : Defines the exported functions for the DLL application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include "stdafx.h"
|
|
@ -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
|
|
@ -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>
|
|
@ -0,0 +1,6 @@
|
|||
// RendererVulkan.cpp : Defines the exported functions for the DLL application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include "stdafx.h"
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
#include "verus.h"
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include "TaskDriver.h"
|
||||
#include "Turret.h"
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#include "verus.h"
|
||||
|
||||
namespace verus
|
||||
{
|
||||
void Make_Anim()
|
||||
{
|
||||
}
|
||||
void Free_Anim()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "Motion.h"
|
||||
#include "Skeleton.h"
|
||||
#include "Animation.h"
|
||||
|
||||
namespace verus
|
||||
{
|
||||
void Make_Anim();
|
||||
void Free_Anim();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include "verus.h"
|
||||
|
||||
namespace verus
|
||||
{
|
||||
void Make_Audio()
|
||||
{
|
||||
Audio::AudioSystem::Make();
|
||||
}
|
||||
void Free_Audio()
|
||||
{
|
||||
Audio::AudioSystem::Free();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 };
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::CGI;
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace CGI
|
||||
{
|
||||
class BaseGeometry
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::CGI;
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace CGI
|
||||
{
|
||||
class BasePipeline
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::CGI;
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace CGI
|
||||
{
|
||||
class BaseShader
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::CGI;
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace CGI
|
||||
{
|
||||
class BaseTexture
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "BaseGeometry.h"
|
||||
#include "BasePipeline.h"
|
||||
#include "BaseShader.h"
|
||||
#include "BaseTexture.h"
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#define VERUS_CT_ASSERT(x) static_assert(x, "VERUS_CT_ASSERT")
|
|
@ -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
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "AssertionRunTime.h"
|
||||
#include "AssertionCompileTime.h"
|
||||
#include "RuntimeError.h"
|
||||
#include "Recoverable.h"
|
||||
#include "Log.h"
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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__)
|
|
@ -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__)
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "State.h"
|
||||
#include "StateMachine.h"
|
||||
#include "BaseGame.h"
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Macros.h"
|
||||
#include "Typedef.h"
|
||||
#include "EnumClass.h"
|
||||
#include "QuickRefs.h"
|
||||
#include "AllocatorAware.h"
|
||||
#include "Singleton.h"
|
|
@ -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);
|
||||
}
|
|
@ -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");
|
||||
}
|
|
@ -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();
|
||||
};
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#include "verus.h"
|
||||
|
||||
int g_numSingletonAlloc;
|
||||
|
||||
namespace verus
|
||||
{
|
||||
void Make_Global()
|
||||
{
|
||||
Timer::Make();
|
||||
}
|
||||
void Free_Global()
|
||||
{
|
||||
Timer::Free();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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; }
|
||||
};
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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()
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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(); }
|
||||
};
|
||||
}
|
|
@ -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>>;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue