/*==========================================================================
 *                                                                         *
 *  Copyright (C) 2001 Dymchenko L.A.                                      *
 *                                                                         *
 *  VirtualRay (Spherical Engine) additional header file                   *
 *                                                                         *
 ***************************************************************************/


#ifndef Typesh
#define Typesh


#include <math.h>
#include <windows.h>                 

///////////////////////////////////////////////////////////////////////

typedef unsigned char byte;
typedef byte* bytept;

typedef WORD w16;
typedef DWORD w32;
typedef unsigned __int64 w64;
typedef w16* w16pt;
typedef w32* w32pt;
typedef w64* w64pt;

typedef __int8 i8;
typedef __int16 i16;
typedef __int32 i32;
typedef __int64 i64;
typedef i8* i8pt;
typedef i16* i16pt;
typedef i32* i32pt;
typedef i64* i64pt;

typedef i32pt* i32ppt;

///////////////////////////////////////////////////////////////////////

typedef float rnumt;
typedef rnumt* rnumpt;

typedef byte bytecolort;
typedef rnumt rcolort;

struct bytecolor3t
{
    byte r,g,b;

  bytecolor3t() {};
  bytecolor3t(byte rin, byte gin, byte bin) { r=rin; g=gin; b=bin; }
};
typedef bytecolor3t* bytecolor3pt;

bool operator == (const bytecolor3t& color1, const bytecolor3t& color2);

struct bcol4t { byte r,g,b,a; };

union bcolor4t
{
    bcol4t c;
    byte car[4];
};

struct rcolor3t
{
  rnumt r,g,b;

  rcolor3t() {};
  rcolor3t(rnumt rin, rnumt gin, rnumt bin) { r=rin; g=gin; b=bin; }
};
typedef struct { rnumt r; rnumt g; rnumt b; rnumt alfa; } rcolor3sset;


class rvectorsset;

class rvectort
{
  public:

    rnumt x,y,z;

    inline  rnumt norm() const;         
    inline rnumt norm2() const;
    inline rnumt normalize();

    void ortbasis(rvectort& v2, rvectort& v3) const;
    void ortbasisz(rvectort& v1, rvectort& v2) const;

    void definerandom();
    void randomvariation(rnumt intense);

//    inline void operator + (const rvectort& v) { x+=v.x; y+=v.y; z+=v.z; }

//    inline void operator = (rvectort v) { x=v.x; y=v.y; z=v.z; }

/*
    inline rvectort(const rvectort& v)
    {
      x=v.x; y=v.y; z=v.z;
    }

    rvectort& operator = (const rvectort &v)
    {
      x=v.x; y=v.y; z=v.z; return *this;
    }
*/

    inline rnumt& operator () (const i32 index) { return *(((rnumpt)this)+index); }; 

    inline void set0() { x=0.0f; y=0.0f; z=0.0f; }; 

    inline void operator =  (const rvectorsset& ssev);
    inline void operator = (const float*  fvectorp);

    rvectort() {};
    inline rvectort(rvectorsset& ssev);
    inline rvectort(rnumt xin, rnumt yin, rnumt zin);
};

typedef rvectort* rvectorpt;
typedef rvectort rpointt;
typedef rvectorpt rpointpt;

class rvectorsset
{
  public:

    rnumt x,y,z,w;

//    inline rnumt norm2();

    inline void operator =  (const rvectort& v);

    rvectorsset() { w=0.0f; };
};

typedef rvectorsset* rvectorssept; 


class gspheret
{
  public:

    rvectort cp; 
    rnumt r;

    inline bool iscontain(rvectort sphcp, rnumt sphr);

    gspheret () {};
    gspheret (rvectort cpin, rnumt rin) { cp=cpin; r=rin; };
    gspheret (rnumt x, rnumt y, rnumt z, rnumt rin)
             { cp.x=x; cp.y=y; cp.z=z; r=rin; };
};

typedef gspheret* gspherept;

////////////////////////////////////////////////////////////////////////

typedef struct { w16 w0,w1;} dw16;
typedef struct { i16 i0,i1;} di16;
typedef struct { byte b0,b1,b2,b3;} qbyte;
typedef struct { i8 i0,i1,i2,i3;} qi8;

typedef union
                {
                    i32 i32;
                    dw16 w;
                    di16 i;
          qbyte b;
                    qi8 i8;
                }
                mm32;
typedef mm32* mm32pt;


typedef struct { i32 i0,i1;} di32;
typedef struct { w16 w0,w1,w2,w3;} qw16;
typedef struct { i16 i0,i1,i2,i3;} qi16;
typedef struct { i8 i0,i1,i2,i3,i4,i5,i6,i7;} oi8;

typedef union
                {
          di32 i32;
                    qw16 w;
                    qi16 i;
                    oi8 i8;
                    w16 war[4];
                    i16 iar[4];
          qi16 i16;
                }
                mm64;
typedef mm64* mm64pt;
typedef mm64pt* mm64ppt;

///////////////////////////////////////////////////////////////////////

#define nil    NULL

#define align16     __declspec(align(16))

///////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

#define PI    3.1415926535897932384626433832795

#define min_i32 LONG_MIN
#define max_i32 LONG_MAX

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

struct  pixelformatt
{
    byte rpos,gpos,bpos,apos;

  void set(byte rp, byte gp, byte bp, byte ap)
  {
    rpos=rp; gpos=gp; bpos=bp; apos=ap;
  }

  pixelformatt () {};

  pixelformatt(byte rp, byte gp, byte bp, byte ap)
  {
    rpos=rp; gpos=gp; bpos=bp; apos=ap;
  }
};

inline bool operator == (pixelformatt& pf1, pixelformatt& pf2)
{
    return ((pf1.rpos==pf2.rpos)&&
            (pf1.gpos==pf2.gpos)&&
                    (pf1.bpos==pf2.bpos)&&
          (pf1.apos==pf2.apos));
}

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

struct mousesensitivityt
{
  rnumt mxsensitivety,mysensitivety,mzsensitivety;
};

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

inline rnumt rvectort::norm() const
{
    return sqrt(x*x+y*y+z*z);
}

inline rnumt rvectort::norm2() const
{
    return x*x+y*y+z*z;
}

inline rnumt rvectort::normalize()
{
    rnumt norm,invnorm;

  norm=sqrt(x*x+y*y+z*z);

    if (norm<0.0000000001f) return 0.0f;

  invnorm=1.0f/norm;

    x*=invnorm;
    y*=invnorm;
    z*=invnorm;

  return norm;
}


inline rvectort::rvectort(rvectorsset& ssev)
{
    x=ssev.x;
    y=ssev.y;
    z=ssev.z;
}

inline rvectort::rvectort(rnumt xin, rnumt yin, rnumt zin)
{
    x=xin;
    y=yin;
    z=zin;
}


inline bool operator == (const rvectort& v1, const rvectort& v2)
{
    return ((v1.x==v2.x)&&(v1.y==v2.y)&&(v1.z==v2.z));
}

inline bool operator != (const rvectort& v1, const rvectort& v2)
{
    return ((v1.x!=v2.x)||(v1.y!=v2.y)||(v1.z!=v2.z));
}

inline bool equality(const rvectort& v1, const rvectort& v2, rnumt e)
{
    return ((fabs(v1.x-v2.x)<e)&&(fabs(v1.y-v2.y)<e)&&(fabs(v1.z-v2.z)<e));
}


inline rvectort operator +  (const rvectort& v1, const rvectort& v2)
{
    return  rvectort(v1.x+v2.x,v1.y+v2.y,v1.z+v2.z);
}

inline rvectort operator -  (const rvectort& v1, const rvectort& v2)
{
    return  rvectort(v1.x-v2.x,v1.y-v2.y,v1.z-v2.z);
}

inline rvectort operator *  (const rvectort& v, const rnumt t)
{
    return  rvectort(v.x*t,v.y*t,v.z*t);
}

inline rvectort operator *  (const rnumt t, const rvectort& v)
{
    return  rvectort(v.x*t,v.y*t,v.z*t);
}

inline rvectort& operator *=  (rvectort& v, const rnumt t)
{
    v.x*=t;
    v.y*=t;
    v.z*=t;

    return v;
}

inline rvectort operator /  (const rvectort& v, const rnumt t)
{
  rnumt invt;

    invt=1.0f/t;
    return  rvectort(v.x*invt,v.y*invt,v.z*invt);
}

inline rvectort& operator /=  (rvectort& v, const rnumt t)
{
  rnumt invt;

    invt=1.0f/t;

    v.x*=invt;
    v.y*=invt;
    v.z*=invt;

    return  v;
}

inline rvectort& operator +=  (rvectort& v1, const rvectort& v2)
{
    v1.x+=v2.x;
    v1.y+=v2.y;
    v1.z+=v2.z;

    return  v1;
}

inline rvectort& operator -=  (rvectort& v1, const rvectort& v2)
{
    v1.x-=v2.x;
    v1.y-=v2.y;
    v1.z-=v2.z;

    return  v1;
}

inline rvectort operator -  (const rvectort& v)
{
    rvectort nv;

    nv.x=-v.x;
    nv.y=-v.y;
    nv.z=-v.z;

    return  nv;
}


inline  rnumt dot(const rvectort& v1, const rvectort& v2)
{
    return (v1.x*v2.x+v1.y*v2.y+v1.z*v2.z);
}

inline rvectort operator & (const rvectort& v1, const rvectort& v2)
{
    rvectort v3;

    v3.x=v1.y*v2.z-v1.z*v2.y;
    v3.y=-(v1.x*v2.z-v1.z*v2.x);
    v3.z=v1.x*v2.y-v1.y*v2.x;

    return v3;
}

//////////////////////////////////////////////////////////////////////////

inline void rvectort::operator = (const rvectorsset&  ssev)
{
    x=ssev.x;
    y=ssev.y;
    z=ssev.z;
}

inline void rvectort::operator = (const float*  fvectorp)
{
    x=fvectorp[0];
    y=fvectorp[1];
    z=fvectorp[2];
}


inline void rvectorsset::operator = (const rvectort&  v)
{
    x=v.x;
    y=v.y;
    z=v.z;
}


/*
inline rnumt rvectorsset::norm2()
{
    return x*x+y*y+z*z;
}
*/

inline rvectorsset operator - (const rvectorsset& v)
{
    rvectorsset nv;

    nv.x=-v.x;
    nv.y=-v.y;
    nv.z=-v.z;

    return  nv;
}


inline rvectorsset& operator *= (rvectorsset& v, rnumt t)
{
    v.x*=t;
    v.y*=t;
    v.z*=t;

    return v;
}


/////////////////////////////////////////////////////////////////////////

inline rnumt sqr(rnumt x)
{
  return x*x;
}


inline rnumt normv(const rvectort& v)
{
  return sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
}

inline rnumt normv2(const rvectort& v)
{
  return v.x*v.x+v.y*v.y+v.z*v.z;
}

inline void normalize(rvectort& v)
{
  rnumt norminv;

  norminv=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
  if (norminv<0.000000000001f) return;

  norminv=1.0f/norminv;

  v.x*=norminv;
  v.y*=norminv;
  v.z*=norminv;
}

inline rnumt dist(const rvectort& v1, const rvectort& v2)
{
    return sqrt(sqr(v1.x-v2.x)+sqr(v1.y-v2.y)+sqr(v1.z-v2.z));
}

inline rnumt dist2(const rvectort& v1, const rvectort& v2)
{
    return sqr(v1.x-v2.x)+sqr(v1.y-v2.y)+sqr(v1.z-v2.z);
}


inline rnumt normv(const rvectorsset& v)
{
  return sqrt(sqr(v.x)+sqr(v.y)+sqr(v.z));
}

inline rnumt normv2(const rvectorsset& v)
{
  return v.x*v.x+v.y*v.y+v.z*v.z;
}

inline rnumt normalize(rvectorsset& v)
{
  rnumt norm,norminv;

  norm=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
  if (norm==0.0f) return 0.0f;

  norminv=1.0f/norm;

  v.x*=norminv;
  v.y*=norminv;
  v.z*=norminv;

  return norm;
}


inline  rnumt root(rnumt x)
{
  return sqrt(x);
}


#ifdef SSECOMPILER

/*
inline rnumt  apprinv(rnumt x)
{
  rnumt r;
//  #pragma warning( disable : 1011 )  

//  return 1.0f/x;

  __asm
  {
    rcpss xmm0,x
    movss r,xmm0
  }

  return r;
}

inline rnumt apprinvsqrt(rnumt x)
{
  rnumt r;

//  return 1.0f/sqrt(x);

  __asm
  {
    rsqrtss xmm0,x
    movss r,xmm0
  }

  return r; 
}

inline rnumt apprsqrt(rnumt x)
{
  rnumt r;

//  return sqrt(x);

  __asm
  {
    rsqrtss xmm0,x
    rcpss xmm0,xmm0
//    mulss xmm0,x
    movss r,xmm0
  }

  return r; 
}
*/

rnumt apprinv(rnumt x);
rnumt apprinvsqrt(rnumt x);
rnumt apprsqrt(rnumt x);

#endif SSECOMPILER


#endif







