357 lines
10 KiB
C++
357 lines
10 KiB
C++
// ==============================================================
|
|
// This file is part of MegaGlest Unit Tests (www.megaglest.org)
|
|
//
|
|
// Copyright (C) 2013 Mark Vejvoda
|
|
//
|
|
// You can redistribute this code 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
|
|
// ==============================================================
|
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
#ifdef WIN32
|
|
#include <winsock2.h>
|
|
#include <winsock.h>
|
|
#endif
|
|
|
|
#include "vec.h"
|
|
#include "skill_type.h"
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
#ifdef WIN32
|
|
#include <io.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
using namespace Shared::Util;
|
|
using namespace Shared::Graphics;
|
|
using namespace Glest::Game;
|
|
//
|
|
// Tests for streflop floating point consistency
|
|
//
|
|
const int64 PROGRESS_SPEED_MULTIPLIER = 100000;
|
|
const float standardAirHeight = 5.0f;
|
|
const float FLOAT_TOLERANCE = 1e-10f;
|
|
|
|
class StreflopTest : public CppUnit::TestFixture {
|
|
// Register the suite of tests for this fixture
|
|
CPPUNIT_TEST_SUITE( StreflopTest );
|
|
|
|
CPPUNIT_TEST( test_warmup_cases );
|
|
CPPUNIT_TEST( test_known_out_of_synch_cases );
|
|
|
|
CPPUNIT_TEST_SUITE_END();
|
|
// End of Fixture registration
|
|
|
|
private:
|
|
|
|
float cellHeight;
|
|
Field currField;
|
|
float tileSetAirHeight;
|
|
int cellLandUnitHeight;
|
|
int cellObjectHeight;
|
|
SkillClass currSkill;
|
|
int curUnitTypeSize;
|
|
int64 progress;
|
|
Vec2i lastPos;
|
|
Vec2i pos;
|
|
|
|
void reset() {
|
|
cellHeight = 0.f;
|
|
currField = fLand;
|
|
tileSetAirHeight = standardAirHeight;
|
|
cellLandUnitHeight = 0;
|
|
cellObjectHeight = 0;
|
|
currSkill = scStop;
|
|
curUnitTypeSize = 0;
|
|
progress = 0;
|
|
lastPos = Vec2i(0,0);
|
|
pos = Vec2i(0,0);
|
|
}
|
|
|
|
public:
|
|
|
|
StreflopTest() {
|
|
#ifdef USE_STREFLOP
|
|
//#define STREFLOP_NO_DENORMALS
|
|
//
|
|
//#if defined(STREFLOP_SSE)
|
|
// const char *instruction_set = "[SSE]";
|
|
//#elif defined(STREFLOP_X87)
|
|
// const char *instruction_set = "[X87]";
|
|
//#elif defined(STREFLOP_SOFT)
|
|
// const char *instruction_set = "[SOFTFLOAT]";
|
|
//#else
|
|
// const char *instruction_set = "[none]";
|
|
//#endif
|
|
//
|
|
//#if defined(STREFLOP_NO_DENORMALS)
|
|
// const char *denormals = "[no-denormals]";
|
|
//#else
|
|
// const char *denormals = "[denormals]";
|
|
//#endif
|
|
//
|
|
// printf("Tests - using STREFLOP %s - %s\n",instruction_set,denormals);
|
|
|
|
streflop_init<streflop::Simple>();
|
|
|
|
#endif
|
|
|
|
reset();
|
|
}
|
|
|
|
void test_warmup_cases() {
|
|
int unitTypeHeight = 0;
|
|
|
|
cellHeight = 1.1f;
|
|
currField = fLand;
|
|
tileSetAirHeight = standardAirHeight;
|
|
cellLandUnitHeight = 1;
|
|
cellObjectHeight = 0;
|
|
currSkill = scMove;
|
|
curUnitTypeSize = 1;
|
|
progress = 10;
|
|
lastPos = Vec2i(1,1);
|
|
pos = Vec2i(1,2);
|
|
unitTypeHeight = 1;
|
|
Vec3f result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [1.6] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 0;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [1.1] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 2;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [2.1] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fAir;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [6.6] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fAir;
|
|
currSkill = scAttack;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [6.6] z [2]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fLand;
|
|
currSkill = scAttack;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [1.6] z [2]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fLand;
|
|
currSkill = scAttack;
|
|
cellLandUnitHeight = -1;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [1.6] z [2]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fAir;
|
|
currSkill = scAttack;
|
|
cellLandUnitHeight = -1;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [6.6] z [2]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fLand;
|
|
currSkill = scMove;
|
|
cellLandUnitHeight = 2;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [1.6] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fAir;
|
|
currSkill = scMove;
|
|
cellLandUnitHeight = 2;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [6.6] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fLand;
|
|
currSkill = scMove;
|
|
cellLandUnitHeight = -1;
|
|
cellObjectHeight = 0;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [1.6] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fLand;
|
|
currSkill = scMove;
|
|
cellLandUnitHeight = -1;
|
|
cellObjectHeight = 1;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [1.6] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fAir;
|
|
currSkill = scMove;
|
|
cellLandUnitHeight = -1;
|
|
cellObjectHeight = 1;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [6.6] z [1.0001]"), result.getString() );
|
|
|
|
unitTypeHeight = 1;
|
|
currField = fLand;
|
|
currSkill = scMove;
|
|
progress = 1324312;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [1] y [1.6] z [14.2431]"), result.getString() );
|
|
|
|
cellHeight = 2.870369f;
|
|
currField = fLand;
|
|
tileSetAirHeight = standardAirHeight;
|
|
cellLandUnitHeight = 0;
|
|
cellObjectHeight = 0;
|
|
currSkill = scAttack;
|
|
curUnitTypeSize = 1;
|
|
progress = 21250;
|
|
lastPos = Vec2i(96,34);
|
|
pos = Vec2i(95,35);
|
|
unitTypeHeight = 3;
|
|
result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [95] y [4.37037] z [35]"), result.getString() );
|
|
|
|
double x = 1.0;
|
|
x /= 10.0;
|
|
double y = x;
|
|
// THIS IS NOT ALWAYS TRUE without streflop!
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( x, y, FLOAT_TOLERANCE );
|
|
|
|
float xf = 1.0;
|
|
xf /= 10.0;
|
|
float yf = xf;
|
|
// THIS IS NOT ALWAYS TRUE without streflop!
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( xf, yf, FLOAT_TOLERANCE );
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.2f, 0.1f + 0.1f, FLOAT_TOLERANCE );
|
|
CPPUNIT_ASSERT_EQUAL( string("0.200000"), floatToStr(0.1f + 0.1f,6) );
|
|
CPPUNIT_ASSERT_EQUAL( string("0.2000000"), floatToStr(0.1f + 0.1f,7) );
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.01f, 0.1f * 0.1f, 1e-9 );
|
|
CPPUNIT_ASSERT_EQUAL( string("0.010000"), floatToStr(0.1f * 0.1f,6) );
|
|
CPPUNIT_ASSERT_EQUAL( string("0.0100000"), floatToStr(0.1f * 0.1f,7) );
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.002877f, 2877.0f / 1000000.0f, FLOAT_TOLERANCE );
|
|
CPPUNIT_ASSERT_EQUAL( string("0.002877"), floatToStr(2877.0f / 1000000.0f,6) );
|
|
CPPUNIT_ASSERT_EQUAL( string("0.0028770"), floatToStr(2877.0f / 1000000.0f,7) );
|
|
}
|
|
|
|
void test_known_out_of_synch_cases() {
|
|
// Documented cases of out of synch go here to test cross platform for
|
|
// consistency
|
|
int unitTypeHeight = 0;
|
|
|
|
cellHeight = 2.814814f;
|
|
currField = fLand;
|
|
tileSetAirHeight = 5.000000f;
|
|
cellLandUnitHeight = -1;
|
|
cellObjectHeight = -1;
|
|
currSkill = scMove;
|
|
curUnitTypeSize = 1;
|
|
progress = 35145;
|
|
lastPos = Vec2i(40,41);
|
|
pos = Vec2i(39,40);
|
|
unitTypeHeight = 2;
|
|
|
|
Vec3f result = getCurrVector(unitTypeHeight);
|
|
CPPUNIT_ASSERT_EQUAL( string("x [39.6485] y [3.81481] z [40.6485]"), result.getString() );
|
|
}
|
|
|
|
// =========================== Helper Methods =================================
|
|
|
|
float computeHeight(const Vec2i &pos) const {
|
|
|
|
float height = cellHeight;
|
|
|
|
if(currField == fAir) {
|
|
float airHeight = tileSetAirHeight;
|
|
airHeight = truncateDecimal<float>(airHeight,6);
|
|
|
|
height += airHeight;
|
|
height = truncateDecimal<float>(height,6);
|
|
|
|
if(cellLandUnitHeight >= 0 && cellLandUnitHeight > airHeight) {
|
|
height += (min((float)cellLandUnitHeight,standardAirHeight * 3) - airHeight);
|
|
height = truncateDecimal<float>(height,6);
|
|
}
|
|
else {
|
|
if(cellObjectHeight >= 0) {
|
|
if(cellObjectHeight > airHeight) {
|
|
height += (min((float)cellObjectHeight,standardAirHeight * 3) - airHeight);
|
|
height = truncateDecimal<float>(height,6);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return height;
|
|
}
|
|
|
|
float getProgressAsFloat() const {
|
|
float result = (static_cast<float>(progress) / static_cast<float>(PROGRESS_SPEED_MULTIPLIER));
|
|
result = truncateDecimal<float>(result,6);
|
|
return result;
|
|
}
|
|
|
|
Vec3f getVectorFlat(const Vec2i &lastPosValue, const Vec2i &curPosValue) const {
|
|
Vec3f v;
|
|
|
|
float y1= computeHeight(lastPosValue);
|
|
float y2= computeHeight(curPosValue);
|
|
|
|
if(currSkill == scMove) {
|
|
float progressAsFloat = getProgressAsFloat();
|
|
|
|
v.x = lastPosValue.x + progressAsFloat * (curPosValue.x - lastPosValue.x);
|
|
v.z = lastPosValue.y + progressAsFloat * (curPosValue.y - lastPosValue.y);
|
|
v.y = y1 + progressAsFloat * (y2-y1);
|
|
|
|
v.x = truncateDecimal<float>(v.x,6);
|
|
v.y = truncateDecimal<float>(v.y,6);
|
|
v.z = truncateDecimal<float>(v.z,6);
|
|
}
|
|
else {
|
|
v.x = static_cast<float>(curPosValue.x);
|
|
v.z = static_cast<float>(curPosValue.y);
|
|
v.y = y2;
|
|
|
|
v.x = truncateDecimal<float>(v.x,6);
|
|
v.y = truncateDecimal<float>(v.y,6);
|
|
v.z = truncateDecimal<float>(v.z,6);
|
|
}
|
|
v.x += curUnitTypeSize / 2.f - 0.5f;
|
|
v.z += curUnitTypeSize / 2.f - 0.5f;
|
|
|
|
v.x = truncateDecimal<float>(v.x,6);
|
|
v.z = truncateDecimal<float>(v.z,6);
|
|
|
|
return v;
|
|
}
|
|
|
|
Vec3f getCurrVectorFlat() const {
|
|
return getVectorFlat(lastPos, pos);
|
|
}
|
|
|
|
Vec3f getCurrVector(int unitTypeHeight) const {
|
|
Vec3f result = getCurrVectorFlat() + Vec3f(0.f, unitTypeHeight / 2.f, 0.f);
|
|
result.x = truncateDecimal<float>(result.x,6);
|
|
result.y = truncateDecimal<float>(result.y,6);
|
|
result.z = truncateDecimal<float>(result.z,6);
|
|
|
|
return result;
|
|
}
|
|
|
|
};
|
|
|
|
// Test Suite Registrations
|
|
CPPUNIT_TEST_SUITE_REGISTRATION( StreflopTest );
|
|
//
|