Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heightmap collision shape support in Godot Physics #47347

Merged
merged 1 commit into from
Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions COPYRIGHT.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ Files: ./servers/physics_3d/gjk_epa.cpp
./servers/physics_3d/joints/slider_joint_3d_sw.h
./servers/physics_3d/soft_body_3d_sw.cpp
./servers/physics_3d/soft_body_3d_sw.h
./servers/physics_3d/shape_3d_sw.cpp
./servers/physics_3d/shape_3d_sw.h
Comment: Bullet Continuous Collision Detection and Physics Library
Copyright: 2003-2008, Erwin Coumans
2007-2021, Juan Linietsky, Ariel Manzur.
Expand Down
2 changes: 1 addition & 1 deletion doc/classes/HeightMapShape3D.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="HeightMapShape3D" inherits="Shape3D" version="4.0">
<brief_description>
Height map shape for 3D physics (Bullet only).
Height map shape for 3D physics.
</brief_description>
<description>
Height map shape resource, which can be added to a [PhysicsBody3D] or [Area3D].
Expand Down
25 changes: 7 additions & 18 deletions modules/bullet/shape_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ btScaledBvhTriangleMeshShape *ShapeBullet::create_shape_concave(btBvhTriangleMes
}
}

btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(Vector<float> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
const btScalar ignoredHeightScale(1);
const int YAxis = 1; // 0=X, 1=Y, 2=Z
const bool flipQuadEdges = false;
Expand Down Expand Up @@ -480,17 +480,10 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {
ERR_FAIL_COND_MSG(l_width < 2, "Map width must be at least 2.");
ERR_FAIL_COND_MSG(l_depth < 2, "Map depth must be at least 2.");

// TODO This code will need adjustments if real_t is set to `double`,
// because that precision is unnecessary for a heightmap and Bullet doesn't support it...

Vector<real_t> l_heights;
Vector<float> l_heights;
Variant l_heights_v = d["heights"];

#ifdef REAL_T_IS_DOUBLE
if (l_heights_v.get_type() == Variant::PACKED_FLOAT64_ARRAY) {
#else
if (l_heights_v.get_type() == Variant::PACKED_FLOAT32_ARRAY) {
#endif
// Ready-to-use heights can be passed

l_heights = l_heights_v;
Expand All @@ -511,21 +504,17 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {

l_heights.resize(l_image->get_width() * l_image->get_height());

real_t *w = l_heights.ptrw();
float *w = l_heights.ptrw();
const uint8_t *r = im_data.ptr();
real_t *rp = (real_t *)r;
float *rp = (float *)r;
// At this point, `rp` could be used directly for Bullet, but I don't know how safe it would be.

for (int i = 0; i < l_heights.size(); ++i) {
w[i] = rp[i];
}

} else {
#ifdef REAL_T_IS_DOUBLE
ERR_FAIL_MSG("Expected PackedFloat64Array or float Image.");
#else
ERR_FAIL_MSG("Expected PackedFloat32Array or float Image.");
#endif
}

ERR_FAIL_COND(l_width <= 0);
Expand All @@ -534,11 +523,11 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {

// Compute min and max heights if not specified.
if (!d.has("min_height") && !d.has("max_height")) {
const real_t *r = l_heights.ptr();
const float *r = l_heights.ptr();
int heights_size = l_heights.size();

for (int i = 0; i < heights_size; ++i) {
real_t h = r[i];
float h = r[i];

if (h < l_min_height) {
l_min_height = h;
Expand All @@ -559,7 +548,7 @@ PhysicsServer3D::ShapeType HeightMapShapeBullet::get_type() const {
return PhysicsServer3D::SHAPE_HEIGHTMAP;
}

void HeightMapShapeBullet::setup(Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
void HeightMapShapeBullet::setup(Vector<float> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
// TODO cell size must be tweaked using localScaling, which is a shared property for all Bullet shapes

// If this array is resized outside of here, it should be preserved due to CoW
Expand Down
6 changes: 3 additions & 3 deletions modules/bullet/shape_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class ShapeBullet : public RIDBullet {
/// IMPORTANT: Remember to delete the shape interface by calling: delete my_shape->getMeshInterface();
static class btConvexPointCloudShape *create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling = btVector3(1, 1, 1));
static class btScaledBvhTriangleMeshShape *create_shape_concave(btBvhTriangleMeshShape *p_mesh_shape, const btVector3 &p_local_scaling = btVector3(1, 1, 1));
static class btHeightfieldTerrainShape *create_shape_height_field(Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
static class btHeightfieldTerrainShape *create_shape_height_field(Vector<float> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
static class btRayShape *create_shape_ray(real_t p_length, bool p_slips_on_slope);
};

Expand Down Expand Up @@ -212,7 +212,7 @@ class ConcavePolygonShapeBullet : public ShapeBullet {

class HeightMapShapeBullet : public ShapeBullet {
public:
Vector<real_t> heights;
Vector<float> heights;
int width = 0;
int depth = 0;
real_t min_height = 0.0;
Expand All @@ -226,7 +226,7 @@ class HeightMapShapeBullet : public ShapeBullet {
virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);

private:
void setup(Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
void setup(Vector<float> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
};

class RayShapeBullet : public ShapeBullet {
Expand Down
12 changes: 6 additions & 6 deletions scene/resources/height_map_shape_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Vector<Vector3> HeightMapShape3D::get_debug_mesh_lines() const {
Vector2 size(map_width - 1, map_depth - 1);
Vector2 start = size * -0.5;

const real_t *r = map_data.ptr();
const float *r = map_data.ptr();

// reserve some memory for our points..
points.resize(((map_width - 1) * map_depth * 2) + (map_width * (map_depth - 1) * 2));
Expand Down Expand Up @@ -100,7 +100,7 @@ void HeightMapShape3D::set_map_width(int p_new) {
int new_size = map_width * map_depth;
map_data.resize(map_width * map_depth);

real_t *w = map_data.ptrw();
float *w = map_data.ptrw();
while (was_size < new_size) {
w[was_size++] = 0.0;
}
Expand All @@ -124,7 +124,7 @@ void HeightMapShape3D::set_map_depth(int p_new) {
int new_size = map_width * map_depth;
map_data.resize(new_size);

real_t *w = map_data.ptrw();
float *w = map_data.ptrw();
while (was_size < new_size) {
w[was_size++] = 0.0;
}
Expand All @@ -146,8 +146,8 @@ void HeightMapShape3D::set_map_data(PackedFloat32Array p_new) {
}

// copy
real_t *w = map_data.ptrw();
const real_t *r = p_new.ptr();
float *w = map_data.ptrw();
const float *r = p_new.ptr();
for (int i = 0; i < size; i++) {
float val = r[i];
w[i] = val;
Expand Down Expand Up @@ -189,7 +189,7 @@ void HeightMapShape3D::_bind_methods() {
HeightMapShape3D::HeightMapShape3D() :
Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_HEIGHTMAP)) {
map_data.resize(map_width * map_depth);
real_t *w = map_data.ptrw();
float *w = map_data.ptrw();
w[0] = 0.0;
w[1] = 0.0;
w[2] = 0.0;
Expand Down
4 changes: 2 additions & 2 deletions scene/resources/height_map_shape_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class HeightMapShape3D : public Shape3D {
int map_width = 2;
int map_depth = 2;
PackedFloat32Array map_data;
float min_height = 0.0;
float max_height = 0.0;
real_t min_height = 0.0;
real_t max_height = 0.0;

protected:
static void _bind_methods();
Expand Down
Loading