SkipLOd problem

So, I have a lot of smaller detail objects in my spaceships, and I simply want to skip them if they are pretty smalle and do not add much to the scene.

So I created a simple SkipController

package de.visiongamestudios.shared.assetdb;

import java.io.IOException;

import com.jme3.bounding.BoundingVolume;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.scene.control.AreaUtils;
import com.jme3.scene.control.Control;

public class SkipLodControll implements Control {

	private Spatial	model;

	@Override
	public void write(final JmeExporter ex) throws IOException {

	}

	@Override
	public void read(final JmeImporter im) throws IOException {

	}

	@Override
	public Control cloneForSpatial(final Spatial spatial) {
		return new SkipLodControll();
	}

	@Override
	public void setSpatial(final Spatial spatial) {
		this.model = spatial;
	}

	@Override
	public void update(final float tpf) {

	}

	@Override
	public void render(final RenderManager rm, final ViewPort vp) {
		final BoundingVolume bv = this.model.getWorldBound();

		final Camera cam = vp.getCamera();
		final float newDistance = bv.distanceTo(vp.getCamera().getLocation());
		final float area = AreaUtils.calcScreenArea(bv, newDistance, cam.getWidth());
		System.out.println(area);
		if (area < 150) {
			this.model.setCullHint(CullHint.Always);
		} else {
			this.model.setCullHint(CullHint.Never);
		}
	}
}

As you can see, this is pretty much as primitive as it gets. However my problem is, the render is of course not called for the culled spatials. I however do not want to give a specific camera to the controll, as I need several cameras at different positions.
Is there any clean way to do this?

I’ve got several ideas:

a)
You could use a Visitor to update the Camera as soon as you switch cameras - just let the Visitor start at rootNode and if it detects a Spatial with SkipLodControll (with 2x L?) - then set the camera.
→ not a perfect solution, but it might work (if camera switches are rare)

b)
You could have a CameraAppState or otherwise global system (“CameraManagerSingleton” or likewise) to which you attach your SkipLodControll instances as listeners to an event (simple callback). Then you send an event when you change the camera and your listeners will react by internally changing the reference to the new Camera.
→ good solution, but…
The problem with this idea is: you have a hard reference, a permanent link from SkipLodControls to the global camera system - and as a result you lose automatic garbage collection.

How to fix this idea (b)?

  • The first solution to this: let your SkipLodControll poll the current Camera each frame (cam = appStates.getCameraAppState().getActiveCamera()) - this avoids the need to register as a listener, but you are polling, which means that you have at least one lookup (my example is bad - it creates 2 method calls, you could simply do this instead: cam = app.sActiveCamera - which would be the fastest polling possible.

  • Another solution would be to use the WeakReference API that Java offers to avoid hard references.

Final words:
I don’t really know if I understood you correctly regarding the “multiple cameras” part. In my monkey game I have different cameras too (one top-down ortho camera, and then 3 different perspective cameras). But I don’t know if that is the same thing that you want to achieve or at least similar.

Maybe any of my thoughts could help? :chimpanzee_smile:

I think most LOD controls grab the camera on the first call to render()… as long as things are rendered at least once then you could do it that way, else you are looking at more complicated solutions.

Personally, I’d probably put one LOD control on the ship and have it responsible for showing/hiding the smaller bits on the ship.

1 Like

Ah, now I see the problem. Well, you would need to do some of the stuff I wrote in the update() call then. :chimpanzee_rolleyes:

Thanks for the suggestions so far,

the reason I ask, is that I have multiple cameras at the same time, so for one frame i might need to switch the cullhint several time. This kind of prevents me from using any fixed reference to a single camera.

Maybee I should do this the other way around, and try to hook into the renderer instead.

I built this kind of stuff into my pager. Things know what zones they are in already and the zones know what’s in them. As a zone transitions from one LOD to another it is therefore pretty easy to let all of the other things know.

May not work in your situation but it is simple.