Commit add4f1f5 authored by Martin Turski's avatar Martin Turski

- added basic QuadTree implementation (WIP)

- added WorldMath.natvis file, a sample of what is yet to come!
- added boolean ConsoleArgumentType implementation
- fixed LoopRange * dereference operator (now returns actual type instead of int ptr)
- added math self-test to before running ATG
- added add_cdimage command because it was missing
- disabled some stupid warnings regarding deprecated C++/C features
- made some progress on WorldMath.cpp plane equations (not done yet)
- fixed some compiler warnings by casting things properly
parent bab581ca
Pipeline #55 skipped
......@@ -135,7 +135,55 @@ struct ConsoleArgumentName<std::string>
};
template <typename TArgument>
struct ConsoleArgumentType<TArgument, std::enable_if_t<std::is_integral<TArgument>::value>>
struct ConsoleArgumentType <TArgument, typename std::enable_if <std::is_same <TArgument, bool>::value>::type>
{
static std::string Unparse( const TArgument& input )
{
if ( input == true )
{
return "true";
}
else
{
return "false";
}
}
static bool Parse( const std::string& input, TArgument *out )
{
const char *inputPtr = input.c_str();
bool retBool = false;
if ( _stricmp( inputPtr, "TRUE" ) == 0 )
{
retBool = true;
}
else if ( _stricmp( inputPtr, "FALSE" ) == 0 )
{
retBool = false;
}
else
{
// If the boolean declaration is not a recognized string, then just check whether its integral.
try
{
retBool = ( std::stoull( input ) != 0 );
}
catch( ... )
{
// Just do nothing.
// Assume that the best default is already written to retBool.
}
}
*out = retBool;
return true;
}
};
template <typename TArgument>
struct ConsoleArgumentType<TArgument, std::enable_if_t<std::is_integral<TArgument>::value && !std::is_same<TArgument,bool>::value>>
{
static std::string Unparse(const TArgument& input)
{
......@@ -146,7 +194,7 @@ struct ConsoleArgumentType<TArgument, std::enable_if_t<std::is_integral<TArgumen
{
try
{
*out = std::stoull(input);
*out = (TArgument)std::stoull(input);
// no way to know if an integer is valid this lazy way, sadly :(
return true;
......@@ -170,7 +218,7 @@ struct ConsoleArgumentType<TArgument, std::enable_if_t<std::is_floating_point<TA
{
try
{
*out = std::stod(input);
*out = (TArgument)std::stod(input);
return true;
}
......
......@@ -28,7 +28,7 @@ public:
return (m_value != right.m_value);
}
const int& operator*() const
const T& operator*() const
{
return m_value;
}
......
......@@ -34,6 +34,13 @@ public:
return Get(i);
}
inline const std::string& operator[](size_t i) const
{
assert(i < m_arguments.size());
return m_arguments[i];
}
inline size_t Count() const
{
return m_arguments.size();
......
......@@ -4,10 +4,16 @@
#include "Game.h"
#include "WorldMath.h"
namespace krt
{
int Main::Run(const ProgramArguments& arguments)
{
// Run test code, meow.
// We should do that to self assert our correctness!
krt::math::Tests();
// parse argument list and handle console commands
sys::InitializeConsole();
......@@ -16,7 +22,7 @@ int Main::Run(const ProgramArguments& arguments)
std::vector<std::pair<std::string, std::string>> setList;
{
for (int i : irange(arguments.Count()))
for (size_t i : irange(arguments.Count()))
{
const std::string& argument = arguments[i];
......
......@@ -50,6 +50,8 @@ class Game
private:
void MountUserDirectory();
void YieldThreadForShortTime();
void LoadUniverseIfAvailable();
private:
......
......@@ -4,6 +4,8 @@
#include <vfs/Device.h>
#include <Console.CommandHelpers.h>
namespace krt
{
struct GameConfiguration
......@@ -56,14 +58,21 @@ class GameUniverse
{
auto it = m_modelIndexMapping.find(localId);
// We kind of do not want this to happen in our testing.
// But if it does, then handle it appropriately.
assert(it != m_modelIndexMapping.end());
if ( it == m_modelIndexMapping.end() )
return -1;
return it->second;
}
private:
void AddImage(const std::string& relativePath);
ConsoleCommand cmdAddImage;
void LoadConfiguration(const std::string& relativePath);
private:
......
#pragma once
// Basic QuadTree implementation for world sectoring.
// It works recursively until a predefined depth.
#include "WorldMath.h"
#include <type_traits>
namespace krt
{
template <size_t depth, size_t boundDimm, typename DataType>
struct QuadTree
{
inline QuadTree( void )
{
}
inline ~QuadTree( void )
{
}
template <typename numberType, size_t minX, size_t minY, size_t maxX, size_t maxY>
MATH_INLINE static bool IsPointInBounds( numberType x, numberType y )
{
return ( x >= minX && x >= minY && x < maxX && y < maxY );
}
template <typename numberType, size_t minX, size_t minY, size_t maxX, size_t maxY>
MATH_INLINE static bool IsBoundsInBounds( numberType box_minX, numberType box_minY, numberType box_maxX, numberType box_maxY )
{
return ( false ); // TODO.
}
template <size_t depth, size_t boundDimm, typename DataType, size_t xOff, size_t yOff>
struct Node
{
inline Node( void )
{
}
inline ~Node( void )
{
}
static size_t constexpr boundDimm = boundDimm;
private:
static constexpr size_t subdimm_bound = ( boundDimm / 2 );
Node <depth - 1, subdimm_bound, DataType, xOff, yOff> topLeft;
Node <depth - 1, subdimm_bound, DataType, xOff + subdimm_bound, yOff> topRight;
Node <depth - 1, subdimm_bound, DataType, xOff, yOff + subdimm_bound> bottomLeft;
Node <depth - 1, subdimm_bound, DataType, xOff + subdimm_bound, yOff + subdimm_bound> bottomRight;
public:
template <typename numberType, typename callbackType>
MATH_INLINE void VisitByPoint( numberType x, numberType y, callbackType& cb )
{
// Each node takes care of bound checking itself.
if ( IsPointInBounds <numberType, xOff, yOff, xOff + boundDimm, yOff + boundDimm> ( x, y ) )
{
topLeft.VisitByPoint( x, y, cb );
topRight.VisitByPoint( x, y, cb );
bottomLeft.VisitByPoint( x, y, cb );
bottomRight.VisitByPoint( x, y, cb );
}
}
};
template <size_t boundDimm, typename DataType, size_t xOff, size_t yOff>
struct Node <0, boundDimm, DataType, xOff, yOff>
{
inline Node( void )
{
}
inline ~Node( void )
{
}
static size_t constexpr boundDimm = boundDimm;
private:
DataType data;
public:
template <typename numberType, typename callbackType>
MATH_INLINE void VisitByPoint( numberType x, numberType y, callbackType& cb )
{
// Each node takes care of bound checking itself.
if ( IsPointInBounds <numberType, xOff, yOff, xOff + boundDimm, yOff + boundDimm> ( x, y ) )
{
// Call the thing.
cb( this->data );
}
}
};
Node <depth, boundDimm, DataType, 0, 0> root;
};
}
\ No newline at end of file
......@@ -13,6 +13,8 @@ struct World
World( void );
~World( void );
void PutEntitiesOnGrid( void );
private:
NestedList <Entity> entityList;
};
......
......@@ -2,11 +2,22 @@
// Important math about camera frustum and world sectoring.
#define MATH_INLINE __forceinline
namespace krt
{
namespace math
{
struct Plane
{
rw::V3d pos;
rw::V3d a;
rw::V3d b;
inline bool intersectWith( const Plane& right ) const;
};
struct Sphere
{
rw::V3d point;
......
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="krt::QuadTree &lt;*,*,*&gt;" >
<DisplayString>QuadTree ({$T2} x {$T2}, type: {"$T3"})</DisplayString>
<Expand HideRawView="true">
<Item Name="Depth">$T1</Item>
<ExpandedItem>this->root</ExpandedItem>
</Expand>
</Type>
<Type Name="krt::QuadTree &lt;*,*,*&gt;::Node &lt;*,*,*,*,*&gt;">
<DisplayString>Node</DisplayString>
<Expand HideRawView="true">
<Item Name="Dimm">$T5</Item>
<Synthetic Name="Pos">
<DisplayString>({$T7},{$T8})</DisplayString>
</Synthetic>
<Item Name="[TL]">this->topLeft</Item>
<Item Name="[TR]">this->topRight</Item>
<Item Name="[BL]">this->bottomLeft</Item>
<Item Name="[BR]">this->bottomRight</Item>
</Expand>
</Type>
<Type Name="krt::QuadTree &lt;*,*,*&gt;::Node &lt;*,*,*,*,*&gt;">
<DisplayString>Data</DisplayString>
<Expand HideRawView="true">
<Item Name="Dimm">$T5</Item>
<Synthetic Name="Pos">
<DisplayString>({$T7},{$T8})</DisplayString>
</Synthetic>
<Item Name="Data">this->data</Item>
</Expand>
</Type>
</AutoVisualizer>
\ No newline at end of file
......@@ -11,6 +11,8 @@
#include <Console.VariableHelpers.h>
#pragma warning(disable:4996)
namespace krt
{
static void make_lower(std::string& str)
......
......@@ -47,4 +47,11 @@ void Game::MountUserDirectory()
vfs::Mount(device, "user:/");
}
}
void Game::YieldThreadForShortTime()
{
// I do not want this thing to max out my CPU :/
// And we are not doing realistic simulations yet.
Sleep( 1 );
}
}
\ No newline at end of file
......@@ -17,6 +17,8 @@
#include <src/rwgta.h>
#include <Windows.h>
#pragma warning(disable : 4996)
namespace krt
......@@ -101,7 +103,7 @@ void Game::Run()
{
// limit frame rate and handle events
// TODO: non-busy wait?
int minMillis = (this->maxFPS > 0) ? (1000 / this->maxFPS) : 1;
uint32_t minMillis = (this->maxFPS > 0) ? (1000u / (uint32_t)this->maxFPS) : 1u; // we can cast to unsigned because its bigger than zero.
uint32_t millis = 0;
uint64_t thisTime = 0;
......@@ -110,12 +112,14 @@ void Game::Run()
{
thisTime = eventSystem.HandleEvents();
millis = thisTime - lastTime;
millis = (uint32_t)( thisTime - lastTime );
YieldThreadForShortTime();
} while (millis < minMillis);
// handle time scaling
float scale = this->timescale; // to be replaced by a console value, again
millis *= scale;
millis = (uint32_t)( (float)millis * scale );
if (millis < 1)
{
......
......@@ -14,7 +14,14 @@
namespace krt
{
GameUniverse::GameUniverse(const GameConfiguration& configuration)
: m_configuration(configuration), m_game(theGame)
: m_configuration(configuration), m_game(theGame),
// Initialize all game universe commands.
cmdAddImage("add_cdimage",
[](const GameUniversePtr& universe, const std::string& path)
{
universe->AddImage( path );
})
{
}
......
#include "StdInc.h"
#include "World.h"
#include "QuadTree.h"
namespace krt
{
......@@ -8,6 +10,14 @@ World::World( void )
{
// A world can store a lot of entities.
LIST_CLEAR( this->entityList.root );
QuadTree <3, 6000, int> tree;
tree.root.VisitByPoint( 200, 200,
[]( int& ok )
{
ok = 1337;
});
}
World::~World( void )
......@@ -26,4 +36,9 @@ World::~World( void )
// TODO: add more cool world stuff.
void World::PutEntitiesOnGrid( void )
{
}
}
\ No newline at end of file
This diff is collapsed.
......@@ -65,7 +65,8 @@ workspace 'krt'
'streaming/**.h',
'streaming/**.cpp',
'game/**.h',
'game/**.cpp'
'game/**.cpp',
'**.natvis'
}
links
......
......@@ -90,7 +90,8 @@ bool CdImageDevice::OpenImage(const std::string& imagePath)
}
// use the directory path in case bulk handles are equivalent to the parent handle
numEntries = parentDevice->GetLength(directoryPath) / sizeof(Entry);
// We assume that you dont actually be that crazy and make such tiny entires in the CdImage that you have more than 2^32 - 1.
numEntries = (uint32_t)( parentDevice->GetLength(directoryPath) / sizeof(Entry) );
}
// read the directory entry list
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment