/*
								+----------------------------------+
								|                                  |
								|  ***  Platonic primitives  ***   |
								|                                  |
								|   Copyright © -tHE SWINe- 2007   |
								|                                  |
								|            PlatPrim.h            |
								|                                  |
								+----------------------------------+
*/

#pragma once
#ifndef __PLATONIC_PRIMITIVE_GENERATOR_INCLUDED
#define __PLATONIC_PRIMITIVE_GENERATOR_INCLUDED

/**
 *	@file lml/PlatPrim.h
 *	@date 2007
 *	@author -tHE SWINe-
 *	@brief platonic primitives
 *
 *	@date 2008-06-24
 *
 *	renamed CPolygon2::r_t_Vertex() and CPolyMesh::r_t_Vertex() to
 *	CPolygon2::r_Vertex() and CPolyMesh::r_Vertex() respectively
 *
 *	@date 2009-10-20
 *
 *	fixed some warnings when compiling under VC 2005, implemented "Security
 *	Enhancements in the CRT" for VC 2008. compare against MyProjects_2009-10-19_
 *
 *	@date 2012-06-19
 *
 *	Moved multiple inclusion guard before file documentation comment.
 *
 *	@date 2013-02-25
 *
 *	Added doxygen documentation, cleaned up.
 *
 */

#include "PolyMesh.h"

/**
 *	@def __PLATONIC_PRIMITIVES_GENERATE_TEXCOORDS
 *	@brief if defined, 2D texture coordinates are automatically generated in channel 0
 *		when creating mesh, unless specified otherwise
 */
#define __PLATONIC_PRIMITIVES_GENERATE_TEXCOORDS

/**
 *	@brief platonic primitive mesh generator
 */
class CPlatonicPrimitives {
public:
	/**
	 *	@brief makes unit sphere mesh (sphere has center at O and radius 1)
	 *
	 *	@param[out] r_mesh is filled with the sphere mesh; any original contents are deleted
	 *	@param[in] n_tess_axis is number of mesh segments along y-axis
	 *	@param[in] n_tess_radius is number of mesh segments arround y-axis
	 *	@param[in] n_material is material id to set to the mesh faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool MakeSphere(CPolyMesh &r_mesh, size_t n_tess_axis, size_t n_tess_radius,
		CPolyMesh::TMaterialId n_material = 0);

	/**
	 *	@brief makes unit cube mesh (axis-aligned cube with min vertex
	 *		at (-1, -1, -1) and max vertex at (1, 1, 1))
	 *
	 *	@param[out] r_mesh is filled with the sphere mesh; any original contents are deleted
	 *	@param[in] n_tess_x is number of mesh segments along x-axis
	 *	@param[in] n_tess_y is number of mesh segments along y-axis
	 *	@param[in] n_tess_z is number of mesh segments along z-axis
	 *	@param[in] n_material is material id to set to the mesh faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool MakeCube(CPolyMesh &r_mesh, size_t n_tess_x, size_t n_tess_y, size_t n_tess_z,
		CPolyMesh::TMaterialId n_material = 0);

	/**
	 *	@brief makes unit plane mesh (x-z plane with min vertex
	 *		at (-1, 0, -1) and max vertex at (1, 0, 1))
	 *
	 *	@param[out] r_mesh is filled with the sphere mesh; any original contents are deleted
	 *	@param[in] n_tess_x is number of mesh segments along x-axis
	 *	@param[in] n_tess_y is number of mesh segments along y-axis
	 *	@param[in] n_material is material id to set to the mesh faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool MakePlane(CPolyMesh &r_mesh, size_t n_tess_x, size_t n_tess_y,
		CPolyMesh::TMaterialId n_material = 0);

	/**
	 *	@brief creates cylinder mesh (cylinder axis is identical to y-axis, radius is 1,
	 *		bottom cap is at y = -1, top cap is at y = 1)
	 *
	 *	@param[out] r_mesh is filled with the sphere mesh; any original contents are deleted
	 *	@param[in] n_tess_axis is number of mesh segments along y-axis
	 *	@param[in] n_tess_radius is number of mesh segments arround y-axis
	 *	@param[in] n_cap_tess is number of mesh segments in caps (if zero, caps are omitted)
	 *	@param[in] n_material_coat is material id to set to the coat faces
	 *	@param[in] n_material_caps is material id to set to the caps faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool MakeCylinder(CPolyMesh &r_mesh, size_t n_tess_axis, size_t n_tess_radius,
		size_t n_cap_tess, CPolyMesh::TMaterialId n_material_coat = 0,
		CPolyMesh::TMaterialId n_material_caps = 0);

	/**
	 *	@brief creates cone mesh (cone axis is identical to y-axis, base radius is 1,
	 *		base lies at y = -1, top vertex is at y = 1)
	 *
	 *	@param[out] r_mesh is filled with the sphere mesh; any original contents are deleted
	 *	@param[in] n_tess_axis is number of mesh segments along y-axis
	 *	@param[in] n_tess_radius is number of mesh segments arround y-axis
	 *	@param[in] n_cap_tess is number of mesh segments in cap (if zero, cap is omitted)
	 *	@param[in] n_material_coat is material id to set to the coat faces
	 *	@param[in] n_material_cap is material id to set to the cap faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool MakeCone(CPolyMesh &r_mesh, size_t n_tess_axis, size_t n_tess_radius,
		size_t n_cap_tess, CPolyMesh::TMaterialId n_material_coat = 0,
		CPolyMesh::TMaterialId n_material_cap = 0);

	/**
	 *	@brief creates tube mesh (tube axis is identical to y-axis, radius is 1,
	 *		inner radius is specified, bottom cap is at y = -1, top cap is at y = 1)
	 *
	 *	@param[out] r_mesh is filled with the sphere mesh; any original contents are deleted
	 *	@param[in] n_tess_axis is number of mesh segments along y-axis
	 *	@param[in] n_tess_radius is number of mesh segments arround y-axis
	 *	@param[in] f_inner_radius is the inner radius (while the outer radius is always 1)
	 *	@param[in] n_material_inner_coat is material id to set to the inner coat faces
	 *	@param[in] n_material_outer_coat is material id to set to the outer coat faces
	 *	@param[in] n_material_caps is material id to set to the caps faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool MakeTube(CPolyMesh &r_mesh, size_t n_tess_axis,
		size_t n_tess_radius, float f_inner_radius,
		CPolyMesh::TMaterialId n_material_inner_coat = 0,
		CPolyMesh::TMaterialId n_material_outer_coat = 0,
		CPolyMesh::TMaterialId n_material_caps = 0);

	/**
	 *	@brief creates a torus (annuloid); center is at O, major radius is 1 and lies on x-z plane
	 *
	 *	@param[out] r_mesh is filled with the sphere mesh; any original contents are deleted
	 *	@param[in] n_tess_major is number of mesh segments arround y-axis
	 *	@param[in] n_tess_minor is number of mesh segments arround the annuloid ring
	 *	@param[in] f_minor_radius is the minor radius (while the major radius is always 1)
	 *	@param[in] n_material is material id to set to the mesh faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool MakeTorus(CPolyMesh &r_mesh, size_t n_tess_major,
		size_t n_tess_minor, float f_minor_radius, CPolyMesh::TMaterialId n_material = 0);

	/**
	 *	@brief creates winding of a rectangular grid of quads
	 *
	 *	Requires (n_size_x + 1) * (n_size_y + 1) vertices. Writes n_size_x * n_size_y quads.
	 *
	 *	@param[in,out] r_mesh is mesh where the grid should be generated (only the polygons are touched)
	 *	@param[in] n_face is the first face of grid
	 *	@param[in] n_vertex is the first vertex of grid
	 *	@param[in] n_size_x is grid dimension
	 *	@param[in] n_size_y is grid dimension
	 *	@param[in] b_flip is flip flag (if set, the faces are wound with reversed vertex order)
	 *	@param[in] n_material is material id to set to the mesh faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool WindGrid(CPolyMesh &r_mesh, size_t n_face, size_t n_vertex,
		size_t n_size_x, size_t n_size_y, bool b_flip, CPolyMesh::TMaterialId n_material);

	/**
	 *	@brief creates winding of triangle fan
	 *
	 *	Requires n_fan_vertex + n_fan_length vertices, not counting a single n_center_vertex.
	 *	Writes n_fan_length faces if b_loop is set, otherwise n_fan_length - 1.
	 *
	 *	@param[in,out] r_mesh is mesh where the grid should be generated (only the polygons are touched)
	 *	@param[in] n_face is zero-based index of the first face of triangle fan
	 *	@param[in] n_center_vertex is zero-based index of shared vertex of triangle fan
	 *	@param[in] n_fan_vertex is zero-based index of satellite vertices of triangle fan
	 *	@param[in] n_fan_length is number of satellite vertices forming fan
	 *	@param[in] b_loop is a loop flag (if set, a face between the first and the last
	 *		fan vertex is created to close the fan)
	 *	@param[in] b_flip is flip flag (if set, the faces are wound with reversed vertex order)
	 *	@param[in] n_material is material id to set to the mesh faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool WindFan(CPolyMesh &r_mesh, size_t n_face, size_t n_center_vertex,
		size_t n_fan_vertex, size_t n_fan_length, bool b_loop, bool b_flip,
		CPolyMesh::TMaterialId n_material);

	/**
	 *	@brief winds quadriliteral section between left and right vertices
	 *
	 *	Requires twice n_section_length vertices.
	 *	Writes n_section_length quads if b_loop is set, otherwise n_section_length - 1.
	 *
	 *	@param[in,out] r_mesh is mesh where the grid should be generated (only the polygons are touched)
	 *	@param[in] n_face is zero-based index of the first face of section
	 *	@param[in] n_left_vertex is zero-based index of the first of the left vertices
	 *	@param[in] n_right_vertex is zero-based index of the first of the right vertices
	 *	@param[in] n_section_length is number of section vertices (there's
	 *		n_section_length vertices in both left and right array)
	 *	@param[in] b_loop is a loop flag (if set, a quad between the first and the last
	 *		section vertices is created to close the fan)
	 *	@param[in] b_flip is flip flag (if set, the faces are wound with reversed vertex order)
	 *	@param[in] n_material is material id to set to the mesh faces
	 *
	 *	@return Returns true on success, false on failure.
	 */
	static bool WindSection(CPolyMesh &r_mesh, size_t n_face, size_t n_left_vertex,
		size_t n_right_vertex, size_t n_section_length, bool b_loop, bool b_flip,
		CPolyMesh::TMaterialId n_material);
};

#endif // !__PLATONIC_PRIMITIVE_GENERATOR_INCLUDED
