Пример #1
0
void UVWChannel::SetWithMesh(MNMesh *mesh,int channel)
{
	MNMap *mnmap = mesh->M(channel);
	if(mnmap&&mnmap->numv>0&&mnmap->numf>0)
	{
		int i;
		mNumVerts = mnmap->numv;
		mVerts = new UVVert[mNumVerts];
		for(i=0;i<mNumVerts;++i)
		{
			mVerts[i] = mnmap->v[i];
		}		
		
		mNumFaces = mnmap->numf;
		mFaces = new UVWChannel::Face[mNumFaces];
		for(i=0;i<mNumFaces;++i)
		{
			MNMapFace *face = mnmap->F(i);
			mFaces[i].AllocateVerts(face->deg);
			for(int j=0;j<mFaces[i].mNumVerts;++j)
			{
				mFaces[i].mTVVerts[j] = face->tv[j];
			}
		}
	}
}
Пример #2
0
void EditPolyData::ApplyAllOperations (MNMesh & mesh)
{
#ifdef __DEBUG_PRINT_EDIT_POLY
	DebugPrint (_T("EditPolyData::ApplyAllOperations\n"));
#endif

	if (mpOpList) {
		// Preallocate if possible.  (Upon first application, this will do nothing.)
		PolyOperationRecord* pOpRec = NULL;
		int newFaces(0), newVertices(0), newEdges(0);
		Tab<int> newMapVertices;
		newMapVertices.SetCount (mesh.numm + NUM_HIDDENMAPS);
		for (int mp=-NUM_HIDDENMAPS; mp<mesh.numm; mp++) newMapVertices[mp+NUM_HIDDENMAPS] = 0;
		for (pOpRec=mpOpList; pOpRec != NULL; pOpRec=pOpRec->Next()) {
			newFaces += pOpRec->Operation()->NewFaceCount();
			newVertices += pOpRec->Operation()->NewVertexCount();
			newEdges += pOpRec->Operation()->NewEdgeCount ();

			for (int mp=-NUM_HIDDENMAPS; mp<mesh.numm; mp++) {
				if (mesh.M(mp)->GetFlag (MN_DEAD)) continue;
				newMapVertices[mp+NUM_HIDDENMAPS] += pOpRec->Operation()->NewMapVertexCount(mp);
			}
		}

		mesh.VAlloc (mesh.numv + newVertices);
		mesh.EAlloc (mesh.nume + newEdges);
		mesh.FAlloc (mesh.numf + newFaces);
		for (int mp=-NUM_HIDDENMAPS; mp<mesh.numm; mp++) {
			MNMap *map = mesh.M(mp);
			if (map->GetFlag (MN_DEAD)) continue;
			map->VAlloc (map->numv + newMapVertices[mp+NUM_HIDDENMAPS]);
			map->FAlloc (map->numf + newFaces);
		}

		for (pOpRec=mpOpList; pOpRec != NULL; pOpRec=pOpRec->Next())
		{
#ifdef __DEBUG_PRINT_EDIT_POLY
			DebugPrint (_T("EditPolyData::Applying %s\n"), pOpRec->Operation()->Name());
#endif
			pOpRec->Operation()->SetUserFlags (mesh);
			bool ret = pOpRec->Operation()->Apply (mesh, pOpRec->LocalData());
			if (ret && pOpRec->Operation()->CanDelete()) mesh.CollapseDeadStructs ();
		}
	}
}
Пример #3
0
/////////////////////////////////////////////////////////////////////
// Note: 
//    The vertex color data that is used by the ModifyPolyObject 
//    method was created based on this PolyObject's displayed 
//    TriMesh (Mesh). This data is mapped back to the original 
//    PolyMesh (MNMesh).  The mapping relies on the same process 
//    that was used by the method MNMesh::OutToTri() to generate 
//    the Mesh.
// Warning:
//    The mapping used in this method will need to be updated if 
//    anything changes in the way MNMesh generates its displayed Mesh.
// Author: 
//    Wayne Catalfano
// Date:
//    August 30, 2000
//
///////////////////////////////////////////////////////////////////////
void ApplyVCMod::ModifyPolyObject(PolyObject* pPolyObj, TimeValue t)
{
	static int calls = 0;
	iValid = FOREVER;
	Interval valid = GetValidity(t);

	MNMesh& mesh = pPolyObj->GetMesh();
	if (mesh.MNum() < 1) mesh.SetMapNum (1);

	// get the vertex color map
	MNMap* pVCMap = mesh.M(0);

	// initialize to an all white map if necessary
	if (pVCMap->GetFlag(MN_DEAD)) mesh.InitMap(0);

	if (mixedVertexColors.Count() > 0) {
		pVCMap->setNumVerts (mesh.VNum());
		pVCMap->setNumFaces (mesh.FNum());

		// MNMesh keeps the vertices in the same order when it creates
		// the Mesh.  The Mesh vertices Map directly back to the MNMesh
		// vertices in the same order.
		for (int i=0; i<mesh.VNum(); i++) {
			pVCMap->v[i] = i<mixedVertexColors.Count() ?
				Point3(mixedVertexColors[i]->r, mixedVertexColors[i]->g, mixedVertexColors[i]->b) :
				Point3(1.0f, 1.0f, 1.0f);
		}

		for (int i=0; i<mesh.FNum(); i++) {
			if (mesh.F(i)->GetFlag (MN_DEAD)) continue;
			pVCMap->F(i)->SetSize(mesh.F(i)->deg);
			for (int j=0; j<mesh.F(i)->deg;++j) {
				pVCMap->F(i)->tv[j] = mesh.F(i)->vtx[j];
			}
		}
	}
	else if (faceColors.Count() > 0) {
		int numVCVerts = 0;
		for (int i=0; i<mesh.FNum(); i++) {
			if (mesh.F(i)->GetFlag (MN_DEAD)) continue;
			numVCVerts += mesh.F(i)->deg;
		}
		pVCMap->setNumVerts (numVCVerts);
		pVCMap->setNumFaces (mesh.FNum());

		// This mapping process mimicks the process used to generate  
		// the Mesh in the method MNMesh::OutToTri().
		int faceVert = 0;
		int triFaceIndx = 0;
		BitArray faceVertSet;
		for (int i=0; i<mesh.FNum(); i++) {
			if (mesh.F(i)->GetFlag (MN_DEAD)) continue;
			pVCMap->F(i)->SetSize(mesh.F(i)->deg);
			faceVertSet.SetSize(mesh.F(i)->deg);
			faceVertSet.ClearAll();
			int tnum = mesh.F(i)->TriNum()*3;
			Tab<int> triVerts;
			// The method MNFace::GetTriangles is at the heart of the 
			// process used to map Mesh triangles back to MNMesh faces.
			mesh.F(i)->GetTriangles (triVerts);
			for (int j=0; j<tnum; j+=3) {
				for (int k=0; k<3; ++k) {
					int vertIndex = triVerts[j+k];
					// check if we already added a vert for this index
					if (!faceVertSet[vertIndex]) {
						pVCMap->v[faceVert] = triFaceIndx<faceColors.Count() ? 
							Point3(faceColors[triFaceIndx]->colors[k].r, 
								   faceColors[triFaceIndx]->colors[k].g, 
								   faceColors[triFaceIndx]->colors[k].b) :
							Point3(1.0f, 1.0f, 1.0f);

						pVCMap->F(i)->tv[vertIndex] = faceVert;
						faceVertSet.Set(vertIndex);
						faceVert++; 
					}
				}
				++triFaceIndx;
			}
		}
	}

	NotifyDependents(Interval(t,t), PART_VERTCOLOR & PART_EXCLUDE_RADIOSITY, REFMSG_CHANGE);
	NotifyDependents(Interval(t,t), PART_TOPO & PART_EXCLUDE_RADIOSITY, REFMSG_CHANGE);
	pPolyObj->UpdateValidity(VERT_COLOR_CHAN_NUM, valid);
}
Пример #4
0
IGeometryChecker::ReturnVal MissingUVCoordinatesChecker::GeometryCheck(TimeValue t,INode *nodeToCheck, IGeometryChecker::OutputVal &val)
{
	val.mIndex.ZeroCount();
	if(IsSupported(nodeToCheck))
	{
		LARGE_INTEGER	ups,startTime;
		QueryPerformanceFrequency(&ups);
		QueryPerformanceCounter(&startTime); //used to see if we need to pop up a dialog 
		bool compute = true;
		bool checkTime = GetIGeometryCheckerManager()->GetAutoUpdate();//only check time for the dialog if auto update is active!
		UVWChannel uvmesh;
		ObjectState os  = nodeToCheck->EvalWorldState(t);
		Object *obj = os.obj;
		if(os.obj->IsSubClassOf(triObjectClassID))
		{
			TriObject *tri = dynamic_cast<TriObject *>(os.obj);
			if(tri)
			{
				BitArray arrayOfVertices;
				arrayOfVertices.SetSize(tri->mesh.numVerts);
				arrayOfVertices.ClearAll();
				IGeometryChecker::ReturnVal returnval=IGeometryChecker::eFail;
				int numChannels = tri->mesh.getNumMaps();
				int index;
				for(int i=0;i<numChannels;++i)
				{
					if(tri->mesh.mapSupport(i))
					{

						MeshMap *map  = &tri->mesh.Map(i);
						if(map->getNumVerts()>0 &&map->getNumFaces()>0)
						{
							returnval= TypeReturned();
							int numFaces = map->getNumFaces();
							TVFace * tvFaces = map->tf;
							UVVert *  uvVerts= map->tv;
						
							#pragma omp parallel for
							for(int faceIndex =0;faceIndex<numFaces;++faceIndex)
							{
								if(compute)
								{
									TVFace& tvFace = tvFaces[faceIndex];
									Point3 tv = uvVerts[tvFace.t[0]];
									if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z))
									{
										index = tri->mesh.faces[faceIndex].v[0];
										if(index>=0&&index<tri->mesh.numVerts)
										{
											#pragma omp critical
											{
												arrayOfVertices.Set(index);
											}
										}
									}
									tv = uvVerts[tvFace.t[1]];
									if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z))
									{
										index = tri->mesh.faces[faceIndex].v[1];
										if(index>=0&&index<tri->mesh.numVerts)
										{
											#pragma omp critical
											{
												arrayOfVertices.Set(index);
											}
										}
									}
									tv = uvVerts[tvFace.t[2]];
									if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z))
									{
										index = tri->mesh.faces[faceIndex].v[2];
										if(index>=0&&index<tri->mesh.numVerts)
										{
											#pragma omp critical
											{
												arrayOfVertices.Set(index);
											}
										}
									}
									if(checkTime==true)
									{
										#pragma omp critical
										{
											DialogChecker::Check(checkTime,compute,numFaces,startTime,ups);
										}
									}
								}
							}
						}
					}
				}
				if(arrayOfVertices.IsEmpty()==false) //we have overlapping faces
				{
					int localsize= arrayOfVertices.GetSize();
					for(int i=0;i<localsize;++i)
					{
						if(arrayOfVertices[i])
							val.mIndex.Append(1,&i);
					}
				}
				return returnval;
			}
			else return IGeometryChecker::eFail;
		}
		else if(os.obj->IsSubClassOf(polyObjectClassID))
		{
			PolyObject *poly = dynamic_cast<PolyObject *>(os.obj);
			if(poly)
			{
				BitArray arrayOfVertices;
				arrayOfVertices.SetSize(poly->GetMesh().numv);
				arrayOfVertices.ClearAll();
				IGeometryChecker::ReturnVal returnval=IGeometryChecker::eFail;
				int numChannels= poly->GetMesh().MNum();
				int index;
				for(int i=0;i<numChannels;++i)
				{
					if(poly->GetMesh().M(i))
					{
						MNMesh *mesh = &(poly->GetMesh());
						MNMap *mnmap = mesh->M(i);
						if(mnmap&&mnmap->numv>0&&mnmap->numf>0)
						{
							returnval= TypeReturned();
							int numFaces = mnmap->numf;
							#pragma omp parallel for
							for(int faceIndex =0;faceIndex<numFaces;++faceIndex)
							{
								if(compute)
								{
									Point3 tv;
									int a,b,c;
									MNMapFace *face = mnmap->F(faceIndex);
									UVVert *  uvVerts=  mnmap->v;
									for(int j=0;j<(face->deg);++j)
									{
										if(j==(face->deg-2))
										{
											a  = j; b = j+1; c = 0;
										}
										else if(j==(face->deg-1))
										{
											a  = j; b = 0; c = 1;
										}
										else
										{
											a  = j; b = j+1; c = j+2;
										}
										tv = uvVerts[face->tv[a]];
										if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z))
										{
											index = mesh->f->vtx[a];
											if(index>=0&&index<mesh->numv)
											{
												#pragma omp critical
												{
													arrayOfVertices.Set(index);
												}
											}
										}
										tv = uvVerts[face->tv[b]];
										if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z))
										{
											index = mesh->f->vtx[b];
											if(index>=0&&index<mesh->numv)
											{
												#pragma omp critical
												{
													arrayOfVertices.Set(index);
												}
											}
										}
										tv = uvVerts[face->tv[c]];
										if(_isnan(tv.x) || !_finite(tv.x)||_isnan(tv.y) || !_finite(tv.y)||_isnan(tv.z) || !_finite(tv.z))
										{
											index = mesh->f->vtx[c];
											if(index>=0&&index<mesh->numv)
											{
												#pragma omp critical
												{
													arrayOfVertices.Set(index);
												}
											}
										}
										if(checkTime==true)
										{
											#pragma omp critical
											{
												DialogChecker::Check(checkTime,compute,numFaces,startTime,ups);
											}
										}
									}
								}
							}	
						}
					}
				}
				if(arrayOfVertices.IsEmpty()==false) //we have overlapping faces
				{
					int localsize= arrayOfVertices.GetSize();
					for(int i=0;i<localsize;++i)
					{
						if(arrayOfVertices[i])
							val.mIndex.Append(1,&i);
					}
				}
				return returnval;
			}
			else return IGeometryChecker::eFail;
		}
	}
	return IGeometryChecker::eFail;
}
Пример #5
0
// This method needs to be moved to class MNMesh when the SDK opens up again.
// Note that it's an exact copy of some code in the EditablePoly source.
bool MNMeshCollapseEdges (MNMesh & mm, DWORD edgeFlag) {
	// Collect average locations ourselves
	// We do this by collecting information about which vertex
	// or map vertex each eliminated point was welded to - its destination.
	// Then we average things out at the end.
	Tab<int> pointDest;
	pointDest.SetCount (mm.numv);
	for (int i=0; i<mm.numv; i++) pointDest[i] = -1;

	Tab<Tab<int> *> mapPointDest;
	mapPointDest.SetCount (mm.numm + NUM_HIDDENMAPS);
	for (int mapChannel=-NUM_HIDDENMAPS; mapChannel<mm.numm; mapChannel++) {
		int nhm = mapChannel + NUM_HIDDENMAPS;
		if (mm.M(mapChannel)->GetFlag (MN_DEAD)) mapPointDest[nhm] = NULL;
		else {
			int nv = mm.M(mapChannel)->numv;
			if (!nv) mapPointDest[nhm] = NULL;
			else {
				mapPointDest[nhm] = new Tab<int>;
				mapPointDest[nhm]->SetCount (nv);
				int *md = mapPointDest[nhm]->Addr(0);
				for (i=0; i<nv; i++) md[i] = -1;
			}
		}
	}

	// Perform topological welding, edge by edge
	bool ret=false;
	for (i=0; i<mm.nume; i++) {
		if (mm.e[i].GetFlag (MN_DEAD)) continue;
		if (!mm.e[i].GetFlag (MN_USER)) continue;
		int v1 = mm.e[i].v1;
		int v2 = mm.e[i].v2;
		int f1 = mm.e[i].f1;
		int f2 = mm.e[i].f2;
		int eid1 = mm.f[f1].EdgeIndex (i);
		int eid2 = (f2>-1) ? mm.f[f2].EdgeIndex (i) : -1;
		Tab<int> mv1, mv2;
		mv1.SetCount ((mm.numm+NUM_HIDDENMAPS)*2);
		mv2.SetCount ((mm.numm+NUM_HIDDENMAPS)*2);
		for (int mapChannel = -NUM_HIDDENMAPS; mapChannel<mm.numm; mapChannel++) {
			MNMap *map = mm.M(mapChannel);
			int nhm = (NUM_HIDDENMAPS + mapChannel)*2;
			if (map->GetFlag (MN_DEAD)) {
				mv1[nhm] = -1;
				continue;
			}
			mv1[nhm] = map->f[f1].tv[eid1];
			mv1[nhm+1] = (f2>-1) ? map->f[f2].tv[(eid2+1)%mm.f[f2].deg] : mv1[nhm];
			mv2[nhm] = map->f[f1].tv[(eid1+1)%mm.f[f1].deg];
			mv2[nhm+1] = (f2>-1) ? map->f[f2].tv[eid2] : mv2[nhm];
		}
		if (mm.WeldEdge (i)) {
			pointDest[v2] = v1;
			for (int nhm=0; nhm<mapPointDest.Count(); nhm++) {
				if (mapPointDest[nhm] == NULL) continue;
				if (!mapPointDest[nhm]->Count()) continue;
				if (mv1[nhm*2]<0) continue;
				int *mpd = mapPointDest[nhm]->Addr(0);
				mpd[mv2[nhm*2]] = mv1[nhm*2];
				if (mv2[nhm*2+1] != mv2[nhm*2]) mpd[mv2[nhm*2+1]] = mv1[nhm*2+1];
			}
			ret = true;
		}
	}

	// Then set all the welded vertices to the correct averaged locations
	if (ret) {
		for (mapChannel = -NUM_HIDDENMAPS-1; mapChannel<mm.numm; mapChannel++) {
			// note - -NUM_HIDDENMAPS-1 is not a valid map channel,
			// We're using it for a convenient extra loop for the actual geometry.
			int nhm = mapChannel+NUM_HIDDENMAPS;
			if ((nhm>-1) && mapPointDest[nhm] == NULL) continue;
			Tab<int> & destinations = (nhm<0) ? pointDest : *(mapPointDest[nhm]);

			for (i=0; i<destinations.Count(); i++) {
				if (destinations[i] < 0) continue;
				if (destinations[destinations[i]] > -1) {
					// We have nested destinations - straighten them out.
					// Form a stack of all the intermediate destinations:
					Tab<int> intermediate;
					for (int last=i; destinations[last]>-1; last=destinations[last]) {
						intermediate.Append (1, &last, 2);
					}
					// Now destinations[current] = -1, which means it's the final destination of all of these.
					// Correct whole chain.
					for (int k=0; k<intermediate.Count()-1; k++) destinations[intermediate[k]] = last;
				}

				if (nhm<0) mm.v[destinations[i]].p += mm.v[i].p;
				else mm.M(mapChannel)->v[destinations[i]] += mm.M(mapChannel)->v[i];

				destinations[destinations[i]]--;
			}

			for (i=0; i<destinations.Count(); i++) {
				if (destinations[i] > -2) continue;
				if (nhm<0) mm.v[i].p /= float(-destinations[i]);
				else mm.M(mapChannel)->v[i] /= float(-destinations[i]);
			}

			// Free memory
			if (nhm>-1) {
				delete mapPointDest[nhm];
				mapPointDest[nhm] = NULL;
			}
		}
	}

	return ret;
}
Пример #6
0
void ModifierPtex::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node) 
{
	Interval valid = FOREVER;

	int uvw_channel = 0;

	if ( m_pblock->GetInt( UVW_TYPE ) == 0 ) 
	{
		uvw_channel = m_pblock->GetInt( UVW_CHANNEL );
	}

	if ( os->obj->IsSubClassOf( polyObjectClassID ) )
	{ 
		PolyObject *polyObj = (PolyObject*)os->obj;
		MNMesh &mnMesh = polyObj->GetMesh();

		bool has_map;
		if ( uvw_channel >= mnMesh.MNum() )
		{
			mnMesh.SetMapNum( uvw_channel + 1 );
			has_map = false;
		} 
		else 
		{
			has_map = mnMesh.M( uvw_channel )->GetFlag( MN_DEAD ) == false;
		}

		MNMap *mc = mnMesh.M( uvw_channel );

		if ( has_map == false )
		{
			mc->setNumFaces( mnMesh.numf );

			for ( int i_f = 0; i_f < mnMesh.numf; i_f++ )
			{
				mc->f[ i_f ].SetSize( mnMesh.f[ i_f ].deg );
			}
		}

		if ( mc->GetFlag( MN_DEAD ) ) mc->ClearFlag( MN_DEAD );

		unsigned int num_tverts = 0;

		for ( int i_f = 0; i_f < mnMesh.numf; i_f++ )
		{
			num_tverts += mc->f[ i_f ].deg;
		}

		mc->setNumVerts( num_tverts );

		unsigned int tvert_id = 0;

		for ( int i_f = 0; i_f < mnMesh.numf; i_f++ )
		{
			unsigned int deg = mc->f[ i_f ].deg;

			for ( unsigned int i_v = 0; i_v < deg; i_v++ )
			{
				mc->f[ i_f ].tv[ i_v ] = tvert_id;

				Point3 tv;

				if      ( i_v == 0 ) tv = Point3( (float)i_f,        0.0f, 0.0f );
				else if ( i_v == 1 ) tv = Point3( (float)i_f + 1.0f, 0.0f, 0.0f );
				else if ( i_v == 2 ) tv = Point3( (float)i_f + 1.0f, 1.0f, 0.0f );
				else                 tv = Point3( (float)i_f,        1.0f, 0.0f );

				tv.z = 0.0f;

				mc->v[ tvert_id ] = tv;
			
				tvert_id++;
			}
		}
	}

	// Update all the caches etc
	Interval iv = LocalValidity(t);
	iv = iv & os->obj->ChannelValidity( t, GEOM_CHAN_NUM );
	iv = iv & os->obj->ChannelValidity( t, TOPO_CHAN_NUM );
	os->obj->UpdateValidity( TEXMAP_CHAN_NUM, iv );
}