Class MNMesh

3DS Max Plug-In SDK

Class MNMesh

See Also: Class FlagUser, Class MNFace, Class MNVert, Class MNEdge, Class MNMap, Class PerData, Class MNMeshBorder, Class Mesh, Class BitArray, Template Class Tab, MNMesh Note on Edge Characteristics, Class MNMeshBorder, MNMesh Notes on Debugging.

class MNMesh : public FlagUser, public BaseInterfaceServer

Description:

This class is available in release 2.0 and later only.

The MNMesh class is provided for temporary use by plug-ins, to help with complex topology-based modifications to Meshes. It has certain capabilities, such as the ability to recognize faces with more than 3 sides, that are useful in some applications. It is not suitable for use as a pipeline object. All methods of this class are implemented by the system.

MNMesh has a winged-edge structure and a highly interlinked topology. This is very useful for some modifiers, but requires far more memory & processing time than an equivalent normal mesh. It's convenient for the programmer, but may be sluggish for the user.

Although some methods can be a bit slow, none of them are non-linear in the amount of time they take. Even the tessellation algorithms, which can as much as quadruple the size of the meshes, operate locally, vertex by vertex, so they are order-of-n algorithms.

Note: You must #include "MNMATH.H" to use this class as it's not included by default by MAX.H.

Methods Groups:

The hyperlinks below take you to the start of groups of related methods within the class:

 

Initialization & Cleanup

Access to mesh components

Adding new components

Removing & deleting components

Internal computation

Component Targeting & Flag methods

Component information methods

Smoothing-group & Material methods

Face-joining methods

Splitting methods

Border methods

Tessellation & related methods

Welding methods

Boolean operations

Debugging methods

Operators

Data Members:

public:

MNVert *v;

This data member is available in release 3.0 and later only.

The array of MNMesh verticies.

MNEdge *e;

This data member is available in release 3.0 and later only.

The array of MNMesh edges.

MNFace *f;

This data member is available in release 3.0 and later only.

The array of MNMesh faces.

int numv

This data member is available in release 3.0 and later only.

The number of MNVerts in v.

int nume

This data member is available in release 3.0 and later only.

The number of MNEdges in e.

int numf

This data member is available in release 3.0 and later only.

The number of MNFaces in f.

int numm;

This data member is available in release 3.0 and later only.

The number of MNMaps in m.

PerData *vd;

This data member is available in release 3.0 and later only.

The array of PerData objects which maintain and provide access to the floating point vertex data. There is one of these for each supported channel. PerData objects are used to store such information as vertex weighting and weighted selections.

BitArray vdSupport;

This data member is available in release 3.0 and later only.

This bit array indicates if a particular vertex data channel is supported in this MNMesh. If the bit is set the channel is suported.

PerData *ed;

This data member is available in release 3.0 and later only.

The array of PerData objects which maintain and provide access to the floating point edge data. There is one of these for each supported channel. One PerData object store edge weighting for NURMS-type MeshSmooths.

BitArray edSupport;

This data member is available in release 3.0 and later only.

This bit array indicates if a particular edge data channel is supported in this MNMesh. If the bit is set the channel is suported.

DWORD selLevel;

This data member is available in release 3.0 and later only. Note however that, since MNMeshes are not yet used as pipeline objects, the subobject selection methods are not yet used in 3ds max. Third party developers are welcome to use these methods themselves, but they should be aware that this is a work-in-progress.

The current MNMesh selection level. One of the following values:

MNM_SL_OBJECT - object level selection.

MNM_SL_VERTEX - select vertices

MNM_SL_EDGE - select edges

MNM_SL_FACE - select polygon faces

DWORD dispFlags;

This data member is available in release 3.0 and later only. Note however that, since MNMeshes are not yet used as pipeline objects, the display methods and flags are not yet used in 3ds max. Third party developers are welcome to use the display methods themselves, but they should be aware that this is a work-in-progress.

The display flags. One or more of the following values:

MNDISP_VERTTICKS - Display vertex tick marks.

MNDISP_SELVERTS - Display selected verticies.

MNDISP_SELFACES - Display selected faces.

MNDISP_SELEDGES - Display selected edges.

MNDISP_NORMALS - Display face normals.

MNDISP_SMOOTH_SUBSEL - Analogous to the Mesh display flag MESH_SMOOTH_SUBSEL, this indicates whether we should display smooth faces with selection-color outlines (TRUE) or transparent shaded faces (FALSE).

MNDISP_BEEN_DISP - Set when the MNMesh has been displayed (at the end of the render method.)

MNDISP_DIAGONALS – Set when diagonals should be displayed.

Tab<int> *vedg;

This data member is available in release 3.0 and later only.

This is an array of int Tabs that records which edges use each vertex. For instance, if edges 3, 5, and 6 have an endpoint at vertex 0, vedg[0] would include 3, 5, and 6, though not in any particular order. This replaces the 2.5 MNVert::edg data member. Note that this information is only valid if the MN_MESH_FILLED_IN flag is set.

Tab<int> *vfac;

This data member is available in release 3.0 and later only.

This is an array of int Tabs that records which faces touch each vertex. For instance, if faces 0, 1, 3, 8, and 9 use vertex 0 as one of their corners, vfac[0] would include 0, 1, 3, 8, and 9, though not in any particular order. This replaces the 2.5 MNVert::fac data member. Note that this information is only valid if the MN_MESH_FILLED_IN flag is set.

Flags:

For more information on flags, see Class FlagUser.

MN_MESH_NONTRI

If set, this mesh's faces are not all triangles -- at least one face has more than 3 sides.

MN_MESH_FILLED_IN

If set, all topological links, such as the list of edges, are complete.

MN_MESH_RATSNEST

Some regular Meshes have more than two faces referencing the same edge, or more than one referencing it in the same direction. These are termed "rats' nest meshes". Since our edge structure only permits 1 or 2 faces (one in each direction), these meshes are unacceptable. Upon conversion, certain vertices & edges are replicated (increasing the vertex count) to separate these into regular, non-rats'-nest parts. If this happens, this flag is set to let you know this change has occurred. In particular, converting this MNMesh back into a regular Mesh will produce a Mesh with more vertices than you started with.

MN_MESH_NO_BAD_VERTS

This indicates that the mesh has had its vertices checked and "bad" ones eliminated by EliminateBadVerts .

MN_MESH_VERTS_ORDERED

This indicates that the mesh has had its vertices ordered by the method OrderVerts.

MN_MESH_HAS_VOLUME

This flag is available in release 2.5 or later only.

This mesh has at least one connected component which contains volume, i.e. represents a solid object with no gaps or holes. The flag is set by the MNMesh::FindOpenRegions() method.

MN_USER(1<<16)

Flag bits at or above MN_USER are reserved in all MNMesh components for the plug-in developer, if needed. Since FlagUser-derived classes have 32 flag bits, this allows for up to 16 user-defined flags.

Methods:

Initialization & Cleanup

Prototype:

MNMesh();

Remarks:

Constructor. Initializes the MNMesh with no components and the default flags.

Prototype:

MNMesh(Mesh &from);

Remarks:

Constructor. Initializes the MNMesh with the mesh "from", and fills in the topology completely (using FillInMesh).

Prototype:

MNMesh(const MNMesh &from);

Remarks:

This method is available in release 3.0 and later only.

Copy constructor.

Prototype:

~MNMesh();

Remarks:

Destructor. Frees all allocated memory (using Clear).

Prototype:

MNMap *M(int mp) const;

Remarks:

This method is available in release 4.0 and later only.

Access to the MNMaps in each MNMesh is made private. Instead of using the MNMap *m data member, you must now use this accessor method. This accessor now accepts a value in the range -NUM_HIDDENMAPS to MNum().

Parameters:

int mp

The map channel

Prototype:

void DefaultFlags();

Remarks:

Clears all flags.

Prototype:

void Init();

Remarks:

This method is available in release 3.0 and later only.

The data members are initialized as follows:

nv_alloc = ne_alloc = nf_alloc = nm_alloc = 0;

numv = nume = numf = numm = 0;

v = NULL;

e = NULL;

f = NULL;

m = NULL;

vd = NULL;

ed = NULL;

vedg = NULL;

vfac = NULL;

bdgBox.Init();

fnorm = NULL;

dispFlags = 0;

rVerts = NULL;

cacheGW = NULL;

normalsBuilt = 0;

norScale = 0.0f;

selLevel = MNM_SL_OBJECT;

Prototype:

void VAlloc(int num, bool keep=TRUE);

Remarks:

This method is available in release 3.0 and later only.

Allocates and inits the specified number of MNVerts.

Parameters:

int num

The number of verts to allocate.

bool keep=TRUE

If TRUE any previous verts are kept; otherwise they are discarded.

Prototype:

void VShrink(int num=-1);

Remarks:

This method is available in release 3.0 and later only.

Shrinks the nv_alloc size of the MNVert array to the specified size.

Parameters:

int num=-1

The new size of the array. The default -1 means to shrink array allocation to numv.

Prototype:

void freeVEdge();

Remarks:

This method is available in release 3.0 and later only.

Deallocates any MNEdges in the vedg table and sets the vedg pointer to NULL.

Prototype:

void VEdgeAlloc();

Remarks:

This method is available in release 3.0 and later only.

Allocates the vedg array.

Prototype:

void freeVFace();

Remarks:

This method is available in release 3.0 and later only.

Deallocates the vfac array.

Prototype:

void VFaceAlloc();

Remarks:

This method is available in release 3.0 and later only.

Allocates the vfac array.

Prototype:

void EAlloc(int num, bool keep=TRUE);

Remarks:

This method is available in release 3.0 and later only.

Allocates the MNEdge data array e with the specified size.

Parameters:

int num

The number of MNEdges to allocate.

bool keep=TRUE

If TRUE any previously allocated edges are kept; otherwise they are discarded.

Prototype:

void EShrink(int num=-1);

Remarks:

This method is available in release 3.0 and later only.

Reduces the ne_alloc size of the MNEdge data array e to the specified number of elements.

Parameters:

int num=-1

The new size for the array. The value -1 means to use the current number of edges, nume.

Prototype:

void FAlloc(int num, bool keep=TRUE);

Remarks:

This method is available in release 3.0 and later only.

Allocates the MNFace array f with the specified size.

Parameters:

int num

The number of MNFaces to allocate.

bool keep=TRUE

If TRUE any previously allocated faces are kept; otherwise they are discarded.

Prototype:

void FShrink(int num=-1);

Remarks:

This method is available in release 3.0 and later only.

Reduces the nf_alloc size of the MNFace data array f to the specified number of elements.

Parameters:

int num=-1

The new size for the array. The value -1 means to use the current number of faces, numf.

Prototype:

void MAlloc(int num, bool keep=TRUE);

Remarks:

This method is available in release 3.0 and later only.

Allocates the MNMap array m with the specified size.

Parameters:

int num

The number of MNMap elements to allocate.

bool keep=TRUE

If TRUE any previously allocated MNMaps are kept; otherwise they are discarded.

Prototype:

void MShrink(int num=-1);

Remarks:

This method is available in release 3.0 and later only.

Reduces the nm_alloc size of the MNMap data array m to the specified number of elements.

Parameters:

int num=-1

The new size for the array. The value -1 means to use the current number of maps, numm.

Prototype:

void PrepForPipeline ();

Remarks:

This method is available in release 4.0 and later only.

This method reconciles flags with arrays, checks and modifies data, ensures that the caches are consistent, and prepares the MNMesh pipeline. For instance, if the MN_MESH_FILLED_IN flag is absent but there is still an edge array, this will free the edge array. This method is important to call if a MNMesh has been subjected to topology changing operations and should be called at the end of any operation on an MNMesh.

Prototype:

BaseInterface* GetInterface(Interface_ID id);

Remarks:

This method is available in release 4.0 and later only.

This method returns a pointer to the base interface of the associated and provided Interface ID.

Parameters:

Interface_ID id

The interface ID.

I/O with regular meshes

Prototype:

void SetFromTri(const Mesh & from);

Remarks:

Clears out all current information, and copies in new faces & vertices from "from".

Prototype:

void AddTri(const Mesh & from);

Remarks:

Adds vertices and faces in "from" to current MNMesh.

Prototype:

void OutToTri(Mesh & tmesh);

Remarks:

Outputs current MNMesh into the mesh given. Note that even if the MNMesh was originally taken from this Mesh, the internal processing may have changed PART_TOPO, PART_GEOM, PART_SELECT, PART_MAPPING, or PART_VERTCOLOR.

Access to components

Prototype:

int VNum();

Remarks:

Returns the number of vertices.

Prototype:

MNVert *V(int i);

Remarks:

Returns a pointer to the i'th MNVert.

Prototype:

Point3 &P(int i);

Remarks:

Returns the point in the i'th MNVert. P(i) is the same as V(i)->p.

Prototype:

int ENum();

Remarks:

Returns the number of edges.

Prototype:

MNEdge *E(int i);

Remarks:

Returns a pointer to the i'th MNEdge.

Prototype:

int FNum();

Remarks:

Returns the number of faces.

Prototype:

MNFace *F(int i);

Remarks:

Returns a pointer to the i'th MNFace.

Prototype:

void SetMapNum(int mpnum);

Remarks:

This method is available in release 3.0 and later only.

Allocates and initializes the specified number of MNMap elements in the m array. Initializing sets the number of verts and faces in the map to zero and sets the MN_DEAD flag.

Parameters:

int mpnum

The number of MNMaps to allocate and initalize.

Prototype:

void InitMap(int mp);

Remarks:

This method is available in release 3.0 and later only.

Allocates and initializes basic planar map, or a white map for the vertex color channel.

Parameters:

int mp

The map channel to initialize:

0: Vertex Color channel.

1: Default mapping channel.

2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0.

Prototype:

void ClearMap(int mp);

Remarks:

This method is available in release 3.0 and later only.

Clears and frees the specified map channel, setting the MN_DEAD flag.

Parameters:

int mp

The map channel to clear.

0: Vertex Color channel.

1: Default mapping channel.

2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0.

Prototype:

UVVert MV(int mp, int i) const;

Remarks:

This method is available in release 3.0 and later only.

Returns the specified UVVert from the specified mapping channel.

Parameters:

int mp

The map channel.

0: Vertex Color channel.

1: Default mapping channel.

2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0.

int i

The zero based index of the UVVert to return.

Prototype:

MNMapFace *MF(int mp, int i) const;

Remarks:

This method is available in release 3.0 and later only.

Returns a pointer to the specified MNMapFace from the specified mapping channel.

Parameters:

int mp

The map channel:

0: Vertex Color channel.

1: Default mapping channel.

2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0.

int i

The zero based index of the MNMapFace to return.

Prototype:

int TriNum() const;

Remarks:

Returns the total number of triangles; this is a sum of the number of triangles in each face that does not have the MN_DEAD flag set.

Prototype:

void setNumVData(int ct, BOOL keep=FALSE);

Remarks:

This method is available in release 3.0 and later only.

Sets the specified number of vertex data elements.

Parameters:

int ct

The number of vertex data elements to set.

BOOL keep=FALSE

If TRUE any previously allocated elements are kept; otherwise they are discarded.

Prototype:

int VDNum() const;

Remarks:

This method is available in release 3.0 and later only.

Returns the number of vertex data channels maintained by this MNMesh.

Prototype:

BOOL vDataSupport(int vdChan) const;

Remarks:

This method is available in release 3.0 and later only.

Returns TRUE if the specified channel of vertex data is available for this MNMesh; otherwise FALSE.

Parameters:

int vdChan

The vertex data channel. See List of Vertex Data Index Options.

Prototype:

void setVDataSupport(int vdChan, BOOL support=TRUE);

Remarks:

This method is available in release 3.0 and later only.

Sets if the specified channel of vertex data is supported by this MNMesh.

Parameters:

int vdChan

The vertex data channel. See List of Vertex Data Index Options.

BOOL support=TRUE

TRUE to indicate the channel is supported; FALSE to indicate it's not. If TRUE is specified then elements are allocated (if needed). If FALSE is specified the data for the channel is freed.

Prototype:

void *vertexData(int vdChan) const;

Remarks:

This method is available in release 3.0 and later only.

Returns a pointer to the vertex data for the specified channel or NULL if the channel is not supported.

Parameters:

int vdChan

The vertex data channel. See List of Vertex Data Index Options.

Prototype:

float *vertexFloat(int vdChan) const;

Remarks:

This method is available in release 3.0 and later only.

Returns a pointer to the floating point vertex data for the specified channel of this mesh or NULL if the channel is not supported.

Parameters:

int vdChan

The vertex data channel. See List of Vertex Data Index Options.

Prototype:

void freeVData(int vdChan);

Remarks:

This method is available in release 3.0 and later only.

Deletes (deallocates) the vertex data for the specified channel.

Parameters:

int vdChan

The vertex data channel. See List of Vertex Data Index Options.

Prototype:

void freeAllVData();

Remarks:

This method is available in release 3.0 and later only.

Deallocates the vertex data from all channels and sets the number of supported channels to 0.

Prototype:

float *getVertexWeights();

Remarks:

This method is available in release 3.0 and later only.

Returns a pointer to the floating point vertex weight data.

Prototype:

void SupportVertexWeights();

Remarks:

This method is available in release 3.0 and later only.

Sets the channel support for the vertex weights channel (VDATA_WEIGHT).

Prototype:

void freeVertexWeights();

Remarks:

This method is available in release 3.0 and later only.

Frees (deallocates) the vertex weight channel data.

Prototype:

float *getVSelectionWeights();

Remarks:

This method is available in release 3.0 and later only.

Returns a pointer to the floating point vertex selection weight data.

Prototype:

void SupportVSelectionWeights();

Remarks:

This method is available in release 3.0 and later only.

Sets the channel support for the vertex weights channel (VDATA_SELECT).

Prototype:

void freeVSelectionWeights();

Remarks:

This method is available in release 3.0 and later only.

Frees (deallocates) the vertex selection weight channel data.

Prototype:

void setNumEData(int ct, BOOL keep=FALSE);

Remarks:

This method is available in release 3.0 and later only.

Sets the specified number of edge data elements.

Parameters:

int ct

The number of edge data elements to set.

BOOL keep=FALSE

If TRUE any previously allocated elements are kept; otherwise they are discarded.

Prototype:

int EDNum() const;

Remarks:

This method is available in release 3.0 and later only.

Returns the number of edge data channels maintained by this MNMesh.

Prototype:

BOOL eDataSupport(int edChan) const;

Remarks:

This method is available in release 3.0 and later only.

Returns TRUE if the specified channel of edge data is available for this MNMesh; otherwise FALSE.

Parameters:

int edChan

The edge data channel. See List of Edge Data Index Options.

Prototype:

void setEDataSupport(int edChan, BOOL support=TRUE);

Remarks:

This method is available in release 3.0 and later only.

Sets if the specified channel of edge data is supported by this MNMesh.

Parameters:

int edChan

The edge data channel. See List of Edge Data Index Options.

BOOL support=TRUE

TRUE to indicate the channel is supported; FALSE to indicate it's not.

Prototype:

void *edgeData(int edChan) const;

Remarks:

This method is available in release 3.0 and later only.

Returns a pointer to the edge data for the specified channel or NULL if the channel is not supported.

Parameters:

int edChan

The edge data channel. See List of Edge Data Index Options.

Prototype:

float *edgeFloat(int edChan) const;

Remarks:

This method is available in release 3.0 and later only.

Returns a pointer to the floating point edge data for the specified channel of this MNMesh or NULL if the channel is not supported.

Parameters:

int edChan

The edge data channel. See List of Edge Data Index Options.

Prototype:

void freeEData(int edChan);

Remarks:

This method is available in release 3.0 and later only.

Deletes (deallocates) the edge data for the specified channel.

Parameters:

int edChan

The edge data channel. See List of Edge Data Index Options.

Prototype:

void freeAllEData();

Remarks:

This method is available in release 3.0 and later only.

Deallocates the edge data from all channels and sets the number of supported channels to 0.

Prototype:

float *getEdgeKnots();

Remarks:

This method is available in release 3.0 and later only.

Returns a pointer to the floating point edge knot data.

Prototype:

void SupportEdgeKnots();

Remarks:

This method is available in release 3.0 and later only.

Sets the channel support for the edge knot channel (EDATA_KNOT).

Prototype:

void freeEdgeKnots();

Remarks:

This method is available in release 3.0 and later only.

Frees (deallocates) the edge knot channel data.

Prototype:

void VClear(int vv);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::Clear method.

Clears and frees the flags and face/edge lists for the specified vertex.

Parameters:

int vv

The vertex to clear.

Prototype:

void VInit(int vv);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::Init method.

Initializes the specified MNVert, clearing its flags and emptying its face & edge lists (if vfac & edg are allocated).

Parameters:

int vv

The vertex to initialize.

Prototype:

int VFaceIndex(int vv, int ff, int ee=-1);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::FaceIndex method.

Returns the index of face ff in the vfac[vv] table.

NOTE that if this face cannot be found, or if it cannot be found accompanied by edge ee>-1, it will cause an assertion failure.

Parameters:

int vv

The vertex to check the face list of.

int ff

The face to look for.

int ee=-1

In cases where the same face touches this vertex more than once, and is therefore represented twice in the vfac table, an optional edge parameter is used to specify which instance of the face you want the index of. However, if the parent MNMesh doesn’t have its vertices ordered (as indicated by the MN_MESH_VERTS_ORDERED flag), the extra edge parameter is meaningless and should not be used.

Prototype:

int VEdgeIndex(int vv, int ee);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::EdgeIndex method.

Finds the position of edge ee in this MNVert’s vedg table. Unlike VFaceIndex (and MNFace’s VertIndex and EdgeIndex), each vertex can only touch an edge once, so there’s no need for an additional parameter. (There’s no such thing as an edge with both ends at the same vertex.)

Parameters:

int vv

The vertex whose edge list should be searched.

int ee

The edge to find.

Return Value:

Returns -1 if edge ee is not in the edge table.

Prototype:

void VDeleteEdge(int vv, int ee);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::DeleteEdge method.

Finds edge ee in the vedg[vv] table and removes it.

Parameters:

int vv

The vertex from whose edge list the edge should be deleted.

int ee

The edge to delete from the vertex’s edge list.

Return Value:

Returns -1 if edge ee is not in the edge table.

 

Prototype:

void VDeleteFace(int vv, int ff);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::DeleteFace method.

Finds face ff in the vfac[vv] table and removes it. NOTE that this method causes an assertion failure if face ff is not in the vfac table. If ff occurs more than once, which is possible on some valid NONTRI meshes, only the first ff is removed.

Parameters:

int vv

The vertex from whose face list the face should be deleted.

int ff

The face to delete from the vertex’s face list.

Prototype:

void VReplaceEdge(int vv, int oe, int ne);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::ReplaceEdge method.

Finds edge oe in the vedg[vv] table and replaces it with ne. NOTE that this method causes an assertion failure if edge oe is not in the vedg table.

Parameters:

int vv

The vertex in whose edge list the edge should be replaced.

int oe

The edge to replace.

int ne

The replacement edge.

Prototype:

void VReplaceFace(int vv, int of, int nf);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::ReplaceFace method.

Finds face of in the vfac[vv] table and replaces it with nf. NOTE that this method causes an assertion failure if face of is not in the vfac table. If of occurs more than once, which is possible on some valid NONTRI meshes, only the first of is replaced.

Parameters:

int vv

The vertex in whose face list the face should be replaced.

int of

The face to replace.

int nf

The replacement.

Prototype:

void CopyVert(int nv, int ov);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::operator= by allowing the developer to copy face and edge adjacency information as well as vertex location and flags.

Copies the MNVert data from ov to nv. The face and edge data is copied too if appropriate (ie if MN_MESH_FILLED_IN is set and vfac and vedg are allocated).

Parameters:

int nv

The destination index.

int ov

The source index.

Prototype:

void MNVDebugPrint(int vv);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNVert::MNDebugPrint method.

Uses DebugPrint to print out vertex information to the Debug Results window in DevStudio. The information consists of the position, edge list, and face list. It is generally a good idea to put in a DebugPrint immediately before this with the index of the vertex, so you know which vertex is being printed out:

DebugPrint ("Vertex %d: ", vid);

MNVDebugPrint(vid);

Parameters:

int vv

The zero based index of the MNVert to debug print.

Prototype:

BOOL SubObjectHitTest(GraphicsWindow *gw, Material *ma, HitRegion *hr, DWORD flags, SubObjHitList& hitList, int numMat=1 );

Remarks:

This method is available in release 4.0 and later only.

This method may be called to perform sub-object hit testing on this mesh.

Parameters:

GraphicsWindow *gw

The graphics window associated with the viewport the mesh is being hit tested in.

Material *ma

The list of materials for the mesh. See Class Material

HitRegion *hr

This describes the properties of a region used for the hit testing. See Class HitRegion.

DWORD flags

Flags for sub object hit testing. One or more of the following values:

SUBHIT_MNUSECURRENTSEL

When this bit is set, the sel only and unsel only tests will use the current level (edge or face) selection when doing a vertex level hit test.) This is like the Mesh hit-testing flag SUBHIT_USEFACESEL.

SUBHIT_MNVERTS

SUBHIT_MNFACES

SUBHIT_MNEDGES

SUBHIT_MNTYPEMASK (SUBHIT_MNVERTS|SUBHIT_MNFACES|SUBHIT_MNEDGES)

SubObjHitList& hitList

The results are stored here. See Class SubObjHitList.

int numMat=1

The number of materials for the mesh.

Return Value:

TRUE if the item was hit; otherwise FALSE.

Prototype:

void UpdateDisplayVertexColors ();

Remarks:

This method is available in release 4.0 and later only.

This method is used to manage the display of vertex colors from any channel (or those that are passed in by some calling routine). For instance, to set the mesh to display the Illumination channel as the current vertex colors, you would call SetDisplayVertexColors (MAP_SHADING). (Normally, it shows the standard vertex color channel, channel 0.) UpdateDisplayVertexColors() is used to refresh the vertex color pointers just before the MNMesh displays itself.

Prototype:

void SetDisplayVertexColors (int chan);

Remarks:

This method is available in release 4.0 and later only.

This method is used to manage the display of vertex colors from any channel (or those that are passed in by some calling routine). For instance, to set the mesh to display the Illumination channel as the current vertex colors, you would call SetDisplayVertexColors (MAP_SHADING). (Normally, it shows the standard vertex color channel, channel 0.) UpdateDisplayVertexColors() is used to refresh the vertex color pointers just before the MNMesh displays itself.

Parameters:

int chan

The channel you wish to use.

Prototype:

void SetDisplayVertexColors (UVVert *mv, MNMapFace *mf);

Remarks:

This method is available in release 4.0 and later only.

If you have cached your own vertex color information that isn't in any of the map channels provided, you can use this method to set the internal pointers to use your data.

Parameters:

UVVert *mv

The array of UV vertices.

MNMapFace *mf

The map face data.

Prototype:

void FillInFaceEdges ();

Remarks:

This method is available in release 4.0 and later only.

Fills in the faces' edge arrays based on the edge list.

Prototype:

void FillInVertEdgesFaces ();

Remarks:

This method is available in release 4.0 and later only.

Fills in the vertex edge and face lists based on the edge list.

Prototype:

Box3 getBoundingBox (Matrix3 *tm=NULL, bool targonly=FALSE);

Remarks:

This method is available in release 4.0 and later only.

Retrieves a bounding box for the MNMesh.

Parameters:

Matrix3 *tm

Like the corresponding method in class Mesh, this method takes an optional transform, so the user can get a bounding box in any desired space (with a slower calculation, as all the points must be transformed).

bool targonly

If set, only vertices with the MN_TARG flag set are used to compute the bounding box.

Prototype:

void ComputeNormal (int ff, Point3 & N, Point3 *ctr=NULL);

Remarks:

This method is available in release 4.0 and later only.

Computes a "balanced" normal, in that the normal takes the contribution of all vertices equally. (This is significant in the case of nonplanar polygons.)

Parameters:

int ff

The face you want the normal of.

Point3 & N

The place to store the computed normal.

Point3 *ctr

If not NULL, it points to a place where ComputeNormal should put the face center.

Prototype:

void GetVertexSpace (int vrt, Matrix3 & tm);

Remarks:

This method is available in release 4.0 and later only.

Chooses a suitable "local space", and sets tm's rotation to match that space. Does not set tm's translation component. (This is easily done by setting tm.SetRow (3, v[vrt].p).)

The purpose of this method is to support a consistent definition of "local space" around a given vertex. As usual, Z comes from the local normal; the X direction is chosen to be a particular edge, but then this direction is modified to balance the contribution of the other edges. (Thus it points roughly in the direction of one edge, but moving other edges' far endpoints will rotate which way is considered "X" just as much as moving that edge will.)

Parameters:

int vrt

The vertex index.

Matrix3 & tm

The transformation matrix.

Prototype:

float EdgeAngle (int ed);

Remarks:

This method is available in release 4.0 and later only.

Computes the angle at the given edge. (In other words, the angle between the planes of the faces on either side.) Note that in the case of nonplanar polygons, these planes are the "average" planes for the polygon, not the plane of the triangle nearest the edge.

Parameters:

int ed

The edge index.

Return Value:

The angle in radians.

Prototype:

void FlipNormal(int faceIndex);

Remarks:

This method is available in release 4.0 and later only.

Flips the normal of the specified face, as well as the corresponding map faces in active maps. Note that doing this on an isolated face with neighbors will cause an illegal condition. Use the FlipElementNormals method to safely and completely flip the normals of entire elements to avoid this problem.

This method uses the MNFace and MNMapFace methods "Flip", which changes the order of the vertices from (0,1,2…,deg-1) to (0, deg-1, deg-2,…1) and rearrange the edge and diagonal information accordingly.

Parameters:

int faceIndex

The face index.

Prototype:

void AutoSmooth (float angle, BOOL useSel, BOOL preventIndirectSmoothing);

Remarks:

This method is available in release 4.0 and later only.

Applies new smoothing groups to the whole mesh or to selected faces based on angles between faces.

Parameters:

float angle

The threshold angle in radians. Edges with angles above this amount will not be smoothed across.

BOOL useSel

Indicates if the auto-smoothing should be done only on selected faces.

BOOL preventIndirectSmoothing

Sometimes even though two neighboring faces are more than "angle" apart, there may be a path from one to the other via other faces, crossing only edges that are less than "angle" apart, so they'll wind up sharing the same smoothing group anyway. To prevent this sort of "indirect" smoothing, set this value to TRUE.

Prototype:

void RestrictPolySize (int maxdeg);

Remarks:

This method is available in release 4.0 and later only.

Subdivides polygons as needed so that no polygon has degree larger than maxdeg. (For instance, if maxdeg was 4, an octagon would have edges added until it was composed of 3 quads, or some combination of quads and tris.)

Parameters:

int maxdeg

Maximum degrees.

Prototype:

void MakePlanar (float planarThresh);

Remarks:

This method is available in release 4.0 and later only.

Makes all faces planar, within the angle threshold given, by subdividing them as necessary. (See MakeFacePlanar.)

Parameters:

float planarThresh

The planar angle threshold.

Prototype:

void MakeFacePlanar (int ff, float planarThresh);

Remarks:

This method is available in release 4.0 and later only.

Makes the specified face planar by subdividing if necessary. planarThresh represents an angle in radians. If the angle across any of the face's diagonals is larger than this amount, the face is divided on that diagonal.

Parameters:

int ff

The face of the index to make planar

float planarThresh

The planar angle threshold.

Prototype:

UVVert ExtrapolateMapValue (int face, int edge, Point3 & pt, int mp);

Remarks:

This method is available in release 4.0 and later only.

Given a point near a given edge of a given face, but near to it, this method will extrapolate what that point's mapping coordinates would be in the mapping scheme used by the face.

Parameters:

int face

The face we want to base mapping information on.

int edge

The index of the edge we're closest to on the face. (This should be the face-based index, in the range (0, deg-1), not the index of the edge in the MNMesh.)

Point3 & pt

The object-space coordinates of the point.

int mp

The map channel we're analyzing.

Prototype:

void EliminateDoubledMappingVerts();

Remarks:

This method is available in release 4.0 and later only.

"Doubled" mapping vertices are individual map vertices that are used to correspond to different regular vertices. For instance, a box could have a single (1,1,0) map vertex that it uses in the upper-right corner of all quads. This design is harmful to some of our algorithms, such as the various Tessellators. So this method is available to fix such vertices. It clones map vertices as needed to ensure that a given map vertex is only used by one regular vertex. Linear-time algorithm.

Prototype:

BOOL CheckForDoubledMappingVerts();

Remarks:

This method is available in release 4.0 and later only.

This method is a debugging tool. All doubled mapping verts are DebugPrinted. Return value is TRUE if there is at least one doubled mapping vertex (on at least one map channel). FALSE if the mesh is clean. Note that this method is not significantly faster than EliminateDoubledMappingVerts, so you should not use it to determine if EliminateDoubledMappingVerts should be called.

Prototype:

void EliminateIsoMapVerts();

Remarks:

This method is available in release 4.0 and later only.

Deletes isolated mapping vertices - i.e., mapping vertices that aren't used by any mapping faces.

Prototype:

void EliminateIsoMapVerts(int mp);

Remarks:

This method is available in release 4.0 and later only.

Deletes isolated mapping vertices - i.e., mapping vertices that aren't used by any mapping faces. If the "int mp" parameter is given, the algorithm operates only on that map channel. If not, the algorithm operates on all map channels.

Parameters:

int mp

The map channel to operate on.

Prototype:

int SplitEdge (int ee, float prop, Tab<int> *newTVerts);

Remarks:

This method is available in release 4.0 and later only.

This new SplitEdge variant allows you to recover information about the new map vertices created at the point where the edge is split. Everything else is the same as the existing SplitEdge (int ee, float prop=.5f) method.

Parameters:

Tab<int> *newTVerts

Pointer to a table in which the new map vertices can be stored. This table is set to size (NUM_HIDDENMAPS + numm)*2. The two entries for each map channel are used to store the two new map vertices at this edge split: newTVerts[(NUM_HIDDENMAPS+mp)*2+0] is the map vertex for map channel mp on the "f1" side of the edge, and newTVerts[mp*2+1] is the map vertex for the "f2" side if f2>=0 (or otherwise left uninitialized). (These values are often, but not always, the same. They are different if the map has a seam along this edge.)

Prototype:

void FacePointBary (int ff, Point3 & p, Tab<float> & bary);

Remarks:

This method is available in release 4.0 and later only.

Finds "Generalized Barycentric Coordinates" for the point given. Generalized barycentric coordinates are not uniquely determined for polygons of degree greater than 3, but this algorithm should find a reasonable balance, where for instance a point in the center of a polygon would have a significant contribution from all vertices.

Generalized barycentric coordinates are a set of floats, one per vertex in the polygon, such that the sum of all the floats is 1, and the sum of all the floats times the corresponding vertices comes out to the point given.

Parameters:

int ff

The face we're finding barycentric coordinates on.

Point3 & p

The point we're trying to find barycentric coordinates for. If this point is not in the plane of the polygon, the coordinates produced should represent its projection into the polygon's plane. Points outside the boundary of the polygon should be acceptable; some of the barycentric coordinates will be negative in this case.

Tab<float> & bary

The table to put the results in. This table is set to size f[ff].deg.

Prototype:

void CloneVerts (DWORD cloneFlag = MN_SEL, bool clear_orig=TRUE);

Remarks:

This method is available in release 4.0 and later only.

Clones flagged vertices, creating new vertices that aren't used by any faces.

Parameters:

DWORD cloneFlag = MN_SEL

Indicates which vertices should be cloned.

bool clear_orig = TRUE

If true, the original vertices should have the cloneFlag cleared. (The clones will always have this flag set.)

Prototype:

void CloneFaces (DWORD cloneFlag = MN_SEL, bool clear_orig=TRUE);

Remarks:

This method is available in release 4.0 and later only.

Clones the flagged faces, as well as all the vertices and edges that are used by the faces.

Parameters:

DWORD cloneFlag = MN_SEL

Indicates which faces should be cloned.

bool clear_orig = TRUE

If true, the original faces should have the cloneFlag cleared. (The clones will always have this flag set.)

Prototype:

int DivideFace (int ff, Tab<float> & bary);

Remarks:

This method is available in release 4.0 and later only.

Divides a face by creating a point in the face's interior and creating an edge from that point to each of the face's vertices. An n-gon becomes n triangles by this method.

Parameters:

int ff

The face to divide.

Tab<float> & bary

The generalized barycentric coordinates of the point that should be created. (See FacePointBary for details on barycentric coordinates.)

Return Value:

The index of the newly created vertex, or -1 if there's an error.

Prototype:

int CreateFace (int degg, int *vv);

Remarks:

This method is available in release 4.0 and later only.

Creates a new face, using the vertices given.

Note that this method, unlike the similar NewFace method, maintains all topological links. If there's an edge between vv[0] and vv[1] which is already used by some other face (on the other side), that edge is modified to use this face on its "f2" side. If there's an edge between two sequential vertices with faces on both sides, the creation fails, because it would create an illegal condition.

This method also creates map faces in any active map channels to maintain the validity of the mesh. These map faces use the map vertices that other faces use for the vertices passed in, or if there are no corresponding map vertices yet, use newly created map vertices with the value (1,1,1).

Parameters:

int degg

The degree of the new face.

int *vv

A pointer to an array of degg vertices for the new face.

Return Value:

The index of the new face, or -1 if the method was unable to create that face.

Prototype:

bool MakeFlaggedPlanar (int selLev, DWORD flag=MN_SEL, Point3 *delta=NULL);

Remarks:

This method is available in release 4.0 and later only.

Moves the flagged components into their "average plane". (Plane computed using average component positions and normals.)

Parameters:

int selLev

Selection level, one of MNM_SL_VERTEX, MNM_SL_EDGE, MNM_SL_FACE, or MNM_SL_OBJECT.

DWORD flag=MN_SEL

The flag that indicates which components to align. Ignored if msl is set to MNM_SL_OBJECT.

Point3 *delta=NULL

If non-NULL, this is presumed to point to an array of size equal to MNMesh::numv, and instead of actually moving the vertices, the algorithm stores offsets in this array such that v[i].p + delta[i] is in the plane.

Return Value:

Indicates whether anything was moved. (Or if delta is non-NULL, if any deltas are nonzero.)

Prototype:

bool MoveVertsToPlane (Point3 & norm, float offset, DWORD flag=MN_SEL, Point3 *delta=NULL);

Remarks:

This method is available in release 4.0 and later only.

Projects the flagged vertices into the specified plane.

Parameters:

Point3 & norm, float offset

The definition of the plane: DotProd (norm, x) - offset = 0.

DWORD flag=MN_SEL

The flag that indicates which vertices to move.

Point3 *delta=NULL

If non-NULL, this is presumed to point to an array of size equal to MNMesh::numv, and instead of actually moving the vertices, the algorithm stores offsets in this array such that v[i].p + delta[i] is in the plane.

Return Value:

Indicates whether anything was moved. (Or if delta is non-NULL, if any deltas are nonzero.)

Prototype:

bool SplitFlaggedVertices (DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

Splits the flagged vertices into a clone for each face using the vertex. For example, if used on the front top left corner of a standard 3ds max box, it splits the vertex into 3, one for the front face, one for the top face, and one for the left face.

Parameters:

DWORD flag=MN_SEL

The flag that indicates which vertices to split.

Return Value:

TRUE if anything happened, FALSE if none of the vertices were split. (Note that this method will return FALSE if no vertices are flagged, but also if there are flagged vertices but they're all on 1 or 0 faces already.)

Prototype:

bool SplitFlaggedEdges (DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

"Splits" edges by breaking vertices on two or more flagged edges into as many copies as needed. In this way, any path of flagged edges becomes an two open seams.

Parameters:

DWORD flag=MN_SEL

Indicates which edges should be split. (Left at the default, selected edges are split.)

Return Value:

True if any topological changes happened, false if nothing happened.

Prototype:

bool DetachFaces (DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

Detaches specified faces to a separate element, cloning vertices and edges as necessary on the boundary between flagged and unflagged faces.

Parameters:

DWORD flag=MN_SEL

Indicates which edges should be split. (Left at the default, selected edges are split.)

Return Value:

True if any faces were detached, false if nothing happened. (Note that the algorithm will return false if, for instance, all flagged faces form elements which are already distinct from those formed from non-flagged faces.)

Prototype:

bool DetachElementToObject (MNMesh & nmesh, DWORD fflags=MN_SEL, bool delDetached=true);

Remarks:

This method is available in release 4.0 and later only.

Detaches specified faces to a new MNMesh.

Parameters:

MNMesh & mesh

An empty new mesh into which the detached faces (and accompanying vertices and edges) should be put.

DWORD fflags=MN_SEL

Indicates which faces should be detached.

Return Value:

True if any faces were detached, false if nothing happened.

Prototype:

bool ExtrudeFaceClusters (MNFaceClusters & fclust);

Remarks:

This method is available in release 4.0 and later only.

Performs the topological component of an extrusion on all face clusters. Each cluster is "extruded", which means that vertices and edges on the boundary of the cluster are cloned and new faces and edges are created to connect the clones to the originals. (Note that nothing is moved in this process - movement is handled separately. See GetExtrudeDirection for details.)

Parameters:

MNFaceClusters & fclust

A list of face clusters. See the constructors in class MNFaceClusters and the face cluster related methods of class MNTempData for information on how to set up these clusters based on edge angles and face flags.

Return Value:

True if any faces were extruded, false if nothing happened.

Prototype:

bool ExtrudeFaceCluster (MNFaceClusters & fclust, int cl);

Remarks:

This method is available in release 4.0 and later only.

Performs the topological component of an extrusion on the specified face cluster. This means that vertices and edges on the boundary of the cluster are cloned and new faces and edges are created to connect the clones to the originals. (Note that nothing is moved in this process - movement is handled separately. See GetExtrudeDirection for details.)

Parameters:

MNFaceClusters & fclust

A list of face clusters. See the constructors in class MNFaceClusters and the face cluster related methods of class MNTempData for information on how to set up these clusters based on edge angles and face flags.

int cl

The cluster we wish to extrude.

Return Value:

True if any faces were extruded, false if nothing happened.

Prototype:

bool ExtrudeFaces (DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

Performs the topological component of an extrusion on each flagged face individually. (This differs from ExtrudeFaceClusters in that each face is treated like its own cluster.) Extrusion means that the vertices and edges used by each flagged face are cloned, and new faces and edges are created on the "sides" to connect the clones to their originals. (Note that nothing is moved in this process - movement is handled separately. See GetExtrudeDirection for details.)

Parameters:

DWORD flag=MN_SEL

The flag that identifies the faces we wish to extrude.

Return Value:

True if any faces were extruded, false if nothing happened.

Prototype:

void GetExtrudeDirection (MNChamferData *mcd, MNFaceClusters *fclust=NULL, Point3 *clustNormals=NULL);

Remarks:

This method is available in release 4.0 and later only.

Finds the direction vectors for the geometric component of an extrusion after the topological component has been completed. (See methods ExtrudeFaceClusters, ExtrudeFaceCluster, and ExtrudeFaces for details on the topological component.)

Parameters:

MNChamferData *mcd

The data structure in which the extrusion directions are stored. (Note that there is no map support for this operation, as there is no well-defined way to modify mapping values during an extrusion drag.)

MNFaceClusters *fclust = NULL

The face clusters.

Point3 *clustNormals = NULL

The cluster normals.

This information is only needed if we're extruding by cluster normals. If we're extruding clusters by local normals or just extruding faces separately, these parameters can be left at NULL. See class MNTempData for handy methods to obtain cluster normals.

Prototype:

bool SetVertColor (UVVert clr, int mp, DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

Sets vertex colors for the specified vertices. This is done by finding all map vertices in the specified vertex color channel that correspond to each flagged vertex and setting them to the color given.

Parameters:

UVVert clr

The color to set the vertices to.

int mp

The map channel - use 0 for the standard vertex color channel, MAP_SHADING for the vertex illumination channel, or MAP_ALPHA for the alpha channel. (Note that alpha color values should always be shades of grey - clr.r should equal clr.g and clr.b.)

DWORD flag=MN_SEL

Indicates which vertices to modify the colors of.

Return Value:

Returns true if any vertex colors were modified.

Prototype:

bool SetFaceColor (UVVert clr, int mp, DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

Sets vertex colors for the specified faces. This is done by finding all map vertices used by flagged faces and setting them to the color given. In cases where a map vertex is used by both a flagged and an unflagged face, the map vertex is split so that the unflagged faces' colors are unaffected by this change.

Parameters:

UVVert clr

The color to set the faces to.

int mp

The map channel - use 0 for the standard vertex color channel, MAP_SHADING for the vertex illumination channel, or MAP_ALPHA for the alpha channel. (Note that alpha color values should always be shades of grey - clr.r should equal clr.g and clr.b.)

DWORD flag=MN_SEL

Indicates which faces to modify the colors of.

Return Value:

Returns true if any vertex colors were modified.

Prototype:

bool ChamferVertices (DWORD flag=MN_SEL, MNChamferData *mcd=NULL);

Remarks:

This method is available in release 4.0 and later only.

Performs the topological component of a vertex chamfer on the flagged vertices, and provides the data needed to do the geometric component. That is to say, this method clones the flagged vertices and creates the new edges and faces needed in a chamfer operation. It also determines the direction each vertex and mapping vertex will go as the user drags out the chamfer - but it doesn't actually move any vertices.

Parameters:

DWORD flag=MN_SEL

Indicates which vertices to chamfer.

MNChamferData *mcd=NULL

If non-NULL, this points to a data structure which should be filled with information needed to perform the geometric component of the chamfer, such as vertex directions and limits. See class MNChamferData for additional information.

Return Value:

True if any vertices were chamfered, false otherwise.

Prototype:

bool ChamferEdges (DWORD flag=MN_SEL, MNChamferData *mcd=NULL);

Remarks:

This method is available in release 4.0 and later only.

Performs the topological component of an edge chamfer on the flagged edges, and provides the data needed to do the geometric component. That is to say, this method clones the flagged edges and creates the new vertices and faces needed in the edge chamfer operation. It also determines the direction each vertex and mapping vertex will go as the user drags out the chamfer - but it doesn't actually move anything.

Parameters:

DWORD flag=MN_SEL

Indicates which edges to chamfer.

MNChamferData *mcd=NULL

If non-NULL, this points to a data structure which should be filled with information needed to perform the geometric component of the chamfer, such as vertex directions and limits. See class MNChamferData for additional information.

Return Value:

True if any edges were chamfered, false otherwise.

Prototype:

bool FlipElementNormals (DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

Flips the normals of the specified elements in the mesh.

Parameters:

DWORD flag=MN_SEL

Indicates which elements should be flipped, in the following way: any element that has at least one flagged face is completely flipped. Elements without any flagged faces are not.

Return Value:

Returns true if anything was flipped, false otherwise.

Prototype:

void SmoothByCreases (DWORD creaseFlag);

Remarks:

This method is available in release 4.0 and later only.

This is an auto-smooth algorithm that allows the developer to specify exactly which edges should be creases and which should be smoothed across. All face smoothing groups are rewritten by this algorithm. This algorithm is used, for example, in MeshSmooth, NURMS style, when the user turns on "smooth result" and applies crease values to some edges.

Parameters:

DWORD creaseFlag

Indicates which edges should be treated as creases. Edges that have the flag (or flags) set should be creases. Those that don't should not be creases.

Prototype:

int CutFace (int f1, Point3 & p1, Point3 & p2, Point3 & Z, bool split);

Remarks:

This method is available in release 4.0 and later only.

Implements the Editable Poly Cut algorithm from the face level - cuts from a point on one face to a point on another face.

Parameters:

int f1

The starting face of the Cut.

Point3 & p1

The starting point of the Cut, which should lie on face f1.

Point3 & p2

The end point of the Cut.

Point3 & Z

The view direction. All Cut algorithms require a view direction to establish the plane that the cut occurs in. This plane is defined by this Z vector and by the vector p2-p1. All new vertices created by the cut are in this plane.

bool split

If true, the faces on the top and bottom of the cut should have an open seam between them. All the edges and vertices along the cut (except for the first and last vertex) are split into two parts, one copy for the top and one for the bottom.

Return Value:

The last vertex created by the cut, or -1 if the cut was unable to finish.

Prototype:

int CutEdge (int e1, float prop1, int e2, float prop2, Point3 & Z, bool split);

Remarks:

This method is available in release 4.0 and later only.

Implements the Editable Poly Cut algorithm from the edge level - cuts from a point on one edge to a point on another edge.

Parameters:

int e1

The starting edge of the Cut.

float prop1

The proportion along edge e1 where the cut should begin. That is, the first point should be located at (1-prop1)*v[e[e1].v1].p + prop1*v[e[e1].v2].p.

int e2

The ending edge of the Cut.

float prop2

The proportion along edge e2 where the cut should end. That is, the last point should be located at (1-prop2)*v[e[e2].v1].p + prop2*v[e[e2].v2].p.

Point3 & Z

The view direction. All Cut algorithms require a view direction to establish the plane that the cut occurs in. This plane is defined by this Z vector and by the vector between the start and end points. All new vertices created by the cut are in this plane.

bool split

If true, the faces on the top and bottom of the cut should have an open seam between them. All the edges and vertices along the cut (except for the first and last vertex) are split into two parts, one copy for the top and one for the bottom.

Return Value:

The last vertex created by the cut, or -1 if the cut was unable to finish.

Prototype:

int Cut (int startv, Point3 & end, Point3 & Z, bool split);

Remarks:

This method is available in release 4.0 and later only.

Implements the Editable Poly Cut algorithm from the vertex level - cuts from one vertex to another.

Parameters:

int startv

The starting vertex of the Cut.

Point3 & end

The location of the end vertex of the Cut.

Point3 & Z

The view direction. All Cut algorithms require a view direction to establish the plane that the cut occurs in. This plane is defined by this Z vector and by the vector between the start and end points. All new vertices created by the cut are in this plane.

bool split

If true, the faces on the top and bottom of the cut should have an open seam between them. All the edges and vertices along the cut (except for the first and last vertex) are split into two parts, one copy for the top and one for the bottom.

Return Value:

The last vertex created by the cut, or -1 if the cut was unable to finish.

Prototype:

bool WeldBorderVerts (int v1, int v2, Point3 *destination);

Remarks:

This method is available in release 4.0 and later only.

Welds the specified border vertices together.

Parameters:

int v1, int v2

The vertices to be welded. They must be border vertices, in the sense that each of them must be used by open edges (those on only one face).

Point3 *destination

If non-NULL, this indicates where the joined vertex should be located. (If NULL, it's put at the average location, (v[v1].p + v[v2].p)/2.)

Return Value:

True if anything was welded, false if the operation could not proceed.

Prototype:

bool WeldBorderEdges (int e1, int e2);

Remarks:

This method is available in release 4.0 and later only.

Welds the specified border edges together.

Parameters:

int e1, int e2

The edges to be welded. They must be border edges, in the sense that each of them must be open (used by only one face). The result is located where edge e2 was. e[e1].v1 is joined to e[e2].v2, and e[e1].v2 is joined to e[e2].v1.

Return Value:

True if anything was welded, false if the operation could not proceed.

Prototype:

bool WeldBorderVerts (float thresh, DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

Welds the specified border vertices together.

Parameters:

float thresh

The welding threshold. Vertices further apart than this distance (in object space) will not be welded.

DWORD flag=MN_SEL

Indicates which vertices should be welded. (Non-border vertices, those in the "interior" of the surface, are ignored even if flagged.)

Return Value:

True if anything was welded, false otherwise.

Adding new components

 

NOTE: all face creation methods clear the MN_MESH_FILLED_IN, MN_MESH_NO_BAD_VERTS, and MN_MESH_VERTS_ORDERED flags. If your calling routine takes care of the work of updating or creating all relevant MNVertices and MNEdges, you may be able to set these flags again -- but be careful! For some convenient face & edge subdivision methods that preserve a complete topology, check out the Splitting methods.

Prototype:

int NewTri(int a, int b, int c, DWORD smG=0, MtlID mt=0);

Remarks:

Creates a new tri-face. Note that no mapping coords or vertex colors can be specified.

Parameters:

int a,b,c

The indices of the vertices that form this triangle.

DWORD smG=0

The smoothing group(s) assigned to the new face.

MtlID mt=0

The material ID assigned to the new face.

Return Value:

Returns the index of the new face created.

Prototype:

int NewTri(int *vv, int *tt, int *cc, DWORD smG=0, MtlID mt=0);

Remarks:

Creates a new face of degree 3. Edge selection and visibility flags are set to the default: all visible and not selected.

Parameters:

int *vv

The indices of the vertices that form this face. (There must be 3 of these.)

int *tt

If this is not NULL, it points to the indices of 3 mapping coordinates for this face.

int *cc

If this is not NULL, it points to the indices of 3 vertex colors for this face.

DWORD smG

The smoothing group(s) assigned to this face.

MtlID mt

The material ID assigned to this face

Return Value:

The index of the face created.

Prototype:

int NewQuad(int a, int b, int c, int d, DWORD smG=0, MtlID mt=0);

Remarks:

This method will create a new quad.

Previous to 4.0 this method used two tri-faces that shared and invisible edge.

Parameters:

int a, b, c, d

The indices of the vertices that form this quad.

DWORD smG=0

The smoothing group(s) assigned to the new faces.

MtlID mt=0

The material ID assigned to the new faces.

Return Value:

Returns the index of the quad face created.

Prototype:

int NewQuad(int *vv, int *tt, int *cc, DWORD smG=0, MtlID mt=0);

Remarks:

This method will create a new quad.

Previous to 4.0 this method used two tri-faces that shared and invisible edge.

Parameters:

int *vv

The indices of the vertices that form this face. (There must be 4 of these.)

int *tt

If this is not NULL, it points to the indices of 4 mapping coordinates for this face.

int *cc

If this is not NULL, it points to the indices of 4 vertex colors for this face.

DWORD smG

The smoothing group(s) assigned to this face.

MtlID mt

The material ID assigned to this face

Return Value:

Returns the index of the quad face created.

Prototype:

int NewFace(MNFace *ff, int degg=0, int *vv=NULL, bool *vis=NULL, bool *sel=NULL);

Remarks:

This method creates a (single) new face with the characteristics given. The default triangulation for a face of this degree is used; if the face is not convex, this triangulation may be inappropriate. If this is the case, call RetriangulateFace() on this face after it’s created.

Parameters:

MNFace *ff

A current face from which smoothing groups, material ID, and flags should be copied. If this is NULL, these values are left at their default values.

int degg

The degree of the face to be created.

int *vv

The indices of the vertices that form the new face. (There must be degg of these.)

bool *vis

This is an array of visibility bits for the edges of the new face. If this is NULL, the default of all edges being visible is used. If this is not NULL, there must be degg values.

bool *sel

This is an array of selection bits for the edges of the new face. If this is NULL, the default of all edges not being selected is used. If this is not NULL, there must be degg values.

Prototype:

int AppendNewFaces(int nfnum);

Remarks:

This method is available in release 3.0 and later only.

Appends the specified number of MNFaces to f.

Parameters:

int nfnum

The number of MNFaces to append.

Return Value:

The index of the first appended face (ie the old numf).

Prototype:

void setNumFaces(int nfnum);

Remarks:

This method is available in release 3.0 and later only.

Sets the specified number of MNFaces allocated in f.

Parameters:

int nfnum

The number of MNFaces to set.

Prototype:

int RegisterEdge(int v1, int v2, int f, int fpos);

Remarks:

Edge creation tool. If there is no edge currently joining vertices v1 and v2, it creates such an edge. If there is an edge starting at v2 and ending on v1, it registers face f as being on the "other side" of the edge.

Parameters:

int v1, v2

The start & end vertices of the edge you wish to register.

int f

The face on the "left" side of this edge, if you’re looking from v1 towards v2 with the surface normal above.

int fpos

The index of this edge in face f. This is used to extract visibility and selection information from the face.

Return Value:

The index of the new edge, or -1 if the edge already exists in the specified direction.

Prototype:

int SimpleNewEdge(int v1, int v2);

Remarks:

Edge creation tool. Simply makes a new edge from v1 to v2, without worrying about whether such an edge may already exist, or what faces may be on either side. Since edges are required to have at least one valid face on them, using this method obligates the developer to assign f1 on the new edge themselves.

Return Value:

The index of the new edge.

Prototype:

int NewEdge(int v1, int v2, int f, int fpos);

Remarks:

Edge creation tool. Requires the developer to previously ascertain that there is no edge from v1 to v2 or from v2 to v1.

Parameters:

int v1, v2

The start & end vertices of the edge you wish to create.

int f

The face on the "left" side of this edge, if you’re looking from v1 towards v2 with the surface normal above.

int fpos

The index of this edge in face f. This is used to extract visibility and selection information from the face.

Return Value:

The index of the new edge.

Prototype:

int AppendNewEdges(int nenum);

Remarks:

This method is available in release 3.0 and later only.

Appends the specified number of edges.

Parameters:

int nenum

The number of edges to append.

Prototype:

void setNumEdges(int nenum);

Remarks:

This method is available in release 3.0 and later only.

Sets the number of MNEdges allocated in e.

Parameters:

int nenum

The number of MNEdges to set.

Prototype:

int NewVert(Point3 &p);

Remarks:

This method is available in release 3.0 and later only.

Creates a new vertex (increasing numv) and sets it to the specified point.

Parameters:

Point3 &p

The point to which the new vert should be initialized.

Prototype:

int NewVert(Point3 &p, int vid);

Remarks:

This method is available in release 3.0 and later only. It replaces the old MNMesh::NewVert (Point3 &p, MNVert *mv=NULL) method.

Creates a new vertex (increasing numv) and initializes it to the point p and the flags and other characteristics of vertex vid.

Parameters:

Point3 &p

The point to which the new vert should be initialized.

int vid

The index of the existing MNVert from which flags and PerData info should be copied. (Only the MN_SEL and MN_TARG flags are copied.)

Prototype:

int NewVert(int vid);

Remarks:

This method is available in release 3.0 and later only.

Creates a new vertex and initializes it to location, flags and other characteristics of vertex vid.

Parameters:

int vid

The index of the existing MNVert from which location, flags and PerData info should be copied. (Only the MN_SEL and MN_TARG flags are copied.)

Prototype:

int NewVert(int v1, int v2, float prop);

Remarks:

This method is available in release 3.0 and later only.

Creates a new vertex which is a linear combination of two existing vertices. The new vertex has the MN_SEL and MN_TARG flags of whichever vertex it’s closest to. The location and PerData info is interpolated.

Parameters:

int v1

The first vertex to combine.

int v2

The second vertex to combine.

float prop

The proportion along the segment from v1 to v2 where the new vertex should be located.

Prototype:

int AppendNewVerts(int nvnum);

Remarks:

This method is available in release 3.0 and later only.

Appends the specified number of MNVerts.

Parameters:

int nvnum

The number of MNVerts to append.

Return Value:

The index of the first appended vertex (ie the old numv).

Prototype:

void setNumVerts(int nvnum);

Remarks:

This method is available in release 3.0 and later only.

Sets the number of verts, allocating if needed.

Parameters:

int nvnum

The desired number of vertices in the mesh.

Removing & Deleting Components

Prototype:

void CollapseDeadVerts();

Remarks:

Removes all MNVerts with the MN_DEAD flag from the list of vertices. Also, it re-indexes all the faces’ and edges’ vertex references to maintain mesh integrity.

Prototype:

void CollapseDeadEdges();

Remarks:

Removes all MNEdges with the MN_DEAD flag from the list of edges. Also, re-indexes all the faces’ and vertices’ edge references to maintain mesh integrity.

Prototype:

void CollapseDeadFaces();

Remarks:

Removes all MNFaces with the MN_DEAD flag from the list of faces. Also, re-indexes all the edges’ and vertices’ face references to maintain mesh integrity.

Prototype:

void CollapseDeadStructs();

Remarks:

Performs all 5 of the above collapse functions, safely removing all unused components from this mesh.

Prototype:

void Clear();

Remarks:

Reinitializes all verts, faces, and edges, freeing the data members of these components, but not freeing the vertex, edge, and face arrays themselves. This option is suitable if you need to clear a MNMesh you will be reusing. numv, etc, are set to 0.

Prototype:

void ClearAndFree();

Remarks:

This method is available in release 3.0 and later only.

Deletes everything and frees all relevant memory. Leaves you with an empty MNMesh with the default flags.

Prototype:

void freeVerts();

Remarks:

This method is available in release 3.0 and later only.

Deletes the MNVert array and frees any corresponding vertex data.

Prototype:

void freeEdges();

Remarks:

This method is available in release 3.0 and later only.

Deletes the MNEdge array and frees and corresponding edge data.

Prototype:

void freeFaces();

Remarks:

This method is available in release 3.0 and later only.

Deletes the MNFace array.

Prototype:

void freeMap(int mp);

Remarks:

This method is available in release 3.0 and later only.

Deletes the MNMap on the specified map channel.

Parameters:

int mp

The map channel.

0: Vertex Color channel.

1: Default mapping channel.

2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0.

Prototype:

void freeMaps();

Remarks:

This method is available in release 3.0 and later only.

Deletes and frees all the MNMaps.

Prototype:

void DeleteFlaggedFaces(DWORD deathflags, DWORD nvCopyFlags=0x0);

Remarks:

This method is available in release 2.5 and later only.

Deletes faces with any of the death flags set, as well as delete vertices and edges surrounded by faces with death flags, and correct the mesh components remaining.

Parameters:

DWORD deathflags

The collection of flags marking the faces you wish to kill.

DWORD nvCopyFlags=0x0

If the NO_BAD_VERTS flag is set on this mesh, DeleteFlaggedFaces will preserve this property. This may involve duplicating some vertices. (See EliminateBadVerts for more information.) If you have vertex flags that you want preserved in this duplication, indicate them in nvCopyFlags. MN_SEL and MN_TARG are always copied, but all other flags are cleared on the new vertex.

Prototype:

void SetDispFlag(DWORD f);

Remarks:

This method is available in release 4.0 and later only.

This method allows you to set the display flags.

Parameters:

DWORD f

The following flags are supported;

MNDISP_VERTTICKS

Displays vertices with tick-marks (plus signs).

MNDISP_SELVERTS

Displays selected vertices in red (and soft-selected vertices in soft selection colors).

MNDISP_SELFACES

Displays selected faces.

MNDISP_SELEDGES

Displays selected edges.

MNDISP_NORMALS

Displays face normals on selected faces.

MNDISP_DIAGONALS

Displays diagonals (using the same drawing style as regular Meshes use for hidden edges).

Prototype:

DWORD GetDispFlag(DWORD f);

Remarks:

This method is available in release 4.0 and later only.

This method returns the displFlags & f.

Parameters:

DWORD f

The following flags are supported;

MNDISP_VERTTICKS

Displays vertices with tick-marks (plus signs).

MNDISP_SELVERTS

Displays selected vertices in red (and soft-selected vertices in soft selection colors).

MNDISP_SELFACES

Displays selected faces.

MNDISP_SELEDGES

Displays selected edges.

MNDISP_NORMALS

Displays face normals on selected faces.

MNDISP_DIAGONALS

Displays diagonals (using the same drawing style as regular Meshes use for hidden edges).

Prototype:

void ClearDispFlag(DWORD f);

Remarks:

This method is available in release 4.0 and later only.

This method allows you to clear the specified display flags.

Parameters:

DWORD f

The following flags are supported;

MNDISP_VERTTICKS

Displays vertices with tick-marks (plus signs).

MNDISP_SELVERTS

Displays selected vertices in red (and soft-selected vertices in soft selection colors).

MNDISP_SELFACES

Displays selected faces.

MNDISP_SELEDGES

Displays selected edges.

MNDISP_NORMALS

Displays face normals on selected faces.

MNDISP_DIAGONALS

Displays diagonals (using the same drawing style as regular Meshes use for hidden edges).

Internal computation

Prototype:

void FillInMesh();

Remarks:

If this mesh does not have the MN_MESH_FILLED_IN flag, this method completely recomputes all combinatorial information. It re-creates all MNEdges and MNFace::edg, MNVert::edg, and MNVert::fac lists based on the information in the MNFace::vtx lists.

Since this routine completely reconstructs the combinatorics, it clears the MN_MESH_VERTS_ORDERED flag.

Prototype:

bool EliminateBadVerts (DWORD flag=0);

Remarks:

A "bad" vertex in this context is one which is shared between two distinct boundaries for this mesh. As an example, imagine a union between two circles, converted to meshes, that touch at a single vertex. This causes a vertex to exist which is on two faces, but four edges. Since most vertices are on equal numbers of faces and edges (if they’re not on a boundary) or on one more edge than face (if they are on a boundary), these types of vertices can mess up some forms of processing. This method eliminates such vertices by duplicating them, assigning one vertex to each boundary. A MNMesh that has gone through this method will have the MN_MESH_NO_BAD_VERTS flag set until a method (such as NewFace) is called that could conceivably create bad vertices.

EliminateBadVerts requires a filled in mesh, and will call FillInMesh if the MN_MESH_FILLED_IN flag is not set.

Parameters:

DWORD flag:

This parameter is available in release 4.0 and later only.

If nonzero, it indicates that only flagged vertices should be split up if "bad".

Return Value:

False if nothing changed, true if at least one bad vertex was found and split.

 

Prototype:

void OrderVert (int vid);

Remarks:

This method is available in release 4.0 and later only.

This routine organizes the face and edge lists of the specified vertex such that going counterclockwise around the vertex (with the surface normal pointing towards you), you'll encounter edg[0], fac[0], edg[1], fac[1], etc, ending in either the last face if the vertex is not on a boundary or the last edge if the vertex is on a boundary. (If the vertex is on a boundary, the first & last edges are part of that boundary.)

NOTE: OrderVert requires a filled-in mesh with no "bad" vertices. Failing to adequately prepare your mesh may result in a crash. (See the methods FillInMesh and EliminateBadVerts for details.)

Prototype:

void OrderVerts();

Remarks:

This routine organizes the face and edge lists of each vertex such that going counterclockwise around the vertex (with the surface normal pointing up), you’ll encounter edg[0], fac[0], edg[1], fac[1], etc, ending in either the last face if the vertex is not on a boundary or the last edge if the vertex is on a boundary. (If the vertex is on a boundary, the first & last edges are part of that boundary.)

OrderVerts requires a filled-in mesh with no bad vertices, so it will call FillInMesh and/or EliminateBadVerts as needed.

Prototype:

void Triangulate();

Remarks:

Converts a MN_MESH_NONTRI mesh, with polygon faces and possibly hidden vertices, into a completely triangulated mesh, wherein all faces have degree 3. This routine is called from OutToTri if the MN_MESH_NONTRI flag is set.

Prototype:

void TriangulateFace(int ff);

Remarks:

Triangulates the specified face, splitting it into as many faces as are needed (deg-2+hdeg*2) to represent all the triangles.

Parameters:

int ff

Specifies the face to triangulate.

Prototype:

void InvalidateTopoCache();

Remarks:

Clears out topology-dependent cache information. Note that this method clears topology-dependent flags such as MN_MESH_FILLED_IN, and thus invalidates the edge list. If you have taken pains to preserve the integrity of your edge list, you should set the MN_MESH_FILLED_IN flag immediately after calling InvalidateTopoCache().

Prototype:

void Transform(Matrix3 &xfm);

Remarks:

Transforms all vertices & hidden vertices by xfm.

Prototype:

bool IsClosed();

Remarks:

Figures out if this mesh is completely closed. Meshes with the MN_MESH_RATSNEST flags are automatically considered open. Otherwise, each edge is checked to see if it has a face on both sides. If so, the mesh is closed. Otherwise, it’s open.

Prototype:

void BBox(Box3 & bbox, bool targonly=FALSE);

Remarks:

Calculates the bounding box of the vertices & hidden vertices of this mesh.

Parameters:

Box3 & bbox

The computed bounding box is placed here.

bool targonly

If this is TRUE, only targeted vertices are used to compute the bounding box. Hidden vertices, which are also normally used, will be ignored in this case, since they cannot be targeted.

Prototype:

void checkNormals (BOOL illum);

Remarks:

This method is available in release 4.0 and later only.

This method can be used to build the normals and allocate RVert space only if necessary. This is a very inexpensive call if the normals are already calculated. When illum is FALSE, only the RVerts allocation is checked (since normals aren't needed for non-illum rendering). When illum is TRUE, normals will also be built, if they aren't already. So, to make sure normals are built, call this with illum=TRUE.

Parameters:

BOOL illum

If TRUE normals are built. If FALSE only the RVert array is allocated.

Prototype:

void buildNormals ();

Remarks:

This method is available in release 4.0 and later only.

This method resolves the normals on the RVertex array. If the MNMesh already has normals prescribed on each vertex, the normal is just moved to the RVertex array. See Class RVertex and Class RNormal.

If you are creating or modifying a MNMesh, after you are done specifying all the vertices and faces, this method should be called. This allocates the RVertex and RNormal database for the MNMesh. This will allow you to query the MNMesh and ask about normals on the vertices.

This method also builds the face normals for the mesh if needed.

Prototype:

void buildRenderNormals();

Remarks:

This method is available in release 4.0 and later only.

This method is similar to buildNormals() above, but ignores the material index (mtlIndex). In other words, the difference between this and buildNormals() is that it doesn't look at the mtlIndex of the faces: normals of faces with the same smoothing group are averaged regardless.

Prototype:

void UpdateBackfacing (GraphicsWindow *gw, bool force);

Remarks:

This method is available in release 4.0 and later only.

Updates the MN_BACKFACING flag in all components based on the specified view.

Parameters:

GraphicsWindow *gw

A pointer to the current graphics window.

bool force

If the gw points to the same GraphicsWindow that it did last time this method was called, it doesn't necessarily need to update the flags. If force is true, it will update them anyway. (Useful if you think the GraphicsWindow perspective may have changed.)

Prototype:

void render(GraphicsWindow *gw, Material *ma, RECT *rp, int compFlags, int numMat=1, InterfaceServer *pi=NULL);

Remarks:

This method is available in release 4.0 and later only.

Causes the MNMesh to display itself in the indicated GraphicsWindow.

Parameters:

GraphicsWindow *gw

Points to the graphics window to render to.

Material *ma

The list of materials to use to render the mesh. See Class Material.

RECT *rp

Specifies the rectangular region to render. If the mesh should be rendered to the entire viewport pass NULL.

int compFlags

One or more of the following flags:

COMP_TRANSFORM

Forces recalculation of the model to screen transformation; otherwise attempt to use the cache.

COMP_IGN_RECT

Forces all polygons to be rendered; otherwise only those intersecting the box will be rendered.

COMP_LIGHTING

Forces re-lighting of all vertices (as when a light moves); otherwise only re-light moved vertices

COMP_ALL

All of the above flags.

COMP_OBJSELECTED

If this bit is set then the node being displayed by this mesh is selected. Certain display flags only activate when this bit is set.

int numMat=1

The number of materials for the MNMesh.

Prototype:

void renderFace (GraphicsWindow *gw, int ff);

Remarks:

This method is available in release 4.0 and later only.

Displays the indicated face in the GraphicsWindow. This method is usually called only by MNMesh::render().

Parameters:

GraphicsWindow *gw

The GraphicsWindow in which to display this face.

int ff

The face to display.

Prototype:

void render3DFace (GraphicsWindow *gw, int ff);

Remarks:

This method is available in release 4.0 and later only.

Displays the indicated face in the GraphicsWindow using hardware acceleration for texture and lighting if available. This method is usually called only by MNMesh::render().

Parameters:

GraphicsWindow *gw

The GraphicsWindow in which to display this face.

int ff

The face to display.

Prototype:

void render3DDiagonals (GraphicsWindow *gw, DWORD compFlags);

Remarks:

This method is available in release 4.0 and later only.

Displays all face diagonals in the GraphicsWindow using hardware acceleration for texture and lighting if available. See the render method for a description of the parameters. This method is usually called only by MNMesh::render().

Prototype:

void renderDiagonals (GraphicsWindow *gw, DWORD compFlags);

Remarks:

This method is available in release 4.0 and later only.

Displays all face diagonals in the GraphicsWindow. See the render method for a description of the parameters. This method is usually called only by MNMesh::render().

Prototype:

void renderDiagonal (GraphicsWindow *gw, int ff, bool useSegments=false, bool *lastColorSubSel=NULL);

Remarks:

This method is available in release 4.0 and later only.

Displays diagonals for the specified face in the GraphicsWindow. This method is usually called only by MNMesh::render().

Parameters:

GraphicsWindow *gw

The GraphicsWindow in which to display these diagonals.

int ff

The face to display the diagonals of.

bool useSegments = false

Indicates if we are in segment-drawing mode. See class GraphicsWindow, method segment() for details.

bool *lastColorSubSel=NULL

If non-NULL, it points to a bool variable which should be true if the last color set was the subobject selection color (GetSubSelColor()), and false if the color is set to the selected object color (GetSelColor()). This saves processing time that would be needed to switch between the two colors.

Prototype:

void render3DEdges (GraphicsWindow *gw, DWORD compFlags);

Remarks:

This method is available in release 4.0 and later only.

Displays all edges in the GraphicsWindow using hardware acceleration for texture and lighting if available. See the render method for a description of the parameters. This method is usually called only by MNMesh::render().

Prototype:

void renderEdges (GraphicsWindow *gw, DWORD compFlags);

Remarks:

This method is available in release 4.0 and later only.

Displays all edges in the GraphicsWindow. See the render method for a description of the parameters. This method is usually called only by MNMesh::render().

Prototype:

void renderEdge (GraphicsWindow *gw, int ee, bool useSegments=false, bool *lastColorSubSel=NULL);

Remarks:

This method is available in release 4.0 and later only.

Displays an edge in a GraphicsWindow. This method is usually called only by MNMesh::render().

Parameters:

GraphicsWindow *gw

The GraphicsWindow in which to display this edge.

int ee

The edge to display.

bool useSegments = false

Indicates if we are in segment-drawing mode. See class GraphicsWindow, method segment() for details.

bool *lastColorSubSel=NULL

If non-NULL, it points to a bool variable which should be true if the last color set was the subobject selection color (GetSubSelColor()), and false if the color is set to the selected object color (GetSelColor()). This saves processing time that would be needed to switch between the two colors.

Prototype:

BOOL select (GraphicsWindow *gw, Material *ma, HitRegion *hr, int abortOnHit=FALSE, int numMat=1);

Remarks:

This method is available in release 4.0 and later only.

Checks the given HitRegion to see if it intersects this Mesh object.

Parameters:

GraphicsWindow *gw

Points to the graphics window to check.

Material *ma

The list of materials for the mesh.

HitRegion *hr

This describes the properties of a region used for the hit testing. See Class HitRegion.

int abortOnHit = FALSE

If nonzero, the hit testing is complete after any hit. Note that although there is only one object to hit, setting this to TRUE prevents the algorithm from finding the closest hit on the MNMesh.

int numMat=1

The number of materials for the mesh.

Return Value:

TRUE if the item was hit; otherwise FALSE.

Component Targeting & Flag methods

Prototype:

void ClearVFlags(DWORD fl);

Remarks:

Clears all specified flag bits in all MNVerts.

Prototype:

void ClearEFlags(DWORD fl);

Remarks:

Clears all specified flag bits in all MNEdges.

Prototype:

void ClearFFlags(DWORD fl);

Remarks:

Clears all specified flag bits in all MNFaces.

Prototype:

void PaintFaceFlag(int ff, DWORD fl, DWORD fenceflags=0x0);

Remarks:

This method is available in release 2.5 and later only.

Recursively sets flag on given face and all faces connected to it.

Parameters:

int ff

The face to begin painting the face flag on.

DWORD fl

The flag to set on these faces.

DWORD fenceflags=0x0

If nonzero, this represents flags of edges that should not be crossed. In this way you can set up a "fence" of edges and set a particular face flag on all the faces within that fence.

Prototype:

void VertexSelect(const BitArray & vsel);

Remarks:

This method is available in release 3.0 and later only.

Selects or deselects the verticies as specified by on bits in the given bit array. If the bit array size is smaller than the number of verticies then only those verticies in the bit array are modified.

Parameters:

const BitArray & vsel

Specifies which verticies to select or deselect.

Prototype:

void EdgeSelect(const BitArray & esel);

Remarks:

This method is available in release 3.0 and later only.

Selects or deselects the edges as specified by on bits in the given bit array. If the bit array size is smaller than the number of edges then only those edges in the bit array are modified.

Parameters:

const BitArray & esel

Specifies which edges to select or deselect.

Prototype:

void FaceSelect(const BitArray & fsel);

Remarks:

This method is available in release 3.0 and later only.

Selects or deselects the faces as specified by on bits in the given bit array. If the bit array size is smaller than the number of faces then only those faces in the bit array are modified.

Parameters:

const BitArray & fsel

Specifies which faces to select or deselect.

Prototype:

bool getVertexSel(BitArray & vsel);

Remarks:

This method is available in release 3.0 and later only.

Fills the given bit array with the current vertex selection state.

Parameters:

BitArray & vsel

The results are stored here. Bits which are on indicate selected verticies.

Prototype:

bool getEdgeSel(BitArray & esel);

Remarks:

This method is available in release 3.0 and later only.

Fills the given bit array with the current edge selection state.

Parameters:

BitArray & esel

The results are stored here. Bit which are on indicate selected edges.

Prototype:

bool getFaceSel(BitArray & fsel);

Remarks:

This method is available in release 3.0 and later only.

Fills the given bit array with the current face selection state.

Parameters:

BitArray & fsel

The results are stored here. Bit which are on indicate selected faces.

Prototype:

bool getVerticesByFlag(BitArray & vset, DWORD flags, DWORD fmask=0x0);

Remarks:

This method is available in release 3.0 and later only.

Creates a BitArray of all vertices using the specified flags.

Parameters:

BitArray & vset

The BitArray which is filled in. vset is set to size numv.

DWORD flags

The flags to search for.

DWORD fmask=0x0

This optional parameter allows the user to look for particular combinations of on and off flags. For instance, if flags is MN_DEAD and fmask is 0, the method finds vertices with the MN_DEAD flag set. But if flags is MN_SEL and fmask is MN_SEL|MN_DEAD, it would find vertices that have MN_SEL set, but don’t have MN_DEAD set.

Prototype:

bool getEdgesByFlag(BitArray & eset, DWORD flags, DWORD fmask=0x0);

Remarks:

This method is available in release 3.0 and later only.

Creates a BitArray of all edges using the specified flags.

Parameters:

BitArray & eset

The BitArray which is filled in. eset is set to size nume.

DWORD flags

The flags to search for.

DWORD fmask=0x0

This optional parameter allows the user to look for particular combinations of on and off flags. For instance, if flags is MN_DEAD and fmask is 0, the method finds edges with the MN_DEAD flag set. But if flags is MN_SEL and fmask is MN_SEL|MN_DEAD, it would find edges that have MN_SEL set, but don’t have MN_DEAD set.

Prototype:

bool getFacesByFlag(BitArray & fset, DWORD flags, DWORD fmask=0x0);

Remarks:

This method is available in release 3.0 and later only.

Creates a BitArray of all faces using the specified flags.

Parameters:

BitArray & fset

The BitArray which is filled in. fset is set to size numf.

DWORD flags

The flags to search for.

DWORD fmask=0x0

This optional parameter allows the user to look for particular combinations of on and off flags. For instance, if flags is MN_DEAD and fmask is 0, the method finds faces with the MN_DEAD flag set. But if flags is MN_SEL and fmask is MN_SEL|MN_DEAD, it would find faces that have MN_SEL set, but don’t have MN_DEAD set.

Prototype:

void ElementFromFace(int ff, BitArray & fset);

Remarks:

This method is available in release 3.0 and later only.

Sets bits for all faces in the same "element", or connected component, with face ff. Faces already selected in fset will be considered "walls" for this processing and will not be evaluated. That is, if ff is not selected, but there’s a ring of faces around it that is, the algorithm will stop at that ring.

Parameters:

int ff

The zero based index of the face.

BitArray & fset

The bits of the faces in the element are selected in this array.

Prototype:

void BorderFromEdge(int ee, BitArray & eset);

Remarks:

This method is available in release 3.0 and later only.

Takes a one-sided edge and sets the bits representing this edge’s "border". (All one-sided edges in MNMeshes can be grouped into chains, end to end, that represent boundaries of the mesh. For instance, in a box with one side deleted, all the one-sided edges are part of the chain that goes around the hole.

Parameters:

int ee

The edge to start looking from. (Note that edge ee should be one-sided – e[ee].f2 should be -1.

BitArray & eset

The bitarray to return the border’s edge set in.

Prototype:

void SetEdgeVis(int ee, BOOL vis=TRUE);

Remarks:

This method is available in release 3.0 and later only.

This not only sets the edge’s MN_EDGE_INVIS flag, it also sets the visedg state of the faces on either side. This is the proper way to set edge visibility permanently, as the MNEdge flag will be lost if the edge list needs to be reconstructed.

Parameters:

int ee

The edge whose visibility should be set.

BOOL vis=TRUE

The desired visibility – TRUE for visible, FALSE for invisible.

Prototype:

void SetEdgeSel(int ee, BOOL sel=TRUE);

Remarks:

This method is available in release 3.0 and later only.

This not only sets the edge’s MN_SEL flag, it also sets the edgsel state of the faces on either side. This is the proper way to set edge selection permanently, as the MNEdge flag will be lost if the edge list needs to be reconstructed.

Parameters:

int ee

The edge whose selection state should be set.

BOOL sel=TRUE

The desired selection state.

Prototype:

int TargetVertsBySelection(DWORD selLevel);

Remarks:

Sets vertex MN_TARG flags based on the existing MN_SEL flags.

Parameters:

DWORD selLevel

Specifies which components to check for MN_SEL flags. If selLevel is MNM_SL_OBJECT, all vertices are targeted. If selLevel is MNM_SL_VERTEX, the vertices with MN_SEL flags set also have their MN_TARG flags set. If selLevel is MNM_SL_FACE or MNM_SL_EDGE, vertices that touch selected faces or edges, respectively, have their MN_TARG flags set.

Return Value:

The (highly) approximate number of targeted vertices.

Prototype:

int TargetEdgesBySelection(DWORD selLevel);

Remarks:

Sets edge MN_TARG flags based on the existing MN_SEL flags.

Parameters:

DWORD selLevel

Specifies which components to check for MN_SEL flags. If selLevel is MNM_SL_OBJECT, all edges are targeted. If selLevel is MNM_SL_EDGE, the edges with MN_SEL flags set also have their MN_TARG flags set. If selLevel is MNM_SL_FACE or MNM_SL_VERTEX, edges that touch selected faces or vertices, respectively, have their MN_TARG flags set.

Return Value:

The (highly) approximate number of targeted edges.

Prototype:

int TargetFacesBySelection(DWORD selLevel);

Remarks:

Sets face MN_TARG flags based on the existing MN_SEL flags.

Parameters:

DWORD selLevel

Specifies which components to check for MN_SEL flags. If selLevel is MNM_SL_OBJECT, all faces are targeted. If selLevel is MNM_SL_FACE, the faces with MN_SEL flags set also have their MN_TARG flags set. If selLevel is MNM_SL_EDGE or MNM_SL_VERTEX, faces that touch selected edges or vertices, respectively, have their MN_TARG flags set.

Return Value:

The (highly) approximate number of targeted faces.

Prototype:

int PropegateComponentFlags(DWORD slTo, DWORD flTo, DWORD slFrom, DWORD flFrom, bool ampersand=FALSE, bool set=TRUE);

Remarks:

This method is available in release 3.0 and later only.

This allows the developer to set flags in one type of component based on what the nearby flags of another type of component are. For instance, you might want to set MN_TARG on all vertices that are used by faces with the MN_SEL flag set; that would be PropegateComponentFlags (MESH_VERTEX, MN_TARG, MESH_FACE, MN_SEL);

Another example:

PropegateComponentFlags (MNM_SL_OBJECT, MN_MESH_FILLED_IN, MNM_SL_EDGE, MN_DEAD, FALSE, FALSE);

This would clear the MN_MESH_FILLED_IN flag from the MNMesh if any of its MNEdges were dead.

Parameters:

DWORD slTo

The selection level of the components you wish to set. This would be one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE.

DWORD flTo

The flag to set.

DWORD slFrom

The selection level of the components you wish to base the selection upon. This would be one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE.

DWORD flFrom

The flag to test.

bool ampersand=FALSE

When slFrom and slTo are different, this indicates whether the flags of the nearby components should be "or'd" or "and'd". If it's false, then any flagged components in the "from" level will cause the component in the "to" level to be affected. If true, then all the components in the "from" level that touch a component in the "to" level must be flagged in order for the "to" level component to be affected. (i.e., if from is faces and to is vertices, a vertex would only be modified if all faces that use it have the flFrom flag set.)

bool set=TRUE

If TRUE (as would be usual) the slTo components have flags flTo set. If FALSE, these flags would be cleared instead.

Return Value:

Returns the number of slFrom components that tested positive for the flFrom flags. (If 0, nothing happened.)

Prototype:

void DetargetVertsBySharpness(float sharpval);

Remarks:

Clears the MN_TARG flag on vertices representing relatively flat areas, keeping the flag on vertices at sharper corners. The purpose of this method is to avoid working on smooth areas of the mesh in, for instance, tessellation algorithms which are designed to smooth an area. An example of this is the sharpness option in 3ds max’s MeshSmooth modifier, although the parameter there is 1.0 - this value.

Note that this method requires filled in geometry and ordered vertices, and will call FillInMesh and OrderVerts as needed.

Parameters:

float sharpval

The threshold for determining whether a vertex is sharp enough to continue being targeted. A value of 0 indicates that all vertices are sharp enough; a value of 1 would de-target all vertices. The actual determination is made by comparing the dot product of any two consecutive face normals is less that 1 - 2*sharpval.

 

The following "fence" methods are useful for algorithms such as SabinDoo wherein you don’t want to mix faces with different characteristics.

Prototype:

void FenceMaterials();

Remarks:

Sets the MN_EDGE_NOCROSS flag on all edges that lie between faces with different material IDs.

Prototype:

void FenceSmGroups();

Remarks:

Sets the MN_EDGE_NOCROSS flag on all edges that lie between faces with exclusive smoothing groups.

Prototype:

void FenceFaceSel();

Remarks:

Sets the MN_EDGE_NOCROSS flag on all edges that lie between selected & non-selected faces. (This checks the MN_SEL, not the MN_TARG, flags on the faces.)

Prototype:

void FenceOneSidedEdges();

Remarks:

Sets the MN_EDGE_NOCROSS flag on all edges that are on the boundary.

Prototype:

void FenceNonPlanarEdges(float thresh=.9999f, bool makevis=FALSE);

Remarks:

This method is available in release 2.5 and later only.

Sets MN_EDGE_NOCROSS flags on edges between faces that aren't in the same plane.

Parameters:

float thresh=.9999f

This is the threshold used to determine if two adjacent faces have the same normals, i.e. lie in the same plane. If the dot product between the normals is less than thresh, they are considered different, otherwise they're considered the same. The threshold angle between faces is the arc cosine of this amount, so for instance to set a threshold angle of .5 degrees, you would call FenceNonPlanarEdges with a thresh of cos(.5*PI/180.). The default value is equivalent to about .81 degrees.

bool makevis=FALSE

Indicates whether nonplanar edges should be made visible, i.e. have their MN_EDGE_INVIS flag cleared. (This is sometimes done before MakePolyMesh, so it can be used to influence whether nonplanar faces are joined together.)

Prototype:

void SetMapSeamFlags ();

Remarks:

This method is available in release 4.0 and later only.

Sets the MN_EDGE_MAP_SEAM on all edges that are "seams" for any active map(s). A map seam is an edge where the faces on either side use different mapping vertices for at least one end.

Prototype:

void SetMapSeamFlags (int mp);

Remarks:

This method is available in release 4.0 and later only.

Sets the MN_EDGE_MAP_SEAM on all edges that are "seams" for the specified map(s). A map seam is an edge where the faces on either side use different mapping vertices for at least one end.

Parameters:

int mp

The map to use to set the seams. If left at the default -1, it’ll check all active maps.

Prototype:

void SetTVSeamFlags();

Remarks:

Sets the MN_EDGE_TV_SEAM flag on all edges whose endpoints on one face have mapping coordinates that are offset from the mapping coordinates of the same endpoints on the other face by the same amount. Operating on a standard cylinder with mapping coordinates assigned, for instance, this will set the MN_EDGE_TV_SEAM flag on the column of edges that forms the "wrap" boundary for the mapping coordinates.

Prototype:

void PrepForPipeline ();

Remarks:

This method is available in release 4.0 and later only.

Prepares MNMesh for pipeline. This just does a few basic checks and modifies data caches to be consistent. In particular it throws away the edge list if the MN_MESH_FILLED_IN flag is not set, and it frees any data in MN_DEAD map channels. This is a good method to call at the end of any operation on an MNMesh.

Component information methods

 

In the following face center methods, hidden vertices have no effect.

Prototype:

void ComputeCenters(Point3 *ctr, bool targonly=FALSE);

Remarks:

Finds the centers of all the faces, using repeated calls to ComputeCenter.

Parameters:

Point3 *ctr

An array of at least FNum() points for storing the centers.

bool targonly

If this is TRUE, centers will only be computed for targeted faces. (The rest of the ctr array will remain unmodified.)

Prototype:

void ComputeCenter(int ff, Point3 & ctr);

Remarks:

Finds the center of face ff by finding the average of all its vertices.

Prototype:

void ComputeSafeCenters(Point3 *ctr, bool targonly=FALSE, bool detarg=FALSE);

Remarks:

Finds the "safe" centers of all the faces, using repeated calls to ComputeSafeCenter.

Parameters:

Point3 *ctr

An array of at least FNum() points for storing the centers.

bool targonly

If this is TRUE, centers will only be computed for targeted faces. (The rest of the ctr array will remain unmodified.)

bool detarg

If TRUE, this will remove the MN_TARG flag from faces where safe centers could not be found.

Prototype:

bool ComputeSafeCenter(int ff, Point3 & ctr);

Remarks:

Finds the "safe" center of face ff, if possible. For non-convex faces, the average point found in ComputeCenter is unsuitable for some applications because it can lie outside the face completely, or in a region where it cannot "see" all the faces’ vertices. (I.e., line segments from the center to the corner pass outside of the face.)

This routine provides a better solution in some cases by finding the center of the convex hull of the face. The convex hull is defined as the region in a face with a clear line-of-sight to all the corners. Some faces, such as the top face in an extruded letter M, have an empty convex hull, in which case this routine fails and merely provides the regular center given by ComputeCenter.

Return Value:

Returns TRUE if a safe center was found, FALSE if no such center could be found.

Prototype:

void RetriangulateFace(int ff);

Remarks:

This method is available in release 2.5 and later only.

Throws out the current triangulation for face ff and computes a new one. Note that hidden vertices that actually fall outside of the region of the face will be thrown out during this routine, since they cannot be incorporated into any triangulation and don’t make sense anyway.

Prototype:

void BestConvexDiagonals (int ff, int *diag=NULL);

Remarks:

This method is available in release 2.5 and later only.

If the given face is convex, this will often produce a better diagonals than RetriangulateFace would. The diagonals are less likely to overuse any single vertex. The face is not checked for convexity, but if it is not convex the diagonals produced will probably be self-overlapping.

Parameters:

int ff

The face to find a diagonal for.

int *diag=NULL

If NULL, the new diagonals are put into the face's tri array. If this tri is non-NULL, the diagonals are put here instead. Be sure that tri is allocated with space for at least (deg-2+hdeg)*3 elements.

Prototype:

void BestConvexDiagonals (int deg, int *vv, int *diag);

Remarks:

This method is available in release 4.0 and later only.

Uses a triangulation scheme optimized for convex polygons to find a set of diagonals for this sequence of vertices, creating a triangulation for the polygon they form.

Parameters:

int deg

The number of vertices in the sequence.

int *vv

The array of vertices.

int *diag

A pointer to an array of size (deg-3)*2 where the diagonals can be put.

Prototype:

void FindDiagonals (int ff, int *diag);

Remarks:

Finds a diagonal of face ff that does not include any hidden vertices. This can be used with the method FindFacePointTri to get a sub-triangle and barycentric coordinates for a hidden vertex, so that vertex can be kept in the face when the non-hidden vertices are moved in some way.

Parameters:

int ff

The face to get an external diagonal of.

int *diag

An array of at least (F(ff)->deg-2)*3 elements to store the diagonals in.

Prototype:

void FindDiagonals (int deg, int *vv, int *diag);

Remarks:

This method is available in release 4.0 and later only.

This method finds diagonals for this sequence of vertices, creating a triangulation for the polygon they form.

Parameters:

int deg

The number of vertices in the sequence.

int *vv

The array of vertices.

int *diag

A pointer to an array of size (deg-3)*2 where the diagonals can be put.

Prototype:

void FaceBBox(int ff, Box3 & bbox);

Remarks:

Finds the bounding box of all vertices and hidden vertices used by face ff.

Prototype:

int FindEdgeFromVertToVert(int vrt1, int vrt2);

Remarks:

Finds an edge connecting these two vertices, if one exists. This algorithm is relatively fast, since it just checks the edges in V(vrt1)’s edge list. However, it requires that the MNMesh be filled in, and it WILL call the much slower FillInMesh routine if the MN_MESH_FILLED_IN flag is not set.

Return Value:

The index of the desired edge, or -1 if no such edge could be found.

Prototype:

void GetVertexSpace (int vrt, Matrix3 & tm);

Remarks:

This method is available in release 4.0 and later only.

Chooses a suitable "local space", and sets tm's rotation to match that space. Does not set tm's translation component. This is easily done by setting tm.SetRow (3, v[vrt].p).

Parameters:

int vrt

The vertex index.

Matrix3 & tm

The transformation matrix.

Prototype:

Point3 GetVertexNormal(int vrt);

Remarks:

Returns the surface normal at the vertex vrt. It computes the normal by taking the average of the face normals from faces that V(vrt) is on, weighted by the angles of the vrt corners of each of those faces. That is, if vrt is at a very acute angle on one face, but a very obtuse angle on the next, the face with the obtuse vrt corner will count much more heavily. The return value has a length of 1.

This normal is not related to the normals used in rendering.

Prototype:

Point3 GetEdgeNormal(int ed);

Remarks:

Returns the surface normal at the edge ed. This is just the average of the face normals on either side, or, if this is an edge with only one face, it’s just that face’s normal. The return value has a length of 1.

This normal is not related to the normals used in rendering.

Prototype:

Point3 GetFaceNormal(int fc, bool nrmlz=FALSE);

Remarks:

Returns the surface normal of face fc. If this face has degree 3, this is the same as the regular 3ds max normal for this face. However, if the face is more complex, the normal may not be the same as the ones for the component triangles.

Parameters:

int fc

The index of the face to find the normal for.

bool nrmlz

Whether or not to scale the result to length 1. If this is FALSE, the length of the return value corresponds (in planar faces) to the area of the face, times 2.

Prototype:

void FlipNormal(int faceIndex);

Remarks:

This method is available in release 4.0 and later only.

This method flips the normal of the indicated face. This is done by reordering the vertices. The faces for any assigned texture map is handled as well.

Parameters:

int faceIndex

The index of the face for which to flip the normal.

Prototype:

Point3 GetEdgeNormal(int vrt1, int vrt2);

Remarks:

This merely combines GetEdgeNormal (int ed) with FindEdge (int vrt1, int vrt2). It returns the normal of the edge connecting vrt1 to vrt2, if such an edge can be found. (If there is no such edge, it returns Point3(0.0f, 0.0f, 0.0f).)

Prototype:

int FindFacePointTri(int ff, Point3 & pt, double *bary, int *tri);

Remarks:

Finds the sub-triangle and (optionally) barycentric coordinates within that triangle of a point that lies on this face. For faces that are not themselves triangles, this helps in particular to create mapping coordinates or vertex colors for new points on this face. To use this method, you must now call MNFace::GetTriangles to get a triangle table, then pass the contents of that table to this method. Note that the optional size of the triangulation array was removed; this is assumed to be (f[ff].deg-2)*3.

Parameters:

int ff

The face.

Point3 & pt

The point.

double *bary

An array of 3 double-precision values to store the barycentric coordinates in. If this is NULL, barycentric coordinates are not computed.

int *tri

An optional alternative triangulation, such as that produced by FindExternalTriangulation. (If NULL, the face’s regular triangulation is used.)

Return Value:

3 times the index of the triangle the point is found in, or -1 if this point doesn’t seem to lie on this face. That is, if this point is found in the triangle represented by tri[6], tri[7], and tri[8], this routine will return 6.

Prototype:

UVVert FindFacePointMapValue(int ff, Point3 & pt, int mp);

Remarks:

This method is available in release 3.0 and later only. It’s the generalized version of the old FindFacePointCV and FindFacePointTV.

Uses FindFacePointTri and the mapping coordinates of the endpoints of the relevant triangle to compute a map vertex corresponding to the point pt. If the point is not on face ff, UVVert (0,0,0) is returned.

This method is useful e.g. for getting map coordinates to match a new vertex when dividing up a face.

Parameters:

int ff

The face to find map coordinates on.

Point3 & pt

The point (lying on the face) to find map coordinates for.

int mp

The map channel to get map coordinates in.

Prototype:

VertColor FindFacePointCV(int ff, Point3 & pt);

Remarks:

Uses FindFacePointTri and the vertex colors of the endpoints of the relevant triangle to compute a vertex color corresponding to the point pt. If the point is not on face ff, VertColor (0.0f,0.0f,0.0f) (black) is returned.

Prototype:

UVVert FindFacePointTV(int ff, Point3 & pt);

Remarks:

Uses FindFacePointTri and the mapping coordinates of the endpoints of the relevant triangle to compute mapping coordinates corresponding to the point pt. If the point is not on face ff, UVVert (0.0f,0.0f,0.0f) is returned.

Prototype:

int IntersectRay (Ray& ray, float& at, Point3& norm);

Remarks:

This method is available in release 4.0 and later only.

Provides the intersection point and normal for the ray with this mesh.

Parameters:

Ray & ray

The ray we want an intersection point for.

float & at

This is filled in with a value giving the intersection point along the ray. (The actual point is computed by ray.p + ray.dir*at.)

Point3 & norm

Filled in with the surface normal at the intersection point.

Return Value:

Returns TRUE if an intersection point was found, or FALSE if the ray doesn't intersect this MNMesh.

Prototype:

int IntersectRay (Ray& ray, float& at, Point3& norm, int &fi, Tab<float> & bary);

Remarks:

This method is available in release 4.0 and later only.

Provides the intersection point and normal for the ray with this mesh.

Parameters:

Ray & ray

The ray we want an intersection point for.

float & at

This is filled in with a value giving the intersection point along the ray. (The actual point is computed by ray.p + ray.dir*at.)

Point3 & norm

Filled in with the surface normal at the intersection point.

int & fi

Filled in with the face index for the face that was hit by the ray.

Tab<float> & bary

Filled in with the "generalized barycentric coordinates" of the intersection point on the face. This is a table of floats of size f[fi].deg, where each float represents the contribution of the corresponding face vertex, and where the floats all sum to 1.

Return Value:

Returns TRUE if an intersection point was found, or FALSE if the ray doesn't intersect this MNMesh.

Prototype:

BitArray VertexTempSel (DWORD fmask=MN_DEAD|MN_SEL, DWORD fset=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

Gets the current vertex selection, based on the current selection level. That is, if the current selection level is MNM_SL_VERTEX and the parameters are at their defaults, it'll return the current vertex selection, but if the selection level is MNM_SL_FACE, for instance, it'll return the vertices used by currently selected faces.

This method is used, e.g. in PolyObject::Deform to determine which vertices to affect by pipeline modifiers.

Parameters:

DWORD fmask=MN_DEAD|MN_SEL

Indicates the flags we're trying to match in the components at the current selection level.

DWORD fset=MN_SEL

Indicates which flags (from fmask) we want to see set. The default values mean "find components with MN_SEL set and MN_DEAD cleared".

Prototype:

void ShallowCopy(MNMesh *amesh, ULONG_PTR channels);

Remarks:

This method is available in release 4.0 and later only.

Provides the guts of pipeline shallow copying. Used by PolyObject::ShallowCopy().

Prototype:

void NewAndCopyChannels(ULONG_PTR channels);

Remarks:

This method is available in release 4.0 and later only.

Provides the guts of pipeline new & copying. Used by PolyObject::NewAndCopyChannels().

Prototype:

void FreeChannels (ULONG_PTR channels, BOOL zeroOthers=1);

Remarks:

This method is available in release 4.0 and later only.

Provides the guts of pipeline channel freeing. Used by PolyObject::FreeChannels().

Smoothing-group & Material methods

Prototype:

void Resmooth(bool smooth=TRUE, bool targonly=FALSE, DWORD targmask=~0x0);

Remarks:

Applies new smoothing (or removes smoothing groups) from selected areas of the MNMesh. With the default parameters, it smoothes all faces with the same group.

Parameters:

bool smooth

If TRUE, Resmooth will generate a new smoothing group (using GetNewSmGroup) to apply to the relevant faces. All smoothing groups previously assigned to the faces will be removed. If FALSE, Resmooth will strip all smoothing groups, leaving the faces faceted.

bool targonly

If TRUE, Resmooth will not affect faces that are do not have the MN_TARG flag set.

DWORD targmask

Resmooth will only affect faces whose smoothing groups are included in targmask. Some examples: with the default value of ~0x0, this is no restriction at all. With a value of 0, Resmooth will only affect faces that previously had no smoothing group assigned. With a value of 0x02, Resmooth will only affect faces that either had smoothing group 2 (and nothing else) or no smoothing group.

Note: if targonly is TRUE and targmask is not at the default, a face must both be targeted and have its smoothing groups fall into targmask in order to be affected.

Prototype:

DWORD CommonSmoothing(bool targonly=FALSE);

Remarks:

Finds what smoothing groups, if any, are common to all faces in this MNMesh.

Parameters:

bool targonly

If this is TRUE, this routine will find smoothing groups that are common to all faces with MN_TARG set, ignoring the rest.

Prototype:

DWORD GetAllSmGroups(bool targonly=FALSE);

Remarks:

This method is available in release 2.5 and later only.

Find all smoothing groups used in this mesh.

Parameters:

bool targonly=FALSE

If TRUE, this method will return only smoothing groups set in targeted faces, i.e. those with the MN_TARG flag set.

Return Value:

The return value is a DWORD with every used smoothing bit set.

Prototype:

DWORD GetNewSmGroup(bool targonly=FALSE);

Remarks:

Produces a single smoothing group that is not currently used in the MNMesh. If this is impossible because all smoothing groups are used (a rare condition), it produces the least commonly used group.

Parameters:

bool targonly

If TRUE, this routine will find a smoothing group not used by any of the faces with MN_TARG set. If this is impossible because all smoothing groups are used in targeted faces, it produces the least commonly used group.

Prototype:

DWORD FindReplacementSmGroup(int ff, DWORD os);

Remarks:

This method is available in release 2.5 and later only.

Finds available smoothing groups you can use to replace the given smoothing group without messing up the mesh's shading. This method recursively looks at the entire region of faces sharing this smoother with this face, and it finds all smoothing groups used by neighboring faces. Then it returns the bits which are not used by any of them.

This is useful if, for instance, you want to attach two separate mesh components, but you don't want smooth shading across the join. It's used internally by SeparateSmGroups.

Parameters:

int ff

The face to start the examination on.

DWORD os

The old smoothing group you wish to replace.

Return Value:

All bits that are available to replace the old smoothing group with.

Prototype:

void PaintNewSmGroup(int ff, DWORD os, DWORD ns);

Remarks:

This method is available in release 2.5 and later only.

Recursively replaces the old smoothing group with the new smoothing group. The recursion traverses all faces with the old smoother that share an edge or a vertex.

Parameters:

int ff

The face to begin the replacement on

DWORD os

The old smoothing group

DWORD ns

The new smoothing group

Prototype:

bool SeparateSmGroups(int v1, int v2);

Remarks:

This method is available in release 2.5 and later only.

Changes the smoothing groups on faces using v2 so that they are distinct from any smoothing groups on faces using v1. This is used, for instance, in joining the seam between the operands MakeBoolean. Before welding each pair of vertices, this method is called to prevent smoothing across the boolean seam.

Return Value:

If, due to overuse of the 32 smoothing groups, the algorithm can't find enough new ones to replace the overlapping smoothing groups around v2, it will do the best it can and return FALSE. If it succeeds, it returns TRUE.

Prototype:

MtlID GetNewMtlID(bool targonly = FALSE);

Remarks:

Produces the lowest material ID not used in any faces in the MNMesh.

Parameters:

bool targonly

If TRUE, this routine will instead find the lowest material ID not used in the targeted faces of this MNMesh.

Prototype:

DWORD GetOldSmGroup(bool targonly=FALSE);

Remarks:

Returns a smoothing group that is currently used somewhere in the mesh, or returns zero if all faces have no smoothing.

Parameters:

bool targonly

If TRUE, this routine will find a smoothing group used in one of the targeted faces, or return zero if all targeted faces have no smoothing.

Prototype:

void AutoSmooth(float angle,BOOL useSel,BOOL preventIndirectSmoothing);

Remarks:

This method is available in release 4.0 and later only.

This method performs an auto smooth on the mesh, setting the smoothing groups based on the surface normals.

Parameters:

float angle

The minimum angle between surface normals for smoothing to be applied, in radians.

BOOL useSel

If TRUE only the selected faces are smoothed.

BOOL preventIndirectSmoothing=FALSE

TRUE to turn on; FALSE to leave off. This matches the option in the Smooth Modifier UI -- use this to prevent smoothing ‘leaks" when using this method. If you use this method, and portions of the mesh that should not be smoothed become smoothed, then try this option to see if it will correct the problem. Note that the problem it corrects is rare, and that checking this slows the Auto Smooth process.

Prototype:

void ApplyMapper (UVWMapper & mp, BOOL channel=0, BOOL useSel=FALSE);

Remarks:

This method is available in release 4.0 and later only.

Applies UVW Mapper to create the desired mapping in the specified channel.

Parameters:

UVWMapper & mp

The mapping scheme. See class UVWMapper for details.

BOOL channel=0

The channel to apply the map to. Channel 0 is normally the vertex color channel. Channels 1-99 are the normal user-accessible mapping channels. Channels MAP_SHADING and MAP_ALPHA are used for vertex illumination and alpha.

BOOL useSel=FALSE

Indicates whether the specified mapping should be applied only to selected faces (instead of the whole object). In cases where the map channel was previously unused, a default map will be applied to nonselected faces, and the specified map will be applied to the selected faces.

Face-joining methods

Prototype:

void MakePolyMesh();

Remarks:

Turns a mesh with triangle faces into a mesh with (fewer) polygon faces by removing all hidden edges. This method can take unusually long if there are faces of ridiculously high degree, such as the top of a cylinder with 200 sides but only 1 cap segment. (It can be up to an n-squared routine where n is the number of invisible edges removed to make a given face.)

This routine is essentially a bunch of calls to RemoveEdge(), followed by a call to EliminateCollinearVerts().

Prototype:

void MakeConvexPolyMesh();

Remarks:

This method is available in release 2.5 and later only.

Turns a mesh with triangle faces into a mesh with (fewer) convex polygon faces by removing all hidden edges that aren't necessary to maintain convexity. As of the 2.5 release this method has not been thoroughly tested to ensure that the result is indeed always convex and that it doesn't leave edges that should ideally be removed. Therefore a call to MakeConvex is recommended after use. What we can say about it is that it will not produce any hidden vertices, as MakePolyMesh does, and that if you're going to use MakeConvex anyway, MakeConvexPolyMesh and MakeConvex are more efficient than MakePolyMesh and MakeConvex are.

MakeConvex essentially undoes a lot of the work done by MakePolyMesh. MakeConvexPolyMesh gives it much less (if anything) to undo.

Prototype:

void RemoveEdge(int edge);

Remarks:

Kills the edge and joins the faces on either side. Does not work with one-sided edges. Re-indexes triangulation in the resulting face to maintain MN_MESH_FILLED_IN integrity. This routine also checks the resulting face for "dangling" edges: if two faces share a common boundary of 3 edges, and the middle edge is removed, the other two edges will actually have the same face on both sides. This is silly, so such edges are also removed & killed, reducing the degree of the face and adding a hidden vertex.

Prototype:

void MakeConvex();

Remarks:

Calls MakeFaceConvex() on all (non-dead) faces, producing a mesh with 100% convex faces.

Prototype:

void MakeFaceConvex(int ff);

Remarks:

Makes face ff convex, essentially by chopping off corners. The corners themselves become new faces. This routine is actually recursive: if this face is already convex, it returns without affecting it. If not, it finds a suitable line (between outside vertices) to divide the face along, and then calls MakeFaceConvex() again on both of the smaller faces. It is crucial that the face given to MakeFaceConvex has a valid triangulation.

Prototype:

void EliminateCollinearVerts();

Remarks:

This routine scans through a mesh from which invisible edges have been removed, looking for vertices that essentially seem to lie in the middle of edges. Such "collinear vertices" actually lie between two edges that are parallel, with the same faces on either side, and with no other edges incident on them. These are easily removed, and if not removed, they can cause unpleasant artifacts in some tessellation algorithms.

The removal of these vertices consists of deleting them, merging the parallel edges into one (longer) edge, and correcting the faces on either side to have one less vertex and edge.

Note that this is essentially the opposite of the method SplitEdge.

Prototype:

void EliminateCoincidentVerts(float thresh=MNEPS);

Remarks:

This merges vertices that lie extremely close together, similar to what’s done in Edit Mesh’s Weld function, but it only affects vertices that are joined by an edge. Another way of looking at it is that it uses weld to remove extremely small edges.

Parameters:

float thresh=MNEPS

This is the maximum length of an edge that will be welded away. The default value of MNEPS is defined in MNCommon.h to be .0001 -- generally we use this to delete edges of more or less zero length.

Splitting methods

Prototype:

int SplitEdge(int ee, float prop=.5f);

Remarks:

This method is available in release 2.5 and later only.

Creates a new vertex somewhere in the middle of an edge, splitting the edge into two edges. Incident faces are updated in their vertex, edge, mapping coordinate, and vertex color lists, as well as in their triangulation. This method requires that MN_MESH_FILLED_IN be set (otherwise it will cause an assertion failure), and maintains the combinatorics completely.

Parameters:

int ee

The edge to split.

float prop=.5f

The proportion along the edge where the new vertex should go. This proportion should be between 0 and 1. The new vertex location is P(E(ee)->v1)*(1.0f-prop) + P(E(ee)->v2)*prop.

Return Value:

The index of the new vertex.

Prototype:

int SplitEdge(int ff, int ed, float prop, bool right, int *nf=NULL, int *ne=NULL, bool neVis=FALSE, bool neSel=FALSE, bool allconvex=FALSE);

Remarks:

This method is available in release 2.5 and later only.

Splits an edge that is specified from the face level, and splits off triangles from the adjacent faces. This method is often preferable in convex meshes, when it's important that no nonconvex faces are introduced. The other SplitEdge methods leave faces with three vertices in a line, which is not strongly convex. This version makes a triangle out of half of the split edge, the next face edge, and a diagonal.

Note: This method absolutely requires that the faces on either side of the edge being split are Convex. Use MakeFaceConvex if needed.

Parameters:

int ff

One of the faces which uses the edge you wish to split.

int ed

The index of the edge in face ff.

float prop

The proportion along the edge where the new vertex should go. This proportion should be between 0 and 1. The new vertex location is P(E(ee)->v1)*(1.0f-prop) + P(E(ee)->v2)*prop.

bool right

If FALSE, the new triangle is formed from the lower or "left" half of the split edge. If TRUE, it's formed from the higher or "right" half. (These orientations make sense if you imagine viewing the face from above with the split edge on the bottom, as pictured.) If you want the triangle to be formed from the smaller half, use (prop<=.5f) for this argument.

int *nf=NULL

If non-NULL, this should point to an array of at least 2 elements where the new face indices should be put. Nf[0] is set to the new face created from face ff, while nf[1] is set to the new face created from the face on the other side of the edge, if any.

int *ne=NULL

If non-NULL, this should point to an array of at least 3 elements where the new edge indices should be put. Ne[0] is set to the new edge created from the second half of the edge we're splitting. Ne[1] represents the diagonal edge on face ff, while ne[2] represents the diagonal edge on the face on the other side of the split edge (if any).

bool neVis=FALSE

Indicates whether the new edges ne[1] and ne[2] should be visible.

bool neSel=FALSE

Indicates whether the new edges ne[1] and ne[2] should be selected.

bool allconvex=FALSE

Indicates whether the original faces on both sides of the edge are guaranteed to be convex. If so, these faces are retriangulated with BestConvexTriangulation; otherwise, RetriangulateFace is used.

Return Value:

The index of the new vertex.

Prototype:

int SplitTriEdge(int ee, float prop=.5f, float thresh=MNEPS, bool neVis=TRUE, bool neSel=FALSE);

Remarks:

Creates a new vertex in the middle of an edge, splitting the edge into two edges. Unlike SplitEdge, this routine requires a triangle face on each side. Since it has this, it also creates new edges connecting the new vertex with the point opposite the split edge on each face. This in turn splits the faces. So two triangles sharing this single edge become four triangles with four shared edges meeting at a single new vertex.

This method requires that MN_MESH_FILLED_IN be set (otherwise it will cause an assertion failure), and maintains the combinatorics completely.

Parameters:

int ee

The edge to split. Note that if the faces on either side do not have deg=3 and hdeg=0, an assertion failure will result.

float prop

The proportion along the edge for the new vertex to be located. This ranges from 0, at v1, to 1, at v2. A value of .3, for instance, would create a new vertex at .7*P(v1) + .3*P(v2).

float thresh

If prop is less than thresh or more than 1-thresh, the method will not split the edge, and will return v1 or v2 respectively. This is so that calling routines can safely pass values anywhere from 0 to 1, without worrying about creating tiny "shard" faces.

bool neVis

This tells whether the new edges that split the faces should be visible. (The new edge formed from part of the old edge takes such characteristics from the old edge.)

bool neSel

This tells whether the new edges that split the faces should be selected. (The new edge formed from part of the old edge takes such characteristics from the old edge.)

Return Value:

The index of the new vertex created, or the index of the old vertex you can use instead if you’re within thresh of the endpoints.

Prototype:

int IndentFace(int ff, int ei, int nv, int *ne=NULL, bool nevis=TRUE, bool nesel=FALSE);

Remarks:

This method is available in release 2.5 and later only.

Uses a new vertex to "indent" one of the sides of the face. The indentation triangle is split off as a new face, which is returned.

Parameters:

int ff

The face to be "indented".

int ei

The index of the edge which will be replaced by the indentation.

int nv

The index of the new vertex. This vertex should lie within the face, in the face's plane, and should not be connected to any faces or edges.

int *ne=NULL

If non-NULL, this should point to an array of at least 2 elements where the new edges should be stored.

bool nevis=TRUE

Indicates whether the new edges should be visible.

bool nesel=FALSE

Indicates whether the new edges should be selected.

Return Value:

The index of the new face representing the indentation triangle.

Prototype:

void SeparateFace(int ff, int a, int b, int & nf, int & ne);

Remarks:

This routine is used in MakeFaceConvex, but can be used outside of it too. It takes a larger face and divides it into two smaller faces, creating a new edge in the process.

It is crucial that the face given to SeparateFace has a valid triangulation.

Parameters:

int ff

The face to divide.

int a,b

The indices (in the face’s vtx list) of the vertices used to divide the face. Note that a and b should be at least two units apart in each direction: a can’t be (b+1) mod deg, and b can’t be (a+1) mod deg. Also, the straight line connecting MNVerts V(vtx[a]) and V(vtx[b]) should not cross any of the edges of the face, otherwise the results will be truly screwed.

int & nf

A variable to hold the new face created by this division. (Half the face remains as face ff, the other half is the new face nf.)

int & ne

A variable to hold the new edge created by this division.

Prototype:

void SeparateFace(int ff, int a, int b, int & nf, int & ne, bool neVis, bool neSel);

Remarks:

This method is available in release 2.5 and later only.

This routine takes a larger face and divides it into two smaller faces, creating a new edge in the process. It is crucial that the face given to SeparateFace has a valid triangulation.

Parameters:

int ff

The face to divide.

int a, b

The indices (in the face’s vtx list) of the vertices used to divide the face. Note that a and b should be at least two units apart in each direction: a can’t be (b+1) mod deg, and b can’t be (a+1) mod deg. Also, the straight line connecting MNVerts V(vtx[a]) and V(vtx[b]) should not cross any of the edges of the face, otherwise the results will not be valid.

int & nf

A variable to hold the new face created by this division. (Half the face remains as face ff, the other half is the new face nf.)

int & ne

A variable to hold the new edge created by this division.

bool neVis

Indicates whether the new edge should be visible. (The other version of SeparateFace always leaves the edge invisible.)

bool neSel

Indicates whether the new edge should be selected. (The other version of SeparateFace always leaves the edge unselected.)

Prototype:

void Slice(Point3 & N, float off, float thresh, bool split, bool remove, DWORD selLevel);

Remarks:

This method is available in release 2.5 and later only.

Slices the MNMesh along a specified plane, splitting edges and faces as needed to divide faces into those above and those below the plane. Equivalent to the Slice modifier.

Parameters:

Point3 & N

The normal to the slice plane. This should be a unit vector.

float off

The offset of the slice plane. For any point X in the plane, DotProd(N,X) = off.

float thresh

If a vertex lies within thresh of the splitting plane, ie if absf(DotProd (N,X) - offset) < thresh for a point X, it's considered to be on the plane. This prevents some points being created extremely close to each other. Zero is an acceptable value; the constant MNEPS is what's used in the Slice Modifier.

bool split

Indicates whether the points and edges along the slice should be replicated, dividing the mesh into separate "above" and "below" connected components. Equivalent to the Slice modifier's "Split Mesh".

bool remove

Indicates whether the portion of the mesh above the split plane should be removed. Equivalent to the Slice modifier's "Remove Top". (To "Remove Bottom", just multiply N and off by -1.)

DWORD selLevel

Indicates whether the Slice effect should be restricted to selected faces.

There is no support currently for slicing selected edges or vertices, but

if selLevel== MNM_SL_FACE, only selected faces will be sliced or removed.

Prototype:

int SplitTriFace(int ff, double *bary=NULL, float thresh=MNEPS, bool neVis=TRUE, bool neSel=FALSE);

Remarks:

Adds a vertex somewhere in a triangle face, and also adds edges from that vertex to each of the corners, splitting the face into 3 smaller triangle faces. The triangle face used here can have hidden vertices, as long as it is of degree 3. However, if the threshold parameter comes into play and this routine calls SplitTriEdge, both this face and the one across the relevant edge will need to have both degree 3. (Otherwise there’s an assertion failure.)

This method requires that MN_MESH_FILLED_IN be set (otherwise it will cause an assertion failure), and maintains the combinatorics completely.

Parameters:

int ff

The face to split.

double *bary

The barycentric coordinates of the new point you wish to add. If this is NULL, the default values of (1/3, 1/3, 1/3) (the middle of the triangle) are used. These values MUST all fall between 0 and 1, and they MUST add up to 1 (give or take a floating point error) to get a sensible result.

float thresh

If one of the barycentric coordinates is greater than 1-thresh, that vertex dominates completely. No splitting is done, and that vertex is returned. If not, but if one of the barycentric coordinates is less than thresh, the new point must fall on the opposite edge. SplitTriEdge is therefore called on that edge, and passes along the value this returns.

bool neVis

Whether or not the new edges connecting the new vertex to the corners should be visible.

bool neSel

Whether or not the new edges connecting the new vertex to the corners should be selected.

Return Value:

The index of the new vertex created, or the index of the old vertex you can use instead if you’re within thresh of one of the corners.

Prototype:

void SplitTri6(int ff, double *bary=NULL, int *nv=NULL);

Remarks:

This is another way to subdivide a face on a triangular mesh into sub-triangles. In this case, 4 new vertices are produced, and this face becomes 6 new faces. MN_MESH_FILLED_IN is required and preserved, and MN_MESH_NONTRI cannot be true when this method is called.

The subdivision technique is as follows: a new point is added at the barycentric coordinates given on the face given. New points are also added in each edge of the original face, such that a line from each of these three new edge points to the opposite original vertex passes through the new center point. These three edge points have edges drawn between them, and have edges to the new center point, dividing the face into 3 large outer triangles and 3 smaller inner triangles. Neighboring faces are split into 2 triangles, since the common edge is divided. This is a useful subdivision technique when you know you're going to want to add a lot of detail to a specific region of a face.

Parameters:

int ff

The face to split.

double *bary=NULL

The barycentric coordinates for the center point. If bary is NULL, the default barycentric coordinates of (1/3, 1/3, 1/3) are used.

int *nv=NULL

This is a pointer to an array of at least 4 int's in which the 4 new vertex indices should be stored. (This is mainly if the calling routine needs to know what these new vertices are.) If this is NULL, it is ignored.

Border methods

Prototype:

void GetBorder(MNMeshBorder & brd, DWORD selLevel=MESH_OBJECT);

Remarks:

Finds border loops composed of all one-sided edges. (One-sided edges on a mesh must necessarily be organizable into closed loops along the borders of the mesh.)

Parameters:

MNMeshBorder & brd

The class in which to put the border loops. See Class MNMeshBorder for details.

DWORD selLevel

The selection level in the mesh to use to decide whether the border loops are targeted or not. For instance, with the default MNM_SL_OBJECT, all border loops are targeted, but with a value of MNM_SL_VERTEX, only those border loops containing at least one selected vertex will be targeted. Same for MNM_SL_EDGE. For MNM_SL_FACE, those loops touching at least one selected face will be targeted.

Prototype:

void FillInBorders(MNMeshBorder *b=NULL);

Remarks:

Fills in all the borders of a mesh. This is what the 3ds max CapHoles modifier does. It creates new faces on the other side of each of the loops.

Parameters:

MNMeshBorder *b

If this is NULL, FillInBorders finds all the borders with a call to GetBorders. If you have already found the borders, however, you can save time by passing a pointer to the MNMeshBorder class here. (This is especially convenient if you wish to modify the border targeting; only targeted borders are filled in.)

Prototype:

void FindOpenRegions();

Remarks:

This method is available in release 2.5 and later only.

Scans mesh to determine what parts of it are open or closed. Consider a "submesh" to be one connected components of faces and edges. Each submesh is open if it has any holes, i.e. if there's at least one edge which has only one face. (The hole is on the other side.) A submesh is closed if it doesn't have any. This method sets the MN_FACE_OPEN_REGION flag on all faces in open submeshes, and sets the MN_MESH_HAS_VOLUME flag if at least one submesh is closed.

Examples:

A 3ds max box has one submesh, itself, and it is closed.

A 3ds max teapot has four distinct submeshes (handle, spout, lid, and body), and they are all open.

Prototype:

void FindEdgeListTCVerts(const IntTab & lp, IntTab & tv, IntTab & cv);

Remarks:

Given a complete loop boundary of edges in the MNMesh, this method will find mapping coordinates and/or vertex colors for the vertices of the loop.

Parameters:

(IntTab means Tab<int>)

const IntTab & lp

The loop of edges.

IntTab & tv

The location to put the mapping coordinates’ indices. Since each vertex on the loop lies can lie on two faces, one corresponding to each border edge touching the vertex, there are 2*lp.Count() of these values. tv[i*2] is the mapping vertex used for vertex E(lp[i])->v1 in face E(lp[i])->f1, while tv[(i-1)*2+1] is the mapping vertex used for vertex E(lp[i-1])->v2 (which is also E(lp[i]->v1) in face E(lp[i-1])->f1.

IntTab & cv

The location to put the vertex colors’ indices. Since each vertex on the loop lies can lie on two faces, one corresponding to each border edge touching the vertex, there are 2*lp.Count() of these values. cv[i*2] is the vertex color used for vertex E(lp[i])->v1 in face E(lp[i])->f1, while tv[(i-1)*2+1] is the vertex color used for vertex E(lp[i-1])->v2 (which is also E(lp[i]->v1) in face E(lp[i-1])->f1.

Tessellation & related methods

Prototype:

void Relax(float relaxval, bool targonly=TRUE);

Remarks:

Similar to the 3ds max "Relax" modifier: this modifier moves each MNVert towards the average of all vertices to which it is connected (by MNEdges).

Parameters:

float relaxval

The proportion to move it. If p is the original location of this vertex and q is the average point of all vertices it’s connected to, this vertex is moved to p*(1-relaxval) + q*relaxval. A value of 0 generates no "relaxation", 1 is maximum relaxation, and values below 0 or above 1 generate non-relaxing results.

bool targonly

If this is set, only those MNVerts with the MN_TARG flag set will be moved.

Prototype:

void FindEdgeListMapVerts(const Tab<int> & lp, Tab<int> & mv, int mp);

Remarks:

This method is available in release 3.0 and later only.

Returns map verts for both ends of each edge (from f1's perspective) (Very useful for creating new faces at borders.) mv[j*2] is the map vertex corresponding to edge j's v1.

Parameters:

const Tab<int> & lp

A loop of border edges, such as is generated by MNMesh::FindBorders.

Tab<int> & mv

The table into which the map vertices should be put. The size is set to 2*lp.Count().

int mp

The map channel we’re analyzing.

Prototype:

bool AndersonDo(float interp, DWORD selLevel, MeshOpProgress *mop=NULL, DWORD subdivFlags=0);

Remarks:

This is a tessellation routine. It breaks every MNFace into deg new faces with four sides. The four vertices of each of these new quads come from the center point of the original face, one corner of the original face, and the middles of the two edges on either side of that corner. For a demonstration of the effect this algorithm has on meshes, apply 3ds max’s MeshSmooth modifier with the "Quad Output" box checked. Note that this algorithm roughly quadruples the size of the MNMesh.

Parameters:

float interp

This is the proportion of relaxation applied to the original vertices to produce a smoothed result. Vertices in the result correspond to three sources: all the original vertices are still included, new vertices are produced at the center of each face, and new vertices are produced in the middle of each edge. Face-vertices are always at the exact center of the original faces, but edge-vertices and vertex-vertices are relaxed into the mesh to improve smoothness.

DWORD selLevel

The selection level that the Mesh we’re modifying was set to. If this selection level is MNM_SL_FACE, we’d want to keep non-selected faces as unmodified as possible, whereas if the selection level is MNM_SL_OBJECT or MNM_SL_VERTEX, we could break off chunks of some unselected faces that touch modified vertices. Again, observe the result of MeshSmooth, with Quad Output, on various selection sets of a mesh for examples of this behavior.

MeshOpProgress *mop=NULL

This optional parameter points to an instance of the virtual class MeshOpProgress, which is used to allow the user to abort out of lengthy calculations. (SabinDoo is a lengthy calculation.) See class MeshOpProgress.

DWORD subdivFlags=0

This parameter is available in release 4.0 and later only.

There is currently only one flag for the extra argument, MNM_SUBDIV_NEWMAP. If this flag is set, the new mapping scheme will be used.

Prototype:

void TessellateByEdges(float bulge, MeshOpProgress *mop=NULL);

Remarks:

This is a tessellation routine similar to AndersonDo. It produces the same topology, but bulges new vertices outward to maintain even curvature instead of bringing the original vertices inward. For a demonstration of the effect this algorithm has on meshes, apply 3ds max’s Tessellate modifier with the "Edge" and "Operate On: Polygons" options selected. Note that this algorithm roughly quadruples the size of the MNMesh.

Parameters:

float bulge

The factor to "push out" new vertices by in the direction of the surface curvature. Values of about .25 are reasonable. This value is equivalent to one hundredth of the value specified as "Tension" in the Tessellate modifier.

MeshOpProgress *mop=NULL

A pointer to a MeshOpProgress. See Class MeshOpProgress for details.

Prototype:

void TessellateByCenters();

Remarks:

This is a tessellation routine. Note that this algorithm roughly triples the size of the MNMesh. For an example of how it works, apply 3ds max’s Tessellate modifier with the "Face" and "Operate On: Polygons" options selected. This algorithm splits each face into deg triangles, where each triangle contains the center of the face and one edge from the perimeter.

Prototype:

void SabinDoo(float interp, DWORD selLevel, MeshOpProgress *mop=NULL, Tab<Point3> *offsets=NULL);

Remarks:

This is a tessellation routine. Note that this algorithm roughly triples the size of the MNMesh. For an example of how it works, apply 3ds max’s MeshSmooth modifier with "classic" MeshSmooth Type.

This technique for tessellation is based on a paper, "A Subdivision Algorithm for Smoothing Down Irregularly Shaped Polygons", published by D. W. H. Doo of Brunel University, Middlesex, England, in IEEE in 1978. It essentially creates a new face for every vertex, face, and edge of the original mesh. The new vertices this technique requires are made by creating one vertex for each corner of each original face. These vertices are located on a line from the original face corner to its center. All the faces around a given (targeted) vertex will create such a point; these points form the corners of the face created from this vertex. The original faces become smaller, as they use the new points instead of their old corners. And the four new points created on the faces on either side of an edge, for the endpoints of that edge, become the four corners of the new face representing the edge. Apply a MeshSmooth with default values to a 3ds max box to see how this plays out.

Parameters:

float interp

The position along the line from a vertex to the center of each face to create the new vertex at. If this value is near 0, the original faces will shrink very little, and the new faces at the vertices and edges will be very small. If this value is near 1, the original faces will shrink to almost nothing, and the new vertex faces will be dominant. Again, adjust the Strength parameter in MeshSmooth to gain an understanding of this parameter.

DWORD selLevel

This parameter is included so that special handling can be applied to selected faces, if we’re at the MNM_SL_FACE selection level. Generally, this algorithm works on all targeted vertices, affecting all faces that contain at least one targeted vertex. However, if the vertices are targeted by whether or not they’re on selected faces, we’ll wind up "spilling" the algorithm over into the non-selected faces. Generally in such routines as MeshSmooth, the user would want non-selected faces not to be affected at all. If this is the case, setting this value to MNM_SL_FACE will prevent faces without the MN_SEL flag from being affected.

MeshOpProgress *mop=NULL

This optional parameter points to an instance of the virtual class MeshOpProgress, which is used to allow the user to abort out of lengthy calculations. (SabinDoo is a lengthy calculation.) See Class MeshOpProgress.

Tab<Point3> *offsets=NULL

The SabinDoo algorithm is typically used to go from one polygonal approximation of a smooth surface to another polygonal approximation of 4 times the size, but it never actually returns the vertices as they would appear on the "limit surface". If this parameter is non-NULL, it’s filled in with offsets that will, when added to the vertices in the SabinDoo result, take those vertices onto the limit surface. This makes a smoother result that matches better between different iterations.

Prototype:

void SabinDooVert(int vid, float interp, DWORD selLevel, Point3 *ctr, MeshOpProgress *mop=NULL, Tab<Point3> *offsets=NULL);

Remarks:

This applies the Sabin-Doo tessellation technique described above to a single vertex. The vertex is split into as many new vertices as there are faces using this vertex. The incident faces are shrunk back to make use of these new vertices, and a new face is created from them representing the vertex. Incident edges are split into triangles using their other end and the appropriate edge from the new vertex-face. To see the result of this algorithm, apply MeshSmooth (with default parameters) to an EditableMesh with a single vertex selected.

Parameters:

int vid

The vertex to SabinDoo.

float interp

The proportion from this vertex to the center of each of the incident faces to put the new vertex for that face.

DWORD selLevel

If this is equal to MNM_SL_FACE, faces without the MN_SEL flag will not be affected.

Point3 *ctr

This is a list of centers of all the faces, which cannot be NULL. Since this algorithm changes the original faces, merely computing face centers on the fly won’t work. (When SabinDooing two vertices on a given face, the second vertex will get bad center information.) Thus the user should compute all the face centers in advance using ComputeCenters or (preferably) ComputeSafeCenters.

MeshOpProgress *mop=NULL

This optional parameter points to an instance of the virtual class MeshOpProgress, which is used to allow the user to abort out of lengthy calculations. (SabinDoo is a lengthy calculation.) See Class MeshOpProgress.

Tab<Point3> *offsets=NULL

The SabinDoo algorithm is typically used to go from one polygonal approximation of a smooth surface to another polygonal approximation of 4 times the size, but it never actually returns the vertices as they would appear on the "limit surface". If this parameter is non-NULL, it’s filled in with offsets that will, when added to the vertices in the SabinDoo result, take those vertices onto the limit surface. This makes a smoother result that matches better between different iterations.

(In SabinDooVert, the offsets for the vertices created by this method are filled in. The offsets table is resized if necessary to accommodate this.)

Prototype:

void CubicNURMS(MeshOpProgress *mop=NULL, Tab<Point3> *offsets=NULL, DWORD subdivFlags=0);

Remarks:

This method is available in release 3.0 and later only.

This is a tessellation routine. Note that this algorithm roughly quadruples the size of the MNMesh. For an example of how it works, apply 3ds max’s MeshSmooth modifier with "NURMS" MeshSmooth Type.

This technique for tessellation is based loosely on a 1998 SIGGraph paper, "Non-Uniform Recursive Subdivision Surfaces", by Sederberg, Zheng, Sewell, and Sabin, with additional work by Autodesk staff. Topologically, it’s quite simple, as it creates a vertex in the center of every edge and face and connects these vertices with quads. However, the geometry is a non-uniform rational extension of the old Catmull-Clark standard cubic subdivision.

To set the vertex and edge weights used by the algorithm, use the EdgeKnots and VertexWeights methods of MNMesh. Like other subdivision routines, this routine only subdivides areas of the MNMesh indicated by the MN_TARG flag on vertices, and uses the MNEdge::Uncrossable method to determine where the regional boundaries should be.

Parameters:

MeshOpProgress *mop=NULL

See Class MeshOpProgress – provides a way to abort the calculation.

Tab<Point3> *offsets=NULL

Unused for now.

DWORD subdivFlags=0

This parameter is available in release 4.0 and later only.

There is currently only one flag for the extra argument, MNM_SUBDIV_NEWMAP. If this flag is set, the new mapping scheme will be used.

Prototype:

BOOL CheckForDoubledMappingVerts();

Remarks:

This method is available in release 4.0 and later only.

This method is used as a debugging tool. All double mapping vertices will be debugprinted. "Doubled" mapping verts are individual map vertices that are used to correspond to different regular vertices. For example, the standard map on the box object uses the same mapping vertices on the top as on the bottom. This can be a problem if the user wants to change the map in one region, but not the other. It also causes problems in NURMS MeshSmooth, where the user can change weights in one region but not in the other.

Prototype:

void EliminateDoubledMappingVerts();

Remarks:

This method is available in release 4.0 and later only.

This method will allow you to eliminate double mapping vertices. "Doubled" mapping verts are individual map vertices that are used to correspond to different regular vertices. For example, the standard map on the box object uses the same mapping vertices on the top as on the bottom. This can be a problem if the user wants to change the map in one region, but not the other. It also causes problems in NURMS MeshSmooth, where the user can change weights in one region but not in the other.

Prototype:

void EliminateIsoMapVerts();

Remarks:

This method is available in release 4.0 and later only.

Eliminates mapping vertices that aren't used by any mapping faces.

Prototype:

void EliminateIsoMapVerts(int mp);

Remarks:

This method is available in release 4.0 and later only.

Eliminates mapping vertices that aren't used by any mapping faces.

Parameters:

int mp

If mp>=0, it indicates the mapping channel that should have its isolated verts removed. If left at the default, all mapping channels are cleared of iso verts.

Welding methods

Prototype:

bool WeldVerts(int a, int b);

Remarks:

This method is available in release 2.5 and later only.

Welds vertices a and b, correcting the mesh topology to match. All references to b are moved to a, and b is killed. If there is a topological problem preventing the weld from occurring, the method does nothing and returns FALSE. If there is no such problem, the weld goes ahead and returns TRUE. Note that if a and b are joined by an edge, this method just calls WeldEdge on that edge.

Prototype:

bool WeldEdge(int ee);

Remarks:

This method is available in release 2.5 and later only.

Welds the endpoints of edge ee, correcting the mesh topology to match. All references to E(ee)->v2 are moved to E(ee)->v1, and both ee and E(ee)->v2 are killed. If there is a topological problem preventing the weld from occurring, the method does nothing and returns FALSE. If there is no such problem, the weld goes ahead and returns TRUE.

Prototype:

bool WeldBorderVerts (int v1, int v2, Point3 *destination);

Remarks:

This method is available in release 4.0 and later only.

This method welds vertices v1 and v2 together. Both vertices must be on borders, and they cannot share an edge. If destination isn't NULL, it indicates where the welded vertex should be located. (If it is NULL, the welded vertex is placed at the midpoint of the inputs.)

Parameters:

int v1, v2

The vertex indices to wel.

Point3 *destination

The destination of the welded vertex.

Return Value:

TRUE if something was welded, FALSE otherwise.

Prototype:

bool WeldBorderEdges (int e1, int e2);

Remarks:

This method is available in release 4.0 and later only.

This method welds edges e1 and e2 together. Both edges must be on borders.

Parameters:

int e1, e2

The two edges you want to weld.

Return Value:

TRUE if something was welded, FALSE otherwise.

Prototype:

bool WeldBorderVerts (float thresh, DWORD flag=MN_SEL);

Remarks:

This method is available in release 4.0 and later only.

This method welds all flagged border vertices within "thresh" of each other. Vertices are only welded pairwise. If vert A's closest target is vert B, but vert B is closer to vert C, verts B and C are welded and A is left out in the cold.

Parameters:

float thresh

The threshold.

DWORD flag=MN_SEL

This indicates the vertices we look at. If left at the default, selected vertices' colors are analyzed. If flag were to equal MN_WHATEVER, then vertices with the MN_WHATEVER flag would have their colors analyzed.

Return Value:

TRUE if something was welded, FALSE otherwise.

Prototype:

bool DetachElementToObject (MNMesh & nmesh, DWORD fflags=MN_SEL, bool delDetached=true);

Remarks:

This method is available in release 4.0 and later only.

Detaches specified faces (and related vertices and edges) to a new MNMesh. As indicated by the name, the specified region should be a single element; crashes will occur if faces that are flagged share vertices or edges with nonflagged faces.

Parameters:

MNMesh & nmesh

The new mesh. This is assumed to be empty. The flagged elements are put here, and reindexed so there are no unused components. (This occurs for all map channels as well - only the necessary map vertices are copied over.)

DWORD fflags

The flags that indicate the faces which compose the element we want to detach.

bool delDetached=true

Indicates whether the specified element should be deleted from this MNMesh.

Return Value:

true if anything was detached, false otherwise.

Boolean operations

Prototype:

void PrepForBoolean();

Remarks:

This method is available in release 2.5 and later only.

Prepares a MNMesh for a Boolean operation. This is required for successful Booleans. Generally, it makes the mesh into a convex poly mesh, removing any hidden vertices, finds open regions, and collapses dead structures.

Prototype:

bool BooleanCut(MNMesh & m2, int cutType, int fstart=0, MeshOpProgress *mop=NULL);

Remarks:

This method is available in release 3.0 and later only.

BooleanCut uses the same techniques as MakeBoolean to cut the faces of this with the faces of m2. As with Boolean, both this and m2 should be prepared with the PrepForBoolean method.

Parameters:

MNMesh & m2

The MNMesh to use to cut this one.

int cutType

One of the following:

BOOLOP_CUT_REFINE

Slice the faces of this with the surface of m2, but do not separate the mesh along the seam.

BOOLOP_CUT_SEPARATE

Slice and separate the faces of this along the surface of m2.

BOOLOP_CUT_REMOVE_IN

Slice the faces of this with the surface of m2, then remove all the faces of this that are inside m2.

BOOLOP_CUT_REMOVE_OUT

Slice the faces of this with the surface of m2, then remove all the faces of this that are inside m2.

int fstart=0

Indicates the face (of this) we should start checking for cuts by m2. This can be useful if, for example, you know that the first 100 faces of this are nowhere near m2.

MeshOpProgress *mop=NULL

See Class MeshOpProgress. Provides a way to abort the calculation.

Return Value:

TRUE if finished successfully; FALSE if aborted by the MeshOpProgress.

Prototype:

bool MakeBoolean(MNMesh & m1, MNMesh & m2, int type, MeshOpProgress *mop=NULL);

Remarks:

This method is available in release 2.5 and later only.

Makes this MNMesh into a Boolean result of the given MNMeshes. The operands are not modified during this process. The Boolean algorithm is identical to the one used in the Boolean 2 compound object. Notice that there are no transform arguments, as there are in the previously used CalcBoolOp – transforms should be applied to the operands beforehand using the MNMesh::Transform method.

Parameters:

MNMesh & m1

The first operand mesh, which should have had PrepForBoolean called.

MNMesh & m2

The second operand mesh, which should have had PrepForBoolean called.

int type

The type of Boolean. The Boolean types are defined in mesh.h, and are one of MESHBOOL_UNION, MESHBOOL_INTERSECTION, or MESHBOOL_DIFFERENCE. If MESHBOOL_DIFFERENCE is selected, operand m2 is subtracted from operand m1. (To get the opposite result, just switch the order of m1 and m2.)

MeshOpProgress *mop=NULL

A pointer to a MeshOpProgress. See Class MeshOpProgress for details. The mop is initialized with the number of faces in mesh 1 plus the number of faces in mesh 2 plus 10. MakeBoolean aborts acceptably if mop->Progress returns FALSE, in which case the partially Booleaned MNMesh is returned. (Usually this consists of mesh 1 partially cut by mesh 2, or mesh 1 fully cut and mesh 2 partially cut, with no faces removed.) This argument may safely be left at NULL if you do not wish to be updated on the Boolean progress or have the capability to abort.

Return Value:

Returns FALSE if the operation was cancelled by the MeshOpProgress or if it was unable to match the seams of the two operands at the end, resulting in a mesh with holes. It returns TRUE if everything went well, producing a solid, hole-free mesh.

Note that it will always return FALSE if one of the operands has holes.

Sample Code:

Sample code: the following code can be used to replace the old CalcBoolOp method.

BOOL CalcNewBooleanOp(Mesh & mesh, Mesh & mesh1, Mesh & mesh2, int op, MeshOpProgress *prog=NULL, Matrix3 *tm1=NULL, Matrix3 *tm2=NULL, int whichinv=0) {

 MNMesh m1(mesh1);

 MNMesh m2(mesh2);

 if(tm1) m1.Transform(*tm1);

 if(tm2) m2.Transform(*tm2);

 m1.PrepForBoolean();

 m2.PrepForBoolean();

 MNMesh mOut;

 mOut.MakeBoolean(m1, m2, op, prog);

 if(whichinv==0) mOut.Transform(Inverse(*tm1));

 if(whichinv==1) mOut.Transform(Inverse(*tm2));

mOut.OutToTri(mesh);

 return TRUE;

}

Prototype:

void ConnectLoops (Tab<int> & loop1, Tab<int> & loop2, int segs, float tension, DWORD smGroup, MtlID mat, bool sm_ends);

Remarks:

This method is available in release 4.0 and later only.

Connects two border loops by filling in new geometry between them, as is done in the Connect compound object.

Parameters:

Tab<int> & loop1

Tab<int> & loop2

These parameters, which are interchangeable, are lists of edges that represent border loops in the MNMesh. It is assumed that the MNMesh is filled in, that each of the edges in the loops is in fact one-sided (e[loop1[i]].f2 == -1), and that the edges go in counterclockwise order when looking from outside the mesh (so e[loop1[i]].v1 == e[loop1[i+1]].v2). (These are the sort of border loops you find in an MNMeshBorder class.)

int segs

The number of segments in the bridge.

float tension

The tension of the bridge - this controls how much the surface tangents at each end of the bridge affect the bridge's shape.

DWORD smGroup

These smoothing group(s) should be applied to the entire bridge. (Use 0 for a faceted bridge.)

MtlID mat

This is the material used for the bridge faces.

bool sm_ends

If TRUE, additional smoothing groups are applied to the end faces of the bridge to ensure that the bridge smoothes with the existing faces around each border loop.

Prototype:

void Connect (MNMeshBorder & borderList, int segs, float tension, bool sm_bridge, bool sm_ends, Tab<int> *vsep=NULL);

Remarks:

This method is available in release 4.0 and later only.

Connect automatically figures out which loops in the given MNMeshBorder would make good candidates for connecting, and calls ConnectLoop on them all to connect them. Good candidates are pairs of loops that face each other. Centers and normals of each of the "holes" are compared to find the best matches.

Parameters:

MNMeshBorder & borderList

The boundary information for the MNMesh mesh.

int segs

The number of segments in each bridge.

float tension

The tension of each bridge - this controls how much the surface tangents at each end of the bridge affect the bridge's shape.

bool sm_bridge

If TRUE, each bridge should be smoothed with some unused smoothing group.

bool sm_ends

If TRUE, additional smoothing groups are applied to the end faces of each bridge to ensure that the bridge smoothes with the existing faces around each border loop.

Tab<int> *vsep=NULL

If not NULL, this points to a "separation list" of vertices. Frequently the user wishes to connect two distinct object (as with the Connect compound object). In these cases, the vertices of the different connected components are often grouped in distinct sets: vertices 0 through 26 come from the first component, 27 through 118 from the second, etc. Generally the user would not want a component to connect to itself, but rather only to other components. So if non-NULL, this is assumed to point to a list describing the vertex ranges for each component - (0, 27, 119, etc). The list should have size (number of components+1), and the last element should be MNMesh::numv. Given such an input, the Connect algorithm will only connect loops to loops in other components.

Prototype:

void InvalidateGeomCache();

Remarks:

This method is available in release 3.0 and later only.

Invalidates information, like bounding box and face normals, that’s dependent on Geometry. Call after changing the geometry.

Prototype:

void InvalidateTopoCache();

Remarks:

This method is available in release 3.0 and later only.

Invalidates information, like the edge list and the render verts, that’s dependent on Topology. Clears the MN_MESH_FILLED_IN and related flags in MN_MESH_CACHE_FLAGS.

Prototype:

void allocRVerts();

Remarks:

This method is available in release 3.0 and later only.

Allocates the "render vertices" used to optimize display routines. Called by the system as needed.

Prototype:

void updateRVerts(GraphicsWindow *gw);

Remarks:

This method is available in release 3.0 and later only.

Fills in the render vertices with display coordinates based on the specified view.

Prototype:

void freeRVerts();

Remarks:

This method is available in release 3.0 and later only.

Frees the "render vertices" used to optimize display routines.

Debugging Methods

Please see the MNMesh Notes on Debugging for more information.

Prototype:

void MNDebugPrint(bool triprint=FALSE);

Remarks:

This method is available in release 2.5 and later only.

Uses DebugPrint to print out the entire MNMesh to the Debug Results window in DevStudio. This can be useful for tracking down bugs. Be careful not to leave MNDebugPrint calls in your final build; they will slow down your effect to no purpose.

Parameters:

bool triprint=FALSE

Controls whether or not triangulation information is printed out for each face. Usually this information isn't desired.

Prototype:

void MNDebugPrintVertexNeighborhood(int vv, bool triprint=FALSE);

Remarks:

This method is available in release 2.5 and later only.

Uses DebugPrint to print out information about all the edges, faces, and vertices in the immediate vicinity of vertex vv.

Parameters:

int vv

The vertex whose information is output.

bool triprint=FALSE

Controls whether or not triangulation information is printed out for each face. Usually this information isn't desired.

Prototype:

bool CheckAllData();

Remarks:

This method is available in release 2.5 and later only.

Thoroughly checks a MNMesh to make sure that no components refer to dead components; that when one component refers to another, the other refers back to the first; and that orientation is correctly matched between faces and edges. If everything checks out, TRUE is returned. If any errors are detected, DebugPrint is used to send a message to the DevStudio Debug Results window and FALSE is returned. Be careful not to leave CheckAllData calls in your final build; they will slow down your effect to no purpose.

Here is the sort of debug output you can expect. CheckAllData always outputs one of the following messages:

Checking all data in filled-in MNMesh: (if the mesh has the MN_MESH_FILLED_IN flag set)

Checking all data in MNMesh: (if the mesh does not)

 

These errors will be detected for any mesh:

Face %d has an out-of-range vertex: %d

Face %d has an out-of-range tvert: %d

Face %d has an out-of-range cvert: %d

Face %d refs dead edge %d.

Face %d has bad triangulation index: %d

 

These errors will be detected only for filled-in meshes:

Face %d has an out-of-range edge: %d

Face %d uses dead edge %d.

Face %d refs edge %d, but edge doesn't ref face.

Face %d refs edge %d from vert %d to vert %d, but edge doesn't go there.

Orientation mismatch between face %d and edge %d.

Face %d refs vertex %d, but vertex doesn't ref face.

Edge %d refs dead vertex %d.

Edge %d refs vertex %d, but vertex doesn't ref edge.

Edge %d has no face-1

Edge %d refs dead face %d.

Edge %d refs face %d, but face doesn't ref edge.

Vertex %d refs dead edge %d.

Vertex %d refs edge %d, but edge doesn't ref vertex.

Vertex %d references more faces than edges.

Vertex %d refs dead face %d.

Vertex %d refs face %d, but face doesn't ref vertex.

Operators

Prototype:

MNMesh & operator=(const MNMesh & from);

Remarks:

Assignment operator. Allocates space & copies over all data from "from".

Prototype:

MNMesh & operator+=(const MNMesh & from);

Remarks:

Union operator. Adds all data from "from" to this MNMesh. Flags MN_MESH_NONTRI and MN_MESH_RATSNEST are or’d together, while flags MN_MESH_FILLED_IN, MN_MESH_NO_BAD_VERTS, and MN_MESH_VERTS_ORDERED are and’d together. (Uniting a rat’s nest with a non-rat’s nest makes a rat’s nest, but uniting a mesh with mapping coordinates and one without makes one without.)

 

Prototype:

void ClearSpecifiedNormals ();

Remarks:

This method is available in release 5 and later only.

Clears out the specified normal interface, if present. Removes it

completely, so it won't flow up the stack, etc.

 

Prototype:

void SpecifyNormals ();

Remarks:

This method is available in release 5 and later only.

Creates the user-specified normal interface in this mesh. Initializes

the MNNormalSpec's "Parent" to this mesh, but does not allocate normal faces

or otherwise prepare the normals. Note that this interface will flow

up the pipeline, in the PART_GEOM and PART_TOPO channels.

 

Prototype:

MNNormalSpec *GetSpecifiedNormals();

Remarks:

This method is available in release 5 and later only.

Returns a pointer to the user-specified normal interface, if present.

 

Return Value:

A pointer to this mesh's MNNormalSpec interface, or NULL if the interface

has not been created in this mesh.

 

Prototype:

MNNormalSpec *GetSpecifiedNormalsForDisplay();

Remarks:

This method is available in release 5 and later only.

 

Returns a non-NULL MNNormalSpec interface pointer only if the interface

is present, and is prepared for use in display - otherwise, it returns

NULL, and we fall back on the smoothing groups.

 

A MNNormalSpec is considered "prepared for display" only if the

MNNORMAL_NORMALS_BUILT and MNNORMAL_NORMALS_COMPUTED flags are set.

(See the MNNormalSpec methods BuildNormals and ComputeNormals.)

 

Prototype:

void CopyBasics (const MNMesh & from, bool copyEdges = false);

Remarks:

This method is available in release 4.5 and later only.

Copies bare geometry only - no per-vertex data, maps, or normals.

Useful for keeping low-memory local caches of a mesh where map,

vertex data, edge data, normals, and other interfaces are not required.

Parameters:

const MNMesh & from

The mesh to copy into this mesh.

bool copyEdges = false

Indicates if the winged-edge array, as well as vertex and face

references to edges, should be copied. If false, the

MN_MESH_FILLED_IN flag is cleared in this mesh.