Super Smash Bros Camera (Solved)

I’m trying to create a camera that encompasses a group of objects. I have a possibly working formula, but I don’t like the results. Maybe someone could help me?

This is my code:
[java]
public void updateCamera() {
Vector3f targetLocation;
Vector3f leftMostPosition = Vector3f.ZERO;
Vector3f rightMostPosition = Vector3f.ZERO;
for (int i = 0; i < 4; i++) {
if (players[i] != null) {
if (players[i].getLocalTranslation().x < leftMostPosition.x) {
leftMostPosition = players[i].getLocalTranslation();
}

            if (players[i].getLocalTranslation().x &gt; rightMostPosition.x) {
                rightMostPosition = players[i].getLocalTranslation();
            }
        }
    }

    targetLocation = rightMostPosition.subtract(leftMostPosition).divide(2f).add(leftMostPosition);
    float cameraDistance = rightMostPosition.distance(leftMostPosition) + 4f;
    targetLocation.z = Math.min(Math.max(cameraDistance, 4f), 100f);
    cam.setLocation(targetLocation);
}

[/java]

What are the results that you don’t like…?
And I’ve never played the game before, but I am guessing the camera is supposed to back up until all players/NPCs are visible?

My first guess would be that the word frustum should appear in the code above at some point, since this is what needs to encompass everything.

I was 100% certain frustum was the render cut off on the camera. I need the camera to adjust its distance to keep all characters visible on screen, while following, say, a center point between all characters. This is so that all players share one view rather than split screen gameplay. If you do a Google search on super smash bros and watch a video, you may know what I’m talking about.

@TrashCaster
The camera’s frustum has near and far for clipping, but it also has left, right, bottom, top.

See: https://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/renderer/Camera.java?r=8464

But I don’t want to cut out rendering. I want the cameras view to expand so that players going out of view are still seen.

This has nothing to do with frustum. Its all to do with distancing the camera from the stage to allow more to be visible as the players spread apart.

@TrashCaster said: But I don't want to cut out rendering. I want the cameras view to expand so that players going out of view are still seen.

This has nothing to do with frustum. Its all to do with distancing the camera from the stage to allow more to be visible as the players spread apart.

frustum defines a shape + distance that is rendered.

If you want to see how to use the frustum to do what you are trying to, take a look at the shadow renderers. They use the camera frustum to position the shadow cam to ensure everything that needs to be rendered in the shadow map is rendered.

frustum != culling based on frustum

This is the code I use in the atlas generator for SimArboreal to make sure that the entire tree (and only the tree) is in view to optimize the atlas. See if you can follow it. I think it’s reasonably well commented:

https://code.google.com/p/simsilica-tools/source/browse/trunk/SimArboreal-Editor/src/main/java/com/simsilica/arboreal/AtlasGeneratorState.java#441

I think you should be able to adapt it to your use-case.

1 Like
@pspeed said: This is the code I use in the atlas generator for SimArboreal to make sure that the entire tree (and only the tree) is in view to optimize the atlas. See if you can follow it. I think it's reasonably well commented:

https://code.google.com/p/simsilica-tools/source/browse/trunk/SimArboreal-Editor/src/main/java/com/simsilica/arboreal/AtlasGeneratorState.java#441

I think you should be able to adapt it to your use-case.

That was exactly what I needed thanks. :slight_smile:

I’ll change this to solved.

[java]
BoundingVolume totalBounds = null;
for (int i = 0; i < 4; i++) {
if (players[i] != null) {

            if (totalBounds == null) {
                totalBounds = players[i].getWorldBound();
            } else {
                totalBounds.merge(players[i].getWorldBound());
            }
        }
    }
    
    if (totalBounds == null) {
        return;
    }
    BoundingBox bb = (BoundingBox) totalBounds;

    Vector3f target = bb.getCenter();
    Vector3f minCorner;
    Vector3f maxCorner;
    minCorner = bb.getMin(null);
    maxCorner = bb.getMax(null);
    target.z = Math.max(maxCorner.x - minCorner.x, maxCorner.y - minCorner.y);
    cam.setLocation(target);

[/java]

EDIT: Appears I can’t edit the main post. Maybe a moderator could do it?

@TrashCaster Try to edit here.