Skip to content

Commit

Permalink
Closed add object <-> object collision handling
Browse files Browse the repository at this point in the history
  • Loading branch information
sapier authored and PilzAdam committed Mar 27, 2013
1 parent 880d9e5 commit 8800896
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 33 deletions.
2 changes: 1 addition & 1 deletion src/activeobject.h
Expand Up @@ -61,7 +61,7 @@ class ActiveObject
}

virtual u8 getType() const = 0;

virtual bool getCollisionBox(aabb3f *toset) = 0;
protected:
u16 m_id; // 0 is invalid, "no id"
};
Expand Down
72 changes: 70 additions & 2 deletions src/collision.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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);

Expand All @@ -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;
{
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions src/collision.h
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
21 changes: 19 additions & 2 deletions src/content_cao.cpp
Expand Up @@ -174,6 +174,7 @@ class TestCAO : public ClientActiveObject

void processMessage(const std::string &data);

bool getCollisionBox(aabb3f *toset) { return false; }
private:
scene::IMeshSceneNode *m_node;
v3f m_position;
Expand Down Expand Up @@ -329,6 +330,7 @@ class ItemCAO : public ClientActiveObject
std::string infoText()
{return m_infotext;}

bool getCollisionBox(aabb3f *toset) { return false; }
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
Expand Down Expand Up @@ -643,6 +645,22 @@ class GenericCAO : public ClientActiveObject
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;
Expand Down Expand Up @@ -1127,8 +1145,7 @@ class GenericCAO : public ClientActiveObject
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
Expand Down
38 changes: 34 additions & 4 deletions src/content_sao.cpp
Expand Up @@ -64,6 +64,10 @@ class DummyLoadSAO : public ServerActiveObject
infostream<<"DummyLoadSAO step"<<std::endl;
}

bool getCollisionBox(aabb3f *toset) {
return false;
}

private:
};

Expand Down Expand Up @@ -132,6 +136,10 @@ class TestSAO : public ServerActiveObject
}
}

bool getCollisionBox(aabb3f *toset) {
return false;
}

private:
float m_timer1;
float m_age;
Expand Down Expand Up @@ -208,8 +216,7 @@ class ItemSAO : public ServerActiveObject
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);

Expand Down Expand Up @@ -314,6 +321,10 @@ class ItemSAO : public ServerActiveObject
return 0;
}

bool getCollisionBox(aabb3f *toset) {
return false;
}


private:
std::string m_itemstring;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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;
}
3 changes: 3 additions & 0 deletions src/content_sao.h
Expand Up @@ -78,6 +78,7 @@ class LuaEntitySAO : public ServerActiveObject
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);
Expand Down Expand Up @@ -235,6 +236,8 @@ class PlayerSAO : public ServerActiveObject
m_is_singleplayer = is_singleplayer;
}

bool getCollisionBox(aabb3f *toset);

private:
std::string getPropertyPacket();

Expand Down
2 changes: 1 addition & 1 deletion src/environment.cpp
Expand Up @@ -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);
}
}
Expand Down

0 comments on commit 8800896

Please sign in to comment.