I've been trying to add some basic gui elements to a openGl (via LWJGL) application using nifty gui, and while I've been successful in rendering panels and static text on top of the the applications graphics, using the built-in nifty controls (e.g. an editable text field) causes the rest of the application to not render. The strange part is that I don't even have to render the gui control, merely declaring it appears to cause this problem.
Compiler ready code showing the basic layout of the problem:
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.*;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.builder.LayerBuilder;
import de.lessvoid.nifty.builder.ScreenBuilder;
import de.lessvoid.nifty.builder.TextBuilder;
import de.lessvoid.nifty.controls.textfield.builder.TextFieldBuilder;
import de.lessvoid.nifty.nulldevice.NullSoundDevice;
import de.lessvoid.nifty.renderer.lwjgl.input.LwjglInputSystem;
import de.lessvoid.nifty.renderer.lwjgl.render.LwjglRenderDevice;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.tools.TimeProvider;
public class NiftyBreaksRendering {
private Nifty nifty;
private Screen screen;
public NiftyBreaksRendering() throws Exception{
//init display
Display.setDisplayMode(new DisplayMode(640,480));
Display.create();
//init nifty gui
LwjglInputSystem inputSystem = new LwjglInputSystem();
inputSystem.startup();
nifty = new Nifty(
new LwjglRenderDevice(),
new NullSoundDevice(),
inputSystem,
new TimeProvider());
// load default styles
nifty.loadStyleFile("nifty-default-styles.xml");
// load standard controls
nifty.loadControlFile("nifty-default-controls.xml");
screen = new ScreenBuilder("start") {{
layer(new LayerBuilder("baseLayer") {{
childLayoutHorizontal();
text(new TextBuilder("test"){{
font("aurulent-sans-16.fnt");
color("#f00f");
backgroundColor("#33af");
text("l33t");
}});
//begin: lines that break the rendering
control(new TextFieldBuilder("input","asdf") {{
width("200px");
}});
//end: lines that break the rendering
}});
}}.build(nifty);
nifty.gotoScreen("start");
//init opengl
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,640,480,0,1,-1);
glMatrixMode(GL_MODELVIEW);
while(!Display.isCloseRequested())
{
//render
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glVertex2i(400,400); //Upper left
glVertex2i(450,400);//upper right
glVertex2i(450,450);//bottom right
glVertex2i(400,450);//bottom left
glEnd();
glBegin(GL_LINES);
glVertex2i(100,100);
glVertex2i(200,200);
glEnd();
nifty.render(false);
Display.update();
Display.sync(60);
}
Display.destroy();
}
public static void main(String[] args) throws Exception {
new NiftyBreaksRendering();
}
}
What would really help to diagnose this kind of problems is a link to a http://sscce.org/
I guess this is related to OpenGL states changed by Nifty OR to textures being loaded by the Nifty controls which might mess up the rest of your application.
If you could provide more or the complete code I'm pretty sure we can find the problem.
Modified answer after complete example code was provided:
Thanks for providing a complete example!
As expected the problem is, that Nifty changes OpenGL state and leaves you with OpenGL basically in undefined state. The solution is to save your OpenGL states before you call Nifty and restore it afterwards. Here is some code that does exactly that. I've added the call to nifty.update() as well so that Nifty actually updates the GUI (and makes keyboard and mouse events work):
// update nifty
nifty.update();
// save your OpenGL state
// (assuming you are in glMatrixMode(GL_MODELVIEW) all the time)
glPushMatrix();
glPushAttrib(GL_ALL_ATTRIB_BITS);
// render Nifty (this will change OpenGL state)
nifty.render(false);
// restore your OpenGL state
glPopAttrib();
glPopMatrix();
With this change to your original code your example works for me now.
NiftyGUI (as a non-shader-based render) will at some point modify the modelview matrix. Do you clean up the damage it does to the modelview matrix, by initializing it with identity? You know, like this:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLU.gluOrtho2D(0f,(float)VIEWPORT_DIMENSIONS[0],0f,(float)VIEWPORT_DIMENSIONS[1]);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(translation[0],translation[1],0);
glRectf(-1,-1,1,1);
Related
After many years with Processing IDE, I missed Intellij IDEA too much so I went back for it but Processing stays on :wink:
However, the shapes drawn are way less sharp than in the real PDE, for example, a simple circle is rendered differently using both time the latest version of Processing available 4.1.2, Java 17, the same PC and the same monitor :
In PDE :
public void setup() {
size(500, 500);
}
public void draw() {
background(40);
noStroke();
fill(255);
circle(width/2, height/2, 400);
saveFrame("./PDE.png");
noLoop();
}
and the result is :
With Intellij however :
import processing.core.PApplet;
public class Main extends PApplet {
public void settings() {
size(500, 500);
}
public void draw() {
background(40);
noStroke();
fill(255);
circle(width/2, height/2, 400);
saveFrame("Intellij IDEA.png");
noLoop();
}
public static void main(String... args) {
Main pt = new Main();
PApplet.runSketch(new String[]{"testRendering"}, pt);
}
}
the saveFrame() is exactly the same as with Processing IDE but the real view in the sketch is :
I guess that it is a problem of renderer but I can't change it using fullScreen(P2D) for example because it throws errors.
The only solution I found were using Maven but I am not so I'd rather find a solution for my problem.
This problem arises because the window is being scaled (according to windows scaling settings) but its content is not rendered in a higher resolution (hence the "jaggies").
It's a problem only with the default (Java AWT) renderer. To fix it:
Call System.setProperty("sun.java2d.uiScale", "1") before PApplet.runSketch() -- this will prevent the window from being scaled.
An alternative solution is to use the JavaFX renderer (size(500, 500, FX2D)), which seems to behave correctly (the content renders at a higher resolution).
If however high DPI scaling is not desired with the FX2D renderer, you can call System.setProperty("prism.allowhidpi", "false")to disable it.
I am new to using LWJGL (and relatively so to Java in general) and as such, I was reading their page on getting started where they supplied an example Hello World program. I tried to run it myself and found that it errored with the following:
2020-03-18 10:20:02.145 java[19779:1119716] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+[NSUndoManager(NSInternal) _endTopLevelGroupings] is only safe to invoke on the main thread.
I was confused as to what this meant because I didn't think the init() method was running in any thread other than main, and so I added a line to print which thread it was running in, and sure enough, it printed Thread[main,5,main].
What is going on here, and how can I fix it?
The full code is below for context.
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;
import java.nio.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
public class HelloWorld {
// The window handle
private long window;
public void run() {
System.out.println("Hello LWJGL " + Version.getVersion() + "!");
init();
loop();
// Free the window callbacks and destroy the window
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
// Terminate GLFW and free the error callback
glfwTerminate();
glfwSetErrorCallback(null).free();
}
private void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set();
// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( !glfwInit() )
throw new IllegalStateException("Unable to initialize GLFW");
// Configure GLFW
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable
// This should be running on main?
System.out.println(Thread.currentThread());
// Create the window -- This is where the problem is
window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
});
// Get the thread stack and push a new frame
try ( MemoryStack stack = stackPush() ) {
IntBuffer pWidth = stack.mallocInt(1); // int*
IntBuffer pHeight = stack.mallocInt(1); // int*
// Get the window size passed to glfwCreateWindow
glfwGetWindowSize(window, pWidth, pHeight);
// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center the window
glfwSetWindowPos(
window,
(vidmode.width() - pWidth.get(0)) / 2,
(vidmode.height() - pHeight.get(0)) / 2
);
} // the stack frame is popped automatically
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
}
private void loop() {
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities();
// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while ( !glfwWindowShouldClose(window) ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glfwSwapBuffers(window); // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}
public static void main(String[] args) {
new HelloWorld().run();
}
}
There appears to be multiple issues with the example presented by the LWJGl3.org group.
1> The glfwInit() function call may need to be called a good deal earlier. this function needs to be called before other LWJGL function calls according to the library documentation.
1.1> Suggestion: place the call in the main()
public static void main(String[] args) {
glfwInit();
.....
1.2 OR- Suggestion: place it by itself as the first statement of the init() function
private void init() {
glfwInit();
....
1.3>OR- Suggestion:Create a class constructor and place the glfwInit(); function call in it so you are guaranteed that it is call early.
2> The import static declarations may need to be be altered
2.1> Suggestion: Try
import static org.lwjgl.glfw.GLFW.* ; // fires glfwInit;
//not helpful import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
//import static org.lwjgl.glfw.GLFWKeyCallback.*; //fails to do any thing
3> Give the "window" class variable a unique name in its declaration to avoid name collisions with the "window" associated with the Lambda function call --discussed later.
3.1 Suggestion:
// The window handle
private long windowid;
4> The init() function needs to have "local variable declarations;
int key;
int scancode;
int action ;
int mods;
5> The example as presented employs the new JRE8 feature Lambda function syntax: () -> trick. However Lambda functions are not "supported" for Eclipse 3.8.1 (ubuntu 16.04) already running on JRE8 but with Java SDK compliance set by default to 1.7. That required substantial child-birthing to move to Eclipse 2020-6R. Unfortunately, the effort is now in my Limbo like CPM86.
5.1> A "possible" work around may evolve from following Warmful Development's Setting up LWJGL 3 with Eclipse video at https://www.youtube.com/watch?v=VH9KAhjXVFM. The plan is to scan his series to see if a possible solution can evolve to my specific need.
I have spent the past couple of days trying to figure out what is wrong with my code. Im trying to render a tile map (.tmx) in libgdx but it does not render and it just shows a red screen with no error. I have re-written the code a few times and I always getting the same result.
my code:
public class Main extends ApplicationAdapter {
SpriteBatch batch;
TiledMap map;
TmxMapLoader loader;
OrthogonalTiledMapRenderer renderer;
OrthographicCamera camera;
#Override
public void create () {
batch = new SpriteBatch();
loader = new TmxMapLoader();
map = loader.load("TiledMaps/TestMap.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
camera = new OrthographicCamera();
camera.setToOrtho(false,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
renderer.setView(camera);
renderer.render();
batch.begin();
batch.end();
}
#Override
public void dispose () {
batch.dispose();
renderer.dispose();
map.dispose();
}
}
Can anybody find what is happening here I have the tmx file with the tilesheet in the TileMaps folder in the android assets folder.
Any help is appreciated, Thanks in advance.
If I understand correctly, you're attempting something complex (map rendering) but encountering a simple problem (not rendering anything).
Have you got a simple program where you do have something rendering? Built it up so you have a few hard coded tiles rendering? Built it up a bit more to correctly read and display the first tile from the map? Before finally extending it further to read and display all the tiles, once you know the basics are working?
That's how I would tackle this problem. Been programming for years, and just used the same process to get CreateProcess working in C++ on Windows. Wasn't working within my code so I built an empty project that just runs CreateProcess on notepad.exe and tweaked things with answers from StackOverflow.com till I got it working, now it's about adding back in the other complications bit by bit so I'm not completely lost by taking on too much at once.
FIX: Converting the models to g3db format fixed the issue.
I am using Java 1.8.0_60, Android 6.0
So I've decided to have a go at 3D in LibGdx, and I'm running into some weird issues with the AssetManager.
I've been following tutorials pretty much completely so far, and am trying to load a .obj model of a ship I got from one of the tutorials.
I am creating the AssetManager and adding the .obj file to the queue, with Model.class as the second parameter of the load method.
I am then waiting for the asset to load, calling update() on the AssetManager each render to check whether it has loaded.
Right now, my printlns are pretty much looking like this:
Assets in queue: 1
Progress: 0.0
My render method looks like this (In GameRenderer class):
public void render(){
if(!created){
return;
}
if(assets.loading() && assets.update()){
assets.bindModels();
}
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(assets.getInstances(), environment);
modelBatch.end();
}
And my asset loading methods look like this (in AssetLoader class):
public void loadModels(){
assets.load("ship.obj", Model.class);
loading = true;
}
public void bindModels() {
ModelInstance model = new ModelInstance(assets.get("ship.obj", Model.class));
instances.add(model);
loading = false;
}
public boolean update(){
System.out.println("Assets in queue: " + assets.getQueuedAssets());
return assets.update();
}
There are no exceptions being thrown.
My guess is that something is causing the AssetManager to jam, but I'm lost on what could be causing it. Any help would be very much appreciated.
Thanks!
EDIT:
If I call finishLoading() on the AssetManager, which blocks until the assets are all done, the game freezes.
I'm using Processing 2.0.3 on Windows 8. I tried to use the following code but I've no idea why my sketch couldn't run when I'm using the processing.video.* library:
import processing.video.*;
Capture cam;
void setup() {
size(200, 200);
cam = new Capture(this);
cam.start();
}
void draw() {
if (cam.available()) {
// Reads the new frame
cam.read();
}
image(cam, 0, 0);
}
I notice that the sketch will get stuck and will not open the sketch applet window at all if I call anything related to the Capture class. Calling println(Capture.list()); for example will cause the sketch to stuck at where ever that line was called.
What do I have to do to resolve this problem?