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; } }
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; }
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); }
void SymmetryMod::SlicePolyObject (MNMesh & mesh, Point3 & N, float offset) { // Steve Anderson 9/14/2002 // Using the new "MN_MESH_TEMP_1" flag to override Slice selection behavior, // which is undesirable here. mesh.SetFlag (MN_MESH_TEMP_1); // Slice off everything below the plane: mesh.Slice (N, offset, MNEPS, false, true); mesh.ClearFlag (MN_MESH_TEMP_1); // Make sure we have a valid edge list: if (!mesh.GetFlag (MN_MESH_FILLED_IN)) mesh.FillInMesh(); // Mark the vertices on the plane boundary: 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) > MNEPS) continue; mesh.v[i].SetFlag (MN_USER); } // Strip out faces on the mirror plane: (These aren't always removed by slice.) // Find the faces that use only mirror-plane vertices: mesh.ClearFFlags (MN_USER); mesh.PropegateComponentFlags (MNM_SL_FACE, MN_USER, MNM_SL_VERTEX, MN_USER, true); mesh.DeleteFlaggedFaces (MN_USER); // Clear out dead components: mesh.CollapseDeadStructs (); }
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 (); } }
//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); }