Make heightmap shape usable from PhysicsServer
- Fixed bad size check - Fixed bad member initialization - Removed unused cell_size (Bullet expects us to use localScaling) - Accept precomputed min/max height, will be calculated if not provided
This commit is contained in:
parent
4a5723f59e
commit
a66e1af168
|
@ -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 ignoredHeightScale(1);
|
||||||
const btScalar fieldHeight(500); // Meters
|
|
||||||
const int YAxis = 1; // 0=X, 1=Y, 2=Z
|
const int YAxis = 1; // 0=X, 1=Y, 2=Z
|
||||||
const bool flipQuadEdges = false;
|
const bool flipQuadEdges = false;
|
||||||
const void *heightsPtr = p_heights.read().ptr();
|
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) {
|
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;
|
Dictionary d = p_data;
|
||||||
ERR_FAIL_COND(!d.has("width"));
|
ERR_FAIL_COND(!d.has("width"));
|
||||||
ERR_FAIL_COND(!d.has("depth"));
|
ERR_FAIL_COND(!d.has("depth"));
|
||||||
ERR_FAIL_COND(!d.has("cell_size"));
|
|
||||||
ERR_FAIL_COND(!d.has("heights"));
|
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_width = d["width"];
|
||||||
int l_depth = d["depth"];
|
int l_depth = d["depth"];
|
||||||
real_t l_cell_size = d["cell_size"];
|
|
||||||
PoolVector<real_t> l_heights = d["heights"];
|
PoolVector<real_t> l_heights = d["heights"];
|
||||||
|
|
||||||
ERR_FAIL_COND(l_width <= 0);
|
ERR_FAIL_COND(l_width <= 0);
|
||||||
ERR_FAIL_COND(l_depth <= 0);
|
ERR_FAIL_COND(l_depth <= 0);
|
||||||
ERR_FAIL_COND(l_cell_size <= CMP_EPSILON);
|
ERR_FAIL_COND(l_heights.size() != (l_width * l_depth));
|
||||||
ERR_FAIL_COND(l_heights.size() != (width * depth));
|
|
||||||
setup(heights, width, depth, cell_size);
|
// 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 {
|
Variant HeightMapShapeBullet::get_data() const {
|
||||||
|
@ -410,8 +434,14 @@ PhysicsServer::ShapeType HeightMapShapeBullet::get_type() const {
|
||||||
return PhysicsServer::SHAPE_HEIGHTMAP;
|
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
|
{ // 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();
|
const int heights_size = p_heights.size();
|
||||||
heights.resize(heights_size);
|
heights.resize(heights_size);
|
||||||
PoolVector<real_t>::Read p_heights_r = p_heights.read();
|
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];
|
heights_w[i] = p_heights_r[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
width = p_width;
|
width = p_width;
|
||||||
depth = p_depth;
|
depth = p_depth;
|
||||||
cell_size = p_cell_size;
|
min_height = p_min_height;
|
||||||
|
max_height = p_max_height;
|
||||||
notifyShapeChanged();
|
notifyShapeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
|
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);
|
cs->setLocalScaling(p_implicit_scale);
|
||||||
prepare(cs);
|
prepare(cs);
|
||||||
cs->setMargin(p_margin);
|
cs->setMargin(p_margin);
|
||||||
|
|
|
@ -85,7 +85,7 @@ public:
|
||||||
/// IMPORTANT: Remember to delete the shape interface by calling: delete my_shape->getMeshInterface();
|
/// 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 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 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);
|
static class btRayShape *create_shape_ray(real_t p_length, bool p_slips_on_slope);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,7 +199,8 @@ public:
|
||||||
PoolVector<real_t> heights;
|
PoolVector<real_t> heights;
|
||||||
int width;
|
int width;
|
||||||
int depth;
|
int depth;
|
||||||
real_t cell_size;
|
real_t min_height;
|
||||||
|
real_t max_height;
|
||||||
|
|
||||||
HeightMapShapeBullet();
|
HeightMapShapeBullet();
|
||||||
|
|
||||||
|
@ -209,7 +210,7 @@ public:
|
||||||
virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
|
virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
|
||||||
|
|
||||||
private:
|
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 {
|
class RayShapeBullet : public ShapeBullet {
|
||||||
|
|
Loading…
Reference in New Issue