Various questions: Physics, shadows and lighting

Hi all. I have recently started to use JME (with Kotlin) and so far things are looking good. I have a few questions. First physics. I have a system in my game where the player can grab an object and drag it around. I got this working using a SixDofJoint but there are some stability problems with the grabbed objects. Especially if these objects are small. What can I do to fix these issues? What tips in general are there to get a good working physical world. I want the player to be able to interact with many objects like grab them, stack them on top of each other, open doors, chests, and so on.

My other question is about lighting. I’m using SpotLightShadowRenderer and adding it as a processor. How many processors are considered to be good? How does one manage which lights should get shadows and which not? Is there some system for doing this in JME or do you have to manage this manually?

Thanks!

3 Likes

Here is the grabbing code btw:

private fun startGrab() {
    val pair = findHovering()
    if (pair != null) {
        val (result, gob) = pair
        if (gob.mesh?.flags?.mass ?: 0f > 0f) {
            grabDistance = result.distance
            val contactPoint = gob.control?.spatial?.worldToLocal(result.contactPoint, null)

            if (handle == null) {
                handle = RigidBodyControl(BoxCollisionShape(.1f), 1.0f).also {
                    it.isKinematic = true
                    bulletAppState.physicsSpace.add(it)
                }
            }
            if (joint == null) {
                joint = SixDofJoint(handle, gob.control, Vector3f.ZERO, contactPoint, true).also {
                    it.setAngularLowerLimit(Vector3f.ZERO)
                    it.setAngularUpperLimit(Vector3f.ZERO)
                    bulletAppState.physicsSpace.add(it)
                }
            }
            updateGrab()
        }
    }
}

And to update the joint:

private fun updateGrab() {
    val pos = cam.location.add(cam.getDirection().mult(grabDistance))
    handle?.physicsLocation = pos
}
1 Like

Once you start getting around 7 shadow renderers (give or take depending on your spatials), things start slowing down. It is good to make a class to manage your shadow renderers and only enable the most necessary ones.

If you don’t want a light to not have shadows, simply don’t add it to a processor.

There is no class to manage shadow renderers that I know of. There might be in one in v3.4. If not, you can always make your own.

Correct. Every game would need something a little different.

Some games will bake lighting into the level. Some will only put shadows on one light, some will pick two… some will pick two based on distance, some based on visibility based on some reachability algorithm, PVS data, etc… It’s going to be VERY game specific.

…and at the end of the day, each shadow renderer means rendering the scene again. Games with a lot of dynamic lights will sink time into building a deferred renderer.

If level geometry is already static, prebaked lighting (even in multiple layers if they need to be turned on/off) may look the best for how little work it would require.

“How to handle shadows” is one of those big differentiators with lots of options, each with their own costs and limitations.

Thanks for the replies. It’s ok that I have to handle this myself. Just wanted to be sure that I’m not reinventing the wheel

3 Likes

I got this working using a SixDofJoint but there are some stability problems with the grabbed objects. Especially if these objects are small. What can I do to fix these issues?

What sort of stability problems? Please describe or post video.

Also, which physics library are you using?

I’m using com.github.stephengold:Minie:4.0.0

I actually managed to get things working better by increasing the mass of my ‘handle’ (the invisible object that I’m using to hang my other object on). When I’m grabbing smaller and lighter objects the objects still seem to jitter a bit. Also there are some other stability issues. I made a small video showing the problems. Notice how in the beginning of this video the cans are slightly dancing on the table without me doing anything. Not sure what’s causing that:

Thanks for the help

2 Likes

I think those may help , you can alter them differently according to the situation:

        rigidBodyControl.setContactDamping(0);
        rigidBodyControl.setRollingFriction(LARGE_VAL);
        rigidBodyControl.setKinematic(true);

Rolling friction default value is zero for any RigidBodyControl , so increasing the values would create a torsional force(break-like) opposing the angular motion of that object on an orthogonal plane(the table in your case).

EDIT there’s also setSpinningFriction(value:Float); i think this would be better than rolling.

1 Like

Ok interesting. I’m now playing with these values and it’s indeed a lot better if my objects in the world are set up like:

        val control = RigidBodyControl(shape, (flags.mass ?: 0.0f) * 10f)
        control.angularDamping = 0.1f
        control.contactDamping = 0.2f
        control.friction = 2.8f
        control.rollingFriction = 0.05f
        control.spinningFriction = 0.05f

Sometimes when I grab a smaller ‘box’ type object and let it fall it stays down without rotating correctly. i.e. it seems to balance. Decreasing the friction helps but that increases the instability again. So it’s a bit hard to find correct values. But it’s certainly better. Thanks!

1 Like

i think , you may try something like that :

do a friction values mapping & use according to the distance between the object & the ground according to your findings…

val control = RigidBodyControl(shape, (flags.mass ?: 0.0f) * 10f)
val maxMap=0.05f
var distanceToFloor=0.0f
distanceToFloor=control.physicsLocation.distance(floorControl.physicsLocation)
control.rollingFriction = (distanceToFloor!=0 ? distanceToFloor % maxMap : maxMap)
control.spinningFriction = (distanceToFloor!=0 ? distanceToFloor % maxMap : maxMap)

So, it gets lesser tending your domain range , whenever it approaches the ground , but if its in your hand or on the table its mobility is still valid , but it will differ only as you approach the ground.

Hmm that seems complicated and also how would I know when to update those values when the objects move?

According to the perpendicular distance between the object physics location & your ground , it would be updated , but it should be placed in update(tpf:Float) or an AbstractControl :

EDIT : Draw an imaginary line between the object & the ground , then according to the interpolation in this line , ask yourself when I would like to decrease or increase the spinningFriction , so in short you will find an implicit relationship between both the friction & distanceToFloor.

The modulo function operator (value%base) , it basically creates a mapping values according to the given input(distanceToFloor in this case) starting from the base & ending before base*2 when it reaches base*2 it constrains the output back to values less than 0.05 & bigger than 0 [0,0.05] , you can replace this with an array of your own.

I think the idea would be to tweak these values only while the object is grabbed and then put them back again when you release it.

…depending on whether you adjusted those values for grabbing or for the tiny item jitter.

(Note: the tiny item jitter is something that even pro physics engines have to deal with which is why sometimes in fallout3 the jitter is bad enough that you can hear objects clanging around before settling down.)

1 Like

Ah indeed. That’s a good idea. Thanks

Jiggling (as seen in your video) can be caused by not enough physics accuracy (too long timestep) for small objects under high gravity.

There’s a direct connection between gravity, timestep, and object dimensions, as discussed in the Minie project README file:

Dynamic bodies in forced contact tend to jiggle. Jiggling is mostly noticeable for sharp-edged bodies (such as boxes) resting on uneven surfaces, under high gravity. The higher the gravity (in psu per second squared), the shorter the simulation time step (in seconds) needs to be. For efficient and realistic simulation of Earth-like gravity (9.8 m/s) with the default margin (0.04 psu) and time step (0.0167 seconds), the psu should be 0.3 meters or larger. This puts a soft upper limit on the size (in psu) of dynamic bodies.

Note: “psu” is shorthand for “physics-space unit(s)”. Also, I should’ve written “soft lower limit”, not “soft upper limit”. I’ll correct the README!

Not sure I fully understand what ‘psu’ means? How do I set that? I checked and couldn’t find any setting related to that

Note: “psu” is shorthand for “physics-space unit(s)”.

When a physics object moves from location (0,0,0) to location (0,0,1), it moves a distance of 1 physics-space unit.

Ok but how can I change the psu from 0.04 to 0.3?

You can change the margin of each collision shape from 0.04 psu to 0.3 psu, but that might introduce other issues. Better options are to reduce gravity or shorten the timestep.

Ok, I think there is some misunderstanding here on my part. My question was. What code do I use to change the psu value from 0.04 to 0.3? How do I do that in the API?