//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * 回転補間圧縮ヘッダ
 * @author Junpee
 */

#ifndef ROTATION_INTERPOLATION_COMPRESSOR_H_
#define ROTATION_INTERPOLATION_COMPRESSOR_H_

namespace Lamp{

class RotationInterpolator;
class EulerArrayInterpolator;
class QuaternionArrayInterpolator;

//------------------------------------------------------------------------------
/**
 * 回転補間圧縮
 */
class RotationInterpolationCompressor{
public:
	//--------------------------------------------------------------------------
	// 生成、破棄
	//--------------------------------------------------------------------------
	/**
	 * コンストラクタ
	 */
	RotationInterpolationCompressor();

	/**
	 * デストラクタ
	 */
	virtual ~RotationInterpolationCompressor();

	//--------------------------------------------------------------------------
	// 圧縮
	//--------------------------------------------------------------------------
	/**
	 * 圧縮
	 * @param source 圧縮を行うオイラー回転配列補間
	 * @param tolerance 許容誤差の角度をラジアンで指定する
	 * @return 圧縮を行った回転補間
	 */
	virtual RotationInterpolator* compress(
		EulerArrayInterpolator* source, float tolerance);

	//--------------------------------------------------------------------------
	/**
	 * 圧縮
	 * @param source 圧縮を行う四元数回転配列補間
	 * @param tolerance 許容誤差の角度をラジアンで指定する
	 * @return 圧縮を行った回転補間
	 */
	virtual RotationInterpolator* compress(
		QuaternionArrayInterpolator* source, float tolerance);

	//--------------------------------------------------------------------------
	// 圧縮結果
	//--------------------------------------------------------------------------
	/**
	 * 許容誤差の取得
	 * @return 許容誤差
	 */
	virtual float getTolerance() const{ return tolerance_; }

	/**
	 * 長さの取得
	 * @return 長さ
	 */
	virtual float getLength() const{ return length_; }

	//--------------------------------------------------------------------------
	/**
	 * ソースキー数の取得
	 * @return ソースキー数
	 */
	virtual int getSourceKeyCount() const{ return sourceKeyCount_; }

	/**
	 * ソースサイズの取得
	 * @return ソースサイズ
	 */
	virtual int getSourceSize() const{
		return getSourceKeyCount() * sourceKeySize_;
	}

	//--------------------------------------------------------------------------
	/**
	 * 圧縮後キー数の取得
	 * @return 圧縮後キー数
	 */
	virtual int getCompressedKeyCount() const{ return compressedKeyCount_; }

	/**
	 * 圧縮後サイズの取得
	 * @return 圧縮後サイズ
	 */
	virtual int getCompressedSize() const{
		return getCompressedKeyCount() * compressedKeySize_;
	}

	//--------------------------------------------------------------------------
	/**
	 * 圧縮率の取得
	 * @return 圧縮率
	 */
	virtual float getCompressionRate() const{
		if(getSourceSize() == 0){ return 0.f; }
		return (float)getCompressedSize() / (float)getSourceSize();
	}

	/**
	 * 結果文字列の取得
	 * @return 結果文字列
	 */
	virtual String getResultString() const;

protected:
	//--------------------------------------------------------------------------
	/// 線形キー
	class LinearKey{
	friend class RotationInterpolationCompressor;
	private:
		/// 値
		Quaternion value_;
		/// 時間
		float time_;
		/// 最大誤差のコサイン
		float errorCos_;
	};

	//--------------------------------------------------------------------------
	// 圧縮
	//--------------------------------------------------------------------------
	/**
	 * 圧縮準備
	 * @param source 圧縮を行う四元数回転配列補間
	 * @param tolerance 許容誤差
	 */
	virtual void compressSetup(
		QuaternionArrayInterpolator* source, float tolerance);

	/**
	 * 定数圧縮
	 * @param source 圧縮を行う四元数回転配列補間
	 * @return 圧縮結果、失敗ならNULL
	 */
	virtual RotationInterpolator* compressConstant(
		QuaternionArrayInterpolator* source);

	/**
	 * 線形圧縮
	 * @param source 圧縮を行う四元数回転配列補間
	 * @return 圧縮結果、失敗ならNULL
	 */
	virtual RotationInterpolator* compressLinear(
		QuaternionArrayInterpolator* source);

	/**
	 * 線形圧縮誤差の再計算
	 * @param source 圧縮を行う四元数回転配列補間
	 * @param preKey 前のキー
	 * @param key 再計算するキー
	 * @param postKey 後ろのキー
	 */
	virtual void recalcLinearError(QuaternionArrayInterpolator* source,
		LinearKey& preKey, LinearKey& key, LinearKey& postKey);

	/**
	 * 圧縮結果の設定
	 * @param compressedKeyCount 圧縮後キー数
	 * @param compressedKeySize 圧縮後キーサイズ
	 */
	virtual void setCompressedData(
		int compressedKeyCount, int compressedKeySize){
		compressedKeyCount_ = compressedKeyCount;
		compressedKeySize_ = compressedKeySize;
	}

	//--------------------------------------------------------------------------
	// メンバ
	//--------------------------------------------------------------------------
	/// ソースキーサイズ
	static const int sourceKeySize_ = sizeof(Quaternion);

private:
	//--------------------------------------------------------------------------
	// コピーコンストラクタの隠蔽
	RotationInterpolationCompressor(const RotationInterpolationCompressor& copy);

	// 代入コピーの隠蔽
	void operator =(const RotationInterpolationCompressor& copy);

	//--------------------------------------------------------------------------
	// メンバ
	//--------------------------------------------------------------------------
	// 許容誤差
	float tolerance_;
	// 長さ
	float length_;
	// ソースキー数
	int sourceKeyCount_;
	// 圧縮後キー数
	int compressedKeyCount_;
	// 圧縮後キーサイズ
	int compressedKeySize_;

};

//------------------------------------------------------------------------------
} // End of namespace Lamp
#endif // End of ROTATION_INTERPOLATION_COMPRESSOR_H_
//------------------------------------------------------------------------------

