Comments (5)
So, for instance, per this, for Body
instances there'd be new functions then with a signatures like the following as convenience functions to the named underlying settings:
void SetInvMassData(World& world, BodyID id, NonNegative<InvMass> invMass, NonNegative<InvRotInertia> invRotI);
void SetUnderActiveTime(World& world, BodyID id, Time value);
from playrho.
This issue brings up questions for me:
- Is it a mistake to have these world-oriented "convenience" interfaces to begin with?
- How can the maintenance overhead of keeping these synced be reduced? It's not hard for me to come up with ways to reduce it, but none are clearly winners for me. Let's say
Body
gets a new "setter", it'd be nice to not have to manually add a new world interface to match it, that in turn also begs for new unit test code to be added for the new interfaces to avoid losing test coverage. Internally the implementation could be done using a macro or functor taking interface. Doing the latter externally though then exposes the type to using code such that a convenience to modifyingBody
then effectively exportsBody.hpp
to the calling code whichWorldBody,hpp
currently does not. - Does furthering this "convenience" pattern not also begs for similar interfaces between say
Body
andBodyConf
? - Is it already clear enough the difference between
*Conf
types and their respective component types? The former types are intended to be more LiteralType oriented, moreconstexpr
friendly, cache-less, and free of invariants between member variables. The latter types are intended to be the opposite basically: not entirelyconstexpr
, potentially having caches for speed optimizations, potentially having invariants between member variables, and enforcing those invariants. - Should component types like
Body
also support a builder pattern like the*Conf
types tend to? Then the typical three line pattern could become one liners likeSetBody(world, id, GetBody(world, id).Enabled(true))
. This has the downside of exposing the component type - i.e.Body.hpp
then gets pulled in to user's code - and also making users' code lines longer. An upside though may be potentially no longer wanting the current 3-line to 1-line conveniences as much then and not dealing with as much code maintenance.
from playrho.
- Is it a mistake to have these world-oriented "convenience" interfaces to begin with?
When I first came across these, I actually thought it might be a mistake to have any methods other than these, because these are often better to use to make sure that the world state always remains synchronized to the modifications you make. However, I realized such a change might require exposing the specific setters of the components to the world implementation.
- Is it already clear enough the difference between
*Conf
types and their respective component types? The former types are intended to be more LiteralType oriented, moreconstexpr
friendly, cache-less, and free of invariants between member variables. The latter types are intended to be the opposite basically: not entirelyconstexpr
, potentially having caches for speed optimizations, potentially having invariants between member variables, and enforcing those invariants.
I'm not sure if the difference is clear enough actually. Is it correct that the specific shapes and joints only have Conf
types? Like the ChainShapeConf
for example, is its corresponding component type just the Shape
or is there a ChainShape
somewhere as well?
- Should component types like
Body
also support a builder pattern like the*Conf
types tend to? Then the typical three line pattern could become one liners likeSetBody(world, id, GetBody(world, id).Enabled(true))
. This has the downside of exposing the component type - i.e.Body.hpp
then gets pulled in to user's code - and also making users' code lines longer. An upside though may be potentially no longer wanting the current 3-line to 1-line conveniences as much then and not dealing with as much code maintenance.
I actually like this solution very much! It would simplify things a lot if the Conf
types could just be dropped entirely in favor of having the component types implement the builder pattern directly themselves. I guess the reason why Box2D has these structs to begin with is because their objects don't have a builder pattern like PlayRho does, so those are used instead. When creating a new body it would be nice if it could look something like this instead:
CreateBody(world).UseType(BodyType::Dynamic).Use(shapes);
But then the CreateBody
would have to return a Body
instead of a BodyID
, so there has to be some other way of getting the new ID back. Perhaps storing it directly as an immutable value in the body so you can just do body.GetID()
. I'm just brainstorming ideas here though.
Removing them would also reduce maintenance because preferably the Conf
types should always be enough to construct a perfect copy of an object. This was actually what I did first when serializing and deserializing the objects: I looked at the values in the Conf
type and falsely concluded that these should be the ones enough to pass through. It was only after looking at the ==
operator that I realized there were some values that were missing in it (thus #549).
If going for this approach, I think I would just drop the convenience methods completely as well. Another upside of this is when you press the .
in your IDE, the massive list of methods you see would shrink a lot, when now there can sometimes be like 8 different variants of the same function.
from playrho.
I appreciate the feedback. It's helpful for me.
Is it correct that the specific shapes and joints only have Conf types?
Currently, yes. Specific shape types and joint types are all named with a pattern of *ShapeConf
or *JointConf
respectively.
Incidentally, I have been considering dropping the Conf
part of these types' names. Perhaps that's better put off to like a 3.0 release though. Would you prefer these types' names not ending with Conf
?
it would be nice if it could look something like this instead
CreateBody(world).UseType(BodyType::Dynamic).Use(shapes)
With respect to a coding pattern like that, that's not too different syntactically from the SetBody(world, id, GetBody(world, id).Enabled(true))
example I'd given.
But, I think the coding pattern you mention could run against the separation of spaces that I want. This is where getting the body from the world is like asking the kernel for a copy of kernel state, and changing the body is a copy back into the kernel. The kernel in this case conceptually being the World
.
A setup I'm striving towards in this regard is being able to have worlds implementable on speciality hardware like GPUs without changing the user's interface. I think this also simplifies exporting the engine to other languages without having to reimplement it all in the other language.
I can imagine the separation could be maintained by having that kind of CreateBody
return a new builder type that stored the BodyID
along with BodyConf
like state. Then on its destruction, or on like a Sync
call, it'd set the state back into the world using the ID it stored.
from playrho.
Incidentally, I have been considering dropping the
Conf
part of these types' names. Perhaps that's better put off to like a 3.0 release though. Would you prefer these types' names not ending withConf
?
I would definitely prefer that!
I can imagine the separation could be maintained by having that kind of
CreateBody
return a new builder type that stored theBodyID
along withBodyConf
like state. Then on its destruction, or on like aSync
call, it'd set the state back into the world using the ID it stored.
That sounds like a kinda cool solution, as long as it doesn't become too complex for the average user to wrap their head around it. I was thinking another way to do it is to just call CreateBody
with a Body
, which I saw is already overloaded, and if the Body
also implements a builder pattern like BodyConf
, you can just keep it like:
CreateBody(world, Body{}.UseType(BodyType::Dynamic).Use(shapes));
from playrho.
Related Issues (20)
- ToSigned shouldn't be under playrho::d2
- Bug in cmake install: not all necessary headers get installed
- API documentation publication not part of CI HOT 1
- Make use of new allocator stats support
- Testbed, UnitTests, Benchmark require git recursive clone
- Pass values from the ShapeConf to other (sub)shape configs HOT 2
- Set multiple shapes to BodyConf at once HOT 3
- No GetShapes function HOT 4
- Incomplete equality operator for Body HOT 2
- Missing properties for BodyConf HOT 7
- Should caches be compared in the equality operator for the world? HOT 2
- Missing getters and setters for flags and inv_dt0 (for serialization purposes) HOT 1
- Ability to manually create a Contact (for serialization purposes) HOT 2
- Wrong position for transformation HOT 5
- No equivalent "IsDestroyed" method in World interface HOT 6
- Incorrect manifolds when deserializing/recreating the World state HOT 2
- GetContacts GetBodies GetJoints but no GetShapes inconsistency
- Just two very similar functions HOT 4
- Make UnitVec initializing constructor public HOT 15
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from playrho.