#include "Geometry.h"
#include "Camera.h"
#include <iostream>

Geometry::Geometry()
{
	alreadyAddedVertices = 0;
}

void Geometry::render(ID3D10EffectPass* pass)
{
	//if(!Camera::getInstance()->testSphereInFrustum(bs))
	//	return;

	ID3D10Device* device = DXUTGetD3D10Device();
	
	UINT stride = vertexDataSize*sizeof(float);
    UINT offset = 0;
    device->IASetVertexBuffers( 0, 1, &vbo, &stride, &offset );
    	
	device->Draw(nrOfVertices,0);
	
}

void Geometry::createVBO(ID3D10Effect* effect)
{
    D3D10_BUFFER_DESC bd;
    bd.Usage = D3D10_USAGE_DEFAULT;
	bd.ByteWidth = sizeof( float ) * nrOfVertices * vertexDataSize;
    bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;
    bd.MiscFlags = 0;
    D3D10_SUBRESOURCE_DATA InitData;
	InitData.pSysMem = vertexBuffer;
	DXUTGetD3D10Device()->CreateBuffer( &bd, &InitData, &vbo );
	
	delete[] vertexBuffer;
	vertexBuffer = NULL;
}

void Geometry::setName(string _name)
{
	name = _name;
}

string Geometry::getName()
{
	return name;
}

void Geometry::setBoundingBox(float* bbMin,float* bbMax)
{
	bb.min = D3DXVECTOR3(bbMin[0],bbMin[1],bbMin[2]);
	bb.max = D3DXVECTOR3(bbMax[0],bbMax[1],bbMax[2]);
}

void Geometry::setBoundingSphere(float* bsCenter,float bsRadius)
{
	bs.center = D3DXVECTOR3(bsCenter[0],bsCenter[1],bsCenter[2]);
	bs.radius = bsRadius;
}

void Geometry::setHasTangents(bool hasTangents)
{
	_hasTangents = hasTangents;
}

void Geometry::setHasBinormals(bool hasBinormals)
{
	_hasBinormals = hasBinormals;
}

void Geometry::setTextureDimensions(int nrTexCoords,int* dimensions)
{
	nrOfTexCoords = nrTexCoords;
	for(int i=0; i < nrTexCoords;i++)
		texCoordsDimensions.push_back(dimensions[i]);

}

void Geometry::setNumVertices(int numVertices)
{
	vertexDataSize = 6;								//every vertex has a position and a normal for sure
	nrOfVertices = numVertices;
	if(_hasBinormals)
		vertexDataSize +=3;
	if(_hasTangents)
		vertexDataSize +=3;
	for( unsigned int i=0; i<texCoordsDimensions.size();i++)
		vertexDataSize += texCoordsDimensions[i];

	vertexBuffer = new float[nrOfVertices*vertexDataSize];
	alreadyAddedVertices = 0;
}

void Geometry::addVertex(float* position, float* normal, float* tangent, float* binormal, float** texcoords)
{
	int bufferPosition = alreadyAddedVertices*vertexDataSize;

	memcpy(vertexBuffer+bufferPosition, position, 3*sizeof(float));
	bufferPosition += 3;

	memcpy(vertexBuffer+bufferPosition, normal, 3*sizeof(float));
	bufferPosition += 3;

	if(_hasTangents)
	{
		memcpy(vertexBuffer+bufferPosition, tangent, 3*sizeof(float));
		bufferPosition += 3;
	}

	if(_hasBinormals)
	{
		memcpy(vertexBuffer+bufferPosition, binormal, 3*sizeof(float));
		bufferPosition += 3;
	}

	for(unsigned int i=0; i<texCoordsDimensions.size(); i++)
	{
		memcpy(vertexBuffer+bufferPosition, texcoords[i], texCoordsDimensions[i]*sizeof(float));
		bufferPosition +=  texCoordsDimensions[i];
	}
	alreadyAddedVertices++;
}

BoundingBox Geometry::getBoundingBox()
{
	return bb;
}

BoundingSphere Geometry::getBoundingSphere()
{
	return bs;
}

bool Geometry::hasTangents()
{
	return _hasTangents;
}

bool Geometry::hasBinormals()
{
	return _hasBinormals;
}

int Geometry::getNrOfTexCoords()
{
	return nrOfTexCoords;
}

vector<int> Geometry::getTexCoordDimensions()
{
	return texCoordsDimensions;
}

int Geometry::getNrOfVertices()
{
	return nrOfVertices;
}

Geometry::~Geometry()
{
	SAFE_RELEASE(vbo);
}

