//***************************************************************************************
//
// File supervisor: Softimage Rendering & Pipeline team
//
// (c) Copyright 2001-2005 Avid Technology, Inc. . All rights reserved.
//
//***************************************************************************************

/**************************************************************************************
THIS CODE IS PUBLISHED AS A SAMPLE ONLY AND IS PROVIDED "AS IS".
IN NO EVENT SHALL SOFTIMAGE, AVID TECHNOLOGY, INC. AND/OR THEIR RESPECTIVE
SUPPLIERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS CODE .

COPYRIGHT NOTICE. Copyright © 1999-2005 Avid Technology Inc. . All rights reserved. 

SOFTIMAGE is a registered trademark of Avid Technology Inc. or its subsidiaries 
or divisions. Windows NT is a registered trademark of Microsoft Corp. All other
trademarks contained herein are the property of their respective owners. 
****************************************************************************************/
/*! \file cnv_mesh_clusterprop.cpp
/*!
	Mesh cluster property conversion classes
*/

#include "stdafx.h"
#include "cnv_mesh_clusterprop.h"
#include <xsi_polygonmesh.h>
#include <xsi_geometryaccessor.h>
#include <xsi_meshbuilder.h>
#include <XSIMesh.h>
#include <XSIShape.h>
#include <xsi_x3dobject.h>
#include <xsi_time.h>
#include <xsi_primitive.h>
#include <xsi_cluster.h>
#include <Model.h>
#include <XSISubComponentAttributeList.h>
#include <XSIVertexList.h>
#include <MaterialLibrary.h>
#include <Material.h>
#include <xsi_material.h>
#include <XSIPolygonList.h>
#include <XSITriangleList.h>
#include <GlobalMaterial.h>
#include <Cluster.h>
#include <xsi_clusterpropertybuilder.h>


/**************************************************************************************
CMeshClusterPropFromXSI
**************************************************************************************/
CMeshClusterPropFromXSI::CMeshClusterPropFromXSI(short in_CryFiletype) : CHierarchyTraverserCallback(in_CryFiletype) {};

CMeshClusterPropFromXSI::~CMeshClusterPropFromXSI() {};

CStatus CMeshClusterPropFromXSI::Execute(CdotXSIConverter *in_pContext, CRef in_XSIParent, CSLTemplate *in_pFTKParent, CHierarchyElementInfo* in_pInfo, CRef *io_pXSIModel, CSLTemplate **io_pFTKModel)
{
	CStatus status = CStatus::OK;
	Application XSI;

	LONG loop, loop2;

	X3DObject l_XSIModel = (X3DObject) *io_pXSIModel;

	if((*io_pFTKModel) && (wcscmp(l_XSIModel.GetType().GetWideString(), L"polymsh") == 0))
	{
		// polynode and vertex attribute value lists are the same
		// for polygon or triangle export
		CSLModel *l_pFTKModel = (CSLModel*)*io_pFTKModel;

		CSLXSIMesh			*l_pFTKMesh = (CSLXSIMesh *) l_pFTKModel->Primitive();
		PolygonMesh			l_XSIMesh = (PolygonMesh) l_XSIModel.GetActivePrimitive().GetGeometry();

		CSIBCUserData *l_pUserData = l_pFTKMesh->FindUserData("GEOMETRYACCESSOR");
		if(l_pUserData)
		{
			CRef *l_pCRef = (CRef*)(l_pUserData->GetData());
			CGeometryAccessor l_XSIGeometryAccessor = (CGeometryAccessor) *l_pCRef;

			if (l_XSIGeometryAccessor.IsValid())
			{
				CFloatArray l_XSINormalArray;
				CSLXSISubComponentAttributeList *l_pFTKNormals = NULL;
				CSLXSISubComponentAttributeList::CSLFloatArray *l_pFTKNormalArray = NULL;

				// export the user normals
				CRefArray l_XSIUserNormalPropArray = l_XSIGeometryAccessor.GetUserNormals();

				bool l_bExportXSINormals = true;

				for (loop = 0; loop < l_XSIUserNormalPropArray.GetCount(); loop++)
				{
					ClusterProperty					l_XSIUserNormalProp(l_XSIUserNormalPropArray.GetItem(loop));

					CFloatArray						l_XSIUserNormalArray;

					l_XSIUserNormalProp.GetValues( l_XSIUserNormalArray );

					l_pFTKNormals = l_pFTKMesh->XSIShape()->AddNormalList();

					l_pFTKNormals->SetName((char*)l_XSIUserNormalProp.GetName().GetAsciiString());

					if (strcmp("XSINormal",(char*)l_XSIUserNormalProp.GetName().GetAsciiString()) == 0)
					{
						l_bExportXSINormals = false;
					}

					l_pFTKNormalArray = l_pFTKNormals->GetAttributeArray();
					l_pFTKNormalArray->Extend(l_XSIUserNormalArray.GetCount());

					for(loop2 = 0; loop2 < l_XSIUserNormalArray.GetCount(); loop2++)
					{
						(*l_pFTKNormalArray)[loop2] = l_XSIUserNormalArray[loop2];
					}
				}

				if (l_bExportXSINormals)
					l_bExportXSINormals = in_pContext->exportproperty().GetParameterValue(L"ExportXSINormals");

				// export the XSI generated normals
				if (l_bExportXSINormals)
				{
					l_XSIGeometryAccessor.GetNodeNormals(l_XSINormalArray);
					l_pFTKNormals = l_pFTKMesh->XSIShape()->AddNormalList();
					l_pFTKNormals->SetName("XSINormal");
					l_pFTKNormalArray = l_pFTKNormals->GetAttributeArray();
					l_pFTKNormalArray->Extend(l_XSINormalArray.GetCount());

					for(loop = 0; loop < l_XSINormalArray.GetCount(); loop++)
					{
						(*l_pFTKNormalArray)[loop] = l_XSINormalArray[loop];
					}
				}

				// export the texture coordinates (UVs)
				CRefArray l_XSIUVPropArray = l_XSIGeometryAccessor.GetUVs();

				for (loop = 0; loop < l_XSIUVPropArray.GetCount(); loop++)
				{
					ClusterProperty					l_XSIUVProp(l_XSIUVPropArray.GetItem(loop));

					CFloatArray						l_XSIUVArray;

					l_XSIUVProp.GetValues( l_XSIUVArray );

					CSLXSISubComponentAttributeList *l_pFTKUVs = l_pFTKMesh->XSIShape()->AddTexCoordList();

					l_pFTKUVs->SetName((char*)l_XSIUVProp.GetName().GetAsciiString());

					CSLXSISubComponentAttributeList::CSLFloatArray *l_pFTKUVArray = l_pFTKUVs->GetAttributeArray();
					
					// in XSI the UV array actually contain UV and W values (3 values)
					// but in the FTK we only take into account the U and the V values (we skip the W value).
					LONG l_nUVCount = l_XSIUVArray.GetCount()/3;
					l_pFTKUVArray->Extend(l_nUVCount*2);

					CString csVersion = XSI.GetVersion();
					CStringArray csSplitVersion = csVersion.Split(CString(L"."));
					float fMajor = 0.0f;
					float fMinor = 0.0f;

					if (csSplitVersion.GetCount() > 1)
					{
						sscanf(csSplitVersion[0].GetAsciiString(), "%f", &fMajor);
						sscanf(csSplitVersion[1].GetAsciiString(), "%f", &fMinor);
					}

					if ( fMajor > 6.0f || 
						(fMajor == 6.0f && fMinor > 5.0f) )
					{
						for(loop2 = 0; loop2 < l_nUVCount; loop2++)
						{
							// U
							//
							(*l_pFTKUVArray)[loop2*2] = l_XSIUVArray[loop2*3];

							// V
							//
							(*l_pFTKUVArray)[loop2*2+1] = l_XSIUVArray[loop2*3+1];
						}
					}
					else
					{
						// We used to uniformize the coordinates in the dotXSIConverter before.
						// Post XSI 6.5, this is done in the cluster property for homogeneous coordinates 
						// only
						//
						for(loop2 = 0; loop2 < l_nUVCount; loop2++)
						{
							// W
							float l_W = ((l_XSIUVArray[loop2*3+2] != 0.0f) && (abs(l_XSIUVArray[loop2*3+2]) > 0.000001f)) ? l_XSIUVArray[loop2*3+2] : 1.0f;
							// U
							(*l_pFTKUVArray)[loop2*2] = l_XSIUVArray[loop2*3]/l_W;
							// V
							(*l_pFTKUVArray)[loop2*2+1] = l_XSIUVArray[loop2*3+1]/l_W;
						}
					}
				}

				// export the color at verticies
				CRefArray l_XSIVertexColorPropArray = l_XSIGeometryAccessor.GetVertexColors();

				Property exportProp = in_pContext->exportproperty();
				bool l_bTangentsAsVtxColors = exportProp.GetParameterValue(L"ExportTangentsAsVtxColor");

				for (loop = 0; loop < l_XSIVertexColorPropArray.GetCount(); loop++)
				{
					l_XSIGeometryAccessor.GetNodeCount();

					ClusterProperty					l_XSIVertexColorProp(l_XSIVertexColorPropArray.GetItem(loop));
					CFloatArray						l_XSIVertexColorArray;

					CSIBCString l_PropName((char*)l_XSIVertexColorProp.GetName().GetAsciiString());
					l_PropName.LowerCase();
					l_XSIVertexColorProp.GetValues( l_XSIVertexColorArray );



					if(strstr(l_PropName.GetText(), "tangent") && !l_bTangentsAsVtxColors)
					{

						CSLXSISubComponentAttributeList *l_pFTKTangents = l_pFTKMesh->XSIShape()->AddTangentList();

						l_pFTKTangents->SetName((char*)l_XSIVertexColorProp.GetName().GetAsciiString());

						CSLXSISubComponentAttributeList::CSLFloatArray *l_pFTKTangentArray = l_pFTKTangents->GetAttributeArray();
						l_pFTKTangentArray->Extend(l_XSIVertexColorArray.GetCount());

						for(loop2 = 0; loop2 < l_XSIVertexColorArray.GetCount(); loop2++)
						{
							(*l_pFTKTangentArray)[loop2] = (l_XSIVertexColorArray[loop2] * 2.0f) - 1.0f;
						}
					}
					else
					{

						CSLXSISubComponentAttributeList *l_pFTKVertexColors = l_pFTKMesh->XSIShape()->AddColorList();

						l_pFTKVertexColors->SetName((char*)l_XSIVertexColorProp.GetName().GetAsciiString());

						CSLXSISubComponentAttributeList::CSLFloatArray *l_pFTKVertexColorArray = l_pFTKVertexColors->GetAttributeArray();
						l_pFTKVertexColorArray->Extend(l_XSIVertexColorArray.GetCount());

						for(loop2 = 0; loop2 < l_XSIVertexColorArray.GetCount(); loop2++)
						{
							(*l_pFTKVertexColorArray)[loop2] = l_XSIVertexColorArray[loop2];
						}
					}
				}

				// export the weight maps
				CRefArray l_XSIWeightMapPropArray = l_XSIGeometryAccessor.GetWeightMaps();

				for (loop = 0; loop < l_XSIWeightMapPropArray.GetCount(); loop++)
				{
					ClusterProperty					l_XSIWeightMapProp(l_XSIWeightMapPropArray.GetItem(loop));
					CFloatArray						l_XSIWeightMapArray;

					l_XSIWeightMapProp.GetValues( l_XSIWeightMapArray );

					// export the weights
					CSLXSISubComponentAttributeList *l_pFTKWeights = l_pFTKMesh->XSIShape()->AddWeightMapList();	

					l_pFTKWeights->SetName((char*)l_XSIWeightMapProp.GetName().GetAsciiString());

					CSLXSISubComponentAttributeList::CSLFloatArray *l_pFTKWeightArray = l_pFTKWeights->GetAttributeArray();
					l_pFTKWeightArray->Extend(l_XSIWeightMapArray.GetCount());

					for(loop2 = 0; loop2 < l_XSIWeightMapArray.GetCount(); loop2++)
					{
						(*l_pFTKWeightArray)[loop2] = (float)l_XSIWeightMapArray[loop2];
					}
				}
			}
		}
	}

	return status;
}

wchar_t *CMeshClusterPropFromXSI::GetClassID(){return L"CMeshClusterPropFromXSI";}

/**************************************************************************************
CMeshClusterPropToXSI
**************************************************************************************/
CMeshClusterPropToXSI::CMeshClusterPropToXSI(short in_CryFiletype) : CHierarchyTraverserCallback(in_CryFiletype) {};

CMeshClusterPropToXSI::~CMeshClusterPropToXSI() {};

CStatus CMeshClusterPropToXSI::Execute(CdotXSIConverter *in_pContext, CRef in_XSIParent, CSLTemplate *in_pFTKParent, CHierarchyElementInfo* in_pInfo, CRef *io_pXSIModel, CSLTemplate **io_pFTKModel)
{
	CStatus status = CStatus::OK;
	LONG loop, loop2;
	CString l_csEmpty, l_csNodeProperties(L"NodeProperties"), l_csVertexProperties(L"VertexProperties");

	if (*io_pFTKModel)
	{
		CSLModel *l_pFTKModel = (CSLModel *)(*io_pFTKModel);

		if (l_pFTKModel->Primitive() && l_pFTKModel->Primitive()->Type() == CSLTemplate::XSI_MESH)
		{
			CSLXSIMesh* l_pFTKMesh = (CSLXSIMesh*)l_pFTKModel->Primitive();

			// test if we want to add these cluster properties
			CSIBCUserData * l_bAddClusterProperties = l_pFTKMesh->FindUserData("BADPOLYS");
			if ( (l_bAddClusterProperties != NULL) && (l_bAddClusterProperties->GetData() != 0) )
			{
				return CStatus::OK;
			}

			X3DObject	l_XSIParent = (X3DObject) in_XSIParent;
	
			CString l_Name;
			l_Name.PutAsciiString(l_pFTKModel->GetName());

			X3DObject l_XSIObject(*io_pXSIModel);
			PolygonMesh	l_XSIMesh = l_XSIObject.GetActivePrimitive().GetGeometry(); 

			// now import the cluster property (Normals, UVs, Vertex Colors, Texture Coordinates, Weight Maps)
			CClusterPropertyBuilder l_XSIClusterPropBuilder = l_XSIMesh.GetClusterPropertyBuilder();

			if (l_XSIClusterPropBuilder.IsValid())
			{
				// count the total number of polynode
				LONG l_lPolynodeCount = 0;
				LONG l_nIndex = 0;

				for (loop = 0; loop < l_pFTKMesh->GetXSIPolygonListCount(); loop++)
				{
					l_lPolynodeCount += l_pFTKMesh->XSIPolygonLists()[loop]->GetCount();
				}

				for (loop = 0; loop < l_pFTKMesh->GetXSITriangleListCount(); loop++)
				{
					l_lPolynodeCount += l_pFTKMesh->XSITriangleLists()[loop]->GetCount();
				}

				// IF there exists an index list, and IF there are the right number of indices in the list
				// THEN we'll know that the polygons are already in order. Otherwise, we won't and will
				// need to use the polynode array.
				// this boolean represents whether we'll use index lists or not
				bool bPolyClusterSupport = true;
				for (loop = 0; bPolyClusterSupport && loop < l_pFTKMesh->GetXSIPolygonListCount(); loop++)
				{
					// grab poly list stuff
					CSLXSIPolygonList *l_pFTKPolygonList = l_pFTKMesh->XSIPolygonLists()[loop];
					ULONG l_polyCount = l_pFTKPolygonList->GetPolygonCount();

					// set up the index list
					CSLXSIIndexList *l_pFTKIndexList = l_pFTKPolygonList->GetIndexList();
					if (!l_pFTKIndexList) {
						// index list not found
						bPolyClusterSupport = false;
						break;
					}
					int l_indexListCount = l_pFTKIndexList->GetCount();
					bPolyClusterSupport = (l_indexListCount == l_polyCount);
				}

				// create an array to hold the property value array that we will use to 
				float *l_pFTKPolynodesValue = new float[l_lPolynodeCount*4];

				// normal
				CSLXSISubComponentAttributeList *l_pAttribute = l_pFTKMesh->XSIShape()->GetFirstNormalList();
				while (l_pAttribute)
				{
					float *l_pFTKValues = l_pAttribute->GetAttributeArray()->ArrayPtr();

					// set the indices array
					l_lPolynodeCount = 0;

					for (loop = 0; loop < l_pFTKMesh->GetXSIPolygonListCount(); loop++)
					{
						CSLXSIPolygonList *l_pFTKPolygonList = l_pFTKMesh->XSIPolygonLists()[loop];

						CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKPolygonList->GetAttributeByName (l_pAttribute->GetName());

						if ( l_pAttrib == NULL )
							break;

						int* l_pFTKPolygonListIndices = l_pAttrib->ArrayPtr();

						for (loop2 = 0; loop2 < l_pFTKPolygonList->GetCount(); loop2++)
						{
							l_nIndex = bPolyClusterSupport ? l_lPolynodeCount : l_pFTKPolygonListIndices[loop2];
							l_pFTKPolynodesValue[l_lPolynodeCount*3] = l_pFTKValues[l_nIndex*3];
							l_pFTKPolynodesValue[l_lPolynodeCount*3+1] = l_pFTKValues[l_nIndex*3+1];
							l_pFTKPolynodesValue[l_lPolynodeCount*3+2] = l_pFTKValues[l_nIndex*3+2];

							if(	(l_pFTKPolynodesValue[l_lPolynodeCount*3] == 0.0f) && 
								(l_pFTKPolynodesValue[l_lPolynodeCount*3+1] == 0.0f) && 
								(l_pFTKPolynodesValue[l_lPolynodeCount*3+2] == 0.0f))
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*3+1] = 1.0f; // dummy value and should not happen
							}

							l_lPolynodeCount++;
						}
					}

					for (loop = 0; loop < l_pFTKMesh->GetXSITriangleListCount(); loop++)
					{
						CSLXSITriangleList *l_pFTKTriangleList = l_pFTKMesh->XSITriangleLists()[loop];

						CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKTriangleList->GetAttributeByName (l_pAttribute->GetName());

						if ( l_pAttrib == NULL )
							break;
						
						int* l_pFTKTriangleListIndices = l_pAttrib->ArrayPtr();

						for (loop2 = 0; loop2 < l_pFTKTriangleList->GetCount(); loop2++)
						{
							l_pFTKPolynodesValue[l_lPolynodeCount*3] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*3];
							l_pFTKPolynodesValue[l_lPolynodeCount*3+1] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*3+1];
							l_pFTKPolynodesValue[l_lPolynodeCount*3+2] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*3+2];

							if(	(l_pFTKPolynodesValue[l_lPolynodeCount*3] == 0.0f) && 
								(l_pFTKPolynodesValue[l_lPolynodeCount*3+1] == 0.0f) && 
								(l_pFTKPolynodesValue[l_lPolynodeCount*3+2] == 0.0f))
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*3+1] = 1.0f; // dummy value and should not happen
							}

							l_lPolynodeCount++;
						}
					}

					ClusterProperty l_XSIClusterProp = l_XSIClusterPropBuilder.AddUserNormal(l_csEmpty, l_csNodeProperties);

					if (l_pAttribute->Name().GetLength() > 0)
					{
						CString l_PropName;
						l_PropName.PutAsciiString(l_pAttribute->Name().GetText());
						l_XSIClusterProp.PutName(l_PropName);
					}

					l_XSIClusterProp.SetValues(	l_pFTKPolynodesValue, l_lPolynodeCount );
	
					l_pAttribute = l_pFTKMesh->XSIShape()->GetNextNormalList();
				}

				// vertex color
				l_pAttribute = l_pFTKMesh->XSIShape()->GetFirstColorList();
				while (l_pAttribute)
				{
					float *l_pFTKValues = l_pAttribute->GetAttributeArray()->ArrayPtr();

					// set the indices array
					l_lPolynodeCount = 0;

					for (loop = 0; loop < l_pFTKMesh->GetXSIPolygonListCount(); loop++)
					{
						CSLXSIPolygonList *l_pFTKPolygonList = l_pFTKMesh->XSIPolygonLists()[loop];

						CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKPolygonList->GetAttributeByName(l_pAttribute->GetName());

						if ( l_pAttrib == NULL )
							break;

						int* l_pFTKPolygonListIndices = l_pAttrib->ArrayPtr();

						for (loop2 = 0; loop2 < l_pFTKPolygonList->GetCount(); loop2++)
						{
							l_nIndex = bPolyClusterSupport ? l_lPolynodeCount : l_pFTKPolygonListIndices[loop2];
							l_pFTKPolynodesValue[l_lPolynodeCount*4] = l_pFTKValues[l_nIndex*4];
							l_pFTKPolynodesValue[l_lPolynodeCount*4+1] = l_pFTKValues[l_nIndex*4+1];
							l_pFTKPolynodesValue[l_lPolynodeCount*4+2] = l_pFTKValues[l_nIndex*4+2];
							l_pFTKPolynodesValue[l_lPolynodeCount*4+3] = l_pFTKValues[l_nIndex*4+3];
							l_lPolynodeCount++;
						}
					}

					for (loop = 0; loop < l_pFTKMesh->GetXSITriangleListCount(); loop++)
					{
						CSLXSITriangleList *l_pFTKTriangleList = l_pFTKMesh->XSITriangleLists()[loop];

						CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKTriangleList->GetAttributeByName(l_pAttribute->GetName());
						if ( l_pAttrib == NULL )
							break;

						int* l_pFTKTriangleListIndices = l_pAttrib->ArrayPtr();

						for (loop2 = 0; loop2 < l_pFTKTriangleList->GetCount(); loop2++)
						{
							l_pFTKPolynodesValue[l_lPolynodeCount*4] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*4];
							l_pFTKPolynodesValue[l_lPolynodeCount*4+1] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*4+1];
							l_pFTKPolynodesValue[l_lPolynodeCount*4+2] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*4+2];
							l_pFTKPolynodesValue[l_lPolynodeCount*4+3] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*4+3];
							l_lPolynodeCount++;
						}
					}

					ClusterProperty l_XSIClusterProp = l_XSIClusterPropBuilder.AddVertexColor(l_csEmpty, l_csNodeProperties);

					if (l_pAttribute->Name().GetLength() > 0)
					{
						CString l_PropName;
						l_PropName.PutAsciiString(l_pAttribute->Name().GetText());
						l_XSIClusterProp.PutName(l_PropName);
					}
	
					l_XSIClusterProp.SetValues( l_pFTKPolynodesValue, l_lPolynodeCount);

					l_pAttribute = l_pFTKMesh->XSIShape()->GetNextColorList();
				}

				// texture coord
				l_pAttribute = l_pFTKMesh->XSIShape()->GetFirstTexCoordList();
				while (l_pAttribute)
				{
					float *l_pFTKValues = l_pAttribute->GetAttributeArray()->ArrayPtr();
					int stride = 3;

					if(l_pAttribute->GetAttributeType() == CSLXSISubComponentAttributeList::FLOAT)
					{
						stride = 1;
					}
					else if(l_pAttribute->GetAttributeType() == CSLXSISubComponentAttributeList::FLOAT2)
					{
						stride = 2;
					}					
					else if(l_pAttribute->GetAttributeType() == CSLXSISubComponentAttributeList::FLOAT3)
					{
						stride = 3;
					}					
					else if(l_pAttribute->GetAttributeType() == CSLXSISubComponentAttributeList::FLOAT4)
					{
						stride = 4;
					}
					else if(l_pAttribute->GetAttributeType() == CSLXSISubComponentAttributeList::FLOAT5)
					{
						stride = 5;
					}


					// set the indices array
					l_lPolynodeCount = 0;

					for (loop = 0; loop < l_pFTKMesh->GetXSIPolygonListCount(); loop++)
					{
						CSLXSIPolygonList *l_pFTKPolygonList = l_pFTKMesh->XSIPolygonLists()[loop];

						CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKPolygonList->GetAttributeByName(l_pAttribute->GetName());
						if ( l_pAttrib == NULL )
							break;

						int* l_pFTKPolygonListIndices = l_pAttrib->ArrayPtr();

						for (loop2 = 0; loop2 < l_pFTKPolygonList->GetCount(); loop2++)
						{
							l_nIndex = bPolyClusterSupport ? l_lPolynodeCount : l_pFTKPolygonListIndices[loop2];
							l_pFTKPolynodesValue[l_lPolynodeCount*3] = l_pFTKValues[l_nIndex*stride];
							l_pFTKPolynodesValue[l_lPolynodeCount*3+1] = l_pFTKValues[l_nIndex*stride+1];
							if(stride >= 3)
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*3+2] = l_pFTKValues[l_nIndex*stride+2];
							}
							else
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*3+2] = 0.0f;
							}

							l_lPolynodeCount++;
						}
					}

					for (loop = 0; loop < l_pFTKMesh->GetXSITriangleListCount(); loop++)
					{
						CSLXSITriangleList *l_pFTKTriangleList = l_pFTKMesh->XSITriangleLists()[loop];

						CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKTriangleList->GetAttributeByName(l_pAttribute->GetName());
						if ( l_pAttrib == NULL )
							break;

						int* l_pFTKTriangleListIndices = l_pAttrib->ArrayPtr();

						for (loop2 = 0; loop2 < l_pFTKTriangleList->GetCount(); loop2++)
						{
							l_pFTKPolynodesValue[l_lPolynodeCount*3] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*stride];
							l_pFTKPolynodesValue[l_lPolynodeCount*3+1] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*stride+1];

							if(stride >= 3)
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*3+2] = l_pFTKValues[l_pFTKTriangleListIndices[loop2]*stride+2];
							}
							else
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*3+2] = 0.0f;
							}

							l_lPolynodeCount++;
						}
					}

					ClusterProperty l_XSIClusterProp = l_XSIClusterPropBuilder.AddUV(l_csEmpty, l_csNodeProperties);

					if (l_pAttribute->Name().GetLength() > 0)
					{
						CString l_PropName;
						l_PropName.PutAsciiString(l_pAttribute->Name().GetText());
						l_XSIClusterProp.PutName(l_PropName);
					}

					l_XSIClusterProp.SetValues( l_pFTKPolynodesValue, l_lPolynodeCount );

					l_pAttribute = l_pFTKMesh->XSIShape()->GetNextTexCoordList();
				}

				// weight map
				l_pAttribute = l_pFTKMesh->XSIShape()->GetFirstWeightMapList();
				while (l_pAttribute)
				{
					CSLXSIVertexList* l_pFTKVertexList = l_pFTKMesh->XSIVertexList();

					CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKVertexList->GetAttributeByName(l_pAttribute->GetName());
					if ( l_pAttrib == NULL )
							break;
					int* l_pFTKVertexListIndices = l_pAttrib->ArrayPtr();

					ClusterProperty l_XSIClusterProp = l_XSIClusterPropBuilder.AddWeightMap(l_csEmpty, l_csVertexProperties);

					const CClusterPropertyElementArray l_Elem = l_XSIClusterProp.GetElements();

					LONG l_lCount = l_Elem.GetCount();

					if (l_pAttribute->Name().GetLength() > 0)
					{
						CString l_PropName;
						l_PropName.PutAsciiString(l_pAttribute->Name().GetText());
						l_XSIClusterProp.PutName(l_PropName);
					}

					float *l_pFTKValues = l_pAttribute->GetAttributeArray()->ArrayPtr();

					l_XSIClusterProp.SetValues( l_pFTKValues, l_pFTKVertexList->GetCount() );

					l_pAttribute = l_pFTKMesh->XSIShape()->GetNextWeightMapList();
				}

				// tangents
				l_pAttribute = l_pFTKMesh->XSIShape()->GetFirstTangentList();
				while (l_pAttribute)
				{
					float *l_pFTKValues = l_pAttribute->GetAttributeArray()->ArrayPtr();

					// set the indices array
					l_lPolynodeCount = 0;

					for (loop = 0; loop < l_pFTKMesh->GetXSIPolygonListCount(); loop++)
					{
						CSLXSIPolygonList *l_pFTKPolygonList = l_pFTKMesh->XSIPolygonLists()[loop];

						CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKPolygonList->GetAttributeByName(l_pAttribute->GetName());
						
						if ( l_pAttrib == NULL )
							break;
						int* l_pFTKPolygonListIndices = l_pAttrib->ArrayPtr();

						for (loop2 = 0; loop2 < l_pFTKPolygonList->GetCount(); loop2++)
						{
							l_nIndex = bPolyClusterSupport ? l_lPolynodeCount : l_pFTKPolygonListIndices[loop2];
							if(l_pAttribute->GetAttributeType() == CSLXSISubComponentAttributeList::FLOAT4)
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*4] = (l_pFTKValues[l_nIndex*4] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+1] = (l_pFTKValues[l_nIndex*4+1] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+2] = (l_pFTKValues[l_nIndex*4+2] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+3] = (l_pFTKValues[l_nIndex*4+3] + 1.0f)/2.0f;
							}
							else
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*4] = (l_pFTKValues[l_nIndex*3] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+1] = (l_pFTKValues[l_nIndex*3+1] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+2] = (l_pFTKValues[l_nIndex*3+2] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+3] = 1.0f;
							}
							l_lPolynodeCount++;
						}
					}

					for (loop = 0; loop < l_pFTKMesh->GetXSITriangleListCount(); loop++)
					{
						CSLXSITriangleList *l_pFTKTriangleList = l_pFTKMesh->XSITriangleLists()[loop];

						CSLArrayProxy<SI_Int, SI_Int,1>* l_pAttrib = l_pFTKTriangleList->GetAttributeByName(l_pAttribute->GetName());
						if ( l_pAttrib == NULL )
							break;
						int* l_pFTKTriangleListIndices = l_pAttrib->ArrayPtr();

						for (loop2 = 0; loop2 < l_pFTKTriangleList->GetCount(); loop2++)
						{
							if(l_pAttribute->GetAttributeType() == CSLXSISubComponentAttributeList::FLOAT4)
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*4] = (l_pFTKValues[l_pFTKTriangleListIndices[loop2]*4] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+1] = (l_pFTKValues[l_pFTKTriangleListIndices[loop2]*4+1] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+2] = (l_pFTKValues[l_pFTKTriangleListIndices[loop2]*4+2] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+3] = (l_pFTKValues[l_pFTKTriangleListIndices[loop2]*4+3] + 1.0f)/2.0f;
							}
							else
							{
								l_pFTKPolynodesValue[l_lPolynodeCount*4] = (l_pFTKValues[l_pFTKTriangleListIndices[loop2]*3] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+1] = (l_pFTKValues[l_pFTKTriangleListIndices[loop2]*3+1] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+2] = (l_pFTKValues[l_pFTKTriangleListIndices[loop2]*3+2] + 1.0f)/2.0f;
								l_pFTKPolynodesValue[l_lPolynodeCount*4+3] = 1.0f;
							}

							l_lPolynodeCount++;
						}
					}

					ClusterProperty l_XSIClusterProp = l_XSIClusterPropBuilder.AddVertexColor(l_csEmpty, l_csNodeProperties);

					if (l_pAttribute->Name().GetLength() > 0)
					{
						CString l_PropName;
						l_PropName.PutAsciiString(l_pAttribute->Name().GetText());
						l_XSIClusterProp.PutName(l_PropName);
					}
	
					l_XSIClusterProp.SetValues( l_pFTKPolynodesValue, l_lPolynodeCount);

					l_pAttribute = l_pFTKMesh->XSIShape()->GetNextTangentList();
				}

				delete [] l_pFTKPolynodesValue;
			}
		}
	}

	return status;
}

wchar_t *CMeshClusterPropToXSI::GetClassID(){return L"CMeshClusterPropToXSI";}

