I am trying to create a four way symmetric program that has 1 camera viewing a specific scene, but just flipping the view of the camera for each of the 4 panels.
For example: symmetry
Quadrant 1 would be the regular orientation of the world with positive x to the right and positive y upwards. Quadrant 2 would be positive x to the left and positive y upwards, and so on.
I've figured out a way to draw the same camera view in multiple panels by starting and ending my spritebatch multiple times (not sure if this is a bad thing but it's the way I got it to work) and changing the glViewport of each panel.
batch.setProjectionMatrix(cam.combined);
batch.begin();
Gdx.gl.glViewport(0,Gdx.graphics.getHeight()/2,Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
batch.draw(img, 0, 0);
batch.end();
batch.begin();
Gdx.gl.glViewport(0,0,Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
batch.draw(img, 0, 0);
batch.end();
batch.begin();
Gdx.gl.glViewport(Gdx.graphics.getWidth()/2,0,Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
batch.draw(img, 0, 0);
batch.end();
batch.begin();
Gdx.gl.glViewport(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2,Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
batch.draw(img, 0, 0);
batch.end();
I think a linear transformation would do it but I haven't worked with libgdx or linear algebra enough to see an immediate clear answer.
Any help would be appreciated. Thanks.
There are a couple ways you can do this.
Flipping the camera
Keep a matrix around for doing the flips without messing with the camera.
private final Matrix4 tmpM = new Matrix4();
Then you can flip it for the three flipped quadrants:
Gdx.gl.glViewport(0,Gdx.graphics.getHeight()/2,Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
Gdx.gl.glViewport(0,0,Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
batch.setProjectionMatrix(tmpM.set(cam.combined).scl(1, -1, 1));
batch.begin();
batch.draw(img, 0, 0);
batch.end();
Gdx.gl.glViewport(Gdx.graphics.getWidth()/2,0,Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
batch.setProjectionMatrix(tmpM.set(cam.combined).scl(-1, -1, 1));
batch.begin();
batch.draw(img, 0, 0);
batch.end();
Gdx.gl.glViewport(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2,Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
batch.setProjectionMatrix(tmpM.set(cam.combined).scl(-1, -1, 1));
batch.begin();
batch.draw(img, 0, 0);
batch.end();
FrameBuffer
If your scene is complex, this may be faster because the actual scene is drawn only one time. Create your frame buffer object in resize. The try/catch is because some old or budget phones don't support RGBA8888 color in a frame buffer object.
public void resize (int width, int height){
if (frameBuffer != null) frameBuffer.dispose();
try {
frameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, width/2, height/2, false);
} catch (GdxRuntimeException e) {
frameBuffer = new FrameBuffer(Pixmap.Format.RGB565, width/2, height/2, false);
}
}
Then use it as follows:
frameBuffer.begin();
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
frameBuffer.end();
Texture fbTex = frameBuffer.getColorBufferTexture();
batch.getProjectionMatrix().idt();
batch.begin();
batch.draw(fbTex, -1, 1, 1, -1);
batch.draw(fbTex, -1, 0, 1, 1);
batch.draw(fbTex, 0, 0, 1, 1);
batch.draw(fbTex, 0, 1, 1, -1);
batch.end();