Example #1
0
bool CTriangleObj::saveMeshWavefrontObj(const char *fname, const double *matrix)
{
	int i;

	Vector3d *pVertex = new Vector3d[m_nVertexCount];
	assert(pVertex!=NULL);
	for (i=0; i<m_nVertexCount; i++)
		TransformVertex3dToVertex3d(m_pVertex[i], matrix, &pVertex[i].x);

	vector<OglMaterial> mats;

	std::string objname = GetObjectName();
	if (objname.empty()) objname+="defaultname";
	Vector3f *pNormal = m_pVertexNorm;
	if (pNormal==NULL){
		ComputeVertexNormals();
		pNormal = m_pVertexNorm;
		assert(pNormal!=NULL);
	}
	vector<Vector3f> texCoords;
	unsigned int faceMatIndex[2], nFaceMatIndex=0;
	const Vector3i *pTexIndex = NULL;

	const bool r = writeOBJFile(fname, objname,
		mats, 
		pVertex, m_nVertexCount,
		pNormal, m_nVertexCount, texCoords,
		(const Vector3i*)m_pPolygon, m_nPolygonCount, pTexIndex,
		faceMatIndex, nFaceMatIndex);

	delete [] pVertex;
	return r;
}
Example #2
0
Solid *ConstructHalfEdge_ModelFromOBJ_WStatus( char *FileName )
{
	struct _Model *m;
	FILE *file;
	Solid *s;
	int i;

	/* open the file */
	file = fopen(FileName, "r");
	if (!file) return NULL;

	/* load the OBJ, unitize it, compute facet normals, etc */
	m = (struct _Model *) malloc( sizeof( struct _Model ) );
	memset( m, 0, sizeof( struct _Model ) );
	m->file = strdup( FileName );
	ReadOBJFirstPass( m, file );
	rewind(file);
	ReadOBJSecondPass( m, file );
	Unitize_Model( m );
	ComputeFacetNormals( m );
	ComputeVertexNormals( m );
	fclose( file );
    
    s = SolidNew( );
	for (i=0; i< m->numVertices; i++)
		VertexConstructN( &s, m->vertexPos[3*i+0], m->vertexPos[3*i+1], m->vertexPos[3*i+2],
							  m->normList[3*i+0],  m->normList[3*i+1],  m->normList[3*i+2] );

	printf("    (-) Constructing faces (%8.4f%% done)...", 0.0f ); fflush( stdout );
	for (i=0; i< m->numTriangles; i++)
	{
		 Vertex *va = VertexListIndex( s, m->triVertexIndex[3*i+0] );
		 Vertex *vb = VertexListIndex( s, m->triVertexIndex[3*i+1] );
		 Vertex *vc = VertexListIndex( s, m->triVertexIndex[3*i+2] );
		 FaceConstruct( &s, va, vb, vc);
		 if (i%1000 == 0)
		 {
			printf("\r    (-) Constructing faces (%8.4f%% done)...", 100.0f*((float)i/m->numTriangles) ); 
			fflush( stdout );
		 }
	}
	printf("\r    (-) Constructing faces (%8.4f%% done)...\n", 100.0f ); fflush( stdout );

    EdgeListConstructVerbose(&s, m->numTriangles);

    return s;
}
Example #3
0
Solid *ConstructHalfEdge_ModelFromOBJ( char *FileName )
{
	struct _Model *m;
	FILE *file;
	Solid *s;
	int i;

	/* open the file */
	file = fopen(FileName, "r");
	if (!file) return NULL;

	/* load the OBJ, unitize it, compute facet normals, etc */
	m = (struct _Model *) malloc( sizeof( struct _Model ) );
	memset( m, 0, sizeof( struct _Model ) );
	m->file = strdup( FileName );
	ReadOBJFirstPass( m, file );
	rewind(file);
	ReadOBJSecondPass( m, file );
	Unitize_Model( m );
	ComputeFacetNormals( m );
	ComputeVertexNormals( m );
	fclose( file );
    
    s = SolidNew( );
	for (i=0; i< m->numVertices; i++)
		VertexConstructN( &s, m->vertexPos[3*i+0], m->vertexPos[3*i+1], m->vertexPos[3*i+2],
							  m->normList[3*i+0],  m->normList[3*i+1],  m->normList[3*i+2] );

	for (i=0; i< m->numTriangles; i++)
	{
		 Vertex *va = VertexListIndex( s, m->triVertexIndex[3*i+0] );
		 Vertex *vb = VertexListIndex( s, m->triVertexIndex[3*i+1] );
		 Vertex *vc = VertexListIndex( s, m->triVertexIndex[3*i+2] );
		 FaceConstruct( &s, va, vb, vc);
	}

    EdgeListConstruct(&s);

    return s;
}
Example #4
0
void RenderMesh::ConvertFaces(Mesh *Mesh, int MatIndex, Tab<Vert3> &Verts, Tab<Face3> &Faces, bool NegScale)
{
    Face3			TmpFace;
    Vert3			TmpVert;
	BitArray		Written;
	int				i,j,k,NumFace;
	int				NumUV,UVCount,Index;
	int				NumVert,Count,VIndex;
	Face			*aFace;
	Tab<BasisVert>	FNormals;
	Tab<VNormal>	Normals;
	UVVert			*UVVert;
	TVFace			*UVFace;
	Point3			S,T,SxT;
	unsigned long	Sg;

	bool useMeshNorms = false;


	if(NegScale)
	{
		gVIndex[0] = 2;
		gVIndex[1] = 1;
		gVIndex[2] = 0;
	}
	else
	{
		gVIndex[0] = 0;
		gVIndex[1] = 1;
		gVIndex[2] = 2;
	}

	// Do we have an EditNormal modifier present - if so we use those normals instead.
	// We only use this if they have been applied on a face with smoothing groups, otherwise
	// it messes up the tangent space calculation.  Probably not the most obtmized route, but it
	// works...

	MeshNormalSpec * meshNorm = Mesh->GetSpecifiedNormals();
	if(meshNorm && meshNorm->GetNumNormals())
		useMeshNorms = true;

	NumFace = 0;

	for(i=0; i < Mesh->getNumFaces(); i++) 
	{
		if(!Mesh->faces[i].Hidden())
		{
			Index = Mesh->getFaceMtlIndex(i) + 1;

			if(Index == MatIndex || MatIndex == 0)
			{
				NumFace++;
			}
		}

	}

	NumVert = Mesh->getNumVerts();
    Verts.SetCount(NumVert);

    Faces.SetCount(NumFace);

	if(NumVert == 0 || NumFace == 0)
	{
		return;
	}

	ComputeVertexNormals(Mesh,FNormals,Normals,NegScale);

    Written.SetSize(Mesh->getNumVerts());
    Written.ClearAll();

	NumUV = Mesh->getNumMaps();	

	if(NumUV)
	{	
		Count = 0;

		if(NumUV > MAX_TMUS + 1)
		{
			NumUV = MAX_TMUS + 1;
		}

		for(i=0; i < Mesh->getNumFaces(); i++) 
		{
			aFace = &Mesh->faces[i];

			TmpFace.m_Num[0] = aFace->v[gVIndex[0]];
			TmpFace.m_Num[1] = aFace->v[gVIndex[1]];
			TmpFace.m_Num[2] = aFace->v[gVIndex[2]];


			Sg = aFace->smGroup;

			for(j=0; j < 3; j++) 
			{
				VIndex			 = aFace->v[gVIndex[j]];
				TmpVert.m_Pos	 = Mesh->verts[VIndex];

				if(Sg)
				{
					if(useMeshNorms)
					{
						int normID = meshNorm->Face(i).GetNormalID(gVIndex[j]);
						TmpVert.m_Normal = meshNorm->Normal(normID).Normalize();
						Normals[VIndex].GetNormal(Sg,S,T,SxT);
					}
					else
					        TmpVert.m_Normal = Normals[VIndex].GetNormal(Sg,S,T,SxT);
					
					TmpVert.m_S		 = S;
					TmpVert.m_T		 = T;
					TmpVert.m_SxT	 = SxT;

				}
				else
				{
					TmpVert.m_Normal = FNormals[i].m_Normal;
					TmpVert.m_S		 = FNormals[i].m_S;
					TmpVert.m_T		 = FNormals[i].m_T;
					TmpVert.m_SxT	 = FNormals[i].m_SxT;
				}

				UVCount		 = 0;
				TmpVert.m_Sg = Sg;

				for(k=0;k<m_MapChannels.Count();k++)
				{	
					int index = m_MapChannels[k];

					if(Mesh->getNumMapVerts(index))
					{
						UVVert = Mesh->mapVerts(index);
						UVFace = Mesh->mapFaces(index);

						TmpVert.m_UV[k].x = UVVert[UVFace[i].t[gVIndex[j]]].x;
						TmpVert.m_UV[k].y = UVVert[UVFace[i].t[gVIndex[j]]].y;

	
					}
					else
					{
						TmpVert.m_UV[k].x = 0.0f;
						TmpVert.m_UV[k].y = 0.0f;
					}
				}
				
		
				if(Written[VIndex]) 
				{
					if((Sg == 0) || 
					   (Verts[VIndex].m_Sg != TmpVert.m_Sg) ||	
					   (!UVVertEqual(Verts[VIndex].m_UV[0],TmpVert.m_UV[0]))) 
					{
						TmpFace.m_Num[j] = Verts.Count();
						Verts.Append(1,&TmpVert,10);
					}
				} 
				else 
				{
					Verts[VIndex] = TmpVert;
					Written.Set(VIndex);
				}

			}

			if(!Mesh->faces[i].Hidden())
			{
				Index = Mesh->getFaceMtlIndex(i) + 1;

				if(Index == MatIndex || MatIndex == 0)
				{
					Faces[Count++] = TmpFace;
				}

			}

		}

	}
	else
	{
		for(i=0; i < Mesh->getNumFaces(); i++) 
		{
			aFace = &Mesh->faces[i];

			Faces[i].m_Num[0] = aFace->v[gVIndex[0]];
			Faces[i].m_Num[1] = aFace->v[gVIndex[1]];
			Faces[i].m_Num[2] = aFace->v[gVIndex[2]];

			for(j=0; j < 3; j++) 
			{
				VIndex					= aFace->v[gVIndex[j]];
				Verts[VIndex].m_Pos		= Mesh->verts[VIndex];
				Verts[VIndex].m_Normal	= Normals[VIndex].GetNormal(aFace->smGroup,S,T,SxT);
				Verts[VIndex].m_S		= Point3(0.0f,0.0f,0.0f);
				Verts[VIndex].m_T		= Point3(0.0f,0.0f,0.0f);
				Verts[VIndex].m_SxT		= Point3(0.0f,0.0f,0.0f);

				for(k=0; k < MAX_TMUS; k++)
				{
					Verts[VIndex].m_UV[k].x = 0.0f;
					Verts[VIndex].m_UV[k].y = 0.0f;
				}

			}

		}

	}
	Verts.Shrink();
	

}
//--
//
// Analysis
//
//--
bool MultiresolutionMesh::Analysis(int)
{
	//
	// HSI
	//
	#ifdef _HSI_COLOR_
		std::vector<Vector3d> color_backup;
		if( ColorNumber() == VertexNumber() )
		{
			color_backup = colors;
			Vector3d tmp_hsi;
			for( int i=0; i<ColorNumber(); i++ )
			{
				Rgb2Hsi( Color(i), tmp_hsi );
				Color(i) = tmp_hsi;
			}
		}
	#endif


	//
	// RGB 2 Grayscale
	//
	#ifdef _RGB_2_GRAYSCALE_
		std::vector<Vector3d> color_backup;
		if( ColorNumber() == VertexNumber() ) {
			color_backup = colors;
			double tmp;
			for( int i=0; i<ColorNumber(); i++ ) {
				tmp = (Color(i)[0]+Color(i)[1]+Color(i)[2])/3.0;
				Color(i) = tmp;
			}
		}
	#endif
	

	// Initialize member variables
	current_level_number = -1;
	levels.clear();
	mean_curvature.clear();
	gaussian_curvature.clear();
	texture.Reset();
	vertex_map.clear();
	edge_list.clear();

	// Initialize normals
	ComputeFaceNormals();
	ComputeVertexNormals();

	// Initialize progressive decomposition
	BeginProgressiveDecomposition();
	

	// Initialize curvatures
//	mean_curvature.resize( VertexNumber() );
//	gaussian_curvature.resize( VertexNumber() );
//	ComputeMeanCurvature();
//	ComputeGaussianCurvature();

	// Initialize texture
	if( (TextureNumber()!=0) && (TextureName().empty()==false) ) {
		use_texture = texture.ReadFile( TextureName() );
	}
	else {
		use_texture = false;
	}

	if( ColorNumber() == VertexNumber() ) {
		use_color = true;
	}
	else {
		use_color = false;
	}

	use_normal = true;

//	permutation.assign(VertexNumber(), -1);
//	map.assign( VertexNumber(), -1);

	// Initialize vertex map
	// This table indicates on which vertex each vertex has collapsed to
	vertex_map.resize( VertexNumber() );
	for( int i=0; i<VertexNumber(); i++ ) {
		vertex_map[i] = i;
	}

//	std::cout<<bounding_box.Center()<<std::endl;
//	for( int i=0; i<VertexNumber(); i++ ) {
//		if( 
//			Vertex(i)[0]>-0.01 &&
//			Vertex(i)[2]>-0.01 &&
//			Vertex(i)[0]<0.01 &&
//			Vertex(i)[2]<0.01
//		)
//			std::cout<<i<<" "<<Vertex(i)<<std::endl;
//	}


	ConstPairContractionIterator itp;
	ConstNeighborIterator itn;
	std::vector<bool> locked_vertices(VertexNumber(), false);
//	levels.resize( base_level );
	current_level_number = 0;

	//-- Test --
	//int vnum = VertexNumber();
	//timer.Reset();
	//timer.Start();
	//test<<current_level_number<<'\t'<<vnum<<endl;
	//--

	#ifdef _OUTPUT_LEVELS_
		// Write the finest level statistics
		std::ofstream level_stats_file("levels.log");
		level_stats_file<<current_level_number<<'\t'<<ValidVertexNumber()<<'\t'<<ValidFaceNumber()<<std::endl;
		// Write the finest level mesh (the initial mesh)
		char filename[255];
		sprintf(filename,"level%02d.wrl",current_level_number);
		WriteFile(filename);
	#endif


	//
	// Create the levels of details
	//
	while( 1 ) {

		// Add a new level
		levels.push_back( ResolutionLevel() );

		//
		// Select the odd vertices
		// Remove the odd vertices
		// Lock the neighbors
		// Odd vertices are a set of independent vertices selected to be removed
		// The remaining (even) vertices compose the next coarse level
		//
		while( !pair_contractions.empty() ) {

			#ifdef _TEST_PLAN_
				// Lock one predefined vertex
				locked_vertices[1844] = true; // plan-20000
			//	locked_vertices[30670] = true; // plan-irregulier
			#endif

			// Get pair contraction with minimum cost
			PairContraction pair = MinimumPairContraction();
			
			// Remove pair from contraction candidate list
			RemovePairContraction( pair.Candidate() );
			
			// Do not perform bad contraction until the level of detail is very low
			if( pair.Cost()>=invalid_contraction_penalty && current_level_number<15 ) {
				locked_vertices[pair.Candidate()] = true;
				continue;
			}
			
			// Test to see if after the pair contraction,
			// one vertex has a valence of 3
			// This case screws up the predict operator
			itn = NeighborVertices(pair.Candidate()).begin();
			while( itn != NeighborVertices(pair.Candidate()).end() ) {
				if(current_level_number<15 && NeighborVertexNumber(*itn)==4 && FindNeighborVertex(pair.Target(), *itn) && !IsBorderVertex(*itn)) {
					locked_vertices[pair.Candidate()] = true;
				}
				++itn;
			}
			
			if( locked_vertices[pair.Candidate()] ) continue;
			
			// Map the candidate to the target
			vertex_map[pair.Candidate()] = pair.Target();
			
			// Lock the selected vertex and its neighbors
		//	valid_vertices[pair.Candidate()] = false;
		
			// Collapse candidate
			Collapse( pair );
			
			// Update normals
			UpdateNormals( pair );
			
			// Update quadrics
			UpdateQuadrics(pair);
			
			// Update pair cost of surronding vertices
			if( pair.Target() >= 0 ) {	
				// Compute neighbor vertex cost
				itn = NeighborVertices(pair.Target()).begin();
				while( itn != NeighborVertices(pair.Target()).end() ) {
					if( locked_vertices[*itn] == false ) {
						RemovePairContraction(*itn);
						ComputeEdgeCostAtVertex(*itn);
					}
					++itn;
				}
			}
			
			// Lock the neighborhood of the selected vertex
			itn = NeighborVertices(pair.Candidate()).begin();
			while( itn != NeighborVertices(pair.Candidate()).end() ) {
				// If the vertex is not already locked
				if( locked_vertices[*itn] == false ) {
					// Remove its pair contraction estimation
					RemovePairContraction(*itn);
					// Lock it
					locked_vertices[*itn] = true;
				}
				// Next neighbor
				++itn;
			}
			
			// Record pair contraction
			levels[current_level_number].pair_contractions.push_front( pair );
		}

//		bool left = false;
		int left_vertex_number = 0;

		// Compute new edge collapse pairs
		for(int i=0; i<VertexNumber(); i++ ) {
			if( valid_vertices[i] == false ) continue;
			left_vertex_number++;
			locked_vertices[i] = false;
			ComputeEdgeCostAtVertex(i);
		}

		// Update the normals
		ComputeProgressiveFaceNormals();
		ComputeProgressiveVertexNormals();

		// Next level
		current_level_number++;
		
		#ifdef _OUTPUT_LEVELS_
			// Write the current level statistics
			level_stats_file<<current_level_number<<'\t'<<ValidVertexNumber()<<'\t'<<ValidFaceNumber()<<std::endl;
			// Write the current level mesh
			sprintf(filename,"level%02d.wrl",current_level_number);
			WriteFile(filename);
		#endif

		// Is there any vertex left ?
//		if( left_vertex_number == 0 ) break;
	//	if( left_vertex_number < 100 ) break;
		if( left_vertex_number < 10 ) break;

	}

	// End the progressive decomposition
	EndProgressiveDecomposition();

	// Reset
	locked_vertices.clear();


	//
	// Go back the initial fine level
	// Reconstruct all levels
	//
	while( current_level_number > 0 ) {
		// Next level
		current_level_number--;

		// Insert odd vertices
		itp = levels[current_level_number].pair_contractions.begin();
		while( itp != levels[current_level_number].pair_contractions.end() ) {
			// Expand candidate of current pair contraction
			Expand( *itp );
			// Next pair contraction
			++itp;
		}
	}

	// Update the normals
	ComputeProgressiveFaceNormals();
	ComputeProgressiveVertexNormals();

	for( int i=0; i<(int)levels.size(); i++ ) {
		levels[i].Resize( VertexNumber() );
	}

	//
	// Compute the details
	//
	while( current_level_number < LevelNumber() ) {

		//
		// Predict odd vertices
		//
		itp = levels[current_level_number].pair_contractions.begin();
		while( itp != levels[current_level_number].pair_contractions.end() ) {
			// Compute wavelet coefficient
			PredictVertex( itp->Candidate(), ODD_VERTEX );
			
			// Invalidate the odd vertex
			valid_vertices[itp->Candidate()] = false;

			#ifdef _TEST_PLAN_
				// Null the details
				levels[current_level_number].geometric_details[itp->Candidate()] = 0;
			#endif
			
			// Next pair contraction
			++itp;
		}


		//
		// Predict even vertices
		//
		for(int i=0; i<VertexNumber(); i++ ) {
			// Valid vertex ?
			if( valid_vertices[i] == false ) continue;
			
			// Predict even vertex
			PredictVertex( i, EVEN_VERTEX );

			#ifdef _TEST_PLAN_
				// Null the details
				levels[current_level_number].geometric_details[i] = 0;
			#endif
		}

		//
		// Simplify
		// Removed odd vertices to go to next coarse level
		//
		itp = levels[current_level_number].pair_contractions.begin();
		while( itp != levels[current_level_number].pair_contractions.end() ) {
		
			// Collapse candidate
			Collapse( *itp );
			
			// Next Pair contrction
			++itp;
		}

		// Update the normals
		ComputeProgressiveFaceNormals();
		ComputeProgressiveVertexNormals();

		// Go to the next coarse level
		current_level_number++;
	}

	// Test plan
	#ifdef _TEST_PLAN_
		Vertex(1844)[1] = -1.0; // plan-2000
//		Vertex(30670)[1] = -1.0; // plan-irregulier
		char filename[255];
		sprintf(filename,"plan-base.wrl");
		WriteFile(filename);
	#endif


	//-- Test --
	//timer.Stop();
	//test<<VertexNumber()<<'\t'<<vnum<<'\t'<<((double)VertexNumber()/vnum - 1.0)*100.0<<'\t'<<timer.Total()<<'\t'<<memory<<endl;
	//--

	//
	// HSI
	//
/*
	#ifdef _HSI_COLOR_
	if( ColorNumber() == VertexNumber() )
	{
		colors = color_backup;
	}
	#endif
*/

	return true;
}
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;
}