issue #2771: change angular damping to moment. (these two have different meaning, change to the correct one)

This commit is contained in:
boyu0 2013-10-14 13:56:08 +08:00
parent 2e01b532f4
commit 5c7603e0ce
5 changed files with 162 additions and 79 deletions

View File

@ -56,8 +56,7 @@ NS_CC_BEGIN
namespace namespace
{ {
static const float MASS_DEFAULT = 1.0; static const float MASS_DEFAULT = 1.0;
static const float DENSITY_DEFAULT = 1.0; static const float MOMENT_DEFAULT = 200;
static const float ANGULARDAMPING_DEFAULT = 200;
} }
PhysicsBody::PhysicsBody() PhysicsBody::PhysicsBody()
@ -67,11 +66,11 @@ PhysicsBody::PhysicsBody()
, _dynamic(true) , _dynamic(true)
, _enable(true) , _enable(true)
, _massDefault(true) , _massDefault(true)
, _angularDampingDefault(true) , _momentDefault(true)
, _mass(MASS_DEFAULT) , _mass(MASS_DEFAULT)
, _area(0.0) , _area(0.0)
, _density(DENSITY_DEFAULT) , _density(0)
, _angularDamping(ANGULARDAMPING_DEFAULT) , _moment(MOMENT_DEFAULT)
, _tag(0) , _tag(0)
{ {
} }
@ -217,7 +216,7 @@ bool PhysicsBody::init()
_info = new PhysicsBodyInfo(); _info = new PhysicsBodyInfo();
CC_BREAK_IF(_info == nullptr); CC_BREAK_IF(_info == nullptr);
_info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_angularDamping)); _info->body = cpBodyNew(PhysicsHelper::float2cpfloat(_mass), PhysicsHelper::float2cpfloat(_moment));
CC_BREAK_IF(_info->body == nullptr); CC_BREAK_IF(_info->body == nullptr);
return true; return true;
@ -233,7 +232,7 @@ void PhysicsBody::setDynamic(bool dynamic)
if (dynamic) if (dynamic)
{ {
cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass)); cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass));
cpBodySetMoment(_info->body, PhysicsHelper::float2cpfloat(_angularDamping)); cpBodySetMoment(_info->body, PhysicsHelper::float2cpfloat(_moment));
}else }else
{ {
cpBodySetMass(_info->body, PHYSICS_INFINITY); cpBodySetMass(_info->body, PHYSICS_INFINITY);
@ -322,21 +321,7 @@ void PhysicsBody::addShape(PhysicsShape* shape)
} }
} }
if (shape->getAngularDumping() > 0) addMoment(shape->getMoment());
{
if (shape->getAngularDumping() == INFINITY)
{
_angularDamping = INFINITY;
_angularDampingDefault = false;
cpBodySetMoment(_info->body, _angularDamping);
}
else if (_angularDamping != INFINITY)
{
_angularDamping = (_angularDampingDefault ? 0 : _angularDamping) + shape->getAngularDumping();
_angularDampingDefault = false;
cpBodySetMoment(_info->body, _angularDamping);
}
}
if (_world != nullptr) _world->addShape(shape); if (_world != nullptr) _world->addShape(shape);
@ -371,12 +356,112 @@ void PhysicsBody::applyTorque(float torque)
void PhysicsBody::setMass(float mass) void PhysicsBody::setMass(float mass)
{ {
if (mass <= 0)
{
return;
}
_mass = mass; _mass = mass;
_massDefault = false; _massDefault = false;
// update density
if (_mass == PHYSICS_INFINITY)
{
_density = PHYSICS_INFINITY;
}
else
{
if (_area > 0)
{
_density = _mass / _area;
}else
{
_density = 0;
}
}
cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass)); cpBodySetMass(_info->body, PhysicsHelper::float2cpfloat(_mass));
} }
void PhysicsBody::addMass(float mass)
{
if (mass == PHYSICS_INFINITY)
{
mass = PHYSICS_INFINITY;
_massDefault = false;
_density = PHYSICS_INFINITY;
}
else if (mass == -PHYSICS_INFINITY)
{
return;
}
else if (_mass != PHYSICS_INFINITY)
{
if (_massDefault)
{
_mass = 0;
_massDefault = false;
}
if (_mass + mass > 0)
{
_mass += mass;
}else
{
_mass = MASS_DEFAULT;
_massDefault = true;
}
if (_area > 0)
{
_density = _mass / _area;
}
else
{
_density = 0;
}
}
}
void PhysicsBody::addMoment(float moment)
{
if (moment == PHYSICS_INFINITY)
{
// if moment is INFINITY, the moment of the body will become INFINITY
_moment = PHYSICS_INFINITY;
_momentDefault = false;
}
else if (moment == -PHYSICS_INFINITY)
{
// if moment is -INFINITY, it won't change
return;
}
else
{
// if moment of the body is INFINITY is has no effect
if (_moment != PHYSICS_INFINITY)
{
if (_momentDefault)
{
_moment = 0;
_momentDefault = false;
}
if (_moment + moment > 0)
{
_moment += moment;
}
else
{
_moment = MOMENT_DEFAULT;
_momentDefault = true;
}
}
}
cpBodySetMoment(_info->body, moment);
}
void PhysicsBody::setVelocity(Point velocity) void PhysicsBody::setVelocity(Point velocity)
{ {
cpBodySetVel(_info->body, PhysicsHelper::point2cpv(velocity)); cpBodySetVel(_info->body, PhysicsHelper::point2cpv(velocity));
@ -387,12 +472,12 @@ Point PhysicsBody::getVelocity()
return PhysicsHelper::cpv2point(cpBodyGetVel(_info->body)); return PhysicsHelper::cpv2point(cpBodyGetVel(_info->body));
} }
void PhysicsBody::setAngularDamping(float angularDamping) void PhysicsBody::setMoment(float moment)
{ {
_angularDamping = angularDamping; _moment = moment;
_angularDampingDefault = false; _momentDefault = false;
cpBodySetMoment(_info->body, _angularDamping); cpBodySetMoment(_info->body, _moment);
} }
PhysicsShape* PhysicsBody::getShapeByTag(int tag) PhysicsShape* PhysicsBody::getShapeByTag(int tag)
@ -434,42 +519,11 @@ void PhysicsBody::removeShape(PhysicsShape* shape)
_shapes.erase(it); _shapes.erase(it);
// deduce the mass, area and angularDamping // deduce the area, mass and moment
if (_mass != PHYSICS_INFINITY && shape->getMass() != PHYSICS_INFINITY) // area must update before mass, because the density changes depend on it.
{ _area -= shape->getArea();
if (_mass - shape->getMass() <= 0) addMass(-shape->getMass());
{ addMoment(-shape->getMoment());
_mass = MASS_DEFAULT;
_massDefault = true;
}else
{
_mass = _mass = shape->getMass();
}
_area -= shape->getArea();
if (_mass == PHYSICS_INFINITY)
{
_density = PHYSICS_INFINITY;
}
else if (_area > 0)
{
_density = _mass / _area;
}
else
{
_density = DENSITY_DEFAULT;
}
if (_angularDamping - shape->getAngularDumping() > 0)
{
_angularDamping -= shape->getAngularDumping();
}else
{
_angularDamping = ANGULARDAMPING_DEFAULT;
_angularDampingDefault = true;
}
}
shape->release(); shape->release();
} }

View File

@ -172,21 +172,49 @@ public:
/* /*
* @brief set the body mass. * @brief set the body mass.
* @note if you need add/subtract mass to body, don't use setMass(getMass() +/- mass), because the mass of body may be equal to PHYSICS_INFINITY, it will cause some unexpected result, please use addMass() instead.
*/ */
void setMass(float mass); void setMass(float mass);
/* /*
* @brief get the body mass. * @brief get the body mass.
*/ */
inline float getMass() { return _mass; } inline float getMass() { return _mass; }
/*
* @brief add mass to body.
* if _mass(mass of the body) == PHYSICS_INFINITY, it remains.
* if mass == PHYSICS_INFINITY, _mass will be PHYSICS_INFINITY.
* if mass == -PHYSICS_INFINITY, _mass will not change.
* if mass + _mass <= 0, _mass will equal to MASS_DEFAULT(1.0)
* other wise, mass = mass + _mass;
*/
void addMass(float mass);
/*
* @brief set the body moment of inertia.
* @note if you need add/subtract moment to body, don't use setMoment(getMoment() +/- moment), because the moment of body may be equal to PHYSICS_INFINITY, it will cause some unexpected result, please use addMoment() instead.
*/
void setMoment(float moment);
/*
* @brief get the body moment of inertia.
*/
inline float getMoment(float moment) { return _moment; }
/*
* @brief add moment of inertia to body.
* if _moment(moment of the body) == PHYSICS_INFINITY, it remains.
* if moment == PHYSICS_INFINITY, _moment will be PHYSICS_INFINITY.
* if moment == -PHYSICS_INFINITY, _moment will not change.
* if moment + _moment <= 0, _moment will equal to MASS_DEFAULT(1.0)
* other wise, moment = moment + _moment;
*/
void addMoment(float moment);
/* /*
* @brief set angular damping. * @brief set angular damping.
*/ */
void setAngularDamping(float angularDamping); //void setAngularDamping(float angularDamping);
/* /*
* @brief get angular damping. * @brief get angular damping.
*/ */
inline float getAngularDamping() { return _angularDamping; } //inline float getAngularDamping() { return _angularDamping; }
//virtual Clonable* clone() const override; //virtual Clonable* clone() const override;
@ -196,6 +224,7 @@ public:
inline int getTag() { return _tag; } inline int getTag() { return _tag; }
inline void setTag(int tag) { _tag = tag; } inline void setTag(int tag) { _tag = tag; }
protected: protected:
bool init(); bool init();
@ -216,11 +245,12 @@ protected:
bool _dynamic; bool _dynamic;
bool _enable; bool _enable;
bool _massDefault; bool _massDefault;
bool _angularDampingDefault; bool _momentDefault;
float _mass; float _mass;
float _area; float _area;
float _density; float _density;
float _angularDamping; float _moment;
//float _angularDamping;
int _tag; int _tag;
int _categoryBitmask; int _categoryBitmask;

View File

@ -48,7 +48,7 @@ PhysicsShape::PhysicsShape()
, _type(Type::UNKNOWN) , _type(Type::UNKNOWN)
, _area(0) , _area(0)
, _mass(0) , _mass(0)
, _angularDamping(0) , _moment(0)
, _tag(0) , _tag(0)
, _enable(true) , _enable(true)
{ {
@ -234,7 +234,7 @@ bool PhysicsShapeCircle::init(float radius, PhysicsMaterial material/* = Materia
_area = PhysicsHelper::cpfloat2float(cpAreaForCircle(0, radius)); _area = PhysicsHelper::cpfloat2float(cpAreaForCircle(0, radius));
_mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area; _mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area;
_angularDamping = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForCircle(_mass, 0, radius, PhysicsHelper::point2cpv(offset)); _moment = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForCircle(_mass, 0, radius, PhysicsHelper::point2cpv(offset));
_info->add(shape); _info->add(shape);
@ -273,7 +273,7 @@ bool PhysicsShapeEdgeSegment::init(Point a, Point b, PhysicsMaterial material/*
CC_BREAK_IF(shape == nullptr); CC_BREAK_IF(shape == nullptr);
_mass = PHYSICS_INFINITY; _mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY; _moment = PHYSICS_INFINITY;
_info->add(shape); _info->add(shape);
@ -311,7 +311,7 @@ bool PhysicsShapeBox::init(Size size, PhysicsMaterial material/* = MaterialDefau
_area = PhysicsHelper::cpfloat2float(cpAreaForPoly(4, ((cpPolyShape*)shape)->verts)); _area = PhysicsHelper::cpfloat2float(cpAreaForPoly(4, ((cpPolyShape*)shape)->verts));
_mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area; _mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area;
_angularDamping = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForBox(_mass, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height)); _moment = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForBox(_mass, PhysicsHelper::float2cpfloat(size.width), PhysicsHelper::float2cpfloat(size.height));
_info->add(shape); _info->add(shape);
@ -352,7 +352,7 @@ bool PhysicsShapePolygon::init(Point* points, int count, PhysicsMaterial materia
_area = PhysicsHelper::cpfloat2float(cpAreaForPoly(((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts)); _area = PhysicsHelper::cpfloat2float(cpAreaForPoly(((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts));
_mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area; _mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : _material.density * _area;
_angularDamping = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, PhysicsHelper::point2cpv(offset)); _moment = _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY : cpMomentForPoly(_mass, ((cpPolyShape*)shape)->numVerts, ((cpPolyShape*)shape)->verts, PhysicsHelper::point2cpv(offset));
_info->add(shape); _info->add(shape);
@ -401,7 +401,7 @@ bool PhysicsShapeEdgeBox::init(Size size, PhysicsMaterial material/* = MaterialD
CC_BREAK_IF(i < 4); CC_BREAK_IF(i < 4);
_mass = PHYSICS_INFINITY; _mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY; _moment = PHYSICS_INFINITY;
initEnd(); initEnd();
@ -450,7 +450,7 @@ bool PhysicsShapeEdgePolygon::init(Point* points, int count, PhysicsMaterial mat
CC_BREAK_IF(i < count); CC_BREAK_IF(i < count);
_mass = PHYSICS_INFINITY; _mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY; _moment = PHYSICS_INFINITY;
initEnd(); initEnd();
@ -500,7 +500,7 @@ bool PhysicsShapeEdgeChain::init(Point* points, int count, PhysicsMaterial mater
CC_BREAK_IF(i < count); CC_BREAK_IF(i < count);
_mass = PHYSICS_INFINITY; _mass = PHYSICS_INFINITY;
_angularDamping = PHYSICS_INFINITY; _moment = PHYSICS_INFINITY;
initEnd(); initEnd();

View File

@ -79,8 +79,8 @@ public:
inline PhysicsBody* getBody(){ return _body; } inline PhysicsBody* getBody(){ return _body; }
inline Type getType() { return _type; } inline Type getType() { return _type; }
inline float getArea() { return _area; } inline float getArea() { return _area; }
inline float getAngularDumping() { return _angularDamping; } inline float getMoment() { return _moment; }
void setAngularDumping(float angularDumping); void setMoment(float moment);
inline void setTag(int tag) { _tag = tag; } inline void setTag(int tag) { _tag = tag; }
inline int getTag() { return _tag; } inline int getTag() { return _tag; }
void setEnable(bool enable); void setEnable(bool enable);
@ -115,7 +115,7 @@ protected:
Type _type; Type _type;
float _area; float _area;
float _mass; float _mass;
float _angularDamping; float _moment;
PhysicsMaterial _material; PhysicsMaterial _material;
int _tag; int _tag;
bool _enable; bool _enable;

View File

@ -311,9 +311,8 @@ Node* PhysicsDemoLogoSmash::makeBall(float x, float y)
auto body = PhysicsBody::createCircle(0.95, PhysicsMaterial(1, 0, 0)); auto body = PhysicsBody::createCircle(0.95, PhysicsMaterial(1, 0, 0));
body->setMass(1.0); body->setMass(1.0);
body->setAngularDamping(PHYSICS_INFINITY); body->setMoment(PHYSICS_INFINITY);
//body->setDynamic(false);
ball->setPhysicsBody(body); ball->setPhysicsBody(body);
ball->setPosition(Point(x, y)); ball->setPosition(Point(x, y));