Add descriptions to command line arguments
[oweals/minetest.git] / src / collision.cpp
index 83cefe4d1e1a5db78db65a18281b4e0c46b4caab..3460b04fdb719f75072c444ae243f61a5957de0a 100644 (file)
@@ -20,9 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "collision.h"
 #include "mapblock.h"
 #include "map.h"
+#include "nodedef.h"
+#include "gamedef.h"
 
-collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
-               const core::aabbox3d<f32> &box_0,
+collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
+               f32 pos_max_d, const core::aabbox3d<f32> &box_0,
                f32 dtime, v3f &pos_f, v3f &speed_f)
 {
        collisionMoveResult result;
@@ -71,13 +73,20 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
        /*
                Go through every node around the object
        */
-       for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
-       for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
-       for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
+       s16 min_x = (box_0.MinEdge.X / BS) - 2;
+       s16 min_y = (box_0.MinEdge.Y / BS) - 2;
+       s16 min_z = (box_0.MinEdge.Z / BS) - 2;
+       s16 max_x = (box_0.MaxEdge.X / BS) + 1;
+       s16 max_y = (box_0.MaxEdge.Y / BS) + 1;
+       s16 max_z = (box_0.MaxEdge.Z / BS) + 1;
+       for(s16 y = oldpos_i.Y + min_y; y <= oldpos_i.Y + max_y; y++)
+       for(s16 z = oldpos_i.Z + min_z; z <= oldpos_i.Z + max_z; z++)
+       for(s16 x = oldpos_i.X + min_x; x <= oldpos_i.X + max_x; x++)
        {
                try{
                        // Object collides into walkable nodes
-                       if(content_walkable(map->getNode(v3s16(x,y,z)).d) == false)
+                       MapNode n = map->getNode(v3s16(x,y,z));
+                       if(gamedef->getNodeDefManager()->get(n).walkable == false)
                                continue;
                }
                catch(InvalidPositionException &e)
@@ -173,6 +182,7 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
                                speed_f -= speed_f.dotProduct(dirs[i]) * dirs[i];
                                pos_f -= pos_f.dotProduct(dirs[i]) * dirs[i];
                                pos_f += oldpos_f.dotProduct(dirs[i]) * dirs[i];
+                               result.collides = true;
                        }
                
                }
@@ -181,4 +191,60 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
        return result;
 }
 
+collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
+               f32 pos_max_d, const core::aabbox3d<f32> &box_0,
+               f32 dtime, v3f &pos_f, v3f &speed_f)
+{
+       collisionMoveResult final_result;
+
+       // Maximum time increment (for collision detection etc)
+       // time = distance / speed
+       f32 dtime_max_increment = pos_max_d / speed_f.getLength();
+       
+       // Maximum time increment is 10ms or lower
+       if(dtime_max_increment > 0.01)
+               dtime_max_increment = 0.01;
+       
+       // Don't allow overly huge dtime
+       if(dtime > 2.0)
+               dtime = 2.0;
+       
+       f32 dtime_downcount = dtime;
+
+       u32 loopcount = 0;
+       do
+       {
+               loopcount++;
+
+               f32 dtime_part;
+               if(dtime_downcount > dtime_max_increment)
+               {
+                       dtime_part = dtime_max_increment;
+                       dtime_downcount -= dtime_part;
+               }
+               else
+               {
+                       dtime_part = dtime_downcount;
+                       /*
+                               Setting this to 0 (no -=dtime_part) disables an infinite loop
+                               when dtime_part is so small that dtime_downcount -= dtime_part
+                               does nothing
+                       */
+                       dtime_downcount = 0;
+               }
+
+               collisionMoveResult result = collisionMoveSimple(map, gamedef,
+                               pos_max_d, box_0, dtime_part, pos_f, speed_f);
+
+               if(result.touching_ground)
+                       final_result.touching_ground = true;
+               if(result.collides)
+                       final_result.collides = true;
+       }
+       while(dtime_downcount > 0.001);
+               
+
+       return final_result;
+}
+