From 0678eac4531a547e2d366937df0ecc08febd3ae2 Mon Sep 17 00:00:00 2001 From: Bill Meltsner Date: Fri, 23 Sep 2011 21:25:41 -0400 Subject: [PATCH] A first attempt at overhauling collision. New everything. --HG-- branch : box2d-update --- src/modules/physics/box2d/Contact.cpp | 78 +++++++++++++------- src/modules/physics/box2d/Contact.h | 67 ++++++++++++------ src/modules/physics/box2d/World.cpp | 36 +++++++--- src/modules/physics/box2d/World.h | 8 ++- src/modules/physics/box2d/wrap_Contact.cpp | 82 +++++++++++++++++----- src/modules/physics/box2d/wrap_Contact.h | 11 ++- 6 files changed, 203 insertions(+), 79 deletions(-) diff --git a/src/modules/physics/box2d/Contact.cpp b/src/modules/physics/box2d/Contact.cpp index bc9583ab0..7a1b9ffa8 100644 --- a/src/modules/physics/box2d/Contact.cpp +++ b/src/modules/physics/box2d/Contact.cpp @@ -28,54 +28,82 @@ namespace physics { namespace box2d { - Contact::Contact(World * world, b2Contact * contact) - : contact(contact), world(world) + Contact::Contact(b2Contact * contact) + : contact(contact) { - world->retain(); } Contact::~Contact() { - world->release(); } - int Contact::getPosition(lua_State * L) + int Contact::getPositions(lua_State * L) { love::luax_assert_argc(L, 1, 1); - lua_pushnumber(L, Physics::scaleUp(point.position.x)); - lua_pushnumber(L, Physics::scaleUp(point.position.y)); - return 2; - } - - int Contact::getVelocity(lua_State * L) - { - love::luax_assert_argc(L, 1, 1); - lua_pushnumber(L, Physics::scaleUp(point.velocity.x)); - lua_pushnumber(L, Physics::scaleUp(point.velocity.y)); - return 2; + b2WorldManifold manifold; + contact->GetWorldManifold(&manifold); + int points = contact->GetManifold()->pointCount; + for (int i = 0; i < points; i++) { + b2Vec2 position = Physics::scaleUp(manifold.points[i]); + lua_pushnumber(L, position.x); + lua_pushnumber(L, position.y); + } + return points*2; } int Contact::getNormal(lua_State * L) { love::luax_assert_argc(L, 1, 1); - lua_pushnumber(L, Physics::scaleUp(point.normal.x)); - lua_pushnumber(L, Physics::scaleUp(point.normal.y)); + b2WorldManifold manifold; + contact->GetWorldManifold(&manifold); + lua_pushnumber(L, Physics::scaleUp(manifold.normal.x)); + lua_pushnumber(L, Physics::scaleUp(manifold.normal.y)); return 2; } - float Contact::getSeparation() const - { - return Physics::scaleUp(point.separation); - } - float Contact::getFriction() const { - return point.friction; + return contact->GetFriction(); } float Contact::getRestitution() const { - return point.restitution; + return contact->GetRestitution(); + } + + bool Contact::isEnabled() const + { + return contact->IsEnabled(); + } + + bool Contact::isTouching() const + { + return contact->IsTouching(); + } + + void Contact::setFriction(float friction) + { + contact->SetFriction(friction); + } + + void Contact::setRestitution(float restitution) + { + contact->SetRestitution(restitution); + } + + void Contact::setEnabled(bool enabled) + { + contact->SetEnabled(enabled); + } + + void Contact::resetFriction() + { + contact->ResetFriction(); + } + + void Contact::resetRestitution() + { + contact->ResetRestitution(); } } // box2d diff --git a/src/modules/physics/box2d/Contact.h b/src/modules/physics/box2d/Contact.h index 150bfdc91..8db2f5233 100644 --- a/src/modules/physics/box2d/Contact.h +++ b/src/modules/physics/box2d/Contact.h @@ -51,10 +51,7 @@ namespace box2d // The Box2D contact. b2Contact* contact; - - // The parent world. Needed for scaling. - World * world; - + public: /** @@ -63,23 +60,16 @@ namespace box2d * data pointed to. * @param point Pointer to the Box2D contact. **/ - Contact(World * world, const b2Contact * contact); + Contact(b2Contact * contact); virtual ~Contact(); /** - * Gets the position of the Contact. + * Gets the position of each point of contact. * @return The position along the x-axis. * @return The position along the y-axis. **/ - int getPosition(lua_State * L); - - /** - * Gets the linear impact velocity. - * @return The velocity along the x-axis. - * @return The velocity along the y-axis. - **/ - int getVelocity(lua_State * L); + int getPositions(lua_State * L); /** * Gets the collision normal. @@ -89,22 +79,55 @@ namespace box2d int getNormal(lua_State * L); /** - * How far apart the shapes are. If they are intersecting - * this value is negative. - **/ - float getSeparation() const; - - /** - * The mixed friction between the two shapes at + * The mixed friction between the two fixtures at * the point of impact. **/ float getFriction() const; /** - * The mixed restitution of the two shapes + * The mixed restitution of the two fixtures * at the point of impact. **/ float getRestitution() const; + + /** + * Check if the contact is enabled. + **/ + bool isEnabled() const; + + /** + * Check if the contact is touching. + **/ + bool isTouching() const; + + // Only call the setters in PreSolve + + /** + * Override the default friction mixture. + **/ + void setFriction(float friction); + + /** + * Override the default restitution mixture. + **/ + void setRestitution(float restitution); + + /** + * Enable/disable this contact. + **/ + void setEnabled(bool enabled); + + /** + * Reset the friction mixture to the default + * value. + **/ + void resetFriction(); + + /** + * Reset the restitution mixture to the default + * value. + **/ + void resetRestitution(); }; diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index ab3ce8425..9649d9f8a 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -44,7 +44,7 @@ namespace box2d delete ref; } - void World::ContactCallback::add(World * world, const b2Contact* contact) + void World::ContactCallback::add(b2Contact* contact) { /** * We must copy contacts, since we're not allowed to process @@ -53,7 +53,15 @@ namespace box2d **/ if(ref != 0) - contacts.push_back(new Contact(world, contact)); + contacts.push_back(new Contact(contact)); + } + + void World::ContactCallback::add(b2Contact* contact, const b2ContactImpulse* impulse) + { + if(ref != 0) { + contacts.push_back(new Contact(contact)); + impulses.push_back(impulse); + } } void World::ContactCallback::process() @@ -86,13 +94,25 @@ namespace box2d } luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void*)contacts[i], false); - lua_call(L, 3, 0); + + int args = 3; + if ((int)impulses.size() > i) { + const b2ContactImpulse * impulse = impulses[i]; + for (int c = 0; c < impulse->count; c++) { + lua_pushnumber(L, Physics::scaleUp(impulse->normalImpulses[c])); + lua_pushnumber(L, Physics::scaleUp(impulse->tangentImpulses[c])); + args += 2; + } + } + lua_call(L, args, 0); } // Clear contacts. for(int i = 0;i<(int)contacts.size();i++) delete contacts[i]; contacts.clear(); + // Clear impulses. + impulses.clear(); } } @@ -134,22 +154,22 @@ namespace box2d void World::BeginContact(b2Contact* contact) { - begin.add(this, contact); + begin.add(contact); } void World::EndContact(b2Contact* contact) { - end.add(this, contact); + end.add(contact); } - void World::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) + void World::PreSolve(b2Contact* contact) { - presolve.add(this, contact); + presolve.add(contact); } void World::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) { - postsolve.add(this, contact); + postsolve.add(contact, impulse); } int World::setCallbacks(lua_State * L) diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index 21ae6f754..25ae32b2c 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -67,9 +67,13 @@ namespace box2d public: Reference * ref; std::vector contacts; + std::vector impulses; + b2Manifold* oldManifold; + b2ContactImpulse* impulse; ContactCallback(); ~ContactCallback(); - void add(World * world, const b2Contact* contact); + void add(b2Contact* contact); + void add(b2Contact* contact, const b2ContactImpulse* impulse); void process(); }; @@ -113,7 +117,7 @@ namespace box2d // From b2ContactListener void BeginContact(b2Contact* contact); void EndContact(b2Contact* contact); - void PreSolve(b2Contact* contact, const b2Manifold* oldManifold); + void PreSolve(b2Contact* contact); void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse); /** diff --git a/src/modules/physics/box2d/wrap_Contact.cpp b/src/modules/physics/box2d/wrap_Contact.cpp index 16eefa818..71997d790 100644 --- a/src/modules/physics/box2d/wrap_Contact.cpp +++ b/src/modules/physics/box2d/wrap_Contact.cpp @@ -32,31 +32,18 @@ namespace box2d return luax_checktype(L, idx, "Contact", PHYSICS_CONTACT_T); } - int w_Contact_getPosition(lua_State * L) + int w_Contact_getPositions(lua_State * L) { Contact * t = luax_checkcontact(L, 1); - return t->getPosition(L); + return t->getPositions(L); } - - int w_Contact_getVelocity(lua_State * L) - { - Contact * t = luax_checkcontact(L, 1); - return t->getVelocity(L); - } - + int w_Contact_getNormal(lua_State * L) { Contact * t = luax_checkcontact(L, 1); return t->getNormal(L); } - int w_Contact_getSeparation(lua_State * L) - { - Contact * t = luax_checkcontact(L, 1); - lua_pushnumber(L, t->getSeparation()); - return 1; - } - int w_Contact_getFriction(lua_State * L) { Contact * t = luax_checkcontact(L, 1); @@ -70,16 +57,73 @@ namespace box2d lua_pushnumber(L, t->getRestitution()); return 1; } + + int w_Contact_isEnabled(lua_State * L) + { + Contact * t = luax_checkcontact(L, 1); + lua_pushboolean(L, t->isEnabled()); + return 1; + } + + int w_Contact_isTouching(lua_State * L) + { + Contact * t = luax_checkcontact(L, 1); + lua_pushboolean(L, t->isTouching()); + return 1; + } + + int w_Contact_setFriction(lua_State * L) + { + Contact * t = luax_checkcontact(L, 1); + float f = (float)luaL_checknumber(L, 2); + t->setFriction(f); + return 0; + } + + int w_Contact_setRestitution(lua_State * L) + { + Contact * t = luax_checkcontact(L, 1); + float r = (float)luaL_checknumber(L, 2); + t->setRestitution(r); + return 0; + } + + int w_Contact_setEnabled(lua_State * L) + { + Contact * t = luax_checkcontact(L, 1); + bool e = luax_toboolean(L, 2); + t->setEnabled(e); + return 0; + } + + int w_Contact_resetFriction(lua_State * L) + { + Contact * t = luax_checkcontact(L, 1); + t->resetFriction(); + return 0; + } + + int w_Contact_resetRestitution(lua_State * L) + { + Contact * t = luax_checkcontact(L, 1); + t->resetRestitution(); + return 0; + } int luaopen_contact(lua_State * L) { static const luaL_Reg functions[] = { - { "getPosition", w_Contact_getPosition }, - { "getVelocity", w_Contact_getVelocity }, + { "getPositions", w_Contact_getPositions }, { "getNormal", w_Contact_getNormal }, - { "getSeparation", w_Contact_getSeparation }, { "getFriction", w_Contact_getFriction }, { "getRestitution", w_Contact_getRestitution }, + { "isEnabled", w_Contact_isEnabled }, + { "isTouching", w_Contact_isTouching }, + { "setFriction", w_Contact_setFriction }, + { "setRestitution", w_Contact_setRestitution }, + { "setEnabled", w_Contact_setEnabled }, + { "resetFriction", w_Contact_resetFriction }, + { "resetRestitution", w_Contact_resetRestitution }, { 0, 0 } }; diff --git a/src/modules/physics/box2d/wrap_Contact.h b/src/modules/physics/box2d/wrap_Contact.h index 2e261a8f3..3c0c906a8 100644 --- a/src/modules/physics/box2d/wrap_Contact.h +++ b/src/modules/physics/box2d/wrap_Contact.h @@ -32,12 +32,17 @@ namespace physics namespace box2d { Contact * luax_checkcontact(lua_State * L, int idx); - int w_Contact_getPosition(lua_State * L); - int w_Contact_getVelocity(lua_State * L); + int w_Contact_getPositions(lua_State * L); int w_Contact_getNormal(lua_State * L); - int w_Contact_getSeparation(lua_State * L); int w_Contact_getFriction(lua_State * L); int w_Contact_getRestitution(lua_State * L); + int w_Contact_isEnabled(lua_State * L); + int w_Contact_isTouching(lua_State * L); + int w_Contact_setFriction(lua_State * L); + int w_Contact_setRestitution(lua_State * L); + int w_Contact_setEnabled(lua_State * L); + int w_Contact_resetFriction(lua_State * L); + int w_Contact_resetRestitution(lua_State * L); int luaopen_contact(lua_State * L); } // box2d