diff --git a/cpp/coord/camgame.cpp b/cpp/coord/camgame.cpp index 1bc78dd59a..abbed18bfe 100644 --- a/cpp/coord/camgame.cpp +++ b/cpp/coord/camgame.cpp @@ -25,11 +25,9 @@ phys3_delta camgame_delta::to_phys3(phys_t up) { // apply scaling factor, to get 'scaled' // scaling factor: w/2 for x, h/2 for y // plus the phys_per_tu fixed-point scaling factor - vec2 scaled; - scaled.x = (settings::phys_per_tile * (phys_t) x) / - (phys_t) engine_coord_data->tile_halfsize.x; - scaled.y = (settings::phys_per_tile * (phys_t) y) / - (phys_t) engine_coord_data->tile_halfsize.y; + phys_t scaled_x = phys_t{x} / phys_t{engine_coord_data->tile_halfsize.x}; + phys_t scaled_y = phys_t{y} / phys_t{engine_coord_data->tile_halfsize.y}; + // apply transformation matrix to 'scaled', // to get the relative phys3 position @@ -46,8 +44,8 @@ phys3_delta camgame_delta::to_phys3(phys_t up) { // (se) = (+0.5 -0.5 -0.5) (scaled.y) // (up) = (+0.0 +0.0 +1.0) ( up) phys3_delta result; - result.ne = (scaled.x + scaled.y + up)/2; - result.se = (scaled.x - scaled.y - up)/2; + result.ne = (scaled_x + scaled_y + up) / 2; + result.se = (scaled_x - scaled_y - up) / 2; result.up = ( up); return result; diff --git a/cpp/coord/chunk.cpp b/cpp/coord/chunk.cpp index a5e0adc225..e0bc79c277 100644 --- a/cpp/coord/chunk.cpp +++ b/cpp/coord/chunk.cpp @@ -10,10 +10,8 @@ namespace coord { tile chunk::to_tile(tile_delta pos_on_chunk) { tile result; - result.ne = (((tile_t) ne) << settings::tiles_per_chunk_bits) - + pos_on_chunk.ne; - result.se = (((tile_t) se) << settings::tiles_per_chunk_bits) - + pos_on_chunk.se; + result.ne = static_cast(ne) * chunk::tiles_per_chunk + pos_on_chunk.ne; + result.se = static_cast(se) * chunk::tiles_per_chunk + pos_on_chunk.se; return result; } diff --git a/cpp/coord/chunk.h b/cpp/coord/chunk.h index f7af7a5486..3088d3941f 100644 --- a/cpp/coord/chunk.h +++ b/cpp/coord/chunk.h @@ -19,6 +19,8 @@ struct chunk { #include "ops/abs.h" tile to_tile(tile_delta pos_on_chunk); + + static constexpr tile_t tiles_per_chunk = 16; }; struct chunk_delta { diff --git a/cpp/coord/decl.h b/cpp/coord/decl.h index ebe1fa1e09..fc29c6234d 100644 --- a/cpp/coord/decl.h +++ b/cpp/coord/decl.h @@ -5,6 +5,8 @@ #include +#include "fixed_point.h" + /* * forward declarations of all coordinate structs, * scalar type name aliases, and scaling factors @@ -16,7 +18,7 @@ namespace openage { namespace coord { /* physics-based vector types */ -using phys_t = int64_t; +using phys_t = FixedPoint; struct phys2; struct phys2_delta; @@ -62,16 +64,6 @@ struct vec2f_delta; struct vec3f; struct vec3f_delta; - -namespace settings { -constexpr unsigned phys_t_radix_pos = 16; -constexpr phys_t phys_t_scaling_factor = (1 << phys_t_radix_pos); -constexpr phys_t phys_per_tile = phys_t_scaling_factor; -constexpr unsigned tiles_per_chunk_bits = 4; //yeah, this needs a better name. -constexpr tile_t tiles_per_chunk = (1 << tiles_per_chunk_bits); -} // namespace settings - - } // namespace coord } // namespace openage diff --git a/cpp/coord/fixed_point.h b/cpp/coord/fixed_point.h new file mode 100644 index 0000000000..767327b9c5 --- /dev/null +++ b/cpp/coord/fixed_point.h @@ -0,0 +1,286 @@ +// Copyright 2015-2015 the openage authors. See copying.md for legal info. + +#ifndef OPENAGE_COORD_FIXED_POINT_H_ +#define OPENAGE_COORD_FIXED_POINT_H_ + +#include +#include + +#include "../util/misc.h" + +namespace openage { +namespace coord { + +template +struct FixedPoint { + + int_type data; + + static const int_type one = int_type(1) << fractional_bits; + + static const int_type fraction_bitmask = one - 1; + + + // constructors + constexpr FixedPoint() : data(0) { + } + + constexpr FixedPoint(int_type n) : data(n << fractional_bits) { + } + + constexpr FixedPoint(int n) : data(n << fractional_bits) { + } + + constexpr FixedPoint(unsigned int n) : data(n << fractional_bits) { + } + + // Constructing FixedPoint numbers with values like 1/2 and 1/8 won't lose precision + constexpr FixedPoint(float n) : data(static_cast(n * one)) { + } + + constexpr FixedPoint(double n) : data(static_cast(n * one)) { + } + + static FixedPoint from_raw(int_type data) { + FixedPoint result; + result.data = data; + return result; + } + + constexpr FixedPoint(const FixedPoint &o) : data(o.data) { + } + + FixedPoint &operator=(const FixedPoint &o) { + data = o.data; + return *this; + } + + + // Comparison operators + bool operator==(const FixedPoint &o) const { + return data == o.data; + } + + bool operator!=(const FixedPoint &o) const { + return data != o.data; + } + + bool operator<(const FixedPoint &o) const { + return data < o.data; + } + + bool operator>(const FixedPoint &o) const { + return data > o.data; + } + + bool operator<=(const FixedPoint &o) const { + return data <= o.data; + } + + bool operator>=(const FixedPoint &o) const { + return data >= o.data; + } + + // Unary operators + bool operator!() const { + return !data; + } + + FixedPoint operator+() const { + return *this; + } + + FixedPoint operator-() const { + FixedPoint f(*this); + f.data = -f.data; + return f; + } + + + // Basic operators + FixedPoint &operator+=(const FixedPoint &n) { + data += n.data; + return *this; + } + + FixedPoint &operator-=(const FixedPoint &n) { + data -= n.data; + return *this; + } + + FixedPoint &operator*=(const FixedPoint &n) { + *this = *this * n; + return *this; + } + + FixedPoint &operator/=(const FixedPoint &n) { + *this = *this / n; + return *this; + } + + + // Conversions + int to_int() const { + return (data >> fractional_bits); + } + + float to_float() const { + return static_cast(data) / FixedPoint::one; + } + + float to_double() const { + return static_cast(data) / FixedPoint::one; + } + + FixedPoint get_fraction() const { + return from_raw(data & fraction_bitmask); + } + + int_type to_raw() const { + return data; + } + + explicit operator float() const { + return to_float(); + } + + explicit operator double() const { + return to_double(); + } + + explicit operator int() const { + return to_int(); + } + + void swap(FixedPoint &rhs) { + std::swap(data, rhs.data); + } +}; + + +// Binary operators +template +FixedPoint operator +(const FixedPoint &lhs, const FixedPoint rhs) { + return FixedPoint::from_raw(lhs.data + rhs.data); +} + +template +FixedPoint operator -(const FixedPoint &lhs, const FixedPoint rhs) { + return FixedPoint::from_raw(lhs.data - rhs.data); +} + +template +FixedPoint operator *(const FixedPoint &lhs, const FixedPoint rhs) { + auto n = lhs.data * rhs.data; + return FixedPoint::from_raw(n >> F); +} + +template +FixedPoint operator /(const FixedPoint &lhs, const FixedPoint rhs) { + auto n = lhs.data << F; + return FixedPoint::from_raw(util::div(n, rhs.data)); +} + + +// N `op` FixedPoint +template +typename std::enable_if::value, FixedPoint>::type +operator +(const N &lhs, const FixedPoint rhs) { + return FixedPoint{ lhs } + rhs; +} +template +typename std::enable_if::value, FixedPoint>::type +operator -(const N &lhs, const FixedPoint rhs) { + return FixedPoint{ lhs } - rhs; +} +template +typename std::enable_if::value, FixedPoint>::type +operator *(const N &lhs, const FixedPoint rhs) { + return FixedPoint{ lhs } * rhs; +} +template +typename std::enable_if::value, FixedPoint>::type +operator /(const N &lhs, const FixedPoint rhs) { + return FixedPoint{ lhs } / rhs; +} + +// FixedPoint `op` N +template +typename std::enable_if::value, FixedPoint>::type +operator +(const FixedPoint lhs, const N &rhs) { + return lhs + FixedPoint{ rhs }; +} +template +typename std::enable_if::value, FixedPoint>::type +operator -(const FixedPoint lhs, const N &rhs) { + return lhs - FixedPoint{ rhs }; +} +template +typename std::enable_if::value, FixedPoint>::type +operator *(const FixedPoint lhs, const N &rhs) { + return lhs * FixedPoint{ rhs }; +} +template +typename std::enable_if::value, FixedPoint>::type +operator /(const FixedPoint lhs, const N &rhs) { + return lhs / FixedPoint{ rhs }; +} + + +// I/O operators +template +std::ostream &operator <<(std::ostream &os, FixedPoint n) { + os << n.data; + return os; +} + +template +std::istream &operator >>(std::istream &is, FixedPoint n) { + is >> n.data; + return is; +} + +} // namespace coord +} // namespace openage + + +// std function overloads +namespace std { + +using openage::coord::FixedPoint; + +template +FixedPoint sqrt(FixedPoint n) { + return FixedPoint { std::sqrt(n.to_double()) }; +} + +template +FixedPoint min(FixedPoint x, FixedPoint y) { + return FixedPoint { std::min(x.data, y.data) }; +} + +template +FixedPoint max(FixedPoint x, FixedPoint y) { + return FixedPoint { std::max(x.data, y.data) }; +} + +template +FixedPoint abs(FixedPoint n) { + return FixedPoint { std::abs(n.data) }; +} + +template +FixedPoint hypot(FixedPoint x, FixedPoint y) { + return FixedPoint { std::hypot(x.to_double(), y.to_double()) }; +} + +template +struct hash> { + size_t operator ()(const openage::coord::FixedPoint &n) const { + return std::hash{}(n.data); + } +}; + +} // namespace std + +#endif diff --git a/cpp/coord/phys2.cpp b/cpp/coord/phys2.cpp index b672af8ee4..e29b52647e 100644 --- a/cpp/coord/phys2.cpp +++ b/cpp/coord/phys2.cpp @@ -18,20 +18,14 @@ phys3_delta phys2_delta::to_phys3(phys_t up) const { } tile phys2::to_tile() const { - tile result; - result.ne = (ne >> settings::phys_t_radix_pos); - result.se = (se >> settings::phys_t_radix_pos); - return result; + return tile{ ne.to_int(), se.to_int() }; } phys2_delta phys2::get_fraction() const { phys2_delta result; - // define a bitmask that keeps the last n bits - decltype(result.ne) bitmask = ((1 << settings::phys_t_radix_pos) - 1); - - result.ne = (ne & bitmask); - result.se = (se & bitmask); + result.ne = ne.get_fraction(); + result.se = se.get_fraction(); return result; } diff --git a/cpp/coord/phys3.cpp b/cpp/coord/phys3.cpp index b7b5cc0ae0..b1ce9e3aff 100644 --- a/cpp/coord/phys3.cpp +++ b/cpp/coord/phys3.cpp @@ -37,37 +37,29 @@ camgame_delta phys3_delta::to_camgame() const { // (ne) // (x) = (+1 +1 +0) (se) // (y) = (+1 -1 +1) (up) - vec2 scaled; - scaled.x = +1 * this->ne +1 * this->se +0 * this->up; - scaled.y = +1 * this->ne -1 * this->se +1 * this->up; + phys_t x = +1 * this->ne +1 * this->se +0 * this->up; + phys_t y = +1 * this->ne -1 * this->se +1 * this->up; //remove scaling factor from scaled, to get result //scaling factor: w/2 for x, h/2 for y //and the (1 << 16) fixed-point scaling factor for both. camgame_delta result; - result.x = (pixel_t) util::div(scaled.x * engine_coord_data->tile_halfsize.x, settings::phys_per_tile); - result.y = (pixel_t) util::div(scaled.y * engine_coord_data->tile_halfsize.y, settings::phys_per_tile); + result.x = static_cast(x * phys_t{engine_coord_data->tile_halfsize.x}); + result.y = static_cast(y * phys_t{engine_coord_data->tile_halfsize.y}); return result; } tile3 phys3::to_tile3() const { - tile3 result; - result.ne = (ne >> settings::phys_t_radix_pos); - result.se = (se >> settings::phys_t_radix_pos); - result.up = (up >> settings::phys_t_radix_pos); - return result; + return tile3 { ne.to_int(), se.to_int(), up.to_int() }; } phys3_delta phys3::get_fraction() { phys3_delta result; - // define a bitmask that keeps the last n bits - decltype(result.ne) bitmask = ((1 << settings::phys_t_radix_pos) - 1); - - result.ne = (ne & bitmask); - result.se = (se & bitmask); - result.up = (up & bitmask); + result.ne = ne.get_fraction(); + result.se = se.get_fraction(); + result.up = up.get_fraction(); return result; } diff --git a/cpp/coord/tests.cpp b/cpp/coord/tests.cpp index b73dc8d0ab..66649e1684 100644 --- a/cpp/coord/tests.cpp +++ b/cpp/coord/tests.cpp @@ -18,6 +18,40 @@ namespace openage { namespace coord { namespace tests { +/** + * This function tests the phys_t type + */ +int phys_t_0() { + phys_t expected; + phys_t results; + + int stage = 0; + if (phys_t{3} + phys_t{5} != phys_t{8}) { return stage; } + + stage = 1; + if (phys_t{1} * phys_t{1} != phys_t{1}) { return stage; } + + stage = 2; + results = phys_t{2}; + results *= phys_t{5}; + if (results != phys_t{10}) { return stage; } + + stage = 3; + if (phys_t{12} / phys_t{4} != phys_t{3}) { return stage; } + + stage = 4; + if (phys_t{1} / phys_t{2} != phys_t::from_raw(32768)) { return stage; } + + stage = 5; + // Test calculations with 2-powers (1/2, 1/4 and 1/8 etc. should be fine) + if (phys_t{0.5f} * phys_t{3} != phys_t{1.5f}) { return stage; } + + stage = 6; + if (phys_t{7} - 1 != phys_t{4} + 2) { return stage; } + + return -1; +} + /** * This function tests the methods of phys2. */ @@ -44,7 +78,7 @@ int phys2_0() { // Test phys size just under a whole tile tile expected_tile{0, 0}; - p = {65535, 65535}; + p = {phys_t::from_raw(65535), phys_t::from_raw(65535)}; tile results_tile = p.to_tile(); if (not (results_tile == expected_tile)) { return stage; } @@ -53,7 +87,7 @@ int phys2_0() { // Test phys size right at a whole tile size expected_tile = {1, 2}; - p = {65536, 131072}; + p = {phys_t::from_raw(65536), phys_t::from_raw(131072)}; results_tile = p.to_tile(); if ( not(results_tile == expected_tile)) { return stage; } @@ -62,7 +96,7 @@ int phys2_0() { // Test phys size in the middle of tile size expected_tile = {1, 2}; - p = {65789, 142311}; + p = {phys_t::from_raw(65789), phys_t::from_raw(142311)}; results_tile = p.to_tile(); if ( not(results_tile == expected_tile)) { return stage; } @@ -71,9 +105,9 @@ int phys2_0() { // Test get fraction // As seen above 65536 is a whole tile, so here test getting the // Fraction with the whole tiles removed - phys2_delta expected_p2d{32768, 32768}; + phys2_delta expected_p2d{phys_t::from_raw(32768), phys_t::from_raw(32768)}; - p = {98304, 98304}; + p = {phys_t::from_raw(98304), phys_t::from_raw(98304)}; phys2_delta results_p2d = p.get_fraction(); if (not (results_p2d == expected_p2d)) { return stage; } @@ -132,7 +166,7 @@ int tile_0() { stage += 1; // 3 // Test to_phys2 with default arg - phys2 expected_p2{32768, 32768}; + phys2 expected_p2{phys_t::from_raw(32768), phys_t::from_raw(32768)}; t = {0, 0}; @@ -142,7 +176,7 @@ int tile_0() { stage += 1; // 4 // Test to_phys with default arg and non zero tile - expected_p2 = {98304, 98304}; + expected_p2 = {phys_t::from_raw(98304), phys_t::from_raw(98304)}; t = {1, 1}; @@ -152,11 +186,11 @@ int tile_0() { stage += 1; // 5 // Test to_phys with arg - expected_p2 = {16384, 16384}; + expected_p2 = {phys_t::from_raw(16384), phys_t::from_raw(16384)}; t = {0, 0}; - results_p2 = t.to_phys2({16384, 16384}); + results_p2 = t.to_phys2({phys_t::from_raw(16384), phys_t::from_raw(16384)}); if (not (results_p2 == expected_p2)) { return stage; } stage += 1; // 6 @@ -254,7 +288,7 @@ int tile_and_phys2_0() { // Test convert phys2 to tile and back, phys under whole tile size phys2 expected_p2{0, 0}; - phys2 p2{65535, 65535}; + phys2 p2{phys_t::from_raw(65535), phys_t::from_raw(65535)}; phys2 results_p2 = p2.to_tile().to_phys2({0, 0}); if (not (results_p2 == expected_p2)) { return stage; } @@ -262,8 +296,8 @@ int tile_and_phys2_0() { stage += 1; // 3 // Test convert phys2 to tile and back, phys at whole tile size - expected_p2 = {65536, 65536}; - p2 = {65536, 65536}; + expected_p2 = {phys_t::from_raw(65536), phys_t::from_raw(65536)}; + p2 = {phys_t::from_raw(65536), phys_t::from_raw(65536)}; results_p2 = p2.to_tile().to_phys2({0, 0}); if (not (results_p2 == expected_p2)) { return stage; } @@ -340,7 +374,7 @@ int phys3_0() { // we should see -96 in x from moving one ne and one se // then -24 from moving one up expected_c = {-96, -24}; - engine_coord_data->camgame_phys = {720896, 720896, 65536}; + engine_coord_data->camgame_phys = {phys_t::from_raw(720896), phys_t::from_raw(720896), phys_t::from_raw(65536)}; results_c = gameP3.to_camgame(); if( not(results_c == expected_c)) { return stage; } @@ -349,7 +383,7 @@ int phys3_0() { // Testing phys3 to tile3 just under a whole tile size tile3 expected_tile{0, 0, 0}; - p3 = {65535, 65535, 65535}; + p3 = {0.99f, 0.99f, 0.99f}; tile3 results_tile = p3.to_tile3(); if (not(results_tile == expected_tile)) { return stage; } @@ -358,7 +392,7 @@ int phys3_0() { // Testing phys3 to tile3 at whole tile sizes expected_tile = {1, 2, 3}; - p3 = {65536, 131072, 196608}; + p3 = {phys_t::from_raw(65536), phys_t::from_raw(131072), phys_t::from_raw(196608)}; results_tile = p3.to_tile3(); if( not(results_tile == expected_tile)) { return stage; } @@ -367,7 +401,7 @@ int phys3_0() { // Testing phys3 to tile3 above whole tile sizes expected_tile = {1, 2, 3}; - p3 = {85641, 171072, 205465}; + p3 = {phys_t::from_raw(85641), phys_t::from_raw(171072), phys_t::from_raw(205465)}; results_tile = p3.to_tile3(); if( not(results_tile == expected_tile)) { return stage; } @@ -375,8 +409,8 @@ int phys3_0() { stage += 1; // 6 // Testing phys3 get_fraction just below whole tile size - phys3_delta expected_p3d{65535, 65535, 65535}; - p3 = {65535, 131071, 196607}; + phys3_delta expected_p3d{phys_t::from_raw(65535), phys_t::from_raw(65535), phys_t::from_raw(65535)}; + p3 = {phys_t::from_raw(65535), phys_t::from_raw(131071), phys_t::from_raw(196607)}; phys3_delta results_p3d = p3.get_fraction(); if( not(results_p3d == expected_p3d)) { return stage; } @@ -385,16 +419,16 @@ int phys3_0() { // Testing phys3 get_fraction at whole tile size expected_p3d = {0, 0, 0}; - p3 = {65536, 131072, 196608}; + p3 = {phys_t::from_raw(65536), phys_t::from_raw(131072), phys_t::from_raw(196608)}; results_p3d = p3.get_fraction(); if( not(results_p3d == expected_p3d)) { return stage; } - stage += 1; // 7 + stage += 1; // 8 // Testing phys3 get_fraction above whole tile size - expected_p3d = {1, 1, 1}; - p3 = {65537, 131073, 196609}; + expected_p3d = {phys_t::from_raw(1), phys_t::from_raw(1), phys_t::from_raw(1)}; + p3 = {phys_t::from_raw(65537), phys_t::from_raw(131073), phys_t::from_raw(196609)}; results_p3d = p3.get_fraction(); if( not(results_p3d == expected_p3d)) { return stage; } @@ -412,7 +446,7 @@ int phys3_delta_0() { // phys3_delta to camgame_delta 1 tile ne camgame_delta expected_cd{48, 24}; - phys3_delta p3d{65536, 0, 0}; + phys3_delta p3d{1, 0, 0}; camgame_delta results_cd = p3d.to_camgame(); if( not(results_cd == expected_cd)) { return stage; } @@ -421,7 +455,7 @@ int phys3_delta_0() { // Testing that se has the same effect on x and negative on y expected_cd = {48, -24}; - p3d = {0, 65536, 0}; + p3d = {0, 1, 0}; results_cd = p3d.to_camgame(); if( not(results_cd == expected_cd)) { return stage; } @@ -430,7 +464,7 @@ int phys3_delta_0() { // Testing that up effects y only expected_cd = {0, 24}; - p3d = {0, 0, 65536}; + p3d = {0, 0, 1}; results_cd = p3d.to_camgame(); if( not(results_cd == expected_cd)) { return stage; } @@ -439,7 +473,7 @@ int phys3_delta_0() { // Testing ne and se add on x and cancel on y expected_cd = {96, 0}; - p3d = {65536, 65536, 0}; + p3d = {1, 1, 0}; results_cd = p3d.to_camgame(); if( not(results_cd == expected_cd)) { return stage; } @@ -472,7 +506,7 @@ int tile3_0() { stage += 1; // 1 // Tests tile3 to phys3 with default arg - phys3 expected_p3{32768, 32768, 0}; + phys3 expected_p3{0.5f, 0.5f, 0}; t3 = {0, 0, 0}; phys3 results_p3 = t3.to_phys3(); @@ -489,7 +523,7 @@ int tile3_0() { stage += 1; // 3 // Test tile3 to phys3 with args - expected_p3 = {65536, 131072, 196608}; + expected_p3 = {1, 2, 3}; t3 = {1, 2, 3}; results_p3 = t3.to_phys3({0, 0, 0}); @@ -509,7 +543,7 @@ int camgame_0() { coord_data* engine_coord_data{ Engine::get_coord_data() }; // Reset camgame_phys to its normal starting value - engine_coord_data->camgame_phys = {655360, 655360, 0}; + engine_coord_data->camgame_phys = {10, 10, 0}; phys3 expected_p3 = engine_coord_data->camgame_phys; camgame c{0, 0}; @@ -523,34 +557,34 @@ int camgame_0() { // plus ((1 pixel / 48(px per tile)) * 65536 phys per tile ) / 2 // for both the ne and se components since we only added x. // Also this get rounded down so we end up adding 682 to ne and se - expected_p3 = {656042, 656042, 0}; + expected_p3 = {phys_t::from_raw(656042), phys_t::from_raw(656042), 0}; c = {1, 0}; results_p3 = c.to_phys3(); if( not(results_p3 == expected_p3)) { return stage; } stage += 1; // 2 - // Test camgame to phys3 with default arg and y=1 for camagame + // Test camgame to phys3 with default arg and y=1 for camgame // This is the base camgame_phys position {655360, 655360, 0} // plus ((1 pixel / 24(px per tile)) * 65536 phys per tile ) / 2 // this add to ne and subracted from se // Also this get rounded down so we end up adding 1365 to ne and se - expected_p3 = {656725, 653995, 0}; + expected_p3 = {phys_t::from_raw(656725), phys_t::from_raw(653995), 0}; c = {0, 1}; results_p3 = c.to_phys3(); if( not(results_p3 == expected_p3)) { return stage; } stage += 1; // 3 - // Test camgame to phys3 with a pased arg + // Test camgame to phys3 with a passed arg // Here we start with the same ne and se ad before but we add/subract // the passed arg divided by 2. The passed arg is also applied directly // to the up component - expected_p3 = {656726, 653994, 2}; + expected_p3 = {phys_t::from_raw(656726), phys_t::from_raw(653994), phys_t::from_raw(2)}; - results_p3 = c.to_phys3(2); + results_p3 = c.to_phys3(phys_t::from_raw(2)); if( not(results_p3 == expected_p3)) { return stage; } stage += 1; // 4 @@ -593,7 +627,7 @@ int camgame_delta_0() { // This is ((1 pixel / 48(px per tile)) * 65536 phys per tile ) / 2 // for both the ne and se components since we only added x. // Also this get rounded down so we end up adding 682 to ne and se - expected_p3d = {682, 682, 0}; + expected_p3d = {phys_t::from_raw(682), phys_t::from_raw(682), 0}; cd = {1, 0}; results_p3d = cd.to_phys3(); @@ -605,7 +639,7 @@ int camgame_delta_0() { // This is ((1 pixel / 24(px per tile)) * 65536 phys per tile ) / 2 // this add to ne and subracted frim se // Also this get rounded down so we end up adding 1365 to ne and se - expected_p3d = {1365, -1365, 0}; + expected_p3d = {phys_t::from_raw(1365), phys_t::from_raw(-1365), 0}; cd = {0, 1}; results_p3d = cd.to_phys3(); @@ -617,9 +651,9 @@ int camgame_delta_0() { // Here we start with the same ne and se ad before but we add/subract // the passed arg divided by 2. The passed arg is also applied directly // to the up component - expected_p3d = {1366, -1366, 2}; + expected_p3d = {phys_t::from_raw(1366), phys_t::from_raw(-1366), phys_t::from_raw(2)}; - results_p3d = cd.to_phys3(2); + results_p3d = cd.to_phys3(phys_t::from_raw(2)); if( not(results_p3d == expected_p3d)) { return stage; } stage += 1; // 4 @@ -736,6 +770,11 @@ void coord() { int ret; const char *testname; + if ((ret = phys_t_0()) != -1) { + testname = "phys_t test"; + goto out; + } + if ((ret = phys2_0()) != -1) { testname = "phys2 test"; goto out; diff --git a/cpp/coord/tile.cpp b/cpp/coord/tile.cpp index 77b36b6908..f08501d492 100644 --- a/cpp/coord/tile.cpp +++ b/cpp/coord/tile.cpp @@ -20,15 +20,15 @@ tile3_delta tile_delta::to_tile3(tile_t up) const { phys2 tile::to_phys2(phys2_delta frac) const { phys2 result; - result.ne = (((phys_t) ne) << settings::phys_t_radix_pos) + frac.ne; - result.se = (((phys_t) se) << settings::phys_t_radix_pos) + frac.se; + result.ne = phys_t{ne} + frac.ne; + result.se = phys_t{se} + frac.se; return result; } chunk tile::to_chunk() const { chunk result; - result.ne = (ne >> settings::tiles_per_chunk_bits); - result.se = (se >> settings::tiles_per_chunk_bits); + result.ne = ne / chunk::tiles_per_chunk; + result.se = se / chunk::tiles_per_chunk; return result; } @@ -42,11 +42,8 @@ tile tile_delta::to_tile() { tile_delta tile::get_pos_on_chunk() const { tile_delta result; - // define a bitmask that keeps the last n bits - decltype(result.ne) bitmask = ((1 << settings::tiles_per_chunk_bits) - 1); - - result.ne = (ne & bitmask); - result.se = (se & bitmask); + result.ne = ne % chunk::tiles_per_chunk; + result.se = se % chunk::tiles_per_chunk; return result; } diff --git a/cpp/coord/tile.h b/cpp/coord/tile.h index 6c7d6c4547..b7f1e04895 100644 --- a/cpp/coord/tile.h +++ b/cpp/coord/tile.h @@ -23,7 +23,7 @@ struct tile { #include "ops/abs.h" tile3 to_tile3(tile_t up = 0) const; - phys2 to_phys2(phys2_delta frac = {settings::phys_per_tile / 2, settings::phys_per_tile / 2}) const; + phys2 to_phys2(phys2_delta frac = {0.5f, 0.5f}) const; chunk to_chunk() const; tile_delta get_pos_on_chunk() const; }; diff --git a/cpp/coord/tile3.cpp b/cpp/coord/tile3.cpp index 7847b65a32..8070333625 100644 --- a/cpp/coord/tile3.cpp +++ b/cpp/coord/tile3.cpp @@ -19,9 +19,9 @@ tile_delta tile3_delta::to_tile() const { phys3 tile3::to_phys3(phys3_delta frac) { phys3 result; - result.ne = (((phys_t) ne) << settings::phys_t_radix_pos) + frac.ne; - result.se = (((phys_t) se) << settings::phys_t_radix_pos) + frac.se; - result.up = (((phys_t) up) << settings::phys_t_radix_pos) + frac.up; + result.ne = phys_t{ne} + frac.ne; + result.se = phys_t{se} + frac.se; + result.up = phys_t{up} + frac.up; return result; } diff --git a/cpp/coord/tile3.h b/cpp/coord/tile3.h index 8291b054d2..6e91a8dbdc 100644 --- a/cpp/coord/tile3.h +++ b/cpp/coord/tile3.h @@ -20,7 +20,7 @@ struct tile3 { #include "ops/abs.h" tile to_tile() const; - phys3 to_phys3(phys3_delta frac = {settings::phys_per_tile / 2, settings::phys_per_tile / 2, 0}); + phys3 to_phys3(phys3_delta frac = {0.5f, 0.5f, 0}); }; struct tile3_delta { diff --git a/cpp/engine.h b/cpp/engine.h index 3de42a7822..ec3fd73ca9 100644 --- a/cpp/engine.h +++ b/cpp/engine.h @@ -32,7 +32,7 @@ class ResizeHandler; struct coord_data { coord::window window_size{800, 600}; - coord::phys3 camgame_phys{10 * coord::settings::phys_per_tile, 10 * coord::settings::phys_per_tile, 0}; + coord::phys3 camgame_phys{10, 10, 0}; coord::window camgame_window{400, 300}; coord::window camhud_window{0, 600}; coord::camgame_delta tile_halfsize{48, 24}; // TODO: get from convert script diff --git a/cpp/game_main.cpp b/cpp/game_main.cpp index 4280775c9f..04bcf74e01 100644 --- a/cpp/game_main.cpp +++ b/cpp/game_main.cpp @@ -419,13 +419,11 @@ bool GameMain::on_input(SDL_Event *e) { " x " << std::setw(9) << mousepos_window.x << " y " << std::setw(9) << mousepos_window.y); - constexpr auto phys_per_tile = openage::coord::settings::phys_per_tile; - log::log(MSG(dbg) << "LMB [phys3]: " - " NE " << util::FixedPoint{mousepos_phys3.ne} << - " SE " << util::FixedPoint{mousepos_phys3.se} << - " UP " << util::FixedPoint{mousepos_phys3.up}); + " NE " << util::FloatFixed<3, 8>{mousepos_phys3.ne.to_float()} << + " SE " << util::FloatFixed<3, 8>{mousepos_phys3.se.to_float()} << + " UP " << util::FloatFixed<3, 8>{mousepos_phys3.up.to_float()}); log::log(MSG(dbg) << "LMB [tile]: " diff --git a/cpp/game_save.cpp b/cpp/game_save.cpp index 43957c3872..d5a13c49a6 100644 --- a/cpp/game_save.cpp +++ b/cpp/game_save.cpp @@ -29,7 +29,7 @@ void load_unit(std::ifstream &file, openage::GameMain *game) { file >> se; UnitType &saved_type = *game->datamanager.get_type(pr_id); - game->placed_units.new_unit(saved_type, game->players[player_no], coord::tile{ne, se}.to_phys2().to_phys3()); + game->placed_units.new_unit(saved_type, game->players[player_no], coord::tile{ne.to_int(), se.to_int()}.to_phys2().to_phys3()); } void save_tile_content(std::ofstream &file, openage::TileContent *content) { diff --git a/cpp/pathfinding/a_star.cpp b/cpp/pathfinding/a_star.cpp index e7fa7dd26b..abb3fde355 100644 --- a/cpp/pathfinding/a_star.cpp +++ b/cpp/pathfinding/a_star.cpp @@ -32,7 +32,7 @@ Path to_point(coord::phys3 start, auto valid_end = [&](const coord::phys3 &point) -> bool { coord::phys_t dx = point.ne - end.ne; coord::phys_t dy = point.se - end.se; - return std::hypot(dx, dy) < path_grid_size; + return std::hypot(dx, dy).to_float() < path_grid_size; }; auto h = [&](const coord::phys3 &point) -> cost_t { return euclidean_cost(point, end); }; return a_star(start, valid_end, h, passable); @@ -47,7 +47,7 @@ Path to_object(openage::TerrainObject *to_move, return end->from_edge(pos) < rad; }; auto heuristic = [&](const coord::phys3 &pos) -> cost_t { - return end->from_edge(pos) - to_move->min_axis() / 2; + return static_cast(end->from_edge(pos) - (to_move->min_axis() / 2)); }; return a_star(start, valid_end, heuristic, to_move->passable); } @@ -93,7 +93,7 @@ Path a_star(coord::phys3 start, if (valid_end(best_candidate->position)) { log::log(MSG(dbg) << "path cost is " << - util::FloatFixed<3, 8>{closest_node->future_cost / coord::settings::phys_per_tile}); + util::FloatFixed<3, 8>{ coord::phys_t {closest_node->future_cost}.to_float() }); return best_candidate->generate_backtrace(); } @@ -142,7 +142,7 @@ Path a_star(coord::phys3 start, log::log(MSG(dbg) << "incomplete path cost is " << - util::FloatFixed<3, 8>{closest_node->future_cost / coord::settings::phys_per_tile}); + util::FloatFixed<3, 8>{ coord::phys_t {closest_node->future_cost}.to_float()}); return closest_node->generate_backtrace(); } diff --git a/cpp/pathfinding/heuristics.cpp b/cpp/pathfinding/heuristics.cpp index b54283cc4a..2bf79167de 100644 --- a/cpp/pathfinding/heuristics.cpp +++ b/cpp/pathfinding/heuristics.cpp @@ -1,4 +1,4 @@ -// Copyright 2014-2014 the openage authors. See copying.md for legal info. +// Copyright 2014-2015 the openage authors. See copying.md for legal info. #include "heuristics.h" @@ -9,21 +9,21 @@ namespace openage { namespace path { cost_t manhattan_cost(const coord::phys3 &start, const coord::phys3 &end) { - cost_t dx = std::abs((cost_t)start.ne - end.ne); - cost_t dy = std::abs((cost_t)start.se - end.se); - return dx + dy; + coord::phys_t dx = std::abs(start.ne - end.ne); + coord::phys_t dy = std::abs(start.se - end.se); + return static_cast(dx + dy); } cost_t chebyshev_cost(const coord::phys3 &start, const coord::phys3 &end) { - cost_t dx = start.ne - end.ne; - cost_t dy = start.se - end.se; - return std::max(dx, dy); + coord::phys_t dx = start.ne - end.ne; + coord::phys_t dy = start.se - end.se; + return static_cast(std::max(dx, dy)); } cost_t euclidean_cost(const coord::phys3 &start, const coord::phys3 &end) { - cost_t dx = start.ne - end.ne; - cost_t dy = start.se - end.se; - return std::hypot(dx, dy); + coord::phys_t dx = start.ne - end.ne; + coord::phys_t dy = start.se - end.se; + return static_cast(std::hypot(dx, dy)); } } // namespace path diff --git a/cpp/pathfinding/path.cpp b/cpp/pathfinding/path.cpp index 0a870d419a..215ba550e3 100644 --- a/cpp/pathfinding/path.cpp +++ b/cpp/pathfinding/path.cpp @@ -27,8 +27,8 @@ Node::Node(const coord::phys3 &pos, node_pt prev) heap_node(nullptr) { if (prev) { - cost_t dx = this->position.ne - prev->position.ne; - cost_t dy = this->position.se - prev->position.se; + cost_t dx = static_cast(this->position.ne - prev->position.ne); + cost_t dy = static_cast(this->position.se - prev->position.se); cost_t hyp = std::hypot(dx, dy); this->dir_ne = dx / hyp; this->dir_se = dy / hyp; @@ -59,9 +59,9 @@ bool Node::operator ==(const Node &other) const { } cost_t Node::cost_to(const Node &other) const { - cost_t dx = this->position.ne - other.position.ne; - cost_t dy = this->position.se - other.position.se; - return std::hypot(dx, dy) * other.factor * this->factor; + coord::phys_t dx = this->position.ne - other.position.ne; + coord::phys_t dy = this->position.se - other.position.se; + return static_cast(std::hypot(dx, dy)) * other.factor * this->factor; } Path Node::generate_backtrace() { @@ -97,10 +97,11 @@ bool passable_line(node_pt start, node_pt end, std::functionposition.ne + percent * end->position.ne; - coord::phys_t se = (1.0 - percent) * start->position.se + percent * end->position.se; - coord::phys_t up = (1.0 - percent) * start->position.up + percent * end->position.up; + coord::phys_t percent = coord::phys_t {(double) i / samples}; + + coord::phys_t ne = (1 - percent) * start->position.ne + percent * end->position.ne; + coord::phys_t se = (1 - percent) * start->position.se + percent * end->position.se; + coord::phys_t up = (1 - percent) * start->position.up + percent * end->position.up; if (!passable(coord::phys3{ne, se, up})) { return false; diff --git a/cpp/pathfinding/path.h b/cpp/pathfinding/path.h index 55d472c46a..7e80fc7c46 100644 --- a/cpp/pathfinding/path.h +++ b/cpp/pathfinding/path.h @@ -56,7 +56,7 @@ using heap_t = datastructure::PairingHeap; * * This equals a node grid size of (phys/tile) / 8. */ -constexpr int path_grid_size = coord::settings::phys_per_tile >> 3; +constexpr float path_grid_size = 1 / 8.0f; /** * Phys3 delta coordinates to select for path neighbors. diff --git a/cpp/terrain/terrain_object.cpp b/cpp/terrain/terrain_object.cpp index 77305413a4..5c01e1b2e4 100644 --- a/cpp/terrain/terrain_object.cpp +++ b/cpp/terrain/terrain_object.cpp @@ -369,7 +369,7 @@ bool SquareObject::intersects(const TerrainObject &other, const coord::phys3 &po } coord::phys_t SquareObject::min_axis() const { - return std::min( this->size.ne, this->size.se ) * coord::settings::phys_per_tile; + return coord::phys_t{std::min( this->size.ne, this->size.se )}; } RadialObject::RadialObject(Unit &u, float rad) @@ -380,7 +380,7 @@ RadialObject::RadialObject(Unit &u, float rad) RadialObject::RadialObject(Unit &u, float rad, std::shared_ptr out_tex) : TerrainObject(u), - phys_radius(coord::settings::phys_per_tile * rad) { + phys_radius(rad) { this->outline_texture = out_tex; } @@ -458,8 +458,8 @@ tile_range building_center(coord::phys3 west, coord::tile_delta size) { // TODO temporary hacky solution until openage::coord has been properly fixed. coord::phys2 draw_pos = result.start.to_phys2(); - draw_pos.ne += ((size.ne - 1) * coord::settings::phys_per_tile) / 2; - draw_pos.se += ((size.se - 1) * coord::settings::phys_per_tile) / 2; + draw_pos.ne += coord::phys_t{size.ne - 1} / 2; + draw_pos.se += coord::phys_t{size.se - 1} / 2; result.draw = draw_pos.to_phys3(); return result; diff --git a/cpp/terrain/terrain_object.h b/cpp/terrain/terrain_object.h index 12d99c3f00..d180b39567 100644 --- a/cpp/terrain/terrain_object.h +++ b/cpp/terrain/terrain_object.h @@ -60,8 +60,8 @@ tile_range building_center(coord::phys3 west, coord::tile_delta size); * half a tile */ constexpr coord::phys3_delta phys_half_tile = coord::phys3_delta{ - coord::settings::phys_per_tile / 2, - coord::settings::phys_per_tile / 2, + 0.5f, + 0.5f, 0 }; diff --git a/cpp/unit/action.cpp b/cpp/unit/action.cpp index c6f6d04e8e..5f32a69406 100644 --- a/cpp/unit/action.cpp +++ b/cpp/unit/action.cpp @@ -484,7 +484,7 @@ void MoveAction::update(unsigned int time) { coord::phys3_delta move_dir = waypoint - new_position; // normalise dir - coord::phys_t distance_to_waypoint = (coord::phys_t) std::hypot(move_dir.ne, move_dir.se); + coord::phys_t distance_to_waypoint = std::hypot(move_dir.ne, move_dir.se); if (distance_to_waypoint <= distance_to_move) { distance_to_move -= distance_to_waypoint; @@ -574,7 +574,7 @@ void MoveAction::set_distance() { } else { coord::phys3_delta move_dir = this->target - this->entity->location->pos.draw; - this->distance_to_target = static_cast(std::hypot(move_dir.ne, move_dir.se)); + this->distance_to_target = std::hypot(move_dir.ne, move_dir.se); } } @@ -906,8 +906,8 @@ ProjectileAction::ProjectileAction(Unit *e, coord::phys3 target) // distance and time to target coord::phys3_delta d = target - this->entity->location->pos.draw; - coord::phys_t distance_to_target = (coord::phys_t) std::hypot(d.ne, d.se); - int flight_time = distance_to_target / projectile_speed; + coord::phys_t distance_to_target = std::hypot(d.ne, d.se); + int flight_time = (distance_to_target / projectile_speed).to_int(); if (projectile_arc < 0) { diff --git a/cpp/unit/producer.cpp b/cpp/unit/producer.cpp index 3de805e225..1cdeaa0005 100644 --- a/cpp/unit/producer.cpp +++ b/cpp/unit/producer.cpp @@ -352,14 +352,14 @@ void MovableProducer::initialise(Unit *unit, Player &player) { * distance per millisecond -- consider original game speed * where 1.5 in game seconds pass in 1 real second */ - coord::phys_t sp = this->unit_data.speed * coord::settings::phys_per_tile / 666; + coord::phys_t sp = coord::phys_t{this->unit_data.speed} * 666; unit->add_attribute(new Attribute(sp)); // projectile of melee attacks if (this->unit_data.projectile_unit_id > 0 && this->projectile) { // calculate requirements for ranged attacks - coord::phys_t range_phys = coord::settings::phys_per_tile * this->unit_data.max_range; + coord::phys_t range_phys = coord::phys_t{this->unit_data.max_range}; unit->add_attribute(new Attribute(this->projectile, range_phys, 48000, 1, this->graphics)); } else { @@ -528,7 +528,7 @@ void BuildingProducer::initialise(Unit *unit, Player &player) { unit->push_action(std::make_unique(unit, has_destruct_graphic), true); if (this->unit_data.projectile_unit_id > 0 && this->projectile) { - coord::phys_t range_phys = coord::settings::phys_per_tile * this->unit_data.max_range; + coord::phys_t range_phys = coord::phys_t{this->unit_data.max_range}; unit->add_attribute(new Attribute(this->projectile, range_phys, 350000, 1, this->graphics)); unit->give_ability(std::make_shared()); } @@ -588,8 +588,8 @@ TerrainObject *BuildingProducer::place(Unit *u, std::shared_ptr terrain // make objects for annex coord::phys3 a_pos = u->location->pos.draw; - a_pos.ne += annex.misplaced0 * coord::settings::phys_per_tile; - a_pos.se += annex.misplaced1 * coord::settings::phys_per_tile; + a_pos.ne += coord::phys_t{annex.misplaced0}; + a_pos.se += coord::phys_t{annex.misplaced1}; this->make_annex(*u, terrain, annex.unit_id, a_pos, i == 0); } } @@ -613,8 +613,8 @@ TerrainObject *BuildingProducer::make_annex(Unit &u, std::shared_ptr t, // producers place by the nw tile coord::phys3 start_tile = annex_pos; - start_tile.ne -= b->radius_size0 * coord::settings::phys_per_tile; - start_tile.se -= b->radius_size1 * coord::settings::phys_per_tile; + start_tile.ne -= coord::phys_t{b->radius_size0}; + start_tile.se -= coord::phys_t{b->radius_size1}; // create and place on terrain TerrainObject *annex_loc = u.location->make_annex(annex_foundation); @@ -678,7 +678,7 @@ void ProjectileProducer::initialise(Unit *unit, Player &) { unit->graphics = &this->graphics; // projectile speed - coord::phys_t sp = this->unit_data.speed * coord::settings::phys_per_tile / 666; + coord::phys_t sp = coord::phys_t{this->unit_data.speed} / 666; unit->add_attribute(new Attribute(sp)); unit->add_attribute(new Attribute(this->unit_data.projectile_arc)); unit->add_attribute(new Attribute(coord::phys3_delta{ 1, 0, 0 })); diff --git a/cpp/unit/unit_texture.cpp b/cpp/unit/unit_texture.cpp index 8d6af7f76a..bf5e30da98 100644 --- a/cpp/unit/unit_texture.cpp +++ b/cpp/unit/unit_texture.cpp @@ -98,8 +98,8 @@ void UnitTexture::draw(const coord::camgame &draw_pos, coord::phys3_delta &dir, // up 1 => tilt 0 // up -1 => tilt 1 // up has a scale 5 times smaller - double len = sqrt(dir.ne*dir.ne + dir.se*dir.se + dir.up*dir.up/25); - double up = static_cast(dir.up/5.0) / len; + coord::phys_t len = std::sqrt(dir.ne*dir.ne + dir.se*dir.se + dir.up*dir.up/25); + double up = static_cast((dir.up/5.0) / len); frame_to_use = (0.5 - (0.5 * up)) * this->frame_count; } else if (this->sound && frame == 0.0) { @@ -145,9 +145,9 @@ unsigned int dir_group(coord::phys3_delta dir, unsigned int angles) { unsigned int first_angle = 5 * angles / 8; // normalise direction vector - double len = std::hypot(dir.ne, dir.se); - double dir_ne = static_cast(dir.ne) / len; - double dir_se = static_cast(dir.se) / len; + coord::phys_t len = std::hypot(dir.ne, dir.se); + double dir_ne = static_cast(dir.ne / len); + double dir_se = static_cast(dir.se / len); // formula to find the correct angle return static_cast( diff --git a/cpp/util/strings.h b/cpp/util/strings.h index d91bf3801f..ca61c03b1d 100644 --- a/cpp/util/strings.h +++ b/cpp/util/strings.h @@ -66,21 +66,6 @@ std::ostream &operator <<(std::ostream &os, FloatFixed f) { } -template -struct FixedPoint { - int64_t value; -}; - - -template -std::ostream &operator <<(std::ostream &os, FixedPoint f) { - static_assert(divisor > 0, "Divisor for fixed-point numbers must be > 0"); - - os << FloatFixed{((float) f.value) / (float) divisor}; - return os; -} - - /** * Formats fmt to a std::string */