/*
								+----------------------------------+
								|                                  |
								|  ***  Geo-Sphere primitive  ***  |
								|                                  |
								|   Copyright © -tHE SWINe- 2007   |
								|                                  |
								|           GeoSphere.h            |
								|                                  |
								+----------------------------------+
*/

#pragma once
#ifndef __GEOSPHERE_GEN_INCLUDED
#define __GEOSPHERE_GEN_INCLUDED

/**
 *	@file lml/GeoSphere.h
 *	@date 2007
 *	@author -tHE SWINe-
 *	@brief Geo-Sphere primitive
 *
 *	@date 2008-06-24
 *
 *	renamed CPolygon2::r_t_Vertex() and CPolyMesh::r_t_Vertex() to
 *	CPolygon2::r_Vertex() and CPolyMesh::r_Vertex() respectively
 *
 *	@date 2012-06-19
 *
 *	Moved multiple inclusion guard before file documentation comment.
 *
 *	@date 2013-02-25
 *
 *	Added doxygen documentation, cleaned up.
 *
 */

#include "PolyMesh.h"

/**
 *	@brief simple tesselation modifier without surface tension
 */
class CTesselate {
public:
	/**
	 *	@brief tesselates the mesh
	 *
	 *	Works by turning each of it's triangles to four smaller triangles
	 *	by bisecting edges of the original triangle and winding triangles between them
	 *	in case mesh is not just triangles or b_force_quads is true, each polygon
	 *	is turned to as many quads as polygon vertices, using bisected edges again
	 *	and all sharing one more vertex in center of the polygon
	 *
	 *	@param[in,out] r_mesh is the mesh to be tesselated
	 *	@param[in] b_force_quads is quadrilateral tesselation flag (if set, the output
	 *		contains only quads, otherwise it contains triangles and quads)
	 *
	 *	@return Returns true on success, false on failure.
	 *
	 *	@note This adds duplicate vertices on the edges of the polygons (works with no
	 *		connectivity information).
	 */
	static bool Tesselate(CPolyMesh &r_mesh, bool b_force_quads = false);
};

/**
 *	@brief spherify modifier; moves mesh vertices to surface of a sphere
 */
class CSpherify {
public:
	/**
	 *	@brief projects all vertices of the mesh onto a sphere with a given center and radius
	 *
	 *	@param[in,out] r_mesh is the mesh to be spherified
	 *	@param[in] v_center is the projection center
	 *	@param[in] f_radius is radius of the projection sphere
	 */
	static void Spherify(CPolyMesh &r_mesh, Vector3f v_center, float f_radius);

	/**
	 *	@brief projects all vertices of the mesh onto a sphere with
	 *		center and radius based on the bounding box
	 *
	 *	@param[in,out] r_mesh is the mesh to be spherified
	 */
	static void Spherify(CPolyMesh &r_mesh);
};

/**
 *	@brief geodesic spehre factory class (uses icosahedron as base)
 */
class CMakeGeoSphere {
protected:
	static const float m_p_vertex[12][3]; /**< @brief base icosahedron vertices */
	static const int m_p_face[20][3]; /**< @brief base icosahedron triangle indices */

public:
	/**
	 *	@brief creates a geodesic sphere with center at origin, given the radius and tesselation
	 *
	 *	@param[out] r_mesh is filled with the sphere mesh; any original contents are deleted
	 *	@param[in] f_radius is desired sphere radius
	 *	@param[in] n_tesselation is mesh tesselation (tesselation 0 yields icosahedron)
	 *	@param[in] n_material is material id to set to the mesh faces
	 *	@param[in] b_force_quads is quadrilateral tesselation flag (if set, the mesh will
	 *		contain quadriliterals (unless n_tesselation is null), otherwise triangles)
	 *
	 *	@return Returns true on success, false on failure.
	 *
	 *	@note The resulting mesh does not contain any duplicate vertices.
	 */
	static bool MakeGeoSphere(CPolyMesh &r_mesh,
		size_t n_tesselation, CPolyMesh::TMaterialId n_material = 0,
		bool b_force_quads = false, float f_radius = 1);
};

#endif // !__GEOSPHERE_GEN_INCLUDED
