使用正弦或余弦函数在C / C ++中进行3D烟花效果

问题描述 投票:1回答:2

我想在C中实现烟花效果。我有一个尺寸为10x10x10的立方体。火箭从地面开始,当它到达8楼时,它会爆炸。这是我不能做的 - 爆炸。如何使用正弦或余弦函数实现此功能?

所以在点(5,0,7)//(x,y,z)//火箭飞向空中

for (j=0; j<9; j++) {
    setpoint(x, y, j);
    delay(100);
    clean();  //clears everything
}

这就是制造爆炸的重点。如何实现这一目标?它也可以在随机位置闪烁。提前致谢。

c++ c animation sine cosine
2个回答
2
投票

最好使用倒置抛物线而不是sin / cos来做到这一点。在爆炸点处给每个粒子一个随机的水平速度。这个速度是恒定的,直到粒子撞击地面。您还需要为每个粒子提供随机垂直速度。但是,这一次,你将增加这个速度与-0.5*g*dt^2成比例(严格来说,这在数字上是错误的,但除非你进行科学分析,否则你不会注意到)。在这里,g是由于引力引起的加速度,而dt是时间步长。就这样。


5
投票

嘿我确实找到了一些时间(在1.5 hod完成)并将为这个有趣的东西:)

确定首先在LED_cube类中进行一些更新以支持体素点输出,并使其余调光与来自另一个问题的球体相同...

//---------------------------------------------------------------------------
//--- 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<n;x++)
     for (y=0;y<n;y++)
      for (z=0;z<n;z++)
       map[x][y][z]=col;
    }
//---------------------------------------------------------------------------
void LED_cube::mul(int mul)
    {
    union { BYTE db[4]; int dd; } c;
    int x,y,z,i;
    for (x=0;x<n;x++)
     for (y=0;y<n;y++)
      for (z=0;z<n;z++)
        {
        c.dd=map[x][y][z];
        i=c.db[0]; i=(i*mul)>>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<n))
     if ((y>=0)&&(y<n))
      if ((z>=0)&&(z<n))
       map[x][y][z]=col;
    }
//---------------------------------------------------------------------------
void LED_cube::sphere(int x0,int y0,int z0,int r,int col)
    {
    int x,y,z,xa,ya,za,xb,yb,zb,xr,yr,zr,xx,yy,zz,rr=r*r;
    // bounding box
    xa=x0-r; if (xa<0) xa=0; xb=x0+r; if (xb>n) 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;x<xb;x++,xr++,xx=xr*xr)
     for (y=ya,yr=y-y0,yy=yr*yr;y<yb;y++,yr++,yy=yr*yr)
        {
        zz=rr-xx-yy; if (zz<0) continue; zr=sqrt(zz);
        z=z0-zr; if ((z>0)&&(z<n)) map[x][y][z]=col;
        z=z0+zr; if ((z>0)&&(z<n)) map[x][y][z]=col;
        }
    // project xz plane
    for (x=xa,xr=x-x0,xx=xr*xr;x<xb;x++,xr++,xx=xr*xr)
     for (z=za,zr=z-z0,zz=zr*zr;z<zb;z++,zr++,zz=zr*zr)
        {
        yy=rr-xx-zz; if (yy<0) continue; yr=sqrt(yy);
        y=y0-yr; if ((y>0)&&(y<n)) map[x][y][z]=col;
        y=y0+yr; if ((y>0)&&(y<n)) map[x][y][z]=col;
        }
    // project yz plane
    for (y=ya,yr=y-y0,yy=yr*yr;y<yb;y++,yr++,yy=yr*yr)
     for (z=za,zr=z-z0,zz=zr*zr;z<zb;z++,zr++,zz=zr*zr)
        {
        xx=rr-zz-yy; if (xx<0) continue; xr=sqrt(xx);
        x=x0-xr; if ((x>0)&&(x<n)) map[x][y][z]=col;
        x=x0+xr; if ((x>0)&&(x<n)) map[x][y][z]=col;
        }
    }
//---------------------------------------------------------------------------
void LED_cube::glDraw()
    {
    #ifdef __gl_h_
    int x,y,z;
    float p[3],dp=1.0/float(n-1);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE,GL_ONE);

    glPointSize(2.0);

    glBegin(GL_POINTS);

    for (p[0]=-0.5,x=0;x<n;x++,p[0]+=dp)
     for (p[1]=-0.5,y=0;y<n;y++,p[1]+=dp)
      for (p[2]=-0.5,z=0;z<n;z++,p[2]+=dp)
        {
        glColor4ubv((BYTE*)(&map[x][y][z]));
        glVertex3fv(p);
        }
    glEnd();
    glDisable(GL_BLEND);
    glPointSize(1.0);
    #endif
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//--------------------------------------------------------------------------
  • 重要的是:
  • void mul(int mul); - 用于调整整个体素图
  • qazxsw poi - 用于设置单个体素的颜色

现在是粒子

void point(int x,int y,int z,int col);

这是如何绘制场景:

//---------------------------------------------------------------------------
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<particle> particles; // use any list/array you have at your disposal you need just function add and delete item
//---------------------------------------------------------------------------

这是如何更新某些计时器的模拟(双dt =计时器间隔,以秒为单位!!!)

cube.mul(200);          // dimm the voxel map insted of clearing it  (intensity*=200/256)
for (int i=0;i<particles.num;i++)
    {
    particle *p=&particles[i];
    int j=double(255.0*p->i);
    if (j<0) j=0;
    if (j>255) j=255;
    cube.point(p->x,p->y,p->z,0x00010101*j);
    }
cube.glDraw();

这是它的外观

对不起横幅,但我没有任何可靠的gif转换,这个网站将不接受wmv ...你必须使用常量来匹配你的LED立方体大小常量的所需输出:

  1. 每帧的整个立方体贴图dimm rate(cube.mul(200))当前(200/256)
  2. 速度,强度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;i<particles.num;i++) // update all particles in list { particle *p=&particles[i]; p->update(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 } }
  3. 爆炸后新粒子的数量目前为50
  4. 爆炸后颗粒强度dimm率目前为0.95

[笔记]

v0,v1,i0,i1只是动态数组的模板可以使用List<>或自己的数组中的任何东西......

不要忘记将std::设置为更新之间经过的时间。希望我没有忘记复制一些东西。希望能帮助到你

© www.soinside.com 2019 - 2024. All rights reserved.