mirror of https://github.com/axmolengine/axmol.git
issue #2771: implement contact callbacks
This commit is contained in:
parent
a8ddca81bd
commit
fdcf019665
|
@ -142,7 +142,7 @@ public:
|
|||
/*
|
||||
* @brief get all joints the body have
|
||||
*/
|
||||
inline const std::vector<PhysicsJoint*>* getJoints() const { return &_joints; }
|
||||
inline const std::vector<PhysicsJoint*>& getJoints() const { return _joints; }
|
||||
|
||||
/*
|
||||
* @brief get the sprite the body set to.
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#include "chipmunk/CCPhysicsContactInfo.h"
|
||||
#include "box2d/CCPhysicsContactInfo.h"
|
||||
#include "chipmunk/CCPhysicsHelper.h"
|
||||
#include "box2d/CCPhysicsHelper.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -39,7 +41,11 @@ PhysicsContact::PhysicsContact()
|
|||
: _shapeA(nullptr)
|
||||
, _shapeB(nullptr)
|
||||
, _info(nullptr)
|
||||
, _notify(true)
|
||||
, _begin(false)
|
||||
, _data(nullptr)
|
||||
, _contactInfo(nullptr)
|
||||
, _contactData(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -47,6 +53,7 @@ PhysicsContact::PhysicsContact()
|
|||
PhysicsContact::~PhysicsContact()
|
||||
{
|
||||
CC_SAFE_DELETE(_info);
|
||||
CC_SAFE_DELETE(_contactData);
|
||||
}
|
||||
|
||||
PhysicsContact* PhysicsContact::create(PhysicsShape* a, PhysicsShape* b)
|
||||
|
@ -78,37 +85,69 @@ bool PhysicsContact::init(PhysicsShape* a, PhysicsShape* b)
|
|||
return false;
|
||||
}
|
||||
|
||||
// PhysicsContactPreSolve implementation
|
||||
PhysicsContactPreSolve::PhysicsContactPreSolve()
|
||||
void PhysicsContact::generateContactData()
|
||||
{
|
||||
if (_contactInfo == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cpArbiter* arb = (cpArbiter*)_contactInfo;
|
||||
_contactData = new PhysicsContactData();
|
||||
_contactData->count = cpArbiterGetCount(arb);
|
||||
for (int i=0; i<_contactData->count; ++i)
|
||||
{
|
||||
_contactData->points[i] = PhysicsHelper::cpv2point(cpArbiterGetPoint(arb, i));
|
||||
}
|
||||
|
||||
_contactData->normal = _contactData->count > 0 ? PhysicsHelper::cpv2point(cpArbiterGetNormal(arb, 0)) : Point::ZERO;
|
||||
}
|
||||
|
||||
// PhysicsContactPreSolve implementation
|
||||
PhysicsContactPreSolve::PhysicsContactPreSolve(PhysicsContactData* data, void* contactInfo)
|
||||
: _preContactData(data)
|
||||
, _contactInfo(contactInfo)
|
||||
{
|
||||
}
|
||||
|
||||
float PhysicsContactPreSolve::getElasticity()
|
||||
{
|
||||
return ((cpArbiter*)_contactInfo)->e;
|
||||
}
|
||||
|
||||
float PhysicsContactPreSolve::getFriciton()
|
||||
{
|
||||
return ((cpArbiter*)_contactInfo)->u;
|
||||
}
|
||||
|
||||
Point PhysicsContactPreSolve::getSurfaceVelocity()
|
||||
{
|
||||
return PhysicsHelper::cpv2point(((cpArbiter*)_contactInfo)->surface_vr);
|
||||
}
|
||||
|
||||
void PhysicsContactPreSolve::setElasticity(float elasticity)
|
||||
{
|
||||
((cpArbiter*)_contactInfo)->e = elasticity;
|
||||
}
|
||||
|
||||
void PhysicsContactPreSolve::setFriction(float friction)
|
||||
{
|
||||
((cpArbiter*)_contactInfo)->u = friction;
|
||||
}
|
||||
|
||||
void PhysicsContactPreSolve::setSurfaceVelocity(Point surfaceVelocity)
|
||||
{
|
||||
((cpArbiter*)_contactInfo)->surface_vr = PhysicsHelper::point2cpv(surfaceVelocity);
|
||||
}
|
||||
|
||||
PhysicsContactPreSolve::~PhysicsContactPreSolve()
|
||||
{
|
||||
|
||||
CC_SAFE_DELETE(_preContactData);
|
||||
}
|
||||
|
||||
PhysicsContactPreSolve* PhysicsContactPreSolve::create()
|
||||
{
|
||||
PhysicsContactPreSolve * solve = new PhysicsContactPreSolve();
|
||||
if(solve && solve->init())
|
||||
{
|
||||
return solve;
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(solve);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool PhysicsContactPreSolve::init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// PhysicsContactPostSolve implementation
|
||||
PhysicsContactPostSolve::PhysicsContactPostSolve()
|
||||
PhysicsContactPostSolve::PhysicsContactPostSolve(void* contactInfo)
|
||||
: _contactInfo(contactInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -118,21 +157,19 @@ PhysicsContactPostSolve::~PhysicsContactPostSolve()
|
|||
|
||||
}
|
||||
|
||||
PhysicsContactPostSolve* PhysicsContactPostSolve::create()
|
||||
float PhysicsContactPostSolve::getElasticity()
|
||||
{
|
||||
PhysicsContactPostSolve * solve = new PhysicsContactPostSolve();
|
||||
if(solve && solve->init())
|
||||
{
|
||||
return solve;
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(solve);
|
||||
return nullptr;
|
||||
return ((cpArbiter*)_contactInfo)->e;
|
||||
}
|
||||
|
||||
bool PhysicsContactPostSolve::init()
|
||||
float PhysicsContactPostSolve::getFriciton()
|
||||
{
|
||||
return true;
|
||||
return ((cpArbiter*)_contactInfo)->u;
|
||||
}
|
||||
|
||||
Point PhysicsContactPostSolve::getSurfaceVelocity()
|
||||
{
|
||||
return PhysicsHelper::cpv2point(((cpArbiter*)_contactInfo)->surface_vr);
|
||||
}
|
||||
|
||||
PhysicsContactListener::PhysicsContactListener()
|
||||
|
|
|
@ -38,6 +38,18 @@ class PhysicsWorld;
|
|||
|
||||
class PhysicsContactInfo;
|
||||
|
||||
|
||||
typedef struct PhysicsContactData
|
||||
{
|
||||
Point points[PHYSICS_CONTACT_POINT_MAX];
|
||||
int count;
|
||||
Point normal;
|
||||
|
||||
PhysicsContactData()
|
||||
: count(0)
|
||||
{}
|
||||
}PhysicsContactData;
|
||||
|
||||
/**
|
||||
* @brief Contact infomation. it will created automatically when two shape contact with each other. and it will destoried automatically when two shape separated.
|
||||
*/
|
||||
|
@ -52,6 +64,7 @@ public:
|
|||
* @brief get contact shape B.
|
||||
*/
|
||||
inline PhysicsShape* getShapeB() const { return _shapeB; }
|
||||
inline const PhysicsContactData* getContactData() const { return _contactData; }
|
||||
/*
|
||||
* @brief get data.
|
||||
*/
|
||||
|
@ -68,6 +81,8 @@ private:
|
|||
inline bool getNotify() { return _notify; }
|
||||
inline void setNotify(bool notify) { _notify = notify; }
|
||||
|
||||
void generateContactData();
|
||||
|
||||
private:
|
||||
PhysicsContact();
|
||||
~PhysicsContact();
|
||||
|
@ -76,8 +91,12 @@ private:
|
|||
PhysicsShape* _shapeA;
|
||||
PhysicsShape* _shapeB;
|
||||
PhysicsContactInfo* _info;
|
||||
void* _data;
|
||||
bool _notify;
|
||||
bool _begin;
|
||||
|
||||
void* _data;
|
||||
void* _contactInfo;
|
||||
PhysicsContactData* _contactData;
|
||||
|
||||
friend class PhysicsWorld;
|
||||
friend class PhysicsWorldCallback;
|
||||
|
@ -88,14 +107,27 @@ private:
|
|||
*/
|
||||
class PhysicsContactPreSolve
|
||||
{
|
||||
public:
|
||||
// getter/setter
|
||||
float getElasticity();
|
||||
float getFriciton();
|
||||
Point getSurfaceVelocity();
|
||||
void setElasticity(float elasticity);
|
||||
void setFriction(float friction);
|
||||
void setSurfaceVelocity(Point surfaceVelocity);
|
||||
|
||||
private:
|
||||
PhysicsContactPreSolve();
|
||||
PhysicsContactPreSolve(PhysicsContactData* data, void* contactInfo);
|
||||
~PhysicsContactPreSolve();
|
||||
|
||||
static PhysicsContactPreSolve* create();
|
||||
bool init();
|
||||
private:
|
||||
float _elasticity;
|
||||
float _friction;
|
||||
Point _surfaceVelocity;
|
||||
PhysicsContactData* _preContactData;
|
||||
void* _contactInfo;
|
||||
|
||||
friend class PhysicsWorldCallback;
|
||||
friend class PhysicsWorld;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -103,14 +135,20 @@ private:
|
|||
*/
|
||||
class PhysicsContactPostSolve
|
||||
{
|
||||
public:
|
||||
// getter
|
||||
float getElasticity();
|
||||
float getFriciton();
|
||||
Point getSurfaceVelocity();
|
||||
|
||||
private:
|
||||
PhysicsContactPostSolve();
|
||||
PhysicsContactPostSolve(void* contactInfo);
|
||||
~PhysicsContactPostSolve();
|
||||
|
||||
static PhysicsContactPostSolve* create();
|
||||
bool init();
|
||||
private:
|
||||
void* _contactInfo;
|
||||
|
||||
friend class PhysicsWorldCallback;
|
||||
friend class PhysicsWorld;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -161,10 +161,10 @@ void PhysicsJoint::setCollisionEnable(bool enable)
|
|||
{
|
||||
_collisionEnable = enable;
|
||||
|
||||
for (auto shape : _bodyB->_shapes)
|
||||
{
|
||||
shape->_info->setGroup(enable ? _bodyB->_info->group : _bodyA->_info->group);
|
||||
}
|
||||
// for (auto shape : _bodyB->_shapes)
|
||||
// {
|
||||
// shape->_info->setGroup(enable ? _bodyB->_info->group : _bodyA->_info->group);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,11 @@
|
|||
namespace cocos2d
|
||||
{
|
||||
extern const float PHYSICS_INFINITY;
|
||||
|
||||
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
|
||||
static const int PHYSICS_CONTACT_POINT_MAX = 4;
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // __CCPHYSICS_SETTING_H__
|
||||
|
|
|
@ -272,12 +272,12 @@ void PhysicsShape::setBody(PhysicsBody *body)
|
|||
if (body == nullptr)
|
||||
{
|
||||
_info->setBody(nullptr);
|
||||
_info->setGroup(CP_NO_GROUP);
|
||||
//_info->setGroup(CP_NO_GROUP);
|
||||
_body = nullptr;
|
||||
}else
|
||||
{
|
||||
_info->setBody(body->_info->body);
|
||||
_info->setGroup(body->_info->group);
|
||||
//_info->setGroup(body->_info->group);
|
||||
_body = body;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,8 @@ NS_CC_BEGIN
|
|||
|
||||
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
|
||||
|
||||
const float PHYSICS_INFINITY = INFINITY;
|
||||
|
||||
namespace
|
||||
{
|
||||
typedef struct RayCastCallbackInfo
|
||||
|
@ -96,8 +98,6 @@ public:
|
|||
|
||||
bool PhysicsWorldCallback::continues = true;
|
||||
|
||||
const float PHYSICS_INFINITY = INFINITY;
|
||||
|
||||
int PhysicsWorldCallback::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSpace *space, PhysicsWorld *world)
|
||||
{
|
||||
CP_ARBITER_GET_SHAPES(arb, a, b);
|
||||
|
@ -108,20 +108,19 @@ int PhysicsWorldCallback::collisionBeginCallbackFunc(cpArbiter *arb, struct cpSp
|
|||
|
||||
PhysicsContact* contact = PhysicsContact::create(ita->second->shape, itb->second->shape);
|
||||
arb->data = contact;
|
||||
contact->_contactInfo = arb;
|
||||
|
||||
return world->collisionBeginCallback(*static_cast<PhysicsContact*>(arb->data));
|
||||
return world->collisionBeginCallback(*contact);
|
||||
}
|
||||
|
||||
int PhysicsWorldCallback::collisionPreSolveCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world)
|
||||
{
|
||||
return world->collisionPreSolveCallback(*static_cast<PhysicsContact*>(arb->data),
|
||||
PhysicsContactPreSolve());
|
||||
return world->collisionPreSolveCallback(*static_cast<PhysicsContact*>(arb->data));
|
||||
}
|
||||
|
||||
void PhysicsWorldCallback::collisionPostSolveCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world)
|
||||
{
|
||||
world->collisionPostSolveCallback(*static_cast<PhysicsContact*>(arb->data),
|
||||
PhysicsContactPostSolve());
|
||||
world->collisionPostSolveCallback(*static_cast<PhysicsContact*>(arb->data));
|
||||
}
|
||||
|
||||
void PhysicsWorldCallback::collisionSeparateCallbackFunc(cpArbiter *arb, cpSpace *space, PhysicsWorld *world)
|
||||
|
@ -445,7 +444,24 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
|
|||
bool ret = true;
|
||||
PhysicsBody* bodyA = contact.getShapeA()->getBody();
|
||||
PhysicsBody* bodyB = contact.getShapeB()->getBody();
|
||||
std::vector<PhysicsJoint*> jointsA = bodyA->getJoints();
|
||||
|
||||
// check the joint is collision enable or not
|
||||
for (PhysicsJoint* joint : jointsA)
|
||||
{
|
||||
if (!joint->isCollisionEnable())
|
||||
{
|
||||
PhysicsBody* body = joint->getBodyA() == bodyA ? bodyB : bodyA;
|
||||
|
||||
if (body == bodyB)
|
||||
{
|
||||
contact.setNotify(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bitmask check
|
||||
if ((bodyA->getCategoryBitmask() & bodyB->getContactTestBitmask()) == 0
|
||||
|| (bodyB->getContactTestBitmask() & bodyA->getCategoryBitmask()) == 0)
|
||||
{
|
||||
|
@ -460,6 +476,9 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
|
|||
|
||||
if (contact.getNotify() && _listener && _listener->onContactBegin)
|
||||
{
|
||||
contact._begin = true;
|
||||
contact.generateContactData();
|
||||
|
||||
// the mask has high priority than _listener->onContactBegin.
|
||||
// so if the mask test is false, the two bodies won't have collision.
|
||||
if (ret)
|
||||
|
@ -474,7 +493,7 @@ int PhysicsWorld::collisionBeginCallback(PhysicsContact& contact)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact, const PhysicsContactPreSolve& solve)
|
||||
int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact)
|
||||
{
|
||||
if (!contact.getNotify())
|
||||
{
|
||||
|
@ -483,13 +502,17 @@ int PhysicsWorld::collisionPreSolveCallback(PhysicsContact& contact, const Physi
|
|||
|
||||
if (_listener && _listener->onContactPreSolve)
|
||||
{
|
||||
PhysicsContactPreSolve solve(contact._begin ? nullptr : contact._contactData, contact._contactInfo);
|
||||
contact._begin = false;
|
||||
contact.generateContactData();
|
||||
|
||||
return _listener->onContactPreSolve(*this, contact, solve);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact, const PhysicsContactPostSolve& solve)
|
||||
void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact)
|
||||
{
|
||||
if (!contact.getNotify())
|
||||
{
|
||||
|
@ -498,6 +521,7 @@ void PhysicsWorld::collisionPostSolveCallback(PhysicsContact& contact, const Phy
|
|||
|
||||
if (_listener && _listener->onContactPreSolve)
|
||||
{
|
||||
PhysicsContactPostSolve solve(contact._contactInfo);
|
||||
_listener->onContactPostSolve(*this, contact, solve);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,8 +40,6 @@ class PhysicsJoint;
|
|||
class PhysicsWorldInfo;
|
||||
class PhysicsShape;
|
||||
class PhysicsContact;
|
||||
class PhysicsContactPreSolve;
|
||||
class PhysicsContactPostSolve;
|
||||
class PhysicsContactListener;
|
||||
class Array;
|
||||
|
||||
|
@ -135,8 +133,8 @@ protected:
|
|||
|
||||
|
||||
virtual int collisionBeginCallback(PhysicsContact& contact);
|
||||
virtual int collisionPreSolveCallback(PhysicsContact& contact, const PhysicsContactPreSolve& solve);
|
||||
virtual void collisionPostSolveCallback(PhysicsContact& contact, const PhysicsContactPostSolve& solve);
|
||||
virtual int collisionPreSolveCallback(PhysicsContact& contact);
|
||||
virtual void collisionPostSolveCallback(PhysicsContact& contact);
|
||||
virtual void collisionSeparateCallback(PhysicsContact& contact);
|
||||
|
||||
protected:
|
||||
|
|
Loading…
Reference in New Issue