You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Chunk tilemap physics
This commit is contained in:
@@ -98,21 +98,20 @@ public:
|
||||
class DebugQuadrant;
|
||||
#endif // DEBUG_ENABLED
|
||||
class RenderingQuadrant;
|
||||
class PhysicsQuadrant;
|
||||
|
||||
struct CellData {
|
||||
Vector2i coords;
|
||||
TileMapCell cell;
|
||||
|
||||
// Debug.
|
||||
SelfList<CellData> debug_quadrant_list_element;
|
||||
|
||||
// Rendering.
|
||||
Ref<RenderingQuadrant> rendering_quadrant;
|
||||
SelfList<CellData> rendering_quadrant_list_element;
|
||||
LocalVector<LocalVector<RID>> occluders;
|
||||
|
||||
// Physics.
|
||||
LocalVector<RID> bodies;
|
||||
Ref<PhysicsQuadrant> physics_quadrant;
|
||||
SelfList<CellData> physics_quadrant_list_element;
|
||||
|
||||
// Navigation.
|
||||
LocalVector<RID> navigation_regions;
|
||||
@@ -135,28 +134,26 @@ struct CellData {
|
||||
coords = p_other.coords;
|
||||
cell = p_other.cell;
|
||||
occluders = p_other.occluders;
|
||||
bodies = p_other.bodies;
|
||||
navigation_regions = p_other.navigation_regions;
|
||||
scene = p_other.scene;
|
||||
runtime_tile_data_cache = p_other.runtime_tile_data_cache;
|
||||
}
|
||||
|
||||
CellData(const CellData &p_other) :
|
||||
debug_quadrant_list_element(this),
|
||||
rendering_quadrant_list_element(this),
|
||||
physics_quadrant_list_element(this),
|
||||
dirty_list_element(this) {
|
||||
coords = p_other.coords;
|
||||
cell = p_other.cell;
|
||||
occluders = p_other.occluders;
|
||||
bodies = p_other.bodies;
|
||||
navigation_regions = p_other.navigation_regions;
|
||||
scene = p_other.scene;
|
||||
runtime_tile_data_cache = p_other.runtime_tile_data_cache;
|
||||
}
|
||||
|
||||
CellData() :
|
||||
debug_quadrant_list_element(this),
|
||||
rendering_quadrant_list_element(this),
|
||||
physics_quadrant_list_element(this),
|
||||
dirty_list_element(this) {
|
||||
}
|
||||
};
|
||||
@@ -177,6 +174,11 @@ public:
|
||||
SelfList<CellData>::List cells;
|
||||
RID canvas_item;
|
||||
|
||||
RID physics_mesh;
|
||||
|
||||
// Used to deleted unused quadrants.
|
||||
bool drawn_to = false;
|
||||
|
||||
SelfList<DebugQuadrant> dirty_quadrant_list_element;
|
||||
|
||||
DebugQuadrant() :
|
||||
@@ -220,6 +222,88 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class PhysicsQuadrant : public RefCounted {
|
||||
GDCLASS(PhysicsQuadrant, RefCounted);
|
||||
|
||||
public:
|
||||
struct PhysicsBodyKey {
|
||||
int physics_layer = 0;
|
||||
Vector2 linear_velocity;
|
||||
real_t angular_velocity = 0.0;
|
||||
bool one_way_collision = false;
|
||||
real_t one_way_collision_margin = 0.0;
|
||||
|
||||
bool operator<(const PhysicsBodyKey &p_other) const {
|
||||
if (physics_layer == p_other.physics_layer) {
|
||||
if (linear_velocity == p_other.linear_velocity) {
|
||||
if (angular_velocity == p_other.angular_velocity) {
|
||||
if (one_way_collision == p_other.one_way_collision) {
|
||||
return one_way_collision_margin < p_other.one_way_collision_margin;
|
||||
}
|
||||
return one_way_collision < p_other.one_way_collision;
|
||||
}
|
||||
return angular_velocity < p_other.angular_velocity;
|
||||
}
|
||||
return linear_velocity < p_other.linear_velocity;
|
||||
}
|
||||
return physics_layer < p_other.physics_layer;
|
||||
}
|
||||
|
||||
bool operator!=(const PhysicsBodyKey &p_other) const {
|
||||
return !this->operator==(p_other);
|
||||
}
|
||||
bool operator==(const PhysicsBodyKey &p_other) const {
|
||||
return physics_layer == p_other.physics_layer &&
|
||||
linear_velocity == p_other.linear_velocity &&
|
||||
angular_velocity == p_other.angular_velocity &&
|
||||
one_way_collision == p_other.one_way_collision &&
|
||||
one_way_collision_margin == p_other.one_way_collision_margin;
|
||||
}
|
||||
};
|
||||
|
||||
struct PhysicsBodyKeyHasher {
|
||||
static uint32_t hash(const PhysicsBodyKey &p_hash) {
|
||||
uint32_t h = hash_murmur3_one_32(p_hash.physics_layer);
|
||||
h = hash_murmur3_one_real(p_hash.linear_velocity.x);
|
||||
h = hash_murmur3_one_real(p_hash.linear_velocity.y, h);
|
||||
h = hash_murmur3_one_real(p_hash.angular_velocity, h);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct PhysicsBodyValue {
|
||||
RID body;
|
||||
Vector<Vector<Vector2>> polygons;
|
||||
};
|
||||
|
||||
struct CoordsWorldComparator {
|
||||
_ALWAYS_INLINE_ bool operator()(const Vector2 &p_a, const Vector2 &p_b) const {
|
||||
// We sort the cells by their local coords, as it is needed by rendering.
|
||||
if (p_a.y == p_b.y) {
|
||||
return p_a.x > p_b.x;
|
||||
} else {
|
||||
return p_a.y < p_b.y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Vector2i quadrant_coords;
|
||||
SelfList<CellData>::List cells;
|
||||
|
||||
HashMap<PhysicsBodyKey, PhysicsBodyValue, PhysicsBodyKeyHasher> bodies;
|
||||
LocalVector<Ref<ConvexPolygonShape2D>> shapes;
|
||||
|
||||
SelfList<PhysicsQuadrant> dirty_quadrant_list_element;
|
||||
|
||||
PhysicsQuadrant() :
|
||||
dirty_quadrant_list_element(this) {
|
||||
}
|
||||
|
||||
~PhysicsQuadrant() {
|
||||
cells.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class TileMapLayer : public Node2D {
|
||||
GDCLASS(TileMapLayer, Node2D);
|
||||
|
||||
@@ -254,6 +338,7 @@ public:
|
||||
DIRTY_FLAGS_LAYER_RENDERING_QUADRANT_SIZE,
|
||||
DIRTY_FLAGS_LAYER_COLLISION_ENABLED,
|
||||
DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES,
|
||||
DIRTY_FLAGS_LAYER_PHYSICS_QUADRANT_SIZE,
|
||||
DIRTY_FLAGS_LAYER_COLLISION_VISIBILITY_MODE,
|
||||
DIRTY_FLAGS_LAYER_OCCLUSION_ENABLED,
|
||||
DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED,
|
||||
@@ -288,6 +373,7 @@ private:
|
||||
|
||||
bool collision_enabled = true;
|
||||
bool use_kinematic_bodies = false;
|
||||
int physics_quadrant_size = 16;
|
||||
DebugVisibilityMode collision_visibility_mode = DEBUG_VISIBILITY_MODE_DEFAULT;
|
||||
|
||||
bool occlusion_enabled = true;
|
||||
@@ -324,13 +410,16 @@ private:
|
||||
void _clear_runtime_update_tile_data_for_cell(CellData &r_cell_data);
|
||||
void _update_cells_callback(bool p_force_cleanup);
|
||||
|
||||
// Coords to quadrant coords
|
||||
Vector2i _coords_to_quadrant_coords(const Vector2i &p_coords, const int p_quadrant_size) const;
|
||||
|
||||
// Per-system methods.
|
||||
#ifdef DEBUG_ENABLED
|
||||
HashMap<Vector2i, Ref<DebugQuadrant>> debug_quadrant_map;
|
||||
Vector2i _coords_to_debug_quadrant_coords(const Vector2i &p_coords) const;
|
||||
bool _debug_was_cleaned_up = false;
|
||||
void _debug_update(bool p_force_cleanup);
|
||||
void _debug_quadrants_update_cell(CellData &r_cell_data, SelfList<DebugQuadrant>::List &r_dirty_debug_quadrant_list);
|
||||
void _debug_quadrants_update_cell(CellData &r_cell_data);
|
||||
void _get_debug_quadrant_for_cell(const Vector2i &p_coords);
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
HashMap<Vector2i, Ref<RenderingQuadrant>> rendering_quadrant_map;
|
||||
@@ -344,14 +433,16 @@ private:
|
||||
void _rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data);
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
HashMap<Vector2i, Ref<PhysicsQuadrant>> physics_quadrant_map;
|
||||
HashMap<RID, Vector2i> bodies_coords; // Mapping for RID to coords.
|
||||
bool _physics_was_cleaned_up = false;
|
||||
void _physics_update(bool p_force_cleanup);
|
||||
void _physics_notification(int p_what);
|
||||
void _physics_quadrants_update_cell(CellData &r_cell_data, SelfList<PhysicsQuadrant>::List &r_dirty_physics_quadrant_list);
|
||||
void _physics_clear_cell(CellData &r_cell_data);
|
||||
void _physics_update_cell(CellData &r_cell_data);
|
||||
#ifdef DEBUG_ENABLED
|
||||
void _physics_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data);
|
||||
void _physics_draw_quadrant_debug(const RID &p_canvas_item, DebugQuadrant &r_debug_quadrant);
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
bool _navigation_was_cleaned_up = false;
|
||||
@@ -502,6 +593,8 @@ public:
|
||||
bool is_using_kinematic_bodies() const;
|
||||
void set_collision_visibility_mode(DebugVisibilityMode p_show_collision);
|
||||
DebugVisibilityMode get_collision_visibility_mode() const;
|
||||
void set_physics_quadrant_size(int p_size);
|
||||
int get_physics_quadrant_size() const;
|
||||
|
||||
void set_occlusion_enabled(bool p_enabled);
|
||||
bool is_occlusion_enabled() const;
|
||||
|
||||
Reference in New Issue
Block a user