Trouble Converting to Z-Up

Greetings jMonkey devs!

First off, let me say that jMonkey is a real accomplishment, and has enabled me to quickly play around with games again after a nearly 20 year break. Kudos!

Last night I had my first frustration with jMonkey, specifically converting CharacterControl to BetterCharacterControl, and then trying to switch “up” from Y to Z. (I’m a mathematical purist, and would like X & Y to be ground coordinates). A couple of observations about the BetterCharacterControl class and the physics model in general:

  • If y is not up, getShape() returns wrong orientation shape. I had to write my own variant that creates a CapsuleCollisionShape(r, g, Z_UP_AXIS)

  • Its tricky to get BCC to recreate the shape. It happens at Construction time, and then in “duck”, but not when attaching a physic space with non-Y gravity, nor when setGravity() is called.

  • In general, capsules in the wrong orientation have a much greater chance of completely missing any collisions! I didn’t debug this in depth, but it seems to be the case.

  • If gravity is too strong, objects seem to pass through each other. I assumes it just a issue with any strong force.

  • Even with a few patches to BCC to get Z-up to work, onGround is still not ever “true”. It seems that the capsule is floating a little ways off the ground, so that the ray test doesn’t collide with the world. I’m forced to increase the tolerance from ZERO_TOLERANCE to nearly the height of the capsule. Wondering if there is a bug in conversion of CapsuleShapeZ to its peer in the physics model.

  • Even when “forcing” onGround, jump appears to do nothing, even with tremendous force.

Note that all the above works fine if I leave Y-up, so I’m going to proceed with that… but it makes me a bit sad. Also take the above with a grain of salt… some may be “user error” due to late night debugging session, but I do suspect there are some lurking issues with changing gravity direction.

Thanks again for all your work in this really interesting project. I look forward to getting deeper into the builtin animation / bones capabilities.

JJ

PS: I’m also seeing some performance problems with the physics engine, specifically adding static “world” models seems slow, and if the model is decimated into many sub-Spatials frame-rate drops, suggesting its not using sub-bounding box per Spatial (or I’m not computing them correctly?)

PPS: I notice that many internal buffers are doubly cleared before use (once in Java nio, and another buf.clear()), and for me that is 2 more than needed. Clearing buffers is ~1000x slower than just malloc, and there are tricks using Unsafe where you can do your own allocation and blast the pointer into the DirectBuffer without clearing first. (you are going to fill it with floats soon enough, but this at least saves 66% of the work)

Thanks again!

@JJ3d said: ...
  • If gravity is too strong, objects seem to pass through each other. I assumes it just a issue with any strong force.

PPS: I notice that many internal buffers are doubly cleared before use (once in Java nio, and another buf.clear()), and for me that is 2 more than needed. Clearing buffers is ~1000x slower than just malloc, and there are tricks using Unsafe where you can do your own allocation and blast the pointer into the DirectBuffer without clearing first. (you are going to fill it with floats soon enough, but this at least saves 66% of the work)

Is this also the case only when you change up to Z? Otherwise, you can increase the number of Physics substeps/ flag the object as a bullet and this should go away.

And… I’m interested in seeing where the second part’s conversation goes.

@t0neg0d said: Is this also the case only when you change up to Z? Otherwise, you can increase the number of Physics substeps/ flag the object as a bullet and this should go away.

And… I’m interested in seeing where the second part’s conversation goes.

Fallthrough issues are not limited to one “up” direction. But when gravity is high, the behavior is sensitive to the exact value: higher sometimes results in no fallthrough, or sometimes causes strange “stuck in the floor” issues. It doesn’t seem like I should have to adjust the model params to ensure collisions. (at least my own homerolled collision works fairly well even with extreme speeds)

As for Buffers, you can start playing around with performance implication with a 1 line change:

[java]
public static FloatBuffer createFloatBuffer(int size) {
FloatBuffer buf = ByteBuffer.allocateDirect(4 * size).order(ByteOrder.nativeOrder()).asFloatBuffer();
buf.clear(); // <---- this is totally unnecessary since the buffer always gets created clear. Both clear ops are unneeded, or at least undesirable in the extreme cases.
onBufferAllocated(buf);
return buf;
}
[/java]

@JJ3d said: Fallthrough issues are not limited to one "up" direction. But when gravity is high, the behavior is sensitive to the exact value: higher sometimes results in no fallthrough, or sometimes causes strange "stuck in the floor" issues. It doesn't seem like I should have to adjust the model params to ensure collisions. (at least my own homerolled collision works fairly well even with extreme speeds)

As for Buffers, you can start playing around with performance implication with a 1 line change:

[java]
public static FloatBuffer createFloatBuffer(int size) {
FloatBuffer buf = ByteBuffer.allocateDirect(4 * size).order(ByteOrder.nativeOrder()).asFloatBuffer();
buf.clear(); // <---- this is totally unnecessary since the buffer always gets created clear. Both clear ops are unneeded, or at least undesirable in the extreme cases.
onBufferAllocated(buf);
return buf;
}
[/java]

a) Increasing the substeps may be a bit overboard, but I’m fairly sure that you have to flag fast moving objects as isBullet (or some such thing) to ensure this doesn’t happen.

b) How much of a performance increase would this potentially be (any little bit helps with Android at least)? EDIT: And if the buffer if full of null’s… is it the iteration time you are saving by remove the clear() call? Or is there more to it?

So, I made the decision a long time ago that Mythruna would internally treat it’s world as Z-up… because like you, having dealt with simulations and other map visualization apps over the years, I think of the ground as x,y or lat/lon or whatever… and z is elevation.

However, you should carefully weight whether it’s worth the fight. I’ve half regretted the decision on more occasions than I can count where I track down some bug only to determine that it’s because I’ve screwed up a y-up to z-up conversion somewhere.

Sometimes it’s much easier for your brain to adapt than it is to constantly struggle with this.

@t0neg0d said: b) How much of a performance increase would this potentially be (any little bit helps with Android at least)? EDIT: And if the buffer if full of null's... is it the iteration time you are saving by remove the clear() call? Or is there more to it?

I can’t say exactly how much time you will save by removing the clear call(s); Its architecture dependent. A 1 megabyte malloc takes order hundreds of nanos, but clearing the data (with Unsafe.setMemory()) is order hundreds of micros. Doing it twice is naturally double. If you are allocating lots of large buffers within the rendering loop you might see a performance difference. I certainly recommend at least removing the one extra “clear()” call since its not doing any good. More aggressively trying to avoid the Java DirectBuffer clear is trickier, but doable at the risk of having uninitialized memory (ala C++). If you are just going to fill it with your vertexes immediately anyway, it seems safe enough. Maybe it can be an option.

As to what the savings is, its physically clearing the memory. Native memory isn’t cleared by default as it is in Java. Writing 0x00 to all the bytes takes time and memory bandwidth, more than you might think.

@pspeed said: So, I made the decision a long time ago that Mythruna would internally treat it's world as Z-up...

However, you should carefully weight whether it’s worth the fight.

This is wise advice that I will likely follow. Still, I think we are looking at just a couple of bugs preventing this particular case from working.

Ultimately I’m more concerned about the quirks in the physics model. I don’t foresee myself needing highly complex rigid body physics (due to lots of server side interactions) so I might consider going back to my homebrew model. Having off the shelf capsules etc sure would be nice assuming they are reasonably numerically stable.

I had a lot of ‘fun’ trying to get water filter working with z-up world… If you will need it, let me know, I still have a patch somewhere.

Well you could always make a own character based on a Ghostshape, then you can completly define your own logic, but also your own issues. This is very hard to get even accectable. Using a rigidbody as base reduces some problems like tunneling (ccd is your friend here when using antive bullet) and problems like what happens if you are in a door that closes ect. With some more or less extensive tweaking you can get a rigidbody to behave somewhat as expected.