/*
								+----------------------------------+
								|                                  |
								|     ***  MyVertex class  ***     |
								|                                  |
								|   Copyright © -tHE SWINe- 2007   |
								|                                  |
								|            MyVertex.h            |
								|                                  |
								+----------------------------------+
*/

#pragma once
#ifndef __MY_VERTEX_INCLUDED
#define __MY_VERTEX_INCLUDED

/**
 *	@file lml/MyVertex.h
 *	@date 2007
 *	@author -tHE SWINe-
 *	@brief MyVertex class
 *
 *	@date 2012-06-19
 *
 *	Added \#pragma once.
 *
 *	@date 2013-02-25
 *
 *	Added doxygen documentation, cleaned up.
 *
 */

/*
 *								=== TMyVertex ===
 */

#include "../Vector.h"

/**
 *	@brief generic vertex class
 */
struct TMyVertex {
	Vector3f v_position; /**< @brief position */

	/**
	 *	@brief parameters stored as enum
	 */
	enum {
		n_Texcoord_Num = 4 /**< @brief number of texture coordinates */
	};

	Vector3f v_normal; /**< @brief normal vector */
	Vector4f v_color; /**< @brief color */
	Vector4f p_texture_coord[n_Texcoord_Num]; /**< @brief texture coordinates */
	// some more coordinates to make it more curly

	typedef TMyVertex TIntermediate; /**< @brief intermediate result of operations on vertices */

	/**
	 *	@brief default constructor; has no effect
	 */
	inline TMyVertex()
	{}

	/**
	 *	@brief constructor with position parameter
	 *
	 *	Initializes position to the given coordinates, all other parameters to zero,
	 *	texcoords' w components are set to 1)
	 *
	 *	@param[in] f_x is the x coordinate of the position
	 *	@param[in] f_y is the y coordinate of the position
	 *	@param[in] f_z is the z coordinate of the position
	 */
	inline TMyVertex(float f_x, float f_y, float f_z)
		:v_position(f_x, f_y, f_z), v_normal(0, 0, 0), v_color(0, 0, 0, 0)
	{
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			p_texture_coord[i] = Vector4f(0, 0, 0, 1);
	}

	/**
	 *	@brief constructor with position parameter
	 *
	 *	Initializes position to the given coordinates, all other parameters to zero,
	 *	texcoords' w components are set to 1)
	 *
	 *	@param[in] r_v_vector is vertex position
	 */
	inline TMyVertex(const Vector3f &r_v_vector)
		:v_position(r_v_vector), v_normal(0, 0, 0), v_color(0, 0, 0, 0)
	{
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			p_texture_coord[i] = Vector4f(0, 0, 0, 1);
	}

	/**
	 *	@brief copy-constructor
	 *	@param[in] r_t_vertex is the vertex to copy from
	 */
	inline TMyVertex(const TMyVertex &r_t_vertex)
		:v_position(r_t_vertex.v_position), v_normal(r_t_vertex.v_normal),
		v_color(r_t_vertex.v_color)
	{
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			p_texture_coord[i] = r_t_vertex.p_texture_coord[i];
	}

	/**
	 *	@brief copy-constructor
	 *	@param[in] r_t_vertex is the vertex to copy from
	 *	@return Returns reference to this.
	 */
	inline TMyVertex &operator =(const TMyVertex &r_t_vertex)
	{
		v_position = r_t_vertex.v_position;
		v_normal = r_t_vertex.v_normal;
		v_color = r_t_vertex.v_color;
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			p_texture_coord[i] = r_t_vertex.p_texture_coord[i];
		return *this;
	}

	/**
	 *	@brief conversion to Vector3f to get vertex position
	 *	@return Returns vertex position.
	 */
	inline operator Vector3f() const
	{
		return v_position;
	}

	/**
	 *	@brief assignment of Vector3f to set vertex position
	 *	@param[in] r_v_position is the new position
	 *	@return Returns reference to this.
	 */
	inline TMyVertex &operator =(const Vector3f &r_v_position)
	{
		v_position = r_v_position;
		return *this;
	}

	/**
	 *	@brief vertex scaling operation
	 *	@param[in] f_scalar is the scaling factor
	 *	@return Returns vertex, scaled by the scalar.
	 */
	TMyVertex operator *(float f_scalar) const
	{
		TMyVertex t_tmp;

		t_tmp.v_position = v_position * f_scalar;
		t_tmp.v_normal = v_normal * f_scalar;
		t_tmp.v_color = v_color * f_scalar;
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			t_tmp.p_texture_coord[i] = p_texture_coord[i] * f_scalar;
		// scale vertex

		return t_tmp;
	}

	/**
	 *	@brief vertex addition operation
	 *	@param[in] r_vertex is the second operand
	 *	@return Returns the sum of both vertices.
	 */
	TMyVertex operator +(const TMyVertex &r_vertex) const
	{
		TMyVertex t_tmp;

		t_tmp.v_position = v_position + r_vertex.v_position;
		t_tmp.v_normal = v_normal + r_vertex.v_normal;
		t_tmp.v_color = v_color + r_vertex.v_color;
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			t_tmp.p_texture_coord[i] = p_texture_coord[i] + r_vertex.p_texture_coord[i];
		// add vertex

		return t_tmp;
	}

	/**
	 *	@brief vertex subtraction operation
	 *	@param[in] r_vertex is the second operand
	 *	@return Returns the difference of the two vertices.
	 */
	TMyVertex operator -(const TMyVertex &r_vertex) const
	{
		TMyVertex t_tmp;

		t_tmp.v_position = v_position - r_vertex.v_position;
		t_tmp.v_normal = v_normal - r_vertex.v_normal;
		t_tmp.v_color = v_color - r_vertex.v_color;
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			t_tmp.p_texture_coord[i] = p_texture_coord[i] - r_vertex.p_texture_coord[i];
		// add vertex

		return t_tmp;
	}

	/**
	 *	@brief inplace vertex scaling operation
	 *	@param[in] f_scalar is the scaling factor
	 *	@return Returns reference to this.
	 */
	TMyVertex &operator *=(float f_scalar)
	{
		v_position *= f_scalar;
		v_normal *= f_scalar;
		v_color *= f_scalar;
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			p_texture_coord[i] *= f_scalar;
		// scale vertex

		return *this;
	}

	/**
	 *	@brief inplace vertex addition operation
	 *	@param[in] r_vertex is the second operand
	 *	@return Returns reference to this.
	 */
	TMyVertex &operator +=(const TMyVertex &r_vertex)
	{
		v_position += r_vertex.v_position;
		v_normal += r_vertex.v_normal;
		v_color += r_vertex.v_color;
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			p_texture_coord[i] += r_vertex.p_texture_coord[i];
		// add vertex

		return *this;
	}

	/**
	 *	@brief inplace vertex subtraction operation
	 *	@param[in] r_vertex is the second operand
	 *	@return Returns reference to this.
	 */
	TMyVertex &operator -=(const TMyVertex &r_vertex)
	{
		v_position -= r_vertex.v_position;
		v_normal -= r_vertex.v_normal;
		v_color -= r_vertex.v_color;
		for(int i = 0; i < n_Texcoord_Num; ++ i)
			p_texture_coord[i] -= r_vertex.p_texture_coord[i];
		// add vertex

		return *this;
	}
};

/*
 *								=== ~TMyVertex ===
 */

#endif // !__MY_VERTEX_INCLUDED
