2014-07-25 146 views
1

我想在C中實現煙花效果。我有一個尺寸爲10x10x10的立方體。一枚火箭從地面開始,當它到達8層時爆炸。這是我無法做到的 - 爆炸。我如何使用正弦函數或餘弦函數來實現? enter image description here使用正弦或餘弦函數的C/C++中的3D煙花效果

a busy cat

在點

所以(5,0,7)//(X,Y,Z)//火箭雲在空中

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

這裏談到的一點,使爆炸。這可以如何實現?它也可以在隨機位置閃閃發光。提前致謝。

+2

彈道學更接近拋物線,實際上... – EOF

+0

除非你的煙花有一些小推進器和集成制導系統,使它們能夠沿着正弦路徑行進,否則它們將遵循拋物線路徑 - 至少在目前強制執行的物理定律,並忽略風阻等的影響...... – twalberg

+0

@Ezio_我很可能會使用粒子模擬(重力+某些峯值控制的爆炸......只是在一段時間或高度後分裂到各個方向。 ..)http://stackoverflow.com/a/20017455/2521214幾十年來沒有編碼這個效果(在ZXS之前最後一次在386上的asm中)也許我會爲了樂趣,如果我有時間以後(如果是的會在這裏發佈) – Spektre

回答

2

用倒置的拋物線而不是sin/cos來做這個更好。在爆炸點給每個粒子一個隨機的水平速度。這個速度是恆定的,直到粒子撞擊地面。你還需要給每個粒子一個隨機的垂直速度。然而,這次你會增加一個與-0.5*g*dt^2成比例的數值(嚴格來說,這在數值上是錯誤的,但除非你正在進行科學分析,否則你不會注意到)。在這裏,g是重力引起的加速度,dt是時間步長。就這樣。

+0

你能告訴我一個示例C代碼的單向拋物線繪圖嗎? –

+0

類似於http://www.kirupa.com/forum/attachment.php?attachmentid=52027&d=1273492985 –

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); - 用於調出整體素地圖
  • 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'Lambert 
     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 
//--------------------------------------------------------------------------- 

這是如何繪製場景:

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(); 

這是如何更新模擬一些定時器(double dt =定時器間隔,單位爲秒)

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 
     } 
    } 

這是它的外觀

particles

很抱歉的旗幟,但我沒有什麼紮實的GIF轉換與本網站不接受WMV ......你有常量來匹配玩所需的LED立方體尺寸常數上的輸出:

  1. 整個立方體貼圖dimm率(立方體。每幀MUL(200))目前(256分之200)
  2. 速度,強度v0,v1,i0,i1
  3. 數目新粒子的後爆炸目前0.95

[後爆炸目前50

  • 粒子強度DIMM率注意事項]

    List<>是動態數組可以用任何東西從std::或自己的數組只是模板...

    不要忘記將dt設置爲與更新之間經過的時間不變。希望我沒有忘記複製一些東西。希望它有幫助