DWORD MeshParameterization::OnGenerateAtlas( DWORD size, void * params )
{
	VERIFY_MESSAGE_SIZE( size, sizeof( GENERATEATLASMESSAGE ) );
	GENERATEATLASMESSAGE * msg = (GENERATEATLASMESSAGE*)params;
	if( !msg )
	{
		return MSG_ERROR;
	}
	bool bUseIncomingTexCoords = msg->useIncomingTexCoords;
	GenerateBounds();
	HRESULT hr;
	//This should be changed to use a new mesh parameterization technique
	DWORD numFaces = (DWORD)m_Faces->size();
	DWORD numVertices = (DWORD)m_CollapsedMesh->size();
	DWORD curError = 0;
	if( !bUseIncomingTexCoords &&
		numFaces > 0 &&
		numVertices > 0 )
	{
		DWORD fvf = D3DFVF_XYZ |  D3DFVF_NORMAL | D3DFVF_TEX1 ;
		DWORD flags =  D3DXMESH_SYSTEMMEM ;//  | D3DXMESH_MANAGED ;// | D3DXMESH_SOFTWAREPROCESSING | D3DXMESH_SYSTEMMEM |;
		
		LPD3DXMESH mesh = NULL;
		hr = D3DXCreateMeshFVF( numFaces, numVertices, flags, fvf, m_pDevice, &mesh );
		if( FAILED( hr ) )
		{
			curError = GetLastError();
			EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in create mesh fvf\n"));
			return MSG_ERROR;
		}
		//now fill with data
		BYTE * vertexData;
		BYTE * indexData;
		hr = mesh->LockVertexBuffer( 0, (LPVOID*)&vertexData );
		hr = mesh->LockIndexBuffer( 0, (LPVOID*)&indexData );
		D3DVERTEXELEMENT9 Decl[ MAX_FVF_DECL_SIZE ];
		mesh->GetDeclaration( Decl );
		
		paramVertex * pVertOriginal = (paramVertex*)vertexData;
		for( int i = 0; i < (int)numVertices; i++ )
		{
			paramVertex * pVert = (paramVertex*)vertexData;
			pVert->x = (*m_CollapsedMesh)[i].originalPosition.x;
			pVert->y = (*m_CollapsedMesh)[i].originalPosition.y;
			pVert->z = (*m_CollapsedMesh)[i].originalPosition.z;
			pVert->nx = -(*m_CollapsedMesh)[i].normal.x;
			pVert->ny = -(*m_CollapsedMesh)[i].normal.y;
			pVert->nz = -(*m_CollapsedMesh)[i].normal.z;
			pVert->u = (*m_CollapsedMesh)[i].generatedU;
			pVert->v = (*m_CollapsedMesh)[i].generatedV;
			NormalizeUV( pVert->u );
			NormalizeUV( pVert->v );

			vertexData += sizeof( paramVertex );
		}
		for( int i = 0; i < (int)numFaces; i++ )
		{
			unsigned short * index = (unsigned short*)indexData;
			index[0] = ( unsigned short )(*m_Faces)[ i ].index[ 0 ];
			index[1] = ( unsigned short )(*m_Faces)[ i ].index[ 1 ];
			index[2] = ( unsigned short )(*m_Faces)[ i ].index[ 2 ];
			indexData += sizeof( unsigned short )*3;//32 bit indices triangles
		}

		LPD3DXBUFFER imt;
		hr = D3DXComputeIMTFromPerVertexSignal( mesh, (const float*)pVertOriginal + 3*sizeof(float), 3, sizeof(paramVertex),
											0L, 0, 0, &imt );		
		mesh->UnlockIndexBuffer();
		mesh->UnlockVertexBuffer();
		//tensors
   		float * tensors = new float[ 3*numFaces ];
   		for( int i = 0; i < 3*(int)numFaces; i += 3 )
   		{
   			tensors[ i ] = 4.f;
   			tensors[ i + 1 ] = 0.f;
   			tensors[ i + 2 ] = 4.f;
   		}
		
		//some checks 
		numVertices = mesh->GetNumVertices();
		numFaces = mesh->GetNumFaces();

		//create adjacency
		DWORD * adjacency = new DWORD[	3*numFaces ];
		memset( adjacency, 0, sizeof(DWORD)*3*numFaces );
		hr = mesh->GenerateAdjacency( 0.001f, adjacency );
		//hr = mesh->ConvertPointRepsToAdjacency( NULL, adjacency );
		if( FAILED( hr ) )
		{
			curError = GetLastError();
			EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in generate adjacency\n"));
			return MSG_ERROR;
		}
		/* save to mesh to check model uvs
		D3DXMATERIAL mat;
		mat.MatD3D.Ambient.r = mat.MatD3D.Ambient.a =mat.MatD3D.Ambient.b =mat.MatD3D.Ambient.g = 0;
		mat.MatD3D.Diffuse.r = mat.MatD3D.Diffuse.a =mat.MatD3D.Diffuse.b =mat.MatD3D.Diffuse.g = 1;
		mat.pTextureFilename = "tex.dds";
		D3DXSaveMeshToX( "mesh.x", mesh, adjacency, &mat, NULL, 0, D3DXF_FILEFORMAT_TEXT );
		*/

		float * imtTensor = tensors;//(float*)imt->GetBufferPointer();

		float stretchout;
		unsigned int charts;
		LPD3DXMESH meshOut = NULL;
		LPD3DXBUFFER remappedData = NULL;
		LPD3DXBUFFER faceData = NULL;

		D3DXATTRIBUTERANGE Attrib;
		memset(&Attrib, 0, sizeof(D3DXATTRIBUTERANGE));
		Attrib.FaceCount = numFaces;
		Attrib.VertexCount = numVertices;
		mesh->SetAttributeTable(&Attrib, 1);
		int gutter = m_TexSize / 32;
		gutter = min( gutter, 6 );
		hr = D3DXUVAtlasCreate( mesh, 0, .5, m_TexSize, m_TexSize, 
								6, //gutter
								0, adjacency, 0,
								imtTensor, (LPD3DXUVATLASCB)UVGenCallback, .0001f, 0,
								//D3DXUVATLAS_GEODESIC_QUALITY ,
								D3DXUVATLAS_GEODESIC_FAST,
								&meshOut, &faceData, &remappedData, 
								&stretchout, &charts );
		if( FAILED( hr ) )
		{
			curError = GetLastError();
			EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in uv atlas create\n"));
			return MSG_ERROR;
		}
		/* save to mesh to check model uvs
		hr = meshOut->ConvertPointRepsToAdjacency( NULL, adjacency );
		D3DXSaveMeshToX( "mesh2.x", meshOut, adjacency, &mat, NULL, 0, D3DXF_FILEFORMAT_TEXT );
		*/
		delete [] adjacency;
		delete [] tensors;

		//Generate our lightmap cache data for passing on and saving
		GenerateCache( meshOut, remappedData );
		GenerateTriangleTexelData();
		
		meshOut->Release();
		faceData->Release();
		remappedData->Release();
		mesh->Release();
	}    
	else 
	if( bUseIncomingTexCoords )
	{
		GenerateCache();
		GenerateTriangleTexelData();
	}
	return MSG_HANDLED_STOP;
}