#include #include #include #include #include "Pattern.h" /* In this version: use forward projection instead of sime-lagrangian lookups combine ood2 lookup with dirx and diry */ //---- Render buffer PATTERN_RGB buf; //---- GLOBAL DATA -----------------------------------------------------------// /* * Size of the simulation grid, i.e. the number of grid * points are (DIM x DIM). * */ #define DIM 64 #define ARRAYSIZE (DIM * 2*(DIM/2+1)) /* * Simulation time step: you may need to change this to suit * your particular machine speed. * */ double dt = 2.0; // default 0.4 int winWidth, winHeight; int drawVelocities = 0; int wireframe = 0; int lmx, lmy; double t = 0; /* * See Jos Stam, "A Simple Fluid Solver Based on the FFT", * http://www.dgp.utoronto.ca/people/stam/reality/Research/pub.html * for more details on the following code. * */ fftw_real u[DIM * 2*(DIM/2+1)]; fftw_real v[DIM * 2*(DIM/2+1)]; fftw_real u0[DIM * 2*(DIM/2+1)]; fftw_real v0[DIM * 2*(DIM/2+1)]; fftw_real rho[DIM * DIM]; fftw_real rho0[DIM * DIM]; /* Smoke density */ fftw_real u_u0[DIM * DIM]; fftw_real u_v0[DIM * DIM]; /* User-induced forces */ static rfftwnd_plan plan_rc, plan_cr; //---- init_FFT // Sets up the FFT engine #define FFT(s,u)\ if(s==1) rfftwnd_one_real_to_complex(plan_rc,(fftw_real *)u,(fftw_complex*)u);\ else rfftwnd_one_complex_to_real(plan_cr,(fftw_complex *)u,(fftw_real *)u) #define floor(x) ((x)>=0.0?((int)(x)):(-((int)(1-(x))))) void stable_solve ( int n, fftw_real * u, fftw_real * v, fftw_real * u0, fftw_real * v0, fftw_real visc, fftw_real dt ) { fftw_real x, y, x0, y0, f, r, U[2], V[2], s, t; int i, j, i0, j0, i1, j1; // apply forces for ( i=0 ; i 255 ) c = 255; buf.buf[j+DIM*2][i][0] = c; buf.buf[j+DIM*2][i][1] = c; buf.buf[j+DIM*2][i][2] = c; // y velocity c = (int)(v0[idx] * 128.0 + 128.0); if( c < 0 ) c = 0; if( c > 255 ) c = 255; buf.buf[j+DIM*2][i+DIM][0] = c; buf.buf[j+DIM*2][i+DIM][1] = c; buf.buf[j+DIM*2][i+DIM][2] = c; } } */ for ( i=0 ; i<=n ; i+=2 ) { x = 0.5f*i; for ( j=0 ; j (DIM - 1)) { X = DIM - 1; } if (Y > (DIM - 1)) { Y = DIM - 1; } if (X < 0) { X = 0; } if (Y < 0) { Y = 0; } /* Add force at the cursor location */ // my = winHeight - my; /* dx = mx - lmx; dy = my - lmy; len = sqrt(dx * dx + dy * dy); if (len != 0.0) { dx *= 1.f / len; dy *= 1.f / len; } u_u0[Y * DIM + X] += dx; u_v0[Y * DIM + X] += dy; */ /* Increase matter density at the cursor location */ rho[Y * DIM + X] += 10.0f; lmx = mx; lmy = my; } /* */ double dist_lookup[ DIM*2 ][ DIM*2 ]; double ood2_lookup[ DIM*2 ][ DIM*2 ]; double dirx_lookup[ DIM*2 ][ DIM*2 ]; double diry_lookup[ DIM*2 ][ DIM*2 ]; void calculate_gravity_field() { int i, j, x, y; double px, py; double m1; double oodist2; int idx1=0,idx2=0; double scale_factor = 1.0/(DIM*DIM); for(j=0; j 0.001 ) { for( y=0; y (x,y) oodist2 *= m1+rho[idx2++]; px += dirx_lookup[DIM+y-j][DIM+x-i] * oodist2; py += diry_lookup[DIM+y-j][DIM+x-i] * oodist2; } } u0[ idx1 ] = -px*scale_factor / m1; v0[ idx1 ] = -py*scale_factor / m1; } else { u0[idx1] = v0[idx1] = 0; } u0[idx1] += u_u0[idx1]; v0[idx1] += u_v0[idx1]; u_u0[idx1]=0; u_v0[idx1]=0; idx1 ++; } } void setForces(void) { int i, j; for (i = 0; i < DIM * DIM; i++) { rho0[i] = rho[i]; } calculate_gravity_field(); } //---- Pattern_Startup -------------------------------------------------------// void Pattern_Startup() { int x, y; // calculate the distance from the centre point (SIZE,SIZE) in (SIZE*2,SIZE*2) array double dx, dy, d2, d; for( y=0; y 20 && x < DIM-20 && y>20 && y 255 ) c = 255; buf.buf[j+DIM*2][i][0] = c; buf.buf[j+DIM*2][i][1] = c; buf.buf[j+DIM*2][i][2] = c; // y force c = (int)(v0[idx] * 12800.0 + 128.0); if( c < 0 ) c = 0; if( c > 255 ) c = 255; buf.buf[j+DIM*2][i+DIM][0] = c; buf.buf[j+DIM*2][i+DIM][1] = c; buf.buf[j+DIM*2][i+DIM][2] = c; } } //- Update fluid stable_solve(DIM, u, v, u0, v0, 0.0, dt); diffuse_matter(DIM, u, v, rho, rho0, dt); t += dt; //- Copy matter into RGB buffer for (j = 0; j < DIM - 1; j++) { idx = j * DIM; for (i = 0; i < DIM - 1; i++, idx++) { // mass c = (int)(rho0[idx] * 255); if( c < 0 ) c = 0; if( c > 255 ) c = 255; buf.buf[j][i][0] = c; buf.buf[j][i][1] = c; buf.buf[j][i][2] = c; // x velocity c = (int)(u[idx] * 12800.0 + 128.0); if( c < 0 ) c = 0; if( c > 255 ) c = 255; buf.buf[j+DIM][i][0] = c; buf.buf[j+DIM][i][1] = c; buf.buf[j+DIM][i][2] = c; // y velocity c = (int)(v[idx] * 12800.0 + 128.0); if( c < 0 ) c = 0; if( c > 255 ) c = 255; buf.buf[j+DIM][i+DIM][0] = c; buf.buf[j+DIM][i+DIM][1] = c; buf.buf[j+DIM][i+DIM][2] = c; } } //- Return buffer for rendering return &buf; } //---- END OF FILE -----------------------------------------------------------//