Julio Jerez wrote:there is the problem of who has the owner ship of an object.
That's easy: The application. So in your case, you would manage ownership in the sandbox, but not in the engine.
I just realize, i would prefer to call it library instead engine, as the engine term more likely associates with higher level concepts such as managing ownership.
But since there is no general solution to such problems they should not be part of a library meant to implement lower level functionality such as physics simulation.
This becomes even more true because the application, e.g. a game, basically must implement solutions for ownership management anyway. So we most likely end up with multiple implementations addressing the same problems, increasing complexity and difficulty to the programmer, who now has to know and keep all the implementations in mind.
In other words, smart pointers, but memory on static data should be optional components of the library at a higher levels, which the users then can adopt or not. And additionally, you do not need to implement them at all, offloading the responsibility to the users.
I see that's not in line with the OOP paradigm, and it's also not how any physics engine i ever saw works. They all manage their objects internally. But imo they shouldn't.
I also see you need memory management for your internal data anyway, so it's ofc. an obvious choice to make no difference between static and dynamic data, handling all with the same management and enforcing its adoption. But imo that's not ideal.
To be clear, what i mean with static data is, for example:
A model, consisting of shapes, bodies and joints, plus the nodes remaining static to that model, e.g. graphs or trees to form a ragdoll skeleton or spatial acceleration structure.
Eventually, we want to have all this in one block of memory. Then we can stream this block from disk quickly, and adding it to the simulation means only to connect pointers.
The memory manager then only has to manage one block, not dozens of object. We always remove or add it as a whole.
It will not always work this way. E.g. eventually we can not effort to store BVH on disk, and have to build it on load. Which makes this entire ideal block idea optional. It should be possible, but not enforced as a concept for everything.
The dynamic data would be contact constraints, top level acceleration structure, and maybe some stuff.
If you do need (or benefit from) shared pointers for that, i neither complain nor notice. And ofc. you need to manage the memory dynamically, without much options to make assumptions on something like 'ideal blocks'.
So exposing this system to be used also for the static stuff is fine and makes sense, but it should be optional on enforced.
One rule i personally try to follow with this 'static / dynamic' context in mind, is that potentially static objects must have a default constructor. Otherwise we can't generate the data without a need to construct objects, while what we actually want is just to copy the data. That's why i missed it in the base joint.
Another similar issue was when i hacked the static geometry to extend adjacency to neighboring objects. Functionality was available only by calling constructors, or it was private. That's the things i call OOP dictatorship. When things like abstraction meant to make things easier become actual obstacles.
and them you will see that although that are not perfect, they do render a service when use properly.
Yeah, it's like with most patterns or concepts. They try to make it easier using automation and abstraction. And it works for 90% of cases. But the remaining 10% become even more difficult and error prone. So the benefits and losses cancel each other out, and all that's left is the additional need to know the pattern or concept.
That's how it looks to me at least. An amateur who never did read any programming books, so i do not even know if i have used above fancy terms correctly.
But maybe my 2 cents still have some value regardless.