3D Fireworks Effect in C/C++ using sine or cosine function

前端 未结 2 2027
天命终不由人
天命终不由人 2021-01-25 05:49

I am trying to implement fireworks effect in C. I have a cube with dimensions 10x10x10. A rocket starts from the ground, and when it reaches 8th floor it explodes. Here\'s the p

2条回答
  •  不思量自难忘°
    2021-01-25 06:14

    Heh I did find some time (done in 1.5 hod) and will for this funny stuff :)

    OK first some updates in the LED_cube class to support voxel point output and dimming the rest is the same as for the sphere from your another question ...

    //---------------------------------------------------------------------------
    //--- LED cube class ver: 1.01 ----------------------------------------------
    //---------------------------------------------------------------------------
    #ifndef _LED_cube_h
    #define _LED_cube_h
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    const int _LED_cube_size=32;
    //---------------------------------------------------------------------------
    class LED_cube
        {
    public:
        int n,map[_LED_cube_size][_LED_cube_size][_LED_cube_size];
    
        LED_cube()              { n=_LED_cube_size; }
        LED_cube(LED_cube& a)   { *this=a; }
        ~LED_cube()             { }
        LED_cube* operator = (const LED_cube *a) { *this=*a; return this; }
        //LED_cube* operator = (const LED_cube &a) { /*...copy...*/ return this; }
        void cls(int col);                                  // clear cube with col 0x00BBGGRR
        void mul(int mul);                                  // mull all channels by mul and then shr by 8
        void point(int x,int y,int z,int col);              // draws voxel with col 0x00BBGGRR
        void sphere(int x0,int y0,int z0,int r,int col);    // draws sphere surface with col 0x00BBGGRR
        void glDraw();                                      // render cube by OpenGL as 1x1x1 cube at 0,0,0
        };
    //---------------------------------------------------------------------------
    void LED_cube::cls(int col)
        {
        int x,y,z;
        for (x=0;x>8; c.db[0]=i;
            i=c.db[1]; i=(i*mul)>>8; c.db[1]=i;
            i=c.db[2]; i=(i*mul)>>8; c.db[2]=i;
            map[x][y][z]=c.dd;
            }
        }
    //---------------------------------------------------------------------------
    void LED_cube::point(int x,int y,int z,int col)
        {
        if ((x>=0)&&(x=0)&&(y=0)&&(zn) xb=n;
        ya=y0-r; if (ya<0) ya=0; yb=y0+r; if (yb>n) yb=n;
        za=z0-r; if (za<0) za=0; zb=z0+r; if (zb>n) zb=n;
        // project xy plane
        for (x=xa,xr=x-x0,xx=xr*xr;x0)&&(z0)&&(z0)&&(y0)&&(y0)&&(x0)&&(x
    • the important stuff are:
    • void mul(int mul); - used for dimming out the whole voxel map
    • void point(int x,int y,int z,int col); - used to set collor of single voxel

    Now the particles

    //---------------------------------------------------------------------------
    class particle
        {
    public:
        double  x, y, z;    // position
        double vx,vy,vz;    // velocity
        double ax,ay,az;    // acceleration driving force/m after update is reseted
        double i;           // intensity
        particle()
            {
             x=0.0;  y=0.0;  z=0.0;
            vx=0.0; vy=0.0; vz=0.0;
            ax=0.0; ay=0.0; az=0.0;
            i=0.0;
            };
        particle(particle& a){ *this=a; };
        ~particle(){};
        particle* operator = (const particle *a) { *this=*a; return this; };
    //  particle* operator = (const particle &a) { ...copy... return this; };
    
        void update(double dt)
            {
            double c0,c;
            // gravity
            ay-=9.81;
            // friction in gass
            c=0.001;
            if (vx>0.0) c0=-c; else c0=+c; ax+=vx*vx*c0;
            if (vy>0.0) c0=-c; else c0=+c; ay+=vy*vy*c0;
            if (vz>0.0) c0=-c; else c0=+c; az+=vz*vz*c0;
            // friction in liquid
            c=0.0;
            ax-=vx*vx*vx*c;
            ay-=vy*vy*vy*c;
            az-=vz*vz*vz*c;
            // D'ALembert
            vx+=ax*dt;
            vy+=ay*dt;
            vz+=az*dt;
             x+=vx*dt;
             y+=vy*dt;
             z+=vz*dt;
            // reset acceleration
            ax=0.0; ay=0.0; az=0.0;
            }
        };
    //---------------------------------------------------------------------------
    List particles; // use any list/array you have at your disposal you need just function add and delete item
    //---------------------------------------------------------------------------
    

    this is how to draw the scene:

    cube.mul(200);          // dimm the voxel map insted of clearing it  (intensity*=200/256)
    for (int i=0;ii);
        if (j<0) j=0;
        if (j>255) j=255;
        cube.point(p->x,p->y,p->z,0x00010101*j);
        }
    cube.glDraw();
    

    This is how to update simulation in some timer (double dt=timer interval in seconds !!!)

    double i0=1.0; // intensity at shoot start
    double i1=0.9*i0; // intensity after explosion
    double v0=0.6*double(_LED_cube_size); // shoot start speed
    double v1=0.5*v0,v1h=0.5*v1; // explosion speed
    if (particles.num==0) // shoot new particle if none in list
        {
        particle p;
        p.x=_LED_cube_size>>1;
        p.y=0.0;
        p.z=_LED_cube_size>>1;
        p.vy=v0;
        p.i=i0;
        particles.add(p);
        }
    for (int i=0;iupdate(dt);
        if (fabs(p->i-i0)<1e-6)     // intensity detect state before explosion
            {
            if (p->vy<=0.0)         // explode near/after peak reached
                {
                particle q;
                q.x=p->x;               // copy position
                q.y=p->y;
                q.z=p->z;
                q.i=i1;                 // new intensity
                particles.del(i);       // remove old particle
                i--;
                for (int j=0;j<50;j++)  // add new random particles
                    {
                    q.vx=v1*Random()-v1h;
                    q.vy=v1*Random()-v1h;
                    q.vz=v1*Random()-v1h;
                    particles.add(q)-v1h;
                    }
                continue;               // avoid usage of p pointer after delete
                }
            }
        else{                       // after explosion
            p->i*=0.95;             // dimm intensity
            }
        if ((p->y<0.0)||(p->i<0.01))// remove particles below the ground or too dimmed out
            {
            particles.del(i);
            i--;
            continue;               // avoid usage of p pointer after delete
            }
        }
    

    This is how it looks

    particles

    Sorry for the banner but I do not have anything solid for gif conversion and this site will not accept wmv ... You have to play with constants to match desired output on your LED cube size constants to play with:

    1. whole cube map dimm rate (cube.mul(200)) currently (200/256) per frame
    2. speeds,intensities v0,v1,i0,i1
    3. number of new particles after explosion currently 50
    4. particle intensity dimm rate after explosion currently 0.95

    [Notes]

    List<> is just template for dynamic array can use anything from std:: or own array ...

    Do not forget to set dt constant to time elapsed between updates. Hope I did not forget to copy something. Hope it helps

提交回复
热议问题