Merge pull request #28326 from BastiaanOlij/center_heightmap
Center shape according to logic Bullet applies
This commit is contained in:
commit
647021e864
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="HeightMapShape" inherits="Shape" category="Core" version="3.2">
|
||||
<brief_description>
|
||||
Height map shape for 3D physics (bullet only)
|
||||
Height map shape for 3D physics (Bullet only).
|
||||
</brief_description>
|
||||
<description>
|
||||
Height map shape resource, which can be added to a [PhysicsBody] or [Area].
|
||||
|
@ -59,6 +59,25 @@ void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_tra
|
||||
transform = p_transform;
|
||||
}
|
||||
|
||||
btTransform CollisionObjectBullet::ShapeWrapper::get_adjusted_transform() const {
|
||||
if (shape->get_type() == PhysicsServer::SHAPE_HEIGHTMAP) {
|
||||
const HeightMapShapeBullet *hm_shape = (const HeightMapShapeBullet *)shape; // should be safe to cast now
|
||||
btTransform adjusted_transform;
|
||||
|
||||
// Bullet centers our heightmap:
|
||||
// https://github.com/bulletphysics/bullet3/blob/master/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h#L33
|
||||
// This is really counter intuitive so we're adjusting for it
|
||||
|
||||
adjusted_transform.setIdentity();
|
||||
adjusted_transform.setOrigin(btVector3(0.0, hm_shape->min_height + ((hm_shape->max_height - hm_shape->min_height) * 0.5), 0.0));
|
||||
adjusted_transform *= transform;
|
||||
|
||||
return adjusted_transform;
|
||||
} else {
|
||||
return transform;
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_scale) {
|
||||
if (!bt_shape) {
|
||||
if (active)
|
||||
@ -345,7 +364,8 @@ void RigidCollisionObjectBullet::reload_shapes() {
|
||||
// Try to optimize by not using compound
|
||||
if (1 == shape_count) {
|
||||
shpWrapper = &shapes.write[0];
|
||||
if (shpWrapper->transform.getOrigin().isZero() && shpWrapper->transform.getBasis() == shpWrapper->transform.getBasis().getIdentity()) {
|
||||
btTransform transform = shpWrapper->get_adjusted_transform();
|
||||
if (transform.getOrigin().isZero() && transform.getBasis() == transform.getBasis().getIdentity()) {
|
||||
shpWrapper->claim_bt_shape(body_scale);
|
||||
mainShape = shpWrapper->bt_shape;
|
||||
main_shape_changed();
|
||||
@ -359,7 +379,7 @@ void RigidCollisionObjectBullet::reload_shapes() {
|
||||
for (int i(0); i < shape_count; ++i) {
|
||||
shpWrapper = &shapes.write[i];
|
||||
shpWrapper->claim_bt_shape(body_scale);
|
||||
btTransform scaled_shape_transform(shpWrapper->transform);
|
||||
btTransform scaled_shape_transform(shpWrapper->get_adjusted_transform());
|
||||
scaled_shape_transform.getOrigin() *= body_scale;
|
||||
compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape);
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
|
||||
void set_transform(const Transform &p_transform);
|
||||
void set_transform(const btTransform &p_transform);
|
||||
btTransform get_adjusted_transform() const;
|
||||
|
||||
void claim_bt_shape(const btVector3 &body_scale);
|
||||
};
|
||||
|
@ -65,7 +65,6 @@ void CollisionShape::make_convex_from_brothers() {
|
||||
}
|
||||
|
||||
void CollisionShape::_update_in_shape_owner(bool p_xform_only) {
|
||||
|
||||
parent->shape_owner_set_transform(owner_id, get_transform());
|
||||
if (p_xform_only)
|
||||
return;
|
||||
@ -228,6 +227,9 @@ void CollisionShape::_update_debug_shape() {
|
||||
}
|
||||
|
||||
void CollisionShape::_shape_changed() {
|
||||
// If this is a heightfield shape our center may have changed
|
||||
_update_in_shape_owner(true);
|
||||
|
||||
if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !debug_shape_dirty) {
|
||||
debug_shape_dirty = true;
|
||||
call_deferred("_update_debug_shape");
|
||||
|
@ -34,35 +34,43 @@
|
||||
Vector<Vector3> HeightMapShape::_gen_debug_mesh_lines() {
|
||||
Vector<Vector3> points;
|
||||
|
||||
// This will be slow for large maps...
|
||||
// also we'll have to figure out how well bullet centers this shape...
|
||||
if ((map_width != 0) && (map_depth != 0)) {
|
||||
|
||||
Vector2 size(map_width - 1, map_depth - 1);
|
||||
Vector2 start = size * -0.5;
|
||||
int offset = 0;
|
||||
// This will be slow for large maps...
|
||||
// also we'll have to figure out how well bullet centers this shape...
|
||||
|
||||
PoolRealArray::Read r = map_data.read();
|
||||
Vector2 size(map_width - 1, map_depth - 1);
|
||||
Vector2 start = size * -0.5;
|
||||
|
||||
for (int d = 0; d < map_depth; d++) {
|
||||
Vector3 height(start.x, 0.0, start.y);
|
||||
PoolRealArray::Read r = map_data.read();
|
||||
|
||||
for (int w = 0; w < map_width; w++) {
|
||||
height.y = r[offset++];
|
||||
// reserve some memory for our points..
|
||||
points.resize(((map_width - 1) * map_depth * 2) + (map_width * (map_depth - 1) * 2));
|
||||
|
||||
if (w != map_width - 1) {
|
||||
points.push_back(height);
|
||||
points.push_back(Vector3(height.x + 1.0, r[offset], height.z));
|
||||
// now set our points
|
||||
int r_offset = 0;
|
||||
int w_offset = 0;
|
||||
for (int d = 0; d < map_depth; d++) {
|
||||
Vector3 height(start.x, 0.0, start.y);
|
||||
|
||||
for (int w = 0; w < map_width; w++) {
|
||||
height.y = r[r_offset++];
|
||||
|
||||
if (w != map_width - 1) {
|
||||
points.write[w_offset++] = height;
|
||||
points.write[w_offset++] = Vector3(height.x + 1.0, r[r_offset], height.z);
|
||||
}
|
||||
|
||||
if (d != map_depth - 1) {
|
||||
points.write[w_offset++] = height;
|
||||
points.write[w_offset++] = Vector3(height.x, r[r_offset + map_width - 1], height.z + 1.0);
|
||||
}
|
||||
|
||||
height.x += 1.0;
|
||||
}
|
||||
|
||||
if (d != map_depth - 1) {
|
||||
points.push_back(height);
|
||||
points.push_back(Vector3(height.x, r[offset + map_width - 1], height.z + 1.0));
|
||||
}
|
||||
|
||||
height.x += 1.0;
|
||||
start.y += 1.0;
|
||||
}
|
||||
|
||||
start.y += 1.0;
|
||||
}
|
||||
|
||||
return points;
|
||||
|
Loading…
Reference in New Issue
Block a user