Jump to content
  • Advertisement
Sign in to follow this  

Particle Engine

This topic is 4523 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, having problems with the NeHe particle engine tutorial (i 'think' this is the right forum page for it...). Basically ive tried to copy what he has done but fit it around my existing framework, and it wont work. Few things ive noticed: i) It wont display the texture, although it seems to load it fine. ii) the 'rainbow' effect isnt on <EDIT: FIXED>
#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
#include <math.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>


#define COLOUR_DEPTH 16	//Colour depth
#define	MAX_PARTICLES	1000		// Number Of Particles To Create

typedef struct Mouse
{
	int x,y;
}Mouse;



static GLfloat colors[12][3]=				// Rainbow Of Colors
{
	{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
	{0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
	{0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}
};
typedef struct		// Create A Structure For Particle
{
	bool	active;					// Active (Yes/No)
	float	life;					// Particle Life
	float	fade;					// Fade Speed
	float	r;					// Red Value
	float	g;					// Green Value
	float	b;					// Blue Value
	float	x;					// X Position
	float	y;					// Y Position
	float	z;					// Z Position
	float	xi;					// X Direction
	float	yi;					// Y Direction
	float	zi;					// Z Direction
	float	xg;					// X Gravity
	float	yg;					// Y Gravity
	float	zg;					// Z Gravity
}particles;						// Particles Structure

particles particle[MAX_PARTICLES];			// Create an array of 1000 particles
HWND        ghwnd;
HDC			ghdc;
HGLRC		ghrc;			//hardware RENDERING CONTEXT
HINSTANCE	ghInstance;
RECT		gRect;
RECT		screenRect;

int S_WIDTH	 =	800;		//client area resolution
int S_HEIGHT =	600;


bool		keys[256];
bool	rainbow=true;			// Rainbow Mode?	
Mouse MousePos;

float	slowdown=2.0f;			// Slow Down Particles
float	xspeed = 0.0f;				// Base X Speed (To Allow Keyboard Direction Of Tail)
float	yspeed = 0.0f;				// Base Y Speed (To Allow Keyboard Direction Of Tail)
float	zoom=-40.0f;			// Used To Zoom Out

GLuint	loop;				// Misc Loop Variable
GLuint	col;				// Current Color Selection
GLuint	delay;				// Rainbow Effect Delay
GLuint	texture[1];			// Storage For Particle Texture

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

AUX_RGBImageRec *LoadBMP(char *Filename)				// Loads A Bitmap Image
{
        FILE *File=NULL;								// File Handle
        if (!Filename)									// Make Sure A Filename Was Given
        {
                return NULL;							// If Not Return NULL
        }
        File=fopen(Filename,"r");						// Check To See If The File Exists
        if (File)										// Does The File Exist?
        {
			fclose(File);								// Close The Handle
			return auxDIBImageLoad(Filename);			// Load The Bitmap And Return A Pointer
        }
        return NULL;									// If Load Failed Return NULL
}

int LoadGLTextures()									// Load Bitmap And Convert To A Texture
{
        int Status=FALSE;								// Status Indicator
        AUX_RGBImageRec *TextureImage[1];				// Create Storage Space For The Textures
        memset(TextureImage,0,sizeof(void *)*1);		// Set The Pointer To NULL

        if (TextureImage[0]=LoadBMP("Data/Particle.bmp"))	// Load Particle Texture
        {
			Status=TRUE;								// Set The Status To TRUE
			glGenTextures(1, &texture[0]);				// Create One Texture

			glBindTexture(GL_TEXTURE_2D, texture[0]);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
			glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
        }

        if (TextureImage[0])							// If Texture Exists
		{
			if (TextureImage[0]->data)					// If Texture Image Exists
			{
				free(TextureImage[0]->data);			// Free The Texture Image Memory
			}
			free(TextureImage[0]);						// Free The Image Structure
		}
        return Status;									// Return The Status
}
HWND CreateOurWindow(LPSTR strWindowName, int width, int height, DWORD dwStyle, bool bFullScreen, HINSTANCE hInstance)
{
	HWND hwnd;

	WNDCLASS wcex;

	memset(&wcex, 0, sizeof(WNDCLASS));
	wcex.style			= CS_HREDRAW | CS_VREDRAW;		
	wcex.lpfnWndProc	= WndProc;		
	wcex.hInstance		= hInstance;						
	wcex.hIcon			= LoadIcon(NULL, IDI_APPLICATION);; 
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);		
	wcex.hbrBackground	= (HBRUSH) (COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;	
	wcex.lpszClassName	= "FirstWindowClass";	

	
	RegisterClass(&wcex);// Register the class

	dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

	ghInstance	= hInstance;// Assign our global hInstance to the window's hInstance

	//Set the Client area of the window to be our resolution.
	RECT glwindow;
	glwindow.left		= 0;		
	glwindow.right		= width;	
	glwindow.top		= 0;		
	glwindow.bottom		= height;	

	AdjustWindowRect( &glwindow, dwStyle, false);

	//Create the window
	hwnd = CreateWindow(	"FirstWindowClass", 
							strWindowName, 
							dwStyle, 
							0, 
							0,
							glwindow.right  - glwindow.left,
							glwindow.bottom - glwindow.top, 
							NULL,
							NULL,
							hInstance,
							NULL
							);

	if(!hwnd) return NULL;// If we could get a handle, return NULL

	ShowWindow(hwnd, SW_SHOWNORMAL);	
	UpdateWindow(hwnd);					
	SetFocus(hwnd);						

	return hwnd;
}

bool SetPixelFormat(HDC hdc) 
{ 
    PIXELFORMATDESCRIPTOR pfd = {0}; 
    int pixelformat; 
 
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);	// Set the size of the structure
    pfd.nVersion = 1;							// Always set this to 1
	// Pass in the appropriate OpenGL flags
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 
    pfd.dwLayerMask = PFD_MAIN_PLANE;			// standard mask (this is ignored anyway)
    pfd.iPixelType = PFD_TYPE_RGBA;				// RGB and Alpha pixel type
    pfd.cColorBits = COLOUR_DEPTH;				// Here we use our #define for the color bits
    pfd.cDepthBits = COLOUR_DEPTH;				// Ignored for RBA
    pfd.cAccumBits = 0;							// nothing for accumulation
    pfd.cStencilBits = 0;						// nothing for stencil
 
	//Gets a best match on the pixel format as passed in from device
    if ( (pixelformat = ChoosePixelFormat(hdc, &pfd)) == false ) 
    { 
        MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK); 
        return false; 
    } 
 
	//sets the pixel format if its ok. 
    if (SetPixelFormat(hdc, pixelformat, &pfd) == false) 
    { 
        MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK); 
        return false; 
    } 
 
    return true;
}

void ResizeGLWindow(int width, int height)// Initialize The GL Window
{
	if (height==0)// Prevent A Divide By Zero error
	{
		height=1;// Make the Height Equal One
	}

	glViewport(0,0,width,height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	// Calculate The Aspect Ratio Of The Window
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,200.0f);

	glMatrixMode(GL_MODELVIEW);// Select The Modelview Matrix
	glLoadIdentity();// Reset The Modelview Matrix
}

int InitializeOpenGL(int width, int height) 
{  
    ghdc = GetDC(ghwnd);//  sets  global HDC
	if (!LoadGLTextures())								// Jump To Texture Loading Routine
	{
		return FALSE;									// If Texture Didn't Load Return FALSE
	}
    if (!SetPixelFormat(ghdc))//  sets  pixel format
        PostQuitMessage (0);


    ghrc = wglCreateContext(ghdc);	//  creates  rendering context from  hdc
    wglMakeCurrent(ghdc, ghrc);		//	Use this HRC.

	ResizeGLWindow(width, height);	// Setup the Screen

	return true;
}



void Init(HWND hwnd)
{
	ghwnd = hwnd;
	GetClientRect(ghwnd, &gRect);	//get rect into our handy global rect
	InitializeOpenGL(gRect.right, gRect.bottom);// initialise openGL

	//OpenGL settings
	glShadeModel(GL_SMOOTH);						// Enables Smooth Shading
	glClearColor(0.0f,0.0f,0.0f,0.0f);					// Black Background
	glClearDepth(1.0f);							// Depth Buffer Setup
	glDisable(GL_DEPTH_TEST);						// Disables Depth Testing
	glEnable(GL_BLEND);							// Enable Blending
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);					// Type Of Blending To Perform
	glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);			// Really Nice Perspective Calculations
	glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);					// Really Nice Point Smoothing
	glEnable(GL_TEXTURE_2D);						// Enable Texture Mapping
	glBindTexture(GL_TEXTURE_2D,texture[0]);				// Select Our Texture

	for (loop=0;loop<MAX_PARTICLES;loop++)				// Initials All The Textures
	{
		particle[loop].active=true;								// Make All The Particles Active
		particle[loop].life=1.0f;								// Give All The Particles Full Life
		particle[loop].fade=float(rand()%100)/1000.0f+0.003f;	// Random Fade Speed
		particle[loop].r=colors[loop*(12/MAX_PARTICLES)][0];	// Select Red Rainbow Color
		particle[loop].g=colors[loop*(12/MAX_PARTICLES)][1];	// Select Red Rainbow Color
		particle[loop].b=colors[loop*(12/MAX_PARTICLES)][2];	// Select Red Rainbow Color
		particle[loop].xi=float((rand()%50)-26.0f)*10.0f;		// Random Speed On X Axis
		particle[loop].yi=float((rand()%50)-25.0f)*10.0f;		// Random Speed On Y Axis
		particle[loop].zi=float((rand()%50)-25.0f)*10.0f;		// Random Speed On Z Axis
		particle[loop].xg=0.0f;									// Set Horizontal Pull To Zero
		particle[loop].yg=-0.8f;								// Set Vertical Pull Downward
		particle[loop].zg=0.0f;									// Set Pull On Z Axis To Zero
	}
	
	//Also, do any other setting of variables here for your app if you wish. 
}

void DrawScene() 
{	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// Clear Screen And Depth Buffer
	glLoadIdentity();										// Reset The ModelView Matrix

	for (loop=0;loop<MAX_PARTICLES;loop++)					// Loop Through All The Particles
	{
		if (particle[loop].active)							// If The Particle Is Active
		{
			float x=particle[loop].x;						// Grab Our Particle X Position
			float y=particle[loop].y;						// Grab Our Particle Y Position
			float z=particle[loop].z+zoom;					// Particle Z Pos + Zoom

			// Draw The Particle Using Our RGB Values, Fade The Particle Based On It's Life
			glColor4f(particle[loop].r,particle[loop].g,particle[loop].b,particle[loop].life);

			glBegin(GL_TRIANGLE_STRIP);						// Build Quad From A Triangle Strip
			    glTexCoord2d(1,1); glVertex3f(x+0.5f,y+0.5f,z); // Top Right
				glTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z); // Top Left
				glTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z); // Bottom Right
				glTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z); // Bottom Left
			glEnd();										// Done Building Triangle Strip

			particle[loop].x+=particle[loop].xi/(slowdown*1000);// Move On The X Axis By X Speed
			particle[loop].y+=particle[loop].yi/(slowdown*1000);// Move On The Y Axis By Y Speed
			particle[loop].z+=particle[loop].zi/(slowdown*1000);// Move On The Z Axis By Z Speed

			particle[loop].xi+=particle[loop].xg;			// Take Pull On X Axis Into Account
			particle[loop].yi+=particle[loop].yg;			// Take Pull On Y Axis Into Account
			particle[loop].zi+=particle[loop].zg;			// Take Pull On Z Axis Into Account
			particle[loop].life-=particle[loop].fade;		// Reduce Particles Life By 'Fade'

			if (particle[loop].life<0.0f)					// If Particle Is Burned Out
			{
				particle[loop].life=1.0f;					// Give It New Life
				particle[loop].fade=float(rand()%100)/1000.0f+0.003f;	// Random Fade Value
				particle[loop].x=0.0f;						// Center On X Axis
				particle[loop].y=0.0f;						// Center On Y Axis
				particle[loop].z=0.0f;						// Center On Z Axis
				particle[loop].xi=xspeed+float((rand()%60)-32.0f);	// X Axis Speed And Direction
				particle[loop].yi=yspeed+float((rand()%60)-30.0f);	// Y Axis Speed And Direction
				particle[loop].zi=float((rand()%60)-30.0f);	// Z Axis Speed And Direction
				particle[loop].r=colors[col][0];			// Select Red From Color Table
				particle[loop].g=colors[col][1];			// Select Green From Color Table
				particle[loop].b=colors[col][2];			// Select Blue From Color Table
			}

			// If Number Pad 8 And Y Gravity Is Less Than 1.5 Increase Pull Upwards
			if (keys[VK_NUMPAD8] && (particle[loop].yg<1.5f)) particle[loop].yg+=0.01f;

			// If Number Pad 2 And Y Gravity Is Greater Than -1.5 Increase Pull Downwards
			if (keys[VK_NUMPAD2] && (particle[loop].yg>-1.5f)) particle[loop].yg-=0.01f;

			// If Number Pad 6 And X Gravity Is Less Than 1.5 Increase Pull Right
			if (keys[VK_NUMPAD6] && (particle[loop].xg<1.5f)) particle[loop].xg+=0.01f;

			// If Number Pad 4 And X Gravity Is Greater Than -1.5 Increase Pull Left
			if (keys[VK_NUMPAD4] && (particle[loop].xg>-1.5f)) particle[loop].xg-=0.01f;

			if (keys[VK_TAB])										// Tab Key Causes A Burst
			{
				particle[loop].x=0.0f;								// Center On X Axis
				particle[loop].y=0.0f;								// Center On Y Axis
				particle[loop].z=0.0f;								// Center On Z Axis
				particle[loop].xi=float((rand()%50)-26.0f)*10.0f;	// Random Speed On X Axis
				particle[loop].yi=float((rand()%50)-25.0f)*10.0f;	// Random Speed On Y Axis
				particle[loop].zi=float((rand()%50)-25.0f)*10.0f;	// Random Speed On Z Axis
			}
		}
    }
			SwapBuffers(ghdc);// Swap the frame buffers.
}


void Cleanup()
{
	if (ghrc)
	{
		wglMakeCurrent(NULL, NULL);	// free rendering memory
		wglDeleteContext(ghrc);		// Delete our OpenGL Rendering Context
	}

	if (ghdc) 
	ReleaseDC(ghwnd, ghdc);			// Release our HDC from memory

	UnregisterClass("FirstWindowClass", ghInstance);// Free the window class

	PostQuitMessage (0);		// Post a QUIT message to the window
}



LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{


    switch (message)											
    {														
		case WM_CREATE:	
			break;

		case WM_SIZE:
			//resize the open gl window when the window is resized
			ResizeGLWindow(LOWORD(lParam),HIWORD(lParam));
			GetClientRect(hwnd, &gRect);
			break;	

		case WM_KEYDOWN:
		       switch (wParam) 
            { 
				case VK_SPACE: 
                   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
                    break; 	

				case VK_RETURN:
					rainbow=!rainbow;		// Toggle Rainbow Mode On / Off
					break;

			// If Up Arrow And Y Speed Is Less Than 200 Increase Upward Speed
				case VK_UP:
				if (yspeed<200) 
					yspeed+=1.0f;
					break;
			// If Down Arrow And Y Speed Is Greater Than -200 Increase Downward Speed
				case VK_DOWN:
					if (yspeed>-200)
					yspeed-=1.0f;
					break;

			// If Right Arrow And X Speed Is Less Than 200 Increase Speed To The Right
				case VK_RIGHT:
					if (xspeed<200)
					xspeed+=1.0f;
					break;

			// If Left Arrow And X Speed Is Greater Than -200 Increase Speed To The Left
				case VK_LEFT:
					if (xspeed>-200)
					xspeed-=1.0f;
					break;

		// If Number Pad 8 And Y Gravity Is Less Than 1.5 Increase Pull Upwards
				case VK_NUMPAD8:
					for(loop=0;loop<1000;loop++){
					if(particle[loop].yg<1.5f)
					particle[loop].yg+=0.01f;
					}
				break;

		// If Number Pad 2 And Y Gravity Is Greater Than -1.5 Increase Pull Downwards
				case VK_NUMPAD2:
					for(loop=0;loop<1000;loop++){
					if (particle[loop].yg>-1.5f)
					particle[loop].yg-=0.01f;
					}
				break;

			// If Number Pad 6 And X Gravity Is Less Than 1.5 Increase Pull Right
				case VK_NUMPAD6:
					for(loop=0;loop<1000;loop++){
					if(particle[loop].xg<1.5f)
				particle[loop].xg+=0.01f;
					}
				break;

			// If Number Pad 4 And X Gravity Is Greater Than -1.5 Increase Pull Left
				case VK_NUMPAD4:
					for(loop=0;loop<1000;loop++){
					if(particle[loop].xg>-1.5f)
					particle[loop].xg-=0.01f;
					}
				break;

				case VK_TAB:						// Tab Key Causes A Burst
				particle[loop].x=0.0f;					// Center On X Axis
				particle[loop].y=0.0f;					// Center On Y Axis
				particle[loop].z=0.0f;					// Center On Z Axis
				particle[loop].xi=float((rand()%50)-26.0f)*10.0f;	// Random Speed On X Axis
				particle[loop].yi=float((rand()%50)-25.0f)*10.0f;	// Random Speed On Y Axis
				particle[loop].zi=float((rand()%50)-25.0f)*10.0f;	// Random Speed On Z Axis
				break;

				case VK_ADD:
					if(slowdown>1.0f)
					slowdown-=0.01f;		// Speed Up Particles
					break;
				case VK_SUBTRACT:
					if (slowdown<4.0f)
					slowdown+=0.01f;	// Slow Down Particles
					break;


				case VK_HOME:
					zoom+=0.1f;		// Zoom In
					break;

				case VK_END:
					zoom-=0.1f;		// Zoom Out
					break;


				case 'Q':
					PostQuitMessage(0);	
					break;

			}

		case WM_KEYUP:
			keys[wParam]=false;
			break;

		case WM_MOUSEMOVE:
			MousePos.x = LOWORD (lParam);
			MousePos.y = HIWORD (lParam);
			break;

		case WM_PAINT:
			
	
		    break;		

		case WM_DESTROY:	
			
			PostQuitMessage(0);	
								
			break;				
	}													

	return DefWindowProc (hwnd, message, wParam, lParam);		
															
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int nCmdShow)			
{	
	HWND		hwnd;
    MSG         msg;	

	//initialise and create window
	hwnd = CreateOurWindow("SuperDuper Opengl APP", S_WIDTH, S_HEIGHT, 0, false, hInstance);	
	if(hwnd == NULL) return true;

	//initialise opengl and other settings
	Init(hwnd);
	
	while (true)					
    {							
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
		    if (msg.message==WM_QUIT)
				break;
			TranslateMessage (&msg);							
			DispatchMessage (&msg);
		}

		else
		{	
			if ((rainbow) && (delay>25))	// Space Or Rainbow Mode
			{
				delay=0;						// Reset The Rainbow Color Cycling Delay
				col++;							// Change The Particle Color
				if (col>11)	col=0;				// If Color Is To High Reset It
			}
				delay++;							// Increase Rainbow Mode Color Cycling Delay Counter


			//any intensive proccessing for the app,  do it here. 
			DrawScene();
		}
    }

	return msg.wParam ;										
}





[Edited by - Winegums on December 29, 2005 7:37:42 PM]

Share this post


Link to post
Share on other sites
Advertisement
nobody able to give me a clue? i think its something to do with the lighting just competley colouring the texture, which means theres a blending problem i think?

tried again from scratch, no dice :(

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Try loading textures after you set the rendering context.

Share this post


Link to post
Share on other sites
no difference...got a picture now should anyone be able to spot-diagnose the problem:

http://img416.imageshack.us/img416/8001/broken5vn.jpg

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Are you sure you moved loading textures to after setting the RC? That is the only thing I changed and it's working for me.

screen shot: http://img512.imageshack.us/my.php?image=screen2ou.jpg

Try this code


int InitializeOpenGL(int width, int height)
{
ghdc = GetDC(ghwnd);// sets global HDC

if (!SetPixelFormat(ghdc))// sets pixel format
PostQuitMessage (0);


ghrc = wglCreateContext(ghdc); // creates rendering context from hdc
wglMakeCurrent(ghdc, ghrc); // Use this HRC.

ResizeGLWindow(width, height); // Setup the Screen

if (!LoadGLTextures()) // Jump To Texture Loading Routine
{
return FALSE; // If Texture Didn't Load Return FALSE
}

return true;
}


Share this post


Link to post
Share on other sites
turns out i missunderstood what you meant. incidentally this is the second time that ive made this mistake...i should really write it down.

thanks a lot for your help though :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!