Example #1
0
void				check_arg(char **av, t_img *img, t_frac *frac)
{
	if (av[2])
		frac->max_iter = ft_atoi(av[2]);
	init_color(frac, av);
	if (ft_strequ(av[1], "mandel") == 1)
	{
		set_mandel(frac);
		draw_mandelbrot(img, frac);
	}
	else if (ft_strequ(av[1], "julia") == 1)
	{
		set_julia(frac);
		draw_julia(img, frac);
	}
	else if (ft_strequ(av[1], "ship") == 1)
	{
		set_ship(frac);
		draw_ship(img, frac);
	}
	else if (ft_strequ(av[1], "triangle") == 1)
	{
		set_triangle(frac);
		draw_sierpinski(img, frac);
	}
	else
		exit(0);
}
	void operator ()(VcacheMesh &vcache_mesh, submesh_id_t const &submesh_id, ProgressCallback & progress_callback, bool const reorder_vertices = true)
	{
		//////// prerequisites
		//////////////////////

		has_best_triangle = false;
		best_triangle = 0;

		optimized_tris.clear();
		lru_cache.clear();

		vtx_data.resize(get_num_vertices(vcache_mesh, submesh_id));
		tri_data.resize(get_num_triangles(vcache_mesh, submesh_id));

		// fetch the triangle data and put it in the internal vector
		// also fill the tri_indices_using vectors in the process
		{
			for (triangle_index_t tri_index = 0; tri_index < get_num_triangles(vcache_mesh, submesh_id); ++tri_index)
			{
				triangle_t triangle = get_triangle(vcache_mesh, submesh_id, tri_index);

				for (int i = 0; i < 3; ++i)
				{
					tri_data[tri_index].indices[i] = triangle[i];
					vtx_data[triangle[i]].tri_indices_using.insert(tri_index);
				}
			}
		}


		//////// optimize triangles
		///////////////////////////

		// calculate vertex and triangle scores
		{
			for (vertex_index_t vtx_index = 0; vtx_index < get_num_vertices(vcache_mesh, submesh_id); ++vtx_index)
			{
				vertex_data &vtx = vtx_data[vtx_index];
				vtx.score = find_vertex_score(vtx); // calculate the vertex score

				for (typename tri_indices_using_t::const_iterator tri_idx_iter = vtx.tri_indices_using.begin(); tri_idx_iter != vtx.tri_indices_using.end(); ++tri_idx_iter)
					tri_data[*tri_idx_iter].score += vtx.score; // add the vertex score to the triangles using this vertex
			}
		}

		// tell the progress callback the maximum progress value
		set_maximum_optimizing_triangles_progress(progress_callback, tri_data.size());

		/*
		the actual optimization step; reorder triangles by repeatedly finding a "best" triangle
		(= look at all the vertices in the LRU cache, and from all the triangles using these vertices,
		find the one with the highest score, remove this one from the vertices and put it in
		optimized_tris, and then find the next best triangle etc.)
		*/
		{
			size_t progress_counter = 0;
			while (optimized_tris.size() < tri_data.size())
			{
				push_best_triangle();
				++progress_counter;
				set_current_optimizing_triangles_progress(progress_callback, progress_counter);
			}
		}


		//////// reoder vertices
		////////////////////////

		if (reorder_vertices)
		{
			// even though *vertices* are reordered, reordering happens across *triangles*
			set_maximum_reordering_vertices_progress(progress_callback, tri_data.size());

			// get the vertices from the mesh
			std::vector < vertex_t > src_vertices;
			src_vertices.resize(vtx_data.size());
			for (vertex_index_t vtx_index = 0; vtx_index < vtx_data.size(); ++vtx_index)
				src_vertices[vtx_index] = get_vertex(vcache_mesh, submesh_id, vtx_index);

			// create and initialize the permutation sequence;
			// this sequence will be used for updating the triangle vertex indices later
			std::vector < std::pair < bool, vertex_index_t > > permutation;
			permutation.resize(vtx_data.size());
			std::fill(permutation.begin(), permutation.end(), std::pair < bool, vertex_index_t > (false, 0));

			/*
			reordering is done according to the order of access
			"access" refers to the triangles; for example, it makes no sense when the first
			triangle's vertices are at the end of the list of vertices, the second triangle's
			are in the middle etc.
			Instead, the first triangle's vertices should be at the beginning, the second triangle's
			should be right after these etc.
			*/
			size_t progress_counter = 0;
			vertex_index_t mesh_vertex_index = 0;
			for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index)
			{
				triangle_data const &tri = tri_data[tri_index];

				// go through all 3 indices of each triangle,
				// and if it wasn't reordered, do so
				for (int i = 0; i < 3; ++i)
				{
					vertex_index_t vtx_index = tri.indices[i];
					if (!permutation[vtx_index].first) // first false -> was not reordered yet
					{
						// check for overflow; it should never happen, since
						// each vertex is reordered only once
						assert(mesh_vertex_index < src_vertices.size());

						// mark the vertex as reordered and store its new index
						permutation[vtx_index].first = true;
						permutation[vtx_index].second = mesh_vertex_index;

						// write the vertex at its new position in the mesh
						set_vertex(vcache_mesh, submesh_id, mesh_vertex_index, src_vertices[vtx_index]);
						++mesh_vertex_index;
					}
				}

				++progress_counter;
				set_current_reordering_vertices_progress(progress_callback, progress_counter);
			}

			// After the vertices have been reodered, the triangle vertex indices need to be updated
			for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index)
			{
				triangle_data &tri = optimized_tris[tri_index];
				for (int i = 0; i < 3; ++i)
					tri.indices[i] = permutation[tri.indices[i]].second;
			}
		}

		// finally, store the contents of optimized_tris in the mesh
		{
			for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index)
			{
				triangle_data const &tri = optimized_tris[tri_index];
				triangle_t new_triangle = create_new_triangle(
					vcache_mesh,
					tri.indices[0],
					tri.indices[1],
					tri.indices[2]
				);

				set_triangle(vcache_mesh, submesh_id, tri_index, new_triangle);
			}
		}
	}