1
0
forked from 0ad/0ad

Switch everything to 15.16-bit precision fixeds, to allow more accurate unit vectors and angles.

This was SVN commit r7497.
This commit is contained in:
Ykkrosh 2010-05-02 20:32:37 +00:00
parent ab45b4c787
commit f33706bf8b
48 changed files with 479 additions and 263 deletions

View File

@ -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))));
}
// <orientation>
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<ICmpOwnership> 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));
}
}
}

View File

@ -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);
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -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 ;

View File

@ -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()

View File

@ -172,7 +172,7 @@ std::vector<entity_id_t> 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)

View File

@ -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()));
}

View File

@ -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<typename T, T max_t, int total_bits, int int_bits, int fract_bits_, int fract_pow2>
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<T>(scaled));
}
static CFixed FromDouble(double n)
{
if (!isfinite(n))
@ -137,14 +139,19 @@ public:
return CFixed(round_away_from_zero<T>(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<i32, (i32)0x7fffffff, 32, 23, 8, 256> CFixed_23_8;
typedef CFixed<i32, (i32)0x7fffffff, 32, 15, 16, 65536> 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

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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);
}
};

View File

@ -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()

View File

@ -113,10 +113,10 @@ public:
convert_to<const char*>("test", "\"test\"");
convert_to<const char*>(s1.c_str(), "\"t\"");
roundtrip<CFixed_23_8>(CFixed_23_8::FromInt(0), "0");
roundtrip<CFixed_23_8>(CFixed_23_8::FromInt(123), "123");
roundtrip<CFixed_23_8>(CFixed_23_8::FromInt(-123), "-123");
roundtrip<CFixed_23_8>(CFixed_23_8::FromDouble(123.25), "123.25");
roundtrip<fixed>(fixed::FromInt(0), "0");
roundtrip<fixed>(fixed::FromInt(123), "123");
roundtrip<fixed>(fixed::FromInt(-123), "-123");
roundtrip<fixed>(fixed::FromDouble(123.25), "123.25");
}
void test_integers()

View File

@ -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

View File

@ -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;

View File

@ -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<ICmpPosition> 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
}
}
}

View File

@ -72,17 +72,17 @@ public:
{
case MT_Update:
{
CFixed_23_8 dt = static_cast<const CMessageUpdate&> (msg).turnLength;
fixed dt = static_cast<const CMessageUpdate&> (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<ICmpPosition> cmpPosition(context, GetEntityId());
if (cmpPosition.null())

View File

@ -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);

View File

@ -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<std::pair<u16, u16>, 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();

View File

@ -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<Projectile> 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

View File

@ -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<const CMessageUpdate&> (msg).turnLength;
fixed dt = static_cast<const CMessageUpdate&> (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))

View File

@ -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;

View File

@ -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)

View File

@ -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)
};

View File

@ -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)

View File

@ -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.

View File

@ -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)

View File

@ -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)
};

View File

@ -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()

View File

@ -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:

View File

@ -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);

View File

@ -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

View File

@ -171,17 +171,17 @@ template<> jsval ScriptInterface::ToJSVal<CColor>(JSContext* cx, CColor const& v
return OBJECT_TO_JSVAL(obj);
}
template<> bool ScriptInterface::FromJSVal<CFixed_23_8>(JSContext* cx, jsval v, CFixed_23_8& out)
template<> bool ScriptInterface::FromJSVal<fixed>(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<CFixed_23_8>(JSContext* cx, const CFixed_23_8& val)
template<> jsval ScriptInterface::ToJSVal<fixed>(JSContext* cx, const fixed& val)
{
jsval rval = JSVAL_VOID;
JS_NewNumberValue(cx, val.ToDouble(), &rval); // ignore return value

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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);

View File

@ -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";
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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))

View File

@ -19,6 +19,7 @@
#include "ParamNode.h"
#include "ps/CStr.h"
#include "ps/XML/Xeromyces.h"
#include <sstream>
@ -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

View File

@ -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)

View File

@ -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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000);
@ -252,7 +252,7 @@ public:
TS_ASSERT_EQUALS(static_cast<ICmpTest2*> (man.QueryInterface(ent3, IID_Test2))->GetX(), 201000);
CMessageTurnStart msg1;
CMessageUpdate msg2(CFixed_23_8::FromInt(25));
CMessageUpdate msg2(fixed::FromInt(25));
man.BroadcastMessage(msg1);

View File

@ -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);

View File

@ -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
{