Multicamera question

I am puzzled by Cameras and Viewports (firstly, I don’t see why Viewport isn’t submerged within Camera, as they appear to have a 1:1 relationship).



I am trying to create a virtual coincidence rangefinder, which is essentially produces a single image, the top half of which is filled from a camera to the left of the observer and the bottom half from a camera situated the same distance to his right… both cameras looking ahead, and the right one able to yaw in toward the left to converge on an object. The task of using it, then, much resembles focusing a SLR type camera… the user aligns the top and bottom halves by yawing the camera on the right.



However, though I am making progress, I find that the worlds visible in these two half images show objects things are wider than they should be, perhaps by a factor of two which seems a likely mistake. But I don’t see HOW I should fix it, as telling the cameras their height is half the screen height does nothing close to the desired effect – using Camera(settings.getWidth(), settings.getHeight() / 2f) gave me two quarter-screen-height horizontal bands drawn in the bottom half of my screen.



Here is pseudo-code (because I wrap Cameras to make them Spatials, and to place Viewports within them) of what I have now that produces the proper situation of the screen filled with top and bottom half-images of the scene, but those half-images seems pressed flat in screen Y:



[java]

topLeftCamera = new Camera(settings.getWidth(), settings.getHeight()); // why not height/2f?

topLeftViewPort = getRenderManager().createMainView(“TopLeft”, topLeftCamera);

topLeftViewPort.setClearFlags(true, true, true);

topLeftViewPort.attachScene(getRootNode());

topLeftCameraHolder = new Node(); // this has to be pitched slightly to properly join the image halves – not shown here

topLeftCameraHolder.attachChild(topLeftCamera);

topLeftCameraHolder.setLocalTranslation(-baseLength / 2f, 0f, 0f);

getRootNode().attachChild(topLeftCameraHolder);

topLeftCamera.setViewPort(0f, 1f, .5f, 1f); // entire width, top half of height



bottomRightCamera = new Camera(settings.getWidth(), settings.getHeight()); // again, why not height/2f?

bottomRightViewPort = getRenderManager().createMainView(“BottomRight”, bottomRightCamera);

bottomRightViewPort.setClearFlags(true, true, true);

bottomRightViewPort.attachScene(getRootNode());

bottomRightCameraHolder = new Node(); // this is what I yaw under user control to converge

bottomRightCameraHolder.attachChild(bottomRightCamera);

bottomRightCameraHolder.setLocalTranslation(baseLength / 2f, 0f, 0f);

getRootNode().attachChild(topLeftCameraHolder);

bottomRightCamera.setViewPort(0f, 1f, 0f, .5f); // entire width, bottom half of height

[/java]

@DulcetTone said:
I am puzzled by Cameras and Viewports (firstly, I don't see why Viewport isn't submerged within Camera, as they appear to have a 1:1 relationship).


Many viewports can have the same camera.

As Paul said, viewports can share a camera. This is useful if you want to overlay some scene objects on top of your existing scene, like an overlay view.

Play around with camera.setFrustumPerspective() to get them to look right.

1 Like

This proved difficult, but I got it – thanks for the last tip.



For the benefit of others, I added some data members to my Camera wrapper to help manage the relationship of camera to viewport and viewport to screen.



MyCamera (which has a mJMECamera)

[java]



// these remember how much of screen is taken up by our viewport in X and Y

float mViewPortFractionX, mViewPortFractionY;



// from our frustum… maybe can be used from there?

float mNearClipping, mFarClipping;



// our field of view, in degrees

float mFov;



ViewPort mViewPort;



public final void setViewPort(float left, float right, float bottom, float top) {

mViewPortFractionX = (right - left);

mViewPortFractionY = (top - bottom);

getJMECamera().setViewPort(left, right, bottom, top);

}





private static float screenWidth() {

return (float)settings.getWidth();

}



private static final float screenHeight() {

return (float)settings.getHeight();

}



private static final float screenAspectRatio() {

return screenWidth() / screenHeight();

}



private final float viewPortAspectRatio() {

return screenAspectRatio() * (viewPortFractionX / viewPortFractionY);

}





private void setJmeFrustrum() {

getJMECamera().setFrustumPerspective(mFov, viewPortAspectRatio(), mNearClipping, mFarClipping);

}



// how many degrees between top and bottom edges of the screen? Or half this? I Have no idea

public final void setFOV(float f) {

mFov = f;

setJmeFrustrum();

}



public final void setClipping(float near, float far) {

mNearClipping = near;

mFarClipping = far;



setJmeFrustrum();

}



public final void setNearClipping(float f) {

mNearClipping = f;

setJmeFrustrum();

}



public final void setFarClipping(float f) {

mFarClipping = f;

setJmeFrustrum();

}

[/java]



A constructor for this Node-derived wrapper that will render undistorted into a viewport expressed in its arguments looks like this



[java]



// creates a second camera, covering the given part of the screen, ranged 0-1

// its images will be undistorted no matter what aspect ratio the viewport is

public Camera3D(String name, float left, float right, float bottom, float top) {

super();

setName(name);



mJMECam = new Camera(settings.getWidth(), settings.getHeight());



setFOV(NORMAL_FOV);

setClipping(0.5f, GraphicScene3D.sideLength);

setViewPort(left, right, bottom, top);



mViewPort = PlayerClient.get().getRenderManager().createMainView(getName(), mJMECam);

mViewPort.setClearFlags(true, true, true);

mViewPort.attachScene(getRootNode());

}

[/java]

cool, glad you got it working.

Any chance of a screenshot to better visualize what this produces?