Author Topic: Software Renderer in Swing Component and swapping out the jPCT class  (Read 8967 times)

Offline Knuffi

  • byte
  • *
  • Posts: 19
    • View Profile
Hello,

I searched this site, but did not find any hint. I read the examples which render the "Hello World" in software, OpenGL and AWTGL, but I don't get the clue.
I have two problems:
1. I want to render a scene in a JPanel. As it is not very GPU demanding, software renderer will be enough - as I read, it is the only one really working with SWING components. Can someone give me an example? I thought, I've seen one somewhere in the wiki, but I can't find it anymore.

2. Is it possible to swap the HelloWorld class out of the "GUI class"?
As the GUI of the programme I want to write is very complex, I use WindowsBuilder in Eclipse, so I want to write a jPCT class and then just call it in the GUI. Is this possible?

Thanks in advance!

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #1 on: April 05, 2012, 04:02:52 pm »
The software renderer doesn't care about Swing or AWT component. All it puts out is an Image: http://www.jpct.net/doc/com/threed/jpct/FrameBuffer.html#getOutputBuffer()

You can use that Image instance in a component of your own in any way you like, so you can easily create a "gui class" that deals with the rendered image.

Offline Knuffi

  • byte
  • *
  • Posts: 19
    • View Profile
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #2 on: April 05, 2012, 04:37:32 pm »
Ok, thanks.

But how do I manage the loop then?

Is there anywhere an example?

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #3 on: April 05, 2012, 09:01:01 pm »
Not from my side as i usually don't do any swing stuff. You don't have to use a loop. You can either do your rendering in the overriden paintComponent()-method of your new component or trigger it from anywhere you like and let the component only do the display work. In that case, you have to synchronize the rendering with the awt event dispatch thread or otherwise, you'll display corrupted images.

Offline raft

  • quad
  • ******
  • Posts: 1993
    • View Profile
    • http://www.aptalkarga.com
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #4 on: April 06, 2012, 12:03:51 pm »
I prefer to do rendering in AWT (GUI) thread as discussed in this thread. the main reason is, that way swing events layouts etc runs as expected.

for running samples, have a look at Bones' samples. all use software rendering

Offline Knuffi

  • byte
  • *
  • Posts: 19
    • View Profile
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #5 on: April 07, 2012, 05:53:16 pm »
I had a look at the bones examples, but it did not get very clear to me. This is my first try, but when starting the app, nothing is rendered.
I initialize the BoxSoft Class to create the world, the camera  and the framebuffer and give it as a Graphics to the canvas. I thought a loop is not necessary as the scene does not change or has any movement in it.

GUI:
Code: [Select]
package jPCT;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.Canvas;

public class HelloGui extends JFrame {

private JPanel contentPane;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
HelloGui frame = new HelloGui();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}



public HelloGui() throws Exception {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 600);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);

JButton btnTest = new JButton("Test 1");
btnTest.setBounds(10, 11, 89, 23);
contentPane.add(btnTest);

JButton btnTest_1 = new JButton("Test 2");
btnTest_1.setBounds(10, 45, 89, 23);
contentPane.add(btnTest_1);

JButton btnTest_2 = new JButton("Test 3");
btnTest_2.setBounds(10, 79, 89, 23);
contentPane.add(btnTest_2);

Canvas canvas = new Canvas();
canvas.setBounds(105, 10, 669, 542);
contentPane.add(canvas);

BoxSoft bs = new BoxSoft();
canvas.paint(bs.paint());

}
}

The "jPCT Class":
Code: [Select]
package jPCT;

import java.awt.Color;
import java.awt.Graphics;


import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.World;

public class BoxSoft {
private World world;
private FrameBuffer buffer;
private Object3D box;

public BoxSoft() {

world = new World();
// world.setAmbientLight(200, 255, 200);

// TextureManager.getInstance().addTexture("box", new Texture("box.jpg"));

box = Primitives.getBox(3f, 2f);
// box.setTexture("box");
// box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
world.addObject(box);

world.getCamera().setPosition(50, -50, -5);
world.getCamera().lookAt(box.getTransformedCenter());
buffer = new FrameBuffer(660, 540, FrameBuffer.SAMPLINGMODE_NORMAL);

}
public Graphics paint(){
buffer.clear(java.awt.Color.DARK_GRAY);
world.renderScene(buffer);
world.drawWireframe(buffer, Color.WHITE);
buffer.update();

return buffer.getGraphics();

}


}

Offline raft

  • quad
  • ******
  • Posts: 1993
    • View Profile
    • http://www.aptalkarga.com
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #6 on: April 07, 2012, 06:08:26 pm »
in Swing, you normally (if will do the rendering in UI thread) override paintComponent(Graphics) method to do the painting.

I dont see such thing in your code. calling canvas.paint(..) does not actually do rendering

Offline Knuffi

  • byte
  • *
  • Posts: 19
    • View Profile
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #7 on: April 07, 2012, 07:00:13 pm »
I thought the framebuffer method getGraphics does the job ...

so the jPCT Class has to be an extension of an component?

Offline raft

  • quad
  • ******
  • Posts: 1993
    • View Profile
    • http://www.aptalkarga.com
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #8 on: April 07, 2012, 07:11:22 pm »
FrameBuffer.getGraphics gives you an image output. you need to draw that image into a component and typically do that in overriden paintComponent method

Offline Knuffi

  • byte
  • *
  • Posts: 19
    • View Profile
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #9 on: April 07, 2012, 08:22:44 pm »
Is there a way to do it without extending a JPanel or JLabel or ...
because otherwise I cannot use WindowsBuilder ...

Got it at least working :
Code: [Select]
package jPCT;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.World;

public class RenderPanel extends JPanel {
private static final long serialVersionUID = 1L;

private World world;
private FrameBuffer buffer;
private Object3D box;


public RenderPanel() {
world = new World();
// world.setAmbientLight(200, 255, 200);

// TextureManager.getInstance().addTexture("box", new Texture("box.jpg"));

box = Primitives.getBox(3f, 2f);
// box.setTexture("box");
// box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
world.addObject(box);

world.getCamera().setPosition(50, -50, -5);
world.getCamera().lookAt(box.getTransformedCenter());
buffer = new FrameBuffer(660, 530, FrameBuffer.SAMPLINGMODE_NORMAL);

setPreferredSize(new Dimension(buffer.getOutputWidth(), buffer.getOutputHeight()));
setFocusable(true);
setLayout(null);

buffer.clear(java.awt.Color.DARK_GRAY);
world.renderScene(buffer);
world.drawWireframe(buffer, Color.WHITE);
buffer.update();

}
   
@Override
    public void paintComponent(Graphics g) {
        buffer.display(g);
    }
   
}
« Last Edit: April 07, 2012, 08:34:12 pm by Knuffi »

Offline raft

  • quad
  • ******
  • Posts: 1993
    • View Profile
    • http://www.aptalkarga.com
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #10 on: April 07, 2012, 08:44:27 pm »
no, AFAIK there is no other way

Offline raft

  • quad
  • ******
  • Posts: 1993
    • View Profile
    • http://www.aptalkarga.com
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #11 on: April 07, 2012, 08:51:03 pm »
if your scene and camera position really doesnt change, you can create an Image and put it into an image showing class like JLabel. but it would be a strange way for a 3D app IMHO ;)

Offline Knuffi

  • byte
  • *
  • Posts: 19
    • View Profile
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #12 on: April 07, 2012, 08:55:45 pm »
Yeah, you are right, I want to rotate at least the camera around the scene ... :)

Ok, then I will go this way further. Mysteriously WindowBuilder opens the GUI correctly.   :)

How do I update the component, e.g. when I add new objects or rotate something? How do I force the paint-method of my component?

Offline raft

  • quad
  • ******
  • Posts: 1993
    • View Profile
    • http://www.aptalkarga.com
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #13 on: April 07, 2012, 09:01:43 pm »
call repaint(). but remember it's asynchronous, it returns immediately and painting is done later on in UI thread.

paintImmediately(bounds) is synchronous but you should call in UI thread.

Code: [Select]
SwingUtilities.invokeAndWait(new Runnable() {
    public void run() {
        panel.paintImmediately(panel.getBounds());
    }
});

Offline Knuffi

  • byte
  • *
  • Posts: 19
    • View Profile
Re: Software Renderer in Swing Component and swapping out the jPCT class
« Reply #14 on: April 08, 2012, 11:11:11 am »
Got it working :)

There are two problems I still have:
1. Camera rotation left-right is ok, as it is a rotation around the z-axis, but rotation up-down is quite difficult. I will open up a new thread for this.
2. Why do the world and the frame buffer to be static?



GUI:
Code: [Select]
package jPCT;

import java.awt.EventQueue;

public class HelloGui extends JFrame {

private JPanel contentPane;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
HelloGui frame = new HelloGui();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}



public HelloGui() throws Exception {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 600);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);

JButton btnTest = new JButton("Test 1");
btnTest.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
RenderPanel.rotateleft();
repaint();
}
});
btnTest.setBounds(10, 11, 89, 23);
contentPane.add(btnTest);

JButton btnTest_1 = new JButton("Test 2");
btnTest_1.setBounds(10, 45, 89, 23);
contentPane.add(btnTest_1);

JButton btnTest_2 = new JButton("Test 3");
btnTest_2.setBounds(10, 79, 89, 23);
contentPane.add(btnTest_2);

JPanel panel = new JPanel();
panel.setBounds(109, 11, 665, 540);
contentPane.add(panel);
panel.setLayout(new BorderLayout(0, 0));

RenderPanel panel_1 = new RenderPanel();
panel.add(panel_1, BorderLayout.CENTER);


}
}

RenderPanel Class
Code: [Select]
package jPCT;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;

public class RenderPanel extends JPanel {
private static final long serialVersionUID = 1L;

static World world;
static FrameBuffer buffer;
Object3D box;
{

world = new World();
// world.setAmbientLight(200, 255, 200);

// TextureManager.getInstance().addTexture("box", new Texture("box.jpg"));

box = Primitives.getBox(3f, 2f);
// box.setTexture("box");
// box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
world.addObject(box);

world.getCamera().setPosition(50, -20, -5);
world.getCamera().lookAt(box.getTransformedCenter());
buffer = new FrameBuffer(660, 530, FrameBuffer.SAMPLINGMODE_NORMAL);}


public RenderPanel() {
setPreferredSize(new Dimension(buffer.getOutputWidth(), buffer.getOutputHeight()));
setFocusable(true);
setLayout(null);

buffer.clear(java.awt.Color.DARK_GRAY);
world.renderScene(buffer);
world.drawWireframe(buffer, Color.WHITE);
buffer.update();
}

public static void rotateleft(){
SimpleVector temp = world.getCamera().getPosition();
float rotation = (float) Math.PI/30;
temp.rotateY(-rotation);


world.getCamera().setPosition(temp);
world.getCamera().lookAt(new SimpleVector(0,0,0));

buffer.clear(java.awt.Color.DARK_GRAY);
world.renderScene(buffer);
world.drawWireframe(buffer, Color.WHITE);
buffer.update();
}


@Override
    public void paintComponent(Graphics g) {
        buffer.display(g);
    }
   
}