double EigenSolverPoissonImageEditing::solve(const NamedParameters& solverParameters, const NamedParameters& problemParameters, bool profileSolve, std::vector<SolverIteration>& iters) { int numUnknowns = 0; std::unordered_map<vec2i, int, vec2iHash> pixelLocationsToIndex; std::vector<vec2i> pixelLocations; size_t pixelCount = m_dims[0] * m_dims[1]; std::vector<float4> h_unknownFloat(pixelCount); std::vector<float4> h_target(pixelCount); std::vector<float> h_mask(pixelCount); findAndCopyArrayToCPU("X", h_unknownFloat, problemParameters); findAndCopyArrayToCPU("T", h_target, problemParameters); findAndCopyArrayToCPU("M", h_mask, problemParameters); for (int y = 0; y < (int)m_dims[1]; ++y) { for (int x = 0; x < (int)m_dims[0]; ++x) { if (h_mask[y*m_dims[0] + x] == 0.0f) { ++numUnknowns; vec2i p(x, y); pixelLocationsToIndex[p] =(int)pixelLocations.size(); pixelLocations.push_back(p); } } } printf("# Unknowns: %d\n", numUnknowns); int numResiduals = (int)pixelLocations.size() * 4; Eigen::VectorXf x_r(numUnknowns), b_r(numResiduals); Eigen::VectorXf x_g(numUnknowns), b_g(numResiduals); Eigen::VectorXf x_b(numUnknowns), b_b(numResiduals); Eigen::VectorXf x_a(numUnknowns), b_a(numResiduals); b_r.setZero(); b_g.setZero(); b_b.setZero(); b_a.setZero(); for (int i = 0; i < pixelLocations.size(); ++i) { vec2i p = pixelLocations[i]; float4 color = sampleImage(h_unknownFloat.data(), p, m_dims[0]); x_r[i] = color.x; //printf("%f\n", color.x); x_g[i] = color.y; x_b[i] = color.z; x_a[i] = color.w; } SpMatrixf A(numResiduals, numUnknowns); A.setZero(); printf("Constructing Matrix\n"); std::vector<Tripf> entriesA; std::vector<vec2i> offsets; offsets.push_back(vec2i(-1, 0)); offsets.push_back(vec2i(1, 0)); offsets.push_back(vec2i(0, -1)); offsets.push_back(vec2i(0, 1)); for (int i = 0; i < pixelLocations.size(); ++i) { vec2i p = pixelLocations[i]; int numInternalNeighbors = 0; float4 g_p = sampleImage(h_target.data(), p, m_dims[0]); int j = 0; for (vec2i off : offsets) { vec2i q = p + off; if (q.x >= 0 && q.y >= 0 && q.x < (int)m_dims[0] && q.y < (int)m_dims[1]) { auto it = pixelLocationsToIndex.find(q); int row = 4 * i + j; if (it == pixelLocationsToIndex.end()) { float4 f_q = sampleImage(h_unknownFloat.data(), q, m_dims[0]); b_r[row] += f_q.x; b_g[row] += f_q.y; b_b[row] += f_q.z; b_a[row] += f_q.w; } else { entriesA.push_back(Tripf(row, it->second, -1.0f)); } entriesA.push_back(Tripf(row, i, 1.0f)); float4 g_q = sampleImage(h_target.data(), q, m_dims[0]); b_r[row] += (g_p.x - g_q.x); b_g[row] += (g_p.y - g_q.y); b_b[row] += (g_p.z - g_q.z); b_a[row] += (g_p.w - g_q.w); } ++j; } } printf("Entries Set\n"); A.setFromTriplets(entriesA.begin(), entriesA.end()); printf("Sparse Matrix Constructed\n"); A.makeCompressed(); printf("Matrix Compressed\n"); { float totalCost = 0.0f; float cost_r = (A*x_r - b_r).squaredNorm(); float cost_g = (A*x_g - b_g).squaredNorm(); float cost_b = (A*x_b - b_b).squaredNorm(); float cost_a = (A*x_a - b_a).squaredNorm(); totalCost = cost_r + cost_g + cost_b + cost_a; printf("Initial Cost: %f : (%f, %f, %f, %f)\n", totalCost, cost_r, cost_g, cost_b, cost_a); } AxEqBSolver solver; solver.setMaxIterations(97); printf("Solvers Initialized\n"); clock_t start = clock(), diff; solver.compute(A); //printf("solver.compute(A)\n"); solveAxEqb(solver, b_r, x_r); //printf("Red solve done\n"); solveAxEqb(solver, b_g, x_g); //printf("Green solve done\n"); solveAxEqb(solver, b_b, x_b); //printf("Blue solve done\n"); solveAxEqb(solver, b_a, x_a); diff = clock() - start; printf("Time taken %f ms\n", diff*1000.0 / double(CLOCKS_PER_SEC)); float totalCost = 0.0f; float cost_r = (A*x_r - b_r).squaredNorm(); float cost_g = (A*x_g - b_g).squaredNorm(); float cost_b = (A*x_b - b_b).squaredNorm(); float cost_a = (A*x_a - b_a).squaredNorm(); totalCost = cost_r + cost_g + cost_b + cost_a; printf("Final Cost: %f : (%f, %f, %f, %f)\n", totalCost, cost_r, cost_g, cost_b, cost_a); for (int i = 0; i < pixelLocations.size(); ++i) { setPixel(h_unknownFloat.data(), pixelLocations[i], m_dims[0], x_r[i], x_g[i], x_b[i]); } findAndCopyToArrayFromCPU("X", h_unknownFloat, problemParameters);; return (double)totalCost; }
void obliqueangle_engine::render(level_ptr level, boost::shared_ptr<image_operations> oper) { pos_t iw, ih; part_c.get_obliqueangle_limits(iw, ih); BlockRotation b_r(s, level->get_blocks()); BlockRotation b_d(s, level->get_data()); BlockRotation bl_r(s, level->get_blocklight()); BlockRotation sl_r(s, level->get_skylight()); BlockRotation hm_r(s, level->get_heightmap()); pos_t bmt = iw * ih; boost::scoped_array<bool> blocked(new bool[bmt]); memset(blocked.get(), 0x0, sizeof(bool) * bmt); oper->set_limits(iw + 1, ih); for (int z = mc::MapZ - 1; z >= 0; z--) { for (int x = mc::MapX - 1; x >= 0; x--) { bool cave_initial = true; bool hell_initial = true; bool hell_solid = true; hm_r.set_xz(x, z); b_r.set_xz(x, z); b_d.set_xz(x, z); bl_r.set_xz(x, z); sl_r.set_xz(x, z); int hmval = hm_r.get8(); if (s.hellmode) { for (int y = s.top; y >= s.bottom && hell_solid; y--) { hell_solid = !is_open(b_r.get8(y)); } } for (int y = s.top; y >= s.bottom; y--) { int bt = b_r.get8(y); if (s.cavemode && cave_ignore_block(s, y, bt, b_r, cave_initial)) { continue; } if (s.hellmode && !hell_solid && hell_ignore_block(s, y, bt, b_r, hell_initial)) { continue; } if (s.excludes[bt]) { continue; } point p(x, y, z); pos_t px, py; part_c.project_obliqueangle(p, px, py); color top, side; if (bt == mc::Wool) { int md = b_d.get4(y); top = mc::WoolColor[md]; side = mc::WoolColor[md]; } else if ((bt == mc::Step) || (bt == mc::DoubleStep)) { int md = b_d.get4(y); top = mc::StepColor[md]; side = mc::StepColor[md]; } else { top = mc::MaterialColor[bt]; side = mc::MaterialSideColor[bt]; } if (mc::MaterialModes[bt] == mc::Block) { int bp = px + iw * py; if (blocked[bp]) { continue; } blocked[bp] = top.is_opaque(); } int bl = bl_r.get4(y + 1); apply_shading(s, bl, sl_r.get4(y + 1), hmval, y, top); apply_shading(s, bl, -1, hmval, y, side); switch(mc::MaterialModes[bt]) { case mc::Block: oper->add_pixel(px, py, top); oper->add_pixel(px + 1, py, top); oper->add_pixel(px, py + 1, side); side.lighten(0x20); oper->add_pixel(px + 1, py + 1, side); break; case mc::HalfBlock: oper->add_pixel(px, py + 1, top); oper->add_pixel(px + 1, py + 1, top); break; case mc::TorchBlock: oper->add_pixel(px, py, top); top.lighten(0x20); top.a -= 0xb0; oper->add_pixel(px - 1, py, top); oper->add_pixel(px + 2, py, top); oper->add_pixel(px, py - 1, top); oper->add_pixel(px, py + 1, top); oper->add_pixel(px, py + 1, side); break; } } } } }
void fatiso_engine::render(level_ptr level, boost::shared_ptr<image_operations> oper) { BlockRotation b_r(s, level->get_blocks()); BlockRotation b_d(s, level->get_data()); BlockRotation bl_r(s, level->get_blocklight()); BlockRotation sl_r(s, level->get_skylight()); BlockRotation hm_r(s, level->get_heightmap()); pos_t iw, ih; part_c.get_fatiso_limits(iw, ih); pos_t bmt = iw * ih; boost::scoped_array<bool> blocked(new bool[bmt]); memset(blocked.get(), 0x0, sizeof(bool) * bmt); oper->set_limits(iw + 1, ih); for (int z = mc::MapZ - 1; z >= 0; z--) { for (int x = mc::MapX - 1; x >= 0; x--) { bool cave_initial = true; bool hell_initial = true; bool hell_solid = true; hm_r.set_xz(x, z); b_r.set_xz(x, z); b_d.set_xz(x, z); bl_r.set_xz(x, z); sl_r.set_xz(x, z); int hmval = hm_r.get8(); if (s.hellmode) { for (int y = s.top; y >= s.bottom && hell_solid; y--) { hell_solid = !is_open(b_r.get8(y)); } } for (int y = s.top; y >= s.bottom; y--) { int bt = b_r.get8(y); if (s.cavemode && cave_ignore_block(s, y, bt, b_r, cave_initial)) { continue; } if (s.hellmode && !hell_solid && hell_ignore_block(s, y, bt, b_r, hell_initial)) { continue; } if (s.excludes[bt]) { continue; } point p(x, y, z); pos_t px, py; part_c.project_fatiso(p, px, py); color top = blockColor_top(bt, y, b_d), side = blockColor_side(bt, y, b_d); if (mc::MaterialModes[bt] == mc::Block) { int bp = px + iw * py; if (blocked[bp]) { continue; } blocked[bp] = top.is_opaque() && bt != mc::Fence; } int bl = bl_r.get4(y + 1); apply_shading(s, bl, sl_r.get4(y + 1), hmval, y, top); apply_shading(s, bl, -1, hmval, y, side); color topdark(top); color toplight(top); color sidelight(side); if (bt == mc::Grass) { topdark.darken(0x20); toplight.darken(0x10); sidelight.lighten(0x20); } else { toplight = color(side); topdark = color(side); } oper->add_pixel(px + 0, py + 0, side); oper->add_pixel(px + 0, py + 1, side); oper->add_pixel(px + 0, py + 2, side); oper->add_pixel(px + 1, py - 1, side); oper->add_pixel(px + 1, py + 0, side); oper->add_pixel(px + 1, py + 1, side); oper->add_pixel(px + 2, py - 1, side); oper->add_pixel(px + 2, py + 0, side); oper->add_pixel(px + 2, py + 1, side); oper->add_pixel(px + 3, py - 2, side); oper->add_pixel(px + 3, py - 1, side); oper->add_pixel(px + 3, py + 0, side); oper->add_pixel(px - 1, py + 0, sidelight); oper->add_pixel(px - 1, py + 1, sidelight); oper->add_pixel(px - 1, py + 2, sidelight); oper->add_pixel(px - 2, py - 1, sidelight); oper->add_pixel(px - 2, py + 0, sidelight); oper->add_pixel(px - 2, py + 1, sidelight); oper->add_pixel(px - 3, py - 1, sidelight); oper->add_pixel(px - 3, py + 0, sidelight); oper->add_pixel(px - 3, py + 1, sidelight); oper->add_pixel(px - 4, py - 2, sidelight); oper->add_pixel(px - 4, py - 1, sidelight); oper->add_pixel(px - 4, py + 0, sidelight); oper->add_pixel(px + 0, py - 2, topdark); oper->add_pixel(px + 0, py - 1, topdark); oper->add_pixel(px + 1, py - 3, topdark); oper->add_pixel(px + 1, py - 2, topdark); oper->add_pixel(px + 2, py - 3, topdark); oper->add_pixel(px + 2, py - 2, topdark); oper->add_pixel(px + 3, py - 4, topdark); oper->add_pixel(px + 3, py - 3, topdark); oper->add_pixel(px - 1, py - 2, toplight); oper->add_pixel(px - 1, py - 1, toplight); oper->add_pixel(px - 2, py - 3, toplight); oper->add_pixel(px - 2, py - 2, toplight); oper->add_pixel(px - 3, py - 3, toplight); oper->add_pixel(px - 3, py - 2, toplight); oper->add_pixel(px - 4, py - 4, toplight); oper->add_pixel(px - 4, py - 3, toplight); oper->add_pixel(px - 3, py - 5, top); oper->add_pixel(px - 3, py - 4, top); oper->add_pixel(px - 2, py - 5, top); oper->add_pixel(px - 2, py - 4, top); oper->add_pixel(px - 1, py - 6, top); oper->add_pixel(px - 1, py - 5, top); oper->add_pixel(px - 1, py - 4, top); oper->add_pixel(px - 1, py - 3, top); oper->add_pixel(px + 0, py - 6, top); oper->add_pixel(px + 0, py - 5, top); oper->add_pixel(px + 0, py - 4, top); oper->add_pixel(px + 0, py - 3, top); oper->add_pixel(px + 1, py - 5, top); oper->add_pixel(px + 1, py - 4, top); oper->add_pixel(px + 2, py - 5, top); oper->add_pixel(px + 2, py - 4, top); } } } return; }