OpenGL样本粒子模拟不会显示粒子

时间:2011-11-07 04:44:01

标签: visual-c++ opengl particle-system

我从这个source为喷泉创建了一个简单的粒子模拟。我也想用C ++类实现它。所以,尝试将上面的逻辑部分放在这个source的类中(这是一个非常好的框架)。我只需继承该类并重新定义我想要的功能。

我定义了display()的函数,我调用了DrawObjects()。 我遇到了以下问题:

  1. 我正在将粒子数量初始化为50或100或500.没有任何可见的。
  2. 我正在尝试为我的粒子加载纹理(BMP)。由于某种原因它失败了。我尝试了相对路径和绝对路径。然后尝试加载RAW纹理(使用IrfanViewer),没有运气。还尝试删除纹理代码,使其成为简单的OpenGL基元。再没有运气。
  3. 我写了一个简单的DrawAxis()函数,它实际上需要用红色彩色字符串绘制青色彩色轴。但是,灰色彩色基元正在显示。我检查了代码是否使用grayscale配置,但没有这样的事情。
  4. 注意:使用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 个答案:

答案 0 :(得分:2)

在拥有OpenGL上下文(通过LoadTextureBMP())之前,正在调用<startFramework()(通过其常规的OpenGL调用)。

在发出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()中轴渲染中的颜色。通过ParticleSimulation::display()

glDisable(GL_LIGHTING)中将其停用

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