/*-------------------------------------------------------------------------*/
/*  J3W ver 6.40  3D Animation Kit                                         */
/*  hobj3d.cpp    10/15/98                                                 */
/*  Copyright (C) 1996 - 1999 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.                   */
/*                                                                         */
/*-------------------------------------------------------------------------*/

#include  "hobj3d.h"
#include  "misc3d.h"

THObj3D::THObj3D(int vn, int pn, THObj3D* p):TObject3D(vn,pn),
                           velocity(0,0,0), wvelocity(0,0,0), accele(0,0,0)
{
    gravity  = 0;
    parent   = p;
    brother  = 0;
    child    = 0;
    sx = 1.0;
    sy = 1.0;
    sz = 1.0;
    sf = 0;
}

THObj3D::~THObj3D()
{
    THObj3D *p;
    THObj3D *q;

    if (child) {
        p = child;
        do {
            p->parent = 0;
            p->Axis.set_matrix(p->wm);
            p->Axis.set_origin(p->wp.x, p->wp.y, p->wp.z);
            q = p->brother;
            p->brother = 0;
            p = q;
        } while (p != 0);
    }
    if (parent)
      if (parent->child == this) {
          if (brother == 0) parent->child = 0;
          else parent->child = brother;
      } else {
          p = parent->child;
          while (p->brother != this) p = p->brother;
          if (brother == 0) p->brother = 0;
          else p->brother = brother;
      }
}

void THObj3D::SetWorld()
{
    wp = Axis.get_origin();
    wm = Axis.get_matrix();
}

void THObj3D::SetNodeWorldMatrix(long delta)
{
    Vector lg;
    Vector  d;

    if (!parent) {
        double time = delta / 1000.0;
        double t2 = time*time / 2;
        lg.x = 0; lg.y = 0; lg.z = 0;
        if (gravity != 0)
            lg = ConvCoordinate2(wm, Vector(0,0,gravity));
#ifdef WS
        d.x = j3w_round(((lg.x  + accele.x) * t2 + velocity.x * time)/1000);
        d.y = j3w_round(((lg.y  + accele.y) * t2 + velocity.y * time)/1000);
        d.z = j3w_round(((lg.z  + accele.z) * t2 + velocity.z * time)/1000);
        velocity.x = j3w_round(double(lg.x + accele.x) * time + velocity.x);
        velocity.y = j3w_round(double(lg.y + accele.y) * time + velocity.y);
        velocity.z = j3w_round(double(lg.z + accele.z) * time + velocity.z);
#else //WS
        d.x = round(((lg.x  + accele.x) * t2 + velocity.x * time)/1000);
        d.y = round(((lg.y  + accele.y) * t2 + velocity.y * time)/1000);
        d.z = round(((lg.z  + accele.z) * t2 + velocity.z * time)/1000);
        velocity.x = round(double(lg.x + accele.x) * time + velocity.x);
        velocity.y = round(double(lg.y + accele.y) * time + velocity.y);
        velocity.z = round(double(lg.z + accele.z) * time + velocity.z);
#endif
        Axis.move(d);
        wvelocity = ConvCoordinate(wm, velocity);

#ifdef WS
        long h = j3w_round(AngleVelocity.x * time);
        long p = j3w_round(AngleVelocity.y * time);
        long b = j3w_round(AngleVelocity.z * time);
#else //WS
        long h = round(AngleVelocity.x * time);
        long p = round(AngleVelocity.y * time);
        long b = round(AngleVelocity.z * time);
#endif //WS
        Axis.rotate(h, p, b);
        SetWorld();
    } else {
        wp.x = long(Axis.get_origin().x * parent->sx + 0.5);
        wp.y = long(Axis.get_origin().y * parent->sy + 0.5);
        wp.z = long(Axis.get_origin().z * parent->sz + 0.5);
        wp = ConvCoordinate(parent->wm, wp);
        wp = wp + parent->wp;
        wm = MulMatrix3(parent->wm, Axis.get_matrix());

    }

    if (child) child->SetNodeWorldMatrix(delta);

    if (brother) brother->SetNodeWorldMatrix(delta);
}

void THObj3D::SetVelocity(Vector v)
{
    velocity = v;
    wvelocity = ConvCoordinate(wm, v);
}

void THObj3D::SetWVelocity(Vector wv)
{
    wvelocity = wv;
    velocity = ConvCoordinate2(wm, wv);
}

void THObj3D::show(THObj3D *eye)
{
    Vector v;
    int n =  Polygon.Vertex.GetCount();
#ifdef WS
	int i;
    for (i=0; i<n; i++) {
#else //WS
    for (int i=0; i<n; i++) {
#endif //WS
        Vector w = Polygon.Vertex.vert[i]->local;
        if (sf) {
            w.x = long(w.x * sx + 0.5);
            w.y = long(w.y * sy + 0.5);
            w.z = long(w.z * sz + 0.5);
        }
        v = ConvCoordinate(wm, w);
        Polygon.Vertex.vert[i]->world = v + wp;
    }
    Axis.reset_change();
#ifdef WS
    for (i=0; i<n; i++) {
#else //WS
    for (int i=0; i<n; i++) {
#endif //WS
        v = Polygon.Vertex.vert[i]->world - eye->wp;
        Polygon.Vertex.vert[i]->eye = ConvCoordinate2(eye->wm, v);
    }
}

void THObj3D::GetWorldPosition(Vector &pos, long &h, long &p, long &b)
{
    pos = wp;
    b  = DEG( atan2(wm.m8, wm.m9) );
    p  = DEG( - asin(wm.m7) );
    h  = DEG( atan2(wm.m4, wm.m1) );
}

