Merge pull request #17806 from Zylann/fix_heightmap_shape_size_check
Make heightmap shape usable in PhysicsServer
This commit is contained in:
commit
e1b9c98032
2 changed files with 47 additions and 14 deletions
|
@ -125,14 +125,13 @@ btScaledBvhTriangleMeshShape *ShapeBullet::create_shape_concave(btBvhTriangleMes
|
|||
}
|
||||
}
|
||||
|
||||
btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size) {
|
||||
btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
|
||||
const btScalar ignoredHeightScale(1);
|
||||
const btScalar fieldHeight(500); // Meters
|
||||
const int YAxis = 1; // 0=X, 1=Y, 2=Z
|
||||
const bool flipQuadEdges = false;
|
||||
const void *heightsPtr = p_heights.read().ptr();
|
||||
|
||||
return bulletnew(btHeightfieldTerrainShape(p_width, p_depth, heightsPtr, ignoredHeightScale, -fieldHeight, fieldHeight, YAxis, PHY_FLOAT, flipQuadEdges));
|
||||
return bulletnew(btHeightfieldTerrainShape(p_width, p_depth, heightsPtr, ignoredHeightScale, p_min_height, p_max_height, YAxis, PHY_FLOAT, flipQuadEdges));
|
||||
}
|
||||
|
||||
btRayShape *ShapeBullet::create_shape_ray(real_t p_length, bool p_slips_on_slope) {
|
||||
|
@ -387,19 +386,44 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {
|
|||
Dictionary d = p_data;
|
||||
ERR_FAIL_COND(!d.has("width"));
|
||||
ERR_FAIL_COND(!d.has("depth"));
|
||||
ERR_FAIL_COND(!d.has("cell_size"));
|
||||
ERR_FAIL_COND(!d.has("heights"));
|
||||
|
||||
real_t l_min_height = 0.0;
|
||||
real_t l_max_height = 0.0;
|
||||
|
||||
// If specified, min and max height will be used as precomputed values
|
||||
if (d.has("min_height"))
|
||||
l_min_height = d["min_height"];
|
||||
if (d.has("max_height"))
|
||||
l_max_height = d["max_height"];
|
||||
|
||||
ERR_FAIL_COND(l_min_height > l_max_height);
|
||||
|
||||
int l_width = d["width"];
|
||||
int l_depth = d["depth"];
|
||||
real_t l_cell_size = d["cell_size"];
|
||||
PoolVector<real_t> l_heights = d["heights"];
|
||||
|
||||
ERR_FAIL_COND(l_width <= 0);
|
||||
ERR_FAIL_COND(l_depth <= 0);
|
||||
ERR_FAIL_COND(l_cell_size <= CMP_EPSILON);
|
||||
ERR_FAIL_COND(l_heights.size() != (width * depth));
|
||||
setup(heights, width, depth, cell_size);
|
||||
ERR_FAIL_COND(l_heights.size() != (l_width * l_depth));
|
||||
|
||||
// Compute min and max heights if not specified.
|
||||
if (!d.has("min_height") && !d.has("max_height")) {
|
||||
|
||||
PoolVector<real_t>::Read r = heights.read();
|
||||
int heights_size = heights.size();
|
||||
|
||||
for (int i = 0; i < heights_size; ++i) {
|
||||
real_t h = r[i];
|
||||
|
||||
if (h < l_min_height)
|
||||
l_min_height = h;
|
||||
else if (h > l_max_height)
|
||||
l_max_height = h;
|
||||
}
|
||||
}
|
||||
|
||||
setup(l_heights, l_width, l_depth, l_min_height, l_max_height);
|
||||
}
|
||||
|
||||
Variant HeightMapShapeBullet::get_data() const {
|
||||
|
@ -410,8 +434,14 @@ PhysicsServer::ShapeType HeightMapShapeBullet::get_type() const {
|
|||
return PhysicsServer::SHAPE_HEIGHTMAP;
|
||||
}
|
||||
|
||||
void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size) {
|
||||
void HeightMapShapeBullet::setup(PoolVector<real_t> &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
|
||||
|
||||
{ // Copy
|
||||
|
||||
// TODO If Godot supported 16-bit integer image format, we could share the same memory block for heightfields
|
||||
// without having to copy anything, optimizing memory and loading performance (Bullet only reads and doesn't take ownership of the data).
|
||||
|
||||
const int heights_size = p_heights.size();
|
||||
heights.resize(heights_size);
|
||||
PoolVector<real_t>::Read p_heights_r = p_heights.read();
|
||||
|
@ -420,14 +450,16 @@ void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int
|
|||
heights_w[i] = p_heights_r[i];
|
||||
}
|
||||
}
|
||||
|
||||
width = p_width;
|
||||
depth = p_depth;
|
||||
cell_size = p_cell_size;
|
||||
min_height = p_min_height;
|
||||
max_height = p_max_height;
|
||||
notifyShapeChanged();
|
||||
}
|
||||
|
||||
btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
|
||||
btCollisionShape *cs(ShapeBullet::create_shape_height_field(heights, width, depth, cell_size));
|
||||
btCollisionShape *cs(ShapeBullet::create_shape_height_field(heights, width, depth, min_height, max_height));
|
||||
cs->setLocalScaling(p_implicit_scale);
|
||||
prepare(cs);
|
||||
cs->setMargin(p_margin);
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
/// 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(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size);
|
||||
static class btHeightfieldTerrainShape *create_shape_height_field(PoolVector<real_t> &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);
|
||||
};
|
||||
|
||||
|
@ -199,7 +199,8 @@ public:
|
|||
PoolVector<real_t> heights;
|
||||
int width;
|
||||
int depth;
|
||||
real_t cell_size;
|
||||
real_t min_height;
|
||||
real_t max_height;
|
||||
|
||||
HeightMapShapeBullet();
|
||||
|
||||
|
@ -209,7 +210,7 @@ public:
|
|||
virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
|
||||
|
||||
private:
|
||||
void setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size);
|
||||
void setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
|
||||
};
|
||||
|
||||
class RayShapeBullet : public ShapeBullet {
|
||||
|
|
Loading…
Reference in a new issue