Finding the centre of a fixture in Box2D - c++

I'm trying to make a system of "chunks" in Box2D - i.e. shapes that are attached together in a big lump, so that you can break chunks off into their own body.
Currently, my system is very basic (just starting really) and modelled after the "Breakable" test in the Box2D testbed. It's a body with quite a few basic box fixtures (which will later become polygons). When you click a body, it deletes the fixture and creates a new body with the same fixture, rotation, etc in the same place as the old "chunk".
However, I can only get it to create the new body at the big body's origin
(->GetWorldCenter). What I want to do is find the global location of the fixture to be deleted and replaced, so I can make the new chunk there.
I've read some stuff about b2PolygonShape having a "centroid", but I'm not sure how to access and use that...
To put it simply, I want to find the global location (as x+y or a b2Vec2) of a FIXTURE, NOT a body (that's easy). The fixture will move with the body it's attached to, but I only currently need the position for one frame (having it update would be useful too though).

For Box2D position of the body not so important. Body position is only shift for fixture coordinates. It do not impact to simulation process. So, I don't understand, why you so care about this.
I made something like this, and can say, that using big body's origin works fine. You can see into Box2D testbed to Breakable test. There also used big body's origin. Only reason to calculate new coordinates that I see is strange behavior of SetAngle method.
If you still want centroid, look at ComputeCentroid, located at b2PolygonShape.cpp. Pay attention, method don't declared at b2PolygonShape.h. You can copy code from cpp and use it like this:
b2Fixture* chunk = ...;
b2Vec2 chunkCentroidLocal = ComputeCentorid(chunk->m_vertices,
chunk->m_vertexCount);
b2Vec2 chunkCentroidWorld = bigBody->GetWorldPoint(chunkCentroidLocal);
p.s. Don't forget to transform polygon points, when you will create new body. Simply find difference between big body and new body, and subtract it from every point of polygon.
b2Vec2 shift = chunkCentroidWorld - bigBody->GetWorldCenter();
b2Vec2 newVertices = new b2Vec2[chunk->m_vertexCount];
for(int i = 0; i< chunk->m_vertexCount; i++)
{
newVertices[i] = chunk->m_vertices[i] - shift;
}

Related

Multiple instances of btDefaultMotionState, all ignored, but one

To summarize the problem(s):
I have two bodies in my world so far, one being the ground, the other one being a falling box called "fallingStar".
1) I do not understand why my bullet world is not aligned with my drawn world unless I set an offset of btVector3(2,2,2) to the (btDefault)MotionState.
There is no fancy magic going on anywhere in the code that would explain the offset. Or at least I could not find any reason, not in the shaders, not anywhere.
2) I expected to be able to use multiple instances of btDefaultMotionState, to be precise, I wanted to use one instance for the falling entity and place it somewhere above the ground and then create another instance for the ground that should simply be aligned with my graphics-ground, ever unmoving.
What I am experiencing in regards to 2) is that for whatever reason the btDefaultMotionState instance for the falling entity is always also influencing the one for the ground, without any reference.
Now to the code:
Creation of the fallingBox:
btCollisionShape *fallingBoxShape = new btBoxShape(btVector3(1,1,1));
btScalar fallingBoxMass = 1;
btVector3 fallingBoxInertia(0,0,0);
fallingBoxShape->calculateLocalInertia(fallingBoxMass, fallingBoxInertia);
// TODO this state somehow defines where exactly _ALL_ of the physicsWorld is...
btDefaultMotionState *fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(2,2,2)));
//btDefaultMotionState *fallMotionState = new btDefaultMotionState();
btRigidBody::btRigidBodyConstructionInfo fallingBoxBodyCI(fallingBoxMass, fallMotionState, fallingBoxShape, fallingBoxInertia);
/*btTransform initialTransform;
initialTransform.setOrigin(btVector3(0,5,0));*/
this->fallingBoxBody = new btRigidBody(fallingBoxBodyCI);
/*fallMotionState->setWorldTransform(initialTransform);
this->fallingBoxBody->setWorldTransform(initialTransform);*/
this->physicsWorld->addBody(*fallingBoxBody);
Now the interesting parts to me are the necessary offset of btVector3(2,2,2) to align it with my drawn world and this:
btTransform initialTransform;
initialTransform.setOrigin(btVector3(0,5,0));
this->fallingStarBody = new btRigidBody(fallingStarBodyCI);
fallMotionState->setWorldTransform(initialTransform);
If I reenable this part of the code ALL the bodies again show an offset, but NOT just 5 up, which I could somehow comprehend if for whatever reason the worldTransform would effect every entity, but about 2,2,2 off... which I cannot grasp at all.
I guess that this line is useless:
fallMotionState->setWorldTransform(initialTransform); as it does not change anything whether it's there or not.
Now to the code of the ground creation:
btCompoundShape *shape = new btCompoundShape();
... just some logic, nothing to do with bullet
btTransform transform;
transform.setIdentity();
transform.setOrigin(btVector3(x + (this->x * Ground::width),
y + (this->y * Ground::height),
z + (this->z * Ground::depth)));
btBoxShape *boxShape = new btBoxShape(btVector3(1,0,1)); // flat surface, no box
shape->addChildShape(transform, boxShape);
(this portion just creates a compoundshape for each surface tile :)
btRigidBody::btRigidBodyConstructionInfo info(0, nullptr, shape);
return new btRigidBody(info);
Here I purposely set the motionstate to nullptr, but this doesn't change anything.
Now I really am curious... I thought maybe the implementation of btDefaultMotionState is a singleton, but it doesn't look so, so... why the hell is setting the motionState of one body affecting the whole world?
Bullet is a good library but only few dedicate time to write good documentation.
To set position of a btRigidBody, try this :-
btTransform transform = body -> getCenterOfMassTransform();
transform.setOrigin(aNewPosition); //<- set orientation / position that you like
body -> setCenterOfMassTransform(transform);
If your code is wrong only at the set transformation part (that is what I guess from skimming your code), it should be solved.
Note that this snippet works only for dynamic body, not static body.
About CompoundBody:-
If it is a compound body, e.g. shape B contains shape C.
Setting transformation of B would work (set body of B), but not work for C.
(because C is just a shape, transformation support only body.)
If I want to change relative transformation of C to B, I would create a whole new compound shape and a new rigid body. Don't forget to remove old body & shape.
That is a library limitation.
P.S.
I can't answer some of your doubt/questions, these information are what I gathered after stalking in Bullet forum for a while, and tested by myself.
(I am also coding game + game library from scratch, using Bullet and other open sources.)
Edit: (about the new problem)
it just slowly falls down (along with the ground itself, which should
not move as I gave it a mass of 0)
I would try to solve it in this order.
Idea A
Set to the compound mass = 0 instead, because setting a child shape's mass has no meaning.
Idea B
First check -> getCenterOfMassTransform() every time-step , is it really falling?
If it is actually falling, to be sure, try dynamicsWorld->setGravity(btVector3(0,0,0));.
If still not work, try with very simple world (1 simple object, no compound) and see.
Idea C (now I start to be desperate)
Ensure your camera position is constant.
If the problem is still alive, I think you now can create a simple test-case and post it in Bullet forum without too much effort.
Lower amounts of lines of code = better feedback
What you are describing is not normal bullet behavior. Your understanding of the library is correct.
What you are most likely dealing with is either a buffer overrun or a dangling pointer. The code you have posted does not have an obvious one of either, so it would be coming from somewhere else in your codebase. You might be able to track that down using a well-placed memory breakpoint.
You "might" be dealing with a header/binary version inconsistency issue, but that's less likely as you would probably be seeing other major issues.
Just had the exact same type of behavior with the DebugDrawer suspended on top of the world. Solved it by passing to Bullet Physics the projectionview matrix alone, without the model matrix that he has and multiplies with already:
glUseProgram(shaderID);
m_MVP = m_camera->getProjectionViewMatrix();
glUniformMatrix4fv(shaderIDMVP, 1, GL_FALSE, &m_MVP[0][0]);
if (m_dynamicWorld) m_dynamicWorld->debugDrawWorld();

Python 3 Graphics Programming: how can I get a mouse click within a polygon shape?

So I'm working on a project for a class and I'm still trying to figure out how to go about doing something.
I am making a game where there is a board of squares or hexagons, they are either black or white, each being a state of being "Flipped", and when you click one square/hexagon, it flips all the adjacent shapes too.
Here is an image of what I am aiming to create.
Assignment images
I have gotten it running with squares, but now I need to do it with Hexagons. With the squares I registered a mouseclick as being within a square parameters of the x and y location of the click, and the state changes are assigned to a list of values assigned similarly to how the shapes were assigned within a list.
I will include a quick recording of the square program running in a folder I'm going to link.
Now, I believe I can't apply this kind of system to hexagons since they don't really line up like the squares did.
So how would I go about making a click register within a single hexagon on a grid? I have already drawn out the grid, but I am stuck on what to do to register a click to allow a hexagon to change it's state from un-flipped to flipped. I'm pretty sure I know what to do for the state change itself, but I don't know how to go about this, would it involve something with making a separate Class or something? I would appreciate any help with this.
I'll put a dropbox link here for the progress I made so far, and a pdf manual for graphics.py.
Dropbox: Python files
You can view the python code in your web-browser with dropbox too, I don't really want to fill this page pull of an entire thing of code..
Any help and feedback would be wonderful, thank you c:
so, TL;DR: How do you register a click within a polygon shape in python that allows it to change a value (within a list?) and change its visual appearance.
Just for the general side of your question, you can use a test to check if a point (x, y) is inside a polygon (formed by a list of x, y pairs).
Here's one such solution: http://www.ariel.com.au/a/python-point-int-poly.html
# determine if a point is inside a given polygon or not
# Polygon is a list of (x,y) pairs.
def point_inside_polygon(x,y,poly):
n = len(poly)
inside =False
p1x,p1y = poly[0]
for i in range(n+1):
p2x,p2y = poly[i % n]
if y > min(p1y,p2y):
if y <= max(p1y,p2y):
if x <= max(p1x,p2x):
if p1y != p2y:
xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x or x <= xinters:
inside = not inside
p1x,p1y = p2x,p2y
return inside
This can be used in a way that is quite symmetrical to your drawing code, as you also form polygons in the same way for drawing as you would to test to see if the cursor is inside a hex.
You can modify the above implementation also to work with this Point type you are using to draw the polygons.
The rest you should be able to figure out, especially considering that you managed the input handling and drawing for the square grid.

Transform part of an ID3D11Buffer

I am making a racing game as part of an assignment using DirectX 11, and I have loaded in a model of a car into a ID3D11Buffer. From this, I was wondering how to rotate the wheels of the car separately to the rest of the model. I have the start and end indices of each part of the car, so I know which part it is to be rotated, just not how to translate it separately. (I'm not sure if me including code would help, but if so, just let me know)
Why not load the model to mess? the wheels is part of the car, and thus a sub-mess of the car.
with sub-mess, you can transform and render it separately without changes the other parts.
If you really want to load it into a ID3DBuffer, I recommend you create two buffers, one hold the static part of the car, another hold the wheels, in this way, you can transform and render the wheels while keep the static part unchanged.
Immediately after asking, I figured it out, and now I have it implemented so that it works fine.
Given that .obj files support groups of vertices, when you load in the file, store the start and end location of each group of vertices, the name of each part that's preceded in the .obj file with a 'g' at the beginning of a line, and calculate the centre point of each group.
Then, make sure that you have a XMFLOAT4X4 for each part that you want to transform separately, as well as one for the whole object. In this case, I have objectMatrix, and wheel1-4Matrix. I apply any transformations I want to the objectMatrix that is general world transformations to do with moving the car. For each wheel, do the following translation
XMMATRIX translate;
translate = XMMatrixTranslation(-centre.x, -centre.y, -centre.z);
translate *= XMMatrixRotationX(angleToBeMoved);
translate *= XMMatrixTranslation(centre.x, centre.y, centre.z);
translate = XMMatrixMultiply(translate, XMLoadFloat4x4(&objectMatrix));
XMStoreFloat4x4(&wheel1, translate);
Apply this to each wheel during the update. During the Draw method, make sure that you're using the DrawIndexed method, pass it both the start and end index for each group, and update your constant buffer's world view matrix with the relevant wheel matrix if it's a wheel, or with the objectMatrix in all other circumstances.

Positioning Circle Shapes within a Body in Box2D Web

I've had to completely revamp this question as I don't think I was explicit enough about my problem.
I'm attempting to learn the ropes of Box2D Web. I started having problems when I wanted to learn how to put multiple shapes in one rigid body (to form responsive concave bodies). One of the assumptions I made was that this kind of feature would only really be useful if I could change the positions of the shapes (so that I can be in control of what the overall rigid body looked like). An example would be creating an 'L' body with two rectangle shapes, one of which was positioned below and to-the-right of the first shape.
I've gotten that far in so-far-as I've found the SetAsOrientedBox method where you can pass the box its position in the 3rd argument (center).
All well and good. But when I tried to create two circle shapes in one rigid body, I found undesirable behaviour. My instinct was to use the SetLocalPosition method (found in the b2CircleShape class). This seems to work to an extent. In the debug draw, the body responds physically as it should do, but visually (within the debug) it doesn't seem to be drawing the shapes in their position. It simply draws the circle shapes at the centre position. I'm aware that this is probably a problem with Box2D's debug draw logic - but it seems strange to me that there is no online-patter regarding this issue. One would think that creating two circle shapes at different positions in the body's coordinate space would be a popular and well-documented phenomina. Clearly not.
Below is the code I'm using to create the bodies. Assume that the world has been passed to this scope effectively:
// first circle shape and def
var fix_def1 = new b2FixtureDef;
fix_def1.density = 1.0;
fix_def1.friction = 0.5;
fix_def1.restitution = .65;
fix_def1.bullet = false;
var shape1 = new b2CircleShape();
fix_def1.shape = shape1;
fix_def1.shape.SetLocalPosition(new b2Vec2(-.5, -.5));
fix_def1.shape.SetRadius(.3);
// second circle def and shape
var fix_def2 = new b2FixtureDef;
fix_def2.density = 1.0;
fix_def2.friction = 0.5;
fix_def2.restitution = .65;
fix_def2.bullet = false;
var shape2 = new b2CircleShape();
fix_def2.shape = shape2;
fix_def2.shape.SetLocalPosition(new b2Vec2(.5, .5));
fix_def2.shape.SetRadius(.3);
// creating the body
var body_def = new b2BodyDef();
body_def.type = b2Body.b2_dynamicBody;
body_def.position.Set(5, 1);
var b = world.CreateBody( body_def );
b.CreateFixture(fix_def1);
b.CreateFixture(fix_def2);
Please note that I'm using Box2D Web ( http://code.google.com/p/box2dweb/ ) with the HTML5 canvas.
It looks like you are not actually using the standard debug draw at all, but a function that you have written yourself - which explains the lack of online-patter about it (pastebin for posterity).
Take a look in the box2dweb source and look at these functions for a working reference:
b2World.prototype.DrawDebugData
b2World.prototype.DrawShape
b2DebugDraw.prototype.DrawSolidCircle
You can use the canvas context 'arc' function to avoid the need for calculating points with sin/cos and then drawing individual lines to make a circle. It also lets the browser use the most efficient way it knows of to render the curve, eg. hardware support on some browsers.
Since it seems like you want to do custom rendering, another pitfall to watch out for is the different call signatures for DrawCircle and DrawSolidCircle. The second of these takes a parameter for the axis direction, so if you mistakenly use the three parameter version Javascript will silently use the color parameter for the axis, leaving you with an undefined color parameter. Hours of fun!
DrawCircle(center, radius, color)
DrawSolidCircle(center, radius, axis, color)

Distinguish between collision surface orientations in box2d

I've been working on an iOS project, using Cocos2D 1.0 and Box2D, and I've run into a bit of a problem.
What I need to be able to do is determine the orientation of a surface my player has hit. For example, if we have a rectangular platform, and the player collides with it, I need to know whether the player has hit the left, right, top, or bottom face of it. ALL the objects in the game are square, and the ONLY one moving is the player.
I'm currently using a b2ContactListener in Box2D (well, my own subclass of one, anyway), and have been playing around with the local normal of the manifold from the contact in BeginContact. The main problem I have is that that normal seems to be affected by the rotation of the player body (e.g. the player has rotated 90 degrees, OR the player is spinning wildly on impact - both situations are giving me trouble), and I seem to end up with ambiguity (i.e. collisions with different faces that give the same normal...) if I try to allow for that - although of course I could just be doing something horribly wrong. Now, I don't understand manifolds very well, so it's possible that my problem stems from that, or maybe I'm missing something obvious.
Any suggestions?
I would prefer to do this in the cleanest and least ugly manner possible. Bear in mind that the main categorisation I care about is "player is landing on something from above" vs "everything else", but I may end up needing the exact
If you need more information or clarification about anything, just ask.
EDIT: Just to clarify, I am aware that the normal points from A to B (in a collision between A and B) by convention in Box2D, and my code does check to see which one is the player and takes this into account before doing any calculations to determine which face has been hit.
So, I feel a little awkward about answering my own question, but apparently it's officially encouraged.
Anyway, the problem with the way I was approaching things was twofold. Firstly, I was using the contact manifold's local normal instead of the world normal. Secondly, my code for reversing the object transformations was buggy (I would never have needed to do this if I had been using the world manifold).
The world manifold takes into account object transformations and sizes and as such contains data more easily applicable to the world co-ordinate system.
By convention in Box2d, the collision normal (for both the world manifold and the contact manifold) points from A to B - this has to be taken into account for some uses, since the normal from A to B is the inverse of the normal from B to A, so you can't just assume that one body will always be A.
So, the solution is to use get the world manifold for each collision, examine its normal, and then make whatever decisions you want to make.
For example, in the BeginContact method of a b2ContactListener subclass (if you have no idea what I'm talking about then check out part 2 of this tutorial):
void ContactListener::BeginContact(b2Contact* contact)
{
b2WorldManifold worldManifold;
contact->GetWorldManifold(&worldManifold); // this method calls b2WorldManifold::Initialize with the appropriate transforms and radii so you don't have to worry about that
b2Vec2 worldNormal = worldManifold.normal;
// inspect it or do whatever you want based on that...
}
Since you'll likely need to check what bodies are colliding, and which one is A and which one is B, you may want to keep a vector of structs containing the fixtures that collided (as in that tutorial) and the normal, and iterate over the vector in your tick() method or similar. (You can get these out of the contact with contact->GetFixtureA() and contact->GetFixtureB().)
Now, you could get the point data from the world manifold, and make your decisions based on that, but why would you when the normal is already available, since in this particular case the normal (combined with which shapes the normal points from and to) is all that is needed.
Edit (for #iBradApps):
First, I'm assuming here that you have followed the tutorial I linked to and have a contact listener set up. If you haven't, follow it because Ray explains it in depth quite well.
Second, I want to point out that there is no absolute guarantee which object is A and which is B (well, it depends on what kind of Box2D objects they are; suffice to say if they can both move, you can't guarantee the ordering, at least as far as I know), so in my case I wanted to see if the player object had hit something, so I created a class variable (b2Fixture *playerF) in my contact listener that stored a reference to the player object so I could determine whether contact A or contact B was the player.
You asked about detecting a collision where something else collided with the top of B. Something like the following should work, although I haven't had a chance to test it for you:
In your ContactListener.h:
public:
b2Fixture *playerF;
// along with the vector etc mentioned in Ray's tutorial
// and anything else you want
When you make the ContactListener in your init() (assuming you called it _contactListener):
_contactListener->playerF = playerFixture; // or whatever you called the player body fixture
BeginContact method:
void ContactListener::BeginContact(b2Contact* contact)
{
b2WorldManifold worldManifold;
contact->GetWorldManifold(&worldManifold); // this method calls b2WorldManifold::Initialize with the appropriate transforms and radii so you don't have to worry about that
b2Vec2 worldNormal = worldManifold.normal; // this points from A to B
if (playerF == contact->GetFixtureA()) {
// note that +ve y-axis is "up" in Box2D but down in OpenGL and Cocos2D
if (worldNormal.y < -0.707) { // use a constant for performance reasons
// if the y component is less than -1/sqrt(2) (approximately -0.707),
// then the normal points more downwards than across, so A must be hitting B
// from roughly above. You could tune this more towards the top by increasing
// towards -1 if you want but it worked fine for me like this last time and
// you might run into issues with missing hits
NSLog(#"Player (A) hit B roughly on the top side!");
// here you can set any class variables you want to check in
// your update()/tick(), such as flags for whether the player has died from
// falling or whatever
}
} else if (playerF == contact->GetFixtureB()) {
if (worldNormal.y > 0.707) {
NSLog(#"Player (B) hit A roughly on the top side!");
}
} else {
// it's something else hitting something else and we don't care about it
}
}
As for doing it in your tick() method instead, yes, you can. I actually did all my stuff in PostSolve in the contact listener because I needed to know how hard the player hit, but all I cared about beyond that was whether the player had hit hard enough to kill them, so I didn't need or want to iterate over all the contacts in my tick() - I just set a flag in the contact listener that said the player had suffered a fatal impact.
If you want to do this all in the update method, then starting from what Ray has, add a b2Vec2 to the MyContact struct, and in BeginContact, add both the two fixtures (like Ray does) and get the collision normal (as I do) and add it too.
The modified MyContact struct:
struct MyContact {
b2Fixture *fixtureA;
b2Fixture *fixtureB;
b2Vec2 normal;
bool operator==(const MyContact& other) const
{
return (fixtureA == other.fixtureA) && (fixtureB == other.fixtureB);
}
};
The new BeginContact method:
void MyContactListener::BeginContact(b2Contact* contact) {
b2WorldManifold wordManifold;
contact->GetWorldManifold(&worldManifold);
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB(), worldManifold.normal };
_contacts.push_back(myContact);
}
This will give you all the information you need to do the checking I initially described in your tick().
Edit again:
Your tick() method might contain something like this if you want to do the processing there, assuming you have called the player fixture (or ball fixture, like in the tutorial, or whatever it is you're interested in) _playerFixture, that you've got a contact listener with the same name as in the tutorial, that you added the b2Vec2 normal to the MyContact struct, that you are adding contacts to the vector (as above) in BeginContact, and that you are deleting contacts from the vector in the EndContact (as shown in the tutorial - it's probably fine as is):
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin(); pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
if (_playerFixture == contact.fixtureA && contact.normal.y < -0.707) {
NSLog(#"Player (A) hit B roughly on the top side!");
} else if (_playerFixture == contact.fixtureB && contact.normal.y > 0.707) {
NSLog(#"Player (B) hit A roughly on the top side!");
} else {
// it's something else hitting something else and we don't care about it
}
}