Skip to content

Commit 85258ec

Browse files
committed
Merge pull request godotengine#102662 from groud/chunk_tilemap_physics
Chunk tilemap physics
2 parents 1b631ed + 4765bc8 commit 85258ec

File tree

5 files changed

+604
-256
lines changed

5 files changed

+604
-256
lines changed

core/math/geometry_2d.cpp

+57-7
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,63 @@
3838
const int clipper_precision = 5; // Based on CMP_EPSILON.
3939
const double clipper_scale = Math::pow(10.0, clipper_precision);
4040

41-
Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(const Vector<Point2> &polygon) {
41+
void Geometry2D::merge_many_polygons(const Vector<Vector<Vector2>> &p_polygons, Vector<Vector<Vector2>> &r_out_polygons, Vector<Vector<Vector2>> &r_out_holes) {
42+
using namespace Clipper2Lib;
43+
44+
PathsD subjects;
45+
for (const Vector<Vector2> &polygon : p_polygons) {
46+
PathD path(polygon.size());
47+
for (int i = 0; i < polygon.size(); i++) {
48+
const Vector2 &point = polygon[i];
49+
path[i] = PointD(point.x, point.y);
50+
}
51+
subjects.push_back(path);
52+
}
53+
54+
PathsD solution = Union(subjects, FillRule::NonZero);
55+
solution = SimplifyPaths(solution, 0.01);
56+
57+
r_out_polygons.clear();
58+
r_out_holes.clear();
59+
for (PathsD::size_type i = 0; i < solution.size(); ++i) {
60+
PathD &path = solution[i];
61+
62+
Vector<Point2> output_polygon;
63+
output_polygon.resize(path.size());
64+
for (PathsD::size_type j = 0; j < path.size(); ++j) {
65+
output_polygon.set(j, Vector2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
66+
}
67+
if (IsPositive(path)) {
68+
r_out_polygons.push_back(output_polygon);
69+
} else {
70+
r_out_holes.push_back(output_polygon);
71+
}
72+
}
73+
}
74+
75+
Vector<Vector<Vector2>> Geometry2D::decompose_many_polygons_in_convex(const Vector<Vector<Point2>> &p_polygons, const Vector<Vector<Point2>> &p_holes) {
4276
Vector<Vector<Vector2>> decomp;
4377
List<TPPLPoly> in_poly, out_poly;
4478

45-
TPPLPoly inp;
46-
inp.Init(polygon.size());
47-
for (int i = 0; i < polygon.size(); i++) {
48-
inp.GetPoint(i) = polygon[i];
79+
for (const Vector<Vector2> &polygon : p_polygons) {
80+
TPPLPoly inp;
81+
inp.Init(polygon.size());
82+
for (int i = 0; i < polygon.size(); i++) {
83+
inp.GetPoint(i) = polygon[i];
84+
}
85+
inp.SetOrientation(TPPL_ORIENTATION_CCW);
86+
in_poly.push_back(inp);
87+
}
88+
for (const Vector<Vector2> &polygon : p_holes) {
89+
TPPLPoly inp;
90+
inp.Init(polygon.size());
91+
for (int i = 0; i < polygon.size(); i++) {
92+
inp.GetPoint(i) = polygon[i];
93+
}
94+
inp.SetOrientation(TPPL_ORIENTATION_CW);
95+
inp.SetHole(true);
96+
in_poly.push_back(inp);
4997
}
50-
inp.SetOrientation(TPPL_ORIENTATION_CCW);
51-
in_poly.push_back(inp);
5298
TPPLPartition tpart;
5399
if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { // Failed.
54100
ERR_PRINT("Convex decomposing failed!");
@@ -72,6 +118,10 @@ Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(const Vector<Poi
72118
return decomp;
73119
}
74120

121+
Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(const Vector<Point2> &p_polygon) {
122+
return Geometry2D::decompose_many_polygons_in_convex({ p_polygon }, {});
123+
}
124+
75125
struct _AtlasWorkRect {
76126
Size2i s;
77127
Point2i p;

core/math/geometry_2d.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,10 @@ class Geometry2D {
488488
return points;
489489
}
490490

491-
static Vector<Vector<Vector2>> decompose_polygon_in_convex(const Vector<Point2> &polygon);
491+
static void merge_many_polygons(const Vector<Vector<Point2>> &p_polygons, Vector<Vector<Vector2>> &r_out_polygons, Vector<Vector<Vector2>> &r_out_holes);
492+
static Vector<Vector<Vector2>> decompose_many_polygons_in_convex(const Vector<Vector<Point2>> &p_polygons, const Vector<Vector<Point2>> &p_holes);
493+
494+
static Vector<Vector<Vector2>> decompose_polygon_in_convex(const Vector<Point2> &p_polygon);
492495

493496
static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size);
494497
static Vector<Vector3i> partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size);

doc/classes/TileMapLayer.xml

+7-2
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@
115115
<return type="Vector2i" />
116116
<param index="0" name="body" type="RID" />
117117
<description>
118-
Returns the coordinates of the tile for given physics body [RID]. Such an [RID] can be retrieved from [method KinematicCollision2D.get_collider_rid], when colliding with a tile.
118+
Returns the coordinates of the physics quadrant (see [member physics_quadrant_size]) for given physics body [RID]. Such an [RID] can be retrieved from [method KinematicCollision2D.get_collider_rid], when colliding with a tile.
119119
</description>
120120
</method>
121121
<method name="get_navigation_map" qualifiers="const">
@@ -311,8 +311,13 @@
311311
<member name="occlusion_enabled" type="bool" setter="set_occlusion_enabled" getter="is_occlusion_enabled" default="true">
312312
Enable or disable light occlusion.
313313
</member>
314+
<member name="physics_quadrant_size" type="int" setter="set_physics_quadrant_size" getter="get_physics_quadrant_size" default="16">
315+
The [TileMapLayer]'s physics quadrant size. Within a physics quadrant, cells with similar physics properties are grouped together and their collision shapes get merged. [member physics_quadrant_size] defines the length of a square's side, in the map's coordinate system, that forms the quadrant. Thus, the default quadrant size groups together [code]16 * 16 = 256[/code] tiles.
316+
[b]Note:[/b] As quadrants are created according to the map's coordinate system, the quadrant's "square shape" might not look like square in the [TileMapLayer]'s local coordinate system.
317+
[b]Note:[/b] This impacts the value returned by [method get_coords_for_body_rid].
318+
</member>
314319
<member name="rendering_quadrant_size" type="int" setter="set_rendering_quadrant_size" getter="get_rendering_quadrant_size" default="16">
315-
The [TileMapLayer]'s quadrant size. A quadrant is a group of tiles to be drawn together on a single canvas item, for optimization purposes. [member rendering_quadrant_size] defines the length of a square's side, in the map's coordinate system, that forms the quadrant. Thus, the default quadrant size groups together [code]16 * 16 = 256[/code] tiles.
320+
The [TileMapLayer]'s rendering quadrant size. A quadrant is a group of tiles to be drawn together on a single canvas item, for optimization purposes. [member rendering_quadrant_size] defines the length of a square's side, in the map's coordinate system, that forms the quadrant. Thus, the default quadrant size groups together [code]16 * 16 = 256[/code] tiles.
316321
The quadrant size does not apply on a Y-sorted [TileMapLayer], as tiles are grouped by Y position instead in that case.
317322
[b]Note:[/b] As quadrants are created according to the map's coordinate system, the quadrant's "square shape" might not look like square in the [TileMapLayer]'s local coordinate system.
318323
</member>

0 commit comments

Comments
 (0)