/*-------------------------------------------------------------------------*/
/*  J3W ver 6.42  3D Animation Kit                                         */
/*  misc3d.h      10/22/2000                                               */
/*  Copyright (C) 1995 - 2000 Jun Mizutani <mizutani.jun@nifty.ne.jp>      */
/*                      All rights reserved.                               */
/*                                                                         */
/*   This file is part of the J3W 3D Animation Kit, and is covered under   */
/*  the terms of the GNU General Public License, version 2. This file has  */
/*  NO WARRANTY. See file COPYING for copyright details.                   */
/*                                                                         */
/*-------------------------------------------------------------------------*/

#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))

#ifdef WS
inline long j3w_round(double x) { \
    double d = 0.5;           \
    if (x < 0) d = -0.5;      \
    return long(x + d); }
#else //WS
inline long round(double x) { \
    double d = 0.5;           \
    if (x < 0) d = -0.5;      \
    return long(x + d); }
#endif //WS

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);

#endif
