Add physics::Fixture

This commit is contained in:
Nomango 2019-10-22 16:49:34 +08:00
parent 765e4404b2
commit 2c4258c087
10 changed files with 374 additions and 94 deletions

View File

@ -12,6 +12,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\kiwano-physics\Body.h" />
<ClInclude Include="..\..\src\kiwano-physics\Fixture.h" />
<ClInclude Include="..\..\src\kiwano-physics\helper.h" />
<ClInclude Include="..\..\src\kiwano-physics\Joint.h" />
<ClInclude Include="..\..\src\kiwano-physics\kiwano-physics.h" />
@ -20,6 +21,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\kiwano-physics\Body.cpp" />
<ClCompile Include="..\..\src\kiwano-physics\Fixture.cpp" />
<ClCompile Include="..\..\src\kiwano-physics\Joint.cpp" />
<ClCompile Include="..\..\src\kiwano-physics\Shape.cpp" />
<ClCompile Include="..\..\src\kiwano-physics\World.cpp" />

View File

@ -7,11 +7,13 @@
<ClInclude Include="..\..\src\kiwano-physics\Joint.h" />
<ClInclude Include="..\..\src\kiwano-physics\Shape.h" />
<ClInclude Include="..\..\src\kiwano-physics\helper.h" />
<ClInclude Include="..\..\src\kiwano-physics\Fixture.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\kiwano-physics\Body.cpp" />
<ClCompile Include="..\..\src\kiwano-physics\World.cpp" />
<ClCompile Include="..\..\src\kiwano-physics\Joint.cpp" />
<ClCompile Include="..\..\src\kiwano-physics\Shape.cpp" />
<ClCompile Include="..\..\src\kiwano-physics\Fixture.cpp" />
</ItemGroup>
</Project>

View File

@ -25,8 +25,10 @@ namespace kiwano
{
namespace physics
{
Body::Body()
: body_(nullptr)
: ignore_rotation_(false)
, body_(nullptr)
, actor_(nullptr)
, world_(nullptr)
{
@ -50,6 +52,7 @@ namespace kiwano
SetB2Body(body);
}
SetActor(actor);
UpdateFromActor();
}
Body::~Body()
@ -60,54 +63,61 @@ namespace kiwano
}
}
b2Fixture* Body::AddShape(ShapePtr shape, Property const& prop)
Fixture Body::AddShape(Shape* shape, Fixture::Property const& prop)
{
KGE_ASSERT(body_ && world_);
KGE_ASSERT(shape);
if (shape)
{
shape->FitWorld(world_);
b2FixtureDef fd;
fd.density = prop.density;
fd.friction = prop.friction;
fd.restitution = prop.restitution;
fd.shape = shape->GetB2Shape();
return body_->CreateFixture(&fd);
return Fixture(this, shape, prop);
}
return nullptr;
return Fixture();
}
b2Fixture* Body::AddCircleShape(float radius, Property const& prop)
Fixture Body::AddCircleShape(float radius, Fixture::Property const& prop)
{
ShapePtr shape = new CircleShape(radius);
return AddShape(shape, prop);
return AddShape(&CircleShape(radius), prop);
}
b2Fixture* Body::AddBoxShape(Vec2 const& size, Property const& prop)
Fixture Body::AddBoxShape(Vec2 const& size, Fixture::Property const& prop)
{
ShapePtr shape = new BoxShape(size);
return AddShape(shape, prop);
return AddShape(&BoxShape(size), prop);
}
b2Fixture* Body::AddPolygonShape(Vector<Point> const& vertexs, Property const& prop)
Fixture Body::AddPolygonShape(Vector<Point> const& vertexs, Fixture::Property const& prop)
{
ShapePtr shape = new PolygonShape(vertexs);
return AddShape(shape, prop);
return AddShape(&PolygonShape(vertexs), prop);
}
Body::Type Body::GetType() const
Fixture Body::AddEdgeShape(Point const& p1, Point const& p2, Fixture::Property const& prop)
{
KGE_ASSERT(body_);
return Type(body_->GetType());
return AddShape(&EdgeShape(p1, p2), prop);
}
void Body::SetType(Type type)
Fixture Body::AddChainShape(Vector<Point> const& vertexs, bool loop, Fixture::Property const& prop)
{
KGE_ASSERT(body_);
body_->SetType(static_cast<b2BodyType>(type));
return AddShape(&ChainShape(vertexs, loop), prop);
}
void Body::RemoveFixture(Fixture const& fixture)
{
if (fixture.GetB2Fixture())
{
b2Fixture* ptr = const_cast<b2Fixture*>(fixture.GetB2Fixture());
body_->DestroyFixture(ptr);
}
}
Point Body::GetLocalPoint(Point const& world) const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetLocalPoint(world_->Stage2World(world)));
}
Point Body::GetWorldPoint(Point const& local) const
{
KGE_ASSERT(body_ && world_);
return world_->World2Stage(body_->GetWorldPoint(world_->Stage2World(local)));
}
void Body::SetB2Body(b2Body* body)
@ -131,7 +141,11 @@ namespace kiwano
{
actor_->SetPosition(World2Stage(body_->GetPosition()));
}
actor_->SetRotation(math::Radian2Angle(body_->GetAngle()));
if (!ignore_rotation_)
{
actor_->SetRotation(math::Radian2Angle(body_->GetAngle()));
}
}
}
@ -139,22 +153,24 @@ namespace kiwano
{
if (actor_ && body_)
{
float rotation = ignore_rotation_ ? body_->GetAngle() : math::Angle2Radian(actor_->GetRotation());
if (world_)
{
body_->SetTransform(
world_->Stage2World(actor_->GetPosition()),
math::Angle2Radian(actor_->GetRotation())
rotation
);
}
else
{
body_->SetTransform(
Stage2World(actor_->GetPosition()),
math::Angle2Radian(actor_->GetRotation())
rotation
);
}
}
}
}
}
}

View File

@ -21,6 +21,7 @@
#pragma once
#include <kiwano-physics/helper.h>
#include <kiwano-physics/Shape.h>
#include <kiwano-physics/Fixture.h>
namespace kiwano
{
@ -40,54 +41,52 @@ namespace kiwano
Dynamic,
};
struct Property
{
float density; // ÃÜ¶È kg/m^2
float friction; // Ħ²ÁϵÊý [0,1]
float restitution; // µ¯ÐÔ [0,1]
Property()
: density(0.f)
, friction(0.2f)
, restitution(0.f)
{
}
Property(float density, float friction, float restitution)
: density(density)
, friction(friction)
, restitution(restitution)
{
}
};
Body();
Body(b2Body* body, Actor* actor);
Body(World* world, Actor* actor);
virtual ~Body();
b2Fixture* AddShape(ShapePtr shape, Property const& prop);
b2Fixture* AddCircleShape(float radius, Property const& prop = Property());
b2Fixture* AddBoxShape(Vec2 const& size, Property const& prop = Property());
b2Fixture* AddPolygonShape(Vector<Point> const& vertexs, Property const& prop = Property());
// 警속近榴
Fixture AddShape(Shape* shape, Fixture::Property const& prop = Fixture::Property());
Fixture AddCircleShape(float radius, Fixture::Property const& prop = Fixture::Property());
Fixture AddBoxShape(Vec2 const& size, Fixture::Property const& prop = Fixture::Property());
Fixture AddPolygonShape(Vector<Point> const& vertexs, Fixture::Property const& prop = Fixture::Property());
Fixture AddEdgeShape(Point const& p1, Point const& p2, Fixture::Property const& prop = Fixture::Property());
Fixture AddChainShape(Vector<Point> const& vertexs, bool loop = false, Fixture::Property const& prop = Fixture::Property());
Type GetType() const;
void SetType(Type type);
// 삿혤셸야죗깊
Fixture GetFixture() const { KGE_ASSERT(body_); Fixture(body_->GetFixtureList()); }
Actor* GetActor() const { return actor_; }
void SetActor(Actor* actor) { actor_ = actor; }
// 盧뇜셸야
void RemoveFixture(Fixture const& fixture);
b2Body* GetB2Body() { return body_; }
const b2Body* GetB2Body() const { return body_; }
// 삿혤醴좆
float GetMass() const { KGE_ASSERT(body_); return body_->GetMass(); }
Point GetLocalPoint(Point const& world) const;
Point GetWorldPoint(Point const& local) const;
Type GetType() const { KGE_ASSERT(body_); return Type(body_->GetType()); }
void SetType(Type type) { KGE_ASSERT(body_); body_->SetType(static_cast<b2BodyType>(type)); }
bool IsIgnoreRotation() const { return ignore_rotation_; }
void SetIgnoreRotation(bool ignore_rotation) { ignore_rotation_ = ignore_rotation; }
Actor* GetActor() const { return actor_; }
void SetActor(Actor* actor) { actor_ = actor; }
b2Body* GetB2Body() { return body_; }
const b2Body* GetB2Body() const { return body_; }
void SetB2Body(b2Body* body);
World* GetWorld() { return world_; }
const World* GetWorld() const { return world_; }
World* GetWorld() { return world_; }
const World* GetWorld() const { return world_; }
void UpdateActor();
void UpdateFromActor();
protected:
bool ignore_rotation_;
Actor* actor_;
World* world_;
b2Body* body_;

View File

@ -0,0 +1,73 @@
// Copyright (c) 2018-2019 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <kiwano-physics/Fixture.h>
#include <kiwano-physics/Body.h>
#include <kiwano-physics/World.h>
namespace kiwano
{
namespace physics
{
Fixture::Fixture()
: fixture_(nullptr)
{
}
Fixture::Fixture(b2Fixture* fixture)
: Fixture()
{
SetB2Fixture(fixture);
}
Fixture::Fixture(Body* body, Shape* shape, Property const& prop)
: Fixture()
{
KGE_ASSERT(body);
if (shape)
{
shape->FitWorld(body->GetWorld());
b2Body* b2body = body->GetB2Body();
b2FixtureDef fd;
fd.density = prop.density;
fd.friction = prop.friction;
fd.restitution = prop.restitution;
fd.shape = shape->GetB2Shape();
fixture_ = b2body->CreateFixture(&fd);
}
}
Shape Fixture::GetShape() const
{
KGE_ASSERT(fixture_);
return Shape(fixture_->GetShape());
}
Fixture Fixture::GetNext() const
{
KGE_ASSERT(fixture_);
return Fixture(fixture_->GetNext());
}
}
}

View File

@ -0,0 +1,71 @@
// Copyright (c) 2018-2019 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <kiwano-physics/helper.h>
#include <kiwano-physics/Shape.h>
namespace kiwano
{
namespace physics
{
class Body;
// ¼Ð¾ß
class Fixture
{
public:
struct Property
{
float density; // ÃÜ¶È kg/m^2
float friction; // Ħ²ÁϵÊý [0,1]
float restitution; // µ¯ÐÔ [0,1]
Property()
: density(0.f)
, friction(0.2f)
, restitution(0.f)
{
}
Property(float density, float friction, float restitution)
: density(density)
, friction(friction)
, restitution(restitution)
{
}
};
Fixture();
Fixture(b2Fixture* fixture);
Fixture(Body* body, Shape* shape, Property const& prop);
Shape GetShape() const;
Fixture GetNext() const;
b2Fixture* GetB2Fixture() { return fixture_; }
const b2Fixture* GetB2Fixture() const { return fixture_; }
void SetB2Fixture(b2Fixture* fixture) { fixture_ = fixture; }
protected:
b2Fixture* fixture_;
};
}
}

View File

@ -25,6 +25,10 @@ namespace kiwano
{
namespace physics
{
//
// Joint
//
Joint::Joint()
: joint_(nullptr)
, world_(nullptr)

View File

@ -61,21 +61,23 @@ namespace kiwano
{
}
CircleShape::CircleShape(float radius)
CircleShape::CircleShape(float radius, Point const& offset)
: CircleShape()
{
Set(radius);
Set(radius, offset);
}
void CircleShape::Set(float radius)
void CircleShape::Set(float radius, Point const& offset)
{
radius_ = radius;
offset_ = offset;
}
void CircleShape::FitWorld(World* world)
{
KGE_ASSERT(world);
circle_.m_radius = world->Stage2World(radius_);
circle_.m_p = world->Stage2World(offset_);
}
//
@ -85,18 +87,21 @@ namespace kiwano
BoxShape::BoxShape()
: Shape(&polygon_)
, polygon_()
, rotation_(0.f)
{
}
BoxShape::BoxShape(Vec2 const& size)
BoxShape::BoxShape(Vec2 const& size, Point const& offset, float rotation)
: BoxShape()
{
Set(size);
Set(size, offset, rotation);
}
void BoxShape::Set(Vec2 const& size)
void BoxShape::Set(Vec2 const& size, Point const& offset, float rotation)
{
box_size_ = size;
offset_ = offset;
rotation_ = rotation;
}
void BoxShape::FitWorld(World* world)
@ -104,7 +109,8 @@ namespace kiwano
KGE_ASSERT(world);
b2Vec2 box = world->Stage2World(box_size_);
polygon_.SetAsBox(box.x / 2, box.y / 2);
b2Vec2 offset = world->Stage2World(offset_);
polygon_.SetAsBox(box.x / 2, box.y / 2, offset, rotation_);
}
//
@ -142,5 +148,80 @@ namespace kiwano
polygon_.Set(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
}
//
// EdgeShape
//
EdgeShape::EdgeShape()
: Shape(&edge_)
, edge_()
{
}
EdgeShape::EdgeShape(Point const& p1, Point const& p2)
: EdgeShape()
{
Set(p1, p2);
}
void EdgeShape::Set(Point const& p1, Point const& p2)
{
p_[0] = p1;
p_[1] = p2;
}
void EdgeShape::FitWorld(World* world)
{
KGE_ASSERT(world);
b2Vec2 p1 = world->Stage2World(p_[0]);
b2Vec2 p2 = world->Stage2World(p_[1]);
edge_.Set(p1, p2);
}
//
// ChainShape
//
ChainShape::ChainShape()
: Shape(&chain_)
, chain_()
, loop_(false)
{
}
ChainShape::ChainShape(Vector<Point> const& vertexs, bool loop)
: ChainShape()
{
Set(vertexs, loop);
}
void ChainShape::Set(Vector<Point> const& vertexs, bool loop)
{
vertexs_ = vertexs;
loop_ = loop;
}
void ChainShape::FitWorld(World* world)
{
KGE_ASSERT(world);
Vector<b2Vec2> b2vertexs;
b2vertexs.reserve(vertexs_.size());
for (const auto& v : vertexs_)
{
b2vertexs.push_back(world->Stage2World(v));
}
if (loop_)
{
chain_.CreateLoop(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
else
{
chain_.CreateChain(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
}
}
}
}

View File

@ -27,25 +27,18 @@ namespace kiwano
{
class World;
KGE_DECLARE_SMART_PTR(Shape);
KGE_DECLARE_SMART_PTR(CircleShape);
KGE_DECLARE_SMART_PTR(BoxShape);
KGE_DECLARE_SMART_PTR(PolygonShape);
// ÐÎ×´»ùÀà
class KGE_API Shape
: public ObjectBase
{
public:
Shape();
Shape(b2Shape* shape);
b2Shape* GetB2Shape();
const b2Shape* GetB2Shape() const;
void SetB2Shape(b2Shape* shape);
virtual void FitWorld(World* world) = 0;
virtual void FitWorld(World* world) {}
protected:
b2Shape* shape_;
@ -58,14 +51,15 @@ namespace kiwano
public:
CircleShape();
CircleShape(float radius);
CircleShape(float radius, Point const& offset = Point());
void Set(float radius);
void Set(float radius, Point const& offset = Point());
void FitWorld(World* world) override;
protected:
float radius_;
Point offset_;
b2CircleShape circle_;
};
@ -76,14 +70,16 @@ namespace kiwano
public:
BoxShape();
BoxShape(Vec2 const& size);
BoxShape(Vec2 const& size, Point const& offset = Point(), float rotation = 0.f);
void Set(Vec2 const& size);
void Set(Vec2 const& size, Point const& offset = Point(), float rotation = 0.f);
void FitWorld(World* world) override;
protected:
float rotation_;
Vec2 box_size_;
Point offset_;
b2PolygonShape polygon_;
};
@ -104,5 +100,42 @@ namespace kiwano
Vector<Point> vertexs_;
b2PolygonShape polygon_;
};
// 线段形状, 用于表示一条边
class KGE_API EdgeShape
: public Shape
{
public:
EdgeShape();
EdgeShape(Point const& p1, Point const& p2);
void Set(Point const& p1, Point const& p2);
void FitWorld(World* world) override;
protected:
Point p_[2];
b2EdgeShape edge_;
};
// 链式形状
class KGE_API ChainShape
: public Shape
{
public:
ChainShape();
ChainShape(Vector<Point> const& vertexs, bool loop = false);
void Set(Vector<Point> const& vertexs, bool loop = false);
void FitWorld(World* world) override;
protected:
bool loop_;
Vector<Point> vertexs_;
b2ChainShape chain_;
};
}
}

View File

@ -56,7 +56,6 @@ namespace kiwano
BodyPtr World::CreateBody(Actor* actor)
{
BodyPtr body = new Body(this, actor);
body->UpdateFromActor();
bodies_.push_back(body.get());
return body;
}
@ -76,11 +75,11 @@ namespace kiwano
if (iter != bodies_.end())
{
bodies_.erase(iter);
}
if (body->GetB2Body())
{
world_.DestroyBody(body->GetB2Body());
}
if (body->GetB2Body())
{
world_.DestroyBody(body->GetB2Body());
}
}
}
@ -108,11 +107,11 @@ namespace kiwano
if (iter != joints_.end())
{
joints_.erase(iter);
}
if (joint->GetB2Joint())
{
world_.DestroyJoint(joint->GetB2Joint());
}
if (joint->GetB2Joint())
{
world_.DestroyJoint(joint->GetB2Joint());
}
}
}