Yes, visualizing ranges of motion should make it easier to configure a ragdoll, among other things.
I won’t know how different the new soft-body system is until I investigate it. So far, I haven’t noticed any breakage of apps that use the old system, so I believe it’s backward compatible.
As usual, there’s almost no inline documentation. Here’s what the release notes say:
Bullet 2.89 includes a new implementation of volumetric deformable objects and cloth based on the Finite Element Method, thanks to Xuchen Han. Two-way coupling between deformables and rigid/multi body is achieved using a unified constraint solver.
One feature I’m contemplating (for Minie 1.7) would be a setUserData(String key, Object value) method for physics collision objects, analogous to the one for spatials in jme-core. This would be something applications and other libraries could (within limits) use for their own purposes, such as storing entity IDs or visualization hints.
PhysicsCollisionObject already has setUserObject(Object), but physics controls use it (and rely on it being unaltered) so most applications can’t use it for their own purposes.
Current thinking is that getUserData(String), hasUserDataKey(String), and getUserDataKeys() would also be implemented for PhysicsCollisionObject.
To conserve memory, the implementation would be a TreeMap. Furthermore, missing keys would indicate null values, and the values set by setUserObject(), setDebugMaterial(), and setDebugMeshInitListener() (all of which default to null) would be stored in the map, using reserved keys.
This would be incredibly useful, especially in situations where Minie is used apart from a full scenegraph (such as will be the case in MyWorld’s server).
My only suggestion would be to consider leaving the user object/debug with their current implementation to avoid any issues caused by key collisions. Having reserved keys for them is a good first step, but proper use still requires users to remember the presence of those keys.
Why do you think TreeMap would save memory? Have you done testing to prove that?
Do you suspect people might not use this interface much, so the number of objects in the map wouldn’t cause the log(n) getting and setting to hurt performance, especially if called every update? com.jme3.scene.Spatial already uses HashMap, so even in cases with lots of objects in a scenegraph, jme3 has demonstrated a unique HashMap for each object is not a concern for memory usage.
Do you plan on using the natural ordering provided by TreeMap for something? It’s a red-black tree.
My only suggestion would be to consider leaving the user object/debug with their current implementation to avoid any issues caused by key collisions. Having reserved keys for them is a good first step, but proper use still requires users to remember the presence of those keys.
Thanks for the suggestion.
Any reserved keys would be thoroughly documented, of course. And unlike the reserved userdata keys in Spatial, they’d all share some some distinctive prefix, such as “$”. That way I can add more reserved keys with minimal risk of breaking existing apps.
But I think I see your point. Why lay unnecessary traps for developers?
My thinking was based on the belief that a HashMap allocates memory for buckets even when it’s empty or nearly so.
I haven’t done any testing. Based on my past experience with Java microbenchmarking, I expect it would be difficult to prove anything.
Typical usage is hard to predict. i guess 90% of apps will use it for PhysicsControl user objects and nothing else, so the number of mappings will typically be 0 or 1—more often 1.
Spatial doesn’t allocate a HashMap for user data until a key is set. If every Spatial in a large scene-graph had user data, I expect the memory impact would be noticeable. But again, I haven’t tested this.
I don’t foresee any use for the natural ordering of TreeMap in this application, but I’ve found serendipitous uses for it in the past.
Yes… that makes sense (we use a virtually identical scheme for built-in entity attributes in MyWorld), and it’s a good approach. My only thoughts are avoiding the “unnecessary” trap in a few specific cases where it’s avoidable.
Thanks for the explanation. The default capacity for a HashMap is 16, so you could try lowering that to exactly how many you need for Minie’s keys. You could have a high load factor too. I’m not a java pro, though, so I’m probably just thinking premature optimization haha.
Yeah, but tree map has the red/black structure which is not free either. A hasmap has the array of buckets but it’s just an array. For a well distributed set of keys, the memory usage should be ‘pretty good’.
Neither are particularly efficient with respect to memory as they trade it for time… and for a handful of values with string keys, an array or array list based Map implementation may actually perform the same with less memory overhead. Depending on how ‘right sized’ you keep the backing array/list.
Thanks, Paul. I’ll definitely consider an ArrayList implementation.
Baeldung suggests that a TreeMap be used when memory is a consideration, but I don’t trust them 100%: Java TreeMap vs HashMap | Baeldung
On the chance that I might later change the implementation, I’ll make null keys illegal and also document the ordering (if any) of collections returned by getUserDataKeys().
I’m no expert on the subject, and I’m only speaking from my own experience settings lots of UserData on my spatials - but I have not noticed any substantial memory impact from setting UserData on more than a couple hundred objects in the scene graph.
I also implemented a UserData system into my AI library a long time ago (although I haven’t used it much), and I recall looking up the memory usage of a HashMap beforehand because I was afraid it may use too much memory. I’m no expert, so ignore me if I’m making an incorrect conclusion - but a HashMap uses 32 bytes per entry, so even if you end up with 1,000 hash maps with 16 entries each, that is 16,000 * 32 bytes which is only 512 kb (or .512 mb), and I doubt that most developers would exceed that many user data entries.
I wasn’t worried about the incremental cost per entry, but rather the absolute cost of a map with 0 or 1 entries.
Btw, I’m now considering yet another design: add a single Object field to each collision object (with its own getter and setter) and allow app developers to use it without limitation. (I suspect this was the original intent of setUserObject().)
This way, apps needing only a single custom property per collision object will incur minimal overhead. And apps needing multiple custom properties can define their own class for the purpose or attach a HashMap.
I think that would be best @sgold. In some cases I can see where I would want a HashSet over an ArrayList, but in other cases I can see where a map of some type would be useful. Letting the user select the object would be nice.
I am looking at use cases here for my engine, I think I have found a couple.
Once you have this out I will make some performance improvements to PhysicsSync that can utilize this (among other things).
Minie v1.7 is starting to take shape. A few of the changes will involve major refactoring “under the hood.” For instance, there’ll be a new PhysicsNativeObject abstract class, from which most physics objects will be derived, and an AbstractDemo class, from which most demo apps will be derived.
I’ve also been thinking about how physics objects are freed. Jme3-bullet (and past versions of Minie) freed them by invoking native methods from finalize(). This is tricky to implement correctly because the library cannot control the order in which objects are finalized. A redesign of Minie’s native-object management might plug a few memory leaks, making Minie more suitable for long-running apps such as servers. I haven’t decided whether to use Cleanable (requires Java 9) or phantom references (to maintain compatibility with Java 7 and 8). Either way, I don’t expect the change to be in Minie v1.7.
I’m wondering, how many Minie users currently require compatibility with Java 7 and 8?