49 Commits

Author SHA1 Message Date
=
ae3eb3276f fix change camera height
All checks were successful
Linux arm64 / Build (push) Successful in 5m20s
2024-04-15 18:50:20 +02:00
=
615f68b48b dampen player movements mid-air
All checks were successful
Linux arm64 / Build (push) Successful in 5m4s
2024-04-15 16:56:55 +02:00
=
c7547ffab5 document smoother class, minor nitpicks 2024-04-15 16:42:34 +02:00
Morph01
14610c1f94 map with separate objets
Some checks failed
Linux arm64 / Build (push) Failing after 3m17s
2024-04-14 23:47:24 +02:00
68dfc73ad2 better map
Some checks failed
Linux arm64 / Build (push) Failing after 3m30s
2024-04-14 23:13:59 +02:00
98625523ca use fabs
Some checks failed
Linux arm64 / Build (push) Failing after 3m33s
2024-04-14 23:08:16 +02:00
ee84b290a6 transform aabbs
Some checks failed
Linux arm64 / Build (push) Failing after 3m6s
2024-04-14 23:00:34 +02:00
=
6116ff3e59 oe
Some checks failed
Linux arm64 / Build (push) Failing after 2m54s
2024-04-14 22:39:22 +02:00
=
7d8045918e bon jsp si ca marche
Some checks failed
Linux arm64 / Build (push) Failing after 2m59s
2024-04-14 22:26:02 +02:00
d5bda8ab5d temporary render aabb
All checks were successful
Linux arm64 / Build (push) Successful in 5m20s
2024-04-13 15:37:55 +02:00
8ff74d028f load aabb 2024-04-13 15:37:40 +02:00
6089b144eb refactor Axis
All checks were successful
Linux arm64 / Build (push) Successful in 4m59s
2024-04-13 09:53:58 +02:00
ed3322f256 process model aabb 2024-04-13 09:46:21 +02:00
d13030fbb0 better doc 2024-04-13 09:14:57 +02:00
f78f36ffb2 Merge branch 'main' into physics
All checks were successful
Linux arm64 / Build (push) Successful in 5m5s
2024-04-13 09:02:10 +02:00
=
8a35b2390c use axis
All checks were successful
Linux arm64 / Build (push) Successful in 24m41s
2024-04-11 12:53:56 +02:00
=
dc2c74fcb1 almost full doc coverage in Physics.h, improve some functions
Some checks are pending
Linux arm64 / Build (push) Waiting to run
2024-04-11 12:51:43 +02:00
=
bae3d70b3c copium
All checks were successful
Linux arm64 / Build (push) Successful in 23m5s
2024-04-10 17:17:00 +02:00
=
f3d5b4aeab fix windows build 2024-04-10 17:16:50 +02:00
=
1ab0d61890 fix merge 2024-04-10 17:16:37 +02:00
=
2896dbeaf6 Merge branch 'main' into physics
Some checks failed
Linux arm64 / Build (push) Failing after 23m21s
2024-04-10 16:01:38 +02:00
=
0175a1fed0 add ()
All checks were successful
Linux arm64 / Build (push) Successful in 4m55s
2024-04-10 15:32:37 +02:00
=
ce13f6f1ce moooooooonkey 2024-04-10 15:17:40 +02:00
=
69d5547d15 add ToCollision, optimise perspective matrix calculation
Some checks failed
Linux arm64 / Build (push) Failing after 2m19s
2024-04-10 14:55:07 +02:00
1d1a02a7b5 minor architectural changes, Intersection updated
Some checks failed
Linux arm64 / Build (push) Failing after 2m22s
2024-04-10 11:52:35 +02:00
cd7ca3edf0 yes
Some checks failed
Linux arm64 / Build (push) Failing after 2m17s
2024-04-09 12:16:18 +02:00
=
6e6a21ce09 implement bare-bones aabb-aabb intersection
All checks were successful
Linux arm64 / Build (push) Successful in 4m53s
2024-03-26 12:06:15 +01:00
=
0adeba26e4 minor fix
All checks were successful
Linux arm64 / Build (push) Successful in 4m50s
2024-03-26 11:35:37 +01:00
=
011d8a573c fix stupid build error
Some checks failed
Linux arm64 / Build (push) Has been cancelled
2024-03-26 11:33:56 +01:00
=
22406ad020 yes
Some checks failed
Linux arm64 / Build (push) Failing after 2m52s
2024-03-26 11:25:35 +01:00
=
4db55a372b csavgfdslgakdf;g
Some checks failed
Linux arm64 / Build (push) Failing after 2m42s
2024-03-26 11:13:22 +01:00
20d176ccb5 add range overlapping check utilities
Some checks failed
Linux arm64 / Build (push) Failing after 3m10s
2024-03-26 11:07:27 +01:00
3863e7907f better edge case handling 2024-03-26 10:24:35 +01:00
=
35b7d7bab0 I am fucking retarded what the fuck is this stupid brain smoking
All checks were successful
Linux arm64 / Build (push) Successful in 4m47s
2024-03-26 10:19:21 +01:00
6aca413b4f small refactor
Some checks failed
Linux arm64 / Build (push) Failing after 5m21s
2024-03-24 18:14:02 +01:00
ee322e3e7b improve tests, fix some bugs in Distance, (not working yet)
Some checks failed
Linux arm64 / Build (push) Failing after 2m28s
2024-03-24 17:43:07 +01:00
864a15e4c8 Squashed commit of the following:
All checks were successful
Linux arm64 / Build (push) Successful in 4m45s
commit c1ded40cc4
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 21 17:24:05 2024 +0100

    improve network test

commit 285bf880ee
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 21 17:14:43 2024 +0100

    fix warning

commit 06ff76607d
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 21 15:45:33 2024 +0100

    add bots

commit 19229bbe8a
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 21 14:55:57 2024 +0100

    fix warnings

commit 2b0930a734
Author: Morph01 <thibaut6969delastreet@gmail.com>
Date:   Tue Mar 19 10:43:55 2024 +0100

    hud of blitz (#16)

    Résoudre partiellement #12

    Co-authored-by: Persson-dev <sim16.prib@gmail.com>
    Co-authored-by: Morph01 <145839520+Morph01@users.noreply.github.com>
    Co-authored-by: Simon Pribylski <sim16.prib@gmail.com>
    Reviewed-on: #16

commit 84b6acad4c
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Tue Mar 19 10:15:54 2024 +0100

    less spooky light

commit 9f94d51fc4
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 14 16:36:15 2024 +0100

    Ajout de tests d'intégration (#17)

    Le paquet fournissant OpenGL a été temporairement remplacé par glew

    Reviewed-on: #17
    Co-authored-by: Persson-dev <sim16.prib@gmail.com>
    Co-committed-by: Persson-dev <sim16.prib@gmail.com>

commit 9951256881
Author: Simon Pribylski <sim16.prib@gmail.com>
Date:   Wed Mar 13 20:19:37 2024 +0100

    action: install libsdl via apt

commit 4a02054648
Author: Morph01 <145839520+Morph01@users.noreply.github.com>
Date:   Wed Mar 13 13:53:20 2024 +0100

    compression tests

commit 19c39312bf
Author: Morph01 <145839520+Morph01@users.noreply.github.com>
Date:   Wed Mar 13 13:51:57 2024 +0100

    setup action

commit d5014b1e8a
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Tue Mar 12 10:26:47 2024 +0100

    Revert "extend Vec3"

    This reverts commit dccfa9c936.

commit dccfa9c936
Author: = <=>
Date:   Tue Mar 12 10:01:00 2024 +0100

    extend Vec3
Merge branch 'main' into physics
2024-03-22 19:33:45 +01:00
7efd8218ea moved functions in Maths.h
Some checks failed
Linux arm64 / Build (push) Has been cancelled
2024-03-22 19:28:46 +01:00
08db7f84b9 add missing include
All checks were successful
Linux arm64 / Build (push) Successful in 5m7s
2024-03-22 19:16:48 +01:00
7119dea783 merge 'main' branch
commit c1ded40cc4
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 21 17:24:05 2024 +0100

    improve network test

commit 285bf880ee
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 21 17:14:43 2024 +0100

    fix warning

commit 06ff76607d
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 21 15:45:33 2024 +0100

    add bots

commit 19229bbe8a
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 21 14:55:57 2024 +0100

    fix warnings

commit 2b0930a734
Author: Morph01 <thibaut6969delastreet@gmail.com>
Date:   Tue Mar 19 10:43:55 2024 +0100

    hud of blitz (#16)

    Résoudre partiellement #12

    Co-authored-by: Persson-dev <sim16.prib@gmail.com>
    Co-authored-by: Morph01 <145839520+Morph01@users.noreply.github.com>
    Co-authored-by: Simon Pribylski <sim16.prib@gmail.com>
    Reviewed-on: #16

commit 84b6acad4c
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Tue Mar 19 10:15:54 2024 +0100

    less spooky light

commit 9f94d51fc4
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Thu Mar 14 16:36:15 2024 +0100

    Ajout de tests d'intégration (#17)

    Le paquet fournissant OpenGL a été temporairement remplacé par glew

    Reviewed-on: #17
    Co-authored-by: Persson-dev <sim16.prib@gmail.com>
    Co-committed-by: Persson-dev <sim16.prib@gmail.com>

commit 9951256881
Author: Simon Pribylski <sim16.prib@gmail.com>
Date:   Wed Mar 13 20:19:37 2024 +0100

    action: install libsdl via apt

commit 4a02054648
Author: Morph01 <145839520+Morph01@users.noreply.github.com>
Date:   Wed Mar 13 13:53:20 2024 +0100

    compression tests

commit 19c39312bf
Author: Morph01 <145839520+Morph01@users.noreply.github.com>
Date:   Wed Mar 13 13:51:57 2024 +0100

    setup action

commit d5014b1e8a
Author: Persson-dev <sim16.prib@gmail.com>
Date:   Tue Mar 12 10:26:47 2024 +0100

    Revert "extend Vec3"

    This reverts commit dccfa9c936.

commit dccfa9c936
Author: = <=>
Date:   Tue Mar 12 10:01:00 2024 +0100

    extend Vec3
2024-03-22 19:15:01 +01:00
6e998fc368 change tests
All checks were successful
Linux arm64 / Build (push) Successful in 4m29s
2024-03-22 16:41:52 +01:00
441131a2f5 rename Intersects to distance 2024-03-22 16:14:56 +01:00
c875fa1dee more template
All checks were successful
Linux arm64 / Build (push) Successful in 4m46s
2024-03-22 15:50:32 +01:00
5e4b318d67 inline Reduce_<> functions
All checks were successful
Linux arm64 / Build (push) Successful in 4m34s
2024-03-22 15:26:07 +01:00
076fa7badc fix compilation error
Some checks failed
Linux arm64 / Build (push) Failing after 4m22s
2024-03-22 15:18:39 +01:00
1091abd034 fix some compilation errors
Some checks failed
Linux arm64 / Build (push) Failing after 2m14s
2024-03-22 14:58:26 +01:00
dd9ea3ece8 update intersects, document changes
Some checks failed
Linux arm64 / Build (push) Failing after 2m12s
2024-03-22 12:02:39 +01:00
6226161e31 fix compilation error, add min/max functions for Vec3d
Some checks failed
Linux arm64 / Build (push) Failing after 2m23s
2024-03-22 09:22:06 +01:00
6b32e8878e fix min/max functions
Some checks failed
Linux arm64 / Build (push) Failing after 2m18s
2024-03-22 09:18:34 +01:00
26 changed files with 647 additions and 167 deletions

Binary file not shown.

BIN
assets/sol.glb Normal file

Binary file not shown.

View File

@@ -2,17 +2,38 @@
namespace blitz {
/**
* \struct An exponential moving average smoother, or one pole lowpass filter
* smoothes incoming data by attenutating sharp/sudden changes
*/
class EMASmoother {
private:
float Alpha;
public:
float Current;
EMASmoother();
void TickUnitT(float target);
void Tick(float target, float delta);
float GetAlpha();
void SetAlpha(float alpha);
public:
/**
* \brief the current output value of the smoother
*/
float Current;
EMASmoother();
/**
* \brief behaves like `Tick(target, 1.0f)` but optimised
*/
void TickUnitT(float target);
/**
* \brief feed in the next value to the filter, and update `Current` accordingly
* \param target the value in question
* \param delta the time that has passed sinced the last value has been provided
*/
void Tick(float target, float delta);
/**
* \brief set the amount of time it should take to reacha certain value, the higher this is
* the "smoother the output signal"
*/
void SetSmoothingTime(float t);
};

View File

@@ -7,9 +7,11 @@
#include "Player.h"
#include "blitz/game/Listeners.h"
#include "blitz/game/World.h"
#include "blitz/misc/ObjectNotifier.h"
#include "blitz/misc/Time.h"
#include <map>
#include <memory>
namespace blitz {
namespace game {
@@ -45,6 +47,7 @@ class Game : public utils::ObjectNotifier<GameListener> {
GameState m_GameState;
utils::Timer m_GameTimer;
GameConfig m_Config;
std::unique_ptr<World> m_World;
public:
/** \brief Default constructor */
@@ -135,6 +138,13 @@ class Game : public utils::ObjectNotifier<GameListener> {
std::uint64_t GetGameStateRemainingTime() const {
return m_GameTimer.GetTimeRemaining();
}
/**
* \return The world associated with this game
*/
const World* GetWorld() const {
return m_World.get();
}
};

View File

@@ -7,6 +7,7 @@
#include "blitz/common/Defines.h"
#include "blitz/maths/Vector.h"
#include "blitz/maths/Physics.h"
#include <cstdint>
#include <string>
@@ -42,6 +43,7 @@ struct PlayerStats {
*/
class Player {
private:
maths::AABB m_Hitbox;
PlayerID m_ID;
std::string m_Name;
Vec3f m_Position;
@@ -83,6 +85,20 @@ class Player {
m_Name = name;
}
/**
* \brief Get the player's hitbox
*/
maths::AABB GetHitBox() const {
return m_Hitbox + m_Position;
}
/**
* \brief Sets the player's hitbox
*/
void SetHitBoxSize(const maths::AABB& aabb) {
m_Hitbox = aabb;
}
/**
* \brief Get the position of the player
* \return The position of the player

View File

@@ -0,0 +1,27 @@
#pragma once
#include "blitz/game/Listeners.h"
#include "blitz/maths/Physics.h"
#include <vector>
namespace blitz {
namespace game {
class Game;
class World {
protected:
Game* m_Game;
std::vector<maths::AABB> m_AABBs;
public:
World(Game* game);
virtual ~World();
const std::vector<maths::AABB>& GetAABBs() const {
return m_AABBs;
}
};
} // namespace game
} // namespace blitz

View File

@@ -128,18 +128,32 @@ T ReduceMax(const Vec3<T>& vect) {
* \param v a vector
* \return the (signed) minimal coordinate of the vector
*/
template <>
inline float ReduceMin<float>(const Vec3f& v) {
inline float ReduceFMinF(const Vec3f& v) {
return std::fminf(std::fminf(v.x, v.y), v.z);
}
inline Vec3f FmaF(const Vec3f& v, const Vec3f& a, const Vec3f& b) {
return {
std::fmaf(v.x, a.x, b.x),
std::fmaf(v.y, a.y, b.y),
std::fmaf(v.z, a.z, b.z),
};
}
inline Vec3d Fma(const Vec3d& v, const Vec3d& a, const Vec3d& b) {
return {
std::fma(v.x, a.x, b.x),
std::fma(v.y, a.y, b.y),
std::fma(v.z, a.z, b.z),
};
}
/**
* \brief Returns the (signed) maximal coordinate of the vector
* \param v a vector
* \return the (signed) maximal coordinate of the vector
*/
template <>
inline float ReduceMax<float>(const Vec3f& v) {
inline float ReduceFMaxF(const Vec3f& v) {
return std::fmaxf(std::fmaxf(v.x, v.y), v.z);
}
@@ -148,8 +162,7 @@ inline float ReduceMax<float>(const Vec3f& v) {
* \param v a vector
* \return the (signed) minimal coordinate of the vector
*/
template <>
inline double ReduceMin<double>(const Vec3d& v) {
inline double ReduceFMin(const Vec3d& v) {
return std::fmin(std::fmin(v.x, v.y), v.z);
}
@@ -158,8 +171,7 @@ inline double ReduceMin<double>(const Vec3d& v) {
* \param v a vector
* \return the (signed) maximal coordinate of the vector
*/
template <>
inline double ReduceMax<double>(const Vec3d& v) {
inline double ReduceFMax(const Vec3d& v) {
return std::fmax(std::fmax(v.x, v.y), v.z);
}
@@ -182,13 +194,30 @@ constexpr Vec3<T> Min(const Vec3<T>& self, const Vec3<T>& other) {
}
/**
* \brief returns the coordinate-wise maximum of the given vectors,
* where a coordinate in the returned vector is NAN iff any of the two compared ones are NAN
* \tparam T
* \param self a vector
* \param other an other vector
* \return returns the coordinate-wise maximum of the given vectors,
* @brief returns the coordinate-wise minimum of the given vectors,
* where a coordinate in the returned vector is NAN iff both of the two compared ones are NAN
*
* @tparam T
* @param self
* @param other
* @return constexpr Vec3f
*/
constexpr Vec3f FMinF(const Vec3f& self, const Vec3f& other) {
return {
std::fminf(self.x, other.x),
std::fminf(self.y, other.y),
std::fminf(self.z, other.z),
};
}
/**
* @brief returns the coordinate-wise maximum of the given vectors,
* where a coordinate in the returned vector is NAN iff any of the two compared ones are NAN
*
* @tparam T
* @param self
* @param other
* @return constexpr Vec3
*/
template <typename T>
constexpr Vec3<T> Max(const Vec3<T>& self, const Vec3<T>& other) {
@@ -199,8 +228,47 @@ constexpr Vec3<T> Max(const Vec3<T>& self, const Vec3<T>& other) {
};
}
/**
* @brief returns the coordinate-wise maximum of the given vectors,
* where a coordinate in the returned vector is NAN iff both of the two compared ones are NAN
*
* @tparam T
* @param self
* @param other
* @return constexpr Vec3
*/
constexpr Vec3f FMaxF(const Vec3f& self, const Vec3f& other) {
return {
std::fmaxf(self.x, other.x),
std::fmaxf(self.y, other.y),
std::fmaxf(self.z, other.z),
};
}
/**
* @brief lane-wise copysign
*/
constexpr Vec3f CopysignF(const Vec3f& v, const Vec3f& signs) {
return {
std::copysignf(v.x, signs.x),
std::copysignf(v.y, signs.y),
std::copysignf(v.z, signs.z),
};
}
/**
* @brief lane-wise copysign
*/
constexpr Vec3d Copysign(const Vec3d& v, const Vec3d& signs) {
return {
std::copysign(v.x, signs.x),
std::copysign(v.y, signs.y),
std::copysign(v.z, signs.z),
};
}
//////////////////////////////////////////////////////////////////
// Matricies //
// Matrices //
//////////////////////////////////////////////////////////////////
/**

View File

@@ -1,30 +1,149 @@
#pragma once
#include "blitz/maths/Vector.h"
/**
* \file Physics.h
* \brief Physics logic
*/
#include "blitz/maths/Maths.h"
#include <optional>
namespace blitz {
namespace maths {
struct Ray {
Vec3f origin;
Vec3f direction;
/**
* \enum Axis
* \brief represents an axis in 3-dimensional space
*/
enum Axis : std::size_t { aX = 0, aY, aZ };
/**
* \brief encodes the movement an entity must perform, in an environment containing other
* entitis it may collide with
*/
struct CollisionData {
/**
* \brief the effective movement the entity can/should perform, immediately
*/
Vec3f delta;
/**
* \brief the direction of "slide" along a side of a bounding
* box, this is 0 if no collisions occured
*/
Vec3f slide;
};
/**
* \struct IntersectionData
* \brief Intermediate data encoding an intersection between a Ray/AABB and an AABB
*/
struct IntersectionData {
/**
* \brief by how much to translate before intersecting with the AABB
*/
float distance;
/**
* \brief the axis along which the collision happens, used to solve sliding requirements
*/
Axis axis;
/**
* \brief Returns the movements that the entity must perform. It is advised to make sure
* `0.0f <= distance <= 1.0f` as this would return incoherent data
* \pre `0.0f <= distance <= 1.0f`
* \param dir
* \return
*/
CollisionData ToCollision(const Vec3f& dir) const;
};
/**
* \struct AABB
* \brief an Axis Aligned Bounding Box, see wikipedia for more
*/
struct AABB {
Vec3f from;
Vec3f to;
/**
* \return A vector representing the center of mass of the box
*/
inline Vec3f Center() const;
/**
* \return The same box but all the coordinates in `from` are less than their
* counterparts in `to`.
*/
AABB Direct() const;
/**
* \brief Enlarges this box along each axis by the length of the box along said axis
* \param with
* \return The new, big, box
*
*/
AABB Enlarge(const AABB& with) const;
AABB operator+(const Vec3f& offset) const;
AABB operator+=(const Vec3f& offset);
/**
* \brief checks if this box overlaps with another one
* \param aabb
* \return whether this box overlaps with another one
*/
bool OverlapsWith(const AABB& aabb) const;
/**
* \brief Given this box is to be offset by some vector colinear to dir,
* this function behave exactly like Ray::Intersection
* \param aabb
* \param dir
* \return
*/
std::optional<IntersectionData> Intersection(const AABB& aabb, const Vec3f& dir) const;
};
inline AABB operator+(const AABB& aabb, const Vec3f& offset) {
AABB result = aabb;
result.from += offset;
result.to += offset;
return result;
}
/**
* \struct Ray
* \brief represents a (half-)line
*/
struct Ray {
/**
* \brief the origin/start/initial point of the line
*/
Vec3f origin;
/**
* \brief the direction of the line
*/
Vec3f direction;
float Distance(const Ray& ray, const AABB& aabb);
/**
* \brief Note that t isn't necessarily positive
* \param t
* \return `origin` + `direction` * `t`
*/
Vec3f operator()(float t) const;
bool Intersects(const Ray& ray, const AABB& aabb);
/**
* \brief Is essentially Intersection(aabb).distance >= 0.0f
* \returns `true` if the half-line `ray` _strictly_ intersects with `aabb`,
* and `false` if it _strictly_ doesn't intersect.
* Note that if it only intersects with corners, edges, or sides of the box,
* or if any coordinate in `ray` is `NAN` or `inf` or if any coordinate in
* `aabb` is `NAN` the result is unspecified.
*/
bool Intersects(const AABB& aabb) const;
/**
* \brief The `distance` field of the returned value is smallest number t
* (in absolute value), if it exists, such that `ray(t)` is in `aabb`. otherwise
* a quiet `NaN` is returned. The `axis` field is the axis to along
* which `ray` intersects/collides with `aabb`
*/
std::optional<IntersectionData> Intersection(const AABB& aabb) const;
};
} // namespace maths
} // namespace blitz

View File

@@ -6,7 +6,6 @@
*/
#include <algorithm>
#include <cmath>
#include <cstddef>
namespace blitz {
@@ -48,6 +47,34 @@ struct Vec3 {
};
constexpr Vec3(T X = 0, T Y = 0, T Z = 0) : x(X), y(Y), z(Z) {}
static Vec3 splat(T val) {
return Vec3(val, val, val);
}
const T* data() const {
return reinterpret_cast<const T*>(this);
}
T* data() {
return reinterpret_cast<T*>(this);
}
const T& at(std::size_t index) const {
return data()[index];
}
T& at(std::size_t index) {
return data()[index];
}
const T& operator[](std::size_t index) const {
return at(index);
}
T& operator[](std::size_t index) {
return at(index);
}
};
template <typename T>
@@ -96,10 +123,6 @@ using Vec4d = Vec4<double>;
using Color = Vec3uc;
// Vec2
template <typename T>
@@ -144,10 +167,6 @@ constexpr Vec2<T> operator*(T mult, const Vec2<T>& vect) {
return vect * mult;
}
// Vec3
template <typename T>
@@ -226,11 +245,6 @@ Vec3<T>& operator/=(Vec3<T>& vect, const Vec3<T>& other) {
return vect;
}
template <typename T>
constexpr bool operator<(const Vec3<T>& vec3, const Vec3<T>& other) {
return vec3.x < other.x && vec3.y < other.y && vec3.z < other.z;
}
// Vec4
template <typename T>

View File

@@ -64,6 +64,8 @@ class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener>
private:
void UpdateShootTimer(int bpm);
void UpdatePosition(float delta);
void ApplyForce(const Vec3f& f, float delta);
void ApplyGravity(float delta);
};
} // namespace input

View File

@@ -0,0 +1,20 @@
#pragma once
#include "blitz/game/World.h"
namespace blitz {
namespace client {
class ClientGame;
class ClientWorld : public game::World {
public:
ClientWorld(ClientGame* game);
virtual ~ClientWorld() {}
private:
void LoadAABBs();
};
} // namespace client
} // namespace blitz

View File

@@ -1,5 +1,6 @@
#pragma once
#include "blitz/maths/Physics.h"
#include "client/render/loader/GLLoader.h"
#include <memory>
#include <string>
@@ -16,5 +17,7 @@ struct Model {
Model LoadModel(const std::string& fileName);
std::vector<maths::AABB> LoadModelAABBs(const std::string& fileName);
} // namespace ModelLoader
} // namespace blitz

View File

@@ -19,7 +19,7 @@
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
class SDL_Window;
struct SDL_Window;
struct SDL_Renderer;
typedef union SDL_Event SDL_Event;

View File

@@ -1,4 +1,5 @@
#include "blitz/game/Game.h"
#include <cmath>
namespace blitz {
namespace game {
@@ -25,6 +26,13 @@ void Game::AddPlayer(PlayerID player, const std::string& name) {
static float MAX_HP = 100;
game::Player newPlayer{player};
static const maths::AABB PLAYER_BASE_AABB = {Vec3f{-0.5f, -0.9f, -0.5f}, Vec3f{0.5f, 0.9f, 0.5f}};
newPlayer.SetHitBoxSize(PLAYER_BASE_AABB);
newPlayer.SetPosition({
0.0f,
std::fabs(PLAYER_BASE_AABB.to.y - PLAYER_BASE_AABB.from.y) * 10.0f,
0.0f
});
newPlayer.SetName(name);
newPlayer.SetHP(MAX_HP);

13
src/blitz/game/World.cpp Normal file
View File

@@ -0,0 +1,13 @@
#include "blitz/game/World.h"
#include "blitz/game/Game.h"
namespace blitz {
namespace game {
World::World(Game* game) : m_Game(game) {}
World::~World() {}
} // namespace game
} // namespace blitz

View File

@@ -5,15 +5,20 @@
namespace blitz {
namespace maths {
Mat4f Perspective(float fovY, float aspectRatio, float zNear, float zFar) {
const float tanHalfFovy = std::tan(fovY / 2.0f);
Mat4f Perspective(float fovY, float invAspectRatio, float zNear, float zFar) {
static const float FRAC_PI_2 = 1.5707963267948966;
const float cotanHalfFovy = -std::tan(std::fmaf(fovY, 0.5f, FRAC_PI_2));
float neg_i_z_diff = -1.0f / (zFar - zNear);
Mat4f result{};
result.x0 = 1.0f / (aspectRatio * tanHalfFovy);
result.y1 = 1.0f / (tanHalfFovy);
result.z2 = -(zFar + zNear) / (zFar - zNear);
result.x0 = cotanHalfFovy * invAspectRatio;
result.y1 = cotanHalfFovy;
result.z2 = (zFar + zNear) * neg_i_z_diff;
result.z3 = -1.0f;
result.w2 = -(2.0f * zFar * zNear) / (zFar - zNear);
result.w2 = 2.0f * zFar * zNear * neg_i_z_diff;
return result;
}

113
src/blitz/maths/Physics.cpp Executable file → Normal file
View File

@@ -1,67 +1,112 @@
#include "blitz/maths/Physics.h"
#include "blitz/maths/Maths.h"
#include <cmath>
namespace blitz {
namespace maths {
/**
* @brief Returns `true` if the half-line `ray` _strictly_ intersects with `aabb`,
* and `false` if it _strictly_ doesn't intersect.
* Note that if it only intersects with corners, edges, or sides of the box,
* or if any coordinate in `ray` is `NAN` or `inf` or if any coordinate in
* `aabb` is `NAN` the result is unspecified.
* */
float Distance(const Ray& ray, const AABB& aabb) {
AABB AABB::Enlarge(const AABB& with) const {
const Vec3f dir = 0.5f * (with.to - with.from);
// This function calculates smallest interval I = ] a, b [, for strictly positive a and b
// such that for all t in I, for all l, r, o, d corresponding
// coordinates in aabb.from, aabb.to, ray.origin, ray.direction, respectively
return AABB{
from - dir,
to + dir,
};
}
AABB AABB::Direct() const {
return AABB{Min(from, to), Max(from, to)};
}
Vec3f AABB::Center() const {
return (from + to) * 0.5f;
}
AABB AABB::operator+(const Vec3f& offset) const {
return AABB{from + offset, to + offset};
}
AABB AABB::operator+=(const Vec3f& offset) {
*this = *this + offset;
return *this;
}
bool AABB::OverlapsWith(const AABB& aabb) const {
return RangesOverlapping(from.x, to.x, aabb.from.x, aabb.to.x) &&
RangesOverlapping(from.y, to.y, aabb.from.y, aabb.to.y) &&
RangesOverlapping(from.z, to.z, aabb.from.z, aabb.to.z);
}
std::optional<IntersectionData> AABB::Intersection(const AABB& aabb, const Vec3f& dir) const {
return Ray { Center(), dir }.Intersection(aabb.Enlarge(*this));
}
Vec3f Ray::operator()(float t) const {
return FmaF(Vec3f::splat(t), direction, origin);
}
std::optional<IntersectionData> Ray::Intersection(const AABB& aabb) const {
// This function calculates smallest interval I = ] tmin, tmax [,
// such that for all t in I ray(t) is in the AABB, now, if tmin > tmax
// there is no such t, i.e. the ray never intersects with the AABB
//
// min(l, r) < o + t * d < max(l, r)
//
// and returns true if it's non-empty i.e. a < b
// and returns true if it's non-empty i.e. a < b
// m = min(l, r), M = max(l, r)
// m < o + t * d < M
Vec3f l = Min(aabb.from, aabb.to);
Vec3f r = Max(aabb.to, aabb.from);
AABB directed = aabb.Direct();
Vec3f& l = directed.from;
Vec3f& r = directed.to;
// m - o < t * d < M - o
l -= ray.origin;
r -= ray.origin;
l -= origin;
r -= origin;
// (m - o) / d < t < (M - o) / d
l /= ray.direction;
r /= ray.direction;
l /= direction;
r /= direction;
// but if d is negative the inequality is flipped
Vec3f u = Min(l, r);
r = Max(l, r);
l = u;
float tmin = ReduceMax(l);
float tmax = ReduceMin(r);
const float tmin = ReduceFMaxF(l);
const float tmax = ReduceFMinF(r);
// Since Min propagates NANs and ReduceMin doesn't, and since NAN !< <any float>
// the inequality becomes ignored for coordinates where a NAN is involved
// Since Min propagates NANs and ReduceFMinF doesn't, and since NAN != <any float>
// the inequality becomes ignored for coordinates where a NaN is involved
// (as a result of 0.0 / 0.0). If all coordinates are NAN, this means
// that the box is reduced to a point and the ray has direction 0,
// in which case this returns -1
if (tmax >= 0.0f && tmin <= tmax) {
return std::fmaxf(tmin, 0.0f);
// in which case this returns 0.0, which is technically the correct result
if (tmin <= tmax && tmax > 0.0f) {
Axis axis = Axis::aZ;
for (std::size_t i = 2; i >= 0; i--) {
Axis this_axis = Axis(i);
if (l[this_axis] == tmin) {
axis = this_axis;
break;
}
}
const float dist = std::fmaxf(0.0f, tmin);
return std::make_optional(IntersectionData { dist, axis });
}
return -1.0f;
return std::nullopt;
}
bool Intersects(const AABB& aabb1, const AABB& aabb2) {
return false;
bool Ray::Intersects(const AABB& aabb) const {
auto data = Intersection(aabb);
return data.has_value() && data->distance >= 0.0f;
}
bool Intersects(const Ray& ray, const AABB& aabb) {
return Distance(ray, aabb) >= 0.0f;
CollisionData IntersectionData::ToCollision(const Vec3f& dir) const {
Vec3f new_dir = dir;
new_dir[axis] = 0.0f;
return CollisionData{dir * (distance - 0.07f), new_dir * (1.0f - distance)};
}
} // namespace maths

View File

@@ -32,7 +32,7 @@ float EaseOutCubic(float x) {
}
float EaseInOutCubic(float x) {
return static_cast<float>(x < 0.5 ? 4 * EaseInCubic(x) : 1 - std::pow(-2 * x + 2, 3) / 2.0);
return x < 0.5f ? 4.0f * EaseInCubic(x) : 1.0f - std::pow(-2.0f * x + 2.0f, 3.0f) / 2.0f;
}
/* Quint functions */
@@ -60,8 +60,8 @@ float EaseOutCirc(float x) {
}
float EaseInOutCirc(float x) {
return static_cast<float>(
x < 0.5 ? (1 - std::sqrt(1 - std::pow(2 * x, 2))) / 2.0 : (std::sqrt(1 - std::pow(-2 * x + 2, 2)) + 1) / 2.0);
return x < 0.5f ? (1.0f - std::sqrt(1.0f - std::pow(2.0f * x, 2.0f))) / 2.0f
: (std::sqrt(1.0f - std::pow(-2.0f * x + 2.0f, 2.0f)) + 1.0f) / 2.0f;
}
/* Elastic functions */

View File

@@ -2,6 +2,7 @@
#include "blitz/game/Player.h"
#include "blitz/maths/Maths.h"
#include "blitz/maths/Physics.h"
#include "blitz/misc/Log.h"
#include "client/Client.h"
#include "client/config/BlitzConfig.h"
@@ -25,7 +26,7 @@ PlayerController::PlayerController(Client* client, input::InputManager& inputMan
m_Client(client),
m_InputManager(inputManager),
m_Velocity({}),
m_MaxVelocity(DEFAULT_MAX_LR_SPEED, DEFAULT_MAX_FB_SPEED, DEFAULT_JUMP_VEL),
m_MaxVelocity(DEFAULT_MAX_LR_SPEED, DEFAULT_JUMP_VEL, DEFAULT_MAX_FB_SPEED),
m_OnGround(true) {
m_DxSmoother.Current = 0.0f;
m_DySmoother.Current = 0.0f;
@@ -80,13 +81,19 @@ void PlayerController::Update(float delta) {
static_cast<float>(ImGui::IsKeyDown((ImGuiKey(keys[kaDroite]))));
// scale values in such a way that clamps ||(lr, fb)|| to 1.0
float scale = 1.0f / std::max(sqrt(lr * lr + fb * fb), 1.0f);
float scale = 1.0f / std::fmaxf(sqrt(lr * lr + fb * fb), 1.0f);
static constexpr float AIR_MOVEMENT_DAMP = 3.0f;
float no = std::fmaf(static_cast<float>(!m_OnGround), AIR_MOVEMENT_DAMP, 1.0f);
m_DxSmoother.SetSmoothingTime(DEFAULT_LR_SPEED_SMOOTHING_TIME * no);
m_DySmoother.SetSmoothingTime(DEFAULT_FB_SPEED_SMOOTHING_TIME * no);
m_Velocity.x = lr * m_MaxVelocity.x * scale;
m_Velocity.y = fb * m_MaxVelocity.y * scale;
m_Velocity.z = fb * m_MaxVelocity.z * scale;
if (ImGui::IsKeyDown(ImGuiKey::ImGuiKey_Space) && m_OnGround) {
m_Velocity.z = m_MaxVelocity.z;
m_Velocity.y = m_MaxVelocity.y;
NotifyListeners(&game::PlayerInputListener::OnLocalPlayerJump);
}
@@ -97,12 +104,22 @@ void PlayerController::Update(float delta) {
m_ShootTimer.ApplyCooldown();
}
} else {
m_Velocity.x = m_Velocity.y = 0.0f;
m_Velocity.x = m_Velocity.z = 0.0f;
}
ApplyGravity(delta);
UpdatePosition(delta);
}
void PlayerController::ApplyForce(const Vec3f& f, float delta) {
m_Velocity += f * delta;
}
void PlayerController::ApplyGravity(float delta) {
ApplyForce(Vec3f { 0.0f, -m_Client->GetGame()->GetGameConfig().Gravity, 0.0f }, delta);
}
void PlayerController::UpdatePosition(const float delta) {
float yaw = m_Player->GetYaw();
@@ -110,28 +127,54 @@ void PlayerController::UpdatePosition(const float delta) {
float cosine = std::cos(yaw);
m_DxSmoother.Tick(m_Velocity.x, delta);
m_DySmoother.Tick(m_Velocity.y, delta);
m_DySmoother.Tick(m_Velocity.z, delta);
float dx_smooth = m_DxSmoother.Current;
float dy_smooth = m_DySmoother.Current;
float dx = (dx_smooth * cosine + dy_smooth * sine) * delta;
float dy = (dx_smooth * sine - dy_smooth * cosine) * delta;
Vec3f vel = Vec3f((dx_smooth * cosine + dy_smooth * sine), m_Velocity.y, (dx_smooth * sine - dy_smooth * cosine)) * delta;
maths::CollisionData collision { Vec3f::splat(0.0f), vel };
float dz = m_Velocity.z * delta;
const auto& aabbs = m_Client->GetGame()->GetWorld()->GetAABBs();
maths::AABB hitbox = m_Player->GetHitBox();
// the floor here is y-level zero, once downwards collision lands it will be dynmicallly calculated
// assumed to be a negative number
const float floor_dist = 0.0f - m_Player->GetPosition().y;
bool on_ground = false;
if ((m_OnGround = (dz <= floor_dist))) {
dz = floor_dist;
m_Velocity.z = 0.0f;
} else {
m_Velocity.z -= m_Client->GetGame()->GetGameConfig().Gravity * 1.0f * delta;
}
do {
m_Player->AddPosition({dx, dz, dy});
maths::IntersectionData closest { 1.0f, maths::Axis::aY };
for (const maths::AABB& aabb : aabbs) {
auto intersection = hitbox.Intersection(aabb, collision.slide);
if (intersection.has_value()) {
float d = intersection->distance;
if (d < closest.distance) {
maths::Axis axis = intersection->axis;
on_ground |= (axis == maths::Axis::aY);
closest.distance = d;
closest.axis = axis;
}
}
}
if (closest.distance < 0.99f) {
m_Velocity[closest.axis] = 0.0f;
}
collision = closest.ToCollision(collision.slide);
Vec3f v = collision.delta;
m_Player->AddPosition(v);
m_Player->SetVelocity(v);
} while (maths::Length(collision.slide) > 1e-6);
m_OnGround = on_ground;
}
} // namespace input

View File

@@ -13,12 +13,14 @@
#include "blitz/protocol/packets/UpdateGameStatePacket.h"
#include "blitz/protocol/packets/UpdateHealthPacket.h"
#include "client/Client.h"
#include "client/game/ClientWorld.h"
namespace blitz {
namespace client {
ClientGame::ClientGame(Client* client, protocol::PacketDispatcher* dispatcher) :
protocol::PacketHandler(dispatcher), m_Client(client) {
m_World = std::make_unique<ClientWorld>(this);
RegisterHandlers();
}

View File

@@ -0,0 +1,18 @@
#include "client/game/ClientWorld.h"
#include "client/game/ClientGame.h"
#include "client/render/loader/ModelLoader.h"
namespace blitz {
namespace client {
ClientWorld::ClientWorld(ClientGame* game) : game::World(game) {
LoadAABBs();
}
void ClientWorld::LoadAABBs() {
m_AABBs = ModelLoader::LoadModelAABBs("sol.glb");
}
} // namespace client
} // namespace blitz

View File

@@ -7,7 +7,8 @@
namespace blitz {
namespace render {
static const float EyeHeight = 1.25f;
/// \brief Eye height from center
static const float EyeHeight = 0.5f;
void Camera::Update(float delta) {
int windowWidth = static_cast<int>(ImGui::GetIO().DisplaySize.x);
@@ -16,8 +17,12 @@ void Camera::Update(float delta) {
if (windowWidth != m_LastWindowSize.x || windowHeight != m_LastWindowSize.y) {
m_LastWindowSize = {windowWidth, windowHeight};
m_PerspectiveMatrix =
maths::Perspective(80.0f / 180.0f * maths::PI, static_cast<float>(windowWidth) / windowHeight, 0.1f, 160.0f);
m_PerspectiveMatrix = maths::Perspective(
80.0f / 180.0f * maths::PI,
static_cast<float>(windowHeight) / static_cast<float>(windowWidth),
0.1f,
160.0f
);
}
}

View File

@@ -62,7 +62,7 @@ MainRenderer::~MainRenderer() {
}
void MainRenderer::LoadModels() {
m_WorldModel = ModelLoader::LoadModel("base_deambu.glb");
m_WorldModel = ModelLoader::LoadModel("sol.glb");
m_PlayerModel = ModelLoader::LoadModel("human.obj");
m_GunModel = ModelLoader::LoadModel("fingergun.obj");

View File

@@ -101,14 +101,15 @@ Model LoadModel(const std::string& fileName) {
const aiScene* scene = importer.ReadFileFromMemory(fileData.data(), fileData.GetSize(),
aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_OptimizeGraph |
aiProcess_OptimizeMeshes);
aiProcess_OptimizeMeshes | aiProcess_GenBoundingBoxes);
if (nullptr == scene) {
utils::LOGE("[ModelLoader] Failed to load model !");
return {};
}
utils::LOGD(utils::Format("[ModelLoader]\tModel nodes : %i", scene->mRootNode->mNumMeshes));
utils::LOGD(utils::Format("[ModelLoader]\tModel nodes : %i", scene->mRootNode->mNumChildren));
Model model;
ProcessNode(scene->mRootNode, scene, model.mVaos, {});
@@ -116,5 +117,47 @@ Model LoadModel(const std::string& fileName) {
return model;
}
static void ProcessAABBNode(aiNode* node, const aiScene* scene, std::vector<maths::AABB>& aabbs, const aiMatrix4x4& transform) {
// recursive
for (unsigned int i = 0; i < node->mNumChildren; i++) {
ProcessAABBNode(node->mChildren[i], scene, aabbs, transform * node->mTransformation);
}
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
aiAABB& aabb = mesh->mAABB;
aiVector3D aabbMin = transform * node->mTransformation * aabb.mMin;
aiVector3D aabbMax = transform * node->mTransformation * aabb.mMax;
aabbs.push_back({Vec3f{aabbMin.x, aabbMin.y, aabbMin.z}, {aabbMax.x, aabbMax.y, aabbMax.z}});
}
}
std::vector<maths::AABB> LoadModelAABBs(const std::string& fileName) {
DataBuffer fileData = utils::AssetsManager::GetAsset(fileName);
Assimp::Importer importer;
const aiScene* scene = importer.ReadFileFromMemory(fileData.data(), fileData.GetSize(), aiProcess_GenBoundingBoxes);
if (nullptr == scene) {
utils::LOGE("[ModelLoader] Failed to load AABB model !");
return {};
}
std::vector<maths::AABB> aabbs;
ProcessAABBNode(scene->mRootNode, scene, aabbs, {});
utils::LOGD(utils::Format("[ModelLoader]\tAABB count : %i", aabbs.size()));
return aabbs;
}
} // namespace ModelLoader
} // namespace blitz

View File

@@ -78,15 +78,13 @@ void ServerGame::SendPlayerPositions() {
void ServerGame::ProcessShoot(game::PlayerID shooter, Vec3f position, float yaw, float pitch) {
maths::Ray shootRay;
shootRay.origin = position + Vec3f{0.0, 1.75, 0.0};
shootRay.origin = position + Vec3f{0.0, 0.85, 0.0};
shootRay.direction = {
std::cos(yaw) * std::cos(pitch),
std::sin(pitch),
std::sin(yaw) * std::cos(pitch),
};
static const maths::AABB playerStaticAABB = {Vec3f{-0.5f, 0.0f, -0.5f}, Vec3f{0.5f, 1.8f, 0.5f}};
bool shootLanded = false;
game::Player* shooterPlayer = GetPlayerById(shooter);
@@ -94,7 +92,7 @@ void ServerGame::ProcessShoot(game::PlayerID shooter, Vec3f position, float yaw,
shooterPlayer->GetStats().m_ShootCount++;
for (auto& [playerId, player] : GetPlayers()) {
if (playerId != shooter && maths::Intersects(shootRay, playerStaticAABB + player.GetPosition())) {
if (playerId != shooter && shootRay.Intersects(player.GetHitBox())) {
if (!shootLanded) {
shootLanded = true;
shooterPlayer->GetStats().m_ShootSuccessCount++;

96
test/test_intersects.cpp Executable file → Normal file
View File

@@ -1,105 +1,105 @@
#include "blitz/misc/Test.h"
#include "blitz/maths/Physics.h"
#include "blitz/misc/Log.h"
#include "blitz/misc/Format.h"
#include "blitz/misc/Log.h"
#include <iostream>
#include <ostream>
#include <limits>
#include <ostream>
using namespace blitz;
using namespace maths;
#define let auto // sexy boiiii
#define let auto // sexy boiiii
static void test_left() {
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {-2.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f} };
let box = AABB{{-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{-2.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_right() {
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {2.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} };
let box = AABB{{-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{2.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_forward() {
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {0.0f, 2.0f, 0.0f}, {0.0f, -1.0f, 0.0f} };
let box = AABB{{-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{0.0f, 2.0f, 0.0f}, {0.0f, -1.0f, 0.0f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_backward() {
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {0.0f, -2.0f, 0.0f}, {0.0f, 1.0f, 0.0f} };
let box = AABB{{-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{0.0f, -2.0f, 0.0f}, {0.0f, 1.0f, 0.0f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_above() {
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {0.0f, 0.0f, 2.0f}, {0.0f, 0.0f, -1.0f} };
let box = AABB{{-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{0.0f, 0.0f, 2.0f}, {0.0f, 0.0f, -1.0f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_below() {
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {0.0f, 0.0f, -2.0f}, {0.0f, 0.0f, 1.0f} };
let box = AABB{{-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{0.0f, 0.0f, -2.0f}, {0.0f, 0.0f, 1.0f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_shifted() {
let box = AABB { {-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {-3.0f, 0.0f, 100.0f}, {1.0f, 0.0f, 0.0f} };
let box = AABB{{-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{-3.0f, 0.0f, 100.0f}, {1.0f, 0.0f, 0.0f}};
blitz_test_assert(!Intersects(ray, box));
blitz_test_assert(!ray.Intersects(box));
}
static void test_corner_inside() {
let box = AABB { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {0.0f, 0.0f, 0.0f}, {0.5f, 0.5f, 0.5f} };
let box = AABB{{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{0.0f, 0.0f, 0.0f}, {0.5f, 0.5f, 0.5f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_corner_inside_weird() {
let box = AABB { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
let box = AABB{{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_corner_inside_opposite_big() {
let box = AABB { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {0.0f, 0.0f, 0.0f}, {1.5f, 1.5f, 1.5f} };
let box = AABB{{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{0.0f, 0.0f, 0.0f}, {1.5f, 1.5f, 1.5f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
static void test_corner_inside_opposite_weird() {
let box = AABB { {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f} };
let ray = Ray { {0.4f, 0.4f, 0.4f}, {-1.0f, -1.0f, -1.0f} };
let box = AABB{{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
let ray = Ray{{0.4f, 0.4f, 0.4f}, {-1.0f, -1.0f, -1.0f}};
blitz_test_assert(Intersects(ray, box));
blitz_test_assert(ray.Intersects(box));
}
int main(int argc, const char* args[]) {
test_left();
test_right();
test_forward();
test_backward();
test_below();
test_above();
test_shifted();
test_corner_inside();
test_corner_inside_weird();
test_corner_inside_opposite_big();
test_corner_inside_opposite_weird();
return BLITZ_TEST_SUCCESSFUL;
test_left();
test_right();
test_forward();
test_backward();
test_below();
test_above();
test_shifted();
test_corner_inside();
test_corner_inside_weird();
test_corner_inside_opposite_big();
test_corner_inside_opposite_weird();
return BLITZ_TEST_SUCCESSFUL;
}