#include <math.h>
#include "ptrans.h"

void Update_BasisVectors(ViewVolume *V)
{
  /* basis vector v2 */
  V->v2.x = V->to.x - V->from.x;
  V->v2.y = V->to.y - V->from.y;
  V->v2.z = V->to.z - V->from.z;
  Normalise(&V->v2);

  /* basis vector v1 */
  Cross(&V->up, &V->v2, &V->v1);
  Normalise(&V->v1);

  /* basis vector v3 */
  Cross(&V->v2, &V->v1, &V->v3);
}

void Normalise(Point *p)
{
  register double len;

  len = sqrt(p->x * p->x + p->y * p->y + p->z * p->z);
  p->x /= len;
  p->y /= len;
  p->z /= len;
}

void Cross(Point *a, Point *b, Point *c)
{
  c->x = (a->y * b->z) - (a->z * b->y);
  c->y = (a->z * b->x) - (a->x * b->z);
  c->z = (a->x * b->y) - (a->y * b->x);
}

void Trans_World2Screen(Point p, Point *s, ViewVolume *V)
{
  Point           e, n;
  register double d;

  /* Translate point p so that the view volume is at the origin */
  p.x -= V->from.x;
  p.y -= V->from.y;
  p.z -= V->from.z;

  /* Transform to eye coordinates using the basis vectors */
  e.x = p.x * V->v1.x + p.y * V->v1.y + p.z * V->v1.z;
  e.y = p.x * V->v2.x + p.y * V->v2.y + p.z * V->v2.z;
  e.z = p.x * V->v3.x + p.y * V->v3.y + p.z * V->v3.z;

  /* Convert to normalised coordinates.  Although n.y is copied
     from e.y, the value can be used to check if the point resides
     between the back and front clipping planes of the view frustum */

  d = 1 / e.y;
  n.x = d * e.x;
  n.y = e.y;
  n.z = d * e.z;

  /* Convert to screen coordinates */
  s->x = XCTR - XCTR * n.x;
  s->y = YCTR - YCTR * n.z;
}