Problem rendering objects

Started by guillaumesmo, September 07, 2007, 20:32:50

Previous topic - Next topic

guillaumesmo

Hello everybody,

I've just made a small application, using LWJGL. I have added the OBJ loader of elias4444 to load objets in my 3D world. But the objets have a problem to load:



Like you can see, the plane is not shown correctly.

How can I fix that ?

P.S.: Originally the plane was very very little inside the screen, so I have had to add a glScalef(10f,10f,10f) to be able to see it in an acceptable size.

elias4444

There's several possible things that could be wrong there (one of which is my old code  :P ).

I would recommend trying it with culling turned off first though. It's possible that the normals are messed up with the object. Or, at least, that's what it kinda looks like.
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

elias4444

I went ahead and updated my texturetester demo (includes source for OBJ loader and TrueType Font Renderer). Thought the updated code might help you out a bit too.

www.tommytwisters.com/texturetester.jar
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

elias4444

I also went ahead and posted a webstartable version of the texture tester at:

www.tommytwisters.com/texture/texture.jnlp

I figure, that way you can run it and see how your OBJ file loads up in another application.
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

guillaumesmo

Thank you for your application.

I'll paste my code here, could you take a look and tell me what's going wrong?

import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.glu.GLU;

import java.io.BufferedReader;
import java.io.FileReader;
 
/**
 * Basic game
 *
 * @author Name <email>
 * @version 1.0
 */
public class Main {
 
  /** Game title */
  public static final String GAME_TITLE = "My Game";
 
  /** Desired frame time */
  private static final int FRAMERATE = 60;
 
  /** Exit the game */
  private static boolean finished;
 
  /** Angle of rotating square */
  private static float angle;
 
  /**
   * Application init
   * @param args Commandline args
   */
  public static void main(String[] args) {
    boolean fullscreen = (args.length == 1 && args[0].equals("-fullscreen"));
 
    try {
      init(fullscreen);
      run();
    } catch (Exception e) {
      e.printStackTrace(System.err);
      Sys.alert(GAME_TITLE, "An error occured and the game will exit.");
    } finally {
      cleanup();
    }
    System.exit(0);
  }
 
  /**
   * Initialise the game
   * @throws Exception if init fails
   */
  private static void init(boolean fullscreen) throws Exception {
    // Create a fullscreen window with 1:1 orthographic 2D projection (default)
    Display.setFullscreen(fullscreen);
    
    Display.setTitle(GAME_TITLE);
 
    // Enable vsync if we can (due to how OpenGL works, it cannot be guarenteed to always work)
    Display.setVSyncEnabled(true);
 
    // Create default display of 640x480
    Display.create();
    
  }
 
  /**
   * Runs the game (the "main loop")
   */
  private static void run() {
 
    while (!finished) {
      // Always call Window.update(), all the time - it does some behind the
      // scenes work, and also displays the rendered output
      Display.update();
 
      // Check for close requests
      if (Display.isCloseRequested()) {
	finished = true;
      } 
 
      // The window is in the foreground, so we should play the game
      else if (Display.isActive()) {
        logic();
        render();
        Display.sync(FRAMERATE);
      } 
 
      // The window is not in the foreground, so we can allow other stuff to run and
      // infrequently update
      else {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
        }
        logic();
 
	// Only bother rendering if the window is visible or dirty
        if (Display.isVisible() || Display.isDirty()) {
          render();
        }
      }
    }
  }
 
  /**
   * Do any game-specific cleanup
   */
  private static void cleanup() {
    // Close the window
    Display.destroy();
  }
 
  /**
   * Do all calculations, handle input, etc.
   */
  private static void logic() {
    // Example input handler: we'll check for the ESC key and finish the game instantly when it's pressed
    if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
      finished = true;
    }
 
    // Rotate the square
    angle += 2.0f % 360;
  }
  
    /**
   * Render the current frame
   */
  private static void render() {
    // clear the screen
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
 
    // center square according to screen size
    GL11.glPushMatrix();
    GL11.glTranslatef(Display.getDisplayMode().getWidth() / 2, Display.getDisplayMode().getHeight() / 2, 0.0f);
 
      // rotate square according to angle
      GL11.glRotatef(angle, 0f, 0f, 1.0f);
 
      // render the square
      GL11.glBegin(GL11.GL_QUADS);
        GL11.glVertex2i(-50, -50);
        GL11.glVertex2i(50, -50);
        GL11.glVertex2i(50, 50);
        GL11.glVertex2i(-50, 50);
      GL11.glEnd();
 
    GL11.glPopMatrix();
    
    GL11.glPushMatrix();
    GL11.glTranslatef(Display.getDisplayMode().getWidth() / 3, Display.getDisplayMode().getHeight() / 3, -5f);
    GL11.glRotatef(angle, 0, 1f, 0);
    GL11.glScalef(10f,10f,10f);
    try{
        FileReader fr = new FileReader("C:/java/obj/p51_mustang.obj");
        BufferedReader br = new BufferedReader(fr);
        Object3D letest = new Object3D(br,false);
        letest.opengldraw();
    } catch (Exception e) {
      e.printStackTrace(System.err);
      Sys.alert(GAME_TITLE, "Une erreur est survenue durant le chargement");
    }
    GL11.glPopMatrix();
    
  }
  
}


Thank you!

guillaumesmo

P.S.:

I've just implemented your new code into my application but I'm still having the same problem.
And, I can't see the plane in your Texture Tester.

bobjob

iv had problems like this when:

* culling was enabled.
* the model or ".obj" has not been triangulated.
* texture is not to the power of 2 (eg 32, 64, 128, 256...)
* or texture has alpha channels and alpha blending is enabled.

elias4444

Have you tried loading a different OBJ file? I'm really thinking it may be the object itself.
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

guillaumesmo

Yes, I tried with objects that work in your application too.

elias4444

Ok, I looked at your code, and I found a couple of things. One, you're loading the OBJ file every frame. You should preload it, and then just call the opengldraw() command in your render loop. Also, you should call Display.update() AFTER you've rendered everything in the loop. As it stands now, you update the display, only to clear it again in the same loop. You may be gettings drawing artifacts.

Try those things, and see what happens.
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

guillaumesmo

OK,

The FPS is now way faster (thanks)

But I'm still having the problem with the plane (and other objects)

elias4444

Ok, lets work on your openGL init function:

You'll want to add some of these:

GL11.glEnable(GL11.GL_TEXTURE_2D);
			GL11.glEnable(GL11.GL_NORMALIZE);
			// Setup translucency
			GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
			GL11.glEnable(GL11.GL_BLEND);
			GL11.glEnable(GL11.GL_DITHER);
			
			GL11.glShadeModel(GL11.GL_SMOOTH);
			GL11.glEnable(GL11.GL_COLOR_MATERIAL);
			GL11.glDepthFunc(GL11.GL_LEQUAL);
			GL11.glEnable(GL11.GL_DEPTH_TEST);


This will enable materials, transparency, and setup depth testing and things.  Place it after your Display.create() call. Try it out, and let me know.
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

guillaumesmo

After adding your lines in the init method everyting disappreared.

After some searching, I have commented the line "GL11.glEnable(GL11.GL_DEPTH_TEST);", but now, I still have the same problem as in my very first post ...

May be you should try my code on your own computer, update it their, try what you can, and then say me if you found something.

Thank you very much

elias4444

Here you go:

Issue was that you hadn't setup anything for depth, so 2D images would work fine, but not 3D. I also added the init functions you'd need for transparency and things.

import java.io.BufferedReader;
import java.io.FileReader;

import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

import tools.Object3D;

/**
 * Basic game
 *
 * @author Name <email>
 * @version 1.0
 */
public class Main {

	/** Game title */
	public static final String GAME_TITLE = "My Game";

	/** Exit the game */
	private static boolean finished;

	/** Angle of rotating square */
	private static float angle;
	
	/** The Object to Draw */
	private Object3D letest;

	/**
	 * Application init
	 * @param args Commandline args
	 */
	public static void main(String[] args) {
		boolean fullscreen = (args.length == 1 && args[0].equals("-fullscreen"));

		Main app = new Main();
		
		try {
			app.init(fullscreen);
			app.run();
		} catch (Exception e) {
			e.printStackTrace(System.err);
			Sys.alert(GAME_TITLE, "An error occured and the game will exit.");
		} finally {
			app.cleanup();
		}
		System.exit(0);
	}

	/**
	 * Initialise the game
	 * @throws Exception if init fails
	 */
	private void init(boolean fullscreen) throws Exception {
		// Create a fullscreen window with 1:1 orthographic 2D projection (default)
		Display.setFullscreen(fullscreen);

		Display.setTitle(GAME_TITLE);

		// Enable vsync if we can (due to how OpenGL works, it cannot be guarenteed to always work)
		Display.setVSyncEnabled(true);

		Display.setDisplayMode(new DisplayMode(640,480));
		
		// Create default display of 640x480
		Display.create();
		
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glEnable(GL11.GL_NORMALIZE);
		// Setup translucency
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		GL11.glEnable(GL11.GL_BLEND);
		GL11.glEnable(GL11.GL_DITHER);
		
		GL11.glShadeModel(GL11.GL_SMOOTH);
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		GL11.glClearDepth(1.0);
		GL11.glEnable(GL11.GL_COLOR_MATERIAL);
		GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do
		GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
		
		// OpenGL uses a backwards x,y coordinate system, so use GL_BACK for culling
		GL11.glCullFace(GL11.GL_BACK);
		GL11.glEnable(GL11.GL_CULL_FACE);
		
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity(); // reset projection matrix
		GL11.glViewport(0,0,640,480);
		GL11.glOrtho(-640/2,640/2,-480/2,480/2, -100f, 10000f);
		GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
		GL11.glLoadIdentity();

		
		try{
			FileReader fr = new FileReader("C:/java/obj/p51_mustang.obj");
			BufferedReader br = new BufferedReader(fr);
			letest = new Object3D(br,false,"C:/java/obj/");
		} catch (Exception e) {
			e.printStackTrace(System.err);
			Sys.alert(GAME_TITLE, "Une erreur est survenue durant le chargement");
		}


	}

	/**
	 * Runs the game (the "main loop")
	 */
	private void run() {

		while (!finished) {

			// Check for close requests
			if (Display.isCloseRequested()) {
				finished = true;
			} 

			// The window is in the foreground, so we should play the game
			else if (Display.isActive()) {
				logic();
				render();
			} 

			// The window is not in the foreground, so we can allow other stuff to run and
			// infrequently update
			else {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
				}
				logic();

				// Only bother rendering if the window is visible or dirty
				if (Display.isVisible() || Display.isDirty()) {
					render();
				}
			}
		}
	}

	/**
	 * Do any game-specific cleanup
	 */
	private void cleanup() {
		// Close the window
		Display.destroy();
	}

	/**
	 * Do all calculations, handle input, etc.
	 */
	private void logic() {
		// Example input handler: we'll check for the ESC key and finish the game instantly when it's pressed
		if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
			finished = true;
		}

		// Rotate the square
		angle += 2.0f % 360;
	}

	/**
	 * Render the current frame
	 */
	private void render() {
		// clear the screen
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
		GL11.glLoadIdentity();

		// center square according to screen size
		GL11.glPushMatrix();
		//GL11.glTranslatef(Display.getDisplayMode().getWidth() / 2, Display.getDisplayMode().getHeight() / 2, 0.0f);
		GL11.glTranslatef(0, 0, 0);

		// rotate square according to angle
		GL11.glRotatef(angle, 0f, 0f, 1.0f);

		// render the square
		GL11.glColor4f(1, 1, 1, 1);
		GL11.glBegin(GL11.GL_QUADS);
		GL11.glVertex2i(-50, -50);
		GL11.glVertex2i(50, -50);
		GL11.glVertex2i(50, 50);
		GL11.glVertex2i(-50, 50);
		GL11.glEnd();
		
		GL11.glPopMatrix();
		
		GL11.glPushMatrix();
		GL11.glTranslatef(-100f,-100f,0);
		GL11.glRotatef(angle, 0, 1f, 0);
		GL11.glScalef(10f,10f,10f);
		letest.opengldraw();
		GL11.glPopMatrix();
		
		// Always call Window.update(), all the time - it does some behind the
		// scenes work, and also displays the rendered output
		Display.update();


	}

}


=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

guillaumesmo

Thank you very much!

It works on my PC too ;)

Indeed, I took the code on the wiki for rendering a square. I thought it would work for 3D too.

It was a bit confusing because there is no 3D example on the whole lwjgl.org website :(

But thanks,
you really helped me!