Exemplo n.º 1
0
void UnwrapMod::fnFlattenMap(float angleThreshold, Tab<Point3*> *normalList, float spacing, BOOL normalize, int layoutType, BOOL rotateClusters, BOOL fillHoles)

{
	for (int i = 0; i < mMeshTopoData.Count(); i++)
	{
		mMeshTopoData[i]->HoldSelection();
	}



	BailStart();

	if (preventFlattening) return;
	/*
	if (TVMaps.f.Count() == 0) return;

	BitArray *polySel = fnGetSelectedPolygons();
	if (polySel == NULL) 
	return;
	*/

	theHold.Begin();
	HoldPointsAndFaces();   
	/*
	BitArray holdPolySel;
	holdPolySel.SetSize(polySel->GetSize());
	holdPolySel = *polySel;
	*/
	Point3 normal(0.0f,0.0f,1.0f);

	Tab<Point3> mapNormal;
	mapNormal.SetCount(normalList->Count());
	for (int i =0; i < mapNormal.Count(); i++)
	{
		mapNormal[i] = *(*normalList)[i];
	}

	BOOL noSelection = TRUE;
	for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
	{
		if (mMeshTopoData[ldID]->GetFaceSelection().NumberSet())
			noSelection = FALSE;
	}

	if (noSelection)
	{
		for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
		{
			BitArray fsel = mMeshTopoData[ldID]->GetFaceSelection();
			fsel.SetAll();
			mMeshTopoData[ldID]->SetFaceSelection(fsel);
		}
	}

	TSTR statusMessage;
	MeshTopoData::GroupBy groupBy = MeshTopoData::kFaceAngle;
	int v = 0;
	pblock->GetValue(unwrap_flattenby,0,v,FOREVER);
	if (v == 0)
		groupBy = MeshTopoData::kFaceAngle;
	else if (v == 2)
		groupBy = MeshTopoData::kMaterialID;
	else if (v == 1)
		groupBy = MeshTopoData::kSmoothingGroup;

	BOOL bContinue = BuildCluster( mapNormal, angleThreshold, TRUE,TRUE,groupBy);
	/*
	BitArray sel;
	sel.SetSize(TVMaps.f.Count());
	*/
	gBArea = 0.0f;

	int initialCluster = clusterList.Count();

	if (bContinue)
	{
		for (int i =0; i < clusterList.Count(); i++)
		{
			MeshTopoData *ld = clusterList[i]->ld;
			ld->ClearSelection(TVFACEMODE);//         sel.ClearAll();
			for (int j = 0; j < clusterList[i]->faces.Count();j++)
				ld->SetFaceSelected(clusterList[i]->faces[j],TRUE);//sel.Set(clusterList[i]->faces[j]);
			ld->PlanarMapNoScale(clusterList[i]->normal,this);

			int per = (i * 100)/clusterList.Count();
			statusMessage.printf(_T("%s %d%%."),GetString(IDS_PW_STATUS_MAPPING),per);
			if (Bail(ip,statusMessage))
			{
				i = clusterList.Count();
				bContinue =  FALSE;
			}

		}

		//    if (0)
		if (bContinue)
		{
			for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
				mMeshTopoData[ldID]->UpdateClusterVertices(clusterList);

			if (layoutType == 1)
				bContinue = LayoutClusters( spacing, rotateClusters, TRUE, fillHoles);
			else
			{
				if (flattenMax5)
					bContinue = LayoutClusters3( spacing, rotateClusters, fillHoles);
				else bContinue = LayoutClusters2( spacing, rotateClusters, fillHoles);

			}

			//normalize map to 0,0 to 1,1
			if ((bContinue) && (normalize))
			{
				NormalizeCluster(spacing);
			}
		}

	}

	CleanUpDeadVertices();
	if (bContinue)
	{
		theHold.Accept(GetString(IDS_PW_FLATTEN));

		theHold.Suspend();
		fnSyncTVSelection();
		theHold.Resume();

	}
	else
	{
		theHold.Cancel();
		//    theHold.SuperCancel();
	}

	for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
	{	
		mMeshTopoData[ldID]->SetTVEdgeInvalid();
		mMeshTopoData[ldID]->BuildTVEdges();
		mMeshTopoData[ldID]->BuildVertexClusterList();		
	}


	theHold.Suspend();
	fnSyncTVSelection();
	fnSyncGeomSelection();
	theHold.Resume();

	for (int i = 0; i < mMeshTopoData.Count(); i++)
	{
		mMeshTopoData[i]->RestoreSelection();
	}


	NotifyDependents(FOREVER,PART_SELECT,REFMSG_CHANGE);
	InvalidateView();


#ifdef DEBUGMODE 
	if (gDebugLevel >= 1)
	{
		int finalCluster = clusterList.Count();
		gEdgeHeight = 0.0f;
		gEdgeWidth = 0.0f;
		for (int i =0; i < clusterList.Count(); i++)
		{
			gEdgeHeight += clusterList[i]->h;
			gEdgeWidth += clusterList[i]->w;

		}

		ScriptPrint(_T("Surface Area %f bounds area %f  per used %f\n"),gSArea,gBArea,gSArea/gBArea); 
		ScriptPrint(_T("Edge Height %f Edge Width %f\n"),gEdgeHeight,gEdgeWidth); 
		ScriptPrint(_T("Initial Clusters %d finalClusters %d\n"),initialCluster,finalCluster); 
	}

#endif

	FreeClusterList();

	statusMessage.printf(_T("Done, area coverage %3.2f"),(gSArea/gBArea)*100.f);
	Bail(ip,statusMessage,0);


}
Exemplo n.º 2
0
void  UnwrapMod::fnUnfoldSelectedPolygons(int unfoldMethod, BOOL normalize)
{     

	// flatten selected polygons
	if (!ip) return;
	BailStart();

	theHold.Begin();
	HoldPointsAndFaces();   

	Point3 normal(0.0f,0.0f,1.0f);

	for (int ldID =0; ldID < mMeshTopoData.Count(); ldID++)
	{
		MeshTopoData *ld = mMeshTopoData[ldID];
		ld->HoldFaceSel();
	}

	BOOL bContinue = TRUE;
	for (int ldID =0; ldID < mMeshTopoData.Count(); ldID++)
	{

		Tab<Point3> mapNormal;
		mapNormal.SetCount(0);
		MeshTopoData *ld = mMeshTopoData[ldID];

		for (int ldIDPrep =0; ldIDPrep < mMeshTopoData.Count(); ldIDPrep++)
		{
			MeshTopoData *ldPrep = mMeshTopoData[ldIDPrep];
			if (ld != ldPrep)
				ldPrep->ClearFaceSelection();
			else
				ldPrep->RestoreFaceSel();
		}

		//hold our face selection
		//get our processed list 
		BitArray holdFaces = ld->GetFaceSelection();
		BitArray processedFaces = ld->GetFaceSelection();
		while (processedFaces.NumberSet())
		{
			//select the first one
			int seed = -1;
			for (int faceID = 0; faceID < processedFaces.GetSize(); faceID++)
			{
				if (processedFaces[faceID])
				{
					seed = faceID;
					faceID = processedFaces.GetSize();
				}
			}
			BitArray faceSel = ld->GetFaceSel();
			faceSel.ClearAll();
			//select the element the first one
			faceSel.Set(seed,TRUE);
			//select it
			ld->SetFaceSel(faceSel);
			SelectGeomElement(ld);
			faceSel = ld->GetFaceSel();

//			ld->SelectElement(TVFACEMODE,FALSE);
			faceSel &= holdFaces;			
			//remove that from our process list
			for (int faceID = 0; faceID < faceSel.GetSize(); faceID++)
			{
				if (faceSel[faceID])
				{
					processedFaces.Set(faceID,FALSE);
				}
			}
			ld->SetFaceSel(faceSel);
			
			bContinue = BuildCluster( mapNormal, 5.0f, TRUE, TRUE, MeshTopoData::kFaceAngle);
			TSTR statusMessage;



			if (bContinue)
			{


				for (int i =0; i < clusterList.Count(); i++)
				{
					
					ld->ClearFaceSelection();
					for (int j = 0; j < clusterList[i]->faces.Count();j++)
						ld->SetFaceSelected(clusterList[i]->faces[j],TRUE);//	sel.Set(clusterList[i]->faces[j]);
					ld->PlanarMapNoScale(clusterList[i]->normal,this);


					int per = (i * 100)/clusterList.Count();
					statusMessage.printf(_T("%s %d%%."),GetString(IDS_PW_STATUS_MAPPING),per);
					if (Bail(ip,statusMessage))
					{
						i = clusterList.Count();
						bContinue =  FALSE;
					}
				}

				DebugPrint (_T("Final Vct %d \n"),ld->GetNumberTVVerts());

				if ( (bContinue) && (clusterList.Count() > 1) )
				{




						Tab<Point3> objNormList;
						BuildNormals(ld,objNormList);

						//remove internal edges
						Tab<int> clusterGroups;
						clusterGroups.SetCount(ld->GetNumberFaces());
						for (int i =0; i < clusterGroups.Count(); i++)
						{
							clusterGroups[i] = -1;
						}
						
						for (int i = 0; i < clusterList.Count(); i++)
						{
							for (int j = 0; j < clusterList[i]->faces.Count(); j++)
							{
								int faceIndex = clusterList[i]->faces[j];
								clusterGroups[faceIndex] = i;
							}
						}
						BitArray processedClusters;
						processedClusters.SetSize(clusterList.Count());
						processedClusters.ClearAll();

						Tab<BorderClass> edgesToBeProcessed;

						BOOL done = FALSE;
						processedClusters.Set(0);
						clusterList[0]->newX = 0.0f;
						clusterList[0]->newY = 0.0f;
						//    clusterList[0]->angle = 0.0f;
						for (int i = 0; i < clusterList[0]->borderData.Count(); i++)
						{
							int outerFaceIndex = clusterList[0]->borderData[i].outerFace;
							int connectedClusterIndex = clusterGroups[outerFaceIndex];
							if ((connectedClusterIndex != 0) && (connectedClusterIndex != -1))
							{
								edgesToBeProcessed.Append(1,&clusterList[0]->borderData[i]);
							}
						}
					
						BitArray seedFaceList;
						seedFaceList.SetSize(clusterGroups.Count());
						seedFaceList.ClearAll();
						for (int i = 0; i < seedFaces.Count(); i++)
						{
							seedFaceList.Set(seedFaces[i]);
						}

						while (!done)
						{
							Tab<int> clustersJustProcessed;
							clustersJustProcessed.ZeroCount();
							done = TRUE;

							int edgeToAlign = -1;
							float angDist = PI*2;
							if (unfoldMethod == 1)
								angDist =  PI*2;
							else if (unfoldMethod == 2) angDist = 0;
							int i;
							for (i = 0; i < edgesToBeProcessed.Count(); i++)
							{
								int outerFace = edgesToBeProcessed[i].outerFace;
								int connectedClusterIndex = clusterGroups[outerFace];
								if (!processedClusters[connectedClusterIndex])
								{
									int innerFaceIndex = edgesToBeProcessed[i].innerFace;
									int outerFaceIndex = edgesToBeProcessed[i].outerFace;
									//get angle
									Point3 innerNorm, outerNorm;
									innerNorm = objNormList[innerFaceIndex];
									outerNorm = objNormList[outerFaceIndex];
									float dot = DotProd(innerNorm,outerNorm);

									float angle = 0.0f;

									if (dot == -1.0f)
										angle = PI;
									else if (dot >= 1.0f)
										angle = 0.f;                  
									else angle = acos(dot);

									if (unfoldMethod == 1)
									{
										if (seedFaceList[outerFaceIndex])
											angle = 0.0f;
										if (angle < angDist)
										{
											angDist = angle;
											edgeToAlign = i;
										}
									}

									else if (unfoldMethod == 2)
									{
										if (seedFaceList[outerFaceIndex])
											angle = 180.0f;
										if (angle > angDist)
										{
											angDist = angle;
											edgeToAlign = i;
										}
									}

								}
							}
							if (edgeToAlign != -1)
							{
								int innerFaceIndex = edgesToBeProcessed[edgeToAlign].innerFace;
								int outerFaceIndex = edgesToBeProcessed[edgeToAlign].outerFace;
								int edgeIndex = edgesToBeProcessed[edgeToAlign].edge;


								int connectedClusterIndex = clusterGroups[outerFaceIndex];

								seedFaceList.Set(outerFaceIndex, FALSE);

								processedClusters.Set(connectedClusterIndex);
								clustersJustProcessed.Append(1,&connectedClusterIndex);	
								ld->AlignCluster(clusterList,connectedClusterIndex,innerFaceIndex, outerFaceIndex,edgeIndex,this);
								done = FALSE;
							}

							//build new cluster list
							for (int j = 0; j < clustersJustProcessed.Count(); j++)
							{
								int clusterIndex = clustersJustProcessed[j];
								for (int i = 0; i < clusterList[clusterIndex]->borderData.Count(); i++)
								{
									int outerFaceIndex = clusterList[clusterIndex]->borderData[i].outerFace;
									int connectedClusterIndex = clusterGroups[outerFaceIndex];
									if ((connectedClusterIndex != 0) && (connectedClusterIndex != -1) && (!processedClusters[connectedClusterIndex]))
									{
										edgesToBeProcessed.Append(1,&clusterList[clusterIndex]->borderData[i]);
									}
								}
							}
						}
					
				}

				ld->ClearSelection(TVVERTMODE);

				for (int i = 0; i < clusterList.Count(); i++)
				{
					MeshTopoData *ld = clusterList[i]->ld;
					ld->UpdateClusterVertices(clusterList);
					for (int j =0; j < clusterList[i]->faces.Count(); j++)
					{
						int faceIndex = clusterList[i]->faces[j];
						int degree = ld->GetFaceDegree(faceIndex);
						for (int k =0; k < degree; k++)
						{
							int vertexIndex = ld->GetFaceTVVert(faceIndex,k);//TVMaps.f[faceIndex]->t[k];
							ld->SetTVVertSelected(vertexIndex,TRUE);//vsel.Set(vertexIndex);
						}
					}
				}

				//now weld the verts
				if (normalize)
				{
					NormalizeCluster();
				}


				ld->WeldSelectedVerts(0.001f,this);

			}
	
			FreeClusterList();
		}
	}

	if (bContinue)
	{  
		theHold.Accept(GetString(IDS_PW_PLANARMAP));		

		theHold.Suspend();
		fnSyncTVSelection();
		theHold.Resume();
	}
	else
	{
		theHold.Cancel();
		
	}

	
	for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++)
	{			
		mMeshTopoData[ldID]->BuildTVEdges();
		mMeshTopoData[ldID]->RestoreFaceSel();
	}

	theHold.Suspend();
	fnSyncGeomSelection();
	theHold.Resume();

	if (matid != -1) // if we have a matID fileter set we need to rebuild since topology has changed
		SetMatFilters();

	NotifyDependents(FOREVER,PART_SELECT,REFMSG_CHANGE);
	InvalidateView();

}