Raycast: export exact pointing location (#6304)
authorDániel Juhász <juhdanad@gmail.com>
Thu, 16 Aug 2018 18:10:08 +0000 (20:10 +0200)
committerSmallJoker <SmallJoker@users.noreply.github.com>
Thu, 16 Aug 2018 18:10:08 +0000 (20:10 +0200)
* Return intersection point in node coordinates.
* Clarify 'intersection_point' documentation

doc/lua_api.txt
src/environment.cpp
src/script/common/c_content.cpp
src/script/common/c_content.h
src/script/cpp_api/s_item.cpp
src/script/cpp_api/s_item.h
src/script/lua_api/l_env.cpp
src/util/pointedthing.cpp
src/util/pointedthing.h

index 0c331577b3b8d79d4b80adb2c1d5ffacd88f7d85..ef70fe6f7aecb1a9eafcb323c086e27ad1d9920a 100644 (file)
@@ -1317,6 +1317,17 @@ For helper functions see [Spatial Vectors].
 * `{type="node", under=pos, above=pos}`
 * `{type="object", ref=ObjectRef}`
 
+Exact pointing location (currently only `Raycast` supports these fields):
+* `pointed_thing.intersection_point`: The absolute world coordinates of the
+  point on the selection box which is pointed at. May be in the selection box
+  if the pointer is in the box too.
+* `pointed_thing.box_id`: The ID of the pointed selection box (counting starts
+  from 1).
+* `pointed_thing.intersection_normal`: Unit vector, points outwards of the
+  selected selection box. This specifies which face is pointed at.
+  Is a null vector `{x = 0, y = 0, z = 0}` when the pointer is inside the
+  selection box.
+
 
 
 
@@ -5323,7 +5334,12 @@ It can be created via `PseudoRandom(seed)`.
 ---------
 
 A raycast on the map. It works with selection boxes.
-Can be used as an iterator in a for loop.
+Can be used as an iterator in a for loop as:
+
+    local ray = Raycast(...)
+    for pointed_thing in ray do
+        ...
+    end
 
 The map is loaded as the ray advances. If the map is modified after the
 `Raycast` is created, the changes may or may not have an effect on the object.
@@ -5338,7 +5354,7 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
 
 ### Methods
 
-* `next()`: returns a `pointed_thing`
+* `next()`: returns a `pointed_thing` with exact pointing location
     * Returns the next thing pointed by the ray or nil.
 
 `SecureRandom`
index c2227601a368b2398fc01f4c9f355fd874200679..ac7b7ce693e726df0f6332894dd28823b7eaaf4e 100644 (file)
@@ -175,12 +175,12 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result)
                        bool is_colliding = false;
                        // Minimal distance of all collisions
                        float min_distance_sq = 10000000;
+                       // ID of the current box (loop counter)
+                       u16 id = 0;
 
                        v3f npf = intToFloat(np, BS);
-                       for (std::vector<aabb3f>::const_iterator i = boxes.begin();
-                                       i != boxes.end(); ++i) {
-                               // Get current collision box
-                               aabb3f box = *i;
+                       // This loop translates the boxes to their in-world place.
+                       for (aabb3f &box : boxes) {
                                box.MinEdge += npf;
                                box.MaxEdge += npf;
 
@@ -188,8 +188,10 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result)
                                v3s16 intersection_normal;
                                if (!boxLineCollision(box, state->m_shootline.start,
                                                state->m_shootline.getVector(), &intersection_point,
-                                               &intersection_normal))
+                                               &intersection_normal)) {
+                                       ++id;
                                        continue;
+                               }
 
                                f32 distanceSq = (intersection_point
                                        - state->m_shootline.start).getLengthSQ();
@@ -198,9 +200,11 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result)
                                        min_distance_sq = distanceSq;
                                        result.intersection_point = intersection_point;
                                        result.intersection_normal = intersection_normal;
+                                       result.box_id = id;
                                        found_boxcenter = box.getCenter();
                                        is_colliding = true;
                                }
+                               ++id;
                        }
                        // If there wasn't a collision, stop
                        if (!is_colliding) {
index 889b946602f44f9bb45a031e98fa927c1acd52fc..1d62ad98a008bc8f1c2e0a07f8c45e7c2670dcb6 100644 (file)
@@ -1757,7 +1757,8 @@ void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion)
        lua_pop(L, 1); // Pop value
 }
 
-void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm)
+void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm,
+       bool hitpoint)
 {
        lua_newtable(L);
        if (pointed.type == POINTEDTHING_NODE) {
@@ -1782,6 +1783,14 @@ void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm)
                lua_pushstring(L, "nothing");
                lua_setfield(L, -2, "type");
        }
+       if (hitpoint && (pointed.type != POINTEDTHING_NOTHING)) {
+               push_v3f(L, pointed.intersection_point / BS); // convert to node coords
+               lua_setfield(L, -2, "intersection_point");
+               push_v3s16(L, pointed.intersection_normal);
+               lua_setfield(L, -2, "intersection_normal");
+               lua_pushinteger(L, pointed.box_id + 1); // change to Lua array index
+               lua_setfield(L, -2, "box_id");
+       }
 }
 
 void push_objectRef(lua_State *L, const u16 id)
index 723253559c53960adf130901a8e75bc4c36b27ee..f3a653682ab9006b2cf701cd3a06be0babd3d477 100644 (file)
@@ -178,7 +178,13 @@ bool               push_json_value           (lua_State *L,
 void               read_json_value           (lua_State *L, Json::Value &root,
                                               int index, u8 recursion = 0);
 
-void               push_pointed_thing        (lua_State *L, const PointedThing &pointed, bool csm = false);
+/*!
+ * Pushes a Lua `pointed_thing` to the given Lua stack.
+ * \param csm If true, a client side pointed thing is pushed
+ * \param hitpoint If true, the exact pointing location is also pushed
+ */
+void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm =
+       false, bool hitpoint = false);
 
 void               push_objectRef            (lua_State *L, const u16 id);
 
index 94abe267bdab7e0c2b04d74ef0619438df75af82..cbdfcf1b1476052fe42b317d7583ed99038d3798 100644 (file)
@@ -255,10 +255,10 @@ bool ScriptApiItem::getItemCallback(const char *name, const char *callbackname,
        return false;
 }
 
-void ScriptApiItem::pushPointedThing(const PointedThing& pointed)
+void ScriptApiItem::pushPointedThing(const PointedThing &pointed, bool hitpoint)
 {
        lua_State* L = getStack();
 
-       push_pointed_thing(L, pointed);
+       push_pointed_thing(L, pointed, false, hitpoint);
 }
 
index d91b5c1d631abeb9ed78b202a54dd078e8585717..6c7f286a92652e63c63efcf26155461a79197ced 100644 (file)
@@ -54,6 +54,10 @@ protected:
        friend class LuaRaycast;
 
        bool getItemCallback(const char *name, const char *callbackname, const v3s16 *p = nullptr);
-       void pushPointedThing(const PointedThing& pointed);
+       /*!
+        * Pushes a `pointed_thing` tabe to the stack.
+        * \param hitpoint If true, the exact pointing location is also pushed
+        */
+       void pushPointedThing(const PointedThing &pointed, bool hitpoint = false);
 
 };
index 4944968da6a181371770ff8feaf456aba96b7b03..1e5149f7ab234fb2ed6e1c53981df1e2d866280b 100644 (file)
@@ -150,7 +150,7 @@ int LuaRaycast::l_next(lua_State *L)
        if (pointed.type == POINTEDTHING_NOTHING)
                lua_pushnil(L);
        else
-               script->pushPointedThing(pointed);
+               script->pushPointedThing(pointed, true);
 
        return 1;
 }
index c5961d56e51403c0696c8f16256cd3f736ef9792..b906264d0afeddd4129e434f0dbdcc668940a435 100644 (file)
@@ -25,13 +25,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 PointedThing::PointedThing(const v3s16 &under, const v3s16 &above,
        const v3s16 &real_under, const v3f &point, const v3s16 &normal,
-       f32 distSq):
+       u16 box_id, f32 distSq):
        type(POINTEDTHING_NODE),
        node_undersurface(under),
        node_abovesurface(above),
        node_real_undersurface(real_under),
        intersection_point(point),
        intersection_normal(normal),
+       box_id(box_id),
        distanceSq(distSq)
 {}
 
index 4c4c04234e33b88bdb52fd5bda1da562e97c74dd..5b30ed03135446706883ea3a60408967368b9dd4 100644 (file)
@@ -64,7 +64,8 @@ struct PointedThing
        s16 object_id = -1;
        /*!
         * Only valid if type isn't POINTEDTHING_NONE.
-        * First intersection point of the ray and the nodebox.
+        * First intersection point of the ray and the nodebox in irrlicht
+        * coordinates.
         */
        v3f intersection_point;
        /*!
@@ -74,9 +75,14 @@ struct PointedThing
         * points outside of the box and it's length is 1.
         */
        v3s16 intersection_normal;
+       /*!
+        * Only valid if type isn't POINTEDTHING_NONE.
+        * Indicates which selection box is selected, if there are more of them.
+        */
+       u16 box_id = 0;
        /*!
         * Square of the distance between the pointing
-        * ray's start point and the intersection point.
+        * ray's start point and the intersection point in irrlicht coordinates.
         */
        f32 distanceSq = 0;
 
@@ -85,7 +91,7 @@ struct PointedThing
        //! Constructor for POINTEDTHING_NODE
        PointedThing(const v3s16 &under, const v3s16 &above,
                const v3s16 &real_under, const v3f &point, const v3s16 &normal,
-               f32 distSq);
+               u16 box_id, f32 distSq);
        //! Constructor for POINTEDTHING_OBJECT
        PointedThing(s16 id, const v3f &point, const v3s16 &normal, f32 distSq);
        std::string dump() const;