
#ifndef JL_Vertex_H
#define JL_Vertex_H

#include <iostream.h>
#include "vec4.h"
#include "matrix.h"

class Vertex;
typedef Vertex* VertexPtr;

class Vertex {

	private:
		Vec4	_point;
		Vec4	_normal;

	/*
		static Vertex *_free_list_head;
		static int _chunks_allocated;

		static int _vert_allocated, _vert_in_memory;
	*/
		static Vec4 _NormalizeTemp_P, _NormalizeTemp_N;

		void CopyFrom(const Vertex&);

	public:
		Vertex() { }
		Vertex(const Vertex &v) { CopyFrom(v); }
		Vertex(const Vec4 &v) : _point(v) { }
		Vertex(const Vec4 &v, const Vec4 &n) : _point(v), _normal(n) { }

		~Vertex();

	/*
		void* operator new(size_t size);
		void operator delete(void *deleteme, size_t size);
	*/

		friend ostream& operator<<(ostream&, const Vertex&);

		Vertex& operator=(const Vertex &v) { CopyFrom(v); return *this; }

		inline Vertex& operator*=(const JLmatrix &m) {
				_point.FastJLmatrixMultiply(m);
				_normal.FastJLmatrixMultiply(m);
				return *this;
			}

		inline friend void
			VertexFastAverage(Vertex &v1, const Vertex &v2, const Vertex &v3) {
				Vec4FastAverage(v1._point, v2._point, v3._point);
				Vec4FastAverage(v1._normal, v2._normal, v3._normal);
			}

		inline Vertex& DivideByW() {
				_point.DivideByW();
				_normal.DivideByW();
				return *this;
			}

		inline void NormalizeNormal(JLmatrix *VT, JLmatrix *IVT) {
			_point.FastJLmatrixMultiplyAndDivideByW(_NormalizeTemp_P, *IVT);
			_normal.FastJLmatrixMultiplyAndDivideByW(_NormalizeTemp_N, *IVT);
			Vec4FastSub(_NormalizeTemp_N, _NormalizeTemp_N, _NormalizeTemp_P);
			_NormalizeTemp_N.MakeUnit();
			Vec4FastAdd(_NormalizeTemp_N, _NormalizeTemp_N, _NormalizeTemp_P);
			_NormalizeTemp_N.FastJLmatrixMultiplyAndDivideByW(_normal, *VT);
		}

		inline Vertex& SetPoint(float x, float y, float z, float w) {
			_point.Set(x, y, z, w); return *this; }
		inline Vertex& SetPoint(const Vec4 &v) { _point = v; return *this; }
		inline Vec4 GetPoint() const { return _point; }
		inline Vec4& Point() { return _point; }


		inline void SetNormal(const Vec4 &v) { _normal = v; }
		inline void SetNormal(float x, float y, float z, float w)
				{ _normal.Set(x, y, z, w); }
		inline Vec4& GetNormal() { return _normal; }
};

#endif
