Просмотр исходного кода

Merge pull request #191 from Fidelity3/master

Many box2d Functions added as well as multiple fixtures per body
Ivan Safrin 13 лет назад
Родитель
Сommit
95106f73ab

+ 22 - 15
Modules/Contents/2DPhysics/Include/PolyPhysicsScreen.h

@@ -85,8 +85,13 @@ class _PolyExport PhysicsScreenEvent : public Event {
 		*/			
 		Vector2 worldCollisionPoint;
 
-			
 		/**
+         * Raw Box2d Contact
+         */
+    
+        b2Contact *contact;
+	
+        /**
 		* Strength of the collision impact.
 		*/
 		Number impactStrength;	
@@ -154,7 +159,7 @@ public:
 	/**
 	* Creates a new physics screen.
 	*/ 
-	PhysicsScreen(Number worldScale, Number freq);
+	PhysicsScreen(Number worldScale, Number freq, int velIterations=10, int posIterations=10);
 	
 	/**
 	* Default constructor.
@@ -175,10 +180,11 @@ public:
 	* @param restitution Restitution of the physics entity. Restitution controls how bouncy the entity is.
 	* @param isSensor If this is set to true, the entity won't collide with other entities, but its collision will register.
 	* @param fixedRotation If this is set to true, the entity will always have a locked rotation.
-	* @return The physics entity wrapper.
+    * @param groupIndex is the physiscs shape's collision group. A negative number means objects of that group won't collide with eachother
+    * @return The physics entity wrapper.
 	*/
 	PhysicsScreenEntity *addPhysicsChild(ScreenEntity *newEntity, int entType, bool isStatic, Number friction=0.1, Number density=1, Number restitution = 0, bool isSensor = false, bool fixedRotation = false, int groupIndex = 0);
-
+    
 	/**
 	* Tracks a ScreenEntity as a physics enabled child. 
 	* @param newEntity Screen entity to add.
@@ -189,11 +195,11 @@ public:
 	* @param restitution Restitution of the physics entity. Restitution controls how bouncy the entity is.
 	* @param isSensor If this is set to true, the entity won't collide with other entities, but its collision will register.
 	* @param fixedRotation If this is set to true, the entity will always have a locked rotation.
+    * @param groupIndex is the physiscs shape's collision group. A negative number means objects of that group won't collide with eachother
 	* @return The physics entity wrapper.
 	*/
 	PhysicsScreenEntity *trackPhysicsChild(ScreenEntity *newEntity, int entType, bool isStatic, Number friction=0.1, Number density=1, Number restitution = 0, bool isSensor = false, bool fixedRotation = false, int groupIndex = 0);
-
-	
+    
 	/**
 	* Removes a physics child from the screen.
 	* @param entityToRemove Entity to remove from the screen.
@@ -203,14 +209,13 @@ public:
 	
 	void removeChild(ScreenEntity *entityToRemove);
 	
-	
 	/**
 	* Begins tracking collisions for a ScreenEntity and adds it to the scene.
 	* @param newEntity Entity to track collisions for.
 	* @param entType Physics shape of the entity. Possible values are PhysicsScreenEntity::ENTITY_RECT or PhysicsScreenEntity::ENTITY_CIRCLE.
 	* @param entityToRemove Entity to remove from the screen.
 	*/	
-	PhysicsScreenEntity *addCollisionChild(ScreenEntity *newEntity, int entType, int groupIndex = 0);
+	PhysicsScreenEntity *addCollisionChild(ScreenEntity *newEntity, int entType, int groupIndex = 0, bool sensorOnly = true);
 	
 	/**
 	* Begins tracking collisions for a ScreenEntity.
@@ -343,6 +348,7 @@ public:
 			
 	void BeginContact (b2Contact *contact);
 	void EndContact (b2Contact *contact);	
+    void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);    
 	void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
 
 	/**
@@ -369,7 +375,7 @@ public:
 	* @return If there specified entity overlaps the specified position, this returns true.
 	*/ 														
 	bool testEntityAtPosition(ScreenEntity *ent, Number x, Number y);
-
+    
 	/**
 	* Tests collision between two entities
 	*/
@@ -386,18 +392,19 @@ public:
 	void destroyMouseJoint(b2MouseJoint *mJoint);
 
 
+    
 protected:
 	
+    Number worldScale;
+    
+    std::vector <PhysicsScreenEntity*> physicsChildren;		
 	
-	Number worldScale;
-	
-	void init(Number worldScale, Number physicsTimeStep, int physicsIterations, Vector2 physicsGravity);
+	void init(Number worldScale, Number physicsTimeStep, int velIterations, int posIterations, Vector2 physicsGravity);
 
-	std::vector <PhysicsScreenEntity*> physicsChildren;
 	std::vector<b2Contact*> contacts;
-	b2World *world;
+    b2World *world;    
 	Number timeStep;
-	int32 iterations;
+	int32 velocityIterations, positionIterations;
 };
 
 

+ 73 - 18
Modules/Contents/2DPhysics/Include/PolyPhysicsScreenEntity.h

@@ -34,8 +34,13 @@ namespace Polycode {
 	*/	
 	class _PolyExport PhysicsScreenEntity {
 		public:
+        
+            PhysicsScreenEntity() { collisionOnly = false; }
+        
 			PhysicsScreenEntity(ScreenEntity *entity, b2World *world, Number worldScale, int entType, bool isStatic, Number friction, Number density, Number restitution, bool isSensor, bool fixedRotation, int groupIndex = 0);
-			~PhysicsScreenEntity();		
+			virtual ~PhysicsScreenEntity();
+
+			virtual void Update();
 			
 			/**
 			* Returns the screen entity associated with this physics entity.
@@ -48,43 +53,93 @@ namespace Polycode {
 			void applyTorque(Number torque);
 			
 			/**
-			* Applies force to the physics entity		
-			*/			
+			 * Applies force to the physics entity		
+			 */			
 			void applyForce(Vector2 force);
-		
-			void setTransform(Vector2 pos, Number angle);
+
+			/**
+			 * Applies an impulse to the physics entity		
+			 */
+			void applyImpulse(Number fx, Number fy);
 			
-			void Update();
+			/**
+			 * Sets the position and rotation of entity
+			 */
+			void setTransform(Vector2 pos, Number angle);
 			
+			/**
+             * Sets the velocity of the physics entity
+             */
 			void setVelocity(Number fx, Number fy);	
 			void setVelocityX( Number fx);	
 			void setVelocityY(Number fy);				
-			
-			void applyImpulse(Number fx, Number fy);
-				
+        
+            /**
+             * Sets the dampening of the physics entity
+             */
+            void setLinearDamping(Number damping);
+            void setAngularDamping(Number damping);
+            void setFriction(Number friction);
+        
+            /**
+             * Returns dampening information
+             */ 
+            Number getLinearDamping();
+            Number getAngularDamping();
+            Number getFriction();
+
+            /**
+             * Sets physics entity density
+             */
+            void setDensity(Number density);
+            Number getDensity();
+        
+            /**
+             * Sets collision filtering
+             * Collision category specifies which bits on a 16 bit field the physics entity belongs to. default is 1 (or "0000000000000001")
+             * Collision mask specifies which bits the physics entity will collide with. default 65535 (or 0xFFFF, or "1111111111111111", or everything)
+             * If a physics entity's mask bits don't line up with any of an overlapping entity's category bits, their collisions will be skipped
+             */
+            void setCollisionCategory(int categoryBits);
+            void setCollisionMask(int maskBits);
+            void setCollisionGroupIndex(int group);
+
+			/**
+			 * Gets a specific fixture based on it's index position
+			 */
+			b2Fixture* getFixture(unsigned short index);
+			/**
+			 * Gets the last fixture selected (automatically set to last added on creation)
+			 */
+			b2Fixture* getFixture();
+
 			/**
 			* Rectangular physics entity
-			*/ 
+			*/
 			static const int ENTITY_RECT = 1;
 			/**
 			* Circular physics entity
 			*/ 			
 			static const int ENTITY_CIRCLE = 2;	
 			/**
-			* Mesh entity.
+			* Mesh physics entity.
 			*/ 						
 			static const int ENTITY_MESH = 3;
-		
+			/**
+			* Edge phyiscs Entity
+			*/ 
+            static const int ENTITY_EDGE = 4;
+
+
+			b2Body *body;			
 			b2Fixture *fixture;		
-			b2Body* body;
-			b2Shape *shape;
 			
 			bool collisionOnly;
-		
+
 		protected:
-		
-		Number worldScale;
-		ScreenEntity *screenEntity;
+        
+			Number worldScale;        
+			ScreenEntity *screenEntity;   		
 	};
 
 }

+ 74 - 40
Modules/Contents/2DPhysics/Source/PolyPhysicsScreen.cpp

@@ -43,17 +43,28 @@ ScreenEntity *PhysicsScreenEvent::getSecondEntity() {
 	return entity2;
 }
 
+void PhysicsScreen::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
+{
+    if(((PhysicsScreenEntity*)contact->GetFixtureA()->GetBody()->GetUserData())->collisionOnly ||
+       ((PhysicsScreenEntity*)contact->GetFixtureB()->GetBody()->GetUserData())->collisionOnly) {
+        contact->SetEnabled(false);
+    }    
+}
 
 void PhysicsScreen::BeginContact (b2Contact *contact) {
 
 //	if(!contact->GetFixtureA()->IsSensor() && !contact->GetFixtureB()->IsSensor()) {
 //		return;
 //	}
-	
 	PhysicsScreenEvent *newEvent = new PhysicsScreenEvent();
-	newEvent->entity1 = getPhysicsEntityByFixture(contact->GetFixtureA())->getScreenEntity();
-	newEvent->entity2 = getPhysicsEntityByFixture(contact->GetFixtureB())->getScreenEntity();			
-
+	newEvent->entity1 = (ScreenEntity*)contact->GetFixtureA()->GetUserData();
+	newEvent->entity2 = (ScreenEntity*)contact->GetFixtureB()->GetUserData();			
+
+    if(((PhysicsScreenEntity*)contact->GetFixtureA()->GetBody()->GetUserData())->collisionOnly ||
+        ((PhysicsScreenEntity*)contact->GetFixtureB()->GetBody()->GetUserData())->collisionOnly) {
+        contact->SetEnabled(false);
+    }
+       
 	b2Manifold *manifold = contact->GetManifold();
 	b2Vec2 nor = manifold->localNormal;
 	b2Vec2 point = manifold->localPoint;
@@ -77,6 +88,8 @@ void PhysicsScreen::BeginContact (b2Contact *contact) {
 	newEvent->impactStrength = 0;
 	newEvent->frictionStrength = 0;
 
+    newEvent->contact = contact;
+    
 	dispatchEvent(newEvent, PhysicsScreenEvent::EVENT_NEW_SHAPE_COLLISION);
 	
 	contacts.push_back(contact);
@@ -84,13 +97,19 @@ void PhysicsScreen::BeginContact (b2Contact *contact) {
 
 void PhysicsScreen::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) {
 	PhysicsScreenEvent *newEvent = new PhysicsScreenEvent();
-	newEvent->entity1 = getPhysicsEntityByFixture(contact->GetFixtureA())->getScreenEntity();
-	newEvent->entity2 = getPhysicsEntityByFixture(contact->GetFixtureB())->getScreenEntity();			
+	newEvent->entity1 = (ScreenEntity*)contact->GetFixtureA()->GetUserData();
+	newEvent->entity2 = (ScreenEntity*)contact->GetFixtureB()->GetUserData();		
 
+    
+    if(((PhysicsScreenEntity*)contact->GetFixtureA()->GetBody()->GetUserData())->collisionOnly ||
+       ((PhysicsScreenEntity*)contact->GetFixtureB()->GetBody()->GetUserData())->collisionOnly) {
+        contact->SetEnabled(false);
+    }
+
+    
 	b2Manifold *manifold = contact->GetManifold();
 	b2Vec2 nor = manifold->localNormal;
 	b2Vec2 point = manifold->points[0].localPoint;
-	
 
 	b2WorldManifold w_manifold;
 	contact->GetWorldManifold(&w_manifold);
@@ -109,7 +128,8 @@ void PhysicsScreen::PostSolve(b2Contact* contact, const b2ContactImpulse* impuls
 	
 	newEvent->impactStrength = 0;
 	newEvent->frictionStrength = 0;
-
+    
+    newEvent->contact = contact;
 	for(int i=0; i < manifold->pointCount; i++) {
 		if(impulse->normalImpulses[i] > newEvent->impactStrength)
 			newEvent->impactStrength = impulse->normalImpulses[i];
@@ -123,9 +143,10 @@ void PhysicsScreen::PostSolve(b2Contact* contact, const b2ContactImpulse* impuls
 
 void PhysicsScreen::EndContact (b2Contact *contact) {
 	PhysicsScreenEvent *newEvent = new PhysicsScreenEvent();
-	newEvent->entity1 = getPhysicsEntityByFixture(contact->GetFixtureA())->getScreenEntity();
-	newEvent->entity2 = getPhysicsEntityByFixture(contact->GetFixtureB())->getScreenEntity();
-	
+	newEvent->entity1 = (ScreenEntity*)contact->GetFixtureA()->GetUserData();
+	newEvent->entity2 = (ScreenEntity*)contact->GetFixtureB()->GetUserData();	
+    newEvent->contact = contact;
+    
 	for(int i=0; i < contacts.size(); i++) {
 		if(contacts[i] == contact) {
 			contacts.erase(contacts.begin()+i);
@@ -143,9 +164,10 @@ bool PhysicsScreen::testEntityCollision(ScreenEntity *ent1, ScreenEntity *ent2)
 		return false;
 	
 	for(int i=0; i < contacts.size(); i++) {
-		ScreenEntity *cEnt1 = getPhysicsEntityByFixture(contacts[i]->GetFixtureA())->getScreenEntity();
-		ScreenEntity *cEnt2 = getPhysicsEntityByFixture(contacts[i]->GetFixtureB())->getScreenEntity();
+		ScreenEntity *cEnt1 = (ScreenEntity*)contacts[i]->GetFixtureA()->GetUserData();
+		ScreenEntity *cEnt2 = (ScreenEntity*)contacts[i]->GetFixtureB()->GetUserData();
 		
+	        
 		if((cEnt1 == ent1 && cEnt2 == ent2) || (cEnt1 == ent2 && cEnt2 == ent1)) {
 			return true;
 		}
@@ -154,31 +176,32 @@ bool PhysicsScreen::testEntityCollision(ScreenEntity *ent1, ScreenEntity *ent2)
 }
 
 PhysicsScreen::PhysicsScreen() : Screen() {
-	init(10.0f, 1.0f/60.0f,10,Vector2(0.0f, 10.0f));
+	init(10.0f, 1.0f/60.0f,10,10,Vector2(0.0f, 10.0f));
 }
 
-PhysicsScreen::PhysicsScreen(Number worldScale, Number freq) : Screen() {
-	init(worldScale, 1.0f/freq,10,Vector2(0.0f, 10.0f));	
+PhysicsScreen::PhysicsScreen(Number worldScale, Number freq, int velIterations, int posIterations): Screen() {
+	init(worldScale, 1.0f/freq,velIterations, posIterations, Vector2(0.0f, 10.0f));	
 }
 
-void PhysicsScreen::init(Number worldScale, Number physicsTimeStep, int physicsIterations, Vector2 physicsGravity) {
+void PhysicsScreen::init(Number worldScale, Number physicsTimeStep, int velIterations, int posIterations, Vector2 physicsGravity) {
 	
 	this->worldScale = worldScale;
 	
 	timeStep = physicsTimeStep;
-	iterations = physicsIterations;
+	velocityIterations = velIterations;
+    positionIterations = posIterations;
 	
 	b2Vec2 gravity(physicsGravity.x,physicsGravity.y);
 	bool doSleep = true;
 	world  = new b2World(gravity, doSleep);
-	
+    
 	world->SetContactListener(this);
 }
 
 void PhysicsScreen::setGravity(Vector2 newGravity) {
 	world->SetGravity(b2Vec2(newGravity.x, newGravity.y));
 }
-
+                                
 PhysicsScreenEntity *PhysicsScreen::getPhysicsByScreenEntity(ScreenEntity *ent) {
 	for(int i=0; i<physicsChildren.size();i++) {
 		if(physicsChildren[i]->getScreenEntity() == ent)
@@ -196,8 +219,9 @@ PhysicsJoint *PhysicsScreen::createRevoluteJoint(ScreenEntity *ent1, ScreenEntit
 	PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
 	PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
 	if(pEnt1 == NULL || pEnt2 == NULL)
+    {
 		return NULL;
-	
+	}
 	b2Vec2 anchor((ent1->getPosition().x+ax)/worldScale, (ent1->getPosition().y+ay)/worldScale);
 	b2RevoluteJointDef *jointDef = new b2RevoluteJointDef();
 	jointDef->collideConnected = collideConnected;
@@ -292,9 +316,10 @@ void PhysicsScreen::setVelocityY(ScreenEntity *ent, Number fy) {
 }
 
 
-PhysicsScreenEntity *PhysicsScreen::addCollisionChild(ScreenEntity *newEntity, int entType, int groupIndex) {
+PhysicsScreenEntity *PhysicsScreen::addCollisionChild(ScreenEntity *newEntity, int entType, int groupIndex, bool sensorOnly) {
 	PhysicsScreenEntity *ret;
-	ret = addPhysicsChild(newEntity, entType, false, 0,0.0,0, true, groupIndex);
+	ret = addPhysicsChild(newEntity, entType, false, 0,0,0, sensorOnly, false, groupIndex);
+    
 	ret->collisionOnly = true; 
 	return ret;
 }
@@ -333,7 +358,6 @@ void PhysicsScreen::applyImpulse(ScreenEntity *ent, Number fx, Number fy) {
 }
 
 
-
 PhysicsJoint *PhysicsScreen::createDistanceJoint(ScreenEntity *ent1, ScreenEntity *ent2, bool collideConnected) {
 	PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
 	PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
@@ -384,9 +408,11 @@ ScreenEntity *PhysicsScreen::getEntityAtPosition(Number x, Number y) {
 	
 	for(int i=0;i<physicsChildren.size();i++) {
 		PhysicsScreenEntity *ent = physicsChildren[i];
-		if(ent->shape) {
-			if(ent->shape->TestPoint(ent->body->GetTransform(), mousePosition)) {
-				return ent->getScreenEntity();
+		if(ent->fixture) {
+			for (b2Fixture* f = ent->body->GetFixtureList(); f; f = f->GetNext()) {
+				if(f->TestPoint(mousePosition)) {
+					return ent->getScreenEntity();
+				}
 			}
 		}
 	}	
@@ -403,11 +429,13 @@ bool PhysicsScreen::testEntityAtPosition(ScreenEntity *ent, Number x, Number y)
 	mousePosition.x = x/worldScale;
 	mousePosition.y = y/worldScale;
 	
-	if(pEnt->shape) {
-		if(pEnt->shape->TestPoint(pEnt->body->GetTransform(), mousePosition))
-			return true;
-		else
-			return false;
+	if(pEnt->fixture) {
+		for (b2Fixture* f = pEnt->body->GetFixtureList(); f; f = f->GetNext()) {
+			if(f->TestPoint(mousePosition))
+				return true;
+			else
+				return false;
+		}
 	}
 	return false;
 }
@@ -420,6 +448,7 @@ void PhysicsScreen::destroyMouseJoint(b2MouseJoint *mJoint) {
 PhysicsScreenEntity *PhysicsScreen::addPhysicsChild(ScreenEntity *newEntity, int entType, bool isStatic, Number friction, Number density, Number restitution, bool isSensor, bool fixedRotation, int groupIndex) {
 	addChild(newEntity);
 	return trackPhysicsChild(newEntity, entType, isStatic, friction, density, restitution, isSensor, fixedRotation, groupIndex);
+
 }
 
 PhysicsScreenEntity *PhysicsScreen::trackPhysicsChild(ScreenEntity *newEntity, int entType, bool isStatic, Number friction, Number density, Number restitution, bool isSensor, bool fixedRotation, int groupIndex) {
@@ -430,13 +459,13 @@ PhysicsScreenEntity *PhysicsScreen::trackPhysicsChild(ScreenEntity *newEntity, i
 	return newPhysicsEntity;
 }
 
-
 void PhysicsScreen::removePhysicsChild(ScreenEntity *entityToRemove) {
 	PhysicsScreenEntity *physicsEntityToRemove = getPhysicsByScreenEntity(entityToRemove);
 	if(!physicsEntityToRemove) {
 		return;
 	}
 	world->DestroyBody(physicsEntityToRemove->body);
+    physicsEntityToRemove->body = NULL;
 	for(int i=0;i<physicsChildren.size();i++) {
 		if(physicsChildren[i] == physicsEntityToRemove) {
 			physicsChildren.erase(physicsChildren.begin()+i);
@@ -453,7 +482,6 @@ void PhysicsScreen::removeChild(ScreenEntity *entityToRemove) {
 	}
 }
 
-
 void PhysicsScreen::Shutdown() {
 
 }
@@ -466,17 +494,21 @@ PhysicsScreen::~PhysicsScreen() {
 }
 
 PhysicsScreenEntity *PhysicsScreen::getPhysicsEntityByFixture(b2Fixture *fixture) {
-	for(int i=0; i < physicsChildren.size(); i++) {
-		if(physicsChildren[i]->fixture == fixture)
-			return physicsChildren[i];
+	for(int i=0; i < physicsChildren.size(); i++) {											
+		for (b2Fixture* f = physicsChildren[i]->body->GetFixtureList(); f; f = f->GetNext()) {
+			if(f == fixture)
+				return physicsChildren[i];
+		}
 	}
 	return NULL;	
 }
 
 PhysicsScreenEntity *PhysicsScreen::getPhysicsEntityByShape(b2Shape *shape) {
 	for(int i=0; i < physicsChildren.size(); i++) {
-		if(physicsChildren[i]->shape == shape)
-			return physicsChildren[i];
+		for (b2Fixture *f = physicsChildren[i]->body->GetFixtureList(); f; f = f->GetNext()) {
+			if(f->GetShape() == shape)
+				return physicsChildren[i];
+		}
 	}
 	return NULL;
 }
@@ -486,8 +518,10 @@ void PhysicsScreen::handleEvent(Event *event) {
 }
 
 void PhysicsScreen::Update() {
+    
 	for(int i=0; i<physicsChildren.size();i++) {
 		physicsChildren[i]->Update();
 	}
-	world->Step(timeStep, iterations,iterations);	
+    
+	world->Step(timeStep, velocityIterations,positionIterations);	
 }

+ 156 - 73
Modules/Contents/2DPhysics/Source/PolyPhysicsScreenEntity.cpp

@@ -33,88 +33,95 @@ using namespace Polycode;
 
 PhysicsScreenEntity::PhysicsScreenEntity(ScreenEntity *entity, b2World *world, Number worldScale, int entType, bool isStatic, Number friction, Number density, Number restitution, bool isSensor, bool fixedRotation, int groupIndex) {
 	
-	this->worldScale = worldScale;
-	
-	Vector3 entityScale = entity->getCompoundScale();
-	
 	screenEntity = entity;
+
+	Vector3 entityScale = entity->getCompoundScale();
+	Matrix4 compoundMatrix = screenEntity->getConcatenatedMatrix();
+	entity->ignoreParentMatrix = true;
+	entity->scale = entityScale;
+	this->worldScale = worldScale;
+	collisionOnly = false;
+
 	
-	shape = NULL;
-		
-	b2BodyDef *bodyDef = new b2BodyDef();
-	
-	Matrix4 compoundMatrix = screenEntity->getConcatenatedMatrix();	
-				
-	bodyDef->position.Set(compoundMatrix.getPosition().x/worldScale, compoundMatrix.getPosition().y/worldScale);
-	bodyDef->angle = screenEntity->getRotation()*(PI/180.0f);	
-	bodyDef->bullet = isSensor;	
-	bodyDef->fixedRotation = fixedRotation;	
+	// Create body definition---------------------------------------
+	b2BodyDef bodyDef;
+	bodyDef.position.Set(compoundMatrix.getPosition().x/worldScale, compoundMatrix.getPosition().y/worldScale);
+	bodyDef.angle = screenEntity->getRotation()*(PI/180.0f);	
+	bodyDef.bullet = isSensor;	
+	bodyDef.fixedRotation = fixedRotation;	
+	if(isStatic)
+		bodyDef.type = b2_staticBody;
+	else
+		bodyDef.type = b2_dynamicBody;
+
+	// Create the body
+	body = world->CreateBody(&bodyDef);
+	body->SetUserData(this);
 	
-	if(isStatic) {
-		bodyDef->type = b2_staticBody;		
-	} else {
-		bodyDef->type = b2_dynamicBody;	
-	}
-	body = world->CreateBody(bodyDef);
-	delete bodyDef;
-		
+	// Create fixture definition---------------------------------------------
 	b2FixtureDef fDef;
 	fDef.friction = friction;
 	fDef.restitution = restitution;
 	fDef.density = density;
 	fDef.isSensor = isSensor;
 	fDef.filter.groupIndex = groupIndex;
-	
+
+	// Create Shape definition (Circle/Rectangle/Polygon)---------------------------
 	switch(entType) {
-		case ENTITY_MESH:
-		{
-			b2PolygonShape *b2shape = new b2PolygonShape;			
-			
+		case ENTITY_CIRCLE: {
+			b2CircleShape Shape;
+			fDef.shape = &Shape;
+			// Set the shape
+			Shape.m_radius = screenEntity->getWidth()/(worldScale*2.0f);
+			// Create the fixture
+			fixture = body->CreateFixture(&fDef);
+			break;
+		}
+		case ENTITY_RECT: {
+			b2PolygonShape Shape;
+			fDef.shape = &Shape;
+			// Set the shape
+			Shape.SetAsBox(screenEntity->getWidth()/(worldScale*2.0f) * entityScale.x, screenEntity->getHeight()/(worldScale*2.0f) * entityScale.y);
+			// Create the fixture
+			fixture = body->CreateFixture(&fDef);
+			break;
+		}
+		case ENTITY_EDGE: {
+			b2PolygonShape Shape;	
+			Shape.SetAsEdge(b2Vec2(-screenEntity->getWidth()/(worldScale*2.0f),-screenEntity->getHeight()/(2.0*worldScale)),
+							b2Vec2(screenEntity->getWidth()/(worldScale*2.0f),-screenEntity->getHeight()/(2.0*worldScale)));
+			fDef.shape = &Shape;
+			fixture = body->CreateFixture(&fDef);
+			break;
+        }
+        break;
+		case ENTITY_MESH: {
+			b2PolygonShape Shape;
+			fDef.shape = &Shape;
 			ScreenMesh* screenMesh = dynamic_cast<ScreenMesh*>(entity);
-			if(screenMesh != NULL) {
-				b2Vec2 *vertices = (b2Vec2*)malloc(sizeof(b2Vec2) * screenMesh->getMesh()->getVertexCount());
-	
-				int index = 0;
-				for(int i=0; i < screenMesh->getMesh()->getPolygonCount(); i++) {
-					Polycode::Polygon *poly = screenMesh->getMesh()->getPolygon(i);
-					for(int j = 0; j < poly->getVertexCount(); j++) {
-						vertices[index].x = poly->getVertex(j)->x/worldScale;
-						vertices[index].y = poly->getVertex(j)->y/worldScale;						
-						index++;
+		
+			if(screenMesh) {
+				for(short i=0, polycount=screenMesh->getMesh()->getPolygonCount(); i < polycount; i++) {
+					Polygon* poly = screenMesh->getMesh()->getPolygon(i);
+					unsigned short vertexcount = poly->getVertexCount();
+					if (vertexcount >= 3 && vertexcount <= 8) {
+						b2Vec2* vertices = new b2Vec2[vertexcount];
+						for(short index=0; index < vertexcount; index++) {
+							vertices[index].x = poly->getVertex(index)->x/worldScale;
+							vertices[index].y = poly->getVertex(index)->y/worldScale;						
+						}
+						// Set the shape
+						Shape.Set(vertices, vertexcount);
+						// Create the fixture
+						fixture = body->CreateFixture(&fDef);
+						delete []vertices;
 					}
+					else { Logger::log("Between 3 and 8 vertices allowed per polygon\n"); }
 				}
-				b2shape->Set(vertices, screenMesh->getMesh()->getVertexCount());	
-				free(vertices);
-			} else {
-				Logger::log("Tried to make a mesh collision object from a non-mesh\n");							
 			}
-
-			fDef.shape = b2shape;				
-			shape = b2shape;
-		}
-		break;
-		case ENTITY_RECT: 
-		{
-			b2PolygonShape *b2shape = new b2PolygonShape;			
-			b2shape->SetAsBox(screenEntity->getWidth()/(worldScale*2.0f) * entityScale.x, screenEntity->getHeight()/(worldScale*2.0f) * entityScale.y);
-			fDef.shape = b2shape;						
-			shape = b2shape;
+			else { Logger::log("Tried to make a mesh collision object from a non-mesh\n"); }
 		}
-		break;			
-		case ENTITY_CIRCLE:
-		{			
-			b2CircleShape *b2shape = new b2CircleShape;
-			b2shape->m_radius = screenEntity->getWidth()/(worldScale*2.0f);
-			fDef.shape = b2shape;
-			shape = b2shape;
-		}
-		break;
 	}
-	
-	fixture = body->CreateFixture(&fDef);	
-	
-	collisionOnly = false;
-	
 }
 
 void PhysicsScreenEntity::applyTorque(Number torque) {
@@ -154,6 +161,61 @@ void PhysicsScreenEntity::setVelocityY(Number fy) {
 	body->SetLinearVelocity(f);	
 }
 
+
+void PhysicsScreenEntity::setCollisionCategory(int categoryBits) {
+        b2Filter filter=fixture->GetFilterData();
+        filter.categoryBits = categoryBits;
+        fixture->SetFilterData(filter);
+}
+
+void PhysicsScreenEntity::setCollisionMask(int maskBits) {
+        b2Filter filter=fixture->GetFilterData();
+        filter.maskBits = maskBits;
+        fixture->SetFilterData(filter);
+}
+
+void PhysicsScreenEntity::setCollisionGroupIndex(int group) {
+    b2Filter filter=fixture->GetFilterData();
+    filter.groupIndex = group;
+    fixture->SetFilterData(filter);    
+}
+
+void PhysicsScreenEntity::setLinearDamping(Number damping) {
+    body->SetLinearDamping(damping);
+}
+
+void PhysicsScreenEntity::setAngularDamping(Number damping) {
+    body->SetAngularDamping(damping);
+}
+
+void PhysicsScreenEntity::setFriction(Number friction) {
+    if(fixture) {
+        fixture->SetFriction(friction);
+    }
+}
+
+void PhysicsScreenEntity::setDensity(Number density) {
+    if(fixture) {
+        fixture->SetDensity(density);
+    }
+}
+
+Number PhysicsScreenEntity::getLinearDamping() {
+    return body->GetLinearDamping();
+}
+
+Number PhysicsScreenEntity::getAngularDamping() {
+    return body->GetAngularDamping();
+}
+
+Number PhysicsScreenEntity::getFriction() {
+    return fixture->GetFriction();
+}
+
+Number PhysicsScreenEntity::getDensity() {
+    return fixture->GetDensity();
+}
+
 void PhysicsScreenEntity::applyImpulse(Number fx, Number fy) {
 	body->SetAwake(true);
 	b2Vec2 f =  b2Vec2(fx,fy);
@@ -163,6 +225,7 @@ void PhysicsScreenEntity::applyImpulse(Number fx, Number fy) {
 			
 void PhysicsScreenEntity::setTransform(Vector2 pos, Number angle) {
 	body->SetTransform(b2Vec2(pos.x/worldScale, pos.y/worldScale), angle*(PI/180.0f));
+    screenEntity->setPosition(pos);
 }
 
 void PhysicsScreenEntity::Update() {
@@ -191,12 +254,32 @@ void PhysicsScreenEntity::Update() {
 	}	
 }
 
-PhysicsScreenEntity::~PhysicsScreenEntity() {
-	if (body) {
-		if (fixture) {	
-			body->DestroyFixture(fixture);
-		}	
-		body->GetWorld()->DestroyBody(body);	
+b2Fixture* PhysicsScreenEntity::getFixture(unsigned short index) {
+	if(fixture)	{
+		short i = 0;
+		for (b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext()) {
+			if (i = index) {
+				fixture = f;
+				return fixture;
+			}
+			else {i++;}
+		}
+		
+		Logger::log("That fixture index does not exist\n");	
+		return fixture = NULL;
 	}
-	delete shape;
+
+	Logger::log("Fixturelist is for mesh only\n");
+	return fixture = NULL;	
 }
+
+b2Fixture* PhysicsScreenEntity::getFixture() { return fixture; }
+
+
+// I believe that at runtime you are not supposed to edit Shapes; However you still can
+// by getting a fixture(above) and then adding "->GetShape()" on the end to get the fixtures shape
+
+PhysicsScreenEntity::~PhysicsScreenEntity() {
+	if(body)
+		body->GetWorld()->DestroyBody(body);	// DestroyBody deletes fixtures and shapes automaticaly according to box2d documentation
+}