]> git.lizzy.rs Git - minetest.git/blobdiff - src/raycast.cpp
Add callback on_mapblocks_changed
[minetest.git] / src / raycast.cpp
index 2dbebd83b76a334313d62ade5f48492ad4d516fe..c41b9c3944134a6c7ae5d75f79547cdf77a38a74 100644 (file)
@@ -20,20 +20,31 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "raycast.h"
 #include "irr_v3d.h"
 #include "irr_aabb3d.h"
+#include <quaternion.h>
 #include "constants.h"
 
 bool RaycastSort::operator() (const PointedThing &pt1,
        const PointedThing &pt2) const
 {
-       // "nothing" can not be sorted
+       // "nothing" cannot be sorted
        assert(pt1.type != POINTEDTHING_NOTHING);
        assert(pt2.type != POINTEDTHING_NOTHING);
+       f32 pt1_distSq = pt1.distanceSq;
+
+       // Add some bonus when one of them is an object
+       if (pt1.type != pt2.type) {
+               if (pt1.type == POINTEDTHING_OBJECT)
+                       pt1_distSq -= BS * BS;
+               else if (pt2.type == POINTEDTHING_OBJECT)
+                       pt1_distSq += BS * BS;
+       }
+
        // returns false if pt1 is nearer than pt2
-       if (pt1.distanceSq < pt2.distanceSq) {
+       if (pt1_distSq < pt2.distanceSq) {
                return false;
        }
 
-       if (pt1.distanceSq == pt2.distanceSq) {
+       if (pt1_distSq == pt2.distanceSq) {
                // Sort them to allow only one order
                if (pt1.type == POINTEDTHING_OBJECT)
                        return (pt2.type == POINTEDTHING_OBJECT
@@ -58,7 +69,7 @@ RaycastState::RaycastState(const core::line3d<f32> &shootline,
 
 
 bool boxLineCollision(const aabb3f &box, const v3f &start,
-       const v3f &dir, v3f *collision_point, v3s16 *collision_normal)
+       const v3f &dir, v3f *collision_point, v3f *collision_normal)
 {
        if (box.isPointInside(start)) {
                *collision_point = start;
@@ -125,3 +136,23 @@ bool boxLineCollision(const aabb3f &box, const v3f &start,
        }
        return false;
 }
+
+bool boxLineCollision(const aabb3f &box, const v3f &rotation,
+       const v3f &start, const v3f &dir,
+       v3f *collision_point, v3f *collision_normal, v3f *raw_collision_normal)
+{
+       // Inversely transform the ray rather than rotating the box faces;
+       // this allows us to continue using a simple ray - AABB intersection
+       core::quaternion rot(rotation * core::DEGTORAD);
+       rot.makeInverse();
+
+       bool collision = boxLineCollision(box, rot * start, rot * dir, collision_point, collision_normal);
+       if (!collision) return collision;
+
+       // Transform the results back
+       rot.makeInverse();
+       *collision_point = rot * *collision_point;
+       *raw_collision_normal = *collision_normal;
+       *collision_normal = rot * *collision_normal;
+       return collision;
+}