void	SMDImporter::DetectModel()
{
	XSI::Application app;

	m_pModel = app.GetActiveSceneRoot();

	for (int c=0;c<m_pNodes.GetUsed();c++)
	{
		if ( !m_pNodes[c]->m_pChildren.GetUsed() )
			continue;

		char name[MAX_PATH];
		memset ( name,0,MAX_PATH);
		strcpy ( name, m_pNodes[c]->m_szName );
		char * subname = strchr ( name, '.' );
		if ( subname )
		{
			subname[0] =0;
			subname++;

			LPWSTR l_wszModelName;
			DSA2W(&l_wszModelName,name);

			XSI::CRefArray models = m_pModel.GetModels(false);
			for (int m=0;m<models.GetCount();m++)
			{
				XSI::Model mm = models[m];

				XSI::CString l_szName =l_wszModelName;

				if ( l_szName == mm.GetName() )
				{
					m_pModel = mm;
					return;

				}

			}

			//
			// Create the model
			//

			XSI::Model rootModel;
			XSI::CRefArray nullList;
			

			m_pModel.AddModel(nullList, l_wszModelName, rootModel);

			m_pModel = rootModel;

			m_pModel.AddMixer();
			
			break;

		}
	}

}
void getAnimations(XSI::Model& root, Ogre::AnimationList& animList)
{
	animList.clear();

	findAnimations(root, animList);

	// Find all children (recursively)
	XSI::CRefArray children = root.FindChildren(L"", siModelType, XSI::CStringArray());
	for (int c = 0; c < children.GetCount(); ++c)
	{
		XSI::Model child(children[c]);
		findAnimations(child, animList);
	}

	// Now iterate over the list and eliminate overlapping elements
	for (Ogre::AnimationList::iterator i = animList.begin();
		i != animList.end(); ++i)
	{
		Ogre::AnimationList::iterator j = i;
		++j;
		for (; j != animList.end();)
		{
			bool remove = false;
			if (j->startFrame <= i->endFrame && j->endFrame >= i->startFrame)
			{
				// Merge this one into i, extend boundaries
				remove = true;
				i->startFrame = std::min(j->startFrame, i->startFrame);
				i->endFrame = std::max(j->endFrame, i->endFrame);
			}
			if (remove)
			{
				j = animList.erase(j);
			}
			else
			{
				++j;
			}
		}
	}


}
XSI::Null DoesObjectExist ( XSI::X3DObject in_pModel, XSI::CString in_szName )
{
	XSI::Null theNull;

	XSI::CStringArray emptyArray;
	XSI::CRefArray cRefArray = in_pModel.FindChildren( L"", L"", emptyArray, true );

	XSI::CStringArray nameArray(cRefArray.GetCount());
	for ( long i=0; i < cRefArray.GetCount(); i++ )
	{
		if ( in_szName == XSI::SIObject(cRefArray[i]).GetName() )
		{
			theNull = cRefArray[i];
			break;
		}
	}

	return theNull;

}
SI_Error SMDEnvelope::Write ( FILE* l_fptr, int rigid, SMDNodeList* in_pNodeList )
{

	CSIBCVector3D*	l_pPosition = NULL;
	CSIBCVector3D*	l_pNormal = NULL;
	CSIBCVector2D*	l_pUV = NULL;
	
	XSI::Primitive l_pPrim = m_pModel.GetActivePrimitive();
	
	if ( !l_pPrim.IsValid() )
		return SI_ERR_ERROR_MSG;

	XSI::Application app;

	XSI::UIToolkit kit = app.GetUIToolkit();
	XSI::ProgressBar	m_pBar = kit.GetProgressBar();
	
	m_pBar.PutMaximum( 100 );
	m_pBar.PutMinimum( 1 );
	m_pBar.PutStep( 1 );
	m_pBar.PutValue( 1 );
	m_pBar.PutCaption( L"Writing vertex data..." );
	m_pBar.PutStatusText( L"" );
	m_pBar.PutVisible( true );

	//
	// Get default texture name
	//

	char l_szDefaultTextureName[MAX_PATH];
	XSI::OGLTexture l_pDefaultTexture = m_pModel.GetMaterial().GetOGLTexture();

	if ( !l_pDefaultTexture.IsValid() )
	{
		XSILogMessage ( "Material on enveloped mesh has no texture!", XSI::siErrorMsg );
		sprintf ( l_szDefaultTextureName, "default.tga" );
	} else {

		W2AHelper2 ( l_szDefaultTextureName, l_pDefaultTexture.GetFullName().GetWideString() );
		
		char l_szTextureFile[MAX_PATH];
		char l_szTextureExt[MAX_PATH];
		
		_splitpath ( l_szDefaultTextureName, NULL, NULL, l_szTextureFile, l_szTextureExt );
		sprintf ( l_szDefaultTextureName, "%s%s",  l_szTextureFile, l_szTextureExt );
	}

	XSI::Geometry l_pGeo = l_pPrim.GetGeometry();
	XSI::CPointRefArray l_pPoints = l_pGeo.GetPoints();
	XSI::PolygonMesh l_pPolyMesh = l_pGeo;

	XSI::CPointRefArray pointRefArray(l_pPolyMesh.GetPoints());
	XSI::MATH::CVector3Array  positionArray(pointRefArray.GetPositionArray());
	XSI::CPolygonNodeRefArray nodeRefArray(l_pPolyMesh.GetNodes());
	XSI::MATH::CVector3Array  normalArray(nodeRefArray.GetNormalArray());

	//Take care of the UV's
	XSI::CRefArray		clusterRefArray;
	l_pPolyMesh.GetClusters().Filter(XSI::siSampledPointCluster,XSI::CStringArray(),L"",clusterRefArray);

	XSI::Cluster			samplePointClusterUV;
	XSI::CRefArray       uvClusterPropertiesRefArray;
	
	int i;
	for(i=0;i < clusterRefArray.GetCount(); i++)
	{
		XSI::Cluster cluster(clusterRefArray[i]);		
		if(cluster.GetProperties().Filter(XSI::siClsUVSpaceTxtType,XSI::CStringArray(), L"",uvClusterPropertiesRefArray) == XSI::CStatus::OK)
		{
			samplePointClusterUV = cluster;			
			break;
		}
	}

	XSI::ClusterProperty uvProp(uvClusterPropertiesRefArray[0]);
	XSI::CClusterPropertyElementArray uvElementArray = uvProp.GetElements();
	XSI::CDoubleArray uvValueArray = uvElementArray.GetArray();
	long lnbUV= (long)(uvValueArray.GetCount() / 3);

	//
	// Make sure that UVs are present
	//

	if ( !samplePointClusterUV.IsValid() )
	{
		XSILogMessage ( "Invalid .SMD: Enveloped mesh doesn't have any UVs.", XSI::siErrorMsg );

		return SI_ERR_ERROR_MSG;
	}

	m_pBar.PutCaption( L"Analyzing clusters..." );
	m_pBar.PutStatusText( L"" );
	m_pBar.PutVisible( true );


	SMDNode* in_pNode = in_pNodeList->GetByName ( m_pModel.GetFullName() );
	CSIBCArray < CSIBCVector3D >	l_pVertexNormals;
	ComputeVertexNormals ( l_pVertexNormals, l_pGeo );

	XSI::CRefArray		allClusters;
	l_pPolyMesh.GetClusters().Filter(L"poly",XSI::CStringArray(),L"",allClusters);

	CSIBCArray<MateriaList>	matList;
	
	for (int c=0;c<allClusters.GetCount();c++)
	{
		XSI::Cluster Thecluster = allClusters[c];
		XSI::Material l_pMat = Thecluster.GetMaterial();
		XSI::OGLTexture l_pTexture = l_pMat.GetOGLTexture();
		matList.Extend(1);

		if ( !l_pTexture.IsValid() )
		{
			char mess[1024];
			sprintf ( mess, "Cluster #%d has no texture! Bypassing.", c);
			XSILogMessage ( mess, XSI::siErrorMsg );
			continue;
		}

		W2AHelper2 ( matList[matList.GetUsed()-1].texture, l_pTexture.GetFullName().GetWideString() );

		char l_szTextureFile[MAX_PATH];
		char l_szTextureExt[MAX_PATH];

		_splitpath ( matList[matList.GetUsed()-1].texture, NULL, NULL, l_szTextureFile, l_szTextureExt );
		sprintf ( matList[matList.GetUsed()-1].texture, "%s%s",  l_szTextureFile, l_szTextureExt );


		XSI::CClusterElementArray clusterElementArray = Thecluster.GetElements();
		XSI::CLongArray values(clusterElementArray.GetArray());
		long countPolyIndices = values.GetCount();
		matList[matList.GetUsed()-1].polyIndices.Extend(countPolyIndices);
		for (int v=0;v<countPolyIndices;v++)
		{
			matList[matList.GetUsed()-1].polyIndices[v] = values[v];
		}
	}

	XSI::CTriangleRefArray tris = l_pPolyMesh.GetTriangles();

	
	m_pBar.PutCaption( L"Processing geometry..." );
	m_pBar.PutStatusText( L"" );
	m_pBar.PutVisible( true );

	long progress_value = 0;
	long last_progress_value = 0;

		int vindex = 0;
		int vii = 0;

		for (int v=0;v<tris.GetCount();v++)
		{
			progress_value = (long)(((float)v / (float)tris.GetCount()) * 100.0f);

			if ( progress_value != last_progress_value )
			{
				last_progress_value = progress_value;
				m_pBar.PutValue ( progress_value );
				
				if ( m_pBar.IsCancelPressed() )
				{
					if ( MessageBox ( NULL, "Cancelling the export will create a corrupted SMD file.\n\n Are you sure?", "Cancel Export", MB_YESNO|MB_ICONWARNING ) == IDYES )
					{
						break;
					} else {

						m_pBar.PutVisible( true );
					}

				}

			}
			
			XSI::Triangle tri = tris[v];

			char* textureName = l_szDefaultTextureName;

			long polyI = tri.GetPolygonIndex();

			for (int p=0;p<matList.GetUsed();p++)
			{
				bool found = false;

				for (int h=0;h<matList[p].polyIndices.GetUsed();h++)
				{
					if ( matList[p].polyIndices[h] == polyI )
					{
						textureName = matList[p].texture;
						found = true;
						break;
					}

				}

				if ( found )
					break;
			}


			for (int i=0;i<3;i++)
			{
				//
				// Build a vertex
				//

				CSIBCVector3D	l_vPosition = CSIBCVector3D( (float)tri.GetPositionArray()[i].GetX(), 
																(float)tri.GetPositionArray()[i].GetY(), 
																(float)tri.GetPositionArray()[i].GetZ() );

				XSI::CTriangleVertexRefArray vRef = tri.GetPoints();
				XSI::TriangleVertex l_vTriangleVertex = vRef[i];
				

				CSIBCVector3D	l_vNormal = CSIBCVector3D ( (float)l_vTriangleVertex.GetNormal().GetX(),
															(float)l_vTriangleVertex.GetNormal().GetY(),
															(float)l_vTriangleVertex.GetNormal().GetZ() );

				//if ( SMDType == 1 )
				//{
				//	l_vNormal	= l_pVertexNormals [ l_pVertexList[vii] ];
				//} 

				if (( SMDType == 0 ) || ( SMDType == 1 ))
				{
					CSIBCMatrix4x4 l_pResult = in_pNode->GetMatrix();

					l_pResult.Multiply ( l_vPosition, l_vPosition );
					l_pResult.Multiply ( l_vNormal, l_vNormal );
					l_vNormal = l_vNormal.Normalize();
					
				}

				XSI::CTriangleVertexRefArray l_TriRef = tri.GetPoints();
				XSI::CUVArray l_vuvArray = l_TriRef.GetUVArray();
				XSI::CUV l_uv = l_vuvArray[i];
				int c = l_vuvArray.GetCount();
				long vertexIndex = tri.GetIndexArray()[i];

				CSIBCVector2D	l_vUV;
				l_vUV.m_fX = (float)l_uv.u;
				l_vUV.m_fY = (float)l_uv.v;

				//
				// Build weight list
				//

				SMDVertex*	l_pWeights = m_pVertexList[vertexIndex];

				// not sure the line above works correclty, if not, uncomment
				// the code below
				//for (int w=0;w<m_pVertexList.GetUsed();w++)
				//{
				//	if ( m_pVertexList[w]->GetIndex() == vertexIndex )
				//	{
				//		l_pWeights = m_pVertexList[w];
				//		break;
				//		
				//	}

				//}

				vii++;
				
				//
				// Now output
				//

			
			//	XSI::OGLTexture l_pTexture = useMat.GetOGLTexture();

				if ( vindex == 0 )
				{
					fprintf ( l_fptr, "%s\n", textureName );
				}

				if ( !rigid )
				{
					CSIBCString l_szWeight;
					l_szWeight.Concat ( l_pWeights->GetNumWeights() );
					l_szWeight.Concat (" ");
					for (int f=0;f<l_pWeights->GetNumWeights();f++)
					{
						l_szWeight.Concat ( l_pWeights->GetWeight(f)->m_iBoneID );
						l_szWeight.Concat (" ");
						l_szWeight.Concat ( l_pWeights->GetWeight(f)->m_fWeight );
						l_szWeight.Concat (" ");
					}

					fprintf ( l_fptr, 
								"0 %f %f %f %f %f %f %f %f %s\n",
								l_vPosition.m_fX,
								l_vPosition.m_fY,
								l_vPosition.m_fZ,
								l_vNormal.m_fX,
								l_vNormal.m_fY,
								l_vNormal.m_fZ,
								l_vUV.m_fX,
								l_vUV.m_fY,
								l_szWeight.GetText());
				} else {

					fprintf ( l_fptr, 
								"%d %f %f %f %f %f %f %f %f \n",
								l_pWeights->GetWeight(0)->m_iBoneID,
								l_vPosition.m_fX,
								l_vPosition.m_fY,
								l_vPosition.m_fZ,
								l_vNormal.m_fX,
								l_vNormal.m_fY,
								l_vNormal.m_fZ,
								l_vUV.m_fX,
								l_vUV.m_fY
								);
				}



				vindex++;

				if ( vindex == 3 )
					vindex = 0;
			}

		}

		
	

	return SI_SUCCESS;
}