/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: src/drivers/common/opengl/oglpolygon.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/graphics/graphics.hpp"

#include "drivers/common/opengl/opengl.hpp"

class COGLPolygonData : public CPlatformData {
public:
	GLenum		format;
	GLsizei		stride;
	union {
		COGLPolygonData	*pPolyData;
		void		*ptr;
	};
	tUINT32		faces;

	virtual ~COGLPolygonData();
};

COGLPolygonData::~COGLPolygonData()
{
	delete []pPolyData;
}

void 
COpenGLEngine::drawAlphaPolygonImpl(const sgxGfxPolygon &poly, const sgxMatrix43 &transform)
{
	CSGXGraphicsEngine::drawAlphaPolygonImpl(poly, transform);
}

void 
COpenGLEngine::drawPolygonImpl(const sgxGfxPolygon &poly, const sgxMatrix43 &transform)
{
	CSGXGraphicsEngine::drawPolygonImpl(poly, transform);

	if (0 && !Frustum()->isInside(poly, transform)) {
		return;
	}

	oglMatrix mtx(transform);
	GLenum mode = getOGLMode();
	sgxColorRGBA &col = m_PrimitiveColor.getState();

	if (poly.m_pPlatformData) {
		// Platform-specific polygon data. Used if the data is converted
		// using 'convertPolygon'
		const COGLPolygonData *pData = static_cast<const COGLPolygonData *>(poly.m_pPlatformData);

		sgxAssert(pData);

		glColor4f(col.r, col.g, col.b, col.a);
		glInterleavedArrays(pData->format, pData->stride, pData->ptr);
		glBegin(mode);
		for(tMEM_SIZE i=0;i<pData->faces;i++) {
			glArrayElement(i);
		}
		glEnd();

	} else {
		// Use generic data with the GL driver. This is naturally slower.
		sgxVector<sgxPolyVtx>::const_iterator cit=poly.vtx.begin();
		// TODO: Support masked features: uv
		CSGXTextureManager::get()->applyTexture(poly.pTexture);

		glBegin(mode);
			for(;cit!=poly.vtx.end();++cit) {
				glColor4f((*cit).color.r*col.r, (*cit).color.g*col.g, (*cit).color.b*col.b, (*cit).color.a*col.a);
				// TODO: add this fn to TM with a pTexture param
				// so these can be pre-computed
				sgxVector2 uv((*cit).u, (*cit).v);
				CSGXTextureManager::get()->evaluateUV(uv);
				glTexCoord2f(uv.x, uv.y);
				
				glVertex3f((*cit).vect.x, (*cit).vect.y, (*cit).vect.z);
			}
		glEnd();
	}

}

void 
COpenGLEngine::convertPolygon(sgxGfxPolygon &poly)
{
	// TODO: Use factory to handle this conversion automatically
	COGLPolygonData *pGLPoly = new COGLPolygonData;

	// Combine the:
	//	* Texture co-ords mesh (2 x real)
	//	* Normals (sgxVector3)
	//	* Vertices (sgxVector3)
	// data into a single interleaved data block

	// Currently we only handle texture-based data
	poly.m_pPlatformData = pGLPoly;
	pGLPoly->format = GL_T2F_N3F_V3F;
	pGLPoly->stride = 0;
	pGLPoly->faces = poly.vtx.size();

	tUINT32 size = pGLPoly->faces * sizeof(GLfloat)*8;
	GLfloat *ptr = new GLfloat[size];
	pGLPoly->ptr = (void *)ptr;

	// Copy data, byte-by-byte, into the new array
	sgxVector<sgxPolyVtx>::const_iterator cit = poly.vtx.begin();

	for(;cit!=poly.vtx.end();++cit) {
		// Texture
		// TODO: TM::getUV
		*ptr++ = (*cit).u;
		*ptr++ = (*cit).v;
		// Normal
		*ptr++ = (*cit).norm.x;
		*ptr++ = (*cit).norm.y;
		*ptr++ = (*cit).norm.z;
		// Vertex
		*ptr++ = (*cit).vect.x;
		*ptr++ = (*cit).vect.y;
		*ptr++ = (*cit).vect.z;
	}
}

