Closed add object <-> object collision handling
authorsapier <Sapier at GMX dot net>
Sat, 12 Jan 2013 17:59:19 +0000 (17:59 +0000)
committerPilzAdam <pilzadam@minetest.net>
Wed, 27 Mar 2013 23:09:24 +0000 (00:09 +0100)
src/activeobject.h
src/collision.cpp
src/collision.h
src/content_cao.cpp
src/content_sao.cpp
src/content_sao.h
src/environment.cpp
src/localplayer.cpp
src/localplayer.h
src/particles.cpp

index e454f2c8c8da0d8c27bd3bf805363c78fa6637ef..1a75fba2efb1f67bbf0ced2541d708b901240ebb 100644 (file)
@@ -61,7 +61,7 @@ public:
        }
 
        virtual u8 getType() const = 0;
-
+       virtual bool getCollisionBox(aabb3f *toset) = 0;
 protected:
        u16 m_id; // 0 is invalid, "no id"
 };
index 58517b779444f6e6ec9a9504ce2af521b8e88553..806a3b7203278cdd43a821c869e8a5848672e622 100644 (file)
@@ -23,7 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "nodedef.h"
 #include "gamedef.h"
 #include "log.h"
+#include "environment.h"
+#include "serverobject.h"
 #include <vector>
+#include <set>
 #include "util/timetaker.h"
 #include "main.h" // g_profiler
 #include "profiler.h"
@@ -186,11 +189,12 @@ bool wouldCollideWithCeiling(
 }
 
 
-collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
+collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
                f32 pos_max_d, const aabb3f &box_0,
                f32 stepheight, f32 dtime,
                v3f &pos_f, v3f &speed_f, v3f &accel_f)
 {
+       Map *map = &env->getMap();
        //TimeTaker tt("collisionMoveSimple");
     ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG);
 
@@ -215,6 +219,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
        std::vector<aabb3f> cboxes;
        std::vector<bool> is_unloaded;
        std::vector<bool> is_step_up;
+       std::vector<bool> is_object;
        std::vector<int> bouncy_values;
        std::vector<v3s16> node_positions;
        {
@@ -256,6 +261,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
                                is_step_up.push_back(false);
                                bouncy_values.push_back(n_bouncy_value);
                                node_positions.push_back(p);
+                               is_object.push_back(false);
                        }
                }
                catch(InvalidPositionException &e)
@@ -267,14 +273,72 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
                        is_step_up.push_back(false);
                        bouncy_values.push_back(0);
                        node_positions.push_back(p);
+                       is_object.push_back(false);
                }
        }
        } // tt2
 
+       {
+               ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
+               //TimeTaker tt3("collisionMoveSimple collect object boxes");
+
+               /* add object boxes to cboxes */
+
+
+               std::list<ActiveObject*> objects;
+#ifndef SERVER
+               ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
+               if (c_env != 0)
+               {
+                       f32 distance = speed_f.getLength();
+                       std::vector<DistanceSortedActiveObject> clientobjects;
+                       c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects);
+                       for (int i=0; i < clientobjects.size(); i++)
+                       {
+                               objects.push_back((ActiveObject*)clientobjects[i].obj);
+                       }
+               }
+               else
+#endif
+               {
+                       ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
+                       if (s_env != 0)
+                       {
+                               f32 distance = speed_f.getLength();
+                               std::set<u16> s_objects = s_env->getObjectsInsideRadius(pos_f,distance * 1.5);
+                               for (std::set<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++)
+                               {
+                                       ServerActiveObject *current = s_env->getActiveObject(*iter);
+                                       objects.push_back((ActiveObject*)current);
+                               }
+                       }
+               }
+
+               for (std::list<ActiveObject*>::const_iterator iter = objects.begin();iter != objects.end(); ++iter)
+               {
+                       ActiveObject *object = *iter;
+
+                       if (object != NULL)
+                       {
+                               aabb3f object_collisionbox;
+                               if (object->getCollisionBox(&object_collisionbox))
+                               {
+                                       cboxes.push_back(object_collisionbox);
+                                       is_unloaded.push_back(false);
+                                       is_step_up.push_back(false);
+                                       bouncy_values.push_back(0);
+                                       node_positions.push_back(v3s16(0,0,0));
+                                       is_object.push_back(true);
+                               }
+                       }
+               }
+       } //tt3
+
        assert(cboxes.size() == is_unloaded.size());
        assert(cboxes.size() == is_step_up.size());
        assert(cboxes.size() == bouncy_values.size());
        assert(cboxes.size() == node_positions.size());
+       assert(cboxes.size() == is_object.size());
 
        /*
                Collision detection
@@ -386,7 +450,11 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
                                is_collision = false;
 
                        CollisionInfo info;
-                       info.type = COLLISION_NODE;
+                       if (is_object[nearest_boxindex]) {
+                               info.type = COLLISION_OBJECT;
+                       }
+                       else
+                               info.type = COLLISION_NODE;
                        info.node_p = node_positions[nearest_boxindex];
                        info.bouncy = bouncy;
                        info.old_speed = speed_f;
index 38cc3efb39c00149772f1b077ad7aabe28b18b02..1178184567a3821f8a3d84397000fc8f908b0f85 100644 (file)
@@ -25,10 +25,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 class Map;
 class IGameDef;
+class Environment;
 
 enum CollisionType
 {
-       COLLISION_NODE
+       COLLISION_NODE,
+       COLLISION_OBJECT,
 };
 
 struct CollisionInfo
@@ -65,7 +67,7 @@ struct collisionMoveResult
 };
 
 // Moves using a single iteration; speed should not exceed pos_max_d/dtime
-collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
+collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
                f32 pos_max_d, const aabb3f &box_0,
                f32 stepheight, f32 dtime,
                v3f &pos_f, v3f &speed_f, v3f &accel_f);
index 269667fe5fc7f81c995f1e1b567599ecc43eba4e..ee1009b6cb6e7cfcbdd00762a8232fe88de67373 100644 (file)
@@ -174,6 +174,7 @@ public:
 
        void processMessage(const std::string &data);
 
+       bool getCollisionBox(aabb3f *toset) { return false; }
 private:
        scene::IMeshSceneNode *m_node;
        v3f m_position;
@@ -329,6 +330,7 @@ public:
        std::string infoText()
                {return m_infotext;}
 
+       bool getCollisionBox(aabb3f *toset) { return false; }
 private:
        core::aabbox3d<f32> m_selection_box;
        scene::IMeshSceneNode *m_node;
@@ -643,6 +645,22 @@ public:
                        ClientActiveObject::registerType(getType(), create);
        }
 
+       bool getCollisionBox(aabb3f *toset) {
+               if (m_prop.physical) {
+                       aabb3f retval;
+                       //update collision box
+                       toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
+                       toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
+
+                       toset->MinEdge += m_position;
+                       toset->MaxEdge += m_position;
+
+                       return true;
+               }
+
+               return false;
+       }
+
        void initialize(const std::string &data)
        {
                infostream<<"GenericCAO: Got init data"<<std::endl;
@@ -1127,8 +1145,7 @@ public:
                                v3f p_pos = m_position;
                                v3f p_velocity = m_velocity;
                                v3f p_acceleration = m_acceleration;
-                               IGameDef *gamedef = env->getGameDef();
-                               moveresult = collisionMoveSimple(&env->getMap(), gamedef,
+                               moveresult = collisionMoveSimple(env,env->getGameDef(),
                                                pos_max_d, box, stepheight, dtime,
                                                p_pos, p_velocity, p_acceleration);
                                // Apply results
index d7afc31d80d135154bde34bc79edecbb7fd1bfea..468dfd218e4fe805bd73c12500880fa70c22dcec 100644 (file)
@@ -64,6 +64,10 @@ public:
                infostream<<"DummyLoadSAO step"<<std::endl;
        }
 
+       bool getCollisionBox(aabb3f *toset) {
+               return false;
+       }
+
 private:
 };
 
@@ -132,6 +136,10 @@ public:
                }
        }
 
+       bool getCollisionBox(aabb3f *toset) {
+               return false;
+       }
+
 private:
        float m_timer1;
        float m_age;
@@ -208,8 +216,7 @@ public:
                v3f pos_f_old = pos_f;
                v3f accel_f = v3f(0,0,0);
                f32 stepheight = 0;
-               IGameDef *gamedef = m_env->getGameDef();
-               moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
+               moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
                                pos_max_d, box, stepheight, dtime,
                                pos_f, m_speed_f, accel_f);
                
@@ -314,6 +321,10 @@ public:
                return 0;
        }
 
+       bool getCollisionBox(aabb3f *toset) {
+               return false;
+       }
+
 
 private:
        std::string m_itemstring;
@@ -490,8 +501,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                        v3f p_pos = m_base_position;
                        v3f p_velocity = m_velocity;
                        v3f p_acceleration = m_acceleration;
-                       IGameDef *gamedef = m_env->getGameDef();
-                       moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
+                       moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
                                        pos_max_d, box, stepheight, dtime,
                                        p_pos, p_velocity, p_acceleration);
                        // Apply results
@@ -880,6 +890,22 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
        m_messages_out.push_back(aom);
 }
 
+bool LuaEntitySAO::getCollisionBox(aabb3f *toset) {
+       if (m_prop.physical)
+       {
+               //update collision box
+               toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
+               toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
+
+               toset->MinEdge += m_base_position;
+               toset->MaxEdge += m_base_position;
+
+               return true;
+       }
+
+       return false;
+}
+
 /*
        PlayerSAO
 */
@@ -1434,3 +1460,7 @@ std::string PlayerSAO::getPropertyPacket()
        return gob_cmd_set_properties(m_prop);
 }
 
+bool PlayerSAO::getCollisionBox(aabb3f *toset) {
+       //player collision handling is already done clientside no need to do it twice
+       return false;
+}
index e5b89d44751e8fdf22b91476600bbfdc8f281702..60ca8f319fd88abf852be59a21a3d6e8c58a93d3 100644 (file)
@@ -78,6 +78,7 @@ public:
        void setSprite(v2s16 p, int num_frames, float framelength,
                        bool select_horiz_by_yawpitch);
        std::string getName();
+       bool getCollisionBox(aabb3f *toset);
 private:
        std::string getPropertyPacket();
        void sendPosition(bool do_interpolate, bool is_movement_end);
@@ -235,6 +236,8 @@ public:
                m_is_singleplayer = is_singleplayer;
        }
 
+       bool getCollisionBox(aabb3f *toset);
+
 private:
        std::string getPropertyPacket();
        
index 7c93090b62792ec5da863c40df505c4ad3d9e5bb..07cdb24d10ec887b378e087702868328e0427108 100644 (file)
@@ -2096,7 +2096,7 @@ void ClientEnvironment::step(float dtime)
                                Move the lplayer.
                                This also does collision detection.
                        */
-                       lplayer->move(dtime_part, *m_map, position_max_increment,
+                       lplayer->move(dtime_part, this, position_max_increment,
                                        &player_collisions);
                }
        }
index 9c36e75e6ab53dbe04f23fedefa26814cafdddc1..ee9b41c58eb34f948b2edccdacacb2aed2e63304 100644 (file)
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gamedef.h"
 #include "nodedef.h"
 #include "settings.h"
+#include "environment.h"
 #include "map.h"
 #include "util/numeric.h"
 
@@ -57,9 +58,10 @@ LocalPlayer::~LocalPlayer()
 {
 }
 
-void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
+void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
                std::list<CollisionInfo> *collision_info)
 {
+       Map *map = &env->getMap();
        INodeDefManager *nodemgr = m_gamedef->ndef();
 
        v3f position = getPosition();
@@ -97,15 +99,15 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
                if(in_liquid)
                {
                        v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
-                       in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
-                       liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity;
+                       in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
+                       liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
                }
                // If not in liquid, the threshold of going in is at lower y
                else
                {
                        v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
-                       in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
-                       liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity;
+                       in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
+                       liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
                }
        }
        catch(InvalidPositionException &e)
@@ -118,7 +120,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
        */
        try{
                v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
-               in_liquid_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
+               in_liquid_stable = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
        }
        catch(InvalidPositionException &e)
        {
@@ -132,8 +134,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
        try {
                v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
                v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
-               is_climbing = ((nodemgr->get(map.getNode(pp).getContent()).climbable ||
-               nodemgr->get(map.getNode(pp2).getContent()).climbable) && !free_move);
+               is_climbing = ((nodemgr->get(map->getNode(pp).getContent()).climbable ||
+               nodemgr->get(map->getNode(pp2).getContent()).climbable) && !free_move);
        }
        catch(InvalidPositionException &e)
        {
@@ -197,7 +199,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
 
        v3f accel_f = v3f(0,0,0);
 
-       collisionMoveResult result = collisionMoveSimple(&map, m_gamedef,
+       collisionMoveResult result = collisionMoveSimple(env, m_gamedef,
                        pos_max_d, playerbox, player_stepheight, dtime,
                        position, m_speed, accel_f);
 
@@ -219,7 +221,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
        */
        v3s16 current_node = floatToInt(position - v3f(0,BS/2,0), BS);
        if(m_sneak_node_exists &&
-          nodemgr->get(map.getNodeNoEx(m_old_node_below)).name == "air" &&
+          nodemgr->get(map->getNodeNoEx(m_old_node_below)).name == "air" &&
           m_old_node_below_type != "air")
        {
                // Old node appears to have been removed; that is,
@@ -227,7 +229,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
                m_need_to_get_new_sneak_node = false;
                m_sneak_node_exists = false;
        }
-       else if(nodemgr->get(map.getNodeNoEx(current_node)).name != "air")
+       else if(nodemgr->get(map->getNodeNoEx(current_node)).name != "air")
        {
                // We are on something, so make sure to recalculate the sneak
                // node.
@@ -267,10 +269,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
 
                        try{
                                // The node to be sneaked on has to be walkable
-                               if(nodemgr->get(map.getNode(p)).walkable == false)
+                               if(nodemgr->get(map->getNode(p)).walkable == false)
                                        continue;
                                // And the node above it has to be nonwalkable
-                               if(nodemgr->get(map.getNode(p+v3s16(0,1,0))).walkable == true)
+                               if(nodemgr->get(map->getNode(p+v3s16(0,1,0))).walkable == true)
                                        continue;
                        }
                        catch(InvalidPositionException &e)
@@ -331,7 +333,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
        {
                camera_barely_in_ceiling = false;
                v3s16 camera_np = floatToInt(getEyePosition(), BS);
-               MapNode n = map.getNodeNoEx(camera_np);
+               MapNode n = map->getNodeNoEx(camera_np);
                if(n.getContent() != CONTENT_IGNORE){
                        if(nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2){
                                camera_barely_in_ceiling = true;
@@ -343,21 +345,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
                Update the node last under the player
        */
        m_old_node_below = floatToInt(position - v3f(0,BS/2,0), BS);
-       m_old_node_below_type = nodemgr->get(map.getNodeNoEx(m_old_node_below)).name;
+       m_old_node_below_type = nodemgr->get(map->getNodeNoEx(m_old_node_below)).name;
        
        /*
                Check properties of the node on which the player is standing
        */
-       const ContentFeatures &f = nodemgr->get(map.getNodeNoEx(getStandingNodePos()));
+       const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos()));
        // Determine if jumping is possible
        m_can_jump = touching_ground && !in_liquid;
        if(itemgroup_get(f.groups, "disable_jump"))
                m_can_jump = false;
 }
 
-void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
+void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d)
 {
-       move(dtime, map, pos_max_d, NULL);
+       move(dtime, env, pos_max_d, NULL);
 }
 
 void LocalPlayer::applyControl(float dtime)
index e46ca6147cd5d2152a51509fa13ece6fa08796e0..17434d37910e2103b377afd61e47317651a1a2bc 100644 (file)
@@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "player.h"
 #include <list>
 
+class ClientEnvironment;
+
 class LocalPlayer : public Player
 {
 public:
@@ -38,9 +40,9 @@ public:
 
        v3f overridePosition;
        
-       void move(f32 dtime, Map &map, f32 pos_max_d,
+       void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
                        std::list<CollisionInfo> *collision_info);
-       void move(f32 dtime, Map &map, f32 pos_max_d);
+       void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d);
 
        void applyControl(float dtime);
 
index 0445d77264e44f13f44c53f926cc7e186af28e11..1d814f6191513676f76af074f93d82cb947c3d2e 100644 (file)
@@ -138,7 +138,7 @@ void Particle::step(float dtime, ClientEnvironment &env)
                v3f p_pos = m_pos*BS;
                v3f p_velocity = m_velocity*BS;
                v3f p_acceleration = m_acceleration*BS;
-               collisionMoveSimple(&env.getClientMap(), m_gamedef,
+               collisionMoveSimple(&env, m_gamedef,
                        BS*0.5, box,
                        0, dtime,
                        p_pos, p_velocity, p_acceleration);