////////////////////////////////////////////////////////////////////////////////
// Class Point3D
// Copyright Bjoern Ganster
// Developed since 2000
////////////////////////////////////////////////////////////////////////////////

#ifndef Point3D__h
#define Point3D__h

#include "BGBase.h"

////////////////////////////////////////////////////////////////////////////////
// Class Point3D, stored in homogeneous coordinates

class Point3D FINAL { //: public VirtualClass {
public:
	double x, y, z, w;

	// Constructors
	// Object creation and destruction are much faster if Point3D does not derive from VirtualClass
	Point3D(double _x = 0.0, double _y = 0.0, double _z = 0.0, double _w = 1.0);
	Point3D(const Point3D& a);

	// Destructors
	~Point3D(); // OVERRIDE;

	// Unary -
	Point3D operator-() const;

	// Binary +
	Point3D operator+(const Point3D& a) const;

	// Binary -
	Point3D operator-(const Point3D& a) const;

	// Cross product
	Point3D crossMultiply(const Point3D& a) const;

	// Binary scalar product
	double operator*(const Point3D& a) const;

	// Divide a vector by scalar
	Point3D operator/(double a) const;

	// Equals
	bool operator==(const Point3D& a) const;

	// Not equals
	bool operator!=(const Point3D& a) const;

	// Assignment operator
	void operator=(const Point3D& a);

	// Self-add operator
	void operator+=(const Point3D& a);

	// Self-subtract operator
	void operator-=(const Point3D& a);

	// Calculate a vector's length / distance to origin
	double length() const;

	// Make itself unit length
	bool unitLength();

	// Apply as vertex
	void glVertex() const;

	// Apply as normal
	void glNormal() const;

	// Calculate the angle between ab, bc
	static double angle(const Point3D& a, const Point3D& b, const Point3D& c);
	static double angle(const Point3D& a, const Point3D& b);

	// Find two vectors that are pependicular to self
	bool findPerps(Point3D& b, Point3D& c) const;

	void copy3DCoordsToArray(double* array) const;
	void copy3DCoordsToArray(float* array) const;
};

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

Point3D MinCoords(const Point3D& a, const Point3D& b);
Point3D MaxCoords(const Point3D& a, const Point3D& b);
double dist3D(const Point3D& a, const Point3D& b);

// Check for bounding box intersection
bool boxesIntersect(const Point3D& aMin, const Point3D& aMax, const Point3D& bMin, const Point3D& bMax);

// Scalar multiplication
Point3D operator*(double f, const Point3D& p);
Point3D operator*(const Point3D& p, double f);

// Calculate a polar coordinate as the angle from origin to p in the plane given by origin and normal
// dir0 gives the direction in that plane where the angle would be 0
double calcPolarCoord(const Point3D& origin, const Point3D& normal, const Point3D& dir0, const Point3D& p);

// Calculate a normal for a triangle
Point3D calcNormal(const Point3D& p0, const Point3D& p1, const Point3D p2);

#endif
