Code Monkey home page Code Monkey logo

velcrophysics's Introduction

Velcro Physics (Formerly Farseer Physics)

Build License

Warning: Under construction

The project is under development. Consider donating to support the effort.

What is this?

Velcro Physics is a high performance 2D collision detection system with realistic physics responses. It can be used to create games or real-time robotic simulations.

What is it good for?

You can create a game, robotic simulatons or even UI feedback systems using this engine and associated tools. Everything from a simple platform game to Marsrover simulations are possible.

Features

We have tons of features!

  • Continuous collision detection (with time of impact solver)
  • Contact callbacks: begin, end, pre-solve, post-solve
  • Convex and concave polygons and circles.
  • Multiple shapes per body
  • Dynamic tree and quad tree broadphase
  • Fast broadphase AABB queries and raycasts
  • Collision groups and categories
  • Sleep management
  • Friction and restitution
  • Stable stacking with a linear-time solver
  • Revolute, prismatic, distance, pulley, gear, mouse joint, and other joint types
  • Joint limits and joint motors
  • Controllers (gravity, force generators)
  • Tools to decompose concave polygons, find convex hulls and boolean operations
  • Factories to simplify the creation of bodies

Packages

You can use VelcroPhysics as a normal .NET library. We also have zero-copy integration with MonoGame.

  • NuGet
  • NuGet

Sponsored Project

This is a sponsored project. That means in order to create issues and pull requests, or use the project commercially, you must become a sponsor. Projects like this take up a lot of time and effort, so please help keeping open-source projects alive by becoming a sponsor today. You can stop your sponsorship anytime you want.

velcrophysics's People

Contributors

alan-fgr avatar genbox avatar mattbettcher avatar preetum avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

velcrophysics's Issues

Vector2 normalize (division with zero)

public static void Normalize(ref Vector2 value, out Vector2 result)
        {
            float factor;
            DistanceSquared(ref value, ref zeroVector, out factor);
            factor = 1f / (float)Math.Sqrt(factor);
            result.X = value.X * factor;
            result.Y = value.Y * factor;
        }

I'm currently using Farseer and had some issues with contact solving. I figured the issue might still be with Velcro.

Normalize return a Vector2(X=NaN, Y=NaN) if you try to normalize a zero vector.
because factor will be zero so 1f / (float)Math.Sqrt(factor) will result in Infinity

the solver does something like Normalize(Position1 - Position2) so if the two positions is identical we get the NaN vector which crashes the physics.

Hopes this helps :)

I solved it this way

public static void Normalize(ref Vector2 value, out Vector2 result) {
            if (value == zeroVector)
                result = zeroVector;
            else {
                float factor;
                DistanceSquared(ref value, ref zeroVector, out factor);
                factor = 1f / (float)Math.Sqrt(factor);
                result.x = value.x * factor;
                result.y = value.y * factor;
            }
        }

Make EPCollider static if possible

Currently, we generate garbage each time an edge and polygon collides due to EPCollider. See if we can refactor it into a static class instead.

Testbed sample for benchmarking

Create a sample in the testbed that uses as many core parts of the engine as possible. It should be used when optimizing the engine as a benchmark to see if an optimization worked or not. It should also:

  • Enable detailed debug view
  • Disable sleeping of bodies

I'm thinking the following features should be present:

  • A small pyramid to stress test the contact system and solver
  • A distance calculation between two polygons
  • Time of Impact stress test
  • Raycast stress test (might have too much in common with distance test)

Move Towards Bulk Collision / Separation / Solve Event Handling

Right now, the way to handle physics events is by subscribing to event handlers on a per-body or even per-fixture basis. This has a high overhead-to-use ratio. One potential way to improve efficiency is to defer all events to the end of the update and deliver them in bulk with one callback per event type.

Besides reducing overhead of delegate calls, it will allow engines and games to do efficient batch processing of these events. It might also allow for secondary optimizations in Velcro, as these specific events will no longer cause user code to run during the simulation.

I don't have an API proposal fleshed out, but I'd imagine an array-of-structs approach, potentially even re-using a subsection of the same array across frames unless grown beyond its former size.

As @Genbox mentioned, this should be combined with a way to flag specific entities to be traced with this event:

If we save all the collisions, you would probably get a list of hundreds of events in scenarios where you have stacked objects (things on terrain etc.). This unfortunately will probably slow down the whole thing rather than speed it up. That being said, it could be sped up if this was implemented as a "tracer" - you mark your objects and the engine check for that mark, and if they are marked, their events are recorded for bulk consumption

First mentioned in this comment, issue #2

"raints"

You did the same thing as me. Search & replace "const" => ""
Result:
// Integrate velocities, solve velocity raints, and integrate positions.

I thought "raints" was trendy-speak for "constraints" - until I realised what I'd done. Made me laugh when I saw the same thing in someone else's code!

Might be worth just having a quick scan through the code to make sure all constraints are still correctly named ;)

Refactor body rotation and position

When updating rotation or position of a body, we copy over more data than needed, as well as finding contacts multiple times. Using these properties are therefore slow compared to Get/SetTransform().

Refactoring this code into will yield a performance increase as well.

Implement equality interface

The engine itself uses HashSet in order to quickly index objects. HashSet uses IEqualityComparer implementation unless another comparer is specified in the constructor. Shapes, bodies, fixtures and other data classes should expose the comparer via IEqualityComparer for such features to function correctly.

BeginContact event issue

I added BeginContact event to world.
world.ContactManager.BeginContact += new BeginContactDelegate(OnBeginContact);
And, return false on "OnBeginContact" method.
On FarseerPhysics, I could disabled bodies contact to use this way.
But now, I can't disable bodies contact at VelcroPhysics.
How should I do this?

Optimize DistanceProxy

The engine creates a new DistanceProxy object all the time to hold temporary information. It has a larger impact than it should have since we are also clearing a list to support multiple calls to Set().

Refactor Body.ShouldCollide()

Move it to ContactManager right next to ShouldCollide for fixtures. See if there is an optimization for the O(n) check on joints.

Can't run HelloWorld project on VS 2017

missing2
When I open the solution, Game, Microsoft.Xna.Framework.Graphics, Microsoft.Xna.Framework.Input,... can not be resolve.
Do I need install any missing library? I can't fix MonoGame.Framework reference missing in project. Please help me!

using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Inp
![missing](https://user-images.githubusercontent.com/17638038/33368832-52e03cb6-d525-11e7-9834-455b39b1dbad.PNG)
ut;
namespace VelcroPhysics.Samples.HelloWorld
{
    public class Game1 : Game
...
}

missing

Provide API For Integrating Physics-Generated Bodies With Higher-Level Game Code

Existing physics functionality like cutting tools or breakable bodies create new physics bodies as part of the simulation. However, for higher-level game code, these bodies do not exist. There should be an API that allows user code to be informed about the creation of these bodies, as well as the reason / context of their creation, so they can be integrated into the game properly.

First mentioned in this comment, issue #2

Collide() skips Contacts

Some suggestions on the naming of elements

VelcroPhysics.Dynamics.Body

_xf is strange and it may be abbreviation of XForm which is similiar to Transform .In addition,variable names beginning with an underscore is not compliant with the CLS.

    public class Body
    {
        public Transform _xf; // the body origin transform
    }

Suggest :

    public class Body
    {
        public Transform Transform; // the body origin transform
    }

VelcroPhysics.Dynamics.TimeStep

In general,a public variable should be full word.

    public struct TimeStep
    {
        public float dt;
        public float dtRatio;
        public float inv_dt;
    }

Suggest :

    public struct TimeStep
    {
        public float DeltaTime;
        public float DeltaTimeRatio;
        public float InverseDeltaTime;
    }

VelcroPhysics.Shared.Rot

Rot doesn't name with a full noun,and fields s,c lead to confusion.

    public struct Rot
    {
        public float s,c;
    }

Suggest:

    public struct Rotation
    {
        public float SinValue;
        public float CosValue;
    }

VelcroPhysics.Shared.Transform

Likewise,the meanings of p and q are not clearly.

    public struct Transform
    {
        public Vector2 p;
        public Rot q;
    }

Suggest :

    public struct Transform
    {
        public Vector2 Position;
        public Rotation Rotation;
    }

Avoid List<T> O(n) operations

To simplify the code, Velcro Physics uses simple lists instead of the linked lists Box2D uses. However, operations such as Contains() and Remove() on List are O(n) operations, which slows down the engine considerably when working with many fixtures on a body.

Serializable templates

Hi,

I am wondering whether we can make the templates serializable, specifically, serializable with DataContractSerializer and BinaryFormatter. By storing the template in resources instead of hard-code in C# one by one, it will definitely make the built-in template more useful when we are serializing a game scene.

I am also wondering whether we can add a list/array of FixtureTemplate in BodyTemplate, which allows us to store only one BodyTemplate to create on body. Now we need to specify a BodyTemplate and attach several Fixtures. Also this does the same as FixtureTemplate, which contains a Shape (or ShapeTemplate, please below). The final goal is to make template easier to use, especially more friendly to game scene serialization.

If you think it's reasonable, I can make a pull request. This requires the following work:

  • Add attributes to classes and properties.
  • Add default constructors.
  • Change Shape in FixtureTemplate to ShapeTemplate, and Body to BodyTemplate in JointTemplate. Compared with their templates, Shape and Body are difficult to serialize.
  • Add an array of FixtureTemplate in BodyTemplate.
  • Add a helper function in Factory class to create Body and Joint objects in a World.

This may requires more tests, but I don't have a clear idea on how to do that yet. What are your suggestions?

Thanks.

Refactor DistanceProxy

It basically wraps vertices by copying over the data from shapes. Distance calculation should not have anything to do with shapes or proxies, so we could simplify the code by reducing the proxies to vertices and radius in a struct. The mapping between shapes such as CircleShape could then be simplified by enforcing Shape to have Vertices, where CircleShape would just have 1 vertex (its position).

Refactor chainshape to use static raycasting

ChainShape creates a new EdgeShape in order to piggyback on the raycast code, since it is just a wrapper for multiple EdgeShapes. Refactor the code such that we can avoid the double allocation by sharing the raycasting code between the two shapes.

Remove IDispose pattern in favor of RemoveFromWorld()

I used IDispose it so that a user can call myBody.Dispose() and it will remove the body from the world. There are some issues with this:

  1. The Disposable pattern (IDisposable) is meant for releasing unmanaged resources. Using it for anything else can have unintended consequences.
  2. When an object falls out of scope, not mean the object will be garbage collected right away. Dispose() will therefore not be called until the GC comes to collect.
  3. Since the World object already have a reference to the body, even when the body falls out of the current scope, it does not get garbage collected. There are tricks like WeakReference, but it is currently not implemented and might introduce bugs into user code, since they will need to explicitly state they need a strong reference in the World list.
  4. IDispose gave the ability to use the 'using' pattern like seen below, but it is an esoteric feature since most bodies seem to be long lived.
using (Body b = new Body(_world))
{
   //Do work with body
}

//Body will be removed from world here.

Instead, I propose a RemoveFromWorld() method that needs to be explicitly called whenever a body should leave the world. This is exactly the same as calling World.RemoveBody(body), but sometimes users don't have access to the World object, but do have the Body object.

Any comments, improvements or votes (thumb up/down) are appreciated.

BayazitDecomposer is protected.

In the Farseer documentation, it mentions making use of the BayazitDecomposer to create polygons. However in Velcro this class is protected and not available. Can/should this (and other decomposers) be made public?

Change to Protobuild project

Hello โœ‹
What do you think about change the project to use Protobuild to generate the project files?

Protobuild offers some facilities and better organization for the project and is really easy to use.
๐Ÿค™

Introduce quickshapes for better performance

Polygons are generic and always calculate their normals and centroid. However, sometimes we know a shape is symmetric on both axis, we can therefore quickly just set the normals and centroid with no calculations.

To simplify things, see if we can expose those quickshapes though the factories.

Suggestions

I have attempted to port Box2D to C# twice, I also had a look at Box2DX with a view to bringing it up to date but it was much too far behind. This looks like it's in a far better state than any of those. I may contribute.

My most recent attempt to port was actually porting LiquidFun, but I got to the Particle System and found that a lot of the code is totally bizarre. There seem to be casts from classes to booleans where the cast takes a parameter(?!?!) Even then, I put compiler directives around the particle stuff but couldn't get the Box2D pieces to work nicely. (To be fair, I only spent 3 days on it.)

The reason I wanted to port it to C# was really to get it to use more than one core. The particle system is dead slow after about 4,000 particles, but it's only using 1 of my 8 logical (4 physical) cores.

So...
Once you've got this in a better state,

  1. Multithreading - all collisions are evaluated at the same time, so that could be a good candidate to get started.
  2. Offload to the GPU - not easy, I admit. Keeping a load of data in the GPU might be the best way forward. I'm using SFML for presentation, that provides access to GLSL but it's limited: data can only be sent as a texture, so colours are normalised from a set of four bytes to four floats. It needs a bit of 'encoding' to get anything larger in or out, and granularity of smaller numbers is limited. OpenCL would probably be the natural choice. The Campy and ILGPU libraries are worth investigating, although ILGPU is still young and the website doesn't seem to exist (I don't know if that's anymore, or yet)
  3. Particles! Why not? As I mentioned, LiquidFun is already based on Box2D so there is a relevant reference implementation. And a particle system is a fantastic addition.

If I didn't need particles, I would pick this up, use it, and submit pull requests for anything I fixed. Because of my use case, I'm going to stick with LiquidFun with a C++/CLI facade in front of it. My next project probably won't need a particle system - so there's an opportunity for me to get involved there.

Truly polygon Vertices

I using a BodyFactory.CreatePolygon() and spawn polygons.
But, some vertices are removed by GiftWrap.GetConvexHull().
So, now I add polygon...
2017_04_29 0_05_01
I want to change like this.
2017_04_29 0_04_39

Upgrading from Farseer -- what do you think of Aether?

I've been building my game on FSE 3.5 and finding that there have been advancements in forks, namely Velcro and Aether. I'd like to upgrade to Velcro since it's by the original author, but there are some optimizations in Aether that sound significant. What's the verdict? Does Velcro include all of Aether's optimizations, including multi-threaded support?

PolygonTools.CreatePolygon(uint[], int Width)

Hey Velcrophysics,

I just realized I'm absolutely outdated because I was still using Farseer Monogame. I'm currently creating my own game engine library that has similar functionality to Game Maker, and since I've been including the direct source of all libraries I use I also decided to add Farseer.

Problem is that since you guys have changed to Velcro Physics, and I just added the source to my library, I can not find the PolygonTools class. I think I used an unofficial Monogame version of Farseer that may have had this class already included (do you guys know what it is?)

I used this class to create a polygon out of a Texture2D like so;

   ` /// <summary>
    /// Converts a texture to a compound polygon.
    /// </summary>
    /// <param name="Texture">The texture to create a compound polygon out of.</param>
    /// <returns>The compound polygon. Note: These are not scaled for Farseer Physics.</returns>
    public static Vertices GetTexturePolygon(Texture2D Texture)
    {
        uint[] Data = new uint[Texture.Width * Texture.Height];
        Texture.GetData(Data);
        return PolygonTools.CreatePolygon(Data, Texture.Width);
    }`

FixtureFactory.AttachCompoundPolygon(GetScaledVertices(), 1f, Body);

Does it still exist? If it does, does it automatically scale? Because I'm using a PolygonTools.CreatePolygon that I later have to scale using ConvertUnits.ToSim(1f) -> This makes it an absolute charm to use these polygons in other instances where I don't want to scale them.

Regards,

  • Eddie

TextureConverter.DetectVertices() throws InvalidOperationException on blank textures

In TextureConverter:274 there's a possible InvalidOperationException when accessing polygonEntrance.Value. This will only occur when GetTopMostVertex returns null which will only occur when the texture is blank. As an example of where this might occur in the wild is with programmatically generated textures, or in my case, a texture atlas with the occasional blank tile.

My vote for a resolution is for the method to either return null, or return new List<Vertices>() or throw new Exception("Your texture is blank.") (or some message like that).

EDIT: After further testing, it looks like this method may also throw when there are one pixel wide polygons. I can reproduce consistently with some textures but not with others containing 1 pixel polygons. Will update when I figure out the pattern.

Bad raycasting performance :(

Hi there.

Since I'm using this library for the physics in my game, I decided to also use it for 2d light raycasting, however, I'm having some really bad performance, I don't need anything too fancy, and it's a pixel art game, but I'd like to have at least 15+ lights on screen running @ 60fps, but I get lower framerates with much less lights
image
I am getting the closest shapes using QueryAABB and then I get the shapes vertices and fire 3 rays for each of them.
I've profiled it and apparently the problem parts are Vector2 subtractions, and PolygonShape.get_Normals (what's very odd because after a quick look at the code it just seems to return cached stuff), and also some other operations like Dot product, I wonder if the fact I'm using FNA has something to do with that, maybe the math isn't as fast as in XNA?
Anyway, I'm planning to MT the raycaster since it's not critical for gameplay so we can safely drop some frames and have it lag behind the other stuff, but even though, I don't think the performance is OK, maybe there's a gotcha or something, here's the code I'm using:

//get colliders in range
AABB rect = new AABB(entity.Position, size_*2f-(2+SHADOW_BIAS), size_*2f-(2+SHADOW_BIAS));
List<Fixture> cols = Sz.physWorld.QueryAABB(ref rect);

// build list of points in radius to add to the perimeter
List<Vector2> radiusPoints = new List<Vector2>();
foreach (Fixture col in cols)
{
    PolygonShape shape = col.Shape as PolygonShape;

    // skip the light emitter
    if((col.Body.UserData as Component).entity == entity) continue;
            
    //cast one ray for each vertex of shapes in range
    foreach (Vector2 v in shape.Vertices)
    {
        var worldPoint = col.Body.GetWorldPoint(v);

        Vector2 rayDirection = worldPoint-center;
        Quadrant quadrant = rayDirection.GetQuadrant();

        //get offset for auxiliary rays (fast)
        Vector2 auxOffset = new Vector2(-1,1);
        if (quadrant == Quadrant.TR) auxOffset = new Vector2(1, -1);
        else if (quadrant == Quadrant.TL) auxOffset = Vector2.One;
        else if (quadrant == Quadrant.BR) auxOffset = -Vector2.One;

        var hit = Sz.physWorld.RayCastSingle(center, worldPoint);

        float distMult = (center-hit.Value).Length();
        Vector2 normalizedDirection = Vector2.Normalize(rayDirection);
                
        float auxOffsetAmount = distMult*0.001f;
        Vector2 longRay = center+normalizedDirection*size_*1.4f; //ray besides points

        var auxA = Sz.physWorld.RayCastSingle(center, longRay+auxOffset*auxOffsetAmount);
        var auxB = Sz.physWorld.RayCastSingle(center, longRay-auxOffset*auxOffsetAmount);

        //if we hit something, propagate light a tad bit
        radiusPoints.Add(hit.Value+normalizedDirection *SHADOW_BIAS);
        radiusPoints.Add(auxA.Value+normalizedDirection*SHADOW_BIAS);
        radiusPoints.Add(auxB.Value+normalizedDirection*SHADOW_BIAS);
    }
}

//cast one ray for each corner of the quad
radiusPoints.Add(Sz.physWorld.RayCastSingle(center, center+Vector2.One*      size_).Value+Vector2.One*0.71f*SHADOW_BIAS);
radiusPoints.Add(Sz.physWorld.RayCastSingle(center, center-Vector2.One*      size_).Value-Vector2.One*0.71f*SHADOW_BIAS);
radiusPoints.Add(Sz.physWorld.RayCastSingle(center, center+new Vector2(-1,1)*size_).Value+new Vector2(-1,1)*0.71f*SHADOW_BIAS);
radiusPoints.Add(Sz.physWorld.RayCastSingle(center, center+new Vector2(1,-1)*size_).Value+new Vector2(1,-1)*0.71f*SHADOW_BIAS);     

Extension method:

    public static KeyValuePair<Fixture, Vector2> RayCastSingle(this World w, Vector2 point1, Vector2 point2)
    {
        Fixture fixture = null;
        Vector2 point = point2;

        w.RayCast((f, p, n, fr) =>
        {
            fixture = f;
            point = p;
            return fr;
        }, point1, point2);

        return new KeyValuePair<Fixture, Vector2>(fixture, point);
    }

I don't see anything that could be considerably optimized there. The profiles only shows the Dynamics.World.RayCast function there, the other stuff is negligible, but the tree is somewhat confusing, Collision.DynamicTree`1.RayCast(Func, ref RayCastInput) takes a lot of time, but below it there's a lot of stuff, including Wrapper and OverlapTester.

Am I doing something wrong? Would you guys recommend another approach, maybe using a fast library specialized on raycasting ( I couldn't find any though )? Thanks in advance.

Problem with sliding

I'm coding a simple game with SFML.Net and I'm using Farseer Physics(from codeplex). The player is a rectangle with a fixed rotation. The level is just a bunch of tiles(which are static rectangles with a fixed rotation.). However, when the player is sliding across several tiles, he sometimes gets stuck on the corners of tiles that are close together. Here's a gif demonstrating the issue: https://imgur.com/a/LOp4W
The character gets stuck on the corners. The scale is 90 pixels to 1 meter.
Here is a download of my project(compiled):
YetAnotherSFMLApp.zip
Edit: I didn't have this issue when using Box2Dx.

Precalculate and cache normal of EdgeShape

Edge shapes are static, and as such we can precompute their normal. Raycasts against edge shapes needs the normal, and currently it is calculated on each call to RayCast(). Since we would like branchless code, I think it is better to precompute it and cache it.

Body collision filters

There is already collision filters on fixtures, and bodies contain collision filters as a wrapper for it's fixtures. This proposal is about creating a filter for bodies much like there is for fixtures (no wrapper).

A body is just a point in space and has no real concept of a geometry until fixtures attach shapes to the body. Adding a body filter would mean we break this concept a little bit by filtering on the total geometry (all shapes) of a body in the collision broad phase. We could further speed up processing by merging AABBs together for each shape in a body and check against that instead of each AABB.

Ideas For a High-Performance System Design

Hey there,

I've recently done a bit of work on physics-related tasks and in the process spent some thoughts on how Farseer performance could be improved.

Performance Observations

First, some assumptions on certain performance aspects that hopefully are uncontroversial enough to agree on as a precondition:

  • The fastest way to process data is to iterate over an array of structs.
  • It tends to be faster to bulk-process batches of data in a tight loop than to process one item at a time.
  • Parallelization has a synchronization overhead, except where no synchronization is necessary.
  • Executing user code has a guard overhead, except where no context-specific guard is necessary.
  • There is a non-zero overhead to abstractions like List<T> vs. T[] when it comes to bulk-processing large amounts of data.

Potential Performance Sinks

Next, here is a list of Farseer system design decisions that potentially drag performance below the theoretical maximum:

  • Shape, Joint and Body are all classes stored in lists or similar data structures.
  • Users can subscribe to events that are invoked from the middle of the physics simulation.
  • User events are invoked callback style, item-by-item.
  • Parallelizing physics simulation internally (i.e. not by putting Farseer into its own thread) is complicated because every object may alter the state of every other.

Design Decision Draft for Maximizing Efficiency

Finally, I'll just throw in some rather radical ideas on how to restructure the overall system to address the above issues:

  • Make Body a struct and store all bodies in a World-global (potentially sparse) array.
  • Make Joint a struct (generalized) and store all joints in a World-global (potentially sparse) array.
  • Make Shape a struct (discriminated union) and store all shapes in a Body-local (dense) array.
  • Double-buffer all of the above data within World, so a physics step / update can strictly read-only from buffer A (current frame) and write-only to buffer B (next frame). This enables internal parallelization without synchronization using Parallel.For and similar.
  • Grant users direct access to all of the above World-global arrays so they can perform efficient bulk operations.
  • References between Body, Joint and Shape take the form of int-based handles that represent the access index in their world.
  • Instead of event callbacks, gather all occurrences (structs!) to "subscribed" events in an array over an update step and deliver them in bulk once the update step is finished. This enables users to do efficient batch-processing and frees Velcro from the need for state guards and their overhead. See issue #8.
  • User code that absolutely requires to be executed within the physics frame (such as collision filters, but be really strict here) is required to consist of a pure function that gets all required data read-only via parameter and returns a value.

As a side effect to improved efficiency, less overhead and internal parallel execution, the above changes could also make serialization (see issue #6) a lot easier. It would also make pooling (see issue #5) obsolete.

On the downside, this would require users to adopt a new API and potentially be more careful due to less safety options being around. There will be a bigger need for good documentation so users are primed for certain aspects of the system. This might also generate a large amount of issues that need to be resolved in order to adapt to the new design, but if any of these changes should make it into Velcro, now would likely be a better opportunity to tackle them than later.

I'm totally aware that the above are quite radical suggestions and that I don't have any idea about most of the internal structures and design decisions of Farseer, so please read it as a collection of ideas by an interested observer :)

Setting Body.Enabled = false inside of OnCollision causes crash.

I'm running a 4 year old version of Farseer Physics so if this is not an issue with this version please just mark as resolved.

I'm getting a crash in Contact.Update if the FixtureA OnCollision handler has the code Body.Enabled = false then the FixtureB will be null causing a crash before the FixtureB handlers can be called.

Currently I'm going to just do if(FixtureB != null so it won't crash as I can't see any side effects but OnCollision would also have to check if you had more than 1 collision handler attached.

Reintroduce blueprints

One of the things I did in FPE was to remove Box2D blueprints and simplify the engine to use a factory pattern instead. In Box2d, it is like this:

CircleShapeDef c = new CircleShapeDef();
c.Position = new Vector2(10, 10);
c.Density = 4;

BodyDef b = new BodyDef();
b.Shape = c;

Body cb = b.Create();

Instead I wanted it a little simpler so a user could just do this:

BodyFactory.CreateCircle(new Vector2(10, 10), 4);

I think the factories quickly became the primary thing to use for creating shapes, bodies and fixtures.
The simplification actually removed blueprints (definitions) completely since I could omit a memcopy in the process and do some clever stuff with density calculations at the same time.

However, definitions are good for a couple of things:

  1. Serialization - since they describe user objects.
  2. Cloning - You could convert a Body back into a BodyDef for cloning or serialization

Velcro has support for both serialization and cloning, but since there are no blueprints, they use the real user objects directly, which creates other problems.

This proposal is to re-introduce blueprints/definitions into the engine, while still maintaining factories, cloning and serialization. This change means we will do a little more work in memory, but it should be negligent. For the users, it means all factories will have an overload that takes in a definition, and body, shape and fixture will be extended with methods for converting back and forth between real object and blueprint/definition.

Any comments, improvements or votes (thumbs up/down) are appreciated.

Running Sample Project

Hello,

I am able to run the "HelloWorld" project (in Samples)without incident, but when I try to run "Samples" project (in Samples) I get two errors. Not sure what this are as I am not familiar with XNA or Monogame.

`Severity Code Description Project File Line Suppression State
Error The command ""C:\Program Files (x86)\MSBuild\MonoGame\v3.0\Tools\MGCB.exe" /@:"C:\Users\smatt\code\VelcroPhysics\Samples\Samples\Content\Content.mgcb" /platform:Windows /outputDir:"C:\Users\smatt\code\VelcroPhysics\Samples\Samples\Content\bin\Windows" /intermediateDir:"C:\Users\smatt\code\VelcroPhysics\Samples\Samples\Content\obj\Windows" /quiet" exited with code 1. Samples (Samples\Samples)

Severity Code Description Project File Line Suppression State
Error Failed to create processor 'TextureToVerticesProcessor' Samples (Samples\Samples) C:/Users/smatt/code/VelcroPhysics/Samples/Samples/Content/Pipeline/Object.png

`

Pooling of user objects

Object pooling is an optimization method for reducing the load on garbage collectors. Velcro already makes heavy use of pooling for internal objects such as contacts. This proposal extends this capability to user objects such as Body, Shape and Fixture to further reduce the load on the garbage collector.

The proposal is to add an interface to all 'poolable' objects that contain a Reset() method. Each class will be responsible for providing their own implementation of Reset to make sure they have cleaned their internal state completely. Each user object will be extended with a Destroy() method as well, that can be called by the user when the object is no longer needed.

The factory classes will then be made 'pool' aware and fetch one from the pool rather than create a new object.

Advantages:

  1. Reduced load on the garbage collector since we reuse objects
  2. Faster object creation as we reuse existing objects

Disadvantages:

  1. If the user calls Destroy() on an object and uses it afterwards, it will cause havoc.
  2. The engine will use a little more memory since we keep a small number of objects always

Misc:

  1. I can make a setting for this behavior to be turned on and off. Should there be issues with bodies used after Destroy(), it can easily be determined by turning off pooling.
  2. I will probably pre-load the pool with a couple of objects on World creation. This should also be configurable.

Any comments, improvements or votes (thumbs up/down) are appreciated.

Add collinear points check to PolygonShape

From the point of the physics engine itself, collinear points are useless. ALL points have to get checked at least once in the narrow phase, so we would like the number of vertices of a polygon to be as low as possible. This proposal is to add a collinear check on vertices when creating polygons.

It should be configured using Settings so that a user can decide to disable the check, which would be enabled by default.

VelcroPhysics and Unity

Hi,
Im using Unity 2017.2.0f3 and trying Velcro.

First attempt I see following errors: 'expression body property accessor' is not available in C# 4. Please use language version 7 or greater.'example internal bool IsTouching => (_flags & ContactFlags.TouchingFlag) == ContactFlags.TouchingFlag; and so on. Result - 67 errors.

Ok, Im changed my configuration (Edit->Project Settings->Player->Other Settings-> Scripting Runtime Version from .Net 3.5 to .Net 4.6) Result - 17 errors.
public bool Enabled
{
get => (_flags & ContactFlags.EnabledFlag) == ContactFlags.EnabledFlag;
...

I got new errors ('out variable declaration' is not available in C# 6. Please use language version 7 or greater.)

Velcro dont supported Unity and Im need using Farseer or problem with project configuration?

Zero-Copy optimization

Currently Velcro Physics makes use of a zero-copy optimization when using the MonoGame framework. It is best illustrated with an example:

When you want to use Velcro in your MonoGame game, you have an update loop like this:

public override void Update()
{
    //Vector2 from MonoGame    
    Vector2 position = new Vector2(5, 10);
    
    Vec2 physicsPosition = new Vec2(position.X, position.Y);
    _world.Add(new Body(physicsPosition));
}

As you can see, we have to copy Vector2 into Vec2 to use it in the engine, and in the process, we just wasted a bit of CPU and RAM.

The optimization is that Velcro uses the Vector2 class from MonoGame internally (no dependency - source code is copied out), and then I make a MonoGame version of the library that does take dependency on MonoGame, but then I exclude our local Vector2 class from the project with a compiler constant. This way, when people are using MonoGame, we can zero copy like this:

public override void Update()
{
    //Vector2 from MonoGame    
    Vector2 position = new Vector2(5, 10);
    
    _world.Add(new Body(position));
}

This used to be a major optimization in Farseer Physics Engine since it used pixels as unit. However, now we use the Meter-Kilogram-Second (MKS) system instead, which means we have to copy over values anyway. This issue is to start a discussion on the relevancy of this optimization, as well as provide solutions to a better system, now that we use MKS.

Some General Questions, Roadmap, Relation to Farseer

Hello everyone,

let me preface this by saying that I'm incredibly happy to see a glimpse of life in this project again. We're using a custom port of Farseer 3.3.1 in the Duality project and have been quite happy with it for a few years. I've been considering the possibility of updating to Farseer 3.5 for performance and efficiency reasons, but abandoned the thought as there seemed to be (some of them potentially critical) unresolved issues and no further maintenance, making this switch daunting endeavor.

So, I guess the core question for me is where the project is headed:

  • I don't see a license yet - what will it be? MIT or similar?
  • What are the main goals and focus point for the future development of this project?
  • Is there a rough roadmap on planned short term / long term improvements?
  • Who is behind the VelcroPhysics organization? Are there long-term plans to open up for community-driven development and maintenance?
  • How will you (short-term) handle contributions?

And, going into some more technical detail:

  • The most efficient still viable way of batch processing lots of data in C# I've known so far is packing that data tightly into an array of structs. No garbage, no abstraction overhead. Any thoughts on moving into that direction for some of the internal data structures on critical paths?
  • Are there plans to get rid of the XNA / MonoGame dependency?
  • What are the main to do points on the technical side?

Apologies if my posting is a bit like "falling through your front door" - just very curious and I thought it wouldn't hurt to ask :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.