Isometric 3D in JPanel

Started by dunkedbiscuit, January 12, 2012, 01:03:43 AM

Previous topic - Next topic

dunkedbiscuit

Hi

I've got (I think) isometric 3D working, which is pretty nice. However, when I try to put it into a JPanel I get an error like this:

Exception in thread "main" java.lang.NullPointerException
        at org.lwjgl.opengl.GL11.glMatrixMode(GL11.java:2052)
        at orthogonal_test.Main.loop(Main.java:56)
        at orthogonal_test.Main.main(Main.java:22)


And here's all the code:

package orthogonal_test;

import com.threed.jpct.*;
import org.lwjgl.opengl.GL11;

import javax.swing.*;
import java.awt.*;

/**
* A simple HelloWorld using the OpenGL-renderer.
* @author EgonOlsen
*
*/
public class Main {

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

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

public Main() throws Exception {
world = new World();
world.setAmbientLight(0, 255, 0);

box = Primitives.getBox(1f, 1f);
box.build();
world.addObject(box);

                float dist = 30f;

                cam = world.getCamera();
                cam.setPosition( new SimpleVector( dist, dist, dist ) );
                cam.lookAt( new SimpleVector( 0, 0, 0 ) );
}

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

                JFrame frame = new JFrame();
                Canvas canvas = buffer.enableGLCanvasRenderer();
                frame.add(canvas);
                frame.setVisible(true);
                frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
               
while ( frame.isVisible() ) {

buffer.clear(java.awt.Color.BLACK);
world.renderScene(buffer);
world.drawWireframe(buffer, java.awt.Color.YELLOW);
buffer.update();

                       
                        GL11.glMatrixMode(GL11.GL_PROJECTION);
                        GL11.glLoadIdentity();
                        float scalar = 50f;
                        //GL11.glOrtho(-13, 13, -1, 10, -30, 100);
                        GL11.glMatrixMode(GL11.GL_MODELVIEW);
                        GL11.glLoadIdentity();
                        GL11.glRotatef(35.264f, 1.0f, 0.0f, 0.0f);
                        GL11.glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
                        GL11.glScalef(1.0f, 1.0f, -1.0f);
                        GL11.glTranslatef( 0, 0, 0 );
                       
                        GL11.glBegin(GL11.GL_LINES);
                        GL11.glColor3f(1.0f, 0.0f, 0.0f);
                        GL11.glVertex3d(0, 0, 0);
                        GL11.glVertex3d(10, 0, 0);
                        GL11.glEnd();

                        GL11.glBegin(GL11.GL_LINES);
                        GL11.glColor3f(0.0f, 1.0f, 0.0f);
                        GL11.glVertex3d(0, 0, 0);
                        GL11.glVertex3d(0, 10, 0);
                        GL11.glEnd();

                        GL11.glBegin(GL11.GL_LINES);
                        GL11.glColor3f(0.0f, 0.0f, 1.0f);
                        GL11.glVertex3d(0, 0, 0);
                        GL11.glVertex3d(0, 0, -10);
                        GL11.glEnd();

buffer.displayGLOnly();
Thread.sleep(10);
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
System.exit(0);
}
}


Any help / code snippets would be greatly appreciated.

EgonOlsen

When using the GLCanvasRenderer, the gl context might or might not have been created when entering the loop, because it all happens in another thread. Apart from that, it wouldn't work anyway this way, because the thread which does the rendering isn't the thread of your main loop. COnsider to put your code into an implementation of the IPainterListener interface instead.

dunkedbiscuit

#2
I've tried putting the opengl code in the startPainting() method, but there's no effect. I also put it in finishedPainting() but that didn't work. Am I missing something crucial?

package orthogonal_test;

import com.threed.jpct.*;
import org.lwjgl.opengl.GL11;

import javax.swing.*;
import java.awt.*;

/**
* A simple HelloWorld using the OpenGL-renderer.
* @author EgonOlsen
*
*/
public class Main implements IPaintListener {

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

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

public Main() throws Exception {
world = new World();
world.setAmbientLight(0, 255, 0);

box = Primitives.getBox(1f, 1f);
box.build();
world.addObject(box);

                float dist = 30f;

                cam = world.getCamera();
                cam.setPosition( new SimpleVector( dist, dist, dist ) );
                cam.lookAt( box.getTransformedCenter() );
}

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

                JFrame frame = new JFrame();
                frame.setSize( 800, 600 );
                frame.setResizable(false);
                Canvas canvas = buffer.enableGLCanvasRenderer();
                frame.add(canvas);
                frame.setVisible(true);
                frame.setDefaultCloseOperation( JFrame.HIDE_ON_CLOSE );
               
while ( frame.isVisible() ) {

buffer.clear(java.awt.Color.BLACK);
world.renderScene(buffer);
world.draw(buffer);
buffer.update();

buffer.displayGLOnly();
Thread.sleep(10);
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
System.exit(0);
}

        public void startPainting()
        {
            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glLoadIdentity();
            GL11.glOrtho(-13, 13, -1, 10, -30, 100);
            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            GL11.glLoadIdentity();
            GL11.glRotatef(35.264f, 1.0f, 0.0f, 0.0f);
            GL11.glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
            GL11.glScalef(1.0f, 1.0f, -1.0f);
            GL11.glTranslatef( 0, 0, 0 );

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(1.0f, 0.0f, 0.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(10, 0, 0);
            GL11.glEnd();

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(0.0f, 1.0f, 0.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(0, 10, 0);
            GL11.glEnd();

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(0.0f, 0.0f, 1.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(0, 0, -10);
            GL11.glEnd();
        }

        public void finishedPainting()
        {
           GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glLoadIdentity();
            float scalar = 50f;
            //GL11.glOrtho(-13, 13, -1, 10, -30, 100);
            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            GL11.glLoadIdentity();
            GL11.glRotatef(35.264f, 1.0f, 0.0f, 0.0f);
            GL11.glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
            GL11.glScalef(1.0f, 1.0f, -1.0f);
            GL11.glTranslatef( 0, 0, 0 );

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(1.0f, 0.0f, 0.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(10, 0, 0);
            GL11.glEnd();

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(0.0f, 1.0f, 0.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(0, 10, 0);
            GL11.glEnd();

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(0.0f, 0.0f, 1.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(0, 0, -10);
            GL11.glEnd();
        }
}

EgonOlsen

Quote from: dunkedbiscuit on January 12, 2012, 09:38:20 AM
Am I missing something crucial?
Yes. You aren't adding your IPaintListener to the FrameBuffer...

dunkedbiscuit

Added the IPaintListener. Now the canvas is simply black. I think that the code in the startPainting method isn't called at all since i placed some text to be printed to the console there, and nothing is being printed.

EgonOlsen

Try to add a repaint()-call just like the HelloWorld example for AWT does.

dunkedbiscuit

I've added one, and now I can see the cube. However, the code in startPainting and finishedPainting isn't being called.

package orthogonal_test;

import com.threed.jpct.*;
import org.lwjgl.opengl.GL11;

import javax.swing.*;
import java.awt.*;

/**
* A simple HelloWorld using the OpenGL-renderer.
* @author EgonOlsen
*
*/
public class Main implements IPaintListener {

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

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

public Main() throws Exception {
world = new World();
world.setAmbientLight(0, 255, 0);

box = Primitives.getBox(1f, 1f);
box.build();
world.addObject(box);

                float dist = 30f;

                cam = world.getCamera();
                cam.setPosition( new SimpleVector( dist, dist, dist ) );
                cam.lookAt( box.getTransformedCenter() );
}

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

                JFrame frame = new JFrame();
                frame.setSize( 800, 600 );
                frame.setResizable(false);
                Canvas canvas = buffer.enableGLCanvasRenderer();
                frame.add(canvas);
                frame.setVisible(true);
                frame.setDefaultCloseOperation( JFrame.HIDE_ON_CLOSE );
               
while ( frame.isVisible() ) {

buffer.clear(java.awt.Color.BLACK);
world.renderScene(buffer);
world.draw(buffer);
buffer.update();

buffer.displayGLOnly();
                        canvas.repaint();
Thread.sleep(10);
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
System.exit(0);
}

        public void startPainting()
        {
            System.out.println("here");
            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glLoadIdentity();
            GL11.glOrtho(-13, 13, -1, 10, -30, 100);
            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            GL11.glLoadIdentity();
            GL11.glRotatef(35.264f, 1.0f, 0.0f, 0.0f);
            GL11.glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
            GL11.glScalef(1.0f, 1.0f, -1.0f);
            GL11.glTranslatef( 0, 0, 0 );

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(1.0f, 0.0f, 0.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(10, 0, 0);
            GL11.glEnd();

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(0.0f, 1.0f, 0.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(0, 10, 0);
            GL11.glEnd();

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(0.0f, 0.0f, 1.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(0, 0, -10);
            GL11.glEnd();
        }

        public void finishedPainting()
        {
            System.out.println("here");
            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glLoadIdentity();
            GL11.glOrtho(-13, 13, -1, 10, -30, 100);
            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            GL11.glLoadIdentity();
            GL11.glRotatef(35.264f, 1.0f, 0.0f, 0.0f);
            GL11.glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
            GL11.glScalef(1.0f, 1.0f, -1.0f);
            GL11.glTranslatef( 0, 0, 0 );

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(1.0f, 0.0f, 0.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(10, 0, 0);
            GL11.glEnd();

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(0.0f, 1.0f, 0.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(0, 10, 0);
            GL11.glEnd();

            GL11.glBegin(GL11.GL_LINES);
            GL11.glColor3f(0.0f, 0.0f, 1.0f);
            GL11.glVertex3d(0, 0, 0);
            GL11.glVertex3d(0, 0, -10);
            GL11.glEnd();
        }
}

dunkedbiscuit

Got it to work! It seems I forgot to use the framebuffer's setPaintListenerState() method to activate the IPaintListener. Thanks for your help. Do you know how to add a box where the axis lines are being drawn, i.e. in the centre of them, so that I can see if the view is truly isometric? Further, will object selection through Interact2D continue to work with the isometric view, and if so, how could I implement it to select objects in isometric view?

EgonOlsen

No. A lot of things won't work as expected if you start to fiddle around with gl settings and projections behind the engine's back and i don't recommend to do this. I'm sorry, but i'm not able to support this kind of adventure much further than what i already did. You have the option to hook into the pipeline and do these things, but if you do, you are on your own, i'm afraid. Just expect the unexpected... ;)

dunkedbiscuit

Lol. I guess you're right. I'll have to look at the source for the Interact2D methods. Perhaps a orthogonal mode would be something for a new release?

AGP

So by your count, Egon, this makes how many orthogonal requests? : -)

EgonOlsen

Three, four, hundreds...i don't know exactly, but it's not going to happen.

AGP