I have full code to splite box2d you can copy it and check. I have just a little problem i think it can be sth wrong with:
“b2Vec2 arrVertices[b2_maxPolygonVertices];
std::copy(vertices.begin(), vertices.end(), arrVertices);
slicePoly.Set(arrVertices, count);”
If you guys know how to fix it or you’ve done sth similar please let me know :)))
THANKS ANYWAY
HELLOWORLDSCENE.H
using namespace cocos2d;
class GLESDebugDraw;
struct Segment
{
b2Vec2 p1;
b2Vec2 p2;
};
class HelloWorldScene : public cocos2d::Layer ,public b2RayCastCallback{
public:
~HelloWorldScene();
HelloWorldScene();
static cocos2d::Scene* scene();
void addNewSpriteWithCoords(cocos2d::CCPoint p);
virtual void draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags) override;
bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event unused_event);
void onTouchEnded(cocos2d::Touch touch, cocos2d::Event unused_event);
virtual float32 ReportFixture(b2Fixture fixture, const b2Vec2& point,const b2Vec2& normal, float32 fraction);
b2Vec2 findCenter(std::vector& vertices, int count);
void createSlice(std::vector& vertices, int count);
b2Vec2 toBox2dPoint(CCPoint pt);
CCPoint toCocos2dPoint(b2Vec2& pt);
private:
GLESDebugDraw m_debugDraw;
b2World world;
b2Body m_body;
b2Body m_groundBody;
bool m_bIsDraw;
CCPoint m_startPt;
CCPoint m_endPoint;
bool m_bIsRayCast;
Segment laserSegment;
std::vector entryPoint;
std::vector<b2Body> affectedByLaser;
bool m_bSliceObject;
bool m_bIsDrawEnter;
b2Vec2 enterPoint;
void update(float dt);
};
HELLOWORLDSCENE.CPP
using namespace cocos2d;
PTM_RATIO 32
enum
{
kTagTileMap = 1,
kTagSpriteManager = 1,
kTagAnimation1 = 1,
};
HelloWorldScene::HelloWorldScene()
{
CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
bool doSleep = true;
world = new b2World(gravity);
world->SetAllowSleeping(doSleep);
world->SetContinuousPhysics(true);
m_debugDraw = new GLESDebugDraw( PTM_RATIO ); world->SetDebugDraw(m_debugDraw);
int flags = 0; flags += b2Draw::e_shapeBit; m_debugDraw->SetFlags(flags);
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = CC_CALLBACK_2(HelloWorldScene::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(HelloWorldScene::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(HelloWorldScene::onTouchEnded, this);
this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(screenSize.width/2/PTM_RATIO,
screenSize.height/2/PTM_RATIO); // bottom-left corner
m_groundBody = world->CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
groundBox.SetAsBox(screenSize.width/2/PTM_RATIO, 40 / PTM_RATIO, b2Vec2(0, -screenSize.height/2/PTM_RATIO), 0);
m_groundBody->CreateFixture(&groundBox, 0);
groundBox.SetAsBox(0, screenSize.height/2/PTM_RATIO, b2Vec2(-screenSize.width/2/PTM_RATIO, 0), 0);
m_groundBody->CreateFixture(&groundBox, 0);
groundBox.SetAsBox(0, screenSize.height/2/PTM_RATIO, b2Vec2(screenSize.width/2/PTM_RATIO, 0), 0);
m_groundBody->CreateFixture(&groundBox, 0);
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(80 / PTM_RATIO, 80 / PTM_RATIO);
b2Body *body = world->CreateBody(&bodyDef);
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(50 / PTM_RATIO, 50 / PTM_RATIO);
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
body->CreateFixture(&fixtureDef);
m_bIsDraw = false; laserSegment = NULL;
this->scheduleUpdate();
}
HelloWorldScene::~HelloWorldScene()
{
delete world;
world = NULL;
delete m_debugDraw;
m_debugDraw = NULL;
}
b2Vec2 HelloWorldScene::toBox2dPoint(cocos2d::CCPoint pt)
{
return b2Vec2(pt.x / PTM_RATIO, pt.y / PTM_RATIO);
}
CCPoint HelloWorldScene::toCocos2dPoint(b2Vec2 &pt)
{
return ccp(pt.x * PTM_RATIO, pt.y * PTM_RATIO);
}
void HelloWorldScene::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags)
{
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
world->DrawDebugData();
glClearColor(0.5, 0.5, 0.5, 0.5);
glColor4f(1, 0, 0, 1); if (m_bIsDraw) { ccDrawLine(m_startPt, m_endPoint); }
if (m_bIsDrawEnter) { b2Vec2 center = b2Vec2_zero; for (int i=0; i < entryPoint.size(); ++i) { b2Vec2 entryPt = entryPoint[i]; center += 0.5 * entryPt; CCPoint pt = ccp( entryPt.x * PTM_RATIO, entryPt.y * PTM_RATIO); ccDrawCircle(pt, 7.0f, 0, 40, false); }
if (entryPoint.size() == 2) { CCPoint pt = ccp( center.x * PTM_RATIO, center.y * PTM_RATIO); ccDrawCircle(pt, 7.0f, 0, 40, false); }
}
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
float32 HelloWorldScene::ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float32 fraction)
{
b2Body *affectedBody = fixture->GetBody();
if(m_groundBody == affectedBody){ return -1; } int fixtureIndex = -1; for (int index = 0; index < affectedByLaser.size(); ++index) { if (affectedBody == affectedByLaser[index]) { fixtureIndex = index; break; } } b2PolygonShape* affectedPolygon = (b2PolygonShape*)fixture->GetShape(); if (-1 == fixtureIndex) { affectedByLaser.push_back(affectedBody); entryPoint.push_back(point); }else{
b2Vec2 rayCenter = b2Vec2( (point.x + entryPoint[fixtureIndex].x) / 2.0f, (point.y + entryPoint[fixtureIndex].y) / 2.0f); float rayAngle = b2Atan2(entryPoint[fixtureIndex].y - point.y, entryPoint[fixtureIndex].x - point.x);
std::vector<b2Vec2> polyVertices; b2Transform xf = affectedBody->GetTransform(); int32 vertexCount = affectedPolygon->GetChildCount(); b2Assert(vertexCount <= b2_maxPolygonVertices); for (int32 i = 0; i < vertexCount; ++i) { b2Vec2 vertice = b2Mul(xf, affectedPolygon->m_vertices[i]); polyVertices.push_back(vertice); }
std::vector<b2Vec2> newPolyVertices1; std::vector<b2Vec2> newPolyVertices2; int currentPoly = 0; bool cutPlaced1 = false; bool cutPlaced2 = false;
for (int i=0; i<polyVertices.size(); i++) {
// b2Vec2 worldPoint = affectedBody->GetWorldPoint(polyVertices[i]);
b2Vec2 worldPoint = polyVertices[i];
float cutAngle = b2Atan2(worldPoint.y - rayCenter.y,
worldPoint.x - rayCenter.x) - rayAngle;
if (cutAngle < M_PI * -1) { cutAngle += 2 * M_PI; } if (cutAngle > 0 && cutAngle <= M_PI) { if (currentPoly==2) { cutPlaced1=true; newPolyVertices1.push_back(point); newPolyVertices1.push_back(entryPoint[fixtureIndex]); } newPolyVertices1.push_back(worldPoint); currentPoly=1; } else { if (currentPoly==1) { cutPlaced2=true; newPolyVertices2.push_back(entryPoint[fixtureIndex]); newPolyVertices2.push_back(point); } newPolyVertices2.push_back(worldPoint); currentPoly=2;
} } if (! cutPlaced1) { newPolyVertices1.push_back(point); newPolyVertices1.push_back(entryPoint[fixtureIndex]); } if (! cutPlaced2) { newPolyVertices2.push_back(entryPoint[fixtureIndex]); newPolyVertices2.push_back(point); }
this->createSlice(newPolyVertices1,newPolyVertices1.size()); this->createSlice(newPolyVertices2,newPolyVertices2.size()); world->DestroyBody(affectedBody);
}
return 1;
}
b2Vec2 HelloWorldScene::findCenter(std::vector& vertices, int count)
{
b2Vec2 c;
float area = 0.0f;
float p1x = 0.0f;
float p1y = 0.0f;
float inv3 = 1.0f / 3.0f;
for (int i=0; i < count; ++i) {
b2Vec2 p2 = vertices[i];
b2Vec2 p3 = (i + 1) < count ? vertices[i+1] : vertices[0];
float e1x = p2.x - p1x;
float e1y = p2.y - p1y;
float e2x = p3.x - p1x;
float e2y = p3.y - p1y;
float d = (e1x * e2y - e1y * e2x);
float triangleArea = 0.5f * d;
area += triangleArea;
c.x += triangleArea * inv3 * (p1x + p2.x + p3.x);
c.y += triangleArea * inv3 * (p1y + p2.y + p3.y);
}
c.x *= 1.0 / area;
c.y *= 1.0 / area;
return c;
}
void HelloWorldScene::createSlice(std::vector &vertices, int count)
{
b2Vec2 centre = this->findCenter(vertices, vertices.size());
// if ( centre.x < -50 || centre.x > 50 || centre.y > 50 || centre.y < -50 || centre.y != centre.y
// || count > b2_maxPolygonVertices) {
// return;
// }
for (int i=0; i< count; ++i) { vertices[i] -= centre; }
b2BodyDef sliceBody; sliceBody.position.Set(centre.x, centre.y); sliceBody.type = b2_dynamicBody; b2PolygonShape slicePoly; b2Vec2 arrVertices[b2_maxPolygonVertices]; std::copy(vertices.begin(), vertices.end(), arrVertices); slicePoly.Set(arrVertices, count); b2FixtureDef sliceFixture; sliceFixture.shape = &slicePoly; sliceFixture.density = 1; b2Body *pSliceBody = world->CreateBody(&sliceBody);
pSliceBody->CreateFixture(&sliceFixture); for (int i=0; i < count; ++i) { vertices[i] += centre; }
}
void HelloWorldScene::update(float dt)
{
int velocityIterations = 8;
int positionIterations = 1;
world->Step(dt, velocityIterations, positionIterations);
if (m_bIsRayCast && NULL != laserSegment && (laserSegment->p2 - laserSegment->p1).LengthSquared() > 0) {
entryPoint.clear(); affectedByLaser.clear(); world->RayCast(this, laserSegment->p1,laserSegment->p2); world->RayCast(this, laserSegment->p2,laserSegment->p1); delete laserSegment; laserSegment = NULL; }
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL) {
}
}
}
bool HelloWorldScene::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event){
m_bSliceObject = false;
laserSegment = new Segment; m_bIsRayCast = false; m_bIsDraw = false; m_bIsDrawEnter = false;
m_startPt = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView()); m_endPoint = m_startPt; laserSegment->p1 = b2Vec2(m_startPt.x / PTM_RATIO,m_startPt.y / PTM_RATIO);
return true;
}
void HelloWorldScene::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event){
m_endPoint = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());
m_bIsDraw = true;
}
void HelloWorldScene::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
m_endPoint = location;
laserSegment->p2 = b2Vec2(m_endPoint.x / PTM_RATIO, m_endPoint.y / PTM_RATIO);
m_bIsDraw = false; m_bIsRayCast = true;
}
Scene* HelloWorldScene::scene()
{
CCScene scene = CCScene::create();
CCLayer layer = new HelloWorldScene();
scene->addChild(layer);
layer->release();
return scene;
}