Fix rounding error in g/set_node caused by truncation to float
authorrubenwardy <rw@rubenwardy.com>
Fri, 22 Dec 2017 10:00:57 +0000 (10:00 +0000)
committerSmallJoker <mk939@ymail.com>
Sun, 3 Jun 2018 15:32:00 +0000 (17:32 +0200)
src/irr_v3d.h
src/script/common/c_converter.cpp
src/util/numeric.h

index fa6af36611c79d4285ce04a3ccd80e68b8193bce..3a8d1fd308101691396ab60d35070bc77f531aa3 100644 (file)
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <vector3d.h>
 
 typedef core::vector3df v3f;
+typedef core::vector3d<double> v3d;
 typedef core::vector3d<s16> v3s16;
 typedef core::vector3d<u16> v3u16;
 typedef core::vector3d<s32> v3s32;
index fc516d56a9acf5f03bbc99348d1939be0b818e0a..d9b926e3eae0c2f75102ef217331be8a5d306fc3 100644 (file)
@@ -196,6 +196,44 @@ v3f check_v3f(lua_State *L, int index)
        return pos;
 }
 
+v3d read_v3d(lua_State *L, int index)
+{
+       v3d pos;
+       CHECK_POS_TAB(index);
+       lua_getfield(L, index, "x");
+       pos.X = lua_tonumber(L, -1);
+       lua_pop(L, 1);
+       lua_getfield(L, index, "y");
+       pos.Y = lua_tonumber(L, -1);
+       lua_pop(L, 1);
+       lua_getfield(L, index, "z");
+       pos.Z = lua_tonumber(L, -1);
+       lua_pop(L, 1);
+       return pos;
+}
+
+v3d check_v3d(lua_State *L, int index)
+{
+       v3d pos;
+       CHECK_POS_TAB(index);
+       lua_getfield(L, index, "x");
+       CHECK_POS_COORD("x");
+       pos.X = lua_tonumber(L, -1);
+       CHECK_FLOAT_RANGE(pos.X, "x")
+       lua_pop(L, 1);
+       lua_getfield(L, index, "y");
+       CHECK_POS_COORD("y");
+       pos.Y = lua_tonumber(L, -1);
+       CHECK_FLOAT_RANGE(pos.Y, "y")
+       lua_pop(L, 1);
+       lua_getfield(L, index, "z");
+       CHECK_POS_COORD("z");
+       pos.Z = lua_tonumber(L, -1);
+       CHECK_FLOAT_RANGE(pos.Z, "z")
+       lua_pop(L, 1);
+       return pos;
+}
+
 void push_ARGB8(lua_State *L, video::SColor color)
 {
        lua_newtable(L);
@@ -234,15 +272,15 @@ void push_v3s16(lua_State *L, v3s16 p)
 v3s16 read_v3s16(lua_State *L, int index)
 {
        // Correct rounding at <0
-       v3f pf = read_v3f(L, index);
-       return floatToInt(pf, 1.0);
+       v3d pf = read_v3d(L, index);
+       return doubleToInt(pf, 1.0);
 }
 
 v3s16 check_v3s16(lua_State *L, int index)
 {
        // Correct rounding at <0
-       v3f pf = check_v3f(L, index);
-       return floatToInt(pf, 1.0);
+       v3d pf = check_v3d(L, index);
+       return doubleToInt(pf, 1.0);
 }
 
 bool read_color(lua_State *L, int index, video::SColor *color)
index 4a27f657d23faab74a8a82d584f97c278b4906fc..573f03788c17cfde2f99402799d2a4984b23b955 100644 (file)
@@ -254,6 +254,17 @@ inline v3s16 floatToInt(v3f p, f32 d)
                (p.Z + (p.Z > 0 ? d / 2 : -d / 2)) / d);
 }
 
+/*
+       Returns integer position of node in given double precision position
+ */
+inline v3s16 doubleToInt(v3d p, double d)
+{
+       return v3s16(
+               (p.X + (p.X > 0 ? d / 2 : -d / 2)) / d,
+               (p.Y + (p.Y > 0 ? d / 2 : -d / 2)) / d,
+               (p.Z + (p.Z > 0 ? d / 2 : -d / 2)) / d);
+}
+
 /*
        Returns floating point position of node in given integer position
 */