Моделирование частиц образца OpenGL не показывает частицы - PullRequest
0 голосов
/ 07 ноября 2011

Я создал простое моделирование частиц для фонтана из этого источника .Я также хотел реализовать это с помощью классов C ++.Итак, попытался поместить вышеуказанную часть логики в классы в этом источнике (это очень хорошая структура).Мне просто нужно унаследовать класс и переопределить функции, которые мне нужны.

Я определил функции для 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 Ответ

2 голосов
/ 08 ноября 2011

LoadTextureBMP() вызывается (с учетом множества вызовов OpenGL) до того, как у вас будет контекст OpenGL (через startFramework()).

Вам необходим текущий контекст перед выдачей команд GL.

РЕДАКТИРОВАТЬ:

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

Остановите это.Вы обращаетесь к концу вашей выделенной памяти.

Сделайте следующее:

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

Обратите внимание на меньшее, чем меньшее или равное.Для массивов C / C ++ размера N единственные допустимые индексы находятся в диапазоне [0, N-1].Ваш <= заставит for -петл попытаться получить доступ к элементу N.

Это плохо .

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 .

...