Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create ellipse shapes in box2d?

Tags:

c++

shapes

box2d

I need to create ellipse shape for the body, and do not understand how to make that in box2d.

Any ideas how to do that not by using b2PolygonShape with a lot of vertexes?

like image 832
Buron Avatar asked Oct 26 '25 14:10

Buron


1 Answers

OPTION #1

Use a body with two fixtures: The first would be a central circle shape to give the body some mass. The second would be the ellipse, with the vertices made from a chain shape.

The first fixture allows you to have the body act like a body with some mass, while the second fixture will allow you to handle collisions properly.

I did an example for a roulette wheel recently. I posted the code below to create that. Replace the constant value for the radius (OUTER_RADIUS) with the polar form of the radius for an ellipse found here on wikipedia.

void MainScene::CreateBody()
{
   const float32 INNER_RADIUS = 2.50;
   const float32 OUTER_RADIUS = 3.0;
   const float32 BALL_RADIUS = 0.1;
   const uint32 DIVISIONS = 36;

   Vec2 position(0,0);

   // Create the body.
   b2BodyDef bodyDef;
   bodyDef.position = position;
   bodyDef.type = b2_dynamicBody;
   _body = _world->CreateBody(&bodyDef);
   assert(_body != NULL);

   // Now attach fixtures to the body.
   FixtureDef fixtureDef;
   fixtureDef.density = 1.0;
   fixtureDef.friction = 1.0;
   fixtureDef.restitution = 0.9;
   fixtureDef.isSensor = false;

   // Inner circle.
   b2CircleShape circleShape;
   circleShape.m_radius = INNER_RADIUS;
   fixtureDef.shape = &circleShape;
   _body->CreateFixture(&fixtureDef);

   // Outer shape.
   b2ChainShape chainShape;
   vector<Vec2> vertices;
   const float32 SPIKE_DEGREE = 2*M_PI/180;
   for(int idx = 0; idx < DIVISIONS; idx++)
   {
      float32 angle = ((M_PI*2)/DIVISIONS)*idx;
      float32 xPos, yPos;

      xPos = OUTER_RADIUS*cosf(angle);
      yPos = OUTER_RADIUS*sinf(angle);
      vertices.push_back(Vec2(xPos,yPos));
   }
   vertices.push_back(vertices[0]);
   chainShape.CreateChain(&vertices[0], vertices.size());
   fixtureDef.shape = &chainShape;
   _body->CreateFixture(&fixtureDef);
    
}

You can also check out this post for the roulette wheel (plus picture goodness) solution.

OPTION #2 Instead of using a chain/edge shape, you can create a triangle fan of fixtures. Once you have the vertices for the ellipse, you could do something like:

b2Vec2 triVerts[3];
triVerts[0] = Vec2(0,0);
for(int idx = 1; idx < vertices.size(); idx++)
{
   b2PolygonShape triangle;
   fixtureDef.shape = &triangle;
   // Assumes the vertices are going around
   // the ellipse clockwise as angle increases.
   triVerts[1] = vertices[idx-1];
   triVerts[2] = vertices[idx];
   triangle.Set(triVerts,3);
   _body->CreateFixture(&fixtureDef);
}

Was this helpful?

like image 58
FuzzyBunnySlippers Avatar answered Oct 29 '25 05:10

FuzzyBunnySlippers