/*********************************************************************//**
*	\brief Wind
*	Trida Wind zde implementuje vitr, kde pomoci parametru lze
*	vytvorit silu, ktera simuluje vitr. Zakladni smer 
*	vetru je vektor(1,0,0). Smer se nahodne meni a rychlost
*	vysledneho siloveho vektoru v zavislosti na nastaveni.
*	Vitr pouziva spring system a efekt padani snehu.
*
*	\author Michal Jirous
*	\date 20.12.2008
*	\file wind.h
**********************************************************************/

#ifndef __WIND_H__
#define __WIND_H__

#include "algebraic.h"


const float WIND_MAX_MAGNITUDE = 100.0f;					/*!< @brief Maximalni sila vetru. */
const float WIND_MAX_MAGNITUDE_RANGE = 200.0f;				/*!< @brief Maximalni vychylka vetru. */
const float WIND_CHANGE_SPEED_MODIFICATOR_MINIMUM = 1.0f;	/*!< @brief Minimalni modifikator rychlosti prizpusobeni aktualnich hodnot parametru cilovym hodnotam. */
const float WIND_CHANGE_SPEED_DEFAULT = 100.0f;				/*!< @brief Zakladni hodnota rychlosti prizpusobeni aktualnich hodnot parametru cilovym hodnotam. */

const float WIND_OCCASIONALLY_PROBABILITY = 0.01f;			/*!< @brief Pravdepodobnost, ze nastane zmena parametru pri typu periody WIND_CHANGE_OCCASIONALLY. */
const float WIND_OCCASIONALLY_OFTEN = 0.05f;				/*!< @brief Pravdepodobnost, ze nastane zmena parametru pri typu periody WIND_CHANGE_OFTEN. */

/** @brief Definuje jak casto se maji parametry vetru menit. */
enum wind_change_period
{
	WIND_CHANGE_NEVER = 0,		/*!< @brief Nikdy se nezmeni = konstantni sila. */
	WIND_CHANGE_OCCASIONALLY,	/*!< @brief Pouze obcas. */
	WIND_CHANGE_OFTEN,			/*!< @brief Casta zmena. */
	WIND_CHANGE_ALWAYS,			/*!< @brief Pri kazde aktualizace. */

	WIND_CHANGES_COUNT			/*!< @brief Celkovy pocet typu. */
};

/** @brief Trida simulujici vitr. */
class Wind
{
	bool m_bIsRunning;
	int m_iChangeRate;
	Vector m_vecFinalForce;
	float m_fBaseMagnitude;
	float m_fAngleZAxis, m_fAngleXAxis;
	float m_fAngleXRange, m_fAngleZRange;
	float m_fMagnitudeChangeRange;

	float m_fCurrentAngleZ, m_fCurrentAngleX, m_fCurrentMagnitude;
	float m_fTargetAngleZ, m_fTargetAngleX;
	float m_fTargetMagnitude;
	float m_fSpeedOfChange;
public:
	float getCurrentAngleZ()	{ return m_fCurrentAngleZ; }		/*!< @brief Vraci aktualni hodnotu uhlu kolem osy Z. @return uhel. */
	float getCurrentAngleX()	{ return m_fCurrentAngleX; }		/*!< @brief Vraci aktualni hodnotu uhlu kolem osy X. @return uhel. */
	float getCurrentMagnitude()	{  return m_fCurrentMagnitude; }	/*!< @brief Vraci aktualni silu vetru. @return Sila vetru.*/
	
	float getBaseMagnitude()	{ return m_fBaseMagnitude; }		/*!< @brief Vraci zakladni hodnotu sily vetru. @return Sila vetru. */
	float getBaseAngleZ()	{ return m_fAngleZAxis; }				/*!< @brief Vraci zakladni hodnotu uhlu kolem osy Z. @return uhel. */
	float getBaseAngleX()	{ return m_fAngleXAxis; }				/*!< @brief Vraci zakladni hodnotu uhlu kolem osy X. @return uhel. */
	
	float getAngleZRange()	{ return m_fAngleZRange; }				/*!< @brief Vraci vychylku uhlu kolem osy Z. @return uhel.*/
	float getAngleXRange()	{ return m_fAngleXRange; }				/*!< @brief Vraci vychylku uhlu kolem osy X. @return uhel. */
	float getMagnitudeRange()	{ return m_fMagnitudeChangeRange; }	/*!< @brief Vraci vychylku sily vetru. @return Sila vetru. */


	/** @brief Zjistuje, zda je vitr zapnuty, v pripade false se generuje nulovy vektor sily vetru. 
	*	@return True = zapnuto, false = vypnuto.
	*/
	bool isRunning()	{ return m_bIsRunning; }					
	void setRunning( bool isRunning )	{ m_bIsRunning = isRunning; }	/*!< @brief Nastavuje spusteni vetru. @param isRunning true = spusteno, false = vypnuto. */

	void setAngleX( float angle );								/*!< @brief Nastavi zaklad uhlu kolem osy X. */
	void setAngleZ( float angle );								/*!< @brief Nastavi zaklad uhlu kolem osy Z. */
	void setBasicMagnitude( float mag );						/*!< @brief Nastavi zakladni hodnotu sily vetru. */

	void setAngleXRange( float range );							/*!< @brief Nastavi vychylku uhlu kolem osy X. */
	void setAngleZRange( float range );							/*!< @brief Nastavi vychylku uhlu kolem osy Z. */
	void setMagnitudeRange( float range );						/*!< @brief Nastavi vychylku sily vetru. */
	
	int getValueChangePeriod()	{ return m_iChangeRate; }		/*!< @brief Vraci typ rychlosti zmen parametru. @return Typ z vyctu wind_change_period. */
	void setValueChangePeriod( int period );					/*!< @brief Nastavi typ rychlosti zmen parametru.  */

	void setSpeedOfChange( float speed );						/*!< @brief Nastavi rychlost prizpusobeni aktualnich hodnot parametru cilovym hodnotam. */
	float getSpeedOfChange() { return m_fSpeedOfChange; }		/*!< @brief Vraci rychlost prizpusobeni aktualnich hodnot parametru cilovym hodnotam. @return modifikator rychlosti.*/

	Vector getForce();				/*!< @brief Vraci vektor sily vetru. */
	void init();					/*!< @brief Inicializace objektu. */
	Wind();							/*!< @brief Konstruktor resetuje data. */
	void update();					/*!< @brief Funkce aktualizace, ktera provadi simulaci vetru. */
};


#endif /*__WIND_H__*/
