Relatively snappy object-ground collision detection
authorPerttu Ahola <celeron55@gmail.com>
Mon, 21 Nov 2011 12:36:21 +0000 (14:36 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Tue, 29 Nov 2011 17:13:50 +0000 (19:13 +0200)
data/mods/default/init.lua
src/collision.cpp
src/collision.h
src/content_cao.cpp
src/content_cao.h
src/content_sao.cpp
src/content_sao.h
src/environment.h
src/luaentity_common.cpp

index a8a1d08f4c895160412c20d4a8856cf6ebac7544..4f825626d83f0a7e4877bfeaf2eff41bfa7150a0 100644 (file)
@@ -651,8 +651,7 @@ end
 
 local TNT = {
        -- Static definition
-       -- Maybe handle gravity and collision this way? dunno
-       -- physical = true,
+       physical = true, -- Collides with things
        -- weight = 5,
        collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
        visual = "cube",
@@ -662,17 +661,14 @@ local TNT = {
        -- Initial value for our timer
        timer = 0,
        -- Number of punches required to defuse
-       health = 3,
-       -- List names of state variables, for serializing object state
-       -- (NOTE: not implemented and implementation will not be like this)
-       -- state_variables = {"timer"},
+       health = 1,
 }
 
 -- Called when a TNT object is created
 function TNT:on_activate(staticdata)
        print("TNT:on_activate()")
-       self.object:setvelocity({x=0, y=1, z=0})
-       self.object:setacceleration({x=0, y=-5, z=0})
+       self.object:setvelocity({x=0, y=2, z=0})
+       self.object:setacceleration({x=0, y=-10, z=0})
 end
 
 -- Called periodically
@@ -709,6 +705,7 @@ minetest.register_entity("TNT", TNT)
 function register_falling_node(nodename, texture)
        minetest.register_entity("falling_"..nodename, {
                -- Static definition
+               physical = true,
                collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
                visual = "cube",
                textures = {texture,texture,texture,texture,texture,texture},
@@ -719,7 +716,7 @@ function register_falling_node(nodename, texture)
                        self.object:setacceleration({x=0, y=-10, z=0})
                        -- Turn to actual sand when collides to ground or just move
                        pos = self.object:getpos()
-                       bcp = {x=pos.x, y=pos.y-0.5, z=pos.z} -- Position of bottom center point
+                       bcp = {x=pos.x, y=pos.y-0.6, z=pos.z} -- Position of bottom center point
                        bcn = minetest.env:get_node(bcp)
                        if bcn.name ~= "air" then
                                -- Turn to a sand node
index 674cf4ed4881224f9a282667120db0c05fa44e2b..24f1e9d18614889e93ac1db48f57dcdbf13ca3d0 100644 (file)
@@ -177,6 +177,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
                                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;
                        }
                
                }
@@ -232,6 +233,8 @@ collisionMoveResult collisionMovePrecise(Map *map, IGameDef *gamedef,
 
                if(result.touching_ground)
                        final_result.touching_ground = true;
+               if(result.collides)
+                       final_result.collides = true;
        }
        while(dtime_downcount > 0.001);
                
index 3354ea09a3392eda6923e320bd33d459c9671fb6..e823a08fefb978825e4fe76f24508a818d398163 100644 (file)
@@ -28,9 +28,11 @@ class IGameDef;
 struct collisionMoveResult
 {
        bool touching_ground;
+       bool collides;
 
        collisionMoveResult():
-               touching_ground(false)
+               touching_ground(false),
+               collides(false)
        {}
 };
 
index f5ef3fb0759051dc2ad69b787f76c29df79588bb..213de554b723f024543547e67e7b9252d84896af 100644 (file)
@@ -1457,11 +1457,34 @@ void LuaEntityCAO::updateNodePos()
 
 void LuaEntityCAO::step(float dtime, ClientEnvironment *env)
 {
-       m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
-       m_velocity += dtime * m_acceleration;
-       pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
-       pos_translator.translate(dtime);
-       updateNodePos();
+       if(m_prop->physical){
+               core::aabbox3d<f32> box = m_prop->collisionbox;
+               box.MinEdge *= BS;
+               box.MaxEdge *= BS;
+               collisionMoveResult moveresult;
+               f32 pos_max_d = BS*0.25; // Distance per iteration
+               v3f p_pos = m_position;
+               v3f p_velocity = m_velocity;
+               IGameDef *gamedef = env->getGameDef();
+               moveresult = collisionMovePrecise(&env->getMap(), gamedef,
+                               pos_max_d, box, dtime, p_pos, p_velocity);
+               // Apply results
+               m_position = p_pos;
+               m_velocity = p_velocity;
+               
+               bool is_end_position = moveresult.collides;
+               pos_translator.update(m_position, is_end_position, dtime);
+               pos_translator.translate(dtime);
+               updateNodePos();
+
+               m_velocity += dtime * m_acceleration;
+       } else {
+               m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
+               m_velocity += dtime * m_acceleration;
+               pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
+               pos_translator.translate(dtime);
+               updateNodePos();
+       }
 }
 
 void LuaEntityCAO::processMessage(const std::string &data)
@@ -1487,10 +1510,12 @@ void LuaEntityCAO::processMessage(const std::string &data)
                // update_interval
                float update_interval = readF1000(is);
                
-               if(do_interpolate)
-                       pos_translator.update(m_position, is_end_position, update_interval);
-               else
+               if(do_interpolate){
+                       if(!m_prop->physical)
+                               pos_translator.update(m_position, is_end_position, update_interval);
+               } else {
                        pos_translator.init(m_position);
+               }
                updateNodePos();
        }
 }
index 3f6b9d877c293e19c2b81b81436e5e8938559707..fa7a0cb4cdab65cdf1333463740b6d0d14361a61 100644 (file)
@@ -92,7 +92,7 @@ struct SmoothTranslator
                if(anim_time > 0.001)
                        moveratio = anim_time_counter / anim_time;
                // Move a bit less than should, to avoid oscillation
-               moveratio = moveratio * 0.5;
+               moveratio = moveratio * 0.8;
                float move_end = 1.5;
                if(aim_is_end)
                        move_end = 1.0;
index 986e3f15f657058309323960b8ae19fc6fd7fbe5..5d63b295e8b82dbe729efa7449de63b6ef3324cf 100644 (file)
@@ -1555,6 +1555,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
        m_yaw(0),
        m_last_sent_yaw(0),
        m_last_sent_position(0,0,0),
+       m_last_sent_velocity(0,0,0),
        m_last_sent_position_timer(0),
        m_last_sent_move_precision(0)
 {
@@ -1612,8 +1613,27 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
 {
        m_last_sent_position_timer += dtime;
        
-       m_base_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
-       m_velocity += dtime * m_acceleration;
+       if(m_prop->physical){
+               core::aabbox3d<f32> box = m_prop->collisionbox;
+               box.MinEdge *= BS;
+               box.MaxEdge *= BS;
+               collisionMoveResult moveresult;
+               f32 pos_max_d = BS*0.25; // Distance per iteration
+               v3f p_pos = getBasePosition();
+               v3f p_velocity = m_velocity;
+               IGameDef *gamedef = m_env->getGameDef();
+               moveresult = collisionMovePrecise(&m_env->getMap(), gamedef,
+                               pos_max_d, box, dtime, p_pos, p_velocity);
+               // Apply results
+               setBasePosition(p_pos);
+               m_velocity = p_velocity;
+
+               m_velocity += dtime * m_acceleration;
+       } else {
+               m_base_position += dtime * m_velocity + 0.5 * dtime
+                               * dtime * m_acceleration;
+               m_velocity += dtime * m_acceleration;
+       }
 
        if(m_registered){
                lua_State *L = m_env->getLua();
@@ -1623,7 +1643,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
        if(send_recommended == false)
                return;
        
-       // TODO: force send when velocity/acceleration changes enough
+       // TODO: force send when acceleration changes enough?
        float minchange = 0.2*BS;
        if(m_last_sent_position_timer > 1.0){
                minchange = 0.01*BS;
@@ -1632,7 +1652,9 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
        }
        float move_d = m_base_position.getDistanceFrom(m_last_sent_position);
        move_d += m_last_sent_move_precision;
-       if(move_d > minchange || fabs(m_yaw - m_last_sent_yaw) > 1.0){
+       float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity);
+       if(move_d > minchange || vel_d > minchange ||
+                       fabs(m_yaw - m_last_sent_yaw) > 1.0){
                sendPosition(true, false);
        }
 }
@@ -1675,6 +1697,7 @@ std::string LuaEntitySAO::getStaticData()
 
 InventoryItem* LuaEntitySAO::createPickedUpItem()
 {
+       // TODO: Ask item from scriptapi
        std::istringstream is("CraftItem testobject1 1", std::ios_base::binary);
        IGameDef *gamedef = m_env->getGameDef();
        InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
@@ -1732,7 +1755,7 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
        m_last_sent_position_timer = 0;
        m_last_sent_yaw = m_yaw;
        m_last_sent_position = m_base_position;
-       //m_last_sent_velocity = m_velocity;
+       m_last_sent_velocity = m_velocity;
        //m_last_sent_acceleration = m_acceleration;
 
        float update_interval = m_env->getSendRecommendedInterval();
index 04d33647edba3eaef6fcfff8e2b50c65754adf7f..17d87e3424735e171728703292ad0242fd57ea0a 100644 (file)
@@ -231,6 +231,7 @@ private:
        float m_yaw;
        float m_last_sent_yaw;
        v3f m_last_sent_position;
+       v3f m_last_sent_velocity;
        float m_last_sent_position_timer;
        float m_last_sent_move_precision;
 };
index a8213ea6de8fadf02b32260efcb47d6fa3b74b40..1abf7386752d0eb24e093ea70d1502125d567cb5 100644 (file)
@@ -362,14 +362,13 @@ public:
        ~ClientEnvironment();
 
        Map & getMap()
-       {
-               return *m_map;
-       }
+       { return *m_map; }
 
        ClientMap & getClientMap()
-       {
-               return *m_map;
-       }
+       { return *m_map; }
+
+       IGameDef *getGameDef()
+       { return m_gamedef; }
 
        void step(f32 dtime);
 
index 138e72dcbba67993696bdf3f94c12dc61f0060c0..503083d0b7fdfd2039081940bfee8f9b30e06786 100644 (file)
@@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
 LuaEntityProperties::LuaEntityProperties():
-       physical(true),
+       physical(false),
        weight(5),
        collisionbox(-0.5,-0.5,-0.5, 0.5,0.5,0.5),
        visual("single_sprite")