initial commit

This commit is contained in:
Orange
2023-11-23 05:03:54 +03:00
committed by Vladislav Alpatov
commit 7c533861a7
15 changed files with 954 additions and 0 deletions

5
source/CMakeLists.txt Normal file
View File

@@ -0,0 +1,5 @@
target_sources(uml PRIVATE
Vector3.cpp
matrix.cpp
angles.cpp
ProjectilePredictor.cpp)

View File

@@ -0,0 +1,74 @@
//
// Created by vlad on 11/6/23.
//
#include "uml/ProjectilePredictor.h"
#include "uml/Vector3.h"
#include "uml/angles.h"
#include <cmath>
namespace uml::prediction
{
std::optional<Vector3>
ProjectilePredictor::CalculateViewAngles(const Vector3 &origin,
const Vector3 &target,
const Vector3 &targetVelocity,
float gravity,
float bulletSpeed,
float bulletGravity,
bool inAir)
{
constexpr float maxTime = 3.0f;
constexpr float timeStep = 0.01f;
for (float time = 0.0f; time <= maxTime; time += timeStep)
{
auto predPos = target + targetVelocity * time;
if (inAir)
predPos -= Vector3(0, 0, gravity * (time * time) * 0.5);
const auto angle = CalculateAimPitch(origin, predPos, bulletSpeed, bulletGravity);
if (!angle.has_value())
return std::nullopt;
const auto timeToHit = ProjectileTravelTime((predPos - origin).Length2D(), *angle, bulletSpeed);
if (timeToHit > time)
continue;
auto viewAngles = origin.ViewAngleTo(predPos);
viewAngles.x = angle.value();
return viewAngles;
}
return std::nullopt;
}
std::optional<float>
ProjectilePredictor::CalculateAimPitch(const Vector3 &origin, const Vector3 &target,
float bulletSpeed, float bulletGravity)
{
const auto delta = target - origin;
const auto distance = delta.Length2D();
float root = powf(bulletSpeed, 4) - bulletGravity * (bulletGravity * distance * distance + 2.0f * delta.z * powf(bulletSpeed, 2));
if (root < 0.0f) {
return std::nullopt;
}
root = sqrt(root);
float angle = atanf((powf(bulletSpeed, 2) - root) / (bulletGravity * distance)) * 180.f / (float)M_PI;
return -angle;
}
float ProjectilePredictor::ProjectileTravelTime(float distance, float angle, float speed)
{
return std::abs(distance / (std::cos(angles::DegToRad(angle)) * speed));
}
}

215
source/Vector3.cpp Normal file
View File

@@ -0,0 +1,215 @@
//
// Created by vlad on 10/28/23.
//
#include <uml/Vector3.h>
#include <cmath>
#include <uml/angles.h>
namespace uml
{
bool Vector3::operator==(const Vector3 &src) const
{
return (src.x == x) and (src.y == y) and (src.z == z);
}
bool Vector3::operator!=(const Vector3 &src) const
{
return (src.x != x) or (src.y != y) or (src.z != z);
}
Vector3 &Vector3::operator+=(const Vector3 &v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
Vector3 &Vector3::operator-=(const Vector3 &v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
Vector3 &Vector3::operator*=(const float fl)
{
x *= fl;
y *= fl;
z *= fl;
return *this;
}
Vector3 &Vector3::operator*=(const Vector3 &v)
{
x *= v.x;
y *= v.y;
z *= v.z;
return *this;
}
Vector3 &Vector3::operator/=(const Vector3 &v)
{
x /= v.x;
y /= v.y;
z /= v.z;
return *this;
}
Vector3 &Vector3::operator+=(const float fl)
{
x += fl;
y += fl;
z += fl;
return *this;
}
Vector3 &Vector3::operator/=(const float fl)
{
x /= fl;
y /= fl;
z /= fl;
return *this;
}
Vector3 &Vector3::operator-=(const float fl)
{
x -= fl;
y -= fl;
z -= fl;
return *this;
}
float Vector3::DistTo(const Vector3 &vOther) const
{
Vector3 delta;
delta.x = x - vOther.x;
delta.y = y - vOther.y;
delta.z = z - vOther.z;
return delta.Length();
}
Vector3 &Vector3::Abs()
{
x = fabsf(x);
y = fabsf(y);
z = fabsf(z);
return *this;
}
float Vector3::DistToSqr(const Vector3 &vOther) const
{
Vector3 delta;
delta.x = x - vOther.x;
delta.y = y - vOther.y;
delta.z = z - vOther.z;
return delta.LengthSqr();
}
float Vector3::Dot(const Vector3 &vOther) const
{
return (x * vOther.x + y * vOther.y + z * vOther.z);
}
float Vector3::Length() const
{
return sqrt(x * x + y * y + z * z);
}
float Vector3::LengthSqr(void) const
{
return (x * x + y * y + z * z);
}
float Vector3::Length2D() const
{
return sqrt(x * x + y * y);
}
Vector3 Vector3::operator-(void) const
{
return {-x, -y, -z};
}
Vector3 Vector3::operator+(const Vector3 &v) const
{
return {x + v.x, y + v.y, z + v.z};
}
Vector3 Vector3::operator-(const Vector3 &v) const
{
return {x - v.x, y - v.y, z - v.z};
}
Vector3 Vector3::operator*(float fl) const
{
return {x * fl, y * fl, z * fl};
}
Vector3 Vector3::operator*(const Vector3 &v) const
{
return {x * v.x, y * v.y, z * v.z};
}
Vector3 Vector3::operator/(const float fl) const
{
return {x / fl, y / fl, z / fl};
}
Vector3 Vector3::operator/(const Vector3 &v) const
{
return {x / v.x, y / v.y, z / v.z};
}
Vector3 Vector3::Transform(const Vector3 &angles, const float length) const
{
Vector3 transformed;
transformed.x += cosf(angles.y * static_cast<float>(M_PI / 180.f)) * length;
transformed.y += sinf(angles.y * static_cast<float>(M_PI / 180.f)) * length;
transformed.z += tanf(angles.x * static_cast<float>(M_PI / 180.f)) * length;
return transformed;
}
float Vector3::Sum() const
{
return x + y + z;
}
float Vector3::Sum2D() const
{
return x + y;
}
Vector3 Vector3::ViewAngleTo(const Vector3 &other) const
{
const float distance = DistTo(other);
const auto delta = other - *this;
// Make x negative since -89 is top and 89 is bottom
return
{
-angles::RadToDeg(asinf(delta.z / distance)),
angles::RadToDeg(atan2f(delta.y, delta.x)),
0.f
};
}
}

18
source/angles.cpp Normal file
View File

@@ -0,0 +1,18 @@
//
// Created by vlad on 11/6/23.
//
#include "uml/angles.h"
#include <cmath>
namespace uml::angles
{
float RadToDeg(float rads)
{
return rads * 180.f / static_cast<float>(M_PI);
}
float DegToRad(float degrees)
{
return degrees * static_cast<float>(M_PI) / 180.f;
}
}

288
source/matrix.cpp Normal file
View File

@@ -0,0 +1,288 @@
/*
* Copyright (c) 2022.
* Created by Alpatov Softworks with love in Russia.
*/
#include "uml/matrix.h"
#include "uml/Vector3.h"
#include <utility>
#include <stdexcept>
#include <utility>
namespace uml
{
matrix::matrix(const size_t rows, const size_t columns)
{
if (rows == 0 and columns == 0)
throw std::runtime_error("Matrix cannot be 0x0");
m_rows = rows;
m_columns = columns;
m_pData = std::make_unique<float[]>(m_rows * m_columns);
set(0.f);
}
matrix::matrix(const std::vector<std::vector<float>> &rows)
{
m_rows = rows.size();
m_columns = rows[0].size();
m_pData = std::make_unique<float[]>(m_rows * m_columns);
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i,j) = rows[i][j];
}
matrix::matrix(const matrix &other)
{
m_rows = other.m_rows;
m_columns = other.m_columns;
m_pData = std::make_unique<float[]>(m_rows * m_columns);
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i, j) = other.at(i, j);
}
matrix::matrix(const size_t rows, const size_t columns, float *pRaw)
{
m_rows = rows;
m_columns = columns;
m_pData = std::make_unique<float[]>(m_rows * m_columns);
for (size_t i = 0; i < rows*columns; ++i)
at(i / rows, i % columns) = pRaw[i];
}
size_t matrix::get_rows_count() const noexcept
{
return m_rows;
}
matrix::matrix(matrix &&other) noexcept
{
m_rows = other.m_rows;
m_columns = other.m_columns;
m_pData = std::move(other.m_pData);
}
size_t matrix::get_columns_count() const noexcept
{
return m_columns;
}
std::pair<size_t, size_t> matrix::get_size() const noexcept
{
return {get_rows_count(), get_columns_count()};
}
float &matrix::at(const size_t iRow, const size_t iCol)
{
return const_cast<float&>(std::as_const(*this).at(iRow, iCol));
}
float matrix::get_sum()
{
float sum = 0;
for (size_t i = 0; i < get_rows_count(); i++)
for (size_t j = 0; j < get_columns_count(); j++)
sum += at(i, j);
return sum;
}
const float &matrix::at(const size_t iRow, const size_t iCol) const
{
return m_pData[iRow * m_columns + iCol];
}
matrix matrix::operator*(const matrix &other) const
{
if (m_columns != other.m_rows)
throw std::runtime_error("n != m");
auto outMat = matrix(m_rows, other.m_columns);
for (size_t d = 0; d < m_rows; ++d)
for (size_t i = 0; i < other.m_columns; ++i)
for (size_t j = 0; j < other.m_rows; ++j)
outMat.at(d, i) += at(d, j) * other.at(j, i);
return outMat;
}
matrix matrix::operator*(const float f) const
{
auto out = *this;
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
out.at(i, j) *= f;
return out;
}
matrix &matrix::operator*=(const float f)
{
for (size_t i = 0; i < get_rows_count(); i++)
for (size_t j = 0; j < get_columns_count(); j++)
at(i, j) *= f;
return *this;
}
void matrix::clear()
{
set(0.f);
}
matrix matrix::operator*(const Vector3 &vec3) const
{
auto vecmatrix = matrix(m_rows, 1);
vecmatrix.set(1.f);
vecmatrix.at(0, 0) = vec3.x;
vecmatrix.at(1, 0) = vec3.y;
vecmatrix.at(2, 0) = vec3.z;
return *this * vecmatrix;
}
matrix &matrix::operator=(const matrix &other)
{
if (this == &other)
return *this;
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i, j) = other.at(i, j);
return *this;
}
matrix &matrix::operator=(matrix &&other) noexcept
{
if (this == &other)
return *this;
m_rows = other.m_rows;
m_columns = other.m_columns;
m_pData = std::move(other.m_pData);
return *this;
}
matrix &matrix::operator/=(const float f)
{
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i, j) /= f;
return *this;
}
matrix matrix::operator/(const float f) const
{
auto out = *this;
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
out.at(i, j) /= f;
return out;
}
float matrix::det() const
{
if (m_rows + m_columns == 2)
return at(0, 0);
if (m_rows == 2 and m_columns == 2)
return at(0, 0) * at(1, 1) - at(0, 1) * at(1, 0);
float fDet = 0;
for (size_t i = 0; i < m_columns; i++)
fDet += alg_complement(0, i) * at(0, i);
return fDet;
}
float matrix::alg_complement(const size_t i, const size_t j) const
{
const auto tmp = minor(i, j);
return ((i + j + 2) % 2 == 0) ? tmp : -tmp;
}
matrix matrix::transpose()
{
matrix transposed = {m_columns, m_rows};
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
transposed.at(j, i) = at(i, j);
return transposed;
}
matrix::~matrix() = default;
void matrix::set(const float val)
{
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i, j) = val;
}
matrix matrix::strip(const size_t row, const size_t column) const
{
matrix stripped = {m_rows - 1, m_columns - 1};
size_t iStripRowIndex = 0;
for (size_t i = 0; i < m_rows; i++)
{
if (i == row)
continue;
size_t iStripColumnIndex = 0;
for (size_t j = 0; j < m_columns; ++j)
{
if (j == column)
continue;
stripped.at(iStripRowIndex, iStripColumnIndex) = at(i, j);
iStripColumnIndex++;
}
iStripRowIndex++;
}
return stripped;
}
float matrix::minor(const size_t i, const size_t j) const
{
return strip(i, j).det();
}
matrix matrix::to_screen_matrix(float screenWidth, float screenHeight)
{
return matrix({
{screenWidth / 2.f, 0.f, 0.f, 0.f},
{0.f, -screenHeight / 2.f, 0.f, 0.f},
{0.f, 0.f, 1.f, 0.f},
{screenWidth / 2.f, screenHeight / 2.f, 0.f, 1.f},
});
}
}