diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp index f0ef6754a9..56cddbfa3a 100644 --- a/source/graphics/MapReader.cpp +++ b/source/graphics/MapReader.cpp @@ -848,20 +848,18 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time) { XMBAttributeList attrs = setting.GetAttributes(); Position = CFixedVector3D( - CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_x)).ToFloat()), - CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_y)).ToFloat()), - CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_z)).ToFloat())); - // TODO: shouldn't use floats here + fixed::FromString(CStr(attrs.GetNamedItem(at_x))), + fixed::FromString(CStr(attrs.GetNamedItem(at_y))), + fixed::FromString(CStr(attrs.GetNamedItem(at_z)))); } // else if (element_name == el_orientation) { XMBAttributeList attrs = setting.GetAttributes(); Orientation = CFixedVector3D( - CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_x)).ToFloat()), - CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_y)).ToFloat()), - CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_z)).ToFloat())); - // TODO: shouldn't use floats here + fixed::FromString(CStr(attrs.GetNamedItem(at_x))), + fixed::FromString(CStr(attrs.GetNamedItem(at_y))), + fixed::FromString(CStr(attrs.GetNamedItem(at_z)))); // TODO: what happens if some attributes are missing? } else @@ -1008,7 +1006,7 @@ int CXMLReader::ReadOldEntities(XMBElement parent, double end_time) entity_pos_t x = entity_pos_t::FromFloat(Position.X); entity_pos_t z = entity_pos_t::FromFloat(Position.Z); cmpPos->JumpTo(x, z); - cmpPos->SetYRotation(CFixed_23_8::FromFloat(Orientation)); + cmpPos->SetYRotation(entity_angle_t::FromFloat(Orientation)); } CmpPtr cmpOwner(*m_MapReader.pSimulation2, ent); @@ -1099,7 +1097,7 @@ int CXMLReader::ReadNonEntities(XMBElement parent, double end_time) entity_pos_t x = entity_pos_t::FromFloat(Position.X); // TODO: these should all be parsed as fixeds probably entity_pos_t z = entity_pos_t::FromFloat(Position.Z); cmpPos->JumpTo(x, z); - cmpPos->SetYRotation(CFixed_23_8::FromFloat(Orientation)); + cmpPos->SetYRotation(entity_angle_t::FromFloat(Orientation)); } } } diff --git a/source/graphics/Terrain.cpp b/source/graphics/Terrain.cpp index af451aa716..facfe5937f 100644 --- a/source/graphics/Terrain.cpp +++ b/source/graphics/Terrain.cpp @@ -151,9 +151,9 @@ void CTerrain::CalcPositionFixed(ssize_t i, ssize_t j, CFixedVector3D& pos) cons height = m_Heightmap[j*m_MapSize + i]; else height = 0; - pos.X = CFixed_23_8::FromInt(i)*(int)CELL_SIZE; - pos.Y = CFixed_23_8::FromInt(height)/(int)HEIGHT_UNITS_PER_METRE; - pos.Z = CFixed_23_8::FromInt(j)*(int)CELL_SIZE; + pos.X = fixed::FromInt(i) * (int)CELL_SIZE; + pos.Y = fixed::FromInt(height) / (int)HEIGHT_UNITS_PER_METRE; + pos.Z = fixed::FromInt(j) * (int)CELL_SIZE; } @@ -341,24 +341,30 @@ float CTerrain::GetExactGroundLevel(float x, float z) const + zf * ((1 - xf) * h01 + xf * h11))); } -CFixed_23_8 CTerrain::GetExactGroundLevelFixed(CFixed_23_8 x, CFixed_23_8 z) const +fixed CTerrain::GetExactGroundLevelFixed(fixed x, fixed z) const { // Clamp to size-2 so we can use the tiles (xi,zi)-(xi+1,zi+1) const ssize_t xi = clamp((ssize_t)(x / (int)CELL_SIZE).ToInt_RoundToZero(), (ssize_t)0, m_MapSize-2); const ssize_t zi = clamp((ssize_t)(z / (int)CELL_SIZE).ToInt_RoundToZero(), (ssize_t)0, m_MapSize-2); - const CFixed_23_8 one = CFixed_23_8::FromInt(1); + const fixed one = fixed::FromInt(1); - const CFixed_23_8 xf = clamp((x / (int)CELL_SIZE) - CFixed_23_8::FromInt(xi), CFixed_23_8::FromInt(0), one); - const CFixed_23_8 zf = clamp((z / (int)CELL_SIZE) - CFixed_23_8::FromInt(zi), CFixed_23_8::FromInt(0), one); + const fixed xf = clamp((x / (int)CELL_SIZE) - fixed::FromInt(xi), fixed::Zero(), one); + const fixed zf = clamp((z / (int)CELL_SIZE) - fixed::FromInt(zi), fixed::Zero(), one); u16 h00 = m_Heightmap[zi*m_MapSize + xi]; u16 h01 = m_Heightmap[(zi+1)*m_MapSize + xi]; u16 h10 = m_Heightmap[zi*m_MapSize + (xi+1)]; u16 h11 = m_Heightmap[(zi+1)*m_MapSize + (xi+1)]; + + // Intermediate scaling of xf, so we don't overflow in the multiplications below + // (h00 <= 65535, xf <= 1, max fixed is < 32768; divide by 2 here so xf1*h00 <= 32767.5) + const fixed xf0 = xf / 2; + const fixed xf1 = (one - xf) / 2; + // Linearly interpolate - return ((one - zf).Multiply((one - xf) * h00 + xf * h10) - + zf.Multiply((one - xf) * h01 + xf * h11)) / (int)HEIGHT_UNITS_PER_METRE; + return ((one - zf).Multiply(xf1 * h00 + xf0 * h10) + + zf.Multiply(xf1 * h01 + xf0 * h11)) / (int)(HEIGHT_UNITS_PER_METRE / 2); } /////////////////////////////////////////////////////////////////////////////// diff --git a/source/graphics/Terrain.h b/source/graphics/Terrain.h index d051246bcf..35db428904 100644 --- a/source/graphics/Terrain.h +++ b/source/graphics/Terrain.h @@ -40,7 +40,7 @@ class CFixedVector3D; const ssize_t CELL_SIZE = 4; /// number of u16 height units per metre -const ssize_t HEIGHT_UNITS_PER_METRE = 731; // == int(256.0f/0.35f) +const ssize_t HEIGHT_UNITS_PER_METRE = 732; // == approx int(256.0f/0.35f) /// metres per u16 height unit const float HEIGHT_SCALE = 1.f / HEIGHT_UNITS_PER_METRE; @@ -80,7 +80,7 @@ public: float GetVertexGroundLevel(ssize_t i, ssize_t j) const; float GetExactGroundLevel(float x, float z) const; - CFixed_23_8 GetExactGroundLevelFixed(CFixed_23_8 x, CFixed_23_8 z) const; + fixed GetExactGroundLevelFixed(fixed x, fixed z) const; float GetExactGroundLevel(const CVector2D& v) const; float GetSlope(float x, float z) const ; diff --git a/source/graphics/tests/test_Terrain.h b/source/graphics/tests/test_Terrain.h index ca40386826..9247e4d09f 100644 --- a/source/graphics/tests/test_Terrain.h +++ b/source/graphics/tests/test_Terrain.h @@ -100,25 +100,49 @@ public: Set45Slope(terrain); SetHighPlateau(terrain, 20); - CFixed_23_8 ground; + const double maxDelta = 0.0001; - ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(0.f), CFixed_23_8::FromFloat(1.5f*CELL_SIZE)); - TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE, 0.01f); + fixed ground; - ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(0.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE)); - TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+0.5f*CELL_SIZE, 0.01f); + ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(0.f), fixed::FromFloat(1.5f*CELL_SIZE)); + TS_ASSERT_DELTA(ground.ToDouble(), 100.0/HEIGHT_UNITS_PER_METRE, maxDelta); - ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(1.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE)); - TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+1.5f*CELL_SIZE, 0.01f); + ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(0.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE)); + TS_ASSERT_DELTA(ground.ToDouble(), 100.0/HEIGHT_UNITS_PER_METRE+0.5*CELL_SIZE, maxDelta); - ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(2.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE)); - TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+2.f*CELL_SIZE, 0.01f); + ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(1.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE)); + TS_ASSERT_DELTA(ground.ToDouble(), 100.0/HEIGHT_UNITS_PER_METRE+1.5*CELL_SIZE, maxDelta); - ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(3.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE)); - TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+11.f*CELL_SIZE, 0.01f); + ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(2.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE)); + TS_ASSERT_DELTA(ground.ToDouble(), 100.0/HEIGHT_UNITS_PER_METRE+2.0*CELL_SIZE, maxDelta); - ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(4.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE)); - TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+20.f*CELL_SIZE, 0.01f); + ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(3.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE)); + TS_ASSERT_DELTA(ground.ToDouble(), 100.0/HEIGHT_UNITS_PER_METRE+11.0*CELL_SIZE, maxDelta); + + ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(4.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE)); + TS_ASSERT_DELTA(ground.ToDouble(), 100.0/HEIGHT_UNITS_PER_METRE+20.0*CELL_SIZE, maxDelta); + } + + void test_GetExactGroundLevelFixed_max() + { + CTerrain terrain; + terrain.Initialize(4, NULL); + SetVertex(terrain, 0, 0, 65535); + SetVertex(terrain, 0, 1, 65535); + SetVertex(terrain, 1, 0, 65535); + SetVertex(terrain, 1, 1, 65535); + + const double maxDelta = 0.003; + + int p = 255; + for (int zi = 0; zi < p; ++zi) + { + for (int xi = 0; xi < p; ++xi) + { + fixed ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(xi/(float)p*CELL_SIZE), fixed::FromFloat(zi/(float)p*CELL_SIZE)); + TS_ASSERT_DELTA(ground.ToDouble(), 65535.0/HEIGHT_UNITS_PER_METRE, maxDelta); + } + } } void test_CalcNormal() diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp index e4a12c728c..1d9574b043 100644 --- a/source/gui/scripting/ScriptFunctions.cpp +++ b/source/gui/scripting/ScriptFunctions.cpp @@ -172,7 +172,7 @@ std::vector PickFriendlyEntitiesInRect(void* UNUSED(cbdata), int x0 CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y) { CVector3D pos = g_Game->GetView()->GetCamera()->GetWorldCoordinates(x, y, false); - return CFixedVector3D(CFixed_23_8::FromFloat(pos.X), CFixed_23_8::FromFloat(pos.Y), CFixed_23_8::FromFloat(pos.Z)); + return CFixedVector3D(fixed::FromFloat(pos.X), fixed::FromFloat(pos.Y), fixed::FromFloat(pos.Z)); } std::wstring SetCursor(void* UNUSED(cbdata), std::wstring name) diff --git a/source/maths/Fixed.cpp b/source/maths/Fixed.cpp index 0229d9b452..8627e80ce1 100644 --- a/source/maths/Fixed.cpp +++ b/source/maths/Fixed.cpp @@ -19,32 +19,46 @@ #include "Fixed.h" -// Based on http://www.dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization -CFixed_23_8 atan2_approx(CFixed_23_8 y, CFixed_23_8 x) +#include "ps/CStr.h" + +template<> +CFixed_15_16 CFixed_15_16::FromString(const CStr8& s) { - CFixed_23_8 zero; + return FromDouble(s.ToDouble()); // TODO: shouldn't use floats here +} + +template<> +CFixed_15_16 CFixed_15_16::FromString(const CStrW& s) +{ + return FromDouble(s.ToDouble()); // TODO: shouldn't use floats here +} + +// Based on http://www.dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization +CFixed_15_16 atan2_approx(CFixed_15_16 y, CFixed_15_16 x) +{ + CFixed_15_16 zero; // Special case to avoid division-by-zero if (x.IsZero() && y.IsZero()) return zero; - CFixed_23_8 c1; - c1.SetInternalValue(201); // pi/4 << 8 + CFixed_15_16 c1; + c1.SetInternalValue(51472); // pi/4 << 16 - CFixed_23_8 c2; - c2.SetInternalValue(603); // 3*pi/4 << 8 + CFixed_15_16 c2; + c2.SetInternalValue(154415); // 3*pi/4 << 16 - CFixed_23_8 abs_y = y.Absolute(); + CFixed_15_16 abs_y = y.Absolute(); - CFixed_23_8 angle; + CFixed_15_16 angle; if (x >= zero) { - CFixed_23_8 r = (x - abs_y) / (x + abs_y); + CFixed_15_16 r = (x - abs_y) / (x + abs_y); angle = c1 - c1.Multiply(r); } else { - CFixed_23_8 r = (x + abs_y) / (abs_y - x); + CFixed_15_16 r = (x + abs_y) / (abs_y - x); angle = c2 - c1.Multiply(r); } @@ -55,17 +69,15 @@ CFixed_23_8 atan2_approx(CFixed_23_8 y, CFixed_23_8 x) } template<> -CFixed_23_8 CFixed_23_8::Pi() +CFixed_15_16 CFixed_15_16::Pi() { - return CFixed_23_8(804); // = pi * 256 + return CFixed_15_16(205887); // = pi << 16 } -void sincos_approx(CFixed_23_8 a, CFixed_23_8& sin_out, CFixed_23_8& cos_out) +void sincos_approx(CFixed_15_16 a, CFixed_15_16& sin_out, CFixed_15_16& cos_out) { // XXX: mustn't use floating-point here - need a fixed-point emulation - // TODO: it's stupid doing sin/cos with 8-bit precision - we ought to have a CFixed_16_16 instead - - sin_out = CFixed_23_8::FromDouble(sin(a.ToDouble())); - cos_out = CFixed_23_8::FromDouble(cos(a.ToDouble())); + sin_out = CFixed_15_16::FromDouble(sin(a.ToDouble())); + cos_out = CFixed_15_16::FromDouble(cos(a.ToDouble())); } diff --git a/source/maths/Fixed.h b/source/maths/Fixed.h index c7d173e0bd..88b3c0162c 100644 --- a/source/maths/Fixed.h +++ b/source/maths/Fixed.h @@ -21,6 +21,9 @@ #include "lib/types.h" #include "maths/Sqrt.h" +class CStr8; +class CStrW; + #ifndef NDEBUG #define USE_FIXED_OVERFLOW_CHECKS #endif // NDEBUG @@ -90,12 +93,9 @@ inline T round_away_from_zero(float value) } /** - * A simple fixed-point number class, with no fancy features - * like overflow checking or anything. (It has very few basic - * features too, and needs to be substantially improved before - * it'll be of much use.) + * A simple fixed-point number class. * - * Use CFixed_23_8 rather than using this class directly. + * Use 'fixed' rather than using this class directly. */ template class CFixed @@ -122,6 +122,7 @@ public: { return CFixed(n << fract_bits); } + static CFixed FromFloat(float n) { if (!isfinite(n)) @@ -129,6 +130,7 @@ public: float scaled = n * fract_pow2; return CFixed(round_away_from_zero(scaled)); } + static CFixed FromDouble(double n) { if (!isfinite(n)) @@ -137,14 +139,19 @@ public: return CFixed(round_away_from_zero(scaled)); } + static CFixed FromString(const CStr8& s); + static CFixed FromString(const CStrW& s); + float ToFloat() const { return value / (float)fract_pow2; } + double ToDouble() const { return value / (double)fract_pow2; } + int ToInt_RoundToZero() const { if (value > 0) @@ -220,7 +227,7 @@ public: return CFixed(value * n); } - /// Divide by an integer. Must not have n == 0. Cannot overflow. + /// Divide by an integer. Must not have n == 0. Cannot overflow unless n == -1. CFixed operator/(int n) const { CheckDivisionOverflow(T, value, n, L"Overflow in CFixed::operator/(int n)") @@ -242,6 +249,16 @@ public: return CFixed((T)t); } + /** + * Compute this*m/d. Must not have d == 0. Won't overflow if the result can be represented as a CFixed. + */ + CFixed MulDiv(CFixed m, CFixed d) const + { + i64 t = ((i64)value * (i64)m.value) / (i64)d.value; + CheckCastOverflow(t, T, L"Overflow in CFixed::Multiply(CFixed n)", L"Underflow in CFixed::Multiply(CFixed n)") + return CFixed((T)t); + } + CFixed Sqrt() const { if (value <= 0) @@ -257,16 +274,24 @@ private: }; /** - * A fixed-point number class with 1-bit sign, 23-bit integral part, 8-bit fractional part. + * A fixed-point number class with 1-bit sign, 15-bit integral part, 16-bit fractional part. */ -typedef CFixed CFixed_23_8; +typedef CFixed CFixed_15_16; + +/** + * Default fixed-point type used by the engine. + */ +typedef CFixed_15_16 fixed; /** * Inaccurate approximation of atan2 over fixed-point numbers. * Maximum error is almost 0.08 radians (4.5 degrees). */ -CFixed_23_8 atan2_approx(CFixed_23_8 y, CFixed_23_8 x); +CFixed_15_16 atan2_approx(CFixed_15_16 y, CFixed_15_16 x); -void sincos_approx(CFixed_23_8 a, CFixed_23_8& sin_out, CFixed_23_8& cos_out); +/** + * Compute sin(a) and cos(a). + */ +void sincos_approx(CFixed_15_16 a, CFixed_15_16& sin_out, CFixed_15_16& cos_out); #endif // INCLUDED_FIXED diff --git a/source/maths/FixedVector2D.h b/source/maths/FixedVector2D.h index 60b69ee8f1..1723a4a7f3 100644 --- a/source/maths/FixedVector2D.h +++ b/source/maths/FixedVector2D.h @@ -23,9 +23,6 @@ class CFixedVector2D { -private: - typedef CFixed_23_8 fixed; - public: fixed X, Y; @@ -122,8 +119,6 @@ public: /** * Normalize the vector so that length is close to 1. * If length is 0, does nothing. - * WARNING: The fixed-point numbers only have 8-bit fractional parts, so - * a normalized vector will be very imprecise. */ void Normalize() { @@ -141,19 +136,11 @@ public: */ void Normalize(fixed n) { - if (n.IsZero()) - { - X = Y = fixed::FromInt(0); - return; - } - fixed l = Length(); - // TODO: work out whether this is giving decent precision - fixed d = l / n; - if (!d.IsZero()) + if (!l.IsZero()) { - X = X / d; - Y = Y / d; + X = X.MulDiv(n, l); + Y = Y.MulDiv(n, l); } } diff --git a/source/maths/FixedVector3D.h b/source/maths/FixedVector3D.h index a778295759..1630f3e19e 100644 --- a/source/maths/FixedVector3D.h +++ b/source/maths/FixedVector3D.h @@ -23,9 +23,6 @@ class CFixedVector3D { -private: - typedef CFixed_23_8 fixed; - public: fixed X, Y, Z; @@ -39,6 +36,12 @@ public: return (X == v.X && Y == v.Y && Z == v.Z); } + /// Vector inequality + bool operator!=(const CFixedVector3D& v) const + { + return (X != v.X || Y != v.Y || Z != v.Z); + } + /// Vector addition CFixedVector3D operator+(const CFixedVector3D& v) const { @@ -102,8 +105,6 @@ public: /** * Normalize the vector so that length is close to 1. * If length is 0, does nothing. - * WARNING: The fixed-point numbers only have 8-bit fractional parts, so - * a normalized vector will be very imprecise. */ void Normalize() { @@ -122,20 +123,12 @@ public: */ void Normalize(fixed n) { - if (n.IsZero()) - { - X = Y = Z = fixed::FromInt(0); - return; - } - fixed l = Length(); - // TODO: work out whether this is giving decent precision - fixed d = l / n; - if (!d.IsZero()) + if (!l.IsZero()) { - X = X / d; - Y = Y / d; - Z = Z / d; + X = X.MulDiv(n, l); + Y = Y.MulDiv(n, l); + Z = Z.MulDiv(n, l); } } diff --git a/source/maths/tests/test_Fixed.h b/source/maths/tests/test_Fixed.h index 135a3b9445..738abacbb3 100644 --- a/source/maths/tests/test_Fixed.h +++ b/source/maths/tests/test_Fixed.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,18 +25,18 @@ class TestFixed : public CxxTest::TestSuite public: void test_basic() { - CFixed_23_8 a = CFixed_23_8::FromInt(1234567); - TS_ASSERT_EQUALS((a + a).ToDouble(), 2469134); + fixed a = fixed::FromInt(12345); + TS_ASSERT_EQUALS((a + a).ToDouble(), 24690); TS_ASSERT_EQUALS((a - a).ToDouble(), 0); - TS_ASSERT_EQUALS((-a).ToDouble(), -1234567); + TS_ASSERT_EQUALS((-a).ToDouble(), -12345); TS_ASSERT_EQUALS((a / a).ToDouble(), 1); - TS_ASSERT_EQUALS((a / 127).ToDouble(), 9721); - TS_ASSERT_EQUALS((a * 2).ToDouble(), 2469134); + TS_ASSERT_EQUALS((a / 823).ToDouble(), 15); + TS_ASSERT_EQUALS((a * 2).ToDouble(), 24690); } void test_FromInt() { - CFixed_23_8 a = CFixed_23_8::FromInt(123); + fixed a = fixed::FromInt(123); TS_ASSERT_EQUALS(a.ToFloat(), 123.0f); TS_ASSERT_EQUALS(a.ToDouble(), 123.0); TS_ASSERT_EQUALS(a.ToInt_RoundToZero(), 123); @@ -44,97 +44,95 @@ public: void test_FromFloat() { - CFixed_23_8 a = CFixed_23_8::FromFloat(123.125f); + fixed a = fixed::FromFloat(123.125f); TS_ASSERT_EQUALS(a.ToFloat(), 123.125f); TS_ASSERT_EQUALS(a.ToDouble(), 123.125); - CFixed_23_8 b = CFixed_23_8::FromFloat(-123.125f); + fixed b = fixed::FromFloat(-123.125f); TS_ASSERT_EQUALS(b.ToFloat(), -123.125f); TS_ASSERT_EQUALS(b.ToDouble(), -123.125); - CFixed_23_8 c = CFixed_23_8::FromFloat(INFINITY); + fixed c = fixed::FromFloat(INFINITY); TS_ASSERT_EQUALS(c.GetInternalValue(), (i32)0); - CFixed_23_8 d = CFixed_23_8::FromFloat(-INFINITY); + fixed d = fixed::FromFloat(-INFINITY); TS_ASSERT_EQUALS(d.GetInternalValue(), (i32)0); - CFixed_23_8 e = CFixed_23_8::FromFloat(NAN); + fixed e = fixed::FromFloat(NAN); TS_ASSERT_EQUALS(e.GetInternalValue(), (i32)0); } void test_FromDouble() { - CFixed_23_8 a = CFixed_23_8::FromDouble(123.125); + fixed a = fixed::FromDouble(123.125); TS_ASSERT_EQUALS(a.ToFloat(), 123.125f); TS_ASSERT_EQUALS(a.ToDouble(), 123.125); - CFixed_23_8 b = CFixed_23_8::FromDouble(-123.125); + fixed b = fixed::FromDouble(-123.125); TS_ASSERT_EQUALS(b.ToFloat(), -123.125f); TS_ASSERT_EQUALS(b.ToDouble(), -123.125); - CFixed_23_8 c = CFixed_23_8::FromDouble(INFINITY); + fixed c = fixed::FromDouble(INFINITY); TS_ASSERT_EQUALS(c.GetInternalValue(), (i32)0); - CFixed_23_8 d = CFixed_23_8::FromDouble(-INFINITY); + fixed d = fixed::FromDouble(-INFINITY); TS_ASSERT_EQUALS(d.GetInternalValue(), (i32)0); - CFixed_23_8 e = CFixed_23_8::FromDouble(NAN); + fixed e = fixed::FromDouble(NAN); TS_ASSERT_EQUALS(e.GetInternalValue(), (i32)0); } void test_FromFloat_Rounding() { - double eps = pow(2.0, -8.0); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps).ToDouble(), eps); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.5625).ToDouble(), eps); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.5).ToDouble(), eps); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.4375).ToDouble(), 0.0); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps).ToDouble(), -eps); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.5625).ToDouble(), -eps); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.5).ToDouble(), -eps); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.4375).ToDouble(), 0.0); + double eps = pow(2.0, -16.0); + TS_ASSERT_EQUALS(fixed::FromFloat(eps).ToDouble(), eps); + TS_ASSERT_EQUALS(fixed::FromFloat(eps * 0.5625).ToDouble(), eps); + TS_ASSERT_EQUALS(fixed::FromFloat(eps * 0.5).ToDouble(), eps); + TS_ASSERT_EQUALS(fixed::FromFloat(eps * 0.4375).ToDouble(), 0.0); + TS_ASSERT_EQUALS(fixed::FromFloat(-eps).ToDouble(), -eps); + TS_ASSERT_EQUALS(fixed::FromFloat(-eps * 0.5625).ToDouble(), -eps); + TS_ASSERT_EQUALS(fixed::FromFloat(-eps * 0.5).ToDouble(), -eps); + TS_ASSERT_EQUALS(fixed::FromFloat(-eps * 0.4375).ToDouble(), 0.0); } void test_RoundToZero() { - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.f).ToInt_RoundToZero(), 10); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.1f).ToInt_RoundToZero(), 10); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.5f).ToInt_RoundToZero(), 10); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.99f).ToInt_RoundToZero(), 10); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(0.1f).ToInt_RoundToZero(), 0); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(0.0f).ToInt_RoundToZero(), 0); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-0.1f).ToInt_RoundToZero(), 0); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-0.99f).ToInt_RoundToZero(), 0); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-1.0f).ToInt_RoundToZero(), -1); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.0f).ToInt_RoundToZero(), -2); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.5f).ToInt_RoundToZero(), -2); - TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.99f).ToInt_RoundToZero(), -2); + TS_ASSERT_EQUALS(fixed::FromFloat(10.f).ToInt_RoundToZero(), 10); + TS_ASSERT_EQUALS(fixed::FromFloat(10.1f).ToInt_RoundToZero(), 10); + TS_ASSERT_EQUALS(fixed::FromFloat(10.5f).ToInt_RoundToZero(), 10); + TS_ASSERT_EQUALS(fixed::FromFloat(10.99f).ToInt_RoundToZero(), 10); + TS_ASSERT_EQUALS(fixed::FromFloat(0.1f).ToInt_RoundToZero(), 0); + TS_ASSERT_EQUALS(fixed::FromFloat(0.0f).ToInt_RoundToZero(), 0); + TS_ASSERT_EQUALS(fixed::FromFloat(-0.1f).ToInt_RoundToZero(), 0); + TS_ASSERT_EQUALS(fixed::FromFloat(-0.99f).ToInt_RoundToZero(), 0); + TS_ASSERT_EQUALS(fixed::FromFloat(-1.0f).ToInt_RoundToZero(), -1); + TS_ASSERT_EQUALS(fixed::FromFloat(-2.0f).ToInt_RoundToZero(), -2); + TS_ASSERT_EQUALS(fixed::FromFloat(-2.5f).ToInt_RoundToZero(), -2); + TS_ASSERT_EQUALS(fixed::FromFloat(-2.99f).ToInt_RoundToZero(), -2); } // TODO: test all the arithmetic operators void test_Sqrt() { - TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(1.0).Sqrt().ToDouble(), 1.0); - TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(1000000.0).Sqrt().ToDouble(), 1000.0); - TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(0.0625).Sqrt().ToDouble(), 0.25); - TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(-1.0).Sqrt().ToDouble(), 0.0); - TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(0.0).Sqrt().ToDouble(), 0.0); + TS_ASSERT_EQUALS(fixed::FromDouble(1.0).Sqrt().ToDouble(), 1.0); + TS_ASSERT_EQUALS(fixed::FromDouble(32400.0).Sqrt().ToDouble(), 180.0); + TS_ASSERT_EQUALS(fixed::FromDouble(0.0625).Sqrt().ToDouble(), 0.25); + TS_ASSERT_EQUALS(fixed::FromDouble(-1.0).Sqrt().ToDouble(), 0.0); + TS_ASSERT_EQUALS(fixed::FromDouble(0.0).Sqrt().ToDouble(), 0.0); } void test_Atan2() { - typedef CFixed_23_8 f; - // Special cases from atan2 man page: - TS_ASSERT_DELTA(atan2_approx(f::FromInt(0), f::FromInt(-1)).ToDouble(), M_PI, 0.01); - TS_ASSERT_EQUALS(atan2_approx(f::FromInt(0), f::FromInt(+1)).ToDouble(), 0); - TS_ASSERT_DELTA(atan2_approx(f::FromInt(-1), f::FromInt(0)).ToDouble(), -M_PI_2, 0.01); - TS_ASSERT_DELTA(atan2_approx(f::FromInt(+1), f::FromInt(0)).ToDouble(), +M_PI_2, 0.01); - TS_ASSERT_EQUALS(atan2_approx(f::FromInt(0), f::FromInt(0)).ToDouble(), 0); + TS_ASSERT_DELTA(atan2_approx(fixed::FromInt(0), fixed::FromInt(-1)).ToDouble(), M_PI, 0.01); + TS_ASSERT_EQUALS(atan2_approx(fixed::FromInt(0), fixed::FromInt(+1)).ToDouble(), 0); + TS_ASSERT_DELTA(atan2_approx(fixed::FromInt(-1), fixed::FromInt(0)).ToDouble(), -M_PI_2, 0.01); + TS_ASSERT_DELTA(atan2_approx(fixed::FromInt(+1), fixed::FromInt(0)).ToDouble(), +M_PI_2, 0.01); + TS_ASSERT_EQUALS(atan2_approx(fixed::FromInt(0), fixed::FromInt(0)).ToDouble(), 0); // Test that it approximately matches libc's atan2 - #define T(y, x) TS_ASSERT_DELTA(atan2_approx(f::FromDouble(y), f::FromDouble(x)).ToDouble(), atan2((double)(y), (double)(x)), 0.078) + #define T(y, x) TS_ASSERT_DELTA(atan2_approx(fixed::FromDouble(y), fixed::FromDouble(x)).ToDouble(), atan2((double)(y), (double)(x)), 0.072) // Quadrants T(1, 1); diff --git a/source/maths/tests/test_FixedVector2D.h b/source/maths/tests/test_FixedVector2D.h new file mode 100644 index 0000000000..f2a3e3b7da --- /dev/null +++ b/source/maths/tests/test_FixedVector2D.h @@ -0,0 +1,143 @@ +/* Copyright (C) 2010 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "lib/self_test.h" + +#include "maths/FixedVector2D.h" + +#define TS_ASSERT_VEC_EQUALS(v, x, y) \ + TS_ASSERT_EQUALS(v.X.ToDouble(), x); \ + TS_ASSERT_EQUALS(v.Y.ToDouble(), y); + +#define TS_ASSERT_VEC_DELTA(v, x, y, delta) \ + TS_ASSERT_DELTA(v.X.ToDouble(), x, delta); \ + TS_ASSERT_DELTA(v.Y.ToDouble(), y, delta); + +class TestFixedVector2D : public CxxTest::TestSuite +{ +public: + void test_basic() + { + CFixedVector2D v1 (fixed::FromInt(1), fixed::FromInt(2)); + CFixedVector2D v2 (fixed::FromInt(10), fixed::FromInt(20)); + CFixedVector2D v3; + TS_ASSERT_VEC_EQUALS(v1, 1, 2); + TS_ASSERT_VEC_EQUALS(v2, 10, 20); + TS_ASSERT_VEC_EQUALS(v3, 0, 0); + v3 = v1 + v2; + TS_ASSERT_VEC_EQUALS(v3, 11, 22); + v3 += v2; + TS_ASSERT_VEC_EQUALS(v3, 21, 42); + v3 -= v2; + TS_ASSERT_VEC_EQUALS(v3, 11, 22); + v3 = v1 - v2; + TS_ASSERT_VEC_EQUALS(v3, -9, -18); + v3 = -v3; + TS_ASSERT_VEC_EQUALS(v3, 9, 18); + } + + void test_Length() + { + CFixedVector2D v1 (fixed::FromInt(3), fixed::FromInt(4)); + TS_ASSERT_EQUALS(v1.Length().ToDouble(), 5.0); + + fixed max; + max.SetInternalValue((i32)0x7fffffff); + CFixedVector2D v2 (max, fixed::FromInt(0)); + TS_ASSERT_EQUALS(v2.Length().ToDouble(), max.ToDouble()); + + fixed large; + large.SetInternalValue((i32)((double)0x7fffffff/sqrt(2.0))); // largest value that shouldn't cause overflow + CFixedVector2D v3 (large, large); + TS_ASSERT_DELTA(v3.Length().ToDouble(), sqrt(2.0)*large.ToDouble(), 0.01); + } + + void test_Normalize() + { + CFixedVector2D v0 (fixed::FromInt(0), fixed::FromInt(0)); + v0.Normalize(); + TS_ASSERT_VEC_EQUALS(v0, 0.0, 0.0); + + CFixedVector2D v1 (fixed::FromInt(3), fixed::FromInt(4)); + v1.Normalize(); + TS_ASSERT_VEC_DELTA(v1, 3.0/5.0, 4.0/5.0, 0.01); + + fixed max; + max.SetInternalValue((i32)0x7fffffff); + CFixedVector2D v2 (max, fixed::FromInt(0)); + v2.Normalize(); + TS_ASSERT_VEC_EQUALS(v2, 1.0, 0.0); + + fixed large; + large.SetInternalValue((i32)((double)0x7fffffff/sqrt(2.0))); // largest value that shouldn't cause overflow + CFixedVector2D v3 (large, large); + v3.Normalize(); + TS_ASSERT_VEC_DELTA(v3, 1.0/sqrt(2.0), 1.0/sqrt(2.0), 0.01); + } + + void test_NormalizeTo() + { + { + CFixedVector2D v (fixed::FromInt(0), fixed::FromInt(0)); + v.Normalize(fixed::FromInt(1)); + TS_ASSERT_VEC_EQUALS(v, 0.0, 0.0); + } + + { + CFixedVector2D v (fixed::FromInt(3), fixed::FromInt(4)); + v.Normalize(fixed::FromInt(0)); + TS_ASSERT_VEC_EQUALS(v, 0.0, 0.0); + } + + { + CFixedVector2D v (fixed::FromInt(3), fixed::FromInt(4)); + v.Normalize(fixed::FromInt(1)); + TS_ASSERT_VEC_DELTA(v, 3.0/5.0, 4.0/5.0, 0.01); + } + + { + CFixedVector2D v (fixed::FromInt(3000), fixed::FromInt(4000)); + v.Normalize(fixed::FromInt(1)); + TS_ASSERT_VEC_DELTA(v, 3.0/5.0, 4.0/5.0, 0.01); + } + + { + CFixedVector2D v (fixed::FromInt(3), fixed::FromInt(4)); + v.Normalize(fixed::FromInt(100)); + TS_ASSERT_VEC_DELTA(v, 300.0/5.0, 400.0/5.0, 0.02); + } + + { + CFixedVector2D v (fixed::FromInt(3), fixed::FromInt(4)); + v.Normalize(fixed::FromInt(1)/100); + TS_ASSERT_VEC_DELTA(v, 3.0/500.0, 4.0/500.0, 0.0001); + } + + { + CFixedVector2D v (fixed::FromInt(3), fixed::FromInt(4)); + v.Normalize(fixed::FromInt(1)/10000); + TS_ASSERT_VEC_DELTA(v, 3.0/50000.0, 4.0/50000.0, 0.0001); + } + } + + void test_Dot() + { + CFixedVector2D v1 (fixed::FromInt(5), fixed::FromInt(6)); + CFixedVector2D v2 (fixed::FromInt(8), fixed::FromInt(-9)); + TS_ASSERT_EQUALS(v1.Dot(v2).ToDouble(), 5*8 + 6*-9); + } +}; diff --git a/source/maths/tests/test_FixedVector3D.h b/source/maths/tests/test_FixedVector3D.h index 74618b8216..e4cb0b259b 100644 --- a/source/maths/tests/test_FixedVector3D.h +++ b/source/maths/tests/test_FixedVector3D.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -24,9 +24,13 @@ TS_ASSERT_EQUALS(v.Y.ToDouble(), y); \ TS_ASSERT_EQUALS(v.Z.ToDouble(), z); +#define TS_ASSERT_VEC_DELTA(v, x, y, z, delta) \ + TS_ASSERT_DELTA(v.X.ToDouble(), x, delta); \ + TS_ASSERT_DELTA(v.Y.ToDouble(), y, delta); \ + TS_ASSERT_DELTA(v.Z.ToDouble(), z, delta); + class TestFixedVector3D : public CxxTest::TestSuite { - typedef CFixed_23_8 fixed; public: void test_basic() { @@ -68,31 +72,68 @@ public: { CFixedVector3D v0 (fixed::FromInt(0), fixed::FromInt(0), fixed::FromInt(0)); v0.Normalize(); - TS_ASSERT_EQUALS(v0.X.ToDouble(), 0.0); - TS_ASSERT_EQUALS(v0.Y.ToDouble(), 0.0); - TS_ASSERT_EQUALS(v0.Z.ToDouble(), 0.0); + TS_ASSERT_VEC_EQUALS(v0, 0.0, 0.0, 0.0); CFixedVector3D v1 (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12)); v1.Normalize(); - TS_ASSERT_DELTA(v1.X.ToDouble(), 3.0/13.0, 0.01); - TS_ASSERT_DELTA(v1.Y.ToDouble(), 4.0/13.0, 0.01); - TS_ASSERT_DELTA(v1.Z.ToDouble(), 12.0/13.0, 0.01); + TS_ASSERT_VEC_DELTA(v1, 3.0/13.0, 4.0/13.0, 12.0/13.0, 0.01); fixed max; max.SetInternalValue((i32)0x7fffffff); CFixedVector3D v2 (max, fixed::FromInt(0), fixed::FromInt(0)); v2.Normalize(); - TS_ASSERT_EQUALS(v2.X.ToDouble(), 1.0); - TS_ASSERT_EQUALS(v2.Y.ToDouble(), 0.0); - TS_ASSERT_EQUALS(v2.Z.ToDouble(), 0.0); + TS_ASSERT_VEC_EQUALS(v2, 1.0, 0.0, 0.0); fixed large; large.SetInternalValue((i32)((double)0x7fffffff/sqrt(3.0))+1); // largest value that shouldn't cause overflow CFixedVector3D v3 (large, large, large); v3.Normalize(); - TS_ASSERT_DELTA(v3.X.ToDouble(), 1.0/sqrt(3.0), 0.01); - TS_ASSERT_DELTA(v3.Y.ToDouble(), 1.0/sqrt(3.0), 0.01); - TS_ASSERT_DELTA(v3.Z.ToDouble(), 1.0/sqrt(3.0), 0.01); + TS_ASSERT_VEC_DELTA(v3, 1.0/sqrt(3.0), 1.0/sqrt(3.0), 1.0/sqrt(3.0), 0.01); + } + + void test_NormalizeTo() + { + { + CFixedVector3D v (fixed::FromInt(0), fixed::FromInt(0), fixed::FromInt(0)); + v.Normalize(fixed::FromInt(1)); + TS_ASSERT_VEC_EQUALS(v, 0.0, 0.0, 0.0); + } + + { + CFixedVector3D v (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12)); + v.Normalize(fixed::FromInt(0)); + TS_ASSERT_VEC_EQUALS(v, 0.0, 0.0, 0.0); + } + + { + CFixedVector3D v (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12)); + v.Normalize(fixed::FromInt(1)); + TS_ASSERT_VEC_DELTA(v, 3.0/13.0, 4.0/13.0, 12.0/13.0, 0.01); + } + + { + CFixedVector3D v (fixed::FromInt(3000), fixed::FromInt(4000), fixed::FromInt(12000)); + v.Normalize(fixed::FromInt(1)); + TS_ASSERT_VEC_DELTA(v, 3.0/13.0, 4.0/13.0, 12.0/13.0, 0.01); + } + + { + CFixedVector3D v (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12)); + v.Normalize(fixed::FromInt(100)); + TS_ASSERT_VEC_DELTA(v, 300.0/13.0, 400.0/13.0, 1200.0/13.0, 0.01); + } + + { + CFixedVector3D v (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12)); + v.Normalize(fixed::FromInt(1)/100); + TS_ASSERT_VEC_DELTA(v, 3.0/1300.0, 4.0/1300.0, 12.0/1300.0, 0.0001); + } + + { + CFixedVector3D v (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12)); + v.Normalize(fixed::FromInt(1)/10000); + TS_ASSERT_VEC_DELTA(v, 3.0/130000.0, 4.0/130000.0, 12.0/130000.0, 0.0001); + } } void test_Cross() @@ -100,9 +141,7 @@ public: CFixedVector3D v1 (fixed::FromInt(5), fixed::FromInt(6), fixed::FromInt(7)); CFixedVector3D v2 (fixed::FromInt(8), fixed::FromInt(9), fixed::FromInt(-10)); CFixedVector3D v3 = v1.Cross(v2); - TS_ASSERT_EQUALS(v3.X.ToDouble(), 6*-10 - 7*9); - TS_ASSERT_EQUALS(v3.Y.ToDouble(), 7*8 - 5*-10); - TS_ASSERT_EQUALS(v3.Z.ToDouble(), 5*9 - 8*6); + TS_ASSERT_VEC_EQUALS(v3, 6*-10 - 7*9, 7*8 - 5*-10, 5*9 - 8*6); } void test_Dot() diff --git a/source/scriptinterface/tests/test_ScriptConversions.h b/source/scriptinterface/tests/test_ScriptConversions.h index fea84d9922..6f181830ec 100644 --- a/source/scriptinterface/tests/test_ScriptConversions.h +++ b/source/scriptinterface/tests/test_ScriptConversions.h @@ -113,10 +113,10 @@ public: convert_to("test", "\"test\""); convert_to(s1.c_str(), "\"t\""); - roundtrip(CFixed_23_8::FromInt(0), "0"); - roundtrip(CFixed_23_8::FromInt(123), "123"); - roundtrip(CFixed_23_8::FromInt(-123), "-123"); - roundtrip(CFixed_23_8::FromDouble(123.25), "123.25"); + roundtrip(fixed::FromInt(0), "0"); + roundtrip(fixed::FromInt(123), "123"); + roundtrip(fixed::FromInt(-123), "-123"); + roundtrip(fixed::FromDouble(123.25), "123.25"); } void test_integers() diff --git a/source/simulation2/MessageTypes.h b/source/simulation2/MessageTypes.h index 1839df8ce7..87f3c161a7 100644 --- a/source/simulation2/MessageTypes.h +++ b/source/simulation2/MessageTypes.h @@ -49,12 +49,12 @@ class CMessageUpdate : public CMessage public: DEFAULT_MESSAGE_IMPL(Update) - CMessageUpdate(CFixed_23_8 turnLength) : + CMessageUpdate(fixed turnLength) : turnLength(turnLength) { } - CFixed_23_8 turnLength; + fixed turnLength; }; class CMessageInterpolate : public CMessage @@ -151,12 +151,12 @@ class CMessageMotionChanged : public CMessage public: DEFAULT_MESSAGE_IMPL(MotionChanged) - CMessageMotionChanged(CFixed_23_8 speed) : + CMessageMotionChanged(fixed speed) : speed(speed) { } - CFixed_23_8 speed; // metres per second, or 0 if not moving + fixed speed; // metres per second, or 0 if not moving }; #endif // INCLUDED_MESSAGETYPES diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp index 37712bad90..1b3ab33e09 100644 --- a/source/simulation2/Simulation2.cpp +++ b/source/simulation2/Simulation2.cpp @@ -148,7 +148,7 @@ bool CSimulation2Impl::Update(float frameTime) if (m_DeltaTime >= 0.0) { double turnLength = TURN_LENGTH / 1000.0; - CFixed_23_8 turnLengthFixed = CFixed_23_8::FromInt(TURN_LENGTH) / 1000; + fixed turnLengthFixed = fixed::FromInt(TURN_LENGTH) / 1000; m_DeltaTime -= turnLength; CMessageTurnStart msgTurnStart; diff --git a/source/simulation2/components/CCmpFootprint.cpp b/source/simulation2/components/CCmpFootprint.cpp index 10bd4f3dc0..a8cd0d9e36 100644 --- a/source/simulation2/components/CCmpFootprint.cpp +++ b/source/simulation2/components/CCmpFootprint.cpp @@ -36,9 +36,9 @@ public: DEFAULT_COMPONENT_ALLOCATOR(Footprint) EShape m_Shape; - CFixed_23_8 m_Size0; // width/radius - CFixed_23_8 m_Size1; // height/radius - CFixed_23_8 m_Height; + entity_pos_t m_Size0; // width/radius + entity_pos_t m_Size1; // height/radius + entity_pos_t m_Height; static std::string GetSchema() { @@ -90,7 +90,7 @@ public: { // Error - pick some default m_Shape = CIRCLE; - m_Size0 = m_Size1 = CFixed_23_8::FromInt(1); + m_Size0 = m_Size1 = entity_pos_t::FromInt(1); } m_Height = paramNode.GetChild("Height").ToFixed(); @@ -109,7 +109,7 @@ public: Init(context, paramNode); } - virtual void GetShape(EShape& shape, CFixed_23_8& size0, CFixed_23_8& size1, CFixed_23_8& height) + virtual void GetShape(EShape& shape, entity_pos_t& size0, entity_pos_t& size1, entity_pos_t& height) { shape = m_Shape; size0 = m_Size0; @@ -124,7 +124,7 @@ public: // because the footprint might be inside the obstruction, but it hopefully gives us a nicer // shape.) - CFixedVector3D error(CFixed_23_8::FromInt(-1), CFixed_23_8::FromInt(-1), CFixed_23_8::FromInt(-1)); + CFixedVector3D error(fixed::FromInt(-1), fixed::FromInt(-1), fixed::FromInt(-1)); CmpPtr cmpPosition(GetSimContext(), GetEntityId()); if (cmpPosition.null() || !cmpPosition->IsInWorld()) @@ -142,14 +142,14 @@ public: // else zero // The spawn point should be far enough from this footprint to fit the unit, plus a little gap - CFixed_23_8 clearance = spawnedRadius + entity_pos_t::FromInt(2); + entity_pos_t clearance = spawnedRadius + entity_pos_t::FromInt(2); CFixedVector3D initialPos = cmpPosition->GetPosition(); entity_angle_t initialAngle = cmpPosition->GetRotation().Y; if (m_Shape == CIRCLE) { - CFixed_23_8 radius = m_Size0 + clearance; + entity_pos_t radius = m_Size0 + clearance; // Try equally-spaced points around the circle, starting from the front and expanding outwards in alternating directions const ssize_t numPoints = 31; @@ -157,10 +157,10 @@ public: { entity_angle_t angle = initialAngle + (entity_angle_t::Pi()*2).Multiply(entity_angle_t::FromInt(i)/(int)numPoints); - CFixed_23_8 s, c; + fixed s, c; sincos_approx(angle, s, c); - CFixedVector3D pos (initialPos.X + s.Multiply(radius), CFixed_23_8::Zero(), initialPos.Z + c.Multiply(radius)); + CFixedVector3D pos (initialPos.X + s.Multiply(radius), fixed::Zero(), initialPos.Z + c.Multiply(radius)); SkipTagObstructionFilter filter(spawned); // ignore collisions with the spawned entity if (!cmpObstructionManager->TestUnitShape(filter, pos.X, pos.Z, spawnedRadius)) @@ -169,7 +169,7 @@ public: } else { - CFixed_23_8 s, c; + fixed s, c; sincos_approx(initialAngle, s, c); for (size_t edge = 0; edge < 4; ++edge) @@ -179,7 +179,7 @@ public: // Compute the direction and length of the current edge CFixedVector2D dir; - CFixed_23_8 sx, sy; + fixed sx, sy; switch (edge) { case 0: @@ -214,7 +214,7 @@ public: SkipTagObstructionFilter filter(spawned); // ignore collisions with the spawned entity if (!cmpObstructionManager->TestUnitShape(filter, pos.X, pos.Y, spawnedRadius)) - return CFixedVector3D(pos.X, CFixed_23_8::Zero(), pos.Y); // this position is okay, so return it + return CFixedVector3D(pos.X, fixed::Zero(), pos.Y); // this position is okay, so return it } } } diff --git a/source/simulation2/components/CCmpMotionBall.cpp b/source/simulation2/components/CCmpMotionBall.cpp index 4b4abd7955..253df95c20 100644 --- a/source/simulation2/components/CCmpMotionBall.cpp +++ b/source/simulation2/components/CCmpMotionBall.cpp @@ -72,17 +72,17 @@ public: { case MT_Update: { - CFixed_23_8 dt = static_cast (msg).turnLength; + fixed dt = static_cast (msg).turnLength; Move(context, dt); break; } } } - void Move(const CSimContext& context, CFixed_23_8 dt); + void Move(const CSimContext& context, fixed dt); }; -void CCmpMotionBall::Move(const CSimContext& context, CFixed_23_8 dt) +void CCmpMotionBall::Move(const CSimContext& context, fixed dt) { CmpPtr cmpPosition(context, GetEntityId()); if (cmpPosition.null()) diff --git a/source/simulation2/components/CCmpObstructionManager.cpp b/source/simulation2/components/CCmpObstructionManager.cpp index 8211b6ef10..45b2df994b 100644 --- a/source/simulation2/components/CCmpObstructionManager.cpp +++ b/source/simulation2/components/CCmpObstructionManager.cpp @@ -138,7 +138,7 @@ public: virtual tag_t AddStaticShape(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h) { - CFixed_23_8 s, c; + fixed s, c; sincos_approx(a, s, c); CFixedVector2D u(c, -s); CFixedVector2D v(s, c); @@ -162,7 +162,7 @@ public: } else { - CFixed_23_8 s, c; + fixed s, c; sincos_approx(a, s, c); CFixedVector2D u(c, -s); CFixedVector2D v(s, c); @@ -304,7 +304,7 @@ bool CCmpObstructionManager::TestStaticShape(const IObstructionTestFilter& filte { PROFILE("TestStaticShape"); - CFixed_23_8 s, c; + fixed s, c; sincos_approx(a, s, c); CFixedVector2D u(c, -s); CFixedVector2D v(s, c); diff --git a/source/simulation2/components/CCmpPathfinder.cpp b/source/simulation2/components/CCmpPathfinder.cpp index 1f760a35c2..d71e1a03b4 100644 --- a/source/simulation2/components/CCmpPathfinder.cpp +++ b/source/simulation2/components/CCmpPathfinder.cpp @@ -53,8 +53,6 @@ class CCmpPathfinder; struct PathfindTile; -typedef CFixed_23_8 fixed; - /** * Terrain overlay for pathfinder debugging. * Renders a representation of the most recent pathfinding operation. @@ -494,12 +492,12 @@ typedef PriorityQueueList, u32> PriorityQueue; static u32 CalculateHeuristic(u16 i, u16 j, u16 iGoal, u16 jGoal, u16 rGoal) { #ifdef USE_DIAGONAL_MOVEMENT - CFixedVector2D pos (CFixed_23_8::FromInt(i), CFixed_23_8::FromInt(j)); - CFixedVector2D goal (CFixed_23_8::FromInt(iGoal), CFixed_23_8::FromInt(jGoal)); - CFixed_23_8 dist = (pos - goal).Length(); + CFixedVector2D pos (fixed::FromInt(i), fixed::FromInt(j)); + CFixedVector2D goal (fixed::FromInt(iGoal), fixed::FromInt(jGoal)); + fixed dist = (pos - goal).Length(); // TODO: the heuristic could match the costs better - it's not really Euclidean movement - CFixed_23_8 rdist = dist - CFixed_23_8::FromInt(rGoal); + fixed rdist = dist - fixed::FromInt(rGoal); rdist = rdist.Absolute(); return (rdist * (int)g_CostPerTile).ToInt_RoundToZero(); diff --git a/source/simulation2/components/CCmpProjectileManager.cpp b/source/simulation2/components/CCmpProjectileManager.cpp index 4bab911d27..1b733b4c41 100644 --- a/source/simulation2/components/CCmpProjectileManager.cpp +++ b/source/simulation2/components/CCmpProjectileManager.cpp @@ -89,12 +89,12 @@ public: } } - virtual void LaunchProjectileAtEntity(entity_id_t source, entity_id_t target, CFixed_23_8 speed, CFixed_23_8 gravity) + virtual void LaunchProjectileAtEntity(entity_id_t source, entity_id_t target, fixed speed, fixed gravity) { LaunchProjectile(source, CFixedVector3D(), target, speed, gravity); } - virtual void LaunchProjectileAtPoint(entity_id_t source, CFixedVector3D target, CFixed_23_8 speed, CFixed_23_8 gravity) + virtual void LaunchProjectileAtPoint(entity_id_t source, CFixedVector3D target, fixed speed, fixed gravity) { LaunchProjectile(source, target, INVALID_ENTITY, speed, gravity); } @@ -113,7 +113,7 @@ private: std::vector m_Projectiles; - void LaunchProjectile(entity_id_t source, CFixedVector3D targetPoint, entity_id_t targetEnt, CFixed_23_8 speed, CFixed_23_8 gravity); + void LaunchProjectile(entity_id_t source, CFixedVector3D targetPoint, entity_id_t targetEnt, fixed speed, fixed gravity); void AdvanceProjectile(const CSimContext& context, Projectile& projectile, float dt, float frameOffset); @@ -124,7 +124,7 @@ private: REGISTER_COMPONENT_TYPE(ProjectileManager) -void CCmpProjectileManager::LaunchProjectile(entity_id_t source, CFixedVector3D targetPoint, entity_id_t targetEnt, CFixed_23_8 speed, CFixed_23_8 gravity) +void CCmpProjectileManager::LaunchProjectile(entity_id_t source, CFixedVector3D targetPoint, entity_id_t targetEnt, fixed speed, fixed gravity) { if (!GetSimContext().HasUnitManager()) return; // do nothing if graphics are disabled diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp index b35601c207..476214bb77 100644 --- a/source/simulation2/components/CCmpUnitMotion.cpp +++ b/source/simulation2/components/CCmpUnitMotion.cpp @@ -59,7 +59,7 @@ public: // Template state: - CFixed_23_8 m_Speed; // in units per second + fixed m_Speed; // in units per second entity_pos_t m_Radius; // Dynamic state: @@ -138,12 +138,12 @@ public: { case MT_Update: { - CFixed_23_8 dt = static_cast (msg).turnLength; + fixed dt = static_cast (msg).turnLength; if (m_State == STOPPING) { m_State = IDLE; - CMessageMotionChanged msg(CFixed_23_8::FromInt(0)); + CMessageMotionChanged msg(fixed::Zero()); context.GetComponentManager().PostMessage(GetEntityId(), msg); } @@ -160,7 +160,7 @@ public: } } - virtual CFixed_23_8 GetSpeed() + virtual fixed GetSpeed() { return m_Speed; } @@ -191,7 +191,7 @@ private: /** * Do the per-turn movement and other updates */ - void Move(CFixed_23_8 dt); + void Move(fixed dt); void StopAndFaceGoal(CFixedVector2D pos); @@ -276,7 +276,7 @@ bool CCmpUnitMotion::CheckMovement(CFixedVector2D pos, CFixedVector2D target) return true; } -void CCmpUnitMotion::Move(CFixed_23_8 dt) +void CCmpUnitMotion::Move(fixed dt) { PROFILE("Move"); @@ -292,7 +292,7 @@ void CCmpUnitMotion::Move(CFixed_23_8 dt) // We want to move (at most) m_Speed*dt units from pos towards the next waypoint - while (dt > CFixed_23_8::FromInt(0)) + while (dt > fixed::Zero()) { CFixedVector2D target(m_ShortTargetX, m_ShortTargetZ); CFixedVector2D offset = target - pos; @@ -302,10 +302,10 @@ void CCmpUnitMotion::Move(CFixed_23_8 dt) cmpPosition->TurnTo(angle); // Work out how far we can travel in dt - CFixed_23_8 maxdist = m_Speed.Multiply(dt); + fixed maxdist = m_Speed.Multiply(dt); // If the target is close, we can move there directly - CFixed_23_8 offsetLength = offset.Length(); + fixed offsetLength = offset.Length(); if (offsetLength <= maxdist) { if (!CheckMovement(pos, target)) diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp index d0ad5ce83f..a60ed0e232 100644 --- a/source/simulation2/components/CCmpVisualActor.cpp +++ b/source/simulation2/components/CCmpVisualActor.cpp @@ -230,7 +230,7 @@ public: m_Unit->SetAnimationSync(actiontime, repeattime); } - virtual void SetShadingColour(CFixed_23_8 r, CFixed_23_8 g, CFixed_23_8 b, CFixed_23_8 a) + virtual void SetShadingColour(fixed r, fixed g, fixed b, fixed a) { if (!m_Unit) return; diff --git a/source/simulation2/components/ICmpProjectileManager.cpp b/source/simulation2/components/ICmpProjectileManager.cpp index 8365cb0a43..f0bc5a552d 100644 --- a/source/simulation2/components/ICmpProjectileManager.cpp +++ b/source/simulation2/components/ICmpProjectileManager.cpp @@ -22,6 +22,6 @@ #include "simulation2/system/InterfaceScripted.h" BEGIN_INTERFACE_WRAPPER(ProjectileManager) -DEFINE_INTERFACE_METHOD_4("LaunchProjectileAtEntity", void, ICmpProjectileManager, LaunchProjectileAtEntity, entity_id_t, entity_id_t, CFixed_23_8, CFixed_23_8) -DEFINE_INTERFACE_METHOD_4("LaunchProjectileAtPoint", void, ICmpProjectileManager, LaunchProjectileAtPoint, entity_id_t, CFixedVector3D, CFixed_23_8, CFixed_23_8) +DEFINE_INTERFACE_METHOD_4("LaunchProjectileAtEntity", void, ICmpProjectileManager, LaunchProjectileAtEntity, entity_id_t, entity_id_t, fixed, fixed) +DEFINE_INTERFACE_METHOD_4("LaunchProjectileAtPoint", void, ICmpProjectileManager, LaunchProjectileAtPoint, entity_id_t, CFixedVector3D, fixed, fixed) END_INTERFACE_WRAPPER(ProjectileManager) diff --git a/source/simulation2/components/ICmpProjectileManager.h b/source/simulation2/components/ICmpProjectileManager.h index 434226f0d8..0b80b16466 100644 --- a/source/simulation2/components/ICmpProjectileManager.h +++ b/source/simulation2/components/ICmpProjectileManager.h @@ -38,7 +38,7 @@ public: * @param speed horizontal speed in m/s * @param gravity gravitational acceleration in m/s^2 (determines the height of the ballistic curve) */ - virtual void LaunchProjectileAtEntity(entity_id_t source, entity_id_t target, CFixed_23_8 speed, CFixed_23_8 gravity) = 0; + virtual void LaunchProjectileAtEntity(entity_id_t source, entity_id_t target, fixed speed, fixed gravity) = 0; /** * Launch a projectile from entity @p source to point @p target. @@ -47,7 +47,7 @@ public: * @param speed horizontal speed in m/s * @param gravity gravitational acceleration in m/s^2 (determines the height of the ballistic curve) */ - virtual void LaunchProjectileAtPoint(entity_id_t source, CFixedVector3D target, CFixed_23_8 speed, CFixed_23_8 gravity) = 0; + virtual void LaunchProjectileAtPoint(entity_id_t source, CFixedVector3D target, fixed speed, fixed gravity) = 0; DECLARE_INTERFACE_TYPE(ProjectileManager) }; diff --git a/source/simulation2/components/ICmpUnitMotion.cpp b/source/simulation2/components/ICmpUnitMotion.cpp index 5072448433..5668235453 100644 --- a/source/simulation2/components/ICmpUnitMotion.cpp +++ b/source/simulation2/components/ICmpUnitMotion.cpp @@ -25,6 +25,6 @@ BEGIN_INTERFACE_WRAPPER(UnitMotion) DEFINE_INTERFACE_METHOD_2("MoveToPoint", bool, ICmpUnitMotion, MoveToPoint, entity_pos_t, entity_pos_t) DEFINE_INTERFACE_METHOD_3("IsInAttackRange", bool, ICmpUnitMotion, IsInAttackRange, entity_id_t, entity_pos_t, entity_pos_t) DEFINE_INTERFACE_METHOD_3("MoveToAttackRange", bool, ICmpUnitMotion, MoveToAttackRange, entity_id_t, entity_pos_t, entity_pos_t) -DEFINE_INTERFACE_METHOD_0("GetSpeed", CFixed_23_8, ICmpUnitMotion, GetSpeed) +DEFINE_INTERFACE_METHOD_0("GetSpeed", fixed, ICmpUnitMotion, GetSpeed) DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpUnitMotion, SetDebugOverlay, bool) END_INTERFACE_WRAPPER(UnitMotion) diff --git a/source/simulation2/components/ICmpUnitMotion.h b/source/simulation2/components/ICmpUnitMotion.h index 44aec163b2..c361c96c67 100644 --- a/source/simulation2/components/ICmpUnitMotion.h +++ b/source/simulation2/components/ICmpUnitMotion.h @@ -61,9 +61,9 @@ public: virtual bool MoveToAttackRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange) = 0; /** - * Get the default speed that this unit will have when walking. + * Get the default speed that this unit will have when walking, in metres per second. */ - virtual CFixed_23_8 GetSpeed() = 0; + virtual fixed GetSpeed() = 0; /** * Toggle the rendering of debug info. diff --git a/source/simulation2/components/ICmpVisual.cpp b/source/simulation2/components/ICmpVisual.cpp index 98809bd932..2ecba70a7d 100644 --- a/source/simulation2/components/ICmpVisual.cpp +++ b/source/simulation2/components/ICmpVisual.cpp @@ -24,5 +24,5 @@ BEGIN_INTERFACE_WRAPPER(Visual) DEFINE_INTERFACE_METHOD_4("SelectAnimation", void, ICmpVisual, SelectAnimation, std::string, bool, float, std::wstring) DEFINE_INTERFACE_METHOD_2("SetAnimationSync", void, ICmpVisual, SetAnimationSync, float, float) -DEFINE_INTERFACE_METHOD_4("SetShadingColour", void, ICmpVisual, SetShadingColour, CFixed_23_8, CFixed_23_8, CFixed_23_8, CFixed_23_8) +DEFINE_INTERFACE_METHOD_4("SetShadingColour", void, ICmpVisual, SetShadingColour, fixed, fixed, fixed, fixed) END_INTERFACE_WRAPPER(Visual) diff --git a/source/simulation2/components/ICmpVisual.h b/source/simulation2/components/ICmpVisual.h index d5628d87e6..3a9c0fc577 100644 --- a/source/simulation2/components/ICmpVisual.h +++ b/source/simulation2/components/ICmpVisual.h @@ -82,7 +82,7 @@ public: * @param b blue component, expected range [0, 1] * @param a alpha component, expected range [0, 1] */ - virtual void SetShadingColour(CFixed_23_8 r, CFixed_23_8 g, CFixed_23_8 b, CFixed_23_8 a) = 0; + virtual void SetShadingColour(fixed r, fixed g, fixed b, fixed a) = 0; DECLARE_INTERFACE_TYPE(Visual) }; diff --git a/source/simulation2/components/tests/test_Position.h b/source/simulation2/components/tests/test_Position.h index 773401b459..7c6447c7f3 100644 --- a/source/simulation2/components/tests/test_Position.h +++ b/source/simulation2/components/tests/test_Position.h @@ -32,7 +32,7 @@ public: static CFixedVector3D fixedvec(int x, int y, int z) { - return CFixedVector3D(CFixed_23_8::FromInt(x), CFixed_23_8::FromInt(y), CFixed_23_8::FromInt(z)); + return CFixedVector3D(fixed::FromInt(x), fixed::FromInt(y), fixed::FromInt(z)); } void test_basic() diff --git a/source/simulation2/helpers/Geometry.cpp b/source/simulation2/helpers/Geometry.cpp index 918484a2fb..392cf799bd 100644 --- a/source/simulation2/helpers/Geometry.cpp +++ b/source/simulation2/helpers/Geometry.cpp @@ -27,10 +27,10 @@ using namespace Geometry; bool Geometry::PointIsInSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize) { - CFixed_23_8 du = point.Dot(u); + fixed du = point.Dot(u); if (-halfSize.X <= du && du <= halfSize.X) { - CFixed_23_8 dv = point.Dot(v); + fixed dv = point.Dot(v); if (-halfSize.Y <= dv && dv <= halfSize.Y) return true; } @@ -45,7 +45,7 @@ CFixedVector2D Geometry::GetHalfBoundingBox(CFixedVector2D u, CFixedVector2D v, ); } -Geometry::fixed Geometry::DistanceToSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize) +fixed Geometry::DistanceToSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize) { /* * Relative to its own coordinate system, we have a square like: diff --git a/source/simulation2/helpers/Geometry.h b/source/simulation2/helpers/Geometry.h index cea3378f9f..6dcbc57709 100644 --- a/source/simulation2/helpers/Geometry.h +++ b/source/simulation2/helpers/Geometry.h @@ -30,8 +30,6 @@ class CFixedVector2D; namespace Geometry { -typedef CFixed_23_8 fixed; - bool PointIsInSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize); CFixedVector2D GetHalfBoundingBox(CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize); diff --git a/source/simulation2/helpers/Position.h b/source/simulation2/helpers/Position.h index 71fef07ed5..0f58af762d 100644 --- a/source/simulation2/helpers/Position.h +++ b/source/simulation2/helpers/Position.h @@ -33,12 +33,11 @@ /** * Positions and distances (measured in metres) */ -typedef CFixed_23_8 entity_pos_t; +typedef CFixed_15_16 entity_pos_t; /** * Rotations (measured in radians) */ -typedef CFixed_23_8 entity_angle_t; -// TODO: use a type with more precision +typedef CFixed_15_16 entity_angle_t; #endif // INCLUDED_POSITION diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp index 284bc30fb6..d7b8d8294a 100644 --- a/source/simulation2/scripting/EngineScriptConversions.cpp +++ b/source/simulation2/scripting/EngineScriptConversions.cpp @@ -171,17 +171,17 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, CColor const& v return OBJECT_TO_JSVAL(obj); } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CFixed_23_8& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, fixed& out) { jsdouble ret; if (!JS_ValueToNumber(cx, v, &ret)) return false; - out = CFixed_23_8::FromDouble(ret); + out = fixed::FromDouble(ret); // TODO: ought to check that this conversion is consistent and portable return true; } -template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const CFixed_23_8& val) +template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const fixed& val) { jsval rval = JSVAL_VOID; JS_NewNumberValue(cx, val.ToDouble(), &rval); // ignore return value diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp index dcafbb1ecb..7643ba2e56 100644 --- a/source/simulation2/scripting/MessageTypeConversions.cpp +++ b/source/simulation2/scripting/MessageTypeConversions.cpp @@ -74,7 +74,7 @@ jsval CMessageUpdate::ToJSVal(ScriptInterface& scriptInterface) const CMessage* CMessageUpdate::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); - GET_MSG_PROPERTY(CFixed_23_8, turnLength); + GET_MSG_PROPERTY(fixed, turnLength); return new CMessageUpdate(turnLength); } @@ -168,7 +168,7 @@ jsval CMessageMotionChanged::ToJSVal(ScriptInterface& scriptInterface) const CMessage* CMessageMotionChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val) { FROMJSVAL_SETUP(); - GET_MSG_PROPERTY(CFixed_23_8, speed); + GET_MSG_PROPERTY(fixed, speed); return new CMessageMotionChanged(speed); } diff --git a/source/simulation2/serialization/BinarySerializer.cpp b/source/simulation2/serialization/BinarySerializer.cpp index 1c552a67e8..18f794532c 100644 --- a/source/simulation2/serialization/BinarySerializer.cpp +++ b/source/simulation2/serialization/BinarySerializer.cpp @@ -80,7 +80,7 @@ void CBinarySerializer::PutNumber(const char* name, double value) Put(name, (const u8*)&value, sizeof(double)); } -void CBinarySerializer::PutNumber(const char* name, CFixed_23_8 value) +void CBinarySerializer::PutNumber(const char* name, fixed value) { PutNumber(name, value.GetInternalValue()); } diff --git a/source/simulation2/serialization/BinarySerializer.h b/source/simulation2/serialization/BinarySerializer.h index 01080e6306..d5aa35bd94 100644 --- a/source/simulation2/serialization/BinarySerializer.h +++ b/source/simulation2/serialization/BinarySerializer.h @@ -39,7 +39,7 @@ protected: virtual void PutNumber(const char* name, uint32_t value); virtual void PutNumber(const char* name, float value); virtual void PutNumber(const char* name, double value); - virtual void PutNumber(const char* name, CFixed_23_8 value); + virtual void PutNumber(const char* name, fixed value); virtual void PutBool(const char* name, bool value); virtual void PutString(const char* name, const std::string& value); virtual void PutScriptVal(const char* name, jsval value); diff --git a/source/simulation2/serialization/DebugSerializer.cpp b/source/simulation2/serialization/DebugSerializer.cpp index 38ed50c7bc..69e53a8802 100644 --- a/source/simulation2/serialization/DebugSerializer.cpp +++ b/source/simulation2/serialization/DebugSerializer.cpp @@ -102,7 +102,7 @@ void CDebugSerializer::PutNumber(const char* name, double value) m_Stream << INDENT << name << ": " << canonfloat(value) << "\n"; } -void CDebugSerializer::PutNumber(const char* name, CFixed_23_8 value) +void CDebugSerializer::PutNumber(const char* name, fixed value) { m_Stream << INDENT << name << ": " << canonfloat(value.ToDouble()) << "\n"; } diff --git a/source/simulation2/serialization/DebugSerializer.h b/source/simulation2/serialization/DebugSerializer.h index 68c8add748..00c9f3147b 100644 --- a/source/simulation2/serialization/DebugSerializer.h +++ b/source/simulation2/serialization/DebugSerializer.h @@ -46,7 +46,7 @@ protected: virtual void PutNumber(const char* name, uint32_t value); virtual void PutNumber(const char* name, float value); virtual void PutNumber(const char* name, double value); - virtual void PutNumber(const char* name, CFixed_23_8 value); + virtual void PutNumber(const char* name, fixed value); virtual void PutBool(const char* name, bool value); virtual void PutString(const char* name, const std::string& value); virtual void PutScriptVal(const char* name, jsval value); diff --git a/source/simulation2/serialization/IDeserializer.cpp b/source/simulation2/serialization/IDeserializer.cpp index 3a7b2ff7b3..6418f88c0c 100644 --- a/source/simulation2/serialization/IDeserializer.cpp +++ b/source/simulation2/serialization/IDeserializer.cpp @@ -83,7 +83,7 @@ void IDeserializer::NumberDouble_Unbounded(double& out) Get((u8*)&out, sizeof(double)); } -void IDeserializer::NumberFixed_Unbounded(CFixed_23_8& out) +void IDeserializer::NumberFixed_Unbounded(fixed& out) { int32_t n; NumberI32_Unbounded(n); diff --git a/source/simulation2/serialization/IDeserializer.h b/source/simulation2/serialization/IDeserializer.h index b11ac1c6d4..8da225bbd8 100644 --- a/source/simulation2/serialization/IDeserializer.h +++ b/source/simulation2/serialization/IDeserializer.h @@ -45,7 +45,7 @@ public: virtual void NumberU32_Unbounded(uint32_t& out); virtual void NumberFloat_Unbounded(float& out); virtual void NumberDouble_Unbounded(double& out); - virtual void NumberFixed_Unbounded(CFixed_23_8& out); + virtual void NumberFixed_Unbounded(fixed& out); virtual void Bool(bool& out); virtual void StringASCII(std::string& out, uint32_t minlength, uint32_t maxlength); virtual void String(std::wstring& out, uint32_t minlength, uint32_t maxlength); diff --git a/source/simulation2/serialization/ISerializer.cpp b/source/simulation2/serialization/ISerializer.cpp index 30ae07d259..89b46f85b0 100644 --- a/source/simulation2/serialization/ISerializer.cpp +++ b/source/simulation2/serialization/ISerializer.cpp @@ -71,7 +71,7 @@ void ISerializer::NumberDouble_Unbounded(const char* name, double value) PutNumber(name, value); } -void ISerializer::NumberFixed_Unbounded(const char* name, CFixed_23_8 value) +void ISerializer::NumberFixed_Unbounded(const char* name, fixed value) { PutNumber(name, value); } diff --git a/source/simulation2/serialization/ISerializer.h b/source/simulation2/serialization/ISerializer.h index 37a03c01c4..60668bdd1a 100644 --- a/source/simulation2/serialization/ISerializer.h +++ b/source/simulation2/serialization/ISerializer.h @@ -149,7 +149,7 @@ public: void NumberU32_Unbounded(const char* name, uint32_t value); ///< @copydoc NumberU8_Unbounded void NumberFloat_Unbounded(const char* name, float value); ///< @copydoc NumberU8_Unbounded void NumberDouble_Unbounded(const char* name, double value); ///< @copydoc NumberU8_Unbounded - void NumberFixed_Unbounded(const char* name, CFixed_23_8 value); ///< @copydoc NumberU8_Unbounded + void NumberFixed_Unbounded(const char* name, fixed value); ///< @copydoc NumberU8_Unbounded /** * Serialize a boolean. @@ -205,7 +205,7 @@ protected: virtual void PutNumber(const char* name, uint32_t value) = 0; virtual void PutNumber(const char* name, float value) = 0; virtual void PutNumber(const char* name, double value) = 0; - virtual void PutNumber(const char* name, CFixed_23_8 value) = 0; + virtual void PutNumber(const char* name, fixed value) = 0; virtual void PutBool(const char* name, bool value) = 0; virtual void PutString(const char* name, const std::string& value) = 0; virtual void PutScriptVal(const char* name, jsval value) = 0; diff --git a/source/simulation2/system/ComponentTest.h b/source/simulation2/system/ComponentTest.h index f69966844b..3f7b4ce660 100644 --- a/source/simulation2/system/ComponentTest.h +++ b/source/simulation2/system/ComponentTest.h @@ -164,12 +164,12 @@ public: virtual CFixedVector3D CalcNormal(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) { - return CFixedVector3D(CFixed_23_8::FromInt(0), CFixed_23_8::FromInt(1), CFixed_23_8::FromInt(0)); + return CFixedVector3D(fixed::FromInt(0), fixed::FromInt(1), fixed::FromInt(0)); } virtual entity_pos_t GetGroundLevel(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) { - return CFixed_23_8::FromInt(50); + return entity_pos_t::FromInt(50); } virtual float GetGroundLevel(float UNUSED(x), float UNUSED(z)) diff --git a/source/simulation2/system/ParamNode.cpp b/source/simulation2/system/ParamNode.cpp index ac385264e4..4735dd5c64 100644 --- a/source/simulation2/system/ParamNode.cpp +++ b/source/simulation2/system/ParamNode.cpp @@ -19,6 +19,7 @@ #include "ParamNode.h" +#include "ps/CStr.h" #include "ps/XML/Xeromyces.h" #include @@ -135,14 +136,9 @@ int CParamNode::ToInt() const return ret; } -CFixed_23_8 CParamNode::ToFixed() const +fixed CParamNode::ToFixed() const { - double ret = 0.0; - std::wstringstream strm; - strm << m_Value; - strm >> ret; - return CFixed_23_8::FromDouble(ret); - // TODO: this shouldn't use floating point types + return fixed::FromString(CStrW(m_Value)); } bool CParamNode::ToBool() const diff --git a/source/simulation2/system/ParamNode.h b/source/simulation2/system/ParamNode.h index c56b90b881..7781fe5065 100644 --- a/source/simulation2/system/ParamNode.h +++ b/source/simulation2/system/ParamNode.h @@ -151,7 +151,7 @@ public: /** * Parses the content of this node as a fixed-point number */ - CFixed_23_8 ToFixed() const; + fixed ToFixed() const; /** * Parses the content of this node as a boolean ("true" == true, anything else == false) diff --git a/source/simulation2/tests/test_ComponentManager.h b/source/simulation2/tests/test_ComponentManager.h index f816bb749e..c18c9392b7 100644 --- a/source/simulation2/tests/test_ComponentManager.h +++ b/source/simulation2/tests/test_ComponentManager.h @@ -155,7 +155,7 @@ public: man.AddComponent(ent4, CID_Test2A, noParam); CMessageTurnStart msg1; - CMessageUpdate msg2(CFixed_23_8::FromInt(100)); + CMessageUpdate msg2(fixed::FromInt(100)); CMessageInterpolate msg3(0, 0); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000); @@ -252,7 +252,7 @@ public: TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent3, IID_Test2))->GetX(), 201000); CMessageTurnStart msg1; - CMessageUpdate msg2(CFixed_23_8::FromInt(25)); + CMessageUpdate msg2(fixed::FromInt(25)); man.BroadcastMessage(msg1); diff --git a/source/simulation2/tests/test_Serializer.h b/source/simulation2/tests/test_Serializer.h index 7a0d778e36..38c069fcb0 100644 --- a/source/simulation2/tests/test_Serializer.h +++ b/source/simulation2/tests/test_Serializer.h @@ -44,7 +44,7 @@ public: serialize.NumberU32_Unbounded("u32", (unsigned)-123); serialize.NumberFloat_Unbounded("float", 1e+30f); serialize.NumberDouble_Unbounded("double", 1e+300); - serialize.NumberFixed_Unbounded("fixed", CFixed_23_8::FromFloat(1234.5f)); + serialize.NumberFixed_Unbounded("fixed", fixed::FromFloat(1234.5f)); serialize.Bool("t", true); serialize.Bool("f", false); @@ -93,11 +93,11 @@ public: serialize.NumberDouble_Unbounded("x", 1e-10); serialize.NumberDouble_Unbounded("x", 1e100); serialize.NumberDouble_Unbounded("x", 1e-100); - serialize.NumberFixed_Unbounded("x", CFixed_23_8::FromDouble(1e6)); + serialize.NumberFixed_Unbounded("x", fixed::FromDouble(1e4)); TS_ASSERT_STR_EQUALS(stream.str(), "x: 10000\nx: 0.0001\nx: 100000\nx: 1e-05\nx: 1e+06\nx: 1e-06\nx: 1e+10\nx: 1e-10\n" "x: 10000\nx: 0.0001\nx: 100000\nx: 1e-05\nx: 1e+06\nx: 1e-06\nx: 1e+10\nx: 1e-10\nx: 1e+100\nx: 1e-100\n" - "x: 1e+06\n" + "x: 10000\n" ); } @@ -169,7 +169,7 @@ public: uint32_t u32v; float flt; double dbl; - CFixed_23_8 fixed; + fixed fxd; bool bl; std::string str; std::wstring wstr; @@ -185,8 +185,8 @@ public: TS_ASSERT_EQUALS(flt, 1e+30f); deserialize.NumberDouble_Unbounded(dbl); TS_ASSERT_EQUALS(dbl, 1e+300); - deserialize.NumberFixed_Unbounded(fixed); - TS_ASSERT_EQUALS(fixed.ToDouble(), 1234.5); + deserialize.NumberFixed_Unbounded(fxd); + TS_ASSERT_EQUALS(fxd.ToDouble(), 1234.5); deserialize.Bool(bl); TS_ASSERT_EQUALS(bl, true); diff --git a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp index 01cf7b0c81..5076afbb11 100644 --- a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp @@ -921,7 +921,7 @@ BEGIN_COMMAND(RotateObject) if (cmpPos.null()) return; - cmpPos->SetYRotation(CFixed_23_8::FromFloat(angle)); + cmpPos->SetYRotation(entity_angle_t::FromFloat(angle)); } else {