我正在使用一个有趣的世界编辑器,并使用Java和JLWGL。到目前为止一切正常。现在,我尝试创建一个窗口,可以在其中添加要使用的地形或新模型。问题是,当我尝试从主界面创建地形并创建并显示该地形时,但是当我尝试通过按钮事件监听器调用该地形时,出现错误: 在当前线程中未找到OpenGL上下文。 我基本上知道为什么会得到错误。我用来获取输入并单击按钮的框架没有opengl上下文。
现在的问题是:如何将opengl上下文获取到当前框架?欢迎任何帮助,如果您需要其他课程,请告诉我。
真正的错误是因为如果我运行generateTerrain(args); 从我的主要观点来看,它工作得非常好,即使我在eventlistener addTerrain.addActionListener中 使用了它,然后在 generateTerrain(1,terrains)中 使用了它 ;
这是我的主班:
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); } }
首先,要了解实际的问题:当调用线程中当前存在OpenGL上下文时,才可以发出OpenGL调用。OpenGL使用线程本地存储来跟踪任何线程的当前上下文。您创建的LWJGL 2 Display的OpenGL上下文将在名为Display.create()的线程中处于当前状态,该线程可能在主线程调用的未公开DisplayManager类中的某个位置。另一方面,AWT(和Swing处于这种程度)使用单独的专用线程来处理窗口消息事件,例如单击按钮,并将使用该线程调用事件回调。并且LWJGL Display的OpenGL上下文在该AWT事件线程中不是当前的。
我的建议:创建一个渲染命令队列(可能是java.lang.Runnable的实例),该队列将被轮询,并且所包含的渲染命令由当前LWJGL Display OpenGL上下文的线程处理,并让您的AWT回调将渲染命令发送到那个队列。