예제 #1
0
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 &center, 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);
		}