You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

195 lines
6.3 KiB

#ifndef CHAINLINKS_H
#define CHAINLINKS_H
#include <array>
#include <cmath>
#include <iostream>
#include <vector>
class ChainLinks : public Test {
protected:
float scale;
float thickness;
public:
static void createLinkVertexEdgeArrays(std::vector<b2Vec2>& vertices,
std::vector<std::array<int, 2>>& edges,
float thickness)
{
auto f1 = [](float x) -> float { return -1.25 * x + 1.625; };
auto f2 = [](float x) -> float { return 1.25 * x + 0.375; };
vertices = std::vector<b2Vec2>(10);
vertices[0].Set(-1.5f * f1(thickness / 2), 0.0f);
vertices[1].Set(0.0f, 0.0f);
vertices[2].Set(1.5f * f1(thickness / 2), 0.0f);
vertices[3].Set(-3.0f, -3.0f);
vertices[4].Set(0.0f, -3.0f);
vertices[5].Set(3.0f, -3.0f);
vertices[6].Set(-3.0f, -6.0f);
vertices[7].Set(-1.5f * f2(thickness / 2), -6.0f);
vertices[8].Set(1.5f * f2(thickness / 2), -6.0f);
vertices[9].Set(3.0f, -6.0f);
edges = std::vector<std::array<int, 2>>(9);
edges[0] = { 0, 1 };
edges[1] = { 1, 2 };
edges[2] = { 1, 4 };
edges[3] = { 3, 4 };
edges[4] = { 4, 5 };
edges[5] = { 3, 6 };
edges[6] = { 5, 9 };
edges[7] = { 6, 7 };
edges[8] = { 8, 9 };
}
virtual void createLink(b2World* world, float x, float y, b2BodyType type)
{
// Define the link.
b2BodyDef linkBodyDef;
linkBodyDef.type = type;
linkBodyDef.bullet = type == b2_dynamicBody;
linkBodyDef.position.Set(x, y);
linkBodyDef.angle = 3.14159f / 2.0f;
// Call the body factory which allocates memory for the ground body
// from a pool and creates the link (also from a pool).
// The body is also added to the world.
b2Body* link = world->CreateBody(&linkBodyDef);
// Define the link shape
b2CircleShape circle;
circle.m_radius = thickness / 2.0f;
b2PolygonShape box;
float density = 1.0f;
std::vector<b2Vec2> vertices;
std::vector<std::array<int, 2>> edges;
createLinkVertexEdgeArrays(vertices, edges, thickness);
// Add the shape fixtures to the link body
float friction_coeff = 0.0;
float restitution_coeff = 0.0;
for (const auto& vertex : vertices) {
circle.m_p = scale * vertex;
b2Fixture* fixture = link->CreateFixture(&circle, density);
fixture->SetFriction(friction_coeff);
fixture->SetRestitution(restitution_coeff);
}
for (const auto& edge : edges) {
b2Vec2 v0 = scale * vertices[edge[0]];
b2Vec2 v1 = scale * vertices[edge[1]];
b2Vec2 center = 0.5 * (v1 + v0);
float hx = (v1 - v0).Length() / 2;
float hy = thickness / 2.0f;
float angle = atan2((v1 - v0).y, (v1 - v0).x);
box.SetAsBox(hx, hy, center, angle);
b2Fixture* fixture = link->CreateFixture(&box, density);
fixture->SetFriction(friction_coeff);
fixture->SetRestitution(restitution_coeff);
}
}
ChainLinks(float thickness = 1.0, float scale = 1.0)
: thickness(thickness)
, scale(scale)
{
m_world->SetGravity(b2Vec2(0, -9.81));
float y = 15;
float x = -30;
for (int i = 0; i < 30; i++) {
createLink(m_world, x, y, i ? b2_dynamicBody : b2_staticBody);
x += 4.5 * scale;
}
}
static Test* Create() { return new ChainLinks(); }
static Test* CreateThin() { return new ChainLinks(0.1); }
virtual void Step(Settings* settings) override
{
static bool firstCall = true;
if (firstCall) {
settings->enableSleep = false;
settings->hz = 120; // 1 / 1e-3;
settings->velocityIterations = 300;
settings->positionIterations = 300;
settings->drawContactPoints = true;
settings->drawContactImpulse = true;
firstCall = false;
}
Test::Step(settings);
}
};
class SimpleChainLinks : public Test {
protected:
float scale;
public:
virtual void createLink(b2World* world, float x, float y, b2BodyType type)
{
// Define the link.
b2BodyDef linkBodyDef;
linkBodyDef.type = type;
linkBodyDef.bullet = type == b2_dynamicBody;
linkBodyDef.position.Set(x, y);
linkBodyDef.angle = 3.14159f * 3.0f / 4.0f;
// Call the body factory which allocates memory for the ground body
// from a pool and creates the link (also from a pool).
// The body is also added to the world.
b2Body* link = world->CreateBody(&linkBodyDef);
// Define the link shape
b2EdgeShape edgeShape;
float density = 1.0f;
std::vector<b2Vec2> vertices;
std::vector<std::array<int, 2>> edges;
ChainLinks::createLinkVertexEdgeArrays(vertices, edges, 0.1);
// Add the shape fixtures to the link body
float friction_coeff = 0.0;
float restitution_coeff = 0.0;
for (const auto& edge : edges) {
b2Vec2 v0 = scale * vertices[edge[0]];
b2Vec2 v1 = scale * vertices[edge[1]];
edgeShape.Set(v0, v1);
b2Fixture* fixture = link->CreateFixture(&edgeShape, density);
fixture->SetFriction(friction_coeff);
fixture->SetRestitution(restitution_coeff);
}
}
SimpleChainLinks(float scale = 1.0)
: scale(scale)
{
m_world->SetGravity(b2Vec2(0, -9.81));
float y = 15;
float x = -30;
for (int i = 0; i < 10; i++) {
createLink(m_world, x, y, i ? b2_dynamicBody : b2_staticBody);
x += 3 * scale;
y += 3 * scale;
}
}
static Test* Create() { return new SimpleChainLinks(); }
virtual void Step(Settings* settings) override
{
static bool firstCall = true;
if (firstCall) {
settings->enableSleep = false;
settings->hz = 120; // 1 / 1e-3;
settings->velocityIterations = 300;
settings->positionIterations = 300;
settings->drawContactPoints = true;
settings->drawContactImpulse = true;
firstCall = false;
}
Test::Step(settings);
}
};
#endif