You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-28 16:07:14 +00:00
Merge pull request #75612 from lawnjelly/fix_skele2d_bounds2
[3.x] Fix Polygon2D skinned bounds (for culling)
This commit is contained in:
@@ -907,10 +907,24 @@ public:
|
||||
bool antialiased;
|
||||
bool antialiasing_use_indices;
|
||||
|
||||
struct SkinningData {
|
||||
bool dirty = true;
|
||||
LocalVector<Rect2> active_bounds;
|
||||
LocalVector<uint16_t> active_bone_ids;
|
||||
Rect2 untransformed_bound;
|
||||
};
|
||||
mutable SkinningData *skinning_data = nullptr;
|
||||
|
||||
CommandPolygon() {
|
||||
type = TYPE_POLYGON;
|
||||
count = 0;
|
||||
}
|
||||
virtual ~CommandPolygon() {
|
||||
if (skinning_data) {
|
||||
memdelete(skinning_data);
|
||||
skinning_data = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct CommandMesh : public Command {
|
||||
@@ -983,6 +997,12 @@ public:
|
||||
|
||||
Item *next;
|
||||
|
||||
struct SkinningData {
|
||||
Transform2D skeleton_relative_xform;
|
||||
Transform2D skeleton_relative_xform_inv;
|
||||
};
|
||||
SkinningData *skinning_data = nullptr;
|
||||
|
||||
struct CopyBackBuffer {
|
||||
Rect2 rect;
|
||||
Rect2 screen_rect;
|
||||
@@ -999,6 +1019,11 @@ public:
|
||||
|
||||
Rect2 global_rect_cache;
|
||||
|
||||
private:
|
||||
Rect2 calculate_polygon_bounds(const Item::CommandPolygon &p_polygon) const;
|
||||
void precalculate_polygon_bone_bounds(const Item::CommandPolygon &p_polygon) const;
|
||||
|
||||
public:
|
||||
const Rect2 &get_rect() const {
|
||||
if (custom_rect) {
|
||||
return rect;
|
||||
@@ -1093,61 +1118,8 @@ public:
|
||||
} break;
|
||||
case Item::Command::TYPE_POLYGON: {
|
||||
const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c);
|
||||
int l = polygon->points.size();
|
||||
const Point2 *pp = &polygon->points[0];
|
||||
r.position = pp[0];
|
||||
for (int j = 1; j < l; j++) {
|
||||
r.expand_to(pp[j]);
|
||||
}
|
||||
|
||||
if (skeleton != RID()) {
|
||||
// calculate bone AABBs
|
||||
int bone_count = RasterizerStorage::base_singleton->skeleton_get_bone_count(skeleton);
|
||||
|
||||
Vector<Rect2> bone_aabbs;
|
||||
bone_aabbs.resize(bone_count);
|
||||
Rect2 *bptr = bone_aabbs.ptrw();
|
||||
|
||||
for (int j = 0; j < bone_count; j++) {
|
||||
bptr[j].size = Vector2(-1, -1); //negative means unused
|
||||
}
|
||||
if (l && polygon->bones.size() == l * 4 && polygon->weights.size() == polygon->bones.size()) {
|
||||
for (int j = 0; j < l; j++) {
|
||||
Point2 p = pp[j];
|
||||
for (int k = 0; k < 4; k++) {
|
||||
int idx = polygon->bones[j * 4 + k];
|
||||
float w = polygon->weights[j * 4 + k];
|
||||
if (w == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bptr[idx].size.x < 0) {
|
||||
//first
|
||||
bptr[idx] = Rect2(p, Vector2(0.00001, 0.00001));
|
||||
} else {
|
||||
bptr[idx].expand_to(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rect2 aabb;
|
||||
bool first_bone = true;
|
||||
for (int j = 0; j < bone_count; j++) {
|
||||
Transform2D mtx = RasterizerStorage::base_singleton->skeleton_bone_get_transform_2d(skeleton, j);
|
||||
Rect2 baabb = mtx.xform(bone_aabbs[j]);
|
||||
|
||||
if (first_bone) {
|
||||
aabb = baabb;
|
||||
first_bone = false;
|
||||
} else {
|
||||
aabb = aabb.merge(baabb);
|
||||
}
|
||||
}
|
||||
|
||||
r = r.merge(aabb);
|
||||
}
|
||||
}
|
||||
|
||||
DEV_ASSERT(polygon);
|
||||
r = calculate_polygon_bounds(*polygon);
|
||||
} break;
|
||||
case Item::Command::TYPE_MESH: {
|
||||
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
|
||||
@@ -1213,6 +1185,11 @@ public:
|
||||
final_clip_owner = nullptr;
|
||||
material_owner = nullptr;
|
||||
light_masked = false;
|
||||
|
||||
if (skinning_data) {
|
||||
memdelete(skinning_data);
|
||||
skinning_data = nullptr;
|
||||
}
|
||||
}
|
||||
Item() {
|
||||
light_mask = 1;
|
||||
|
||||
Reference in New Issue
Block a user