Genbox / VelcroPhysics

High performance 2D collision detection system with realistic physics responses.
MIT License
664 stars 113 forks source link

Reintroduce blueprints #6

Open Genbox opened 7 years ago

Genbox commented 7 years ago

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.

Genbox commented 7 years ago

This feature should be aware of #5 such that it can utilize pooling efficiently.

ilexp commented 7 years ago

I'd just like to throw in that I don't think Farseer / Velcro needs or should be concerned with serialization, because every game and game engine will do this differently. In Duality, I actually removed any serialization support from our Farseer port entirely. From a physics library, I expect that it simulates physics based on data that I provide, without making assumptions about how that data will be structured or stored.

On the same vein, I'm not sure body definitions provide more value than overhead. Sure, I can then clone a body easily, but I've had to create the body definition in the first place - so why wouldn't I just execute the same code again? It makes sense only when you see serialization as part of Velcros concerns, which I would tend to argue against.

That said, both of this sounds like a neat addition as a separate utility library on top of Velcro that can be used by Velcro samples and sandboxes - keeping the core library clean and small.

craftworkgames commented 7 years ago

I'd just like to throw in that I don't think Farseer / Velcro needs or should be concerned with serialization, because every game and game engine will do this differently.

It's been a long time since I used Farseer in a real world scenario but I do have vague memories of trying to deal with serialization and if I recall correctly it used to be quite painful.

I agree that serialization doesn't need to be a built in feature of Velcro but I do think it's worth at least thinking about how serialization is going to work because at some point someone is going to want to serialize these things.

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.

Can you elaborate on the types of problems that arise when serializing the real user objects directly?

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.

At this stage I'm in favor, but as I said, it's been a long time since I've actually used the library in the real world so take my opinion with a grain of salt.

In MonoGame.Extended we tend to prefer the JSON.NET serializer which I've found to be very powerful and customizable. My gut feeling tells me it might be possible to get it working with or without the blueprints anyway.

Genbox commented 7 years ago

@ilexp I completely understand where you are from and I tend to think the same thing. However, we need to cater to people that usually need to serialize, but have no idea on how to do it. I worked together with someone back in the day, to make a standard format for serialization, such that you could export from FPE and import in another physics engine. It was formalized in a way where we only serialize "unique" bodies and stuff like that, which makes it very efficient compared to what you might come up with yourself.

I wanted to limit this issue as well.

That being said, the engine is not user friendly for serialization right now, as need to extract bodies, shapes and fixtures from the engine and then know what is important and what is not. You can very quickly blow up the engine if you serialize forces like velocity and don't apply it correctly on deserialization.

Genbox commented 7 years ago

@craftworkgames

Can you elaborate on the types of problems that arise when serializing the real user objects directly?

Yep. It comes down to the fact that I have to extend the internals of the engine every time I introduce a new feature. It also means I have to hack around with the visibility of certain properties that are usually private to an object. Cloning also creates a new object every time; this is where a pool would help, but I have to rewrite all of cloning to make use of it, so I might as well take multiple things into consideration.

In MonoGame.Extended we tend to prefer the JSON.NET serializer which I've found to be very powerful and customizable.

I love JSON.NET and it is amazing to me how James managed to make it this fast. However, as both you and @ilexp have touched on, serialization is often custom made by the user. For this reason, I'll try and see if I can come up with a generalization of blueprints that would make it easy to export a world to any format and thus, not depend on XML (what we do now) or JSON.

If I manage to solve #3 somehow, I can finally split the framework into several projects, and one could be VelcroPhysics.Serialization.JSON, that takes a hard dependency on JSON.NET - this way the engine itself is dependency free.

Genbox commented 7 years ago

@craftworkgames Just a quick note: Did not know what MonoGame.Extended was. Looked it up and this is the first time I see Mercury Particle Engine mentioned in a long time, I think it has been 5 years since I last developed on the project.

ilexp commented 7 years ago

You can very quickly blow up the engine if you serialize forces like velocity and don't apply it correctly on deserialization.

Serializing the physics world representation is not a carefree solution either, as the problem for users shifts from "how to serialize a body" to "how to re-synchronize physics world and higher level game world before / after serialization". Depending on what exactly any given game or engine needs, and which level of detail is required to be serialized, I could imagine not being the only one to prefer problem A over B.

For this reason, I'll try and see if I can come up with a generalization of blueprints that would make it easy to export a world to any format and thus, not depend on XML (what we do now) or JSON.

Maybe that could be a good solution to the overall serialization issue, not just limited to blueprints: Create an intermediate data structure that does not itself carry any serialization logic, but is geared towards being easy to serialize, then allow to create a template or even world based on that, or create it based on an existing world or template.

A separate project could then implement specific serialization techniques for users that need them - all others can either use the intermediate data structure for their own serialization, or roll out something custom entirely.

Genbox commented 7 years ago

Create an intermediate data structure that does not itself carry any serialization logic, but is geared towards being easy to serialize

Yep, that is what I'm also thinking. I'm very much into the whole abstract syntax vs. encoding issue since I work a lot with ASN.1 on a daily basis, and specific implementations (JSON) should be different from the abstract representation (definitions)

craftworkgames commented 7 years ago

I just found myself working on some code and I ran into an issue related to blueprints (or lack of). Ideally, I want to be able to declare the data for my bodies separately from actually adding them to the World.

The first parameter in the factory methods is always the world. However, it's not always the case that you want to add the body to the world immediately. Ideally, I'd like to be able to setup my bodies in one part of the code and defer adding them to the world until later. Clearly blueprints would be useful in this situation.

I can workaround the issue, but I just wanted to bring it up while I think of it as another vote for this issue 👍

Genbox commented 7 years ago

Very good use case, thanks for providing it.

qpaolo commented 7 years ago

Serializing the physics world representation is not a carefree solution either, as the problem for users shifts from "how to serialize a body" to "how to re-synchronize physics world and higher level game world before / after serialization".

Is is safe to reposition a body with the current implementation?
For example I have a snapshot from server and must correct the simulation running on client.

Genbox commented 7 years ago

This library is currently under heavy development. I recommend you download Farseer Physics Engine 3.5 for now. Please create a new issue for stuff not related to this discussion.