Exemple #1
0
void ConvertToPoly::Convert (PolyObject *obj, TimeValue t, MNMesh & mm, Interval & ivalid) {
	int keepConvex;
	int limitSize;
	int maxdeg=0;
	int keepPlanar, elimCollin;
	float planarThresh = 0.0f;

	pblock->GetValue (turn_keep_convex, t, keepConvex, ivalid);
	pblock->GetValue (turn_limit_size, t, limitSize, ivalid);
	if (limitSize) pblock->GetValue (turn_max_size, t, maxdeg, ivalid);
	pblock->GetValue (turn_planar, t, keepPlanar, ivalid);
	if (keepPlanar) {
		pblock->GetValue (turn_thresh, t, planarThresh, ivalid);
		planarThresh = cosf (planarThresh);
	}
	pblock->GetValue (turn_eliminate_collinear, t, elimCollin, ivalid);

	mm = obj->mm;

	// Luna task 747
	// We cannot support specified normals in Convert to Poly at this time.
	mm.ClearSpecifiedNormals();

	if (!mm.GetFlag (MN_MESH_FILLED_IN)) mm.FillInMesh ();
	if (!mm.GetFlag (MN_MESH_NO_BAD_VERTS)) mm.EliminateBadVerts ();

	if (maxdeg) mm.RestrictPolySize (maxdeg);
	if (keepConvex) mm.MakeConvex ();
	if (maxdeg || keepConvex) mm.ClearEFlags (MN_EDGE_INVIS);
	if (keepPlanar) mm.MakePlanar (planarThresh);
	if (elimCollin) mm.EliminateCollinearVerts ();
	mm.selLevel = obj->mm.selLevel;
}
Exemple #2
0
void EditFaceDataModData::ApplyChanges (MNMesh & mesh) {
	// Make sure we're sized correctly for this mesh.
	// (NOTE: If the user reduces, then increases input number of faces, we lose data.)
	if (mesh.numf != mFaceSel.GetSize()) SynchSize (mesh.numf);

	// Set the selection:
	mesh.FaceSelect (mFaceSel);

	// Get the face data manager from the mesh:
	DebugPrint ("EditFaceDataMod: Getting manager from MNMesh (0x%08x)\n", &mesh);
	IFaceDataMgr *pFDMgr = static_cast<IFaceDataMgr*>(mesh.GetInterface (FACEDATAMGR_INTERFACE));
	if (pFDMgr == NULL) return;

	SampleFaceData* fdc = dynamic_cast<SampleFaceData*>(pFDMgr->GetFaceDataChan( FACE_MAXSAMPLEUSE_CLSID ));
	if ( fdc == NULL ) {
		// The mesh does not have our sample face-data channel so we will add it here
		fdc = new SampleFaceData();
		fdc->FacesCreated (0, mFaceSel.GetSize());
		pFDMgr->AddFaceDataChan( fdc );
	}

	if (!mFacesAffected.NumberSet ()) return;

	for (int i=0; i<mFacesAffected.GetSize(); i++) {
		if (!mFacesAffected[i]) continue;
		fdc->SetValue (i, mtNewFaceValues[i]);
	}
}
Exemple #3
0
void PolyOpExtrudeEdge::Do (MNMesh & mesh) {
	MNChamferData chamData;
	chamData.InitToMesh(mesh);
	Tab<Point3> tUpDir;
	tUpDir.SetCount (mesh.numv);

	// Topology change:
	if (!mesh.ExtrudeEdges (MN_USER, &chamData, tUpDir)) return;

	// Apply map changes based on base width:
	int i;
	Tab<UVVert> tMapDelta;
	for (int mapChannel=-NUM_HIDDENMAPS; mapChannel<mesh.numm; mapChannel++) {
		if (mesh.M(mapChannel)->GetFlag (MN_DEAD)) continue;
		chamData.GetMapDelta (mesh, mapChannel, mWidth, tMapDelta);
		UVVert *pMapVerts = mesh.M(mapChannel)->v;
		if (!pMapVerts) continue;
		for (i=0; i<mesh.M(mapChannel)->numv; i++) pMapVerts[i] += tMapDelta[i];
	}

	// Apply geom changes based on base width:
	Tab<Point3> tDelta;
	chamData.GetDelta (mWidth, tDelta);
	for (i=0; i<mesh.numv; i++) mesh.v[i].p += tDelta[i];

	// Move the points up:
	for (i=0; i<tUpDir.Count(); i++) mesh.v[i].p += tUpDir[i]*mHeight;
}
Exemple #4
0
void PolyOpExtrudeFace::Do(MNMesh & mesh)
{
	MNChamferData chamData;
	if (mType<2) {
		MNFaceClusters fclust(mesh, MN_USER);
		if (!mesh.ExtrudeFaceClusters (fclust)) return;
		if (mType == 0) {
			// Get fresh face clusters:
			MNFaceClusters fclustAfter(mesh, MN_USER);
			Tab<Point3> clusterNormals, clusterCenters;
			fclustAfter.GetNormalsCenters (mesh, clusterNormals, clusterCenters);
			mesh.GetExtrudeDirection (&chamData, &fclustAfter, clusterNormals.Addr(0));
		} else {
			mesh.GetExtrudeDirection (&chamData, MN_USER);
		}
	} else {
		// Polygon-by-polygon extrusion.
		if (!mesh.ExtrudeFaces (MN_USER)) return;
		MNFaceClusters fclustAfter(mesh, MN_USER);
		Tab<Point3> clusterNormals, clusterCenters;
		fclustAfter.GetNormalsCenters (mesh, clusterNormals, clusterCenters);
		mesh.GetExtrudeDirection (&chamData, &fclustAfter, clusterNormals.Addr(0));
	}

	// Move vertices
	for (int i=0; i<mesh.numv; i++) {
		if (mesh.v[i].GetFlag (MN_DEAD)) continue;
		mesh.v[i].p += chamData.vdir[i]*mHeight;
	}
}
Exemple #5
0
int EditFaceDataMod::HitTest (TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt, ModContext* mc) {
	Interval valid;
	int savedLimits, res = 0;
	GraphicsWindow *gw = vpt->getGW();
	HitRegion hr;
	
	// Setup GW
	MakeHitRegion(hr,type, crossing,4,p);
	gw->setHitRegion(&hr);
	Matrix3 mat = inode->GetObjectTM(t);
	gw->setTransform(mat);	
	gw->setRndLimits(((savedLimits = gw->getRndLimits()) | GW_PICK) & ~GW_ILLUM);
	gw->clearHitCode();

	if (!mc->localData) return 0;
	EditFaceDataModData *md = (EditFaceDataModData*)mc->localData;
	Mesh *mesh = md->GetCacheMesh ();
	MNMesh *mnmesh = md->GetCacheMNMesh ();

	SubObjHitList hitList;
	if (mesh) {
		res = mesh->SubObjectHitTest(gw, gw->getMaterial(), &hr, flags|hitLevel[selLevel], hitList);
	} else if (mnmesh) {
		res = mnmesh->SubObjectHitTest (gw, gw->getMaterial(), &hr, flags|mnhitLevel[selLevel], hitList);
	}

	MeshSubHitRec *rec = hitList.First();
	while (rec) {
		vpt->LogHit(inode,mc,rec->dist,rec->index,NULL);
		rec = rec->Next();
	}

	gw->setRndLimits(savedLimits);	
	return res;	
}
Exemple #6
0
void EditFaceDataMod::GetSubObjectTMs (SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc) {
	if (!mc->localData) return;
	if (selLevel == SEL_OBJECT) return;	// shouldn't happen.
	EditFaceDataModData *modData = (EditFaceDataModData *) mc->localData;

	Mesh *mesh = modData->GetCacheMesh();
	MNMesh *mnmesh = modData->GetCacheMNMesh();
	if (!mesh && !mnmesh) return;

	Matrix3 tm = node->GetObjectTM(t);
	Box3 box;
	if (mesh) {
		BitArray sel = mesh->VertexTempSel ();
		if (!sel.NumberSet()) return;
		for (int i=0; i<mesh->numVerts; i++) if (sel[i]) box += mesh->verts[i] * tm;
	} else {
		int numSel, which;
		float value;
		bool valueDetermined;
		modData->DescribeSelection (numSel, which, value, valueDetermined);
		if (!numSel) return;
		if (numSel==1) {
			for (int j=0; j<mnmesh->f[which].deg; j++) box += mnmesh->P(mnmesh->f[which].vtx[j]) * tm;
		} else {
			for (int i=0; i<mnmesh->numf; i++) {
				if (mnmesh->f[i].GetFlag (MN_DEAD)) continue;
				if (!modData->GetFaceSel()[i]) continue;
				for (int j=0; j<mnmesh->f[i].deg; j++) box += mnmesh->P(mnmesh->f[i].vtx[j]) * tm;
			}
		}
	}
	Matrix3 ctm(1);
	ctm.SetTrans (box.Center());
	cb->TM (ctm,0);
}
Exemple #7
0
void VWeldMod::SetPolyFlags (MNMesh & mesh, DWORD flag) {
	// Convert existing selection (at whatever level) to vertex selection:
	mesh.ClearVFlags (flag);
	if (mesh.selLevel == MNM_SL_OBJECT) {
		for (int i=0; i<mesh.numv; i++) mesh.v[i].SetFlag (flag);
	} else {
		mesh.PropegateComponentFlags (MNM_SL_VERTEX, flag, mesh.selLevel, MN_SEL);
	}
}
void get_convex_hull(Mesh& mesh, Mesh& outmesh)
{  
	MNMesh mn;
	map<int, int> ptmap;
	vector<Vector3> vertmap;
	for (int i = 0; i < mesh.getNumVerts(); ++i)
	{
		Vector3 temp(mesh.getVert(i).x, mesh.getVert(i).y, mesh.getVert(i).z);
		vertmap.push_back(temp);
	}
	vector<Triangle> outshape = NifQHull::compute_convex_hull(vertmap);
	vector<Triangle>::size_type sz = outshape.size();
	for (int i = 0; i < mesh.getNumVerts(); ++i)
	{
		mn.NewVert(Point3(mesh.getVert(i).x, mesh.getVert(i).y, mesh.getVert(i).z));
	}
	for (unsigned i = 0; i < sz; i++)
	{
		mn.NewTri(outshape[i].v1, outshape[i].v2, outshape[i].v3);
	}
	mn.EliminateIsoMapVerts();
	mn.MakeConvex();
	mn.FillInMesh();
	mn.EliminateBadVerts(0);
	mn.Triangulate();
	mn.OutToTri(outmesh);
}
Exemple #9
0
void PolyOpChamferEdge::Do (MNMesh & mesh)
{
	MNChamferData *pMeshChamData = new MNChamferData;
	mesh.ChamferEdges (MN_USER, pMeshChamData);
	Tab<UVVert> mapDelta;
	for (int mapChannel = -NUM_HIDDENMAPS; mapChannel<mesh.numm; mapChannel++) {
		if (mesh.M(mapChannel)->GetFlag (MN_DEAD)) continue;
		pMeshChamData->GetMapDelta (mesh, mapChannel, mAmount, mapDelta);
		for (int i=0; i<mapDelta.Count(); i++) mesh.M(mapChannel)->v[i] += mapDelta[i];
	}

	Tab<Point3> vertexDelta;
	pMeshChamData->GetDelta (mAmount, vertexDelta);
	for (int i=0; i<vertexDelta.Count(); i++) mesh.P(i) += vertexDelta[i];
}
Exemple #10
0
void SymmetryMod::WeldPolyObject (MNMesh & mesh, Point3 & N, float offset, float threshold) {
	// Mark the vertices within the welding threshold of the plane:
	mesh.ClearVFlags (MN_USER);
	for (int i=0; i<mesh.numv; i++) {
		if (mesh.v[i].GetFlag (MN_DEAD)) continue;
		float dist = DotProd (N, mesh.P(i)) - offset;
		if (fabsf(dist) > threshold) continue;
		mesh.v[i].SetFlag (MN_USER);
	}

	// Do the welding:
	if (mesh.WeldBorderVerts (threshold, MN_USER)) {
		// If result was true, we have some MN_DEAD components:
		mesh.CollapseDeadStructs ();
	}
}
Exemple #11
0
void PolyOpWeldVertex::Do(MNMesh & mesh)
{
	// Weld the suitable border vertices:
	bool haveWelded = false;
	if (mesh.WeldBorderVerts (mThreshold, MN_USER)) {
		mesh.CollapseDeadStructs ();
		haveWelded = true;
	}

	// Weld vertices that share short edges:
	if (WeldShortPolyEdges (mesh, MN_USER)) haveWelded = true;

	if (haveWelded) {
		mesh.InvalidateTopoCache ();
		mesh.FillInMesh ();
	}
}
Exemple #12
0
void ConvertToPoly::Convert (TriObject *obj, TimeValue t, MNMesh & mm, Interval & ivalid) {
	int keepConvex;
	int limitSize;
	int maxdeg=0;
	int keepPlanar;
	float planarThresh = 0.0f;
	int elimCollin;

	pblock->GetValue (turn_keep_convex, t, keepConvex, ivalid);
	pblock->GetValue (turn_limit_size, t, limitSize, ivalid);
	if (limitSize) pblock->GetValue (turn_max_size, t, maxdeg, ivalid);
	pblock->GetValue (turn_planar, t, keepPlanar, ivalid);
	if (keepPlanar) {
		pblock->GetValue (turn_thresh, t, planarThresh, ivalid);
		planarThresh = cosf (planarThresh);
	}
	pblock->GetValue (turn_eliminate_collinear, t, elimCollin, ivalid);

	mm.AddTri (obj->mesh);
	mm.FillInMesh ();
	mm.EliminateBadVerts ();
	if (maxdeg != 3) {
		if (keepPlanar) mm.FenceNonPlanarEdges (planarThresh, TRUE);
		mm.MakePolyMesh (maxdeg, elimCollin);
		if (keepConvex) mm.MakeConvex ();
	}
	mm.ClearEFlags (MN_EDGE_INVIS);
	switch (obj->mesh.selLevel) {
	case MESH_VERTEX: mm.selLevel = MNM_SL_VERTEX; break;
	case MESH_EDGE: mm.selLevel = MNM_SL_EDGE; break;
	case MESH_FACE: mm.selLevel = MNM_SL_FACE; break;
	default: mm.selLevel = MNM_SL_OBJECT; break;
	}
}
Exemple #13
0
bool PolyOpWeldVertex::WeldShortPolyEdges (MNMesh & mesh, DWORD vertFlag) {
	// In order to collapse vertices, we turn them into edge selections,
	// where the edges are shorter than the weld threshold.
	bool canWeld = false;
	mesh.ClearEFlags (MN_USER);
	float threshSq = mThreshold*mThreshold;
	for (int i=0; i<mesh.nume; i++) {
		if (mesh.e[i].GetFlag (MN_DEAD)) continue;
		if (!mesh.v[mesh.e[i].v1].GetFlag (vertFlag)) continue;
		if (!mesh.v[mesh.e[i].v2].GetFlag (vertFlag)) continue;
		if (LengthSquared (mesh.P(mesh.e[i].v1) - mesh.P(mesh.e[i].v2)) > threshSq) continue;
		mesh.e[i].SetFlag (MN_USER);
		canWeld = true;
	}
	if (!canWeld) return false;

	return MNMeshCollapseEdges (mesh, MN_USER);
}
Exemple #14
0
void PolyOpRetriangulate::Do (MNMesh & mesh)
{
	int i;
	for (i=0; i<mesh.numf; i++) {
		if (mesh.f[i].GetFlag (MN_DEAD)) continue;
		if (!mesh.f[i].GetFlag (MN_USER)) continue;
		mesh.RetriangulateFace (i);
	}
}
void SMBrushSculpt::Proc(ViewExp *vpt, const SMHit &hit, IPoint2 &m, IPoint2 &lastm)
{
  if (!m_stroking || SMHit_hasNoFaceHit(hit))
    return;

  int startid = SMHit_getSOid(hit,m_subobj);
  Point3 startpos = hit.face.pos;

  MNMeshConVertBuffer *mcon = m_SM->GetMConVert();

  // compute affected + distances
  mcon->SeedSingle(m_subobj,startid,m_SM->m_brushsize,startpos,TRUE,m_SM->m_ip->SelectionFrozen());
  mcon->BuildAffectedSoft(m_SM->m_brushsize,startpos);
  mcon->AffectedDistWeights(hit.brushinner,hit.brush);

  // run sculpt
  MNMesh* mesh = m_SM->m_mesh;

  Point3  extrudedir = (m_SM->m_workplane.IsLocal()) ? mcon->GetAffectedNormal(TRUE) : m_SM->m_workplane.GetNormal();

  extrudedir *= m_dirsign * hit.pressure * m_speed;

  IMNMeshUtilities8* mesh8 = static_cast<IMNMeshUtilities8*>(mesh->GetInterface( IMNMESHUTILITIES8_INTERFACE_ID ));
  MNMeshConVertIter it;
  MNMeshConVertIter itend;
  mcon->GetIterators(it,itend);

  MESHCONVERT_IT_MASK(mcon->GetMasked())
    mesh->v[it->vid].p += extrudedir*it->dist;

  #if MAX_RELEASE >= 9000
    mesh8->InvalidateVertexCache(it->vid);
  #endif
  MESHCONVERT_IT_NORM
    mesh->v[it->vid].p += extrudedir*it->dist;
  #if MAX_RELEASE >= 9000
    mesh8->InvalidateVertexCache(it->vid);
  #endif
  MESHCONVERT_IT_END;

  // update draw geo
  MNMesh_updateDrawGeo(mesh,m_SM->m_polyobj);

}
Exemple #16
0
// (This code was copied from EditPolyObj::EpfnCollapse.)
bool VWeldMod::WeldShortPolyEdges (MNMesh & mesh, float thresh, DWORD flag) {
	// In order to collapse vertices, we turn them into edge selections,
	// where the edges are shorter than the weld threshold.
	bool canWeld = false;
	mesh.ClearEFlags (flag);
	float threshSq = thresh*thresh;
	for (int i=0; i<mesh.nume; i++) {
		if (mesh.e[i].GetFlag (MN_DEAD)) continue;
		if (!mesh.v[mesh.e[i].v1].GetFlag (flag)) continue;
		if (!mesh.v[mesh.e[i].v2].GetFlag (flag)) continue;
		if (LengthSquared (mesh.P(mesh.e[i].v1) - mesh.P(mesh.e[i].v2)) > threshSq) continue;
		mesh.e[i].SetFlag (flag);
		canWeld = true;
	}
	if (!canWeld) return false;

	MNMeshUtilities mmu(&mesh);
	return mmu.CollapseEdges (MN_USER);
}
Exemple #17
0
void SymmetryMod::MirrorPolyObject (MNMesh & mesh, int axis, Matrix3 & tm, Matrix3 & itm) {
	// Create scaling matrix for mirroring on selected axis:
	Point3 scale(1,1,1);
	scale[axis] = -1.0f;
	itm.Scale(scale,TRUE);

	// Make the mirror copy of the entire mesh:
	int oldnumv = mesh.numv;
	for (int i=0; i<mesh.numf; i++) mesh.f[i].SetFlag (MN_USER);
	mesh.CloneFaces (MN_USER, true);

	// Transform the vertices to their mirror images:
	for (int i=oldnumv; i<mesh.numv; i++) mesh.v[i].p = (itm*mesh.v[i].p)*tm;

	// Flip over faces, edges:
	mesh.FlipElementNormals (MN_USER);	// flag should now be set only on clones.

	DbgAssert (mesh.CheckAllData ());
}
Exemple #18
0
void PolyOpBevelFace::Do (MNMesh & mesh)
{
	// Topological extrusion first:
	MNChamferData chamData;
	if (mType<2) {
		MNFaceClusters fclust(mesh, MN_USER);
		if (!mesh.ExtrudeFaceClusters (fclust)) return;
		if (mType == 0) {
			// Get fresh face clusters:
			MNFaceClusters fclustAfter(mesh, MN_USER);
			Tab<Point3> clusterNormals, clusterCenters;
			fclustAfter.GetNormalsCenters (mesh, clusterNormals, clusterCenters);
			mesh.GetExtrudeDirection (&chamData, &fclustAfter, clusterNormals.Addr(0));
		} else {
			mesh.GetExtrudeDirection (&chamData, MN_USER);
		}
	} else {
		// Polygon-by-polygon extrusion.
		if (!mesh.ExtrudeFaces (MN_USER)) return;
		MNFaceClusters fclustAfter(mesh, MN_USER);
		Tab<Point3> clusterNormals, clusterCenters;
		fclustAfter.GetNormalsCenters (mesh, clusterNormals, clusterCenters);
		mesh.GetExtrudeDirection (&chamData, &fclustAfter, clusterNormals.Addr(0));
	}

	int i;
	if (mHeight) {
		for (i=0; i<mesh.numv; i++) mesh.v[i].p += chamData.vdir[i]*mHeight;
	}

	if (mOutline) {
		MNTempData temp(&mesh);
		Tab<Point3> *outDir;
		if (mType == 0) outDir = temp.OutlineDir (MESH_EXTRUDE_CLUSTER, MN_USER);
		else outDir = temp.OutlineDir (MESH_EXTRUDE_LOCAL, MN_USER);
		if (outDir && outDir->Count()) {
			Point3 *od = outDir->Addr(0);
			for (i=0; i<mesh.numv; i++) mesh.v[i].p += od[i]*mOutline;
		}
	}
}
Exemple #19
0
void ConvertToPoly::Convert (PatchObject *obj, TimeValue t, MNMesh & mm, Interval & ivalid) {
	int selConv, useSoftSel;
	int keepConvex, limitSize;
	int maxdeg=0;
	int keepPlanar;
	float planarThresh = 0.0f;
	int elimCollin;

	pblock->GetValue (turn_sel_type, t, selConv, ivalid);
	pblock->GetValue (turn_softsel, t, useSoftSel, ivalid);
	pblock->GetValue (turn_keep_convex, t, keepConvex, ivalid);
	pblock->GetValue (turn_limit_size, t, limitSize, ivalid);
	if (limitSize) pblock->GetValue (turn_max_size, t, maxdeg, ivalid);
	pblock->GetValue (turn_planar, t, keepPlanar, ivalid);
	if (keepPlanar) {
		pblock->GetValue (turn_thresh, t, planarThresh, ivalid);
		planarThresh = cosf (planarThresh);
	}
	pblock->GetValue (turn_eliminate_collinear, t, elimCollin, ivalid);

	DWORD flags=0;
	if (selConv != 1) {
		flags = CONVERT_KEEPSEL;
		if (useSoftSel) flags |= CONVERT_USESOFTSEL;
	}

	ConvertPatchToPoly (obj->patch, mm, flags);
	if (maxdeg) mm.RestrictPolySize (maxdeg);
	if (keepConvex) mm.MakeConvex ();
	if (keepPlanar) mm.MakePlanar (planarThresh);
	if (elimCollin) mm.EliminateCollinearVerts ();

	switch (obj->patch.selLevel) {
	case PATCH_VERTEX: mm.selLevel = MNM_SL_VERTEX; break;
	case PATCH_EDGE: mm.selLevel = MNM_SL_EDGE; break;
	case PATCH_PATCH: mm.selLevel = MNM_SL_FACE; break;
	default: mm.selLevel = MNM_SL_OBJECT; break;
	}
}
Exemple #20
0
void SymmetryMod::RemovePolySpurs (MNMesh & mesh) {
	// Make sure we don't have any "spurs".
	for (int i=0; i<mesh.numv; i++) {
		if (mesh.v[i].GetFlag (MN_DEAD)) continue;
		if (mesh.vedg[i].Count() != 1) continue;
		int vid = i;
		while ((!mesh.v[vid].GetFlag (MN_DEAD)) && (mesh.vedg[vid].Count() == 1)) {
			int edge = mesh.vedg[vid][0];
			int otherEnd = mesh.e[edge].OtherVert (vid);
			mesh.RemoveSpur (edge);
			// The other end might be a tip of a spur now:
			vid = otherEnd;
			if (vid == i) {	// shouldn't happen - extra check to prevent loops.
				DbgAssert (0);
				break;
			}
		}
	}
}
Exemple #21
0
float EditFaceDataModData::FaceValue (int faceID) {
	if (faceID<0) return 0.0f;
	if (faceID>mFacesAffected.GetSize()) return 0.0f;
	if (mFacesAffected[faceID]) return mtNewFaceValues[faceID];
	IFaceDataMgr *pFDMgr = NULL;
	if (mpCacheMesh && (faceID < mpCacheMesh->numFaces)) {
		// Get the face data manager from the mesh:
		pFDMgr = static_cast<IFaceDataMgr*>(mpCacheMesh->GetInterface (FACEDATAMGR_INTERFACE));
	}
	if (mpCacheMNMesh && (faceID < mpCacheMNMesh->numf)) {
		// Get the face data manager from the mesh:
		pFDMgr = static_cast<IFaceDataMgr*>(mpCacheMNMesh->GetInterface (FACEDATAMGR_INTERFACE));
	}
	if (pFDMgr == NULL) return 0.0f;
	SampleFaceData* fdc = dynamic_cast<SampleFaceData*>(pFDMgr->GetFaceDataChan( FACE_MAXSAMPLEUSE_CLSID ));
	if (!fdc) return 0.0f;
	float val;
	if (!fdc->GetValue (faceID, val)) return 0.0f;
	return val;
}
Exemple #22
0
void PolyOpExtrudeAlongSpline::Do (MNMesh & mesh) {
	if (mpSpline == NULL) return;
	
	Tab<Matrix3> tTransforms;
	theFrenetFinder.ConvertPathToFrenets (mpSpline, mSplineXfm, tTransforms,
		mSegments, mAlign?true:false, mRotation);

	// Apply taper and twist to transforms:
	float denom = float(tTransforms.Count()-1);
	for (int i=1; i<tTransforms.Count(); i++) {
		float amount = float(i)/denom;
		// This equation taken from Taper modifier:
		float taperAmount =	1.0f + amount*mTaper + mTaperCurve*amount*(1.0f-amount);
		if (taperAmount != 1.0f) {
			// Pre-scale matrix by taperAmount.
			tTransforms[i].PreScale (Point3(taperAmount, taperAmount, taperAmount));
		}
		if (mTwist != 0.0f) {
			float twistAmount = mTwist * amount;
			tTransforms[i].PreRotateZ (twistAmount);
		}
	}

	// Note:
	// If there are multiple face clusters, the first call to ExtrudeFaceClusterAlongPath
	// will bring mesh.numf and fClust.clust.Count() out of synch - fClust isn't updated.
	// So we fix that here.
	MNFaceClusters fClust (mesh, MN_USER);
	for (i=0; i<fClust.count; i++) {
		if (mesh.ExtrudeFaceClusterAlongPath (tTransforms, fClust, i, mAlign?true:false)) {
			if (i+1<fClust.count) {
				// New faces not in any cluster.
				int oldnumf = fClust.clust.Count();
				fClust.clust.SetCount (mesh.numf);
				for (int j=oldnumf; j<mesh.numf; j++) fClust.clust[j] = -1;
			}
		}
	}
}
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 ();
		}
	}
}
//ModifyObject will do all the work in a full modifier
//This includes casting objects to their correct form, doing modifications
//changing their parameters, etc
void ProjectionHolderUVW::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) 
{
	ObjectWrapper object;
	object.Init(t,*os,false, ObjectWrapper::allEnable, ObjectWrapper::triObject);

	if( object.IsEmpty() )
		return;

	// Check topology
	if( object.NumFaces() != mData.mFaces.Count() )
		return;
	
	for( int i=0; i<object.NumFaces(); i++ ) {
		GenFace face = object.GetFace(i);
		if( face.numVerts != mData.mFaces[i].numVerts )
			return;
	}

	if( mData.miMapChannel != VERTEX_CHANNEL_NUM ) {
		// Check Channel Support
		if( !object.GetChannelSupport(mData.miMapChannel) ) 
			object.SetChannelSupport( mData.miMapChannel, true );

		object.SetNumMapVerts( mData.miMapChannel, mData.mP3Data.Count() );

		for( int i=0; i<mData.mP3Data.Count(); i++ )
			object.SetMapVert( mData.miMapChannel, i, mData.mP3Data[i] );

		for( int i=0; i<mData.mFaces.Count(); i++ ) {
			object.SetMapFace( mData.miMapChannel, i, mData.mFaces[i] );
			// Material ID Support
			if( mData.mDoMaterialIDs )
				object.SetMtlID(i, mData.mMatID[i] );
		}

		os->obj->PointsWereChanged();
	}
	else {
		object.SetNumVerts( mData.mP3Data.Count() );

		for( int i=0; i<mData.mP3Data.Count(); i++ )
			object.SetVert( i, mData.mP3Data[i] );

		for( int i=0; i<mData.mFaces.Count(); i++ ) {
			object.SetFace( i, mData.mFaces[i] );
			// Material ID Support
			if( mData.mDoMaterialIDs )
				object.SetMtlID(i, mData.mMatID[i] );
		}

		os->obj->PointsWereChanged();
		if( object.Type() == ObjectWrapper::polyObject ) {
			MNMesh *poly = object.GetPolyMesh();
			if( poly )
				poly->FillInMesh();
		}
		else if( object.Type() == ObjectWrapper::triObject ) {
			Mesh *mesh = object.GetTriMesh();
			if( mesh )
				mesh->InvalidateTopologyCache();
		}
	}

	Interval iv;
	iv = FOREVER;
	iv &= mData.mSrcInterval;

	if( mData.miMapChannel > 0 ) 
		iv &= os->obj->ChannelValidity (t, TEXMAP_CHAN_NUM);
	else if( mData.miMapChannel == VERTEX_CHANNEL_NUM ) {
		iv &= os->obj->ChannelValidity(t,GEOM_CHAN_NUM);
		iv &= os->obj->ChannelValidity(t,TOPO_CHAN_NUM);
	}
	else
		iv &= os->obj->ChannelValidity(t,VERT_COLOR_CHAN_NUM);

	if( mData.miMapChannel > 0 ) 
		os->obj->UpdateValidity(TEXMAP_CHAN_NUM,iv);
	else if( mData.miMapChannel == VERTEX_CHANNEL_NUM ) {
		os->obj->UpdateValidity(GEOM_CHAN_NUM,iv);	
		os->obj->UpdateValidity(TOPO_CHAN_NUM,iv);	
	}
	else
		os->obj->UpdateValidity(VERT_COLOR_CHAN_NUM,iv);
}
void MeshTopoData::ApplyMapping(MNMesh &mesh, int mapChannel)
{
	// allocate texture verts. Setup tv faces into a parallel
	// topology as the regular faces
	int numMaps = mesh.MNum ();
	if (mapChannel >= numMaps) 
	{
		mesh.SetMapNum(mapChannel+1);
		mesh.InitMap(mapChannel);
	}

	MNMapFace *tvFace = mesh.M(mapChannel)->f;

	if (!tvFace)
	{
		mesh.InitMap(mapChannel);
		tvFace = mesh.M(mapChannel)->f;
	}

	int tvFaceCount =  mesh.FNum();

	if (mesh.selLevel!=MNM_SL_FACE) 
	{
		//copy into mesh struct

		for (int k=0; k<tvFaceCount; k++) 
		{
			if (k < TVMaps.f.Count())
			{
				for (int m = 0; m< TVMaps.f[k]->count; m++) 
					tvFace[k].tv[m] = TVMaps.f[k]->t[m];
			}
			else 
			{
				for (int m = 0; m< TVMaps.f[k]->count; m++) 
					tvFace[k].tv[m] = 0;
			}
		}
		//match verts
		mesh.M(mapChannel)->setNumVerts( TVMaps.v.Count());
		Point3 *tVerts = mesh.M(mapChannel)->v;
		for ( int k=0; k<TVMaps.v.Count(); k++) 
		{
			tVerts[k] = GetTVVert(k);
		}


	}
	else
	{
		//copy into mesh struct
		//check if mesh has existing tv faces
		int offset = mesh.M(mapChannel)->VNum();
		int current = 0;
		BitArray s;
		mesh.getFaceSel(s);
		for (int k=0; k<tvFaceCount; k++) 
		{
			//copy if face is selected
			if (s[k]==1)
			{
				for (int m = 0; m< TVMaps.f[k]->count; m++) 
					tvFace[k].tv[m] = TVMaps.f[k]->t[m] + offset;
			}
		}
		//add our verts
		for ( int k=0; k<TVMaps.v.Count(); k++) 
			mesh.M(mapChannel)->NewVert( GetTVVert(k));
	}
	mesh.M(mapChannel)->CollapseDeadVerts(mesh.f);
}
void MeshTopoData::SetCache(MNMesh &mesh, int mapChannel)
{
	FreeCache();
	this->mnMesh = new MNMesh(mesh);


	TVMaps.channel = mapChannel;

	BitArray s;
	mesh.getFaceSel(s);
	mesh.getFaceSel(mFSelPrevious);

	if ( (mesh.selLevel==MNM_SL_FACE) && (s == 0) ) 
	{
		TVMaps.SetCountFaces(0);
		TVMaps.v.SetCount(0);
		TVMaps.FreeEdges();
		TVMaps.FreeGeomEdges();
		mVSel.SetSize(0);
		mESel.SetSize(0);
		mFSel.SetSize(0);
		mGESel.SetSize(0);
		mGVSel.SetSize(0);
		return;
	}


	//get from mesh based on cahne
	int numMaps = mesh.MNum ();
	MNMapFace *tvFace=NULL;
	Point3 *tVerts = NULL;
	if (mapChannel >= numMaps) 
	{
	}
	else
	{
		tvFace = mesh.M(mapChannel)->f;
		tVerts = mesh.M(mapChannel)->v;
	}

	if (mesh.selLevel!=MNM_SL_FACE) 
	{
		//copy into our structs
		TVMaps.SetCountFaces(mesh.FNum());
		if (tVerts)
		{
			TVMaps.v.SetCount(mesh.M(mapChannel)->VNum());
			mVSel.SetSize(mesh.M(mapChannel)->VNum());
		}
		else
		{
			TVMaps.v.SetCount(mesh.VNum());
			mVSel.SetSize(mesh.VNum());
		}


		TVMaps.geomPoints.SetCount(mesh.VNum());

		for (int j=0; j<TVMaps.f.Count(); j++) 
		{
			TVMaps.f[j]->flags = 0;
			int fct;
			fct = mesh.f[j].deg;

			if (mesh.f[j].GetFlag(MN_DEAD)) fct = 0;

			if (fct > 0)
			{
				TVMaps.f[j]->t = new int[fct];
				TVMaps.f[j]->v = new int[fct];
			}
			else
			{
				TVMaps.f[j]->t = NULL;
				TVMaps.f[j]->v = NULL;
			}

			if (tvFace == NULL)
			{
				for (int k=0; k < fct;k++)
					TVMaps.f[j]->t[k] = 0;
				TVMaps.f[j]->FaceIndex = j;
				TVMaps.f[j]->MatID = mesh.f[j].material;
				TVMaps.f[j]->flags = 0;
				TVMaps.f[j]->count = fct;
				for (int k = 0; k < fct; k++)
				{
					int index = mesh.f[j].vtx[k];
					TVMaps.f[j]->v[k] = index;
					TVMaps.geomPoints[index] = mesh.v[index].p;
				}
			}
			else
			{
				for (int k=0; k < fct;k++)
					TVMaps.f[j]->t[k] = tvFace[j].tv[k];
				TVMaps.f[j]->FaceIndex = j;
				TVMaps.f[j]->MatID = mesh.f[j].material;


				TVMaps.f[j]->flags = 0;
				TVMaps.f[j]->count = fct;
				for (int k = 0; k < fct; k++)
				{
					int index = mesh.f[j].vtx[k];
					TVMaps.f[j]->v[k] = index;
					TVMaps.geomPoints[index] = mesh.v[index].p;
				}


			}
		}
		for ( int j=0; j<TVMaps.v.Count(); j++) 
		{
			TVMaps.v[j].SetFlag(0);
			if (tVerts)
				TVMaps.v[j].SetP(tVerts[j]);
			else TVMaps.v[j].SetP(Point3(.0f,0.0f,0.0f));
			TVMaps.v[j].SetInfluence(0.0f);
			TVMaps.v[j].SetControlID(-1);
		}
		if (tvFace == NULL) BuildInitialMapping(&mesh);

		TVMaps.mSystemLockedFlag.SetSize(TVMaps.v.Count());
		TVMaps.mSystemLockedFlag.ClearAll();

	}
	else
	{
		//copy into our structs
		TVMaps.SetCountFaces(mesh.FNum());

		int tvVertCount = 0;
		if (mapChannel < numMaps) 
		{
			tvVertCount = mesh.M(mapChannel)->VNum();
		}

		TVMaps.v.SetCount(tvVertCount);

		mVSel.SetSize(tvVertCount);

		TVMaps.geomPoints.SetCount(mesh.VNum());

		BitArray bs;
		mesh.getFaceSel(bs);

		for (int j=0; j<TVMaps.f.Count(); j++) 
		{
			TVMaps.f[j]->flags = 0;

			int fct;
			fct = mesh.f[j].deg;

			if (mesh.f[j].GetFlag(MN_DEAD)) fct = 0;


			if (fct > 0)
			{			
				TVMaps.f[j]->t = new int[fct];
				TVMaps.f[j]->v = new int[fct];
			}
			else
			{
				TVMaps.f[j]->t = NULL;
				TVMaps.f[j]->v = NULL;
			}

			if (tvFace == NULL)
			{
				for (int k=0; k < fct;k++)
					TVMaps.f[j]->t[k] = 0;
				TVMaps.f[j]->FaceIndex = j;
				TVMaps.f[j]->MatID = mesh.f[j].material;
				TVMaps.f[j]->count = fct;
				if (bs[j])
					TVMaps.f[j]->flags = 0;
				else TVMaps.f[j]->flags = FLAG_DEAD;
				for (int k = 0; k < fct; k++)
				{
					int index = mesh.f[j].vtx[k];
					TVMaps.f[j]->v[k] = index;
					TVMaps.geomPoints[index] = mesh.v[index].p;
				}
			}
			else
			{
				for (int k=0; k < fct;k++)
					TVMaps.f[j]->t[k] = tvFace[j].tv[k];
				TVMaps.f[j]->FaceIndex = j;
				TVMaps.f[j]->MatID = mesh.f[j].material;
				TVMaps.f[j]->count = fct;
				if (bs[j])
					TVMaps.f[j]->flags = 0;
				else TVMaps.f[j]->flags = FLAG_DEAD;
				for ( int k = 0; k < fct; k++)
				{
					int index = mesh.f[j].vtx[k];
					TVMaps.f[j]->v[k] = index;
					TVMaps.geomPoints[index] = mesh.v[index].p;
				}

			}
		}



		for (int j=0; j<TVMaps.v.Count(); j++) 
		{
			if (tVerts)
				TVMaps.v[j].SetP(tVerts[j]);
			else TVMaps.v[j].SetP(Point3(0.0f,0.0f,0.0f));
			//check if vertex for this face selected
			TVMaps.v[j].SetInfluence(0.0f);
			TVMaps.v[j].SetControlID(-1);

		}
		if (tvFace == NULL) BuildInitialMapping(&mesh);

		TVMaps.mSystemLockedFlag.SetSize(TVMaps.v.Count());
		TVMaps.mSystemLockedFlag.SetAll();

		for (int j=0; j<TVMaps.f.Count(); j++) 
		{
			if (!(TVMaps.f[j]->flags & FLAG_DEAD))
			{
				int a;
				for (int k =0 ; k < TVMaps.f[j]->count;k++)
				{
					a = TVMaps.f[j]->t[k];
					TVMaps.v[a].SetFlag(0);
					TVMaps.mSystemLockedFlag.Set(a,FALSE);
				}
			}
		}
	}
}
void FaceDataToColorMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) {
	if (mDisabled) return;

	IFaceDataMgr* pFDMgr = NULL;

	// We can work with Face Data in a couple different object types:
	TriObject *pTri = NULL;
	PolyObject *pPoly = NULL;
	Mesh *pMesh = NULL;
	MNMesh *pMNMesh = NULL;
	int numFaces = 0;

	if (os->obj->IsSubClassOf(triObjectClassID)) {
		pTri = (TriObject*)os->obj;
		pMesh = &(pTri->GetMesh());
		numFaces = pMesh->getNumFaces();
		// Get the face-data manager from the incoming object
		pFDMgr = static_cast<IFaceDataMgr*>(pMesh->GetInterface( FACEDATAMGR_INTERFACE ));
	} else if (os->obj->IsSubClassOf(polyObjectClassID)) {
		pPoly = (PolyObject*)os->obj;
		pMNMesh = &pPoly->GetMesh();
		numFaces = pMNMesh->numf;
		// Get the face-data manager from the incoming object
		pFDMgr = static_cast<IFaceDataMgr*>(pMNMesh->GetInterface( FACEDATAMGR_INTERFACE ));
	}

	if (pFDMgr == NULL) return;

	//Get our parameters
	int channel;
	float r, g, b;
	Interval ourValidity = os->obj->ChannelValidity (t, TOPO_CHAN_NUM);
	mpParams->GetValue (pb_channel, t, channel, ourValidity);
	mpParams->GetValue (pb_red, t, r, ourValidity);
	mpParams->GetValue (pb_green, t, g, ourValidity);
	mpParams->GetValue (pb_blue, t, b, ourValidity);

	// Get at our SampleFaceData:
	SampleFaceData *pFaceData = dynamic_cast<SampleFaceData *>(pFDMgr->GetFaceDataChan (FACE_MAXSAMPLEUSE_CLSID));

	// Apply the colors - different code depending on object type:
	if (pMesh) {
		pMesh->setMapSupport (-channel, true);
		pMesh->setNumMapVerts (-channel, 3*numFaces);
		TVFace *pFace = pMesh->mapFaces(-channel);
		VertColor *pColor = pMesh->mapVerts (-channel);

		int maxFaceData = pFaceData ? pFaceData->Count() : 0;

		for (int i=0; i<numFaces; i++) {
			for (int j=0; j<3; j++) {
				int k = i*3+j;
				pFace[i].t[j] = k;
				if (i<maxFaceData) {
					float fdValue = pFaceData->data[i];
					VertColor val;
					val.x = r*fdValue;
					if (val.x < 0) val.x = 0.0f;
					if (val.x > 1) val.x = 1.0f;
					val.y = g*fdValue;
					if (val.y < 0) val.y = 0.0f;
					if (val.y > 1) val.y = 1.0f;
					val.z = b*fdValue;
					if (val.z < 0) val.z = 0.0f;
					if (val.z > 1) val.z = 1.0f;
					pColor[k] = val;
				} else pColor[k] = VertColor(0,0,0);
			}
		}
	}

	if (pMNMesh) {
		if ((channel == 0) && (pMNMesh->numm == 0)) pMNMesh->SetMapNum (1);
		pMNMesh->M(-channel)->ClearFlag (MN_DEAD);
		pMNMesh->M(-channel)->setNumFaces (numFaces);

		// Precount the number of map vertices we need:
		int numColors = 0;
		for (int i=0; i<numFaces; i++) {
			if (pMNMesh->f[i].GetFlag (MN_DEAD)) continue;
			numColors += pMNMesh->f[i].deg;
		}
		pMNMesh->M(-channel)->setNumVerts (numColors);

		MNMapFace *pFace = pMNMesh->M(-channel)->f;
		VertColor *pColor = pMNMesh->M(-channel)->v;

		int maxFaceData = pFaceData ? pFaceData->Count() : 0;

		for (int i=0, k = 0; i<numFaces; i++) {
			if (pMNMesh->f[i].GetFlag (MN_DEAD)) continue;
			pFace[i].SetSize (pMNMesh->f[i].deg);
			for (int j=0; j<pMNMesh->f[i].deg; j++) {
				pFace[i].tv[j] = k;
				if (i<maxFaceData) {
					float fdValue = pFaceData->data[i];
					VertColor val;
					val.x = r*fdValue;
					if (val.x < 0) val.x = 0.0f;
					if (val.x > 1) val.x = 1.0f;
					val.y = g*fdValue;
					if (val.y < 0) val.y = 0.0f;
					if (val.y > 1) val.y = 1.0f;
					val.z = b*fdValue;
					if (val.z < 0) val.z = 0.0f;
					if (val.z > 1) val.z = 1.0f;
					pColor[k] = val;
				} else pColor[k] = VertColor(0,0,0);
				k++;
			}
		}
	}

	os->obj->SetChannelValidity (VERT_COLOR_CHAN_NUM, ourValidity);
}
	//------------------------------
	bool MorphControllerCreator::initializeChannelGeometry( morphChannel* channel, Object* geometryObject )
	{
		if ( !channel || !geometryObject )
		{
			return false;
		}

		Class_ID geometryObjectClassId = geometryObject->ClassID();
	
		MNMesh* polyMesh = 0;
		Mesh* triangleMesh = 0;
	
		if ( (geometryObjectClassId == EPOLYOBJ_CLASS_ID)  || (geometryObjectClassId.PartA() == POLYOBJ_CLASS_ID) )
		{
			polyMesh = &((PolyObject*)geometryObject)->GetMesh();
		}
		else if ( (geometryObjectClassId.PartA() == TRIOBJ_CLASS_ID) || (geometryObjectClassId.PartA() == EDITTRIOBJ_CLASS_ID ) )
		{
			triangleMesh = &((TriObject*)geometryObject)->GetMesh();
		}

		if ( !polyMesh && !triangleMesh )
		{
			// unsupported object type
			return true;
		}

		// Verify that the COLLADA source size matches the original mesh's vertex count
		int vertexCount = polyMesh ? polyMesh->VNum() : triangleMesh->numVerts;
		if (vertexCount != channel->mp->cache.count) 
		{
			return false;
		}

		// Set the channel's name and the necessary flags
		channel->mName = getObjectNameByObject(geometryObject).c_str();
		channel->mInvalid = false;
		channel->mActive = true;
		channel->mModded = true;


		// Allocate the channel's buffers and fill them with the relative vertex positions
		channel->AllocBuffers(vertexCount, vertexCount);
		channel->mSel.SetSize(vertexCount);
		channel->mSel.ClearAll();
		channel->mNumPoints = vertexCount;

		if ( polyMesh )
		{
			for (int i = 0; i < vertexCount; ++i)
			{
				channel->mPoints[i] = polyMesh->V( i )->p;
				channel->mDeltas[i] = (channel->mPoints[i] - channel->mp->cache.points[i]) / 100.0f;
				channel->mSel.Set(i, false);
				channel->mWeights[i] = 1.0f; // Not too sure of what the value should be here.
			}
		}
		else 
		{
			for (int i = 0; i < vertexCount; ++i)
			{
				channel->mPoints[i] = triangleMesh->verts[ i ];
				channel->mDeltas[i] = (channel->mPoints[i] - channel->mp->cache.points[i]) / 100.0f;
				channel->mSel.Set(i, false);
				channel->mWeights[i] = 1.0f; // Not too sure of what the value should be here.
			}
		}

		// Update all the UI stuff. Important? Must it be done for every channel?
		channel->mp->NotifyDependents(FOREVER,(PartID) PART_ALL,REFMSG_CHANGE);
		channel->mp->NotifyDependents(FOREVER,(PartID) PART_ALL,REFMSG_SUBANIM_STRUCTURE_CHANGED);
		channel->mp->Update_channelFULL();
		channel->mp->Update_channelParams();

		return true;
	}
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;
}
Exemple #30
0
void SelectByChannel::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) 
{
	//TODO: Add the code for actually modifying the object

	//get th map id

	
//	TriObject *tobj = (TriObject*)os->obj;
//	Mesh &mesh = tobj->GetMesh();		

	Mesh *mesh = NULL;
	MNMesh *mnmesh = NULL;
		
	TriObject *collapsedtobj = NULL;
	if (os->obj->IsSubClassOf(triObjectClassID))
	{
		TriObject *tobj = (TriObject*)os->obj;
		mesh = &tobj->GetMesh();
	}
	else if (os->obj->IsSubClassOf(polyObjectClassID))
	{
		PolyObject *pobj = (PolyObject*)os->obj;
		mnmesh = &pobj->GetMesh();
	}



	int mapID;
	int subID;

	int selType;

	pblock->GetValue(pb_mapid,0,mapID,FOREVER);
	pblock->GetValue(pb_mapsubid,0,subID,FOREVER);

	pblock->GetValue(pb_seltype,0,selType,FOREVER);

	if (subID < 0) subID = 0;
	if (subID > 2) subID = 2;
	
	
	if (mnmesh)
	{
		
		int numMaps = mnmesh->numm;

		mnmesh->dispFlags = MNDISP_VERTTICKS|MNDISP_SELVERTS ;
		mnmesh->selLevel = MNM_SL_VERTEX;

		if (mapID < numMaps)
		
		{
			UVVert *uvw = mnmesh->M(mapID)->v;
			MNMapFace *uvwFace = mnmesh->M(mapID)->f;
			if (uvw && uvwFace)
				
			{
				float *vsw = NULL;

				MNFace *face = mnmesh->f;

					

				vsw = mnmesh->getVSelectionWeights ();

				if (vsw == NULL)
				{
					mnmesh->SupportVSelectionWeights();
					vsw = mnmesh->getVSelectionWeights ();
				}

				BitArray processed;
				processed.SetSize(mnmesh->numv);
				processed.ClearAll();

				if (vsw && uvwFace && uvw)
				{
					if (selType == 0)
					{
						mnmesh->ClearVFlags (MN_SEL);
						for (int i = 0; i < mnmesh->numv; i++)
							vsw[i] = 0.0f;
					}

					for (int i = 0; i < mnmesh->numf; i++)
					{
						int deg = face[i].deg;
						for (int j = 0; j < deg; j++)
						{
							
							int index = uvwFace[i].tv[j];
							int gindex = face[i].vtx[j];
							if (!processed[gindex])
							{
								processed.Set(gindex);
								if (selType == 0)
								{	
									float w = uvw[index][subID];
									if (w >= 1.0f)
										mnmesh->v[gindex].SetFlag (MN_SEL);
//										mesh.vertSel.Set(gindex);
									else vsw[gindex] = uvw[index][subID];
								}
								else if (selType == 1)
								{	
									float w = uvw[index][subID];
									w += vsw[gindex];
									if (w >= 1.0f)
										mnmesh->v[gindex].SetFlag (MN_SEL);
//										mesh.vertSel.Set(gindex);
									else vsw[gindex] = uvw[index][subID];
								}
								else if (selType == 2)
								{	
									float w = uvw[index][subID];
									if (mnmesh->v[gindex].GetFlag (MN_SEL))//(mesh.vertSel[gindex])
										w = 1.0f - w;
									else w = vsw[gindex] - w;;
									if (w < 1.0f)
										mnmesh->v[gindex].ClearFlag (MN_SEL);
//										mesh.vertSel.Set(gindex,FALSE);
									vsw[gindex] = w;
								}
							}

						}
					}
				}
			}

		}
		
	}

	else if (mesh)
	{
		mesh->dispFlags = DISP_VERTTICKS|DISP_SELVERTS;
		mesh->selLevel = MESH_VERTEX;

		if (mesh->mapSupport(mapID))
		{
			UVVert *uvw = mesh->mapVerts(mapID);
			TVFace *uvwFace = mesh->mapFaces(mapID);	
			float *vsw = NULL;

			Face *face = mesh->faces;

				

			vsw = mesh->getVSelectionWeights ();

			if (vsw == NULL)
			{
				mesh->SupportVSelectionWeights();
				vsw = mesh->getVSelectionWeights ();
			}

			BitArray processed;
			processed.SetSize(mesh->numVerts);
			processed.ClearAll();

			if (vsw && uvwFace && uvw)
			{
				if (selType == 0)
				{
					mesh->vertSel.ClearAll();
					for (int i = 0; i < mesh->numVerts; i++)
						vsw[i] = 0.0f;
				}

				for (int i = 0; i < mesh->numFaces; i++)
				{
					for (int j = 0; j < 3; j++)
					{
						
						int index = uvwFace[i].t[j];
						int gindex = face[i].v[j];
						if (!processed[gindex])
						{
							processed.Set(gindex);
							if (selType == 0)
							{	
								float w = uvw[index][subID];
								if (w >= 1.0f)
									mesh->vertSel.Set(gindex);
								else vsw[gindex] = uvw[index][subID];
							}
							else if (selType == 1)
							{	
								float w = uvw[index][subID];
								w += vsw[gindex];
								if (w >= 1.0f)
									mesh->vertSel.Set(gindex);
								else vsw[gindex] = uvw[index][subID];
							}
							else if (selType == 2)
							{	
								float w = uvw[index][subID];
								if (mesh->vertSel[gindex])
									w = 1.0f - w;
								else w = vsw[gindex] - w;;
								if (w < 1.0f)
									mesh->vertSel.Set(gindex,FALSE);
								vsw[gindex] = w;
							}
						}

					}
				}
			}

		}
	}
	


	Interval iv;
	iv = FOREVER;

	os->obj->PointsWereChanged();

	iv = iv & os->obj->ChannelValidity(t,GEOM_CHAN_NUM);
	iv = iv & os->obj->ChannelValidity(t,TOPO_CHAN_NUM);
	iv = iv & os->obj->ChannelValidity(t,SELECT_CHAN_NUM);

	os->obj->UpdateValidity (SELECT_CHAN_NUM, iv);


}