X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fcollision.cpp;h=3460b04fdb719f75072c444ae243f61a5957de0a;hb=800d3b4ee7dfe527d8540c9e2464117dc24ad1d0;hp=63186a84a5e72a2b803777f4c8795d652b5097b9;hpb=7cfb71385d00d1cbbbfd9c76f6c01adafa9e648a;p=minetest.git diff --git a/src/collision.cpp b/src/collision.cpp index 63186a84a..3460b04fd 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -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 &box_0, +collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, + f32 pos_max_d, const core::aabbox3d &box_0, f32 dtime, v3f &pos_f, v3f &speed_f) { collisionMoveResult result; @@ -70,15 +72,21 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, /* Go through every node around the object - TODO: Calculate the range of nodes that need to be checked */ - 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) @@ -174,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; } } @@ -182,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 &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; +} +