|
|
@@ -13,12 +13,12 @@ namespace gameplay
|
|
|
PhysicsRigidBody::PhysicsRigidBody(Node* node, const PhysicsCollisionShape::Definition& shape, const Parameters& parameters)
|
|
|
: PhysicsCollisionObject(node), _body(NULL), _mass(parameters.mass), _constraints(NULL)
|
|
|
{
|
|
|
- // Create our collision sh ape
|
|
|
- Vector3 centerOfMassOffset;
|
|
|
- _collisionShape = Game::getInstance()->getPhysicsController()->createShape(node, shape, ¢erOfMassOffset);
|
|
|
+ // Create our collision shape
|
|
|
+ Vector3 centerOfMassOffset;
|
|
|
+ _collisionShape = Game::getInstance()->getPhysicsController()->createShape(node, shape, ¢erOfMassOffset);
|
|
|
|
|
|
- // Create motion state object
|
|
|
- _motionState = new PhysicsMotionState(node, (centerOfMassOffset.lengthSquared() > MATH_EPSILON) ? ¢erOfMassOffset : NULL);
|
|
|
+ // Create motion state object
|
|
|
+ _motionState = new PhysicsMotionState(node, (centerOfMassOffset.lengthSquared() > MATH_EPSILON) ? ¢erOfMassOffset : NULL);
|
|
|
|
|
|
// If the mass is non-zero, then the object is dynamic so we calculate the local
|
|
|
// inertia. However, if the collision shape is a triangle mesh, we don't calculate
|
|
|
@@ -34,48 +34,48 @@ PhysicsRigidBody::PhysicsRigidBody(Node* node, const PhysicsCollisionShape::Defi
|
|
|
rbInfo.m_linearDamping = parameters.linearDamping;
|
|
|
rbInfo.m_angularDamping = parameters.angularDamping;
|
|
|
|
|
|
- // Create + assign the new bullet rigid body object.
|
|
|
- _body = bullet_new<btRigidBody>(rbInfo);
|
|
|
+ // Create + assign the new bullet rigid body object.
|
|
|
+ _body = bullet_new<btRigidBody>(rbInfo);
|
|
|
|
|
|
- // Set other initially defined properties.
|
|
|
+ // Set other initially defined properties.
|
|
|
setKinematic(parameters.kinematic);
|
|
|
- setAnisotropicFriction(parameters.anisotropicFriction);
|
|
|
- setGravity(parameters.gravity);
|
|
|
+ setAnisotropicFriction(parameters.anisotropicFriction);
|
|
|
+ setGravity(parameters.gravity);
|
|
|
|
|
|
// Add ourself to the physics world.
|
|
|
Game::getInstance()->getPhysicsController()->addCollisionObject(this);
|
|
|
|
|
|
- if (_collisionShape->getType() == PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
|
|
|
- {
|
|
|
- // Add a listener on the node's transform so we can track dirty changes to calculate
|
|
|
- // an inverse matrix for transforming heightfield points between world and local space.
|
|
|
- _node->addListener(this);
|
|
|
- }
|
|
|
+ if (_collisionShape->getType() == PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
|
|
|
+ {
|
|
|
+ // Add a listener on the node's transform so we can track dirty changes to calculate
|
|
|
+ // an inverse matrix for transforming heightfield points between world and local space.
|
|
|
+ _node->addListener(this);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
PhysicsRigidBody::~PhysicsRigidBody()
|
|
|
{
|
|
|
- // Clean up all constraints linked to this rigid body.
|
|
|
- if (_constraints)
|
|
|
- {
|
|
|
- for (unsigned int i = 0; i < _constraints->size(); ++i)
|
|
|
- {
|
|
|
- SAFE_DELETE((*_constraints)[i]);
|
|
|
- }
|
|
|
- SAFE_DELETE(_constraints);
|
|
|
- }
|
|
|
-
|
|
|
- // Remove collision object from physics controller
|
|
|
+ // Clean up all constraints linked to this rigid body.
|
|
|
+ if (_constraints)
|
|
|
+ {
|
|
|
+ for (unsigned int i = 0; i < _constraints->size(); ++i)
|
|
|
+ {
|
|
|
+ SAFE_DELETE((*_constraints)[i]);
|
|
|
+ }
|
|
|
+ SAFE_DELETE(_constraints);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Remove collision object from physics controller
|
|
|
Game::getInstance()->getPhysicsController()->removeCollisionObject(this);
|
|
|
|
|
|
// Clean up the rigid body and its related objects.
|
|
|
- SAFE_DELETE(_body);
|
|
|
+ SAFE_DELETE(_body);
|
|
|
|
|
|
- // Unregister node listener (only registered for heihgtfield collision shape types)
|
|
|
- if (_collisionShape->getType() == PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
|
|
|
- {
|
|
|
- _node->removeListener(this);
|
|
|
- }
|
|
|
+ // Unregister node listener (only registered for heihgtfield collision shape types)
|
|
|
+ if (_collisionShape->getType() == PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
|
|
|
+ {
|
|
|
+ _node->removeListener(this);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
PhysicsCollisionObject::Type PhysicsRigidBody::getType() const
|
|
|
@@ -141,25 +141,6 @@ void PhysicsRigidBody::applyTorqueImpulse(const Vector3& torque)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-PhysicsRigidBody* PhysicsRigidBody::create(Node* node, const char* filePath)
|
|
|
-{
|
|
|
- assert(filePath);
|
|
|
-
|
|
|
- // Load the rigid body properties from file.
|
|
|
- Properties* properties = Properties::create(filePath);
|
|
|
- assert(properties);
|
|
|
- if (properties == NULL)
|
|
|
- {
|
|
|
- WARN_VARG("Failed to load rigid body file: %s", filePath);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- PhysicsRigidBody* body = create(node, properties->getNextNamespace());
|
|
|
- SAFE_DELETE(properties);
|
|
|
-
|
|
|
- return body;
|
|
|
-}
|
|
|
-
|
|
|
PhysicsRigidBody* PhysicsRigidBody::create(Node* node, Properties* properties)
|
|
|
{
|
|
|
// Check if the properties is valid and has a valid namespace.
|
|
|
@@ -170,41 +151,23 @@ PhysicsRigidBody* PhysicsRigidBody::create(Node* node, Properties* properties)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- // Set values to their defaults.
|
|
|
- bool typeSpecified = false;
|
|
|
- PhysicsCollisionShape::Type type;
|
|
|
- Parameters parameters;
|
|
|
- const char* imagePath = NULL;
|
|
|
- float radius, height;
|
|
|
- Vector3 center, min, max;
|
|
|
- int bits = 0;
|
|
|
+ // Load the physics collision shape definition.
|
|
|
+ PhysicsCollisionShape::Definition* shape = PhysicsCollisionShape::Definition::create(node, properties);
|
|
|
+ if (shape == NULL)
|
|
|
+ {
|
|
|
+ WARN("Failed to create collision shape during rigid body creation.");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set the rigid body parameters to their defaults.
|
|
|
+ Parameters parameters;
|
|
|
|
|
|
- // Load the defined properties.
|
|
|
+ // Load the defined rigid body parameters.
|
|
|
properties->rewind();
|
|
|
const char* name;
|
|
|
while ((name = properties->getNextProperty()) != NULL)
|
|
|
{
|
|
|
- if (strcmp(name, "type") == 0)
|
|
|
- {
|
|
|
- std::string typeStr = properties->getString();
|
|
|
- if (typeStr == "BOX")
|
|
|
- type = PhysicsCollisionShape::SHAPE_BOX;
|
|
|
- else if (typeStr == "SPHERE")
|
|
|
- type = PhysicsCollisionShape::SHAPE_SPHERE;
|
|
|
- else if (typeStr == "CAPSULE")
|
|
|
- type = PhysicsCollisionShape::SHAPE_CAPSULE;
|
|
|
- else if (typeStr == "HEIGHTFIELD")
|
|
|
- type = PhysicsCollisionShape::SHAPE_HEIGHTFIELD;
|
|
|
- else if (typeStr == "MESH")
|
|
|
- type = PhysicsCollisionShape::SHAPE_MESH;
|
|
|
- else
|
|
|
- {
|
|
|
- WARN_VARG("Could not create rigid body; unsupported value for rigid body type: '%s'.", typeStr.c_str());
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- typeSpecified = true;
|
|
|
- }
|
|
|
- else if (strcmp(name, "mass") == 0)
|
|
|
+ if (strcmp(name, "mass") == 0)
|
|
|
{
|
|
|
parameters.mass = properties->getFloat();
|
|
|
}
|
|
|
@@ -236,136 +199,11 @@ PhysicsRigidBody* PhysicsRigidBody::create(Node* node, Properties* properties)
|
|
|
{
|
|
|
properties->getVector3(NULL, ¶meters.gravity);
|
|
|
}
|
|
|
- else if (strcmp(name, "image") == 0)
|
|
|
- {
|
|
|
- imagePath = properties->getString();
|
|
|
- }
|
|
|
- else if (strcmp(name, "radius") == 0)
|
|
|
- {
|
|
|
- radius = properties->getFloat();
|
|
|
- bits |= 1;
|
|
|
- }
|
|
|
- else if (strcmp(name, "height") == 0)
|
|
|
- {
|
|
|
- height = properties->getFloat();
|
|
|
- bits |= 2;
|
|
|
- }
|
|
|
- else if (strcmp(name, "center") == 0)
|
|
|
- {
|
|
|
- properties->getVector3(NULL, ¢er);
|
|
|
- bits |= 4;
|
|
|
- }
|
|
|
- else if (strcmp(name, "min") == 0)
|
|
|
- {
|
|
|
- properties->getVector3(NULL, &min);
|
|
|
- bits |= 8;
|
|
|
- }
|
|
|
- else if (strcmp(name, "max") == 0)
|
|
|
- {
|
|
|
- properties->getVector3(NULL, &max);
|
|
|
- bits |= 16;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
- if (!typeSpecified)
|
|
|
- {
|
|
|
- WARN("Missing 'type' specifier for rigid body definition.");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- PhysicsRigidBody* body = NULL;
|
|
|
-
|
|
|
- switch (type)
|
|
|
- {
|
|
|
- case PhysicsCollisionShape::SHAPE_BOX:
|
|
|
- if ((bits & 8/*min*/) || (bits & 16/*max*/))
|
|
|
- {
|
|
|
- // Explicitly defined box shape
|
|
|
- body = new PhysicsRigidBody(node, PhysicsCollisionShape::box(min, max), parameters);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Auto box shape
|
|
|
- body = new PhysicsRigidBody(node, PhysicsCollisionShape::box(), parameters);
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case PhysicsCollisionShape::SHAPE_SPHERE:
|
|
|
- if ((bits & 4/*center*/) || (bits & 1/*radius*/))
|
|
|
- {
|
|
|
- // Explicitly defined sphere shape
|
|
|
- body = new PhysicsRigidBody(node, PhysicsCollisionShape::sphere(radius, center), parameters);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Auto sphere shape
|
|
|
- body = new PhysicsRigidBody(node, PhysicsCollisionShape::sphere(), parameters);
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case PhysicsCollisionShape::SHAPE_CAPSULE:
|
|
|
- if ((bits & 1/*radius*/) || (bits & 2/*height*/))
|
|
|
- {
|
|
|
- // Explicitly defined capsule shape
|
|
|
- body = new PhysicsRigidBody(node, PhysicsCollisionShape::capsule(radius, height, center), parameters);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Auto capsule shape
|
|
|
- body = new PhysicsRigidBody(node, PhysicsCollisionShape::capsule(), parameters);
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case PhysicsCollisionShape::SHAPE_HEIGHTFIELD:
|
|
|
- {
|
|
|
- if (imagePath == NULL)
|
|
|
- {
|
|
|
- WARN("Heightfield rigid body requires an image path.");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- // Load the image data from the given file path.
|
|
|
- Image* image = Image::create(imagePath);
|
|
|
- if (!image)
|
|
|
- {
|
|
|
- WARN_VARG("Failed to load heightmap image: %s", imagePath);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- // Ensure that the image's pixel format is supported.
|
|
|
- switch (image->getFormat())
|
|
|
- {
|
|
|
- case Image::RGB:
|
|
|
- case Image::RGBA:
|
|
|
- break;
|
|
|
- default:
|
|
|
- WARN_VARG("Heightmap: pixel format is not supported: %d", image->getFormat());
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- body = new PhysicsRigidBody(node, PhysicsCollisionShape::heightfield(image), parameters);
|
|
|
-
|
|
|
- SAFE_RELEASE(image);
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case PhysicsCollisionShape::SHAPE_MESH:
|
|
|
- {
|
|
|
- // Mesh is required on node
|
|
|
- Mesh* mesh = node->getModel() ? node->getModel()->getMesh() : NULL;
|
|
|
- if (mesh == NULL)
|
|
|
- {
|
|
|
- WARN("Cannot create mesh rigid body for node without mode/mesh.");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- body = new PhysicsRigidBody(node, PhysicsCollisionShape::mesh(mesh), parameters);
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
+ // Create the rigid body.
|
|
|
+ PhysicsRigidBody* body = new PhysicsRigidBody(node, *shape, parameters);
|
|
|
+ SAFE_DELETE(shape);
|
|
|
|
|
|
return body;
|
|
|
}
|
|
|
@@ -387,21 +225,21 @@ void PhysicsRigidBody::setKinematic(bool kinematic)
|
|
|
float PhysicsRigidBody::getHeight(float x, float y) const
|
|
|
{
|
|
|
// This function is only supported for heightfield rigid bodies.
|
|
|
- if (_collisionShape->getType() != PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
|
|
|
+ if (_collisionShape->getType() != PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
|
|
|
{
|
|
|
WARN("Attempting to get the height of a non-heightfield rigid body.");
|
|
|
return 0.0f;
|
|
|
}
|
|
|
|
|
|
// Calculate the correct x, y position relative to the heightfield data.
|
|
|
- if (_collisionShape->_shapeData.heightfieldData->inverseIsDirty)
|
|
|
+ if (_collisionShape->_shapeData.heightfieldData->inverseIsDirty)
|
|
|
{
|
|
|
- _node->getWorldMatrix().invert(&_collisionShape->_shapeData.heightfieldData->inverse);
|
|
|
- _collisionShape->_shapeData.heightfieldData->inverseIsDirty = false;
|
|
|
+ _node->getWorldMatrix().invert(&_collisionShape->_shapeData.heightfieldData->inverse);
|
|
|
+ _collisionShape->_shapeData.heightfieldData->inverseIsDirty = false;
|
|
|
}
|
|
|
|
|
|
- float w = _collisionShape->_shapeData.heightfieldData->width;
|
|
|
- float h = _collisionShape->_shapeData.heightfieldData->height;
|
|
|
+ float w = _collisionShape->_shapeData.heightfieldData->width;
|
|
|
+ float h = _collisionShape->_shapeData.heightfieldData->height;
|
|
|
|
|
|
Vector3 v = _collisionShape->_shapeData.heightfieldData->inverse * Vector3(x, 0.0f, y);
|
|
|
x = (v.x + (0.5f * (w - 1))) * w / (w - 1);
|
|
|
@@ -414,43 +252,43 @@ float PhysicsRigidBody::getHeight(float x, float y) const
|
|
|
return 0.0f;
|
|
|
}
|
|
|
|
|
|
- return PhysicsController::calculateHeight(_collisionShape->_shapeData.heightfieldData->heightData, w, h, x, y);
|
|
|
+ return PhysicsController::calculateHeight(_collisionShape->_shapeData.heightfieldData->heightData, w, h, x, y);
|
|
|
}
|
|
|
|
|
|
void PhysicsRigidBody::addConstraint(PhysicsConstraint* constraint)
|
|
|
{
|
|
|
- if (_constraints == NULL)
|
|
|
- _constraints = new std::vector<PhysicsConstraint*>();
|
|
|
+ if (_constraints == NULL)
|
|
|
+ _constraints = new std::vector<PhysicsConstraint*>();
|
|
|
|
|
|
_constraints->push_back(constraint);
|
|
|
}
|
|
|
|
|
|
void PhysicsRigidBody::removeConstraint(PhysicsConstraint* constraint)
|
|
|
{
|
|
|
- if (_constraints)
|
|
|
- {
|
|
|
- for (unsigned int i = 0; i < _constraints->size(); ++i)
|
|
|
- {
|
|
|
- if ((*_constraints)[i] == constraint)
|
|
|
- {
|
|
|
- _constraints->erase(_constraints->begin() + i);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ if (_constraints)
|
|
|
+ {
|
|
|
+ for (unsigned int i = 0; i < _constraints->size(); ++i)
|
|
|
+ {
|
|
|
+ if ((*_constraints)[i] == constraint)
|
|
|
+ {
|
|
|
+ _constraints->erase(_constraints->begin() + i);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
bool PhysicsRigidBody::supportsConstraints()
|
|
|
{
|
|
|
- return (getShapeType() != PhysicsCollisionShape::SHAPE_HEIGHTFIELD && getShapeType() != PhysicsCollisionShape::SHAPE_MESH);
|
|
|
+ return (getShapeType() != PhysicsCollisionShape::SHAPE_HEIGHTFIELD && getShapeType() != PhysicsCollisionShape::SHAPE_MESH);
|
|
|
}
|
|
|
|
|
|
void PhysicsRigidBody::transformChanged(Transform* transform, long cookie)
|
|
|
{
|
|
|
- if (getShapeType() == PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
|
|
|
- {
|
|
|
- _collisionShape->_shapeData.heightfieldData->inverseIsDirty = true;
|
|
|
- }
|
|
|
+ if (getShapeType() == PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
|
|
|
+ {
|
|
|
+ _collisionShape->_shapeData.heightfieldData->inverseIsDirty = true;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
}
|