GUI or swing??? help!!!

Started by majitri, October 04, 2009, 12:13:17 PM

Previous topic - Next topic

majitri

hello, I think to make a window in the engine jpct can do by creating your own GUI or awt / swing (do not know if there are more forms).
I know what are the pros and cons, because I've done my project creating my GUI, but has many windows and there comes a point where it goes slower and do not know why

JavaMan

Swing is a library to create GUIs in Java. Your question is rather unclear.

jpct can paint into any Java component by calling
yourframebuffer.display(java.awt.Graphics);


majitri

already, but how do I swing interface within jpct? thanks

majitri

what I mean is how to represent such a JButton

JavaMan

So, you want to put a Swing component on top of jpct? Something like this http://www.jpct.net/forum2/index.php/topic,1338.0.html, only with software:swing.

Or, do you want like 3D Swing objects in a jpct world?

majitri

I do windows with Swing components, something like what you put first, as the link

JavaMan

Ok, got it.

I think what you want to look into is the FrameBuffer.blit method. http://www.jpct.net/doc/ I haven't used the method, but I know others have talked about it. I built a test case here:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package version;
import com.threed.jpct.*;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.image.BufferedImage;
/**
*
* @author vanceman
*/
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)throws Exception {
        // TODO code application logic here

        FrameBuffer buffer = new FrameBuffer(800,600,FrameBuffer.SAMPLINGMODE_NORMAL);
       
        World world = new World();
        Camera cam = world.getCamera();
        cam.moveCamera(cam.CAMERA_MOVEOUT, 5);

        JFrame render_frame = new JFrame("jpct blit test.!!!");
        render_frame.setSize(810,610);
        render_frame.setDefaultCloseOperation(render_frame.EXIT_ON_CLOSE);
        render_frame.setVisible(true);


        JButton button = new JButton("Simple JPCT blit");
        //I don't know how to manually size a JButton, so I do it this way. ;)
        JFrame frame2 = new JFrame();
        frame2.setLayout(new java.awt.GridLayout(1,1));
        frame2.add(button);
        frame2.pack();
        frame2.setVisible(true);

        //Get the image RGB pixel data
        BufferedImage image = new BufferedImage(button.getWidth(),button.getHeight(),BufferedImage.TYPE_INT_RGB);
        button.paint(image.createGraphics());
        int[] data =  image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, button.getWidth());

        //some other stuff so that we see something
        Object3D box = Primitives.getBox(1, 1);
        box.build();
        world.addObject(box);

        //Now the fun stuff.
        while(true){
            buffer.clear(java.awt.Color.BLACK);
            world.renderScene(buffer);
            world.draw(buffer);
            buffer.update();
            buffer.blit(data, image.getWidth(), image.getHeight(), 0, 0, 100, 100, image.getWidth(), image.getHeight(), true);
            buffer.display(render_frame.getGraphics());
            box.rotateY((float)Math.PI/14);
        }
    }

}



EgonOlsen

The problem with this approach is, that it blits int[]-arrays, which is pretty slow when using a hardware renderer. Which renderer are you using btw?

Anyway, i'm still not sure what the actual question is...do you want to use swing and it doesn't work? Or it does work, just too slow? Or are you doing something else, which is too slow? I don't really get the question in this thread... ???

majitri

   
I had done creating my own GUI library, and this is what is slow.
Then wanted to try making it swing to see if it was so slow to display menus, I think I found an example that I can help SwingGL

majitri

I mean, I built my own GUI components that can be blitted into the LWJGL-window by jPCT

EgonOlsen

That shouldn't be too slow unless you are recreating the blitting textures or int[]s each frame. Try to copy your gui data into existing textures by using an ITextureEffect and do this only if the gui has been updated, not for each frame. That should actually be fast enough.

majitri

How do I use this to say about ITextureEffect?

EgonOlsen

That's a replacement for blitting int[]s directly. Instead of just blitting the int[], you are filling the int[] of the Texture via your own implementation of an ITextureEffect. That way, you enable jPCT to only upload the texture if something has changed (i.e. if the effect has been applied). If you are blitting int[]s, you always trigger a new upload each frame.
If you are not blitting int[]s at all in your code, this doesn't apply, of course.

paulscode

I assume your GUI could be written onto a BufferedImage.  If you are having trouble getting started, here is one possible ITextureEffect implementation for copying the contents of an AWT.Image onto a texture:

    private class AWTImageTextureEffect implements ITextureEffect
    {
        /**
         * Ignored by AWTImageTextureEffect.
         * @param tex The texture.
        */
        @Override
        public void init( Texture tex)
        {}

        /**
         * Changes the contents of the texture.
         * @param dest Pixels to change.
         * @param dest Current pixels.
        */
        @Override
        public void apply(int[] dest, int[] source)
        {
            PixelGrabber pg = new PixelGrabber( guiImage, 0, 0,
                                                imageWidth,
                                                imageHeight,
                                                dest, 0, textureWidth );
            try
            {
                pg.grabPixels();
            }
            catch( InterruptedException e )
            {
                System.err.println( "interrupted waiting for pixels!" );
                return;
            }
            if( ( pg.getStatus() & ImageObserver.ABORT ) != 0 )
            {
                System.err.println( "image fetch aborted or errored" );
                return;
            }
        }
    }


And here is a simple example for how to set the effect up for a Quad:

        guiImage = new BufferedImage( imageWidth, imageHeight,
                                   BufferedImage.TYPE_4BYTE_ABGR );

        //only needed if image dimensions are not powers of 2:
        textureWidth = nextPowerOf2( imageWidth);
        textureHeight = nextPowerOf2( imageHeight );

        //these can both be 1.0f if image dimensions are powers of 2:
        float uw = (float) imageWidth / (float) textureWidth;
        float uh = (float) imageHeight / (float) textureHeight;

        guiTexture = new Texture( textureWidth, textureHeight, Color.BLACK );
        TextureManager.getInstance().addTexture( "GUI Texture", guiTexture );
        guiTexture.setEffect( new AWTImageTextureEffect() );
        SimpleVector br = new SimpleVector( 0, 0, 0 );
        SimpleVector bl = new SimpleVector( imageWidth, 0, 0 );
        SimpleVector tr = new SimpleVector( 0, imageHeight, 0 );
        SimpleVector tl = new SimpleVector( imageWidth, imageHeight, 0 );
        guiQuad = new Object3D( 2 );
        guiQuad.addTriangle( tl, 0, 0, bl, 0, uh, br, uw, uh,
                          TextureManager.getInstance().getTextureID( "GUI Texture" ) );
        guiQuad.addTriangle( br, uw, uh, tr, uw, 0, tl, 0, 0,
                          TextureManager.getInstance().getTextureID( "GUI Texture" ) );
        guiQuad.build();
        world.addObject( guiQuad );
        guiQuad.setVisibility( true );

TODO: Do something with the GUI quad (use it as an overlay, for example)
...

    private static int nextPowerOf2( int x )
    {
        --x;
        x |= x >> 1;
        x |= x >> 2;
        x |= x >> 4;
        x |= x >> 8;
        x |= x >> 16;
        return ++x;
    }


With this, you could draw your GUI onto the guiImage (with getGraphics(), for example).  Then, any time something changes, you would simply call:
            synchronized( frameBuffer.getLock() )
            {
                guiTexture.applyEffect();
            }


One more note - there are a couple of ways you could add transparency to the above guiTexture.  One way would be to use the Alpha channel, and the other way would be to use black (0,0,0) as the transparent color.

majitri

You say:

  public void apply (int [] dest, int [] source)
         (
             PixelGrabber pg = new PixelGrabber (guiImage, 0, 0,
                                                 imageWidth,
                                                 imageHeight,
                                                 dest, 0, textureWidth);

but where guiImage and get those parameters?