added more retentive stuff
This commit is contained in:
parent
75df9ad96d
commit
b947b0b263
8 changed files with 117 additions and 107 deletions
|
@ -1,7 +1,7 @@
|
|||
|
||||
add_library(nm_utils STATIC
|
||||
"Window.cpp"
|
||||
"RetentiveArray.hpp" "RetentiveObject.hpp" "RetentiveEntity.hpp")
|
||||
"RetentiveArray.hpp" "RetentiveObject.hpp" "RetentiveEntity.hpp" "VectorField.hpp" "VectorField.cpp")
|
||||
|
||||
target_include_directories(nm_utils PUBLIC ${SDL2_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(nm_utils PUBLIC ${SDL2_LIBRARIES})
|
||||
|
|
|
@ -3,6 +3,76 @@
|
|||
#include <vector>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
template<
|
||||
typename Type,
|
||||
unsigned int AttentionSpan,
|
||||
bool IsPointerType>
|
||||
class _RetentiveEntityBase;
|
||||
|
||||
template<
|
||||
typename Type,
|
||||
unsigned int AttentionSpan>
|
||||
class _RetentiveEntityBase<Type, AttentionSpan, false>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Get the entity from `index` generations ago
|
||||
*
|
||||
* @param index Amount of generations to go backwards in time
|
||||
* @return The entity from before `index` generations
|
||||
*/
|
||||
Type& operator[](size_t index)
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the most up-to-date entity
|
||||
*
|
||||
* @return The entity with generation 0
|
||||
*/
|
||||
Type& Current()
|
||||
{
|
||||
return data[0];
|
||||
}
|
||||
|
||||
protected:
|
||||
std::array<Type, AttentionSpan + 1> data;
|
||||
};
|
||||
|
||||
|
||||
template<
|
||||
typename Type,
|
||||
unsigned int AttentionSpan>
|
||||
class _RetentiveEntityBase<Type, AttentionSpan, true>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Get the entity from `index` generations ago
|
||||
*
|
||||
* @param index Amount of generations to go backwards in time
|
||||
* @return The entity from before `index` generations
|
||||
*/
|
||||
Type& operator[](size_t index)
|
||||
{
|
||||
return *(data[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the most up-to-date entity
|
||||
*
|
||||
* @return The entity with generation 0
|
||||
*/
|
||||
Type& Current()
|
||||
{
|
||||
return *(data[0]);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::array<std::shared_ptr<Type>, AttentionSpan + 1> data; // Shared for move semantics
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Abstract base type for all retentive things
|
||||
|
@ -13,8 +83,8 @@
|
|||
template<
|
||||
typename Type,
|
||||
unsigned int AttentionSpan,
|
||||
typename std::enable_if_t<(AttentionSpan > 0), bool> = true>
|
||||
class RetentiveEntity
|
||||
bool IsPointerType = false>
|
||||
class RetentiveEntity : public _RetentiveEntityBase<Type, AttentionSpan, IsPointerType>
|
||||
{
|
||||
public:
|
||||
RetentiveEntity() {}
|
||||
|
@ -23,27 +93,6 @@ public:
|
|||
RetentiveEntity<Type, AttentionSpan>& operator=(const RetentiveEntity<Type, AttentionSpan>& other) = delete;
|
||||
RetentiveEntity<Type, AttentionSpan>& operator=(RetentiveEntity<Type, AttentionSpan>&& other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Get the entity from `index` generations ago
|
||||
*
|
||||
* @param index Amount of generations to go backwards in time
|
||||
* @return The entity from before `index` generations
|
||||
*/
|
||||
virtual Type& operator[](size_t index)
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the most up-to-date entity
|
||||
*
|
||||
* @return The entity with generation 0
|
||||
*/
|
||||
virtual Type& Current()
|
||||
{
|
||||
return data[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evolve the data in the entity
|
||||
*
|
||||
|
@ -92,8 +141,4 @@ protected:
|
|||
* @brief Swaps the objects in the array
|
||||
*/
|
||||
virtual void CycleGenerations() = 0;
|
||||
|
||||
protected:
|
||||
std::array<Type, AttentionSpan + 1> data;
|
||||
std::function<void(void)> rule = std::bind([]() {}); // Do nothing by default
|
||||
};
|
||||
|
|
|
@ -21,9 +21,8 @@
|
|||
*/
|
||||
template<
|
||||
typename Type,
|
||||
unsigned int AttentionSpan,
|
||||
typename std::enable_if_t<(AttentionSpan > 0), bool> = true>
|
||||
class RetentiveObject : public RetentiveEntity<Type*, AttentionSpan>
|
||||
unsigned int AttentionSpan>
|
||||
class RetentiveObject : public RetentiveEntity<Type, AttentionSpan, true>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -34,7 +33,7 @@ public:
|
|||
// Create new vectors for every generation that needs to be remembered
|
||||
for (int n = 0; n <= AttentionSpan; n++)
|
||||
{
|
||||
data[n] = new Type();
|
||||
data[n] = std::make_shared<Type>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,10 +44,10 @@ public:
|
|||
*/
|
||||
RetentiveObject(const Type& initVal)
|
||||
{
|
||||
// Create new vectors for every generation that needs to be remembered
|
||||
// Create new objects for every generation that needs to be remembered
|
||||
for (int n = 0; n <= AttentionSpan; n++)
|
||||
{
|
||||
data[n] = new Type(initVal);
|
||||
data[n] = std::make_shared<Type>(initVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +76,6 @@ public:
|
|||
for (int n = 0; n <= AttentionSpan; n++)
|
||||
{
|
||||
data[n] = other.data[n];
|
||||
other.data[n] = nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -103,36 +101,6 @@ public:
|
|||
*this = other;
|
||||
}
|
||||
|
||||
~RetentiveObject()
|
||||
{
|
||||
for (int n = 0; n <= AttentionSpan; n++)
|
||||
{
|
||||
if (data[n] != nullptr)
|
||||
delete data[n];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the object from `index` generations ago
|
||||
*
|
||||
* @param index Amount of generations to go backwards in time
|
||||
* @return The object from before `index` generations
|
||||
*/
|
||||
Type& operator[](size_t index) override
|
||||
{
|
||||
return *(data[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the most up-to-date object
|
||||
*
|
||||
* @return The object with generation 0
|
||||
*/
|
||||
Type& Current() override
|
||||
{
|
||||
return *(data[0]);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Swaps the objects in the array
|
||||
|
|
76
lib/VectorField.cpp
Normal file
76
lib/VectorField.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include "VectorField.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <SDL.h>
|
||||
|
||||
VectorField::VectorField() :
|
||||
width(0), height(0), biggestMagnitude(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
VectorField::VectorField(int width, int height) :
|
||||
width(width), height(height)
|
||||
{
|
||||
horizontal = std::vector<double>(width * height, 0.0);
|
||||
vertical = std::vector<double>(width * height, 0.0);
|
||||
|
||||
biggestMagnitude = 1.0f;
|
||||
}
|
||||
|
||||
VectorField::VectorField(int width, int height, const std::vector<double>& hori, const std::vector<double>& vert) :
|
||||
width(width), height(height)
|
||||
{
|
||||
horizontal = hori;
|
||||
vertical = vert;
|
||||
|
||||
RecalculateMagnitude();
|
||||
}
|
||||
|
||||
void VectorField::Draw(SDL_Renderer* renderer, const SDL_Rect& targetRect)
|
||||
{
|
||||
double cellWidth = (double)(targetRect.w - targetRect.x) / (double)width;
|
||||
double cellHeight = (double)(targetRect.h - targetRect.y) / (double)height;
|
||||
|
||||
SDL_FRect vectorCenterSquare;
|
||||
vectorCenterSquare.w = cellWidth / 5.0;
|
||||
vectorCenterSquare.h = cellHeight / 5.0;
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 200, 20, 20, 100);
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
vectorCenterSquare.x = (double)targetRect.x + cellWidth * (x + 0.4); // cellWidth * x + cellWidth / 2 - cellWidth / 10
|
||||
vectorCenterSquare.y = (double)targetRect.y + cellHeight * (y + 0.4);
|
||||
SDL_RenderFillRectF(renderer, &vectorCenterSquare);
|
||||
SDL_RenderDrawLineF(renderer,
|
||||
(double)targetRect.x + cellWidth * (x + 0.5),
|
||||
(double)targetRect.y + cellHeight * (y + 0.5),
|
||||
(double)targetRect.x + cellWidth * (x + 0.5) + horizontal[y * width + x] / biggestMagnitude * cellWidth * 2.5,
|
||||
(double)targetRect.y + cellHeight * (y + 0.5) + vertical[y * width + x] / biggestMagnitude * cellHeight * 2.5
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VectorField::RecalculateMagnitude()
|
||||
{
|
||||
for (int y = 0; y < this->height; y++)
|
||||
{
|
||||
for (int x = 0; x < this->width; x++)
|
||||
{
|
||||
double u = horizontal[y * this->width + x];
|
||||
double v = vertical[y * this->width + x];
|
||||
double magnitude = u * u + v * v;
|
||||
|
||||
biggestMagnitude = std::max(biggestMagnitude, magnitude);
|
||||
}
|
||||
}
|
||||
|
||||
if (biggestMagnitude == 0.0) // should use an epsilon probably
|
||||
biggestMagnitude = 1.0;
|
||||
|
||||
biggestMagnitude = sqrt(biggestMagnitude);
|
||||
biggestMagnitude = 0.5f;
|
||||
}
|
26
lib/VectorField.hpp
Normal file
26
lib/VectorField.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct SDL_Rect;
|
||||
struct SDL_Renderer;
|
||||
|
||||
class VectorField
|
||||
{
|
||||
public:
|
||||
VectorField();
|
||||
VectorField(int width, int height);
|
||||
VectorField(int width, int height, const std::vector<double>& hori, const std::vector<double>& vert);
|
||||
|
||||
void Draw(SDL_Renderer* renderer, const SDL_Rect& targetRect);
|
||||
void RecalculateMagnitude();
|
||||
|
||||
public:
|
||||
std::vector<double> horizontal;
|
||||
std::vector<double> vertical;
|
||||
|
||||
private:
|
||||
int width, height;
|
||||
|
||||
double biggestMagnitude = 0.0;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue