void CybOBB::buildOBB(CybVector3D<double>* covMatrix, cybMesh<cybSurfaceTriTraits>* mesh) { //Calculating the eigen vectors and the eigen values of the covariance matrix. //The eigen vectors will be the OBB's orienting vectors. CybVector3D<double> eigenVectors[3]; double eigenValues[3]; calculateEigenSystem(covMatrix, eigenValues, eigenVectors); //Organizing the orientation matrix for(int j = 0; j < 3; ++j) { for(int i = 0; i < 3; ++i) { orientation[j][i] = covMatrix[i][j]; } orientation[j].normalize(); } //Calculating the maximum and minimum values on each axis, projecting onto the orientation vectors. CybVector3D<double> minim(1e10, 1e10, 1e10), maxim(-1e10, -1e10, -1e10); CybVector3D<double> p_prime(0,0,0); CybVector3D<double> aux(0,0,0); int qttPoints = mesh->getNumberOfVertices(); sVertex* cPoint; //current point for(int i = 0; i < qttPoints; ++i) { cPoint = mesh->getVertex(i); aux(cPoint->getCoord(0), cPoint->getCoord(1), cPoint->getCoord(2)); p_prime(orientation[0] ^ aux, orientation[1] ^ aux, orientation[2] ^ aux); minim = minim.min(p_prime); maxim = maxim.max(p_prime); } //Cálculo do centro (ponto médio dos eixos) e dos semi-eixos. CybVector3D<double> cAux = (maxim + minim) * 0.5; center(orientation[0] ^ cAux, orientation[1] ^ cAux, orientation[2] ^ cAux); sizes = (maxim - minim) * 0.5; }
// control_points relative to center void placeFeature(const std::vector<Patch> &patches, const vec2 ¢er, vector<vec2> target_control_points, int patch_size, Heightmap *output) { const float deformation_weight = 1000.0; const float graphcut_weight = 1.0; const float feature_weight = 1.0; // control points if (target_control_points.size() == 0) return; vec2 top_left = center - patch_size / 2; int target_degree = target_control_points.size(); Heightmap best_patch(1,1); float best_cost = numeric_limits<float>::max(); // construct the full set of target points for matching the thin_plate spline vector<vec2> target_points; target_points.push_back(vec2(patch_size / 2)); // push on the center point for (vec2 v : target_control_points) target_points.push_back(v); // for every patch for (const Patch &p : patches) { if (p.degree == target_degree) { // ugh TODO if (!p.degree > 1) return; // Find the best thin plate spline to morph the patch // the spline is used to sample the source patch from the perspective of the target float best_thin_plate_cost = numeric_limits<float>::max(); pair<thin_plate_2f, thin_plate_2f> best_thin_plate; // create the source points for the thin plate spline vector<vec2> source_points = p.controlPoints(); // outpath/control points // for every iteration of target control points for (int offset = 0; offset < target_degree; offset++) { // store the change for a given sample coordinate on the target vector<float> d_points_x; vector<float> d_points_y; // no change for center point d_points_x.push_back(0); d_points_y.push_back(0); for (int i = 0; i < target_degree; i++) { vec2 d_control = source_points[(i + offset) % target_degree] - target_points[i + 1]; d_points_x.push_back(d_control.x); d_points_y.push_back(d_control.y); } // create the pair of thin plates for x and y dimensions pair<thin_plate_2f, thin_plate_2f> thin_plate { thin_plate_2f(target_points, d_points_x), thin_plate_2f(target_points, d_points_y) }; float thin_plate_cost = thin_plate.first.energy() + thin_plate.second.energy(); // find the spline with the minimum energy if (thin_plate_cost < best_thin_plate_cost) { best_thin_plate_cost = thin_plate_cost; best_thin_plate = thin_plate; } } // create a new warped patch Heightmap p_prime(p.data.size()); for (size_t y = 0; y < p_prime.height(); ++y) { for (size_t x = 0; x < p_prime.width(); ++x) { ivec2 target_p(x, y); vec2 source_p = target_p + vec2( best_thin_plate.first.interpolate(target_p), best_thin_plate.second.interpolate(target_p) ); if (p.data.inBounds(source_p) && p.data.inBounds(source_p + 1)) { p_prime.at(target_p) = p.data.sample(source_p.x, source_p.y); } p_prime.at(x, y); } } // calculate graphcut float graph_cut_cost; Heightmap p_prime_prime = graphcut(output, &p_prime, top_left, &graph_cut_cost); //// green is points transformed //image3f img = make_special_heightmap_image(p.data); //for (vec2 v : p.controlPoints()) { // img.drawRect(v - vec2(3), vec2(6), vec3::k()); // blue is original course points //} //img.drawRect(vec2(patch_size/2) - vec2(3), vec2(6), vec3::k()); // blue is original course points //for (vec2 v : target_points) {// green is target point transformed // img.drawRect(v + vec2( // best_thin_plate.first.interpolate(v), // best_thin_plate.second.interpolate(v) // ) - vec2(3), vec2(6), vec3::j() // ); //} ////gui::cache_upload(img, "patch"); // //ostringstream oss; //oss << "best_thin_plate_cost = " << best_thin_plate_cost; //img = make_special_heightmap_image(p_prime); //// blue is target //for (vec2 v : target_control_points) { // img.drawRect(v - vec2(3), vec2(6), vec3::k()); // blue is original //} //gui::cache_upload(img, oss.str()); float total_cost = graphcut_weight * graph_cut_cost + deformation_weight * best_thin_plate_cost; //float total_cost = best_thin_plate_cost; if (total_cost < best_cost) { // save as a Candidate patch best_cost = total_cost; best_patch = p_prime_prime; } } } mergePatch(output, &best_patch, top_left); }