
/*
	file : CCal3dSceneNode.h

	Dragon Wings (c) 2005 Philipp Roßberger, Sebastian Roll
		www.einszunull.net
		www.sebastianroll.de

	This software is provided 'as-is', without any express or implied
	warranty.  In no event will the authors be held liable for any damages
	arising from the use of this software.

	Permission is granted to anyone to use this software for any purpose,
	including commercial applications, and to alter it and redistribute it
	freely, subject to the following restrictions:

	1. The origin of this software must not be misrepresented; you must not
		claim that you wrote the original software. If you use this software
		in a product, an acknowledgment in the product documentation would be
		appreciated but is not required.
	2. Altered source versions must be plainly marked as such, and must not be
		misrepresented as being the original software.
	3. This notice may not be removed or altered from any source distribution.

	Used software libraries from other people (thank you very much):

	The Irrlicht Engine:
		Copyright (c) 2002-2005 Nikolaus Gebhardt
		www.irrlicht.sourceforge.net
  
	The Character Animation Library (cal3D):
		Copyright (c) 2001, 2002 Bruno 'Beosil' Heidelberger
		www.cal3d.sourceforge.net

	The FMOD audio library:
		Copyright (c) Firelight Technologies Pty, Ltd. 1999-2004
		www.fmod.org

	Article - Using Cal3D with Irrlicht:
		Copyright (c) Thomas Suter 2004
		www.thomas.webtracker.ch/jahia/Jahia/cache/off/pid/672
*/


#ifndef CCAL3DSCENENODE_H_INCLUDED
#define CCAL3DSCENENODE_H_INCLUDED

#include <irrlicht.h>

#include <cal3d/cal3d.h>

typedef irr::core::vector3df Vector3;

class CCal3DSceneNode : public irr::scene::ISceneNode
{
protected:
	//! configuration file for the character
	std::string configFile;

	//! the path where the media (textures etc.) are stored
	std::string mediaPath;

	//! core model for cal3d, 
	//! this should raelly be in a seperate coremodel server class
	CalCoreModel* m_calCoreModel;

	//! instance model for cal3d
	CalModel* m_calModel;

	//! indicate if animation is paused
	bool m_bPaused;

	//! model scale
	float m_scale;

	//! id of the current animation
	int m_currentAnimationId;

	//! remaining time for the current animation
	float m_leftAnimationTime;

	//! time the animation blending will take
	float m_blendTime;

	//! level of detail
	float m_lodLevel;

	//! bounding box dummy
	irr::core::aabbox3df Box;

	//! material
	irr::video::SMaterial material;

	//! last frame time
	irr::u32 lastTick;

	//! true iff initialized
	bool bInitialized;

public :

	//! constructor
	//! @param cf, configuration file
	//! @param parent, parent scene node
	//! @param mgr, scene manager
	//! @param id, scenenode id
	CCal3DSceneNode(const char* cf,
		irr::scene::ISceneNode* parent, 
		irr::scene::ISceneManager* mgr, irr::s32 id=-1);

	//! destructur
	virtual ~CCal3DSceneNode();

////////////////////////////////////////////////
// irrlicht rendering stuff
////////////////////////////////////////////////

	void OnPreRender();

	void render();

	void OnPostRender(irr::u32 timeMs);

	const irr::core::aabbox3df& getBoundingBox() const;

	irr::video::SMaterial& getMaterial(irr::s32 i)
	{
		return material;
	}

	irr::s32 getMaterialCount()
	{
		return 1;
	}

////////////////////////////////////////////////
// call 3d stuff
////////////////////////////////////////////////

	//! load and parse the configuration file
	//! @param cf, configuration file name
	//! @return true on success, false otherwise
	bool parseModelConfiguration(const std::string &cf);

	// load all textures
	bool init();

////////////////////////////////////////////////
// dragon stuff
////////////////////////////////////////////////

	void moveBone(int boneID, CalQuaternion& direction);

	CalQuaternion getBoneRotation(int boneID);
	CalQuaternion getCoreBoneRotation(int boneID);

	void setBoneRotation(int boneID, CalQuaternion& newRotation);

	void dumpBoneQaternion(int boneID);
	void quaternionToAxisAndAngle(CalQuaternion qIn, CalVector& vOut, float& aOut);
	void quaternionToAxisAndAngle(CalQuaternion qIn, CalQuaternion& qOut);
	float quaternionGetMagnitude(CalQuaternion qIn);
	void quaternionNormalize(CalQuaternion& qInOut);
};

#endif