General bug fixes (#142)

* Core/Bitset: Fix TestAll method

* Fix documentation

* Fix color and their conversions

* Core/ByteStream: Fix return of Write

* Fix compiler warnings

* Math/Algorithm: Fix angle normalization

* Math/BoundingVolume: Fix lerp

* Math: Fix relation between Matrix4 and Quaternion

* More tests

* X11/Window: Fix mouse moved event generated when doing Mouse::SetPosition

* Update ChangeLog

* Should fix compilation on Windows

* Should fix compilation on Windows

Forgot to include array for Windows
This commit is contained in:
Gawaboumga 2017-11-21 12:16:46 +01:00 committed by Jérôme Leclercq
parent f2506ee918
commit f991a9529e
52 changed files with 1287 additions and 272 deletions

View File

@ -10,6 +10,13 @@ Nazara Engine:
- Fix reflection sometimes being enabled by default for Materials - Fix reflection sometimes being enabled by default for Materials
- Fix built-in unserialization of std::string which was corruption memory - Fix built-in unserialization of std::string which was corruption memory
- Fix Buffer::Destroy() not really destroying buffer - Fix Buffer::Destroy() not really destroying buffer
- Fix Bitset::TestAll() returned wrong result on full of '1' bitset
- ByteStream now returns the number of bytes written as the other streams
- Total rewriting of the color conversions
- Fix NormalizeAngle to the correct range
- Fix BoundingVolume::Lerp() with Extend_Null
- Simplification of methods Matrix4::SetRotation() and Quaternion::MakeRotationBetween()
- Fix mouve moved event generated on X11 platform when doing Mouse::SetPosition()
Nazara Development Kit: Nazara Development Kit:
@ -256,4 +263,4 @@ Issues fixed:
- #80: When initializing the engine, some pixel format errors occurs, this currently has no side-effect. - #80: When initializing the engine, some pixel format errors occurs, this currently has no side-effect.
# 0.1 # 0.1
- Initial release - Initial release

View File

@ -8,8 +8,8 @@
namespace Ndk namespace Ndk
{ {
inline Canvas::Canvas(WorldHandle world, Nz::EventHandler& eventHandler, Nz::CursorControllerHandle cursorController) : inline Canvas::Canvas(WorldHandle world, Nz::EventHandler& eventHandler, Nz::CursorControllerHandle cursorController) :
m_hoveredWidget(InvalidCanvasIndex),
m_keyboardOwner(InvalidCanvasIndex), m_keyboardOwner(InvalidCanvasIndex),
m_hoveredWidget(InvalidCanvasIndex),
m_cursorController(cursorController), m_cursorController(cursorController),
m_world(std::move(world)) m_world(std::move(world))
{ {

View File

@ -355,9 +355,9 @@ namespace Ndk
{ {
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex)); std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
Nz::String subMesh(lua.Check<Nz::String>(&argIndex)); Nz::String subMesh(lua.Check<Nz::String>(&argIndex));
Nz::MaterialRef material(lua.Check<Nz::MaterialRef>(&argIndex)); Nz::MaterialRef materialRef(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(skinIndex, subMesh, std::move(material)); instance->SetMaterial(skinIndex, subMesh, std::move(materialRef));
return 0; return 0;
} }

View File

@ -130,8 +130,6 @@ namespace Nz
* \brief Returns the number of elements in a C-array * \brief Returns the number of elements in a C-array
* \return The number of elements * \return The number of elements
* *
* \param name C-array
*
* \see CountOf * \see CountOf
*/ */
template<typename T, std::size_t N> template<typename T, std::size_t N>

View File

@ -815,7 +815,7 @@ namespace Nz
for (std::size_t i = 0; i < m_blocks.size(); ++i) for (std::size_t i = 0; i < m_blocks.size(); ++i)
{ {
Block mask = (i == m_blocks.size() - 1) ? lastBlockMask : fullBitMask; Block mask = (i == m_blocks.size() - 1) ? lastBlockMask : fullBitMask;
if (m_blocks[i] == mask) // The extra bits are set to zero, thus we can't test without proceeding with a mask if (m_blocks[i] != mask) // The extra bits are set to zero, thus we can't test without proceeding with a mask
return false; return false;
} }

View File

@ -421,7 +421,6 @@ namespace Nz
/*! /*!
* \brief Resizes the string * \brief Resizes the string
* \return A reference to this
* *
* \param newSize Target size * \param newSize Target size
*/ */
@ -433,7 +432,6 @@ namespace Nz
/*! /*!
* \brief Resizes the string * \brief Resizes the string
* \return A reference to this
* *
* \param newSize Target size * \param newSize Target size
* \param byte Byte to add if newSize is greather than actual size * \param byte Byte to add if newSize is greather than actual size

View File

@ -41,7 +41,7 @@ namespace Nz
void SetStream(void* ptr, Nz::UInt64 size); void SetStream(void* ptr, Nz::UInt64 size);
void SetStream(const void* ptr, Nz::UInt64 size); void SetStream(const void* ptr, Nz::UInt64 size);
inline void Write(const void* data, std::size_t size); inline std::size_t Write(const void* data, std::size_t size);
template<typename T> template<typename T>
ByteStream& operator>>(T& value); ByteStream& operator>>(T& value);

View File

@ -101,7 +101,7 @@ namespace Nz
* \brief Reads data * \brief Reads data
* \return Number of data read * \return Number of data read
* *
* \param buffer Preallocated buffer to contain information read * \param ptr Preallocated buffer to contain information read
* \param size Size of the read and thus of the buffer * \param size Size of the read and thus of the buffer
*/ */
@ -117,7 +117,7 @@ namespace Nz
/*! /*!
* \brief Sets the stream endianness * \brief Sets the stream endianness
* *
* \param Type of the endianness * \param endiannes Type of the endianness
*/ */
inline void ByteStream::SetDataEndianness(Endianness endiannes) inline void ByteStream::SetDataEndianness(Endianness endiannes)
@ -154,13 +154,13 @@ namespace Nz
* \remark Produces a NazaraAssert if buffer is nullptr * \remark Produces a NazaraAssert if buffer is nullptr
*/ */
inline void ByteStream::Write(const void* data, std::size_t size) inline std::size_t ByteStream::Write(const void* data, std::size_t size)
{ {
if (!m_context.stream) if (!m_context.stream)
OnEmptyStream(); OnEmptyStream();
FlushBits(); FlushBits();
m_context.stream->Write(data, size); return m_context.stream->Write(data, size);
} }
/*! /*!

View File

@ -23,6 +23,7 @@ namespace Nz
inline explicit Color(UInt8 lightness); inline explicit Color(UInt8 lightness);
inline Color(UInt8 color[3], UInt8 alpha = 255); inline Color(UInt8 color[3], UInt8 alpha = 255);
inline Color(const Color& color) = default; inline Color(const Color& color) = default;
inline Color(Color&& color) = default;
inline ~Color() = default; inline ~Color() = default;
inline bool IsOpaque() const; inline bool IsOpaque() const;
@ -32,6 +33,9 @@ namespace Nz
inline Color operator+(const Color& angles) const; inline Color operator+(const Color& angles) const;
inline Color operator*(const Color& angles) const; inline Color operator*(const Color& angles) const;
inline Color& operator=(const Color& other) = default;
inline Color& operator=(Color&& other) = default;
inline Color operator+=(const Color& angles); inline Color operator+=(const Color& angles);
inline Color operator*=(const Color& angles); inline Color operator*=(const Color& angles);
@ -40,13 +44,13 @@ namespace Nz
static inline Color FromCMY(float cyan, float magenta, float yellow); static inline Color FromCMY(float cyan, float magenta, float yellow);
static inline Color FromCMYK(float cyan, float magenta, float yellow, float black); static inline Color FromCMYK(float cyan, float magenta, float yellow, float black);
static inline Color FromHSL(UInt8 hue, UInt8 saturation, UInt8 lightness); static inline Color FromHSL(float hue, float saturation, float lightness);
static inline Color FromHSV(float hue, float saturation, float value); static inline Color FromHSV(float hue, float saturation, float value);
static inline Color FromXYZ(const Vector3f& vec); static inline Color FromXYZ(const Vector3f& vec);
static inline Color FromXYZ(float x, float y, float z); static inline Color FromXYZ(float x, float y, float z);
static inline void ToCMY(const Color& color, float* cyan, float* magenta, float* yellow); static inline void ToCMY(const Color& color, float* cyan, float* magenta, float* yellow);
static inline void ToCMYK(const Color& color, float* cyan, float* magenta, float* yellow, float* black); static inline void ToCMYK(const Color& color, float* cyan, float* magenta, float* yellow, float* black);
static inline void ToHSL(const Color& color, UInt8* hue, UInt8* saturation, UInt8* lightness); static inline void ToHSL(const Color& color, float* hue, float* saturation, float* lightness);
static inline void ToHSV(const Color& color, float* hue, float* saturation, float* value); static inline void ToHSV(const Color& color, float* hue, float* saturation, float* value);
static inline void ToXYZ(const Color& color, Vector3f* vec); static inline void ToXYZ(const Color& color, Vector3f* vec);
static inline void ToXYZ(const Color& color, float* x, float* y, float* z); static inline void ToXYZ(const Color& color, float* x, float* y, float* z);

View File

@ -219,35 +219,29 @@ namespace Nz
* \brief Converts HSL representation to RGB * \brief Converts HSL representation to RGB
* \return Color resulting * \return Color resulting
* *
* \param hue Hue component * \param hue Hue component in [0, 360]
* \param saturation Saturation component * \param saturation Saturation component [0, 1]
* \param lightness Lightness component * \param lightness Lightness component [0, 1]
*/ */
inline Color Color::FromHSL(UInt8 hue, UInt8 saturation, UInt8 lightness) inline Color Color::FromHSL(float hue, float saturation, float lightness)
{ {
if (saturation == 0) if (NumberEquals(saturation, 0.f))
{ {
// RGB results from 0 to 255 // RGB results from 0 to 255
return Color(lightness * 255, return Color(static_cast<UInt8>(lightness * 255.f));
lightness * 255,
lightness * 255);
} }
else else
{ {
// Norme Windows
float l = lightness/240.f;
float h = hue/240.f;
float s = saturation/240.f;
float v2; float v2;
if (l < 0.5f) if (lightness < 0.5f)
v2 = l * (1.f + s); v2 = lightness * (1.f + saturation);
else else
v2 = (l + s) - (s*l); v2 = (lightness + saturation) - (saturation * lightness);
float v1 = 2.f * l - v2; float v1 = 2.f * lightness - v2;
float h = hue / 360.f;
return Color(static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h + (1.f/3.f))), return Color(static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h + (1.f/3.f))),
static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h)), static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h)),
static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h - (1.f/3.f)))); static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h - (1.f/3.f))));
@ -258,9 +252,9 @@ namespace Nz
* \brief Converts HSV representation to RGB * \brief Converts HSV representation to RGB
* \return Color resulting * \return Color resulting
* *
* \param hue Hue component * \param hue Hue component in [0, 360]
* \param saturation Saturation component * \param saturation Saturation component in [0, 1]
* \param value Value component * \param value Value component in [0, 1]
*/ */
inline Color Color::FromHSV(float hue, float saturation, float value) inline Color Color::FromHSV(float hue, float saturation, float value)
@ -269,16 +263,15 @@ namespace Nz
return Color(static_cast<UInt8>(value * 255.f)); return Color(static_cast<UInt8>(value * 255.f));
else else
{ {
float h = hue/360.f * 6.f; float h = (hue / 360.f) * 6.f;
float s = saturation/360.f;
if (NumberEquals(h, 6.f)) if (NumberEquals(h , 6.f))
h = 0; // hue must be < 1 h = 0.f; // hue must be < 1
int i = static_cast<unsigned int>(h); int i = static_cast<int>(h);
float v1 = value * (1.f - s); float v1 = value * (1.f - saturation);
float v2 = value * (1.f - s * (h - i)); float v2 = value * (1.f - saturation * (h - i));
float v3 = value * (1.f - s * (1.f - (h - i))); float v3 = value * (1.f - saturation * (1.f - (h - i)));
float r, g, b; float r, g, b;
switch (i) switch (i)
@ -321,7 +314,7 @@ namespace Nz
} }
// RGB results from 0 to 255 // RGB results from 0 to 255
return Color(static_cast<UInt8>(r*255.f), static_cast<UInt8>(g*255.f), static_cast<UInt8>(b*255.f)); return Color(static_cast<UInt8>(r * 255.f), static_cast<UInt8>(g * 255.f), static_cast<UInt8>(b * 255.f));
} }
} }
@ -338,7 +331,7 @@ namespace Nz
} }
/*! /*!
* \brief Converts XYZ representation to RGB * \brief Converts XYZ representation (D65/2°) to RGB
* \return Color resulting * \return Color resulting
* *
* \param x X component * \param x X component
@ -362,12 +355,12 @@ namespace Nz
r *= 12.92f; r *= 12.92f;
if (g > 0.0031308f) if (g > 0.0031308f)
g = 1.055f * (std::pow(r, 1.f/2.4f)) - 0.055f; g = 1.055f * (std::pow(g, 1.f/2.4f)) - 0.055f;
else else
g *= 12.92f; g *= 12.92f;
if (b > 0.0031308f) if (b > 0.0031308f)
b = 1.055f * (std::pow(r, 1.f/2.4f)) - 0.055f; b = 1.055f * (std::pow(b, 1.f/2.4f)) - 0.055f;
else else
b *= 12.92f; b *= 12.92f;
@ -427,12 +420,12 @@ namespace Nz
* \brief Converts RGB representation to HSL * \brief Converts RGB representation to HSL
* *
* \param color Color to transform * \param color Color to transform
* \param hue Hue component * \param hue Hue component [0, 360]
* \param saturation Saturation component * \param saturation Saturation component in [0, 1]
* \param lightness Lightness component * \param lightness Lightness component in [0, 1]
*/ */
inline void Color::ToHSL(const Color& color, UInt8* hue, UInt8* saturation, UInt8* lightness) inline void Color::ToHSL(const Color& color, float* hue, float* saturation, float* lightness)
{ {
float r = color.r / 255.f; float r = color.r / 255.f;
float g = color.g / 255.f; float g = color.g / 255.f;
@ -443,42 +436,41 @@ namespace Nz
float deltaMax = max - min; //Delta RGB value float deltaMax = max - min; //Delta RGB value
float l = (max + min)/2.f; float l = (max + min) / 2.f;
*lightness = l;
if (NumberEquals(deltaMax, 0.f)) if (NumberEquals(deltaMax, 0.f))
{ {
//This is a gray, no chroma... //This is a gray, no chroma...
*hue = 0; //HSL results from 0 to 1 *hue = 0.f;
*saturation = 0; *saturation = 0.f;
} }
else else
{ {
//Chromatic data... if (l <= 0.5f)
if (l < 0.5f) *saturation = deltaMax / (max + min);
*saturation = static_cast<UInt8>(deltaMax/(max+min)*240.f);
else else
*saturation = static_cast<UInt8>(deltaMax/(2.f-max-min)*240.f); *saturation = (deltaMax / (2.f - max - min));
*lightness = static_cast<UInt8>(l*240.f); float deltaR = ((max - r) / 6.f + deltaMax / 2.f) / deltaMax;
float deltaG = ((max - g) / 6.f + deltaMax / 2.f) / deltaMax;
float deltaR = ((max - r)/6.f + deltaMax/2.f)/deltaMax; float deltaB = ((max - b) / 6.f + deltaMax / 2.f) / deltaMax;
float deltaG = ((max - g)/6.f + deltaMax/2.f)/deltaMax;
float deltaB = ((max - b)/6.f + deltaMax/2.f)/deltaMax;
float h; float h;
if (NumberEquals(r, max)) if (NumberEquals(r, max))
h = deltaB - deltaG; h = deltaB - deltaG;
else if (NumberEquals(g, max)) else if (NumberEquals(g, max))
h = (1.f/3.f) + deltaR - deltaB; h = (1.f / 3.f) + deltaR - deltaB;
else else
h = (2.f/3.f) + deltaG - deltaR; h = (2.f / 3.f) + deltaG - deltaR;
if (h < 0.f) if (h < 0.f)
h += 1.f; h += 1.f;
else if (h > 1.f) else if (h > 1.f)
h -= 1.f; h -= 1.f;
*hue = static_cast<UInt8>(h*240.f); *hue = h * 360.f;
} }
} }
@ -507,33 +499,33 @@ namespace Nz
if (NumberEquals(deltaMax, 0.f)) if (NumberEquals(deltaMax, 0.f))
{ {
//This is a gray, no chroma... //This is a gray, no chroma...
*hue = 0; //HSV results from 0 to 1 *hue = 0.f;
*saturation = 0; *saturation = 0.f;
} }
else else
{ {
//Chromatic data... //Chromatic data...
*saturation = deltaMax/max*360.f; *saturation = deltaMax / max;
float deltaR = ((max - r)/6.f + deltaMax/2.f)/deltaMax; float deltaR = ((max - r) / 6.f + deltaMax / 2.f) / deltaMax;
float deltaG = ((max - g)/6.f + deltaMax/2.f)/deltaMax; float deltaG = ((max - g) / 6.f + deltaMax / 2.f) / deltaMax;
float deltaB = ((max - b)/6.f + deltaMax/2.f)/deltaMax; float deltaB = ((max - b) / 6.f + deltaMax / 2.f) / deltaMax;
float h; float h;
if (NumberEquals(r, max)) if (NumberEquals(r, max))
h = deltaB - deltaG; h = deltaB - deltaG;
else if (NumberEquals(g, max)) else if (NumberEquals(g, max))
h = (1.f/3.f) + deltaR - deltaB; h = (1.f / 3.f) + deltaR - deltaB;
else else
h = (2.f/3.f) + deltaG - deltaR; h = (2.f / 3.f) + deltaG - deltaR;
if (h < 0.f) if (h < 0.f)
h += 1.f; h += 1.f;
else if (h > 1.f) else if (h > 1.f)
h -= 1.f; h -= 1.f;
*hue = h*360.f; *hue = h * 360.f;
} }
} }

View File

@ -29,7 +29,7 @@ namespace Nz
/*! /*!
* \brief Constructs a Flags object using an Enum value * \brief Constructs a Flags object using an Enum value
* *
* \param value enumVal * \param enumVal enumVal
* *
* Setup a Flags object with only one flag active (corresponding to the enum value passed as argument). * Setup a Flags object with only one flag active (corresponding to the enum value passed as argument).
*/ */

View File

@ -484,16 +484,17 @@ namespace Nz
namespace std namespace std
{ {
/*!
* \ingroup core
* \brief Gives a hash representation of the object, specialisation of std
* \return Hash of the ObjectRef
*
* \param object Object to hash
*/
template<typename T> template<typename T>
struct hash<Nz::ObjectRef<T>> struct hash<Nz::ObjectRef<T>>
{ {
/*!
* \ingroup core
* \brief Gives a hash representation of the object, specialisation of std
* \return Hash of the ObjectRef
*
* \param object Object to hash
*/
size_t operator()(const Nz::ObjectRef<T>& object) const size_t operator()(const Nz::ObjectRef<T>& object) const
{ {
hash<T*> h; hash<T*> h;

View File

@ -385,7 +385,7 @@ namespace Nz
* *
* \param size (Width, Depth) * \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis * \param subdivision Number of subdivision for the axis
* \param planeInfo Information for the plane * \param plane Information for the plane
* \param uvCoords Coordinates for texture * \param uvCoords Coordinates for texture
*/ */
inline Primitive Primitive::Plane(const Vector2f& size, const Vector2ui& subdivision, const Planef& plane, const Rectf& uvCoords) inline Primitive Primitive::Plane(const Vector2f& size, const Vector2ui& subdivision, const Planef& plane, const Rectf& uvCoords)

View File

@ -121,7 +121,7 @@ namespace std
const char* ptr = str.GetConstBuffer(); const char* ptr = str.GetConstBuffer();
do do
h = ((h << 5) + h) + *ptr; h = ((h << 5) + h) + static_cast<size_t>(*ptr);
while (*++ptr); while (*++ptr);
} }

View File

@ -265,7 +265,8 @@ namespace Nz
/*! /*!
* \brief Sets the inner angle in spot light * \brief Sets the inner angle in spot light
* \return innerAngle Inner angle *
* \param innerAngle Inner angle
*/ */
inline void Light::SetInnerAngle(float innerAngle) inline void Light::SetInnerAngle(float innerAngle)
@ -289,7 +290,8 @@ namespace Nz
/*! /*!
* \brief Sets the outer angle in spot light * \brief Sets the outer angle in spot light
* \return outerAngle Outer angle *
* \param outerAngle Outer angle
* *
* \remark Invalidates the bounding volume * \remark Invalidates the bounding volume
*/ */
@ -305,7 +307,8 @@ namespace Nz
/*! /*!
* \brief Sets the radius of the light * \brief Sets the radius of the light
* \return radius Light radius *
* \param radius Light radius
* *
* \remark Invalidates the bounding volume * \remark Invalidates the bounding volume
*/ */

View File

@ -552,11 +552,11 @@ namespace Nz
#endif #endif
const T twoLimit = limit * T(2); const T twoLimit = limit * T(2);
angle = std::fmod(angle + limit, twoLimit); angle = std::fmod(angle, twoLimit);
if (angle < T(0)) if (angle < T(0))
angle += twoLimit; angle += twoLimit;
return angle - limit; return angle;
} }
/*! /*!

View File

@ -541,7 +541,7 @@ namespace Nz
return Infinite(); return Infinite();
case Extend_Null: case Extend_Null:
return from.obb * interpolation; return to.obb * interpolation;
} }
// If we arrive here, the extend is invalid // If we arrive here, the extend is invalid

View File

@ -77,7 +77,6 @@ namespace Nz
/*! /*!
* \brief Makes the euler angle (0, 0, 0) * \brief Makes the euler angle (0, 0, 0)
* \return A reference to this euler angle with components (0, 0, 0)
* *
* \see Zero * \see Zero
*/ */
@ -276,7 +275,7 @@ namespace Nz
* \brief Substracts the components of other euler angle to this euler angle * \brief Substracts the components of other euler angle to this euler angle
* \return A reference to this euler angle where components are the difference of this euler angle and the other one * \return A reference to this euler angle where components are the difference of this euler angle and the other one
* *
* \param angle The other euler angle to substract components with * \param angles The other euler angle to substract components with
*/ */
template<typename T> template<typename T>

View File

@ -664,9 +664,9 @@ namespace Nz
template<typename T> template<typename T>
Vector3<T> Matrix4<T>::GetSquaredScale() const Vector3<T> Matrix4<T>::GetSquaredScale() const
{ {
return Vector3<T>(m11*m11 + m21*m21 + m31*m31, return Vector3<T>(m11 * m11 + m12 * m12 + m13 * m13,
m12*m12 + m22*m22 + m32*m32, m21 * m21 + m22 * m22 + m23 * m23,
m13*m13 + m23*m23 + m33*m33); m31 * m31 + m32 * m32 + m33 * m33);
} }
/*! /*!
@ -1153,36 +1153,32 @@ namespace Nz
* *
* \param rotation Quaternion representing a rotation of space * \param rotation Quaternion representing a rotation of space
* *
* \remark 3rd column and row are unchanged * \remark 3rd column and row are unchanged. Scale is removed.
*/ */
template<typename T> template<typename T>
Matrix4<T>& Matrix4<T>::SetRotation(const Quaternion<T>& rotation) Matrix4<T>& Matrix4<T>::SetRotation(const Quaternion<T>& rotation)
{ {
T tx = rotation.x + rotation.x; T qw = rotation.w;
T ty = rotation.y + rotation.y; T qx = rotation.x;
T tz = rotation.z + rotation.z; T qy = rotation.y;
T twx = tx * rotation.w; T qz = rotation.z;
T twy = ty * rotation.w;
T twz = tz * rotation.w;
T txx = tx * rotation.x;
T txy = ty * rotation.x;
T txz = tz * rotation.x;
T tyy = ty * rotation.y;
T tyz = tz * rotation.y;
T tzz = tz * rotation.z;
m11 = F(1.0) - (tyy + tzz); T qx2 = qx * qx;
m12 = txy + twz; T qy2 = qy * qy;
m13 = txz - twy; T qz2 = qz * qz;
m21 = txy - twz; m11 = F(1.0) - F(2.0) * qy2 - F(2.0) * qz2;
m22 = F(1.0) - (txx + tzz); m21 = F(2.0) * qx * qy - F(2.0) * qz * qw;
m23 = tyz + twx; m31 = F(2.0) * qx * qz + F(2.0) * qy * qw;
m31 = txz + twy; m12 = F(2.0) * qx * qy + F(2.0) * qz * qw;
m32 = tyz - twx; m22 = F(1.0) - F(2.0) * qx2 - F(2.0) * qz2;
m33 = F(1.0) - (txx + tyy); m32 = F(2.0) * qy * qz - F(2.0) * qx * qw;
m13 = F(2.0) * qx * qz - F(2.0) * qy * qw;
m23 = F(2.0) * qy * qz + F(2.0) * qx * qw;
m33 = F(1.0) - F(2.0) * qx2 - F(2.0) * qy2;
return *this; return *this;
} }

View File

@ -106,9 +106,9 @@ namespace Nz
* \brief Returns the distance from the plane to the point * \brief Returns the distance from the plane to the point
* \return Distance to the point * \return Distance to the point
* *
* \param X X position of the point * \param x X position of the point
* \param Y Y position of the point * \param y Y position of the point
* \param Z Z position of the point * \param z Z position of the point
* *
* \remark If T is negative, it means that the point is in the opposite direction of the normal * \remark If T is negative, it means that the point is in the opposite direction of the normal
* *
@ -319,7 +319,7 @@ namespace Nz
* \brief Compares the plane to other one * \brief Compares the plane to other one
* \return true if the planes are the same * \return true if the planes are the same
* *
* \param vec Other vector to compare with * \param plane Other vector to compare with
* *
* \remark Plane with normal N and distance D is the same than with normal -N et distance -D * \remark Plane with normal N and distance D is the same than with normal -N et distance -D
*/ */

View File

@ -251,35 +251,19 @@ namespace Nz
* \param from Initial vector * \param from Initial vector
* \param to Target vector * \param to Target vector
* *
* \remark Vectors are not required to be normalized
*
* \see RotationBetween * \see RotationBetween
*/ */
template<typename T> template<typename T>
Quaternion<T>& Quaternion<T>::MakeRotationBetween(const Vector3<T>& from, const Vector3<T>& to) Quaternion<T>& Quaternion<T>::MakeRotationBetween(const Vector3<T>& from, const Vector3<T>& to)
{ {
// TODO (Gawaboumga): Replace by http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors ? // Based on: http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors
T norm = std::sqrt(from.GetSquaredLength() * to.GetSquaredLength());
T dot = from.DotProduct(to); Vector3<T> crossProduct = from.CrossProduct(to);
if (NumberEquals(dot, F(-1.0))) Set(norm + from.DotProduct(to), crossProduct.x, crossProduct.y, crossProduct.z);
{ return Normalize();
Vector3<T> cross = Vector3<T>::CrossProduct(Vector3<T>::UnitX(), from);
if (NumberEquals(cross.GetLength(), F(0.0)))
cross = Vector3<T>::CrossProduct(Vector3<T>::UnitY(), from);
return Set(F(180.0), cross);
}
else if (NumberEquals(dot, F(1.0)))
return MakeIdentity();
else
{
Vector3<T> a = from.CrossProduct(to);
x = a.x;
y = a.y;
z = a.z;
w = T(1.0) + dot;
return Normalize();
}
} }
/*! /*!
@ -425,7 +409,7 @@ namespace Nz
* \brief Sets the components of the quaternion from another quaternion * \brief Sets the components of the quaternion from another quaternion
* \return A reference to this quaternion * \return A reference to this quaternion
* *
* \param vec The other quaternion * \param quat The other quaternion
*/ */
template<typename T> template<typename T>
@ -647,7 +631,7 @@ namespace Nz
* \brief Compares the quaternion to other one * \brief Compares the quaternion to other one
* \return true if the quaternions are the same * \return true if the quaternions are the same
* *
* \param vec Other quaternion to compare with * \param quat Other quaternion to compare with
*/ */
template<typename T> template<typename T>
@ -663,7 +647,7 @@ namespace Nz
* \brief Compares the quaternion to other one * \brief Compares the quaternion to other one
* \return false if the quaternions are the same * \return false if the quaternions are the same
* *
* \param vec Other quaternion to compare with * \param quat Other quaternion to compare with
*/ */
template<typename T> template<typename T>

View File

@ -500,7 +500,7 @@ namespace Nz
* \brief Multiplies the radius of the sphere with a scalar * \brief Multiplies the radius of the sphere with a scalar
* \return A sphere where the center is the same and radius is the product of this radius and the scalar * \return A sphere where the center is the same and radius is the product of this radius and the scalar
* *
* \param scale The scalar to multiply radius with * \param scalar The scalar to multiply radius with
*/ */
template<typename T> template<typename T>
@ -513,7 +513,7 @@ namespace Nz
* \brief Multiplies the radius of other sphere with a scalar * \brief Multiplies the radius of other sphere with a scalar
* \return A reference to this sphere where the center is the same and radius is the product of this radius and the scalar * \return A reference to this sphere where the center is the same and radius is the product of this radius and the scalar
* *
* \param scale The scalar to multiply radius with * \param scalar The scalar to multiply radius with
*/ */
template<typename T> template<typename T>

View File

@ -692,7 +692,7 @@ namespace Nz
* \brief Multiplies the components of other vector with a scalar * \brief Multiplies the components of other vector with a scalar
* \return A reference to this vector where components are the product of this vector and the scalar * \return A reference to this vector where components are the product of this vector and the scalar
* *
* \param vec The other vector to multiply components with * \param scale The scalar to multiply components with
*/ */
template<typename T> template<typename T>
@ -737,7 +737,7 @@ namespace Nz
* \brief Divides the components of other vector with a scalar * \brief Divides the components of other vector with a scalar
* \return A reference to this vector where components are the quotient of this vector and the scalar * \return A reference to this vector where components are the quotient of this vector and the scalar
* *
* \param vec The other vector to divide components with * \param scale The scalar to divide components with
* *
* \remark Produce a NazaraError if scale is null with NAZARA_MATH_SAFE defined * \remark Produce a NazaraError if scale is null with NAZARA_MATH_SAFE defined
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and scale is null * \throw std::domain_error if NAZARA_MATH_SAFE is defined and scale is null

View File

@ -810,7 +810,7 @@ namespace Nz
* \brief Multiplies the components of other vector with a scalar * \brief Multiplies the components of other vector with a scalar
* \return A reference to this vector where components are the product of this vector and the scalar * \return A reference to this vector where components are the product of this vector and the scalar
* *
* \param vec The other vector to multiply components with * \param scale The scalar to multiply components with
*/ */
template<typename T> template<typename T>
Vector3<T>& Vector3<T>::operator*=(T scale) Vector3<T>& Vector3<T>::operator*=(T scale)
@ -853,7 +853,7 @@ namespace Nz
* \brief Divides the components of other vector with a scalar * \brief Divides the components of other vector with a scalar
* \return A reference to this vector where components are the quotient of this vector and the scalar * \return A reference to this vector where components are the quotient of this vector and the scalar
* *
* \param vec The other vector to divide components with * \param scale The scalar to divide components with
* *
* \remark Produce a NazaraError if scale is null with NAZARA_MATH_SAFE defined * \remark Produce a NazaraError if scale is null with NAZARA_MATH_SAFE defined
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and scale is null * \throw std::domain_error if NAZARA_MATH_SAFE is defined and scale is null

View File

@ -728,7 +728,7 @@ namespace Nz
* \brief Multiplies the components of other vector with a scalar * \brief Multiplies the components of other vector with a scalar
* \return A reference to this vector where components are the product of this vector and the scalar * \return A reference to this vector where components are the product of this vector and the scalar
* *
* \param vec The other vector to multiply components with * \param scale The scalar to multiply components with
*/ */
template<typename T> template<typename T>
@ -777,7 +777,7 @@ namespace Nz
* \brief Divides the components of other vector with a scalar * \brief Divides the components of other vector with a scalar
* \return A reference to this vector where components are the quotient of this vector and the scalar * \return A reference to this vector where components are the quotient of this vector and the scalar
* *
* \param vec The other vector to divide components with * \param scale The scalar to divide components with
* *
* \remark Produce a NazaraError if scale is null with NAZARA_MATH_SAFE defined * \remark Produce a NazaraError if scale is null with NAZARA_MATH_SAFE defined
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and scale is null * \throw std::domain_error if NAZARA_MATH_SAFE is defined and scale is null

View File

@ -312,7 +312,7 @@ namespace Nz
/*! /*!
* \brief Sets the pattern of the directory * \brief Sets the pattern of the directory
* *
* \param dirPath Pattern of the directory * \param pattern Pattern of the directory
*/ */
void Directory::SetPattern(const String& pattern) void Directory::SetPattern(const String& pattern)
@ -327,7 +327,7 @@ namespace Nz
* \return true if copy is successful * \return true if copy is successful
* *
* \param sourcePath Path of the original directory * \param sourcePath Path of the original directory
* \param targetPath Path of the copied directory * \param destPath Path of the copied directory
* *
* \remark Produces a NazaraError if could not create destination directory * \remark Produces a NazaraError if could not create destination directory
* \remark Produces a NazaraError if could not open origin directory * \remark Produces a NazaraError if could not open origin directory

View File

@ -293,7 +293,7 @@ namespace Nz
* *
* \param rects List of rectangles * \param rects List of rectangles
* \param flipped List of flipped rectangles * \param flipped List of flipped rectangles
* \param flipped List of inserted rectangles * \param inserted List of inserted rectangles
* \param count Count of rectangles * \param count Count of rectangles
* \param merge Merge possible * \param merge Merge possible
* \param rectChoice Heuristic to use to free * \param rectChoice Heuristic to use to free

View File

@ -94,7 +94,7 @@ namespace Nz
* \return Raw memory allocated * \return Raw memory allocated
* *
* \param size Size to allocate * \param size Size to allocate
* \parma multi Array or not * \param multi Array or not
* \param file File of the allocation * \param file File of the allocation
* \param line Line of the allocation in the file * \param line Line of the allocation in the file
*/ */

View File

@ -718,7 +718,6 @@ namespace Nz
* \brief Create an uninitialized value of a set name * \brief Create an uninitialized value of a set name
* *
* \param name Name of the parameter * \param name Name of the parameter
* \param value Value of the parameter
* *
* \remark The previous value if any gets destroyed * \remark The previous value if any gets destroyed
*/ */

View File

@ -190,7 +190,7 @@ namespace Nz
/*! /*!
* \brief Unmounts the plugin with a path * \brief Unmounts the plugin with a path
* *
* \param pluginPath Path to the plugin * \param plugin Path to the plugin
* *
* \remark Produces a NazaraError if not initialized * \remark Produces a NazaraError if not initialized
* \remark Produces a NazaraError if plugin is not loaded * \remark Produces a NazaraError if plugin is not loaded

View File

@ -42,7 +42,7 @@ namespace Nz
{ {
String path = libraryPath; String path = libraryPath;
unsigned int pos = path.FindLast(".so"); size_t pos = path.FindLast(".so");
if (pos == String::npos || (path.GetLength() > pos+3 && path[pos+3] != '.')) if (pos == String::npos || (path.GetLength() > pos+3 && path[pos+3] != '.'))
path += ".so"; path += ".so";

View File

@ -295,7 +295,7 @@ namespace Nz
} }
/*! /*!
* \Brief Checks whether the string contains the character * \brief Checks whether the string contains the character
* \return true if found in the string * \return true if found in the string
* *
* \param character Single character * \param character Single character
@ -311,7 +311,7 @@ namespace Nz
} }
/*! /*!
* \Brief Checks whether the string contains the "C string" * \brief Checks whether the string contains the "C string"
* \return true if found in the string * \return true if found in the string
* *
* \param string String to search * \param string String to search
@ -327,7 +327,7 @@ namespace Nz
} }
/*! /*!
* \Brief Checks whether the string contains the string * \brief Checks whether the string contains the string
* \return true if found in the string * \return true if found in the string
* *
* \param string String to search * \param string String to search
@ -2244,7 +2244,7 @@ namespace Nz
* \brief Gets the word until next separator * \brief Gets the word until next separator
* \return Word string * \return Word string
* *
* \param start Index to begin the search * \param index Index to begin the search
* \param flags Flag for the look up * \param flags Flag for the look up
*/ */
@ -2289,7 +2289,7 @@ namespace Nz
* \brief Gets the word position * \brief Gets the word position
* \return Position of the beginning of the word * \return Position of the beginning of the word
* *
* \param start Index to begin the search * \param index Index to begin the search
* \param flags Flag for the look up * \param flags Flag for the look up
*/ */
@ -2729,8 +2729,8 @@ namespace Nz
* \brief Replaces the old "C string" by the new one * \brief Replaces the old "C string" by the new one
* \return Number of changes * \return Number of changes
* *
* \param oldCharacter Pattern to find * \param oldString Pattern to find
* \param newCharacter Pattern to change for * \param replaceString Pattern to change for
* \param start Index to begin the search * \param start Index to begin the search
* \param flags Flag for the look up * \param flags Flag for the look up
*/ */
@ -2744,10 +2744,10 @@ namespace Nz
* \brief Replaces the old "C string" by the new one * \brief Replaces the old "C string" by the new one
* \return Number of changes * \return Number of changes
* *
* \param oldCharacter Pattern to find * \param oldString Pattern to find
* \param oldLength Length of the old string * \param oldLength Length of the old string
* \param newCharacter Pattern to change for * \param replaceString Pattern to change for
* \param Length of the new string * \param replaceLength of the new string
* \param start Index to begin the search * \param start Index to begin the search
* \param flags Flag for the look up * \param flags Flag for the look up
*/ */
@ -2822,8 +2822,8 @@ namespace Nz
* \brief Replaces the old string by the new one * \brief Replaces the old string by the new one
* \return Number of changes * \return Number of changes
* *
* \param oldCharacter Pattern to find * \param oldString Pattern to find
* \param newCharacter Pattern to change for * \param replaceString Pattern to change for
* \param start Index to begin the search * \param start Index to begin the search
* \param flags Flag for the look up * \param flags Flag for the look up
*/ */
@ -2838,7 +2838,7 @@ namespace Nz
* \return Number of changes * \return Number of changes
* *
* \param oldCharacters Pattern to find * \param oldCharacters Pattern to find
* \param newCharacter Pattern to change for * \param replaceCharacter Pattern to change for
* \param start Index to begin the search * \param start Index to begin the search
* \param flags Flag for the look up * \param flags Flag for the look up
* *
@ -3646,7 +3646,7 @@ namespace Nz
* \return The number of splits * \return The number of splits
* *
* \param result Resulting tokens * \param result Resulting tokens
* \param separation List of characters of separation * \param separations List of characters for separation
* \param start Index for the beginning of the search * \param start Index for the beginning of the search
* \param flags Flag for the look up * \param flags Flag for the look up
*/ */
@ -3687,7 +3687,7 @@ namespace Nz
* \return The number of splits * \return The number of splits
* *
* \param result Resulting tokens * \param result Resulting tokens
* \param separation List of characters of separation * \param separations List of characters for separation
* \param start Index for the beginning of the search * \param start Index for the beginning of the search
* \param flags Flag for the look up * \param flags Flag for the look up
*/ */
@ -3885,7 +3885,7 @@ namespace Nz
* \brief Returns a sub string of the string from a character * \brief Returns a sub string of the string from a character
* \return SubString * \return SubString
* *
* \param charater Pattern to find * \param character Pattern to find
* \param startPos Index for the beginning of the search * \param startPos Index for the beginning of the search
* \param fromLast beginning by the end * \param fromLast beginning by the end
* \param include Include the character * \param include Include the character
@ -3975,7 +3975,7 @@ namespace Nz
* \brief Returns a sub string of the string up to a character * \brief Returns a sub string of the string up to a character
* \return SubString * \return SubString
* *
* \param charater Pattern to find * \param character Pattern to find
* \param startPos Index for the beginning of the search * \param startPos Index for the beginning of the search
* \param toLast beginning by the end * \param toLast beginning by the end
* \param include Include the character * \param include Include the character
@ -4124,7 +4124,6 @@ namespace Nz
* \return true if successful * \return true if successful
* *
* \param value Double to convert to * \param value Double to convert to
* \param flags Flag for the look up
*/ */
bool String::ToDouble(double* value) const bool String::ToDouble(double* value) const
@ -4143,7 +4142,7 @@ namespace Nz
* \return true if successful * \return true if successful
* *
* \param value Integer to convert to * \param value Integer to convert to
* \param flags Flag for the look up * \param base Base to convert the integer to
*/ */
bool String::ToInteger(long long* value, UInt8 base) const bool String::ToInteger(long long* value, UInt8 base) const
@ -5483,7 +5482,7 @@ namespace Nz
* \brief Output operator * \brief Output operator
* \return The stream * \return The stream
* *
* \param out The stream * \param os The stream
* \param str The string to output * \param str The string to output
*/ */
@ -5523,7 +5522,7 @@ namespace Nz
* \return String which is the result of the concatenation * \return String which is the result of the concatenation
* *
* \param string String to add * \param string String to add
* \param string String in the right hand side * \param nstring String in the right hand side
*/ */
String operator+(const char* string, const String& nstring) String operator+(const char* string, const String& nstring)
@ -5549,7 +5548,7 @@ namespace Nz
* \return String which is the result of the concatenation * \return String which is the result of the concatenation
* *
* \param string String to add * \param string String to add
* \param string String in the right hand side * \param nstring String in the right hand side
*/ */
String operator+(const std::string& string, const String& nstring) String operator+(const std::string& string, const String& nstring)
@ -5667,7 +5666,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param character Single character in left hand side * \param character Single character in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator==(char character, const String& nstring) bool operator==(char character, const String& nstring)
@ -5680,7 +5679,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator==(const char* string, const String& nstring) bool operator==(const char* string, const String& nstring)
@ -5693,7 +5692,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator==(const std::string& string, const String& nstring) bool operator==(const std::string& string, const String& nstring)
@ -5706,7 +5705,7 @@ namespace Nz
* \return false if it is the case * \return false if it is the case
* *
* \param character Single character in left hand side * \param character Single character in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator!=(char character, const String& nstring) bool operator!=(char character, const String& nstring)
@ -5719,7 +5718,7 @@ namespace Nz
* \return false if it is the case * \return false if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator!=(const char* string, const String& nstring) bool operator!=(const char* string, const String& nstring)
@ -5732,7 +5731,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator!=(const std::string& string, const String& nstring) bool operator!=(const std::string& string, const String& nstring)
@ -5745,7 +5744,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param character Single character in left hand side * \param character Single character in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator<(char character, const String& nstring) bool operator<(char character, const String& nstring)
@ -5758,7 +5757,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator<(const char* string, const String& nstring) bool operator<(const char* string, const String& nstring)
@ -5771,7 +5770,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator<(const std::string& string, const String& nstring) bool operator<(const std::string& string, const String& nstring)
@ -5784,7 +5783,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param character Single character in left hand side * \param character Single character in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator<=(char character, const String& nstring) bool operator<=(char character, const String& nstring)
@ -5797,7 +5796,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator<=(const char* string, const String& nstring) bool operator<=(const char* string, const String& nstring)
@ -5810,7 +5809,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator<=(const std::string& string, const String& nstring) bool operator<=(const std::string& string, const String& nstring)
@ -5823,7 +5822,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param character Single character in left hand side * \param character Single character in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator>(char character, const String& nstring) bool operator>(char character, const String& nstring)
@ -5836,7 +5835,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator>(const char* string, const String& nstring) bool operator>(const char* string, const String& nstring)
@ -5849,7 +5848,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator>(const std::string& string, const String& nstring) bool operator>(const std::string& string, const String& nstring)
@ -5862,7 +5861,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param character Single character in left hand side * \param character Single character in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator>=(char character, const String& nstring) bool operator>=(char character, const String& nstring)
@ -5875,7 +5874,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator>=(const char* string, const String& nstring) bool operator>=(const char* string, const String& nstring)
@ -5888,7 +5887,7 @@ namespace Nz
* \return true if it is the case * \return true if it is the case
* *
* \param string String to compare in left hand side * \param string String to compare in left hand side
* \param second String to compare in right hand side * \param nstring String to compare in right hand side
*/ */
bool operator>=(const std::string& string, const String& nstring) bool operator>=(const std::string& string, const String& nstring)

View File

@ -26,14 +26,14 @@ namespace Nz
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata); auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
if (drawOptions->circleCallback) if (drawOptions->circleCallback)
drawOptions->circleCallback(Vector2f(float(pos.x), float(pos.y)), float(angle), float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata); drawOptions->circleCallback(Vector2f(float(pos.x), float(pos.y)), float(angle), float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
}; }
void DrawDot(cpFloat size, cpVect pos, cpSpaceDebugColor color, cpDataPointer userdata) void DrawDot(cpFloat size, cpVect pos, cpSpaceDebugColor color, cpDataPointer userdata)
{ {
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata); auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
if (drawOptions->dotCallback) if (drawOptions->dotCallback)
drawOptions->dotCallback(Vector2f(float(pos.x), float(pos.y)), float(size), CpDebugColorToColor(color), drawOptions->userdata); drawOptions->dotCallback(Vector2f(float(pos.x), float(pos.y)), float(size), CpDebugColorToColor(color), drawOptions->userdata);
}; }
using DebugDrawPolygonCallback = std::function<void(const Vector2f* vertices, std::size_t vertexCount, float radius, Color outlineColor, Color fillColor, void* userdata)>; using DebugDrawPolygonCallback = std::function<void(const Vector2f* vertices, std::size_t vertexCount, float radius, Color outlineColor, Color fillColor, void* userdata)>;
@ -50,21 +50,21 @@ namespace Nz
drawOptions->polygonCallback(nVertices.data(), vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata); drawOptions->polygonCallback(nVertices.data(), vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
} }
}; }
void DrawSegment(cpVect a, cpVect b, cpSpaceDebugColor color, cpDataPointer userdata) void DrawSegment(cpVect a, cpVect b, cpSpaceDebugColor color, cpDataPointer userdata)
{ {
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata); auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
if (drawOptions->segmentCallback) if (drawOptions->segmentCallback)
drawOptions->segmentCallback(Vector2f(float(a.x), float(a.y)), Vector2f(float(b.x), float(b.y)), CpDebugColorToColor(color), drawOptions->userdata); drawOptions->segmentCallback(Vector2f(float(a.x), float(a.y)), Vector2f(float(b.x), float(b.y)), CpDebugColorToColor(color), drawOptions->userdata);
}; }
void DrawThickSegment(cpVect a, cpVect b, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer userdata) void DrawThickSegment(cpVect a, cpVect b, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer userdata)
{ {
auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata); auto drawOptions = static_cast<PhysWorld2D::DebugDrawOptions*>(userdata);
if (drawOptions->thickSegmentCallback) if (drawOptions->thickSegmentCallback)
drawOptions->thickSegmentCallback(Vector2f(float(a.x), float(a.y)), Vector2f(float(b.x), float(b.y)), float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata); drawOptions->thickSegmentCallback(Vector2f(float(a.x), float(a.y)), Vector2f(float(b.x), float(b.y)), float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata);
}; }
cpSpaceDebugColor GetColorForShape(cpShape* shape, cpDataPointer userdata) cpSpaceDebugColor GetColorForShape(cpShape* shape, cpDataPointer userdata)
{ {
@ -76,7 +76,7 @@ namespace Nz
} }
else else
return cpSpaceDebugColor{255.f, 0.f, 0.f, 255.f}; return cpSpaceDebugColor{255.f, 0.f, 0.f, 255.f};
}; }
} }
PhysWorld2D::PhysWorld2D() : PhysWorld2D::PhysWorld2D() :

View File

@ -55,8 +55,8 @@ namespace Nz
OnRigidBody2DRelease(std::move(object.OnRigidBody2DRelease)), OnRigidBody2DRelease(std::move(object.OnRigidBody2DRelease)),
m_shapes(std::move(object.m_shapes)), m_shapes(std::move(object.m_shapes)),
m_geom(std::move(object.m_geom)), m_geom(std::move(object.m_geom)),
m_userData(object.m_userData),
m_handle(object.m_handle), m_handle(object.m_handle),
m_userData(object.m_userData),
m_world(object.m_world), m_world(object.m_world),
m_isStatic(object.m_isStatic), m_isStatic(object.m_isStatic),
m_gravityFactor(object.m_gravityFactor), m_gravityFactor(object.m_gravityFactor),

View File

@ -58,7 +58,8 @@ namespace Nz
m_parent(parent), m_parent(parent),
m_smoothScrolling(false), m_smoothScrolling(false),
m_mousePos(0, 0), m_mousePos(0, 0),
m_keyRepeat(true) m_keyRepeat(true),
m_lastSequence(0)
{ {
std::memset(&m_size_hints, 0, sizeof(m_size_hints)); std::memset(&m_size_hints, 0, sizeof(m_size_hints));
} }
@ -1244,9 +1245,12 @@ namespace Nz
{ {
xcb_motion_notify_event_t* motionNotifyEvent = (xcb_motion_notify_event_t*)windowEvent; xcb_motion_notify_event_t* motionNotifyEvent = (xcb_motion_notify_event_t*)windowEvent;
if (m_mousePos.x == motionNotifyEvent->event_x && m_mousePos.y == motionNotifyEvent->event_y) // We use the sequence to determine whether the motion is linked to a Mouse::SetPosition
if ((m_mousePos.x == motionNotifyEvent->event_x && m_mousePos.y == motionNotifyEvent->event_y) || m_lastSequence == motionNotifyEvent->sequence)
break; break;
m_lastSequence = motionNotifyEvent->sequence;
WindowEvent event; WindowEvent event;
event.type = Nz::WindowEventType_MouseMoved; event.type = Nz::WindowEventType_MouseMoved;
event.mouseMove.deltaX = motionNotifyEvent->event_x - m_mousePos.x; event.mouseMove.deltaX = motionNotifyEvent->event_x - m_mousePos.x;

View File

@ -113,6 +113,7 @@ namespace Nz
bool m_threadActive; bool m_threadActive;
Vector2i m_mousePos; Vector2i m_mousePos;
bool m_keyRepeat; bool m_keyRepeat;
uint16_t m_lastSequence;
struct struct
{ {

View File

@ -30,9 +30,63 @@ TEST_CASE("Apply", "[CORE][ALGORITHM]")
TEST_CASE("ComputeHash", "[CORE][ALGORITHM]") TEST_CASE("ComputeHash", "[CORE][ALGORITHM]")
{ {
SECTION("Compute hash of '0'") /*SECTION("Compute CRC32 of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_CRC32, "1234");
REQUIRE(result.ToHex().ToUpper() == "596A3B55");
}
SECTION("Compute CRC64 of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_CRC64, "1234");
REQUIRE(result.ToHex().ToUpper() == "33302B9FC23855A8");
}
SECTION("Compute Fletcher16 of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_Fletcher16, "1234");
REQUIRE(result.ToHex().ToUpper() == "F5CA");
}*/
SECTION("Compute MD5 of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_MD5, "1234");
REQUIRE(result.ToHex().ToUpper() == "81DC9BDB52D04DC20036DBD8313ED055");
}
SECTION("Compute SHA1 of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_SHA1, "1234");
REQUIRE(result.ToHex().ToUpper() == "7110EDA4D09E062AA5E4A390B0A572AC0D2C0220");
}
SECTION("Compute SHA224 of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_SHA224, "1234");
REQUIRE(result.ToHex().ToUpper() == "99FB2F48C6AF4761F904FC85F95EB56190E5D40B1F44EC3A9C1FA319");
}
SECTION("Compute SHA256 of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_SHA256, "1234");
REQUIRE(result.ToHex().ToUpper() == "03AC674216F3E15C761EE1A5E255F067953623C8B388B4459E13F978D7C846F4");
}
SECTION("Compute SHA384 of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_SHA384, "1234");
REQUIRE(result.ToHex().ToUpper() == "504F008C8FCF8B2ED5DFCDE752FC5464AB8BA064215D9C5B5FC486AF3D9AB8C81B14785180D2AD7CEE1AB792AD44798C");
}
SECTION("Compute SHA512 of '1234'")
{ {
auto result = Nz::ComputeHash(Nz::HashType_SHA512, "1234"); auto result = Nz::ComputeHash(Nz::HashType_SHA512, "1234");
REQUIRE(result.ToHex().ToUpper() == "D404559F602EAB6FD602AC7680DACBFAADD13630335E951F097AF3900E9DE176B6DB28512F2E000B9D04FBA5133E8B1C6E8DF59DB3A8AB9D60BE4B97CC9E81DB"); REQUIRE(result.ToHex().ToUpper() == "D404559F602EAB6FD602AC7680DACBFAADD13630335E951F097AF3900E9DE176B6DB28512F2E000B9D04FBA5133E8B1C6E8DF59DB3A8AB9D60BE4B97CC9E81DB");
} }
SECTION("Compute Whirlpool of '1234'")
{
auto result = Nz::ComputeHash(Nz::HashType_Whirlpool, "1234");
REQUIRE(result.ToHex().ToUpper() == "2F9959B230A44678DD2DC29F037BA1159F233AA9AB183CE3A0678EAAE002E5AA6F27F47144A1A4365116D3DB1B58EC47896623B92D85CB2F191705DAF11858B8");
}
} }

View File

@ -8,6 +8,7 @@
template<typename Block> void Check(const char* title); template<typename Block> void Check(const char* title);
template<typename Block> void CheckAppend(const char* title); template<typename Block> void CheckAppend(const char* title);
template<typename Block> void CheckBitOps(const char* title); template<typename Block> void CheckBitOps(const char* title);
template<typename Block> void CheckBitOpsMultipleBlocks(const char* title);
template<typename Block> void CheckConstructor(const char* title); template<typename Block> void CheckConstructor(const char* title);
template<typename Block> void CheckCopyMoveSwap(const char* title); template<typename Block> void CheckCopyMoveSwap(const char* title);
template<typename Block> void CheckRead(const char* title); template<typename Block> void CheckRead(const char* title);
@ -28,6 +29,7 @@ void Check(const char* title)
CheckCopyMoveSwap<Block>(title); CheckCopyMoveSwap<Block>(title);
CheckBitOps<Block>(title); CheckBitOps<Block>(title);
CheckBitOpsMultipleBlocks<Block>(title);
CheckAppend<Block>(title); CheckAppend<Block>(title);
CheckRead<Block>(title); CheckRead<Block>(title);
@ -111,7 +113,68 @@ void CheckBitOps(const char* title)
{ {
CHECK(andBitset == Nz::Bitset<Block>("00001")); CHECK(andBitset == Nz::Bitset<Block>("00001"));
CHECK(orBitset == Nz::Bitset<Block>("11111")); CHECK(orBitset == Nz::Bitset<Block>("11111"));
CHECK(orBitset.TestAll());
CHECK(xorBitset == Nz::Bitset<Block>("11110")); CHECK(xorBitset == Nz::Bitset<Block>("11110"));
CHECK(!xorBitset.TestAll());
CHECK((~orBitset).TestNone());
}
}
WHEN("We perform bit shifts")
{
first.ShiftLeft(1);
second.ShiftRight(2);
THEN("We should obtain these")
{
CHECK(first == Nz::Bitset<Block>("10010"));
CHECK(second == Nz::Bitset<Block>("101"));
}
}
}
}
}
template<typename Block>
void CheckBitOpsMultipleBlocks(const char* title)
{
SECTION(title)
{
GIVEN("Two bitsets")
{
Nz::Bitset<Block> first("01001011010010101001010011010101001");
Nz::Bitset<Block> second("10111111101101110110111101101110110");
WHEN("We perform operators")
{
Nz::Bitset<Block> andBitset = first & second;
Nz::Bitset<Block> orBitset = first | second;
Nz::Bitset<Block> xorBitset = first ^ second;
THEN("They should operate as logical operators")
{
CHECK(andBitset == Nz::Bitset<Block>("00001011000000100000010001000100000"));
CHECK(orBitset == Nz::Bitset<Block>("11111111111111111111111111111111111"));
CHECK(orBitset.TestAll());
CHECK(xorBitset == Nz::Bitset<Block>("11110100111111011111101110111011111"));
CHECK(!xorBitset.TestAll());
CHECK((~orBitset).TestNone());
}
}
WHEN("We perform bit shifts")
{
first.ShiftLeft(16);
second.ShiftRight(16);
THEN("We should obtain these")
{
CHECK(first == Nz::Bitset<Block>("10010100110101010010000000000000000"));
first.ShiftLeft(1);
CHECK(first == Nz::Bitset<Block>("00101001101010100100000000000000000"));
CHECK(second == Nz::Bitset<Block>("1011111110110111011"));
second.ShiftRight(1);
CHECK(second == Nz::Bitset<Block>("101111111011011101"));
} }
} }
} }

View File

@ -0,0 +1,73 @@
#include <Nazara/Core/ByteStream.hpp>
#include <Catch/catch.hpp>
#include <array>
SCENARIO("ByteStream", "[CORE][BYTESTREAM]")
{
GIVEN("A bytestream from a bunch of bytes")
{
const int numberOfBytes = 16;
std::array<Nz::Int8, numberOfBytes> data;
Nz::ByteStream byteStream(data.data(), numberOfBytes);
WHEN("We write some data in it")
{
int value = 5;
byteStream << value;
Nz::String string = "string";
byteStream << string;
byteStream.FlushBits();
THEN("We can retrieve them")
{
const void* const ptrData = data.data();
Nz::ByteStream readStream;
CHECK(readStream.GetSize() == 0);
readStream = Nz::ByteStream(ptrData, byteStream.GetSize());
int retrievedValue = 0;
readStream >> retrievedValue;
Nz::String retrievedString;
readStream >> retrievedString;
CHECK(value == retrievedValue);
CHECK(string == retrievedString);
}
}
}
GIVEN("A bytestream with a byte array and a different endianness")
{
const int numberOfBytes = 16;
Nz::ByteArray byteArray(numberOfBytes);
Nz::ByteStream byteStream(&byteArray);
byteStream.SetDataEndianness(Nz::GetPlatformEndianness() == Nz::Endianness_BigEndian ? Nz::Endianness_LittleEndian : Nz::Endianness_BigEndian);
WHEN("We write an integer")
{
int value = 7;
byteStream.Write(&value, sizeof(int));
bool boolean = true;
byteStream << boolean;
byteStream.FlushBits();
THEN("We can retrieve it properly")
{
Nz::ByteStream tmpStream(&byteArray);
tmpStream.SetDataEndianness(byteStream.GetDataEndianness());
int retrievedValue = 0;
tmpStream.Read(&retrievedValue, sizeof(int));
CHECK(value == retrievedValue);
Nz::ByteStream readStream(std::move(tmpStream));
bool retrievedBoolean = false;
readStream >> retrievedBoolean;
CHECK(boolean == retrievedBoolean);
}
}
}
}

View File

@ -6,24 +6,43 @@ SCENARIO("Clock", "[CORE][CLOCK]")
{ {
GIVEN("A clock paused") GIVEN("A clock paused")
{ {
Nz::UInt64 initialTime = 1; Nz::UInt64 initialTime = 100;
Nz::Clock clock(initialTime, true); Nz::Clock clock(initialTime, true);
WHEN("We get time") WHEN("We get time since it is paused")
{ {
THEN("Time must be the initialTime") THEN("Time must be the initialTime")
{ {
REQUIRE(clock.GetMicroseconds() == initialTime); CHECK(clock.GetMicroseconds() == initialTime);
CHECK(clock.IsPaused());
} }
}
AND_WHEN("We unpause it") WHEN("We unpause it")
{
clock.Unpause();
REQUIRE(!clock.IsPaused());
THEN("Time must not be the initialTime")
{ {
clock.Unpause(); Nz::Thread::Sleep(1);
THEN("Time must not be the initialTime") Nz::UInt64 microSeconds = clock.GetMicroseconds();
{ CHECK(microSeconds != initialTime);
Nz::Thread::Sleep(1); CHECK(microSeconds / 1000 <= clock.GetMilliseconds());
REQUIRE(clock.GetMicroseconds() != initialTime); CHECK(microSeconds / (1000.f * 1000.f) <= clock.GetSeconds());
} }
}
WHEN("We restart it")
{
clock.Restart();
THEN("It is unpaused and we can pause it")
{
CHECK(!clock.IsPaused());
clock.Pause();
CHECK(clock.IsPaused());
CHECK(clock.GetMicroseconds() != initialTime);
} }
} }
} }

View File

@ -1,6 +1,63 @@
#include <Nazara/Core/Color.hpp> #include <Nazara/Core/Color.hpp>
#include <Catch/catch.hpp> #include <Catch/catch.hpp>
const float epsilon = 0.01f;
void CompareColor(const Nz::Color& lhs, const Nz::Color& rhs)
{
Nz::UInt8 tolerance = 3;
REQUIRE(Nz::NumberEquals(lhs.r, rhs.r, tolerance));
REQUIRE(Nz::NumberEquals(lhs.g, rhs.g, tolerance));
REQUIRE(Nz::NumberEquals(lhs.b, rhs.b, tolerance));
REQUIRE(Nz::NumberEquals(lhs.a, rhs.a, tolerance));
}
void CompareCMY(const Nz::Color& color, float cyan, float magenta, float yellow)
{
float retrievedCyan = 0.f, retrievedMagenta = 0.f, retrievedYellow = 0.f;
Nz::Color::ToCMY(color, &retrievedCyan, &retrievedMagenta, &retrievedYellow);
CHECK(retrievedCyan == Approx(cyan).epsilon(epsilon));
CHECK(retrievedMagenta == Approx(magenta).epsilon(epsilon));
CHECK(retrievedYellow == Approx(yellow).epsilon(epsilon));
}
void CompareCMYK(const Nz::Color& color, float cyan, float magenta, float yellow, float black)
{
float retrievedCyan = 0.f, retrievedMagenta = 0.f, retrievedYellow = 0.f, retrievedBlack = 0.f;
Nz::Color::ToCMYK(color, &retrievedCyan, &retrievedMagenta, &retrievedYellow, &retrievedBlack);
CHECK(retrievedCyan == Approx(cyan).epsilon(epsilon));
CHECK(retrievedMagenta == Approx(magenta).epsilon(epsilon));
CHECK(retrievedYellow == Approx(yellow).epsilon(epsilon));
CHECK(retrievedBlack == Approx(black).epsilon(epsilon));
}
void CompareHSL(const Nz::Color& color, float hue, float saturation, float luminosity)
{
float retrievedHue = 0.f, retrievedSaturation = 0.f, retrievedLuminosity = 0.f;
Nz::Color::ToHSL(color, &retrievedHue, &retrievedSaturation, &retrievedLuminosity);
CHECK(retrievedHue == Approx(hue).epsilon(epsilon));
CHECK(retrievedSaturation == Approx(saturation).epsilon(epsilon));
CHECK(retrievedLuminosity == Approx(luminosity).epsilon(epsilon));
}
void CompareHSV(const Nz::Color& color, float hue, float saturation, float value)
{
float retrievedHue = 0.f, retrievedSaturation = 0.f, retrievedValue = 0.f;
Nz::Color::ToHSV(color, &retrievedHue, &retrievedSaturation, &retrievedValue);
CHECK(retrievedHue == Approx(hue).epsilon(epsilon));
CHECK(retrievedSaturation == Approx(saturation).epsilon(epsilon));
CHECK(retrievedValue == Approx(value).epsilon(epsilon));
}
void CompareXYZ(const Nz::Color& color, float x, float y, float z)
{
Nz::Vector3f retrievedValues = Nz::Vector3f::Zero();
Nz::Color::ToXYZ(color, &retrievedValues);
CHECK(retrievedValues.x == Approx(x).epsilon(epsilon));
CHECK(retrievedValues.y == Approx(y).epsilon(epsilon));
CHECK(retrievedValues.z == Approx(z).epsilon(epsilon));
}
SCENARIO("Color", "[CORE][COLOR]") SCENARIO("Color", "[CORE][COLOR]")
{ {
GIVEN("Two colors, one red (255) and one gray (128)") GIVEN("Two colors, one red (255) and one gray (128)")
@ -19,4 +76,74 @@ SCENARIO("Color", "[CORE][COLOR]")
} }
} }
} }
GIVEN("A special color in different formats")
{
struct ColorData
{
const char* name;
Nz::Color rgb;
float cyan, magenta, yellow;
float cyanK, magentaK, yellowK, black;
float hue, saturation, luminosity;
float hueV, saturationV, valueV;
float x, y, z;
};
std::vector<ColorData> colors;
colors.push_back({
"blue",
Nz::Color(0, 0, 255),
1.f, 1.f, 0.f, // cmy
1.f, 1.f, 0.f, 0.f, // cmyk
240.f, 1.f, 0.5f, // hsl
240.f, 1.f, 1.f, // hsv
18.05f, 7.22f, 95.05f // xyz
});
colors.push_back({
"white",
Nz::Color(255, 255, 255),
0.f, 0.f, 0.f, // cmy
0.f, 0.f, 0.f, 0.f, // cmyk
0.f, 0.f, 1.f, // hsl
0.f, 0.f, 1.f, // hsv
95.05f, 100.f, 108.09f // xyz
});
colors.push_back({
"greenish",
Nz::Color(5, 191, 25),
0.980f, 0.251f, 0.902f, // cmy
0.974f, 0.000f, 0.869f, 0.251f, // cmyk
126.f, 0.95f, 0.38f, // hsl
126.f, 0.97f, 0.75f, // hsv
18.869f, 37.364f, 7.137f // xyz
});
for (const ColorData& color : colors)
{
WHEN("We perform conversion for: " + color.name)
{
THEN("From other color spaces")
{
CompareColor(color.rgb, Nz::Color::FromCMY(color.cyan, color.magenta, color.yellow));
CompareColor(color.rgb, Nz::Color::FromCMYK(color.cyanK, color.magentaK, color.yellowK, color.black));
CompareColor(color.rgb, Nz::Color::FromHSL(color.hue, color.saturation, color.luminosity));
CompareColor(color.rgb, Nz::Color::FromHSV(color.hueV, color.saturationV, color.valueV));
CompareColor(color.rgb, Nz::Color::FromXYZ(Nz::Vector3f(color.x, color.y, color.z)));
}
THEN("To other color spaces")
{
CompareCMY(color.rgb, color.cyan, color.magenta, color.yellow);
CompareCMYK(color.rgb, color.cyanK, color.magentaK, color.yellowK, color.black);
CompareHSL(color.rgb, color.hue, color.saturation, color.luminosity);
CompareHSV(color.rgb, color.hueV, color.saturationV, color.valueV);
CompareXYZ(color.rgb, color.x, color.y, color.z);
}
}
}
}
} }

View File

@ -24,5 +24,21 @@ SCENARIO("MemoryPool", "[CORE][MEMORYPOOL]")
memoryPool.Delete(vector2); memoryPool.Delete(vector2);
} }
} }
WHEN("We construct three vectors")
{
Nz::Vector2<int>* vector1 = memoryPool.New<Nz::Vector2<int>>(1, 2);
Nz::Vector2<int>* vector2 = memoryPool.New<Nz::Vector2<int>>(3, 4);
Nz::Vector2<int>* vector3 = memoryPool.New<Nz::Vector2<int>>(5, 6);
THEN("Memory is available")
{
vector1->x = 3;
vector2->y = 5;
CHECK(*vector1 == Nz::Vector2<int>(3, 2));
CHECK(*vector2 == Nz::Vector2<int>(3, 5));
CHECK(vector3->GetSquaredLength() == Approx(61.f));
}
}
} }
} }

View File

@ -3,35 +3,204 @@
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
void nullAction(void*)
{
}
SCENARIO("ParameterList", "[CORE][PARAMETERLIST]") SCENARIO("ParameterList", "[CORE][PARAMETERLIST]")
{ {
GIVEN("An empty ParameterList") GIVEN("An empty ParameterList")
{ {
Nz::ParameterList parameterList; Nz::ParameterList parameterList;
WHEN("We add String 'string'") WHEN("We add Bool 'true' and analogous")
{
bool boolean = true;
parameterList.SetParameter("bool", boolean);
long long intTrue = 1;
parameterList.SetParameter("intTrue", intTrue);
long long intFalse = 0;
parameterList.SetParameter("intFalse", intFalse);
Nz::String strTrue = "true";
parameterList.SetParameter("strTrue", strTrue);
Nz::String strFalse = "false";
parameterList.SetParameter("strFalse", strFalse);
THEN("We can get it back")
{
bool retrievedValue = false;
CHECK(parameterList.GetBooleanParameter("bool", &retrievedValue));
CHECK(retrievedValue == boolean);
}
THEN("Conversion from int to bool should also work")
{
bool retrievedValue = false;
CHECK(parameterList.GetBooleanParameter("intTrue", &retrievedValue));
CHECK(retrievedValue);
CHECK(parameterList.GetBooleanParameter("intFalse", &retrievedValue));
CHECK(!retrievedValue);
}
THEN("Conversion from str to bool should also work")
{
bool retrievedValue = false;
CHECK(parameterList.GetBooleanParameter("strTrue", &retrievedValue));
CHECK(retrievedValue);
CHECK(parameterList.GetBooleanParameter("strFalse", &retrievedValue));
CHECK(!retrievedValue);
}
}
WHEN("We add Color 'rgb(1, 2, 3)'")
{
Nz::Color rgb(1, 2, 3);
parameterList.SetParameter("color", rgb);
THEN("We can get it back")
{
Nz::Color retrievedColor;
CHECK(parameterList.GetColorParameter("color", &retrievedColor));
CHECK(retrievedColor == rgb);
}
}
WHEN("We add Double '3.0' and analogous")
{
double fl = 3.0;
parameterList.SetParameter("double", fl);
long long intDouble = 3;
parameterList.SetParameter("intDouble", intDouble);
Nz::String strDouble = "3.0";
parameterList.SetParameter("strDouble", strDouble);
THEN("We can get it back")
{
double retrievedValue;
CHECK(parameterList.GetDoubleParameter("double", &retrievedValue));
CHECK(retrievedValue == fl);
}
THEN("Conversion from int to double should also work")
{
double retrievedValue;
CHECK(parameterList.GetDoubleParameter("intDouble", &retrievedValue));
CHECK(retrievedValue == fl);
}
THEN("Conversion from string to double should also work")
{
double retrievedValue;
CHECK(parameterList.GetDoubleParameter("strDouble", &retrievedValue));
CHECK(retrievedValue == fl);
}
}
WHEN("We add Int '3' and analogous")
{
long long i = 3;
parameterList.SetParameter("int", i);
bool trueInt = 1;
parameterList.SetParameter("trueInt", trueInt);
bool falseInt = 0;
parameterList.SetParameter("falseInt", falseInt);
double doubleInt = 3;
parameterList.SetParameter("doubleInt", doubleInt);
Nz::String strInt = "3";
parameterList.SetParameter("strInt", strInt);
THEN("We can get it back")
{
long long retrievedValue;
CHECK(parameterList.GetIntegerParameter("int", &retrievedValue));
CHECK(retrievedValue == i);
}
THEN("Conversion from bool to int should also work")
{
long long retrievedValue;
CHECK(parameterList.GetIntegerParameter("trueInt", &retrievedValue));
CHECK(retrievedValue == trueInt);
CHECK(parameterList.GetIntegerParameter("falseInt", &retrievedValue));
CHECK(retrievedValue == falseInt);
}
THEN("Conversion from double to int should also work")
{
long long retrievedValue;
CHECK(parameterList.GetIntegerParameter("doubleInt", &retrievedValue));
CHECK(retrievedValue == i);
}
THEN("Conversion from string to int should also work")
{
long long retrievedValue;
CHECK(parameterList.GetIntegerParameter("strInt", &retrievedValue));
CHECK(retrievedValue == i);
}
}
WHEN("We add String 'string' and analogous")
{ {
Nz::String string("string"); Nz::String string("string");
parameterList.SetParameter("string", string); parameterList.SetParameter("string", string);
bool trueString = 1;
parameterList.SetParameter("trueString", trueString);
bool falseString = 0;
parameterList.SetParameter("falseString", falseString);
Nz::Color colorString(1, 2, 3);
parameterList.SetParameter("colorString", colorString);
double doubleString = 3.0;
parameterList.SetParameter("doubleString", doubleString);
long long intString = 3;
parameterList.SetParameter("intString", intString);
THEN("We can get it back") THEN("We can get it back")
{ {
Nz::String newString; Nz::String newString;
REQUIRE(parameterList.GetStringParameter("string", &newString)); CHECK(parameterList.GetStringParameter("string", &newString));
REQUIRE(newString == string); CHECK(newString == string);
} }
}
WHEN("We add Float '3.f'") THEN("Conversion from bool to str should also work")
{
double fl = 3.f;
parameterList.SetParameter("double", fl);
THEN("We can get it back")
{ {
double newFl; Nz::String retrievedValue;
REQUIRE(parameterList.GetDoubleParameter("double", &newFl)); CHECK(parameterList.GetStringParameter("trueString", &retrievedValue));
REQUIRE(newFl == fl); CHECK(retrievedValue == "true");
CHECK(parameterList.GetStringParameter("falseString", &retrievedValue));
CHECK(retrievedValue == "false");
}
THEN("Conversion from color to string should also work")
{
Nz::String retrievedValue;
CHECK(parameterList.GetStringParameter("colorString", &retrievedValue));
CHECK(retrievedValue == colorString.ToString());
}
THEN("Conversion from string to double should also work")
{
Nz::String retrievedValue;
CHECK(parameterList.GetStringParameter("doubleString", &retrievedValue));
CHECK(retrievedValue == "3");
}
THEN("Conversion from string to int should also work")
{
Nz::String retrievedValue;
CHECK(parameterList.GetStringParameter("intString", &retrievedValue));
CHECK(retrievedValue == "3");
} }
} }
@ -44,8 +213,71 @@ SCENARIO("ParameterList", "[CORE][PARAMETERLIST]")
THEN("We can get it back") THEN("We can get it back")
{ {
void* newPtrToStackValue = nullptr; void* newPtrToStackValue = nullptr;
REQUIRE(parameterList.GetPointerParameter("ptr", &newPtrToStackValue)); CHECK(parameterList.GetPointerParameter("ptr", &newPtrToStackValue));
REQUIRE(newPtrToStackValue == ptrToStackValue); CHECK(newPtrToStackValue == ptrToStackValue);
}
}
WHEN("We set our own data")
{
struct Data {
int i;
float f;
};
Data data{ 1, 3.f };
parameterList.SetParameter("userData", &data, nullAction);
THEN("We can get it back")
{
Data retrievedValue;
void* ptrToData = &retrievedValue;
CHECK(parameterList.GetUserdataParameter("userData", &ptrToData));
Data* dataPtr = reinterpret_cast<Data*>(ptrToData);
CHECK(dataPtr->i == data.i);
CHECK(dataPtr->f == data.f);
}
}
}
GIVEN("A parameter list with some values")
{
Nz::ParameterList parameterList;
long long i = 3;
parameterList.SetParameter("i", i);
double d = 1.0;
parameterList.SetParameter("d", d);
parameterList.SetParameter("toaster");
parameterList.SetParameter("str", "ing");
WHEN("We remove two elements")
{
CHECK(parameterList.HasParameter("i"));
CHECK(parameterList.HasParameter("toaster"));
parameterList.RemoveParameter("i");
parameterList.RemoveParameter("toaster");
THEN("They do not exist anymore")
{
CHECK(!parameterList.HasParameter("i"));
CHECK(!parameterList.HasParameter("toaster"));
}
}
WHEN("We copy this list")
{
Nz::ParameterList copy = parameterList;
THEN("It has the same elements")
{
CHECK(parameterList.HasParameter("i"));
CHECK(parameterList.HasParameter("d"));
CHECK(parameterList.HasParameter("toaster"));
CHECK(parameterList.HasParameter("str"));
} }
} }
} }

View File

@ -204,6 +204,69 @@ TEST_CASE("MultiplyAdd", "[MATH][ALGORITHM]")
} }
} }
TEST_CASE("NormalizeAngle", "[MATH][ALGORITHM]")
{
SECTION("-90 should be normalized to +270")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(-90.f)) == Nz::FromDegrees(270.f));
}
SECTION("-540 should be normalized to +180")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(-540.f)) == Nz::FromDegrees(180.f));
}
SECTION("0 should remain 0")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(0.f)) == Nz::FromDegrees(0.f));
}
SECTION("90 should remain 90")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(90.f)) == Nz::FromDegrees(90.f));
}
SECTION("360 should be normalized to 0")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(360.f)) == Nz::FromDegrees(0.f));
}
SECTION("450 should be normalized to 90")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(450.f)) == Nz::FromDegrees(90.f));
}
SECTION("-90 should be normalized to +270")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(-90)) == Nz::FromDegrees(270));
}
SECTION("-540 should be normalized to +180")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(-540)) == Nz::FromDegrees(180));
}
SECTION("0 should remain 0")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(0)) == Nz::FromDegrees(0));
}
SECTION("90 should remain 90")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(90)) == Nz::FromDegrees(90));
}
SECTION("360 should be normalized to 0")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(360)) == Nz::FromDegrees(0));
}
SECTION("450 should be normalized to 90")
{
REQUIRE(Nz::NormalizeAngle(Nz::FromDegrees(450)) == Nz::FromDegrees(90));
}
}
TEST_CASE("NumberEquals", "[MATH][ALGORITHM]") TEST_CASE("NumberEquals", "[MATH][ALGORITHM]")
{ {
SECTION("2.35 and 2.351 should be the same at 0.01") SECTION("2.35 and 2.351 should be the same at 0.01")
@ -211,11 +274,16 @@ TEST_CASE("NumberEquals", "[MATH][ALGORITHM]")
CHECK(Nz::NumberEquals(2.35, 2.35, 0.01)); CHECK(Nz::NumberEquals(2.35, 2.35, 0.01));
} }
SECTION("0 and 4 unsigned should be the same at 1") SECTION("0 and 4 unsigned should be the same at 4")
{ {
CHECK(Nz::NumberEquals(0U, 4U, 4U)); CHECK(Nz::NumberEquals(0U, 4U, 4U));
} }
SECTION("1 and -1 signed should be the same at 2")
{
CHECK(Nz::NumberEquals(1, -1, 2));
}
SECTION("Maximum integer and -1 should not be equal") SECTION("Maximum integer and -1 should not be equal")
{ {
CHECK_FALSE(Nz::NumberEquals(std::numeric_limits<int>::max(), -1)); CHECK_FALSE(Nz::NumberEquals(std::numeric_limits<int>::max(), -1));
@ -229,6 +297,11 @@ TEST_CASE("NumberEquals", "[MATH][ALGORITHM]")
TEST_CASE("NumberToString", "[MATH][ALGORITHM]") TEST_CASE("NumberToString", "[MATH][ALGORITHM]")
{ {
SECTION("0 to string")
{
REQUIRE(Nz::NumberToString(0) == "0");
}
SECTION("235 to string") SECTION("235 to string")
{ {
REQUIRE(Nz::NumberToString(235) == "235"); REQUIRE(Nz::NumberToString(235) == "235");
@ -265,8 +338,20 @@ TEST_CASE("StringToNumber", "[MATH][ALGORITHM]")
REQUIRE(Nz::StringToNumber("-235") == -235); REQUIRE(Nz::StringToNumber("-235") == -235);
} }
SECTION("235 157 in string")
{
REQUIRE(Nz::StringToNumber("235 157") == 235157);
}
SECTION("16 in base 16 in string") SECTION("16 in base 16 in string")
{ {
REQUIRE(Nz::StringToNumber("10", 16) == 16); REQUIRE(Nz::StringToNumber("10", 16) == 16);
} }
SECTION("8 in base 4 in string should not be valid")
{
bool ok = true;
REQUIRE(Nz::StringToNumber("8", 4, &ok) == 0);
REQUIRE(!ok);
}
} }

View File

@ -114,5 +114,52 @@ SCENARIO("BoundingVolume", "[MATH][BOUNDINGVOLUME]")
REQUIRE(Nz::BoundingVolumef::Lerp(nullBoundingVolume, centerAndUnit, 0.5f) == result); REQUIRE(Nz::BoundingVolumef::Lerp(nullBoundingVolume, centerAndUnit, 0.5f) == result);
} }
} }
WHEN("We lerp with special cases")
{
Nz::OrientedBoxf centerAndUnitOBB(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
centerAndUnitOBB.Update(Nz::Matrix4f::Identity());
Nz::BoundingVolumef centerAndUnit(centerAndUnitOBB);
Nz::BoundingVolumef nullBoundingVolume(Nz::Extend_Null);
Nz::BoundingVolumef infiniteBoundingVolume(Nz::Extend_Infinite);
THEN("Normal to null should give a smaller volume")
{
Nz::BoundingVolumef result(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 0.5f);
result.Update(Nz::Matrix4f::Identity());
REQUIRE(Nz::BoundingVolumef::Lerp(centerAndUnit, nullBoundingVolume, 0.5f) == result);
}
THEN("Normal to infinite should give an infinite volume")
{
REQUIRE(Nz::BoundingVolumef::Lerp(centerAndUnit, infiniteBoundingVolume, 0.5f) == infiniteBoundingVolume);
}
THEN("Null to normal should give a small volume")
{
Nz::BoundingVolumef result(Nz::Vector3f::Zero(), Nz::Vector3f::Unit() * 0.5f);
result.Update(Nz::Matrix4f::Identity());
REQUIRE(Nz::BoundingVolumef::Lerp(nullBoundingVolume, centerAndUnit, 0.5f) == result);
}
THEN("Infinite to normal should give an infinite volume")
{
REQUIRE(Nz::BoundingVolumef::Lerp(infiniteBoundingVolume, centerAndUnit, 0.5f) == infiniteBoundingVolume);
}
THEN("Infinite to null should give an infinite volume")
{
REQUIRE(Nz::BoundingVolumef::Lerp(infiniteBoundingVolume, nullBoundingVolume, 0.5f) == infiniteBoundingVolume);
}
THEN("Null to null should give a null volume")
{
REQUIRE(Nz::BoundingVolumef::Lerp(nullBoundingVolume, nullBoundingVolume, 0.5f) == nullBoundingVolume);
}
}
} }
} }

View File

@ -56,6 +56,16 @@ SCENARIO("Box", "[MATH][BOX]")
} }
} }
WHEN("We ask for the intersection when there are none")
{
firstCenterAndUnit.Translate(Nz::Vector3f::UnitZ() * 5.f);
THEN("We should have a center and unit")
{
Nz::Boxf thirdCenterAndUnit;
CHECK(!firstCenterAndUnit.Intersect(secondCenterAndUnit, &thirdCenterAndUnit));
}
}
WHEN("We use the constructor of conversion") WHEN("We use the constructor of conversion")
{ {
THEN("Shouldn't be a problem") THEN("Shouldn't be a problem")

View File

@ -1,7 +1,9 @@
#include <Nazara/Math/Matrix4.hpp> #include <Nazara/Math/Matrix4.hpp>
#include <Catch/catch.hpp> #include <Catch/catch.hpp>
SCENARIO("Matrix4", "[MATH][Matrix4]") #include <array>
SCENARIO("Matrix4", "[MATH][MATRIX4]")
{ {
GIVEN("Two identity matrix") GIVEN("Two identity matrix")
{ {
@ -20,9 +22,9 @@ SCENARIO("Matrix4", "[MATH][Matrix4]")
{ {
THEN("Nz::Vector stay the same") THEN("Nz::Vector stay the same")
{ {
REQUIRE(firstIdentity.Transform(Nz::Vector2f::Unit()) == Nz::Vector2f::Unit()); CHECK(firstIdentity * Nz::Vector2f::Unit() == Nz::Vector2f::Unit());
REQUIRE(firstIdentity.Transform(Nz::Vector3f::Unit()) == Nz::Vector3f::Unit()); CHECK(firstIdentity * Nz::Vector3f::Unit() == Nz::Vector3f::Unit());
REQUIRE(firstIdentity.Transform(Nz::Vector4f(1.f, 1.f, 1.f, 1.f)) == Nz::Vector4f(1.f, 1.f, 1.f, 1.f)); CHECK(firstIdentity * Nz::Vector4f(1.f, 1.f, 1.f, 1.f) == Nz::Vector4f(1.f, 1.f, 1.f, 1.f));
} }
} }
@ -30,11 +32,11 @@ SCENARIO("Matrix4", "[MATH][Matrix4]")
{ {
THEN("It keeps being a identity") THEN("It keeps being a identity")
{ {
REQUIRE(firstIdentity.Concatenate(secondIdentity) == firstIdentity); CHECK(firstIdentity.Concatenate(secondIdentity) == firstIdentity);
REQUIRE(firstIdentity.ConcatenateAffine(secondIdentity) == firstIdentity); CHECK(firstIdentity.ConcatenateAffine(secondIdentity) == firstIdentity);
REQUIRE((firstIdentity * secondIdentity) == firstIdentity); CHECK((firstIdentity * secondIdentity) == firstIdentity);
REQUIRE((1.f * firstIdentity) == firstIdentity); CHECK((1.f * firstIdentity) == firstIdentity);
REQUIRE(firstIdentity.Inverse() == secondIdentity.InverseAffine()); CHECK(firstIdentity.Inverse() == secondIdentity.InverseAffine());
} }
} }
@ -65,8 +67,8 @@ SCENARIO("Matrix4", "[MATH][Matrix4]")
{ {
THEN("These results are expected") THEN("These results are expected")
{ {
REQUIRE(matrix1.GetDeterminant() == Approx(24.f)); CHECK(matrix1.GetDeterminant() == Approx(24.f));
REQUIRE(matrix2.GetDeterminant() == Approx(-1.f)); CHECK(matrix2.GetDeterminant() == Approx(-1.f));
} }
} }
@ -81,12 +83,12 @@ SCENARIO("Matrix4", "[MATH][Matrix4]")
THEN("We get the identity") THEN("We get the identity")
{ {
Nz::Matrix4f tmp = matrix1 * invMatrix1; Nz::Matrix4f tmp = matrix1 * invMatrix1;
REQUIRE(tmp.m32 == Approx(0.f)); CHECK(tmp.m32 == Approx(0.f));
REQUIRE(tmp.m42 == Approx(0.f)); CHECK(tmp.m42 == Approx(0.f));
tmp.m32 = 0.f; tmp.m32 = 0.f;
tmp.m42 = 0.f; tmp.m42 = 0.f;
REQUIRE(tmp == Nz::Matrix4f::Identity()); CHECK(tmp == Nz::Matrix4f::Identity());
REQUIRE((matrix2 * invMatrix2) == Nz::Matrix4f::Identity()); CHECK((matrix2 * invMatrix2) == Nz::Matrix4f::Identity());
} }
} }
} }
@ -106,10 +108,10 @@ SCENARIO("Matrix4", "[MATH][Matrix4]")
0.f, -std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f, 0.f, -std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f,
0.f, 0.f, 0.f, 1.f); 0.f, 0.f, 0.f, 1.f);
REQUIRE(transformedMatrix == rotation45X); CHECK(transformedMatrix == rotation45X);
transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(Nz::FromDegrees(45.f), 0.f, 0.f).ToQuaternion()); transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(Nz::FromDegrees(45.f), 0.f, 0.f).ToQuaternion());
rotation45X.ApplyTranslation(Nz::Vector3f::Unit()); rotation45X.ApplyTranslation(Nz::Vector3f::Unit());
REQUIRE(transformedMatrix == rotation45X); CHECK(transformedMatrix == rotation45X);
} }
THEN("Rotation around Y") THEN("Rotation around Y")
@ -120,10 +122,10 @@ SCENARIO("Matrix4", "[MATH][Matrix4]")
std::sqrt(2.f) / 2.f, 0.f, std::sqrt(2.f) / 2.f, 0.f, std::sqrt(2.f) / 2.f, 0.f, std::sqrt(2.f) / 2.f, 0.f,
0.f, 0.f, 0.f, 1.f); 0.f, 0.f, 0.f, 1.f);
REQUIRE(transformedMatrix == rotation45Y); CHECK(transformedMatrix == rotation45Y);
transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(0.f, Nz::FromDegrees(45.f), 0.f).ToQuaternion()); transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(0.f, Nz::FromDegrees(45.f), 0.f).ToQuaternion());
rotation45Y.ApplyTranslation(Nz::Vector3f::Unit()); rotation45Y.ApplyTranslation(Nz::Vector3f::Unit());
REQUIRE(transformedMatrix == rotation45Y); CHECK(transformedMatrix == rotation45Y);
} }
THEN("Rotation around Z") THEN("Rotation around Z")
@ -134,10 +136,172 @@ SCENARIO("Matrix4", "[MATH][Matrix4]")
0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f); 0.f, 0.f, 0.f, 1.f);
REQUIRE(transformedMatrix == rotation45Z); CHECK(transformedMatrix == rotation45Z);
transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(Nz::EulerAnglesf(0.f, 0.f, Nz::FromDegrees(45.f)).ToQuaternion())); transformedMatrix.MakeTransform(Nz::Vector3f::Unit(), Nz::EulerAnglesf(Nz::EulerAnglesf(0.f, 0.f, Nz::FromDegrees(45.f)).ToQuaternion()));
rotation45Z.ApplyTranslation(Nz::Vector3f::Unit()); rotation45Z.ApplyTranslation(Nz::Vector3f::Unit());
REQUIRE(transformedMatrix == rotation45Z); CHECK(transformedMatrix == rotation45Z);
}
}
}
GIVEN("An identity matrix")
{
std::array<float, 16> content{{ 1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f
}};
Nz::Matrix4f identity(content.data());
REQUIRE(identity.IsIdentity());
WHEN("We rotate it from pitch 30")
{
Nz::Quaternionf rotation(Nz::EulerAnglesf(Nz::FromDegrees(30.f), 0.f, 0.f));
identity.ApplyRotation(rotation);
THEN("We should retrieve it")
{
REQUIRE(identity.GetRotation() == rotation);
}
}
WHEN("We rotate it from yaw 30")
{
Nz::Quaternionf rotation(Nz::EulerAnglesf(0.f, Nz::FromDegrees(30.f), 0.f));
identity.ApplyRotation(rotation);
THEN("We should retrieve it")
{
REQUIRE(identity.GetRotation() == rotation);
}
}
WHEN("We rotate it from roll 30")
{
Nz::Quaternionf rotation(Nz::EulerAnglesf(0.f, 0.f, Nz::FromDegrees(30.f)));
identity.ApplyRotation(rotation);
THEN("We should retrieve it")
{
REQUIRE(identity.GetRotation() == rotation);
}
}
WHEN("We rotate it from a strange rotation")
{
Nz::Quaternionf rotation(Nz::EulerAnglesf(Nz::FromDegrees(10.f), Nz::FromDegrees(20.f), Nz::FromDegrees(30.f)));
identity.ApplyRotation(rotation);
THEN("We should retrieve it")
{
REQUIRE(identity.GetRotation() == rotation);
}
}
WHEN("We scale it")
{
Nz::Vector3f scale(1.f, 2.f, 3.f);
Nz::Vector3f squaredScale(scale.x * scale.x, scale.y * scale.y, scale.z * scale.z);
identity.ApplyScale(scale);
THEN("We should retrieve it")
{
CHECK(identity.GetScale() == scale);
CHECK(identity.GetSquaredScale() == squaredScale);
}
AND_THEN("With a rotation")
{
identity.ApplyRotation(Nz::EulerAnglesf(Nz::FromDegrees(10.f), Nz::FromDegrees(20.f), Nz::FromDegrees(30.f)));
Nz::Vector3f retrievedScale = identity.GetScale();
CHECK(retrievedScale.x == Approx(scale.x));
CHECK(retrievedScale.y == Approx(scale.y));
CHECK(retrievedScale.z == Approx(scale.z));
}
}
}
GIVEN("A matrix with a negative determinant")
{
Nz::Matrix4f negativeDeterminant( -1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f);
WHEN("We ask information about determinant")
{
THEN("We expect those to be true")
{
CHECK(negativeDeterminant.GetDeterminant() == Approx(-1.f));
CHECK(!negativeDeterminant.HasScale());
CHECK(negativeDeterminant.HasNegativeScale());
}
}
}
GIVEN("Some transformed matrices")
{
Nz::Vector3f simpleTranslation = Nz::Vector3f::Zero();
Nz::Quaternionf simpleRotation = Nz::Quaternionf::Identity();
Nz::Vector3f simpleScale = Nz::Vector3f::Unit();
Nz::Matrix4f simple = Nz::Matrix4f::Transform(simpleTranslation, simpleRotation, simpleScale);
Nz::Vector3f complexTranslation = Nz::Vector3f(-5.f, 7.f, 3.5f);
Nz::Quaternionf complexRotation = Nz::EulerAnglesf(Nz::FromDegrees(-22.5f), Nz::FromDegrees(30.f), Nz::FromDegrees(15.f));
Nz::Vector3f complexScale = Nz::Vector3f(1.f, 2.f, 0.5f);
Nz::Matrix4f complex = Nz::Matrix4f::Transform(complexTranslation, complexRotation, complexScale);
Nz::Vector3f oppositeTranslation = Nz::Vector3f(-5.f, 7.f, 3.5f);
Nz::Quaternionf oppositeRotation = Nz::EulerAnglesf(Nz::FromDegrees(-90.f), Nz::FromDegrees(0.f), Nz::FromDegrees(0.f));
Nz::Vector3f oppositeScale = Nz::Vector3f(1.f, 2.f, 0.5f);
Nz::Matrix4f opposite = Nz::Matrix4f::Transform(oppositeTranslation, oppositeRotation, oppositeScale);
WHEN("We retrieve the different components")
{
THEN("It should be the original ones")
{
CHECK(simple.GetTranslation() == simpleTranslation);
CHECK(simple.GetRotation() == simpleRotation);
CHECK(simple.GetScale() == simpleScale);
/*CHECK(complex.GetTranslation() == complexTranslation);
CHECK(complex.GetRotation() == complexRotation);
CHECK(complex.GetScale() == complexScale);
CHECK(opposite.GetTranslation() == oppositeTranslation);
CHECK(opposite.GetRotation() == oppositeRotation);
CHECK(opposite.GetScale() == oppositeScale);*/
}
}
}
GIVEN("Some defined matrix and its opposite")
{
Nz::Vector3f translation(-5.f, 3.f, 0.5);
Nz::Matrix4f initial = Nz::Matrix4f::Translate(translation);
Nz::Quaternionf rotation = Nz::EulerAnglesf(Nz::FromDegrees(30.f), Nz::FromDegrees(-90.f), 0.f);
initial.ApplyRotation(rotation);
Nz::Matrix4f simple = Nz::Matrix4f::Transform(-translation, rotation.GetInverse(), Nz::Vector3f::Unit());
WHEN("We multiply them together")
{
Nz::Matrix4f result = Nz::Matrix4f::Concatenate(simple, initial);
THEN("We should get the identity")
{
Nz::Matrix4f identity = Nz::Matrix4f::Identity();
for (int i = 0; i != 4; ++i)
{
Nz::Vector4f row = result.GetRow(i);
Nz::Vector4f column = result.GetColumn(i);
for (int j = 0; j != 4; ++j)
{
CHECK(Nz::NumberEquals(row[j], identity(i, j), 0.00001f));
CHECK(Nz::NumberEquals(column[j], identity(i, j), 0.00001f));
}
}
} }
} }
} }

View File

@ -173,13 +173,34 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]")
WHEN("We get the rotation between two vectors") WHEN("We get the rotation between two vectors")
{ {
Nz::Quaternionf rotationBetweenXY = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitX(), Nz::Vector3f::UnitY());
THEN("The rotation in right-handed is 90 degree on z") THEN("The rotation in right-handed is 90 degree on z")
{ {
Nz::Quaternionf rotationBetweenXY = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitX(), Nz::Vector3f::UnitY());
Nz::Quaternionf rotation90Z(Nz::FromDegrees(90.f), Nz::Vector3f::UnitZ()); Nz::Quaternionf rotation90Z(Nz::FromDegrees(90.f), Nz::Vector3f::UnitZ());
REQUIRE(rotation90Z == rotationBetweenXY); REQUIRE(rotation90Z == rotationBetweenXY);
} }
THEN("The rotation in right-handed is 90 degree on y")
{
Nz::Quaternionf rotationBetweenXZ = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitX(), Nz::Vector3f::UnitZ());
Nz::Quaternionf rotation90Y(Nz::FromDegrees(-90.f), Nz::Vector3f::UnitY());
REQUIRE(rotation90Y == rotationBetweenXZ);
}
THEN("The rotation in right-handed is 90 degree on x")
{
Nz::Quaternionf rotationBetweenYZ = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitY(), Nz::Vector3f::UnitZ());
Nz::Quaternionf rotation90X(Nz::FromDegrees(90.f), Nz::Vector3f::UnitX());
REQUIRE(rotation90X == rotationBetweenYZ);
}
THEN("The rotation in right-handed is 90 degree on y with non-unit vectors")
{
Nz::Vector3f origin(1.f, 0.f, 1.f);
Nz::Vector3f extremity(-1.f, 0.f, 1.f);
Nz::Quaternionf rotation = Nz::Quaternionf::RotationBetween(origin, extremity);
REQUIRE(rotation * origin == extremity);
}
} }
} }

View File

@ -12,9 +12,9 @@ SCENARIO("Rect", "[MATH][RECT]")
{ {
THEN("They should be") THEN("They should be")
{ {
REQUIRE(firstCenterAndUnit == secondCenterAndUnit); CHECK(firstCenterAndUnit == secondCenterAndUnit);
REQUIRE(firstCenterAndUnit.GetCenter() == secondCenterAndUnit.GetCenter()); CHECK(firstCenterAndUnit.GetCenter() == secondCenterAndUnit.GetCenter());
REQUIRE(firstCenterAndUnit.GetCorner(Nz::RectCorner_LeftBottom) == secondCenterAndUnit.GetCorner(Nz::RectCorner_LeftBottom)); CHECK(firstCenterAndUnit.GetCorner(Nz::RectCorner_LeftBottom) == secondCenterAndUnit.GetCorner(Nz::RectCorner_LeftBottom));
CHECK(firstCenterAndUnit.IsValid()); CHECK(firstCenterAndUnit.IsValid());
} }
} }
@ -43,16 +43,24 @@ SCENARIO("Rect", "[MATH][RECT]")
{ {
THEN("These results are expected") THEN("These results are expected")
{ {
REQUIRE(firstCenterAndUnit.GetLengths() == Nz::Vector2f::Unit()); CHECK(firstCenterAndUnit.GetLengths() == Nz::Vector2f::Unit());
REQUIRE(firstCenterAndUnit.GetMaximum() == Nz::Vector2f::Unit()); CHECK(firstCenterAndUnit.GetMaximum() == Nz::Vector2f::Unit());
REQUIRE(firstCenterAndUnit.GetMinimum() == Nz::Vector2f::Zero()); CHECK(firstCenterAndUnit.GetMinimum() == Nz::Vector2f::Zero());
REQUIRE(firstCenterAndUnit.GetNegativeVertex(Nz::Vector2f::Unit()) == Nz::Vector2f::Zero()); CHECK(firstCenterAndUnit.GetNegativeVertex(Nz::Vector2f::Unit()) == Nz::Vector2f::Zero());
REQUIRE(firstCenterAndUnit.GetPosition() == Nz::Vector2f::Zero()); CHECK(firstCenterAndUnit.GetPosition() == Nz::Vector2f::Zero());
REQUIRE(firstCenterAndUnit.GetPositiveVertex(Nz::Vector2f::Unit()) == Nz::Vector2f::Unit()); CHECK(firstCenterAndUnit.GetPositiveVertex(Nz::Vector2f::Unit()) == Nz::Vector2f::Unit());
} }
} }
WHEN("We ask for intersection")
{
Nz::Rectf intersection;
CHECK(firstCenterAndUnit.Intersect(secondCenterAndUnit, &intersection));
CHECK(intersection == Nz::Rectf(1.f, 1.f));
CHECK(intersection == Nz::Rectf(Nz::Vector2f(1.f, 1.f)));
}
WHEN("We try to lerp") WHEN("We try to lerp")
{ {
THEN("Compilation should be fine") THEN("Compilation should be fine")

View File

@ -1,6 +1,7 @@
#include <Nazara/Math/Vector3.hpp> #include <Nazara/Math/Vector3.hpp>
#include <Catch/catch.hpp> #include <Catch/catch.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Math/Vector4.hpp> #include <Nazara/Math/Vector4.hpp>
SCENARIO("Vector3", "[MATH][VECTOR3]") SCENARIO("Vector3", "[MATH][VECTOR3]")
@ -97,4 +98,24 @@ SCENARIO("Vector3", "[MATH][VECTOR3]")
} }
} }
} }
GIVEN("Two vectors")
{
Nz::Vector2f unit = Nz::Vector2f::Unit();
Nz::Vector3f smaller(-1.f, unit);
float data[3] = { 1.f, unit.x, unit.y };
Nz::Vector3f bigger(data);
WHEN("We combine divisions and multiplications")
{
Nz::Vector3f result = smaller / bigger;
result *= bigger;
THEN("We should get the identity")
{
REQUIRE(result == smaller);
}
}
}
} }

View File

@ -99,6 +99,94 @@ SCENARIO("PhysWorld2D", "[PHYSICS2D][PHYSWORLD2D]")
} }
} }
} }
GIVEN("Three entities, a character, a wall and a trigger zone")
{
unsigned int CHARACTER_COLLISION_ID = 1;
unsigned int WALL_COLLISION_ID = 2;
unsigned int TRIGGER_COLLISION_ID = 3;
Nz::PhysWorld2D world;
Nz::Rectf characterAABB(0.f, 0.f, 1.f, 1.f);
Nz::Collider2DRef characterBox = Nz::BoxCollider2D::New(characterAABB);
characterBox->SetCollisionId(CHARACTER_COLLISION_ID);
Nz::RigidBody2D character(&world, 1.f, characterBox);
character.SetPosition(Nz::Vector2f::Zero());
Nz::Rectf wallAABB(0.f, 0.f, 1.f, 2.f);
Nz::Collider2DRef wallBox = Nz::BoxCollider2D::New(wallAABB);
wallBox->SetCollisionId(WALL_COLLISION_ID);
Nz::RigidBody2D wall(&world, 0.f, wallBox);
wall.SetPosition(Nz::Vector2f(5.f, 0.f));
Nz::Rectf triggerAABB(0.f, 0.f, 1.f, 1.f);
Nz::Collider2DRef triggerBox = Nz::BoxCollider2D::New(triggerAABB);
triggerBox->SetTrigger(true);
triggerBox->SetCollisionId(TRIGGER_COLLISION_ID);
Nz::RigidBody2D trigger(&world, 0.f, triggerBox);
trigger.SetPosition(Nz::Vector2f(2.f, 0.f));
world.Step(0.f);
int statusTriggerCollision = 0;
Nz::PhysWorld2D::Callback characterTriggerCallback;
characterTriggerCallback.startCallback = [&](Nz::PhysWorld2D&, Nz::RigidBody2D&, Nz::RigidBody2D&, void*) -> bool {
statusTriggerCollision = statusTriggerCollision | 1 << 0;
return true;
};
characterTriggerCallback.preSolveCallback = [&](Nz::PhysWorld2D&, Nz::RigidBody2D&, Nz::RigidBody2D&, void*) -> bool {
statusTriggerCollision = statusTriggerCollision | 1 << 1;
return true;
};
characterTriggerCallback.postSolveCallback = [&](Nz::PhysWorld2D&, Nz::RigidBody2D&, Nz::RigidBody2D&, void*) {
statusTriggerCollision = statusTriggerCollision | 1 << 2;
};
characterTriggerCallback.endCallback = [&](Nz::PhysWorld2D&, Nz::RigidBody2D&, Nz::RigidBody2D&, void*) {
statusTriggerCollision = statusTriggerCollision | 1 << 3;
};
world.RegisterCallbacks(CHARACTER_COLLISION_ID, TRIGGER_COLLISION_ID, characterTriggerCallback);
int statusWallCollision = 0;
Nz::PhysWorld2D::Callback characterWallCallback;
characterWallCallback.startCallback = [&](Nz::PhysWorld2D&, Nz::RigidBody2D&, Nz::RigidBody2D&, void*) -> bool {
statusWallCollision = statusWallCollision | 1 << 0;
return true;
};
characterWallCallback.endCallback = [&](Nz::PhysWorld2D&, Nz::RigidBody2D&, Nz::RigidBody2D&, void*) {
statusWallCollision = statusWallCollision | 1 << 1;
};
world.RegisterCallbacks(CHARACTER_COLLISION_ID, WALL_COLLISION_ID, characterWallCallback);
WHEN("We make our character go towards the wall")
{
character.SetVelocity(Nz::Vector2f(1.f, 0.f));
for (int i = 0; i != 11; ++i)
world.Step(0.1f);
THEN("It should trigger several collisions")
{
CHECK(statusTriggerCollision == 3);
for (int i = 0; i != 20; ++i)
world.Step(0.1f);
CHECK(statusTriggerCollision == 11);
CHECK(character.GetPosition().x == Approx(3.1f).epsilon(0.01f));
for (int i = 0; i != 9; ++i)
world.Step(0.1f);
CHECK(character.GetPosition().x == Approx(4.f).epsilon(0.01f));
world.Step(0.1f);
CHECK(character.GetPosition().x == Approx(4.f).epsilon(0.01f));
CHECK(statusWallCollision == 1); // It should be close to the wall
character.SetVelocity(Nz::Vector2f(-2.f, 0.f));
for (int i = 0; i != 10; ++i)
world.Step(0.1f);
CHECK(statusWallCollision == 3);
}
}
}
} }
Nz::RigidBody2D CreateBody(Nz::PhysWorld2D& world, const Nz::Vector2f& position, bool isMoving, const Nz::Vector2f& lengths) Nz::RigidBody2D CreateBody(Nz::PhysWorld2D& world, const Nz::Vector2f& position, bool isMoving, const Nz::Vector2f& lengths)

View File

@ -1,6 +1,7 @@
#include <NDK/Systems/RenderSystem.hpp> #include <NDK/Systems/RenderSystem.hpp>
#include <NDK/World.hpp> #include <NDK/World.hpp>
#include <NDK/Components.hpp> #include <NDK/Components.hpp>
#include <NDK/Systems/PhysicsSystem2D.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp> #include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Graphics/Sprite.hpp> #include <Nazara/Graphics/Sprite.hpp>
#include <Catch/catch.hpp> #include <Catch/catch.hpp>
@ -62,6 +63,7 @@ SCENARIO("RenderSystem", "[NDK][RenderSystem]")
entity->AddComponent<Ndk::CollisionComponent2D>(boxCollider2D); entity->AddComponent<Ndk::CollisionComponent2D>(boxCollider2D);
Ndk::PhysicsComponent2D& physicsComponent2D = entity->AddComponent<Ndk::PhysicsComponent2D>(); Ndk::PhysicsComponent2D& physicsComponent2D = entity->AddComponent<Ndk::PhysicsComponent2D>();
world.GetSystem<Ndk::PhysicsSystem2D>().SetFixedUpdateRate(30.f);
world.Update(1.f); world.Update(1.f);
WHEN("We move it") WHEN("We move it")