   Particle Engine
  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#defineMAX_PARTICLES1000// Number Of Particles To Createtypedef 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{boolactive;// Active (Yes/No)floatlife;// Particle Lifefloatfade;// Fade Speedfloatr;// Red Valuefloatg;// Green Valuefloatb;// Blue Valuefloatx;// X Positionfloaty;// Y Positionfloatz;// Z Positionfloatxi;// X Directionfloatyi;// Y Directionfloatzi;// Z Directionfloatxg;// X Gravityfloatyg;// Y Gravityfloatzg;// Z Gravity}particles;// Particles Structureparticles particle[MAX_PARTICLES];// Create an array of 1000 particlesHWND   ghwnd;HDCghdc;HGLRCghrc;//hardware RENDERING CONTEXTHINSTANCEghInstance;RECTgRect;RECTscreenRect;int S_WIDTH =800;//client area resolutionint S_HEIGHT =600;boolkeys[256];boolrainbow=true;// Rainbow Mode?Mouse MousePos;floatslowdown=2.0f;// Slow Down Particlesfloatxspeed = 0.0f;// Base X Speed (To Allow Keyboard Direction Of Tail)floatyspeed = 0.0f;// Base Y Speed (To Allow Keyboard Direction Of Tail)floatzoom=-40.0f;// Used To Zoom OutGLuintloop;// Misc Loop VariableGLuintcol;// Current Color SelectionGLuintdelay;// Rainbow Effect DelayGLuinttexture[1];// Storage For Particle TextureLRESULT 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 Handlereturn 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 TRUEglGenTextures(1, &texture[0]);// Create One TextureglBindTexture(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 classdwStyle = 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 windowhwnd = 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 NULLShowWindow(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 WindowgluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,200.0f);glMatrixMode(GL_MODELVIEW);// Select The Modelview MatrixglLoadIdentity();// Reset The Modelview Matrix}int InitializeOpenGL(int width, int height) { ghdc = GetDC(ghwnd);//  sets  global HDCif (!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 Screenreturn true;}void Init(HWND hwnd){ghwnd = hwnd;GetClientRect(ghwnd, &gRect);//get rect into our handy global rectInitializeOpenGL(gRect.right, gRect.bottom);// initialise openGL//OpenGL settingsglShadeModel(GL_SMOOTH);// Enables Smooth ShadingglClearColor(0.0f,0.0f,0.0f,0.0f);// Black BackgroundglClearDepth(1.0f);// Depth Buffer SetupglDisable(GL_DEPTH_TEST);// Disables Depth TestingglEnable(GL_BLEND);// Enable BlendingglBlendFunc(GL_SRC_ALPHA,GL_ONE);// Type Of Blending To PerformglHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);// Really Nice Perspective CalculationsglHint(GL_POINT_SMOOTH_HINT,GL_NICEST);// Really Nice Point SmoothingglEnable(GL_TEXTURE_2D);// Enable Texture MappingglBindTexture(GL_TEXTURE_2D,texture[0]);// Select Our Texturefor (loop=0;loop<MAX_PARTICLES;loop++)// Initials All The Textures{particle[loop].active=true;// Make All The Particles Activeparticle[loop].life=1.0f;// Give All The Particles Full Lifeparticle[loop].fade=float(rand()%100)/1000.0f+0.003f;// Random Fade Speedparticle[loop].r=colors[loop*(12/MAX_PARTICLES)][0];// Select Red Rainbow Colorparticle[loop].g=colors[loop*(12/MAX_PARTICLES)][1];// Select Red Rainbow Colorparticle[loop].b=colors[loop*(12/MAX_PARTICLES)][2];// Select Red Rainbow Colorparticle[loop].xi=float((rand()%50)-26.0f)*10.0f;// Random Speed On X Axisparticle[loop].yi=float((rand()%50)-25.0f)*10.0f;// Random Speed On Y Axisparticle[loop].zi=float((rand()%50)-25.0f)*10.0f;// Random Speed On Z Axisparticle[loop].xg=0.0f;// Set Horizontal Pull To Zeroparticle[loop].yg=-0.8f;// Set Vertical Pull Downwardparticle[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 BufferglLoadIdentity();// Reset The ModelView Matrixfor (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 Positionfloat y=particle[loop].y;// Grab Our Particle Y Positionfloat z=particle[loop].z+zoom;// Particle Z Pos + Zoom// Draw The Particle Using Our RGB Values, Fade The Particle Based On It's LifeglColor4f(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 RightglTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z); // Top LeftglTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z); // Bottom RightglTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z); // Bottom LeftglEnd();// Done Building Triangle Stripparticle[loop].x+=particle[loop].xi/(slowdown*1000);// Move On The X Axis By X Speedparticle[loop].y+=particle[loop].yi/(slowdown*1000);// Move On The Y Axis By Y Speedparticle[loop].z+=particle[loop].zi/(slowdown*1000);// Move On The Z Axis By Z Speedparticle[loop].xi+=particle[loop].xg;// Take Pull On X Axis Into Accountparticle[loop].yi+=particle[loop].yg;// Take Pull On Y Axis Into Accountparticle[loop].zi+=particle[loop].zg;// Take Pull On Z Axis Into Accountparticle[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 Lifeparticle[loop].fade=float(rand()%100)/1000.0f+0.003f;// Random Fade Valueparticle[loop].x=0.0f;// Center On X Axisparticle[loop].y=0.0f;// Center On Y Axisparticle[loop].z=0.0f;// Center On Z Axisparticle[loop].xi=xspeed+float((rand()%60)-32.0f);// X Axis Speed And Directionparticle[loop].yi=yspeed+float((rand()%60)-30.0f);// Y Axis Speed And Directionparticle[loop].zi=float((rand()%60)-30.0f);// Z Axis Speed And Directionparticle[loop].r=colors[col][0];// Select Red From Color Tableparticle[loop].g=colors[col][1];// Select Green From Color Tableparticle[loop].b=colors[col][2];// Select Blue From Color Table}// If Number Pad 8 And Y Gravity Is Less Than 1.5 Increase Pull Upwardsif (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 Downwardsif (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 Rightif (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 Leftif (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 Axisparticle[loop].y=0.0f;// Center On Y Axisparticle[loop].z=0.0f;// Center On Z Axisparticle[loop].xi=float((rand()%50)-26.0f)*10.0f;// Random Speed On X Axisparticle[loop].yi=float((rand()%50)-25.0f)*10.0f;// Random Speed On Y Axisparticle[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 memorywglDeleteContext(ghrc);// Delete our OpenGL Rendering Context}if (ghdc) ReleaseDC(ghwnd, ghdc);// Release our HDC from memoryUnregisterClass("FirstWindowClass", ghInstance);// Free the window classPostQuitMessage (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 resizedResizeGLWindow(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 / Offbreak;// If Up Arrow And Y Speed Is Less Than 200 Increase Upward Speedcase VK_UP:if (yspeed<200) yspeed+=1.0f;break;// If Down Arrow And Y Speed Is Greater Than -200 Increase Downward Speedcase VK_DOWN:if (yspeed>-200)yspeed-=1.0f;break;// If Right Arrow And X Speed Is Less Than 200 Increase Speed To The Rightcase VK_RIGHT:if (xspeed<200)xspeed+=1.0f;break;// If Left Arrow And X Speed Is Greater Than -200 Increase Speed To The Leftcase VK_LEFT:if (xspeed>-200)xspeed-=1.0f;break;// If Number Pad 8 And Y Gravity Is Less Than 1.5 Increase Pull Upwardscase 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 Downwardscase 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 Rightcase 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 Leftcase 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 Burstparticle[loop].x=0.0f;// Center On X Axisparticle[loop].y=0.0f;// Center On Y Axisparticle[loop].z=0.0f;// Center On Z Axisparticle[loop].xi=float((rand()%50)-26.0f)*10.0f;// Random Speed On X Axisparticle[loop].yi=float((rand()%50)-25.0f)*10.0f;// Random Speed On Y Axisparticle[loop].zi=float((rand()%50)-25.0f)*10.0f;// Random Speed On Z Axisbreak;case VK_ADD:if(slowdown>1.0f)slowdown-=0.01f;// Speed Up Particlesbreak;case VK_SUBTRACT:if (slowdown<4.0f)slowdown+=0.01f;// Slow Down Particlesbreak;case VK_HOME:zoom+=0.1f;// Zoom Inbreak;case VK_END:zoom-=0.1f;// Zoom Outbreak;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){HWNDhwnd;    MSG    msg;//initialise and create windowhwnd = CreateOurWindow("SuperDuper Opengl APP", S_WIDTH, S_HEIGHT, 0, false, hInstance);if(hwnd == NULL) return true;//initialise opengl and other settingsInit(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 Delaycol++;// Change The Particle Colorif (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]
  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 :(   ;  Try loading textures after you set the rendering context.   ;  no difference...got a picture now should anyone be able to spot-diagnose the problem:http://img416.imageshack.us/img416/8001/broken5vn.jpg   ;  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.jpgTry this codeint 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;};  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 :)   