void FluidSim::compute_phi() { //Estimate from particles liquid_phi.assign(3*dx); for(unsigned int p = 0; p < particles.size(); ++p) { Vec2f point = particles[p]; int i,j; float fx,fy; //determine containing cell; get_barycentric((point[0])/dx-0.5f, i, fx, 0, ni); get_barycentric((point[1])/dx-0.5f, j, fy, 0, nj); //compute distance to surrounding few points, keep if it's the minimum for(int j_off = j-2; j_off<=j+2; ++j_off) for(int i_off = i-2; i_off<=i+2; ++i_off) { if(i_off < 0 || i_off >= ni || j_off < 0 || j_off >= nj) continue; Vec2f pos((i_off+0.5f)*dx, (j_off+0.5f)*dx); float phi_temp = dist(pos, point) - 1.02f*particle_radius; liquid_phi(i_off,j_off) = min(liquid_phi(i_off,j_off), phi_temp); } } //"extrapolate" phi into solids if nearby for(int j = 0; j < nj; ++j) { for(int i = 0; i < ni; ++i) { if(liquid_phi(i,j) < 0.5*dx) { float solid_phi_val = 0.25f*(nodal_solid_phi(i,j) + nodal_solid_phi(i+1,j) + nodal_solid_phi(i,j+1) + nodal_solid_phi(i+1,j+1)); if(solid_phi_val < 0) liquid_phi(i,j) = -0.5f*dx; } } } }
/*software rasterizer TODO could be more efficient*/ void render_triangle(Point2D v0, Point2D v1, Point2D v2, volatile unsigned char *fb, uint16_t colour) { int min_x = min3(v0.x, v1.x, v2.x); int min_y = min3(v0.y, v1.y, v2.y); int max_x = max3(v0.x, v1.x, v2.x); int max_y = max3(v0.y, v1.y, v2.y); Point2D p; for (p.y = min_y; p.y <= max_y; p.y++) { for (p.x = min_x; p.x <= max_x; p.x++) { float w0, w1, w2; get_barycentric(p, v0, v1, v2, &w0, &w1, &w2); // If p is on or inside all edges, render pixel. if (w0 >= 0 && w1 >= 0 && w2 >= 0) { /*TODO render nicely*/ draw_pixel(p.x, p.y, fb, colour); } } } }