/***************************************************************************
 *                          Zanoza Modeler v2.x                            *
 *      This is unpublished propietary source code of Zanoza Software.     *
 *      The copyright notice does not evidence any actual or intended      *
 *                    publication of such source code.                     *
 *                                                                         *
 *                   Copyright (c) 2002 Zanoza Software.                   *
 *                                                                         *
 *                        All rights reserved.                             *
 ***************************************************************************
 *--------------------------------------------------------------------------
 * @author:   Oleg M.
 *--------------------------------------------------------------------------
 * @purpose:  ZModeler's native quaternion
 *--------------------------------------------------------------------------
 * @histroy: 09.03.2003. Created
 */
#ifndef zquaternion_h_included
#define zquaternion_h_included

#ifndef zsequence_h_included
# include "zsequence.h"
#endif

class ZMatrix;
//------------------------------------------------------
//  ZQuatern - ZModeler's native quaternion
//------------------------------------------------------
class DLL_LINKAGE ZQuatern
{
public:
  ZQuatern();
  ZQuatern(const float _x, const float _y, const float _z, const float _w);
  ZQuatern(const ZPoint3D& axis, const ZAngle angle);
  ZQuatern(const float* initdata);
  ZQuatern(const ZQuatern& q);
  ~ZQuatern();

public:
  //
  // access grants
  //
  float& operator [] ( int value );

public:
  //
  // casting operators
  //
  operator float* ();
  operator const float* () const;

public:
  //
  // assignment operators
  //
  ZQuatern& operator =  ( const ZQuatern& q);
  ZQuatern& operator *= ( const ZQuatern& q);
  ZQuatern& operator += ( const ZQuatern& q);
  ZQuatern& operator -= ( const ZQuatern& q);
  ZQuatern& operator *= ( float v);
  ZQuatern& operator /= ( float v);

public:
  //
  // unary operators
  //
  ZQuatern operator + () const;
  ZQuatern operator - () const; //conjugate
  ZQuatern operator ! () const; //conjugate and re-normalize

public:
  //
  // binary operators
  //
  ZQuatern operator * ( const ZQuatern& q) const;
  ZQuatern operator + ( const ZQuatern& q) const;
  ZQuatern operator - ( const ZQuatern& q) const;

public:
  //
  // friend operators
  //
  friend DLL_LINKAGE ZQuatern operator / (const ZQuatern& q, const float v);
  friend DLL_LINKAGE ZQuatern operator / (const float v, const ZQuatern& q);
  friend DLL_LINKAGE ZQuatern operator * (const ZQuatern& q, const float v);
  friend DLL_LINKAGE ZQuatern operator * (const float v, const ZQuatern& q);
  // the multiplication of vector v and quaternion q is defined:
  // V'=q V q(-1)
  // where V = [0,v], V'=[0,v'] 
  friend DLL_LINKAGE ZVector operator * (const ZQuatern& q, const ZVector& p);
  friend DLL_LINKAGE ZVector operator * (const ZVector& p, const ZQuatern& q);


public:
  //
  // compare operators
  //
  bool operator == ( const ZQuatern& q) const;
  bool operator != ( const ZQuatern& q) const;

public:
  //
  // adjacent transformation
  //


public:
  //
  // operations
  //
  ZQuatern& identity();
  bool      isIdentity() const;
  ZQuatern& unify();    //length == 1
  bool      isUnified() const;
  ZQuatern& flip();     //inverts axis and rotation
  ZQuatern& invert();   //InvQ = -Q/Q.length();
  bool      equals(const ZQuatern& q, float epsilon = MINFLOAT) const;
  ZVector&  getAxis(ZVector& axis) const;
  ZQuatern& setAxis(const ZVector axis);
  ZAngle&   getRotation(ZAngle& angle) const;
  ZQuatern& setRotation(const ZAngle angle);
  float     length() const;
  float     length2() const;
  //convertion
  ZMatrix&  toMatrix(ZMatrix& mat) const;
  ZQuatern& fromMatrix(const ZMatrix& mat);
  void      toOrientation(ZVector& axis, ZAngle& angle) const;
  ZQuatern& fromOrientation(const ZVector axis, const ZAngle angle);
  ZQuatern& fromSpherical(const float latitude, const float longitude, const ZAngle angle);
  void      toAngles(ZAngle& yaw, ZAngle& pitch, ZAngle& roll) const;
  ZQuatern& fromAngles(const ZAngle yaw, const ZAngle pitch, const ZAngle roll);
  ZQuatern& slerp(const ZQuatern& q1, const ZQuatern& q2, float phase);
  ZQuatern& squad(const ZQuatern& a, const ZQuatern& p, 
                  const ZQuatern& q, const ZQuatern& b, float phase);
  ZQuatern& ln();
  ZQuatern& rotate(const ZVector& axis, const ZAngle angle);

private:
  //
  // data members
  //
  float x, y, z, w; //([v],w)
};


typedef ZSequence<ZQuatern>  ZQuaternSeq;


#endif //zquaternion_h_included

