为什么opengl不显示我的火焰粒子

why doesn't opengl show my fire particles

这里是main.cpp:

class Vector3
{
private:
   float x,y,z;
public:
    Vector3(float thex=0,float they=0,float thez=0)
        :x(thex),y(they),z(thez)
    {
    }
    float X()const
    {
        return x;
    }
    float Y()const
    {
        return y;
    }
    float Z()const
    {
        return z;
    }
    Vector3 operator -(const Vector3 &other)const
    {
        return Vector3(x-other.x,y-other.y,z-other.z);
    }
    static Vector3 crossproduct(const Vector3 &v,const Vector3 &u)
    {
        Vector3 resVector;
        resVector.x = u.y*v.z - u.z*v.y;
        resVector.y = u.z*v.x - u.x*v.z;
        resVector.z = u.x*v.y - u.y*v.x;

        return resVector;
    }
    Vector3 operator *(const float &scale)const
    {
        return Vector3(x*scale,y*scale,z*scale);
    }
    Vector3 operator /(const float &scale)const
    {
        return Vector3(x/scale,y/scale,z/scale);
    }
    Vector3 &operator +=(const Vector3& other)
    {
        x+=other.x;
        y+=other.y;
        z+=other.z;
        return *this;
    }
    const float *toArray()const
    {
        float *a=new float[3];
        a[0]=x;
        a[1]=y;
        a[2]=z;
        return a;
    }
};
struct Force
{
private :
    float strength;
    Vector3 orentation;
public :
    Force(const Vector3 &v,const float &s)
        :strength(s),orentation(v)
    {
    }
    Force(const Force &f)
        :strength(f.strength),orentation(f.orentation)
    {

    }
    float getStrength() const
    {
        return strength;
    }
    Vector3 getOrentation() const
    {
        return orentation;
    }
};
class Camera
{
private:
    Vector3 Position;
    Vector3 View;
    Vector3 Up;
    Vector3 lineofsight;
public:
    Camera(const Vector3 &pos, const float &lookatx, const float &lookaty):
       Position(pos), View(Vector3(lookatx,lookaty,pos.Z()-1))
       ,Up(Vector3::crossproduct(lineofsight,Vector3(1,0,0))),lineofsight(View-pos)
    {

    }
    void LookAt()
    {
        gluLookAt(Position.X(),Position.Y(),Position.Z(),View.X(),View.Y(),View.Z(),Up.X(),Up.Y(),Up.Z());
    }
};
class Particle
{
  public :
    Vector3 velocity,position,color;
    const float mass;
    float *deltatime;
    Particle(const Vector3 &pos,const Vector3 &col,const float &m,float *dt)
        :velocity(Vector3()),position(pos),color(col),mass(m),deltatime(dt)
    {

    }

    void applyforce(const Force &f)
    {
        Vector3 force=f.getOrentation()*f.getStrength();
        Vector3 accleration=force/mass;
        velocity+=accleration*(*deltatime);
        proceedintime();
    }
    void proceedintime()
    {
        position+=velocity*(*deltatime);
    }
    virtual void draw()const=0;
    virtual ~Particle()
    {

    }
};

class Emmiter;


class ParticleSystem
{
    friend class Emmiter;
private :
    deque<Particle*> particles;
    float elapsedtime;
    float *deltatime;
    float LifeOfParticles;
    unsigned short particlesperframe;
    void deleteparticles()
    {
        float div=fmod(elapsedtime,LifeOfParticles);
        if(div==0)
        {
            deque<Particle*>::const_iterator begin=particles.begin();
            deque<Particle*>::const_iterator end=particles.end();
            for(deque<Particle*>::const_iterator it=begin;it!=end;it++)
                delete (*it);
            particles.clear();
        }
    }

public :
    ParticleSystem(const float &life,float *dt)
        :elapsedtime(0),deltatime(dt),LifeOfParticles(life)
    {

    }
    void drawparticl1es()
    {
        deque<Particle*>::const_iterator begin=particles.begin();
        deque<Particle*>::const_iterator end=particles.end();

        for(deque<Particle*>::const_iterator it=begin;it!=end;it++)
        {
            (*it)->proceedintime();
            (*it)->draw();
        }
        elapsedtime+=(*deltatime);
        deleteparticles();
    }
};

class Emmiter
{
public :
    unsigned short ParticlesPerSecond;
    Vector3 position;
    ParticleSystem *ps;
    unsigned char count;
    float deltatime;
    Particle *(*emitfunc)(const Emmiter &em);
    Emmiter(const unsigned short &parpersec,const Vector3 &pos,ParticleSystem *p,const unsigned char &c)
         :ParticlesPerSecond(parpersec),position(pos),ps(p),count(c)
    {

    }
    unsigned short particlesperframe()const
    {
        return ParticlesPerSecond*deltatime;
    }
    void emitparticles()const
    {
        unsigned short numpars=deltatime*ParticlesPerSecond;
        for(unsigned char i=0;i<count;i++)
        {
            for(unsigned short j=0;j<numpars;j++)
                ps[i].particles.push_back(emitfunc(*this));
        }
    }
};
class BallParticle:public Particle
{
public :
    float radius;
    BallParticle(const Vector3 &pos,const Vector3 &col,const float &rad,const float &m,float *dt)
        :Particle(pos,col,m,dt),radius(rad)
    {


    }
    void draw() const
    {
        glPushMatrix();
        glColor3fv(color.toArray());
        glTranslatef(position.X(), position.Y(), position.Z());
        glutSolidSphere(radius, radius * 20, radius * 20);
        glPopMatrix();
    }
};
using namespace std;

float deltatime;
float oldtime;
float newtime;

ParticleSystem pars(2,&deltatime);
Emmiter emmiter(200,Vector3(0,0,8),&pars,1);

Camera camera(Vector3(0,0,3),0,0);
float myrand(const float &min,const float &max)
{
    return min+(max-min)*(float(rand())/float(RAND_MAX));
}

Particle *emitfunction(const Emmiter &em)
{
    float x=em.position.X(),y=em.position.Y(),z=em.position.Z();
    BallParticle *b=new BallParticle(Vector3(myrand(x-5,x+5),y,myrand(z-5,z+5)),Vector3(myrand(0,1),myrand(0,1),myrand(0,1)),4,0.02,&deltatime);
    b->velocity=Vector3(0,4,0);
    return b;
}
void resize(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,(4/3),2,100);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    camera.LookAt();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    newtime=glutGet(GLUT_ELAPSED_TIME)/1000;
    deltatime=newtime-oldtime;
    oldtime=newtime;
    emmiter.deltatime=deltatime;
    emmiter.emitparticles();
    pars.drawparticl1es();
    glutSwapBuffers();
}
void idle()
{
    glutPostRedisplay();
}
void init()
{
    glClearColor(1, 1, 1, 1);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(640,480);
    glutInitWindowPosition(300,200);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("Fire");
    glutReshapeFunc(resize);
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    init();
    oldtime=glutGet(GLUT_ELAPSED_TIME)/1000;
    emmiter.emitfunc=&emitfunction;
    glutMainLoop();
    return EXIT_SUCCESS;
}

我正在尝试使用 freeglut 在 opengl 中构建一个简单的火焰粒子系统,我有 Nvidia 9400GT 并正在 linux mint 17.1 64 位上工作。

我尝试了 apitrace 但它没有显示任何内容,我调试了我的程序,emmiter 似乎工作正常,因为粒子系统已被填充,但它没有显示任何内容。

大多数时候它是相机,但我没有任何问题。那么问题是什么?

你的相机在 $DEITY-knows-where 关了,你的 glutSolidSphere()s 太大了。并且过度细分。

不要重新发明 vec3 class,使用 GLM, Eigen 或类似的东西。

您在多个地方将整数除以整数并希望得到浮点数。通过 f 后缀强制除数浮动。

总计:

#include <GL/glut.h>

// http://glm.g-truc.net/
#include <glm/glm.hpp>

#include <deque>
using namespace std;

typedef glm::vec3 Vector3;

struct Force
{
private :
    float strength;
    Vector3 orentation;
public :
    Force(const Vector3 &v,const float &s)
        :strength(s),orentation(v)
    {
    }
    Force(const Force &f)
        :strength(f.strength),orentation(f.orentation)
    {

    }
    float getStrength() const
    {
        return strength;
    }
    Vector3 getOrentation() const
    {
        return orentation;
    }
};

class Particle
{
public :
    Vector3 velocity,position,color;
    const float mass;
    float *deltatime;
    Particle(const Vector3 &pos,const Vector3 &col,const float &m,float *dt)
        :velocity(Vector3()),position(pos),color(col),mass(m),deltatime(dt)
    {

    }

    void applyforce(const Force &f)
    {
        Vector3 force=f.getOrentation()*f.getStrength();
        Vector3 accleration=force/mass;
        velocity+=accleration*(*deltatime);
        proceedintime();
    }
    void proceedintime()
    {
        position+=velocity*(*deltatime);
    }
    virtual void draw()const=0;
    virtual ~Particle()
    {

    }
};

class Emmiter;


class ParticleSystem
{
    friend class Emmiter;
private :
    deque<Particle*> particles;
    float elapsedtime;
    float *deltatime;
    float LifeOfParticles;
    unsigned short particlesperframe;
    void deleteparticles()
    {
        float div=fmod(elapsedtime,LifeOfParticles);
        if(div==0)
        {
            deque<Particle*>::const_iterator begin=particles.begin();
            deque<Particle*>::const_iterator end=particles.end();
            for(deque<Particle*>::const_iterator it=begin;it!=end;it++)
                delete (*it);
            particles.clear();
        }
    }

public :
    ParticleSystem(const float &life,float *dt)
        :elapsedtime(0),deltatime(dt),LifeOfParticles(life)
    {

    }
    void drawparticl1es()
    {
        deque<Particle*>::const_iterator begin=particles.begin();
        deque<Particle*>::const_iterator end=particles.end();

        for(deque<Particle*>::const_iterator it=begin;it!=end;it++)
        {
            (*it)->proceedintime();
            (*it)->draw();
        }
        elapsedtime+=(*deltatime);
        deleteparticles();
    }
};

class Emmiter
{
public :
    unsigned short ParticlesPerSecond;
    Vector3 position;
    ParticleSystem *ps;
    unsigned char count;
    float deltatime;
    Particle *(*emitfunc)(const Emmiter &em);
    Emmiter(const unsigned short &parpersec,const Vector3 &pos,ParticleSystem *p,const unsigned char &c)
        :ParticlesPerSecond(parpersec),position(pos),ps(p),count(c)
    {

    }
    unsigned short particlesperframe()const
    {
        return ParticlesPerSecond*deltatime;
    }
    void emitparticles()const
    {
        unsigned short numpars=deltatime*ParticlesPerSecond;
        for(unsigned char i=0;i<count;i++)
        {
            for(unsigned short j=0;j<numpars;j++)
                ps[i].particles.push_back(emitfunc(*this));
        }
    }
};

class BallParticle:public Particle
{
public :
    float radius;
    BallParticle(const Vector3 &pos,const Vector3 &col,const float &rad,const float &m,float *dt)
        :Particle(pos,col,m,dt),radius(rad)
    {
    }

    void draw() const
    {
        glPushMatrix();
        glColor3fv( (GLfloat*)&color );
        glTranslatef(position.x, position.y, position.z);
        glutSolidSphere(radius, 10, 10);
        glPopMatrix();
    }
};

float deltatime;
float oldtime;
float newtime;

ParticleSystem pars(2,&deltatime);
Emmiter emmiter(200,Vector3(0,0,8),&pars,1);

float myrand(const float &min,const float &max)
{
    return min+(max-min)*(float(rand())/float(RAND_MAX));
}

Particle *emitfunction(const Emmiter &em)
{
    float x=em.position.x,y=em.position.y,z=em.position.z;
    BallParticle *b=new BallParticle
        (
        Vector3(myrand(x-5,x+5),y,myrand(z-5,z+5)),
        Vector3(myrand(0,1),myrand(0,1),myrand(0,1)),
        0.2,
        0.02,
        &deltatime
        );
    b->velocity=Vector3(0,4,0);
    return b;
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,(4/3.0f),2,100);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt( 20, 20, 20, 0, 0, 0, 0, 0, 1 );

    newtime=glutGet(GLUT_ELAPSED_TIME)/1000.0f;
    deltatime=newtime-oldtime;
    oldtime=newtime;
    emmiter.deltatime=deltatime;
    emmiter.emitparticles();
    pars.drawparticl1es();

    glutSwapBuffers();
}

void timer( int value )
{
    glutTimerFunc( 16, timer, 0 );
    glutPostRedisplay();
}

void init()
{
    glClearColor(1, 1, 1, 1);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(640,480);
    glutInitWindowPosition(300,200);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("Fire");
    glutDisplayFunc(display);
    glutTimerFunc(0, timer, 0);
    init();
    oldtime=glutGet(GLUT_ELAPSED_TIME)/1000.0f;
    emmiter.emitfunc=&emitfunction;
    glutMainLoop();
    return EXIT_SUCCESS;
}