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:
parent
ab45b4c787
commit
f33706bf8b
@ -848,20 +848,18 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time)
|
|||||||
{
|
{
|
||||||
XMBAttributeList attrs = setting.GetAttributes();
|
XMBAttributeList attrs = setting.GetAttributes();
|
||||||
Position = CFixedVector3D(
|
Position = CFixedVector3D(
|
||||||
CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_x)).ToFloat()),
|
fixed::FromString(CStr(attrs.GetNamedItem(at_x))),
|
||||||
CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_y)).ToFloat()),
|
fixed::FromString(CStr(attrs.GetNamedItem(at_y))),
|
||||||
CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_z)).ToFloat()));
|
fixed::FromString(CStr(attrs.GetNamedItem(at_z))));
|
||||||
// TODO: shouldn't use floats here
|
|
||||||
}
|
}
|
||||||
// <orientation>
|
// <orientation>
|
||||||
else if (element_name == el_orientation)
|
else if (element_name == el_orientation)
|
||||||
{
|
{
|
||||||
XMBAttributeList attrs = setting.GetAttributes();
|
XMBAttributeList attrs = setting.GetAttributes();
|
||||||
Orientation = CFixedVector3D(
|
Orientation = CFixedVector3D(
|
||||||
CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_x)).ToFloat()),
|
fixed::FromString(CStr(attrs.GetNamedItem(at_x))),
|
||||||
CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_y)).ToFloat()),
|
fixed::FromString(CStr(attrs.GetNamedItem(at_y))),
|
||||||
CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_z)).ToFloat()));
|
fixed::FromString(CStr(attrs.GetNamedItem(at_z))));
|
||||||
// TODO: shouldn't use floats here
|
|
||||||
// TODO: what happens if some attributes are missing?
|
// TODO: what happens if some attributes are missing?
|
||||||
}
|
}
|
||||||
else
|
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 x = entity_pos_t::FromFloat(Position.X);
|
||||||
entity_pos_t z = entity_pos_t::FromFloat(Position.Z);
|
entity_pos_t z = entity_pos_t::FromFloat(Position.Z);
|
||||||
cmpPos->JumpTo(x, 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);
|
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 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);
|
entity_pos_t z = entity_pos_t::FromFloat(Position.Z);
|
||||||
cmpPos->JumpTo(x, z);
|
cmpPos->JumpTo(x, z);
|
||||||
cmpPos->SetYRotation(CFixed_23_8::FromFloat(Orientation));
|
cmpPos->SetYRotation(entity_angle_t::FromFloat(Orientation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,9 +151,9 @@ void CTerrain::CalcPositionFixed(ssize_t i, ssize_t j, CFixedVector3D& pos) cons
|
|||||||
height = m_Heightmap[j*m_MapSize + i];
|
height = m_Heightmap[j*m_MapSize + i];
|
||||||
else
|
else
|
||||||
height = 0;
|
height = 0;
|
||||||
pos.X = CFixed_23_8::FromInt(i)*(int)CELL_SIZE;
|
pos.X = fixed::FromInt(i) * (int)CELL_SIZE;
|
||||||
pos.Y = CFixed_23_8::FromInt(height)/(int)HEIGHT_UNITS_PER_METRE;
|
pos.Y = fixed::FromInt(height) / (int)HEIGHT_UNITS_PER_METRE;
|
||||||
pos.Z = CFixed_23_8::FromInt(j)*(int)CELL_SIZE;
|
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)));
|
+ 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)
|
// 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 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 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 fixed xf = clamp((x / (int)CELL_SIZE) - fixed::FromInt(xi), fixed::Zero(), one);
|
||||||
const CFixed_23_8 zf = clamp((z / (int)CELL_SIZE) - CFixed_23_8::FromInt(zi), CFixed_23_8::FromInt(0), one);
|
const fixed zf = clamp((z / (int)CELL_SIZE) - fixed::FromInt(zi), fixed::Zero(), one);
|
||||||
|
|
||||||
u16 h00 = m_Heightmap[zi*m_MapSize + xi];
|
u16 h00 = m_Heightmap[zi*m_MapSize + xi];
|
||||||
u16 h01 = m_Heightmap[(zi+1)*m_MapSize + xi];
|
u16 h01 = m_Heightmap[(zi+1)*m_MapSize + xi];
|
||||||
u16 h10 = m_Heightmap[zi*m_MapSize + (xi+1)];
|
u16 h10 = m_Heightmap[zi*m_MapSize + (xi+1)];
|
||||||
u16 h11 = m_Heightmap[(zi+1)*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
|
// Linearly interpolate
|
||||||
return ((one - zf).Multiply((one - xf) * h00 + xf * h10)
|
return ((one - zf).Multiply(xf1 * h00 + xf0 * h10)
|
||||||
+ zf.Multiply((one - xf) * h01 + xf * h11)) / (int)HEIGHT_UNITS_PER_METRE;
|
+ zf.Multiply(xf1 * h01 + xf0 * h11)) / (int)(HEIGHT_UNITS_PER_METRE / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -40,7 +40,7 @@ class CFixedVector3D;
|
|||||||
const ssize_t CELL_SIZE = 4;
|
const ssize_t CELL_SIZE = 4;
|
||||||
|
|
||||||
/// number of u16 height units per metre
|
/// 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
|
/// metres per u16 height unit
|
||||||
const float HEIGHT_SCALE = 1.f / HEIGHT_UNITS_PER_METRE;
|
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 GetVertexGroundLevel(ssize_t i, ssize_t j) const;
|
||||||
float GetExactGroundLevel(float x, float z) 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 GetExactGroundLevel(const CVector2D& v) const;
|
||||||
|
|
||||||
float GetSlope(float x, float z) const ;
|
float GetSlope(float x, float z) const ;
|
||||||
|
@ -100,25 +100,49 @@ public:
|
|||||||
Set45Slope(terrain);
|
Set45Slope(terrain);
|
||||||
SetHighPlateau(terrain, 20);
|
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));
|
fixed ground;
|
||||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE, 0.01f);
|
|
||||||
|
|
||||||
ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(0.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE));
|
ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(0.f), fixed::FromFloat(1.5f*CELL_SIZE));
|
||||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+0.5f*CELL_SIZE, 0.01f);
|
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));
|
ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(0.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE));
|
||||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+1.5f*CELL_SIZE, 0.01f);
|
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));
|
ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(1.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE));
|
||||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+2.f*CELL_SIZE, 0.01f);
|
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));
|
ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(2.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE));
|
||||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+11.f*CELL_SIZE, 0.01f);
|
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));
|
ground = terrain.GetExactGroundLevelFixed(fixed::FromFloat(3.5f*CELL_SIZE), fixed::FromFloat(1.5f*CELL_SIZE));
|
||||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+20.f*CELL_SIZE, 0.01f);
|
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()
|
void test_CalcNormal()
|
||||||
|
@ -172,7 +172,7 @@ std::vector<entity_id_t> PickFriendlyEntitiesInRect(void* UNUSED(cbdata), int x0
|
|||||||
CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y)
|
CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y)
|
||||||
{
|
{
|
||||||
CVector3D pos = g_Game->GetView()->GetCamera()->GetWorldCoordinates(x, y, false);
|
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)
|
std::wstring SetCursor(void* UNUSED(cbdata), std::wstring name)
|
||||||
|
@ -19,32 +19,46 @@
|
|||||||
|
|
||||||
#include "Fixed.h"
|
#include "Fixed.h"
|
||||||
|
|
||||||
// Based on http://www.dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization
|
#include "ps/CStr.h"
|
||||||
CFixed_23_8 atan2_approx(CFixed_23_8 y, CFixed_23_8 x)
|
|
||||||
|
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
|
// Special case to avoid division-by-zero
|
||||||
if (x.IsZero() && y.IsZero())
|
if (x.IsZero() && y.IsZero())
|
||||||
return zero;
|
return zero;
|
||||||
|
|
||||||
CFixed_23_8 c1;
|
CFixed_15_16 c1;
|
||||||
c1.SetInternalValue(201); // pi/4 << 8
|
c1.SetInternalValue(51472); // pi/4 << 16
|
||||||
|
|
||||||
CFixed_23_8 c2;
|
CFixed_15_16 c2;
|
||||||
c2.SetInternalValue(603); // 3*pi/4 << 8
|
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)
|
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);
|
angle = c1 - c1.Multiply(r);
|
||||||
}
|
}
|
||||||
else
|
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);
|
angle = c2 - c1.Multiply(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,17 +69,15 @@ CFixed_23_8 atan2_approx(CFixed_23_8 y, CFixed_23_8 x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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
|
// 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_15_16::FromDouble(sin(a.ToDouble()));
|
||||||
|
cos_out = CFixed_15_16::FromDouble(cos(a.ToDouble()));
|
||||||
sin_out = CFixed_23_8::FromDouble(sin(a.ToDouble()));
|
|
||||||
cos_out = CFixed_23_8::FromDouble(cos(a.ToDouble()));
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
#include "lib/types.h"
|
#include "lib/types.h"
|
||||||
#include "maths/Sqrt.h"
|
#include "maths/Sqrt.h"
|
||||||
|
|
||||||
|
class CStr8;
|
||||||
|
class CStrW;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define USE_FIXED_OVERFLOW_CHECKS
|
#define USE_FIXED_OVERFLOW_CHECKS
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
@ -90,12 +93,9 @@ inline T round_away_from_zero(float value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple fixed-point number class, with no fancy features
|
* A simple fixed-point number class.
|
||||||
* 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.)
|
|
||||||
*
|
*
|
||||||
* 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>
|
template<typename T, T max_t, int total_bits, int int_bits, int fract_bits_, int fract_pow2>
|
||||||
class CFixed
|
class CFixed
|
||||||
@ -122,6 +122,7 @@ public:
|
|||||||
{
|
{
|
||||||
return CFixed(n << fract_bits);
|
return CFixed(n << fract_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CFixed FromFloat(float n)
|
static CFixed FromFloat(float n)
|
||||||
{
|
{
|
||||||
if (!isfinite(n))
|
if (!isfinite(n))
|
||||||
@ -129,6 +130,7 @@ public:
|
|||||||
float scaled = n * fract_pow2;
|
float scaled = n * fract_pow2;
|
||||||
return CFixed(round_away_from_zero<T>(scaled));
|
return CFixed(round_away_from_zero<T>(scaled));
|
||||||
}
|
}
|
||||||
|
|
||||||
static CFixed FromDouble(double n)
|
static CFixed FromDouble(double n)
|
||||||
{
|
{
|
||||||
if (!isfinite(n))
|
if (!isfinite(n))
|
||||||
@ -137,14 +139,19 @@ public:
|
|||||||
return CFixed(round_away_from_zero<T>(scaled));
|
return CFixed(round_away_from_zero<T>(scaled));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CFixed FromString(const CStr8& s);
|
||||||
|
static CFixed FromString(const CStrW& s);
|
||||||
|
|
||||||
float ToFloat() const
|
float ToFloat() const
|
||||||
{
|
{
|
||||||
return value / (float)fract_pow2;
|
return value / (float)fract_pow2;
|
||||||
}
|
}
|
||||||
|
|
||||||
double ToDouble() const
|
double ToDouble() const
|
||||||
{
|
{
|
||||||
return value / (double)fract_pow2;
|
return value / (double)fract_pow2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ToInt_RoundToZero() const
|
int ToInt_RoundToZero() const
|
||||||
{
|
{
|
||||||
if (value > 0)
|
if (value > 0)
|
||||||
@ -220,7 +227,7 @@ public:
|
|||||||
return CFixed(value * n);
|
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
|
CFixed operator/(int n) const
|
||||||
{
|
{
|
||||||
CheckDivisionOverflow(T, value, n, L"Overflow in CFixed::operator/(int n)")
|
CheckDivisionOverflow(T, value, n, L"Overflow in CFixed::operator/(int n)")
|
||||||
@ -242,6 +249,16 @@ public:
|
|||||||
return CFixed((T)t);
|
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
|
CFixed Sqrt() const
|
||||||
{
|
{
|
||||||
if (value <= 0)
|
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.
|
* Inaccurate approximation of atan2 over fixed-point numbers.
|
||||||
* Maximum error is almost 0.08 radians (4.5 degrees).
|
* 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
|
#endif // INCLUDED_FIXED
|
||||||
|
@ -23,9 +23,6 @@
|
|||||||
|
|
||||||
class CFixedVector2D
|
class CFixedVector2D
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
typedef CFixed_23_8 fixed;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fixed X, Y;
|
fixed X, Y;
|
||||||
|
|
||||||
@ -122,8 +119,6 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Normalize the vector so that length is close to 1.
|
* Normalize the vector so that length is close to 1.
|
||||||
* If length is 0, does nothing.
|
* 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()
|
void Normalize()
|
||||||
{
|
{
|
||||||
@ -141,19 +136,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void Normalize(fixed n)
|
void Normalize(fixed n)
|
||||||
{
|
{
|
||||||
if (n.IsZero())
|
|
||||||
{
|
|
||||||
X = Y = fixed::FromInt(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fixed l = Length();
|
fixed l = Length();
|
||||||
// TODO: work out whether this is giving decent precision
|
if (!l.IsZero())
|
||||||
fixed d = l / n;
|
|
||||||
if (!d.IsZero())
|
|
||||||
{
|
{
|
||||||
X = X / d;
|
X = X.MulDiv(n, l);
|
||||||
Y = Y / d;
|
Y = Y.MulDiv(n, l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,6 @@
|
|||||||
|
|
||||||
class CFixedVector3D
|
class CFixedVector3D
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
typedef CFixed_23_8 fixed;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fixed X, Y, Z;
|
fixed X, Y, Z;
|
||||||
|
|
||||||
@ -39,6 +36,12 @@ public:
|
|||||||
return (X == v.X && Y == v.Y && Z == v.Z);
|
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
|
/// Vector addition
|
||||||
CFixedVector3D operator+(const CFixedVector3D& v) const
|
CFixedVector3D operator+(const CFixedVector3D& v) const
|
||||||
{
|
{
|
||||||
@ -102,8 +105,6 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Normalize the vector so that length is close to 1.
|
* Normalize the vector so that length is close to 1.
|
||||||
* If length is 0, does nothing.
|
* 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()
|
void Normalize()
|
||||||
{
|
{
|
||||||
@ -122,20 +123,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
void Normalize(fixed n)
|
void Normalize(fixed n)
|
||||||
{
|
{
|
||||||
if (n.IsZero())
|
|
||||||
{
|
|
||||||
X = Y = Z = fixed::FromInt(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fixed l = Length();
|
fixed l = Length();
|
||||||
// TODO: work out whether this is giving decent precision
|
if (!l.IsZero())
|
||||||
fixed d = l / n;
|
|
||||||
if (!d.IsZero())
|
|
||||||
{
|
{
|
||||||
X = X / d;
|
X = X.MulDiv(n, l);
|
||||||
Y = Y / d;
|
Y = Y.MulDiv(n, l);
|
||||||
Z = Z / d;
|
Z = Z.MulDiv(n, l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2009 Wildfire Games.
|
/* Copyright (C) 2010 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -25,18 +25,18 @@ class TestFixed : public CxxTest::TestSuite
|
|||||||
public:
|
public:
|
||||||
void test_basic()
|
void test_basic()
|
||||||
{
|
{
|
||||||
CFixed_23_8 a = CFixed_23_8::FromInt(1234567);
|
fixed a = fixed::FromInt(12345);
|
||||||
TS_ASSERT_EQUALS((a + a).ToDouble(), 2469134);
|
TS_ASSERT_EQUALS((a + a).ToDouble(), 24690);
|
||||||
TS_ASSERT_EQUALS((a - a).ToDouble(), 0);
|
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 / a).ToDouble(), 1);
|
||||||
TS_ASSERT_EQUALS((a / 127).ToDouble(), 9721);
|
TS_ASSERT_EQUALS((a / 823).ToDouble(), 15);
|
||||||
TS_ASSERT_EQUALS((a * 2).ToDouble(), 2469134);
|
TS_ASSERT_EQUALS((a * 2).ToDouble(), 24690);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_FromInt()
|
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.ToFloat(), 123.0f);
|
||||||
TS_ASSERT_EQUALS(a.ToDouble(), 123.0);
|
TS_ASSERT_EQUALS(a.ToDouble(), 123.0);
|
||||||
TS_ASSERT_EQUALS(a.ToInt_RoundToZero(), 123);
|
TS_ASSERT_EQUALS(a.ToInt_RoundToZero(), 123);
|
||||||
@ -44,97 +44,95 @@ public:
|
|||||||
|
|
||||||
void test_FromFloat()
|
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.ToFloat(), 123.125f);
|
||||||
TS_ASSERT_EQUALS(a.ToDouble(), 123.125);
|
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.ToFloat(), -123.125f);
|
||||||
TS_ASSERT_EQUALS(b.ToDouble(), -123.125);
|
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);
|
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);
|
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);
|
TS_ASSERT_EQUALS(e.GetInternalValue(), (i32)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_FromDouble()
|
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.ToFloat(), 123.125f);
|
||||||
TS_ASSERT_EQUALS(a.ToDouble(), 123.125);
|
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.ToFloat(), -123.125f);
|
||||||
TS_ASSERT_EQUALS(b.ToDouble(), -123.125);
|
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);
|
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);
|
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);
|
TS_ASSERT_EQUALS(e.GetInternalValue(), (i32)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_FromFloat_Rounding()
|
void test_FromFloat_Rounding()
|
||||||
{
|
{
|
||||||
double eps = pow(2.0, -8.0);
|
double eps = pow(2.0, -16.0);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps).ToDouble(), eps);
|
TS_ASSERT_EQUALS(fixed::FromFloat(eps).ToDouble(), eps);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.5625).ToDouble(), eps);
|
TS_ASSERT_EQUALS(fixed::FromFloat(eps * 0.5625).ToDouble(), eps);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.5).ToDouble(), eps);
|
TS_ASSERT_EQUALS(fixed::FromFloat(eps * 0.5).ToDouble(), eps);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.4375).ToDouble(), 0.0);
|
TS_ASSERT_EQUALS(fixed::FromFloat(eps * 0.4375).ToDouble(), 0.0);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps).ToDouble(), -eps);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-eps).ToDouble(), -eps);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.5625).ToDouble(), -eps);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-eps * 0.5625).ToDouble(), -eps);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.5).ToDouble(), -eps);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-eps * 0.5).ToDouble(), -eps);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.4375).ToDouble(), 0.0);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-eps * 0.4375).ToDouble(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_RoundToZero()
|
void test_RoundToZero()
|
||||||
{
|
{
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.f).ToInt_RoundToZero(), 10);
|
TS_ASSERT_EQUALS(fixed::FromFloat(10.f).ToInt_RoundToZero(), 10);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.1f).ToInt_RoundToZero(), 10);
|
TS_ASSERT_EQUALS(fixed::FromFloat(10.1f).ToInt_RoundToZero(), 10);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.5f).ToInt_RoundToZero(), 10);
|
TS_ASSERT_EQUALS(fixed::FromFloat(10.5f).ToInt_RoundToZero(), 10);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.99f).ToInt_RoundToZero(), 10);
|
TS_ASSERT_EQUALS(fixed::FromFloat(10.99f).ToInt_RoundToZero(), 10);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(0.1f).ToInt_RoundToZero(), 0);
|
TS_ASSERT_EQUALS(fixed::FromFloat(0.1f).ToInt_RoundToZero(), 0);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(0.0f).ToInt_RoundToZero(), 0);
|
TS_ASSERT_EQUALS(fixed::FromFloat(0.0f).ToInt_RoundToZero(), 0);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-0.1f).ToInt_RoundToZero(), 0);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-0.1f).ToInt_RoundToZero(), 0);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-0.99f).ToInt_RoundToZero(), 0);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-0.99f).ToInt_RoundToZero(), 0);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-1.0f).ToInt_RoundToZero(), -1);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-1.0f).ToInt_RoundToZero(), -1);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.0f).ToInt_RoundToZero(), -2);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-2.0f).ToInt_RoundToZero(), -2);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.5f).ToInt_RoundToZero(), -2);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-2.5f).ToInt_RoundToZero(), -2);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.99f).ToInt_RoundToZero(), -2);
|
TS_ASSERT_EQUALS(fixed::FromFloat(-2.99f).ToInt_RoundToZero(), -2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test all the arithmetic operators
|
// TODO: test all the arithmetic operators
|
||||||
|
|
||||||
void test_Sqrt()
|
void test_Sqrt()
|
||||||
{
|
{
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(1.0).Sqrt().ToDouble(), 1.0);
|
TS_ASSERT_EQUALS(fixed::FromDouble(1.0).Sqrt().ToDouble(), 1.0);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(1000000.0).Sqrt().ToDouble(), 1000.0);
|
TS_ASSERT_EQUALS(fixed::FromDouble(32400.0).Sqrt().ToDouble(), 180.0);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(0.0625).Sqrt().ToDouble(), 0.25);
|
TS_ASSERT_EQUALS(fixed::FromDouble(0.0625).Sqrt().ToDouble(), 0.25);
|
||||||
TS_ASSERT_EQUALS(CFixed_23_8::FromDouble(-1.0).Sqrt().ToDouble(), 0.0);
|
TS_ASSERT_EQUALS(fixed::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(0.0).Sqrt().ToDouble(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_Atan2()
|
void test_Atan2()
|
||||||
{
|
{
|
||||||
typedef CFixed_23_8 f;
|
|
||||||
|
|
||||||
// Special cases from atan2 man page:
|
// Special cases from atan2 man page:
|
||||||
TS_ASSERT_DELTA(atan2_approx(f::FromInt(0), f::FromInt(-1)).ToDouble(), M_PI, 0.01);
|
TS_ASSERT_DELTA(atan2_approx(fixed::FromInt(0), fixed::FromInt(-1)).ToDouble(), M_PI, 0.01);
|
||||||
TS_ASSERT_EQUALS(atan2_approx(f::FromInt(0), f::FromInt(+1)).ToDouble(), 0);
|
TS_ASSERT_EQUALS(atan2_approx(fixed::FromInt(0), fixed::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(fixed::FromInt(-1), fixed::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_DELTA(atan2_approx(fixed::FromInt(+1), fixed::FromInt(0)).ToDouble(), +M_PI_2, 0.01);
|
||||||
TS_ASSERT_EQUALS(atan2_approx(f::FromInt(0), f::FromInt(0)).ToDouble(), 0);
|
TS_ASSERT_EQUALS(atan2_approx(fixed::FromInt(0), fixed::FromInt(0)).ToDouble(), 0);
|
||||||
|
|
||||||
// Test that it approximately matches libc's atan2
|
// 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
|
// Quadrants
|
||||||
T(1, 1);
|
T(1, 1);
|
||||||
|
143
source/maths/tests/test_FixedVector2D.h
Normal file
143
source/maths/tests/test_FixedVector2D.h
Normal 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);
|
||||||
|
}
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2009 Wildfire Games.
|
/* Copyright (C) 2010 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 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.Y.ToDouble(), y); \
|
||||||
TS_ASSERT_EQUALS(v.Z.ToDouble(), z);
|
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
|
class TestFixedVector3D : public CxxTest::TestSuite
|
||||||
{
|
{
|
||||||
typedef CFixed_23_8 fixed;
|
|
||||||
public:
|
public:
|
||||||
void test_basic()
|
void test_basic()
|
||||||
{
|
{
|
||||||
@ -68,31 +72,68 @@ public:
|
|||||||
{
|
{
|
||||||
CFixedVector3D v0 (fixed::FromInt(0), fixed::FromInt(0), fixed::FromInt(0));
|
CFixedVector3D v0 (fixed::FromInt(0), fixed::FromInt(0), fixed::FromInt(0));
|
||||||
v0.Normalize();
|
v0.Normalize();
|
||||||
TS_ASSERT_EQUALS(v0.X.ToDouble(), 0.0);
|
TS_ASSERT_VEC_EQUALS(v0, 0.0, 0.0, 0.0);
|
||||||
TS_ASSERT_EQUALS(v0.Y.ToDouble(), 0.0);
|
|
||||||
TS_ASSERT_EQUALS(v0.Z.ToDouble(), 0.0);
|
|
||||||
|
|
||||||
CFixedVector3D v1 (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12));
|
CFixedVector3D v1 (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12));
|
||||||
v1.Normalize();
|
v1.Normalize();
|
||||||
TS_ASSERT_DELTA(v1.X.ToDouble(), 3.0/13.0, 0.01);
|
TS_ASSERT_VEC_DELTA(v1, 3.0/13.0, 4.0/13.0, 12.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);
|
|
||||||
|
|
||||||
fixed max;
|
fixed max;
|
||||||
max.SetInternalValue((i32)0x7fffffff);
|
max.SetInternalValue((i32)0x7fffffff);
|
||||||
CFixedVector3D v2 (max, fixed::FromInt(0), fixed::FromInt(0));
|
CFixedVector3D v2 (max, fixed::FromInt(0), fixed::FromInt(0));
|
||||||
v2.Normalize();
|
v2.Normalize();
|
||||||
TS_ASSERT_EQUALS(v2.X.ToDouble(), 1.0);
|
TS_ASSERT_VEC_EQUALS(v2, 1.0, 0.0, 0.0);
|
||||||
TS_ASSERT_EQUALS(v2.Y.ToDouble(), 0.0);
|
|
||||||
TS_ASSERT_EQUALS(v2.Z.ToDouble(), 0.0);
|
|
||||||
|
|
||||||
fixed large;
|
fixed large;
|
||||||
large.SetInternalValue((i32)((double)0x7fffffff/sqrt(3.0))+1); // largest value that shouldn't cause overflow
|
large.SetInternalValue((i32)((double)0x7fffffff/sqrt(3.0))+1); // largest value that shouldn't cause overflow
|
||||||
CFixedVector3D v3 (large, large, large);
|
CFixedVector3D v3 (large, large, large);
|
||||||
v3.Normalize();
|
v3.Normalize();
|
||||||
TS_ASSERT_DELTA(v3.X.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);
|
||||||
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);
|
|
||||||
|
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()
|
void test_Cross()
|
||||||
@ -100,9 +141,7 @@ public:
|
|||||||
CFixedVector3D v1 (fixed::FromInt(5), fixed::FromInt(6), fixed::FromInt(7));
|
CFixedVector3D v1 (fixed::FromInt(5), fixed::FromInt(6), fixed::FromInt(7));
|
||||||
CFixedVector3D v2 (fixed::FromInt(8), fixed::FromInt(9), fixed::FromInt(-10));
|
CFixedVector3D v2 (fixed::FromInt(8), fixed::FromInt(9), fixed::FromInt(-10));
|
||||||
CFixedVector3D v3 = v1.Cross(v2);
|
CFixedVector3D v3 = v1.Cross(v2);
|
||||||
TS_ASSERT_EQUALS(v3.X.ToDouble(), 6*-10 - 7*9);
|
TS_ASSERT_VEC_EQUALS(v3, 6*-10 - 7*9, 7*8 - 5*-10, 5*9 - 8*6);
|
||||||
TS_ASSERT_EQUALS(v3.Y.ToDouble(), 7*8 - 5*-10);
|
|
||||||
TS_ASSERT_EQUALS(v3.Z.ToDouble(), 5*9 - 8*6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_Dot()
|
void test_Dot()
|
||||||
|
@ -113,10 +113,10 @@ public:
|
|||||||
convert_to<const char*>("test", "\"test\"");
|
convert_to<const char*>("test", "\"test\"");
|
||||||
convert_to<const char*>(s1.c_str(), "\"t\"");
|
convert_to<const char*>(s1.c_str(), "\"t\"");
|
||||||
|
|
||||||
roundtrip<CFixed_23_8>(CFixed_23_8::FromInt(0), "0");
|
roundtrip<fixed>(fixed::FromInt(0), "0");
|
||||||
roundtrip<CFixed_23_8>(CFixed_23_8::FromInt(123), "123");
|
roundtrip<fixed>(fixed::FromInt(123), "123");
|
||||||
roundtrip<CFixed_23_8>(CFixed_23_8::FromInt(-123), "-123");
|
roundtrip<fixed>(fixed::FromInt(-123), "-123");
|
||||||
roundtrip<CFixed_23_8>(CFixed_23_8::FromDouble(123.25), "123.25");
|
roundtrip<fixed>(fixed::FromDouble(123.25), "123.25");
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_integers()
|
void test_integers()
|
||||||
|
@ -49,12 +49,12 @@ class CMessageUpdate : public CMessage
|
|||||||
public:
|
public:
|
||||||
DEFAULT_MESSAGE_IMPL(Update)
|
DEFAULT_MESSAGE_IMPL(Update)
|
||||||
|
|
||||||
CMessageUpdate(CFixed_23_8 turnLength) :
|
CMessageUpdate(fixed turnLength) :
|
||||||
turnLength(turnLength)
|
turnLength(turnLength)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CFixed_23_8 turnLength;
|
fixed turnLength;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CMessageInterpolate : public CMessage
|
class CMessageInterpolate : public CMessage
|
||||||
@ -151,12 +151,12 @@ class CMessageMotionChanged : public CMessage
|
|||||||
public:
|
public:
|
||||||
DEFAULT_MESSAGE_IMPL(MotionChanged)
|
DEFAULT_MESSAGE_IMPL(MotionChanged)
|
||||||
|
|
||||||
CMessageMotionChanged(CFixed_23_8 speed) :
|
CMessageMotionChanged(fixed speed) :
|
||||||
speed(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
|
#endif // INCLUDED_MESSAGETYPES
|
||||||
|
@ -148,7 +148,7 @@ bool CSimulation2Impl::Update(float frameTime)
|
|||||||
if (m_DeltaTime >= 0.0)
|
if (m_DeltaTime >= 0.0)
|
||||||
{
|
{
|
||||||
double turnLength = TURN_LENGTH / 1000.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;
|
m_DeltaTime -= turnLength;
|
||||||
|
|
||||||
CMessageTurnStart msgTurnStart;
|
CMessageTurnStart msgTurnStart;
|
||||||
|
@ -36,9 +36,9 @@ public:
|
|||||||
DEFAULT_COMPONENT_ALLOCATOR(Footprint)
|
DEFAULT_COMPONENT_ALLOCATOR(Footprint)
|
||||||
|
|
||||||
EShape m_Shape;
|
EShape m_Shape;
|
||||||
CFixed_23_8 m_Size0; // width/radius
|
entity_pos_t m_Size0; // width/radius
|
||||||
CFixed_23_8 m_Size1; // height/radius
|
entity_pos_t m_Size1; // height/radius
|
||||||
CFixed_23_8 m_Height;
|
entity_pos_t m_Height;
|
||||||
|
|
||||||
static std::string GetSchema()
|
static std::string GetSchema()
|
||||||
{
|
{
|
||||||
@ -90,7 +90,7 @@ public:
|
|||||||
{
|
{
|
||||||
// Error - pick some default
|
// Error - pick some default
|
||||||
m_Shape = CIRCLE;
|
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();
|
m_Height = paramNode.GetChild("Height").ToFixed();
|
||||||
@ -109,7 +109,7 @@ public:
|
|||||||
Init(context, paramNode);
|
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;
|
shape = m_Shape;
|
||||||
size0 = m_Size0;
|
size0 = m_Size0;
|
||||||
@ -124,7 +124,7 @@ public:
|
|||||||
// because the footprint might be inside the obstruction, but it hopefully gives us a nicer
|
// because the footprint might be inside the obstruction, but it hopefully gives us a nicer
|
||||||
// shape.)
|
// 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());
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
|
||||||
if (cmpPosition.null() || !cmpPosition->IsInWorld())
|
if (cmpPosition.null() || !cmpPosition->IsInWorld())
|
||||||
@ -142,14 +142,14 @@ public:
|
|||||||
// else zero
|
// else zero
|
||||||
|
|
||||||
// The spawn point should be far enough from this footprint to fit the unit, plus a little gap
|
// 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();
|
CFixedVector3D initialPos = cmpPosition->GetPosition();
|
||||||
entity_angle_t initialAngle = cmpPosition->GetRotation().Y;
|
entity_angle_t initialAngle = cmpPosition->GetRotation().Y;
|
||||||
|
|
||||||
if (m_Shape == CIRCLE)
|
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
|
// Try equally-spaced points around the circle, starting from the front and expanding outwards in alternating directions
|
||||||
const ssize_t numPoints = 31;
|
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);
|
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);
|
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
|
SkipTagObstructionFilter filter(spawned); // ignore collisions with the spawned entity
|
||||||
if (!cmpObstructionManager->TestUnitShape(filter, pos.X, pos.Z, spawnedRadius))
|
if (!cmpObstructionManager->TestUnitShape(filter, pos.X, pos.Z, spawnedRadius))
|
||||||
@ -169,7 +169,7 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CFixed_23_8 s, c;
|
fixed s, c;
|
||||||
sincos_approx(initialAngle, s, c);
|
sincos_approx(initialAngle, s, c);
|
||||||
|
|
||||||
for (size_t edge = 0; edge < 4; ++edge)
|
for (size_t edge = 0; edge < 4; ++edge)
|
||||||
@ -179,7 +179,7 @@ public:
|
|||||||
|
|
||||||
// Compute the direction and length of the current edge
|
// Compute the direction and length of the current edge
|
||||||
CFixedVector2D dir;
|
CFixedVector2D dir;
|
||||||
CFixed_23_8 sx, sy;
|
fixed sx, sy;
|
||||||
switch (edge)
|
switch (edge)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -214,7 +214,7 @@ public:
|
|||||||
|
|
||||||
SkipTagObstructionFilter filter(spawned); // ignore collisions with the spawned entity
|
SkipTagObstructionFilter filter(spawned); // ignore collisions with the spawned entity
|
||||||
if (!cmpObstructionManager->TestUnitShape(filter, pos.X, pos.Y, spawnedRadius))
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,17 +72,17 @@ public:
|
|||||||
{
|
{
|
||||||
case MT_Update:
|
case MT_Update:
|
||||||
{
|
{
|
||||||
CFixed_23_8 dt = static_cast<const CMessageUpdate&> (msg).turnLength;
|
fixed dt = static_cast<const CMessageUpdate&> (msg).turnLength;
|
||||||
Move(context, dt);
|
Move(context, dt);
|
||||||
break;
|
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());
|
CmpPtr<ICmpPosition> cmpPosition(context, GetEntityId());
|
||||||
if (cmpPosition.null())
|
if (cmpPosition.null())
|
||||||
|
@ -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)
|
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);
|
sincos_approx(a, s, c);
|
||||||
CFixedVector2D u(c, -s);
|
CFixedVector2D u(c, -s);
|
||||||
CFixedVector2D v(s, c);
|
CFixedVector2D v(s, c);
|
||||||
@ -162,7 +162,7 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CFixed_23_8 s, c;
|
fixed s, c;
|
||||||
sincos_approx(a, s, c);
|
sincos_approx(a, s, c);
|
||||||
CFixedVector2D u(c, -s);
|
CFixedVector2D u(c, -s);
|
||||||
CFixedVector2D v(s, c);
|
CFixedVector2D v(s, c);
|
||||||
@ -304,7 +304,7 @@ bool CCmpObstructionManager::TestStaticShape(const IObstructionTestFilter& filte
|
|||||||
{
|
{
|
||||||
PROFILE("TestStaticShape");
|
PROFILE("TestStaticShape");
|
||||||
|
|
||||||
CFixed_23_8 s, c;
|
fixed s, c;
|
||||||
sincos_approx(a, s, c);
|
sincos_approx(a, s, c);
|
||||||
CFixedVector2D u(c, -s);
|
CFixedVector2D u(c, -s);
|
||||||
CFixedVector2D v(s, c);
|
CFixedVector2D v(s, c);
|
||||||
|
@ -53,8 +53,6 @@
|
|||||||
class CCmpPathfinder;
|
class CCmpPathfinder;
|
||||||
struct PathfindTile;
|
struct PathfindTile;
|
||||||
|
|
||||||
typedef CFixed_23_8 fixed;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Terrain overlay for pathfinder debugging.
|
* Terrain overlay for pathfinder debugging.
|
||||||
* Renders a representation of the most recent pathfinding operation.
|
* 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)
|
static u32 CalculateHeuristic(u16 i, u16 j, u16 iGoal, u16 jGoal, u16 rGoal)
|
||||||
{
|
{
|
||||||
#ifdef USE_DIAGONAL_MOVEMENT
|
#ifdef USE_DIAGONAL_MOVEMENT
|
||||||
CFixedVector2D pos (CFixed_23_8::FromInt(i), CFixed_23_8::FromInt(j));
|
CFixedVector2D pos (fixed::FromInt(i), fixed::FromInt(j));
|
||||||
CFixedVector2D goal (CFixed_23_8::FromInt(iGoal), CFixed_23_8::FromInt(jGoal));
|
CFixedVector2D goal (fixed::FromInt(iGoal), fixed::FromInt(jGoal));
|
||||||
CFixed_23_8 dist = (pos - goal).Length();
|
fixed dist = (pos - goal).Length();
|
||||||
// TODO: the heuristic could match the costs better - it's not really Euclidean movement
|
// 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();
|
rdist = rdist.Absolute();
|
||||||
|
|
||||||
return (rdist * (int)g_CostPerTile).ToInt_RoundToZero();
|
return (rdist * (int)g_CostPerTile).ToInt_RoundToZero();
|
||||||
|
@ -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);
|
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);
|
LaunchProjectile(source, target, INVALID_ENTITY, speed, gravity);
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ private:
|
|||||||
|
|
||||||
std::vector<Projectile> m_Projectiles;
|
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);
|
void AdvanceProjectile(const CSimContext& context, Projectile& projectile, float dt, float frameOffset);
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ private:
|
|||||||
|
|
||||||
REGISTER_COMPONENT_TYPE(ProjectileManager)
|
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())
|
if (!GetSimContext().HasUnitManager())
|
||||||
return; // do nothing if graphics are disabled
|
return; // do nothing if graphics are disabled
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
|
|
||||||
// Template state:
|
// Template state:
|
||||||
|
|
||||||
CFixed_23_8 m_Speed; // in units per second
|
fixed m_Speed; // in units per second
|
||||||
entity_pos_t m_Radius;
|
entity_pos_t m_Radius;
|
||||||
|
|
||||||
// Dynamic state:
|
// Dynamic state:
|
||||||
@ -138,12 +138,12 @@ public:
|
|||||||
{
|
{
|
||||||
case MT_Update:
|
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)
|
if (m_State == STOPPING)
|
||||||
{
|
{
|
||||||
m_State = IDLE;
|
m_State = IDLE;
|
||||||
CMessageMotionChanged msg(CFixed_23_8::FromInt(0));
|
CMessageMotionChanged msg(fixed::Zero());
|
||||||
context.GetComponentManager().PostMessage(GetEntityId(), msg);
|
context.GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual CFixed_23_8 GetSpeed()
|
virtual fixed GetSpeed()
|
||||||
{
|
{
|
||||||
return m_Speed;
|
return m_Speed;
|
||||||
}
|
}
|
||||||
@ -191,7 +191,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Do the per-turn movement and other updates
|
* Do the per-turn movement and other updates
|
||||||
*/
|
*/
|
||||||
void Move(CFixed_23_8 dt);
|
void Move(fixed dt);
|
||||||
|
|
||||||
void StopAndFaceGoal(CFixedVector2D pos);
|
void StopAndFaceGoal(CFixedVector2D pos);
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ bool CCmpUnitMotion::CheckMovement(CFixedVector2D pos, CFixedVector2D target)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCmpUnitMotion::Move(CFixed_23_8 dt)
|
void CCmpUnitMotion::Move(fixed dt)
|
||||||
{
|
{
|
||||||
PROFILE("Move");
|
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
|
// 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 target(m_ShortTargetX, m_ShortTargetZ);
|
||||||
CFixedVector2D offset = target - pos;
|
CFixedVector2D offset = target - pos;
|
||||||
@ -302,10 +302,10 @@ void CCmpUnitMotion::Move(CFixed_23_8 dt)
|
|||||||
cmpPosition->TurnTo(angle);
|
cmpPosition->TurnTo(angle);
|
||||||
|
|
||||||
// Work out how far we can travel in dt
|
// 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
|
// If the target is close, we can move there directly
|
||||||
CFixed_23_8 offsetLength = offset.Length();
|
fixed offsetLength = offset.Length();
|
||||||
if (offsetLength <= maxdist)
|
if (offsetLength <= maxdist)
|
||||||
{
|
{
|
||||||
if (!CheckMovement(pos, target))
|
if (!CheckMovement(pos, target))
|
||||||
|
@ -230,7 +230,7 @@ public:
|
|||||||
m_Unit->SetAnimationSync(actiontime, repeattime);
|
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)
|
if (!m_Unit)
|
||||||
return;
|
return;
|
||||||
|
@ -22,6 +22,6 @@
|
|||||||
#include "simulation2/system/InterfaceScripted.h"
|
#include "simulation2/system/InterfaceScripted.h"
|
||||||
|
|
||||||
BEGIN_INTERFACE_WRAPPER(ProjectileManager)
|
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("LaunchProjectileAtEntity", void, ICmpProjectileManager, LaunchProjectileAtEntity, entity_id_t, entity_id_t, fixed, fixed)
|
||||||
DEFINE_INTERFACE_METHOD_4("LaunchProjectileAtPoint", void, ICmpProjectileManager, LaunchProjectileAtPoint, entity_id_t, CFixedVector3D, CFixed_23_8, CFixed_23_8)
|
DEFINE_INTERFACE_METHOD_4("LaunchProjectileAtPoint", void, ICmpProjectileManager, LaunchProjectileAtPoint, entity_id_t, CFixedVector3D, fixed, fixed)
|
||||||
END_INTERFACE_WRAPPER(ProjectileManager)
|
END_INTERFACE_WRAPPER(ProjectileManager)
|
||||||
|
@ -38,7 +38,7 @@ public:
|
|||||||
* @param speed horizontal speed in m/s
|
* @param speed horizontal speed in m/s
|
||||||
* @param gravity gravitational acceleration in m/s^2 (determines the height of the ballistic curve)
|
* @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.
|
* Launch a projectile from entity @p source to point @p target.
|
||||||
@ -47,7 +47,7 @@ public:
|
|||||||
* @param speed horizontal speed in m/s
|
* @param speed horizontal speed in m/s
|
||||||
* @param gravity gravitational acceleration in m/s^2 (determines the height of the ballistic curve)
|
* @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)
|
DECLARE_INTERFACE_TYPE(ProjectileManager)
|
||||||
};
|
};
|
||||||
|
@ -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_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("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_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)
|
DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpUnitMotion, SetDebugOverlay, bool)
|
||||||
END_INTERFACE_WRAPPER(UnitMotion)
|
END_INTERFACE_WRAPPER(UnitMotion)
|
||||||
|
@ -61,9 +61,9 @@ public:
|
|||||||
virtual bool MoveToAttackRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange) = 0;
|
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.
|
* Toggle the rendering of debug info.
|
||||||
|
@ -24,5 +24,5 @@
|
|||||||
BEGIN_INTERFACE_WRAPPER(Visual)
|
BEGIN_INTERFACE_WRAPPER(Visual)
|
||||||
DEFINE_INTERFACE_METHOD_4("SelectAnimation", void, ICmpVisual, SelectAnimation, std::string, bool, float, std::wstring)
|
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_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)
|
END_INTERFACE_WRAPPER(Visual)
|
||||||
|
@ -82,7 +82,7 @@ public:
|
|||||||
* @param b blue component, expected range [0, 1]
|
* @param b blue component, expected range [0, 1]
|
||||||
* @param a alpha 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)
|
DECLARE_INTERFACE_TYPE(Visual)
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,7 @@ public:
|
|||||||
|
|
||||||
static CFixedVector3D fixedvec(int x, int y, int z)
|
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()
|
void test_basic()
|
||||||
|
@ -27,10 +27,10 @@ using namespace Geometry;
|
|||||||
|
|
||||||
bool Geometry::PointIsInSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize)
|
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)
|
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)
|
if (-halfSize.Y <= dv && dv <= halfSize.Y)
|
||||||
return true;
|
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:
|
* Relative to its own coordinate system, we have a square like:
|
||||||
|
@ -30,8 +30,6 @@ class CFixedVector2D;
|
|||||||
namespace Geometry
|
namespace Geometry
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef CFixed_23_8 fixed;
|
|
||||||
|
|
||||||
bool PointIsInSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize);
|
bool PointIsInSquare(CFixedVector2D point, CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize);
|
||||||
|
|
||||||
CFixedVector2D GetHalfBoundingBox(CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize);
|
CFixedVector2D GetHalfBoundingBox(CFixedVector2D u, CFixedVector2D v, CFixedVector2D halfSize);
|
||||||
|
@ -33,12 +33,11 @@
|
|||||||
/**
|
/**
|
||||||
* Positions and distances (measured in metres)
|
* Positions and distances (measured in metres)
|
||||||
*/
|
*/
|
||||||
typedef CFixed_23_8 entity_pos_t;
|
typedef CFixed_15_16 entity_pos_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotations (measured in radians)
|
* Rotations (measured in radians)
|
||||||
*/
|
*/
|
||||||
typedef CFixed_23_8 entity_angle_t;
|
typedef CFixed_15_16 entity_angle_t;
|
||||||
// TODO: use a type with more precision
|
|
||||||
|
|
||||||
#endif // INCLUDED_POSITION
|
#endif // INCLUDED_POSITION
|
||||||
|
@ -171,17 +171,17 @@ template<> jsval ScriptInterface::ToJSVal<CColor>(JSContext* cx, CColor const& v
|
|||||||
return OBJECT_TO_JSVAL(obj);
|
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;
|
jsdouble ret;
|
||||||
if (!JS_ValueToNumber(cx, v, &ret))
|
if (!JS_ValueToNumber(cx, v, &ret))
|
||||||
return false;
|
return false;
|
||||||
out = CFixed_23_8::FromDouble(ret);
|
out = fixed::FromDouble(ret);
|
||||||
// TODO: ought to check that this conversion is consistent and portable
|
// TODO: ought to check that this conversion is consistent and portable
|
||||||
return true;
|
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;
|
jsval rval = JSVAL_VOID;
|
||||||
JS_NewNumberValue(cx, val.ToDouble(), &rval); // ignore return value
|
JS_NewNumberValue(cx, val.ToDouble(), &rval); // ignore return value
|
||||||
|
@ -74,7 +74,7 @@ jsval CMessageUpdate::ToJSVal(ScriptInterface& scriptInterface) const
|
|||||||
CMessage* CMessageUpdate::FromJSVal(ScriptInterface& scriptInterface, jsval val)
|
CMessage* CMessageUpdate::FromJSVal(ScriptInterface& scriptInterface, jsval val)
|
||||||
{
|
{
|
||||||
FROMJSVAL_SETUP();
|
FROMJSVAL_SETUP();
|
||||||
GET_MSG_PROPERTY(CFixed_23_8, turnLength);
|
GET_MSG_PROPERTY(fixed, turnLength);
|
||||||
return new CMessageUpdate(turnLength);
|
return new CMessageUpdate(turnLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ jsval CMessageMotionChanged::ToJSVal(ScriptInterface& scriptInterface) const
|
|||||||
CMessage* CMessageMotionChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val)
|
CMessage* CMessageMotionChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val)
|
||||||
{
|
{
|
||||||
FROMJSVAL_SETUP();
|
FROMJSVAL_SETUP();
|
||||||
GET_MSG_PROPERTY(CFixed_23_8, speed);
|
GET_MSG_PROPERTY(fixed, speed);
|
||||||
return new CMessageMotionChanged(speed);
|
return new CMessageMotionChanged(speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ void CBinarySerializer::PutNumber(const char* name, double value)
|
|||||||
Put(name, (const u8*)&value, sizeof(double));
|
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());
|
PutNumber(name, value.GetInternalValue());
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ protected:
|
|||||||
virtual void PutNumber(const char* name, uint32_t value);
|
virtual void PutNumber(const char* name, uint32_t value);
|
||||||
virtual void PutNumber(const char* name, float value);
|
virtual void PutNumber(const char* name, float value);
|
||||||
virtual void PutNumber(const char* name, double 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 PutBool(const char* name, bool value);
|
||||||
virtual void PutString(const char* name, const std::string& value);
|
virtual void PutString(const char* name, const std::string& value);
|
||||||
virtual void PutScriptVal(const char* name, jsval value);
|
virtual void PutScriptVal(const char* name, jsval value);
|
||||||
|
@ -102,7 +102,7 @@ void CDebugSerializer::PutNumber(const char* name, double value)
|
|||||||
m_Stream << INDENT << name << ": " << canonfloat(value) << "\n";
|
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";
|
m_Stream << INDENT << name << ": " << canonfloat(value.ToDouble()) << "\n";
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ protected:
|
|||||||
virtual void PutNumber(const char* name, uint32_t value);
|
virtual void PutNumber(const char* name, uint32_t value);
|
||||||
virtual void PutNumber(const char* name, float value);
|
virtual void PutNumber(const char* name, float value);
|
||||||
virtual void PutNumber(const char* name, double 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 PutBool(const char* name, bool value);
|
||||||
virtual void PutString(const char* name, const std::string& value);
|
virtual void PutString(const char* name, const std::string& value);
|
||||||
virtual void PutScriptVal(const char* name, jsval value);
|
virtual void PutScriptVal(const char* name, jsval value);
|
||||||
|
@ -83,7 +83,7 @@ void IDeserializer::NumberDouble_Unbounded(double& out)
|
|||||||
Get((u8*)&out, sizeof(double));
|
Get((u8*)&out, sizeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDeserializer::NumberFixed_Unbounded(CFixed_23_8& out)
|
void IDeserializer::NumberFixed_Unbounded(fixed& out)
|
||||||
{
|
{
|
||||||
int32_t n;
|
int32_t n;
|
||||||
NumberI32_Unbounded(n);
|
NumberI32_Unbounded(n);
|
||||||
|
@ -45,7 +45,7 @@ public:
|
|||||||
virtual void NumberU32_Unbounded(uint32_t& out);
|
virtual void NumberU32_Unbounded(uint32_t& out);
|
||||||
virtual void NumberFloat_Unbounded(float& out);
|
virtual void NumberFloat_Unbounded(float& out);
|
||||||
virtual void NumberDouble_Unbounded(double& 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 Bool(bool& out);
|
||||||
virtual void StringASCII(std::string& out, uint32_t minlength, uint32_t maxlength);
|
virtual void StringASCII(std::string& out, uint32_t minlength, uint32_t maxlength);
|
||||||
virtual void String(std::wstring& out, uint32_t minlength, uint32_t maxlength);
|
virtual void String(std::wstring& out, uint32_t minlength, uint32_t maxlength);
|
||||||
|
@ -71,7 +71,7 @@ void ISerializer::NumberDouble_Unbounded(const char* name, double value)
|
|||||||
PutNumber(name, 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);
|
PutNumber(name, value);
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ public:
|
|||||||
void NumberU32_Unbounded(const char* name, uint32_t value); ///< @copydoc NumberU8_Unbounded
|
void NumberU32_Unbounded(const char* name, uint32_t value); ///< @copydoc NumberU8_Unbounded
|
||||||
void NumberFloat_Unbounded(const char* name, float 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 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.
|
* Serialize a boolean.
|
||||||
@ -205,7 +205,7 @@ protected:
|
|||||||
virtual void PutNumber(const char* name, uint32_t value) = 0;
|
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, float value) = 0;
|
||||||
virtual void PutNumber(const char* name, double 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 PutBool(const char* name, bool value) = 0;
|
||||||
virtual void PutString(const char* name, const std::string& value) = 0;
|
virtual void PutString(const char* name, const std::string& value) = 0;
|
||||||
virtual void PutScriptVal(const char* name, jsval value) = 0;
|
virtual void PutScriptVal(const char* name, jsval value) = 0;
|
||||||
|
@ -164,12 +164,12 @@ public:
|
|||||||
|
|
||||||
virtual CFixedVector3D CalcNormal(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z))
|
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))
|
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))
|
virtual float GetGroundLevel(float UNUSED(x), float UNUSED(z))
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "ParamNode.h"
|
#include "ParamNode.h"
|
||||||
|
|
||||||
|
#include "ps/CStr.h"
|
||||||
#include "ps/XML/Xeromyces.h"
|
#include "ps/XML/Xeromyces.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -135,14 +136,9 @@ int CParamNode::ToInt() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFixed_23_8 CParamNode::ToFixed() const
|
fixed CParamNode::ToFixed() const
|
||||||
{
|
{
|
||||||
double ret = 0.0;
|
return fixed::FromString(CStrW(m_Value));
|
||||||
std::wstringstream strm;
|
|
||||||
strm << m_Value;
|
|
||||||
strm >> ret;
|
|
||||||
return CFixed_23_8::FromDouble(ret);
|
|
||||||
// TODO: this shouldn't use floating point types
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CParamNode::ToBool() const
|
bool CParamNode::ToBool() const
|
||||||
|
@ -151,7 +151,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Parses the content of this node as a fixed-point number
|
* 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)
|
* Parses the content of this node as a boolean ("true" == true, anything else == false)
|
||||||
|
@ -155,7 +155,7 @@ public:
|
|||||||
man.AddComponent(ent4, CID_Test2A, noParam);
|
man.AddComponent(ent4, CID_Test2A, noParam);
|
||||||
|
|
||||||
CMessageTurnStart msg1;
|
CMessageTurnStart msg1;
|
||||||
CMessageUpdate msg2(CFixed_23_8::FromInt(100));
|
CMessageUpdate msg2(fixed::FromInt(100));
|
||||||
CMessageInterpolate msg3(0, 0);
|
CMessageInterpolate msg3(0, 0);
|
||||||
|
|
||||||
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000);
|
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);
|
TS_ASSERT_EQUALS(static_cast<ICmpTest2*> (man.QueryInterface(ent3, IID_Test2))->GetX(), 201000);
|
||||||
|
|
||||||
CMessageTurnStart msg1;
|
CMessageTurnStart msg1;
|
||||||
CMessageUpdate msg2(CFixed_23_8::FromInt(25));
|
CMessageUpdate msg2(fixed::FromInt(25));
|
||||||
|
|
||||||
man.BroadcastMessage(msg1);
|
man.BroadcastMessage(msg1);
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ public:
|
|||||||
serialize.NumberU32_Unbounded("u32", (unsigned)-123);
|
serialize.NumberU32_Unbounded("u32", (unsigned)-123);
|
||||||
serialize.NumberFloat_Unbounded("float", 1e+30f);
|
serialize.NumberFloat_Unbounded("float", 1e+30f);
|
||||||
serialize.NumberDouble_Unbounded("double", 1e+300);
|
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("t", true);
|
||||||
serialize.Bool("f", false);
|
serialize.Bool("f", false);
|
||||||
@ -93,11 +93,11 @@ public:
|
|||||||
serialize.NumberDouble_Unbounded("x", 1e-10);
|
serialize.NumberDouble_Unbounded("x", 1e-10);
|
||||||
serialize.NumberDouble_Unbounded("x", 1e100);
|
serialize.NumberDouble_Unbounded("x", 1e100);
|
||||||
serialize.NumberDouble_Unbounded("x", 1e-100);
|
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(),
|
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\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: 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;
|
uint32_t u32v;
|
||||||
float flt;
|
float flt;
|
||||||
double dbl;
|
double dbl;
|
||||||
CFixed_23_8 fixed;
|
fixed fxd;
|
||||||
bool bl;
|
bool bl;
|
||||||
std::string str;
|
std::string str;
|
||||||
std::wstring wstr;
|
std::wstring wstr;
|
||||||
@ -185,8 +185,8 @@ public:
|
|||||||
TS_ASSERT_EQUALS(flt, 1e+30f);
|
TS_ASSERT_EQUALS(flt, 1e+30f);
|
||||||
deserialize.NumberDouble_Unbounded(dbl);
|
deserialize.NumberDouble_Unbounded(dbl);
|
||||||
TS_ASSERT_EQUALS(dbl, 1e+300);
|
TS_ASSERT_EQUALS(dbl, 1e+300);
|
||||||
deserialize.NumberFixed_Unbounded(fixed);
|
deserialize.NumberFixed_Unbounded(fxd);
|
||||||
TS_ASSERT_EQUALS(fixed.ToDouble(), 1234.5);
|
TS_ASSERT_EQUALS(fxd.ToDouble(), 1234.5);
|
||||||
|
|
||||||
deserialize.Bool(bl);
|
deserialize.Bool(bl);
|
||||||
TS_ASSERT_EQUALS(bl, true);
|
TS_ASSERT_EQUALS(bl, true);
|
||||||
|
@ -921,7 +921,7 @@ BEGIN_COMMAND(RotateObject)
|
|||||||
if (cmpPos.null())
|
if (cmpPos.null())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cmpPos->SetYRotation(CFixed_23_8::FromFloat(angle));
|
cmpPos->SetYRotation(entity_angle_t::FromFloat(angle));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user