简体   繁体   中英

How to get OpenGL context into my current thread, opengl context not found

I'm working on a world editor for fun and using Java and JLWGL. Everything is working so far. Now I tried creating a window where I can add eg a terrain or a new model to use. Problem is, when I try to create the terrain from my main it is created and shown, but when I try to call it by an button eventlistener I get the error: No OpenGL context found in the current thread. I basically know why I get the error. My frame which I use to get the input and click the button has no opengl context.

My question is now: How can I get the opengl context to my current frame? Any help is welcome, if you need other classes, let me know.

it really bugs be because if I run generateTerrain(args); from my main it works perfectly fine, just if I use it in the eventlistener addTerrain.addActionListener and there the generateTerrain(1, terrains);

This is my mainclass:

public class MainGameLoop extends JFrame{
    //CREATING THE LOADER
    final static Loader loader = new Loader();

    public static void main(String[] args) {

        //CREATING THE DISPLAY
        DisplayManager.createDisplay();


        //CREATE CAMERA
        Camera camera = new Camera(15f, 5f, 40f);

        //CREATE MASTER RENDERER
        final MasterRenderer renderer = new MasterRenderer();

        //LISTS
        final List<TexturedModel> texturedModels=new ArrayList<TexturedModel>(); 
        final List<Entity> entities=new ArrayList<Entity>();
        final List<Terrain> terrains=new ArrayList<Terrain>(); 

        //Loading the models into the VAOs
        //1
        loadTexturedModel("stall", "stall", texturedModels);
        //2
        loadTexturedModel("dragon", "white", texturedModels);
        //3
        //loadTexturedModel("lowPolyTree", "lowPolyTree", texturedModels, loader);


        //ERSTELLE ENTITIES
        //generateEntity(texturedModels.get(1-1), 15, 0, 15, 0, 180, 0, 1, entities);
        //generateEntity(texturedModels.get(3-1), 5, 0, 5, 0, 0, 0, 1, entities);
        //generateEntity(texturedModels.get(3-1), 23, 0, 8, 0, 90, 0, 0.7f, entities);


        //TEST REFLECTIVITY
        /*
        ModelTexture texture1 = entities.get(0).getModel().getTexture();
        texture1.setReflectivity(10f);
        texture1.setShineDamper(10);
        */

        //CREATE LIGHT
        Light light = new Light(new Vector3f(3000,2000,2000), new Vector3f(2.5f,2.5f,2.5f));

        //CREATE TERRAIN
        //generateTerrain(0, terrains);
        //generateTerrain(1, terrains);

        ////////////////////////////////////////////////////////////////////
        //WORLD EDITOR FENSTER
        ////////////////////////////////////////////////////////////////////

        //ERSTELLE FENSTER
        final JFrame f=new JFrame("Map Editor"); 

        //MENÜLEISTE
        JMenuBar menuBar;

        //MENÜS 
        JMenu fileMenu;         //FileMenu
        JMenu lightTerrainMenu;     //LightTerrain Menu
        JMenu modelMenu;        //ModelMenu

        //MENÜPUNKTE
        JMenuItem createNewWorld;   //New World
        JMenuItem saveWorld;        //Save
        JMenuItem loadWorld;        //Load
        JMenuItem addTree;          //AddTree
        JMenuItem addModel;         //Add Model
        JMenuItem close;            //Quit

        JMenuItem addTerrain;
        JMenuItem addLight;


        //CREATE MENUBAR
        menuBar = new JMenuBar();

        //CREATE MENUS
        fileMenu = new JMenu("File");
        lightTerrainMenu = new JMenu("Terrain/Light");
        modelMenu = new JMenu("Model");

        //CREATE MENUITEMS
        createNewWorld = new JMenuItem("New world");
        saveWorld = new JMenuItem("Save world");
        loadWorld = new JMenuItem("Load world");
        addTree = new JMenuItem("Add tree");
        addModel = new JMenuItem("Add model");
        close = new JMenuItem("Close");

        addTerrain = new JMenuItem("Add terrain");
        addLight = new JMenuItem("Add light");

        //ADD MENU ITEMS
        fileMenu.add(createNewWorld);
        fileMenu.add(saveWorld);
        fileMenu.add(loadWorld);
        fileMenu.add(close);

        lightTerrainMenu.add(addTerrain);
        lightTerrainMenu.add(addLight);

        modelMenu.add(addTree);
        modelMenu.add(addModel);


        //ADD MENUS TO MENU BAR
        menuBar.add(fileMenu);
        menuBar.add(lightTerrainMenu);
        menuBar.add(modelMenu);


        //ADD MENU TO FRAME
        f.add(menuBar, BorderLayout.NORTH);

        //CREATE WINDOW
        f.setSize(400, 300);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);  


        ////////////////////////////////////////////////////////////////////////////////////////////////
        //LISTENER LISTENER LISTENER LISTENER
        ////////////////////////////////////////////////////////////////////////////////////////////////


      //ADDTERRAIN LISTENR
        addTerrain.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {

                final JFrame f2=new JFrame("Add Terrain");
                final JLabel l1 = new JLabel("Terrain can only be: 1x1, 2x2, 3x3...");
                final JLabel l2 = new JLabel("e.g. if you enter 2 it will be a 2x2 terrain");
                Button b1=new Button("Create Terrain"); 
                final TextField tfield = new TextField("", 1);
                l1.setBounds(50, 10, 250, 30);
                l2.setBounds(50, 40, 250, 30);
                tfield.setBounds(50, 70, 130, 30);  
                b1.setBounds(50,100,120,30);  


                b1.addActionListener(new ActionListener(){  
                public void actionPerformed(ActionEvent e){  

                        String input= tfield.getText();
                        generateTerrain(1, terrains);

                }  
                });


                f2.add(b1);
                f2.add(l1);
                f2.add(l2);
                f2.add(tfield);

                f2.setSize(400,300);  
                f2.setLayout(null);

                f2.setVisible(true);

                }

        });

        //ADDMODEL LISTENER
        addModel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                final JFrame f1=new JFrame("Add Model");
                final JLabel l1 = new JLabel("NO MODEL");
                final JLabel l2 = new JLabel("NO TEXTURE");
                l1.setBounds(100, 30, 120, 30);
                l2.setBounds(250, 30, 120, 30);
                /////////////////////////
                //BUTTON ADD MODEL
                /////////////////////////
                Button b1=new Button("Choose model");  
                b1.setBounds(50,100,120,30);  

                b1.addActionListener(new ActionListener(){  
                public void actionPerformed(ActionEvent e){  
                    //CREATE FILE CHOOSER
                    JFileChooser fc = new JFileChooser();
                    FileNameExtensionFilter filter = new FileNameExtensionFilter("Object Dateien", "obj");
                    fc.setFileFilter(filter);
                    int returnVal = fc.showOpenDialog(null);
                    if(returnVal == JFileChooser.APPROVE_OPTION) {
                       System.out.println("You added the following model to your model library: " + fc.getSelectedFile().getName());
                       String currentLine = fc.getSelectedFile().getName();
                       System.out.println(currentLine);

                       String[] parts = currentLine.split("\\.");

                       String part1 = parts[0];
                       l1.setText(part1);
                    }  

                }  
                });

                /////////////////////////
                //BUTTON ADD TEXTURE
                /////////////////////////
                Button b2=new Button("Choose texture");  
                b2.setBounds(200,100,120,30);  

                b2.addActionListener(new ActionListener(){  
                    public void actionPerformed(ActionEvent e){  
                        //CREATE FILE CHOOSER
                        JFileChooser fc = new JFileChooser();
                        FileNameExtensionFilter filter = new FileNameExtensionFilter("Texture Dateien", "png");
                        fc.setFileFilter(filter);
                        int returnVal = fc.showOpenDialog(null);
                        if(returnVal == JFileChooser.APPROVE_OPTION) {
                            System.out.println("You added the following texture to your model: " + fc.getSelectedFile().getName());
                            String currentLine = fc.getSelectedFile().getName();
                            System.out.println(currentLine);

                            String[] parts = currentLine.split("\\.");

                            String part1 = parts[0];
                            l2.setText(part1);
                        }  

                    }  
                });
               Button b3=new Button("Add Model");  
                b3.setBounds(150,150,120,30);  

                b3.addActionListener(new ActionListener(){  
                    public void actionPerformed(ActionEvent e){  

                        l1.getText();
                        l2.getText();
                        //loadTexturedModel("lowPolyTree", "lowPolyTree", texturedModels, loader);
                        }  


                });


                f1.add(b1);
                f1.add(b2);
                f1.add(b3);
                f1.add(l1);
                f1.add(l2);
                f1.setSize(400,300);  
                f1.setLayout(null);

                f1.setVisible(true);

                }
        });
        //ADDTREE LISTENR
        addTree.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                //TREE

                generateEntity(texturedModels.get(3-1), 0, 0, 0, 0, 0, 0, 1, entities);
            }
        });

        //CLOSE LISTENER
        close.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                //Programm schließen

                int result = JOptionPane.showConfirmDialog((Component) null, "Unsaved changes will be lost!","Quit world editor?", JOptionPane.YES_NO_OPTION);
                if(result==0)
                System.exit(0);
            }
        });





        //////////////////////////////////////////////////////////////////////
        ////MAIN GAME LOOP
        /////////////////////////////////////////////////////////////////////
        while(!Display.isCloseRequested()){

            renderer.render(light, camera);
            DisplayManager.updateDisplay();

            camera.move();

            for(Terrain terr:terrains){
                renderer.processTerrain(terr);
            }

            for(Entity ent:entities){
                renderer.processEntity(ent);
            }


        }
        //////////////////////////////////////////////////////////////////////
        ////END MAIN GAME LOOP
        /////////////////////////////////////////////////////////////////////

        //CLEANUP
        renderer.cleanUp();
        loader.cleanUp();
        DisplayManager.closeDisplay();
    }


    public static void loadTexturedModel(String modelName, String textureName, List<TexturedModel> texturedModels){

        texturedModels.add( new TexturedModel(OBJLoader.loadObjModel(modelName,
                loader), new ModelTexture(loader.loadTexture(textureName))));
    }

    public static void generateEntity(TexturedModel model, int posX, int posY, int posZ,
            float rotX, float rotY, float rotZ, float scale, List<Entity> entities){

        entities.add(new Entity(model, new Vector3f(posX,posY,posZ), rotX, rotY, rotZ, scale));
    }
    public static void generateTerrain(int size, List<Terrain> terrains){
        terrains.add(new Terrain(size, 0, loader, new ModelTexture(loader.loadTexture("grass"))));
    }

    public static void genTexturedModel(String name1, String name2, List texturedModels){
        loadTexturedModel("lowPolyTree", "lowPolyTree", texturedModels);
    }



}

First, to understand the actual problem: OpenGL calls can ony be issued when an OpenGL context is current in the calling Thread. OpenGL uses thread-local storage to keep track of which context is current for any Thread. The OpenGL context of the LWJGL 2 Display you created will be current in the Thread that called Display.create(), which was probably somewhere in your undisclosed DisplayManager class called by the main Thread. AWT (and Swing to that extent) on the other hand uses a separate dedicated Thread to process window message events, such as the click of a button, and will use that Thread to call into your event callbacks. And the OpenGL context of the LWJGL Display will not be current in that AWT Event Thread.

My advice: Create a queue of rendering commands (possibly instances of java.lang.Runnable) which will be polled and the contained render commands processed by the Thread in which the LWJGL Display OpenGL context is current and have your AWT callbacks issue rendering commands into that queue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM