Problems with Explosion

Started by Hellekin, March 28, 2007, 01:15:02

Previous topic - Next topic

Hellekin

I was playing around with lwjgl and decidade to make this explosion, it endend up really nice (much better than I ever expected) but there was just one problem that i couldn't solve, the explision looks really nice if you are viewing it from distance, but when i zoom close to it this super lag comes in and messes everything up =/. I don't know how can I solve it or why thats happening, if anyone have any suggestion pls post here.

This is my main class:
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.glu.*;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;



public class Explode
{
	
	public static final String GAME_TITLE = "Explode";
 
  	private static final int FRAMERATE = 60;
  	 
  	private static boolean finished;
  	
  	private static float cameraX;
  	private static float cameraY;
  	private static float cameraZ = 10;
  	private static float cameraAngleX;
  	private static float cameraAngleY;
  	private static float cameraAngleZ;  	
  	
  	private static Explosion[] explosion = new Explosion[1];
  	
  	  
	public static void main(String[] args)
 	{
   
		try
		{
 	   		init();
 	    	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);
  	}
  	
  	private static void cleanup()
  	{    	
    	Display.destroy();
  	}
  	
  	
  	private static void init()
    {
    	//display mode selection
     		int targetWidth = 800;
			int targetHeight = 600;
	 
			DisplayMode chosenMode = null;
	 
			try
			{
	    		 DisplayMode[] modes = Display.getAvailableDisplayModes();
	 
			     for (int i=0;i<modes.length;i++)
	    		 {
	        		  if ((modes[i].getWidth() == targetWidth) && (modes[i].getHeight() == targetHeight))
	          		{
	               		chosenMode = modes[i];
	               		break;
	          		}
	    		 }
			}
			catch (LWJGLException e)
			{     
	    		 Sys.alert("Error", "Unable to determine display modes.");
	   			 System.exit(0);
			}
	 
			if (chosenMode == null)
			{
	    		Sys.alert("Error", "Unable to find appropriate display mode.");
	     		System.exit(0);
			}
	
	
			try
			{
	   			Display.setDisplayMode(chosenMode);
	   			Display.setTitle("Explode");
	    		Display.create();
			}	
			catch (LWJGLException e)
			{
			    Sys.alert("Error","Unable to create display.");
			    System.exit(0);
			}
			      		 	                    
     	   	//initiate stuff
    		initGraphics();
    		
    		explosion[0] = new Explosion(0.0f,0.0f,0.0f);
    	  		
    	
    }
    
    
    private static void initGraphics()
    {
    	resize();    
     	GL11.glShadeModel(GL11.GL_SMOOTH);          
     	GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
     	GL11.glClearDepth(1.0f);                  
       	GL11.glEnable(GL11.GL_BLEND);	//enable blending
		GL11.glDisable(GL11.GL_DEPTH_TEST); //disable depth test  
        GL11.glDepthFunc(GL11.GL_LEQUAL);            
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE);    
   	
	
    
    }
    
    private static void resize()
    {
        int width = 800;             
        int height = 600;            
        height = Math.max(height, 1);          
        GL11.glViewport(0, 0, width, height);  
        GL11.glMatrixMode(GL11.GL_PROJECTION);   
        GL11.glLoadIdentity();                
        float aspect = (float) width / (float) height;
        GLU.gluPerspective(45.0f, aspect, 0.001f, 2000.0f);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);    
        GL11.glLoadIdentity();                
    }
    
    
    private static void run() //main loop
  	{ 
  		while (!finished)
    	{
   		   	Display.update();
 
    		if (Display.isCloseRequested())
      		{
				finished = true;
		    } 
		    
		    physics();
 			logic(); 		 				
        	render();
        	Display.sync(FRAMERATE);
        	        	
        
   		}
  	}
  	
  private static void physics()
  {
   		for(int e=0;e<explosion.length;e++)
   		{ 	
   			if(explosion[e].alive)	
   				explosion[e].physics();
   		} 		
   		
   }
  	
  	
	  private static void render()
	  {
	       
	        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
	        GL11.glLoadIdentity(); 
	        
	        GL11.glTranslatef(0.0f, 0.0f, 0.0f);
	        	        
	        GL11.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	        
	      	drawExplosions();
	                        
	                
	   }
	   
	   
	   private static void drawExplosions()
 	   {
	   		   
	   		GL11.glPushMatrix();
	    	
	    	GL11.glRotatef (-cameraAngleX, 1.0f, 0.0f, 0.0f);	    
	    	GL11.glRotatef (-cameraAngleY, 0.0f, 1.0f, 0.0f);
	    		
	    	GL11.glTranslatef(-cameraX,-cameraY,-cameraZ);
	    	
	        
	   		for(int e=0;e<explosion.length;e++)
	   		{ 
	   			if(explosion[e].alive)
	   				drawExplosion(explosion[e]);	    		
	   		}
	   		
	   		
	   		GL11.glPopMatrix();
	  	}
	  	
	  	
	     private static void drawExplosion(Explosion e)
  		 {
   				float[] x = {e.xPosition,e.xPosition,e.xPosition,e.xPosition};
		   		float[] y = {e.yPosition,e.yPosition,e.yPosition,e.yPosition};
		   		float[] z = {e.zPosition,e.zPosition,e.zPosition,e.zPosition};
		   			
		   				   					
	   			for(int p=0;p<e.particle.length;p++)
	   			{
	   				if(e.particle[p].alive)
	   				{	   				
		   				x[p%4] = e.particle[p].xPosition;
		   				y[p%4] = e.particle[p].yPosition;
		   				z[p%4] = e.particle[p].zPosition;
		   								
		       			GL11.glColor4f(e.particle[p].red, e.particle[p].green, e.particle[p].blue,e.particle[p].alpha);
		   			
		   						   				
		   				GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
		   				
		   					
		   					GL11.glVertex3f(x[0],y[0],z[0]); 
		   				
							GL11.glVertex3f(x[1],y[1],z[1]); 
							
							GL11.glVertex3f(x[2],y[2],z[2]); 
						
		   					GL11.glVertex3f(x[3],y[3],z[3]);
																					
						GL11.glEnd();					
					}
	   			}
	   
	   		
  		 }
  		 
  		 
  	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;
    	}
    	
    	    	
 		if (Keyboard.isKeyDown(Keyboard.KEY_UP))
    	{
   			cameraAngleX+=2;
    	}
    	else if (Keyboard.isKeyDown(Keyboard.KEY_DOWN))
    	{
    		cameraAngleX-=2;
    	}
    	
    	
 		if (Keyboard.isKeyDown(Keyboard.KEY_LEFT))
    	{
   			cameraAngleY+=2;;
    	}
    	else if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT))
    	{
    		cameraAngleY-=2;
    	}    	
    
    	
    	if (Keyboard.isKeyDown(Keyboard.KEY_A))
    	{
   			cameraZ-= Math.sin(Math.toRadians(-cameraAngleY))*0.02;   	
    		cameraX-= Math.cos(Math.toRadians(-cameraAngleY))*0.02;    	
    		
    	}
    	else if (Keyboard.isKeyDown(Keyboard.KEY_D))
    	{
    		cameraZ+= Math.sin(Math.toRadians(-cameraAngleY))*0.02;   	
    		cameraX+= Math.cos(Math.toRadians(-cameraAngleY))*0.02;    		
    	}
    	
    	if (Keyboard.isKeyDown(Keyboard.KEY_W))
    	{
    		cameraZ-= Math.cos(Math.toRadians(cameraAngleX))*Math.cos(Math.toRadians(cameraAngleY))*0.02;   	
    		cameraX-= Math.cos(Math.toRadians(cameraAngleX))*Math.sin(Math.toRadians(cameraAngleY))*0.02;
    		cameraY+= Math.sin(Math.toRadians(cameraAngleX))*0.02;
    		
       	}
    	else if (Keyboard.isKeyDown(Keyboard.KEY_S))
    	{
			cameraZ+= Math.cos(Math.toRadians(cameraAngleX))*Math.cos(Math.toRadians(cameraAngleY))*0.02;   	
    		cameraX+= Math.cos(Math.toRadians(cameraAngleX))*Math.sin(Math.toRadians(cameraAngleY))*0.02;
    		cameraY-= Math.sin(Math.toRadians(cameraAngleX))*0.02;
    		
    	}
    	
       	if (Keyboard.isKeyDown(Keyboard.KEY_E))
    	{
    		explosion[0] = new Explosion(0.0f,0.0f,0.0f);
    	} 		
    	  	
    	
    	
  	}

	  
  	
   		
}



My Explosion class:
public class Explosion
{
	
	public float xPosition;
	public float yPosition;
	public float zPosition;
	
	public boolean alive;
	
	public Particle[] particle  = new Particle[(int)(Math.random()*2000+1000)];
	
	
	
	public Explosion(float x, float y, float z)
	{
		xPosition = x;
		yPosition = y;
		zPosition = z;
			
		alive = true;
		
		
		for(int c=0;c<particle.length;c++)
		{
			float r = 0.0f;
			float g = 0.0f;
			float b = 0.0f;
			
			if(Math.random()*10<9)			
			{
				r = 1.0f;
				g = (float)Math.random();
				b = 0.0f;
			
			}
			
			particle[c] = new Particle (xPosition,
										yPosition,
										zPosition,
										(float)Math.random()/5-0.1f,
										(float)Math.random()/5-0.1f,
										(float)Math.random()/5-0.1f,
										r,
										g,
										b,
										0.01f,
										(int)(Math.random()*15));
		}
				
	}
	
	
	public void physics()
	{
		for(int p=0;p<particle.length;p++)
   		{
   			particle[p].xPosition += particle[p].xSpeed;
   			particle[p].yPosition += particle[p].ySpeed;
   			particle[p].zPosition += particle[p].zSpeed;
   			particle[p].life--;
   				
   			if(particle[p].life<0)
   				particle[p].alive = false;
   		}
   		
	}
	
}


and finally, my particle class:
public class Particle
{
	
	public float xPosition;
	public float yPosition;
	public float zPosition;
	
	public float xSpeed;
	public float ySpeed;
	public float zSpeed;
	
	public float red;
	public float green;
	public float blue;
	public float alpha;
	
	public boolean alive;
	
	public int life;
	

	
	public Particle(float x,float y,float z,float xs,float ys,float zs,float r,float g, float b,float a,int f)
	{
		xPosition = x;
		yPosition = y;
		zPosition = z;
		
		xSpeed = xs;
		ySpeed = ys;
		zSpeed = zs;
		
		red = r;
		green = g;
		blue = b;
		alpha = a;
		
		life = f;		
		
		alive = true;
		
	}
	
}


There's also i nice multidirectional moving system that's really cool, but you can't really use it well in this explosion program, however you must move around to see my problem, use W and S to zoom in and out, A and S to move to your sides and the arrow keys to change direction. Press E to start a new explosion.

I'm also attaching the program's jar file, if you're lazy and just want to see the exploding efect. It must be placed in the same directory as lwjgl.jar and lwjgl.dll.


Fool Running

I would guess (since your frame rate is dieing when you get close), is that you are reaching the fill rate for the graphics card (The number of pixels that can be drawn per second). My guess is that there are a lot of overlapping polygons in your explosion and the graphics card just can't keep up when it needs to draw that many pixels on the entire screen.

A way to test this is to try at a smaller resolution and/or trying to reduce the number of particles in the explosion. (The second option will probably work best).

Hope that helps.  ;D
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

deepthought


Fool Running

If the problem was getting the data to the graphics card fast enough, then using vertex arrays would probably help a little. However, because it works fine from far away, but the frame rate drops close up, that shouldn't be the problem.
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D