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
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<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);
- used for dimming out the whole voxel mapvoid point(int x,int y,int z,int col);
- used to set collor of single voxelNow 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<particle> 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;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();
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;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
}
}
This is how it looks
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:
v0,v1,i0,i1
[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
It's better to do this using an upside down parabola instead of sin/cos. At the point of explosion give each particle a random horizontal speed. This speed is constant till the particle hits the ground. You also need to give each particle a random vertical speed. this time, however, you'll add to this speed an amount proportional to -0.5*g*dt^2
(strictly speaking, this is numerically wrong, but you won't notice unless you're doing scientific analysis). Here, g
is the acceleration due to gravitation and dt
is the time step. That's all.