//The main fluid simulation step void FluidSim::advance(float dt) { float t = 0; while(t < dt) { float substep = cfl(); if(t + substep > dt) substep = dt - t; //Passively advect particles advect_particles(substep); //Estimate the liquid signed distance compute_phi(); //Advance the velocity advect(substep); add_force(substep); apply_viscosity(substep); apply_projection(substep); //Pressure projection only produces valid velocities in faces with non-zero associated face area. //Because the advection step may interpolate from these invalid faces, //we must extrapolate velocities from the fluid domain into these zero-area faces. extrapolate(u, u_valid); extrapolate(v, v_valid); //For extrapolated velocities, replace the normal component with //that of the object. constrain_velocity(); t+=substep; } }
static void reshape(int w, int h) { window_x = w; window_y = h; glViewport(0, 0, (GLint)w, (GLint)h); apply_projection(); glMatrixMode(GL_MODELVIEW); }
void mnehs_affine_warp(float *warp, float *h, int wh, int hh, int pd, float *a, int wa, int ha, float *b, int wb, int hb, double PA[8], double PB[8]) { for (int j = 0; j < hh; j++) for (int i = 0; i < wh; i++) { float vh = getsample_nan(h, wh, hh, 1, i, j, 0); double ijh[3] = {i, j, vh}; double paijh[3], pbijh[3]; apply_projection(paijh, PA, ijh); apply_projection(pbijh, PB, ijh); float va[pd], vb[pd]; bicubic_interpolation(va, a, wa, ha, pd, paijh[0], paijh[1]); bicubic_interpolation(vb, b, wb, hb, pd, pbijh[0], pbijh[1]); for (int l = 0; l < pd; l++) warp[pd*(j*wh+i)+l] = va[l] - vb[l]; } }
static void draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); apply_projection(); glPushMatrix(); glLoadIdentity(); if (camera_type == 1 || camera_type == 2) cm_apply_target_camera(tcamera); else cm_apply_fps_camera(fcamera); /* +/-X Cubes */ rh_draw_cube((VEC3){ 3, 0, 0 }, (VEC3){ 1, 1, 1 }, (VEC3){ 0, cuberot, 0 }); rh_draw_cube((VEC3){ -3, 0, 0 }, (VEC3){ 1, 1, 1 }, (VEC3){ 0, cuberot, 0 }); /* +/-Z Cubes */ rh_draw_cube((VEC3){ 0, 0, 3 }, (VEC3){ 1.25, 1.25, 1.25 }, (VEC3){ 0, -cuberot, 0 }); rh_draw_cube((VEC3){ 0, 0, -3 }, (VEC3){ 1.25, 1.25, 1.25 }, (VEC3){ 0, -cuberot, 0 }); /* Sphere stack of varing sizes and qualities */ rh_draw_sphere((VEC3){ 0, 0, 0 }, (VEC3){ 1, 1, 1 }, (VEC3){ spherot, 0, 0 }, 3); rh_draw_sphere((VEC3){ 0, -1, 0 }, (VEC3){ .5, .5, .5 }, (VEC3){ -spherot, 0, 0 }, 2); rh_draw_sphere((VEC3){ 0, -1.5, 0 }, (VEC3){ .25, .25, .25 }, (VEC3){ spherot, 0, 0 }, 1); /* Polygon stack of various edge counts and rotations */ rh_draw_extended_polygon((VEC3){ 0, 1, 0 }, (VEC3){ 1, .25, 1 }, (VEC3){ 0, polyrot, 0 }, 3); rh_draw_extended_polygon((VEC3){ 0, 1.75, 0 }, (VEC3){ 1, .25, 1 }, (VEC3){ 0, -polyrot, 0 }, 4); rh_draw_extended_polygon((VEC3){ 0, 2.5, 0 }, (VEC3){ 1, .25, 1 }, (VEC3){ 0, polyrot, 0 }, 5); rh_draw_extended_polygon((VEC3){ 0, 3.25, 0 }, (VEC3){ 1, .25, 1 }, (VEC3){ 0, -polyrot, 0 }, 7); rh_draw_extended_polygon((VEC3){ 0, 4, 0 }, (VEC3){ 1, .25, 1 }, (VEC3){ 0, polyrot, 0 }, 10); draw_gui(); glPopMatrix(); glFlush(); glutSwapBuffers(); }
// Modèle Numérique d'Élévation Horn Schunck (cas affine) void mnehs_affine(float *out_h, float *init_h, int ow, int oh, float *a, int wa, int ha, float *b, int wb, int hb, double PA[8], double PB[8], float alpha2, int niter) { // allocate temporary images float *h = xmalloc(ow * oh * sizeof*h); // h-increment float *Q = xmalloc(ow * oh * sizeof*Q); // Q float *amb = xmalloc(ow * oh * sizeof*amb); // A-B (warped) float *ga = xmalloc(2 * wa * ha * sizeof*ga); // grad(A) float *gb = xmalloc(2 * wb * hb * sizeof*gb); // grad(B) // gradient of A and B fill_gradient(ga, a, wa, ha); fill_gradient(gb, b, wb, hb); // fill images q and amb (a minus b) for (int j = 0; j < oh; j++) for (int i = 0; i < ow; i++) { float h0 = getsample_nan(init_h, ow, oh, 1, i, j, 0); double ijh[3] = {i, j, h0}, paijh[3], pbijh[3]; apply_projection(paijh, PA, ijh); apply_projection(pbijh, PB, ijh); float va, vb, vga[2], vgb[2]; bicubic_interpolation_nans(&va, a, wa, ha, 1, paijh[0], paijh[1]); bicubic_interpolation_nans(&vb, b, wb, hb, 1, pbijh[0], pbijh[1]); bicubic_interpolation(vga, ga, wa, ha, 2, paijh[0], paijh[1]); bicubic_interpolation(vgb, gb, wb, hb, 2, pbijh[0], pbijh[1]); float gapa = vga[0] * PA[2] + vga[1] * PA[6]; float gbpb = vgb[0] * PB[2] + vgb[1] * PB[6]; Q [j*ow+i] = gapa - gbpb; amb[j*ow+i] = va - vb; } nusavec("Q_%d.tiff", global_scale, Q, ow, oh, 1); nusavec("amb_%d.tiff", global_scale, amb, ow, oh, 1); // initialize h for (int i = 0; i < ow * oh; i++) h[i] = 0; // run the iterations (without warps) for (int iter = 0; iter < niter; iter++) { for (int j = 0; j < oh; j++) for (int i = 0; i < ow; i++) { int ij = j * ow + i; if (!isfinite(amb[ij])) continue; float ax = laplacian_at(h, ow, oh, i, j); ax -= Q[ij] * (Q[ij] * h[ij] + amb[ij]) / alpha2; h[ij] += TAU() * ax; } } nusavec("h_%d.tiff", global_scale, h, ow, oh, 1); // update result for (int i = 0; i < ow * oh; i++) out_h[i] = init_h[i] + h[i]; // cleanup and exit free(h); free(Q); free(amb); free(ga); free(gb); }