How to blit a pic into a diferent size

Started by Melssj5, March 03, 2008, 06:01:33 PM

Previous topic - Next topic

Melssj5

Hi, how can I blit an image in a diferent size than the original pic.

I have a pic of 800x600 and I want it to be blitted on all the screen but the resolution is not always of 800x600 so I need it to be resized on somehow.

Is there anyway to change the size of the original pic?

Is there anyway of changing the size of the texture used for blitting?
Nada por ahora

EgonOlsen

Currently, this is not possible "out of the box" albeit i think that i could be done by using some math and a billboarded quad. The question what exactly the picture's function is. Is it a backdrop, a loading screen...what is it?

Melssj5

A loading screen and also for the main menu of my game.
Nada por ahora

EgonOlsen

#3
Here's a class that scales a texture to fit the screen by actually scaling a textured plane. It requires the lastest 116rc2-version (available from the news-section and updated today(!) (without changing the name...so if you already downloaded 116rc2 before, grab it again)) to work correctly. If you can't or don't want to use 116rc2, you have to put a world.renderScene(<FrameBuffer>) in the first line of the adjustPlane()-method as a workaround.
The basic idea of this approach is to make a textured plane fill the whole screen no matter where the camera is looking. This way, you can use this for a single World with no camera movement just to paint the scaled texture or for a complex world with lots of objects as a backdrop, transparent overlay or whatever...
Maybe i should add this to the util-package...it seems to be handy for some things...


import com.threed.jpct.*;

public class ScreenFiller {

private World world;
private FrameBuffer buffer;
private Object3D plane;
private MyController adjuster=null;

public static void main(String[] args) throws Exception {
new ScreenFiller().loop();
}

public ScreenFiller() throws Exception {
world = new World();
TextureManager.getInstance().addTexture("planeTex", new Texture("alpha.png"));
plane = Primitives.getPlane(1, 1);
plane.setTexture("planeTex");
plane.build();
plane.setAdditionalColor(java.awt.Color.WHITE);
world.addObject(plane);
plane.build();
adjuster=new MyController();
plane.getMesh().setVertexController(adjuster, IVertexController.PRESERVE_SOURCE_MESH);
}

private void adjustPlane() {
float depth=10f; // Can be almost anything, but i think 10 is reasonable
SimpleVector upperLeft=Interact2D.reproject2D3D(world.getCamera(), buffer, 0, 0, depth);
SimpleVector lowerLeft=Interact2D.reproject2D3D(world.getCamera(), buffer, 0, buffer.getOutputHeight(), depth);
SimpleVector lowerRight=Interact2D.reproject2D3D(world.getCamera(), buffer, buffer.getOutputWidth(), buffer.getOutputHeight(), depth);
SimpleVector upperRight=Interact2D.reproject2D3D(world.getCamera(), buffer, buffer.getOutputWidth(), 0, depth);
Matrix camMat=world.getCamera().getBack().cloneMatrix();
SimpleVector camPos=world.getCamera().getPosition();
camPos.matMul(camMat);
upperLeft.add(camPos);
lowerLeft.add(camPos);
lowerRight.add(camPos);
upperRight.add(camPos);
Matrix resMat=camMat.invert3x3();

upperLeft.matMul(resMat);
lowerLeft.matMul(resMat);
lowerRight.matMul(resMat);
upperRight.matMul(resMat);
adjuster.setNewBounds(upperLeft, lowerLeft, upperRight, lowerRight);
plane.getMesh().applyVertexController();
}

private void loop() throws Exception {
buffer = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_NORMAL);
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
buffer.enableRenderer(IRenderer.RENDERER_OPENGL);

// The adjustPlane()-method is flexible enough to handle arbitrary camera positions.
// world.getCamera().rotateY((float)Math.PI/12.45555f);
// world.getCamera().moveCamera(Camera.CAMERA_MOVEIN, 50f);

adjustPlane();
while (!org.lwjgl.opengl.Display.isCloseRequested()) {
buffer.clear(java.awt.Color.BLUE);
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
Thread.sleep(100);
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
System.exit(0);
}

private static class MyController extends GenericVertexController {

private SimpleVector[] poss=new SimpleVector[4];

public void apply() {
SimpleVector[] dstMesh=this.getDestinationMesh();
for (int i=0; i<4; i++) {
dstMesh[i]=poss[i];
}
}

public void setNewBounds(SimpleVector ul, SimpleVector ll, SimpleVector ur, SimpleVector lr) {
poss[0]=ul;
poss[1]=ll;
poss[2]=ur;
poss[3]=lr;
}
}
}

EgonOlsen

#4
Ok, i've updated the rc2-package again. It now includes a class "Overlay" in util that basically does what the posted code above does with some enhancements and a little more magic involved. So you can either use the ScreenFiller as a starting point or try this new class and see if it fits your needs.

Melssj5

 :-\ :-\

MM. Sumarizing. Its a plane (Object 3D) with a texture applied and it renders into the FrameBuffer. Its a trick to have a texture in all the screen.

Actually I was using something similar but the problem is that the quiality of the result is not so good. Especially in software mode.

I have noticed that the blitted images look MUCH better that when are applied as textures, and thats the reason for trying to change to blitting instead of texturing. I have tryied the Overlay class and I d k why but its always in front of the rest of my objects3D, anyway is not what I looking for.
Nada por ahora

EgonOlsen

#6
Of course it looks worse, because it is scaled. There's nothing you can do about it except using a higher resolution texture or use simple blitting but with different sized textures for all possible resolutions, which is questionable. Or use one default image and leave a black border around in it resolutions that are higher than the texture's.

The Overlay class lets you specify a depth to position the overlay in space. However, after writing all this, i'm not sure anymore what you really wanted. Maybe you can illustrate it with a screen shot?