diff options
Diffstat (limited to '')
-rw-r--r-- | Server/Plugins/APIDump/Classes/Geometry.lua | 15 | ||||
-rw-r--r-- | Server/Plugins/Debuggers/Debuggers.lua | 46 | ||||
-rw-r--r-- | Server/Plugins/Debuggers/Info.lua | 6 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.cpp | 80 | ||||
-rw-r--r-- | src/BoundingBox.cpp | 4 | ||||
-rw-r--r-- | src/BoundingBox.h | 25 |
6 files changed, 164 insertions, 12 deletions
diff --git a/Server/Plugins/APIDump/Classes/Geometry.lua b/Server/Plugins/APIDump/Classes/Geometry.lua index 36bd222a6..8f2f76849 100644 --- a/Server/Plugins/APIDump/Classes/Geometry.lua +++ b/Server/Plugins/APIDump/Classes/Geometry.lua @@ -29,9 +29,22 @@ return { Params = "{{Vector3d|Pos}}, Radius, Height", Return = "cBoundingBox", Notes = "Creates a new bounding box from the position given and radius (X/Z) and height. Radius is added from X/Z to calculate the maximum coords and subtracted from X/Z to get the minimum; minimum Y is set to Pos.y and maxumim Y to Pos.y plus Height. This corresponds with how {{cEntity|entities}} are represented in Minecraft." }, { Params = "OtherBoundingBox", Return = "cBoundingBox", Notes = "Creates a new copy of the given bounding box. Same result can be achieved by using a simple assignment." }, }, - CalcLineIntersection = { Params = "{{Vector3d|LineStart}}, {{Vector3d|LinePt2}}", Return = "DoesIntersect, LineCoeff, Face", Notes = "Calculates the intersection of a ray (half-line), given by two of its points, with the bounding box. Returns false if the line doesn't intersect the bounding box, or true, together with coefficient of the intersection (how much of the difference between the two ray points is needed to reach the intersection), and the face of the box which is intersected.<br /><b>TODO</b>: Lua binding for this function is wrong atm." }, + CalcLineIntersection = + { + { Params = "{{Vector3d|LineStart}}, {{Vector3d|LinePt2}}", Return = "DoesIntersect, [LineCoeff, Face]", Notes = "Calculates the intersection of a ray (half-line), given by two of its points, with the bounding box. Returns false if the line doesn't intersect the bounding box, or true, together with coefficient of the intersection (how much of the difference between the two ray points is needed to reach the intersection), and the face of the box which is intersected." }, + { Params = "{{Vector3d|BoxMin}}, {{Vector3d|BoxMax}}, {{Vector3d|LineStart}}, {{Vector3d|LinePt2}}", Return = "DoesIntersect, [LineCoeff, Face]", Notes = "(STATIC) Calculates the intersection of a ray (half-line), given by two of its points, with the bounding box specified as its minimum and maximum coords. Returns false if the line doesn't intersect the bounding box, or true, together with coefficient of the intersection (how much of the difference between the two ray points is needed to reach the intersection), and the face of the box which is intersected." }, + }, DoesIntersect = { Params = "OtherBoundingBox", Return = "bool", Notes = "Returns true if the two bounding boxes have an intersection of nonzero volume." }, Expand = { Params = "ExpandX, ExpandY, ExpandZ", Return = "", Notes = "Expands this bounding box by the specified amount in each direction (so the box becomes larger by 2 * Expand in each axis)." }, + GetMax = { Params = "", Return = "{{Vector3d|Point}}", Notes = "Returns the boundary point with the maximum coords" }, + GetMaxX = { Params = "", Return = "number", Notes = "Returns the maximum X coord of the bounding box" }, + GetMaxY = { Params = "", Return = "number", Notes = "Returns the maximum Y coord of the bounding box" }, + GetMaxZ = { Params = "", Return = "number", Notes = "Returns the maximum Z coord of the bounding box" }, + GetMin = { Params = "", Return = "{{Vector3d|Point}}", Notes = "Returns the boundary point with the minimum coords" }, + GetMinX = { Params = "", Return = "number", Notes = "Returns the minimum X coord of the bounding box" }, + GetMinY = { Params = "", Return = "number", Notes = "Returns the minimum Y coord of the bounding box" }, + GetMinZ = { Params = "", Return = "number", Notes = "Returns the minimum Z coord of the bounding box" }, + Intersect = { Params = "{{cBoundingBox|OtherBbox}}", Return = "bool, [{{cBoundingBox|bbox}}]", Notes = "Checks if the intersection between this bounding box and another one is non-empty. Returns false if the intersection is empty, true and a new cBoundingBox representing the intersection of the two boxes." }, IsInside = { { Params = "{{Vector3d|Point}}", Return = "bool", Notes = "Returns true if the specified point is inside (including on the edge) of the box." }, diff --git a/Server/Plugins/Debuggers/Debuggers.lua b/Server/Plugins/Debuggers/Debuggers.lua index aa2205368..362dc4dd9 100644 --- a/Server/Plugins/Debuggers/Debuggers.lua +++ b/Server/Plugins/Debuggers/Debuggers.lua @@ -1921,6 +1921,52 @@ end +function HandleConsoleTestBbox(a_Split, a_EntireCmd) + -- Test bbox intersection: + local bbox1 = cBoundingBox(0, 5, 0, 5, 0, 5) + local bbox2 = cBoundingBox(bbox1) -- Make a copy + bbox2:Move(20, 20, 20) + local bbox3 = cBoundingBox(bbox1) -- Make a copy + bbox3:Move(2, 2, 2) + local doesIntersect, intersection = bbox1:Intersect(bbox2) + LOG("Bbox 2 intersection: " .. tostring(doesIntersect)) + LOG(" Intersection type: " .. type(intersection) .. " / " .. tolua.type(intersection)) + if (intersection) then + LOG(" {" .. intersection:GetMinX() .. ", " .. intersection:GetMinY() .. ", " .. intersection:GetMinZ() .. "}") + LOG(" {" .. intersection:GetMaxX() .. ", " .. intersection:GetMaxY() .. ", " .. intersection:GetMaxZ() .. "}") + end + doesIntersect, intersection = bbox1:Intersect(bbox3) + LOG("Bbox 3 intersection: " .. tostring(doesIntersect)) + LOG(" Intersection type: " .. type(intersection) .. " / " .. tolua.type(intersection)) + if (intersection) then + LOG(" {" .. intersection:GetMinX() .. ", " .. intersection:GetMinY() .. ", " .. intersection:GetMinZ() .. "}") + LOG(" {" .. intersection:GetMaxX() .. ", " .. intersection:GetMaxY() .. ", " .. intersection:GetMaxZ() .. "}") + end + + -- Test line intersection: + local lines = + { + { Vector3d(5, 0, 5), Vector3d(5, 1, 5) }, + { Vector3d(0, 0, 0), Vector3d(0, 1, 0) }, + } + for idx, line in ipairs(lines) do + local doesIntersect, coeff, face = bbox2:CalcLineIntersection(line[1], line[2]) + LOG("Line " .. idx .. " intersection: " .. tostring(doesIntersect)) + LOG(" Coeff: " .. tostring(coeff)) + LOG(" Face: " .. tostring(face)) + local doesIntersect2, coeff2, face2 = cBoundingBox:CalcLineIntersection(bbox2:GetMin(), bbox2:GetMax(), line[1], line[2]) + assert(doesIntersect == doesIntersect2) + assert(coeff == coeff2) + assert(face == face2) + end + + return true +end + + + + + function HandleConsoleTestCall(a_Split, a_EntireCmd) LOG("Testing inter-plugin calls") LOG("Note: These will fail if the Core plugin is not enabled") diff --git a/Server/Plugins/Debuggers/Info.lua b/Server/Plugins/Debuggers/Info.lua index af3461342..8fd04d0ae 100644 --- a/Server/Plugins/Debuggers/Info.lua +++ b/Server/Plugins/Debuggers/Info.lua @@ -254,6 +254,12 @@ g_PluginInfo = HelpString = "Tests the world scheduling", }, + ["testbbox"] = + { + Handler = HandleConsoleTestBbox, + HelpString = "Tests cBoundingBox API" + }, + ["testcall"] = { Handler = HandleConsoleTestCall, diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 91e80acbc..9945929d0 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -37,6 +37,7 @@ #include "../CommandOutput.h" #include "../BuildInfo.h" #include "../HTTP/UrlParser.h" +#include "../BoundingBox.h" @@ -3143,6 +3144,80 @@ static int tolua_cBlockArea_SaveToSchematicString(lua_State * tolua_S) +static int tolua_cBoundingBox_CalcLineIntersection(lua_State * a_LuaState) +{ + /* Function signatures: + bbox:CalcLineIntersection(pt1, pt2) -> bool, [number, blockface] + cBoundingBox:CalcLineIntersection(min, max, pt1, pt2) -> bool, [number, blockface] + */ + cLuaState L(a_LuaState); + const Vector3d * min; + const Vector3d * max; + const Vector3d * pt1; + const Vector3d * pt2; + double lineCoeff; + eBlockFace blockFace; + bool res; + if (L.GetStackValues(2, min, max, pt1, pt2)) // Try the static signature first + { + res = cBoundingBox::CalcLineIntersection(min, max, pt1, pt2, lineCoeff, blockFace); + } + else + { + const cBoundingBox * bbox; + if (!L.GetStackValues(1, bbox, pt1, pt2)) // Try the regular signature + { + L.LogStack(); + tolua_error(a_LuaState, "Invalid function params. Expected either bbox:CalcLineIntersection(pt1, pt2) or cBoundingBox:CalcLineIntersection(min, max, pt1, pt2).", nullptr); + return 0; + } + res = bbox->CalcLineIntersection(pt1, pt2, lineCoeff, blockFace); + } + L.Push(res); + if (res) + { + L.Push(lineCoeff); + L.Push(blockFace); + return 3; + } + return 1; +} + + + + + +static int tolua_cBoundingBox_Intersect(lua_State * a_LuaState) +{ + /* Function signature: + bbox:Intersect(a_OtherBbox) -> bool, cBoundingBox + */ + cLuaState L(a_LuaState); + const cBoundingBox * self; + const cBoundingBox * other; + if (!L.GetStackValues(1, self, other)) + { + L.LogStack(); + tolua_error(a_LuaState, "Invalid function params. Expected bbox:Intersect(otherBbox).", nullptr); + return 0; + } + auto intersection = new cBoundingBox(*self); + auto res = self->Intersect(*other, *intersection); + L.Push(res); + if (!res) + { + delete intersection; + return 1; + } + L.Push(intersection); + tolua_register_gc(L, lua_gettop(L)); // Make Lua own the "intersection" object + return 2; +} + + + + + static int tolua_cCompositeChat_AddRunCommandPart(lua_State * tolua_S) { // function cCompositeChat:AddRunCommandPart(Message, Command, [Style]) @@ -3431,6 +3506,11 @@ void cManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "SaveToSchematicString", tolua_cBlockArea_SaveToSchematicString); tolua_endmodule(tolua_S); + tolua_beginmodule(tolua_S, "cBoundingBox"); + tolua_function(tolua_S, "CalcLineIntersection", tolua_cBoundingBox_CalcLineIntersection); + tolua_function(tolua_S, "Intersect", tolua_cBoundingBox_Intersect); + tolua_endmodule(tolua_S); + tolua_beginmodule(tolua_S, "cClientHandle"); tolua_constant(tolua_S, "MAX_VIEW_DISTANCE", cClientHandle::MAX_VIEW_DISTANCE); tolua_constant(tolua_S, "MIN_VIEW_DISTANCE", cClientHandle::MIN_VIEW_DISTANCE); diff --git a/src/BoundingBox.cpp b/src/BoundingBox.cpp index 8e3bb29a9..bd236bbd7 100644 --- a/src/BoundingBox.cpp +++ b/src/BoundingBox.cpp @@ -261,7 +261,7 @@ bool cBoundingBox::IsInside(const Vector3d & a_Min, const Vector3d & a_Max, doub -bool cBoundingBox::CalcLineIntersection(const Vector3d & a_Line1, const Vector3d & a_Line2, double & a_LineCoeff, eBlockFace & a_Face) +bool cBoundingBox::CalcLineIntersection(const Vector3d & a_Line1, const Vector3d & a_Line2, double & a_LineCoeff, eBlockFace & a_Face) const { return CalcLineIntersection(m_Min, m_Max, a_Line1, a_Line2, a_LineCoeff, a_Face); } @@ -336,7 +336,7 @@ bool cBoundingBox::CalcLineIntersection(const Vector3d & a_Min, const Vector3d & -bool cBoundingBox::Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection) +bool cBoundingBox::Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection) const { a_Intersection.m_Min.x = std::max(m_Min.x, a_Other.m_Min.x); a_Intersection.m_Max.x = std::min(m_Max.x, a_Other.m_Max.x); diff --git a/src/BoundingBox.h b/src/BoundingBox.h index c2aa40dc7..38d567562 100644 --- a/src/BoundingBox.h +++ b/src/BoundingBox.h @@ -63,20 +63,25 @@ public: /** Returns true if the specified point is inside the bounding box specified by its min / max corners */ static bool IsInside(const Vector3d & a_Min, const Vector3d & a_Max, double a_X, double a_Y, double a_Z); + // tolua_end + /** Returns true if this bounding box is intersected by the line specified by its two points - Also calculates the distance along the line in which the intersection occurs (0 .. 1) - Only forward collisions (a_LineCoeff >= 0) are returned. */ - bool CalcLineIntersection(const Vector3d & a_Line1, const Vector3d & a_Line2, double & a_LineCoeff, eBlockFace & a_Face); + Also calculates the distance along the line in which the intersection occurs, and the face hit (BLOCK_FACE_ constants) + Only forward collisions (a_LineCoeff >= 0) are returned. + Exported to Lua manually, because ToLua++ would generate needless input params (a_LineCoeff, a_Face). */ + bool CalcLineIntersection(const Vector3d & a_LinePoint1, const Vector3d & a_LinePoint2, double & a_LineCoeff, eBlockFace & a_Face) const; /** Returns true if the specified bounding box is intersected by the line specified by its two points - Also calculates the distance along the line in which the intersection occurs (0 .. 1) and the face hit (BLOCK_FACE_ constants) - Only forward collisions (a_LineCoeff >= 0) are returned. */ - static bool CalcLineIntersection(const Vector3d & a_Min, const Vector3d & a_Max, const Vector3d & a_Line1, const Vector3d & a_Line2, double & a_LineCoeff, eBlockFace & a_Face); + Also calculates the distance along the line in which the intersection occurs, and the face hit (BLOCK_FACE_ constants) + Only forward collisions (a_LineCoeff >= 0) are returned. + Exported to Lua manually, because ToLua++ would generate needless input params (a_LineCoeff, a_Face). */ + static bool CalcLineIntersection(const Vector3d & a_Min, const Vector3d & a_Max, const Vector3d & a_LinePoint1, const Vector3d & a_LinePoint2, double & a_LineCoeff, eBlockFace & a_Face); - // tolua_end + /** Calculates the intersection of the two bounding boxes; returns true if nonempty. + Exported manually, because ToLua++ would generate needless input params (a_Intersection). */ + bool Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection) const; - /** Calculates the intersection of the two bounding boxes; returns true if nonempty */ - bool Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection); + // tolua_begin double GetMinX(void) const { return m_Min.x; } double GetMinY(void) const { return m_Min.y; } @@ -89,6 +94,8 @@ public: const Vector3d & GetMin(void) const { return m_Min; } const Vector3d & GetMax(void) const { return m_Max; } + // tolua_end + protected: Vector3d m_Min; Vector3d m_Max; |