2011-11-07 40 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