#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;
/*
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)
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;
}
}
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;
+}
+