/*
---------------------------------------------------------------------------
Direct3D AssimpRenderer by ponx
---------------------------------------------------------------------------

This code is heavily based on the "AssimpView" project of the Open Asset Import Library (ASSIMP).
http://assimp.sourceforge.net

/*
---------------------------------------------------------------------------
Open Asset Import Library (ASSIMP)
---------------------------------------------------------------------------

Copyright (c) 2006-2008, ASSIMP Development Team

All rights reserved.

Redistribution and use of this software in source and binary forms, 
with or without modification, are permitted provided that the following 
conditions are met:

* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.

* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.

* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/

#include "stdafx.h"

#include "assethelper.h"


namespace AssimpRendererD3d
{

	/// Sets the ambient light for the whole Asset.
	/** @param ambientLight color (and also intensity) of the ambient light shining on this asset.
	*   @returns true if successful
	*/
	bool AssetHelper::SetAmbientLight(D3DCOLOR ambientLight)
	{
		this->lightAmbient = ambientLight;
		return true;
	}
	
	/// Sets the shining direction of the directional light at the given index.
	/** At the moment only a single directional light is supported. Pass 0 as the lightIndex.
	*	This value is read out every time the asset is rendered. It will not be serialized when 
	*	the Asset is saved and therefore has to be set after importing or loading the asset.
	*	@param lightIndex please pass 0 here until multiple light sources are supported.
	*	@param lightDir	the shining direction originating from the light source in world coordinates
	*	@returns true if successful
	*/
	bool AssetHelper::SetDirectionalLightDirection(unsigned int lightIndex, const aiVector3D& lightDir)
	{
		if (lightIndex < NO_OF_DIRECTIONAL_LIGHTS)
		{
			this->lightDirs[lightIndex] = lightDir;
			return true;
		}
		return false;				
	}

	/// Sets the color and shining direction of the directional light at the given index.
	/** At the moment only a single directional light is supported. Pass 0 as the lightIndex.
	*	This value is read out every time the asset is rendered. It will not be serialized when 
	*	the Asset is saved and therefore has to be set after importing or loading the asset.
	*	@param lightIndex please pass 0 here until multiple light sources are supported.
	*	@param lightColor 
	*	@param lightDir	the shining direction originating from the light source in world coordinates
	*	@returns true if successful
	*/
	bool AssetHelper::SetDirectionalLight(unsigned int lightIndex, D3DCOLOR lightColor, const aiVector3D& lightDir)
	{
		if (lightIndex < NO_OF_DIRECTIONAL_LIGHTS)
		{
			this->lightColors[lightIndex] = lightColor;
			this->lightDirs[lightIndex] = lightDir;
			return true;
		}
		return false;				
	}

	/// Sets the color of the directional light at the given index.
	/** At the moment only a single directional light is supported. Pass 0 as the lightIndex.
	*	This value is read out every time the asset is rendered. It will not be serialized when 
	*	the Asset is saved and therefore has to be set after importing or loading the asset.
	*	@param lightIndex please pass 0 here until multiple light sources are supported.
	*	@param lightColor 
	*	@returns true if successful
	*/
	bool AssetHelper::SetDirectionalLightColor(unsigned int lightIndex, D3DCOLOR lightColor)
	{
		if (lightIndex < NO_OF_DIRECTIONAL_LIGHTS)
		{
			this->lightColors[lightIndex] = lightColor;
			return true;
		}
		return false;				
	}

	/// Alters the shininess of the whole Asset by this multiplier.
	/** The shininess describes the size of "hot spots" reflecting a lightsource, when the
	*   light is reflected directly into the camera ("specular lighting").
	*	Each material of the asset stores its own value for the shininess. The
	*	default multiplier value is 1.0f. Use this method if you want to amplify or weaken 
	*	the shininess of the whole asset.
	*   The multiplier will not be stored when the Asset is saved to a file.
	*	@param modificator the multiplier
	*	@returns true if successful
	**/
	bool AssetHelper::SetSpecularShininessModificator(float modificator)
	{
		this->lightShininessModificator = modificator;
		return true;
	}

	/// Alters the specular strength of the whole Asset by this multiplier.
	/** The specular strength describes the  
	*   This value will not be stored when the Asset is saved to a file.
	*	@param modificator the multiplier
	*	@returns true if successful
	**/
	bool AssetHelper::SetSpecularStrengthModificator(float modificator)
	{
		this->lightSpecularStrengthModificator = modificator;
		return true;
	}

	/// 
	/*
	*/
	bool AssetHelper::operator == (const AssetHelper& otherAsset )
	{
		for (unsigned int i = 0; i < this->numMeshes; i++)
		{
			if (!(*this->apcMeshes[i] == (*otherAsset.apcMeshes[i])))
				return false;
		}

		return true;
	}

	bool AssetHelper::operator != (const AssetHelper& otherAsset)
	{
		return !(*this == otherAsset);
	}

	/** temporal method for debugging purposes. 
	*/
	bool AssetHelper::MeshHelper::operator == ( const AssetHelper::MeshHelper& otherMesh )
	{
		if (this->bHM != otherMesh.bHM)
			return false;

		if (this->bSharedFX != otherMesh.bSharedFX)
			return false;

		if (this->eShadingMode != otherMesh.eShadingMode)
			return false;

		if (this->fOpacity != otherMesh.fOpacity)
			return false;

		if (this->fShininess != otherMesh.fShininess)
			return false;

		if (this->fSpecularStrength != otherMesh.fSpecularStrength)
			return false;

		if (this->indexBufferLength != otherMesh.indexBufferLength)
			return false;

		for (unsigned int i=0; i < indexBufferLength; i++)
		{
			if (this->indexBuffer[i] != otherMesh.indexBuffer[i])
				return false;			
		}

		if (this->numVertices != otherMesh.numVertices)
			return false;

		// compare the vertex buffers
		byte* thisVb = reinterpret_cast<byte*>(this->vertexBuffer);
		byte* otherVb = reinterpret_cast<byte*>(otherMesh.vertexBuffer);		
		byte* limit = this->numVertices * sizeof(AssetHelper::Vertex) + thisVb;
		while (thisVb < limit)
		{
			if (*thisVb != *otherVb)
				return false;

			thisVb++;
			otherVb++;
		}
		// ---
		

		if (this->numFaces != otherMesh.numFaces)
			return false;

		if (this->texturePathAmbient != otherMesh.texturePathAmbient)
			return false;

		if (this->texturePathDiffuse != otherMesh.texturePathDiffuse)
			return false;

		if (this->texturePathDiffuse2 != otherMesh.texturePathDiffuse2)
			return false;

		if (this->texturePathEmissive != otherMesh.texturePathEmissive)
			return false;

		if (this->texturePathNormal != otherMesh.texturePathNormal)
			return false;

		if (this->texturePathOpacity != otherMesh.texturePathOpacity)
			return false;

		if (this->texturePathShininess != otherMesh.texturePathShininess)
			return false;

		if (this->texturePathSpecular != otherMesh.texturePathSpecular)
			return false;

		return true;

	}

	bool AssetHelper::MeshHelper::operator != (const AssetHelper::MeshHelper& otherMesh)
	{
		return !(*this == otherMesh);
	}
} // namespace


