// run the solver... int main(int argc, char *argv[]) { printf("Init\n"); // allocate memory vel_x.resize(SIZE*SIZE); vel_y.resize(SIZE*SIZE); temp.resize(SIZE*SIZE); eta.resize(SIZE*SIZE); // initialize grid for (int i=0;i<SIZE;i++) for (int j=0;j<SIZE;j++) { const int index = i+j*SIZE; vel_x[index] = vel_y[index] = temp[index] = 0.; // default water height 1 eta[index] = 1.; } // init an off-center initial wave for (int i=3*SIZE/6; i<4*SIZE/6; i++) for (int j=3*SIZE/6; j<4*SIZE/6; j++) { const int index = i + j*SIZE; //eta[index] = 1.1; } printf("Starting simulation...\n"); Real simulationTime = 0.; int simulationStep = 0; while (simulationTime < END_TIME) { printf("Step %d ",simulationStep); advectArray( eta ,0 ); advectArray( vel_x ,1 ); advectArray( vel_y ,2 ); updateHeight(); updateVelocities(); setBoundary(); addRandomDrop(); simulationTime += dt; simulationStep++; // should we write an image for this step? if ( (simulationStep % IMAGESTEPS)== 0) { writeImage( simulationStep ); } printf("\n"); } printf("SWS-simulation done!\n"); return 0; }
void WaterBall::update(float dt) { if(state == WATERDROP_STATE_NONE) { return ; } else if(state == WATERDROP_STATE_FILL) { if(drops.size() < 10) { uint64_t now = rx_hrtime(); if(now >= spawn_timeout) { spawn_timeout = now + spawn_delay * 1000000ull; addRandomDrop(); /* if(drops.size() == 10) { printf("We reached N drops, flush!\n"); state = WATERDROP_STATE_FLUSH; flush_timeout = now + flush_delay * 1000000LLU; } */ } } } else if(state == WATERDROP_STATE_FLUSH) { #if 1 // Remove the water drop when we need to flush (see below for a version where we remove // water drops only when they are in a certain radius. uint64_t now = rx_hrtime(); if(now >= flush_timeout) { if(drops.size()) { drops.erase(drops.begin()); flush_timeout = now + flush_delay * 1000000ull; if(!drops.size()) { state = WATERDROP_STATE_FREE; } } else { state = WATERDROP_STATE_NORMAL; } } #endif } if(!drops.size()) { return ; } vec2 dir; float dist = 0.0f; float dist_sq = 0.0f; vec2 f = 0.0f; float radius = drops.size() * radius_per_drop; float radius_sq = radius * radius; float neighbor_dist = 1; float neighbor_dist_sq = neighbor_dist * neighbor_dist; // REPEL FORCES: #if 1 for(size_t i = 0; i < drops.size(); ++i) { WaterDrop& a = drops[i]; for(size_t j = i + i; j < drops.size(); ++j) { WaterDrop& b = drops[j]; dir = b.position - a.position; dist_sq = dot(dir, dir); if(dist_sq > neighbor_dist_sq) { continue; } if(dist_sq < 0.01) { continue; } dir = normalized(dir); f = repel_force * (1.0 - (1.0 / dist_sq)) * dir; a.forces -= f; b.forces += f; } } #endif // ATTRACT FORCES float max_speed_sq = max_speed * max_speed; float speed_sq; float k = 1.0f; uint64_t now = rx_hrtime(); std::vector<WaterDrop>::iterator it = drops.begin(); while(it != drops.end()) { WaterDrop& d = *it; { dir = position - d.position; dist = length(dir); if(dist < 0.01) { dist = 0.01; } if(dist > radius) { /* when the particle is outiside the radius, it's attracted a lot more to the center */ k = 15.0; } #if 0 // This is where we flush the water drops! if(state == WATERDROP_STATE_FLUSH && dist < radius) { if(now >= flush_timeout) { if(drops.size()) { it = drops.erase(drops.begin()); flush_timeout = now + flush_delay * 1000000ull; if(!drops.size()) { state = WATERDROP_STATE_FREE; break; } continue; } } } #endif dir /= dist; f = k * attract_force * (dist/radius) * dir; d.forces += f; } d.forces *= d.inv_mass * dt; d.velocity += d.forces * dt; d.position += d.velocity; d.forces = 0; // we do not add a fake drag force, but we limit the speed, this will make the // particles bounce forever. speed_sq = dot(d.velocity, d.velocity); if(speed_sq > max_speed_sq) { d.velocity = normalized(d.velocity); d.velocity *= max_speed; } ++it; } /* glBindBuffer(GL_ARRAY_BUFFER, basic_vbo); size_t bytes_needed = sizeof(WaterDrop) * drops.size(); if(bytes_needed > bytes_allocated) { glBufferData(GL_ARRAY_BUFFER, bytes_needed, drops[0].position.ptr(), GL_STREAM_DRAW); } else { glBufferSubData(GL_ARRAY_BUFFER, 0, bytes_needed, drops[0].position.ptr()); } */ }