diff options
Diffstat (limited to 'modules/bullet/shape_bullet.cpp')
-rw-r--r-- | modules/bullet/shape_bullet.cpp | 170 |
1 files changed, 102 insertions, 68 deletions
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index f46db09e4a..74d6e073b3 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -46,10 +46,15 @@ @author AndreaCatania */ -ShapeBullet::ShapeBullet() : - margin(0.04) {} +ShapeBullet::ShapeBullet() { +} -ShapeBullet::~ShapeBullet() {} +ShapeBullet::~ShapeBullet() { + if (default_shape != nullptr) { + bulletdelete(default_shape); + default_shape = nullptr; + } +} btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_extra_edge) { btVector3 s; @@ -57,6 +62,22 @@ btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, return create_bt_shape(s, p_extra_edge); } +btCollisionShape *ShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { + if (p_extra_edge == 0.0 && (p_implicit_scale - btVector3(1, 1, 1)).length2() <= CMP_EPSILON) { + return default_shape; + } + + return internal_create_bt_shape(p_implicit_scale, p_extra_edge); +} + +void ShapeBullet::destroy_bt_shape(btCollisionShape *p_shape) const { + if (p_shape != default_shape && p_shape != old_default_shape) { + if (likely(p_shape != nullptr)) { + bulletdelete(p_shape); + } + } +} + btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const { p_btShape->setUserPointer(const_cast<ShapeBullet *>(this)); p_btShape->setMargin(margin); @@ -64,10 +85,21 @@ btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const { } void ShapeBullet::notifyShapeChanged() { + // Store the old shape ptr so to not lose the reference pointer. + old_default_shape = default_shape; + // Create the new default shape with the new data. + default_shape = internal_create_bt_shape(btVector3(1, 1, 1)); + for (Map<ShapeOwnerBullet *, int>::Element *E = owners.front(); E; E = E->next()) { ShapeOwnerBullet *owner = static_cast<ShapeOwnerBullet *>(E->key()); owner->shape_changed(owner->find_shape(this)); } + + if (old_default_shape) { + // At this point now one has the old default shape; just delete it. + bulletdelete(old_default_shape); + old_default_shape = nullptr; + } } void ShapeBullet::add_owner(ShapeOwnerBullet *p_owner) { @@ -81,7 +113,9 @@ void ShapeBullet::add_owner(ShapeOwnerBullet *p_owner) { void ShapeBullet::remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody) { Map<ShapeOwnerBullet *, int>::Element *E = owners.find(p_owner); - if (!E) return; + if (!E) { + return; + } E->get()--; if (p_permanentlyFromThisBody || 0 >= E->get()) { owners.erase(E); @@ -89,7 +123,6 @@ void ShapeBullet::remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFrom } bool ShapeBullet::is_owner(ShapeOwnerBullet *p_owner) const { - return owners.has(p_owner); } @@ -122,8 +155,8 @@ btBoxShape *ShapeBullet::create_shape_box(const btVector3 &boxHalfExtents) { return bulletnew(btBoxShape(boxHalfExtents)); } -btCapsuleShapeZ *ShapeBullet::create_shape_capsule(btScalar radius, btScalar height) { - return bulletnew(btCapsuleShapeZ(radius, height)); +btCapsuleShape *ShapeBullet::create_shape_capsule(btScalar radius, btScalar height) { + return bulletnew(btCapsuleShape(radius, height)); } btCylinderShape *ShapeBullet::create_shape_cylinder(btScalar radius, btScalar height) { @@ -138,21 +171,22 @@ btScaledBvhTriangleMeshShape *ShapeBullet::create_shape_concave(btBvhTriangleMes if (p_mesh_shape) { return bulletnew(btScaledBvhTriangleMeshShape(p_mesh_shape, p_local_scaling)); } else { - return NULL; + return nullptr; } } -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) { +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) { const btScalar ignoredHeightScale(1); const int YAxis = 1; // 0=X, 1=Y, 2=Z const bool flipQuadEdges = false; - const void *heightsPtr = p_heights.read().ptr(); + const void *heightsPtr = p_heights.ptr(); btHeightfieldTerrainShape *heightfield = bulletnew(btHeightfieldTerrainShape(p_width, p_depth, heightsPtr, ignoredHeightScale, p_min_height, p_max_height, YAxis, PHY_FLOAT, flipQuadEdges)); - // The shape can be created without params when you do PhysicsServer.shape_create(PhysicsServer.SHAPE_HEIGHTMAP) - if (heightsPtr) + // The shape can be created without params when you do PhysicsServer3D.shape_create(PhysicsServer3D.SHAPE_HEIGHTMAP) + if (heightsPtr) { heightfield->buildAccelerator(16); + } return heightfield; } @@ -176,8 +210,8 @@ Variant PlaneShapeBullet::get_data() const { return plane; } -PhysicsServer::ShapeType PlaneShapeBullet::get_type() const { - return PhysicsServer::SHAPE_PLANE; +PhysicsServer3D::ShapeType PlaneShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_PLANE; } void PlaneShapeBullet::setup(const Plane &p_plane) { @@ -185,7 +219,7 @@ void PlaneShapeBullet::setup(const Plane &p_plane) { notifyShapeChanged(); } -btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { +btCollisionShape *PlaneShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btVector3 btPlaneNormal; G_TO_B(plane.normal, btPlaneNormal); return prepare(PlaneShapeBullet::create_shape_plane(btPlaneNormal, plane.d)); @@ -204,8 +238,8 @@ Variant SphereShapeBullet::get_data() const { return radius; } -PhysicsServer::ShapeType SphereShapeBullet::get_type() const { - return PhysicsServer::SHAPE_SPHERE; +PhysicsServer3D::ShapeType SphereShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_SPHERE; } void SphereShapeBullet::setup(real_t p_radius) { @@ -213,7 +247,7 @@ void SphereShapeBullet::setup(real_t p_radius) { notifyShapeChanged(); } -btCollisionShape *SphereShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { +btCollisionShape *SphereShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { return prepare(ShapeBullet::create_shape_sphere(radius * p_implicit_scale[0] + p_extra_edge)); } @@ -231,8 +265,8 @@ Variant BoxShapeBullet::get_data() const { return g_half_extents; } -PhysicsServer::ShapeType BoxShapeBullet::get_type() const { - return PhysicsServer::SHAPE_BOX; +PhysicsServer3D::ShapeType BoxShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_BOX; } void BoxShapeBullet::setup(const Vector3 &p_half_extents) { @@ -240,7 +274,7 @@ void BoxShapeBullet::setup(const Vector3 &p_half_extents) { notifyShapeChanged(); } -btCollisionShape *BoxShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { +btCollisionShape *BoxShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { return prepare(ShapeBullet::create_shape_box((half_extents * p_implicit_scale) + btVector3(p_extra_edge, p_extra_edge, p_extra_edge))); } @@ -263,8 +297,8 @@ Variant CapsuleShapeBullet::get_data() const { return d; } -PhysicsServer::ShapeType CapsuleShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CAPSULE; +PhysicsServer3D::ShapeType CapsuleShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CAPSULE; } void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) { @@ -273,8 +307,8 @@ void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) { notifyShapeChanged(); } -btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { - return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1] + p_extra_edge)); +btCollisionShape *CapsuleShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { + return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1])); } /* Cylinder */ @@ -296,8 +330,8 @@ Variant CylinderShapeBullet::get_data() const { return d; } -PhysicsServer::ShapeType CylinderShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CYLINDER; +PhysicsServer3D::ShapeType CylinderShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CYLINDER; } void CylinderShapeBullet::setup(real_t p_height, real_t p_radius) { @@ -306,7 +340,7 @@ void CylinderShapeBullet::setup(real_t p_height, real_t p_radius) { notifyShapeChanged(); } -btCollisionShape *CylinderShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { +btCollisionShape *CylinderShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { return prepare(ShapeBullet::create_shape_cylinder(radius * p_implicit_scale[0] + p_margin, height * p_implicit_scale[1] + p_margin)); } @@ -334,8 +368,8 @@ Variant ConvexPolygonShapeBullet::get_data() const { return out_vertices; } -PhysicsServer::ShapeType ConvexPolygonShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CONVEX_POLYGON; +PhysicsServer3D::ShapeType ConvexPolygonShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CONVEX_POLYGON; } void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) { @@ -348,10 +382,11 @@ void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) { notifyShapeChanged(); } -btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { - if (!vertices.size()) +btCollisionShape *ConvexPolygonShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { + if (!vertices.size()) { // This is necessary since 0 vertices return prepare(ShapeBullet::create_shape_empty()); + } btCollisionShape *cs(ShapeBullet::create_shape_convex(vertices)); cs->setLocalScaling(p_implicit_scale); prepare(cs); @@ -361,8 +396,7 @@ btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_i /* Concave polygon */ ConcavePolygonShapeBullet::ConcavePolygonShapeBullet() : - ShapeBullet(), - meshShape(NULL) {} + ShapeBullet() {} ConcavePolygonShapeBullet::~ConcavePolygonShapeBullet() { if (meshShape) { @@ -370,7 +404,7 @@ ConcavePolygonShapeBullet::~ConcavePolygonShapeBullet() { delete meshShape->getTriangleInfoMap(); bulletdelete(meshShape); } - faces = PoolVector<Vector3>(); + faces = Vector<Vector3>(); } void ConcavePolygonShapeBullet::set_data(const Variant &p_data) { @@ -381,11 +415,11 @@ Variant ConcavePolygonShapeBullet::get_data() const { return faces; } -PhysicsServer::ShapeType ConcavePolygonShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CONCAVE_POLYGON; +PhysicsServer3D::ShapeType ConcavePolygonShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; } -void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) { +void ConcavePolygonShapeBullet::setup(Vector<Vector3> p_faces) { faces = p_faces; if (meshShape) { /// Clear previous created shape @@ -395,14 +429,13 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) { } int src_face_count = faces.size(); if (0 < src_face_count) { - // It counts the faces and assert the array contains the correct number of vertices. ERR_FAIL_COND(src_face_count % 3); btTriangleMesh *shapeInterface = bulletnew(btTriangleMesh); src_face_count /= 3; - PoolVector<Vector3>::Read r = p_faces.read(); - const Vector3 *facesr = r.ptr(); + const Vector3 *r = p_faces.ptr(); + const Vector3 *facesr = r; btVector3 supVec_0; btVector3 supVec_1; @@ -425,17 +458,18 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) { btGenerateInternalEdgeInfo(meshShape, triangleInfoMap); } } else { - meshShape = NULL; + meshShape = nullptr; ERR_PRINT("The faces count are 0, the mesh shape cannot be created"); } notifyShapeChanged(); } -btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { +btCollisionShape *ConcavePolygonShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btCollisionShape *cs = ShapeBullet::create_shape_concave(meshShape); - if (!cs) - // This is necessary since if 0 faces the creation of concave return NULL + if (!cs) { + // This is necessary since if 0 faces the creation of concave return null cs = ShapeBullet::create_shape_empty(); + } cs->setLocalScaling(p_implicit_scale); prepare(cs); cs->setMargin(0); @@ -458,23 +492,28 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) { real_t l_max_height = 0.0; // If specified, min and max height will be used as precomputed values - if (d.has("min_height")) + if (d.has("min_height")) { l_min_height = d["min_height"]; - if (d.has("max_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"]; + 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... - PoolVector<real_t> l_heights; + Vector<real_t> l_heights; Variant l_heights_v = d["heights"]; - if (l_heights_v.get_type() == Variant::POOL_REAL_ARRAY) { + if (l_heights_v.get_type() == Variant::PACKED_FLOAT32_ARRAY) { // Ready-to-use heights can be passed l_heights = l_heights_v; @@ -491,13 +530,13 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) { // We could convert here automatically but it's better to not be intrusive and let the caller do it if necessary. ERR_FAIL_COND(l_image->get_format() != Image::FORMAT_RF); - PoolByteArray im_data = l_image->get_data(); + PackedByteArray im_data = l_image->get_data(); l_heights.resize(l_image->get_width() * l_image->get_height()); - PoolRealArray::Write w = l_heights.write(); - PoolByteArray::Read r = im_data.read(); - float *rp = (float *)r.ptr(); + real_t *w = l_heights.ptrw(); + const uint8_t *r = im_data.ptr(); + 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) { @@ -505,7 +544,7 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) { } } else { - ERR_FAIL_MSG("Expected PoolRealArray or float Image."); + ERR_FAIL_MSG("Expected PackedFloat32Array or float Image."); } ERR_FAIL_COND(l_width <= 0); @@ -514,8 +553,7 @@ 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")) { - - PoolVector<real_t>::Read r = l_heights.read(); + const real_t *r = l_heights.ptr(); int heights_size = l_heights.size(); for (int i = 0; i < heights_size; ++i) { @@ -536,11 +574,11 @@ Variant HeightMapShapeBullet::get_data() const { ERR_FAIL_V(Variant()); } -PhysicsServer::ShapeType HeightMapShapeBullet::get_type() const { - return PhysicsServer::SHAPE_HEIGHTMAP; +PhysicsServer3D::ShapeType HeightMapShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_HEIGHTMAP; } -void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) { +void HeightMapShapeBullet::setup(Vector<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 // If this array is resized outside of here, it should be preserved due to CoW @@ -553,7 +591,7 @@ void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int notifyShapeChanged(); } -btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { +btCollisionShape *HeightMapShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btCollisionShape *cs(ShapeBullet::create_shape_height_field(heights, width, depth, min_height, max_height)); cs->setLocalScaling(p_implicit_scale); prepare(cs); @@ -562,26 +600,22 @@ btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_impli /* Ray shape */ RayShapeBullet::RayShapeBullet() : - ShapeBullet(), - length(1), - slips_on_slope(false) {} + ShapeBullet() {} void RayShapeBullet::set_data(const Variant &p_data) { - Dictionary d = p_data; setup(d["length"], d["slips_on_slope"]); } Variant RayShapeBullet::get_data() const { - Dictionary d; d["length"] = length; d["slips_on_slope"] = slips_on_slope; return d; } -PhysicsServer::ShapeType RayShapeBullet::get_type() const { - return PhysicsServer::SHAPE_RAY; +PhysicsServer3D::ShapeType RayShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_RAY; } void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) { @@ -590,6 +624,6 @@ void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) { notifyShapeChanged(); } -btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { +btCollisionShape *RayShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_extra_edge, slips_on_slope)); } |