2011-11-07 41 views
0

我已經創建了一個簡單的粒子模擬從這個source噴泉。我也想用C++類來實現它。所以,試圖把這個邏輯的上述部分放在這個source的類中(這是一個非常好的框架)。我只需要繼承這個類並重新定義我想要的功能。OpenGL示例粒子模擬不顯示粒子

我定義了display()的函數,其中我稱之爲DrawObjects()。 我遇到了以下問題:

  1. 我初始化粒子的數量低至50或100或500沒有任何可見的。
  2. 我想爲我的粒子加載紋理(BMP)。由於某種原因,這是失敗的。我嘗試了相對和絕對路徑。然後嘗試加載RAW紋理(使用IrfanViewer),但沒有運氣。還嘗試刪除紋理代碼以使它們變得簡單OpenGL基元。再次沒有運氣。
  3. 我寫了一個簡單的DrawAxis()函數,實際上需要畫青色顏色軸與紅色彩色的字符串。但是,灰色彩色原語顯示出來。我檢查了使用grayscale配置的代碼,但沒有這樣的事情。

注意:使用Windows VC++ 2010。代碼可以在NippyZip找到。

最少的代碼

Main.cpp的

#include "ParticleSimulation.h" 
int main(int argc, char *argv[]) { 
    ParticleSimulation particleSimulation(50); 
    particleSimulation.InitParticles(); 
    particleSimulation.setLookAt(80.0, 80.0, 80.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
    particleSimulation.startFramework(argc, argv); 
    // **Note** No code below startFramework() will get executed  
    return 0; 
} 

GlutFramework.cpp

#include "GlutFramework.h" 

namespace glutFramework { 

    // Set constants 
    const double GlutFramework::FRAME_TIME = 1.0/GlutFramework::FPS * 1000.0; // Milliseconds 


    GlutFramework *GlutFramework::instance = NULL; 

    GlutFramework::GlutFramework() { 
     elapsedTimeInSeconds = 0; 
     frameTimeElapsed = 0; 
     title = "GLUT Framework: Paul Solt 2010"; 
     eyeVector = Vector<float>(0.0, 0.0, -10.0); // move the eye position back 
     position = 0.0f; 
     direction = 1.0/FRAME_TIME; 
    } 

    GlutFramework::~GlutFramework() { 
    } 

    void GlutFramework::startFramework(int argc, char *argv[]) { 
     setInstance(); // Sets the instance to self, used in the callback wrapper functions 

     // Initialize GLUT 
     glutInit(&argc, argv); 
     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 
     glutInitWindowPosition(WINDOW_X_POSITION, WINDOW_Y_POSITION); 
     glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); 
     glutCreateWindow(title.c_str()); 

     // Function callbacks with wrapper functions 
     glutReshapeFunc(reshapeWrapper); 
     glutMouseFunc(mouseButtonPressWrapper); 
     glutMotionFunc(mouseMoveWrapper); 
     glutDisplayFunc(displayWrapper); 
     glutKeyboardFunc(keyboardDownWrapper); 
     glutKeyboardUpFunc(keyboardUpWrapper); 
     glutSpecialFunc(specialKeyboardDownWrapper); 
     glutSpecialUpFunc(specialKeyboardUpWrapper); 

     init();      // Initialize 
     glutIdleFunc(runWrapper); // The program run loop 
     glutMainLoop();    // Start the main GLUT thread 
    } 

    void GlutFramework::load() { 
     // Subclass and override this method 
    } 

    void GlutFramework::display(float dTime) { 
     // Subclass and override this method 

     static int frame = 0; 
     std::cout << "GlutFramework Display: Frame: " << frame << ", dt(sec): " << dTime << ", Position: " << position << std::endl; 
     ++frame; 

     // DEMO: Create a teapot and move it back and forth on the x-axis 
     glTranslatef(position, 0.0f, 0.0f); 
     glutSolidTeapot(2.5); 
     if(position > 4 && direction > 0) { 
      direction = -1.0/FRAME_TIME; 
     } else if(position < -4 && direction < 0) { 
      direction = 1.0/FRAME_TIME; 
     }  
     position += direction; 
    } 

    void GlutFramework::reshape(int width, int height) { 
     glViewport(0,0,(GLsizei)width,(GLsizei)height); 
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     gluOrtho2D(0.0, (GLdouble) width, 0.0, (GLdouble) height); 
    } 

    void GlutFramework::mouseButtonPress(int button, int state, int x, int y) { 
     printf("MouseButtonPress: x: %d y: %d\n", x, y);   
    } 

    void GlutFramework::mouseMove(int x, int y) { 
     printf("MouseMove: x: %d y: %d\n", x, y); 
    } 

    void GlutFramework::keyboardDown(unsigned char key, int x, int y) 
    { 
     // Subclass and override this method 
     printf("KeyboardDown: %c = %d\n", key, (int)key); 
     if (key==27) { //27 =- ESC key 
      exit (0); 
     } 

     keyStates.keyDown((int)key); 
    } 

    void GlutFramework::keyboardUp(unsigned char key, int x, int y) 
    { 
     // Subclass and override this method 
     printf("KeyboardUp: %c \n", key); 
     keyStates.keyUp((int)key); 
    } 

    void GlutFramework::specialKeyboardDown(int key, int x, int y) 
    { 
     // Subclass and override this method 
     printf("SpecialKeyboardDown: %d\n", key); 
    } 

    void GlutFramework::specialKeyboardUp(int key, int x, int y) 
    { 
     // Subclass and override this method  
     printf("SpecialKeyboardUp: %d \n", key); 
    } 

    // ****************************** 
    // ** Graphics helper routines ** 
    // ****************************** 

    // Initialize the projection/view matricies. 
    void GlutFramework::setDisplayMatricies() { 
     /* Setup the projection and model view matricies */ 
     int width = glutGet(GLUT_WINDOW_WIDTH); 
     int height = glutGet(GLUT_WINDOW_HEIGHT); 
     float aspectRatio = width/height; 
     glViewport(0, 0, width, height); 
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     gluPerspective(60, aspectRatio, 1, 500.0); 

     glMatrixMode(GL_MODELVIEW); 
     glLoadIdentity(); 
     gluLookAt(eyeVector.x, eyeVector.y, eyeVector.z, 
        centerVector.x, centerVector.y, centerVector.z, 
        upVector.x, upVector.y, upVector.z); 
    } 

    void GlutFramework::setupLights() { 
     GLfloat light1_position[] = { 0.0, 1.0, 1.0, 0.0 }; 
     GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 }; 
     GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 }; 
     GLfloat ambient_light[] = { 0.8, 0.8, 0.8, 1.0 }; 

     glLightfv(GL_LIGHT0, GL_POSITION, light1_position); 
     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light); 
     glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); 
     glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); 

     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); 
    } 

    void GlutFramework::setLookAt(float eyeX, float eyeY, float eyeZ, 
            float centerX, float centerY, float centerZ, float upX, float upY, float upZ) { 

     eyeVector = Vector<float>(eyeX, eyeY, eyeZ); 
     centerVector = Vector<float>(centerX, centerY, centerZ); 
     upVector = Vector<float>(upX, upY, upZ); 
    } 

    Vector<float> GlutFramework::getEyeVector() const { 
     return eyeVector; 
    } 

    Vector<float> GlutFramework::getCenterVector() const { 
     return centerVector; 
    } 

    Vector<float> GlutFramework::getUpVector() const { 
     return upVector; 
    } 

    void GlutFramework::setTitle(std::string theTitle) { 
     title = theTitle; 
    } 

    // ************************** 
    // ** GLUT Setup functions ** 
    // ************************** 
    void GlutFramework::init() { 
     glClearColor(0.0, 0.0, 0.0, 1.0); 

     glEnable(GL_LIGHTING); 
     glEnable(GL_LIGHT0); 
     glShadeModel(GL_SMOOTH); 
     glEnable(GL_DEPTH_TEST); 

     load(); 
    } 

    void GlutFramework::setInstance() { 
     //std::cout << "GlutFramework::setInstance()" << std::endl; 
     instance = this; 
    } 

    void GlutFramework::run() { 
     if(frameRateTimer.isStopped()) { // The initial frame has the timer stopped, start it once 
      frameRateTimer.start(); 
     } 

     frameRateTimer.stop();   // stop the timer and calculate time since last frame 
     double milliseconds = frameRateTimer.getElapsedMilliseconds(); 
     frameTimeElapsed += milliseconds; 

     if(frameTimeElapsed >= FRAME_TIME) { // If the time exceeds a certain "frame rate" then show the next frame 
      glutPostRedisplay(); 
      frameTimeElapsed -= FRAME_TIME;  // remove a "frame" and start counting up again 
     } 
     frameRateTimer.start();   // start the timer 
    } 

    void GlutFramework::displayFramework() { 
     if(displayTimer.isStopped()) {   // Start the timer on the initial frame 
      displayTimer.start(); 
     } 

     glClearColor(0.0, 0.0, 0.0, 1.0); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear once 

     displayTimer.stop();  // Stop the timer and get the elapsed time in seconds 
     elapsedTimeInSeconds = displayTimer.getElapsedSeconds(); // seconds 

     setupLights(); 
     setDisplayMatricies(); 

     display(elapsedTimeInSeconds); 

     glutSwapBuffers(); 
     displayTimer.start();  // reset the timer to calculate the time for the next frame 
    } 

    // ****************************************************************** 
    // ** Static functions which are passed to Glut function callbacks ** 
    // ****************************************************************** 

    void GlutFramework::displayWrapper() { 
     instance->displayFramework(); 
    } 

    void GlutFramework::reshapeWrapper(int width, int height) { 
     instance->reshape(width, height); 
    } 

    void GlutFramework::runWrapper() { 
     instance->run(); 
    } 

    void GlutFramework::mouseButtonPressWrapper(int button, int state, int x, int y) { 
     instance->mouseButtonPress(button, state, x, y); 
    } 

    void GlutFramework::mouseMoveWrapper(int x, int y) { 
     instance->mouseMove(x, y); 
    } 

    void GlutFramework::keyboardDownWrapper(unsigned char key, int x, int y) { 
     instance->keyboardDown(key,x,y); 
    } 

    void GlutFramework::keyboardUpWrapper(unsigned char key, int x, int y) { 
     instance->keyboardUp(key,x,y); 
    } 

    void GlutFramework::specialKeyboardDownWrapper(int key, int x, int y) { 
     instance->specialKeyboardDown(key,x,y); 
    } 

    void GlutFramework::specialKeyboardUpWrapper(int key, int x, int y) { 
     instance->specialKeyboardUp(key,x,y); 
    } 

} // namespace 

ParticleSimulation.h

#include "preheader.h" 
#include "Particle.h" 
#include "GlutFramework.h" 

#ifndef ___PARTICLESIMULATION_H___ 
#define ___PARTICLESIMULATION_H___ 

using namespace glutFramework; 

#ifndef ABS_IMAGE_LOCATION 
#define ABS_IMAGE_LOCATION "E:/IIIT B/College/Sem 3/CG/GraphicAssignment3/images/particle.bmp" 
#endif 

class ParticleSimulation : virtual public GlutFramework{ 

    private: 
     GLuint numParticles;      // total number of particles in the system 
     Particle *particles; 
     GLuint textureParticle; 
     //static GLint textureCount; 

     //functions 
     void AllocateObjects(void); 
     void DeAllocateObjects(void); 

    public: 
     ParticleSimulation(void); 
     ParticleSimulation(GLuint numParticles); 

     ~ParticleSimulation(void); 

     void InitParticles(void); 

     void EvolveParticle(void); 

     void DisplayObjects(void); 

     void LoadTextureRAW(const char * filename, int wrap); 

     void LoadTextureBMP(const char * filename, int wrap); 

     void FreeTexture(void); 

     void DrawAxis(); 

     void RenderBitmapString(GLfloat x, GLfloat y, GLfloat z, void *font, char *string); 

     //virtual functions 
     void display(float dTime); 
}; 

#endif //___PARTICLESIMULATION_H___ 

ParticleSimulation.cpp

#include "ParticleSimulation.h" 

using namespace std; 

. . . 
void ParticleSimulation::DisplayObjects(){ 

    // rendering functions 
    glLoadIdentity(); 

    //glRotatef(20.0, 1.0, 0.0, 0.0);         // show scene from top front 

    //glBindTexture(GL_TEXTURE_2D, this->textureParticle);    // choose particle texture 

    for (int i = 0; i <= this->numParticles; i++){ 

     GLfloat xpos = 0.0f, ypos = 0.0f, zpos = 0.0f; 
     particles[i].getPosition(xpos, ypos, zpos); 

     if(ypos < 0.0) 
      particles[i].setLifeTime(0.0); 

     if(particles[i].getActiveStatus() && particles[i].getLifeTime() > 0.0) { 

      GLfloat red = 0.0f, green = 0.0f, blue = 0.0f; 
      particles[i].getColor(red, green, blue); 

      glColor3f(red, green, blue); 

      glBegin(GL_TRIANGLE_STRIP); 
      glVertex2f(0.0,1.0); glVertex3f(xpos + 0.002, ypos + 0.002, zpos + 0.0);  // top right 
      glVertex2f(0.0,0.0); glVertex3f(xpos - 0.002, ypos + 0.002, zpos + 0.0);  // top left 
      glVertex2f(1.0,1.0); glVertex3f(xpos + 0.002, ypos - 0.002, zpos + 0.0);  // bottom right 
      glVertex2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0);  // bottom left 
      //glTexCoord2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0);  // bottom left 
      glEnd(); 

     } else { 
      particles[i].CreateParticle(); 
     } 
    } 

    EvolveParticle(); 
} 

void ParticleSimulation::EvolveParticle() 
{ 
    for(int i = 0; i <= this->numParticles; i++){  // evolve the particle parameters 

     GLfloat xpos = 0.0f, ypos = 0.0f, zpos = 0.0f; 
     GLfloat green = 0.0f, red = 0.0f, blue = 0.0f; 
     GLfloat xVel = 0.0f, yVel = 0.0f, zVel = 0.0f; 

     particles[i].setLifeTime(particles[i].getLifeTime() - particles[i].getDecay()); 

     particles[i].getPosition(xpos, ypos, zpos); 
     particles[i].getSpeed(xVel, yVel, zVel); 

     particles[i].getPosition(xpos += xVel, ypos += yVel, zpos += zVel); 

     particles[i].getSpeed(xVel, yVel -= 0.00007, zVel); 
    } 
} 


// Texture /////////////////////////////////////////////////////////// 

// load a 256x256 RGB .RAW file as a texture 
void ParticleSimulation::LoadTextureBMP(const char * filename, int wrap) 
{ 
    int width = 0, height = 0; 
    BYTE *data = NULL; 
    FILE *file = NULL;  

    // open texture data 
    file = fopen(filename, "rb"); 
    if (file == NULL) { 
     cout << "\nFile could not be opened." << endl; 
     return; 
    } 

    // allocate buffer 
    width = 256; 
    height = 256; 
    data = (BYTE *) malloc(width * height * 3); 

    // read texture data 
    fread(data, width * height * 3, 1, file); 
    fclose(file); 

    // allocate a texture name 
    this->textureParticle = 0; 
    glGenTextures(1, &this->textureParticle); 

    // select our current texture 
    glBindTexture(GL_TEXTURE_2D, this->textureParticle); 

    // select modulate to mix texture with color for shading 
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 

    // when texture area is small, bilinear filter the closest MIP map 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
        GL_LINEAR_MIPMAP_NEAREST); 
    // when texture area is large, bilinear filter the first MIP map 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

    // if wrap is true, the texture wraps over at the edges (repeat) 
    //  ... false, the texture ends at the edges (clamp) 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
        wrap ? GL_REPEAT : GL_CLAMP); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
        wrap ? GL_REPEAT : GL_CLAMP); 

    // build our texture MIP maps 
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, 
    height, GL_RGB, GL_UNSIGNED_BYTE, data); 

    // free buffer 
    free(data); 

    return; 
} 

void ParticleSimulation::FreeTexture(void) 
{ 
    glDeleteTextures(1, &this->textureParticle); 
}  

void ParticleSimulation::DrawAxis() { 

    char s1[10]; 

    glPushMatrix(); 
     glColor3f(1.0f, 0.0f, 0.0f); 

     sprintf(s1, "X-axis"); 
     RenderBitmapString(50.0f, 0.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1); 

     sprintf(s1, "Y-axis"); 
     RenderBitmapString(0.0f, 50.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1); 

     sprintf(s1, "Z-axis"); 
     RenderBitmapString(0.0f, 0.0f, 50.0f, GLUT_BITMAP_HELVETICA_12, s1); 

     sprintf(s1, "Origin"); 
     RenderBitmapString(0.0f, 0.0f, 0.0f, GLUT_BITMAP_HELVETICA_12, s1); 

     glPointSize(4.0f); 

     glColor3f(0.0f, 1.0f, 1.0f); 

     glBegin(GL_LINE_STRIP); 
      glVertex3f(0.0f, 0.0f, 0.0f); 
      glVertex3f(0.0f, 50.0f, 0.0f); 
     glEnd(); 

     glBegin(GL_LINE_STRIP); 
      glVertex3f(0.0f, 0.0f, 0.0f); 
      glVertex3f(50.0f, 0.0f, 0.0f); 
     glEnd(); 

     glBegin(GL_LINE_STRIP); 
      glVertex3f(0.0f, 0.0f, 0.0f); 
      glVertex3f(0.0f, 0.0f, 50.0f); 
     glEnd(); 

    glPopMatrix(); 
} 

void ParticleSimulation::display(float dTime) 
{ 
    static int frame = 0; 
    //cout << "GlutFramework Display: Frame: " << frame << ", dt(sec): " << dTime << ", Position: " << position << endl; 
    ++frame; 

    //cout << "Calling the DisplayObject Function" << endl; 
    //glTranslatef(0.0f, 0.0f, 0.0f); 
    //glutSolidTeapot(2.5); 
    DrawAxis();   //Aditya: Working with grayscale though 
    DisplayObjects(); //Aditya: Nothing is drawn 
} 
+1

發佈一個完整的*最小*程序來演示問題。 – genpfault

+0

這裏..請找到代碼片段@genpfault – Aditya369

回答

2

LoadTextureBMP()被調用(與它的OpenGL的一羣調用),你有一個OpenGL上下文(通過startFramework())前。

在發出GL命令之前,您需要當前上下文。

編輯:

for(int i = 0; i <= this->numParticles; i++) 

制止。您正在訪問分配的內存末尾。

這樣做:

for(int i = 0; i < this->numParticles; i++) 

通知的低於,而不是低於或相等。對於大小爲N的C/C++數組,唯一有效的索引在[0,N-1]範圍內。您的<=將導致for環回嘗試訪問元素N.

That's bad

EDIT2:

GlutFramework::init()使照明。這正在改變ParticleSimulation::DrawAxis()中的軸渲染顏色。通過glDisable(GL_LIGHTING)禁用它ParticleSimulation::display()

Screenshot

EDIT3:

這將做東西但可能不是你所期望的:

glBegin(GL_TRIANGLE_STRIP); 
glVertex2f(0.0,1.0); glVertex3f(xpos + 0.002, ypos + 0.002, zpos + 0.0);  // top right 
glVertex2f(0.0,0.0); glVertex3f(xpos - 0.002, ypos + 0.002, zpos + 0.0);  // top left 
glVertex2f(1.0,1.0); glVertex3f(xpos + 0.002, ypos - 0.002, zpos + 0.0);  // bottom right 
glVertex2f(1.0,0.0); glVertex3f(xpos - 0.002, ypos - 0.002, zpos + 0.0);  // bottom left 
glEnd(); 

你似乎認爲glVertex2f()會以某種方式生成紋理座標。它不會。您正在尋找glTexCoord2f()

要繪製視圖對齊的三角形,您需要查看billboarding

+0

謝謝你的提示!我糾正了我的代碼,但沒有增益...還有任何想法爲什麼圖形灰度? – Aditya369

+1

@ Aditya369:編輯。 – genpfault