/** 创建多边形物体 */ private void createBody() { // 定义物体的形状是多边形形状 PolygonShape shape = new PolygonShape(); shape.set(vecs, edge); // 设置多边形物体的一些固定的物理属性 FixtureDef fd = new FixtureDef(); fd.shape = shape; // 固定设置参数 fd.density = 5.0f; // 密度 fd.friction = 0.3f; // 摩擦系数 fd.restitution = restitution; // 恢复系数 BodyDef bd = new BodyDef(); bd.position.set(x, y); bd.type = BodyType.DYNAMIC; bd.angle = angle; bd.allowSleep = true; bd.setAwake(true); // 根据bodyDef创建物体到世界中 body = world.createBody(bd); // 设置好物体的固定属性 body.createFixture(fd); }
@Test public void testIsWoundCorrectly() { PolygonShape shape = new PolygonShape(); Vec2 lineVertices[] = new Vec2[] {new Vec2(-1.0f, -1.0f), new Vec2(1.0f, 1.0f)}; shape.set(lineVertices, lineVertices.length); assertFalse(GeometryVerifier.IsWoundCorrectly(shape)); Vec2 boxVertices[] = new Vec2[] { new Vec2(0.25f, 0.25f), new Vec2(-0.25f, 0.25f), new Vec2(-0.25f, -0.25f), new Vec2(0.25f, -0.25f) }; shape.set(boxVertices, boxVertices.length); assertTrue(GeometryVerifier.IsWoundCorrectly(shape)); Vec2 miswoundBoxVertices[] = new Vec2[] { new Vec2(0.25f, -0.25f), new Vec2(-0.25f, -0.25f), new Vec2(-0.25f, 0.25f), new Vec2(0.25f, 0.25f) }; shape.set(miswoundBoxVertices, miswoundBoxVertices.length); assertFalse(GeometryVerifier.IsWoundCorrectly(shape)); Vec2 potatoVertices[] = new Vec2[] { new Vec2(4.0f, 4.0f), new Vec2(5.0f, 3.0f), new Vec2(4.0f, 1.0f), new Vec2(2.0f, 2.0f), new Vec2(3.0f, 3.0f), new Vec2(2.0f, 5.0f) }; shape.set(potatoVertices, potatoVertices.length); assertFalse(GeometryVerifier.IsWoundCorrectly(shape)); }
/** * Create a convex hull from the given array of points. The count must be in the range [3, * Settings.maxPolygonVertices]. * * @warning the points may be re-ordered, even if they form a convex polygon * @warning collinear points are handled but not removed. Collinear points may lead to poor * stacking behavior. */ public final void set(final Vec2[] vertices, final int count) { set(vertices, count, null, null); }
/** * Rozbije objekt. Upravi objekt world tak, ze vymaze triesteny objekt a nahradi ho fragmentami na * zaklade nastaveneho materialu a clenskych premennych. * * @param dt casova dlzka framu */ public void smash(float dt) { if (contact == null) { // riesi sa staticky prvok, ktory ma priliz maly obsah b1.setType(BodyType.DYNAMIC); return; } World w = b1.m_world; Shape s = f1.m_shape; Polygon p = f1.m_polygon; if (p == null) { switch (s.m_type) { case POLYGON: PolygonShape ps = (PolygonShape) s; Vec2[] vertices = ps.m_vertices; p = new Polygon(); for (int i = 0; i < ps.m_count; ++i) { p.add(vertices[ps.m_count - i - 1]); } break; case CIRCLE: CircleShape cs = (CircleShape) s; p = new Polygon(); float radius = cs.m_radius; double u = Math.PI * 2 / CIRCLEVERTICES; radius = (float) Math.sqrt(u / Math.sin(u)) * radius; // upravim radius tak, aby bola zachovana velkost obsahu Vec2 center = cs.m_p; for (int i = 0; i < CIRCLEVERTICES; ++i) { double j = u * i; // uhol float sin = (float) Math.sin(j); float cos = (float) Math.cos(j); Vec2 v = new Vec2(sin, cos).mulLocal(radius).addLocal(center); p.add(v); } break; default: throw new RuntimeException("Dany typ tvaru nepodporuje stiepenie"); } } float mConst = f1.m_material.m_rigidity / normalImpulse; // sila v zavislosti na pevnosti telesa boolean fixA = f1 == contact.m_fixtureA; // true, ak f2 je v objekte contact ako m_fixtureA float oldAngularVelocity = fixA ? contact.m_angularVelocity_bodyA : contact.m_angularVelocity_bodyB; Vec2 oldLinearVelocity = fixA ? contact.m_linearVelocity_bodyA : contact.m_linearVelocity_bodyB; b1.setAngularVelocity( (b1.m_angularVelocity - oldAngularVelocity) * mConst + oldAngularVelocity); b1.setLinearVelocity( b1.m_linearVelocity.sub(oldLinearVelocity).mulLocal(mConst).addLocal(oldLinearVelocity)); if (!w.isFractured(f2) && b2.m_type == BodyType.DYNAMIC && !b2.m_fractureTransformUpdate) { // ak sa druhy objekt nerozbija, tak sa jej nahodia // povodne hodnoty (TREBA MODIFIKOVAT POHYB OBJEKTU, // KTORY SPOSOBUJE ROZPAD) oldAngularVelocity = !fixA ? contact.m_angularVelocity_bodyA : contact.m_angularVelocity_bodyB; oldLinearVelocity = !fixA ? contact.m_linearVelocity_bodyA : contact.m_linearVelocity_bodyB; b2.setAngularVelocity( (b2.m_angularVelocity - oldAngularVelocity) * mConst + oldAngularVelocity); b2.setLinearVelocity( b2.m_linearVelocity.sub(oldLinearVelocity).mulLocal(mConst).addLocal(oldLinearVelocity)); b2.setTransform( b2.m_xf0.p.add(b2.m_linearVelocity.mul(dt)), b2.m_xf0.q.getAngle()); // osetruje jbox2d od posuvania telesa pri rieseni kolizie b2.m_fractureTransformUpdate = true; } Vec2 localPoint = Transform.mulTrans(b1.m_xf, point); Vec2 b1Vec = b1.getLinearVelocityFromWorldPoint(point); Vec2 b2Vec = b2.getLinearVelocityFromWorldPoint(point); Vec2 localVector = b2Vec.subLocal(b1Vec); localVector.mulLocal(dt); Polygon[] fragment; try { fragment = m.split(p, localPoint, localVector, normalImpulse); // rodeli to } catch (RuntimeException ex) { return; } if (fragment.length == 1) { // nerozbilo to na ziadne fragmenty return; } // definuje tela fragmentov - tie maju vsetky rovnaku definiciu (preberaju parametre z povodneho // objektu) BodyDef bodyDef = new BodyDef(); bodyDef.position.set(b1.m_xf.p); // pozicia bodyDef.angle = b1.m_xf.q.getAngle(); // otocenie bodyDef.fixedRotation = b1.isFixedRotation(); bodyDef.angularDamping = b1.m_angularDamping; bodyDef.allowSleep = b1.isSleepingAllowed(); FixtureDef fd = new FixtureDef(); fd.friction = f1.m_friction; // trenie fd.restitution = f1.m_restitution; // odrazivost fd.isSensor = f1.m_isSensor; fd.density = f1.m_density; // odstrani fragmentacne predmety/cele teleso ArrayList<Fixture> fixtures = new ArrayList<>(); if (f1.m_polygon != null) { for (Fixture f = b1.m_fixtureList; f != null; f = f.m_next) { if (f.m_polygon == f1.m_polygon) { fixtures.add(f); } } } else { fixtures.add(f1); } for (Fixture f : fixtures) { b1.destroyFixture(f); } if (b1.m_fixtureCount == 0) { w.destroyBody(b1); } // prida fragmenty do simulacie MyList<Body> newbodies = new MyList<>(); for (Polygon pg : fragment) { // vytvori tela, prida fixtury, poriesi konvexnu dekompoziciu if (pg.isCorrect()) { if (pg instanceof Fragment) { Polygon[] convex = pg.convexDecomposition(); bodyDef.type = BodyType.DYNAMIC; for (Polygon pgx : convex) { Body f_body = w.createBody(bodyDef); pgx.flip(); PolygonShape ps = new PolygonShape(); ps.set(pgx.getArray(), pgx.size()); fd.shape = ps; fd.polygon = null; fd.material = f1.m_material.m_fragments; // rekurzivne stiepenie f_body.createFixture(fd); f_body.setAngularVelocity(b1.m_angularVelocity); f_body.setLinearVelocity(b1.getLinearVelocityFromLocalPoint(f_body.getLocalCenter())); newbodies.add(f_body); } } else { fd.material = f1.m_material.m_fragments; // rekurzivne stiepenie bodyDef.type = b1.getType(); Body f_body = w.createBody(bodyDef); PolygonFixture pf = new PolygonFixture(pg); f_body.createFixture(pf, fd); f_body.setLinearVelocity(b1.getLinearVelocityFromLocalPoint(f_body.getLocalCenter())); f_body.setAngularVelocity(b1.m_angularVelocity); newbodies.add(f_body); } } } // zavola sa funkcia z fraction listeneru (pokial je nadefinovany) FractureListener fl = w.getContactManager().m_fractureListener; if (fl != null) { fl.action(m, normalImpulse, newbodies); } }