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	XSILogMessage ( wchar_t *in_szMessage, XSI::siSeverityType in_eSeverity )
{
	XSI::Application	app;


	app.LogMessage( in_szMessage, in_eSeverity ) ;


}
Example #3
0
	//-----------------------------------------------------------------------------
	ProgressManager::ProgressManager(size_t numberOfStages)
		:mNumberOfStages(numberOfStages), mProgress(0)
	{
		XSI::Application app;

		mProgressBar = app.GetUIToolkit().GetProgressBar();
		mProgressBar.PutMaximum(numberOfStages);
		mProgressBar.PutStep(1);
		mProgressBar.PutVisible(true);
		mProgressBar.PutCaption(L"Exporting");
	}
void	SMDImporter::CreateShapeClips()
{
	if ( !m_pVTA.GetUsed() )
		return;

	XSI::Application app;

	for (int v=0;v<m_pVTA.GetUsed();v++)
	{
		XSI::Geometry geo = m_pMesh.GetActivePrimitive().GetGeometry();
		XSI::MATH::CVector3Array positions( geo.GetPoints().GetPositionArray() );

		for (int i=0;i<m_pVTA[v].m_pVertices.GetUsed();i++)
		{
			VTAVertex* p = &m_pVTA[v].m_pVertices[i];

			positions[m_lVertexMap[p->m_iIndex]] = p->m_vPosition;
//			positions[p->m_iIndex]

		}
		
		geo.GetPoints().PutPositionArray(positions);

		XSI::CValueArray args(7);
		XSI::CValue retval;
		
		args[i++]= m_pMesh;
		args[i++]= L"FacialExpression";
		args[i++]= (long)XSI::siShapeObjectReferenceMode;
		args[i++]= (long)v;
		args[i++]= (long)0;
		args[i++]= (long)0;
		args[i++]= (long)XSI::siShapeContentPrimaryShape;
		
		app.ExecuteCommand( L"StoreShapeKey", args, retval );

	}

}
void	SMDImporter::CreateGeometry()
{

	if ( !m_pTriangles.GetUsed() )
		return;

	long t;

	XSI::MATH::CTransformation xfo;
	xfo.SetRotationFromXYZAnglesValues ( -1.570796, 0.0, 0.0 );

	for (t=0;t<m_pTriangles.GetUsed();t++)
	{
		for (int v=0;v<3;v++)
		{
			XSI::MATH::CVector3 vec = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, m_pTriangles[t]->m_pVertex[v].m_vPosition );
			
			long outindex;
			compress.AddVertex ( vec.GetX(), 
									vec.GetY(), 
									vec.GetZ(), 
									m_pTriangles[t]->m_pVertex[v].m_vUV.GetX(), 
									m_pTriangles[t]->m_pVertex[v].m_vUV.GetY(),
									&m_pTriangles[t]->m_pVertex[v],
									&outindex);

			m_lVertexMap.Extend(1);
			m_lVertexMap[m_lVertexMap.GetUsed()-1] = outindex;
		}
	}

	XSI::MATH::CVector3Array verts(compress.GetCount());
	long vindex = 0;
	long cnt  = compress.GetCount ();
	for (t=0;t<compress.GetCount ();t++)
	{
		uvvec vec;
		compress.GetVertex (t, &vec);
		verts[t] = XSI::MATH::CVector3 ( vec.x, vec.y, vec.z );
	}
	
	
	XSI::CLongArray indices((m_pTriangles.GetUsed() * 3) + m_pTriangles.GetUsed());

	long iindex = 0;
	

	char *l_szGlobalTexture = m_pTriangles[0]->m_szTexture;
	CSIBCArray<TriCluster>	ClusterList;
	
	for (t=0;t<m_pTriangles.GetUsed();t++)
	{
		
		XSI::MATH::CVector3 vec1 = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, m_pTriangles[t]->m_pVertex[0].m_vPosition );
		XSI::MATH::CVector3 vec2 = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, m_pTriangles[t]->m_pVertex[1].m_vPosition );
		XSI::MATH::CVector3 vec3 = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, m_pTriangles[t]->m_pVertex[2].m_vPosition );

		long i1 = compress.GetIndex ( vec1.GetX(), vec1.GetY(), vec1.GetZ(), m_pTriangles[t]->m_pVertex[0].m_vUV.GetX(), m_pTriangles[t]->m_pVertex[0].m_vUV.GetY());
		long i2 = compress.GetIndex ( vec2.GetX(), vec2.GetY(), vec2.GetZ(), m_pTriangles[t]->m_pVertex[1].m_vUV.GetX(), m_pTriangles[t]->m_pVertex[1].m_vUV.GetY());
		long i3 = compress.GetIndex ( vec3.GetX(), vec3.GetY(), vec3.GetZ(), m_pTriangles[t]->m_pVertex[2].m_vUV.GetX(), m_pTriangles[t]->m_pVertex[2].m_vUV.GetY());

		indices[iindex] = 3;
		indices[iindex+1] = i1;
		indices[iindex+2] = i2;
		indices[iindex+3] = i3;
		iindex += 4;

		if ( strcmp ( l_szGlobalTexture, m_pTriangles[t]->m_szTexture ))
		{
			//
			// found a local material
			//

			TriCluster* cls = NULL;

			for (int c=0;c<ClusterList.GetUsed();c++)
			{
				if ( !strcmp ( ClusterList[c].m_szName, m_pTriangles[t]->m_szTexture))
				{
					cls = &ClusterList[c];
					break;
				}

			}

			if ( cls == NULL )
			{
				ClusterList.Extend(1);
				strcpy ( ClusterList[ClusterList.GetUsed()-1].m_szName, m_pTriangles[t]->m_szTexture );
				cls = &ClusterList[ClusterList.GetUsed()-1];
			}

			cls->m_indices.Add ( t );

		}

	}

	char mname[1024];
	sprintf (mname, "mesh" );
	if ( m_pMeshNode )
	{
		sprintf (mname, FixName(m_pMeshNode->m_szName));
	}

	LPWSTR l_wszModelName;
	DSA2W(&l_wszModelName,mname);

	m_pModel.AddPolygonMesh ( verts, indices, l_wszModelName, m_pMesh );


	XSI::Application	app;
	XSI::CValueArray	args(4);
	XSI::CValue			outArg;
	XSI::CStatus		st;

	args[0] = XSI::CValue( XSI::CString(L"") );
	args[1] = XSI::CValue(false);
	args[0] = XSI::CValue(m_pMesh.GetRef());
	args[1] = XSI::CValue((long)XSI::siTxtUV);
	args[2] = XSI::CValue((long)XSI::siTxtDefaultSpherical);
	args[3] = XSI::CValue(XSI::CString(L"Texture_Support"));

	app.ExecuteCommand( L"CreateTextureSupport", args, outArg );

	XSI::CValueArray	moreargs(1);
	XSI::CValueArray	moreoutargs(3);
	moreargs[0] = m_pMesh.GetRef();
	app.ExecuteCommand(L"FreezeObj",moreargs, outArg);

	XSI::Material		l_matMaterial;
	st = m_pMesh.AddMaterial(L"Phong", true, L"CubeMat", l_matMaterial);
		
	XSI::OGLTexture		l_oglTexture(l_matMaterial.GetOGLTexture());

	XSI::CString		l_szFullNameDefaultOut	= l_oglTexture.GetFullName();
	int			l_nHeightDefaultOut		= l_oglTexture.GetHeight();
	int			l_nWidthDefaultOut		= l_oglTexture.GetWidth();

	

	// Now actually add a texture, so we can test it.
	args[0] = XSI::CValue( XSI::CString(L"Image") );
	args[1] = XSI::CValue(m_pMesh.GetRef());
	args[2] = XSI::CValue((short)1);
	args[3] = XSI::CValue(false);
	st = app.ExecuteCommand( L"BlendInPresets", args, outArg );

	
	//
	// create the texture and connect
	//
	
	XSI::CValueArray	clipargs(3);
	XSI::ImageClip2 l_pClip;
	
	char l_szTextureFullname[1024];
	sprintf ( l_szTextureFullname, "%s%s", m_szDirectory, m_pTriangles[0]->m_szTexture);
	char clipname[1024];
	_splitpath ( m_pTriangles[0]->m_szTexture, NULL, NULL, clipname, NULL );

	LPWSTR l_wszClipName;
	DSA2W(&l_wszClipName,l_szTextureFullname);

	LPWSTR l_wszClipName2;
	DSA2W(&l_wszClipName2,clipname);

	
	
	clipargs[0] = XSI::CValue( XSI::CString(l_wszClipName) );
	clipargs[1] = XSI::CValue( XSI::CString(l_wszClipName2) );
	clipargs[2] = XSI::CValue(l_pClip.GetRef());
	app.ExecuteCommand( L"SICreateImageClip", clipargs, outArg );
	
	XSI::CString		l_szMaterialName	= l_matMaterial.GetFullName(); 
	XSI::CString		l_szImageNode = l_szMaterialName + L".CubeMat.ambient_blend.Image.tex";
	XSI::CString		l_szFullclipname = L"Clips." +  XSI::CString(l_wszClipName2);
	
	XSI::CValueArray	clipargs2(2);
	clipargs2[0] = XSI::CValue( XSI::CString(l_szFullclipname) );
	clipargs2[1] = XSI::CValue( XSI::CString(l_szImageNode) );
	
	app.ExecuteCommand( L"SIConnectShaderToCnxPoint", clipargs2, outArg );

	//
	// Create all clusters
	//

	XSI::Geometry geom( m_pMesh.GetActivePrimitive().GetGeometry() );
	
	for (int b=0;b<ClusterList.GetUsed();b++)
	{
		TriCluster* cls = &ClusterList[b];
		
		
		sprintf ( l_szTextureFullname, "%s%s", m_szDirectory, cls->m_szName);
		_splitpath ( cls->m_szName, NULL, NULL, clipname, NULL );
		
		DSA2W(&l_wszClipName,l_szTextureFullname);
		DSA2W(&l_wszClipName2,clipname);
		
		XSI::CLongArray array;
		XSI::Cluster polyCluster ;
		geom.AddCluster( XSI::siPolygonCluster, l_wszClipName2, cls->m_indices, polyCluster ) ;
		
		st = polyCluster.AddMaterial(L"Phong", true, L"CubeMat", l_matMaterial);
		
		XSI::OGLTexture		l_oglTexture(l_matMaterial.GetOGLTexture());
	
		// Now actually add a texture, so we can test it.
		args[0] = XSI::CValue( XSI::CString(L"Image") );
		args[1] = XSI::CValue(polyCluster.GetRef());
		args[2] = XSI::CValue((short)1);
		args[3] = XSI::CValue(false);
		st = app.ExecuteCommand( L"BlendInPresets", args, outArg );
			

		
		
		
		clipargs[0] = XSI::CValue( XSI::CString(l_wszClipName) );
		clipargs[1] = XSI::CValue( XSI::CString(l_wszClipName2) );
		clipargs[2] = XSI::CValue(l_pClip.GetRef());
		app.ExecuteCommand( L"SICreateImageClip", clipargs, outArg );
		
		l_szMaterialName	= l_matMaterial.GetFullName(); 
		l_szImageNode = l_szMaterialName + L".CubeMat.ambient_blend.Image.tex";
		l_szFullclipname = L"Clips." +  XSI::CString(l_wszClipName2);
		
		clipargs2[0] = XSI::CValue( XSI::CString(l_szFullclipname) );
		clipargs2[1] = XSI::CValue( XSI::CString(l_szImageNode) );
		
		app.ExecuteCommand( L"SIConnectShaderToCnxPoint", clipargs2, outArg );
		
	}

	
	if ( m_pMesh.IsValid () )
	{
		XSI::Geometry geom( m_pMesh.GetActivePrimitive().GetGeometry() );
		XSI::PolygonMesh mesh(m_pMesh.GetActivePrimitive().GetGeometry());

		XSI::CPointRefArray Geompoints = geom.GetPoints();
		
				
		XSI::CTriangleRefArray triangles(geom.GetTriangles());
		XSI::ClusterProperty UVWProp(m_pMesh.GetMaterial().GetCurrentUV());
		
		if ( UVWProp.IsValid() )
		{

		XSI::CClusterPropertyElementArray clusterPropertyElements = UVWProp.GetElements();
		XSI::CDoubleArray elementArray = clusterPropertyElements.GetArray();
		
		long totalUvCount = elementArray.GetCount ();
		int cc=0;
		int uvc = 0;
		for (int c=0;c<m_pTriangles.GetUsed();c++)
		{
			long l_iNumVertex = indices[cc];
			
			cc++;
			for (int i=0;i<l_iNumVertex;i++)
			{
				long l_iID = indices[cc];
				cc++;
				
				uvvec vec;
				compress.GetVertex (l_iID, &vec);

				elementArray[ uvc * 3 ] = vec.u;
				
				elementArray[ (uvc * 3) + 1] = vec.v;
				elementArray[ (uvc * 3) + 2] = 0.0f;
				
				uvc++;
			}
			
			
			
		}


			clusterPropertyElements.PutArray(elementArray);
		}
	}

}
void SMDImporter::CreateAnimationSource()
{
	XSI::ActionSource actionSource;

	float animStart = 9999;
	float animEnd = -9999;

	XSI::CString animatedObjects;

	for (int c=0;c<m_pNodes.GetUsed();c++)
	{
		SMDNode* node = m_pNodes[c];

		if ( node->m_pKeys.GetUsed() > 1 )
		{
			if ( !actionSource.IsValid() )
			{
				LPWSTR l_wszActionName;
				DSA2W(&l_wszActionName,m_szActionName);

				actionSource = m_pModel.AddActionSource( l_wszActionName );
			}

			XSI::Parameter x = node->m_x3d.GetParameters().GetItem( L"posx" );
			XSI::Parameter y = node->m_x3d.GetParameters().GetItem( L"posy" );
			XSI::Parameter z = node->m_x3d.GetParameters().GetItem( L"posz" );

			XSI::Parameter rx = node->m_x3d.GetParameters().GetItem( L"rotx" );
			XSI::Parameter ry = node->m_x3d.GetParameters().GetItem( L"roty" );
			XSI::Parameter rz = node->m_x3d.GetParameters().GetItem( L"rotz" );

			node->m_fOldX = x.GetValue();
			node->m_fOldY = y.GetValue();
			node->m_fOldZ = z.GetValue();
			node->m_fOldRX = rx.GetValue();
			node->m_fOldRY = ry.GetValue();
			node->m_fOldRZ = rz.GetValue();


			XSI::FCurve fcrvx;
			x.AddFCurve( XSI::siStandardFCurve, fcrvx	);
			XSI::FCurve fcrvy;
			y.AddFCurve( XSI::siStandardFCurve, fcrvy	);
			XSI::FCurve fcrvz;
			z.AddFCurve( XSI::siStandardFCurve, fcrvz	);
			XSI::FCurve fcrvrx;
			rx.AddFCurve( XSI::siStandardFCurve, fcrvrx	);
			XSI::FCurve fcrvry;
			ry.AddFCurve( XSI::siStandardFCurve, fcrvry	);
			XSI::FCurve fcrvrz;
			rz.AddFCurve( XSI::siStandardFCurve, fcrvrz	);
			
			XSI::CTimeArray time(node->m_pKeys.GetUsed());
			XSI::CValueArray xv(node->m_pKeys.GetUsed());
			XSI::CValueArray yv(node->m_pKeys.GetUsed());
			XSI::CValueArray zv(node->m_pKeys.GetUsed());
			
			XSI::CValueArray rxv(node->m_pKeys.GetUsed());
			XSI::CValueArray ryv(node->m_pKeys.GetUsed());
			XSI::CValueArray rzv(node->m_pKeys.GetUsed());
	
			if ( node->m_pParent ==NULL )
			{
				for (int k=0;k<node->m_pKeys.GetUsed();k++)
				{
				
					if ( node->GetKey(k)->m_fTime < animStart )
					{
						animStart = node->GetKey(k)->m_fTime;
					}

					if ( node->GetKey(k)->m_fTime > animEnd )
					{
						animEnd = node->GetKey(k)->m_fTime;
					}

					XSI::MATH::CTransformation xfo1;
					XSI::MATH::CTransformation xfo2;
					
					xfo1.SetRotationFromXYZAnglesValues ( node->GetKey(k)->m_vRotation.GetX(), node->GetKey(k)->m_vRotation.GetY(), node->GetKey(k)->m_vRotation.GetZ() );
					xfo1.SetTranslationFromValues ( node->GetKey(k)->m_vPosition.GetX(), node->GetKey(k)->m_vPosition.GetY(), node->GetKey(k)->m_vPosition.GetZ() );

					xfo2.SetRotationFromXYZAnglesValues ( -1.570796, 0.0, 0.0 );
					xfo1.MulInPlace(xfo2);

					double dx,dy,dz;
					double drx, dry, drz;

					xfo1.GetTranslationValues ( dx, dy, dz);
					xfo1.GetRotationFromXYZAnglesValues(drx, dry, drz);

					time[k] = k;
					xv[k] = dx;
					yv[k] = dy;
					zv[k] = dz;
					
					rxv[k] = drx * 57.29577951308232286465;
					ryv[k] = dry * 57.29577951308232286465;
					rzv[k] = drz * 57.29577951308232286465;

				}
				
			} else {
				
				for (int k=0;k<node->m_pKeys.GetUsed();k++)
				{
					
					if ( node->GetKey(k)->m_fTime < animStart )
					{
						animStart = node->GetKey(k)->m_fTime;
					}

					if ( node->GetKey(k)->m_fTime > animEnd )
					{
						animEnd = node->GetKey(k)->m_fTime;
					}

					time[k] = k;
					xv[k] = node->GetKey(k)->m_vPosition.GetX();
					yv[k] = node->GetKey(k)->m_vPosition.GetY();
					zv[k] = node->GetKey(k)->m_vPosition.GetZ();
					
					rxv[k] = node->GetKey(k)->m_vRotation.GetX() * 57.29577951308232286465;
					ryv[k] = node->GetKey(k)->m_vRotation.GetY() * 57.29577951308232286465;
					rzv[k] = node->GetKey(k)->m_vRotation.GetZ() * 57.29577951308232286465;
				}
			}

			fcrvx.SetKeys ( time, xv );
			fcrvy.SetKeys ( time, yv );
			fcrvz.SetKeys ( time, zv );

			fcrvrx.SetKeys ( time, rxv );
			fcrvry.SetKeys ( time, ryv );
			fcrvrz.SetKeys ( time, rzv );

			LPWSTR l_wszModelName;
			DSA2W(&l_wszModelName,FixName(node->m_szName));
			XSI::CString cname = l_wszModelName;

			actionSource.AddSourceItem ( cname + L".kine.local.posx", fcrvx, true ); 
			actionSource.AddSourceItem ( cname + L".kine.local.posy", fcrvy, true );
			actionSource.AddSourceItem ( cname + L".kine.local.posz", fcrvz, true );

			actionSource.AddSourceItem ( cname + L".kine.local.rotx", fcrvrx, true ); 
			actionSource.AddSourceItem ( cname + L".kine.local.roty", fcrvry, true );
			actionSource.AddSourceItem ( cname + L".kine.local.rotz", fcrvrz, true );
		
			// build up the string list of objects that we want to remove animation from
			if (animatedObjects.IsEmpty() == false) {
				animatedObjects += L", ";
			}
			animatedObjects += node->m_x3d.GetFullName();
		}
	}

	if ( actionSource.IsValid() )
	{
		actionSource.PutParameterValue(L"FrameStart", (double)animStart);
		actionSource.PutParameterValue(L"FrameEnd", (double)animEnd);
	}

	// remove animation on all objects that were imported
	// and animated
	if (animatedObjects.IsEmpty() == false) {
		XSI::Application app;
		XSI::CValue out;
		XSI::CValueArray args(4);

		args[0] = animatedObjects;
		args[1] = XSI::CValue();
		args[2] = (long)XSI::siBranch;
		args[3] = (long)(XSI::siFCurveSource);
		app.ExecuteCommand(L"RemoveAllAnimation", args, out);
	}
}
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;
}