diff --git a/Benchmark/BenchmarkMain.cpp b/Benchmark/BenchmarkMain.cpp index 02372bc3f2..2a76996882 100644 --- a/Benchmark/BenchmarkMain.cpp +++ b/Benchmark/BenchmarkMain.cpp @@ -55,8 +55,8 @@ #include #include #include -#include -#include +#include +#include static float Rand(float lo, float hi) { @@ -1236,11 +1236,11 @@ static TransformationPairs GetTransformationPairs(unsigned count) static void MaxSepBetweenRelSquaresNoStop(benchmark::State& state) { const auto dim = playrho::Real(2) * playrho::Meter; - const auto shape0 = playrho::PolygonShape(dim, dim); - const auto shape1 = playrho::PolygonShape(dim, dim); + const auto shape0 = playrho::PolygonShapeConf(dim, dim); + const auto shape1 = playrho::PolygonShapeConf(dim, dim); - const auto child0 = shape0.GetChild(0); - const auto child1 = shape1.GetChild(0); + const auto child0 = GetChild(shape0, 0); + const auto child1 = GetChild(shape1, 0); const auto vals = GetTransformationPairs(static_cast(state.range())); for (auto _: state) @@ -1257,11 +1257,11 @@ static void MaxSepBetweenRelSquaresNoStop(benchmark::State& state) static void MaxSepBetweenRel4x4(benchmark::State& state) { const auto dim = playrho::Real(2) * playrho::Meter; - const auto shape0 = playrho::PolygonShape(dim, dim); - const auto shape1 = playrho::PolygonShape(dim, dim); + const auto shape0 = playrho::PolygonShapeConf(dim, dim); + const auto shape1 = playrho::PolygonShapeConf(dim, dim); - const auto child0 = shape0.GetChild(0); - const auto child1 = shape1.GetChild(0); + const auto child0 = GetChild(shape0, 0); + const auto child1 = GetChild(shape1, 0); const auto vals = GetTransformationPairs(static_cast(state.range())); for (auto _: state) @@ -1278,11 +1278,11 @@ static void MaxSepBetweenRel4x4(benchmark::State& state) static void MaxSepBetweenRelSquares(benchmark::State& state) { const auto dim = playrho::Real(2) * playrho::Meter; - const auto shape0 = playrho::PolygonShape(dim, dim); - const auto shape1 = playrho::PolygonShape(dim, dim); + const auto shape0 = playrho::PolygonShapeConf(dim, dim); + const auto shape1 = playrho::PolygonShapeConf(dim, dim); - const auto child0 = shape0.GetChild(0); - const auto child1 = shape1.GetChild(0); + const auto child0 = GetChild(shape0, 0); + const auto child1 = GetChild(shape1, 0); const auto totalRadius = child0.GetVertexRadius() + child1.GetVertexRadius(); const auto vals = GetTransformationPairs(static_cast(state.range())); @@ -1305,8 +1305,8 @@ static void MaxSepBetweenAbsSquares(benchmark::State& state) const auto xfm1 = playrho::Transformation{playrho::Vec2{0, +2} * (playrho::Real(1) * playrho::Meter), playrho::UnitVec2::GetRight()}; // top const auto dim = playrho::Real(2) * playrho::Meter; - const auto shape0 = playrho::PolygonShape{dim, dim}.Transform(xfm0); - const auto shape1 = playrho::PolygonShape{dim, dim}.Transform(xfm1); + const auto shape0 = playrho::PolygonShapeConf{dim, dim}.Transform(xfm0); + const auto shape1 = playrho::PolygonShapeConf{dim, dim}.Transform(xfm1); // Rotate square A and put it below square B. // In ASCII art terms: @@ -1329,8 +1329,8 @@ static void MaxSepBetweenAbsSquares(benchmark::State& state) // \4/ // + - const auto child0 = shape0.GetChild(0); - const auto child1 = shape1.GetChild(0); + const auto child0 = GetChild(shape0, 0); + const auto child1 = GetChild(shape1, 0); const auto totalRadius = child0.GetVertexRadius() + child1.GetVertexRadius(); for (auto _: state) @@ -1345,7 +1345,7 @@ static void ManifoldForTwoSquares1(benchmark::State& state) const auto dim = playrho::Real(2) * playrho::Meter; // creates a square - const auto shape = playrho::PolygonShape(dim, dim); + const auto shape = playrho::PolygonShapeConf(dim, dim); const auto rot0 = playrho::Angle{playrho::Real{45.0f} * playrho::Degree}; const auto xfm0 = playrho::Transformation{playrho::Vec2{0, -2} * (playrho::Real(1) * playrho::Meter), playrho::UnitVec2::Get(rot0)}; // bottom @@ -1374,18 +1374,18 @@ static void ManifoldForTwoSquares1(benchmark::State& state) for (auto _: state) { - // CollideShapes(shape.GetChild(0), xfm0, shape.GetChild(0), xfm1); - benchmark::DoNotOptimize(playrho::CollideShapes(shape.GetChild(0), xfm0, shape.GetChild(0), xfm1)); + // CollideShapes(GetChild(shape, 0), xfm0, GetChild(shape, 0), xfm1); + benchmark::DoNotOptimize(playrho::CollideShapes(GetChild(shape, 0), xfm0, GetChild(shape, 0), xfm1)); } } static void ManifoldForTwoSquares2(benchmark::State& state) { // Shape A: square - const auto shape0 = playrho::PolygonShape(playrho::Real{2} * playrho::Meter, playrho::Real{2} * playrho::Meter); + const auto shape0 = playrho::PolygonShapeConf(playrho::Real{2} * playrho::Meter, playrho::Real{2} * playrho::Meter); // Shape B: wide rectangle - const auto shape1 = playrho::PolygonShape(playrho::Real{3} * playrho::Meter, playrho::Real{1.5f} * playrho::Meter); + const auto shape1 = playrho::PolygonShapeConf(playrho::Real{3} * playrho::Meter, playrho::Real{1.5f} * playrho::Meter); const auto xfm0 = playrho::Transformation{ playrho::Vec2{-2, 0} * (playrho::Real(1) * playrho::Meter), @@ -1411,8 +1411,8 @@ static void ManifoldForTwoSquares2(benchmark::State& state) // for (auto _: state) { - //CollideShapes(shape0.GetChild(0), xfm0, shape1.GetChild(0), xfm1); - benchmark::DoNotOptimize(CollideShapes(shape0.GetChild(0), xfm0, shape1.GetChild(0), xfm1)); + //CollideShapes(GetChild(shape0, 0), xfm0, GetChild(shape1, 0), xfm1); + benchmark::DoNotOptimize(CollideShapes(GetChild(shape0, 0), xfm0, GetChild(shape1, 0), xfm1)); } } @@ -1585,8 +1585,8 @@ static void DropDisks(benchmark::State& state) auto world = playrho::World{playrho::WorldDef{}.UseGravity(playrho::EarthlyGravity2D)}; const auto diskRadius = 0.5f * playrho::Meter; - const auto diskDef = playrho::DiskShape::Conf{}.UseVertexRadius(diskRadius); - const auto shape = std::make_shared(diskDef); + const auto diskDef = playrho::DiskShapeConf{}.UseRadius(diskRadius); + const auto shape = playrho::Shape{diskDef}; const auto numDisks = state.range(); for (auto i = decltype(numDisks){0}; i < numDisks; ++i) { @@ -1607,13 +1607,15 @@ static void DropDisks(benchmark::State& state) static void AddPairStressTest(benchmark::State& state, int count) { - const auto diskConf = playrho::DiskShape::Conf{} - .UseVertexRadius(playrho::Meter / 10) + const auto diskConf = playrho::DiskShapeConf{} + .UseRadius(playrho::Meter / 10) .UseDensity(0.01f * playrho::KilogramPerSquareMeter); - const auto diskShape = std::make_shared(diskConf); + const auto diskShape = playrho::Shape{diskConf}; - const auto polygonConf = playrho::PolygonShape::Conf{}.UseDensity(1.0f * playrho::KilogramPerSquareMeter); - const auto rectShape = std::make_shared(1.5f * playrho::Meter, 1.5f * playrho::Meter, polygonConf); + const auto rectShape = playrho::Shape{ + playrho::PolygonShapeConf{}.UseDensity(1.0f * playrho::KilogramPerSquareMeter) + .SetAsBox(1.5f * playrho::Meter, 1.5f * playrho::Meter) + }; const auto rectBodyDef = playrho::BodyDef{} .UseType(playrho::BodyType::Dynamic) @@ -1662,7 +1664,7 @@ static void DropTiles(int count) const auto linearSlop = playrho::Meter / 1000; const auto angularSlop = (playrho::Pi * 2 * playrho::Radian) / 180; const auto vertexRadius = linearSlop * 2; - auto conf = playrho::PolygonShape::Conf{}.UseVertexRadius(vertexRadius); + auto conf = playrho::PolygonShapeConf{}.UseVertexRadius(vertexRadius); auto m_world = playrho::World{ playrho::WorldDef{}.UseMinVertexRadius(vertexRadius).UseInitialTreeSize(8192) }; @@ -1681,7 +1683,7 @@ static void DropTiles(int count) for (auto i = 0; i < N; ++i) { conf.SetAsBox(a * playrho::Meter, a * playrho::Meter, position, playrho::Angle{0}); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(conf); GetX(position) += 2.0f * a * playrho::Meter; } GetY(position) -= 2.0f * a * playrho::Meter; @@ -1691,8 +1693,8 @@ static void DropTiles(int count) { const auto a = playrho::Real{0.5f}; conf.SetAsBox(a * playrho::Meter, a * playrho::Meter); - conf.SetDensity(playrho::Real{5} * playrho::KilogramPerSquareMeter); - const auto shape = std::make_shared(conf); + conf.UseDensity(playrho::Real{5} * playrho::KilogramPerSquareMeter); + const auto shape = playrho::Shape(conf); playrho::Length2 x(playrho::Real(-7.0f) * playrho::Meter, playrho::Real(0.75f) * playrho::Meter); playrho::Length2 y; @@ -1759,8 +1761,7 @@ class Tumbler playrho::World m_world; playrho::StepConf m_stepConf; playrho::Length m_squareLen = 0.125f * playrho::Meter; - std::shared_ptr m_square = - std::make_shared(m_squareLen, m_squareLen); + playrho::Shape m_square = playrho::PolygonShapeConf(m_squareLen, m_squareLen); }; Tumbler::Tumbler() @@ -1775,16 +1776,16 @@ playrho::Body* Tumbler::CreateEnclosure(playrho::World& world) const auto b = world.CreateBody(playrho::BodyDef{}.UseType(playrho::BodyType::Dynamic) .UseLocation(playrho::Vec2(0, 10) * playrho::Meter) .UseAllowSleep(false)); - playrho::PolygonShape::Conf shape; - shape.SetDensity(5 * playrho::KilogramPerSquareMeter); + playrho::PolygonShapeConf shape; + shape.UseDensity(5 * playrho::KilogramPerSquareMeter); shape.SetAsBox(0.5f * playrho::Meter, 10.0f * playrho::Meter, playrho::Vec2( 10.0f, 0.0f) * playrho::Meter, playrho::Angle{0}); - b->CreateFixture(std::make_shared(shape)); + b->CreateFixture(shape); shape.SetAsBox(0.5f * playrho::Meter, 10.0f * playrho::Meter, playrho::Vec2(-10.0f, 0.0f) * playrho::Meter, playrho::Angle{0}); - b->CreateFixture(std::make_shared(shape)); + b->CreateFixture(shape); shape.SetAsBox(10.0f * playrho::Meter, 0.5f * playrho::Meter, playrho::Vec2(0.0f, 10.0f) * playrho::Meter, playrho::Angle{0}); - b->CreateFixture(std::make_shared(shape)); + b->CreateFixture(shape); shape.SetAsBox(10.0f * playrho::Meter, 0.5f * playrho::Meter, playrho::Vec2(0.0f, -10.0f) * playrho::Meter, playrho::Angle{0}); - b->CreateFixture(std::make_shared(shape)); + b->CreateFixture(shape); return b; } diff --git a/Build/xcode5/PlayRho.xcodeproj/project.pbxproj b/Build/xcode5/PlayRho.xcodeproj/project.pbxproj index f445515563..1a8e424407 100644 --- a/Build/xcode5/PlayRho.xcodeproj/project.pbxproj +++ b/Build/xcode5/PlayRho.xcodeproj/project.pbxproj @@ -83,8 +83,8 @@ 473E01A01F81705100D58CC8 /* Vector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 473E019F1F81705100D58CC8 /* Vector.cpp */; }; 47440F0D1EDA365400AB3F51 /* WorldDef.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 47440F0A1EDA365400AB3F51 /* WorldDef.hpp */; }; 474AFBF51EB19BB6002AA6C8 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 474AFBF41EB19BB6002AA6C8 /* CoreVideo.framework */; }; - 474AFBF81EB1B2CB002AA6C8 /* MultiShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 474AFBF61EB1B2CB002AA6C8 /* MultiShape.cpp */; }; - 474AFBFA1EB1B2CB002AA6C8 /* MultiShape.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 474AFBF71EB1B2CB002AA6C8 /* MultiShape.hpp */; }; + 474AFBF81EB1B2CB002AA6C8 /* MultiShapeConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 474AFBF61EB1B2CB002AA6C8 /* MultiShapeConf.cpp */; }; + 474AFBFA1EB1B2CB002AA6C8 /* MultiShapeConf.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 474AFBF71EB1B2CB002AA6C8 /* MultiShapeConf.hpp */; }; 474AFC001EBA40FA002AA6C8 /* TestEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 474AFBFF1EBA40FA002AA6C8 /* TestEntry.cpp */; }; 474B67221E80466D00B6D126 /* functional.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 474B67211E80466D00B6D126 /* functional.cpp */; }; 474BAB2A1E5CBA010058E08A /* Velocity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 474BAB291E5CBA010058E08A /* Velocity.cpp */; }; @@ -136,7 +136,6 @@ 4768D3FD1E414A0100574143 /* Vector2.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4768D3FA1E414A0100574143 /* Vector2.hpp */; }; 4768D4001E54E7CC00574143 /* StepConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4768D3FF1E54E7CB00574143 /* StepConf.cpp */; }; 476E8ABE1FC8CD9F00705BB5 /* UnitVec2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 476E8ABD1FC8CD9F00705BB5 /* UnitVec2.cpp */; }; - 476E8AC31FCF926F00705BB5 /* FunctionalShapeVisitor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 476E8AC11FCF926F00705BB5 /* FunctionalShapeVisitor.hpp */; }; 476E8AC71FCFA0D400705BB5 /* FunctionalJointVisitor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 476E8AC51FCFA0D400705BB5 /* FunctionalJointVisitor.hpp */; }; 4775A9381E05B032001C2332 /* StepConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4775A9371E05B032001C2332 /* StepConf.cpp */; }; 47791F801F92DB0700E257AF /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 47791F7A1F92D78F00E257AF /* imgui_draw.cpp */; }; @@ -206,7 +205,6 @@ 47CF984B1DF9C4A30077F5F2 /* ShapeSeparation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 47CF98491DF9C4A30077F5F2 /* ShapeSeparation.cpp */; }; 47CF984D1DF9C4A30077F5F2 /* ShapeSeparation.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 47CF984A1DF9C4A30077F5F2 /* ShapeSeparation.hpp */; }; 47CF98501E0088ED0077F5F2 /* Angle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 47CF984F1E0088ED0077F5F2 /* Angle.cpp */; }; - 47D28D871F6DD9540094C032 /* ShapeVisitor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 47D28D851F6DD9540094C032 /* ShapeVisitor.hpp */; }; 47D28D8B1F6DEABF0094C032 /* JointVisitor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 47D28D891F6DEABF0094C032 /* JointVisitor.hpp */; }; 47D28D8E1F6E2C7C0094C032 /* JointType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 47D28D8C1F6E2C7C0094C032 /* JointType.cpp */; }; 47D28D8F1F6E2C7C0094C032 /* JointType.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 47D28D8D1F6E2C7C0094C032 /* JointType.hpp */; }; @@ -240,14 +238,14 @@ 80BB8992141C3E5900F1753A /* DynamicTree.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB8931141C3E5900F1753A /* DynamicTree.hpp */; }; 80BB8993141C3E5900F1753A /* TimeOfImpact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB8932141C3E5900F1753A /* TimeOfImpact.cpp */; }; 80BB8994141C3E5900F1753A /* TimeOfImpact.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB8933141C3E5900F1753A /* TimeOfImpact.hpp */; }; - 80BB8995141C3E5900F1753A /* ChainShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB8935141C3E5900F1753A /* ChainShape.cpp */; }; - 80BB8996141C3E5900F1753A /* ChainShape.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB8936141C3E5900F1753A /* ChainShape.hpp */; }; - 80BB8997141C3E5900F1753A /* DiskShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB8937141C3E5900F1753A /* DiskShape.cpp */; }; - 80BB8998141C3E5900F1753A /* DiskShape.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB8938141C3E5900F1753A /* DiskShape.hpp */; }; - 80BB8999141C3E5900F1753A /* EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB8939141C3E5900F1753A /* EdgeShape.cpp */; }; - 80BB899A141C3E5900F1753A /* EdgeShape.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB893A141C3E5900F1753A /* EdgeShape.hpp */; }; - 80BB899B141C3E5900F1753A /* PolygonShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB893B141C3E5900F1753A /* PolygonShape.cpp */; }; - 80BB899C141C3E5900F1753A /* PolygonShape.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB893C141C3E5900F1753A /* PolygonShape.hpp */; }; + 80BB8995141C3E5900F1753A /* ChainShapeConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB8935141C3E5900F1753A /* ChainShapeConf.cpp */; }; + 80BB8996141C3E5900F1753A /* ChainShapeConf.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB8936141C3E5900F1753A /* ChainShapeConf.hpp */; }; + 80BB8997141C3E5900F1753A /* DiskShapeConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB8937141C3E5900F1753A /* DiskShapeConf.cpp */; }; + 80BB8998141C3E5900F1753A /* DiskShapeConf.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB8938141C3E5900F1753A /* DiskShapeConf.hpp */; }; + 80BB8999141C3E5900F1753A /* EdgeShapeConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB8939141C3E5900F1753A /* EdgeShapeConf.cpp */; }; + 80BB899A141C3E5900F1753A /* EdgeShapeConf.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB893A141C3E5900F1753A /* EdgeShapeConf.hpp */; }; + 80BB899B141C3E5900F1753A /* PolygonShapeConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB893B141C3E5900F1753A /* PolygonShapeConf.cpp */; }; + 80BB899C141C3E5900F1753A /* PolygonShapeConf.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB893C141C3E5900F1753A /* PolygonShapeConf.hpp */; }; 80BB899D141C3E5900F1753A /* Shape.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB893D141C3E5900F1753A /* Shape.hpp */; }; 80BB899E141C3E5900F1753A /* BlockAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 80BB893F141C3E5900F1753A /* BlockAllocator.cpp */; }; 80BB899F141C3E5900F1753A /* BlockAllocator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 80BB8940141C3E5900F1753A /* BlockAllocator.hpp */; }; @@ -460,8 +458,8 @@ 474527391E8877DD002E28FB /* Orbiter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Orbiter.hpp; sourceTree = ""; }; 4745273F1E8AC88F002E28FB /* iforce2d_TopdownCar.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = iforce2d_TopdownCar.hpp; sourceTree = ""; }; 474AFBF41EB19BB6002AA6C8 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; - 474AFBF61EB1B2CB002AA6C8 /* MultiShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiShape.cpp; sourceTree = ""; }; - 474AFBF71EB1B2CB002AA6C8 /* MultiShape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MultiShape.hpp; sourceTree = ""; }; + 474AFBF61EB1B2CB002AA6C8 /* MultiShapeConf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiShapeConf.cpp; sourceTree = ""; }; + 474AFBF71EB1B2CB002AA6C8 /* MultiShapeConf.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MultiShapeConf.hpp; sourceTree = ""; }; 474AFBFD1EBA35A2002AA6C8 /* TestEntry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TestEntry.hpp; sourceTree = ""; }; 474AFBFF1EBA40FA002AA6C8 /* TestEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestEntry.cpp; sourceTree = ""; }; 474B67211E80466D00B6D126 /* functional.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = functional.cpp; sourceTree = ""; }; @@ -514,7 +512,6 @@ 4768D3FA1E414A0100574143 /* Vector2.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Vector2.hpp; sourceTree = ""; }; 4768D3FF1E54E7CB00574143 /* StepConf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StepConf.cpp; sourceTree = ""; }; 476E8ABD1FC8CD9F00705BB5 /* UnitVec2.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnitVec2.cpp; sourceTree = ""; }; - 476E8AC11FCF926F00705BB5 /* FunctionalShapeVisitor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = FunctionalShapeVisitor.hpp; sourceTree = ""; }; 476E8AC51FCFA0D400705BB5 /* FunctionalJointVisitor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = FunctionalJointVisitor.hpp; sourceTree = ""; }; 476E8AC91FD0FB1100705BB5 /* PlayRho.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = PlayRho.profdata; sourceTree = ""; }; 477329D61F9BEFA200C521B4 /* SolarSystem.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SolarSystem.hpp; sourceTree = ""; }; @@ -590,7 +587,6 @@ 47CF98491DF9C4A30077F5F2 /* ShapeSeparation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShapeSeparation.cpp; sourceTree = ""; }; 47CF984A1DF9C4A30077F5F2 /* ShapeSeparation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ShapeSeparation.hpp; sourceTree = ""; }; 47CF984F1E0088ED0077F5F2 /* Angle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Angle.cpp; sourceTree = ""; }; - 47D28D851F6DD9540094C032 /* ShapeVisitor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ShapeVisitor.hpp; sourceTree = ""; }; 47D28D891F6DEABF0094C032 /* JointVisitor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = JointVisitor.hpp; sourceTree = ""; }; 47D28D8C1F6E2C7C0094C032 /* JointType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JointType.cpp; sourceTree = ""; }; 47D28D8D1F6E2C7C0094C032 /* JointType.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = JointType.hpp; sourceTree = ""; }; @@ -633,14 +629,14 @@ 80BB8931141C3E5900F1753A /* DynamicTree.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DynamicTree.hpp; sourceTree = ""; }; 80BB8932141C3E5900F1753A /* TimeOfImpact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeOfImpact.cpp; sourceTree = ""; }; 80BB8933141C3E5900F1753A /* TimeOfImpact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimeOfImpact.hpp; sourceTree = ""; }; - 80BB8935141C3E5900F1753A /* ChainShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ChainShape.cpp; sourceTree = ""; }; - 80BB8936141C3E5900F1753A /* ChainShape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ChainShape.hpp; sourceTree = ""; }; - 80BB8937141C3E5900F1753A /* DiskShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskShape.cpp; sourceTree = ""; }; - 80BB8938141C3E5900F1753A /* DiskShape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskShape.hpp; sourceTree = ""; }; - 80BB8939141C3E5900F1753A /* EdgeShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EdgeShape.cpp; sourceTree = ""; }; - 80BB893A141C3E5900F1753A /* EdgeShape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EdgeShape.hpp; sourceTree = ""; }; - 80BB893B141C3E5900F1753A /* PolygonShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolygonShape.cpp; sourceTree = ""; }; - 80BB893C141C3E5900F1753A /* PolygonShape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PolygonShape.hpp; sourceTree = ""; }; + 80BB8935141C3E5900F1753A /* ChainShapeConf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ChainShapeConf.cpp; sourceTree = ""; }; + 80BB8936141C3E5900F1753A /* ChainShapeConf.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ChainShapeConf.hpp; sourceTree = ""; }; + 80BB8937141C3E5900F1753A /* DiskShapeConf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DiskShapeConf.cpp; sourceTree = ""; }; + 80BB8938141C3E5900F1753A /* DiskShapeConf.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskShapeConf.hpp; sourceTree = ""; }; + 80BB8939141C3E5900F1753A /* EdgeShapeConf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EdgeShapeConf.cpp; sourceTree = ""; }; + 80BB893A141C3E5900F1753A /* EdgeShapeConf.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EdgeShapeConf.hpp; sourceTree = ""; }; + 80BB893B141C3E5900F1753A /* PolygonShapeConf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolygonShapeConf.cpp; sourceTree = ""; }; + 80BB893C141C3E5900F1753A /* PolygonShapeConf.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PolygonShapeConf.hpp; sourceTree = ""; }; 80BB893D141C3E5900F1753A /* Shape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Shape.hpp; sourceTree = ""; }; 80BB893F141C3E5900F1753A /* BlockAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockAllocator.cpp; sourceTree = ""; }; 80BB8940141C3E5900F1753A /* BlockAllocator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = BlockAllocator.hpp; sourceTree = ""; }; @@ -947,21 +943,19 @@ 80BB8934141C3E5900F1753A /* Shapes */ = { isa = PBXGroup; children = ( - 80BB8935141C3E5900F1753A /* ChainShape.cpp */, - 80BB8936141C3E5900F1753A /* ChainShape.hpp */, - 80BB8937141C3E5900F1753A /* DiskShape.cpp */, - 80BB8938141C3E5900F1753A /* DiskShape.hpp */, - 80BB8939141C3E5900F1753A /* EdgeShape.cpp */, - 80BB893A141C3E5900F1753A /* EdgeShape.hpp */, - 476E8AC11FCF926F00705BB5 /* FunctionalShapeVisitor.hpp */, - 474AFBF61EB1B2CB002AA6C8 /* MultiShape.cpp */, - 474AFBF71EB1B2CB002AA6C8 /* MultiShape.hpp */, - 80BB893B141C3E5900F1753A /* PolygonShape.cpp */, - 80BB893C141C3E5900F1753A /* PolygonShape.hpp */, + 80BB8935141C3E5900F1753A /* ChainShapeConf.cpp */, + 80BB8936141C3E5900F1753A /* ChainShapeConf.hpp */, + 80BB8937141C3E5900F1753A /* DiskShapeConf.cpp */, + 80BB8938141C3E5900F1753A /* DiskShapeConf.hpp */, + 80BB8939141C3E5900F1753A /* EdgeShapeConf.cpp */, + 80BB893A141C3E5900F1753A /* EdgeShapeConf.hpp */, + 474AFBF61EB1B2CB002AA6C8 /* MultiShapeConf.cpp */, + 474AFBF71EB1B2CB002AA6C8 /* MultiShapeConf.hpp */, + 80BB893B141C3E5900F1753A /* PolygonShapeConf.cpp */, + 80BB893C141C3E5900F1753A /* PolygonShapeConf.hpp */, 470F9B051EDB8F62007EF7B6 /* Shape.cpp */, 80BB893D141C3E5900F1753A /* Shape.hpp */, 473E019C1F80ACBE00D58CC8 /* ShapeDef.hpp */, - 47D28D851F6DD9540094C032 /* ShapeVisitor.hpp */, ); path = Shapes; sourceTree = ""; @@ -1295,7 +1289,7 @@ 80BB8987141C3E5900F1753A /* PlayRho.hpp in Headers */, 47D28D9D1F6F28C70094C032 /* WrongState.hpp in Headers */, 4731DE581DEC908600E7F931 /* UnitVec2.hpp in Headers */, - 474AFBFA1EB1B2CB002AA6C8 /* MultiShape.hpp in Headers */, + 474AFBFA1EB1B2CB002AA6C8 /* MultiShapeConf.hpp in Headers */, 47B58F641F64C19600354C34 /* RealConstants.hpp in Headers */, 4787D6EB1F2FA0CA008C115E /* LengthError.hpp in Headers */, 80BB8990141C3E5900F1753A /* Distance.hpp in Headers */, @@ -1308,18 +1302,17 @@ 80BB8992141C3E5900F1753A /* DynamicTree.hpp in Headers */, 80BB8994141C3E5900F1753A /* TimeOfImpact.hpp in Headers */, 4787D6BF1F2E968E008C115E /* JointDef.hpp in Headers */, - 80BB8996141C3E5900F1753A /* ChainShape.hpp in Headers */, + 80BB8996141C3E5900F1753A /* ChainShapeConf.hpp in Headers */, 470F94BA1EC4D4F800AA3C82 /* FixtureAtty.hpp in Headers */, 472D35381F98C56200574B73 /* Intervals.hpp in Headers */, 470F94AE1EC4CAE600AA3C82 /* FixtureDef.hpp in Headers */, 4734B2211DC1340500F15E29 /* Span.hpp in Headers */, - 80BB8998141C3E5900F1753A /* DiskShape.hpp in Headers */, + 80BB8998141C3E5900F1753A /* DiskShapeConf.hpp in Headers */, 472724301E315E1A00C64921 /* Fixed.hpp in Headers */, - 476E8AC31FCF926F00705BB5 /* FunctionalShapeVisitor.hpp in Headers */, 47C85D211F0DA14500F70C56 /* Templates.hpp in Headers */, - 80BB899A141C3E5900F1753A /* EdgeShape.hpp in Headers */, + 80BB899A141C3E5900F1753A /* EdgeShapeConf.hpp in Headers */, 470F94CC1EC4D95D00AA3C82 /* BodyAtty.hpp in Headers */, - 80BB899C141C3E5900F1753A /* PolygonShape.hpp in Headers */, + 80BB899C141C3E5900F1753A /* PolygonShapeConf.hpp in Headers */, 470F9B0C1EDE6340007EF7B6 /* Vector3.hpp in Headers */, 47D61F761F1F1F2500E702BD /* DroidSansTtfData.h in Headers */, 4788690A1D78BE2B00AEC7F1 /* PositionConstraint.hpp in Headers */, @@ -1359,7 +1352,6 @@ 478869101D78BF7200AEC7F1 /* VelocityConstraint.hpp in Headers */, 80BB89B7141C3E5900F1753A /* WorldCallbacks.hpp in Headers */, 47B58F661F64D2B500354C34 /* Real.hpp in Headers */, - 47D28D871F6DD9540094C032 /* ShapeVisitor.hpp in Headers */, 4768D3F51E3A7ACA00574143 /* Wider.hpp in Headers */, 4787D6E71F2ED62C008C115E /* WheelJointDef.hpp in Headers */, 470F94E31ECBB3A100AA3C82 /* Range.hpp in Headers */, @@ -1685,13 +1677,13 @@ 47D28D8E1F6E2C7C0094C032 /* JointType.cpp in Sources */, 80BB8993141C3E5900F1753A /* TimeOfImpact.cpp in Sources */, 470F9B4C1EEF20B6007EF7B6 /* BodyDef.cpp in Sources */, - 80BB8995141C3E5900F1753A /* ChainShape.cpp in Sources */, + 80BB8995141C3E5900F1753A /* ChainShapeConf.cpp in Sources */, 4726DD2A1D31B4090012A882 /* RayCastOutput.cpp in Sources */, - 80BB8997141C3E5900F1753A /* DiskShape.cpp in Sources */, - 80BB8999141C3E5900F1753A /* EdgeShape.cpp in Sources */, + 80BB8997141C3E5900F1753A /* DiskShapeConf.cpp in Sources */, + 80BB8999141C3E5900F1753A /* EdgeShapeConf.cpp in Sources */, 4731DE2C1DDF94A600E7F931 /* AABB.cpp in Sources */, 4787D6D21F2ECB8D008C115E /* MouseJointDef.cpp in Sources */, - 80BB899B141C3E5900F1753A /* PolygonShape.cpp in Sources */, + 80BB899B141C3E5900F1753A /* PolygonShapeConf.cpp in Sources */, 80BB899E141C3E5900F1753A /* BlockAllocator.cpp in Sources */, 80BB89A3141C3E5900F1753A /* Math.cpp in Sources */, 47B58F551F570E2C00354C34 /* DynamicMemory.cpp in Sources */, @@ -1728,7 +1720,7 @@ 80BB89D2141C3E5900F1753A /* MouseJoint.cpp in Sources */, 470F9B061EDB8F62007EF7B6 /* Shape.cpp in Sources */, 80BB89D4141C3E5900F1753A /* PrismaticJoint.cpp in Sources */, - 474AFBF81EB1B2CB002AA6C8 /* MultiShape.cpp in Sources */, + 474AFBF81EB1B2CB002AA6C8 /* MultiShapeConf.cpp in Sources */, 80BB89D6141C3E5900F1753A /* PulleyJoint.cpp in Sources */, 4787D6DA1F2ECFFB008C115E /* RevoluteJointDef.cpp in Sources */, 80BB89D8141C3E5900F1753A /* RevoluteJoint.cpp in Sources */, diff --git a/HelloWorld/HelloWorld.cpp b/HelloWorld/HelloWorld.cpp index 5d42c140ed..e3a3b3c7e9 100644 --- a/HelloWorld/HelloWorld.cpp +++ b/HelloWorld/HelloWorld.cpp @@ -40,7 +40,7 @@ int main() // Define the ground shape. Use a polygon configured as a box for this. // The extents are the half-width and half-height of the box. - const auto box = std::make_shared(50_m, 10_m); + const auto box = PolygonShapeConf{}.SetAsBox(50_m, 10_m); // Add the box shape to the ground body. ground->CreateFixture(box); @@ -51,7 +51,7 @@ int main() .UseType(BodyType::Dynamic)); // Define a disk shape for the ball body. - const auto disk = std::make_shared(1_m); + const auto disk = DiskShapeConf{}.UseRadius(1_m); // Add the disk shape to the ball body. ball->CreateFixture(disk); diff --git a/PlayRho/Collision/AABB.cpp b/PlayRho/Collision/AABB.cpp index 1a3e16597f..52b8354a44 100644 --- a/PlayRho/Collision/AABB.cpp +++ b/PlayRho/Collision/AABB.cpp @@ -57,17 +57,17 @@ AABB2D ComputeAABB(const DistanceProxy& proxy, AABB2D ComputeAABB(const Shape& shape, const Transformation& xf) noexcept { auto sum = AABB2D{}; - const auto childCount = shape.GetChildCount(); + const auto childCount = GetChildCount(shape); for (auto i = decltype(childCount){0}; i < childCount; ++i) { - Include(sum, ComputeAABB(shape.GetChild(i), xf)); + Include(sum, ComputeAABB(GetChild(shape, i), xf)); } return sum; } AABB2D ComputeAABB(const Fixture& fixture) noexcept { - return ComputeAABB(*fixture.GetShape(), fixture.GetBody()->GetTransformation()); + return ComputeAABB(fixture.GetShape(), fixture.GetBody()->GetTransformation()); } AABB2D ComputeAABB(const Body& body) @@ -76,7 +76,7 @@ AABB2D ComputeAABB(const Body& body) const auto xf = body.GetTransformation(); for (auto&& f: body.GetFixtures()) { - Include(sum, ComputeAABB(*(GetRef(f).GetShape()), xf)); + Include(sum, ComputeAABB((GetRef(f).GetShape()), xf)); } return sum; } @@ -86,8 +86,8 @@ AABB2D ComputeIntersectingAABB(const Fixture& fA, ChildCounter iA, { const auto xA = fA.GetBody()->GetTransformation(); const auto xB = fB.GetBody()->GetTransformation(); - const auto childA = fA.GetShape()->GetChild(iA); - const auto childB = fB.GetShape()->GetChild(iB); + const auto childA = GetChild(fA.GetShape(), iA); + const auto childB = GetChild(fB.GetShape(), iB); const auto aabbA = ComputeAABB(childA, xA); const auto aabbB = ComputeAABB(childB, xB); return GetIntersectingAABB(aabbA, aabbB); diff --git a/PlayRho/Collision/DistanceProxy.hpp b/PlayRho/Collision/DistanceProxy.hpp index 4dd4d9e7f5..53ed81deae 100644 --- a/PlayRho/Collision/DistanceProxy.hpp +++ b/PlayRho/Collision/DistanceProxy.hpp @@ -174,6 +174,8 @@ namespace playrho NonNegative m_vertexRadius = 0_m; ///< Radius of the vertices of the associated shape. }; + // Free functions... + /// @brief Determines with the two given distance proxies are equal. /// @relatedalso DistanceProxy bool operator== (const DistanceProxy& lhs, const DistanceProxy& rhs) noexcept; @@ -185,6 +187,12 @@ namespace playrho return !(lhs == rhs); } + /// @brief Gets the vertex radius property of a given distance proxy. + inline NonNegative GetVertexRadius(const DistanceProxy& arg) noexcept + { + return arg.GetVertexRadius(); + } + /// @brief Gets the supporting vertex index in the given direction for the given distance proxy. /// @details This finds the vertex that's most significantly in the direction of the given /// vector and returns its index. diff --git a/PlayRho/Collision/MassData.cpp b/PlayRho/Collision/MassData.cpp index d2b55a25bd..ba4e0650ea 100644 --- a/PlayRho/Collision/MassData.cpp +++ b/PlayRho/Collision/MassData.cpp @@ -19,11 +19,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -178,7 +178,7 @@ MassData GetMassData(Length vertexRadius, NonNegative density, MassData GetMassData(const Fixture& f) { - return f.GetShape()->GetMassData(); + return GetMassData(f.GetShape()); } MassData ComputeMassData(const Body& body) noexcept diff --git a/PlayRho/Collision/RayCastOutput.cpp b/PlayRho/Collision/RayCastOutput.cpp index 073ff2eede..6af8386d66 100644 --- a/PlayRho/Collision/RayCastOutput.cpp +++ b/PlayRho/Collision/RayCastOutput.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -233,7 +232,7 @@ RayCastOutput RayCast(const DistanceProxy& proxy, const RayCastInput& input, RayCastOutput RayCast(const Shape& shape, ChildCounter childIndex, const RayCastInput& input, const Transformation& transform) noexcept { - return RayCast(shape.GetChild(childIndex), input, transform); + return RayCast(GetChild(shape, childIndex), input, transform); } } // namespace playrho diff --git a/PlayRho/Collision/Shapes/ChainShape.hpp b/PlayRho/Collision/Shapes/ChainShape.hpp deleted file mode 100644 index d70b081fff..0000000000 --- a/PlayRho/Collision/Shapes/ChainShape.hpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Original work Copyright (c) 2006-2010 Erin Catto http://www.box2d.org - * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PLAYRHO_COLLISION_SHAPES_CHAINSHAPE_HPP -#define PLAYRHO_COLLISION_SHAPES_CHAINSHAPE_HPP - -#include -#include -#include - -namespace playrho { - -class EdgeShape; - -/// @brief Chain shape. -/// -/// @details A chain shape is a free form sequence of line segments. -/// The chain has two-sided collision, so you can use inside and outside collision. -/// Therefore, you may use any winding order. -/// Since there may be many vertices, they are allocated on the memory heap. -/// -/// @image html Chain1.png -/// -/// @warning The chain will not collide properly if there are self-intersections. -/// -/// @ingroup PartsGroup -/// -class ChainShape: public Shape -{ -public: - - /// @brief Gets the default vertex radius. - static PLAYRHO_CONSTEXPR inline NonNegative GetDefaultVertexRadius() noexcept - { - return DefaultLinearSlop * Real{2}; - } - - /// @brief Configuration data for chain shapes. - struct Conf: public ShapeDefBuilder - { - Conf(): ShapeDefBuilder{ShapeDef{ShapeConf{}.UseVertexRadius(GetDefaultVertexRadius())}} - { - // Intentionally empty. - } - - /// @brief Vertices that define a chain shape. - std::vector vertices; - }; - - /// @brief Gets the default configuration. - static Conf GetDefaultConf() noexcept - { - return Conf{}; - } - - /// @brief Initializing constructor. - explicit ChainShape(const Conf& conf = GetDefaultConf()); - - /// @brief Copy constructor. - ChainShape(const ChainShape& other) = default; - - /// @brief Move constructor. - ChainShape(ChainShape&& other) = default; - - ~ChainShape() override = default; - - /// @brief Copy assignment operator. - ChainShape& operator= (const ChainShape& other) = default; - - /// @brief Move assignment operator. - ChainShape& operator= (ChainShape&& other) = default; - - ChildCounter GetChildCount() const noexcept override; - - DistanceProxy GetChild(ChildCounter index) const override; - - MassData GetMassData() const noexcept override; - - void Accept(ShapeVisitor& visitor) const override; - - /// @brief Gets the vertex count. - ChildCounter GetVertexCount() const noexcept; - - /// @brief Gets a vertex by index. - Length2 GetVertex(ChildCounter index) const; - - /// @brief Gets the normal at the given index. - UnitVec2 GetNormal(ChildCounter index) const; - -private: - std::vector m_vertices; ///< Vertices. - std::vector m_normals; ///< Normals. -}; - -inline ChildCounter ChainShape::GetVertexCount() const noexcept -{ - return static_cast(m_vertices.size()); -} - -inline Length2 ChainShape::GetVertex(ChildCounter index) const -{ - assert((0 <= index) && (index < GetVertexCount())); - return m_vertices[index]; -} - -inline UnitVec2 ChainShape::GetNormal(ChildCounter index) const -{ - assert((0 <= index) && (index < GetVertexCount())); - return m_normals[index]; -} - -/// @brief Determines whether the given shape is looped. -inline bool IsLooped(const ChainShape& shape) noexcept -{ - const auto count = shape.GetVertexCount(); - return (count > 1)? (shape.GetVertex(count - 1) == shape.GetVertex(0)): false; -} - -/// @brief Gets the next index after the given index for the given shape. -inline ChildCounter GetNextIndex(const ChainShape& shape, ChildCounter index) noexcept -{ - return GetModuloNext(index, shape.GetVertexCount()); -} - -} // namespace playrho - -#endif // PLAYRHO_COLLISION_SHAPES_CHAINSHAPE_HPP diff --git a/PlayRho/Collision/Shapes/ChainShape.cpp b/PlayRho/Collision/Shapes/ChainShapeConf.cpp similarity index 64% rename from PlayRho/Collision/Shapes/ChainShape.cpp rename to PlayRho/Collision/Shapes/ChainShapeConf.cpp index a31d02659a..7eb39e4e82 100644 --- a/PlayRho/Collision/Shapes/ChainShape.cpp +++ b/PlayRho/Collision/Shapes/ChainShapeConf.cpp @@ -19,8 +19,7 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#include -#include +#include namespace playrho { @@ -43,38 +42,68 @@ namespace { #endif } // anonymous namespace -ChainShape::ChainShape(const Conf& conf): - Shape{conf} +ChainShapeConf::ChainShapeConf(): + ShapeDefBuilder{ShapeDef{ShapeConf{}.UseVertexRadius(GetDefaultVertexRadius())}} { - const auto count = conf.vertices.size(); + // Intentionally empty. +} + +ChainShapeConf& ChainShapeConf::Set(std::vector vertices) +{ + const auto count = vertices.size(); if (count > MaxChildCount) { throw InvalidArgument("too many vertices"); } - m_vertices = conf.vertices; - + m_vertices = vertices; if (count > 1) { - auto vprev = m_vertices[0]; - for (auto i = decltype(count){1}; i < count; ++i) + auto vprev = Length2{}; + auto first = true; + for (const auto v: m_vertices) { - // Get the normal and push it and its reverse. - // This "doubling up" of the normals, makes the GetChild() method work. - const auto v = m_vertices[i]; - const auto normal = GetUnitVector(GetFwdPerpendicular(v - vprev)); - m_normals.push_back(normal); - m_normals.push_back(-normal); + if (!first) + { + // Get the normal and push it and its reverse. + // This "doubling up" of the normals, makes the GetChild() method work. + const auto normal = GetUnitVector(GetFwdPerpendicular(v - vprev)); + m_normals.push_back(normal); + m_normals.push_back(-normal); + } + else + { + first = false; + } vprev = v; } } + return *this; +} + +ChainShapeConf& ChainShapeConf::Add(Length2 vertex) +{ + if (m_vertices.size() > 0) + { + auto vprev = m_vertices.back(); + m_vertices.emplace_back(vertex); + const auto normal = GetUnitVector(GetFwdPerpendicular(vertex - vprev)); + m_normals.push_back(normal); + m_normals.push_back(-normal); + } + else + { + m_vertices.emplace_back(vertex); + } + return *this; } -MassData ChainShape::GetMassData() const noexcept +MassData ChainShapeConf::GetMassData() const noexcept { - const auto density = GetDensity(); + const auto density = this->density; if (density > AreaDensity(0)) { + const auto vertexRadius = this->vertexRadius; const auto vertexCount = GetVertexCount(); if (vertexCount > 1) { @@ -83,7 +112,6 @@ MassData ChainShape::GetMassData() const noexcept auto I = RotInertia{0}; auto area = Area(0); auto center = Length2{}; - const auto vertexRadius = GetVertexRadius(); auto vprev = GetVertex(0); const auto circle_area = Square(vertexRadius) * Pi; for (auto i = decltype(vertexCount){1}; i < vertexCount; ++i) @@ -106,36 +134,25 @@ MassData ChainShape::GetMassData() const noexcept } if (vertexCount == 1) { - return playrho::GetMassData(GetVertexRadius(), density, GetVertex(0)); + return playrho::GetMassData(vertexRadius, density, GetVertex(0)); } } return MassData{}; } -ChildCounter ChainShape::GetChildCount() const noexcept -{ - // edge count = vertex count - 1 - const auto count = GetVertexCount(); - return (count > 1)? count - 1: count; -} - -DistanceProxy ChainShape::GetChild(ChildCounter index) const +DistanceProxy ChainShapeConf::GetChild(ChildCounter index) const { if (index >= GetChildCount()) { throw InvalidArgument("index out of range"); } + const auto vertexRadius = this->vertexRadius; const auto vertexCount = GetVertexCount(); if (vertexCount > 1) { - return DistanceProxy{GetVertexRadius(), 2, &m_vertices[index], &m_normals[index * 2]}; + return DistanceProxy{vertexRadius, 2, &m_vertices[index], &m_normals[index * 2]}; } - return DistanceProxy{GetVertexRadius(), 1, &m_vertices[0], nullptr}; -} - -void ChainShape::Accept(ShapeVisitor &visitor) const -{ - visitor.Visit(*this); + return DistanceProxy{vertexRadius, 1, &m_vertices[0], nullptr}; } } // namespace playrho diff --git a/PlayRho/Collision/Shapes/ChainShapeConf.hpp b/PlayRho/Collision/Shapes/ChainShapeConf.hpp new file mode 100644 index 0000000000..744cee6c2f --- /dev/null +++ b/PlayRho/Collision/Shapes/ChainShapeConf.hpp @@ -0,0 +1,153 @@ +/* + * Original work Copyright (c) 2006-2010 Erin Catto http://www.box2d.org + * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef PLAYRHO_COLLISION_SHAPES_CHAINSHAPECONF_HPP +#define PLAYRHO_COLLISION_SHAPES_CHAINSHAPECONF_HPP + +#include +#include +#include +#include +#include + +namespace playrho { + +/// @brief Chain shape configuration. +/// +/// @details A chain shape is a free form sequence of line segments. +/// The chain has two-sided collision, so you can use inside and outside collision. +/// Therefore, you may use any winding order. +/// Since there may be many vertices, they are allocated on the memory heap. +/// +/// @image html Chain1.png +/// +/// @warning The chain will not collide properly if there are self-intersections. +/// +/// @ingroup PartsGroup +/// +class ChainShapeConf: public ShapeDefBuilder +{ +public: + /// @brief Gets the default vertex radius. + static PLAYRHO_CONSTEXPR inline NonNegative GetDefaultVertexRadius() noexcept + { + return DefaultLinearSlop * 2; + } + + /// @brief Default constructor. + ChainShapeConf(); + + /// @brief Sets the configuration up for representing a chain of the given vertices. + ChainShapeConf& Set(std::vector vertices); + + /// @brief Adds the given vertex. + ChainShapeConf& Add(Length2 vertex); + + /// @brief Gets the "child" shape count. + ChildCounter GetChildCount() const noexcept + { + // edge count = vertex count - 1 + const auto count = GetVertexCount(); + return (count > 1)? count - 1: count; + } + + /// @brief Gets the "child" shape at the given index. + DistanceProxy GetChild(ChildCounter index) const; + + /// @brief Gets the mass data. + MassData GetMassData() const noexcept; + + /// @brief Gets the vertex count. + ChildCounter GetVertexCount() const noexcept + { + return static_cast(m_vertices.size()); + } + + /// @brief Gets a vertex by index. + Length2 GetVertex(ChildCounter index) const + { + assert((0 <= index) && (index < GetVertexCount())); + return m_vertices[index]; + } + + /// @brief Gets the normal at the given index. + UnitVec2 GetNormal(ChildCounter index) const + { + assert((0 <= index) && (index < GetVertexCount())); + return m_normals[index]; + } + + /// @brief Equality operator. + friend bool operator== (const ChainShapeConf& lhs, const ChainShapeConf& rhs) noexcept + { + // Don't need to check normals since normals based on vertices. + return lhs.vertexRadius == rhs.vertexRadius && lhs.friction == rhs.friction + && lhs.restitution == rhs.restitution && lhs.density == rhs.density + && lhs.m_vertices == rhs.m_vertices; + } + + /// @brief Inequality operator. + friend bool operator!= (const ChainShapeConf& lhs, const ChainShapeConf& rhs) noexcept + { + return !(lhs == rhs); + } + +private: + std::vector m_vertices; ///< Vertices. + std::vector m_normals; ///< Normals. +}; + +// Free functions... + +/// @brief Gets the child count for a given chain shape configuration. +inline ChildCounter GetChildCount(const ChainShapeConf& arg) noexcept +{ + return arg.GetChildCount(); +} + +/// @brief Gets the "child" shape for a given chain shape configuration. +inline DistanceProxy GetChild(const ChainShapeConf& arg, ChildCounter index) +{ + return arg.GetChild(index); +} + +/// @brief Gets the mass data for a given chain shape configuration. +inline MassData GetMassData(const ChainShapeConf& arg) noexcept +{ + return arg.GetMassData(); +} + +/// @brief Determines whether the given shape is looped. +inline bool IsLooped(const ChainShapeConf& shape) noexcept +{ + const auto count = shape.GetVertexCount(); + return (count > 1)? (shape.GetVertex(count - 1) == shape.GetVertex(0)): false; +} + +/// @brief Gets the next index after the given index for the given shape. +inline ChildCounter GetNextIndex(const ChainShapeConf& shape, ChildCounter index) noexcept +{ + return GetModuloNext(index, shape.GetVertexCount()); +} + +} // namespace playrho + +#endif // PLAYRHO_COLLISION_SHAPES_CHAINSHAPECONF_HPP diff --git a/PlayRho/Collision/Shapes/DiskShape.hpp b/PlayRho/Collision/Shapes/DiskShape.hpp deleted file mode 100644 index b9dddfc896..0000000000 --- a/PlayRho/Collision/Shapes/DiskShape.hpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org - * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PLAYRHO_COLLISION_SHAPES_DISKSHAPE_HPP -#define PLAYRHO_COLLISION_SHAPES_DISKSHAPE_HPP - -#include -#include - -namespace playrho { - -/// @brief Disk shape. -/// -/// @details A disk shape "is the region in a plane bounded by a circle". This is a -/// two-dimensional solid round shape. This used to be called the circle shape but -/// that's now used for hollow round shapes. -/// -/// @sa https://en.wikipedia.org/wiki/Disk_(mathematics) -/// @sa CircleShape. -/// -/// @ingroup PartsGroup -/// -class DiskShape : public Shape -{ -public: - - /// @brief Gets the default radius. - static PLAYRHO_CONSTEXPR inline Length GetDefaultRadius() noexcept - { - return DefaultLinearSlop * 2; - } - - /// @brief Configuration data for disk shapes. - struct Conf: public ShapeDefBuilder - { - PLAYRHO_CONSTEXPR inline Conf(): ShapeDefBuilder{ShapeConf{}.UseVertexRadius(GetDefaultRadius())} - { - // Intentionally empty. - } - - /// @brief Uses the given value as the location. - PLAYRHO_CONSTEXPR inline Conf& UseLocation(Length2 value) noexcept - { - location = value; - return *this; - } - - /// @brief Sets the radius to the given value. - PLAYRHO_CONSTEXPR inline Conf& SetRadius(Length radius) noexcept - { - SetVertexRadius(radius); - return *this; - } - - /// @brief Sets the location to the given value. - PLAYRHO_CONSTEXPR inline Conf& SetLocation(const Length2 value) noexcept - { - location = value; - return *this; - } - - /// @brief Location for the disk shape to be centered at. - Length2 location = Length2{}; - }; - - /// @brief Gets the default configuration. - static PLAYRHO_CONSTEXPR inline Conf GetDefaultConf() noexcept; - - /// Initializing constructor. - explicit DiskShape(const Conf& conf = GetDefaultConf()) noexcept: - Shape{conf}, m_location{conf.location} - { - // Intentionally empty. - } - - /// @brief Initializing constructor. - explicit DiskShape(const Length radius, const Conf& conf = GetDefaultConf()) noexcept: - Shape{radius, conf}, m_location{conf.location} - { - // Intentionally empty. - } - - /// @brief Copy constructor. - DiskShape(const DiskShape& other) = default; - - /// @brief Move constructor. - DiskShape(DiskShape&& other) = default; - - ~DiskShape() override = default; - - /// @brief Copy assignment operator. - DiskShape& operator= (const DiskShape& other) = default; - - /// @brief Move assignment operator. - DiskShape& operator= (DiskShape&& other) = default; - - ChildCounter GetChildCount() const noexcept override; - - DistanceProxy GetChild(ChildCounter index) const override; - - MassData GetMassData() const noexcept override; - - void Accept(ShapeVisitor& visitor) const override; - - /// @brief Gets the "radius" of the shape. - /// @return Non-negative radius. - NonNegative GetRadius() const noexcept { return GetVertexRadius(); } - - /// @brief Gets the location of the center of this circle shape. - /// @return The origin (0, 0) unless explicitly set otherwise on construction or via - /// the set location method. - /// @sa SetPosition. - Length2 GetLocation() const noexcept { return m_location; } - -private: - /// Location of the shape as initialized on construction or as assigned using the - /// SetPosition method. - Length2 m_location = Length2{}; -}; - -PLAYRHO_CONSTEXPR inline DiskShape::Conf DiskShape::GetDefaultConf() noexcept -{ - return Conf{}; -} - -inline ChildCounter DiskShape::GetChildCount() const noexcept -{ - return 1; -} - -inline DistanceProxy DiskShape::GetChild(ChildCounter index) const -{ - if (index != 0) - { - throw InvalidArgument("only index of 0 is supported"); - } - return DistanceProxy{GetVertexRadius(), 1, &m_location, nullptr}; -} - -} // namespace playrho - -#endif // PLAYRHO_COLLISION_SHAPES_DISKSHAPE_HPP diff --git a/PlayRho/Collision/Shapes/DiskShape.cpp b/PlayRho/Collision/Shapes/DiskShapeConf.cpp similarity index 76% rename from PlayRho/Collision/Shapes/DiskShape.cpp rename to PlayRho/Collision/Shapes/DiskShapeConf.cpp index a7c7054192..44d8140f1c 100644 --- a/PlayRho/Collision/Shapes/DiskShape.cpp +++ b/PlayRho/Collision/Shapes/DiskShapeConf.cpp @@ -17,19 +17,8 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#include -#include +#include namespace playrho { -MassData DiskShape::GetMassData() const noexcept -{ - return playrho::GetMassData(GetVertexRadius(), GetDensity(), GetLocation()); -} - -void DiskShape::Accept(ShapeVisitor& visitor) const -{ - visitor.Visit(*this); -} - } // namespace playrho diff --git a/PlayRho/Collision/Shapes/DiskShapeConf.hpp b/PlayRho/Collision/Shapes/DiskShapeConf.hpp new file mode 100644 index 0000000000..dc3b178285 --- /dev/null +++ b/PlayRho/Collision/Shapes/DiskShapeConf.hpp @@ -0,0 +1,130 @@ +/* + * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org + * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef PLAYRHO_COLLISION_SHAPES_DISKSHAPECONF_HPP +#define PLAYRHO_COLLISION_SHAPES_DISKSHAPECONF_HPP + +#include +#include +#include +#include + +namespace playrho { + +/// @brief Disk shape configuration. +/// +/// @details A disk shape "is the region in a plane bounded by a circle". This is a +/// two-dimensional solid round shape. This used to be called the circle shape but +/// that's now used for hollow round shapes. +/// +/// @sa https://en.wikipedia.org/wiki/Disk_(mathematics) +/// +/// @ingroup PartsGroup +/// +struct DiskShapeConf: ShapeDefBuilder +{ +public: + /// @brief Gets the default radius. + static PLAYRHO_CONSTEXPR inline Length GetDefaultRadius() noexcept + { + return DefaultLinearSlop * 2; + } + + PLAYRHO_CONSTEXPR inline DiskShapeConf(): ShapeDefBuilder{ShapeConf{}.UseVertexRadius(GetDefaultRadius())} + { + // Intentionally empty. + } + + /// @brief Initializing constructor. + PLAYRHO_CONSTEXPR inline DiskShapeConf(Length radius): ShapeDefBuilder{ShapeConf{}.UseVertexRadius(radius)} + { + // Intentionally empty. + } + + /// @brief Uses the given value as the location. + PLAYRHO_CONSTEXPR inline DiskShapeConf& UseLocation(Length2 value) noexcept + { + location = value; + return *this; + } + + /// @brief Uses the given value as the radius. + PLAYRHO_CONSTEXPR inline DiskShapeConf& UseRadius(Length radius) noexcept + { + vertexRadius = radius; + return *this; + } + + /// @brief Gets the radius property. + NonNegative GetRadius() const noexcept + { + return vertexRadius; + } + + /// @brief Gets the location. + Length2 GetLocation() const noexcept + { + return location; + } + + /// @brief Location for the disk shape to be centered at. + Length2 location = Length2{}; +}; + +// Free functions... + +/// @brief Equality operator. +inline bool operator== (const DiskShapeConf& lhs, const DiskShapeConf& rhs) noexcept +{ + return lhs.vertexRadius == rhs.vertexRadius && lhs.friction == rhs.friction + && lhs.restitution == rhs.restitution && lhs.density == rhs.density + && lhs.location == rhs.location; +} + +/// @brief Inequality operator. +inline bool operator!= (const DiskShapeConf& lhs, const DiskShapeConf& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// @brief Gets the "child" count of the given disk shape configuration. +PLAYRHO_CONSTEXPR inline ChildCounter GetChildCount(const DiskShapeConf&) noexcept +{ + return 1; +} + +/// @brief Gets the "child" of the given disk shape configuration. +inline DistanceProxy GetChild(const DiskShapeConf& arg, ChildCounter index) +{ + if (index != 0) + { + throw InvalidArgument("only index of 0 is supported"); + } + return DistanceProxy{arg.vertexRadius, 1, &arg.location, nullptr}; +} + +/// @brief Gets the mass data of the given disk shape configuration. +inline MassData GetMassData(const DiskShapeConf& arg) noexcept +{ + return playrho::GetMassData(arg.vertexRadius, arg.density, arg.location); +} + +} // namespace playrho + +#endif // PLAYRHO_COLLISION_SHAPES_DISKSHAPECONF_HPP diff --git a/PlayRho/Collision/Shapes/EdgeShape.hpp b/PlayRho/Collision/Shapes/EdgeShape.hpp deleted file mode 100644 index f4c3cd15fd..0000000000 --- a/PlayRho/Collision/Shapes/EdgeShape.hpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Original work Copyright (c) 2006-2010 Erin Catto http://www.box2d.org - * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PLAYRHO_COLLISION_SHAPES_EDGESHAPE_HPP -#define PLAYRHO_COLLISION_SHAPES_EDGESHAPE_HPP - -#include -#include - -namespace playrho { - -/// @brief Edge shape. -/// -/// @details A line segment (edge) shape. These can be connected in chains or loops -/// to other edge shapes. The connectivity information is used to ensure correct -/// contact normals. -/// -/// @note This data structure is 56-bytes. -/// -/// @ingroup PartsGroup -/// -class EdgeShape : public Shape -{ -public: - - /// @brief Gets the default vertex radius. - static PLAYRHO_CONSTEXPR inline Length GetDefaultVertexRadius() noexcept - { - return DefaultLinearSlop * Real{2}; - } - - /// @brief Configuration data for edge shapes. - struct Conf: public ShapeDefBuilder - { - PLAYRHO_CONSTEXPR inline Conf(): ShapeDefBuilder{ShapeConf{}.UseVertexRadius(GetDefaultVertexRadius())} - { - // Intentionally empty. - } - - /// @brief Uses the given value for vertex 1. - PLAYRHO_CONSTEXPR inline Conf& UseVertex1(Length2 value) noexcept - { - vertex1 = value; - return *this; - } - - /// @brief Uses the given value for vertex 2. - PLAYRHO_CONSTEXPR inline Conf& UseVertex2(Length2 value) noexcept - { - vertex2 = value; - return *this; - } - - /// @brief Sets both vertices in one call. - PLAYRHO_CONSTEXPR inline Conf& Set(Length2 v1, Length2 v2) noexcept - { - vertex1 = v1; - vertex2 = v2; - return *this; - } - - Length2 vertex1 = Length2{}; ///< Vertex 1. - Length2 vertex2 = Length2{}; ///< Vertex 2. - }; - - /// @brief Gets the default configuration for an EdgeShape. - static PLAYRHO_CONSTEXPR inline Conf GetDefaultConf() noexcept - { - return Conf{}; - } - - /// @brief Initializing constructor. - explicit EdgeShape(const Conf& conf = GetDefaultConf()) noexcept: - Shape{conf}, - m_vertices{conf.vertex1, conf.vertex2} - { - m_normals[0] = GetUnitVector(GetFwdPerpendicular(conf.vertex2 - conf.vertex1)); - m_normals[1] = -m_normals[0]; - } - - /// @brief Initializing constructor. - EdgeShape(Length2 v1, Length2 v2, const Conf& conf = GetDefaultConf()) noexcept: - Shape{conf}, - m_vertices{v1, v2} - { - m_normals[0] = GetUnitVector(GetFwdPerpendicular(v2 - v1)); - m_normals[1] = -m_normals[0]; - } - - /// @brief Copy constructor. - EdgeShape(const EdgeShape& other) = default; - - /// @brief Move constructor. - EdgeShape(EdgeShape&& other) = default; - - ~EdgeShape() override = default; - - /// @brief Copy assignment operator. - EdgeShape& operator= (const EdgeShape& other) = default; - - /// @brief Move assignment operator. - EdgeShape& operator= (EdgeShape&& other) = default; - - ChildCounter GetChildCount() const noexcept override; - - DistanceProxy GetChild(ChildCounter index) const override; - - MassData GetMassData() const noexcept override; - - void Accept(ShapeVisitor& visitor) const override; - - /// @brief Gets vertex number 1 (of 2). - Length2 GetVertex1() const noexcept { return m_vertices[0]; } - - /// @brief Gets vertex number 2 (of 2). - Length2 GetVertex2() const noexcept { return m_vertices[1]; } - - /// @brief Gets normal number 1 (of 2). - UnitVec2 GetNormal1() const noexcept { return m_normals[0]; } - - /// @brief Gets normal number 2 (of 2). - UnitVec2 GetNormal2() const noexcept { return m_normals[1]; } - -private: - Length2 m_vertices[2]; ///< Vertices - UnitVec2 m_normals[2]; ///< Normals. -}; - -inline ChildCounter EdgeShape::GetChildCount() const noexcept -{ - return 1; -} - -inline DistanceProxy EdgeShape::GetChild(ChildCounter index) const -{ - if (index != 0) - { - throw InvalidArgument("only index of 0 is supported"); - } - return DistanceProxy{GetVertexRadius(), 2, m_vertices, m_normals}; -} - -} // namespace playrho - -#endif // PLAYRHO_COLLISION_SHAPES_EDGESHAPE_HPP diff --git a/PlayRho/Collision/Shapes/EdgeShape.cpp b/PlayRho/Collision/Shapes/EdgeShapeConf.cpp similarity index 60% rename from PlayRho/Collision/Shapes/EdgeShape.cpp rename to PlayRho/Collision/Shapes/EdgeShapeConf.cpp index 59531230a4..74c2926620 100644 --- a/PlayRho/Collision/Shapes/EdgeShape.cpp +++ b/PlayRho/Collision/Shapes/EdgeShapeConf.cpp @@ -17,19 +17,32 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#include -#include +#include namespace playrho { -MassData EdgeShape::GetMassData() const noexcept +EdgeShapeConf::EdgeShapeConf(): + ShapeDefBuilder{ShapeConf{}.UseVertexRadius(GetDefaultVertexRadius())} { - return playrho::GetMassData(GetVertexRadius(), GetDensity(), GetVertex1(), GetVertex2()); + // Intentionally empty. } -void EdgeShape::Accept(ShapeVisitor& visitor) const +EdgeShapeConf::EdgeShapeConf(Length2 vA, Length2 vB, const EdgeShapeConf& conf) noexcept: + ShapeDefBuilder{conf}, m_vertices{vA, vB} { - visitor.Visit(*this); + const auto normal = GetUnitVector(GetFwdPerpendicular(vB - vA)); + m_normals[0] = normal; + m_normals[1] = -normal; +} + +EdgeShapeConf& EdgeShapeConf::Set(Length2 vA, Length2 vB) noexcept +{ + m_vertices[0] = vA; + m_vertices[1] = vB; + const auto normal = GetUnitVector(GetFwdPerpendicular(vB - vA)); + m_normals[0] = normal; + m_normals[1] = -normal; + return *this; } } // namespace playrho diff --git a/PlayRho/Collision/Shapes/EdgeShapeConf.hpp b/PlayRho/Collision/Shapes/EdgeShapeConf.hpp new file mode 100644 index 0000000000..1eb61ea9c8 --- /dev/null +++ b/PlayRho/Collision/Shapes/EdgeShapeConf.hpp @@ -0,0 +1,128 @@ +/* + * Original work Copyright (c) 2006-2010 Erin Catto http://www.box2d.org + * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef PLAYRHO_COLLISION_SHAPES_EDGESHAPECONF_HPP +#define PLAYRHO_COLLISION_SHAPES_EDGESHAPECONF_HPP + +#include +#include +#include +#include + +namespace playrho { + +/// @brief Edge shape configuration. +/// +/// @details A line segment (edge) shape. These can be connected in chains or loops +/// to other edge shapes. The connectivity information is used to ensure correct +/// contact normals. +/// +/// @note This data structure is 56-bytes. +/// +/// @ingroup PartsGroup +/// +class EdgeShapeConf: public ShapeDefBuilder +{ +public: + /// @brief Gets the default vertex radius. + static PLAYRHO_CONSTEXPR inline Length GetDefaultVertexRadius() noexcept + { + return DefaultLinearSlop * Real{2}; + } + + /// @brief Gets the default configuration for an EdgeShapeConf. + static inline EdgeShapeConf GetDefaultConf() noexcept + { + return EdgeShapeConf{}; + } + + EdgeShapeConf(); + + /// @brief Initializing constructor. + EdgeShapeConf(Length2 vA, Length2 vB, const EdgeShapeConf& conf = GetDefaultConf()) noexcept; + + /// @brief Sets both vertices in one call. + EdgeShapeConf& Set(Length2 vA, Length2 vB) noexcept; + + /// @brief Gets vertex A. + Length2 GetVertexA() const noexcept + { + return m_vertices[0]; + } + + /// @brief Gets vertex B. + Length2 GetVertexB() const noexcept + { + return m_vertices[1]; + } + + /// @brief Gets the "child" shape. + DistanceProxy GetChild() const noexcept + { + return DistanceProxy{vertexRadius, 2, m_vertices, m_normals}; + } + +private: + Length2 m_vertices[2] = {Length2{}, Length2{}}; ///< Vertices + UnitVec2 m_normals[2] = {UnitVec2{}, UnitVec2{}}; ///< Normals. +}; + +// Free functions... + +/// @brief Equality operator. +inline bool operator== (const EdgeShapeConf& lhs, const EdgeShapeConf& rhs) noexcept +{ + return lhs.vertexRadius == rhs.vertexRadius && lhs.friction == rhs.friction + && lhs.restitution == rhs.restitution && lhs.density == rhs.density + && lhs.GetVertexA() == rhs.GetVertexA() && lhs.GetVertexB() == rhs.GetVertexB(); +} + +/// @brief Inequality operator. +inline bool operator!= (const EdgeShapeConf& lhs, const EdgeShapeConf& rhs) noexcept +{ + return !(lhs == rhs); +} + +/// @brief Gets the "child" count for the given shape configuration. +/// @return 1. +PLAYRHO_CONSTEXPR inline ChildCounter GetChildCount(const EdgeShapeConf&) noexcept +{ + return 1; +} + +/// @brief Gets the "child" shape for the given shape configuration. +inline DistanceProxy GetChild(const EdgeShapeConf& arg, ChildCounter index) +{ + if (index != 0) + { + throw InvalidArgument("only index of 0 is supported"); + } + return arg.GetChild(); +} + +/// @brief Gets the mass data for the given shape configuration. +inline MassData GetMassData(const EdgeShapeConf& arg) noexcept +{ + return playrho::GetMassData(arg.vertexRadius, arg.density, + arg.GetVertexA(), arg.GetVertexB()); +} + +} // namespace playrho + +#endif // PLAYRHO_COLLISION_SHAPES_EDGESHAPECONF_HPP diff --git a/PlayRho/Collision/Shapes/FunctionalShapeVisitor.hpp b/PlayRho/Collision/Shapes/FunctionalShapeVisitor.hpp deleted file mode 100644 index 2863717798..0000000000 --- a/PlayRho/Collision/Shapes/FunctionalShapeVisitor.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PLAYRHO_COLLISION_SHAPES_FUNCTIONALSHAPEVISITOR_HPP -#define PLAYRHO_COLLISION_SHAPES_FUNCTIONALSHAPEVISITOR_HPP - -#include -#include -#include - -namespace playrho { - - /// @brief Functional shape visitor class. - /// @note This class is intended to provide an alternate interface for visiting shapes - /// via the use of lamdas instead of having to subclass ShapeVisitor. - /// @sa ShapeVisitor - class FunctionalShapeVisitor: public ShapeVisitor - { - public: - /// @brief Procedure alias. - template - using Proc = std::function; - - /// @brief Tuple alias. - using Tuple = std::tuple< - Proc, - Proc, - Proc, - Proc, - Proc - >; - - Tuple procs; ///< Procedures. - - /// @brief Uses given procedure. - /// @note Provide a builder pattern mutator method. - template - FunctionalShapeVisitor& Use(const Proc& proc) noexcept - { - std::get>(procs) = proc; - return *this; - } - - // Overrides of all the base class's Visit methods... - // Uses decltype to ensure the correctly typed invocation of the Handle method. - void Visit(const DiskShape& arg) override { Handle(arg); } - void Visit(const EdgeShape& arg) override { Handle(arg); } - void Visit(const PolygonShape& arg) override { Handle(arg); } - void Visit(const ChainShape& arg) override { Handle(arg); } - void Visit(const MultiShape& arg) override { Handle(arg); } - - private: - - /// @brief Handles the joint through the established function. - template - inline void Handle(T arg) const - { - const auto& proc = std::get>(procs); - if (proc) - { - proc(arg); - } - } - }; - -} // namespace playrho - -#endif // PLAYRHO_COLLISION_SHAPES_FUNCTIONALSHAPEVISITOR_HPP - diff --git a/PlayRho/Collision/Shapes/MultiShape.hpp b/PlayRho/Collision/Shapes/MultiShape.hpp deleted file mode 100644 index c25aa28bdd..0000000000 --- a/PlayRho/Collision/Shapes/MultiShape.hpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PLAYRHO_COLLISION_SHAPES_MULTISHAPE_HPP -#define PLAYRHO_COLLISION_SHAPES_MULTISHAPE_HPP - -#include -#include -#include - -namespace playrho { - - class VertexSet; - - /// @brief The "multi-shape" shape. - /// @details Composes zero or more convex shapes into what can be a concave shape. - /// @ingroup PartsGroup - class MultiShape: public Shape - { - public: - /// @brief Convex hull. - class ConvexHull - { - public: - - /// @brief Gets the convex hull for the given set of vertices. - static ConvexHull Get(const VertexSet& pointSet); - - /// @brief Gets the distance proxy for this convex hull. - DistanceProxy GetDistanceProxy(Length vertexRadius) const - { - return DistanceProxy{ - vertexRadius, static_cast(vertices.size()), - vertices.data(), normals.data() - }; - } - - private: - /// @brief Initializing constructor. - ConvexHull(std::vector verts, std::vector norms): - vertices{verts}, normals{norms} - {} - - /// Array of vertices. - /// @details Consecutive vertices constitute "edges" of the polygon. - std::vector vertices; - - /// Normals of edges. - /// @details - /// These are 90-degree clockwise-rotated unit-vectors of the vectors defined by - /// consecutive pairs of elements of vertices. - std::vector normals; - }; - - /// @brief Gets the default vertex radius for the MultiShape. - static PLAYRHO_CONSTEXPR inline Length GetDefaultVertexRadius() noexcept - { - return DefaultLinearSlop * Real{2}; - } - - /// @brief Configuration data for multi-shape shapes. - struct Conf: public ShapeDefBuilder - { - inline Conf(): ShapeDefBuilder{ShapeConf{}.UseVertexRadius(GetDefaultVertexRadius())} - { - // Intentionally empty. - } - - /// Creates a convex hull from the given set of local points. - /// The size of the set must be in the range [1, MaxShapeVertices]. - /// @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. - void AddConvexHull(const VertexSet& pointSet) noexcept; - - std::vector children; ///< Children. - }; - - /// @brief Gets the default configuration for a MultiShape. - static inline Conf GetDefaultConf() noexcept - { - return Conf{}; - } - - /// @brief Default constructor. - /// @details Constructs a polygon shape with a 0,0 centroid and vertex count of 0. - /// @note Polygons with a vertex count less than 1 are "degenerate" and should be - /// treated as invalid. - explicit MultiShape(const Conf& conf = GetDefaultConf()) noexcept: - Shape{conf}, m_children{conf.children} - { - // Intentionally empty. - } - - /// @brief Copy constructor. - MultiShape(const MultiShape&) = default; - - ~MultiShape() override = default; - - ChildCounter GetChildCount() const noexcept override; - - DistanceProxy GetChild(ChildCounter index) const override; - - MassData GetMassData() const noexcept override; - - void Accept(ShapeVisitor& visitor) const override; - - private: - std::vector m_children; ///< Children. - }; - - inline ChildCounter MultiShape::GetChildCount() const noexcept - { - return static_cast(m_children.size()); - } - - inline DistanceProxy MultiShape::GetChild(ChildCounter index) const - { - if (index >= GetChildCount()) - { - throw InvalidArgument("index out of range"); - } - const auto& child = m_children.at(index); - return child.GetDistanceProxy(GetVertexRadius()); - } - -} // namespace playrho - -#endif // PLAYRHO_COLLISION_SHAPES_MULTISHAPE_HPP diff --git a/PlayRho/Collision/Shapes/MultiShape.cpp b/PlayRho/Collision/Shapes/MultiShapeConf.cpp similarity index 79% rename from PlayRho/Collision/Shapes/MultiShape.cpp rename to PlayRho/Collision/Shapes/MultiShapeConf.cpp index 9b83d1dbe5..caa8623331 100644 --- a/PlayRho/Collision/Shapes/MultiShape.cpp +++ b/PlayRho/Collision/Shapes/MultiShapeConf.cpp @@ -18,8 +18,7 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#include -#include +#include #include #include @@ -28,16 +27,19 @@ namespace playrho { /// Computes the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin. /// @return Mass data for this shape. -MassData MultiShape::GetMassData() const noexcept +MassData GetMassData(const MultiShapeConf& arg) noexcept { auto mass = 0_kg; const auto origin = Length2{}; auto weightedCenter = origin * Kilogram; auto I = RotInertia(0); + const auto vertexRadius = arg.vertexRadius; + const auto density = arg.density; - std::for_each(std::begin(m_children), std::end(m_children), [&](const ConvexHull& ch) { - const auto dp = ch.GetDistanceProxy(GetVertexRadius()); - const auto md = playrho::GetMassData(GetVertexRadius(), GetDensity(), + std::for_each(std::begin(arg.children), std::end(arg.children), + [&](const ConvexHull& ch) { + const auto dp = ch.GetDistanceProxy(vertexRadius); + const auto md = playrho::GetMassData(vertexRadius, density, Span(dp.GetVertices().begin(), dp.GetVertexCount())); mass += Mass{md.mass}; weightedCenter += md.center * Mass{md.mass}; @@ -48,7 +50,7 @@ MassData MultiShape::GetMassData() const noexcept return MassData{center, mass, I}; } -MultiShape::ConvexHull MultiShape::ConvexHull::Get(const VertexSet& pointSet) +ConvexHull ConvexHull::Get(const VertexSet& pointSet) { auto vertices = GetConvexHullAsVector(pointSet); assert(!vertices.empty() && vertices.size() < std::numeric_limits::max()); @@ -74,14 +76,10 @@ MultiShape::ConvexHull MultiShape::ConvexHull::Get(const VertexSet& pointSet) return ConvexHull{vertices, normals}; } -void MultiShape::Conf::AddConvexHull(const VertexSet& pointSet) noexcept +MultiShapeConf& MultiShapeConf::AddConvexHull(const VertexSet& pointSet) noexcept { children.emplace_back(ConvexHull::Get(pointSet)); -} - -void MultiShape::Accept(ShapeVisitor &visitor) const -{ - visitor.Visit(*this); + return *this; } } // namespace playrho diff --git a/PlayRho/Collision/Shapes/MultiShapeConf.hpp b/PlayRho/Collision/Shapes/MultiShapeConf.hpp new file mode 100644 index 0000000000..f9d97b3bcb --- /dev/null +++ b/PlayRho/Collision/Shapes/MultiShapeConf.hpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef PLAYRHO_COLLISION_SHAPES_MULTISHAPECONF_HPP +#define PLAYRHO_COLLISION_SHAPES_MULTISHAPECONF_HPP + +#include +#include +#include +#include +#include + +namespace playrho { + + class VertexSet; + + /// @brief Convex hull. + class ConvexHull + { + public: + + /// @brief Gets the convex hull for the given set of vertices. + static ConvexHull Get(const VertexSet& pointSet); + + /// @brief Gets the distance proxy for this convex hull. + DistanceProxy GetDistanceProxy(Length vertexRadius) const + { + return DistanceProxy{ + vertexRadius, static_cast(vertices.size()), + vertices.data(), normals.data() + }; + } + + /// @brief Equality operator. + friend bool operator== (const ConvexHull& lhs, const ConvexHull& rhs) noexcept + { + // Only need to check vertices are same since normals are calculated based on them. + return lhs.vertices == rhs.vertices; + } + + /// @brief Inequality operator. + friend bool operator!= (const ConvexHull& lhs, const ConvexHull& rhs) noexcept + { + return !(lhs == rhs); + } + + private: + /// @brief Initializing constructor. + ConvexHull(std::vector verts, std::vector norms): + vertices{verts}, normals{norms} + {} + + /// Array of vertices. + /// @details Consecutive vertices constitute "edges" of the polygon. + std::vector vertices; + + /// Normals of edges. + /// @details + /// These are 90-degree clockwise-rotated unit-vectors of the vectors defined by + /// consecutive pairs of elements of vertices. + std::vector normals; + }; + + /// @brief The "multi-shape" shape configuration. + /// @details Composes zero or more convex shapes into what can be a concave shape. + /// @ingroup PartsGroup + struct MultiShapeConf: public ShapeDefBuilder + { + /// @brief Gets the default vertex radius for the MultiShapeConf. + static PLAYRHO_CONSTEXPR inline Length GetDefaultVertexRadius() noexcept + { + return DefaultLinearSlop * 2; + } + + /// @brief Gets the default configuration for a MultiShapeConf. + static inline MultiShapeConf GetDefaultConf() noexcept + { + return MultiShapeConf{}; + } + + inline MultiShapeConf(): ShapeDefBuilder{ShapeConf{}.UseVertexRadius(GetDefaultVertexRadius())} + { + // Intentionally empty. + } + + /// Creates a convex hull from the given set of local points. + /// The size of the set must be in the range [1, MaxShapeVertices]. + /// @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. + MultiShapeConf& AddConvexHull(const VertexSet& pointSet) noexcept; + + std::vector children; ///< Children. + }; + + // Free functions... + + /// @brief Equality operator. + inline bool operator== (const MultiShapeConf& lhs, const MultiShapeConf& rhs) noexcept + { + return lhs.vertexRadius == rhs.vertexRadius && lhs.friction == rhs.friction + && lhs.restitution == rhs.restitution && lhs.density == rhs.density + && lhs.children == rhs.children; + } + + /// @brief Inequality operator. + inline bool operator!= (const MultiShapeConf& lhs, const MultiShapeConf& rhs) noexcept + { + return !(lhs == rhs); + } + + /// @brief Gets the "child" count for the given shape configuration. + inline ChildCounter GetChildCount(const MultiShapeConf& arg) noexcept + { + return static_cast(arg.children.size()); + } + + /// @brief Gets the "child" shape for the given shape configuration. + inline DistanceProxy GetChild(const MultiShapeConf& arg, ChildCounter index) + { + if (index >= GetChildCount(arg)) + { + throw InvalidArgument("index out of range"); + } + const auto& child = arg.children.at(index); + return child.GetDistanceProxy(arg.vertexRadius); + } + + /// @brief Gets the mass data for the given shape configuration. + MassData GetMassData(const MultiShapeConf& arg) noexcept; + +} // namespace playrho + +#endif // PLAYRHO_COLLISION_SHAPES_MULTISHAPECONF_HPP diff --git a/PlayRho/Collision/Shapes/PolygonShape.hpp b/PlayRho/Collision/Shapes/PolygonShape.hpp deleted file mode 100644 index 57c164935d..0000000000 --- a/PlayRho/Collision/Shapes/PolygonShape.hpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org - * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PLAYRHO_COLLISION_SHAPES_POLYGONSHAPE_HPP -#define PLAYRHO_COLLISION_SHAPES_POLYGONSHAPE_HPP - -#include -#include -#include -#include -#include - -namespace playrho { - -/// @brief Polygon shape. -/// @details A convex polygon. The interior of the polygon is to the left of each edge. -/// Polygons maximum number of vertices is defined by MaxShapeVertices. -/// In most cases you should not need many vertices for a convex polygon. -/// @image html convex_concave.gif -/// @note This data structure is 64-bytes large (with 4-byte Real). -/// @ingroup PartsGroup -class PolygonShape : public Shape -{ -public: - - /// @brief Gets the default vertex radius for the PolygonShape. - static PLAYRHO_CONSTEXPR inline Length GetDefaultVertexRadius() noexcept - { - return DefaultLinearSlop * Real{2}; - } - - /// @brief Configuration data for polygon shapes. - struct Conf: public ShapeDefBuilder - { - inline Conf(): ShapeDefBuilder{ShapeConf{}.UseVertexRadius(GetDefaultVertexRadius())} - { - // Intentionally empty. - } - - /// @brief Uses the given vertices. - inline Conf& UseVertices(const std::vector& verts) noexcept - { - vertices = verts; - return *this; - } - - /// @brief Sets the vertices for the described box. - Conf& SetAsBox(Length hx, Length hy) noexcept; - - /// @brief Sets the vertices for the described box. - Conf& SetAsBox(Length hx, Length hy, Length2 center, Angle angle) noexcept; - - /// @brief Sets the vertices to the given ones. - Conf& Set(Span verts) noexcept; - - /// @brief Transformas the set vertices. - Conf& Transform(Transformation xfm) noexcept; - - /// @brief Vertices container. - std::vector vertices; - }; - - /// @brief Gets the default configuration for a PolygonShape. - static inline Conf GetDefaultConf() noexcept - { - return Conf{}; - } - - /// Default constructor. - /// @details Constructs a polygon shape with a 0,0 centroid and vertex count of 0. - /// @note Polygons with a vertex count less than 1 are "degenerate" and should be - /// treated as invalid. - explicit PolygonShape(const Conf& conf = GetDefaultConf()) noexcept: - Shape{conf} - { - Set(Span(conf.vertices.data(), conf.vertices.size())); - } - - /// @brief Copy constructor. - PolygonShape(const PolygonShape& other) = default; - - /// @brief Move constructor. - PolygonShape(PolygonShape&& other) = default; - - /// @brief Initializing constructor for rectangles. - /// @param hx the half-width. - /// @param hy the half-height. - /// @param conf Configuration data for the shape. - explicit PolygonShape(Length hx, Length hy, const Conf& conf = GetDefaultConf()) noexcept; - - /// @brief Creates a convex hull from the given array of local points. - /// @note The size of the span must be in the range [1, MaxShapeVertices]. - /// @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. - explicit PolygonShape(Span points, const Conf& conf = GetDefaultConf()) noexcept; - - ~PolygonShape() override = default; - - /// @brief Copy assignment operator. - PolygonShape& operator= (const PolygonShape& other) = default; - - /// @brief Move assignment operator. - PolygonShape& operator= (PolygonShape&& other) = default; - - ChildCounter GetChildCount() const noexcept override; - - DistanceProxy GetChild(ChildCounter index) const override; - - MassData GetMassData() const noexcept override; - - void Accept(ShapeVisitor& visitor) const override; - - /// Gets the vertex count. - /// @return value between 0 and MaxShapeVertices inclusive. - /// @see MaxShapeVertices. - VertexCounter GetVertexCount() const noexcept; - - /// Gets a vertex by index. - /// @details Vertices go counter-clockwise. - Length2 GetVertex(VertexCounter index) const; - - /// Gets a normal by index. - /// @details - /// These are 90-degree clockwise-rotated (outward-facing) unit-vectors of the edges defined - /// by consecutive pairs of vertices starting with vertex 0. - /// @param index Index of the normal to get. - /// @return Normal for the given index. - UnitVec2 GetNormal(VertexCounter index) const; - - /// Gets the span of vertices. - /// @details Vertices go counter-clockwise. - Span GetVertices() const noexcept - { - return Span(&m_vertices[0], GetVertexCount()); - } - - /// @brief Gets the span of normals. - Span GetNormals() const noexcept - { - return Span(&m_normals[0], GetVertexCount()); - } - - /// @brief Gets the centroid. - Length2 GetCentroid() const noexcept { return m_centroid; } - -private: - /// Creates a convex hull from the given array of local points. - /// The size of the span must be in the range [1, MaxShapeVertices]. - /// @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. - void Set(Span points) noexcept; - - /// Creates a convex hull from the given set of local points. - /// The size of the set must be in the range [1, MaxShapeVertices]. - /// @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. - void Set(const VertexSet& points) noexcept; - - /// Build vertices to represent an axis-aligned box centered on the local origin. - /// @param hx the half-width. - /// @param hy the half-height. - void SetAsBox(Length hx, Length hy) noexcept; - - /// Array of vertices. - /// @details Consecutive vertices constitute "edges" of the polygon. - std::vector m_vertices; - - /// Normals of edges. - /// @details - /// These are 90-degree clockwise-rotated unit-vectors of the vectors defined by - /// consecutive pairs of elements of vertices. - std::vector m_normals; - - /// Centroid of this shape. - Length2 m_centroid = GetInvalid(); -}; - -inline ChildCounter PolygonShape::GetChildCount() const noexcept -{ - return 1; -} - -inline DistanceProxy PolygonShape::GetChild(ChildCounter index) const -{ - if (index != 0) - { - throw InvalidArgument("only index of 0 is supported"); - } - return DistanceProxy{GetVertexRadius(), - static_cast(m_vertices.size()), m_vertices.data(), - m_normals.data()}; -} - -inline VertexCounter PolygonShape::GetVertexCount() const noexcept -{ - return static_cast(m_vertices.size()); -} - -inline Length2 PolygonShape::GetVertex(VertexCounter index) const -{ - assert(0 <= index && index < GetVertexCount()); - return m_vertices[index]; -} - -inline UnitVec2 PolygonShape::GetNormal(VertexCounter index) const -{ - assert(0 <= index && index < GetVertexCount()); - return m_normals[index]; -} - -// Free functions... - -/// Gets the identified edge of the given polygon shape. -/// @note This must not be called for shapes with less than 2 vertices. -/// @warning Behavior is undefined if called for a shape with less than 2 vertices. -/// @relatedalso PolygonShape -Length2 GetEdge(const PolygonShape& shape, VertexCounter index); - -/// Validate convexity of the given shape. -/// @note This is a time consuming operation. -/// @returns true if valid -/// @relatedalso PolygonShape -bool Validate(const PolygonShape& shape); - -} // namespace playrho - -#endif // PLAYRHO_COLLISION_SHAPES_POLYGONSHAPE_HPP diff --git a/PlayRho/Collision/Shapes/PolygonShape.cpp b/PlayRho/Collision/Shapes/PolygonShapeConf.cpp similarity index 69% rename from PlayRho/Collision/Shapes/PolygonShape.cpp rename to PlayRho/Collision/Shapes/PolygonShapeConf.cpp index ba1fcf9441..6bb821f075 100644 --- a/PlayRho/Collision/Shapes/PolygonShape.cpp +++ b/PlayRho/Collision/Shapes/PolygonShapeConf.cpp @@ -17,31 +17,32 @@ * 3. This notice may not be removed or altered from any source distribution. */ -#include -#include +#include #include namespace playrho { -PolygonShape::PolygonShape(Length hx, Length hy, const Conf& conf) noexcept: - Shape{conf} +PolygonShapeConf::PolygonShapeConf(): + ShapeDefBuilder{ShapeConf{}.UseVertexRadius(GetDefaultVertexRadius())} { - SetAsBox(hx, hy); + // Intentionally empty. } -PolygonShape::PolygonShape(Span points, const Conf& conf) noexcept: - Shape{conf} +PolygonShapeConf::PolygonShapeConf(Length hx, Length hy, + const PolygonShapeConf& conf) noexcept: + ShapeDefBuilder{conf} { - Set(points); + SetAsBox(hx, hy); } -MassData PolygonShape::GetMassData() const noexcept +PolygonShapeConf::PolygonShapeConf(Span points, + const PolygonShapeConf& conf) noexcept: + ShapeDefBuilder{conf} { - return playrho::GetMassData(GetVertexRadius(), GetDensity(), - Span(m_vertices.data(), m_vertices.size())); + Set(points); } -void PolygonShape::SetAsBox(Length hx, Length hy) noexcept +PolygonShapeConf& PolygonShapeConf::SetAsBox(Length hx, Length hy) noexcept { m_centroid = Length2{}; @@ -63,49 +64,36 @@ void PolygonShape::SetAsBox(Length hx, Length hy) noexcept m_normals.emplace_back(UnitVec2::GetTop()); m_normals.emplace_back(UnitVec2::GetLeft()); m_normals.emplace_back(UnitVec2::GetBottom()); -} - -PolygonShape::Conf& PolygonShape::Conf::SetAsBox(Length hx, Length hy) noexcept -{ - // vertices must be counter-clockwise - - const auto btm_rgt = Length2{+hx, -hy}; - const auto top_rgt = Length2{ hx, hy}; - const auto top_lft = Length2{-hx, +hy}; - const auto btm_lft = Length2{-hx, -hy}; - - vertices.clear(); - vertices.emplace_back(btm_rgt); - vertices.emplace_back(top_rgt); - vertices.emplace_back(top_lft); - vertices.emplace_back(btm_lft); return *this; } -PolygonShape::Conf& PolygonShape::Conf::Set(Span verts) noexcept +/// @brief Uses the given vertices. +PolygonShapeConf& PolygonShapeConf::UseVertices(const std::vector& verts) noexcept { - vertices.assign(verts.cbegin(), verts.cend()); - return *this; + return Set(Span(verts.data(), verts.size())); } -PolygonShape::Conf& PolygonShape::Conf::SetAsBox(Length hx, Length hy, Length2 center, Angle angle) noexcept +PolygonShapeConf& PolygonShapeConf::SetAsBox(Length hx, Length hy, + Length2 center, Angle angle) noexcept { SetAsBox(hx, hy); Transform(Transformation{center, UnitVec2::Get(angle)}); return *this; } -PolygonShape::Conf& PolygonShape::Conf::Transform(Transformation xfm) noexcept +PolygonShapeConf& PolygonShapeConf::Transform(Transformation xfm) noexcept { - for (auto& v: vertices) + for (auto i = decltype(GetVertexCount()){0}; i < GetVertexCount(); ++i) { - v = playrho::Transform(v, xfm); + m_vertices[i] = playrho::Transform(m_vertices[i], xfm); + m_normals[i] = Rotate(m_normals[i], xfm.q); } + m_centroid = playrho::Transform(m_centroid, xfm); return *this; } -void PolygonShape::Set(Span points) noexcept +PolygonShapeConf& PolygonShapeConf::Set(Span points) noexcept { // Perform welding and copy vertices into local buffer. auto point_set = VertexSet(Square(DefaultLinearSlop)); @@ -113,10 +101,10 @@ void PolygonShape::Set(Span points) noexcept { point_set.add(p); } - Set(point_set); + return Set(point_set); } -void PolygonShape::Set(const VertexSet& points) noexcept +PolygonShapeConf& PolygonShapeConf::Set(const VertexSet& points) noexcept { m_vertices = GetConvexHullAsVector(points); assert(m_vertices.size() < std::numeric_limits::max()); @@ -154,14 +142,11 @@ void PolygonShape::Set(const VertexSet& points) noexcept m_centroid = ComputeCentroid(GetVertices()); break; } + + return *this; } -void PolygonShape::Accept(ShapeVisitor& visitor) const -{ - visitor.Visit(*this); -} - -Length2 GetEdge(const PolygonShape& shape, VertexCounter index) +Length2 GetEdge(const PolygonShapeConf& shape, VertexCounter index) { assert(shape.GetVertexCount() > 1); @@ -170,7 +155,7 @@ Length2 GetEdge(const PolygonShape& shape, VertexCounter index) return shape.GetVertex(i1) - shape.GetVertex(i0); } -bool Validate(const PolygonShape& shape) +bool Validate(const PolygonShapeConf& shape) { const auto count = shape.GetVertexCount(); for (auto i = decltype(count){0}; i < count; ++i) diff --git a/PlayRho/Collision/Shapes/PolygonShapeConf.hpp b/PlayRho/Collision/Shapes/PolygonShapeConf.hpp new file mode 100644 index 0000000000..0e913839fe --- /dev/null +++ b/PlayRho/Collision/Shapes/PolygonShapeConf.hpp @@ -0,0 +1,210 @@ +/* + * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org + * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef PLAYRHO_COLLISION_SHAPES_POLYGONSHAPECONF_HPP +#define PLAYRHO_COLLISION_SHAPES_POLYGONSHAPECONF_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace playrho { + +/// @brief Polygon shape configuration. +/// @details A convex polygon. The interior of the polygon is to the left of each edge. +/// Polygons maximum number of vertices is defined by MaxShapeVertices. +/// In most cases you should not need many vertices for a convex polygon. +/// @image html convex_concave.gif +/// @note This data structure is 64-bytes large (with 4-byte Real). +/// @ingroup PartsGroup +class PolygonShapeConf: public ShapeDefBuilder +{ +public: + /// @brief Gets the default vertex radius for the PolygonShapeConf. + static PLAYRHO_CONSTEXPR inline Length GetDefaultVertexRadius() noexcept + { + return DefaultLinearSlop * 2; + } + + /// @brief Gets the default configuration for a PolygonShapeConf. + static inline PolygonShapeConf GetDefaultConf() noexcept + { + return PolygonShapeConf{}; + } + + PolygonShapeConf(); + + /// @brief Initializing constructor for a 4-sided box polygon. + PolygonShapeConf(Length hx, Length hy, + const PolygonShapeConf& conf = GetDefaultConf()) noexcept; + + /// @brief Creates a convex hull from the given array of local points. + /// @note The size of the span must be in the range [1, MaxShapeVertices]. + /// @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. + explicit PolygonShapeConf(Span points, + const PolygonShapeConf& conf = GetDefaultConf()) noexcept; + + /// @brief Uses the given vertices. + PolygonShapeConf& UseVertices(const std::vector& verts) noexcept; + + /// @brief Sets the vertices to represent an axis-aligned box centered on the local origin. + /// @param hx the half-width. + /// @param hy the half-height. + PolygonShapeConf& SetAsBox(Length hx, Length hy) noexcept; + + /// @brief Sets the vertices for the described box. + PolygonShapeConf& SetAsBox(Length hx, Length hy, Length2 center, Angle angle) noexcept; + + /// @brief Sets the vertices to a convex hull of the given ones. + /// @note The size of the span must be in the range [1, MaxShapeVertices]. + /// @warning 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. + PolygonShapeConf& Set(Span verts) noexcept; + + /// @brief Sets the vertices to a convex hull of the given ones. + /// @note The size of the span must be in the range [1, MaxShapeVertices]. + /// @warning 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. + PolygonShapeConf& Set(const VertexSet& points) noexcept; + + /// @brief Transforms the set vertices. + PolygonShapeConf& Transform(Transformation xfm) noexcept; + + /// @brief Equality operator. + friend bool operator== (const PolygonShapeConf& lhs, const PolygonShapeConf& rhs) noexcept + { + // Don't need to check normals nor centroid since they based on vertices. + return lhs.vertexRadius == rhs.vertexRadius && lhs.friction == rhs.friction + && lhs.restitution == rhs.restitution && lhs.density == rhs.density + && lhs.m_vertices == rhs.m_vertices; + } + + /// @brief Inequality operator. + friend bool operator!= (const PolygonShapeConf& lhs, const PolygonShapeConf& rhs) noexcept + { + return !(lhs == rhs); + } + + /// Gets the vertex count. + /// @return value between 0 and MaxShapeVertices inclusive. + /// @see MaxShapeVertices. + VertexCounter GetVertexCount() const noexcept + { + return static_cast(m_vertices.size()); + } + + /// Gets a vertex by index. + /// @details Vertices go counter-clockwise. + Length2 GetVertex(VertexCounter index) const + { + assert(0 <= index && index < GetVertexCount()); + return m_vertices[index]; + } + + /// Gets a normal by index. + /// @details + /// These are 90-degree clockwise-rotated (outward-facing) unit-vectors of the edges defined + /// by consecutive pairs of vertices starting with vertex 0. + /// @param index Index of the normal to get. + /// @return Normal for the given index. + UnitVec2 GetNormal(VertexCounter index) const + { + assert(0 <= index && index < GetVertexCount()); + return m_normals[index]; + } + + /// Gets the span of vertices. + /// @details Vertices go counter-clockwise. + Span GetVertices() const noexcept + { + return Span(&m_vertices[0], GetVertexCount()); + } + + /// @brief Gets the span of normals. + Span GetNormals() const noexcept + { + return Span(&m_normals[0], GetVertexCount()); + } + + /// @brief Gets the centroid. + Length2 GetCentroid() const noexcept { return m_centroid; } + +private: + /// @brief Array of vertices. + /// @details Consecutive vertices constitute "edges" of the polygon. + std::vector m_vertices; + + /// @brief Normals of edges. + /// @details These are 90-degree clockwise-rotated unit-vectors of the vectors defined + /// by consecutive pairs of elements of vertices. + std::vector m_normals; + + /// Centroid of this shape. + Length2 m_centroid = GetInvalid(); +}; + +// Free functions... + +/// @brief Gets the "child" count for the given shape configuration. +/// @return 1. +PLAYRHO_CONSTEXPR inline ChildCounter GetChildCount(const PolygonShapeConf&) noexcept +{ + return 1; +} + +/// @brief Gets the "child" shape for the given shape configuration. +inline DistanceProxy GetChild(const PolygonShapeConf& arg, ChildCounter index) +{ + if (index != 0) + { + throw InvalidArgument("only index of 0 is supported"); + } + return DistanceProxy{arg.vertexRadius, arg.GetVertexCount(), + arg.GetVertices().data(), arg.GetNormals().data()}; +} + +/// @brief Gets the mass data for the given shape configuration. +inline MassData GetMassData(const PolygonShapeConf& arg) noexcept +{ + return playrho::GetMassData(arg.vertexRadius, arg.density, arg.GetVertices()); +} + +/// Gets the identified edge of the given polygon shape. +/// @note This must not be called for shapes with less than 2 vertices. +/// @warning Behavior is undefined if called for a shape with less than 2 vertices. +/// @relatedalso PolygonShapeConf +Length2 GetEdge(const PolygonShapeConf& shape, VertexCounter index); + +/// Validate convexity of the given shape. +/// @note This is a time consuming operation. +/// @returns true if valid +/// @relatedalso PolygonShapeConf +bool Validate(const PolygonShapeConf& shape); + +} // namespace playrho + +#endif // PLAYRHO_COLLISION_SHAPES_POLYGONSHAPECONF_HPP diff --git a/PlayRho/Collision/Shapes/Shape.cpp b/PlayRho/Collision/Shapes/Shape.cpp index b115587b49..e622b08635 100644 --- a/PlayRho/Collision/Shapes/Shape.cpp +++ b/PlayRho/Collision/Shapes/Shape.cpp @@ -24,32 +24,14 @@ namespace playrho { -Shape::Shape(const ShapeDef& conf) noexcept: - m_vertexRadius{conf.vertexRadius}, - m_density{conf.density}, - m_friction{conf.friction}, - m_restitution{conf.restitution} -{ - // Intentionally empty. -} - -Shape::Shape(const Length vertexRadius, const ShapeDef& conf) noexcept: - m_vertexRadius{vertexRadius}, - m_density{conf.density}, - m_friction{conf.friction}, - m_restitution{conf.restitution} -{ - // Intentionally empty. -} - // Free functions... bool TestPoint(const Shape& shape, Length2 point) noexcept { - const auto childCount = shape.GetChildCount(); + const auto childCount = GetChildCount(shape); for (auto i = decltype(childCount){0}; i < childCount; ++i) { - if (playrho::TestPoint(shape.GetChild(i), point)) + if (playrho::TestPoint(GetChild(shape, i), point)) { return true; } diff --git a/PlayRho/Collision/Shapes/Shape.hpp b/PlayRho/Collision/Shapes/Shape.hpp index 46f7912cac..6fc71e1828 100644 --- a/PlayRho/Collision/Shapes/Shape.hpp +++ b/PlayRho/Collision/Shapes/Shape.hpp @@ -26,23 +26,34 @@ #include #include #include +#include +#include +#include namespace playrho { +/// @brief Gets the friction of the given shape. +Real GetFriction(const Shape& shape) noexcept; + +/// @brief Gets the restitution value of the given shape. +Real GetRestitution(const Shape& shape) noexcept; + +/// @brief Gets the density of the given shape. +NonNegative GetDensity(const Shape& shape) noexcept; + +/// @brief Gets the vertex radius of the given shape. +NonNegative GetVertexRadius(const Shape& shape) noexcept; + /// @defgroup PartsGroup Shape Classes -/// @brief Classes for describing shapes with material properties. +/// @brief Classes for configuring shapes with material properties. /// @details These are classes that specify physical characteristics of: shape, /// friction, density and restitution. They've historically been called shape classes /// but are now — with the other properties like friction and density having been /// moved into them — maybe better thought of as "parts". -class ShapeVisitor; -struct ShapeDef; - -/// @brief A base abstract class for describing a type of shape. +/// @brief Shape. /// -/// @details This is a polymorphic abstract base class for shapes. -/// A shape is used for collision detection. You can create a shape however you like. +/// @details A shape is used for collision detection. You can create a shape however you like. /// Shapes used for simulation in World are created automatically when a /// Fixture is created. Shapes may encapsulate zero or more child shapes. /// @@ -56,30 +67,55 @@ class Shape { public: - virtual ~Shape() = default; + /// @brief Visitor type alias for underlying shape configuration. + using Visitor = std::function; + + /// @brief Default constructor. + /// @details This is a base class that shouldn't ever be directly instantiated. + Shape() = delete; + + /// @brief Initializing constructor. + template + Shape(T v): m_self{std::make_shared>(std::move(v))} + {} + + /// @brief Copy constructor. + Shape(const Shape& other) = default; + + /// @brief Move constructor. + Shape(Shape&& other) = default; + + /// @brief Copy assignment operator. + Shape& operator= (const Shape& other) = default; + + /// @brief Move assignment operator. + Shape& operator= (Shape&& other) = default; /// @brief Gets the number of child primitives of the shape. /// @return Non-negative count. - virtual ChildCounter GetChildCount() const noexcept = 0; + friend ChildCounter GetChildCount(const Shape& shape) noexcept + { + return shape.m_self->GetChildCount_(); + } - /// @brief Gets the child for the given index. + /// @brief Gets the "child" for the given index. + /// @param shape Shape to get "child" shape of. /// @param index Index to a child element of the shape. Value must be less /// than the number of child primitives of the shape. /// @note The shape must remain in scope while the proxy is in use. /// @throws InvalidArgument if the given index is out of range. /// @sa GetChildCount - virtual DistanceProxy GetChild(ChildCounter index) const = 0; + friend DistanceProxy GetChild(const Shape& shape, ChildCounter index) + { + return shape.m_self->GetChild_(index); + } /// @brief Gets the mass properties of this shape using its dimensions and density. /// @return Mass data for this shape. - virtual MassData GetMassData() const noexcept = 0; - - /// @brief Accepts a visitor. - /// @details This is the Accept method definition of a "visitor design pattern" for - /// for doing shape subclass specific types of processing for a constant shape. - /// @sa ShapeVisitor - /// @sa https://en.wikipedia.org/wiki/Visitor_pattern - virtual void Accept(ShapeVisitor& visitor) const = 0; + friend MassData GetMassData(const Shape& shape) noexcept + { + return shape.m_self->GetMassData_(); + } /// @brief Gets the vertex radius. /// @@ -88,100 +124,193 @@ class Shape /// are straight, corners between them (the vertices) are rounded and treated /// as rounded. Shapes with larger vertex radiuses compared to edge lengths /// therefore will be more prone to rolling or having other shapes more prone - /// to roll off of them. Here's an image of a PolygonShape with it's skin drawn: + /// to roll off of them. Here's an image of a shape configured via a PolygonShapeConf + /// with it's skin drawn: /// /// @image html SkinnedPolygon.png /// /// @note This must be a non-negative value. /// - /// @sa SetVertexRadius + /// @sa UseVertexRadius /// - NonNegative GetVertexRadius() const noexcept; - - /// @brief Gets the density of this fixture. - /// @return Non-negative density (in mass per area). - NonNegative GetDensity() const noexcept; + friend NonNegative GetVertexRadius(const Shape& shape) noexcept + { + return shape.m_self->GetVertexRadius_(); + } /// @brief Gets the coefficient of friction. /// @return Value of 0 or higher. - Real GetFriction() const noexcept; + friend Real GetFriction(const Shape& shape) noexcept + { + return shape.m_self->GetFriction_(); + } /// @brief Gets the coefficient of restitution. - Real GetRestitution() const noexcept; - -protected: + friend Real GetRestitution(const Shape& shape) noexcept + { + return shape.m_self->GetRestitution_(); + } - /// @brief Default constructor. - /// @details This is a base class that shouldn't ever be directly instantiated. - Shape() = default; + /// @brief Gets the density of this fixture. + /// @return Non-negative density (in mass per area). + friend NonNegative GetDensity(const Shape& shape) noexcept + { + return shape.m_self->GetDensity_(); + } - /// @brief Initializing constructor. - /// - explicit Shape(const ShapeDef& conf) noexcept; + /// @brief Gets a pointer to the underlying data. + /// @note Provided for introspective purposes like visitation. + /// @note Generally speaking, try to avoid using this method unless there's + /// no other way to access the underlying data. + friend const void* GetData(const Shape& shape) noexcept + { + return shape.m_self->GetData_(); + } - /// @brief Initializing constructor. - /// - Shape(const Length vertexRadius, const ShapeDef& conf) noexcept; - - /// @brief Copy constructor. - Shape(const Shape& other) = default; + /// @brief Accepts a visitor. + /// @details This is the "accept" method definition of a "visitor design pattern" + /// for doing shape configuration specific types of processing for a constant shape. + /// @sa https://en.wikipedia.org/wiki/Visitor_pattern + friend void Accept(const Shape& shape, const Visitor& visitor) + { + const auto self = shape.m_self; + visitor(self->GetTypeInfo_(), self->GetData_()); + } - /// @brief Move constructor. - Shape(Shape&& other) = default; + /// @brief Equality operator for shape to shape comparisons. + friend bool operator== (const Shape& lhs, const Shape& rhs) noexcept + { + return lhs.m_self == rhs.m_self || *lhs.m_self == *rhs.m_self; + } - /// @brief Copy assignment operator. - Shape& operator= (const Shape& other) = default; - - /// @brief Move assignment operator. - Shape& operator= (Shape&& other) = default; + /// @brief Inequality operator for shape to shape comparisons. + friend bool operator!= (const Shape& lhs, const Shape& rhs) noexcept + { + return !(lhs == rhs); + } private: - - /// @brief Vertex radius. - NonNegative m_vertexRadius = NonNegative{0_m}; - - /// @brief AreaDensity. - NonNegative m_density = NonNegative{0_kgpm2}; - - /// @brief Friction as a coefficient. - NonNegative m_friction = NonNegative{Real{2} / Real{10}}; - /// @brief Restitution as a coefficient. - Finite m_restitution = Finite{0}; -}; + /// @brief Internal shape configuration concept. + /// @note Provides an interface for runtime polymorphism for shape configuration. + struct Concept + { + virtual ~Concept() = default; -inline NonNegative Shape::GetVertexRadius() const noexcept -{ - return m_vertexRadius; -} + /// @brief Gets the "child" count. + virtual ChildCounter GetChildCount_() const noexcept = 0; + + /// @brief Gets the "child" specified by the given index. + virtual DistanceProxy GetChild_(ChildCounter index) const = 0; + + /// @brief Gets the mass data. + virtual MassData GetMassData_() const noexcept = 0; + + /// @brief Gets the vertex radius. + virtual NonNegative GetVertexRadius_() const noexcept = 0; -inline NonNegative Shape::GetDensity() const noexcept -{ - return m_density; -} + /// @brief Gets the density. + virtual NonNegative GetDensity_() const noexcept = 0; + + /// @brief Gets the friction. + virtual Real GetFriction_() const noexcept = 0; + + /// @brief Gets the restitution. + virtual Real GetRestitution_() const noexcept = 0; + + /// @brief Equality checking method. + virtual bool IsEqual_(const Concept& other) const noexcept = 0; + + /// @brief Gets the type information of the underlying configuration. + virtual const std::type_info& GetTypeInfo_() const = 0; + + /// @brief Gets the data for the underlying configuration. + virtual const void* GetData_() const noexcept = 0; + + /// @brief Equality operator. + friend bool operator== (const Concept& lhs, const Concept &rhs) noexcept + { + return &lhs == &rhs || lhs.IsEqual_(rhs); + } + + /// @brief Inequality operator. + friend bool operator!= (const Concept& lhs, const Concept &rhs) noexcept + { + return !(lhs == rhs); + } + }; -inline Real Shape::GetFriction() const noexcept -{ - return m_friction; -} + /// @brief Internal model configuration concept. + /// @note Provides an implementation for runtime polymorphism for shape configuration. + template + struct Model final: Concept + { + /// @brief Type alias for the type of the data held. + using data_type = T; -inline Real Shape::GetRestitution() const noexcept -{ - return m_restitution; -} + /// @brief Initializing constructor. + Model(T arg): data{std::move(arg)} {} + + ChildCounter GetChildCount_() const noexcept override + { + return GetChildCount(data); + } -// Free functions... + DistanceProxy GetChild_(ChildCounter index) const override + { + return GetChild(data, index); + } -/// @brief Gets the vertex radius of the given shape. -/// @details Gets the radius of every vertex of this shape. -/// This is used for collision handling. -/// @note This value should never be less than zero. -/// @relatedalso Shape -/// @sa Shape::GetVertexRadius -inline NonNegative GetVertexRadius(const Shape& shape) noexcept -{ - return shape.GetVertexRadius(); -} + MassData GetMassData_() const noexcept override + { + return GetMassData(data); + } + + NonNegative GetVertexRadius_() const noexcept override + { + return GetVertexRadius(data); + } + + NonNegative GetDensity_() const noexcept override + { + return GetDensity(data); + } + + Real GetFriction_() const noexcept override + { + return GetFriction(data); + } + + Real GetRestitution_() const noexcept override + { + return GetRestitution(data); + } + + bool IsEqual_(const Concept& other) const noexcept override + { + return (GetTypeInfo_() == other.GetTypeInfo_()) && + (data == *static_cast(other.GetData_())); + } + + const std::type_info& GetTypeInfo_() const override + { + return typeid(data_type); + } + + const void* GetData_() const noexcept override + { + // Note address of "data" not necessarily same as address of "this" since + // base class is virtual. + return &data; + } + + T data; ///< Data. + }; + + std::shared_ptr m_self; ///< Self shared pointer. +}; + +// Free functions... /// @brief Test a point for containment in the given shape. /// @param shape Shape to use for test. diff --git a/PlayRho/Collision/Shapes/ShapeDef.hpp b/PlayRho/Collision/Shapes/ShapeDef.hpp index e3a41479f1..ad918e8c26 100644 --- a/PlayRho/Collision/Shapes/ShapeDef.hpp +++ b/PlayRho/Collision/Shapes/ShapeDef.hpp @@ -67,7 +67,7 @@ struct ShapeDef /// @note This must be a non-negative value. /// @note Use 0 to indicate that the shape's associated mass should be 0. /// - NonNegative density = NonNegative{0}; + NonNegative density = NonNegative{0_kgpm2}; }; /// @brief Builder configuration structure. @@ -99,22 +99,6 @@ struct ShapeDefBuilder: ShapeDef /// @brief Uses the given density. PLAYRHO_CONSTEXPR inline ConcreteConf& UseDensity(NonNegative value) noexcept; - - /// @brief Uses the given vertex radius. - /// @note Intended for namewise backward compatibility. - PLAYRHO_CONSTEXPR inline ConcreteConf& SetVertexRadius(Length v) noexcept; - - /// @brief Uses the given restitution. - /// @note Intended for namewise backward compatibility. - PLAYRHO_CONSTEXPR inline ConcreteConf& SetRestitution(Real v) noexcept; - - /// @brief Uses the given friction. - /// @note Intended for namewise backward compatibility. - PLAYRHO_CONSTEXPR inline ConcreteConf& SetFriction(Real v) noexcept; - - /// @brief Uses the given density. - /// @note Intended for namewise backward compatibility. - PLAYRHO_CONSTEXPR inline ConcreteConf& SetDensity(AreaDensity v) noexcept; }; template @@ -149,43 +133,37 @@ ShapeDefBuilder::UseDensity(NonNegative value) noexce return static_cast(*this); } -template -PLAYRHO_CONSTEXPR inline ConcreteConf& -ShapeDefBuilder::SetVertexRadius(Length v) noexcept +/// @brief Shape configuration structure. +struct ShapeConf: public ShapeDefBuilder { - vertexRadius = v; - return static_cast(*this); -} + using ShapeDefBuilder::ShapeDefBuilder; +}; -template -PLAYRHO_CONSTEXPR inline ConcreteConf& -ShapeDefBuilder::SetRestitution(Real v) noexcept +// Free functions... + +/// @brief Gets the vertex radius of the given shape configuration. +PLAYRHO_CONSTEXPR inline NonNegative GetVertexRadius(const ShapeDef& arg) noexcept { - restitution = v; - return static_cast(*this); + return arg.vertexRadius; } -template -PLAYRHO_CONSTEXPR inline ConcreteConf& -ShapeDefBuilder::SetFriction(Real v) noexcept +/// @brief Gets the density of the given shape configuration. +PLAYRHO_CONSTEXPR inline NonNegative GetDensity(const ShapeDef& arg) noexcept { - friction = v; - return static_cast(*this); + return arg.density; } -template -PLAYRHO_CONSTEXPR inline ConcreteConf& -ShapeDefBuilder::SetDensity(AreaDensity v) noexcept +/// @brief Gets the restitution of the given shape configuration. +PLAYRHO_CONSTEXPR inline Finite GetRestitution(const ShapeDef& arg) noexcept { - density = v; - return static_cast(*this); + return arg.restitution; } -/// @brief Shape configuration structure. -struct ShapeConf: public ShapeDefBuilder +/// @brief Gets the friction of the given shape configuration. +PLAYRHO_CONSTEXPR inline NonNegative GetFriction(const ShapeDef& arg) noexcept { - using ShapeDefBuilder::ShapeDefBuilder; -}; + return arg.friction; +} } // namespace playrho diff --git a/PlayRho/Collision/Shapes/ShapeVisitor.hpp b/PlayRho/Collision/Shapes/ShapeVisitor.hpp deleted file mode 100644 index 0533583016..0000000000 --- a/PlayRho/Collision/Shapes/ShapeVisitor.hpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PLAYRHO_COLLISION_SHAPES_SHAPEVISITOR_HPP -#define PLAYRHO_COLLISION_SHAPES_SHAPEVISITOR_HPP - -namespace playrho { - -class DiskShape; -class EdgeShape; -class PolygonShape; -class ChainShape; -class MultiShape; - -/// @brief Vistor interface for Shape instances. -/// -/// @details Interface to inherit from for objects wishing to "visit" shapes. -/// This uses the visitor design pattern. -/// @sa https://en.wikipedia.org/wiki/Visitor_pattern . -/// -class ShapeVisitor -{ -public: - virtual ~ShapeVisitor() = default; - - /// @brief Visits a DiskShape. - virtual void Visit(const DiskShape& shape) = 0; - - /// @brief Visits an EdgeShape. - virtual void Visit(const EdgeShape& shape) = 0; - - /// @brief Visits a PolygonShape. - virtual void Visit(const PolygonShape& shape) = 0; - - /// @brief Visits a ChainShape. - virtual void Visit(const ChainShape& shape) = 0; - - /// @brief Visits a MultiShape. - virtual void Visit(const MultiShape& shape) = 0; - -protected: - ShapeVisitor() = default; - - /// @brief Copy constructor. - ShapeVisitor(const ShapeVisitor& other) = default; - - /// @brief Move constructor. - ShapeVisitor(ShapeVisitor&& other) = default; - - /// @brief Copy assignment operator. - ShapeVisitor& operator= (const ShapeVisitor& other) = default; - - /// @brief Move assignment operator. - ShapeVisitor& operator= (ShapeVisitor&& other) = default; -}; - -/// @brief A ShapeVisitor implementation that reports whether it's been visited. -/// @sa ShapeVisitor -class IsVisitedShapeVisitor: public ShapeVisitor -{ -public: - - IsVisitedShapeVisitor() = default; - - /// @brief Copy constructor. - IsVisitedShapeVisitor(const IsVisitedShapeVisitor& other) = default; - - /// @brief Move constructor. - IsVisitedShapeVisitor(IsVisitedShapeVisitor&& other) = default; - - ~IsVisitedShapeVisitor() override = default; - - /// @brief Copy assignment operator. - IsVisitedShapeVisitor& operator= (const IsVisitedShapeVisitor& other) = default; - - /// @brief Move assignment operator. - IsVisitedShapeVisitor& operator= (IsVisitedShapeVisitor&& other) = default; - - /// @brief Visits a DiskShape. - void Visit(const DiskShape& /*shape*/) override - { - visited = true; - } - - /// @brief Visits an EdgeShape. - void Visit(const EdgeShape& /*shape*/) override - { - visited = true; - } - - /// @brief Visits a PolygonShape. - void Visit(const PolygonShape& /*shape*/) override - { - visited = true; - } - - /// @brief Visits a ChainShape. - void Visit(const ChainShape& /*shape*/) override - { - visited = true; - } - - /// @brief Visits a MultiShape. - void Visit(const MultiShape& /*shape*/) override - { - visited = true; - } - - /// @brief Whether this visitor has been visited. - bool IsVisited() const noexcept - { - return visited; - } - -private: - bool visited = false; ///< Visited flag. -}; - -} // namespace playrho - -#endif // PLAYRHO_COLLISION_SHAPES_SHAPEVISITOR_HPP diff --git a/PlayRho/Collision/WorldManifold.cpp b/PlayRho/Collision/WorldManifold.cpp index 2ea0a95bfb..c1619fa60a 100644 --- a/PlayRho/Collision/WorldManifold.cpp +++ b/PlayRho/Collision/WorldManifold.cpp @@ -126,11 +126,11 @@ WorldManifold GetWorldManifold(const Contact& contact) { const auto fA = contact.GetFixtureA(); const auto xfA = GetTransformation(*fA); - const auto radiusA = GetVertexRadius(*(fA->GetShape())); + const auto radiusA = GetVertexRadius(fA->GetShape()); const auto fB = contact.GetFixtureB(); const auto xfB = GetTransformation(*fB); - const auto radiusB = GetVertexRadius(*(fB->GetShape())); + const auto radiusB = GetVertexRadius(fB->GetShape()); return GetWorldManifold(contact.GetManifold(), xfA, radiusA, xfB, radiusB); } diff --git a/PlayRho/Common/CodeDumper.cpp b/PlayRho/Common/CodeDumper.cpp index 9d34a0a24b..0336ad5580 100644 --- a/PlayRho/Common/CodeDumper.cpp +++ b/PlayRho/Common/CodeDumper.cpp @@ -36,12 +36,12 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include -#include #include @@ -58,17 +58,41 @@ namespace va_end(args); } - class ShapeDumper: public ShapeVisitor + class ShapeDumper { public: - void Visit(const DiskShape& shape) override; - void Visit(const EdgeShape& shape) override; - void Visit(const PolygonShape& shape) override; - void Visit(const ChainShape& shape) override; - void Visit(const MultiShape& shape) override; + void operator() (const std::type_info& ti, const void* data) + { + if (ti == typeid(DiskShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(EdgeShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(PolygonShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(ChainShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(MultiShapeConf)) + { + Visit(*static_cast(data)); + } + } + + void Visit(const DiskShapeConf& shape); + void Visit(const EdgeShapeConf& shape); + void Visit(const PolygonShapeConf& shape); + void Visit(const ChainShapeConf& shape); + void Visit(const MultiShapeConf& shape); }; - void ShapeDumper::Visit(const playrho::DiskShape& s) + void ShapeDumper::Visit(const playrho::DiskShapeConf& s) { log(" DiskShape shape;\n"); log(" shape.m_radius = %.15lef;\n", static_cast(StripUnit(s.GetRadius()))); @@ -77,19 +101,19 @@ namespace static_cast(StripUnit(Get<1>(s.GetLocation())))); } - void ShapeDumper::Visit(const playrho::EdgeShape& s) + void ShapeDumper::Visit(const playrho::EdgeShapeConf& s) { log(" EdgeShape shape;\n"); - log(" shape.m_radius = %.15lef;\n", static_cast(StripUnit(GetVertexRadius(s)))); + log(" shape.m_radius = %.15lef;\n", static_cast(StripUnit(s.vertexRadius))); log(" shape.m_vertex1.Set(%.15lef, %.15lef);\n", - static_cast(StripUnit(Get<0>(s.GetVertex1()))), - static_cast(StripUnit(Get<1>(s.GetVertex1())))); + static_cast(StripUnit(Get<0>(s.GetVertexA()))), + static_cast(StripUnit(Get<1>(s.GetVertexA())))); log(" shape.m_vertex2.Set(%.15lef, %.15lef);\n", - static_cast(StripUnit(Get<0>(s.GetVertex2()))), - static_cast(StripUnit(Get<1>(s.GetVertex2())))); + static_cast(StripUnit(Get<0>(s.GetVertexB()))), + static_cast(StripUnit(Get<1>(s.GetVertexB())))); } - void ShapeDumper::Visit(const playrho::PolygonShape& s) + void ShapeDumper::Visit(const playrho::PolygonShapeConf& s) { const auto vertexCount = s.GetVertexCount(); log(" PolygonShape shape;\n"); @@ -103,7 +127,7 @@ namespace log(" shape.Set(vs, %d);\n", vertexCount); } - void ShapeDumper::Visit(const playrho::ChainShape& s) + void ShapeDumper::Visit(const playrho::ChainShapeConf& s) { log(" ChainShape shape;\n"); log(" Vec2 vs[%d];\n", s.GetVertexCount()); @@ -116,7 +140,7 @@ namespace log(" shape.CreateChain(vs, %d);\n", s.GetVertexCount()); } - void ShapeDumper::Visit(const playrho::MultiShape&) + void ShapeDumper::Visit(const playrho::MultiShapeConf&) { // TODO } @@ -251,7 +275,9 @@ void playrho::Dump(const Fixture& fixture, std::size_t bodyIndex) const auto shape = fixture.GetShape(); ShapeDumper shapeDumper; - shape->Accept(shapeDumper); + Accept(shape, [&](const std::type_info& ti, const void* data) { + shapeDumper(ti, data); + }); log("\n"); log(" fd.shape = &shape;\n"); diff --git a/PlayRho/Dynamics/Body.cpp b/PlayRho/Dynamics/Body.cpp index 7c4d7fe268..67e229854e 100644 --- a/PlayRho/Dynamics/Body.cpp +++ b/PlayRho/Dynamics/Body.cpp @@ -111,7 +111,7 @@ void Body::SetType(BodyType type) m_world->SetType(*this, type); } -Fixture* Body::CreateFixture(const std::shared_ptr& shape, const FixtureDef& def, +Fixture* Body::CreateFixture(const Shape& shape, const FixtureDef& def, bool resetMassData) { return m_world->CreateFixture(*this, shape, def, resetMassData); diff --git a/PlayRho/Dynamics/Body.hpp b/PlayRho/Dynamics/Body.hpp index 3c82f6d481..3253927eac 100644 --- a/PlayRho/Dynamics/Body.hpp +++ b/PlayRho/Dynamics/Body.hpp @@ -168,7 +168,7 @@ class Body /// /// @sa PhysicalEntities /// - Fixture* CreateFixture(const std::shared_ptr& shape, + Fixture* CreateFixture(const Shape& shape, const FixtureDef& def = GetDefaultFixtureDef(), bool resetMassData = true); diff --git a/PlayRho/Dynamics/BodyAtty.hpp b/PlayRho/Dynamics/BodyAtty.hpp index 21b2db52f3..2e0880c2f6 100644 --- a/PlayRho/Dynamics/BodyAtty.hpp +++ b/PlayRho/Dynamics/BodyAtty.hpp @@ -48,7 +48,7 @@ class BodyAtty private: /// @brief Creates a fixture. - static Fixture* CreateFixture(Body& b, std::shared_ptr shape, const FixtureDef& def) + static Fixture* CreateFixture(Body& b, Shape shape, const FixtureDef& def) { const auto fixture = new Fixture{&b, def, std::move(shape)}; b.m_fixtures.push_back(fixture); diff --git a/PlayRho/Dynamics/Contacts/Contact.cpp b/PlayRho/Dynamics/Contacts/Contact.cpp index 64d035b65a..b326cdeb73 100644 --- a/PlayRho/Dynamics/Contacts/Contact.cpp +++ b/PlayRho/Dynamics/Contacts/Contact.cpp @@ -63,8 +63,6 @@ Contact::Contact(Fixture* fA, ChildCounter iA, Fixture* fB, ChildCounter iB): m_restitution{MixRestitution(fA->GetRestitution(), fB->GetRestitution())} { assert(fA != fB); - assert(fA->GetShape()); - assert(fB->GetShape()); assert(fA->GetBody() != fB->GetBody()); } @@ -94,14 +92,14 @@ void Contact::Update(const UpdateConf& conf, ContactListener* listener) const auto xfA = fixtureA->GetBody()->GetTransformation(); const auto shapeB = fixtureB->GetShape(); const auto xfB = fixtureB->GetBody()->GetTransformation(); - const auto childA = shapeA->GetChild(indexA); - const auto childB = shapeB->GetChild(indexB); + const auto childA = GetChild(shapeA, indexA); + const auto childB = GetChild(shapeB, indexB); // NOTE: Ideally, the touching state returned by the TestOverlap function // agrees 100% of the time with that returned from the CollideShapes function. // This is not always the case however especially as the separation or overlap // approaches zero. -#define OVERLAP_TOLERANCE (SquareMeter / Real(1e3)) +#define OVERLAP_TOLERANCE (SquareMeter / Real(20)) const auto sensor = fixtureA->IsSensor() || fixtureB->IsSensor(); if (sensor) @@ -299,8 +297,8 @@ TOIOutput CalcToi(const Contact& contact, ToiConf conf) const auto bA = fA->GetBody(); const auto bB = fB->GetBody(); - const auto proxyA = fA->GetShape()->GetChild(contact.GetChildIndexA()); - const auto proxyB = fB->GetShape()->GetChild(contact.GetChildIndexB()); + const auto proxyA = GetChild(fA->GetShape(), contact.GetChildIndexA()); + const auto proxyB = GetChild(fB->GetShape(), contact.GetChildIndexB()); // Large rotations can make the root finder of TimeOfImpact fail, so normalize sweep angles. const auto sweepA = GetNormalized(bA->GetSweep()); diff --git a/PlayRho/Dynamics/Fixture.cpp b/PlayRho/Dynamics/Fixture.cpp index 8b9347d51e..591f9499a0 100644 --- a/PlayRho/Dynamics/Fixture.cpp +++ b/PlayRho/Dynamics/Fixture.cpp @@ -59,21 +59,6 @@ Fixture::Fixture(const Fixture& other): } } -AreaDensity Fixture::GetDensity() const noexcept -{ - return m_shape->GetDensity(); -} - -Real Fixture::GetFriction() const noexcept -{ - return m_shape->GetFriction(); -} - -Real Fixture::GetRestitution() const noexcept -{ - return m_shape->GetRestitution(); -} - FixtureProxy Fixture::GetProxy(ChildCounter index) const noexcept { assert(index < GetProxyCount()); @@ -122,7 +107,7 @@ void Fixture::SetSensor(bool sensor) noexcept bool TestPoint(const Fixture& f, Length2 p) noexcept { - return TestPoint(*f.GetShape(), InverseTransform(p, GetTransformation(f))); + return TestPoint(f.GetShape(), InverseTransform(p, GetTransformation(f))); } void SetAwake(const Fixture& f) noexcept diff --git a/PlayRho/Dynamics/Fixture.hpp b/PlayRho/Dynamics/Fixture.hpp index 89222cf838..c6621b962b 100644 --- a/PlayRho/Dynamics/Fixture.hpp +++ b/PlayRho/Dynamics/Fixture.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ namespace playrho { class Body; -class Shape; /// @brief An association between a body and a shape. /// @@ -74,14 +74,14 @@ class Fixture /// AreaDensity must be greater-than-or-equal-to zero. /// @param shape Sharable shape to associate fixture with. Must be non-null. /// - Fixture(NonNull body, const FixtureDef& def, const std::shared_ptr& shape): + Fixture(NonNull body, const FixtureDef& def, const Shape& shape): m_body{body}, m_userData{def.userData}, m_shape{shape}, m_filter{def.filter}, m_isSensor{def.isSensor} { - assert(shape); + // Intentionally empty. } /// @brief Copy constructor. @@ -101,7 +101,7 @@ class Fixture /// @brief Gets the child shape. /// @details The shape is not modifiable. Use a new fixture instead. - std::shared_ptr GetShape() const noexcept; + Shape GetShape() const noexcept; /// @brief Set if this fixture is a sensor. void SetSensor(bool sensor) noexcept; @@ -185,7 +185,7 @@ class Fixture /// @note Set on construction. /// @note Either null or pointer to a heap-memory private copy of the assigned shape. /// @note 16-bytes. - std::shared_ptr m_shape; + Shape m_shape; FixtureProxies m_proxies; ///< Collection of fixture proxies for the assigned shape. 8-bytes. @@ -198,7 +198,7 @@ class Fixture bool m_isSensor = false; ///< Is/is-not sensor. 1-bytes. }; -inline std::shared_ptr Fixture::GetShape() const noexcept +inline Shape Fixture::GetShape() const noexcept { return m_shape; } @@ -274,6 +274,21 @@ inline void Fixture::ResetProxies() noexcept m_proxyCount = 0; } +inline Real Fixture::GetFriction() const noexcept +{ + return playrho::GetFriction(m_shape); +} + +inline Real Fixture::GetRestitution() const noexcept +{ + return playrho::GetRestitution(m_shape); +} + +inline AreaDensity Fixture::GetDensity() const noexcept +{ + return playrho::GetDensity(m_shape); +} + // Free functions... /// @brief Tests a point for containment in a fixture. diff --git a/PlayRho/Dynamics/FixtureAtty.hpp b/PlayRho/Dynamics/FixtureAtty.hpp index 829e405d58..fb7156c974 100644 --- a/PlayRho/Dynamics/FixtureAtty.hpp +++ b/PlayRho/Dynamics/FixtureAtty.hpp @@ -63,7 +63,7 @@ class FixtureAtty /// @brief Creates a new fixture for the given body and with the given settings. static auto Create(Body* body, const FixtureDef& def, - const std::shared_ptr& shape) + const Shape& shape) { return new Fixture{body, def, shape}; } diff --git a/PlayRho/Dynamics/World.cpp b/PlayRho/Dynamics/World.cpp index 5c22a036ab..1d19743696 100644 --- a/PlayRho/Dynamics/World.cpp +++ b/PlayRho/Dynamics/World.cpp @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include #include @@ -303,8 +303,8 @@ namespace { const auto bodyConstraintA = At(bodies, bodyA); const auto bodyConstraintB = At(bodies, bodyB); - const auto radiusA = GetVertexRadius(*shapeA); - const auto radiusB = GetVertexRadius(*shapeB); + const auto radiusA = GetVertexRadius(shapeA); + const auto radiusB = GetVertexRadius(shapeB); return PositionConstraint{ manifold, *bodyConstraintA, radiusA, *bodyConstraintB, radiusB @@ -344,8 +344,8 @@ namespace { const auto bodyConstraintA = At(bodies, bodyA); const auto bodyConstraintB = At(bodies, bodyB); - const auto radiusA = shapeA->GetVertexRadius(); - const auto radiusB = shapeB->GetVertexRadius(); + const auto radiusA = GetVertexRadius(shapeA); + const auto radiusB = GetVertexRadius(shapeB); const auto xfA = GetTransformation(bodyConstraintA->GetPosition(), bodyConstraintA->GetLocalCenter()); @@ -1990,7 +1990,7 @@ void World::RayCast(Length2 point1, Length2 point2, RayCastCallback callback) co const auto index = leafData.childIndex; const auto shape = fixture->GetShape(); const auto body = fixture->GetBody(); - const auto child = shape->GetChild(index); + const auto child = GetChild(shape, index); const auto transformation = body->GetTransformation(); const auto output = playrho::RayCast(child, input, transformation); if (output.has_value()) @@ -2548,7 +2548,7 @@ void World::SetType(Body& body, BodyType type) } } -Fixture* World::CreateFixture(Body& body, const std::shared_ptr& shape, +Fixture* World::CreateFixture(Body& body, const Shape& shape, const FixtureDef& def, bool resetMassData) { if (body.GetWorld() != this) @@ -2556,11 +2556,7 @@ Fixture* World::CreateFixture(Body& body, const std::shared_ptr& sh throw InvalidArgument("World::CreateFixture: invalid body"); } - if (!shape) - { - throw InvalidArgument("World::CreateFixture: null shape"); - } - const auto vr = GetVertexRadius(*shape); + const auto vr = GetVertexRadius(shape); if (!(vr >= GetMinVertexRadius())) { throw InvalidArgument("World::CreateFixture: vertex radius < min"); @@ -2665,11 +2661,11 @@ void World::CreateProxies(Fixture& fixture, Length aabbExtension) const auto xfm = GetTransformation(fixture); // Reserve proxy space and create proxies in the broad-phase. - const auto childCount = shape->GetChildCount(); + const auto childCount = GetChildCount(shape); auto proxies = std::make_unique(childCount); for (auto childIndex = decltype(childCount){0}; childIndex < childCount; ++childIndex) { - const auto dp = shape->GetChild(childIndex); + const auto dp = GetChild(shape, childIndex); const auto aabb = ComputeAABB(dp, xfm); // Note: treeId from CreateLeaf can be higher than the number of fixture proxies. @@ -2757,7 +2753,7 @@ ContactCounter World::Synchronize(Fixture& fixture, const auto treeId = proxy.treeId; // Compute an AABB that covers the swept shape (may miss some rotation effect). - const auto aabb = ComputeAABB(shape->GetChild(childIndex), xfm1, xfm2); + const auto aabb = ComputeAABB(GetChild(shape, childIndex), xfm1, xfm2); if (!Contains(m_tree.GetAABB(treeId), aabb)) { const auto newAabb = GetDisplacedAABB(GetFattenedAABB(aabb, extension), @@ -2810,11 +2806,11 @@ size_t GetFixtureCount(const World& world) noexcept size_t GetShapeCount(const World& world) noexcept { - auto shapes = std::set(); + auto shapes = std::set(); for_each(cbegin(world.GetBodies()), cend(world.GetBodies()), [&](const World::Bodies::value_type &b) { const auto fixtures = GetRef(b).GetFixtures(); for_each(cbegin(fixtures), cend(fixtures), [&](const Body::Fixtures::value_type& f) { - shapes.insert(GetRef(f).GetShape().get()); + shapes.insert(GetData(GetRef(f).GetShape())); }); }); return shapes.size(); @@ -2858,7 +2854,7 @@ Body* CreateRectangularEnclosingBody(World& world, Length2 dimensions, const Sha { const auto body = world.CreateBody(); - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.restitution = baseConf.restitution; conf.vertexRadius = baseConf.vertexRadius; conf.friction = baseConf.friction; @@ -2871,13 +2867,13 @@ Body* CreateRectangularEnclosingBody(World& world, Length2 dimensions, const Sha const auto topLeft = Length2(-halfWidth, +halfHeight); const auto topRight = Length2(+halfWidth, +halfHeight); - conf.vertices.push_back(btmRight); - conf.vertices.push_back(topRight); - conf.vertices.push_back(topLeft); - conf.vertices.push_back(btmLeft); - conf.vertices.push_back(conf.vertices[0]); + conf.Add(btmRight); + conf.Add(topRight); + conf.Add(topLeft); + conf.Add(btmLeft); + conf.Add(conf.GetVertex(0)); - body->CreateFixture(std::make_shared(conf)); + body->CreateFixture(Shape{conf}); return body; } diff --git a/PlayRho/Dynamics/World.hpp b/PlayRho/Dynamics/World.hpp index 258254f9a9..7c61efaa8f 100644 --- a/PlayRho/Dynamics/World.hpp +++ b/PlayRho/Dynamics/World.hpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -321,7 +322,7 @@ class World /// @throws InvalidArgument if called for a shape with a vertex radius greater than the /// maximum vertex radius. /// @throws WrongState if this method is called while the world is locked. - Fixture* CreateFixture(Body& body, const std::shared_ptr& shape, + Fixture* CreateFixture(Body& body, const Shape& shape, const FixtureDef& def = GetDefaultFixtureDef(), bool resetMassData = true); diff --git a/PlayRho/PlayRho.hpp b/PlayRho/PlayRho.hpp index fa167bcd00..bc0fa07aef 100644 --- a/PlayRho/PlayRho.hpp +++ b/PlayRho/PlayRho.hpp @@ -56,11 +56,11 @@ For mathemtical insight, see: #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include diff --git a/Testbed/Framework/Main.cpp b/Testbed/Framework/Main.cpp index 08ed066030..3bee57a6cd 100644 --- a/Testbed/Framework/Main.cpp +++ b/Testbed/Framework/Main.cpp @@ -1143,11 +1143,11 @@ static void EntityUI(const Shape& shape) { ImGui::ItemWidthContext itemWidthCtx(60); - const auto density = shape.GetDensity(); - const auto vertexRadius = shape.GetVertexRadius(); - const auto friction = shape.GetFriction(); - const auto restitution = shape.GetRestitution(); - const auto childCount = shape.GetChildCount(); + const auto density = GetDensity(shape); + const auto vertexRadius = GetVertexRadius(shape); + const auto friction = GetFriction(shape); + const auto restitution = GetRestitution(shape); + const auto childCount = GetChildCount(shape); ImGui::LabelText("Density (kg/m^2)", "%.2e", static_cast(Real{density * SquareMeter / Kilogram})); @@ -1245,10 +1245,10 @@ static void EntityUI(Fixture& fixture) } { - const auto shape = fixture.GetShape().get(); - if (ImGui::TreeNodeEx(shape, 0, "Shape/Part")) + const auto& shape = fixture.GetShape(); + if (ImGui::TreeNodeEx(&shape, 0, "Shape/Part")) { - EntityUI(*shape); + EntityUI(shape); ImGui::TreePop(); } } diff --git a/Testbed/Framework/Test.cpp b/Testbed/Framework/Test.cpp index 53d0a7a534..95b52f869c 100644 --- a/Testbed/Framework/Test.cpp +++ b/Testbed/Framework/Test.cpp @@ -46,7 +46,7 @@ static void DrawCorner(Drawer& drawer, Length2 p, Length r, Angle a0, Angle a1, } } -class ShapeDrawer: public ShapeVisitor +class ShapeDrawer { public: ShapeDrawer(Drawer& d, Color c, bool s, Transformation t): @@ -54,12 +54,36 @@ class ShapeDrawer: public ShapeVisitor { // Intentionally empty. } - - void Visit(const DiskShape& shape) override; - void Visit(const EdgeShape& shape) override; - void Visit(const PolygonShape& shape) override; - void Visit(const ChainShape& shape) override; - void Visit(const MultiShape& shape) override; + + void operator() (const std::type_info& ti, const void* data) + { + if (ti == typeid(DiskShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(EdgeShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(PolygonShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(ChainShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(MultiShapeConf)) + { + Visit(*static_cast(data)); + } + } + + void Visit(const DiskShapeConf& shape); + void Visit(const EdgeShapeConf& shape); + void Visit(const PolygonShapeConf& shape); + void Visit(const ChainShapeConf& shape); + void Visit(const MultiShapeConf& shape); void Draw(const DistanceProxy& proxy); @@ -69,7 +93,7 @@ class ShapeDrawer: public ShapeVisitor Transformation xf; }; -void ShapeDrawer::Visit(const DiskShape& shape) +void ShapeDrawer::Visit(const DiskShapeConf& shape) { const auto center = Transform(shape.GetLocation(), xf); const auto radius = shape.GetRadius(); @@ -82,15 +106,15 @@ void ShapeDrawer::Visit(const DiskShape& shape) drawer.DrawSegment(center, center + radius * axis, color); } -void ShapeDrawer::Visit(const EdgeShape& shape) +void ShapeDrawer::Visit(const EdgeShapeConf& shape) { - const auto v1 = Transform(shape.GetVertex1(), xf); - const auto v2 = Transform(shape.GetVertex2(), xf); + const auto v1 = Transform(shape.GetVertexA(), xf); + const auto v2 = Transform(shape.GetVertexB(), xf); drawer.DrawSegment(v1, v2, color); if (skins) { - const auto r = shape.GetVertexRadius(); + const auto r = GetVertexRadius(shape); if (r > 0_m) { const auto skinColor = Color{color.r * 0.6f, color.g * 0.6f, color.b * 0.6f}; @@ -107,10 +131,10 @@ void ShapeDrawer::Visit(const EdgeShape& shape) } } -void ShapeDrawer::Visit(const ChainShape& shape) +void ShapeDrawer::Visit(const ChainShapeConf& shape) { const auto count = shape.GetVertexCount(); - const auto r = shape.GetVertexRadius(); + const auto r = GetVertexRadius(shape); const auto skinColor = Color{color.r * 0.6f, color.g * 0.6f, color.b * 0.6f}; auto v1 = Transform(shape.GetVertex(0), xf); @@ -151,7 +175,7 @@ void ShapeDrawer::Draw(const DistanceProxy& shape) } const auto skinColor = Color{color.r * 0.6f, color.g * 0.6f, color.b * 0.6f}; - const auto r = shape.GetVertexRadius(); + const auto r = GetVertexRadius(shape); for (auto i = decltype(vertexCount){0}; i < vertexCount; ++i) { if (i > 0) @@ -182,17 +206,17 @@ void ShapeDrawer::Draw(const DistanceProxy& shape) } } -void ShapeDrawer::Visit(const PolygonShape& shape) +void ShapeDrawer::Visit(const PolygonShapeConf& shape) { - Draw(shape.GetChild(0)); + Draw(GetChild(shape, 0)); } -void ShapeDrawer::Visit(const MultiShape& shape) +void ShapeDrawer::Visit(const MultiShapeConf& shape) { - const auto count = shape.GetChildCount(); + const auto count = GetChildCount(shape); for (auto i = decltype(count){0}; i < count; ++i) { - Draw(shape.GetChild(i)); + Draw(GetChild(shape, i)); } } @@ -201,7 +225,9 @@ static void Draw(Drawer& drawer, const Fixture& fixture, const Color& color, boo const auto xf = GetTransformation(fixture); auto shapeDrawer = ShapeDrawer{drawer, color, skins, xf}; const auto shape = fixture.GetShape(); - shape->Accept(shapeDrawer); + Accept(shape, [&](const std::type_info& ti, const void* data) { + shapeDrawer(ti, data); + }); } static Color GetColor(const Body& body) @@ -601,11 +627,11 @@ void Test::LaunchBomb(const Length2& at, const LinearVelocity2 v) m_bomb = m_world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic).UseBullet(true) .UseLocation(at).UseLinearVelocity(v)); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = m_bombRadius; conf.density = m_bombDensity; conf.restitution = 0.0f; - m_bomb->CreateFixture(std::make_shared(conf)); + m_bomb->CreateFixture(Shape{conf}); } static void ShowHelpMarker(const char* desc) diff --git a/Testbed/Framework/Test.hpp b/Testbed/Framework/Test.hpp index 8198061f72..ac6525b420 100644 --- a/Testbed/Framework/Test.hpp +++ b/Testbed/Framework/Test.hpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -192,9 +191,9 @@ class Test : public ContactListener protected: - EdgeShape::Conf GetGroundEdgeConf() const noexcept + EdgeShapeConf GetGroundEdgeConf() const noexcept { - return EdgeShape::Conf{}.UseVertex1(Vec2(-40, 0) * 1_m).UseVertex2(Vec2(40, 0) * 1_m); + return EdgeShapeConf{}.Set(Vec2(-40, 0) * 1_m, Vec2(40, 0) * 1_m); } struct Conf diff --git a/Testbed/Framework/TestEntry.cpp b/Testbed/Framework/TestEntry.cpp index 7b075e255c..1b1db09c71 100644 --- a/Testbed/Framework/TestEntry.cpp +++ b/Testbed/Framework/TestEntry.cpp @@ -100,7 +100,7 @@ static const TestEntry testEntries[] = {"Basic Slider Crank", MakeUniqueTest}, {"Slider Crank", MakeUniqueTest}, {"Sphere Stack", MakeUniqueTest}, - {"Convex Hull", MakeUniqueTest}, + {"Convex Hull", MakeUniqueTest}, {"Tumbler", MakeUniqueTest}, {"Ray-Cast", MakeUniqueTest}, {"Dump Shell", MakeUniqueTest}, diff --git a/Testbed/Tests/AddPair.hpp b/Testbed/Tests/AddPair.hpp index 9cbd683e53..05e8c2d27a 100644 --- a/Testbed/Tests/AddPair.hpp +++ b/Testbed/Tests/AddPair.hpp @@ -38,35 +38,25 @@ class AddPair : public Test { m_world.SetGravity(LinearAcceleration2{}); { - const auto conf = DiskShape::Conf{}.UseVertexRadius(1_dm).UseDensity(0.01_kgpm2); - const auto shape = std::make_shared(conf); - + const auto conf = DiskShapeConf{}.UseRadius(1_dm).UseDensity(0.01_kgpm2); const auto minX = -6.0f; const auto maxX = 0.0f; const auto minY = 4.0f; const auto maxY = 6.0f; - const auto bd = BodyDef{}.UseType(BodyType::Dynamic); for (auto i = 0; i < 400; ++i) { const auto location = Vec2(RandomFloat(minX, maxX), RandomFloat(minY, maxY)) * 1_m; // Use () instead of {} to avoid MSVC++ doing const preserving copy elision. const auto body = m_world.CreateBody(BodyDef(bd).UseLocation(location)); - body->CreateFixture(shape); + body->CreateFixture(Shape{conf}); } } - - { - const auto bd = BodyDef{} - .UseType(BodyType::Dynamic) - .UseBullet(true) - .UseLocation(Length2{-40_m, 5_m}) - .UseLinearVelocity(LinearVelocity2{150_mps, 0_mps}); - const auto body = m_world.CreateBody(bd); - - const auto conf = PolygonShape::Conf{}.UseDensity(1.0_kgpm2); - body->CreateFixture(std::make_shared(1.5_m, 1.5_m, conf)); - } + const auto bd = BodyDef{}.UseType(BodyType::Dynamic).UseBullet(true) + .UseLocation(Length2{-40_m, 5_m}).UseLinearVelocity(LinearVelocity2{150_mps, 0_mps}); + const auto body = m_world.CreateBody(bd); + const auto conf = PolygonShapeConf{}.UseDensity(1.0_kgpm2).SetAsBox(1.5_m, 1.5_m); + body->CreateFixture(Shape{conf}); } }; diff --git a/Testbed/Tests/ApplyForce.hpp b/Testbed/Tests/ApplyForce.hpp index 0dcca5b837..367bfbf69c 100644 --- a/Testbed/Tests/ApplyForce.hpp +++ b/Testbed/Tests/ApplyForce.hpp @@ -53,25 +53,25 @@ class ApplyForce : public Test bd.location = Length2(0_m, 20_m); ground = m_world.CreateBody(bd); - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.density = 0; conf.restitution = k_restitution; // Left vertical conf.Set(Length2{-20_m, -20_m}, Length2{-20_m, 20_m}); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape{conf}); // Right vertical conf.Set(Length2{20_m, -20_m}, Length2{20_m, 20_m}); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape{conf}); // Top horizontal conf.Set(Length2{-20_m, 20_m}, Length2{20_m, 20_m}); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape{conf}); // Bottom horizontal conf.Set(Length2{-20_m, -20_m}, Length2{20_m, -20_m}); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape{conf}); } { @@ -84,10 +84,10 @@ class ApplyForce : public Test vertices[1] = Transform(Length2{1_m, 0_m}, xf1); vertices[2] = Transform(Length2{0_m, 0.5_m}, xf1); - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 4_kgpm2; - const auto poly1 = PolygonShape(Span(vertices, 3), conf); + const auto poly1 = PolygonShapeConf(Span(vertices, 3), conf); Transformation xf2; xf2.q = UnitVec2::Get(-0.3524_rad * Pi); @@ -98,7 +98,7 @@ class ApplyForce : public Test vertices[2] = Transform(Length2{0_m, 0.5_m}, xf2); conf.density = 2_kgpm2; - const auto poly2 = PolygonShape(Span(vertices, 3), conf); + const auto poly2 = PolygonShapeConf(Span(vertices, 3), conf); BodyDef bd; bd.type = BodyType::Dynamic; @@ -108,15 +108,16 @@ class ApplyForce : public Test bd.angle = Pi * 1_rad; bd.allowSleep = false; m_body = m_world.CreateBody(bd); - m_body->CreateFixture(std::make_shared(poly1)); - m_body->CreateFixture(std::make_shared(poly2)); + m_body->CreateFixture(Shape(poly1)); + m_body->CreateFixture(Shape(poly2)); } { - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 1_kgpm2; conf.friction = Real{0.3f}; - const auto shape = std::make_shared(0.5_m, 0.5_m, conf); + conf.SetAsBox(0.5_m, 0.5_m); + const auto shape = Shape(conf); const auto gravity = LinearAcceleration{10_mps2}; for (auto i = 0; i < 10; ++i) diff --git a/Testbed/Tests/BagOfDisks.hpp b/Testbed/Tests/BagOfDisks.hpp index 1c5edf26a4..2223848cdd 100644 --- a/Testbed/Tests/BagOfDisks.hpp +++ b/Testbed/Tests/BagOfDisks.hpp @@ -53,25 +53,24 @@ namespace playrho { SetAngularVelocity(*m_ground, angularVelocity - 0.1_rad / Second); }); - auto boundaryConf = ChainShape::Conf{}.UseFriction(Real(100)); + auto boundaryConf = ChainShapeConf{}.UseFriction(Real(100)); boundaryConf.UseVertexRadius(0.04_m); - boundaryConf.vertices.push_back(Vec2(-12, +20) * 1_m); - boundaryConf.vertices.push_back(Vec2(-12, +0) * 1_m); - boundaryConf.vertices.push_back(Vec2(+12, +0) * 1_m); - boundaryConf.vertices.push_back(Vec2(+12, +20) * 1_m); - m_ground->CreateFixture(std::make_shared(boundaryConf)); + boundaryConf.Add(Vec2(-12, +20) * 1_m); + boundaryConf.Add(Vec2(-12, +0) * 1_m); + boundaryConf.Add(Vec2(+12, +0) * 1_m); + boundaryConf.Add(Vec2(+12, +20) * 1_m); + m_ground->CreateFixture(Shape(boundaryConf)); const auto vertices = GetCircleVertices(10_m, 90); const auto halfSegmentLength = GetMagnitude(vertices[1] - vertices[0]) / 2; - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.vertexRadius = 0.125_m; conf.density = 10_kgpm2; conf.friction = 0.2f; - conf.vertex1 = Length2{-halfSegmentLength, 0_m}; - conf.vertex2 = Length2{+halfSegmentLength, 0_m}; + conf.Set(Length2{-halfSegmentLength, 0_m}, Length2{+halfSegmentLength, 0_m}); const auto vertexOffset = Vec2(0, 14) * 1_m; - const auto shape = std::make_shared(conf); + const auto shape = Shape(conf); auto prevBody = static_cast(nullptr); auto firstBody = static_cast(nullptr); auto prevVertex = Optional{}; @@ -102,11 +101,7 @@ namespace playrho { m_world.CreateJoint(RevoluteJointDef{prevBody, firstBody, vertices[0] + vertexOffset}); const auto diskRadius = 0.15_m; - const auto diskShape = std::make_shared(DiskShape::Conf{} - .UseVertexRadius(diskRadius) - .UseDensity(10_kgpm2) - .UseFriction(Real(0))); - + const auto diskShape = Shape(DiskShapeConf{}.UseRadius(diskRadius).UseDensity(10_kgpm2).UseFriction(Real(0))); auto angleIncrement = 90_deg; auto angle = 0_deg; const auto alpha = diskRadius; diff --git a/Testbed/Tests/BasicSliderCrank.hpp b/Testbed/Tests/BasicSliderCrank.hpp index 1ee80b505c..dc1e7ba884 100644 --- a/Testbed/Tests/BasicSliderCrank.hpp +++ b/Testbed/Tests/BasicSliderCrank.hpp @@ -39,9 +39,10 @@ class BasicSliderCrank : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(-8.0f, 20.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 2_kgpm2; - body->CreateFixture(std::make_shared(4_m, 1_m, conf)); + conf.SetAsBox(4_m, 1_m); + body->CreateFixture(Shape(conf)); m_world.CreateJoint(RevoluteJointDef{prevBody, body, Vec2(-12.0f, 20.0f) * 1_m}); prevBody = body; } @@ -52,9 +53,10 @@ class BasicSliderCrank : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(4.0f, 20.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 2_kgpm2; - body->CreateFixture(std::make_shared(8_m, 1_m, conf)); + conf.SetAsBox(8_m, 1_m); + body->CreateFixture(Shape(conf)); m_world.CreateJoint(RevoluteJointDef{prevBody, body, Vec2(-4.0f, 20.0f) * 1_m}); prevBody = body; } @@ -66,8 +68,8 @@ class BasicSliderCrank : public Test bd.fixedRotation = true; bd.location = Vec2(12.0f, 20.0f) * 1_m; const auto body = m_world.CreateBody(bd); - const auto conf = PolygonShape::Conf{}.UseDensity(2_kgpm2); - body->CreateFixture(std::make_shared(3_m, 3_m, conf)); + const auto conf = PolygonShapeConf{}.UseDensity(2_kgpm2).SetAsBox(3_m, 3_m); + body->CreateFixture(Shape(conf)); m_world.CreateJoint(RevoluteJointDef{prevBody, body, Vec2(12.0f, 20.0f) * 1_m}); const PrismaticJointDef pjd{ground, body, Vec2(12.0f, 17.0f) * 1_m, UnitVec2::GetRight()}; m_world.CreateJoint(pjd); diff --git a/Testbed/Tests/BodyTypes.hpp b/Testbed/Tests/BodyTypes.hpp index 257f1c8dcf..41e81997c9 100644 --- a/Testbed/Tests/BodyTypes.hpp +++ b/Testbed/Tests/BodyTypes.hpp @@ -30,7 +30,7 @@ class BodyTypes : public Test BodyTypes() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-20, 0) * 1_m, Vec2(20, 0) * 1_m)); + ground->CreateFixture(Shape(EdgeShapeConf{}.Set(Vec2(-20, 0) * 1_m, Vec2(20, 0) * 1_m))); RegisterForKey(GLFW_KEY_D, GLFW_PRESS, 0, "Dynamic", [&](KeyActionMods) { m_platform->SetType(BodyType::Dynamic); @@ -47,8 +47,8 @@ class BodyTypes : public Test { const auto bd = BodyDef{}.UseType(BodyType::Dynamic).UseLocation(Vec2(0, 3) * 1_m); m_attachment = m_world.CreateBody(bd); - const auto conf = PolygonShape::Conf{}.UseDensity(2_kgpm2); - m_attachment->CreateFixture(std::make_shared(0.5_m, 2_m, conf)); + const auto conf = PolygonShapeConf{}.UseDensity(2_kgpm2).SetAsBox(0.5_m, 2_m); + m_attachment->CreateFixture(Shape(conf)); } // Define platform @@ -56,9 +56,9 @@ class BodyTypes : public Test const auto bd = BodyDef{}.UseType(BodyType::Dynamic).UseLocation(Vec2(-4, 5) * 1_m); m_platform = m_world.CreateBody(bd); - const auto conf = PolygonShape::Conf{}.UseFriction(Real(0.6f)).UseDensity(2_kgpm2) + const auto conf = PolygonShapeConf{}.UseFriction(Real(0.6f)).UseDensity(2_kgpm2) .SetAsBox(0.5_m, 4_m, Vec2(4, 0) * 1_m, Pi * 0.5_rad); - m_platform->CreateFixture(std::make_shared(conf)); + m_platform->CreateFixture(Shape{conf}); RevoluteJointDef rjd(m_attachment, m_platform, Vec2(0, 5) * 1_m); rjd.maxMotorTorque = 50_Nm; @@ -81,8 +81,8 @@ class BodyTypes : public Test const auto bd = BodyDef{}.UseType(BodyType::Dynamic).UseLocation(Vec2(0, 8) * 1_m); const auto body = m_world.CreateBody(bd); - const auto conf = PolygonShape::Conf{}.UseFriction(Real(0.6f)).UseDensity(2_kgpm2); - body->CreateFixture(std::make_shared(0.75_m, 0.75_m, conf)); + const auto conf = PolygonShapeConf{}.UseFriction(Real(0.6f)).UseDensity(2_kgpm2).SetAsBox(0.75_m, 0.75_m); + body->CreateFixture(Shape(conf)); } } diff --git a/Testbed/Tests/Breakable.hpp b/Testbed/Tests/Breakable.hpp index bf6ad73cb6..cd96bae250 100644 --- a/Testbed/Tests/Breakable.hpp +++ b/Testbed/Tests/Breakable.hpp @@ -36,16 +36,13 @@ class Breakable : public Test Breakable() { - auto conf = PolygonShape::Conf{}.SetDensity(1_kgpm2); - // Ground body - { - const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); - } + m_world.CreateBody()->CreateFixture(Shape(EdgeShapeConf{}.Set(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m))); // Breakable dynamic body { + auto conf = PolygonShapeConf{}.UseDensity(1_kgpm2); + BodyDef bd; bd.type = BodyType::Dynamic; bd.location = Vec2(0.0f, 40.0f) * 1_m; @@ -53,11 +50,11 @@ class Breakable : public Test m_body1 = m_world.CreateBody(bd); conf.SetAsBox(0.5_m, 0.5_m, Vec2(-0.5f, 0.0f) * 1_m, 0_rad); - m_shape1 = std::make_shared(conf); + m_shape1 = conf; m_piece1 = m_body1->CreateFixture(m_shape1); conf.SetAsBox(0.5_m, 0.5_m, Vec2(0.5f, 0.0f) * 1_m, 0_rad); - m_shape2 = std::make_shared(conf); + m_shape2 = conf; m_piece2 = m_body1->CreateFixture(m_shape2); } @@ -140,8 +137,8 @@ class Breakable : public Test Body* m_body1; LinearVelocity2 m_velocity; AngularVelocity m_angularVelocity; - std::shared_ptr m_shape1; - std::shared_ptr m_shape2; + PolygonShapeConf m_shape1; + PolygonShapeConf m_shape2; Fixture* m_piece1; Fixture* m_piece2; diff --git a/Testbed/Tests/BreakableTwo.hpp b/Testbed/Tests/BreakableTwo.hpp index 233f5654d3..25f76b1126 100644 --- a/Testbed/Tests/BreakableTwo.hpp +++ b/Testbed/Tests/BreakableTwo.hpp @@ -37,9 +37,6 @@ class BreakableTwo: public Test BreakableTwo(): Test(GetTestConf()) { - const auto vr = 2 * DefaultLinearSlop; - const auto polygonConf = PolygonShape::Conf{}.UseVertexRadius(vr).SetDensity(100_kgpm2); - m_shape = std::make_shared(0.5_m - vr, 0.5_m - vr, polygonConf); m_world.SetGravity(LinearAcceleration2{}); Body* bodies[20 * 20]; @@ -109,7 +106,8 @@ class BreakableTwo: public Test } private: - std::shared_ptr m_shape; + const Length vr = 2 * DefaultLinearSlop; + Shape m_shape{PolygonShapeConf{}.UseVertexRadius(vr).UseDensity(100_kgpm2).SetAsBox(0.5_m - vr, 0.5_m - vr)}; Body* m_body = nullptr; }; diff --git a/Testbed/Tests/Bridge.hpp b/Testbed/Tests/Bridge.hpp index b04377cf5e..7135794bdd 100644 --- a/Testbed/Tests/Bridge.hpp +++ b/Testbed/Tests/Bridge.hpp @@ -33,13 +33,14 @@ class Bridge : public Test Bridge() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(GetGroundEdgeConf())); + ground->CreateFixture(Shape(GetGroundEdgeConf())); { - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 20_kgpm2; conf.friction = 0.2f; - const auto shape = std::make_shared(0.5_m, 0.125_m, conf); + conf.SetAsBox(0.5_m, 0.125_m); + const auto shape = Shape{conf}; auto prevBody = ground; for (auto i = 0; i < Count; ++i) { @@ -60,12 +61,12 @@ class Bridge : public Test m_world.CreateJoint(RevoluteJointDef{prevBody, ground, Vec2(-15.0f + Count, 5.0f) * 1_m}); } - const auto conf = PolygonShape::Conf{}.UseDensity(1_kgpm2).UseVertices({ + const auto conf = PolygonShapeConf{}.UseDensity(1_kgpm2).UseVertices({ Vec2(-0.5f, 0.0f) * 1_m, Vec2(0.5f, 0.0f) * 1_m, Vec2(0.0f, 1.5f) * 1_m }); - const auto polyshape = std::make_shared(conf); + const auto polyshape = Shape(conf); for (auto i = 0; i < 2; ++i) { const auto body = m_world.CreateBody(BodyDef{} @@ -74,9 +75,7 @@ class Bridge : public Test body->CreateFixture(polyshape); } - const auto diskShape = std::make_shared(DiskShape::Conf{} - .UseDensity(1_kgpm2) - .UseVertexRadius(0.5_m)); + const auto diskShape = Shape{DiskShapeConf{}.UseDensity(1_kgpm2).UseRadius(0.5_m)}; for (auto i = 0; i < 3; ++i) { const auto body = m_world.CreateBody(BodyDef{} diff --git a/Testbed/Tests/BulletTest.hpp b/Testbed/Tests/BulletTest.hpp index 8676f94b68..dec4309a26 100644 --- a/Testbed/Tests/BulletTest.hpp +++ b/Testbed/Tests/BulletTest.hpp @@ -33,12 +33,9 @@ class BulletTest : public Test { BodyDef bd; bd.location = Length2{}; - Body* body = m_world.CreateBody(bd); - - body->CreateFixture(std::make_shared(Vec2(-10.0f, 0.0f) * 1_m, Vec2(10.0f, 0.0f) * 1_m)); - - const auto shape = PolygonShape::Conf{}.SetAsBox(0.2_m, 1_m, Vec2(0.5f, 1.0f) * 1_m, 0_rad); - body->CreateFixture(std::make_shared(shape)); + const auto body = m_world.CreateBody(bd); + body->CreateFixture(Shape(EdgeShapeConf{Vec2(-10.0f, 0.0f) * 1_m, Vec2(10.0f, 0.0f) * 1_m})); + body->CreateFixture(Shape{PolygonShapeConf{}.SetAsBox(0.2_m, 1_m, Vec2(0.5f, 1.0f) * 1_m, 0_rad)}); } { @@ -46,12 +43,12 @@ class BulletTest : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(0.0f, 4.0f) * 1_m; - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.UseDensity(1_kgpm2); conf.SetAsBox(2_m, 0.1_m); m_body = m_world.CreateBody(bd); - m_body->CreateFixture(std::make_shared(conf)); + m_body->CreateFixture(Shape{conf}); conf.UseDensity(100_kgpm2); conf.SetAsBox(0.25_m, 0.25_m); @@ -62,7 +59,7 @@ class BulletTest : public Test bd.bullet = true; m_bullet = m_world.CreateBody(bd); - m_bullet->CreateFixture(std::make_shared(conf)); + m_bullet->CreateFixture(Shape{conf}); m_bullet->SetVelocity(Velocity{Vec2{0.0f, -50.0f} * 1_mps, 0_rpm}); } diff --git a/Testbed/Tests/Cantilever.hpp b/Testbed/Tests/Cantilever.hpp index 668f01bbfd..fc2616bec3 100644 --- a/Testbed/Tests/Cantilever.hpp +++ b/Testbed/Tests/Cantilever.hpp @@ -42,18 +42,15 @@ class Cantilever : public Test const auto ground = m_world.CreateBody(); // Creates bottom ground - ground->CreateFixture(std::make_shared(GetGroundEdgeConf())); + ground->CreateFixture(Shape(GetGroundEdgeConf())); // Creates left-end-fixed 8-part plank (below the top one) { - auto conf = PolygonShape::Conf{}; - conf.density = 20_kgpm2; - const auto shape = std::make_shared(0.5_m, 0.125_m, conf); - + const auto shape = Shape{PolygonShapeConf{}.UseDensity(20_kgpm2).SetAsBox(0.5_m, 0.125_m)}; auto prevBody = ground; for (auto i = 0; i < e_count; ++i) { - BodyDef bd; + auto bd = BodyDef{}; bd.type = BodyType::Dynamic; bd.location = Vec2(-14.5f + 1.0f * i, 5.0f) * 1_m; const auto body = m_world.CreateBody(bd); @@ -69,14 +66,11 @@ class Cantilever : public Test // Creates left-end-fixed 3-part plank at top { - auto conf = PolygonShape::Conf{}; - conf.density = 20_kgpm2; - const auto shape = std::make_shared(1_m, 0.125_m, conf); - + const auto shape = Shape{PolygonShapeConf{}.UseDensity(20_kgpm2).SetAsBox(1_m, 0.125_m)}; auto prevBody = ground; for (auto i = 0; i < 3; ++i) { - BodyDef bd; + auto bd = BodyDef{}; bd.type = BodyType::Dynamic; bd.location = Vec2(-14.0f + 2.0f * i, 15.0f) * 1_m; const auto body = m_world.CreateBody(bd); @@ -93,45 +87,36 @@ class Cantilever : public Test // Creates 8-part plank to the right of the fixed planks (but not farthest right) { - auto conf = PolygonShape::Conf{}; - conf.density = 20_kgpm2; - const auto shape = std::make_shared(0.5_m, 0.125_m, conf); - + const auto shape = Shape{PolygonShapeConf{}.UseDensity(20_kgpm2).SetAsBox(0.5_m, 0.125_m)}; auto prevBody = ground; for (auto i = 0; i < e_count; ++i) { - BodyDef bd; + auto bd = BodyDef{}; bd.type = BodyType::Dynamic; bd.location = Vec2(-4.5f + 1.0f * i, 5.0f) * 1_m; const auto body = m_world.CreateBody(bd); body->CreateFixture(shape); - if (i > 0) { m_world.CreateJoint(WeldJointDef{ prevBody, body, Vec2(-5.0f + 1.0f * i, 5.0f) * 1_m }); } - prevBody = body; } } // Creates 8-part farthest-right plank { - auto conf = PolygonShape::Conf{}; - conf.density = 20_kgpm2; - const auto shape = std::make_shared(0.5_m, 0.125_m, conf); - + const auto shape = Shape{PolygonShapeConf{}.UseDensity(20_kgpm2).SetAsBox(0.5_m, 0.125_m)}; auto prevBody = ground; for (auto i = 0; i < e_count; ++i) { - BodyDef bd; + auto bd = BodyDef{}; bd.type = BodyType::Dynamic; bd.location = Vec2(5.5f + 1.0f * i, 10.0f) * 1_m; const auto body = m_world.CreateBody(bd); body->CreateFixture(shape); - if (i > 0) { auto jd = WeldJointDef{prevBody, body, Vec2(5.0f + 1.0f * i, 10.0f) * 1_m}; @@ -139,18 +124,17 @@ class Cantilever : public Test jd.dampingRatio = 0.7f; m_world.CreateJoint(jd); } - prevBody = body; } } // Creates triangles - const auto conf = PolygonShape::Conf{}.UseDensity(1_kgpm2).UseVertices({ + const auto conf = PolygonShapeConf{}.UseDensity(1_kgpm2).UseVertices({ Vec2(-0.5f, 0.0f) * 1_m, Vec2(0.5f, 0.0f) * 1_m, Vec2(0.0f, 1.5f) * 1_m}); - const auto polyshape = std::make_shared(conf); + const auto polyshape = Shape{conf}; for (auto i = 0; i < 2; ++i) { - BodyDef bd; + auto bd = BodyDef{}; bd.type = BodyType::Dynamic; bd.location = Vec2(-8.0f + 8.0f * i, 12.0f) * 1_m; const auto body = m_world.CreateBody(bd); @@ -158,12 +142,10 @@ class Cantilever : public Test } // Creates circles - const auto circleshape = std::make_shared(DiskShape::Conf{} - .UseVertexRadius(0.5_m) - .UseDensity(1_kgpm2)); + const auto circleshape = Shape{DiskShapeConf{}.UseRadius(0.5_m).UseDensity(1_kgpm2)}; for (auto i = 0; i < 2; ++i) { - BodyDef bd; + auto bd = BodyDef{}; bd.type = BodyType::Dynamic; bd.location = Vec2(-6.0f + 6.0f * i, 10.0f) * 1_m; const auto body = m_world.CreateBody(bd); diff --git a/Testbed/Tests/Car.hpp b/Testbed/Tests/Car.hpp index b7228f31d8..f11bc1d031 100644 --- a/Testbed/Tests/Car.hpp +++ b/Testbed/Tests/Car.hpp @@ -57,11 +57,11 @@ class Car : public Test const auto ground = m_world.CreateBody(); { - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.UseDensity(0_kgpm2).UseFriction(Real(0.6f)); conf.Set(Vec2(-20.0f, 0.0f) * 1_m, Vec2(20.0f, 0.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); Real hs[10] = {0.25f, 1.0f, 4.0f, 0.0f, 0.0f, -1.0f, -2.0f, -2.0f, -1.25f, 0.0f}; @@ -73,7 +73,7 @@ class Car : public Test { const auto y2 = hs[i]; conf.Set(Vec2(x, y1) * 1_m, Vec2(x + dx, y2) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); y1 = y2; x += dx; } @@ -82,29 +82,29 @@ class Car : public Test { const auto y2 = hs[i]; conf.Set(Vec2(x, y1) * 1_m, Vec2(x + dx, y2) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); y1 = y2; x += dx; } conf.Set(Vec2(x, 0.0f) * 1_m, Vec2(x + 40.0f, 0.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); x += 80.0f; conf.Set(Vec2(x, 0.0f) * 1_m, Vec2(x + 40.0f, 0.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); x += 40.0f; conf.Set(Vec2(x, 0.0f) * 1_m, Vec2(x + 10.0f, 5.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); x += 20.0f; conf.Set(Vec2(x, 0.0f) * 1_m, Vec2(x + 40.0f, 0.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); x += 40.0f; conf.Set(Vec2(x, 0.0f) * 1_m, Vec2(x, 20.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); } // Teeter @@ -113,10 +113,7 @@ class Car : public Test bd.location = Vec2(140.0f, 1.0f) * 1_m; bd.type = BodyType::Dynamic; const auto body = m_world.CreateBody(bd); - - const auto box = std::make_shared(10_m, 0.25_m, - PolygonShape::Conf{}.SetDensity(1_kgpm2)); - body->CreateFixture(box); + body->CreateFixture(Shape{PolygonShapeConf{}.UseDensity(1_kgpm2).SetAsBox(10_m, 0.25_m)}); RevoluteJointDef jd(ground, body, body->GetLocation()); jd.lowerAngle = -8_deg; @@ -131,10 +128,9 @@ class Car : public Test // Bridge { const auto N = 20; - const auto shape = std::make_shared(1_m, 0.125_m, - PolygonShape::Conf{} - .SetDensity(1_kgpm2).SetFriction(Real(0.6f))); - + const auto shape = Shape{ + PolygonShapeConf{}.UseDensity(1_kgpm2).UseFriction(Real(0.6f)).SetAsBox(1_m, 0.125_m) + }; auto prevBody = ground; for (auto i = 0; i < N; ++i) { @@ -149,15 +145,13 @@ class Car : public Test prevBody = body; } - m_world.CreateJoint(RevoluteJointDef{prevBody, ground, Vec2(160.0f + 2.0f * N, -0.125f) * 1_m}); } // Boxes { - const auto box = std::make_shared(0.5_m, 0.5_m, - PolygonShape::Conf{}.SetDensity(0.5_kgpm2)); + const auto box = Shape{PolygonShapeConf{}.UseDensity(0.5_kgpm2).SetAsBox(0.5_m, 0.5_m)}; auto body = static_cast(nullptr); BodyDef bd; @@ -186,7 +180,7 @@ class Car : public Test // Car { - const auto chassis = std::make_shared(PolygonShape::Conf{} + const auto chassis = Shape(PolygonShapeConf{} .UseDensity(1_kgpm2).UseVertices({ Vec2(-1.5f, -0.5f) * 1_m, Vec2(1.5f, -0.5f) * 1_m, @@ -196,10 +190,9 @@ class Car : public Test Vec2(-1.5f, 0.2f) * 1_m })); - const auto circle = std::make_shared(DiskShape::Conf{} - .UseVertexRadius(0.4_m) - .UseDensity(1_kgpm2) - .UseFriction(Real(0.9f))); + const auto circle = Shape{ + DiskShapeConf{}.UseRadius(0.4_m).UseDensity(1_kgpm2).UseFriction(Real(0.9f)) + }; BodyDef bd; bd.type = BodyType::Dynamic; diff --git a/Testbed/Tests/Chain.hpp b/Testbed/Tests/Chain.hpp index c4b511e2f2..c2481791f9 100644 --- a/Testbed/Tests/Chain.hpp +++ b/Testbed/Tests/Chain.hpp @@ -30,22 +30,19 @@ class Chain : public Test Chain() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(GetGroundEdgeConf())); + ground->CreateFixture(Shape(GetGroundEdgeConf())); + const auto shape = Shape{PolygonShapeConf{}.UseDensity(20_kgpm2).UseFriction(Real(0.2f)).SetAsBox(0.6_m, 0.125_m)}; + const auto y = 25.0f; + auto prevBody = ground; + for (auto i = 0; i < 30; ++i) { - const auto shape = std::make_shared(0.6_m, 0.125_m, - PolygonShape::Conf{}.SetDensity(20_kgpm2).SetFriction(Real(0.2f))); - const auto y = 25.0f; - auto prevBody = ground; - for (auto i = 0; i < 30; ++i) - { - BodyDef bd; - bd.type = BodyType::Dynamic; - bd.location = Vec2(0.5f + i, y) * 1_m; - const auto body = m_world.CreateBody(bd); - body->CreateFixture(shape); - m_world.CreateJoint(RevoluteJointDef(prevBody, body, Vec2(Real(i), y) * 1_m)); - prevBody = body; - } + BodyDef bd; + bd.type = BodyType::Dynamic; + bd.location = Vec2(0.5f + i, y) * 1_m; + const auto body = m_world.CreateBody(bd); + body->CreateFixture(shape); + m_world.CreateJoint(RevoluteJointDef(prevBody, body, Vec2(Real(i), y) * 1_m)); + prevBody = body; } } }; diff --git a/Testbed/Tests/CharacterCollision.hpp b/Testbed/Tests/CharacterCollision.hpp index 6882ea6034..06c9a853b5 100644 --- a/Testbed/Tests/CharacterCollision.hpp +++ b/Testbed/Tests/CharacterCollision.hpp @@ -41,129 +41,128 @@ class CharacterCollision : public Test { // Ground body const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-20, 0) * 1_m, Vec2(20, 0) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-20, 0) * 1_m, Vec2(20, 0) * 1_m}}); { - auto shape = PolygonShape::Conf{}; + auto shape = PolygonShapeConf{}; shape.SetAsBox(0.5_m, 0.5_m, Vec2(20.015f, 0.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(20.015f, 1.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(20.015f, 2.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(20.015f, 3.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(20.015f, 4.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(20.015f, 5.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(20.015f, 6.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(17.985f, 0.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(17.985f, 1.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(17.985f, 2.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(17.985f, 3.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(17.985f, 4.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(17.985f, 5.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 0.5_m, Vec2(17.985f, 6.545f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); } // Collinear edges. { - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.Set(Vec2(-8.0f, 1.0f) * 1_m, Vec2(-6.0f, 1.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(Vec2(-6.0f, 1.0f) * 1_m, Vec2(-4.0f, 1.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(Vec2(-4.0f, 1.0f) * 1_m, Vec2(-2.0f, 1.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); } // Collinear 2-gons. { - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.UseVertices({Vec2(-8.0f, 20.0f) * 1_m, Vec2(-6.0f, 20.0f) * 1_m}); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape{conf}); conf.UseVertices({Vec2(-6.0f, 20.0f) * 1_m, Vec2(-4.0f, 20.0f) * 1_m}); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape{conf}); conf.UseVertices({Vec2(-4.0f, 20.0f) * 1_m, Vec2(-2.0f, 20.0f) * 1_m}); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape{conf}); } // Chain shape { const auto body = m_world.CreateBody(BodyDef{}.UseAngle(45_deg)); - auto conf = ChainShape::Conf{}; - conf.vertices.push_back(Vec2(5.0f, 7.0f) * 1_m); - conf.vertices.push_back(Vec2(6.0f, 8.0f) * 1_m); - conf.vertices.push_back(Vec2(7.0f, 8.0f) * 1_m); - conf.vertices.push_back(Vec2(8.0f, 7.0f) * 1_m); - body->CreateFixture(std::make_shared(conf)); + auto conf = ChainShapeConf{}; + conf.Add(Vec2(5.0f, 7.0f) * 1_m); + conf.Add(Vec2(6.0f, 8.0f) * 1_m); + conf.Add(Vec2(7.0f, 8.0f) * 1_m); + conf.Add(Vec2(8.0f, 7.0f) * 1_m); + body->CreateFixture(Shape(conf)); } // Square tiles. { - auto shape = PolygonShape::Conf{}; + auto shape = PolygonShapeConf{}; shape.SetAsBox(1_m, 1_m, Vec2(4.0f, 3.0f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(1_m, 1_m, Vec2(6.0f, 3.0f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); shape.SetAsBox(1_m, 1_m, Vec2(8.0f, 3.0f) * 1_m, 0_rad); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); } // Square made from an edge loop. Collision should be smooth. { - auto conf = ChainShape::Conf{}; - conf.vertices.push_back(Vec2(-1.0f, 3.0f) * 1_m); - conf.vertices.push_back(Vec2(1.0f, 3.0f) * 1_m); - conf.vertices.push_back(Vec2(1.0f, 5.0f) * 1_m); - conf.vertices.push_back(Vec2(-1.0f, 5.0f) * 1_m); - conf.vertices.push_back(conf.vertices[0]); // to loop chain shape around - ground->CreateFixture(std::make_shared(conf)); + auto conf = ChainShapeConf{}; + conf.Add(Vec2(-1.0f, 3.0f) * 1_m); + conf.Add(Vec2(1.0f, 3.0f) * 1_m); + conf.Add(Vec2(1.0f, 5.0f) * 1_m); + conf.Add(Vec2(-1.0f, 5.0f) * 1_m); + conf.Add(conf.GetVertex(0)); // to loop chain shape around + ground->CreateFixture(Shape(conf)); } // Edge loop. Collision should be smooth. { const auto body = m_world.CreateBody(BodyDef{}.UseLocation(Vec2(-10.0f, 4.0f) * 1_m)); - auto conf = ChainShape::Conf{}; - conf.vertices.push_back(Length2{}); - conf.vertices.push_back(Vec2(6.0f, 0.0f) * 1_m); - conf.vertices.push_back(Vec2(6.0f, 2.0f) * 1_m); - conf.vertices.push_back(Vec2(4.0f, 1.0f) * 1_m); - conf.vertices.push_back(Vec2(2.0f, 2.0f) * 1_m); - conf.vertices.push_back(Vec2(0.0f, 2.0f) * 1_m); - conf.vertices.push_back(Vec2(-2.0f, 2.0f) * 1_m); - conf.vertices.push_back(Vec2(-4.0f, 3.0f) * 1_m); - conf.vertices.push_back(Vec2(-6.0f, 2.0f) * 1_m); - conf.vertices.push_back(Vec2(-6.0f, 0.0f) * 1_m); - conf.vertices.push_back(conf.vertices[0]); // to loop back completely. - body->CreateFixture(std::make_shared(conf)); + auto conf = ChainShapeConf{}; + conf.Add(Length2{}); + conf.Add(Vec2(6.0f, 0.0f) * 1_m); + conf.Add(Vec2(6.0f, 2.0f) * 1_m); + conf.Add(Vec2(4.0f, 1.0f) * 1_m); + conf.Add(Vec2(2.0f, 2.0f) * 1_m); + conf.Add(Vec2(0.0f, 2.0f) * 1_m); + conf.Add(Vec2(-2.0f, 2.0f) * 1_m); + conf.Add(Vec2(-4.0f, 3.0f) * 1_m); + conf.Add(Vec2(-6.0f, 2.0f) * 1_m); + conf.Add(Vec2(-6.0f, 0.0f) * 1_m); + conf.Add(conf.GetVertex(0)); // to loop back completely. + body->CreateFixture(Shape(conf)); } // Square character 1 { BodyDef bd; - bd.location = Vec2(-3.0f, 8.0f) * 1_m; bd.type = BodyType::Dynamic; bd.fixedRotation = false; bd.allowSleep = false; + bd.location = Vec2(-3.0f, 8.0f) * 1_m; const auto body = m_world.CreateBody(bd); - - auto conf = PolygonShape::Conf{}; - conf.friction = Real(0); - conf.density = 20_kgpm2; - const auto square = std::make_shared(0.5_m, 0.5_m, conf); + + const auto square = Shape{ + PolygonShapeConf{}.UseFriction(Real(0)).UseDensity(20_kgpm2).SetAsBox(0.5_m, 0.5_m) + }; body->CreateFixture(square); bd.location = Vec2(19.0f, 7.0f) * 1_m; @@ -179,11 +178,9 @@ class CharacterCollision : public Test bd.fixedRotation = true; bd.allowSleep = false; - const auto body = m_world.CreateBody(bd); - - auto conf = PolygonShape::Conf{}; - conf.density = 20_kgpm2; - body->CreateFixture(std::make_shared(0.25_m, 0.25_m, conf)); + m_world.CreateBody(bd)->CreateFixture(Shape{ + PolygonShapeConf{}.UseDensity(20_kgpm2).SetAsBox(0.25_m, 0.25_m) + }); } // Hexagon character @@ -205,8 +202,8 @@ class CharacterCollision : public Test angle += delta; } - auto conf = PolygonShape::Conf{}.UseDensity(20_kgpm2).UseVertices(vertices); - body->CreateFixture(std::make_shared(conf)); + auto conf = PolygonShapeConf{}.UseDensity(20_kgpm2).UseVertices(vertices); + body->CreateFixture(Shape{conf}); } // Disk character @@ -218,10 +215,10 @@ class CharacterCollision : public Test bd.allowSleep = false; const auto body = m_world.CreateBody(bd); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.density = 20_kgpm2; conf.vertexRadius = 0.5_m; - body->CreateFixture(std::make_shared(conf)); + body->CreateFixture(Shape(conf)); } // Disk character @@ -233,11 +230,11 @@ class CharacterCollision : public Test m_character = m_world.CreateBody(bd); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.density = 20_kgpm2; conf.friction = 1.0f; conf.vertexRadius = 0.25_m; - m_character->CreateFixture(std::make_shared(conf)); + m_character->CreateFixture(Shape(conf)); } } diff --git a/Testbed/Tests/CollisionFiltering.hpp b/Testbed/Tests/CollisionFiltering.hpp index 7f4ac4e5eb..5264783ea5 100644 --- a/Testbed/Tests/CollisionFiltering.hpp +++ b/Testbed/Tests/CollisionFiltering.hpp @@ -48,21 +48,15 @@ class CollisionFiltering : public Test CollisionFiltering() { // Ground body - { - auto conf = EdgeShape::Conf{}; - conf.friction = 0.3f; - - BodyDef bd; - const auto ground = m_world.CreateBody(bd); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m, conf)); - } - + m_world.CreateBody()->CreateFixture(Shape(EdgeShapeConf{}.UseFriction(0.3f) + .Set(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m))); + // Small triangle Length2 vertices[3]; vertices[0] = Vec2(-1.0f, 0.0f) * 1_m; vertices[1] = Vec2(1.0f, 0.0f) * 1_m; vertices[2] = Vec2(0.0f, 2.0f) * 1_m; - auto polygon = PolygonShape::Conf{}; + auto polygon = PolygonShapeConf{}; polygon.UseDensity(1_kgpm2); polygon.Set(Span{vertices, 3}); @@ -77,7 +71,7 @@ class CollisionFiltering : public Test triangleBodyDef.location = Vec2(-5.0f, 2.0f) * 1_m; const auto body1 = m_world.CreateBody(triangleBodyDef); - body1->CreateFixture(std::make_shared(polygon), triangleShapeDef); + body1->CreateFixture(Shape(polygon), triangleShapeDef); // Large triangle (recycle definitions) vertices[0] *= 2.0f; @@ -89,16 +83,14 @@ class CollisionFiltering : public Test triangleBodyDef.fixedRotation = true; // look at me! const auto body2 = m_world.CreateBody(triangleBodyDef); - body2->CreateFixture(std::make_shared(polygon), triangleShapeDef); + body2->CreateFixture(Shape(polygon), triangleShapeDef); { BodyDef bd; bd.type = BodyType::Dynamic; bd.location = Vec2(-5.0f, 10.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; - conf.density = 1_kgpm2; - body->CreateFixture(std::make_shared(0.5_m, 1_m, conf)); + body->CreateFixture(Shape{PolygonShapeConf{}.UseDensity(1_kgpm2).SetAsBox(0.5_m, 1_m)}); PrismaticJointDef jd; jd.bodyA = body2; @@ -129,7 +121,7 @@ class CollisionFiltering : public Test boxBodyDef.location = Vec2(0.0f, 2.0f) * 1_m; const auto body3 = m_world.CreateBody(boxBodyDef); - body3->CreateFixture(std::make_shared(polygon), boxShapeDef); + body3->CreateFixture(Shape(polygon), boxShapeDef); // Large box (recycle definitions) polygon.SetAsBox(2_m, 1_m); @@ -137,10 +129,10 @@ class CollisionFiltering : public Test boxBodyDef.location = Vec2(0.0f, 6.0f) * 1_m; const auto body4 = m_world.CreateBody(boxBodyDef); - body4->CreateFixture(std::make_shared(polygon), boxShapeDef); + body4->CreateFixture(Shape(polygon), boxShapeDef); // Small circle - auto circleConf = DiskShape::Conf{}; + auto circleConf = DiskShapeConf{}; circleConf.density = 1_kgpm2; FixtureDef circleShapeDef; @@ -155,7 +147,7 @@ class CollisionFiltering : public Test const auto body5 = m_world.CreateBody(circleBodyDef); circleConf.vertexRadius = 1_m; - body5->CreateFixture(std::make_shared(circleConf), circleShapeDef); + body5->CreateFixture(Shape(circleConf), circleShapeDef); // Large circle circleShapeDef.filter.groupIndex = k_largeGroup; @@ -163,7 +155,7 @@ class CollisionFiltering : public Test const auto body6 = m_world.CreateBody(circleBodyDef); circleConf.vertexRadius = circleConf.vertexRadius * 2; - body6->CreateFixture(std::make_shared(circleConf), circleShapeDef); + body6->CreateFixture(Shape(circleConf), circleShapeDef); } }; diff --git a/Testbed/Tests/CollisionProcessing.hpp b/Testbed/Tests/CollisionProcessing.hpp index 825649c84c..83b104816d 100644 --- a/Testbed/Tests/CollisionProcessing.hpp +++ b/Testbed/Tests/CollisionProcessing.hpp @@ -35,7 +35,7 @@ class CollisionProcessing : public Test // Ground body { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-50, 0) * 1_m, Vec2(50, 0) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-50, 0) * 1_m, Vec2(50, 0) * 1_m}}); } auto xLo = -5.0f, xHi = 5.0f; @@ -47,16 +47,16 @@ class CollisionProcessing : public Test vertices[1] = Vec2(1.0f, 0.0f) * 1_m; vertices[2] = Vec2(0.0f, 2.0f) * 1_m; - auto polygon = PolygonShape::Conf{}; + auto polygon = PolygonShapeConf{}; polygon.Set(Span{vertices, 3}); - polygon.SetDensity(1_kgpm2); + polygon.UseDensity(1_kgpm2); BodyDef triangleBodyDef; triangleBodyDef.type = BodyType::Dynamic; triangleBodyDef.location = Vec2(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)) * 1_m; const auto body1 = m_world.CreateBody(triangleBodyDef); - body1->CreateFixture(std::make_shared(polygon)); + body1->CreateFixture(Shape(polygon)); // Large triangle (recycle definitions) vertices[0] *= 2.0f; @@ -67,7 +67,7 @@ class CollisionProcessing : public Test triangleBodyDef.location = Vec2(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)) * 1_m; const auto body2 = m_world.CreateBody(triangleBodyDef); - body2->CreateFixture(std::make_shared(polygon)); + body2->CreateFixture(Shape(polygon)); // Small box polygon.SetAsBox(1_m, 0.5_m); @@ -77,14 +77,14 @@ class CollisionProcessing : public Test boxBodyDef.location = Vec2(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)) * 1_m; const auto body3 = m_world.CreateBody(boxBodyDef); - body3->CreateFixture(std::make_shared(polygon)); + body3->CreateFixture(Shape(polygon)); // Large box (recycle definitions) polygon.SetAsBox(2_m, 1_m); boxBodyDef.location = Vec2(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)) * 1_m; const auto body4 = m_world.CreateBody(boxBodyDef); - body4->CreateFixture(std::make_shared(polygon)); + body4->CreateFixture(Shape(polygon)); BodyDef circleBodyDef; circleBodyDef.type = BodyType::Dynamic; @@ -92,16 +92,12 @@ class CollisionProcessing : public Test // Small circle circleBodyDef.location = Vec2(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)) * 1_m; const auto body5 = m_world.CreateBody(circleBodyDef); - body5->CreateFixture(std::make_shared(DiskShape::Conf{} - .UseVertexRadius(1_m) - .UseDensity(1_kgpm2))); + body5->CreateFixture(Shape(DiskShapeConf{}.UseRadius(1_m).UseDensity(1_kgpm2))); // Large circle circleBodyDef.location = Vec2(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)) * 1_m; const auto body6 = m_world.CreateBody(circleBodyDef); - body6->CreateFixture(std::make_shared(DiskShape::Conf{} - .UseVertexRadius(2_m) - .UseDensity(1_kgpm2))); + body6->CreateFixture(Shape(DiskShapeConf{}.UseRadius(2_m).UseDensity(1_kgpm2))); } void PostStep(const Settings&, Drawer&) override diff --git a/Testbed/Tests/CompoundShapes.hpp b/Testbed/Tests/CompoundShapes.hpp index dba43f7658..928b8cfabf 100644 --- a/Testbed/Tests/CompoundShapes.hpp +++ b/Testbed/Tests/CompoundShapes.hpp @@ -30,21 +30,16 @@ class CompoundShapes : public Test public: CompoundShapes() { + m_world.CreateBody()->CreateFixture(Shape{EdgeShapeConf{Vec2(50.0f, 0.0f) * 1_m, Vec2(-50.0f, 0.0f) * 1_m}}); + { - BodyDef bd; - bd.location = Length2{}; - const auto body = m_world.CreateBody(bd); - body->CreateFixture(std::make_shared(Vec2(50.0f, 0.0f) * 1_m, Vec2(-50.0f, 0.0f) * 1_m)); - } - - { - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 0.5_m; conf.location = Vec2{-0.5f, 0.5f} * 1_m; - const auto circle1 = std::make_shared(DiskShape::Conf(conf).SetDensity(2_kgpm2)); + const auto circle1 = Shape{DiskShapeConf(conf).UseDensity(2_kgpm2)}; conf.location = Vec2{0.5f, 0.5f} * 1_m; - const auto circle2 = std::make_shared(conf); + const auto circle2 = Shape(conf); for (auto i = 0; i < 10; ++i) { const auto x = RandomFloat(-0.1f, 0.1f); @@ -59,12 +54,13 @@ class CompoundShapes : public Test } { - auto conf = PolygonShape::Conf{}; - conf.SetDensity(2_kgpm2); - const auto polygon1 = std::make_shared(0.25_m, 0.5_m, conf); - conf.SetDensity(2_kgpm2); + auto conf = PolygonShapeConf{}; + conf.UseDensity(2_kgpm2); + conf.SetAsBox(0.25_m, 0.5_m); + const auto polygon1 = Shape{conf}; + conf.UseDensity(2_kgpm2); conf.SetAsBox(0.25_m, 0.5_m, Vec2(0.0f, -0.5f) * 1_m, 0.5_rad * Pi); - const auto polygon2 = std::make_shared(conf); + const auto polygon2 = Shape{conf}; for (int i = 0; i < 10; ++i) { const auto x = RandomFloat(-0.1f, 0.1f); @@ -83,27 +79,27 @@ class CompoundShapes : public Test xf1.q = UnitVec2::Get(0.3524_rad * Pi); xf1.p = GetVec2(GetXAxis(xf1.q)) * 1_m; - auto triangleConf1 = PolygonShape::Conf{}; + auto triangleConf1 = PolygonShapeConf{}; triangleConf1.Set(Span{ Transform(Vec2(-1.0f, 0.0f) * 1_m, xf1), Transform(Vec2(1.0f, 0.0f) * 1_m, xf1), Transform(Vec2(0.0f, 0.5f) * 1_m, xf1) }); - triangleConf1.SetDensity(2_kgpm2); - const auto triangle1 = std::make_shared(triangleConf1); + triangleConf1.UseDensity(2_kgpm2); + const auto triangle1 = Shape(triangleConf1); Transformation xf2; xf2.q = UnitVec2::Get(-0.3524_rad * Pi); xf2.p = -GetVec2(GetXAxis(xf2.q)) * 1_m; - auto trianglConf2 = PolygonShape::Conf{}; + auto trianglConf2 = PolygonShapeConf{}; trianglConf2.Set(Span{ Transform(Vec2(-1.0f, 0.0f) * 1_m, xf2), Transform(Vec2(1.0f, 0.0f) * 1_m, xf2), Transform(Vec2(0.0f, 0.5f) * 1_m, xf2) }); - trianglConf2.SetDensity(2_kgpm2); - const auto triangle2 = std::make_shared(trianglConf2); + trianglConf2.UseDensity(2_kgpm2); + const auto triangle2 = Shape(trianglConf2); for (auto i = 0; i < 10; ++i) { @@ -119,14 +115,15 @@ class CompoundShapes : public Test } { - auto conf = PolygonShape::Conf{}; - conf.SetDensity(4_kgpm2); - const auto bottom = std::make_shared(1.5_m, 0.15_m, conf); + auto conf = PolygonShapeConf{}; + conf.UseDensity(4_kgpm2); + conf.SetAsBox(1.5_m, 0.15_m); + const auto bottom = Shape{conf}; conf.SetAsBox(0.15_m, 2.7_m, Vec2(-1.45f, 2.35f) * 1_m, +0.2_rad); - const auto left = std::make_shared(conf); - conf.SetDensity(4_kgpm2); + const auto left = Shape{conf}; + conf.UseDensity(4_kgpm2); conf.SetAsBox(0.15_m, 2.7_m, Vec2(1.45f, 2.35f) * 1_m, -0.2_rad); - const auto right = std::make_shared(conf); + const auto right = Shape{conf}; BodyDef bd; bd.type = BodyType::Dynamic; diff --git a/Testbed/Tests/Confined.hpp b/Testbed/Tests/Confined.hpp index 558c93213e..d425c89499 100644 --- a/Testbed/Tests/Confined.hpp +++ b/Testbed/Tests/Confined.hpp @@ -69,11 +69,11 @@ class Confined : public Test }); const auto radius = 0.5_m; - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = radius; conf.density = 1_kgpm2; conf.friction = 0.1f; - const auto shape = std::make_shared(conf); + const auto shape = Shape(conf); for (auto j = 0; j < e_columnCount; ++j) { @@ -116,30 +116,25 @@ class Confined : public Test bd.bullet = m_bullet_mode; bd.location = Vec2{0, 20} * 1_m + GetRandomOffset(); //bd.allowSleep = false; - - const auto body = m_world.CreateBody(bd); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.density = 1_kgpm2; conf.restitution = 0.8f; conf.vertexRadius = radius; - body->CreateFixture(std::make_shared(conf)); + m_world.CreateBody(bd)->CreateFixture(Shape(conf)); } void CreateBox() { const auto side_length = wall_length / Real{5}; // 4 - - auto conf = PolygonShape::Conf{}; - conf.density = 1_kgpm2; - conf.restitution = 0; // originally 0.8 - + // originally restitution was 0.8f BodyDef bd; bd.type = BodyType::Dynamic; bd.bullet = m_bullet_mode; bd.location = Vec2{0, 20} * 1_m + GetRandomOffset(); - const auto body = m_world.CreateBody(bd); - body->CreateFixture(std::make_shared(side_length/Real{2}, side_length/Real{2}, conf)); + m_world.CreateBody(bd)->CreateFixture(Shape{ + PolygonShapeConf{}.UseDensity(1_kgpm2).UseRestitution(0).SetAsBox(side_length/2, side_length/2) + }); } void ToggleBulletMode() diff --git a/Testbed/Tests/ContinuousTest.hpp b/Testbed/Tests/ContinuousTest.hpp index c9faf8d411..ef5006f87f 100644 --- a/Testbed/Tests/ContinuousTest.hpp +++ b/Testbed/Tests/ContinuousTest.hpp @@ -31,26 +31,19 @@ class ContinuousTest : public Test ContinuousTest() { { - BodyDef bd; - bd.location = Length2{}; - Body* body = m_world.CreateBody(bd); - - body->CreateFixture(std::make_shared(Vec2(-10.0f, 0.0f) * 1_m, Vec2(10.0f, 0.0f) * 1_m)); - - const auto shape = PolygonShape::Conf{}.SetAsBox(0.2_m, 1_m, Vec2(0.5f, 1.0f) * 1_m, 0_rad); - body->CreateFixture(std::make_shared(shape)); + const auto body = m_world.CreateBody(); + body->CreateFixture(Shape{EdgeShapeConf{Vec2(-10.0f, 0.0f) * 1_m, Vec2(10.0f, 0.0f) * 1_m}}); + body->CreateFixture(Shape{PolygonShapeConf{}.SetAsBox(0.2_m, 1_m, Vec2(0.5f, 1.0f) * 1_m, 0_rad)}); } { - BodyDef bd; + auto bd = BodyDef{}; bd.type = BodyType::Dynamic; bd.location = Vec2(0.0f, 20.0f) * 1_m; //bd.angle = 0.1f; - const auto shape = std::make_shared(2_m, 0.1_m, - PolygonShape::Conf{}.SetDensity(1_kgpm2)); m_body = m_world.CreateBody(bd); - m_body->CreateFixture(shape); + m_body->CreateFixture(PolygonShapeConf{}.UseDensity(1_kgpm2).SetAsBox(2_m, 0.1_m)); m_angularVelocity = RandomFloat(-50.0f, 50.0f) * 1_rad / 1_s; //m_angularVelocity = 46.661274f; m_body->SetVelocity(Velocity{Vec2(0.0f, -100.0f) * 1_mps, m_angularVelocity}); diff --git a/Testbed/Tests/ConvexHull.hpp b/Testbed/Tests/ConvexHull.hpp index 09fa58f046..d30b7bb7c9 100644 --- a/Testbed/Tests/ConvexHull.hpp +++ b/Testbed/Tests/ConvexHull.hpp @@ -25,7 +25,7 @@ namespace playrho { -class ConvexHull : public Test +class ConvexHullTest : public Test { public: enum: std::size_t @@ -33,7 +33,7 @@ class ConvexHull : public Test e_count = 16 }; - ConvexHull() + ConvexHullTest() { Generate(); m_auto = false; @@ -69,8 +69,7 @@ class ConvexHull : public Test void PostStep(const Settings&, Drawer& drawer) override { - const auto conf = PolygonShape::Conf{}; - const auto shape = PolygonShape{Span{&m_points[0], m_points.size()}, conf}; + const auto shape = PolygonShapeConf{}.Set(Span{&m_points[0], m_points.size()}); drawer.DrawPolygon(shape.GetVertices().begin(), shape.GetVertexCount(), Color(0.9f, 0.9f, 0.9f)); diff --git a/Testbed/Tests/ConveyorBelt.hpp b/Testbed/Tests/ConveyorBelt.hpp index 94ab113997..244616218b 100644 --- a/Testbed/Tests/ConveyorBelt.hpp +++ b/Testbed/Tests/ConveyorBelt.hpp @@ -31,10 +31,8 @@ class ConveyorBelt : public Test ConveyorBelt() { // Ground - { - const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-20.0f, 0.0f) * 1_m, Vec2(20.0f, 0.0f) * 1_m)); - } + m_world.CreateBody()->CreateFixture(Shape{ + EdgeShapeConf{Vec2(-20.0f, 0.0f) * 1_m, Vec2(20.0f, 0.0f) * 1_m}}); // Platform { @@ -42,13 +40,14 @@ class ConveyorBelt : public Test bd.location = Vec2(-5.0f, 5.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.friction = 0.8f; - m_platform = body->CreateFixture(std::make_shared(10_m, 0.5_m, conf)); + conf.SetAsBox(10_m, 0.5_m); + m_platform = body->CreateFixture(Shape{conf}); } // Boxes - const auto boxshape = std::make_shared(0.5_m, 0.5_m, PolygonShape::Conf{}.SetDensity(20_kgpm2)); + const auto boxshape = Shape{PolygonShapeConf{}.UseDensity(20_kgpm2).SetAsBox(0.5_m, 0.5_m)}; for (auto i = 0; i < 5; ++i) { BodyDef bd; diff --git a/Testbed/Tests/DistanceTest.hpp b/Testbed/Tests/DistanceTest.hpp index fd1d4581ae..87cbc55813 100644 --- a/Testbed/Tests/DistanceTest.hpp +++ b/Testbed/Tests/DistanceTest.hpp @@ -118,11 +118,11 @@ class DistanceTest : public Test const auto body = fixture? static_cast(fixture->GetBody()): nullptr; if (body && fixture) { - const auto polygon = static_cast(fixture->GetShape().get()); - auto conf = PolygonShape::Conf{}; + const auto polygon = static_cast(GetData(fixture->GetShape())); + auto conf = PolygonShapeConf{}; conf.Set(polygon->GetVertices()); - conf.SetVertexRadius(polygon->GetVertexRadius() + RadiusIncrement); - const auto newf = body->CreateFixture(std::make_shared(conf)); + conf.UseVertexRadius(polygon->vertexRadius + RadiusIncrement); + const auto newf = body->CreateFixture(Shape{conf}); fixtures.erase(fixtures.begin()); fixtures.insert(newf); SetSelectedFixtures(fixtures); @@ -136,15 +136,15 @@ class DistanceTest : public Test if (body && fixture) { const auto shape = fixture->GetShape(); - const auto lastLegitVertexRadius = shape->GetVertexRadius(); + const auto lastLegitVertexRadius = GetVertexRadius(shape); const auto newVertexRadius = lastLegitVertexRadius - RadiusIncrement; if (newVertexRadius >= 0_m) { - const auto polygon = static_cast(shape.get()); - auto conf = PolygonShape::Conf{}; + const auto polygon = static_cast(GetData(shape)); + auto conf = PolygonShapeConf{}; conf.Set(polygon->GetVertices()); - conf.SetVertexRadius(newVertexRadius); - auto newf = body->CreateFixture(std::make_shared(conf)); + conf.UseVertexRadius(newVertexRadius); + auto newf = body->CreateFixture(Shape{conf}); if (newf) { fixtures.erase(fixtures.begin()); @@ -166,21 +166,21 @@ class DistanceTest : public Test void CreateFixtures() { const auto radius = RadiusIncrement * Real{20}; - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 1_kgpm2; conf.vertexRadius = radius; auto polygonA = conf; //polygonA.SetAsBox(8.0f, 6.0f); polygonA.Set(Span{Vec2{-8, -6} * 1_m, Vec2{8, -6} * 1_m, Vec2{0, 6} * 1_m}); - m_bodyA->CreateFixture(std::make_shared(polygonA)); + m_bodyA->CreateFixture(Shape(polygonA)); conf.vertexRadius = radius * Real{2}; auto polygonB = conf; // polygonB.SetAsBox(7.2_m, 0.8_m); polygonB.Set(Span{Vec2{-7.2f, 0} * 1_m, Vec2{+7.2f, 0} * 1_m}); //polygonB.Set(Span{Vec2{float(-7.2), 0}, Vec2{float(7.2), 0}}); - m_bodyB->CreateFixture(std::make_shared(polygonB)); + m_bodyB->CreateFixture(Shape(polygonB)); } static const Fixture* GetFixture(Body* body) @@ -243,11 +243,11 @@ class DistanceTest : public Test { m_status.clear(); - const auto shapeA = static_cast(GetFixture(m_bodyA)->GetShape().get()); - const auto shapeB = static_cast(GetFixture(m_bodyB)->GetShape().get()); + const auto shapeA = GetFixture(m_bodyA)->GetShape(); + const auto shapeB = GetFixture(m_bodyB)->GetShape(); - const auto proxyA = shapeA->GetChild(0); - const auto proxyB = shapeB->GetChild(0); + const auto proxyA = GetChild(shapeA, 0); + const auto proxyB = GetChild(shapeB, 0); const auto xfmA = m_bodyA->GetTransformation(); const auto xfmB = m_bodyB->GetTransformation(); @@ -315,15 +315,17 @@ class DistanceTest : public Test if (AlmostEqual(static_cast(Real{maxIndicesAB.distance / 1_m}), static_cast(Real{maxIndicesBA.distance / 1_m}))) { + const auto childA = GetChild(shapeA, 0); + const auto childB = GetChild(shapeB, 0); //assert(maxIndicesAB.index1 == maxIndicesBA.index2); //assert(maxIndicesAB.index2 == maxIndicesBA.index1); const auto ifaceA = maxIndicesAB.indices.first; - const auto nA = InverseRotate(Rotate(shapeA->GetNormal(ifaceA), xfmA.q), xfmB.q); + const auto nA = InverseRotate(Rotate(childA.GetNormal(ifaceA), xfmA.q), xfmB.q); // shapeA face maxIndicesAB.index1 is coplanar to an edge intersecting shapeB vertex maxIndicesAB.index2 const auto i1 = maxIndicesAB.indices.second; - const auto i0 = GetModuloPrev(i1, shapeB->GetVertexCount()); - const auto n0 = shapeB->GetNormal(i0); - const auto n1 = shapeB->GetNormal(i1); + const auto i0 = GetModuloPrev(i1, childB.GetVertexCount()); + const auto n0 = childB.GetNormal(i0); + const auto n1 = childB.GetNormal(i1); const auto s0 = Dot(nA, n0); const auto s1 = Dot(nA, n1); assert(s0 != s1); diff --git a/Testbed/Tests/Dominos.hpp b/Testbed/Tests/Dominos.hpp index 3c6e006ac5..ffa63b08a6 100644 --- a/Testbed/Tests/Dominos.hpp +++ b/Testbed/Tests/Dominos.hpp @@ -31,18 +31,19 @@ class Dominos : public Test Dominos() { const auto b1 = m_world.CreateBody(); - b1->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); + b1->CreateFixture(EdgeShapeConf(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); { BodyDef bd; bd.location = Vec2(-1.5f, 10.0f) * 1_m; const auto ground = m_world.CreateBody(bd); - ground->CreateFixture(std::make_shared(PolygonShape{6_m, 0.25_m})); + ground->CreateFixture(PolygonShapeConf{6_m, 0.25_m}); } { - const auto shape = std::make_shared(0.1_m, 1_m, - PolygonShape::Conf{}.SetDensity(20_kgpm2).SetFriction(Real(0.05f))); + const auto shape = Shape{ + PolygonShapeConf{}.UseDensity(20_kgpm2).UseFriction(Real(0.05f)).SetAsBox(0.1_m, 1_m) + }; for (auto i = 0; i < 10; ++i) { const auto body = m_world.CreateBody(BodyDef{} @@ -53,17 +54,17 @@ class Dominos : public Test } { - auto shape = PolygonShape::Conf{}; + auto shape = PolygonShapeConf{}; shape.SetAsBox(7.2_m, 0.25_m, Length2{}, 0.3_rad); BodyDef bd; bd.location = Vec2(1.2f, 6.0f) * 1_m; const auto ground = m_world.CreateBody(bd); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(Shape(shape)); } const auto b2 = m_world.CreateBody(BodyDef{}.UseLocation(Vec2(-7.0f, 4.0f) * 1_m)); - b2->CreateFixture(std::make_shared(0.25_m, 1.5_m)); + b2->CreateFixture(PolygonShapeConf{}.SetAsBox(0.25_m, 1.5_m)); Body* b3; { @@ -71,11 +72,8 @@ class Dominos : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(-0.9f, 1.0f) * 1_m; bd.angle = -0.15_rad; - b3 = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; - conf.density = 10_kgpm2; - b3->CreateFixture(std::make_shared(6_m, 0.125_m, conf)); + b3->CreateFixture(PolygonShapeConf{}.UseDensity(10_kgpm2).SetAsBox(6_m, 0.125_m)); } m_world.CreateJoint(RevoluteJointDef{b1, b3, Vec2(-2, 1) * 1_m}.UseCollideConnected(true)); @@ -86,9 +84,7 @@ class Dominos : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(-10.0f, 15.0f) * 1_m; b4 = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; - conf.density = 10_kgpm2; - b4->CreateFixture(std::make_shared(0.25_m, 0.25_m, conf)); + b4->CreateFixture(PolygonShapeConf{}.UseDensity(10_kgpm2).SetAsBox(0.25_m, 0.25_m)); } m_world.CreateJoint(RevoluteJointDef{b2, b4, Vec2(-7, 15) * 1_m}.UseCollideConnected(true)); @@ -100,15 +96,15 @@ class Dominos : public Test bd.location = Vec2(6.5f, 3.0f) * 1_m; b5 = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 10_kgpm2; conf.friction = 0.1f; conf.SetAsBox(1_m, 0.1_m, Vec2(0.0f, -0.9f) * 1_m, 0_rad); - b5->CreateFixture(std::make_shared(conf)); + b5->CreateFixture(Shape{conf}); conf.SetAsBox(0.1_m, 1_m, Vec2(-0.9f, 0.0f) * 1_m, 0_rad); - b5->CreateFixture(std::make_shared(conf)); + b5->CreateFixture(Shape{conf}); conf.SetAsBox(0.1_m, 1_m, Vec2(0.9f, 0.0f) * 1_m, 0_rad); - b5->CreateFixture(std::make_shared(conf)); + b5->CreateFixture(Shape{conf}); } m_world.CreateJoint(RevoluteJointDef{b1, b5, Vec2(6, 2) * 1_m}.UseCollideConnected(true)); @@ -119,9 +115,7 @@ class Dominos : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(6.5f, 4.1f) * 1_m; b6 = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; - conf.density = 30_kgpm2; - b6->CreateFixture(std::make_shared(PolygonShape(1_m, 0.1_m, conf))); + b6->CreateFixture(PolygonShapeConf(1_m, 0.1_m).UseDensity(30_kgpm2)); } m_world.CreateJoint(RevoluteJointDef{b5, b6, Vec2(7.5f, 4.0f) * 1_m} @@ -134,9 +128,10 @@ class Dominos : public Test bd.location = Vec2(7.4f, 1.0f) * 1_m; b7 = m_world.CreateBody(bd); - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 10_kgpm2; - b7->CreateFixture(std::make_shared(PolygonShape(0.1_m, 1_m, conf))); + conf.SetAsBox(0.1_m, 1_m); + b7->CreateFixture(Shape{conf}); } DistanceJointDef djd; @@ -150,10 +145,10 @@ class Dominos : public Test { const auto radius = 0.2_m; - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.density = 10_kgpm2; conf.vertexRadius = radius; - const auto shape = std::make_shared(conf); + const auto shape = Shape(conf); for (auto i = 0; i < 4; ++i) { BodyDef bd; diff --git a/Testbed/Tests/DumpShell.hpp b/Testbed/Tests/DumpShell.hpp index 03d33a330d..96270a6acd 100644 --- a/Testbed/Tests/DumpShell.hpp +++ b/Testbed/Tests/DumpShell.hpp @@ -63,23 +63,23 @@ class DumpShell : public Test bodies[0] = m_world.CreateBody(bd); { - auto shape = PolygonShape::Conf{}; + auto shape = PolygonShapeConf{}; Length2 vs[8]; vs[0] = Vec2(7.733039855957031e-01f, -1.497260034084320e-01f) * 1_m; vs[1] = Vec2(-4.487270116806030e-01f, 1.138330027461052e-01f) * 1_m; vs[2] = Vec2(-1.880589962005615e+00f, -1.365900039672852e-01f) * 1_m; vs[3] = Vec2(3.972740173339844e-01f, -3.897832870483398e+00f) * 1_m; shape.Set(Span(vs, 4)); - shape.SetFriction(Real(2.000000029802322e-01f)); - shape.SetRestitution(Real(0.000000000000000e+00f)); - shape.SetDensity(Real{1.000000000000000e+00f} * 1_kgpm2); + shape.UseFriction(Real(2.000000029802322e-01f)); + shape.UseRestitution(Real(0.000000000000000e+00f)); + shape.UseDensity(Real{1.000000000000000e+00f} * 1_kgpm2); FixtureDef fd; fd.isSensor = bool(0); fd.filter.categoryBits = Filter::bits_type(1); fd.filter.maskBits = Filter::bits_type(65535); fd.filter.groupIndex = Filter::index_type(0); - bodies[0]->CreateFixture(std::make_shared(shape), fd); + bodies[0]->CreateFixture(Shape(shape), fd); } } { @@ -99,7 +99,7 @@ class DumpShell : public Test bodies[1] = m_world.CreateBody(bd); { - auto shape = PolygonShape::Conf{}; + auto shape = PolygonShapeConf{}; Length2 vs[8]; vs[0] = Vec2(3.473900079727173e+00f, -2.009889930486679e-01f) * 1_m; vs[1] = Vec2(3.457079887390137e+00f, 3.694039955735207e-02f) * 1_m; @@ -108,15 +108,15 @@ class DumpShell : public Test vs[4] = Vec2(-2.590820074081421e+00f, -5.472509860992432e-01f) * 1_m; vs[5] = Vec2(2.819370031356812e+00f, -5.402340292930603e-01f) * 1_m; shape.Set(Span(vs, 6)); - shape.SetFriction(Real(5.000000000000000e-01f)); - shape.SetRestitution(Real(0.000000000000000e+00f)); - shape.SetDensity(Real{5.000000000000000e+00f} * 1_kgpm2); + shape.UseFriction(Real(5.000000000000000e-01f)); + shape.UseRestitution(Real(0.000000000000000e+00f)); + shape.UseDensity(Real{5.000000000000000e+00f} * 1_kgpm2); FixtureDef fd; fd.isSensor = bool(0); fd.filter.categoryBits = Filter::bits_type(1); fd.filter.maskBits = Filter::bits_type(65535); fd.filter.groupIndex = Filter::index_type(0); - bodies[1]->CreateFixture(std::make_shared(shape), fd); + bodies[1]->CreateFixture(Shape(shape), fd); } } { @@ -136,22 +136,22 @@ class DumpShell : public Test bodies[2] = m_world.CreateBody(bd); { - auto shape = PolygonShape::Conf{}; + auto shape = PolygonShapeConf{}; Length2 vs[8]; vs[0] = Vec2(1.639146506786346e-01f, 4.428443685173988e-02f) * 1_m; vs[1] = Vec2(-1.639146655797958e-01f, 4.428443685173988e-02f) * 1_m; vs[2] = Vec2(-1.639146655797958e-01f, -4.428443312644958e-02f) * 1_m; vs[3] = Vec2(1.639146357774734e-01f, -4.428444057703018e-02f) * 1_m; shape.Set(Span(vs, 4)); - shape.SetFriction(Real(9.499999880790710e-01f)); - shape.SetRestitution(Real(0.000000000000000e+00f)); - shape.SetDensity(Real{1.000000000000000e+01f} * 1_kgpm2); + shape.UseFriction(Real(9.499999880790710e-01f)); + shape.UseRestitution(Real(0.000000000000000e+00f)); + shape.UseDensity(Real{1.000000000000000e+01f} * 1_kgpm2); FixtureDef fd; fd.isSensor = bool(0); fd.filter.categoryBits = Filter::bits_type(1); fd.filter.maskBits = Filter::bits_type(65535); fd.filter.groupIndex = Filter::index_type(-3); - bodies[2]->CreateFixture(std::make_shared(shape), fd); + bodies[2]->CreateFixture(Shape(shape), fd); } } Free(joints); diff --git a/Testbed/Tests/EdgeShapes.hpp b/Testbed/Tests/EdgeShapes.hpp index 781da878de..e4ef4c9bfd 100644 --- a/Testbed/Tests/EdgeShapes.hpp +++ b/Testbed/Tests/EdgeShapes.hpp @@ -46,28 +46,28 @@ class EdgeShapes : public Test { const auto x2 = x1 + 0.5f; const auto y2 = 2.0f * std::cos(x2 / 10.0f * static_cast(Pi)); - ground->CreateFixture(std::make_shared(Vec2(x1, y1) * 1_m, Vec2(x2, y2) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(x1, y1) * 1_m, Vec2(x2, y2) * 1_m}}); x1 = x2; y1 = y2; } } - auto conf = PolygonShape::Conf{}; - conf.SetFriction(Real(0.3f)); - conf.SetDensity(20_kgpm2); + auto conf = PolygonShapeConf{}; + conf.UseFriction(Real(0.3f)); + conf.UseDensity(20_kgpm2); conf.Set({ Vec2(-0.5f, 0.0f) * 1_m, Vec2(0.5f, 0.0f) * 1_m, Vec2(0.0f, 1.5f) * 1_m }); - m_polygons[0] = std::make_shared(conf); + m_polygons[0] = Shape(conf); conf.Set({ Vec2(-0.1f, 0.0f) * 1_m, Vec2(0.1f, 0.0f) * 1_m, Vec2(0.0f, 1.5f) * 1_m }); - m_polygons[1] = std::make_shared(conf); + m_polygons[1] = Shape(conf); { const auto w = 1.0f; @@ -84,11 +84,11 @@ class EdgeShapes : public Test Vec2(-0.5f * w, b) * 1_m, Vec2(-0.5f * s, 0.0f) * 1_m }); - m_polygons[2] = std::make_shared(conf); + m_polygons[2] = Shape(conf); } conf.SetAsBox(0.5_m, 0.5_m); - m_polygons[3] = std::make_shared(conf); + m_polygons[3] = Shape(conf); m_bodyIndex = 0; std::memset(m_bodies, 0, sizeof(m_bodies)); @@ -202,9 +202,8 @@ class EdgeShapes : public Test int m_bodyIndex; Body* m_bodies[e_maxBodies]; - std::shared_ptr m_polygons[4]; - std::shared_ptr m_circle = std::make_shared(0.5_m, - DiskShape::Conf{}.SetFriction(Real(0.3f)).SetDensity(20_kgpm2)); + Shape m_polygons[4] = {PolygonShapeConf{}, PolygonShapeConf{}, PolygonShapeConf{}, PolygonShapeConf{}}; + Shape m_circle = Shape{DiskShapeConf{}.UseRadius(0.5_m).UseFriction(Real(0.3f)).UseDensity(20_kgpm2)}; Real m_angle; }; diff --git a/Testbed/Tests/EdgeTest.hpp b/Testbed/Tests/EdgeTest.hpp index 3d3cceea7b..a78e9579fe 100644 --- a/Testbed/Tests/EdgeTest.hpp +++ b/Testbed/Tests/EdgeTest.hpp @@ -41,19 +41,19 @@ class EdgeTest : public Test const auto v6 = Vec2(7.0f, 2.0f) * 1_m; const auto v7 = Vec2(10.0f, 0.0f) * 1_m; - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.Set(v1, v2); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(v2, v3); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(v3, v4); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(v4, v5); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(v5, v6); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(v6, v7); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); } { @@ -63,10 +63,10 @@ class EdgeTest : public Test bd.allowSleep = false; const auto body = m_world.CreateBody(bd); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.density = 1_kgpm2; conf.vertexRadius = 0.5_m; - body->CreateFixture(std::make_shared(conf)); + body->CreateFixture(Shape(conf)); } { @@ -76,11 +76,11 @@ class EdgeTest : public Test bd.allowSleep = false; const auto body = m_world.CreateBody(bd); - auto shape = PolygonShape::Conf{}; - shape.SetVertexRadius(1_m); + auto shape = PolygonShapeConf{}; + shape.UseVertexRadius(1_m); shape.SetAsBox(0.5_m, 0.5_m); - shape.SetDensity(1_kgpm2); - body->CreateFixture(std::make_shared(shape)); + shape.UseDensity(1_kgpm2); + body->CreateFixture(Shape(shape)); } } }; diff --git a/Testbed/Tests/FifteenPuzzle.hpp b/Testbed/Tests/FifteenPuzzle.hpp index 2454416f20..2ebcd6e243 100644 --- a/Testbed/Tests/FifteenPuzzle.hpp +++ b/Testbed/Tests/FifteenPuzzle.hpp @@ -73,9 +73,10 @@ namespace playrho { const auto halfSide = sideLength / Real{2} - skinWidth; const auto relPos = Length2{(col - 2) * sideLength, (row - 2) * sideLength}; - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.density = 1_kgpm2; conf.vertexRadius = skinWidth; + conf.SetAsBox(halfSide, halfSide); BodyDef bd; bd.type = BodyType::Dynamic; @@ -83,7 +84,7 @@ namespace playrho { bd.location = GetCenter() + relPos + Length2{sideLength / 2, sideLength / 2}; bd.linearDamping = 20_Hz; const auto body = m_world.CreateBody(bd); - body->CreateFixture(std::make_shared(halfSide, halfSide, conf)); + body->CreateFixture(conf); return body; } diff --git a/Testbed/Tests/Gears.hpp b/Testbed/Tests/Gears.hpp index ac7bab83af..db0021e606 100644 --- a/Testbed/Tests/Gears.hpp +++ b/Testbed/Tests/Gears.hpp @@ -30,11 +30,11 @@ class Gears : public Test Gears() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(50.0f, 0.0f) * 1_m, Vec2(-50.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(50.0f, 0.0f) * 1_m, Vec2(-50.0f, 0.0f) * 1_m}}); - const auto circle1 = std::make_shared(1_m, DiskShape::Conf{}.SetDensity(5_kgpm2)); - const auto circle2 = std::make_shared(2_m, DiskShape::Conf{}.SetDensity(5_kgpm2)); - const auto box = std::make_shared(0.5_m, 5_m, PolygonShape::Conf{}.SetDensity(5_kgpm2)); + const auto circle1 = DiskShapeConf{}.UseRadius(1_m).UseDensity(5_kgpm2); + const auto circle2 = DiskShapeConf{}.UseRadius(2_m).UseDensity(5_kgpm2); + const auto box = Shape{PolygonShapeConf{}.SetAsBox(0.5_m, 5_m).UseDensity(5_kgpm2)}; { auto bd1 = BodyDef{}; @@ -58,7 +58,7 @@ class Gears : public Test auto joint2 = m_world.CreateJoint(RevoluteJointDef{body2, body3, bd3.location}); auto jd4 = GearJointDef{joint1, joint2}; - jd4.ratio = circle2->GetRadius() / circle1->GetRadius(); + jd4.ratio = circle2.GetRadius() / circle1.GetRadius(); m_world.CreateJoint(jd4); } @@ -100,11 +100,11 @@ class Gears : public Test m_joint3 = static_cast(m_world.CreateJoint(jd3)); auto jd4 = GearJointDef{m_joint1, m_joint2}; - jd4.ratio = circle2->GetRadius() / circle1->GetRadius(); + jd4.ratio = circle2.GetRadius() / circle1.GetRadius(); m_joint4 = static_cast(m_world.CreateJoint(jd4)); auto jd5 = GearJointDef{m_joint2, m_joint3}; - jd5.ratio = -1.0f / (circle2->GetRadius() / 1_m); + jd5.ratio = -1.0f / (circle2.GetRadius() / 1_m); m_joint5 = static_cast(m_world.CreateJoint(jd5)); } } diff --git a/Testbed/Tests/HalfPipe.hpp b/Testbed/Tests/HalfPipe.hpp index 1a97df3934..c8ea1d467e 100644 --- a/Testbed/Tests/HalfPipe.hpp +++ b/Testbed/Tests/HalfPipe.hpp @@ -26,24 +26,19 @@ namespace playrho { class HalfPipe : public Test { public: - HalfPipe() { const auto pipeBody = m_world.CreateBody(BodyDef{}.UseLocation(Vec2(0, 20) * 1_m)); { - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.UseFriction(Real(1)); - conf.vertices = GetCircleVertices(20_m, 90, 180_deg, Real(0.5f)); - pipeBody->CreateFixture(std::make_shared(conf)); + conf.Set(GetCircleVertices(20_m, 90, 180_deg, Real(0.5f))); + pipeBody->CreateFixture(Shape{conf}); } - const auto ballBody = m_world.CreateBody(BodyDef{} .UseType(BodyType::Dynamic) .UseLocation(Vec2(-19, 28) * 1_m)); - ballBody->CreateFixture(std::make_shared(DiskShape::Conf{} - .UseDensity(0.01_kgpm2) - .UseVertexRadius(1_m) - .UseFriction(Real(1)))); + ballBody->CreateFixture(DiskShapeConf{}.UseDensity(0.01_kgpm2).UseRadius(1_m).UseFriction(Real(1))); } }; diff --git a/Testbed/Tests/HeavyOnLight.hpp b/Testbed/Tests/HeavyOnLight.hpp index 826817b14e..ac1010dfbb 100644 --- a/Testbed/Tests/HeavyOnLight.hpp +++ b/Testbed/Tests/HeavyOnLight.hpp @@ -34,22 +34,20 @@ class HeavyOnLight : public Test const auto upperBodyDef = BodyDef(bd).UseLocation(Vec2(0.0f, 6.0f) * 1_m); const auto lowerBodyDef = BodyDef(bd).UseLocation(Vec2(0.0f, 0.5f) * 1_m); - const auto groundConf = EdgeShape::Conf{} - .UseVertex1(Vec2(-40.0f, 0.0f) * 1_m) - .UseVertex2(Vec2(40.0f, 0.0f) * 1_m); + const auto groundConf = EdgeShapeConf{} + .Set(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m); - const auto diskConf = DiskShape::Conf{}.UseDensity(10_kgpm2); - const auto smallerDiskConf = DiskShape::Conf(diskConf).UseVertexRadius(0.5_m); - const auto biggerDiskConf = DiskShape::Conf(diskConf).UseVertexRadius(5_m); + const auto diskConf = DiskShapeConf{}.UseDensity(10_kgpm2); + const auto smallerDiskConf = DiskShapeConf(diskConf).UseRadius(0.5_m); + const auto biggerDiskConf = DiskShapeConf(diskConf).UseRadius(5_m); - const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(groundConf)); + m_world.CreateBody()->CreateFixture(Shape(groundConf)); const auto lowerBody = m_world.CreateBody(lowerBodyDef); const auto upperBody = m_world.CreateBody(upperBodyDef); - lowerBody->CreateFixture(std::make_shared(smallerDiskConf)); - m_top = upperBody->CreateFixture(std::make_shared(biggerDiskConf)); + lowerBody->CreateFixture(Shape(smallerDiskConf)); + m_top = upperBody->CreateFixture(Shape(biggerDiskConf)); RegisterForKey(GLFW_KEY_KP_ADD, GLFW_PRESS, 0, "increase density of top shape", [&](KeyActionMods) { ChangeDensity(+1_kgpm2); @@ -61,7 +59,7 @@ class HeavyOnLight : public Test void ChangeDensity(AreaDensity change) { - const auto oldDensity = m_top->GetShape()->GetDensity(); + const auto oldDensity = m_top->GetDensity(); const auto newDensity = std::max(oldDensity + change, 1_kgpm2); if (newDensity != oldDensity) { @@ -70,10 +68,10 @@ class HeavyOnLight : public Test const auto wasSelected = selectedFixture == m_top; const auto body = m_top->GetBody(); body->DestroyFixture(m_top); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 5_m; conf.density = newDensity; - m_top = body->CreateFixture(std::make_shared(conf)); + m_top = body->CreateFixture(Shape(conf)); if (wasSelected) { selectedFixtures.erase(selectedFixtures.begin()); @@ -87,7 +85,7 @@ class HeavyOnLight : public Test { std::stringstream stream; stream << "Area density of top shape: "; - stream << double(Real{m_top->GetShape()->GetDensity() / 1_kgpm2}); + stream << double(Real{m_top->GetDensity() / 1_kgpm2}); stream << " kg/m^2."; m_status = stream.str(); } diff --git a/Testbed/Tests/HeavyOnLightTwo.hpp b/Testbed/Tests/HeavyOnLightTwo.hpp index a589717e13..0402833b3c 100644 --- a/Testbed/Tests/HeavyOnLightTwo.hpp +++ b/Testbed/Tests/HeavyOnLightTwo.hpp @@ -31,7 +31,7 @@ class HeavyOnLightTwo : public Test public: HeavyOnLightTwo() { - m_world.CreateBody()->CreateFixture(std::make_shared(GetGroundEdgeConf())); + m_world.CreateBody()->CreateFixture(Shape(GetGroundEdgeConf())); // Use () instead of {} to avoid MSVC++ doing const preserving copy elision. m_world.CreateBody(BodyDef(DynBD).UseLocation(Length2{0_m, 2.5_m}))->CreateFixture(lilDisk); m_world.CreateBody(BodyDef(DynBD).UseLocation(Length2{0_m, 3.5_m}))->CreateFixture(lilDisk); @@ -56,9 +56,9 @@ class HeavyOnLightTwo : public Test } const BodyDef DynBD = BodyDef{}.UseType(BodyType::Dynamic); - const DiskShape::Conf DiskDef = DiskShape::Conf{}.UseDensity(10_kgpm2); - const std::shared_ptr lilDisk = std::make_shared(0.5_m, DiskDef); - const std::shared_ptr bigDisk = std::make_shared(5.0_m, DiskDef); + const DiskShapeConf DiskDef = DiskShapeConf{}.UseDensity(10_kgpm2); + const Shape lilDisk = DiskShapeConf(DiskDef).UseRadius(0.5_m); + const Shape bigDisk = DiskShapeConf(DiskDef).UseRadius(5.0_m); Body* m_heavy = nullptr; }; diff --git a/Testbed/Tests/JointsTest.hpp b/Testbed/Tests/JointsTest.hpp index f19caee863..c564a76b98 100644 --- a/Testbed/Tests/JointsTest.hpp +++ b/Testbed/Tests/JointsTest.hpp @@ -36,23 +36,11 @@ class JointsTest: public Test return conf; } - using DiskConf = DiskShape::Conf; - using PolyConf = PolygonShape::Conf; + using DiskConf = DiskShapeConf; + using PolyConf = PolygonShapeConf; JointsTest(): Test(GetTestConf()) { - m_diskShape = std::make_shared(DiskConf{} - .UseVertexRadius(1_m).UseDensity(1_kgpm2)); - m_smallDiskShape = std::make_shared(DiskConf{} - .UseVertexRadius(0.5_m) - .UseDensity(1_kgpm2) - .UseRestitution(Real(0))); - m_squareShape = std::make_shared(PolygonShape{0.5_m, 0.5_m, - PolyConf{}.UseDensity(1_kgpm2) - }); - m_rectShape = std::make_shared(PolygonShape{RectHWidth, RectHHeight, - PolyConf{}.UseDensity(1_kgpm2)}); - // Eleven joint types. Arrange demos in a 4 column by 3 row layout. const auto columnStart = -1.5f * ColumnSize; @@ -196,13 +184,12 @@ class JointsTest: public Test const auto right = Length2{+2_m, +2.5_m}; { // Use () instead of {} to avoid MSVC++ doing const preserving copy elision. - const auto conf = DiskConf{}.UseVertexRadius(0.7_m); - cbody->CreateFixture(std::make_shared(DiskConf(conf).UseLocation(left))); - cbody->CreateFixture(std::make_shared(DiskConf(conf).UseLocation(right))); + const auto conf = DiskConf{}.UseRadius(0.7_m); + cbody->CreateFixture(DiskConf(conf).UseLocation(left)); + cbody->CreateFixture(DiskConf(conf).UseLocation(right)); } { - const auto pconf = PolyConf{}.UseDensity(5_kgpm2); - const auto shape = std::make_shared(0.5_m, 0.5_m, pconf); + const auto shape = Shape{PolyConf{}.UseDensity(5_kgpm2).SetAsBox(0.5_m, 0.5_m)}; const auto ganchor1 = center + left; const auto ganchor2 = center + right; const auto anchor1 = ganchor1 - Length2{0_m, 1.5_m}; @@ -224,8 +211,8 @@ class JointsTest: public Test { const auto containerBody = SetupContainer(center); - const auto sr = m_smallDiskShape->GetVertexRadius(); - const auto nr = m_diskShape->GetVertexRadius(); + const auto sr = GetVertexRadius(m_smallDiskShape); + const auto nr = GetVertexRadius(m_diskShape); const auto tr = sr + nr; const auto bd1 = BodyDef(DynamicBD).UseLocation(center - Length2{tr, 0_m}); const auto body1 = m_world.CreateBody(bd1); @@ -260,11 +247,11 @@ class JointsTest: public Test const auto joint3 = static_cast(m_world.CreateJoint(jd3)); auto jd4 = GearJointDef{joint1, joint2}; - jd4.ratio = m_diskShape->GetRadius() / m_smallDiskShape->GetRadius(); + jd4.ratio = GetVertexRadius(m_diskShape) / GetVertexRadius(m_smallDiskShape); m_gearJoint0 = static_cast(m_world.CreateJoint(jd4)); auto jd5 = GearJointDef{joint2, joint3}; - jd5.ratio = -1.0f / (m_diskShape->GetRadius() / 1_m); + jd5.ratio = -1.0f / (GetVertexRadius(m_diskShape) / 1_m); m_gearJoint1 = static_cast(m_world.CreateJoint(jd5)); } @@ -281,13 +268,12 @@ class JointsTest: public Test Vec2(-1.15f, 0.9f) * 1_m, Vec2(-1.5f, 0.2f) * 1_m }); - const auto chassis = std::make_shared(Span(carVerts.data(), carVerts.size()), - PolygonShape::Conf{}.SetDensity(1_kgpm2)); - const auto circle = std::make_shared(0.4_m, DiskShape::Conf{}.SetDensity(1_kgpm2).SetFriction(Real(0.9f))); + const auto circle = Shape{ + DiskShapeConf{}.UseDensity(1_kgpm2).UseFriction(Real(0.9f)).UseRadius(0.4_m)}; const auto carLocation = center - Vec2(3.3f, 1.0f) * 1_m; const auto car = m_world.CreateBody(BodyDef(DynamicBD).UseLocation(carLocation)); - car->CreateFixture(chassis); + car->CreateFixture(PolygonShapeConf{}.UseDensity(1_kgpm2).Set(Span(carVerts.data(), carVerts.size()))); const auto backWheel = m_world.CreateBody(BodyDef(DynamicBD).UseLocation(carLocation + Vec2(-1.0f, -0.65f) * 1_m)); backWheel->CreateFixture(circle); @@ -371,11 +357,11 @@ class JointsTest: public Test { const auto lftEye = m_world.CreateBody(BodyDef(StaticBD).UseLocation(ctr + lftOffs)); const auto rgtEye = m_world.CreateBody(BodyDef(StaticBD).UseLocation(ctr + rgtOffs)); - auto cconf = ChainShape::Conf{}; + auto cconf = ChainShapeConf{}; cconf.restitution = 0; cconf.friction = 0; - cconf.vertices = GetCircleVertices(1.8_m, 24, 0_deg, 1); - const auto eyeEnc = std::make_shared(cconf); + cconf.Set(GetCircleVertices(1.8_m, 24, 0_deg, 1)); + const auto eyeEnc = Shape(cconf); lftEye->CreateFixture(eyeEnc); rgtEye->CreateFixture(eyeEnc); } @@ -438,10 +424,10 @@ class JointsTest: public Test const BodyDef DynamicBD = BodyDef{}.UseType(BodyType::Dynamic); const Length RectHHeight = 0.25_m; const Length RectHWidth = 2_m; - std::shared_ptr m_diskShape; - std::shared_ptr m_smallDiskShape; - std::shared_ptr m_squareShape; - std::shared_ptr m_rectShape; + Shape m_diskShape{DiskConf{}.UseRadius(1_m).UseDensity(1_kgpm2)}; + Shape m_smallDiskShape{DiskConf{}.UseRadius(0.5_m).UseDensity(1_kgpm2).UseRestitution(Real(0))}; + Shape m_squareShape{PolyConf{}.UseDensity(1_kgpm2).SetAsBox(0.5_m, 0.5_m)}; + Shape m_rectShape{PolyConf{}.UseDensity(1_kgpm2).SetAsBox(RectHWidth, RectHHeight)}; const Length2 offset = Length2{+2_m, 0_m}; double m_time = 0; diff --git a/Testbed/Tests/Mobile.hpp b/Testbed/Tests/Mobile.hpp index cd56efea56..1ffefbe8bc 100644 --- a/Testbed/Tests/Mobile.hpp +++ b/Testbed/Tests/Mobile.hpp @@ -39,8 +39,7 @@ class Mobile : public Test const auto ground = m_world.CreateBody(BodyDef{}.UseLocation(Vec2(0.0f, 20.0f) * 1_m)); const auto a = Real{0.5f}; - const auto shape = std::make_shared(Real{0.25f} * a * 1_m, a * 1_m, - PolygonShape::Conf{}.SetDensity(20_kgpm2)); + const auto shape = Shape(PolygonShapeConf{}.UseDensity(20_kgpm2).SetAsBox(Real{0.25f} * a * 1_m, a * 1_m)); RevoluteJointDef jointDef; jointDef.bodyA = ground; @@ -51,7 +50,7 @@ class Mobile : public Test } Body* AddNode(Body* parent, Length2 localAnchor, int depth, float offset, float a, - std::shared_ptr shape) + Shape shape) { const auto h = Vec2(0.0f, a) * 1_m; diff --git a/Testbed/Tests/MobileBalanced.hpp b/Testbed/Tests/MobileBalanced.hpp index 9a636d6eb2..8cefb1f0d7 100644 --- a/Testbed/Tests/MobileBalanced.hpp +++ b/Testbed/Tests/MobileBalanced.hpp @@ -39,15 +39,12 @@ class MobileBalanced : public Test { const auto ground = m_world.CreateBody(BodyDef{}.UseLocation(Vec2(0.0f, 20.0f) * 1_m)); - const auto a = Real{0.5f}; - const auto h = Vec2(0.0f, a) * 1_m; + const auto a = 0.5_m; + const auto h = Length2{0_m, a}; + const auto root = AddNode(ground, Length2{}, 0, 3.0f, a, + PolygonShapeConf{}.UseDensity(density).SetAsBox(a * 1_m / 4, a * 1_m)); - auto conf = PolygonShape::Conf{}; - conf.density = density; - const auto shape = std::make_shared(Real{0.25f} * a * 1_m, a * 1_m, conf); - const auto root = AddNode(ground, Length2{}, 0, 3.0f, a, shape); - - RevoluteJointDef jointDef; + auto jointDef = RevoluteJointDef{}; jointDef.bodyA = ground; jointDef.bodyB = root; jointDef.localAnchorA = Length2{}; @@ -56,10 +53,9 @@ class MobileBalanced : public Test } Body* AddNode(const Body* parent, const Length2 localAnchor, const int depth, - const Real offset, const Real a, std::shared_ptr shape) + const Real offset, const Length a, Shape shape) { - const auto h = Vec2(0.0f, a) * 1_m; - + const auto h = Length2{0_m, a}; const auto p = parent->GetLocation() + localAnchor - h; BodyDef bodyDef; @@ -74,15 +70,15 @@ class MobileBalanced : public Test return body; } - auto shape2 = PolygonShape::Conf{}; - shape2.SetDensity(density); - shape2.SetAsBox(offset * 1_m, Real{0.25f} * a * 1_m, Vec2(0, -a) * 1_m, 0_rad); - body->CreateFixture(std::make_shared(shape2)); + auto shape2 = PolygonShapeConf{}; + shape2.UseDensity(density); + shape2.SetAsBox(offset * 1_m, a / 4, Length2{0_m, -a}, 0_rad); + body->CreateFixture(Shape(shape2)); - const auto a1 = Vec2(offset, -a) * 1_m; - const auto a2 = Vec2(-offset, -a) * 1_m; - const auto body1 = AddNode(body, a1, depth + 1, 0.5f * offset, a, shape); - const auto body2 = AddNode(body, a2, depth + 1, 0.5f * offset, a, shape); + const auto a1 = Length2{offset * 1_m, -a}; + const auto a2 = Length2{-offset * 1_m, -a}; + const auto body1 = AddNode(body, a1, depth + 1, offset / 2, a, shape); + const auto body2 = AddNode(body, a2, depth + 1, offset / 2, a, shape); RevoluteJointDef jointDef; jointDef.bodyA = body; diff --git a/Testbed/Tests/MotorJoint.hpp b/Testbed/Tests/MotorJoint.hpp index 1d1eaf3fc6..c29b78820b 100644 --- a/Testbed/Tests/MotorJoint.hpp +++ b/Testbed/Tests/MotorJoint.hpp @@ -42,16 +42,13 @@ class MotorJointTest : public Test MotorJointTest(): Test(GetTestConf()) { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-20.0f, 0.0f) * 1_m, Vec2(20.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-20.0f, 0.0f) * 1_m, Vec2(20.0f, 0.0f) * 1_m}}); // Define motorized body const auto body = m_world.CreateBody(BodyDef{} .UseType(BodyType::Dynamic) .UseLocation(Vec2(0.0f, 8.0f) * 1_m)); - - const auto conf = PolygonShape::Conf{}.UseFriction(Real(0.6f)).UseDensity(2_kgpm2); - body->CreateFixture(std::make_shared(2_m, 0.5_m, conf)); - + body->CreateFixture(PolygonShapeConf{}.SetAsBox(2_m, 0.5_m).UseFriction(Real(0.6f)).UseDensity(2_kgpm2)); auto mjd = MotorJointDef{ground, body}; mjd.maxForce = 1000_N; mjd.maxTorque = 1000_Nm; diff --git a/Testbed/Tests/NewtonsCradle.hpp b/Testbed/Tests/NewtonsCradle.hpp index 6f56df6223..5cbe90dbcb 100644 --- a/Testbed/Tests/NewtonsCradle.hpp +++ b/Testbed/Tests/NewtonsCradle.hpp @@ -106,8 +106,8 @@ namespace playrho { const auto body = m_world.CreateBody(bd); const auto frame_width = frame_width_per_arm * static_cast(m_num_arms); - const auto shape = PolygonShape::Conf{}.SetAsBox(frame_width / 2, frame_width / 24).SetDensity(20_kgpm2); - body->CreateFixture(std::make_shared(shape)); + const auto shape = PolygonShapeConf{}.SetAsBox(frame_width / 2, frame_width / 24).UseDensity(20_kgpm2); + body->CreateFixture(Shape(shape)); return body; }(); @@ -157,8 +157,8 @@ namespace playrho { def.location = Length2{frame_width / 2 + frame_width / 24, frame_height - (arm_length / 2)}; const auto body = m_world.CreateBody(def); - const auto shape = PolygonShape::Conf{}.SetAsBox(frame_width / 24, arm_length / 2 + frame_width / 24).SetDensity(20_kgpm2); - body->CreateFixture(std::make_shared(shape)); + const auto shape = PolygonShapeConf{}.SetAsBox(frame_width / 24, arm_length / 2 + frame_width / 24).UseDensity(20_kgpm2); + body->CreateFixture(Shape(shape)); m_right_side_wall = body; } @@ -177,8 +177,8 @@ namespace playrho { }; const auto body = m_world.CreateBody(def); - const auto shape = PolygonShape::Conf{}.SetAsBox(frame_width/Real{24}, (arm_length / Real{2} + frame_width / Real{24})).SetDensity(20_kgpm2); - body->CreateFixture(std::make_shared(shape)); + const auto shape = PolygonShapeConf{}.SetAsBox(frame_width/Real{24}, (arm_length / Real{2} + frame_width / Real{24})).UseDensity(20_kgpm2); + body->CreateFixture(Shape(shape)); m_left_side_wall = body; } @@ -204,19 +204,19 @@ namespace playrho { Fixture* CreateBall(Body* body, Length2 pos, Length radius) { - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = radius; conf.location = pos; conf.density = 20_kgpm2; conf.restitution = 1; conf.friction = 0; - return body->CreateFixture(std::make_shared(conf)); + return body->CreateFixture(Shape(conf)); } Fixture* CreateArm(Body* body, Length length = 10_m) { - const auto shape = PolygonShape::Conf{}.SetAsBox(length / Real{2000}, length / Real{2}).SetDensity(20_kgpm2); - return body->CreateFixture(std::make_shared(shape)); + const auto shape = PolygonShapeConf{}.SetAsBox(length / Real{2000}, length / Real{2}).UseDensity(20_kgpm2); + return body->CreateFixture(Shape(shape)); } void ToggleRightSideWall() diff --git a/Testbed/Tests/OneSidedPlatform.hpp b/Testbed/Tests/OneSidedPlatform.hpp index 2436c4a61b..2708a8e75b 100644 --- a/Testbed/Tests/OneSidedPlatform.hpp +++ b/Testbed/Tests/OneSidedPlatform.hpp @@ -38,17 +38,14 @@ class OneSidedPlatform : public Test OneSidedPlatform() { // Ground - { - const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-20.0f, 0.0f) * 1_m, Vec2(20.0f, 0.0f) * 1_m)); - } + m_world.CreateBody()->CreateFixture(Shape{EdgeShapeConf{Vec2(-20.0f, 0.0f) * 1_m, Vec2(20.0f, 0.0f) * 1_m}}); // Platform { BodyDef bd; bd.location = Vec2(0.0f, 10.0f) * 1_m; const auto body = m_world.CreateBody(bd); - m_platform = body->CreateFixture(std::make_shared(3_m, 0.5_m)); + m_platform = body->CreateFixture(PolygonShapeConf{}.SetAsBox(3_m, 0.5_m)); m_bottom = Real(10.0f - 0.5f) * 1_m; m_top = Real(10.0f + 0.5f) * 1_m; } @@ -59,10 +56,10 @@ class OneSidedPlatform : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(0.0f, 12.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = m_radius; conf.density = 20_kgpm2; - m_character = body->CreateFixture(std::make_shared(conf)); + m_character = body->CreateFixture(Shape(conf)); body->SetVelocity(Velocity{Vec2(0.0f, -50.0f) * 1_mps, 0_rpm}); } } @@ -86,8 +83,7 @@ class OneSidedPlatform : public Test #if 1 const auto position = m_character->GetBody()->GetLocation(); - - if (GetY(position) < m_top + m_radius - m_platform->GetShape()->GetVertexRadius()) + if (GetY(position) < m_top + m_radius - GetVertexRadius(m_platform->GetShape())) { contact.UnsetEnabled(); } diff --git a/Testbed/Tests/Orbiter.hpp b/Testbed/Tests/Orbiter.hpp index a04613c5a7..adc41b788f 100644 --- a/Testbed/Tests/Orbiter.hpp +++ b/Testbed/Tests/Orbiter.hpp @@ -37,14 +37,12 @@ namespace playrho { bd.type = BodyType::Static; bd.location = m_center; const auto ctrBody = m_world.CreateBody(bd); - ctrBody->CreateFixture(std::make_shared(DiskShape::Conf{}.UseVertexRadius(3_m))); + ctrBody->CreateFixture(DiskShapeConf{}.UseRadius(3_m)); bd.type = BodyType::Dynamic; bd.location = Length2{GetX(m_center), GetY(m_center) + radius * 1_m}; m_orbiter = m_world.CreateBody(bd); - m_orbiter->CreateFixture(std::make_shared(DiskShape::Conf{} - .UseVertexRadius(0.5_m) - .UseDensity(1_kgpm2))); + m_orbiter->CreateFixture(DiskShapeConf{}.UseRadius(0.5_m).UseDensity(1_kgpm2)); const auto velocity = Velocity{ Vec2{Pi * radius / 2, 0} * 1_mps, @@ -52,11 +50,11 @@ namespace playrho { }; m_orbiter->SetVelocity(velocity); - auto conf = ChainShape::Conf{}; - conf.vertices = GetCircleVertices(20_m, 180); + auto conf = ChainShapeConf{}; + conf.Set(GetCircleVertices(20_m, 180)); conf.UseVertexRadius(0.1_m); conf.UseDensity(1_kgpm2); - const auto outerCicle = std::make_shared(conf); + const auto outerCicle = Shape(conf); bd.type = BodyType::Dynamic; bd.location = m_center; diff --git a/Testbed/Tests/Pinball.hpp b/Testbed/Tests/Pinball.hpp index c07d8f5ed1..f3e21aab46 100644 --- a/Testbed/Tests/Pinball.hpp +++ b/Testbed/Tests/Pinball.hpp @@ -34,15 +34,15 @@ class Pinball : public Test // Ground body const auto ground = m_world.CreateBody(); { - auto conf = ChainShape::Conf{}; - conf.vertices.push_back(Vec2(0.0f, -2.0f) * 1_m); - conf.vertices.push_back(Vec2(8.0f, 6.0f) * 1_m); - conf.vertices.push_back(Vec2(8.0f, 20.0f) * 1_m); - conf.vertices.push_back(Vec2(-8.0f, 20.0f) * 1_m); - conf.vertices.push_back(Vec2(-8.0f, 6.0f) * 1_m); - conf.vertices.push_back(conf.vertices[0]); // to loop back around completely. + auto conf = ChainShapeConf{}; + conf.Add(Vec2(0.0f, -2.0f) * 1_m); + conf.Add(Vec2(8.0f, 6.0f) * 1_m); + conf.Add(Vec2(8.0f, 20.0f) * 1_m); + conf.Add(Vec2(-8.0f, 20.0f) * 1_m); + conf.Add(Vec2(-8.0f, 6.0f) * 1_m); + conf.Add(conf.GetVertex(0)); // to loop back around completely. conf.UseDensity(0_kgpm2); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); } // Flippers @@ -59,8 +59,7 @@ class Pinball : public Test bd.location = p2; const auto rightFlipper = m_world.CreateBody(bd); - const auto box = std::make_shared(1.75_m, 0.1_m, PolygonShape::Conf{}.SetDensity(1_kgpm2)); - + const auto box = Shape(PolygonShapeConf{}.SetAsBox(1.75_m, 0.1_m).UseDensity(1_kgpm2)); leftFlipper->CreateFixture(box); rightFlipper->CreateFixture(box); @@ -95,10 +94,10 @@ class Pinball : public Test m_ball = m_world.CreateBody(bd); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.density = 1_kgpm2; conf.vertexRadius = 0.2_m; - m_ball->CreateFixture(std::make_shared(conf)); + m_ball->CreateFixture(Shape(conf)); } RegisterForKey(GLFW_KEY_A, GLFW_PRESS, 0, "To control the flippers", [&](KeyActionMods) { diff --git a/Testbed/Tests/PolyCollision.hpp b/Testbed/Tests/PolyCollision.hpp index f20ca15bc2..d583aa495c 100644 --- a/Testbed/Tests/PolyCollision.hpp +++ b/Testbed/Tests/PolyCollision.hpp @@ -65,8 +65,8 @@ class PolyCollision : public Test { NOT_USED(settings); - const auto proxyA = m_polygonA.GetChild(0); - const auto proxyB = m_polygonB.GetChild(0); + const auto proxyA = GetChild(m_polygonA, 0); + const auto proxyB = GetChild(m_polygonB, 0); const auto manifold = CollideShapes(proxyA, m_transformA, proxyB, m_transformB); const auto pointCount = manifold.GetPointCount(); @@ -107,8 +107,8 @@ class PolyCollision : public Test } } - PolygonShape m_polygonA{PolygonShape::Conf{}.SetAsBox(0.2_m, 0.4_m)}; - PolygonShape m_polygonB{PolygonShape::Conf{}.SetAsBox(0.5_m, 0.5_m)}; + PolygonShapeConf m_polygonA{PolygonShapeConf{}.SetAsBox(0.2_m, 0.4_m)}; + PolygonShapeConf m_polygonB{PolygonShapeConf{}.SetAsBox(0.5_m, 0.5_m)}; Transformation m_transformA; Transformation m_transformB; diff --git a/Testbed/Tests/PolyShapes.hpp b/Testbed/Tests/PolyShapes.hpp index 9e7480adf2..449f2a8502 100644 --- a/Testbed/Tests/PolyShapes.hpp +++ b/Testbed/Tests/PolyShapes.hpp @@ -32,18 +32,30 @@ namespace playrho { /// This callback is called by World::QueryAABB. We find all the fixtures /// that overlap an AABB. Of those, we use TestOverlap to determine which fixtures /// overlap a circle. Up to 4 overlapped fixtures will be highlighted with a yellow border. -class ShapeDrawer: public IsVisitedShapeVisitor +class ShapeDrawer { public: - void Visit(const DiskShape& shape) override + void operator() (const std::type_info& ti, const void* data) + { + if (ti == typeid(DiskShapeConf)) + { + Visit(*static_cast(data)); + } + else if (ti == typeid(PolygonShapeConf)) + { + Visit(*static_cast(data)); + } + } + + void Visit(const DiskShapeConf& shape) { const auto center = Transform(shape.GetLocation(), m_xf); const auto radius = shape.GetRadius(); g_debugDraw->DrawCircle(center, radius, m_color); } - void Visit(const PolygonShape& shape) override + void Visit(const PolygonShapeConf& shape) { const auto vertexCount = shape.GetVertexCount(); auto vertices = std::vector(vertexCount); @@ -71,18 +83,15 @@ class PolyShapes : public Test PolyShapes() { // Ground body - { - const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); - } + m_world.CreateBody()->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); - auto conf = PolygonShape::Conf{}; - conf.SetDensity(1_kgpm2); - conf.SetFriction(Real(0.3f)); + auto conf = PolygonShapeConf{}; + conf.UseDensity(1_kgpm2); + conf.UseFriction(Real(0.3f)); conf.Set({Vec2(-0.5f, 0.0f) * 1_m, Vec2(0.5f, 0.0f) * 1_m, Vec2(0.0f, 1.5f) * 1_m}); - m_polygons[0] = std::make_shared(conf); + m_polygons[0] = Shape(conf); conf.Set({Vec2(-0.1f, 0.0f) * 1_m, Vec2(0.1f, 0.0f) * 1_m, Vec2(0.0f, 1.5f) * 1_m}); - m_polygons[1] = std::make_shared(conf); + m_polygons[1] = Shape(conf); { const auto w = Real(1); const auto b = w / (2.0f + sqrt(2.0f)); @@ -98,10 +107,10 @@ class PolyShapes : public Test Vec2(-0.5f * w, b) * 1_m, Vec2(-0.5f * s, 0.0f) * 1_m }); - m_polygons[2] = std::make_shared(conf); + m_polygons[2] = Shape(conf); } conf.SetAsBox(0.5_m, 0.5_m); - m_polygons[3] = std::make_shared(conf); + m_polygons[3] = Shape(conf); m_bodyIndex = 0; std::memset(m_bodies, 0, sizeof(m_bodies)); @@ -185,10 +194,9 @@ class PolyShapes : public Test void PostStep(const Settings&, Drawer& drawer) override { - auto circleConf = DiskShape::Conf{}; + auto circleConf = DiskShapeConf{}; circleConf.location = Vec2(0.0f, 1.1f) * 1_m; circleConf.vertexRadius = 2_m; - const auto circle = DiskShape{circleConf}; const auto transform = Transform_identity; @@ -197,19 +205,21 @@ class PolyShapes : public Test PLAYRHO_CONSTEXPR const int e_maxCount = 4; int count = 0; - const auto aabb = ComputeAABB(circle, transform); + const auto circleChild = GetChild(circleConf, 0); + const auto aabb = ComputeAABB(circleChild, transform); m_world.QueryAABB(aabb, [&](Fixture* f, const ChildCounter) { if (count < e_maxCount) { const auto xfm = GetTransformation(*f); const auto shape = f->GetShape(); - const auto shapeChild = shape->GetChild(0); - const auto circleChild = circle.GetChild(0); + const auto shapeChild = GetChild(shape, 0); const auto overlap = TestOverlap(shapeChild, xfm, circleChild, transform); if (overlap >= Area{0}) { shapeDrawer.m_xf = xfm; - shape->Accept(shapeDrawer); + Accept(shape, [&](const std::type_info& ti, const void* data) { + shapeDrawer(ti, data); + }); ++count; } return true; @@ -218,14 +228,13 @@ class PolyShapes : public Test }); const auto color = Color(0.4f, 0.7f, 0.8f); - drawer.DrawCircle(circle.GetLocation(), circle.GetRadius(), color); + drawer.DrawCircle(circleConf.GetLocation(), circleConf.GetRadius(), color); } int m_bodyIndex; Body* m_bodies[e_maxBodies]; - std::shared_ptr m_polygons[4]; - std::shared_ptr m_circle = std::make_shared(0.5_m, - DiskShape::Conf{}.SetDensity(1_kgpm2).SetFriction(Real(0.3f))); + Shape m_polygons[4] = {PolygonShapeConf{}, PolygonShapeConf{}, PolygonShapeConf{}, PolygonShapeConf{}}; + Shape m_circle = DiskShapeConf{}.UseRadius(0.5_m).UseDensity(1_kgpm2).UseFriction(Real(0.3f)); }; } // namespace playrho diff --git a/Testbed/Tests/Prismatic.hpp b/Testbed/Tests/Prismatic.hpp index 27ea798983..2c388b00db 100644 --- a/Testbed/Tests/Prismatic.hpp +++ b/Testbed/Tests/Prismatic.hpp @@ -31,7 +31,7 @@ class Prismatic : public Test Prismatic() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); { BodyDef bd; @@ -40,18 +40,13 @@ class Prismatic : public Test bd.angle = 0.5_rad * Pi; bd.allowSleep = false; const auto body = m_world.CreateBody(bd); - - auto polygonConf = PolygonShape::Conf{}; - polygonConf.density = 5_kgpm2; - body->CreateFixture(std::make_shared(2_m, 0.5_m, polygonConf)); + body->CreateFixture(PolygonShapeConf{}.UseDensity(5_kgpm2).SetAsBox(2_m, 0.5_m)); // Bouncy limit const auto axis = GetUnitVector(Vec2(2.0f, 1.0f)); PrismaticJointDef pjd(ground, body, Length2{}, axis); - // Non-bouncy limit //pjd.Initialize(ground, body, Vec2(-10.0f, 10.0f), Vec2(1.0f, 0.0f)); - pjd.motorSpeed = 10_rad / 1_s; pjd.maxMotorForce = 10000_N; pjd.enableMotor = true; diff --git a/Testbed/Tests/Pulleys.hpp b/Testbed/Tests/Pulleys.hpp index b0a2cc6223..5b5b39a13b 100644 --- a/Testbed/Tests/Pulleys.hpp +++ b/Testbed/Tests/Pulleys.hpp @@ -36,16 +36,17 @@ class Pulleys : public Test const auto ground = m_world.CreateBody(); { - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 2_m; conf.location = Vec2(-10.0f, y + b + L) * 1_m; - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.location = Vec2(+10.0f, y + b + L) * 1_m; - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); } { - const auto shape = std::make_shared(a * 1_m, b * 1_m, PolygonShape::Conf{}.SetDensity(5_kgpm2)); + const auto shape = Shape{ + PolygonShapeConf{}.SetAsBox(a * 1_m, b * 1_m).UseDensity(5_kgpm2)}; BodyDef bd; bd.type = BodyType::Dynamic; diff --git a/Testbed/Tests/Pyramid.hpp b/Testbed/Tests/Pyramid.hpp index 743e664c42..4ec92725b5 100644 --- a/Testbed/Tests/Pyramid.hpp +++ b/Testbed/Tests/Pyramid.hpp @@ -35,15 +35,13 @@ class Pyramid : public Test Pyramid() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); const auto a = 0.5_m; - const auto shape = std::make_shared(a, a, PolygonShape::Conf{}.SetDensity(5_kgpm2)); - + const auto shape = Shape{PolygonShapeConf{}.SetAsBox(a, a).UseDensity(5_kgpm2)}; auto x = Vec2(-7.0f, 0.75f); const auto deltaX = Vec2(0.5625f, 1.25f); const auto deltaY = Vec2(1.125f, 0.0f); - Vec2 y; for (auto i = 0; i < e_count; ++i) { diff --git a/Testbed/Tests/RayCast.hpp b/Testbed/Tests/RayCast.hpp index 81fea7355e..839bf84039 100644 --- a/Testbed/Tests/RayCast.hpp +++ b/Testbed/Tests/RayCast.hpp @@ -48,24 +48,22 @@ class RayCast : public Test RayCast() { // Ground body - const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, - Vec2(40.0f, 0.0f) * 1_m)); + m_world.CreateBody()->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); - auto conf = PolygonShape::Conf{}; - conf.SetFriction(Real(0.3f)); + auto conf = PolygonShapeConf{}; + conf.UseFriction(Real(0.3f)); conf.Set({ Vec2(-0.5f, 0.0f) * 1_m, Vec2(0.5f, 0.0f) * 1_m, Vec2(0.0f, 1.5f) * 1_m }); - m_polygons[0] = std::make_shared(conf); + m_polygons[0] = Shape(conf); conf.Set({ Vec2(-0.1f, 0.0f) * 1_m, Vec2(0.1f, 0.0f) * 1_m, Vec2(0.0f, 1.5f) * 1_m }); - m_polygons[1] = std::make_shared(conf); + m_polygons[1] = Shape(conf); { const auto w = 1.0f; const auto b = w / (2.0f + sqrt(2.0f)); @@ -82,9 +80,9 @@ class RayCast : public Test Vec2(-0.5f * s, 0.0f) * 1_m }); } - m_polygons[2] = std::make_shared(conf); + m_polygons[2] = Shape(conf); conf.SetAsBox(0.5_m, 0.5_m); - m_polygons[3] = std::make_shared(conf); + m_polygons[3] = Shape(conf); std::memset(m_bodies, 0, sizeof(m_bodies)); RegisterForKey(GLFW_KEY_1, GLFW_PRESS, 0, "drop triangles that should be ignored by the ray.", [&](KeyActionMods kam) { @@ -339,7 +337,7 @@ class RayCast : public Test //vertices[2] = Vec2(22.875f, 3.0f); //vertices[3] = Vec2(-22.875f, 3.0f); - PolygonShape shape; + PolygonShapeConf shape; //shape.Set(vertices, 4); shape.SetAsBox(22.875f, 3.0f); @@ -374,11 +372,9 @@ class RayCast : public Test int m_bodyIndex = 0; Body* m_bodies[e_maxBodies]; int m_userData[e_maxBodies]; - std::shared_ptr m_polygons[4]; - std::shared_ptr m_circle = std::make_shared( - DiskShape::Conf{}.SetVertexRadius(0.5_m).SetFriction(Real(0.3f))); - std::shared_ptr m_edge = std::make_shared(Vec2(-1.0f, 0.0f) * 1_m, Vec2(1.0f, 0.0f) * 1_m, - EdgeShape::Conf{}.SetFriction(Real(0.3f))); + Shape m_polygons[4] = {PolygonShapeConf{}, PolygonShapeConf{}, PolygonShapeConf{}, PolygonShapeConf{}}; + Shape m_circle = DiskShapeConf{}.UseRadius(0.5_m).UseFriction(Real(0.3f)); + Shape m_edge = Shape{EdgeShapeConf{Vec2(-1.0f, 0.0f) * 1_m, Vec2(1.0f, 0.0f) * 1_m}.UseFriction(Real(0.3f))}; Real m_angle = 0.0f; Mode m_mode = Mode::e_closest; }; diff --git a/Testbed/Tests/Revolute.hpp b/Testbed/Tests/Revolute.hpp index b9920027f9..cc249720e2 100644 --- a/Testbed/Tests/Revolute.hpp +++ b/Testbed/Tests/Revolute.hpp @@ -30,8 +30,7 @@ class Revolute : public Test Revolute() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, - Vec2( 40.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2( 40.0f, 0.0f) * 1_m}}); { BodyDef bd; @@ -39,10 +38,10 @@ class Revolute : public Test bd.location = Vec2(-10.0f, 20.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto circleConf = DiskShape::Conf{}; + auto circleConf = DiskShapeConf{}; circleConf.vertexRadius = 0.5_m; circleConf.density = 5_kgpm2; - body->CreateFixture(std::make_shared(circleConf)); + body->CreateFixture(Shape(circleConf)); const auto w = 100.0f; body->SetVelocity(Velocity{ @@ -70,21 +69,21 @@ class Revolute : public Test fd.filter.maskBits = 1; m_ball = m_world.CreateBody(circle_bd); - auto circleConf = DiskShape::Conf{}; + auto circleConf = DiskShapeConf{}; circleConf.vertexRadius = 3_m; circleConf.density = 5_kgpm2; - m_ball->CreateFixture(std::make_shared(circleConf), fd); + m_ball->CreateFixture(Shape(circleConf), fd); - auto polygon_shape = PolygonShape::Conf{}; + auto polygon_shape = PolygonShapeConf{}; polygon_shape.SetAsBox(10_m, 0.2_m, Vec2(-10.0f, 0.0f) * 1_m, 0_rad); - polygon_shape.SetDensity(2_kgpm2); + polygon_shape.UseDensity(2_kgpm2); BodyDef polygon_bd; polygon_bd.location = Vec2(20.0f, 10.0f) * 1_m; polygon_bd.type = BodyType::Dynamic; polygon_bd.bullet = true; const auto polygon_body = m_world.CreateBody(polygon_bd); - polygon_body->CreateFixture(std::make_shared(polygon_shape)); + polygon_body->CreateFixture(Shape(polygon_shape)); RevoluteJointDef rjd(ground, polygon_body, Vec2(20.0f, 10.0f) * 1_m); rjd.lowerAngle = -0.25_rad * Pi; @@ -95,14 +94,14 @@ class Revolute : public Test // Tests mass computation of a small object far from the origin { - const auto polyShape = PolygonShape::Conf{}.Set({ + const auto polyShape = PolygonShapeConf{}.Set({ Vec2(17.63f, 36.31f) * 1_m, Vec2(17.52f, 36.69f) * 1_m, Vec2(17.19f, 36.36f) * 1_m - }).SetDensity(1_kgpm2); + }).UseDensity(1_kgpm2); const auto body = m_world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic)); - body->CreateFixture(std::make_shared(polyShape)); + body->CreateFixture(Shape(polyShape)); } RegisterForKey(GLFW_KEY_L, GLFW_PRESS, 0, "Limits", [&](KeyActionMods) { diff --git a/Testbed/Tests/RopeJoint.hpp b/Testbed/Tests/RopeJoint.hpp index 682efd70ca..5de9ab017b 100644 --- a/Testbed/Tests/RopeJoint.hpp +++ b/Testbed/Tests/RopeJoint.hpp @@ -38,13 +38,15 @@ class RopeJointTest : public Test RopeJointTest() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); { - const auto rectangle = std::make_shared(0.5_m, 0.125_m, - PolygonShape::Conf{}.SetDensity(20_kgpm2).SetFriction(Real(0.2f))); - const auto square = std::make_shared(1.5_m, 1.5_m, - PolygonShape::Conf{}.SetDensity(100_kgpm2).SetFriction(Real(0.2f))); + const auto rectangle = Shape{ + PolygonShapeConf{}.UseDensity(20_kgpm2).UseFriction(Real(0.2f)).SetAsBox(0.5_m, 0.125_m) + }; + const auto square = Shape{ + PolygonShapeConf{}.UseDensity(100_kgpm2).UseFriction(Real(0.2f)).SetAsBox(1.5_m, 1.5_m) + }; FixtureDef fd; fd.filter.categoryBits = 0x0001; diff --git a/Testbed/Tests/SensorTest.hpp b/Testbed/Tests/SensorTest.hpp index 71180e5094..783ede1996 100644 --- a/Testbed/Tests/SensorTest.hpp +++ b/Testbed/Tests/SensorTest.hpp @@ -38,7 +38,7 @@ class SensorTest : public Test { { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); #if 0 { @@ -51,25 +51,23 @@ class SensorTest : public Test { FixtureDef fd; fd.isSensor = true; - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 5_m; conf.location = Vec2(0.0f, 10.0f) * 1_m; - m_sensor = ground->CreateFixture(std::make_shared(conf), fd); + m_sensor = ground->CreateFixture(Shape(conf), fd); } #endif } - const auto shape = std::make_shared(1_m, DiskShape::Conf{}.SetDensity(1_kgpm2)); + const auto shape = Shape{DiskShapeConf{}.UseDensity(1_kgpm2).UseRadius(1_m)}; for (auto i = 0; i < e_count; ++i) { BodyDef bd; bd.type = BodyType::Dynamic; bd.location = Vec2(-10.0f + 3.0f * i, 20.0f) * 1_m; bd.userData = m_touching + i; - m_touching[i] = false; m_bodies[i] = m_world.CreateBody(bd); - m_bodies[i]->CreateFixture(shape); } } @@ -141,12 +139,9 @@ class SensorTest : public Test const auto body = m_bodies[i]; const auto ground = m_sensor->GetBody(); - - const auto circle = static_cast(m_sensor->GetShape().get()); + const auto circle = static_cast(GetData(m_sensor->GetShape())); const auto center = GetWorldPoint(*ground, circle->GetLocation()); - const auto position = body->GetLocation(); - const auto d = center - position; if (AlmostZero(GetMagnitudeSquared(d) / SquareMeter)) { diff --git a/Testbed/Tests/ShapeEditing.hpp b/Testbed/Tests/ShapeEditing.hpp index 947a98607d..2b5e006196 100644 --- a/Testbed/Tests/ShapeEditing.hpp +++ b/Testbed/Tests/ShapeEditing.hpp @@ -30,18 +30,17 @@ class ShapeEditing : public Test ShapeEditing() { - const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); + m_world.CreateBody()->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); BodyDef bd; bd.type = BodyType::Dynamic; bd.location = Vec2(0.0f, 10.0f) * 1_m; m_body = m_world.CreateBody(bd); - auto shape = PolygonShape::Conf{}; + auto shape = PolygonShapeConf{}; shape.SetAsBox(4_m, 4_m, Length2{}, 0_deg); - shape.SetDensity(10_kgpm2); - m_fixture1 = m_body->CreateFixture(std::make_shared(shape)); + shape.UseDensity(10_kgpm2); + m_fixture1 = m_body->CreateFixture(Shape(shape)); m_fixture2 = nullptr; @@ -50,11 +49,11 @@ class ShapeEditing : public Test RegisterForKey(GLFW_KEY_C, GLFW_PRESS, 0, "Create a shape.", [&](KeyActionMods) { if (!m_fixture2) { - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 3_m; conf.location = Vec2(0.5f, -4.0f) * 1_m; conf.density = 10_kgpm2; - m_fixture2 = m_body->CreateFixture(std::make_shared(conf)); + m_fixture2 = m_body->CreateFixture(Shape(conf)); m_body->SetAwake(); } }); diff --git a/Testbed/Tests/SliderCrank.hpp b/Testbed/Tests/SliderCrank.hpp index 2b433a60e3..3995d3aff2 100644 --- a/Testbed/Tests/SliderCrank.hpp +++ b/Testbed/Tests/SliderCrank.hpp @@ -31,7 +31,7 @@ class SliderCrank : public Test SliderCrank() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); { auto prevBody = ground; @@ -42,9 +42,7 @@ class SliderCrank : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(0.0f, 7.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto shapeConf = PolygonShape::Conf{}; - shapeConf.density = 2_kgpm2; - body->CreateFixture(std::make_shared(0.5_m, 2_m, shapeConf)); + body->CreateFixture(PolygonShapeConf{}.UseDensity(2_kgpm2).SetAsBox(0.5_m, 2_m)); RevoluteJointDef rjd{prevBody, body, Vec2(0.0f, 5.0f) * 1_m}; rjd.motorSpeed = Pi * 1_rad / 1_s; @@ -61,9 +59,7 @@ class SliderCrank : public Test bd.type = BodyType::Dynamic; bd.location = Vec2(0.0f, 13.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto shapeConf = PolygonShape::Conf{}; - shapeConf.density = 2_kgpm2; - body->CreateFixture(std::make_shared(0.5_m, 4_m, shapeConf)); + body->CreateFixture(PolygonShapeConf{}.UseDensity(2_kgpm2).SetAsBox(0.5_m, 4_m)); RevoluteJointDef rjd{prevBody, body, Vec2(0.0f, 9.0f) * 1_m}; rjd.enableMotor = false; @@ -79,17 +75,12 @@ class SliderCrank : public Test bd.fixedRotation = true; bd.location = Vec2(0.0f, 17.0f) * 1_m; const auto body = m_world.CreateBody(bd); - auto shapeConf = PolygonShape::Conf{}; - shapeConf.density = 2_kgpm2; - body->CreateFixture(std::make_shared(1.5_m, 1.5_m, shapeConf)); - + body->CreateFixture(PolygonShapeConf{}.UseDensity(2_kgpm2).SetAsBox(1.5_m, 1.5_m)); m_world.CreateJoint(RevoluteJointDef{prevBody, body, Vec2(0.0f, 17.0f) * 1_m}); PrismaticJointDef pjd(ground, body, Vec2(0.0f, 17.0f) * 1_m, UnitVec2::GetTop()); - pjd.maxMotorForce = 1000_N; pjd.enableMotor = true; - m_joint2 = static_cast(m_world.CreateJoint(pjd)); } @@ -98,10 +89,7 @@ class SliderCrank : public Test BodyDef bd; bd.type = BodyType::Dynamic; bd.location = Vec2(0.0f, 23.0f) * 1_m; - const auto body = m_world.CreateBody(bd); - auto shapeConf = PolygonShape::Conf{}; - shapeConf.density = 2_kgpm2; - body->CreateFixture(std::make_shared(1.5_m, 1.5_m, shapeConf)); + m_world.CreateBody(bd)->CreateFixture(PolygonShapeConf{}.UseDensity(2_kgpm2).SetAsBox(1.5_m, 1.5_m)); } } RegisterForKey(GLFW_KEY_F, GLFW_PRESS, 0, "toggle friction", [&](KeyActionMods) { diff --git a/Testbed/Tests/SolarSystem.hpp b/Testbed/Tests/SolarSystem.hpp index 64258abc01..b99d95b448 100644 --- a/Testbed/Tests/SolarSystem.hpp +++ b/Testbed/Tests/SolarSystem.hpp @@ -128,8 +128,8 @@ class SolarSystem: public Test const auto a = 2 * Pi * 1_rad / sso.rotationalPeriod; b->SetVelocity(Velocity{LinearVelocity2{0_mps, v}, a}); const auto d = sso.mass / (Pi * Square(sso.radius)); - const auto sconf = DiskShape::Conf{}.UseVertexRadius(sso.radius).UseDensity(d); - const auto shape = std::make_shared(sconf); + const auto sconf = DiskShapeConf{}.UseRadius(sso.radius).UseDensity(d); + const auto shape = Shape(sconf); b->CreateFixture(shape); } RegisterForKey(GLFW_KEY_EQUAL, GLFW_PRESS, 0, diff --git a/Testbed/Tests/SphereStack.hpp b/Testbed/Tests/SphereStack.hpp index 441f289e97..7145c265fb 100644 --- a/Testbed/Tests/SphereStack.hpp +++ b/Testbed/Tests/SphereStack.hpp @@ -35,10 +35,8 @@ class SphereStack : public Test SphereStack() { - const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); - - const auto shape = std::make_shared(1_m, DiskShape::Conf{}.SetDensity(1_kgpm2)); + m_world.CreateBody()->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); + const auto shape = Shape{DiskShapeConf{}.UseRadius(1_m).UseDensity(1_kgpm2)}; for (auto i = 0; i < e_count; ++i) { BodyDef bd; diff --git a/Testbed/Tests/SpinningCircle.hpp b/Testbed/Tests/SpinningCircle.hpp index 1fa246bad8..41045243fe 100644 --- a/Testbed/Tests/SpinningCircle.hpp +++ b/Testbed/Tests/SpinningCircle.hpp @@ -48,19 +48,19 @@ namespace playrho { bodyDef.location = Vec2{0, 14} * 1_m; const auto body2 = m_world.CreateBody(bodyDef); - auto shapeConf = DiskShape::Conf{}; + auto shapeConf = DiskShapeConf{}; shapeConf.density = 10_kgpm2; shapeConf.vertexRadius = 2_m; shapeConf.location = Length2{}; - auto circle = std::make_shared(shapeConf); + auto circle = Shape(shapeConf); shapeConf.vertexRadius = 1.5_m; shapeConf.location = Vec2{0, 3} * 1_m; - auto circleA = std::make_shared(shapeConf); + auto circleA = Shape(shapeConf); shapeConf.vertexRadius = 1.5_m; shapeConf.location = Vec2{0, -3} * 1_m; - auto circleB = std::make_shared(shapeConf); + auto circleB = Shape(shapeConf); body1->CreateFixture(circleA); body1->CreateFixture(circleB); diff --git a/Testbed/Tests/TheoJansen.hpp b/Testbed/Tests/TheoJansen.hpp index 49d08236ca..e2768b0fff 100644 --- a/Testbed/Tests/TheoJansen.hpp +++ b/Testbed/Tests/TheoJansen.hpp @@ -40,8 +40,8 @@ class TheoJansen : public Test const auto p5 = Vec2(6.0f * s, 1.5f) * 1_m; const auto p6 = Vec2(2.5f * s, 3.7f) * 1_m; - auto poly1 = PolygonShape::Conf{}; - auto poly2 = PolygonShape::Conf{}; + auto poly1 = PolygonShapeConf{}; + auto poly2 = PolygonShapeConf{}; if (s > 0.0f) { poly1.Set({p1, p2, p3}); @@ -52,8 +52,8 @@ class TheoJansen : public Test poly1.Set({p1, p3, p2}); poly2.Set({Length2{}, p6 - p4, p5 - p4}); } - poly1.SetDensity(1_kgpm2); - poly2.SetDensity(1_kgpm2); + poly1.UseDensity(1_kgpm2); + poly2.UseDensity(1_kgpm2); FixtureDef fd1, fd2; fd1.filter.groupIndex = -1; @@ -71,8 +71,8 @@ class TheoJansen : public Test const auto body1 = m_world.CreateBody(bd1); const auto body2 = m_world.CreateBody(bd2); - body1->CreateFixture(std::make_shared(poly1), fd1); - body2->CreateFixture(std::make_shared(poly2), fd2); + body1->CreateFixture(Shape(poly1), fd1); + body2->CreateFixture(Shape(poly2), fd2); // Using a soft distance constraint can reduce some jitter. // It also makes the structure seem a bit more fluid by @@ -101,23 +101,23 @@ class TheoJansen : public Test BodyDef bd; const auto ground = m_world.CreateBody(bd); - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.Set(Vec2(-50.0f, 0.0f) * 1_m, Vec2(50.0f, 0.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(Vec2(-50.0f, 0.0f) * 1_m, Vec2(-50.0f, 10.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); conf.Set(Vec2(50.0f, 0.0f) * 1_m, Vec2(50.0f, 10.0f) * 1_m); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape(conf)); } // Balls - auto circleConf = DiskShape::Conf{}; + auto circleConf = DiskShapeConf{}; circleConf.vertexRadius = 0.25_m; circleConf.density = 1_kgpm2; - const auto circle = std::make_shared(circleConf); + const auto circle = Shape(circleConf); for (auto i = 0; i < 40; ++i) { BodyDef bd; @@ -136,9 +136,7 @@ class TheoJansen : public Test bd.type = BodyType::Dynamic; bd.location = pivot + m_offset; m_chassis = m_world.CreateBody(bd); - auto polygonConf = PolygonShape::Conf{}; - polygonConf.density = 1_kgpm2; - m_chassis->CreateFixture(std::make_shared(2.5_m, 1_m, polygonConf), sd); + m_chassis->CreateFixture(PolygonShapeConf{}.UseDensity(1_kgpm2).SetAsBox(2.5_m, 1_m), sd); } { @@ -148,10 +146,10 @@ class TheoJansen : public Test bd.type = BodyType::Dynamic; bd.location = pivot + m_offset; m_wheel = m_world.CreateBody(bd); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 1.6_m; conf.density = 1_kgpm2; - m_wheel->CreateFixture(std::make_shared(conf), sd); + m_wheel->CreateFixture(Shape(conf), sd); } { diff --git a/Testbed/Tests/Tiles.hpp b/Testbed/Tests/Tiles.hpp index 5f6cc55b09..783a2f487c 100644 --- a/Testbed/Tests/Tiles.hpp +++ b/Testbed/Tests/Tiles.hpp @@ -54,8 +54,7 @@ class Tiles : public Test GetX(position) = -N * a; for (auto i = 0; i < N; ++i) { - const auto shape = PolygonShape::Conf{}.SetAsBox(a * 1_m, a * 1_m, position * 1_m, 0_deg); - ground->CreateFixture(std::make_shared(shape)); + ground->CreateFixture(PolygonShapeConf{}.SetAsBox(a * 1_m, a * 1_m, position * 1_m, 0_deg)); ++m_fixtureCount; GetX(position) += 2.0f * a; } @@ -65,7 +64,7 @@ class Tiles : public Test { const auto a = Real{0.5f}; - const auto shape = std::make_shared(a * 1_m, a * 1_m, PolygonShape::Conf{}.SetDensity(5_kgpm2)); + const auto shape = Shape{PolygonShapeConf{}.UseDensity(5_kgpm2).SetAsBox(a * 1_m, a * 1_m)}; Vec2 x(-7.0f, 0.75f); Vec2 y; diff --git a/Testbed/Tests/TimeOfImpact.hpp b/Testbed/Tests/TimeOfImpact.hpp index 3a8e47e427..54954a5a78 100644 --- a/Testbed/Tests/TimeOfImpact.hpp +++ b/Testbed/Tests/TimeOfImpact.hpp @@ -43,8 +43,8 @@ class TimeOfImpactTest : public Test Position{Vec2(54.595478f, -51.083473f) * 1_m + offset, 513.62781_rad} }; - const auto output = GetToiViaSat(m_shapeA.GetChild(0), sweepA, - m_shapeB.GetChild(0), sweepB); + const auto output = GetToiViaSat(GetChild(m_shapeA, 0), sweepA, + GetChild(m_shapeB, 0), sweepB); std::stringstream stream; stream << "At TOI "; @@ -115,8 +115,8 @@ class TimeOfImpactTest : public Test #endif } - PolygonShape m_shapeA{PolygonShape::Conf{}.SetAsBox(25_m, 5_m)}; - PolygonShape m_shapeB{PolygonShape::Conf{}.SetAsBox(2.5_m, 2.5_m)}; + PolygonShapeConf m_shapeA{PolygonShapeConf{}.SetAsBox(25_m, 5_m)}; + PolygonShapeConf m_shapeB{PolygonShapeConf{}.SetAsBox(2.5_m, 2.5_m)}; }; } // namespace playrho diff --git a/Testbed/Tests/Tumbler.hpp b/Testbed/Tests/Tumbler.hpp index 933361f7d1..1cf9ab42e1 100644 --- a/Testbed/Tests/Tumbler.hpp +++ b/Testbed/Tests/Tumbler.hpp @@ -89,15 +89,15 @@ class Tumbler : public Test { const auto b = m_world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic) .UseLocation(at).UseAllowSleep(false)); - auto shape = PolygonShape::Conf{}.UseDensity(5_kgpm2); + auto shape = PolygonShapeConf{}.UseDensity(5_kgpm2); shape.SetAsBox(0.5_m, 10_m, Vec2( 10, 0) * 1_m, 0_rad); - b->CreateFixture(std::make_shared(shape)); + b->CreateFixture(Shape(shape)); shape.SetAsBox(0.5_m, 10_m, Vec2(-10, 0) * 1_m, 0_rad); - b->CreateFixture(std::make_shared(shape)); + b->CreateFixture(Shape(shape)); shape.SetAsBox(10_m, 0.5_m, Vec2( 0, 10) * 1_m, 0_rad); - b->CreateFixture(std::make_shared(shape)); + b->CreateFixture(Shape(shape)); shape.SetAsBox(10_m, 0.5_m, Vec2( 0, -10) * 1_m, 0_rad); - b->CreateFixture(std::make_shared(shape)); + b->CreateFixture(Shape(shape)); return b; } @@ -134,13 +134,9 @@ class Tumbler : public Test const AngularVelocity MotorInc = 0.5_rpm; int m_count = 0; - std::shared_ptr m_square = std::make_shared(0.125_m, 0.125_m, - PolygonShape::Conf{}.SetDensity(1_kgpm2)); - std::shared_ptr m_disk = std::make_shared(DiskShape::Conf{} - .UseVertexRadius(0.125_m) - .UseFriction(Real(0)) - .SetDensity(0.1_kgpm2)); - std::shared_ptr m_shape = m_square; + Shape m_square = Shape{PolygonShapeConf{}.SetAsBox(0.125_m, 0.125_m).UseDensity(1_kgpm2)}; + Shape m_disk = Shape{DiskShapeConf{}.UseRadius(0.125_m).UseFriction(Real(0)).UseDensity(0.1_kgpm2)}; + Shape m_shape = m_square; }; } // namespace playrho diff --git a/Testbed/Tests/VaryingFriction.hpp b/Testbed/Tests/VaryingFriction.hpp index 544bb05364..76a1ceb8ea 100644 --- a/Testbed/Tests/VaryingFriction.hpp +++ b/Testbed/Tests/VaryingFriction.hpp @@ -30,10 +30,10 @@ class VaryingFriction : public Test VaryingFriction() { - m_world.CreateBody()->CreateFixture(std::make_shared(GetGroundEdgeConf())); + m_world.CreateBody()->CreateFixture(Shape(GetGroundEdgeConf())); - const auto sliderPlank = std::make_shared(13_m, 0.25_m); - const auto sliderWall = std::make_shared(0.25_m, 1_m); + const auto sliderPlank = Shape{PolygonShapeConf{}.SetAsBox(13_m, 0.25_m)}; + const auto sliderWall = Shape{PolygonShapeConf{}.SetAsBox(0.25_m, 1_m)}; m_world.CreateBody(BodyDef{}.UseLocation(Vec2(-4, 22) * 1_m).UseAngle(-0.25_rad))->CreateFixture(sliderPlank); m_world.CreateBody(BodyDef{}.UseLocation(Vec2(10.5f, 19) * 1_m))->CreateFixture(sliderWall); @@ -41,16 +41,16 @@ class VaryingFriction : public Test m_world.CreateBody(BodyDef{}.UseLocation(Vec2(-10.5f, 11) * 1_m))->CreateFixture(sliderWall); m_world.CreateBody(BodyDef{}.UseLocation(Vec2(-4, 6) * 1_m).UseAngle(-0.25_rad))->CreateFixture(sliderPlank); - auto shape = PolygonShape::Conf{}.SetAsBox(0.5_m, 0.5_m).SetDensity(25_kgpm2); + auto shape = PolygonShapeConf{}.SetAsBox(0.5_m, 0.5_m).UseDensity(25_kgpm2); float friction[5] = {std::sqrt(std::numeric_limits::max()), 0.5f, 0.35f, 0.1f, 0.0f}; for (auto i = 0; i < 5; ++i) { - BodyDef bd; + auto bd = BodyDef{}; bd.type = BodyType::Dynamic; bd.location = Vec2(-15.0f + 4.0f * i, 28.0f) * 1_m; const auto body = m_world.CreateBody(bd); - shape.SetFriction(Real(friction[i])); - body->CreateFixture(std::make_shared(shape)); + shape.UseFriction(Real(friction[i])); + body->CreateFixture(Shape(shape)); } } }; diff --git a/Testbed/Tests/VaryingRestitution.hpp b/Testbed/Tests/VaryingRestitution.hpp index 238b5ede43..280259c1f4 100644 --- a/Testbed/Tests/VaryingRestitution.hpp +++ b/Testbed/Tests/VaryingRestitution.hpp @@ -33,18 +33,18 @@ class VaryingRestitution : public Test VaryingRestitution() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(GetGroundEdgeConf())); + ground->CreateFixture(Shape(GetGroundEdgeConf())); Real restitution[7] = {0.0f, 0.1f, 0.3f, 0.5f, 0.75f, 0.9f, 1.0f}; - auto shape = DiskShape::Conf{}.UseVertexRadius(1_m).UseDensity(1_kgpm2); + auto shape = DiskShapeConf{}.UseRadius(1_m).UseDensity(1_kgpm2); for (auto i = 0; i < 7; ++i) { BodyDef bd; bd.type = BodyType::Dynamic; bd.location = Vec2(Real(-10 + 3 * i), 20) * 1_m; const auto body = m_world.CreateBody(bd); - shape.SetRestitution(restitution[i]); - body->CreateFixture(std::make_shared(shape)); + shape.UseRestitution(restitution[i]); + body->CreateFixture(Shape(shape)); } } }; diff --git a/Testbed/Tests/VerticalStack.hpp b/Testbed/Tests/VerticalStack.hpp index 449beab62e..6f2123e8f5 100644 --- a/Testbed/Tests/VerticalStack.hpp +++ b/Testbed/Tests/VerticalStack.hpp @@ -40,15 +40,16 @@ class VerticalStack : public Test VerticalStack() { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); - ground->CreateFixture(std::make_shared(Vec2(20.0f, 0.0f) * 1_m, Vec2(20.0f, 20.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(20.0f, 0.0f) * 1_m, Vec2(20.0f, 20.0f) * 1_m}}); const float xs[] = {0.0f, -10.0f, -5.0f, 5.0f, 10.0f}; assert(e_columnCount <= sizeof(xs)/sizeof(xs[0])); const auto hdim = Real{0.1f}; // 0.5f is less stable than 1.0f for boxes not at origin (x of 0) - const auto shape = std::make_shared(hdim * 1_m, hdim * 1_m, - PolygonShape::Conf{}.SetDensity(1_kgpm2).SetFriction(Real(0.3f))); + const auto shape = Shape{ + PolygonShapeConf{}.UseDensity(1_kgpm2).UseFriction(Real(0.3f)).SetAsBox(hdim * 1_m, hdim * 1_m) + }; for (auto j = 0; j < e_columnCount; ++j) { for (auto i = 0; i < e_rowCount; ++i) @@ -61,9 +62,7 @@ class VerticalStack : public Test //const auto x = i % 2 == 0 ? -0.01f : 0.01f; //bd.position = Vec2(xs[j] + x, (hdim - hdim/20) + (hdim * 2 - hdim / 20) * i); bd.location = Vec2(xs[j] + x, (i + 1) * hdim * 4) * 1_m; - - const auto body = m_world.CreateBody(bd); - body->CreateFixture(shape); + m_world.CreateBody(bd)->CreateFixture(shape); } } @@ -90,9 +89,7 @@ class VerticalStack : public Test } Body* m_bullet; - std::shared_ptr m_bulletshape = std::make_shared( - DiskShape::Conf{}.SetVertexRadius(0.25_m).SetDensity(20_kgpm2).SetRestitution(Real(0.05f)) - ); + Shape m_bulletshape = DiskShapeConf{}.UseRadius(0.25_m).UseDensity(20_kgpm2).UseRestitution(Real(0.05f)); }; } // namespace playrho diff --git a/Testbed/Tests/Web.hpp b/Testbed/Tests/Web.hpp index d873549d47..28612dd820 100644 --- a/Testbed/Tests/Web.hpp +++ b/Testbed/Tests/Web.hpp @@ -38,10 +38,10 @@ class Web : public Test Web(): Test(GetTestConf()) { const auto ground = m_world.CreateBody(); - ground->CreateFixture(std::make_shared(Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m)); + ground->CreateFixture(Shape{EdgeShapeConf{Vec2(-40.0f, 0.0f) * 1_m, Vec2(40.0f, 0.0f) * 1_m}}); { - const auto shape = std::make_shared(0.5_m, 0.5_m, PolygonShape::Conf{}.SetDensity(5_kgpm2)); + const auto shape = Shape{PolygonShapeConf{}.UseDensity(5_kgpm2).SetAsBox(0.5_m, 0.5_m)}; BodyDef bd; bd.type = BodyType::Dynamic; diff --git a/Testbed/Tests/iforce2d_TopdownCar.hpp b/Testbed/Tests/iforce2d_TopdownCar.hpp index 2eca0b6b60..3cf310edc9 100644 --- a/Testbed/Tests/iforce2d_TopdownCar.hpp +++ b/Testbed/Tests/iforce2d_TopdownCar.hpp @@ -96,7 +96,7 @@ class TDTire public: - TDTire(World* world, std::shared_ptr tireShape) + TDTire(World* world, Shape tireShape) { BodyDef bodyDef; bodyDef.type = BodyType::Dynamic; @@ -252,10 +252,10 @@ class TDCar vertices[5] = Vec2(-2.8f, +5.5f) * 1_m; vertices[6] = Vec2(-3.0f, +2.5f) * 1_m; vertices[7] = Vec2(-1.5f, +0.0f) * 1_m; - auto polygonShape = PolygonShape::Conf{}; + auto polygonShape = PolygonShapeConf{}; polygonShape.Set(Span(vertices, 8)); - polygonShape.SetDensity(0.1_kgpm2); - m_body->CreateFixture(std::make_shared(polygonShape)); + polygonShape.UseDensity(0.1_kgpm2); + m_body->CreateFixture(Shape(polygonShape)); //prepare common joint parameters RevoluteJointDef jointDef; @@ -272,10 +272,10 @@ class TDCar const auto backTireMaxLateralImpulse = 9_Ns; // 8.5f; const auto frontTireMaxLateralImpulse = 9_Ns; // 7.5f; - auto tireShape = PolygonShape::Conf{}; + auto tireShape = PolygonShapeConf{}; tireShape.SetAsBox(0.5_m, 1.25_m); - tireShape.SetDensity(1_kgpm2); - const auto sharedTireShape = std::make_shared(tireShape); + tireShape.UseDensity(1_kgpm2); + const auto sharedTireShape = Shape(tireShape); TDTire* tire; @@ -389,16 +389,16 @@ class iforce2d_TopdownCar : public Test BodyDef bodyDef; m_groundBody = m_world.CreateBody(bodyDef); - auto polygonShape = PolygonShape::Conf{}; + auto polygonShape = PolygonShapeConf{}; FixtureDef fixtureDef; fixtureDef.isSensor = true; polygonShape.SetAsBox(9_m, 7_m, Vec2(-10,15) * 1_m, 20_deg ); - groundAreaFixture = m_groundBody->CreateFixture(std::make_shared(polygonShape), fixtureDef); + groundAreaFixture = m_groundBody->CreateFixture(Shape(polygonShape), fixtureDef); groundAreaFixture->SetUserData( new GroundAreaFUD( 0.5f, false ) ); polygonShape.SetAsBox(9_m, 5_m, Vec2(5,20) * 1_m, -40_deg ); - groundAreaFixture = m_groundBody->CreateFixture(std::make_shared(polygonShape), fixtureDef); + groundAreaFixture = m_groundBody->CreateFixture(Shape(polygonShape), fixtureDef); groundAreaFixture->SetUserData( new GroundAreaFUD( 0.2f, false ) ); } diff --git a/Testbed/Tests/iforce2d_Trajectories.hpp b/Testbed/Tests/iforce2d_Trajectories.hpp index a4d951db21..34a6dfe40f 100644 --- a/Testbed/Tests/iforce2d_Trajectories.hpp +++ b/Testbed/Tests/iforce2d_Trajectories.hpp @@ -43,22 +43,22 @@ class iforce2d_Trajectories : public Test { //add four walls to the ground body FixtureDef myFixtureDef; - auto polygonShape = PolygonShape::Conf{}; + auto polygonShape = PolygonShapeConf{}; polygonShape.SetAsBox(20_m, 1_m); //ground - m_groundBody->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + m_groundBody->CreateFixture(Shape(polygonShape), myFixtureDef); polygonShape.SetAsBox(20_m, 1_m, Vec2(0, 40) * 1_m, 0_rad); //ceiling - m_groundBody->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + m_groundBody->CreateFixture(Shape(polygonShape), myFixtureDef); polygonShape.SetAsBox(1_m, 20_m, Vec2(-20, 20) * 1_m, 0_rad); //left wall - m_groundBody->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + m_groundBody->CreateFixture(Shape(polygonShape), myFixtureDef); polygonShape.SetAsBox(1_m, 20_m, Vec2(20, 20) * 1_m, 0_rad); //right wall - m_groundBody->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + m_groundBody->CreateFixture(Shape(polygonShape), myFixtureDef); //small ledges for target practice - polygonShape.SetFriction(Real(0.95f)); + polygonShape.UseFriction(Real(0.95f)); polygonShape.SetAsBox(1.5_m, 0.25_m, Vec2(3, 35) * 1_m, 0_rad); - m_groundBody->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + m_groundBody->CreateFixture(Shape(polygonShape), myFixtureDef); polygonShape.SetAsBox(1.5_m, 0.25_m, Vec2(13, 30) * 1_m, 0_rad); - m_groundBody->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + m_groundBody->CreateFixture(Shape(polygonShape), myFixtureDef); //another ledge which we can move with the mouse BodyDef kinematicBody; @@ -71,22 +71,20 @@ class iforce2d_Trajectories : public Test verts[1] = Length2( w, 0_m); verts[2] = Length2( 0_m, -w); polygonShape.Set(Span(verts, 3)); - m_targetBody->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + m_targetBody->CreateFixture(Shape(polygonShape), myFixtureDef); verts[0] = Length2( 0_m, -2*w); verts[2] = Length2( 0_m, -w); verts[1] = Length2( -w, 0_m); polygonShape.Set(Span(verts, 3)); - m_targetBody->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + m_targetBody->CreateFixture(Shape(polygonShape), myFixtureDef); //create dynamic circle body BodyDef myBodyDef; myBodyDef.type = BodyType::Dynamic; myBodyDef.location = Vec2(-15, 5) * 1_m; m_launcherBody = m_world.CreateBody(myBodyDef); - m_launcherBody->CreateFixture(std::make_shared(DiskShape::Conf{} - .UseVertexRadius(2_m) - .UseFriction(Real(0.95f)) - .UseDensity(1_kgpm2)), myFixtureDef); + m_launcherBody->CreateFixture(DiskShapeConf{}.UseRadius(2_m).UseFriction(Real(0.95f)).UseDensity(1_kgpm2), + myFixtureDef); //pin the circle in place RevoluteJointDef revoluteJointDef; @@ -103,15 +101,14 @@ class iforce2d_Trajectories : public Test myBodyDef.location = Length2(0_m, -5_m);//will be positioned later m_littleBox = m_world.CreateBody(myBodyDef); polygonShape.SetAsBox( 0.5_m, 0.5_m ); - polygonShape.SetDensity(1_kgpm2); - m_littleBox->CreateFixture(std::make_shared(polygonShape), myFixtureDef); + polygonShape.UseDensity(1_kgpm2); + m_littleBox->CreateFixture(Shape(polygonShape), myFixtureDef); //ball for computer 'player' to fire m_littleBox2 = m_world.CreateBody(myBodyDef); - m_littleBox2->CreateFixture(std::make_shared(DiskShape::Conf{} - .UseVertexRadius(BallSize * 1_m) - .UseFriction(Real(0.95f)) - .UseDensity(1_kgpm2)), myFixtureDef); + m_littleBox2->CreateFixture(DiskShapeConf{}.UseRadius(BallSize * 1_m) + .UseFriction(Real(0.95f)).UseDensity(1_kgpm2), + myFixtureDef); m_firing = false; m_littleBox->SetAcceleration(LinearAcceleration2{}, AngularAcceleration{}); diff --git a/UnitTests/AABB.cpp b/UnitTests/AABB.cpp index d03ee7b32f..4c2c85026e 100644 --- a/UnitTests/AABB.cpp +++ b/UnitTests/AABB.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -416,8 +416,8 @@ TEST(AABB2D, StreamOutputOperator) TEST(AABB2D, ComputeAabbForFixtureAtBodyOrigin) { - const auto shape = std::make_shared(); - const auto shapeAabb = ComputeAABB(*shape, Transformation{}); + const auto shape = DiskShapeConf{}; + const auto shapeAabb = ComputeAABB(Shape(shape), Transformation{}); World world; const auto body = world.CreateBody(); @@ -430,8 +430,8 @@ TEST(AABB2D, ComputeAabbForFixtureAtBodyOrigin) TEST(AABB2D, ComputeAabbForFixtureOffFromBodyOrigin) { - const auto shape = std::make_shared(); - const auto shapeAabb = ComputeAABB(*shape, Transformation{}); + const auto shape = DiskShapeConf{}; + const auto shapeAabb = ComputeAABB(shape, Transformation{}); const auto bodyLocation = Length2{2_m, 3_m}; World world; @@ -446,8 +446,8 @@ TEST(AABB2D, ComputeAabbForFixtureOffFromBodyOrigin) TEST(AABB2D, ComputeIntersectingAABBForSameFixture) { - const auto shape = std::make_shared(); - const auto shapeAabb = ComputeAABB(*shape, Transformation{}); + const auto shape = DiskShapeConf{}; + const auto shapeAabb = ComputeAABB(shape, Transformation{}); World world; const auto body = world.CreateBody(); @@ -465,8 +465,8 @@ TEST(AABB2D, ComputeIntersectingAABBForTwoFixtures) { const auto shapeInterval = LengthInterval{-2_m, +2_m}; - const auto shape = std::make_shared(DiskShape::Conf{}.UseVertexRadius(2_m)); - const auto shapeAabb = ComputeAABB(*shape, Transformation{}); + const auto shape = DiskShapeConf{}.UseRadius(2_m); + const auto shapeAabb = ComputeAABB(shape, Transformation{}); ASSERT_EQ(shapeAabb, (AABB2D{shapeInterval, shapeInterval})); const auto bodyLocation0 = Length2{+1_m, 0_m}; @@ -494,8 +494,8 @@ TEST(AABB2D, ComputeIntersectingAABBForContact) { const auto shapeInterval = LengthInterval{-2_m, +2_m}; - const auto shape = std::make_shared(DiskShape::Conf{}.UseVertexRadius(2_m)); - const auto shapeAabb = ComputeAABB(*shape, Transformation{}); + const auto shape = DiskShapeConf{}.UseRadius(2_m); + const auto shapeAabb = ComputeAABB(shape, Transformation{}); ASSERT_EQ(shapeAabb, (AABB2D{shapeInterval, shapeInterval})); const auto bodyLocation0 = Length2{+1_m, 0_m}; diff --git a/UnitTests/Body.cpp b/UnitTests/Body.cpp index 6e776c5aff..5c6aab8f6d 100644 --- a/UnitTests/Body.cpp +++ b/UnitTests/Body.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include @@ -254,19 +254,37 @@ TEST(Body, CreateFixture) const auto body = world.CreateBody(); EXPECT_EQ(GetFixtureCount(*body), std::size_t(0)); - const auto valid_shape = std::make_shared(1_m); + const auto valid_shape = DiskShapeConf(1_m); EXPECT_NE(body->CreateFixture(valid_shape, FixtureDef{}), nullptr); EXPECT_EQ(GetFixtureCount(*body), std::size_t(1)); } +TEST(Body, DestroyFixture) +{ + World world; + const auto bodyA = world.CreateBody(); + const auto bodyB = world.CreateBody(); + ASSERT_EQ(GetFixtureCount(*bodyA), std::size_t(0)); + ASSERT_EQ(GetFixtureCount(*bodyB), std::size_t(0)); + + const auto fixtureA = bodyA->CreateFixture(DiskShapeConf(1_m), FixtureDef{}); + ASSERT_NE(fixtureA, nullptr); + ASSERT_EQ(GetFixtureCount(*bodyA), std::size_t(1)); + + EXPECT_FALSE(bodyB->DestroyFixture(fixtureA)); + EXPECT_EQ(GetFixtureCount(*bodyA), std::size_t(1)); + EXPECT_TRUE(bodyA->DestroyFixture(fixtureA)); + EXPECT_EQ(GetFixtureCount(*bodyA), std::size_t(0)); +} + TEST(Body, SetEnabled) { auto stepConf = StepConf{}; World world; const auto body = world.CreateBody(); - const auto valid_shape = std::make_shared(1_m); - + const auto valid_shape = DiskShapeConf(1_m); + const auto fixture = body->CreateFixture(valid_shape, FixtureDef{}); ASSERT_NE(fixture, nullptr); ASSERT_TRUE(body->IsEnabled()); @@ -298,7 +316,7 @@ TEST(Body, SetFixedRotation) { World world; const auto body = world.CreateBody(); - const auto valid_shape = std::make_shared(1_m); + const auto valid_shape = DiskShapeConf(1_m); ASSERT_NE(body->CreateFixture(valid_shape, FixtureDef{}), nullptr); ASSERT_FALSE(body->IsFixedRotation()); @@ -322,19 +340,17 @@ TEST(Body, CreateAndDestroyFixture) EXPECT_TRUE(body->GetFixtures().empty()); EXPECT_FALSE(body->IsMassDataDirty()); - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 2.871_m; conf.location = Vec2{1.912f, -77.31f} * 1_m; conf.density = 1_kgpm2; - const auto shape = std::make_shared(conf); + const auto shape = Shape(conf); { auto fixture = body->CreateFixture(shape, FixtureDef{}, false); const auto fshape = fixture->GetShape(); - ASSERT_NE(fshape, nullptr); - EXPECT_EQ(typeid(fshape.get()), typeid(const Shape*)); - EXPECT_EQ(GetVertexRadius(*fshape), GetVertexRadius(*shape)); - EXPECT_EQ(static_cast(fshape.get())->GetLocation(), shape->GetLocation()); + EXPECT_EQ(GetVertexRadius(fshape), GetVertexRadius(shape)); + EXPECT_EQ(static_cast(GetData(fshape))->GetLocation(), conf.GetLocation()); EXPECT_FALSE(body->GetFixtures().empty()); { int i = 0; @@ -363,10 +379,8 @@ TEST(Body, CreateAndDestroyFixture) { auto fixture = body->CreateFixture(shape, FixtureDef{}, false); const auto fshape = fixture->GetShape(); - ASSERT_NE(fshape, nullptr); - EXPECT_EQ(typeid(fshape.get()), typeid(const Shape*)); - EXPECT_EQ(GetVertexRadius(*fshape), GetVertexRadius(*shape)); - EXPECT_EQ(static_cast(fshape.get())->GetLocation(), shape->GetLocation()); + EXPECT_EQ(GetVertexRadius(fshape), GetVertexRadius(shape)); + EXPECT_EQ(static_cast(GetData(fshape))->GetLocation(), conf.GetLocation()); EXPECT_FALSE(body->GetFixtures().empty()); { int i = 0; @@ -426,11 +440,11 @@ TEST(Body, CreateLotsOfFixtures) { BodyDef bd; bd.type = BodyType::Dynamic; - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 2.871_m; conf.location = Vec2{1.912f, -77.31f} * 1_m; conf.density = 1.3_kgpm2; - const auto shape = std::make_shared(conf); + const auto shape = Shape(conf); const auto num = 5000; std::chrono::time_point start, end; @@ -566,10 +580,7 @@ TEST(Body, CalcGravitationalAcceleration) const auto l1 = Length2{-8_m, 0_m}; const auto l2 = Length2{+8_m, 0_m}; const auto l3 = Length2{+16_m, 0_m}; - - const auto shape = std::make_shared(DiskShape::Conf{} - .UseVertexRadius(2_m) - .UseDensity(1e10_kgpm2)); + const auto shape = DiskShapeConf{}.UseRadius(2_m).UseDensity(1e10_kgpm2); const auto b1 = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic).UseLocation(l1)); b1->CreateFixture(shape); @@ -586,3 +597,27 @@ TEST(Body, CalcGravitationalAcceleration) const auto b3 = world.CreateBody(BodyDef{}.UseType(BodyType::Static).UseLocation(l3)); EXPECT_EQ(CalcGravitationalAcceleration(*b3), Acceleration{}); } + +TEST(Body, RotateAboutWorldPointFF) +{ + auto world = World{}; + const auto body = world.CreateBody(); + const auto locationA = body->GetLocation(); + ASSERT_EQ(locationA, Length2(0_m, 0_m)); + RotateAboutWorldPoint(*body, 90_deg, Length2{2_m, 0_m}); + const auto locationB = body->GetLocation(); + EXPECT_NEAR(static_cast(Real(GetX(locationB)/Meter)), +2.0, 0.001); + EXPECT_NEAR(static_cast(Real(GetY(locationB)/Meter)), -2.0, 0.001); +} + +TEST(Body, RotateAboutLocalPointFF) +{ + auto world = World{}; + const auto body = world.CreateBody(); + const auto locationA = body->GetLocation(); + ASSERT_EQ(locationA, Length2(0_m, 0_m)); + RotateAboutLocalPoint(*body, 90_deg, Length2{2_m, 0_m}); + const auto locationB = body->GetLocation(); + EXPECT_NEAR(static_cast(Real(GetX(locationB)/Meter)), +2.0, 0.001); + EXPECT_NEAR(static_cast(Real(GetY(locationB)/Meter)), -2.0, 0.001); +} diff --git a/UnitTests/ChainShape.cpp b/UnitTests/ChainShape.cpp index ec012cf73f..84dbe474e5 100644 --- a/UnitTests/ChainShape.cpp +++ b/UnitTests/ChainShape.cpp @@ -19,96 +19,85 @@ */ #include "gtest/gtest.h" -#include -#include +#include +#include #include using namespace playrho; -TEST(ChainShape, ByteSize) +TEST(ChainShapeConf, ByteSize) { switch (sizeof(Real)) { case 4: #if defined(_WIN64) #if !defined(NDEBUG) - EXPECT_EQ(sizeof(ChainShape), std::size_t(88)); + EXPECT_EQ(sizeof(ChainShapeConf), std::size_t(88)); #else - EXPECT_EQ(sizeof(ChainShape), std::size_t(72)); + EXPECT_EQ(sizeof(ChainShapeConf), std::size_t(64)); #endif #elif defined(_WIN32) #if !defined(NDEBUG) - EXPECT_EQ(sizeof(ChainShape), std::size_t(52)); + EXPECT_EQ(sizeof(ChainShapeConf), std::size_t(52)); #else - EXPECT_EQ(sizeof(ChainShape), std::size_t(44)); + EXPECT_EQ(sizeof(ChainShapeConf), std::size_t(40)); #endif #else - EXPECT_EQ(sizeof(ChainShape), std::size_t(72)); + EXPECT_EQ(sizeof(ChainShapeConf), std::size_t(64)); #endif break; - case 8: EXPECT_EQ(sizeof(ChainShape), std::size_t(88)); break; - case 16: EXPECT_EQ(sizeof(ChainShape), std::size_t(128)); break; + case 8: EXPECT_EQ(sizeof(ChainShapeConf), std::size_t(80)); break; + case 16: EXPECT_EQ(sizeof(ChainShapeConf), std::size_t(112)); break; default: FAIL(); break; } } -TEST(ChainShape, DefaultConstruction) +TEST(ChainShapeConf, DefaultConstruction) { - ChainShape foo{}; + const auto foo = ChainShapeConf{}; const auto defaultMassData = MassData{}; - const auto defaultConf = ChainShape::Conf{}; + const auto defaultConf = ChainShapeConf{}; - EXPECT_EQ(typeid(foo), typeid(ChainShape)); - EXPECT_EQ(foo.GetChildCount(), ChildCounter{0}); + EXPECT_EQ(typeid(foo), typeid(ChainShapeConf)); + EXPECT_EQ(GetChildCount(foo), ChildCounter{0}); EXPECT_EQ(foo.GetVertexCount(), ChildCounter{0}); - EXPECT_EQ(foo.GetMassData(), defaultMassData); + EXPECT_EQ(GetMassData(foo), defaultMassData); - EXPECT_EQ(foo.GetVertexRadius(), ChainShape::GetDefaultVertexRadius()); - EXPECT_EQ(foo.GetDensity(), defaultConf.density); - EXPECT_EQ(foo.GetFriction(), defaultConf.friction); - EXPECT_EQ(foo.GetRestitution(), defaultConf.restitution); + EXPECT_EQ(GetVertexRadius(foo), ChainShapeConf::GetDefaultVertexRadius()); + EXPECT_EQ(GetDensity(foo), defaultConf.density); + EXPECT_EQ(GetFriction(foo), defaultConf.friction); + EXPECT_EQ(GetRestitution(foo), defaultConf.restitution); } -TEST(ChainShape, GetInvalidChildThrows) +TEST(ChainShapeConf, GetInvalidChildThrows) { - ChainShape foo{}; + const auto foo = ChainShapeConf{}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{0}); - EXPECT_THROW(foo.GetChild(0), InvalidArgument); - EXPECT_THROW(foo.GetChild(1), InvalidArgument); + ASSERT_EQ(GetChildCount(foo), ChildCounter{0}); + EXPECT_THROW(GetChild(foo, 0), InvalidArgument); + EXPECT_THROW(GetChild(foo, 1), InvalidArgument); } -TEST(ChainShape, Accept) +TEST(ChainShapeConf, Accept) { - class Visitor: public IsVisitedShapeVisitor - { - public: - void Visit(const ChainShape&) override + auto visited = false; + auto shapeVisited = false; + const auto foo = ChainShapeConf{}; + ASSERT_FALSE(visited); + ASSERT_FALSE(shapeVisited); + + Accept(Shape(foo), [&](const std::type_info& ti, const void*) { + visited = true; + if (ti == typeid(ChainShapeConf)) { - visited = true; + shapeVisited = true; } - bool visited = false; - }; - - ChainShape foo{}; - Visitor v; - ASSERT_FALSE(v.visited); - ASSERT_FALSE(v.IsVisited()); - foo.Accept(v); - EXPECT_TRUE(v.visited); - EXPECT_FALSE(v.IsVisited()); -} - -TEST(ChainShape, BaseVisitorForDiskShape) -{ - const auto shape = ChainShape{}; - auto visitor = IsVisitedShapeVisitor{}; - ASSERT_FALSE(visitor.IsVisited()); - shape.Accept(visitor); - EXPECT_TRUE(visitor.IsVisited()); + }); + EXPECT_TRUE(visited); + EXPECT_TRUE(shapeVisited); } -TEST(ChainShape, OneVertexLikeDisk) +TEST(ChainShapeConf, OneVertexLikeDisk) { const auto vertexRadius = 1_m; const auto density = 1_kgpm2; @@ -116,21 +105,21 @@ TEST(ChainShape, OneVertexLikeDisk) const auto expectedMassData = ::GetMassData(vertexRadius, density, location); const auto expectedDistanceProxy = DistanceProxy{vertexRadius, 1, &location, nullptr}; - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.density = density; conf.vertexRadius = vertexRadius; - conf.vertices.push_back(location); - auto foo = ChainShape{conf}; - EXPECT_EQ(foo.GetChildCount(), ChildCounter{1}); + conf.Add(location); + auto foo = ChainShapeConf{conf}; + EXPECT_EQ(GetChildCount(foo), ChildCounter{1}); EXPECT_EQ(foo.GetVertexCount(), ChildCounter{1}); - EXPECT_EQ(foo.GetVertexRadius(), vertexRadius); - EXPECT_EQ(foo.GetMassData(), expectedMassData); + EXPECT_EQ(GetVertexRadius(foo), vertexRadius); + EXPECT_EQ(GetMassData(foo), expectedMassData); - const auto child = foo.GetChild(0); + const auto child = GetChild(foo, 0); EXPECT_EQ(child, expectedDistanceProxy); } -TEST(ChainShape, TwoVertexLikeEdge) +TEST(ChainShapeConf, TwoVertexLikeEdge) { const auto vertexRadius = 1_m; const auto density = NonNegative(1_kgpm2); @@ -138,18 +127,18 @@ TEST(ChainShape, TwoVertexLikeEdge) Length2{0_m, 0_m}, Length2(4_m, 0_m) }}; - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.density = density; conf.vertexRadius = vertexRadius; - conf.vertices.push_back(locations[0]); - conf.vertices.push_back(locations[1]); - auto foo = ChainShape{conf}; - EXPECT_EQ(foo.GetChildCount(), ChildCounter{1}); + conf.Add(locations[0]); + conf.Add(locations[1]); + auto foo = ChainShapeConf{conf}; + EXPECT_EQ(GetChildCount(foo), ChildCounter{1}); EXPECT_EQ(foo.GetVertexCount(), ChildCounter{2}); - EXPECT_EQ(foo.GetVertexRadius(), vertexRadius); + EXPECT_EQ(GetVertexRadius(foo), vertexRadius); } -TEST(ChainShape, TwoVertexDpLikeEdgeDp) +TEST(ChainShapeConf, TwoVertexDpLikeEdgeDp) { const auto vertexRadius = 1_m; const auto density = NonNegative(1_kgpm2); @@ -159,19 +148,19 @@ TEST(ChainShape, TwoVertexDpLikeEdgeDp) const auto normals = std::array{{UnitVec2::GetTop(), UnitVec2::GetBottom()}}; const auto expectedDistanceProxy = DistanceProxy{vertexRadius, 2, locations.data(), normals.data()}; - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.density = density; conf.vertexRadius = vertexRadius; - conf.vertices.push_back(locations[0]); - conf.vertices.push_back(locations[1]); - auto foo = ChainShape{conf}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{1}); + conf.Add(locations[0]); + conf.Add(locations[1]); + auto foo = ChainShapeConf{conf}; + ASSERT_EQ(GetChildCount(foo), ChildCounter{1}); - const auto child = foo.GetChild(0); + const auto child = GetChild(foo, 0); EXPECT_EQ(child, expectedDistanceProxy); } -TEST(ChainShape, TwoVertexMassLikeEdgeMass) +TEST(ChainShapeConf, TwoVertexMassLikeEdgeMass) { const auto vertexRadius = 1_m; const auto density = NonNegative(1_kgpm2); @@ -180,14 +169,14 @@ TEST(ChainShape, TwoVertexMassLikeEdgeMass) }}; const auto expectedMassData = ::GetMassData(vertexRadius, density, locations[0], locations[1]); - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.density = density; conf.vertexRadius = vertexRadius; - conf.vertices.push_back(locations[0]); - conf.vertices.push_back(locations[1]); - auto foo = ChainShape{conf}; + conf.Add(locations[0]); + conf.Add(locations[1]); + auto foo = ChainShapeConf{conf}; - const auto massData = foo.GetMassData(); + const auto massData = GetMassData(foo); EXPECT_NEAR(static_cast(Real{GetX(massData.center)/1_m}), static_cast(Real{GetX(expectedMassData.center)/1_m}), 0.000001); @@ -198,7 +187,7 @@ TEST(ChainShape, TwoVertexMassLikeEdgeMass) EXPECT_EQ(massData.I, expectedMassData.I); } -TEST(ChainShape, FourVertex) +TEST(ChainShapeConf, FourVertex) { const auto vertexRadius = 1_m; const auto density = 1_kgpm2; @@ -211,50 +200,89 @@ TEST(ChainShape, FourVertex) }}; const auto edgeMassData0 = ::GetMassData(vertexRadius, density, locations[0], locations[1]); - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.density = density; conf.vertexRadius = vertexRadius; - conf.vertices = std::vector(std::begin(locations), std::end(locations)); - auto foo = ChainShape{conf}; - EXPECT_EQ(foo.GetChildCount(), ChildCounter{4}); + conf.Set(std::vector(std::begin(locations), std::end(locations))); + auto foo = ChainShapeConf{conf}; + EXPECT_EQ(GetChildCount(foo), ChildCounter{4}); EXPECT_EQ(foo.GetVertexCount(), ChildCounter{5}); - EXPECT_EQ(foo.GetVertexRadius(), vertexRadius); + EXPECT_EQ(GetVertexRadius(foo), vertexRadius); - const auto massData = foo.GetMassData(); + const auto massData = GetMassData(foo); EXPECT_EQ(massData.center, (Length2{})); const auto expectedMass = Mass{edgeMassData0.mass} * Real(4); EXPECT_EQ(massData.mass, NonNegative{expectedMass}); } -TEST(ChainShape, WithCircleVertices) +TEST(ChainShapeConf, WithCircleVertices) { const auto circleRadius = 4_m; const auto vertices = GetCircleVertices(circleRadius, 4, 0_deg, Real(1) / Real(2)); const auto density = 1_kgpm2; const auto vertexRadius = 1_m / 10; - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.density = density; conf.vertexRadius = vertexRadius; - conf.vertices = vertices; - auto foo = ChainShape{conf}; - EXPECT_EQ(foo.GetChildCount(), ChildCounter{4}); + conf.Set(vertices); + auto foo = ChainShapeConf{conf}; + EXPECT_EQ(GetChildCount(foo), ChildCounter{4}); EXPECT_EQ(foo.GetVertexCount(), ChildCounter{5}); - EXPECT_EQ(foo.GetVertexRadius(), vertexRadius); + EXPECT_EQ(GetVertexRadius(foo), vertexRadius); - const auto massData = foo.GetMassData(); + const auto massData = GetMassData(foo); EXPECT_NEAR(static_cast(Real(GetX(massData.center) / 1_m)), 0.0, 0.0001); EXPECT_NEAR(static_cast(Real(GetY(massData.center) / 1_m)), 2.4142134189605713, 0.0001); } -TEST(ChainShape, TooManyVertices) +TEST(ChainShapeConf, TooManyVertices) { const auto density = 1_kgpm2; const auto vertexRadius = 1_m / 10; - auto conf = ChainShape::Conf{}; + auto conf = ChainShapeConf{}; conf.density = density; conf.vertexRadius = vertexRadius; - conf.vertices = std::vector(MaxChildCount + 1); - EXPECT_THROW(ChainShape{conf}, InvalidArgument); + EXPECT_THROW(conf.Set(std::vector(MaxChildCount + 1)), InvalidArgument); +} + +TEST(ChainShapeConf, Equality) +{ + EXPECT_TRUE(ChainShapeConf() == ChainShapeConf()); + + EXPECT_FALSE(ChainShapeConf().UseVertexRadius(10_m) == ChainShapeConf()); + EXPECT_TRUE(ChainShapeConf().UseVertexRadius(10_m) == ChainShapeConf().UseVertexRadius(10_m)); + + EXPECT_FALSE(ChainShapeConf().UseDensity(10_kgpm2) == ChainShapeConf()); + EXPECT_TRUE(ChainShapeConf().UseDensity(10_kgpm2) == ChainShapeConf().UseDensity(10_kgpm2)); + + EXPECT_FALSE(ChainShapeConf().UseFriction(Real(10)) == ChainShapeConf()); + EXPECT_TRUE(ChainShapeConf().UseFriction(Real(10)) == ChainShapeConf().UseFriction(Real(10))); + + EXPECT_FALSE(ChainShapeConf().UseRestitution(Real(10)) == ChainShapeConf()); + EXPECT_TRUE(ChainShapeConf().UseRestitution(Real(10)) == ChainShapeConf().UseRestitution(Real(10))); + + EXPECT_FALSE(ChainShapeConf().Add(Length2(1_m, 2_m)) == ChainShapeConf()); + EXPECT_TRUE(ChainShapeConf().Add(Length2(1_m, 2_m)) == ChainShapeConf().Add(Length2(1_m, 2_m))); +} + +TEST(ChainShapeConf, Inequality) +{ + EXPECT_FALSE(ChainShapeConf() != ChainShapeConf()); + + EXPECT_TRUE(ChainShapeConf().UseVertexRadius(10_m) != ChainShapeConf()); + EXPECT_FALSE(ChainShapeConf().UseVertexRadius(10_m) != ChainShapeConf().UseVertexRadius(10_m)); + + EXPECT_TRUE(ChainShapeConf().UseDensity(10_kgpm2) != ChainShapeConf()); + EXPECT_FALSE(ChainShapeConf().UseDensity(10_kgpm2) != ChainShapeConf().UseDensity(10_kgpm2)); + + EXPECT_TRUE(ChainShapeConf().UseFriction(Real(10)) != ChainShapeConf()); + EXPECT_FALSE(ChainShapeConf().UseFriction(Real(10)) != ChainShapeConf().UseFriction(Real(10))); + + EXPECT_TRUE(ChainShapeConf().UseRestitution(Real(10)) != ChainShapeConf()); + EXPECT_FALSE(ChainShapeConf().UseRestitution(Real(10)) != ChainShapeConf().UseRestitution(Real(10))); + + EXPECT_TRUE(ChainShapeConf().Add(Length2(1_m, 2_m)) != ChainShapeConf()); + EXPECT_FALSE(ChainShapeConf().Add(Length2(1_m, 2_m)) != ChainShapeConf().Add(Length2(1_m, 2_m))); } diff --git a/UnitTests/CollideShapes.cpp b/UnitTests/CollideShapes.cpp index 59a8b42efc..b183e3862d 100644 --- a/UnitTests/CollideShapes.cpp +++ b/UnitTests/CollideShapes.cpp @@ -20,21 +20,21 @@ #include #include #include -#include -#include -#include +#include +#include +#include using namespace playrho; TEST(CollideShapes, IdenticalOverlappingCircles) { const auto radius = 1_m; - const auto shape = DiskShape{radius}; + const auto shape = DiskShapeConf{}.UseRadius(radius); const auto position = Vec2{11, -4} * Meter; const auto xfm = Transformation{position, UnitVec2::GetRight()}; // put shape 1 to left of shape 2 - const auto manifold = CollideShapes(shape.GetChild(0), xfm, shape.GetChild(0), xfm); + const auto manifold = CollideShapes(GetChild(shape, 0), xfm, GetChild(shape, 0), xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_circles); @@ -54,15 +54,15 @@ TEST(CollideShapes, CircleCircleOrientedHorizontally) { const auto r1 = 1_m; const auto r2 = 1_m; - const auto s1 = DiskShape{r1}; - const auto s2 = DiskShape{r2}; + const auto s1 = DiskShapeConf{}.UseRadius(r1); + const auto s2 = DiskShapeConf{}.UseRadius(r2); const auto p1 = Vec2{11, -4} * Meter; const auto p2 = Vec2{13, -4} * Meter; const auto t1 = Transformation{p1, UnitVec2::GetRight()}; const auto t2 = Transformation{p2, UnitVec2::GetRight()}; // put shape 1 to left of shape 2 - const auto manifold = CollideShapes(s1.GetChild(0), t1, s2.GetChild(0), t2); + const auto manifold = CollideShapes(GetChild(s1, 0), t1, GetChild(s2, 0), t2); EXPECT_EQ(manifold.GetType(), Manifold::e_circles); @@ -82,8 +82,8 @@ TEST(CollideShapes, CircleCircleOrientedVertically) { const auto r1 = 1_m; const auto r2 = 1_m; - const auto s1 = DiskShape{r1}; - const auto s2 = DiskShape{r2}; + const auto s1 = DiskShapeConf{}.UseRadius(r1); + const auto s2 = DiskShapeConf{}.UseRadius(r2); const auto p1 = Vec2{7, -2} * Meter; const auto p2 = Vec2{7, -1} * Meter; @@ -92,14 +92,11 @@ TEST(CollideShapes, CircleCircleOrientedVertically) const auto t2 = Transformation{p2, UnitVec2::Get(-21_deg)}; // put shape 1 to left of shape 2 - const auto manifold = CollideShapes(s1.GetChild(0), t1, s2.GetChild(0), t2); + const auto manifold = CollideShapes(GetChild(s1, 0), t1, GetChild(s2, 0), t2); EXPECT_EQ(manifold.GetType(), Manifold::e_circles); - EXPECT_EQ(manifold.GetLocalPoint(), Length2{}); - EXPECT_EQ(manifold.GetPointCount(), Manifold::size_type(1)); - ASSERT_GT(manifold.GetPointCount(), Manifold::size_type(0)); EXPECT_EQ(manifold.GetPoint(0).localPoint, Length2{}); EXPECT_EQ(manifold.GetPoint(0).contactFeature.typeA, ContactFeature::e_vertex); @@ -111,11 +108,11 @@ TEST(CollideShapes, CircleCircleOrientedVertically) TEST(CollideShapes, CircleTouchingTrianglePointBelow) { const auto circleRadius = 1_m; - const auto circle = DiskShape(circleRadius); + const auto circle = DiskShapeConf{}.UseRadius(circleRadius); const auto triangleTopPt = Vec2{0, +1} * Meter; const auto triangleLeftPt = Vec2{-1, -1} * Meter; const auto triangleRightPt = Vec2{+1, -1} * Meter; - const auto triangle = PolygonShape({triangleLeftPt, triangleRightPt, triangleTopPt}); + const auto triangle = PolygonShapeConf{}.Set({triangleLeftPt, triangleRightPt, triangleTopPt}); const auto triangleXfm = Transformation{ Length2{}, UnitVec2::GetRight() @@ -125,7 +122,7 @@ TEST(CollideShapes, CircleTouchingTrianglePointBelow) UnitVec2::GetRight() }; - const auto manifold = CollideShapes(triangle.GetChild(0), triangleXfm, circle.GetChild(0), circleXfm); + const auto manifold = CollideShapes(GetChild(triangle, 0), triangleXfm, GetChild(circle, 0), circleXfm); EXPECT_EQ(manifold.GetType(), Manifold::e_circles); EXPECT_EQ(manifold.GetLocalPoint(), triangleTopPt); @@ -141,11 +138,11 @@ TEST(CollideShapes, CircleTouchingTrianglePointBelow) TEST(CollideShapes, CircleTouchingTrianglePointLeft) { const auto circleRadius = 1_m; - const auto circle = DiskShape(circleRadius); + const auto circle = DiskShapeConf{}.UseRadius(circleRadius); const auto triangleTopPt = Vec2{0, +1} * Meter; const auto triangleLeftPt = Vec2{-1, -1} * Meter; const auto triangleRightPt = Vec2{+1, -1} * Meter; - const auto triangle = PolygonShape({triangleLeftPt, triangleRightPt, triangleTopPt}); + const auto triangle = PolygonShapeConf{}.Set({triangleLeftPt, triangleRightPt, triangleTopPt}); const auto circleXfm = Transformation{ triangleLeftPt + UnitVec2::Get(225_deg) * circleRadius, UnitVec2::GetRight() @@ -155,7 +152,7 @@ TEST(CollideShapes, CircleTouchingTrianglePointLeft) UnitVec2::GetRight() }; - const auto manifold = CollideShapes(triangle.GetChild(0), triangleXfm, circle.GetChild(0), circleXfm); + const auto manifold = CollideShapes(GetChild(triangle, 0), triangleXfm, GetChild(circle, 0), circleXfm); EXPECT_EQ(manifold.GetType(), Manifold::e_circles); EXPECT_EQ(manifold.GetLocalPoint(), triangleLeftPt); @@ -171,18 +168,18 @@ TEST(CollideShapes, CircleTouchingTrianglePointLeft) TEST(CollideShapes, CircleTouchingTrianglePointRight) { const auto circleRadius = 1_m; - const auto circle = DiskShape(circleRadius); + const auto circle = DiskShapeConf(circleRadius); const auto triangleTopPt = Vec2{0, +1} * Meter; const auto triangleLeftPt = Vec2{-1, -1} * Meter; const auto triangleRightPt = Vec2{+1, -1} * Meter; - const auto triangle = PolygonShape({triangleLeftPt, triangleRightPt, triangleTopPt}); + const auto triangle = PolygonShapeConf({triangleLeftPt, triangleRightPt, triangleTopPt}); const auto circleXfm = Transformation{ triangleRightPt + UnitVec2::Get(-45_deg) * circleRadius, UnitVec2::GetRight() }; const auto triangleXfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(triangle.GetChild(0), triangleXfm, circle.GetChild(0), circleXfm); + const auto manifold = CollideShapes(GetChild(triangle, 0), triangleXfm, GetChild(circle, 0), circleXfm); EXPECT_EQ(manifold.GetType(), Manifold::e_circles); EXPECT_EQ(manifold.GetLocalPoint(), triangleRightPt); @@ -198,15 +195,13 @@ TEST(CollideShapes, CircleTouchingTrianglePointRight) TEST(CollideShapes, CircleJustPastTrianglePointRightDoesntCollide) { const auto circleRadius = 1_m; - const auto circle = DiskShape(circleRadius); + const auto circle = DiskShapeConf(circleRadius); const auto triangleTopPt = Vec2{0, +1} * Meter; const auto triangleLeftPt = Vec2{-1, -1} * Meter; const auto triangleRightPt = Vec2{+1, -1} * Meter; - auto triangle = PolygonShape{ - PolygonShape::Conf{} - .SetVertexRadius(Real{0.0001f * 2} * Meter) - .Set({triangleLeftPt, triangleRightPt, triangleTopPt}) - }; + auto triangle = PolygonShapeConf{} + .UseVertexRadius(Real{0.0001f * 2} * Meter) + .Set({triangleLeftPt, triangleRightPt, triangleTopPt}); const auto circleXfm = Transformation{ triangleRightPt + UnitVec2::Get(-45_deg) * circleRadius * Real(1.01), UnitVec2::GetRight() @@ -216,7 +211,7 @@ TEST(CollideShapes, CircleJustPastTrianglePointRightDoesntCollide) UnitVec2::GetRight() }; - const auto manifold = CollideShapes(triangle.GetChild(0), triangleXfm, circle.GetChild(0), circleXfm); + const auto manifold = CollideShapes(GetChild(triangle, 0), triangleXfm, GetChild(circle, 0), circleXfm); EXPECT_EQ(manifold.GetType(), Manifold::e_unset); EXPECT_EQ(manifold.GetPointCount(), Manifold::size_type(0)); @@ -225,11 +220,11 @@ TEST(CollideShapes, CircleJustPastTrianglePointRightDoesntCollide) TEST(CollideShapes, CircleOverRightFaceOfTriangle) { const auto circleRadius = 1_m; - const auto circle = DiskShape(circleRadius); + const auto circle = DiskShapeConf(circleRadius); const auto triangleTopPt = Vec2{0, +1} * Meter; const auto triangleLeftPt = Vec2{-1, -1} * Meter; const auto triangleRightPt = Vec2{+1, -1} * Meter; - const auto triangle = PolygonShape({triangleLeftPt, triangleRightPt, triangleTopPt}); + const auto triangle = PolygonShapeConf({triangleLeftPt, triangleRightPt, triangleTopPt}); const auto circleXfm = Transformation{ Vec2{1, 1} * Meter, UnitVec2::GetRight() @@ -239,7 +234,7 @@ TEST(CollideShapes, CircleOverRightFaceOfTriangle) UnitVec2::GetRight() }; - const auto manifold = CollideShapes(triangle.GetChild(0), triangleXfm, circle.GetChild(0), circleXfm); + const auto manifold = CollideShapes(GetChild(triangle, 0), triangleXfm, GetChild(circle, 0), circleXfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (triangleTopPt + triangleRightPt) / Real{2}); @@ -261,8 +256,8 @@ TEST(CollideShapes, CircleOverRightFaceOfTriangle) TEST(CollideShapes, CircleOverLeftFaceOfTriangle) { const auto circleRadius = 1_m; - const auto circle = DiskShape(circleRadius); - const auto triangle = PolygonShape({Vec2{-1, -1} * Meter, Vec2{+1, -1} * Meter, Vec2{0, +1} * Meter}); + const auto circle = DiskShapeConf(circleRadius); + const auto triangle = PolygonShapeConf({Vec2{-1, -1} * Meter, Vec2{+1, -1} * Meter, Vec2{0, +1} * Meter}); const auto circleXfm = Transformation{ Vec2{-1, 1} * Meter, UnitVec2::GetRight() @@ -272,7 +267,7 @@ TEST(CollideShapes, CircleOverLeftFaceOfTriangle) UnitVec2::GetRight() }; - const auto manifold = CollideShapes(triangle.GetChild(0), triangleXfm, circle.GetChild(0), circleXfm); + const auto manifold = CollideShapes(GetChild(triangle, 0), triangleXfm, GetChild(circle, 0), circleXfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Vec2{-0.5f, 0} * Meter)); @@ -297,13 +292,13 @@ TEST(CollideShapes, TallRectangleLeftCircleRight) const auto hx = Real(2.2); const auto hy = Real(4.8); - const auto s1 = PolygonShape(hx * Meter, hy * Meter); + const auto s1 = PolygonShapeConf(hx * Meter, hy * Meter); ASSERT_EQ(s1.GetVertex(0), (Vec2{+hx, -hy} * Meter)); // bottom right ASSERT_EQ(s1.GetVertex(1), (Vec2{+hx, +hy} * Meter)); // top right ASSERT_EQ(s1.GetVertex(2), (Vec2{-hx, +hy} * Meter)); // top left ASSERT_EQ(s1.GetVertex(3), (Vec2{-hx, -hy} * Meter)); // bottom left - const auto s2 = DiskShape{r2}; + const auto s2 = DiskShapeConf{r2}; const auto p1 = Vec2{-1, 0} * Meter; const auto p2 = Vec2{3, 0} * Meter; @@ -311,7 +306,7 @@ TEST(CollideShapes, TallRectangleLeftCircleRight) const auto t2 = Transformation{p2, UnitVec2::GetRight()}; // rotate rectangle 45 degrees and put it on the left of the circle - const auto manifold = CollideShapes(s1.GetChild(0), t1, s2.GetChild(0), t2); + const auto manifold = CollideShapes(GetChild(s1, 0), t1, GetChild(s2, 0), t2); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -334,14 +329,14 @@ TEST(CollideShapes, TallRectangleLeftCircleRight) TEST(CollideShapes, IdenticalOverlappingSquaresDim1) { const auto dim = Real(1); - const auto shape = PolygonShape(dim * Meter, dim * Meter); + const auto shape = PolygonShapeConf(dim * Meter, dim * Meter); ASSERT_EQ(shape.GetVertex(0), (Vec2{+dim, -dim} * Meter)); // bottom right ASSERT_EQ(shape.GetVertex(1), (Vec2{+dim, +dim} * Meter)); // top right ASSERT_EQ(shape.GetVertex(2), (Vec2{-dim, +dim} * Meter)); // top left ASSERT_EQ(shape.GetVertex(3), (Vec2{-dim, -dim} * Meter)); // bottom left const auto xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(shape.GetChild(0), xfm, shape.GetChild(0), xfm); + const auto manifold = CollideShapes(GetChild(shape, 0), xfm, GetChild(shape, 0), xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -375,14 +370,14 @@ TEST(CollideShapes, IdenticalOverlappingSquaresDim1) TEST(CollideShapes, IdenticalOverlappingSquaresDim2) { const auto dim = Real(2); - const auto shape = PolygonShape(dim * Meter, dim * Meter); + const auto shape = PolygonShapeConf(dim * Meter, dim * Meter); ASSERT_EQ(shape.GetVertex(0), (Vec2{+dim, -dim} * Meter)); // bottom right ASSERT_EQ(shape.GetVertex(1), (Vec2{+dim, +dim} * Meter)); // top right ASSERT_EQ(shape.GetVertex(2), (Vec2{-dim, +dim} * Meter)); // top left ASSERT_EQ(shape.GetVertex(3), (Vec2{-dim, -dim} * Meter)); // bottom left const auto xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(shape.GetChild(0), xfm, shape.GetChild(0), xfm); + const auto manifold = CollideShapes(GetChild(shape, 0), xfm, GetChild(shape, 0), xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -416,7 +411,7 @@ TEST(CollideShapes, IdenticalOverlappingSquaresDim2) TEST(CollideShapes, IdenticalVerticalTouchingSquares) { const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); ASSERT_EQ(shape.GetVertex(0), (Vec2{+2, -2} * Meter)); // bottom right ASSERT_EQ(shape.GetVertex(1), (Vec2{+2, +2} * Meter)); // top right ASSERT_EQ(shape.GetVertex(2), (Vec2{-2, +2} * Meter)); // top left @@ -430,7 +425,7 @@ TEST(CollideShapes, IdenticalVerticalTouchingSquares) Vec2{0, +1} * Meter, UnitVec2::GetRight() }; // top - const auto manifold = CollideShapes(shape.GetChild(0), xfm0, shape.GetChild(0), xfm1); + const auto manifold = CollideShapes(GetChild(shape, 0), xfm0, GetChild(shape, 0), xfm1); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -464,7 +459,7 @@ TEST(CollideShapes, IdenticalVerticalTouchingSquares) TEST(CollideShapes, IdenticalHorizontalTouchingSquares) { const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); ASSERT_EQ(shape.GetVertex(0), Vec2(+2, -2) * Meter); // bottom right ASSERT_EQ(shape.GetVertex(1), Vec2(+2, +2) * Meter); // top right ASSERT_EQ(shape.GetVertex(2), Vec2(-2, +2) * Meter); // top left @@ -478,7 +473,7 @@ TEST(CollideShapes, IdenticalHorizontalTouchingSquares) Vec2{+2, 0} * Meter, UnitVec2::GetRight() }; // right - const auto manifold = CollideShapes(shape.GetChild(0), xfm0, shape.GetChild(0), xfm1); + const auto manifold = CollideShapes(GetChild(shape, 0), xfm0, GetChild(shape, 0), xfm1); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -516,8 +511,8 @@ TEST(CollideShapes, GetMaxSeparationFreeFunction1) const auto xfm1 = Transformation{Vec2{0, +2} * Meter, UnitVec2::GetRight()}; // top const auto dim = 2_m; - const auto shape0 = PolygonShape(dim, dim); - const auto shape1 = PolygonShape(dim, dim); + const auto shape0 = PolygonShapeConf(dim, dim); + const auto shape1 = PolygonShapeConf(dim, dim); ASSERT_EQ(shape0.GetVertex(0), Vec2(+2, -2) * Meter); // bottom right ASSERT_EQ(shape0.GetVertex(1), Vec2(+2, +2) * Meter); // top right ASSERT_EQ(shape0.GetVertex(2), Vec2(-2, +2) * Meter); // top left @@ -546,9 +541,9 @@ TEST(CollideShapes, GetMaxSeparationFreeFunction1) // \|/ // + <----- v3 of shape0 - const auto child0 = shape0.GetChild(0); - const auto child1 = shape1.GetChild(0); - const auto totalRadius = shape0.GetVertexRadius() + shape1.GetVertexRadius(); + const auto child0 = GetChild(shape0, 0); + const auto child1 = GetChild(shape1, 0); + const auto totalRadius = GetVertexRadius(shape0) + GetVertexRadius(shape1); const auto maxSep01_4x4 = GetMaxSeparation4x4(child0, xfm0, child1, xfm1); const auto maxSep10_4x4 = GetMaxSeparation4x4(child1, xfm1, child0, xfm0); @@ -599,7 +594,7 @@ TEST(CollideShapes, GetMaxSeparationFreeFunction1) TEST(CollideShapes, GetMaxSeparationFreeFunction2) { const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); ASSERT_EQ(shape.GetVertex(0), Vec2(+2, -2) * Meter); // bottom right ASSERT_EQ(shape.GetVertex(1), Vec2(+2, +2) * Meter); // top right ASSERT_EQ(shape.GetVertex(2), Vec2(-2, +2) * Meter); // top left @@ -607,9 +602,9 @@ TEST(CollideShapes, GetMaxSeparationFreeFunction2) const auto xfm0 = Transformation{Vec2{0, -1} * Meter, UnitVec2::GetRight()}; // bottom const auto xfm1 = Transformation{Vec2{0, +1} * Meter, UnitVec2::GetRight()}; // top - const auto totalRadius = shape.GetVertexRadius() * Real(2); + const auto totalRadius = GetVertexRadius(shape) * Real(2); - const auto child0 = shape.GetChild(0); + const auto child0 = GetChild(shape, 0); const auto maxSep01_4x4 = GetMaxSeparation4x4(child0, xfm0, child0, xfm1); const auto maxSep10_4x4 = GetMaxSeparation4x4(child0, xfm1, child0, xfm0); const auto maxSep01_NxN = GetMaxSeparation(child0, xfm0, child0, xfm1, totalRadius); @@ -641,7 +636,7 @@ TEST(CollideShapes, SquareCornerTouchingSquareFaceAbove) const auto dim = 2_m; // creates a square - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); ASSERT_EQ(shape.GetVertex(0), Vec2(+2, -2) * Meter); // bottom right ASSERT_EQ(shape.GetVertex(1), Vec2(+2, +2) * Meter); // top right ASSERT_EQ(shape.GetVertex(2), Vec2(-2, +2) * Meter); // top left @@ -672,7 +667,7 @@ TEST(CollideShapes, SquareCornerTouchingSquareFaceAbove) // \4/ // + - const auto manifold = CollideShapes(shape.GetChild(0), xfm0, shape.GetChild(0), xfm1); + const auto manifold = CollideShapes(GetChild(shape, 0), xfm0, GetChild(shape, 0), xfm1); EXPECT_EQ(manifold.GetType(), Manifold::e_faceB); @@ -723,14 +718,14 @@ TEST(CollideShapes, SquareCornerTouchingSquareFaceAbove) TEST(CollideShapes, HorizontalOverlappingRects1) { // Shape A: square - const auto shape0 = PolygonShape(2_m, 2_m); + const auto shape0 = PolygonShapeConf(2_m, 2_m); ASSERT_EQ(shape0.GetVertex(0), Vec2(+2,-2) * Meter); // bottom right ASSERT_EQ(shape0.GetVertex(1), Vec2(+2,+2) * Meter); // top right ASSERT_EQ(shape0.GetVertex(2), Vec2(-2,+2) * Meter); // top left ASSERT_EQ(shape0.GetVertex(3), Vec2(-2,-2) * Meter); // bottom left // Shape B: wide rectangle - const auto shape1 = PolygonShape(3_m, 1.5_m); + const auto shape1 = PolygonShapeConf(3_m, 1.5_m); ASSERT_EQ(shape1.GetVertex(0), Length2(+3.0_m, -1.5_m)); // bottom right ASSERT_EQ(shape1.GetVertex(1), Length2(+3.0_m, +1.5_m)); // top right ASSERT_EQ(shape1.GetVertex(2), Length2(-3.0_m, +1.5_m)); // top left @@ -759,7 +754,7 @@ TEST(CollideShapes, HorizontalOverlappingRects1) // +-------2 // - const auto manifold = CollideShapes(shape0.GetChild(0), xfm0, shape1.GetChild(0), xfm1); + const auto manifold = CollideShapes(GetChild(shape0, 0), xfm0, GetChild(shape1, 0), xfm1); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -809,14 +804,14 @@ TEST(CollideShapes, HorizontalOverlappingRects1) TEST(CollideShapes, HorizontalOverlappingRects2) { // Shape A: wide rectangle - const auto shape0 = PolygonShape(3_m, 1.5_m); + const auto shape0 = PolygonShapeConf(3_m, 1.5_m); ASSERT_EQ(shape0.GetVertex(0), Length2(+3.0_m, -1.5_m)); // bottom right ASSERT_EQ(shape0.GetVertex(1), Length2(+3.0_m, +1.5_m)); // top right ASSERT_EQ(shape0.GetVertex(2), Length2(-3.0_m, +1.5_m)); // top left ASSERT_EQ(shape0.GetVertex(3), Length2(-3.0_m, -1.5_m)); // bottom left // Shape B: square - const auto shape1 = PolygonShape(2_m, 2_m); + const auto shape1 = PolygonShapeConf(2_m, 2_m); ASSERT_EQ(shape1.GetVertex(0), Length2(+2_m,-2_m)); // bottom right ASSERT_EQ(shape1.GetVertex(1), Length2(+2_m,+2_m)); // top right ASSERT_EQ(shape1.GetVertex(2), Length2(-2_m,+2_m)); // top left @@ -832,7 +827,7 @@ TEST(CollideShapes, HorizontalOverlappingRects2) }; // right // put wide rectangle on left, square on right - const auto manifold = CollideShapes(shape0.GetChild(0), xfm0, shape1.GetChild(0), xfm1); + const auto manifold = CollideShapes(GetChild(shape0, 0), xfm0, GetChild(shape1, 0), xfm1); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -885,7 +880,7 @@ TEST(CollideShapes, EdgeBelowPolygon) { const auto p1 = Vec2(-1, 0) * Meter; const auto p2 = Vec2(+1, 0) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{ Vec2{0, -1} * Meter, UnitVec2::GetRight() @@ -893,13 +888,13 @@ TEST(CollideShapes, EdgeBelowPolygon) const auto hx = 1_m; const auto hy = 1_m; - const auto polygon_shape = PolygonShape(hx, hy); + const auto polygon_shape = PolygonShapeConf(hx, hy); const auto polygon_xfm = Transformation{ Length2{}, UnitVec2::GetRight() }; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -934,15 +929,15 @@ TEST(CollideShapes, EdgeAbovePolygon) { const auto p1 = Vec2(-1, 0) * Meter; const auto p2 = Vec2(+1, 0) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Vec2{0, +1} * Meter, UnitVec2::GetRight()}; const auto hx = 1_m; const auto hy = 1_m; - const auto polygon_shape = PolygonShape(hx, hy); + const auto polygon_shape = PolygonShapeConf(hx, hy); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -977,15 +972,15 @@ TEST(CollideShapes, EdgeLeftOfPolygon) { const auto p1 = Vec2(0, -1) * Meter; const auto p2 = Vec2(0, +1) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Vec2{-1, 0} * Meter, UnitVec2::GetRight()}; const auto hx = 1_m; const auto hy = 1_m; - const auto polygon_shape = PolygonShape(hx, hy); + const auto polygon_shape = PolygonShapeConf(hx, hy); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -1002,15 +997,15 @@ TEST(CollideShapes, EdgeRightOfPolygon) { const auto p1 = Vec2(0, -1) * Meter; const auto p2 = Vec2(0, +1) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Vec2{+1, 0} * Meter, UnitVec2::GetRight()}; const auto hx = 1_m; const auto hy = 1_m; - const auto polygon_shape = PolygonShape(hx, hy); + const auto polygon_shape = PolygonShapeConf(hx, hy); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); @@ -1027,13 +1022,13 @@ TEST(CollideShapes, EdgeInsideSquare) { const auto p1 = Vec2(0, -1) * Meter; const auto p2 = Vec2(0, +1) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; const auto s = 1_m; - const auto polygon_shape = PolygonShape(s, s); + const auto polygon_shape = PolygonShapeConf(s, s); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Length2{})); @@ -1052,13 +1047,13 @@ TEST(CollideShapes, EdgeTwiceInsideSquare) { const auto p1 = Vec2(0, -2) * Meter; const auto p2 = Vec2(0, +2) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; const auto s = 1_m; - const auto polygon_shape = PolygonShape(s, s); + const auto polygon_shape = PolygonShapeConf(s, s); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Length2{})); @@ -1077,13 +1072,13 @@ TEST(CollideShapes, EdgeHalfInsideSquare) { const auto p1 = Vec2(0, -0.5) * Meter; const auto p2 = Vec2(0, +0.5) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; const auto s = 1_m; - const auto polygon_shape = PolygonShape(s, s); + const auto polygon_shape = PolygonShapeConf(s, s); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Length2{})); @@ -1102,10 +1097,10 @@ TEST(CollideShapes, EdgeR90InsideSquare) { const auto p1 = Vec2(0, -1) * Meter; const auto p2 = Vec2(0, +1) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Length2{}, UnitVec2::GetTop()}; const auto s = 1_m; - const auto polygon_shape = PolygonShape(s, s); + const auto polygon_shape = PolygonShapeConf(s, s); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; // Sets up a collision between a line segment (A) and a square (B) where the line segment is @@ -1125,7 +1120,7 @@ TEST(CollideShapes, EdgeR90InsideSquare) // Note that the square's vertex 0 is at its bottom right corner, and they go // counter-clockwise from there. // - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Length2{})); @@ -1158,13 +1153,13 @@ TEST(CollideShapes, EdgeR45InsideSquare) { const auto p1 = Vec2(0, -1) * Meter; const auto p2 = Vec2(0, +1) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Length2{}, UnitVec2::Get(45_deg)}; const auto s = 1_m; - const auto polygon_shape = PolygonShape(s, s); + const auto polygon_shape = PolygonShapeConf(s, s); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Length2{})); @@ -1201,13 +1196,13 @@ TEST(CollideShapes, EdgeR180InsideSquare) { const auto p1 = Vec2(0, -1) * Meter; const auto p2 = Vec2(0, +1) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Length2{}, UnitVec2::GetLeft()}; const auto s = 1_m; - const auto polygon_shape = PolygonShape(s, s); + const auto polygon_shape = PolygonShapeConf(s, s); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Length2{})); @@ -1261,16 +1256,16 @@ TEST(CollideShapes, EdgeTwiceR180Square) { const auto p1 = Vec2(0, -2) * Meter; const auto p2 = Vec2(0, +2) * Meter; - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{ Vec2{0, 1} * Meter, UnitVec2::GetLeft() }; const auto s = 1_m; - const auto polygon_shape = PolygonShape(s, s); + const auto polygon_shape = PolygonShapeConf(s, s); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Length2{})); @@ -1323,19 +1318,17 @@ TEST(CollideShapes, EdgeFooTriangle) { const auto p1 = Vec2(2, -2) * Meter; const auto p2 = Vec2(-2, +2) * Meter; - const auto edge_shape = EdgeShape(p2, p1, - EdgeShape::Conf{}.UseVertexRadius(0_m)); + const auto edge_shape = EdgeShapeConf(p2, p1, + EdgeShapeConf{}.UseVertexRadius(0_m)); const auto edge_xfm = Transformation{Vec2(0, 0.5) * Meter, UnitVec2::Get(-5_deg)}; const auto triangleTopPt = Vec2{0, +1} * Meter; const auto triangleLeftPt = Vec2{-1, -1} * Meter; const auto triangleRightPt = Vec2{+1, -1} * Meter; - const auto polygon_shape = PolygonShape{ - PolygonShape::Conf{}.SetVertexRadius(0_m).Set({triangleLeftPt, triangleRightPt, triangleTopPt}) - }; + const auto polygon_shape = PolygonShapeConf{}.UseVertexRadius(0_m).Set({triangleLeftPt, triangleRightPt, triangleTopPt}); const auto polygon_xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, - polygon_shape.GetChild(0), polygon_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, + GetChild(polygon_shape, 0), polygon_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_EQ(manifold.GetLocalPoint(), (Length2{})); @@ -1348,11 +1341,11 @@ TEST(CollideShapes, EdgeFooTriangle) TEST(CollideShapes, EdgePolygonFaceB1) { - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.vertexRadius = 0; - const auto edge_shape = EdgeShape(Vec2(6, 8) * Meter, Vec2(7, 8) * Meter, conf); + const auto edge_shape = EdgeShapeConf(Vec2(6, 8) * Meter, Vec2(7, 8) * Meter, conf); const auto edge_xfm = Transformation{Length2{}, GetUnitVector(Vec2(Real(0.707106769), Real(0.707106769)))}; - const auto poly_shape = PolygonShape({ + const auto poly_shape = PolygonShapeConf({ Vec2(0.5, 0) * Meter, Vec2(0.249999985f, 0.433012724f) * Meter, Vec2(-0.25000003f, 0.433012694f) * Meter, @@ -1362,7 +1355,7 @@ TEST(CollideShapes, EdgePolygonFaceB1) }); const auto poly_xfm = Transformation{Vec2(-0.797443091f, 11.0397148f) * Meter, GetUnitVector(Vec2(1, 0))}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, poly_shape.GetChild(0), poly_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(poly_shape, 0), poly_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceB); EXPECT_NEAR(double(StripUnit(GetX(manifold.GetLocalPoint()))), 0.0, 0.0001); @@ -1380,11 +1373,11 @@ TEST(CollideShapes, EdgePolygonFaceB1) TEST(CollideShapes, EdgePolygonFaceB2) { - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.vertexRadius = 0.000199999995_m; - const auto edge_shape = EdgeShape(Vec2(-6, 2) * Meter, Vec2(-6, 0) * Meter, conf); + const auto edge_shape = EdgeShapeConf(Vec2(-6, 2) * Meter, Vec2(-6, 0) * Meter, conf); const auto edge_xfm = Transformation{Vec2(-9.99999904f, 4.0f) * Meter, GetUnitVector(Vec2(Real(1), Real(0)))}; - const auto poly_shape = PolygonShape({ + const auto poly_shape = PolygonShapeConf({ Vec2(0.5f, -0.5f) * Meter, Vec2(0.5f, 0.5f) * Meter, Vec2(-0.5f, 0.5f) * Meter, @@ -1392,7 +1385,7 @@ TEST(CollideShapes, EdgePolygonFaceB2) }); const auto poly_xfm = Transformation{Vec2(-16.0989342f, 3.49960017f) * Meter, GetUnitVector(Vec2(1, 0))}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), edge_xfm, poly_shape.GetChild(0), poly_xfm); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), edge_xfm, GetChild(poly_shape, 0), poly_xfm); EXPECT_EQ(manifold.GetType(), Manifold::e_faceB); EXPECT_NEAR(double(StripUnit(GetX(manifold.GetLocalPoint()))), 0.0, 0.0001); @@ -1411,7 +1404,7 @@ TEST(CollideShapes, EdgeOverlapsItself) { const auto p1 = Vec2(0, -1); const auto p2 = Vec2(0, +1); - const auto edge_shape = EdgeShape(p1, p2); + const auto edge_shape = EdgeShapeConf(p1, p2); const auto edge_xfm = Transformation{Vec2{+1, 0}, UnitVec2::GetRight()}; const auto manifold = CollideShapes(edge_shape, edge_xfm, edge_shape, edge_xfm); @@ -1427,8 +1420,8 @@ TEST(CollideShapes, R0EdgeCollinearAndTouchingR0Edge) const auto p2 = Vec2(+1, 0) * Meter; const auto xfm1 = Transformation{Vec2{+1, 0} * Meter, UnitVec2::GetRight()}; const auto xfm2 = Transformation{Vec2{+3, 0} * Meter, UnitVec2::GetRight()}; - const auto edge_shape = EdgeShape(EdgeShape::Conf{}.UseVertexRadius(0_m).Set(p1, p2)); - const auto manifold = CollideShapes(edge_shape.GetChild(0), xfm1, edge_shape.GetChild(0), xfm2); + const auto edge_shape = EdgeShapeConf(EdgeShapeConf{}.UseVertexRadius(0_m).Set(p1, p2)); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), xfm1, GetChild(edge_shape, 0), xfm2); EXPECT_EQ(manifold.GetType(), Manifold::e_faceA); EXPECT_TRUE(IsValid(manifold.GetLocalNormal())); @@ -1444,10 +1437,10 @@ TEST(CollideShapes, R1EdgeCollinearAndTouchingR1Edge) { const auto p1 = Vec2(-1, 0) * Meter; const auto p2 = Vec2(+1, 0) * Meter; - const auto edge_shape = EdgeShape(EdgeShape::Conf{}.UseVertexRadius(1_m).Set(p1, p2)); + const auto edge_shape = EdgeShapeConf(EdgeShapeConf{}.UseVertexRadius(1_m).Set(p1, p2)); const auto xfm1 = Transformation{Vec2{+1, 0} * Meter, UnitVec2::GetRight()}; const auto xfm2 = Transformation{Vec2{+5, 0} * Meter, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), xfm1, edge_shape.GetChild(0), xfm2); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), xfm1, GetChild(edge_shape, 0), xfm2); ASSERT_NE(manifold.GetType(), Manifold::e_unset); EXPECT_EQ(manifold.GetType(), Manifold::e_circles); @@ -1460,8 +1453,8 @@ TEST(CollideShapes, R0EdgeCollinearAndSeparateFromR0Edge) const auto p2 = Vec2(+1, 0) * Meter; const auto xfm1 = Transformation{Vec2{+1, 0} * Meter, UnitVec2::GetRight()}; const auto xfm2 = Transformation{Vec2{+4, 0} * Meter, UnitVec2::GetRight()}; - const auto edge_shape = EdgeShape(EdgeShape::Conf{}.UseVertexRadius(0_m).Set(p1, p2)); - const auto manifold = CollideShapes(edge_shape.GetChild(0), xfm1, edge_shape.GetChild(0), xfm2); + const auto edge_shape = EdgeShapeConf(EdgeShapeConf{}.UseVertexRadius(0_m).Set(p1, p2)); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), xfm1, GetChild(edge_shape, 0), xfm2); EXPECT_EQ(manifold.GetType(), Manifold::e_unset); } @@ -1472,8 +1465,8 @@ TEST(CollideShapes, R0EdgeParallelAndSeparateFromR0Edge) const auto p2 = Vec2(+1, 0) * Meter; const auto xfm1 = Transformation{Vec2{-4, 1} * Meter, UnitVec2::GetRight()}; const auto xfm2 = Transformation{Vec2{-4, 0} * Meter, UnitVec2::GetRight()}; - const auto edge_shape = EdgeShape(EdgeShape::Conf{}.UseVertexRadius(0_m).Set(p1, p2)); - const auto manifold = CollideShapes(edge_shape.GetChild(0), xfm1, edge_shape.GetChild(0), xfm2); + const auto edge_shape = EdgeShapeConf(EdgeShapeConf{}.UseVertexRadius(0_m).Set(p1, p2)); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), xfm1, GetChild(edge_shape, 0), xfm2); EXPECT_EQ(manifold.GetType(), Manifold::e_unset); } @@ -1482,10 +1475,10 @@ TEST(CollideShapes, R0EdgePerpendicularCrossingFromR0Edge) { const auto p1 = Vec2(-1, 0) * Meter; const auto p2 = Vec2(+1, 0) * Meter; - const auto edge_shape = EdgeShape(EdgeShape::Conf{}.UseVertexRadius(0_m).Set(p1, p2)); + const auto edge_shape = EdgeShapeConf(EdgeShapeConf{}.UseVertexRadius(0_m).Set(p1, p2)); const auto xfm1 = Transformation{Length2{}, UnitVec2::GetRight()}; const auto xfm2 = Transformation{Length2{}, UnitVec2::GetTop()}; - const auto manifold = CollideShapes(edge_shape.GetChild(0), xfm1, edge_shape.GetChild(0), xfm2); + const auto manifold = CollideShapes(GetChild(edge_shape, 0), xfm1, GetChild(edge_shape, 0), xfm2); ASSERT_NE(manifold.GetType(), Manifold::e_unset); ASSERT_TRUE(IsValid(manifold.GetLocalNormal())); diff --git a/UnitTests/Contact.cpp b/UnitTests/Contact.cpp index e3da90fe63..77099f3958 100644 --- a/UnitTests/Contact.cpp +++ b/UnitTests/Contact.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include using namespace playrho; @@ -56,7 +56,7 @@ TEST(Contact, IsNotCopyAssignable) TEST(Contact, SetAwake) { - const auto shape = std::make_shared(); + const auto shape = DiskShapeConf{}; auto bA = Body{nullptr, BodyDef{}.UseType(BodyType::Dynamic)}; auto bB = Body{nullptr, BodyDef{}.UseType(BodyType::Dynamic)}; auto fA = Fixture{&bA, FixtureDef{}, shape}; @@ -77,34 +77,34 @@ TEST(Contact, SetAwake) TEST(Contact, ResetFriction) { - const auto shape = std::make_shared(); + const auto shape = DiskShapeConf{}; auto bA = Body{nullptr, BodyDef{}.UseType(BodyType::Dynamic)}; auto bB = Body{nullptr, BodyDef{}.UseType(BodyType::Dynamic)}; auto fA = Fixture{&bA, FixtureDef{}, shape}; auto fB = Fixture{&bB, FixtureDef{}, shape}; auto c = Contact{&fA, 0u, &fB, 0u}; - ASSERT_GT(shape->GetFriction(), Real(0)); - ASSERT_NEAR(static_cast(c.GetFriction()), static_cast(shape->GetFriction()), 0.01); - c.SetFriction(shape->GetFriction() * Real(2)); - ASSERT_NE(c.GetFriction(), shape->GetFriction()); + ASSERT_GT(GetFriction(shape), Real(0)); + ASSERT_NEAR(static_cast(c.GetFriction()), static_cast(GetFriction(shape)), 0.01); + c.SetFriction(GetFriction(shape) * Real(2)); + ASSERT_NE(c.GetFriction(), GetFriction(shape)); ResetFriction(c); - EXPECT_NEAR(static_cast(c.GetFriction()), static_cast(shape->GetFriction()), 0.01); + EXPECT_NEAR(static_cast(c.GetFriction()), static_cast(GetFriction(shape)), 0.01); } TEST(Contact, ResetRestitution) { - const auto shape = std::make_shared(); + const auto shape = DiskShapeConf{}; auto bA = Body{nullptr, BodyDef{}.UseType(BodyType::Dynamic)}; auto bB = Body{nullptr, BodyDef{}.UseType(BodyType::Dynamic)}; auto fA = Fixture{&bA, FixtureDef{}, shape}; auto fB = Fixture{&bB, FixtureDef{}, shape}; auto c = Contact{&fA, 0u, &fB, 0u}; - ASSERT_EQ(shape->GetRestitution(), Real(0)); - ASSERT_EQ(c.GetRestitution(), shape->GetRestitution()); + ASSERT_EQ(GetRestitution(shape), Real(0)); + ASSERT_EQ(c.GetRestitution(), GetRestitution(shape)); c.SetRestitution(Real(2)); - ASSERT_NE(c.GetRestitution(), shape->GetRestitution()); + ASSERT_NE(c.GetRestitution(), GetRestitution(shape)); ResetRestitution(c); - EXPECT_EQ(c.GetRestitution(), shape->GetRestitution()); + EXPECT_EQ(c.GetRestitution(), GetRestitution(shape)); } diff --git a/UnitTests/ContactSolver.cpp b/UnitTests/ContactSolver.cpp index 86c2e0afb3..faff3ffaa4 100644 --- a/UnitTests/ContactSolver.cpp +++ b/UnitTests/ContactSolver.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include using namespace playrho; @@ -36,10 +36,10 @@ TEST(ContactSolver, SolvePosConstraintsForHorTouchingDoesntMove) const auto old_vB = Velocity{LinearVelocity2{}, 0_deg / 1_s}; const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); const auto xfmA = Transformation{old_pA.linear, UnitVec2::Get(old_pA.angular)}; const auto xfmB = Transformation{old_pB.linear, UnitVec2::Get(old_pB.angular)}; - const auto manifold = CollideShapes(shape.GetChild(0), xfmA, shape.GetChild(0), xfmB); + const auto manifold = CollideShapes(GetChild(shape, 0), xfmA, GetChild(shape, 0), xfmB); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); ASSERT_EQ(manifold.GetPointCount(), 2); @@ -79,10 +79,10 @@ TEST(ContactSolver, SolvePosConstraintsForVerTouchingDoesntMove) const auto old_vB = Velocity{}; const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); const auto xfmA = Transformation{old_pA.linear, UnitVec2::Get(old_pA.angular)}; const auto xfmB = Transformation{old_pB.linear, UnitVec2::Get(old_pB.angular)}; - const auto manifold = CollideShapes(shape.GetChild(0), xfmA, shape.GetChild(0), xfmB); + const auto manifold = CollideShapes(GetChild(shape, 0), xfmA, GetChild(shape, 0), xfmB); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); ASSERT_EQ(manifold.GetPointCount(), 2); @@ -117,10 +117,10 @@ TEST(ContactSolver, SolvePosConstraintsForVerTouchingDoesntMove) TEST(ContactSolver, SolvePosConstraintsForOverlappingZeroRateDoesntMove) { const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); const auto xfmA = Transformation{Length2{}, UnitVec2::GetRight()}; const auto xfmB = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(shape.GetChild(0), xfmA, shape.GetChild(0), xfmB); + const auto manifold = CollideShapes(GetChild(shape, 0), xfmA, GetChild(shape, 0), xfmB); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); ASSERT_EQ(manifold.GetPointCount(), 2); @@ -171,10 +171,10 @@ TEST(ContactSolver, SolvePosConstraintsForHorOverlappingMovesHorOnly1) const auto old_vB = Velocity{}; const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); const auto xfmA = Transformation{old_pA.linear, UnitVec2::Get(old_pA.angular)}; const auto xfmB = Transformation{old_pB.linear, UnitVec2::Get(old_pB.angular)}; - const auto manifold = CollideShapes(shape.GetChild(0), xfmA, shape.GetChild(0), xfmB); + const auto manifold = CollideShapes(GetChild(shape, 0), xfmA, GetChild(shape, 0), xfmB); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); ASSERT_NEAR(static_cast(GetX(GetVec2(manifold.GetLocalNormal()))), +1.0, 0.00001); ASSERT_NEAR(static_cast(GetY(GetVec2(manifold.GetLocalNormal()))), +0.0, 0.00001); @@ -225,10 +225,10 @@ TEST(ContactSolver, SolvePosConstraintsForHorOverlappingMovesHorOnly2) const auto old_vB = Velocity{}; const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); const auto xfmA = Transformation{old_pA.linear, UnitVec2::Get(old_pA.angular)}; const auto xfmB = Transformation{old_pB.linear, UnitVec2::Get(old_pB.angular)}; - const auto manifold = CollideShapes(shape.GetChild(0), xfmA, shape.GetChild(0), xfmB); + const auto manifold = CollideShapes(GetChild(shape, 0), xfmA, GetChild(shape, 0), xfmB); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); ASSERT_NEAR(static_cast(GetX(GetVec2(manifold.GetLocalNormal()))), -1.0, 0.00001); ASSERT_NEAR(static_cast(GetY(GetVec2(manifold.GetLocalNormal()))), +0.0, 0.00001); @@ -279,10 +279,10 @@ TEST(ContactSolver, SolvePosConstraintsForVerOverlappingMovesVerOnly1) const auto old_vB = Velocity{}; const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); const auto xfmA = Transformation{old_pA.linear, UnitVec2::Get(old_pA.angular)}; const auto xfmB = Transformation{old_pB.linear, UnitVec2::Get(old_pB.angular)}; - const auto manifold = CollideShapes(shape.GetChild(0), xfmA, shape.GetChild(0), xfmB); + const auto manifold = CollideShapes(GetChild(shape, 0), xfmA, GetChild(shape, 0), xfmB); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); ASSERT_NEAR(static_cast(GetX(GetVec2(manifold.GetLocalNormal()))), +0.0, 0.00001); ASSERT_NEAR(static_cast(GetY(GetVec2(manifold.GetLocalNormal()))), +1.0, 0.00001); @@ -345,10 +345,10 @@ TEST(ContactSolver, SolvePosConstraintsForVerOverlappingMovesVerOnly2) const auto old_vB = Velocity{}; const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); const auto xfmA = Transformation{old_pA.linear, UnitVec2::Get(old_pA.angular)}; const auto xfmB = Transformation{old_pB.linear, UnitVec2::Get(old_pB.angular)}; - const auto manifold = CollideShapes(shape.GetChild(0), xfmA, shape.GetChild(0), xfmB); + const auto manifold = CollideShapes(GetChild(shape, 0), xfmA, GetChild(shape, 0), xfmB); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); ASSERT_NEAR(static_cast(GetX(GetVec2(manifold.GetLocalNormal()))), +0.0, 0.00001); @@ -404,10 +404,10 @@ TEST(ContactSolver, SolvePosConstraintsForVerOverlappingMovesVerOnly2) TEST(ContactSolver, SolvePosConstraintsForPerfectlyOverlappingSquares) { const auto dim = 2_m; - const auto shape = PolygonShape(dim, dim); + const auto shape = PolygonShapeConf(dim, dim); const auto xfmA = Transformation{Length2{}, UnitVec2::GetRight()}; const auto xfmB = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto manifold = CollideShapes(shape.GetChild(0), xfmA, shape.GetChild(0), xfmB); + const auto manifold = CollideShapes(GetChild(shape, 0), xfmA, GetChild(shape, 0), xfmB); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); ASSERT_EQ(manifold.GetPointCount(), 2); diff --git a/UnitTests/DiskShape.cpp b/UnitTests/DiskShape.cpp index 7ffbebadd6..e57911a43d 100644 --- a/UnitTests/DiskShape.cpp +++ b/UnitTests/DiskShape.cpp @@ -19,103 +19,102 @@ */ #include "gtest/gtest.h" -#include -#include +#include #include +#include using namespace playrho; -TEST(DiskShape, ByteSize) +TEST(DiskShapeConf, ByteSize) { switch (sizeof(Real)) { case 4: #if defined(_WIN32) && !defined(_WIN64) - EXPECT_EQ(sizeof(DiskShape), std::size_t(28)); + EXPECT_EQ(sizeof(DiskShapeConf), std::size_t(24)); #else - EXPECT_EQ(sizeof(DiskShape), std::size_t(32)); + EXPECT_EQ(sizeof(DiskShapeConf), std::size_t(24)); #endif break; - case 8: EXPECT_EQ(sizeof(DiskShape), std::size_t(56)); break; - case 16: EXPECT_EQ(sizeof(DiskShape), std::size_t(112)); break; + case 8: EXPECT_EQ(sizeof(DiskShapeConf), std::size_t(48)); break; + case 16: EXPECT_EQ(sizeof(DiskShapeConf), std::size_t(96)); break; default: FAIL(); break; } } -TEST(DiskShape, DefaultConstruction) +TEST(DiskShapeConf, DefaultConstruction) { - DiskShape foo{}; + const auto foo = DiskShapeConf{}; - EXPECT_EQ(typeid(foo), typeid(DiskShape)); - EXPECT_EQ(foo.GetChildCount(), ChildCounter{1}); - EXPECT_EQ(foo.GetRadius(), DiskShape::GetDefaultRadius()); + EXPECT_EQ(typeid(foo), typeid(DiskShapeConf)); + EXPECT_EQ(GetChildCount(foo), ChildCounter{1}); + EXPECT_EQ(foo.GetRadius(), DiskShapeConf::GetDefaultRadius()); EXPECT_EQ(GetX(foo.GetLocation()), 0_m); EXPECT_EQ(GetY(foo.GetLocation()), 0_m); } -TEST(DiskShape, InitConstruction) +TEST(DiskShapeConf, InitConstruction) { const auto radius = 1_m; const auto position = Length2{-1_m, 1_m}; - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = radius; conf.location = position; - DiskShape foo{conf}; + Shape foo{conf}; - EXPECT_EQ(typeid(foo), typeid(DiskShape)); - EXPECT_EQ(foo.GetChildCount(), ChildCounter{1}); - EXPECT_EQ(foo.GetRadius(), radius); - EXPECT_EQ(GetX(foo.GetLocation()), GetX(position)); - EXPECT_EQ(GetY(foo.GetLocation()), GetY(position)); + EXPECT_EQ(typeid(foo), typeid(Shape)); + EXPECT_EQ(GetChildCount(foo), ChildCounter{1}); + EXPECT_EQ(GetVertexRadius(foo), radius); + EXPECT_EQ(GetX(conf.GetLocation()), GetX(position)); + EXPECT_EQ(GetY(conf.GetLocation()), GetY(position)); } -TEST(DiskShape, GetInvalidChildThrows) +TEST(DiskShapeConf, GetInvalidChildThrows) { - DiskShape foo{}; + Shape foo{DiskShapeConf{}}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{1}); - EXPECT_NO_THROW(foo.GetChild(0)); - EXPECT_THROW(foo.GetChild(1), InvalidArgument); + ASSERT_EQ(GetChildCount(foo), ChildCounter{1}); + EXPECT_NO_THROW(GetChild(foo, 0)); + EXPECT_THROW(GetChild(foo, 1), InvalidArgument); } -TEST(DiskShape, Accept) +TEST(DiskShapeConf, Accept) { - class Visitor: public IsVisitedShapeVisitor - { - public: - void Visit(const DiskShape&) override + auto visited = false; + auto diskVisited = false; + Shape foo{DiskShapeConf{}}; + ASSERT_FALSE(visited); + ASSERT_FALSE(diskVisited); + Accept(foo, [&](const std::type_info &ti, const void *){ + visited = true; + if (ti == typeid(DiskShapeConf)) { - visited = true; + diskVisited = true; } - bool visited = false; - }; - - DiskShape foo{}; - Visitor v; - ASSERT_FALSE(v.visited); - ASSERT_FALSE(v.IsVisited()); - foo.Accept(v); - EXPECT_TRUE(v.visited); - EXPECT_FALSE(v.IsVisited()); + }); + EXPECT_TRUE(visited); + EXPECT_TRUE(diskVisited); } -TEST(DiskShape, BaseVisitorForDiskShape) +#if 0 +TEST(DiskShapeConf, BaseVisitorForDiskShape) { - const auto shape = DiskShape{2_m}; + const auto shape = DiskShapeConf{}.UseRadius(2_m); auto visitor = IsVisitedShapeVisitor{}; ASSERT_FALSE(visitor.IsVisited()); shape.Accept(visitor); EXPECT_TRUE(visitor.IsVisited()); } +#endif -TEST(DiskShape, TestPoint) +TEST(DiskShapeConf, TestPoint) { const auto radius = 1_m; const auto position = Length2{}; - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = radius; conf.location = position; - DiskShape foo{conf}; + Shape foo{conf}; EXPECT_TRUE(TestPoint(foo, Length2{ 0_m, 0_m})); EXPECT_TRUE(TestPoint(foo, Length2{+1_m, 0_m})); EXPECT_TRUE(TestPoint(foo, Length2{ 0_m, +1_m})); @@ -126,14 +125,14 @@ TEST(DiskShape, TestPoint) EXPECT_FALSE(TestPoint(foo, Length2{+0.9_m, +0.9_m})); } -TEST(DiskShape, ComputeAABB) +TEST(DiskShapeConf, ComputeAABB) { const auto radius = 2.4_m; const auto position = Length2{2_m, 1_m}; - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = radius; conf.location = position; - DiskShape foo{conf}; + Shape foo{conf}; const auto aabb = ComputeAABB(foo, Transform_identity); EXPECT_EQ(GetX(GetLowerBound(aabb)), GetX(position) - radius); EXPECT_EQ(GetY(GetLowerBound(aabb)), GetY(position) - radius); @@ -144,3 +143,45 @@ TEST(DiskShape, ComputeAABB) EXPECT_EQ(GetX(GetCenter(aabb)), GetX(position)); EXPECT_EQ(GetY(GetCenter(aabb)), GetY(position)); } + +TEST(DiskShapeConf, Equality) +{ + EXPECT_TRUE(DiskShapeConf() == DiskShapeConf()); + EXPECT_FALSE(DiskShapeConf().UseRadius(10_m) == DiskShapeConf()); + EXPECT_TRUE(DiskShapeConf().UseRadius(10_m) == DiskShapeConf().UseRadius(10_m)); + EXPECT_FALSE(DiskShapeConf().UseLocation(Length2(1_m, 2_m)) == DiskShapeConf()); + EXPECT_TRUE(DiskShapeConf().UseLocation(Length2(1_m, 2_m)) == DiskShapeConf().UseLocation(Length2(1_m, 2_m))); + + EXPECT_FALSE(DiskShapeConf().UseVertexRadius(10_m) == DiskShapeConf()); + EXPECT_TRUE(DiskShapeConf().UseVertexRadius(10_m) == DiskShapeConf().UseVertexRadius(10_m)); + + EXPECT_FALSE(DiskShapeConf().UseDensity(10_kgpm2) == DiskShapeConf()); + EXPECT_TRUE(DiskShapeConf().UseDensity(10_kgpm2) == DiskShapeConf().UseDensity(10_kgpm2)); + + EXPECT_FALSE(DiskShapeConf().UseFriction(Real(10)) == DiskShapeConf()); + EXPECT_TRUE(DiskShapeConf().UseFriction(Real(10)) == DiskShapeConf().UseFriction(Real(10))); + + EXPECT_FALSE(DiskShapeConf().UseRestitution(Real(10)) == DiskShapeConf()); + EXPECT_TRUE(DiskShapeConf().UseRestitution(Real(10)) == DiskShapeConf().UseRestitution(Real(10))); +} + +TEST(DiskShapeConf, Inequality) +{ + EXPECT_FALSE(DiskShapeConf() != DiskShapeConf()); + EXPECT_TRUE(DiskShapeConf().UseRadius(10_m) != DiskShapeConf()); + EXPECT_FALSE(DiskShapeConf().UseRadius(10_m) != DiskShapeConf().UseRadius(10_m)); + EXPECT_TRUE(DiskShapeConf().UseLocation(Length2(1_m, 2_m)) != DiskShapeConf()); + EXPECT_FALSE(DiskShapeConf().UseLocation(Length2(1_m, 2_m)) != DiskShapeConf().UseLocation(Length2(1_m, 2_m))); + + EXPECT_TRUE(DiskShapeConf().UseVertexRadius(10_m) != DiskShapeConf()); + EXPECT_FALSE(DiskShapeConf().UseVertexRadius(10_m) != DiskShapeConf().UseVertexRadius(10_m)); + + EXPECT_TRUE(DiskShapeConf().UseDensity(10_kgpm2) != DiskShapeConf()); + EXPECT_FALSE(DiskShapeConf().UseDensity(10_kgpm2) != DiskShapeConf().UseDensity(10_kgpm2)); + + EXPECT_TRUE(DiskShapeConf().UseFriction(Real(10)) != DiskShapeConf()); + EXPECT_FALSE(DiskShapeConf().UseFriction(Real(10)) != DiskShapeConf().UseFriction(Real(10))); + + EXPECT_TRUE(DiskShapeConf().UseRestitution(Real(10)) != DiskShapeConf()); + EXPECT_FALSE(DiskShapeConf().UseRestitution(Real(10)) != DiskShapeConf().UseRestitution(Real(10))); +} diff --git a/UnitTests/DistanceJoint.cpp b/UnitTests/DistanceJoint.cpp index 86ab9785a7..a853c350d1 100644 --- a/UnitTests/DistanceJoint.cpp +++ b/UnitTests/DistanceJoint.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include using namespace playrho; @@ -114,8 +114,8 @@ TEST(DistanceJoint, Construction) TEST(DistanceJoint, InZeroGravBodiesMoveOutToLength) { World world{WorldDef{}.UseGravity(LinearAcceleration2{})}; - - const auto shape = std::make_shared(0.2_m); + + const auto shape = DiskShapeConf{}.UseRadius(0.2_m); const auto location1 = Length2{-1_m, 0_m}; const auto body1 = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic).UseLocation(location1)); @@ -169,7 +169,7 @@ TEST(DistanceJoint, InZeroGravBodiesMoveInToLength) { World world{WorldDef{}.UseGravity(LinearAcceleration2{0, Real(10) * MeterPerSquareSecond})}; - const auto shape = std::make_shared(DiskShape::Conf{}.UseVertexRadius(0.2_m).SetDensity(1_kgpm2)); + const auto shape = DiskShapeConf{}.UseRadius(0.2_m).UseDensity(1_kgpm2); const auto location1 = Length2{-10_m, 10_m}; const auto body1 = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic).UseLocation(location1)); ASSERT_EQ(body1->GetLocation(), location1); diff --git a/UnitTests/DistanceProxy.cpp b/UnitTests/DistanceProxy.cpp index c3e47749ec..abb0533ce1 100644 --- a/UnitTests/DistanceProxy.cpp +++ b/UnitTests/DistanceProxy.cpp @@ -62,7 +62,7 @@ TEST(DistanceProxy, OneVecInitialization) const auto vertex0 = Length2{2_m, -3_m}; const auto normal0 = UnitVec2{}; const DistanceProxy foo{radius, 1, &vertex0, &normal0}; - EXPECT_EQ(radius, foo.GetVertexRadius()); + EXPECT_EQ(radius, GetVertexRadius(foo)); EXPECT_EQ(1, foo.GetVertexCount()); EXPECT_EQ(vertex0, foo.GetVertex(0)); } @@ -87,7 +87,7 @@ TEST(DistanceProxy, TwoVecInitialization) const auto normal0 = GetUnitVector(vertex1 - vertex0); const UnitVec2 normals[] = {normal0, -normal0}; const DistanceProxy foo{radius, 2, vertices, normals}; - EXPECT_EQ(radius, foo.GetVertexRadius()); + EXPECT_EQ(radius, GetVertexRadius(foo)); EXPECT_EQ(2, foo.GetVertexCount()); EXPECT_EQ(vertex0, foo.GetVertex(0)); EXPECT_EQ(vertex1, foo.GetVertex(1)); @@ -124,7 +124,7 @@ TEST(DistanceProxy, ThreeVertices) const DistanceProxy foo{radius, 3, vertices, normals}; - EXPECT_EQ(foo.GetVertexRadius(), radius); + EXPECT_EQ(GetVertexRadius(foo), radius); ASSERT_EQ(foo.GetVertexCount(), count); EXPECT_EQ(GetX(foo.GetVertex(0)), GetX(v0)); EXPECT_EQ(GetY(foo.GetVertex(0)), GetY(v0)); @@ -236,3 +236,20 @@ TEST(DistanceProxy, GetMaxSeparationFromWorld) EXPECT_EQ(result2.indices.first, static_cast(2)); EXPECT_EQ(result2.indices.second, static_cast(0)); } + +TEST(DistanceProxy, Equality) +{ + const auto pos1 = Length2{3_m, 1_m}; + const auto pos2 = Length2{3_m, 3_m}; + const auto pos3 = Length2{1_m, 3_m}; + const auto pos4 = Length2{1_m, 1_m}; + const Length2 verts[] = {pos1, pos2, pos3, pos4}; + const auto n1 = GetUnitVector(GetFwdPerpendicular(pos2 - pos1)); + const auto n2 = GetUnitVector(GetFwdPerpendicular(pos3 - pos2)); + const auto n3 = GetUnitVector(GetFwdPerpendicular(pos4 - pos3)); + const auto n4 = GetUnitVector(GetFwdPerpendicular(pos1 - pos4)); + const UnitVec2 norms[] = {n1, n2, n3, n4}; + + EXPECT_TRUE(DistanceProxy(0.0_m, 4, verts, norms) == DistanceProxy(0.0_m, 4, verts, norms)); + EXPECT_FALSE(DistanceProxy(1.0_m, 4, verts, norms) == DistanceProxy(0.0_m, 4, verts, norms)); +} diff --git a/UnitTests/EdgeShape.cpp b/UnitTests/EdgeShape.cpp index 581f8a2cff..387986e75f 100644 --- a/UnitTests/EdgeShape.cpp +++ b/UnitTests/EdgeShape.cpp @@ -19,63 +19,102 @@ */ #include "gtest/gtest.h" -#include -#include +#include +#include using namespace playrho; -TEST(EdgeShape, ByteSize) +TEST(EdgeShapeConf, ByteSize) { switch (sizeof(Real)) { case 4: #if defined(_WIN32) && !defined(_WIN64) - EXPECT_EQ(sizeof(EdgeShape), std::size_t(52)); + EXPECT_EQ(sizeof(EdgeShapeConf), std::size_t(48)); #else - EXPECT_EQ(sizeof(EdgeShape), std::size_t(56)); + EXPECT_EQ(sizeof(EdgeShapeConf), std::size_t(48)); #endif break; - case 8: EXPECT_EQ(sizeof(EdgeShape), std::size_t(104)); break; - case 16: EXPECT_EQ(sizeof(EdgeShape), std::size_t(208)); break; + case 8: EXPECT_EQ(sizeof(EdgeShapeConf), std::size_t(96)); break; + case 16: EXPECT_EQ(sizeof(EdgeShapeConf), std::size_t(192)); break; default: FAIL(); break; } } -TEST(EdgeShape, GetInvalidChildThrows) +TEST(EdgeShapeConf, GetInvalidChildThrows) { - EdgeShape foo{}; + const auto foo = EdgeShapeConf{}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{1}); - EXPECT_NO_THROW(foo.GetChild(0)); - EXPECT_THROW(foo.GetChild(1), InvalidArgument); + ASSERT_EQ(GetChildCount(foo), ChildCounter{1}); + EXPECT_NO_THROW(GetChild(foo, 0)); + EXPECT_THROW(GetChild(foo, 1), InvalidArgument); } -TEST(EdgeShape, Accept) +TEST(EdgeShapeConf, Accept) { - class Visitor: public IsVisitedShapeVisitor - { - public: - void Visit(const EdgeShape&) override + auto visited = false; + auto shapeVisited = false; + const auto foo = EdgeShapeConf{}; + ASSERT_FALSE(visited); + ASSERT_FALSE(shapeVisited); + Accept(Shape(foo), [&](const std::type_info& ti, const void*) { + visited = true; + if (ti == typeid(EdgeShapeConf)) { - visited = true; + shapeVisited = true; } - bool visited = false; - }; - - EdgeShape foo{}; - Visitor v; - ASSERT_FALSE(v.visited); - ASSERT_FALSE(v.IsVisited()); - foo.Accept(v); - EXPECT_TRUE(v.visited); - EXPECT_FALSE(v.IsVisited()); + }); + EXPECT_TRUE(visited); + EXPECT_TRUE(shapeVisited); } -TEST(EdgeShape, BaseVisitorForDiskShape) +#if 0 +TEST(EdgeShapeConf, BaseVisitorForDiskShape) { - const auto shape = EdgeShape{}; + const auto shape = EdgeShapeConf{}; auto visitor = IsVisitedShapeVisitor{}; ASSERT_FALSE(visitor.IsVisited()); shape.Accept(visitor); EXPECT_TRUE(visitor.IsVisited()); } +#endif + +TEST(EdgeShapeConf, Equality) +{ + EXPECT_TRUE(EdgeShapeConf() == EdgeShapeConf()); + + EXPECT_FALSE(EdgeShapeConf().Set(Length2(1_m, 2_m), Length2(3_m, 4_m)) == EdgeShapeConf()); + EXPECT_TRUE(EdgeShapeConf().Set(Length2(1_m, 2_m), Length2(3_m, 4_m)) == EdgeShapeConf().Set(Length2(1_m, 2_m), Length2(3_m, 4_m))); + + EXPECT_FALSE(EdgeShapeConf().UseVertexRadius(10_m) == EdgeShapeConf()); + EXPECT_TRUE(EdgeShapeConf().UseVertexRadius(10_m) == EdgeShapeConf().UseVertexRadius(10_m)); + + EXPECT_FALSE(EdgeShapeConf().UseDensity(10_kgpm2) == EdgeShapeConf()); + EXPECT_TRUE(EdgeShapeConf().UseDensity(10_kgpm2) == EdgeShapeConf().UseDensity(10_kgpm2)); + + EXPECT_FALSE(EdgeShapeConf().UseFriction(Real(10)) == EdgeShapeConf()); + EXPECT_TRUE(EdgeShapeConf().UseFriction(Real(10)) == EdgeShapeConf().UseFriction(Real(10))); + + EXPECT_FALSE(EdgeShapeConf().UseRestitution(Real(10)) == EdgeShapeConf()); + EXPECT_TRUE(EdgeShapeConf().UseRestitution(Real(10)) == EdgeShapeConf().UseRestitution(Real(10))); +} + +TEST(EdgeShapeConf, Inequality) +{ + EXPECT_FALSE(EdgeShapeConf() != EdgeShapeConf()); + + EXPECT_TRUE(EdgeShapeConf().Set(Length2(1_m, 2_m), Length2(3_m, 4_m)) != EdgeShapeConf()); + EXPECT_FALSE(EdgeShapeConf().Set(Length2(1_m, 2_m), Length2(3_m, 4_m)) != EdgeShapeConf().Set(Length2(1_m, 2_m), Length2(3_m, 4_m))); + + EXPECT_TRUE(EdgeShapeConf().UseVertexRadius(10_m) != EdgeShapeConf()); + EXPECT_FALSE(EdgeShapeConf().UseVertexRadius(10_m) != EdgeShapeConf().UseVertexRadius(10_m)); + + EXPECT_TRUE(EdgeShapeConf().UseDensity(10_kgpm2) != EdgeShapeConf()); + EXPECT_FALSE(EdgeShapeConf().UseDensity(10_kgpm2) != EdgeShapeConf().UseDensity(10_kgpm2)); + + EXPECT_TRUE(EdgeShapeConf().UseFriction(Real(10)) != EdgeShapeConf()); + EXPECT_FALSE(EdgeShapeConf().UseFriction(Real(10)) != EdgeShapeConf().UseFriction(Real(10))); + + EXPECT_TRUE(EdgeShapeConf().UseRestitution(Real(10)) != EdgeShapeConf()); + EXPECT_FALSE(EdgeShapeConf().UseRestitution(Real(10)) != EdgeShapeConf().UseRestitution(Real(10))); +} diff --git a/UnitTests/Fixture.cpp b/UnitTests/Fixture.cpp index a0b5b6c52e..681048ab76 100644 --- a/UnitTests/Fixture.cpp +++ b/UnitTests/Fixture.cpp @@ -21,7 +21,8 @@ #include #include #include -#include +#include +#include using namespace playrho; @@ -50,8 +51,8 @@ TEST(Fixture, CreateMatchesDef) const auto friction = Real(0.5); const auto restitution = Real(0.4); const auto isSensor = true; - const auto conf = DiskShape::Conf{}.SetFriction(friction).SetRestitution(restitution).SetDensity(density); - const auto shapeA = std::make_shared(conf); + const auto conf = DiskShapeConf{}.UseFriction(friction).UseRestitution(restitution).UseDensity(density); + const auto shapeA = Shape(conf); auto def = FixtureDef{}; def.userData = userData; @@ -73,7 +74,7 @@ TEST(Fixture, CreateMatchesDef) TEST(Fixture, SetSensor) { - const auto shapeA = std::make_shared(); + const auto shapeA = DiskShapeConf{}; const auto bodyCtrPos = Length2(1_m, 2_m); World world; @@ -89,7 +90,7 @@ TEST(Fixture, SetSensor) TEST(Fixture, TestPointFreeFunction) { - const auto shapeA = std::make_shared(); + const auto shapeA = DiskShapeConf{}; const auto bodyCtrPos = Length2(1_m, 2_m); World world; @@ -101,8 +102,8 @@ TEST(Fixture, TestPointFreeFunction) TEST(Fixture, SetAwakeFreeFunction) { - const auto shapeA = std::make_shared(); - + const auto shapeA = DiskShapeConf{}; + World world; const auto body = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic)); body->UnsetAwake(); @@ -120,43 +121,114 @@ TEST(Fixture, CopyConstructor) const auto friction = Real(0.5); const auto restitution = Real(0.4); const auto isSensor = true; - const auto conf = DiskShape::Conf{}.SetFriction(friction).SetRestitution(restitution).SetDensity(density); - const auto shapeA = std::make_shared(conf); auto def = FixtureDef{}; def.userData = userData; def.isSensor = isSensor; - World world; - const auto body = world.CreateBody(); - const auto fixture = body->CreateFixture(shapeA, def); + { + const auto shape = Shape{ + DiskShapeConf{}.UseFriction(friction).UseRestitution(restitution).UseDensity(density) + }; + + World world; + const auto body = world.CreateBody(); + const auto fixture = body->CreateFixture(shape, def); + + ASSERT_EQ(fixture->GetBody(), body); + ASSERT_EQ(fixture->GetShape(), shape); + ASSERT_EQ(fixture->GetDensity(), density); + ASSERT_EQ(fixture->GetFriction(), friction); + ASSERT_EQ(fixture->GetUserData(), userData); + ASSERT_EQ(fixture->GetRestitution(), restitution); + ASSERT_EQ(fixture->IsSensor(), isSensor); + ASSERT_EQ(fixture->GetProxyCount(), ChildCounter{0}); + + const auto stepConf = StepConf{}; + world.Step(stepConf); + ASSERT_EQ(fixture->GetProxyCount(), ChildCounter{1}); + ASSERT_EQ(fixture->GetProxy(0), FixtureProxy{0}); + + Fixture copy{*fixture}; + + EXPECT_EQ(copy.GetBody(), body); + EXPECT_EQ(copy.GetShape(), shape); + EXPECT_EQ(copy.GetDensity(), density); + EXPECT_EQ(copy.GetFriction(), friction); + EXPECT_EQ(copy.GetUserData(), userData); + EXPECT_EQ(copy.GetRestitution(), restitution); + EXPECT_EQ(copy.IsSensor(), isSensor); + EXPECT_EQ(copy.GetProxyCount(), fixture->GetProxyCount()); + if (copy.GetProxyCount() == fixture->GetProxyCount()) + { + EXPECT_EQ(copy.GetProxy(0), fixture->GetProxy(0)); + } + } - ASSERT_EQ(fixture->GetBody(), body); - ASSERT_EQ(fixture->GetShape(), shapeA); - ASSERT_EQ(fixture->GetDensity(), density); - ASSERT_EQ(fixture->GetFriction(), friction); - ASSERT_EQ(fixture->GetUserData(), userData); - ASSERT_EQ(fixture->GetRestitution(), restitution); - ASSERT_EQ(fixture->IsSensor(), isSensor); - ASSERT_EQ(fixture->GetProxyCount(), ChildCounter{0}); - - const auto stepConf = StepConf{}; - world.Step(stepConf); - ASSERT_EQ(fixture->GetProxyCount(), ChildCounter{1}); - ASSERT_EQ(fixture->GetProxy(0), FixtureProxy{0}); - - Fixture copy{*fixture}; + { + const auto shape = Shape{ + ChainShapeConf{}.Add(Length2{-2_m, -3_m}).Add(Length2{-2_m, 0_m}).Add(Length2{0_m, 0_m}) + }; + + World world; + const auto body = world.CreateBody(); + const auto fixture = body->CreateFixture(shape, def); + + ASSERT_EQ(fixture->GetBody(), body); + ASSERT_EQ(fixture->GetShape(), shape); + ASSERT_EQ(fixture->IsSensor(), isSensor); + ASSERT_EQ(fixture->GetProxyCount(), ChildCounter{0}); + + const auto stepConf = StepConf{}; + world.Step(stepConf); + ASSERT_EQ(fixture->GetProxyCount(), ChildCounter{2}); + ASSERT_EQ(fixture->GetProxy(0), FixtureProxy{0}); + ASSERT_EQ(fixture->GetProxy(1), FixtureProxy{1}); + + Fixture copy{*fixture}; + + EXPECT_EQ(copy.GetBody(), body); + EXPECT_EQ(copy.GetShape(), shape); + EXPECT_EQ(copy.IsSensor(), isSensor); + EXPECT_EQ(copy.GetProxyCount(), fixture->GetProxyCount()); + if (copy.GetProxyCount() == fixture->GetProxyCount()) + { + EXPECT_EQ(copy.GetProxy(0), fixture->GetProxy(0)); + } + } - EXPECT_EQ(copy.GetBody(), body); - EXPECT_EQ(copy.GetShape(), shapeA); - EXPECT_EQ(copy.GetDensity(), density); - EXPECT_EQ(copy.GetFriction(), friction); - EXPECT_EQ(copy.GetUserData(), userData); - EXPECT_EQ(copy.GetRestitution(), restitution); - EXPECT_EQ(copy.IsSensor(), isSensor); - EXPECT_EQ(copy.GetProxyCount(), fixture->GetProxyCount()); - if (copy.GetProxyCount() == fixture->GetProxyCount()) { - EXPECT_EQ(copy.GetProxy(0), fixture->GetProxy(0)); + const auto shape = Shape{ + ChainShapeConf{}.Add(Length2{-2_m, -3_m}).Add(Length2{-2_m, 0_m}).Add(Length2{0_m, 0_m}) + .Add(Length2{0_m, +2_m}).Add(Length2{2_m, 2_m}) + }; + + World world; + const auto body = world.CreateBody(); + const auto fixture = body->CreateFixture(shape, def); + + ASSERT_EQ(fixture->GetBody(), body); + ASSERT_EQ(fixture->GetShape(), shape); + ASSERT_EQ(fixture->IsSensor(), isSensor); + ASSERT_EQ(fixture->GetProxyCount(), ChildCounter{0}); + + const auto stepConf = StepConf{}; + world.Step(stepConf); + ASSERT_EQ(fixture->GetProxyCount(), ChildCounter{4}); + ASSERT_EQ(fixture->GetProxy(0), FixtureProxy{0}); + ASSERT_EQ(fixture->GetProxy(1), FixtureProxy{1}); + ASSERT_EQ(fixture->GetProxy(2), FixtureProxy{3}); + ASSERT_EQ(fixture->GetProxy(3), FixtureProxy{5}); + + Fixture copy{*fixture}; + + EXPECT_EQ(copy.GetBody(), body); + EXPECT_EQ(copy.GetShape(), shape); + EXPECT_EQ(copy.IsSensor(), isSensor); + EXPECT_EQ(copy.GetProxyCount(), fixture->GetProxyCount()); + if (copy.GetProxyCount() == fixture->GetProxyCount()) + { + EXPECT_EQ(copy.GetProxy(0), fixture->GetProxy(0)); + } } } diff --git a/UnitTests/FrictionJoint.cpp b/UnitTests/FrictionJoint.cpp index ddaaf7336d..4c3d6e14d2 100644 --- a/UnitTests/FrictionJoint.cpp +++ b/UnitTests/FrictionJoint.cpp @@ -21,7 +21,7 @@ #include "gtest/gtest.h" #include #include -#include +#include #include #include #include @@ -131,7 +131,7 @@ TEST(FrictionJoint, GetFrictionJointDef) TEST(FrictionJoint, WithDynamicCircles) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); World world{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; diff --git a/UnitTests/GearJoint.cpp b/UnitTests/GearJoint.cpp index fdcb5290d8..ed0ba809eb 100644 --- a/UnitTests/GearJoint.cpp +++ b/UnitTests/GearJoint.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include using namespace playrho; @@ -186,7 +186,7 @@ TEST(GearJoint, GetGearJointDef) TEST(GearJoint, WithDynamicCirclesAndRevoluteJoints) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; @@ -217,7 +217,7 @@ TEST(GearJoint, WithDynamicCirclesAndRevoluteJoints) TEST(GearJoint, WithDynamicCirclesAndPrismaticJoints) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; @@ -248,7 +248,7 @@ TEST(GearJoint, WithDynamicCirclesAndPrismaticJoints) TEST(GearJoint, GetAnchorAandB) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; diff --git a/UnitTests/MassData.cpp b/UnitTests/MassData.cpp index 4a28f8b899..81fcaef0d9 100644 --- a/UnitTests/MassData.cpp +++ b/UnitTests/MassData.cpp @@ -18,9 +18,9 @@ #include "gtest/gtest.h" #include -#include -#include -#include +#include +#include +#include using namespace playrho; @@ -180,8 +180,8 @@ TEST(MassData, GetMassDataFreeFunctionForNoVertices) TEST(MassData, GetForZeroVertexRadiusCircle) { - const auto shape = DiskShape(DiskShape::Conf{}.SetRadius(0_m).SetDensity(1_kgpm2)); - const auto mass_data = shape.GetMassData(); + const auto shape = DiskShapeConf{}.UseRadius(0_m).UseDensity(1_kgpm2); + const auto mass_data = GetMassData(shape); EXPECT_EQ(mass_data.mass, NonNegative(0_kg)); EXPECT_EQ(mass_data.I, RotInertia{0}); EXPECT_EQ(GetX(mass_data.center), 0_m); @@ -190,12 +190,11 @@ TEST(MassData, GetForZeroVertexRadiusCircle) TEST(MassData, GetForOriginCenteredCircle) { - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = 1_m; conf.location = Length2{}; conf.density = 1_kgpm2; - const auto foo = DiskShape{conf}; - const auto mass_data = foo.GetMassData(); + const auto mass_data = GetMassData(conf); EXPECT_EQ(Real{Mass{mass_data.mass} / 1_kg}, Pi); EXPECT_NEAR(double(StripUnit(mass_data.I)), 1.5707964, 0.0005); const auto squareVertexRadius = Square(Length{conf.vertexRadius}); @@ -212,12 +211,11 @@ TEST(MassData, GetForCircle) const auto radius = 1_m; const auto position = Length2{-1_m, 1_m}; const auto density = 1_kgpm2; - auto conf = DiskShape::Conf{}; + auto conf = DiskShapeConf{}; conf.vertexRadius = radius; conf.location = position; conf.density = density; - const auto foo = DiskShape{conf}; - const auto mass_data = foo.GetMassData(); + const auto mass_data = GetMassData(conf); EXPECT_EQ(Real{Mass{mass_data.mass} / 1_kg}, Pi); EXPECT_NEAR(double(StripUnit(mass_data.I)), 7.85398, 0.003); EXPECT_EQ(mass_data.center, position); @@ -226,14 +224,14 @@ TEST(MassData, GetForCircle) TEST(MassData, GetForZeroVertexRadiusRectangle) { const auto density = 2.1_kgpm2; - auto conf = PolygonShape::Conf{}; + auto conf = PolygonShapeConf{}; conf.vertexRadius = 0; conf.density = density; conf.SetAsBox(4_m, 1_m); - auto shape = PolygonShape(conf); + auto shape = conf; ASSERT_EQ(GetX(shape.GetCentroid()), 0_m); ASSERT_EQ(GetY(shape.GetCentroid()), 0_m); - const auto mass_data = shape.GetMassData(); + const auto mass_data = GetMassData(shape); EXPECT_TRUE(AlmostEqual(Real(Mass{mass_data.mass} / 1_kg), Real((density / KilogramPerSquareMeter) * (8 * 2)))); EXPECT_NEAR(double(StripUnit(mass_data.I)), @@ -261,11 +259,11 @@ TEST(MassData, GetForZeroVertexRadiusEdge) const auto v1 = Length2{-1_m, 0_m}; const auto v2 = Length2{+1_m, 0_m}; const auto density = 2.1_kgpm2; - auto conf = EdgeShape::Conf{}; + auto conf = EdgeShapeConf{}; conf.vertexRadius = 0_m; conf.density = density; - const auto shape = EdgeShape(v1, v2, conf); - const auto mass_data = shape.GetMassData(); + const auto shape = EdgeShapeConf(v1, v2, conf); + const auto mass_data = GetMassData(shape); EXPECT_EQ(Real(Mass{mass_data.mass} / 1_kg), Real(0)); EXPECT_NEAR(double(Real{RotInertia{mass_data.I} / (SquareMeter * 1_kg / SquareRadian)}), 0.0, 0.00001); @@ -277,9 +275,9 @@ TEST(MassData, GetForSamePointedEdgeIsSameAsCircle) { const auto v1 = Length2{-1_m, 1_m}; const auto density = 1_kgpm2; - const auto shape = EdgeShape(EdgeShape::Conf{}.UseVertexRadius(1_m).UseDensity(density).Set(v1, v1)); - const auto mass_data = shape.GetMassData(); - const auto circleMass = density * Pi * Square(shape.GetVertexRadius()); + const auto shape = EdgeShapeConf(EdgeShapeConf{}.UseVertexRadius(1_m).UseDensity(density).Set(v1, v1)); + const auto mass_data = GetMassData(shape); + const auto circleMass = density * Pi * Square(GetVertexRadius(shape)); EXPECT_TRUE(AlmostEqual(StripUnit(mass_data.mass), StripUnit(circleMass))); EXPECT_TRUE(IsValid(mass_data.I)); @@ -305,11 +303,11 @@ TEST(MassData, GetForCenteredEdge) ASSERT_NEAR(static_cast(Real{circleArea / SquareMeter}), 0.78539818525314331, 0.78539818525314331 / 1000000.0); - const auto shape = EdgeShape(EdgeShape::Conf{}.UseVertexRadius(radius).UseDensity(density).Set(v1, v2)); - ASSERT_EQ(shape.GetVertexRadius(), radius); - ASSERT_EQ(shape.GetVertex1(), v1); - ASSERT_EQ(shape.GetVertex2(), v2); - ASSERT_EQ(shape.GetDensity(), density); + const auto shape = EdgeShapeConf(EdgeShapeConf{}.UseVertexRadius(radius).UseDensity(density).Set(v1, v2)); + ASSERT_EQ(GetVertexRadius(shape), radius); + ASSERT_EQ(shape.GetVertexA(), v1); + ASSERT_EQ(shape.GetVertexB(), v2); + ASSERT_EQ(GetDensity(shape), density); const auto vertices = Vector{ Length2(-2_m, +0.5_m), @@ -347,7 +345,7 @@ TEST(MassData, GetForCenteredEdge) EXPECT_NEAR(static_cast(Real{I / (1_kg * SquareMeter / SquareRadian)}), 18.703510284423828, 18.703510284423828 / 1000000.0); - const auto mass_data = shape.GetMassData(); + const auto mass_data = GetMassData(shape); EXPECT_EQ(mass_data.mass, density * area); { EXPECT_NEAR(static_cast(Real{RotInertia{mass_data.I} / (SquareMeter * 1_kg / SquareRadian)}), diff --git a/UnitTests/MotorJoint.cpp b/UnitTests/MotorJoint.cpp index 6bd61d2dbc..2a06719fac 100644 --- a/UnitTests/MotorJoint.cpp +++ b/UnitTests/MotorJoint.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include using namespace playrho; @@ -181,7 +181,7 @@ TEST(MotorJoint, GetMotorJointDef) TEST(MotorJoint, WithDynamicCircles) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; @@ -207,7 +207,7 @@ TEST(MotorJoint, WithDynamicCircles) TEST(MotorJoint, SetLinearOffset) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; @@ -231,7 +231,7 @@ TEST(MotorJoint, SetLinearOffset) TEST(MotorJoint, SetAngularOffset) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; diff --git a/UnitTests/MultiShape.cpp b/UnitTests/MultiShape.cpp index acd361f6e7..08c082ebd5 100644 --- a/UnitTests/MultiShape.cpp +++ b/UnitTests/MultiShape.cpp @@ -19,96 +19,94 @@ */ #include "gtest/gtest.h" -#include -#include +#include +#include #include #include using namespace playrho; -TEST(MultiShape, ByteSize) +TEST(MultiShapeConf, ByteSize) { switch (sizeof(Real)) { case 4: #if defined(_WIN64) #if !defined(NDEBUG) - EXPECT_EQ(sizeof(MultiShape), std::size_t(56)); + EXPECT_EQ(sizeof(MultiShapeConf), std::size_t(56)); #else - EXPECT_EQ(sizeof(MultiShape), std::size_t(48)); + EXPECT_EQ(sizeof(MultiShapeConf), std::size_t(40)); #endif #elif defined(_WIN32) #if !defined(NDEBUG) - EXPECT_EQ(sizeof(MultiShape), std::size_t(36)); + EXPECT_EQ(sizeof(MultiShapeConf), std::size_t(36)); #else - EXPECT_EQ(sizeof(MultiShape), std::size_t(32)); + EXPECT_EQ(sizeof(MultiShapeConf), std::size_t(28)); #endif #else - EXPECT_EQ(sizeof(MultiShape), std::size_t(48)); + EXPECT_EQ(sizeof(MultiShapeConf), std::size_t(40)); #endif break; - case 8: EXPECT_EQ(sizeof(MultiShape), std::size_t(64)); break; - case 16: EXPECT_EQ(sizeof(MultiShape), std::size_t(112)); break; + case 8: EXPECT_EQ(sizeof(MultiShapeConf), std::size_t(56)); break; + case 16: EXPECT_EQ(sizeof(MultiShapeConf), std::size_t(96)); break; default: FAIL(); break; } } -TEST(MultiShape, DefaultConstruction) +TEST(MultiShapeConf, DefaultConstruction) { - MultiShape foo{}; + const auto foo = MultiShapeConf{}; const auto defaultMassData = MassData{}; - const auto defaultConf = MultiShape::Conf{}; + const auto defaultConf = MultiShapeConf{}; - EXPECT_EQ(typeid(foo), typeid(MultiShape)); - EXPECT_EQ(foo.GetChildCount(), ChildCounter{0}); - EXPECT_EQ(foo.GetMassData(), defaultMassData); + EXPECT_EQ(typeid(foo), typeid(MultiShapeConf)); + EXPECT_EQ(GetChildCount(foo), ChildCounter{0}); + EXPECT_EQ(GetMassData(foo), defaultMassData); - EXPECT_EQ(foo.GetVertexRadius(), MultiShape::GetDefaultVertexRadius()); - EXPECT_EQ(foo.GetDensity(), defaultConf.density); - EXPECT_EQ(foo.GetFriction(), defaultConf.friction); - EXPECT_EQ(foo.GetRestitution(), defaultConf.restitution); + EXPECT_EQ(GetVertexRadius(foo), MultiShapeConf::GetDefaultVertexRadius()); + EXPECT_EQ(GetDensity(foo), defaultConf.density); + EXPECT_EQ(GetFriction(foo), defaultConf.friction); + EXPECT_EQ(GetRestitution(foo), defaultConf.restitution); } -TEST(MultiShape, GetInvalidChildThrows) +TEST(MultiShapeConf, GetInvalidChildThrows) { - MultiShape foo{}; + const auto foo = MultiShapeConf{}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{0}); - EXPECT_THROW(foo.GetChild(0), InvalidArgument); - EXPECT_THROW(foo.GetChild(1), InvalidArgument); + ASSERT_EQ(GetChildCount(foo), ChildCounter{0}); + EXPECT_THROW(GetChild(foo, 0), InvalidArgument); + EXPECT_THROW(GetChild(foo, 1), InvalidArgument); } -TEST(MultiShape, Accept) +TEST(MultiShapeConf, Accept) { - class Visitor: public IsVisitedShapeVisitor - { - public: - void Visit(const MultiShape&) override + auto visited = false; + auto shapeVisited = false; + + const auto foo = MultiShapeConf{}; + ASSERT_FALSE(visited); + ASSERT_FALSE(shapeVisited); + Accept(Shape(foo), [&](const std::type_info &ti, const void *) { + visited = true; + if (ti == typeid(MultiShapeConf)) { - visited = true; + shapeVisited = true; } - bool visited = false; - }; - - MultiShape foo{}; - Visitor v; - ASSERT_FALSE(v.visited); - ASSERT_FALSE(v.IsVisited()); - foo.Accept(v); - EXPECT_TRUE(v.visited); - EXPECT_FALSE(v.IsVisited()); + }); + EXPECT_TRUE(visited); + EXPECT_TRUE(shapeVisited); } - -TEST(MultiShape, BaseVisitorForDiskShape) +#if 0 +TEST(MultiShapeConf, BaseVisitorForDiskShape) { - const auto shape = MultiShape{}; + const auto shape = MultiShapeConf{}; auto visitor = IsVisitedShapeVisitor{}; ASSERT_FALSE(visitor.IsVisited()); shape.Accept(visitor); EXPECT_TRUE(visitor.IsVisited()); } - -TEST(MultiShape, AddConvexHullWithOnePointSameAsDisk) +#endif +TEST(MultiShapeConf, AddConvexHullWithOnePointSameAsDisk) { const auto defaultMassData = MassData{}; const auto center = Length2(1_m, -4_m); @@ -118,24 +116,24 @@ TEST(MultiShape, AddConvexHullWithOnePointSameAsDisk) pointSet.add(center); ASSERT_EQ(pointSet.size(), std::size_t(1)); - auto conf = MultiShape::Conf{}; + auto conf = MultiShapeConf{}; conf.density = 2.3_kgpm2; conf.vertexRadius = 0.7_m; - auto foo = MultiShape{conf}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{0}); - ASSERT_EQ(foo.GetMassData(), defaultMassData); - ASSERT_EQ(foo.GetVertexRadius(), conf.vertexRadius); - ASSERT_EQ(foo.GetDensity(), conf.density); + auto foo = MultiShapeConf{conf}; + ASSERT_EQ(GetChildCount(foo), ChildCounter{0}); + ASSERT_EQ(GetMassData(foo), defaultMassData); + ASSERT_EQ(GetVertexRadius(foo), conf.vertexRadius); + ASSERT_EQ(GetDensity(foo), conf.density); conf.AddConvexHull(pointSet); - foo = MultiShape{conf}; - EXPECT_EQ(foo.GetChildCount(), ChildCounter{1}); + foo = MultiShapeConf{conf}; + EXPECT_EQ(GetChildCount(foo), ChildCounter{1}); - const auto child = foo.GetChild(0); + const auto child = GetChild(foo, 0); EXPECT_EQ(child.GetVertexCount(), VertexCounter(1)); - const auto massData = foo.GetMassData(); + const auto massData = GetMassData(foo); EXPECT_NE(massData, defaultMassData); EXPECT_EQ(massData.center, center); @@ -143,7 +141,7 @@ TEST(MultiShape, AddConvexHullWithOnePointSameAsDisk) EXPECT_EQ(massData, diskMassData); } -TEST(MultiShape, AddConvexHullWithTwoPointsSameAsEdge) +TEST(MultiShapeConf, AddConvexHullWithTwoPointsSameAsEdge) { const auto defaultMassData = MassData{}; const auto p0 = Length2(1_m, -4_m); @@ -155,24 +153,24 @@ TEST(MultiShape, AddConvexHullWithTwoPointsSameAsEdge) pointSet.add(p1); ASSERT_EQ(pointSet.size(), std::size_t(2)); - auto conf = MultiShape::Conf{}; + auto conf = MultiShapeConf{}; conf.density = 2.3_kgpm2; conf.vertexRadius = 0.7_m; - auto foo = MultiShape{conf}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{0}); - ASSERT_EQ(foo.GetMassData(), defaultMassData); - ASSERT_EQ(foo.GetVertexRadius(), conf.vertexRadius); - ASSERT_EQ(foo.GetDensity(), conf.density); + auto foo = MultiShapeConf{conf}; + ASSERT_EQ(GetChildCount(foo), ChildCounter{0}); + ASSERT_EQ(GetMassData(foo), defaultMassData); + ASSERT_EQ(GetVertexRadius(foo), conf.vertexRadius); + ASSERT_EQ(GetDensity(foo), conf.density); conf.AddConvexHull(pointSet); - foo = MultiShape{conf}; - EXPECT_EQ(foo.GetChildCount(), ChildCounter{1}); + foo = MultiShapeConf{conf}; + EXPECT_EQ(GetChildCount(foo), ChildCounter{1}); - const auto child = foo.GetChild(0); + const auto child = GetChild(foo, 0); EXPECT_EQ(child.GetVertexCount(), VertexCounter(2)); - const auto massData = foo.GetMassData(); + const auto massData = GetMassData(foo); EXPECT_NE(massData, defaultMassData); EXPECT_EQ(massData.center, (p0 + p1) / Real(2)); @@ -186,7 +184,7 @@ TEST(MultiShape, AddConvexHullWithTwoPointsSameAsEdge) EXPECT_EQ(massData.mass, edgeMassData.mass); } -TEST(MultiShape, AddTwoConvexHullWithOnePoint) +TEST(MultiShapeConf, AddTwoConvexHullWithOnePoint) { const auto defaultMassData = MassData{}; const auto p0 = Length2(1_m, -4_m); @@ -195,15 +193,15 @@ TEST(MultiShape, AddTwoConvexHullWithOnePoint) auto pointSet = VertexSet{}; ASSERT_EQ(pointSet.size(), std::size_t(0)); - auto conf = MultiShape::Conf{}; + auto conf = MultiShapeConf{}; conf.density = 2.3_kgpm2; conf.vertexRadius = 0.7_m; - auto foo = MultiShape{conf}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{0}); - ASSERT_EQ(foo.GetMassData(), defaultMassData); - ASSERT_EQ(foo.GetVertexRadius(), conf.vertexRadius); - ASSERT_EQ(foo.GetDensity(), conf.density); + auto foo = MultiShapeConf{conf}; + ASSERT_EQ(GetChildCount(foo), ChildCounter{0}); + ASSERT_EQ(GetMassData(foo), defaultMassData); + ASSERT_EQ(GetVertexRadius(foo), conf.vertexRadius); + ASSERT_EQ(GetDensity(foo), conf.density); pointSet.clear(); ASSERT_EQ(pointSet.size(), std::size_t(0)); @@ -211,10 +209,10 @@ TEST(MultiShape, AddTwoConvexHullWithOnePoint) ASSERT_EQ(pointSet.size(), std::size_t(1)); conf.AddConvexHull(pointSet); - foo = MultiShape{conf}; - EXPECT_EQ(foo.GetChildCount(), ChildCounter{1}); + foo = MultiShapeConf{conf}; + EXPECT_EQ(GetChildCount(foo), ChildCounter{1}); - const auto child0 = foo.GetChild(0); + const auto child0 = GetChild(foo, 0); EXPECT_EQ(child0.GetVertexCount(), VertexCounter(1)); EXPECT_EQ(child0.GetVertex(0), p0); @@ -224,14 +222,14 @@ TEST(MultiShape, AddTwoConvexHullWithOnePoint) ASSERT_EQ(pointSet.size(), std::size_t(1)); conf.AddConvexHull(pointSet); - foo = MultiShape{conf}; - EXPECT_EQ(foo.GetChildCount(), ChildCounter{2}); + foo = MultiShapeConf{conf}; + EXPECT_EQ(GetChildCount(foo), ChildCounter{2}); - const auto child1 = foo.GetChild(1); + const auto child1 = GetChild(foo, 1); EXPECT_EQ(child1.GetVertexCount(), VertexCounter(1)); EXPECT_EQ(child1.GetVertex(0), p1); - const auto massData = foo.GetMassData(); + const auto massData = GetMassData(foo); EXPECT_NE(massData, defaultMassData); EXPECT_EQ(massData.center, (p0 + p1) / Real(2)); @@ -240,3 +238,49 @@ TEST(MultiShape, AddTwoConvexHullWithOnePoint) EXPECT_EQ(massData.mass, Mass{massDataP0.mass} + Mass{massDataP1.mass}); EXPECT_EQ(massData.I, RotInertia{massDataP0.I} + RotInertia{massDataP1.I}); } + +TEST(MultiShapeConf, Equality) +{ + EXPECT_TRUE(MultiShapeConf() == MultiShapeConf()); + + auto pointSet = VertexSet{}; + pointSet.add(Length2{1_m, 2_m}); + + EXPECT_FALSE(MultiShapeConf().AddConvexHull(pointSet) == MultiShapeConf()); + EXPECT_TRUE(MultiShapeConf().AddConvexHull(pointSet) == MultiShapeConf().AddConvexHull(pointSet)); + + EXPECT_FALSE(MultiShapeConf().UseVertexRadius(10_m) == MultiShapeConf()); + EXPECT_TRUE(MultiShapeConf().UseVertexRadius(10_m) == MultiShapeConf().UseVertexRadius(10_m)); + + EXPECT_FALSE(MultiShapeConf().UseDensity(10_kgpm2) == MultiShapeConf()); + EXPECT_TRUE(MultiShapeConf().UseDensity(10_kgpm2) == MultiShapeConf().UseDensity(10_kgpm2)); + + EXPECT_FALSE(MultiShapeConf().UseFriction(Real(10)) == MultiShapeConf()); + EXPECT_TRUE(MultiShapeConf().UseFriction(Real(10)) == MultiShapeConf().UseFriction(Real(10))); + + EXPECT_FALSE(MultiShapeConf().UseRestitution(Real(10)) == MultiShapeConf()); + EXPECT_TRUE(MultiShapeConf().UseRestitution(Real(10)) == MultiShapeConf().UseRestitution(Real(10))); +} + +TEST(MultiShapeConf, Inequality) +{ + EXPECT_FALSE(MultiShapeConf() != MultiShapeConf()); + + auto pointSet = VertexSet{}; + pointSet.add(Length2{1_m, 2_m}); + + EXPECT_TRUE(MultiShapeConf().AddConvexHull(pointSet) != MultiShapeConf()); + EXPECT_FALSE(MultiShapeConf().AddConvexHull(pointSet) != MultiShapeConf().AddConvexHull(pointSet)); + + EXPECT_TRUE(MultiShapeConf().UseVertexRadius(10_m) != MultiShapeConf()); + EXPECT_FALSE(MultiShapeConf().UseVertexRadius(10_m) != MultiShapeConf().UseVertexRadius(10_m)); + + EXPECT_TRUE(MultiShapeConf().UseDensity(10_kgpm2) != MultiShapeConf()); + EXPECT_FALSE(MultiShapeConf().UseDensity(10_kgpm2) != MultiShapeConf().UseDensity(10_kgpm2)); + + EXPECT_TRUE(MultiShapeConf().UseFriction(Real(10)) != MultiShapeConf()); + EXPECT_FALSE(MultiShapeConf().UseFriction(Real(10)) != MultiShapeConf().UseFriction(Real(10))); + + EXPECT_TRUE(MultiShapeConf().UseRestitution(Real(10)) != MultiShapeConf()); + EXPECT_FALSE(MultiShapeConf().UseRestitution(Real(10)) != MultiShapeConf().UseRestitution(Real(10))); +} diff --git a/UnitTests/PolygonShape.cpp b/UnitTests/PolygonShape.cpp index 80913f3eaf..a5062a4f76 100644 --- a/UnitTests/PolygonShape.cpp +++ b/UnitTests/PolygonShape.cpp @@ -19,87 +19,75 @@ */ #include "gtest/gtest.h" -#include -#include +#include +#include using namespace playrho; -TEST(PolygonShape, ByteSize) +TEST(PolygonShapeConf, ByteSize) { switch (sizeof(Real)) { case 4: #if defined(_WIN64) #if !defined(NDEBUG) - EXPECT_EQ(sizeof(PolygonShape), std::size_t(96)); + EXPECT_EQ(sizeof(PolygonShapeConf), std::size_t(96)); #else - EXPECT_EQ(sizeof(PolygonShape), std::size_t(80)); + EXPECT_EQ(sizeof(PolygonShapeConf), std::size_t(72)); #endif #elif defined(_WIN32) #if !defined(NDEBUG) - EXPECT_EQ(sizeof(PolygonShape), std::size_t(60)); + EXPECT_EQ(sizeof(PolygonShapeConf), std::size_t(60)); #else - EXPECT_EQ(sizeof(PolygonShape), std::size_t(52)); + EXPECT_EQ(sizeof(PolygonShapeConf), std::size_t(48)); #endif #else - EXPECT_EQ(sizeof(PolygonShape), std::size_t(80)); + EXPECT_EQ(sizeof(PolygonShapeConf), std::size_t(72)); #endif break; - case 8: EXPECT_EQ(sizeof(PolygonShape), std::size_t(104)); break; - case 16: EXPECT_EQ(sizeof(PolygonShape), std::size_t(160)); break; + case 8: EXPECT_EQ(sizeof(PolygonShapeConf), std::size_t(96)); break; + case 16: EXPECT_EQ(sizeof(PolygonShapeConf), std::size_t(144)); break; default: FAIL(); break; } } -TEST(PolygonShape, DefaultConstruction) +TEST(PolygonShapeConf, DefaultConstruction) { - PolygonShape shape; + const auto shape = PolygonShapeConf{}; EXPECT_EQ(shape.GetVertexCount(), 0); - EXPECT_EQ(shape.GetChildCount(), ChildCounter(1)); - EXPECT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + EXPECT_EQ(GetChildCount(shape), ChildCounter(1)); + EXPECT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); EXPECT_FALSE(IsValid(shape.GetCentroid())); } -TEST(PolygonShape, GetInvalidChildThrows) +TEST(PolygonShapeConf, GetInvalidChildThrows) { - PolygonShape foo{}; + const auto foo = PolygonShapeConf{}; - ASSERT_EQ(foo.GetChildCount(), ChildCounter{1}); - EXPECT_NO_THROW(foo.GetChild(0)); - EXPECT_THROW(foo.GetChild(1), InvalidArgument); + ASSERT_EQ(GetChildCount(foo), ChildCounter{1}); + EXPECT_NO_THROW(GetChild(foo, 0)); + EXPECT_THROW(GetChild(foo, 1), InvalidArgument); } -TEST(PolygonShape, Accept) +TEST(PolygonShapeConf, Accept) { - class Visitor: public IsVisitedShapeVisitor - { - public: - void Visit(const PolygonShape&) override + auto visited = false; + auto shapeVisited = false; + const auto foo = PolygonShapeConf{}; + ASSERT_FALSE(visited); + ASSERT_FALSE(shapeVisited); + Accept(Shape(foo), [&](const std::type_info& ti, const void*) { + visited = true; + if (ti == typeid(PolygonShapeConf)) { - visited = true; + shapeVisited = true; } - bool visited = false; - }; - - PolygonShape foo{}; - Visitor v; - ASSERT_FALSE(v.visited); - ASSERT_FALSE(v.IsVisited()); - foo.Accept(v); - EXPECT_TRUE(v.visited); - EXPECT_FALSE(v.IsVisited()); + }); + EXPECT_TRUE(visited); + EXPECT_TRUE(shapeVisited); } -TEST(PolygonShape, BaseVisitorForDiskShape) -{ - const auto shape = PolygonShape{}; - auto visitor = IsVisitedShapeVisitor{}; - ASSERT_FALSE(visitor.IsVisited()); - shape.Accept(visitor); - EXPECT_TRUE(visitor.IsVisited()); -} - -TEST(PolygonShape, FindLowestRightMostVertex) +TEST(PolygonShapeConf, FindLowestRightMostVertex) { Length2 vertices[4]; @@ -113,15 +101,15 @@ TEST(PolygonShape, FindLowestRightMostVertex) EXPECT_EQ(index, std::size_t(2)); } -TEST(PolygonShape, BoxConstruction) +TEST(PolygonShapeConf, BoxConstruction) { const auto hx = 2.3_m; const auto hy = 54.1_m; - const auto shape = PolygonShape{hx, hy}; + const auto shape = PolygonShapeConf{hx, hy}; EXPECT_EQ(shape.GetCentroid(), (Length2{})); - EXPECT_EQ(shape.GetChildCount(), ChildCounter(1)); - EXPECT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + EXPECT_EQ(GetChildCount(shape), ChildCounter(1)); + EXPECT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(shape.GetVertexCount(), VertexCounter(4)); @@ -140,15 +128,15 @@ TEST(PolygonShape, BoxConstruction) EXPECT_TRUE(Validate(shape)); } -TEST(PolygonShape, Copy) +TEST(PolygonShapeConf, Copy) { const auto hx = 2.3_m; const auto hy = 54.1_m; - auto shape = PolygonShape{hx, hy}; + auto shape = PolygonShapeConf{hx, hy}; ASSERT_EQ(shape.GetCentroid(), (Length2{})); - ASSERT_EQ(shape.GetChildCount(), ChildCounter(1)); - ASSERT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + ASSERT_EQ(GetChildCount(shape), ChildCounter(1)); + ASSERT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(shape.GetVertexCount(), VertexCounter(4)); // vertices go counter-clockwise from lowest right-most (and normals follow their edges)... @@ -166,8 +154,8 @@ TEST(PolygonShape, Copy) EXPECT_EQ(typeid(copy), typeid(shape)); EXPECT_EQ(copy.GetCentroid(), (Length2{})); - EXPECT_EQ(copy.GetChildCount(), ChildCounter(1)); - EXPECT_EQ(GetVertexRadius(copy), PolygonShape::GetDefaultVertexRadius()); + EXPECT_EQ(GetChildCount(copy), ChildCounter(1)); + EXPECT_EQ(GetVertexRadius(copy), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(copy.GetVertexCount(), VertexCounter(4)); @@ -184,15 +172,15 @@ TEST(PolygonShape, Copy) EXPECT_EQ(copy.GetNormal(3) * Real{1}, Vec2(0, -1)); } -TEST(PolygonShape, Translate) +TEST(PolygonShapeConf, Translate) { const auto hx = 2.3_m; const auto hy = 54.1_m; - auto shape = PolygonShape{hx, hy}; + auto shape = PolygonShapeConf{hx, hy}; ASSERT_EQ(shape.GetCentroid(), (Length2{})); - ASSERT_EQ(shape.GetChildCount(), ChildCounter(1)); - ASSERT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + ASSERT_EQ(GetChildCount(shape), ChildCounter(1)); + ASSERT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(shape.GetVertexCount(), VertexCounter(4)); // vertices go counter-clockwise from lowest right-most (and normals follow their edges)... @@ -207,16 +195,16 @@ TEST(PolygonShape, Translate) ASSERT_EQ(shape.GetNormal(3) * Real{1}, Vec2(0, -1)); const auto new_ctr = Length2{-3_m, 67_m}; - shape = PolygonShape{ - PolygonShape::Conf{}.SetAsBox(hx, hy).Transform(Transformation{new_ctr, UnitVec2::GetRight()}) + shape = PolygonShapeConf{ + PolygonShapeConf{}.SetAsBox(hx, hy).Transform(Transformation{new_ctr, UnitVec2::GetRight()}) }; EXPECT_NEAR(static_cast(Real{GetX(shape.GetCentroid())/Meter}), static_cast(Real{GetX(new_ctr)/Meter}), 0.001); EXPECT_NEAR(static_cast(Real{GetY(shape.GetCentroid())/Meter}), static_cast(Real{GetY(new_ctr)/Meter}), 0.001); - EXPECT_EQ(shape.GetChildCount(), ChildCounter(1)); - EXPECT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + EXPECT_EQ(GetChildCount(shape), ChildCounter(1)); + EXPECT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(shape.GetVertexCount(), VertexCounter(4)); @@ -231,14 +219,14 @@ TEST(PolygonShape, Translate) EXPECT_EQ(shape.GetNormal(3) * Real{1}, Vec2(0, -1)); } -TEST(PolygonShape, SetAsBox) +TEST(PolygonShapeConf, SetAsBox) { const auto hx = 2.3_m; const auto hy = 54.1_m; - const auto shape = PolygonShape{hx, hy}; + const auto shape = PolygonShapeConf{hx, hy}; EXPECT_EQ(shape.GetCentroid(), (Length2{})); - EXPECT_EQ(shape.GetChildCount(), ChildCounter(1)); - EXPECT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + EXPECT_EQ(GetChildCount(shape), ChildCounter(1)); + EXPECT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(shape.GetVertexCount(), VertexCounter(4)); @@ -255,14 +243,14 @@ TEST(PolygonShape, SetAsBox) EXPECT_EQ(shape.GetNormal(3) * Real{1}, Vec2(0, -1)); } -TEST(PolygonShape, SetAsZeroCenteredRotatedBox) +TEST(PolygonShapeConf, SetAsZeroCenteredRotatedBox) { const auto hx = 2.3_m; const auto hy = 54.1_m; - const auto shape = PolygonShape{PolygonShape::Conf{}.SetAsBox(hx, hy, Length2{}, 0_deg)}; + const auto shape = PolygonShapeConf{PolygonShapeConf{}.SetAsBox(hx, hy, Length2{}, 0_deg)}; EXPECT_EQ(shape.GetCentroid(), (Length2{})); - EXPECT_EQ(shape.GetChildCount(), ChildCounter(1)); - EXPECT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + EXPECT_EQ(GetChildCount(shape), ChildCounter(1)); + EXPECT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(shape.GetVertexCount(), VertexCounter(4)); @@ -279,19 +267,19 @@ TEST(PolygonShape, SetAsZeroCenteredRotatedBox) EXPECT_EQ(shape.GetNormal(3) * Real{1}, Vec2(0, -1)); } -TEST(PolygonShape, SetAsCenteredBox) +TEST(PolygonShapeConf, SetAsCenteredBox) { const auto hx = 2.3_m; const auto hy = 54.1_m; const auto x_off = 10.2_m; const auto y_off = -5_m; - const auto shape = PolygonShape{PolygonShape::Conf{}.SetAsBox(hx, hy, Length2(x_off, y_off), 0_deg)}; + const auto shape = PolygonShapeConf{PolygonShapeConf{}.SetAsBox(hx, hy, Length2(x_off, y_off), 0_deg)}; EXPECT_NEAR(static_cast(Real{GetX(shape.GetCentroid())/Meter}), static_cast(Real{x_off/Meter}), 0.001); EXPECT_NEAR(static_cast(Real{GetY(shape.GetCentroid())/Meter}), static_cast(Real{y_off/Meter}), 0.001); - EXPECT_EQ(shape.GetChildCount(), ChildCounter(1)); - EXPECT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + EXPECT_EQ(GetChildCount(shape), ChildCounter(1)); + EXPECT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(shape.GetVertexCount(), VertexCounter(4)); @@ -308,42 +296,42 @@ TEST(PolygonShape, SetAsCenteredBox) EXPECT_EQ(shape.GetNormal(3) * Real{1}, Vec2(0, -1)); } -TEST(PolygonShape, SetAsBoxAngledDegrees90) +TEST(PolygonShapeConf, SetAsBoxAngledDegrees90) { const auto hx = Real(2.3); const auto hy = Real(54.1); const auto angle = 90.01_deg; - const auto shape = PolygonShape{PolygonShape::Conf{}.SetAsBox(hx * Meter, hy * Meter, Length2{}, angle)}; + const auto shape = PolygonShapeConf{PolygonShapeConf{}.SetAsBox(hx * Meter, hy * Meter, Length2{}, angle)}; EXPECT_NEAR(static_cast(Real{GetX(shape.GetCentroid())/Meter}), 0.0, 0.01); EXPECT_NEAR(static_cast(Real{GetY(shape.GetCentroid())/Meter}), 0.0, 0.01); - EXPECT_EQ(shape.GetChildCount(), ChildCounter(1)); - EXPECT_EQ(GetVertexRadius(shape), PolygonShape::GetDefaultVertexRadius()); + EXPECT_EQ(GetChildCount(shape), ChildCounter(1)); + EXPECT_EQ(GetVertexRadius(shape), PolygonShapeConf::GetDefaultVertexRadius()); ASSERT_EQ(shape.GetVertexCount(), VertexCounter(4)); // vertices go counter-clockwise (and normals follow their edges)... + EXPECT_NEAR(double(Real{GetX(shape.GetVertex(3)) / Meter}), double( hy), 0.02); // right + EXPECT_NEAR(double(Real{GetY(shape.GetVertex(3)) / Meter}), double(-hx), 0.02); // bottom EXPECT_NEAR(double(Real{GetX(shape.GetVertex(0)) / Meter}), double( hy), 0.02); // right - EXPECT_NEAR(double(Real{GetY(shape.GetVertex(0)) / Meter}), double(-hx), 0.02); // bottom - EXPECT_NEAR(double(Real{GetX(shape.GetVertex(1)) / Meter}), double( hy), 0.02); // right + EXPECT_NEAR(double(Real{GetY(shape.GetVertex(0)) / Meter}), double( hx), 0.02); // top + EXPECT_NEAR(double(Real{GetX(shape.GetVertex(1)) / Meter}), double(-hy), 0.02); // left EXPECT_NEAR(double(Real{GetY(shape.GetVertex(1)) / Meter}), double( hx), 0.02); // top EXPECT_NEAR(double(Real{GetX(shape.GetVertex(2)) / Meter}), double(-hy), 0.02); // left - EXPECT_NEAR(double(Real{GetY(shape.GetVertex(2)) / Meter}), double( hx), 0.02); // top - EXPECT_NEAR(double(Real{GetX(shape.GetVertex(3)) / Meter}), double(-hy), 0.02); // left - EXPECT_NEAR(double(Real{GetY(shape.GetVertex(3)) / Meter}), double(-hx), 0.02); // bottom - - EXPECT_NEAR(double(shape.GetNormal(0).GetX()), +1.0, 0.01); - EXPECT_NEAR(double(shape.GetNormal(0).GetY()), 0.0, 0.01); - EXPECT_NEAR(double(shape.GetNormal(1).GetX()), 0.0, 0.01); - EXPECT_NEAR(double(shape.GetNormal(1).GetY()), +1.0, 0.01); - EXPECT_NEAR(double(shape.GetNormal(2).GetX()), -1.0, 0.01); - EXPECT_NEAR(double(shape.GetNormal(2).GetY()), 0.0, 0.01); - EXPECT_NEAR(double(shape.GetNormal(3).GetX()), 0.0, 0.01); - EXPECT_NEAR(double(shape.GetNormal(3).GetY()), -1.0, 0.01); + EXPECT_NEAR(double(Real{GetY(shape.GetVertex(2)) / Meter}), double(-hx), 0.02); // bottom + + EXPECT_NEAR(double(shape.GetNormal(3).GetX()), +1.0, 0.01); + EXPECT_NEAR(double(shape.GetNormal(3).GetY()), 0.0, 0.01); + EXPECT_NEAR(double(shape.GetNormal(0).GetX()), 0.0, 0.01); + EXPECT_NEAR(double(shape.GetNormal(0).GetY()), +1.0, 0.01); + EXPECT_NEAR(double(shape.GetNormal(1).GetX()), -1.0, 0.01); + EXPECT_NEAR(double(shape.GetNormal(1).GetY()), 0.0, 0.01); + EXPECT_NEAR(double(shape.GetNormal(2).GetX()), 0.0, 0.01); + EXPECT_NEAR(double(shape.GetNormal(2).GetY()), -1.0, 0.01); } -TEST(PolygonShape, SetPoints) +TEST(PolygonShapeConf, SetPoints) { const auto points = Vector{ Vec2{-1, +2} * Meter, @@ -352,7 +340,7 @@ TEST(PolygonShape, SetPoints) Vec2{-1, -2} * Meter, Vec2{-4, -1} * Meter }; - const auto shape = PolygonShape{PolygonShape::Conf{}.Set(points)}; + const auto shape = PolygonShapeConf{PolygonShapeConf{}.Set(points)}; ASSERT_EQ(shape.GetVertexCount(), VertexCounter(5)); @@ -367,14 +355,14 @@ TEST(PolygonShape, SetPoints) EXPECT_TRUE(Validate(shape)); } -TEST(PolygonShape, CanSetTwoPoints) +TEST(PolygonShapeConf, CanSetTwoPoints) { const auto points = Vector{ Vec2{-1, +0} * Meter, Vec2{+1, +0} * Meter }; const auto vertexRadius = 2_m; - const auto shape = PolygonShape{PolygonShape::Conf{}.SetVertexRadius(vertexRadius).Set(points)}; + const auto shape = PolygonShapeConf{PolygonShapeConf{}.UseVertexRadius(vertexRadius).Set(points)}; EXPECT_EQ(shape.GetVertexCount(), static_cast(points.size())); EXPECT_EQ(shape.GetVertex(0), points[1]); EXPECT_EQ(shape.GetVertex(1), points[0]); @@ -387,19 +375,59 @@ TEST(PolygonShape, CanSetTwoPoints) EXPECT_NEAR(static_cast(GetY(GetVec2(shape.GetNormal(1)))), -1.0, 1.0/100000.0); EXPECT_EQ(shape.GetCentroid(), Average(Span(points.data(), points.size()))); - EXPECT_EQ(shape.GetVertexRadius(), vertexRadius); + EXPECT_EQ(GetVertexRadius(shape), vertexRadius); EXPECT_TRUE(Validate(shape)); } -TEST(PolygonShape, CanSetOnePoint) +TEST(PolygonShapeConf, CanSetOnePoint) { const auto points = Vector{Length2{}}; const auto vertexRadius = 2_m; - const auto shape = PolygonShape{PolygonShape::Conf{}.SetVertexRadius(vertexRadius).Set(points)}; + const auto shape = PolygonShapeConf{PolygonShapeConf{}.UseVertexRadius(vertexRadius).Set(points)}; EXPECT_EQ(shape.GetVertexCount(), static_cast(points.size())); EXPECT_EQ(shape.GetVertex(0), points[0]); EXPECT_FALSE(IsValid(shape.GetNormal(0))); EXPECT_EQ(shape.GetCentroid(), points[0]); - EXPECT_EQ(shape.GetVertexRadius(), vertexRadius); + EXPECT_EQ(GetVertexRadius(shape), vertexRadius); +} + +TEST(PolygonShapeConf, Equality) +{ + EXPECT_TRUE(PolygonShapeConf() == PolygonShapeConf()); + + EXPECT_FALSE(PolygonShapeConf().SetAsBox(1_m, 2_m) == PolygonShapeConf()); + EXPECT_TRUE(PolygonShapeConf().SetAsBox(1_m, 2_m) == PolygonShapeConf().SetAsBox(1_m, 2_m)); + + EXPECT_FALSE(PolygonShapeConf().UseVertexRadius(10_m) == PolygonShapeConf()); + EXPECT_TRUE(PolygonShapeConf().UseVertexRadius(10_m) == PolygonShapeConf().UseVertexRadius(10_m)); + + EXPECT_FALSE(PolygonShapeConf().UseDensity(10_kgpm2) == PolygonShapeConf()); + EXPECT_TRUE(PolygonShapeConf().UseDensity(10_kgpm2) == PolygonShapeConf().UseDensity(10_kgpm2)); + + EXPECT_FALSE(PolygonShapeConf().UseFriction(Real(10)) == PolygonShapeConf()); + EXPECT_TRUE(PolygonShapeConf().UseFriction(Real(10)) == PolygonShapeConf().UseFriction(Real(10))); + + EXPECT_FALSE(PolygonShapeConf().UseRestitution(Real(10)) == PolygonShapeConf()); + EXPECT_TRUE(PolygonShapeConf().UseRestitution(Real(10)) == PolygonShapeConf().UseRestitution(Real(10))); +} + +TEST(PolygonShapeConf, Inequality) +{ + EXPECT_FALSE(PolygonShapeConf() != PolygonShapeConf()); + + EXPECT_TRUE(PolygonShapeConf().SetAsBox(1_m, 2_m) != PolygonShapeConf()); + EXPECT_FALSE(PolygonShapeConf().SetAsBox(1_m, 2_m) != PolygonShapeConf().SetAsBox(1_m, 2_m)); + + EXPECT_TRUE(PolygonShapeConf().UseVertexRadius(10_m) != PolygonShapeConf()); + EXPECT_FALSE(PolygonShapeConf().UseVertexRadius(10_m) != PolygonShapeConf().UseVertexRadius(10_m)); + + EXPECT_TRUE(PolygonShapeConf().UseDensity(10_kgpm2) != PolygonShapeConf()); + EXPECT_FALSE(PolygonShapeConf().UseDensity(10_kgpm2) != PolygonShapeConf().UseDensity(10_kgpm2)); + + EXPECT_TRUE(PolygonShapeConf().UseFriction(Real(10)) != PolygonShapeConf()); + EXPECT_FALSE(PolygonShapeConf().UseFriction(Real(10)) != PolygonShapeConf().UseFriction(Real(10))); + + EXPECT_TRUE(PolygonShapeConf().UseRestitution(Real(10)) != PolygonShapeConf()); + EXPECT_FALSE(PolygonShapeConf().UseRestitution(Real(10)) != PolygonShapeConf().UseRestitution(Real(10))); } diff --git a/UnitTests/PositionSolverManifold.cpp b/UnitTests/PositionSolverManifold.cpp index d9c212e1f3..57cf139667 100644 --- a/UnitTests/PositionSolverManifold.cpp +++ b/UnitTests/PositionSolverManifold.cpp @@ -18,7 +18,7 @@ #include "gtest/gtest.h" #include -#include +#include #include #include @@ -51,7 +51,7 @@ TEST(PositionSolverManifold, InitializingConstructor) TEST(PositionSolverManifold, GetPSM) { // wide rectangle - const auto shape0 = PolygonShape(3_m, 1.5_m); + const auto shape0 = PolygonShapeConf(3_m, 1.5_m); ASSERT_EQ(GetX(shape0.GetVertex(0)), +3.0_m); // right ASSERT_EQ(GetY(shape0.GetVertex(0)), -1.5_m); // bottom ASSERT_EQ(GetX(shape0.GetVertex(1)), +3.0_m); // right @@ -62,7 +62,7 @@ TEST(PositionSolverManifold, GetPSM) ASSERT_EQ(GetY(shape0.GetVertex(3)), -1.5_m); // bottom // square - const auto shape1 = PolygonShape(2_m, 2_m); + const auto shape1 = PolygonShapeConf(2_m, 2_m); ASSERT_EQ(GetX(shape1.GetVertex(0)), +2_m); // right ASSERT_EQ(GetY(shape1.GetVertex(0)), -2_m); // bottom ASSERT_EQ(GetX(shape1.GetVertex(1)), +2_m); // right @@ -76,7 +76,7 @@ TEST(PositionSolverManifold, GetPSM) const auto xfm1 = Transformation{Length2{+2_m, 0_m}, UnitVec2::GetRight()}; // right // put wide rectangle on left, square on right - const auto manifold = CollideShapes(shape0.GetChild(0), xfm0, shape1.GetChild(0), xfm1); + const auto manifold = CollideShapes(GetChild(shape0, 0), xfm0, GetChild(shape1, 0), xfm1); ASSERT_EQ(manifold.GetType(), Manifold::e_faceA); diff --git a/UnitTests/PrismaticJoint.cpp b/UnitTests/PrismaticJoint.cpp index 363158a462..0f38977092 100644 --- a/UnitTests/PrismaticJoint.cpp +++ b/UnitTests/PrismaticJoint.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include using namespace playrho; @@ -216,7 +216,7 @@ TEST(PrismaticJoint, GetLinearVelocity) TEST(PrismaticJoint, WithDynamicCirclesAndLimitEnabled) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; diff --git a/UnitTests/RevoluteJoint.cpp b/UnitTests/RevoluteJoint.cpp index 91c303f294..220820b428 100644 --- a/UnitTests/RevoluteJoint.cpp +++ b/UnitTests/RevoluteJoint.cpp @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include using namespace playrho; @@ -204,7 +204,7 @@ TEST(RevoluteJoint, MaxMotorTorque) TEST(RevoluteJoint, MovesDynamicCircles) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); World world; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; @@ -232,9 +232,8 @@ TEST(RevoluteJoint, MovesDynamicCircles) TEST(RevoluteJoint, LimitEnabledDynamicCircles) { - const auto circle = std::make_shared(DiskShape::Conf{} - .UseVertexRadius(0.2_m) - .UseDensity(1_kgpm2)); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m).UseDensity(1_kgpm2); + World world; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; @@ -313,11 +312,10 @@ TEST(RevoluteJoint, DynamicJoinedToStaticStaysPut) const auto b1 = world.CreateBody(BodyDef{}.UseType(BodyType::Static).UseLocation(p1)); const auto b2 = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic).UseLocation(p2)); - const auto shape1 = std::make_shared(PolygonShape::Conf{}.SetAsBox(1_m, 1_m)); + const auto shape1 = PolygonShapeConf{}.SetAsBox(1_m, 1_m); b1->CreateFixture(shape1); - const auto shape2 = std::make_shared( - PolygonShape::Conf{}.SetAsBox(0.5_m, 0.5_m).SetDensity(1_kgpm2)); + const auto shape2 = PolygonShapeConf{}.SetAsBox(0.5_m, 0.5_m).UseDensity(1_kgpm2); b2->CreateFixture(shape2); auto jd = RevoluteJointDef{b1, b2, Length2{}}; diff --git a/UnitTests/RopeJoint.cpp b/UnitTests/RopeJoint.cpp index 8efb06fe25..d8e9b8a780 100644 --- a/UnitTests/RopeJoint.cpp +++ b/UnitTests/RopeJoint.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include using namespace playrho; @@ -138,7 +138,7 @@ TEST(RopeJoint, GetRopeJointDef) TEST(RopeJoint, WithDynamicCircles) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; diff --git a/UnitTests/SeparationFinder.cpp b/UnitTests/SeparationFinder.cpp index 0a8ffb3435..411864872e 100644 --- a/UnitTests/SeparationFinder.cpp +++ b/UnitTests/SeparationFinder.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include using namespace playrho; @@ -45,8 +45,8 @@ TEST(SeparationFinder, ByteSize) TEST(SeparationFinder, BehavesAsExpected) { - const auto shape = PolygonShape{0.5_m, 0.5_m}; - const auto distproxy = shape.GetChild(0); + const auto shape = PolygonShapeConf{0.5_m, 0.5_m}; + const auto distproxy = GetChild(shape, 0); const auto x = Real(100); const auto sweepA = Sweep{ diff --git a/UnitTests/Shape.cpp b/UnitTests/Shape.cpp index a92b80ae77..ad40b2cfc7 100644 --- a/UnitTests/Shape.cpp +++ b/UnitTests/Shape.cpp @@ -18,8 +18,9 @@ #include "gtest/gtest.h" #include -#include -#include +#include +#include +#include #include #include #include @@ -32,22 +33,22 @@ TEST(Shape, ByteSize) { case 4: #if defined(_WIN32) && !defined(_WIN64) - EXPECT_EQ(sizeof(Shape), std::size_t(20)); + EXPECT_EQ(sizeof(Shape), std::size_t(8)); #else - EXPECT_EQ(sizeof(Shape), std::size_t(24)); + EXPECT_EQ(sizeof(Shape), std::size_t(16)); #endif break; - case 8: EXPECT_EQ(sizeof(Shape), std::size_t(40)); break; - case 16: EXPECT_EQ(sizeof(Shape), std::size_t(80)); break; + case 8: EXPECT_EQ(sizeof(Shape), std::size_t(16)); break; + case 16: EXPECT_EQ(sizeof(Shape), std::size_t(16)); break; default: FAIL(); break; } } TEST(Shape, TestOverlapSlowerThanCollideShapesForCircles) { - const auto shape = DiskShape{2_m}; + const auto shape = DiskShapeConf{2_m}; const auto xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto child = shape.GetChild(0); + const auto child = GetChild(shape, 0); const auto maxloops = 1000000u; @@ -90,12 +91,11 @@ TEST(Shape, TestOverlapSlowerThanCollideShapesForCircles) } } - TEST(Shape, TestOverlapFasterThanCollideShapesForPolygons) { - const auto shape = PolygonShape{2_m, 2_m}; + const auto shape = PolygonShapeConf{2_m, 2_m}; const auto xfm = Transformation{Length2{}, UnitVec2::GetRight()}; - const auto child = shape.GetChild(0); + const auto child = GetChild(shape, 0); const auto maxloops = 1000000u; @@ -137,3 +137,25 @@ TEST(Shape, TestOverlapFasterThanCollideShapesForPolygons) EXPECT_LT(elapsed_test_overlap.count(), elapsed_collide_shapes.count()); } } + +TEST(Shape, Equality) +{ + EXPECT_TRUE(Shape(EdgeShapeConf()) == Shape(EdgeShapeConf())); + + const auto shapeA = Shape(DiskShapeConf{}.UseRadius(100_m)); + const auto shapeB = Shape(DiskShapeConf{}.UseRadius(100_m)); + EXPECT_TRUE(shapeA == shapeB); + + EXPECT_FALSE(Shape(DiskShapeConf()) == Shape(EdgeShapeConf())); +} + +TEST(Shape, Inequality) +{ + EXPECT_FALSE(Shape(EdgeShapeConf()) != Shape(EdgeShapeConf())); + + const auto shapeA = Shape(DiskShapeConf{}.UseRadius(100_m)); + const auto shapeB = Shape(DiskShapeConf{}.UseRadius(100_m)); + EXPECT_FALSE(shapeA != shapeB); + + EXPECT_TRUE(Shape(DiskShapeConf()) != Shape(EdgeShapeConf())); +} diff --git a/UnitTests/TimeOfImpact.cpp b/UnitTests/TimeOfImpact.cpp index 0961eb3f6f..f3aec9d2f3 100644 --- a/UnitTests/TimeOfImpact.cpp +++ b/UnitTests/TimeOfImpact.cpp @@ -19,7 +19,7 @@ #include "gtest/gtest.h" #include #include -#include +#include #include using namespace playrho; @@ -736,16 +736,16 @@ TEST(TimeOfImpact, ForNonCollidingShapesFails) { // The data for shapes and sweeps comes from PlayRho/Testbed/Tests/TimeOfImpact.hpp - const auto shapeA = PolygonShape{ - PolygonShape::Conf{}.SetVertexRadius(Real{0.0001f * 2} * Meter).SetAsBox(25.0_m, 5.0_m) + const auto shapeA = PolygonShapeConf{ + PolygonShapeConf{}.UseVertexRadius(Real{0.0001f * 2} * Meter).SetAsBox(25.0_m, 5.0_m) }; - const auto shapeB = PolygonShape{ - PolygonShape::Conf{}.SetVertexRadius(Real{0.0001f * 2} * Meter).SetAsBox(2.5_m, 2.5_m) + const auto shapeB = PolygonShapeConf{ + PolygonShapeConf{}.UseVertexRadius(Real{0.0001f * 2} * Meter).SetAsBox(2.5_m, 2.5_m) }; - const auto dpA = shapeA.GetChild(0); - const auto dpB = shapeB.GetChild(0); + const auto dpA = GetChild(shapeA, 0); + const auto dpB = GetChild(shapeB, 0); const auto sweepA = Sweep{ Position{Length2{-11_m, 10_m}, 2.95000005_rad}, @@ -837,10 +837,10 @@ TEST(TimeOfImpact, ToleranceReachedWithT1Of1) 0.000199999995_m, 4, vertices, normals }; - auto shapeB = PolygonShape{ - PolygonShape::Conf{}.SetVertexRadius(Real{0.0001f * 2} * Meter).SetAsBox(0.5_m, 0.5_m) + auto shapeB = PolygonShapeConf{ + PolygonShapeConf{}.UseVertexRadius(Real{0.0001f * 2} * Meter).SetAsBox(0.5_m, 0.5_m) }; - const auto dpB = shapeB.GetChild(0); + const auto dpB = GetChild(shapeB, 0); const auto conf = ToiConf{} .UseMaxToiIters(200) diff --git a/UnitTests/WeldJoint.cpp b/UnitTests/WeldJoint.cpp index 60a50e3aa2..10a1ede13b 100644 --- a/UnitTests/WeldJoint.cpp +++ b/UnitTests/WeldJoint.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include using namespace playrho; @@ -142,7 +142,7 @@ TEST(WeldJoint, GetWeldJointDef) TEST(WeldJoint, WithDynamicCircles) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; @@ -164,7 +164,7 @@ TEST(WeldJoint, WithDynamicCircles) TEST(WeldJoint, WithDynamicCircles2) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; diff --git a/UnitTests/WheelJoint.cpp b/UnitTests/WheelJoint.cpp index ccb8d187fa..b87a897c91 100644 --- a/UnitTests/WheelJoint.cpp +++ b/UnitTests/WheelJoint.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include using namespace playrho; @@ -256,7 +256,7 @@ TEST(WheelJoint, GetWheelJointDef) TEST(WheelJoint, WithDynamicCircles) { - const auto circle = std::make_shared(0.2_m); + const auto circle = DiskShapeConf{}.UseRadius(0.2_m); auto world = World{WorldDef{}.UseGravity(LinearAcceleration2{})}; const auto p1 = Length2{-1_m, 0_m}; const auto p2 = Length2{+1_m, 0_m}; diff --git a/UnitTests/World.cpp b/UnitTests/World.cpp index 0af7ba5b33..03f7bb2eae 100644 --- a/UnitTests/World.cpp +++ b/UnitTests/World.cpp @@ -25,9 +25,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -240,9 +240,7 @@ TEST(World, CopyConstruction) EXPECT_EQ(world.GetTree().GetMaxBalance(), copy.GetTree().GetMaxBalance()); } - const auto shape = std::make_shared(DiskShape::Conf{} - .UseDensity(1_kgpm2) - .UseVertexRadius(1_m)); + const auto shape = Shape{DiskShapeConf{}.UseDensity(1_kgpm2).UseRadius(1_m)}; const auto b1 = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic)); b1->CreateFixture(shape); const auto b2 = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic)); @@ -317,9 +315,7 @@ TEST(World, CopyAssignment) EXPECT_EQ(world.GetTree().GetMaxBalance(), copy.GetTree().GetMaxBalance()); } - const auto shape = std::make_shared(DiskShape::Conf{} - .UseDensity(1_kgpm2) - .UseVertexRadius(1_m)); + const auto shape = Shape{DiskShapeConf{}.UseDensity(1_kgpm2).UseRadius(1_m)}; const auto b1 = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic)); b1->CreateFixture(shape); const auto b2 = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic)); @@ -421,12 +417,9 @@ TEST(World, QueryAABB) const auto v1 = Length2{-1_m, 0_m}; const auto v2 = Length2{+1_m, 0_m}; - auto conf = EdgeShape::Conf{}; - conf.vertexRadius = 1_m; - conf.density = 1_kgpm2; - const auto shape = std::make_shared(v1, v2, conf); - ASSERT_EQ(shape->GetChildCount(), ChildCounter(1)); - const auto fixture = body->CreateFixture(shape); + const auto conf = EdgeShapeConf{}.UseVertexRadius(1_m).UseDensity(1_kgpm2).Set(v1, v2); + ASSERT_EQ(GetChildCount(conf), ChildCounter(1)); + const auto fixture = body->CreateFixture(conf); ASSERT_NE(fixture, nullptr); auto stepConf = StepConf{}; @@ -473,11 +466,9 @@ TEST(World, RayCast) const auto v1 = Length2{-1_m, 0_m}; const auto v2 = Length2{+1_m, 0_m}; - auto conf = EdgeShape::Conf{}; - conf.vertexRadius = 1_m; - conf.density = 1_kgpm2; - const auto shape = std::make_shared(v1, v2, conf); - ASSERT_EQ(shape->GetChildCount(), ChildCounter(1)); + const auto conf = EdgeShapeConf{}.UseVertexRadius(1_m).UseDensity(1_kgpm2).Set(v1, v2); + const auto shape = Shape{conf}; + ASSERT_EQ(GetChildCount(shape), ChildCounter(1)); const auto fixture = body->CreateFixture(shape); ASSERT_NE(fixture, nullptr); @@ -523,10 +514,8 @@ TEST(World, ClearForcesFreeFunction) const auto v1 = Length2{-1_m, 0_m}; const auto v2 = Length2{+1_m, 0_m}; - auto conf = EdgeShape::Conf{}; - conf.vertexRadius = 1_m; - conf.density = 1_kgpm2; - const auto shape = std::make_shared(v1, v2, conf); + const auto conf = EdgeShapeConf{}.UseVertexRadius(1_m).UseDensity(1_kgpm2).Set(v1, v2); + const auto shape = Shape{conf}; const auto fixture = body->CreateFixture(shape); ASSERT_NE(fixture, nullptr); @@ -588,13 +577,11 @@ TEST(World, GetShapeCountFreeFunction) const auto body = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic)); ASSERT_NE(body, nullptr); - const auto shapeConf = EdgeShape::Conf{} - .UseVertexRadius(1_m) - .UseDensity(1_kgpm2); const auto v1 = Length2{-1_m, 0_m}; const auto v2 = Length2{+1_m, 0_m}; + const auto shapeConf = EdgeShapeConf{}.UseVertexRadius(1_m).UseDensity(1_kgpm2).Set(v1, v2); - const auto shape1 = std::make_shared(v1, v2, shapeConf); + const auto shape1 = Shape{shapeConf}; const auto fixture1 = body->CreateFixture(shape1); ASSERT_NE(fixture1, nullptr); @@ -604,8 +591,8 @@ TEST(World, GetShapeCountFreeFunction) ASSERT_NE(fixture2, nullptr); EXPECT_EQ(GetShapeCount(world), std::size_t(1)); - const auto shape2 = std::make_shared(v1, v2, shapeConf); - + const auto shape2 = Shape{shapeConf}; + const auto fixture3 = body->CreateFixture(shape2); ASSERT_NE(fixture3, nullptr); EXPECT_EQ(GetShapeCount(world), std::size_t(2)); @@ -620,13 +607,12 @@ TEST(World, GetFixtureCountFreeFunction) const auto body = world.CreateBody(BodyDef{}.UseType(BodyType::Dynamic)); ASSERT_NE(body, nullptr); - const auto shapeConf = EdgeShape::Conf{} - .UseVertexRadius(1_m) - .UseDensity(1_kgpm2); const auto v1 = Length2{-1_m, 0_m}; const auto v2 = Length2{+1_m, 0_m}; + const auto shapeConf = EdgeShapeConf{} + .UseVertexRadius(1_m).UseDensity(1_kgpm2).Set(v1, v2); - const auto shape = std::make_shared(v1, v2, shapeConf); + const auto shape = Shape{shapeConf}; const auto fixture1 = body->CreateFixture(shape); ASSERT_NE(fixture1, nullptr); @@ -657,10 +643,7 @@ TEST(World, AwakenFreeFunction) const auto v1 = Length2{-1_m, 0_m}; const auto v2 = Length2{+1_m, 0_m}; - const auto shape = std::make_shared(v1, v2, - EdgeShape::Conf{} - .UseVertexRadius(1_m) - .UseDensity(1_kgpm2)); + const auto shape = Shape{EdgeShapeConf{}.UseVertexRadius(1_m).UseDensity(1_kgpm2).Set(v1, v2)}; const auto fixture = body->CreateFixture(shape); ASSERT_NE(fixture, nullptr); @@ -687,9 +670,10 @@ TEST(World, CreateSquareEnclosingBody) for (auto& f: fixtures) { const auto s = f->GetShape(); - for (auto i = ChildCounter{0}; i < s->GetChildCount(); ++i) + const auto childCount = GetChildCount(s); + for (auto i = ChildCounter{0}; i < childCount; ++i) { - const auto child = s->GetChild(i); + const auto child = GetChild(s, i); const auto numVertices = child.GetVertexCount(); for (auto j = decltype(numVertices){0}; j < numVertices; ++j) { @@ -712,20 +696,19 @@ TEST(World, GetTouchingCountFreeFunction) EXPECT_EQ(GetTouchingCount(world), ContactCounter(0)); - const auto groundConf = EdgeShape::Conf{} - .UseVertex1(Vec2(-40.0f, 0.0f) * Meter) - .UseVertex2(Vec2(40.0f, 0.0f) * Meter); + const auto groundConf = EdgeShapeConf{} + .Set(Vec2(-40.0f, 0.0f) * Meter, Vec2(40.0f, 0.0f) * Meter); const auto ground = world.CreateBody(); - ground->CreateFixture(std::make_shared(groundConf)); + ground->CreateFixture(Shape(groundConf)); const auto bd = BodyDef{}.UseType(BodyType::Dynamic); const auto lowerBodyDef = BodyDef(bd).UseLocation(Vec2(0.0f, 0.5f) * Meter); - const auto diskConf = DiskShape::Conf{}.UseDensity(10_kgpm2); - const auto smallerDiskConf = DiskShape::Conf(diskConf).UseVertexRadius(0.5_m); + const auto diskConf = DiskShapeConf{}.UseDensity(10_kgpm2); + const auto smallerDiskConf = DiskShapeConf(diskConf).UseRadius(0.5_m); const auto lowerBody = world.CreateBody(lowerBodyDef); - lowerBody->CreateFixture(std::make_shared(smallerDiskConf)); + lowerBody->CreateFixture(Shape(smallerDiskConf)); while (GetAwakeCount(world) > 0) { @@ -764,26 +747,22 @@ TEST(World, DynamicEdgeBodyHasCorrectMass) const auto v1 = Length2{-1_m, 0_m}; const auto v2 = Length2{+1_m, 0_m}; - auto conf = EdgeShape::Conf{}; - conf.vertexRadius = 1_m; - conf.density = 1_kgpm2; - const auto shape = std::make_shared(v1, v2, conf); - ASSERT_EQ(shape->GetVertexRadius(), 1_m); + const auto conf = EdgeShapeConf{}.UseVertexRadius(1_m).UseDensity(1_kgpm2).Set(v1, v2); + const auto shape = Shape{conf}; + ASSERT_EQ(GetVertexRadius(shape), 1_m); const auto fixture = body->CreateFixture(shape); ASSERT_NE(fixture, nullptr); ASSERT_EQ(fixture->GetDensity(), 1_kgpm2); - const auto circleMass = Mass{fixture->GetDensity() * (Pi * Square(shape->GetVertexRadius()))}; - const auto rectMass = Mass{fixture->GetDensity() * (shape->GetVertexRadius() * Real{2} * GetMagnitude(v2 - v1))}; + const auto circleMass = Mass{fixture->GetDensity() * (Pi * Square(GetVertexRadius(shape)))}; + const auto rectMass = Mass{fixture->GetDensity() * (GetVertexRadius(shape) * 2 * GetMagnitude(v2 - v1))}; const auto totalMass = Mass{circleMass + rectMass}; EXPECT_EQ(body->GetType(), BodyType::Dynamic); EXPECT_NEAR(static_cast(Real{body->GetInvMass() * 1_kg}), static_cast(Real{1_kg / totalMass}), 0.000001); - - ASSERT_NE(fixture->GetShape(), nullptr); } TEST(World, CreateAndDestroyJoint) @@ -1132,10 +1111,7 @@ TEST(World, NoCorrectionsWithNoVelOrPosIterations) body_def.type = BodyType::Dynamic; body_def.bullet = true; - const auto shape = std::make_shared(DiskShape::Conf{} - .SetRadius(1_m) - .SetRestitution(Real(1)) - .SetDensity(1_kgpm2)); + const auto shape = Shape{DiskShapeConf{}.UseRadius(1_m).UseRestitution(Real(1)).UseDensity(1_kgpm2)}; body_def.location = Length2{-x * Meter, 0_m}; body_def.linearVelocity = LinearVelocity2{+x * 1_mps, 0_mps}; @@ -1217,13 +1193,12 @@ TEST(World, HeavyOnLight) const auto upperBodyDef = BodyDef(bd).UseLocation(Vec2(0.0f, 6.0f) * Meter); const auto lowerBodyDef = BodyDef(bd).UseLocation(Vec2(0.0f, 0.5f) * Meter); - const auto groundConf = EdgeShape::Conf{} - .UseVertex1(Vec2(-40.0f, 0.0f) * Meter) - .UseVertex2(Vec2(40.0f, 0.0f) * Meter); + const auto groundConf = EdgeShapeConf{} + .Set(Vec2(-40.0f, 0.0f) * Meter, Vec2(40.0f, 0.0f) * Meter); - const auto diskConf = DiskShape::Conf{}.UseDensity(10_kgpm2); - const auto smallerDiskConf = DiskShape::Conf(diskConf).UseVertexRadius(0.5_m); - const auto biggerDiskConf = DiskShape::Conf(diskConf).UseVertexRadius(5.0_m); + const auto diskConf = DiskShapeConf{}.UseDensity(10_kgpm2); + const auto smallerDiskConf = DiskShapeConf(diskConf).UseRadius(0.5_m); + const auto biggerDiskConf = DiskShapeConf(diskConf).UseRadius(5.0_m); const auto baseStepConf = []() { auto step = StepConf{}.SetInvTime(60_Hz); @@ -1262,14 +1237,14 @@ TEST(World, HeavyOnLight) { auto world = World{WorldDef{}.UseMinVertexRadius(SmallerLinearSlop)}; const auto ground = world.CreateBody(); - ground->CreateFixture(std::make_shared(groundConf)); + ground->CreateFixture(Shape(groundConf)); const auto lowerBody = world.CreateBody(lowerBodyDef); const auto upperBody = world.CreateBody(upperBodyDef); ASSERT_LT(GetY(lowerBody->GetLocation()), GetY(upperBody->GetLocation())); - lowerBody->CreateFixture(std::make_shared(smallerDiskConf)); - upperBody->CreateFixture(std::make_shared(biggerDiskConf)); + lowerBody->CreateFixture(Shape(smallerDiskConf)); + upperBody->CreateFixture(Shape(biggerDiskConf)); ASSERT_LT(GetMass(*lowerBody), GetMass(*upperBody)); auto upperBodysLowestPoint = GetY(upperBody->GetLocation()); @@ -1290,14 +1265,14 @@ TEST(World, HeavyOnLight) { auto world = World{WorldDef{}.UseMinVertexRadius(SmallerLinearSlop)}; const auto ground = world.CreateBody(); - ground->CreateFixture(std::make_shared(groundConf)); + ground->CreateFixture(Shape(groundConf)); const auto upperBody = world.CreateBody(upperBodyDef); const auto lowerBody = world.CreateBody(lowerBodyDef); ASSERT_LT(GetY(lowerBody->GetLocation()), GetY(upperBody->GetLocation())); - lowerBody->CreateFixture(std::make_shared(smallerDiskConf)); - upperBody->CreateFixture(std::make_shared(biggerDiskConf)); + lowerBody->CreateFixture(Shape(smallerDiskConf)); + upperBody->CreateFixture(Shape(biggerDiskConf)); ASSERT_LT(GetMass(*lowerBody), GetMass(*upperBody)); auto upperBodysLowestPoint = GetY(upperBody->GetLocation()); @@ -1319,14 +1294,14 @@ TEST(World, HeavyOnLight) { auto world = World{WorldDef{}.UseMinVertexRadius(SmallerLinearSlop)}; const auto ground = world.CreateBody(); - ground->CreateFixture(std::make_shared(groundConf)); + ground->CreateFixture(Shape(groundConf)); const auto lowerBody = world.CreateBody(lowerBodyDef); const auto upperBody = world.CreateBody(upperBodyDef); ASSERT_LT(GetY(lowerBody->GetLocation()), GetY(upperBody->GetLocation())); - lowerBody->CreateFixture(std::make_shared(smallerDiskConf)); - upperBody->CreateFixture(std::make_shared(biggerDiskConf)); + lowerBody->CreateFixture(Shape(smallerDiskConf)); + upperBody->CreateFixture(Shape(biggerDiskConf)); ASSERT_LT(GetMass(*lowerBody), GetMass(*upperBody)); auto upperBodysLowestPoint = GetY(upperBody->GetLocation()); @@ -1354,14 +1329,14 @@ TEST(World, HeavyOnLight) { auto world = World{WorldDef{}.UseMinVertexRadius(SmallerLinearSlop)}; const auto ground = world.CreateBody(); - ground->CreateFixture(std::make_shared(groundConf)); + ground->CreateFixture(Shape(groundConf)); const auto upperBody = world.CreateBody(upperBodyDef); const auto lowerBody = world.CreateBody(lowerBodyDef); ASSERT_LT(GetY(lowerBody->GetLocation()), GetY(upperBody->GetLocation())); - lowerBody->CreateFixture(std::make_shared(smallerDiskConf)); - upperBody->CreateFixture(std::make_shared(biggerDiskConf)); + lowerBody->CreateFixture(Shape(smallerDiskConf)); + upperBody->CreateFixture(Shape(biggerDiskConf)); ASSERT_LT(GetMass(*lowerBody), GetMass(*upperBody)); auto upperBodysLowestPoint = GetY(upperBody->GetLocation()); @@ -1391,8 +1366,7 @@ TEST(World, HeavyOnLight) TEST(World, PerfectlyOverlappedSameCirclesStayPut) { const auto radius = 1_m; - const auto shape = std::make_shared(radius, DiskShape::Conf{} - .SetDensity(1_kgpm2).SetRestitution(Real(1))); + const auto shape = Shape{DiskShapeConf{}.UseRadius(radius).UseDensity(1_kgpm2).UseRestitution(Real(1))}; const auto gravity = LinearAcceleration2{}; World world{WorldDef{}.UseGravity(gravity)}; @@ -1429,8 +1403,8 @@ TEST(World, PerfectlyOverlappedConcentricCirclesStayPut) { const auto radius1 = 1_m; const auto radius2 = 0.6_m; - const auto shape1 = std::make_shared(radius1, DiskShape::Conf{}.SetDensity(1_kgpm2).SetRestitution(Real(1))); - const auto shape2 = std::make_shared(radius2, DiskShape::Conf{}.SetDensity(1_kgpm2).SetRestitution(Real(1))); + const auto shape1 = Shape(DiskShapeConf{}.UseDensity(1_kgpm2).UseRestitution(Real(1)).UseRadius(radius1)); + const auto shape2 = Shape(DiskShapeConf{}.UseDensity(1_kgpm2).UseRestitution(Real(1)).UseRadius(radius2)); const auto gravity = LinearAcceleration2{}; World world{WorldDef{}.UseGravity(gravity)}; @@ -1476,7 +1450,7 @@ TEST(World, ListenerCalledForCircleBodyWithinCircleBody) auto body_def = BodyDef{}; body_def.type = BodyType::Dynamic; body_def.location = Length2{}; - const auto shape = std::make_shared(1_m, DiskShape::Conf{}.SetDensity(1_kgpm2).SetRestitution(Real(1))); + const auto shape = Shape(DiskShapeConf{}.UseDensity(1_kgpm2).UseRestitution(Real(1)).UseRadius(1_m)); for (auto i = 0; i < 2; ++i) { const auto body = world.CreateBody(body_def); @@ -1510,12 +1484,12 @@ TEST(World, ListenerCalledForSquareBodyWithinSquareBody) auto body_def = BodyDef{}; body_def.type = BodyType::Dynamic; body_def.location = Length2{}; - auto conf = PolygonShape::Conf{}; - conf.SetVertexRadius(1_m); + auto conf = PolygonShapeConf{}; + conf.UseVertexRadius(1_m); conf.SetAsBox(2_m, 2_m); - conf.SetDensity(1_kgpm2); - conf.SetRestitution(Real(1)); - const auto shape = std::make_shared(conf); + conf.UseDensity(1_kgpm2); + conf.UseRestitution(Real(1)); + const auto shape = Shape{conf}; for (auto i = 0; i < 2; ++i) { const auto body = world.CreateBody(body_def); @@ -1546,7 +1520,7 @@ TEST(World, PartiallyOverlappedSameCirclesSeparate) auto body_def = BodyDef{}; body_def.type = BodyType::Dynamic; body_def.bullet = false; // separation is faster if true. - const auto shape = std::make_shared(radius * Meter, DiskShape::Conf{}.SetDensity(1_kgpm2).SetRestitution(Real(1))); + const auto shape = Shape(DiskShapeConf{}.UseDensity(1_kgpm2).UseRestitution(Real(1)).UseRadius(radius * Meter)); const auto body1pos = Length2{(-radius/4) * Meter, 0_m}; body_def.location = body1pos; const auto body1 = world.CreateBody(body_def); @@ -1634,7 +1608,7 @@ TEST(World, PartiallyOverlappedSameCirclesSeparate) TEST(World, PerfectlyOverlappedSameSquaresSeparateHorizontally) { - const auto shape = std::make_shared(1_m, 1_m, PolygonShape::Conf{}.SetDensity(1_kgpm2).SetRestitution(Real(1))); + const auto shape = Shape(PolygonShapeConf{}.UseDensity(1_kgpm2).UseRestitution(Real(1)).SetAsBox(1_m, 1_m)); const auto gravity = LinearAcceleration2{}; World world{WorldDef{}.UseGravity(gravity)}; @@ -1704,8 +1678,7 @@ TEST(World, PartiallyOverlappedSquaresSeparateProperly) body_def.bullet = false; // separation is faster if true. const auto half_dim = Real(64); // 1 causes additional y-axis separation - const auto shape = std::make_shared(half_dim * Meter, half_dim * Meter, - PolygonShape::Conf{}.SetDensity(1_kgpm2).SetRestitution(Real(1))); + const auto shape = Shape(PolygonShapeConf{}.UseDensity(1_kgpm2).UseRestitution(Real(1)).SetAsBox(half_dim * Meter, half_dim * Meter)); const auto body1pos = Length2{Real(half_dim/2) * Meter, 0_m}; // 0 causes additional y-axis separation body_def.location = body1pos; @@ -1861,8 +1834,7 @@ TEST(World, CollidingDynamicBodies) EXPECT_EQ(world.GetGravity(), gravity); world.SetContactListener(&listener); - const auto shape = std::make_shared(radius, - DiskShape::Conf{}.SetDensity(1_kgpm2).SetRestitution(Real(1))); + const auto shape = Shape(DiskShapeConf{}.UseDensity(1_kgpm2).UseRestitution(Real(1)).UseRadius(radius)); body_def.location = Length2{-(x + 1) * Meter, 0_m}; body_def.linearVelocity = LinearVelocity2{+x * 1_mps, 0_mps}; @@ -1988,7 +1960,7 @@ TEST(World, TilesComesToRest) PLAYRHO_CONSTEXPR const auto LinearSlop = Meter / 1000; PLAYRHO_CONSTEXPR const auto AngularSlop = (Pi * 2 * 1_rad) / 180; PLAYRHO_CONSTEXPR const auto VertexRadius = LinearSlop * 2; - auto conf = PolygonShape::Conf{}.UseVertexRadius(VertexRadius); + auto conf = PolygonShapeConf{}.UseVertexRadius(VertexRadius); const auto m_world = std::make_unique(WorldDef{}.UseMinVertexRadius(VertexRadius)); PLAYRHO_CONSTEXPR const auto e_count = 36; @@ -2007,7 +1979,7 @@ TEST(World, TilesComesToRest) for (auto i = 0; i < N; ++i) { conf.SetAsBox(a * Meter, a * Meter, position, 0_deg); - ground->CreateFixture(std::make_shared(conf)); + ground->CreateFixture(Shape{conf}); GetX(position) += 2.0f * a * Meter; } GetY(position) -= 2.0f * a * Meter; @@ -2016,8 +1988,9 @@ TEST(World, TilesComesToRest) { const auto a = Real{0.5f}; - conf.SetDensity(5_kgpm2); - const auto shape = std::make_shared(a * Meter, a * Meter, conf); + conf.UseDensity(5_kgpm2); + conf.SetAsBox(a * Meter, a * Meter); + const auto shape = Shape(conf); Length2 x(-7.0_m, 0.75_m); Length2 y; @@ -2364,12 +2337,11 @@ TEST(World, SpeedingBulletBallWontTunnel) const auto left_edge_x = -0.1_m; const auto right_edge_x = +0.1_m; - const auto edgeConf = EdgeShape::Conf{} + const auto edgeConf = EdgeShapeConf{} .UseVertexRadius(VertexRadius) .UseRestitution(Real(1)) - .UseVertex1(Length2{0_m, +10_m}) - .UseVertex2(Length2{0_m, -10_m}); - const auto edge_shape = std::make_shared(edgeConf); + .Set(Length2{0_m, +10_m}, Length2{0_m, -10_m}); + const auto edge_shape = Shape(edgeConf); BodyDef body_def; body_def.type = BodyType::Static; @@ -2399,8 +2371,7 @@ TEST(World, SpeedingBulletBallWontTunnel) ASSERT_NE(ball_body, nullptr); const auto ball_radius = 0.01_m; - const auto circle_shape = std::make_shared(ball_radius, - DiskShape::Conf{}.SetDensity(1_kgpm2).SetRestitution(Real(1))); + const auto circle_shape = Shape(DiskShapeConf{}.UseDensity(1_kgpm2).UseRestitution(Real(1)).UseRadius(ball_radius)); const auto ball_fixture = ball_body->CreateFixture(circle_shape); ASSERT_NE(ball_fixture, nullptr); @@ -2545,7 +2516,7 @@ TEST(World, MouseJointWontCauseTunnelling) BodyDef body_def; body_def.type = BodyType::Static; - auto edgeConf = EdgeShape::Conf{}; + auto edgeConf = EdgeShapeConf{}; edgeConf.UseFriction(Real(0.4f)); edgeConf.UseRestitution(Real(0.94f)); // changes where bodies will be after collision @@ -2557,7 +2528,7 @@ TEST(World, MouseJointWontCauseTunnelling) const auto left_wall_body = world.CreateBody(body_def); ASSERT_NE(left_wall_body, nullptr); { - const auto wall_fixture = left_wall_body->CreateFixture(std::make_shared(edgeConf)); + const auto wall_fixture = left_wall_body->CreateFixture(Shape(edgeConf)); ASSERT_NE(wall_fixture, nullptr); } Include(container_aabb, ComputeAABB(*left_wall_body)); @@ -2568,7 +2539,7 @@ TEST(World, MouseJointWontCauseTunnelling) const auto right_wall_body = world.CreateBody(body_def); ASSERT_NE(right_wall_body, nullptr); { - const auto wall_fixture = right_wall_body->CreateFixture(std::make_shared(edgeConf)); + const auto wall_fixture = right_wall_body->CreateFixture(Shape(edgeConf)); ASSERT_NE(wall_fixture, nullptr); } Include(container_aabb, ComputeAABB(*right_wall_body)); @@ -2582,7 +2553,7 @@ TEST(World, MouseJointWontCauseTunnelling) const auto btm_wall_body = world.CreateBody(body_def); ASSERT_NE(btm_wall_body, nullptr); { - const auto wall_fixture = btm_wall_body->CreateFixture(std::make_shared(edgeConf)); + const auto wall_fixture = btm_wall_body->CreateFixture(Shape(edgeConf)); ASSERT_NE(wall_fixture, nullptr); } Include(container_aabb, ComputeAABB(*btm_wall_body)); @@ -2593,7 +2564,7 @@ TEST(World, MouseJointWontCauseTunnelling) const auto top_wall_body = world.CreateBody(body_def); ASSERT_NE(top_wall_body, nullptr); { - const auto wall_fixture = top_wall_body->CreateFixture(std::make_shared(edgeConf)); + const auto wall_fixture = top_wall_body->CreateFixture(Shape(edgeConf)); ASSERT_NE(wall_fixture, nullptr); } Include(container_aabb, ComputeAABB(*top_wall_body)); @@ -2609,8 +2580,7 @@ TEST(World, MouseJointWontCauseTunnelling) ASSERT_EQ(GetY(ball_body->GetLocation()), 0_m); const auto ball_radius = Real(half_box_width / 4) * Meter; - const auto object_shape = std::make_shared(ball_radius, ball_radius, - PolygonShape::Conf{}.SetDensity(10_kgpm2)); + const auto object_shape = Shape(PolygonShapeConf{}.UseDensity(10_kgpm2).SetAsBox(ball_radius, ball_radius)); { const auto ball_fixture = ball_body->CreateFixture(object_shape); ASSERT_NE(ball_fixture, nullptr); @@ -2988,7 +2958,7 @@ static void smaller_still_conserves_momentum(bool bullet, Real multiplier, Real }; world.SetContactListener(&listener); - const auto shape = std::make_shared(scale * radius * Meter); + const auto shape = DiskShapeConf{}.UseRadius(scale * radius * Meter); ASSERT_EQ(shape->GetRadius(), scale * radius); auto fixture_def = FixtureDef{}.UseDensity(1); @@ -3081,13 +3051,11 @@ class VerticalStackTest: public ::testing::TestWithParam { const auto hw_ground = 40.0_m; const auto ground = world.CreateBody(); - ground->CreateFixture(std::make_shared(Length2{-hw_ground, 0_m}, - Length2{hw_ground, 0_m})); + ground->CreateFixture(EdgeShapeConf{}.Set(Length2{-hw_ground, 0_m}, Length2{hw_ground, 0_m})); const auto numboxes = boxes.size(); original_x = GetParam(); - const auto boxShape = std::make_shared(hdim, hdim, - PolygonShape::Conf{}.SetDensity(1_kgpm2).SetFriction(Real(0.3f))); + const auto boxShape = Shape{PolygonShapeConf{}.UseDensity(1_kgpm2).UseFriction(Real(0.3f)).SetAsBox(hdim, hdim)}; for (auto i = decltype(numboxes){0}; i < numboxes; ++i) { // (hdim + 0.05f) + (hdim * 2 + 0.1f) * i diff --git a/UnitTests/WorldManifold.cpp b/UnitTests/WorldManifold.cpp index 359b37ec44..25be10167a 100644 --- a/UnitTests/WorldManifold.cpp +++ b/UnitTests/WorldManifold.cpp @@ -21,7 +21,7 @@ #include "gtest/gtest.h" #include #include -#include +#include #include #include #include @@ -148,7 +148,7 @@ TEST(WorldManifold, GetWorldManifoldForCirclesFullyOverlappingManifold) TEST(WorldManifold, GetForContact) { - const auto shape = std::make_shared(); + const auto shape = DiskShapeConf{}; auto bA = Body{nullptr, BodyDef{}}; auto bB = Body{nullptr, BodyDef{}}; auto fA = Fixture{&bA, FixtureDef{}, shape};