//
// Copyright (C) 1999-2004 WideStudio Development Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// WIDESTUDIO DEVELOPMENT TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Except as contained in this notice, the name of WideStudio Development Team 
// shall not be used in advertising or otherwise to promote the sale, use or 
// other dealings in this Software without prior written authorization from  
// WideStudio Development Team.

#if !defined(_misc3d_h)
#define _misc3d_h

#include    <math.h>

#ifdef WS
#if defined( WIN32 ) || defined (TE)
#ifndef M_PI
#define M_PI 3.141592
#endif //M_PI
#endif //WIN32
#endif //WS

#define PI M_PI

#define RAD(d)  (double(d) * PI / 180.0 / 8.0)
#define DEG(r)  (long((r) / PI * 180.0 * 8))

inline long iround(double x) { \
    double d = 0.5;           \
    if (x < 0) d = -0.5;      \
    return long(x + d); }

struct Matrix3 {
    double m1,m2,m3,m4,m5,m6,m7,m8,m9;
};

class Vector {
  public:
    long x, y, z;
    Vector(long xx = 0, long yy = 0, long zz = 0)
                          { x = xx; y = yy; z = zz; }
    friend Vector operator+(const Vector& v, const Vector& u)
                          { return Vector(v.x+u.x,v.y+u.y,v.z+u.z); }
    friend Vector operator-(const Vector& v, const Vector& u)
                          { return Vector(v.x-u.x,v.y-u.y,v.z-u.z); }
};

class Vector_d {
    double size;
  public:
    double x, y, z;
    Vector_d(double xx = 0.0, double yy = 0.0, double zz = 0.0)
            { x = xx; y = yy; z = zz; }
    Vector_d(long xx, long yy, long zz)
            { x = double(xx); y = double(yy); z = double(zz); }
    Vector_d (Vector v) { x = double(v.x); y = double(v.y); z = double(v.z);}
    friend Vector_d operator+(const Vector_d& v, const Vector_d& u)
            { return Vector_d(v.x+u.x,v.y+u.y,v.z+u.z); }
    friend Vector_d operator-(const Vector_d& v, const Vector_d& u)
            { return Vector_d(v.x-u.x,v.y-u.y,v.z-u.z); }
    friend Vector_d operator*(const double& v, const Vector_d& u)
            { return Vector_d(v * u.x, v * u.y, v * u.z); }
    void normalize()
            { size = sqrt(x * x + y * y + z * z);
              x = x / size;
              y = y / size;
              z = z / size;
            }
    void neg() { x=-x; y=-y; z=-z; }
    double dot_product(const Vector_d& v)
            { return x * v.x + y * v.y + z * v.z; }
};

struct VectorSet {
    Vector  local;
    Vector  world;
    Vector  eye;
};

class Vector2D {
  public:

    int x, y, z;
    Vector2D(int xx = 0, int yy = 0, int zz = 0) { x = xx; y = yy; z = zz;}
};

struct Quaternion {
    double _0, _1, _2, _3;
};

extern Matrix3  MulMatrix3(const Matrix3 &a, const Matrix3 &b);
extern Vector   ConvCoordinate(const  Matrix3 &m, const Vector &plocal);
extern Vector   ConvCoordinate2(const Matrix3 &m, const Vector &pworld);
extern Quaternion MulQuat(const Quaternion a, const Quaternion b);
extern Quaternion CondugateQuat(const Quaternion a);
extern Quaternion NormalizeQuat(const Quaternion a);
extern void EularToQuat(long h, long p, long b, Quaternion &qq);
extern int CheckShortestPath(const Quaternion q1, const Quaternion q2);
extern void QuatToMat(const Quaternion q, Matrix3 &m);
extern void Slerp(const Quaternion &a, const Quaternion &b, Quaternion &q, double t);
extern void MatrixToQuat(const Matrix3 &m, Quaternion &q);
extern Vector_d ConvCoordinate_d(const  Matrix3 &m, const Vector_d &plocal);
extern Vector_d ConvCoordinate2_d(const Matrix3 &m, const Vector_d &pworld);

#endif
