Class MeshDelta

3DS Max Plug-In SDK

Class MeshDelta

See Also: Class Mesh, Class FaceChange, Class FaceRemap, Class FaceSmooth, Class VertMove, Class UVVertSet, Class MapDelta, Class VDataDelta, Class AdjEdgeList, Class AdjFaceList, Class MeshChamferData, Template Class Tab, Class BitArray.

class MeshDelta : public BaseInterfaceServer

Description:

This class is available in release 3.0 and later only.

This class represents the notion of a mesh edit.

This is an SDK class that represent some kind of change to a mesh. This "delta" can include topological, geometric, map, and/or selection changes. Most standard mesh "edits" available in the Editable Mesh or Edit Mesh interface are available through the MeshDelta SDK, giving developers a powerful way to manipulate meshes while not having to "sweat the details" of maintaining maps to match the mesh changes, updating edge selections, etc.

The MeshDelta members and methods make use of a number of mesh-related classes, including Class FaceChange, Class FaceRemap, Class FaceSmooth, Class VertMove, Class UVVertSet, Class MapDelta, Class VDataDelta, Class AdjEdgeList, Class AdjFaceList, Class MeshChamferData.

While we often talk about the characteristics of the "input mesh" that a MeshDelta is based on, all MeshDeltas should be able to cope with any mesh.

Note: You must #include "MESHDLIB.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

Mesh Interaction

Composition and operators

Characteristics

Lookup Table Methods

Basic Operations

Advanced additive operations

Advanced operations

I/O, Debugging

Data Members:

public:

DWORD vnum

The expected number of vertices in the input mesh.

DWORD fnum;

The expected number of faces in the input mesh.

Tab<VertMove> vMove;

This data member stores movements of input vertices. Each VertMove consists of a vertex ID indicating which vertex should be moved and a Point3 offset in object space. VertMoves are stored in vertex ID order, and there is never more than one VertMove per original vertex.

Tab<VertMove> vClone;

If the vClone[i] record has a vid of UNDEFINED, it's considered a "create", and the coordinates of vClone[i].p are considered to be in object space. If vClone[i].vid is not undefined, it's the index of a vertex "original" in the input mesh, and vClone[i].p is treated as an offset from that vertex. If the vertex is not present in the input mesh, i.e. vClone[i].vid >= mesh::numVerts, the clone will not be created in the output. All creates and clones are stored in the order created..

BitArray vDelete;

This data member stores deletions of vertices in the input mesh. vDelete’s size is vnum.

Tab<FaceCreate> fCreate;

This data member stores faces newly created as part of the MeshDelta. These are stored in the order created.

Tab<FaceRemap> fRemap;

This data member stores changes in which vertices are used by existing faces. See class FaceRemap for more information. These are stored in original face order, and there is never more than one per original face.

Tab<FaceChange> fChange;

This data member stores changes in input face characteristics, such as material ID, edge visibility, and face hiding. See class FaceChange for more information. These are stored in original face order, and there is never more than one per original face.

Tab<FaceSmooth> fSmooth;

This data member stores changes in input face smoothing groups. See class FaceSmooth for more information. These are stored in original face order, and there is never more than one per original face.

BitArray fDelete;

This data member stores deletions of faces in the input mesh. The size of this BitArray is fnum.

BitArray vsel;

This data member stores the vertex selection of the output mesh.

BitArray esel;

This data member stores the edge selection of the output mesh. As with class Mesh’s edgeSel data member, this information is indexed by side of face: esel[ff*3+k] is the edge selection for face ff, side k.

BitArray fsel;

This data member stores the face selection of the output mesh.

BitArray vhide;

This data member stores the vertex hide information of the output mesh.

MapDelta *map;

Points to an array of MapDeltas which maintain any relevant changes to the various map channels. The size of this array is always equal to mapSupport.GetSize().

BitArray mapSupport;

Indicates which maps are supported by this MeshDelta.

VDataDelta *vd;

Points to an array of VDataDeltas which maintain any relevant changes to the various vertex data channels. The size of this array is always equal to vdSupport.GetSize().

BitArray vdSupport;

Indicates which vertex data channels are supported by this MeshDelta.

Methods:

public:

Initialization & Cleanup

Prototype:

MeshDelta();

Remarks:

Constructor. Initializes the MeshDelta with NULL pointers and 0’s for input mesh size.

Prototype:

MeshDelta(const Mesh &m);

Remarks:

Constructor. Initializes the MeshDelta to be based on the mesh given. MapDeltas and VDataDeltas are allocated as appropriate, and vnum and fnum are set.

Prototype:

~MeshDelta();

Remarks:

Destructor. Frees all allocated memory, including the MapDeltas.

Prototype:

void InitToMesh(const Mesh &m);

Remarks:

Initializes the MeshDelta to the mesh given, setting map and vdata support as appropriate. Does NOT clear out existing changes.

Parameters:

const Mesh &m

The mesh to init from.

Prototype:

void ClearAllOps();

Remarks:

Clears out all existing mesh changes. Zeroes all the vCreate, vMove, etc arrays, as well as those in the active MapDeltas. Does not clear memory.

Prototype:

void SetInFNum(int nface);

Remarks:

Sets the number of faces in the input mesh. NOTE that if nface is less than the current fnum, the data relating to the extra faces will be lost. (That is, if one of your face remaps is applied to face 32, and you SetInFNum to 30, that face remap will be lost, and will not be recovered if you later SetInFNum to 35.) It is NOT necessary to call this method before applying this MeshDelta to a smaller than expected Mesh.

Parameters:

int nface

The number of faces expected from the input mesh.

Prototype:

void SetInVNum(int nv);

Remarks:

Sets the number of vertices in the input mesh. NOTE that if nv is less than the current vnum, the data relating to the extra vertices will be lost. (That is, if one of your vertex moves is applied to vertex 32, and you SetInVNum to 30, that vertex move will be lost, and will not be recovered if you later SetInVNum to 35.) It is NOT necessary to call this method before applying this MeshDelta to a smaller than expected Mesh.

Parameters:

int nv

The number of vertices expected from the input mesh.

Prototype:

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

Remarks:

Sets the number of map channels used by the MeshDelta – allocates the "map" array.

Parameters:

int num

The number of maps to allocate.

bool keep=TRUE

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

Prototype:

int GetMapNum();

Remarks:

Gets the number of map channels in the MeshDelta – equivalent to mapSupport.GetSize().

Prototype:

MapDelta & Map(int mp);

Remarks:

Data accessor - gets the MapDelta for the specified map channel. Since in 4.0 we now have "hidden map channels" which are accessed by negative indices (-1 for MAP_SHADING, for example), data accessor methods like this one should be used instead of the actual arrays. (Hidden map channels are stored in a new private data member, not as part of the public map array.)

Prototype:

bool getMapSupport (int mp);

Remarks:

Indicates whether the specified map channel is supported by this MeshDelta. Since in 4.0 we now have "hidden map channels" which are accessed by negative indices (-1 for MAP_SHADING, for example), data accessor methods like this one should be used instead of the actual data members. (Hidden map channel support information is stored in a new private data member, not as part of the public mapSupport BitArray.)

Prototype:

void setMapSupport (int mp, bool val=true);

Remarks:

Sets map support in this MeshDelta for the specified map channel. Since in 4.0 we now have "hidden map channels" which are accessed by negative indices (-1 for MAP_SHADING, for example), data accessor methods like this one should be used instead of the actual data members. (Hidden map channel support information is stored in a new private data member, not as part of the public mapSupport BitArray.)

Prototype:

bool hasMapSupport ();

Remarks:

Indicates whether any map channel is supported by this MeshDelta.

Prototype:

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

Remarks:

Sets the number of vertex data channels used by the MeshDelta – allocates the "vd" array.

Parameters:

int num

The number of vertex data channels to allocate.

bool keep=TRUE

If TRUE any previous vertex data channels are kept; otherwise they are discarded.

Prototype:

int GetVDataNum();

Remarks:

Gets the number of vertex data channels in the MeshDelta – equivalent to vdSupport.GetSize().

Prototype:

void AddVertexColors();

Remarks:

Activates the vertex color MapDelta, adding whatever new map verts or faces are needed to match the current MeshDelta. After calling this method, applying this MeshDelta to a mesh without vertex colors will result in a vertex color map with all white vertices and a topology identical to the mesh.

Prototype:

void AddMap(int mapID);

Remarks:

Activates the specified MapDelta, adding whatever new map verts or faces are needed to match the current MeshDelta. If mapID is 0, the standard vertex colors (white) will be applied (see AddVertexColors). Otherwise, after calling this method, applying this MeshDelta to a mesh without the specified map active will result in a map with the same topology as the mesh and UVVerts that are copies of the mesh vertices.

Parameters:

int mapID

The map channel to add. 0 represents vertex colors, 1 is the original map channel (referred to in class Mesh by tVerts and tvFaces), and 2-99 are the new map channels (stored in meshes in the MeshMap class).

Prototype:

void AddVertexData(int vdChan, Mesh *m=NULL);

Remarks:

Activates the specified vertex data channel, creating a default set of vertex data to match the output of the current MeshDelta. ("Default" values of vertex data depend on the channel, and are given by VDataDefault (vdChan).)

Parameters:

int vdChan

The vertex data channel

Mesh *m=NULL

A pointer to the Mesh object.

Mesh Interaction

Prototype:

void FillInFaces(Mesh & m);

Remarks:

To make things easy for developers, it’s possible to create or remap mapping faces to use UNDEFINED mapping verts. This routine, which is called by Apply below, fills in those UNDEFINED mapping values with the mapping vertices used by neighboring faces, or, if necessary, by new mapping vertices. (These new mapping vertices are always (.5,.5,0) for regular map channels or (1,1,1) for the vertex color channel.)

This process does not produce very good maps, but it allows a sort of minimal mapping support that prevents maps from being lost before the user can make their manual corrections.

Prototype:

void Apply(Mesh & m);

Remarks:

Changes the given mesh by this MeshDelta, in the following manner:

First, any maps that are supported by the MeshDelta but not by the mesh are assigned to the mesh in their default form. (Vertex color channels are white, and other maps are copies of the mesh vertices. All have the same topology as the mesh.)

Next, any UNDEFINED mapping verts in the MeshDelta are filled in by FillInFaces.

Then the new vertices are added, creates first, followed by clones. The original vertices are then moved.

The faces are then modified, by applying all the FaceRemaps, FaceChanges, and FaceSmooths to the appropriate faces. New faces (in fCreate) are appended to the end of the face list.

Map changes are applied to all active maps, and map channels not supported by this MeshDelta are removed.

After all that is done, the vertices and faces marked in the vDelete and fDelete arrays are deleted.

Finally, the vertex data, vertex hide, and selections kept in the MeshDelta are applied to the result.

Prototype:

DWORD PartsChanged();

Remarks:

Indicates what data channels of a mesh would be changed by this MeshDelta. For instance, a MeshDelta with vertex moves but no other changes would return PART_GEOM|PART_SELECT. PART_GEOM represents the moves, and PART_SELECT represents the fact that MeshDeltas always overwrite selection info. Most of the changes in a MeshDelta will alter PART_TOPO. PART_VERTCOLOR and PART_TEXMAP may also be returned.

This is especially useful for knowing what parts of a mesh to back up in a restore object for an undo/redo. (See the SDK implementation of Editable Mesh for an example of this.) Also, it can be used for invalidating temporary data, as in both Edit and Editable Mesh.

Composition & Operators

MeshDeltas can be multiplied together like Transforms before being applied to a mesh. This is especially useful in Edit Mesh, where a single MeshDelta is used to store the current "state" of the Edit Mesh, and extra MeshDeltas are created for each operation and added on to the main MeshDelta.

An example of this is as follows: given a Mesh m that we want to divide a face on, then we want to break the vertex created in the face divide. These operations are adequately handled by the DivideFace and BreakVerts methods independently, but to combine the two into one operation, we must compose two MeshDeltas.

MeshDelta DivideThenBreak (const Mesh & m, int ff) {

MeshDelta md1, md2;

Mesh mcopy = m;

md1.DivideFace (mcopy, ff);

int nvid = md1.vnum; // since DivideFace creates exactly one vertex, this must be its index in the result.

md1.Apply (mcopy);

md2.InitToMesh (mcopy); // second MeshDelta must be based on first MeshDelta result.

BitArray vset;

vset.SetSize (mcopy.numVerts);

vset.Set (nvid);

md2.BreakVerts (mcopy, vset); // breaks the new vertex into a separate vert for each face.

md1.Compose (md2); // Adds the second MeshDelta into the first.

return md1;

}

If all we wanted was to perform these operations on the mesh given, we could have done so without making the composition. The point here is to be able to construct complex MeshDeltas representing a series of user operations while remaining flexible enough to respond to changes in the actual mesh given as input. This is a central feature of the Edit Mesh modifier, completely rewritten for 3.0, found in MAXSDK\SAMPLES\MODIFIERS.

Prototype:

DWORD Compose(MeshDelta & td);

Remarks:

Appends the given MeshDelta to the current one.

Parameters:

MeshDelta & td

The MeshDelta to append. This MeshDelta may be modified to make it suitable, ie the vnum and fnum values will be set to the expected output of the current MeshDelta if they don’t already match. (This may result in the loss of some data – see "SetInVNum" and "SetInFNum" for more information.)

Prototype:

MeshDelta & operator*=(MeshDelta & td);

Remarks:

Appends the given MeshDelta to the current one.

Parameters:

MeshDelta & td

The MeshDelta to append. This MeshDelta may be modified to make it suitable, ie the vnum and fnum values will be set to the expected output of the current MeshDelta if they don’t already match. (This may result in the loss of some data – see "SetInVNum" and "SetInFNum" for more information.)

Prototype:

MeshDelta & operator=(MeshDelta & td);

Remarks:

Assignment operator – makes this MeshDelta just like the one given.

Prototype:

DWORD ChangeFlags(Tab<DWORD> *mChannels=NULL);

Remarks:

Indicates what parts of a MeshDelta could be changed if this MeshDelta were appended to it. This is useful when backing up MeshDelta for Restore Objects. For instance, if you had a MeshDelta with lots of face smoothing changes, and you wanted to compose it with one that only moved vertices, there would be no reason to back up the smoothing changes for an undo.

Parameters:

Tab<DWORD> *mChannels=NULL

If non-NULL, this points to a table that should be filled with change flags for the various map channels. The table is set to the number of map channels, and each DWORD in it is filled in by calling MapDelta::ChangeFlags on the appropriate map channel (or left at zero if the map channel is inactive.)

Return Value:

Returns some combination of the following flags, corresponding to the data members that would be changed:

MDELTA_VMOVE

MDELTA_VCREATE

MDELTA_VCLONE

MDELTA_VDELETE

MDELTA_VDATA

MDELTA_FREMAP

MDELTA_FCHANGE

MDELTA_FCREATE

MDELTA_FDELETE

MDELTA_FDATA

MDELTA_NUMBERS

MDELTA_FSMOOTH

Note that in 4.0 and thereafter, the MDELTA_VCREATE and MDELTA_VCLONE flags are identical and represent the same information. (This was not true in 3.0 or 3.1.)

Prototype:

void CopyMDChannels(MeshDelta & from, DWORD channels, Tab<DWORD> *mChannels=NULL);

Remarks:

Copies the specified parts of the MeshDelta. (Useful in combination with ChangeFlags to create efficient Restore objects.)

Parameters:

MeshDelta & from

The MeshDelta to copy into this.

DWORD channels

Indicates the parts to copy – some combination of the following flags:

MDELTA_VMOVE

MDELTA_VCREATE

MDELTA_VCLONE

MDELTA_VDELETE

MDELTA_VDATA

MDELTA_FREMAP

MDELTA_FCHANGE

MDELTA_FCREATE

MDELTA_FDELETE

MDELTA_FDATA

MDELTA_NUMBERS

MDELTA_FSMOOTH

Note that in 4.0 and thereafter, the MDELTA_VCREATE and MDELTA_VCLONE flags are identical and represent the same information. (This was not true in 3.0 or 3.1.)

Tab<DWORD> *mChannels=NULL

If non-NULL, this points to a table that contains channels to copy in the various map channels. The table should be of the size of the number of map channels. For each active map channel in from, the corresponding DWORD in this table is passed in MapDelta::CopyMDChannels to copy the relevant parts of the map.

Characteristics

The following methods give useful information about the MeshDelta.

Prototype:

DWORD NumVMove(DWORD inVNum);

Remarks:

Returns the number of vertex moves that would be applied to a mesh with the specified number of vertices. If that number equals this MeshDelta’s vnum, this is simply vMove.Count().

Parameters:

DWORD inVNum

The number of vertices in the input mesh we’re inquiring about.

Prototype:

DWORD NumVClone(DWORD inVNum);

Remarks:

Returns the number of vertex clones & creates that would be applied to a mesh with the specified number of vertices. If that number equals this MeshDelta’s vnum, this is simply vClone.Count(). If, however, inVNum is lower than the expected vnum, some of the clones might be eliminated, reducing this number.

Parameters:

DWORD inVNum

The number of vertices in the input mesh we’re inquiring about.

Prototype:

DWORD NumVDelete(DWORD inVNum);

Remarks:

Returns the number of vertex deletes that would be applied to a mesh with the specified number of vertices. If that number equals this MeshDelta’s vnum, this is simply vDelete.NumberSet ().

Parameters:

DWORD inVNum

The number of vertices in the input mesh we’re inquiring about.

Prototype:

DWORD NumFDelete(DWORD inFNum);

Remarks:

Returns the number of face deletes that would be applied to a mesh with the specified number of faces. If inFNum equals this MeshDelta’s fnum, this is simply fDelete.NumberSet ().

Parameters:

DWORD inFNum

The number of faces in the input mesh we’re inquiring about.

Prototype:

int NumFCreate ();

Remarks:

Returns the number of face creates in this MeshDelta.

Prototype:

DWORD outVNum();

Remarks:

Returns the number of vertices in the output mesh, assuming that the input mesh is of the expected (vnum) size.

Prototype:

DWORD outVNum(int inVNum);

Remarks:

Returns the number of vertices in the output mesh, assuming that the input mesh has the specified number of vertices.

Parameters:

DWORD inVNum

The number of vertices expected in the input mesh.

Prototype:

DWORD outFNum();

Remarks:

Returns the number of faces in the output mesh, assuming that the input mesh is of the expected (fnum) size.

Prototype:

DWORD outFNum(int inFNum);

Remarks:

Returns the number of faces in the output mesh, assuming that the input mesh has the specified number of faces.

Parameters:

DWORD inFNum

The number of faces expected in the input mesh.

Prototype:

Point3 outVert(Mesh & m, DWORD v);

Remarks:

Returns the expected location in the output mesh of the specified vertex.

Parameters:

Mesh & m

The input mesh.

DWORD v

The vertex you want the output location of. This index is input-based – the vertex index in m, not in the output mesh.

Prototype:

Face outFace(Mesh & m, DWORD f);

Remarks:

Returns the specified face as it would appear in the MeshDelta output. Face Changes, Smooths, and Remaps are applied.

Parameters:

Mesh & m

The input mesh.

DWORD f

The index of the face you want the output version of. This index is input-based – the face index in m, not in the output mesh.

Prototype:

DWORD RemapID(DWORD ff);

Remarks:

Obtains the index of the fRemap entry that relates to this face.

Parameters:

DWORD ff

The input-based face index.

Return Value:

If there is such an entry, the index is returned, so fRemap[RemapID(ff)].fid == ff. If there is no remap record for this face, the method returns UNDEFINED.

Prototype:

DWORD IsRemapped(DWORD ff, DWORD vid);

Remarks:

Tells whether the specified corner of the specified face has been remapped in this MeshDelta.

Parameters:

DWORD ff

The input-based face index.

DWORD vid

The corner of the face – 0, 1, or 2.

Return Value:

If this corner has been remapped, it returns the vertex it’s been remapped to. Otherwise, it returns UNDEFINED.

Prototype:

DWORD MoveID(DWORD i);

Remarks:

Obtains the index of the vMove entry that relates to this vertex.

Parameters:

DWORD i

The input-based vertex index.

Return Value:

The index in the vMove array of the vertex move corresponding to this vertex, or UNDEFINED if this vertex has no move associated with it.

Prototype:

bool IsVCreate(DWORD i);

Remarks:

No longer used.

This method was used in 3.0 and 3.1 to indicate whether the specified vertex was created as a create, not a clone in this MeshDelta. In 4.0, we integrated the clone and create records together, and this method is now set to always return FALSE.

Parameters:

DWORD i

The output-based vertex index.

Prototype:

bool IsVClone(DWORD i);

Remarks:

Indicates whether or not the specified vertex is created in this MeshDelta.

Parameters:

DWORD i

The output-based vertex index.

Prototype:

DWORD VCloneOf(DWORD i);

Remarks:

Tells you what input vertex the specified output vertex is a clone of.

Parameters:

DWORD i

The output-based vertex index.

Return Value:

The index in the input mesh of the original vertex this one’s a clone of. If this vertex is not a clone, UNDEFINED is returned.

Prototype:

bool IsFCreate(DWORD i);

Remarks:

Indicated whether the specified face was created in this MeshDelta.

Parameters:

DWORD i

The face index in the output mesh.

Lookup Table Methods

Prototype:

void UpdateLUTs(int extraV=0, int extraF=0);

Remarks:

Updates the MeshDelta’s internal lookup tables, which make use of all delete and create records to set up a correspondence between output and input vertices and faces.

Parameters:

int extraV

If nonzero, this indicates the number of extra spaces that should be added to the lookup table. This is useful for example if you want the lookup table to still be valid after the next <extraV> vertex creates or clones.

int extraF

If nonzero, this indicates the number of extra spaces that should be added to the lookup table. This is useful for example if you want the lookup table to still be valid after the next <extraF> face creates.

Prototype:

void ClearLUTs();

Remarks:

Invalidates and clears the lookup tables. This usually only needs to be called internally.

Prototype:

DWORD VLut(DWORD i);

Remarks:

Finds the input mesh index of the vertex with the specified output mesh index.

Note that these indices are the same if there are no vertex deletes.

Parameters:

DWORD i

The output mesh index.

Return Value:

The input mesh index of the same vertex. If the vertex specified is actually created by this MeshDelta, the return value would be vnum+i for vClone[i].

Prototype:

DWORD FLut(DWORD i);

Remarks:

Finds the input mesh index of the face with the specified output mesh index.

Note that these indices are the same if there are no face deletes.

Parameters:

DWORD i

The output mesh index.

Return Value:

The input mesh index of the same face. If the face specified is actually created by this MeshDelta, the return value would be fnum+i for fCreate[i].

Prototype:

DWORD PostVIndex(DWORD i);

Remarks:

Returns the index in the output mesh of the specified input vertex.

Note that these indices are the same if there are no vertex deletes.

Parameters:

DWORD i

The index of the vertex in the input mesh.

Return Value:

The output mesh index of the same vertex. If the vertex was deleted in this MeshDelta, UNDEFINED is returned.

Prototype:

DWORD PostFIndex(DWORD i);

Remarks:

Returns the index in the output mesh of the specified input face.

Note that these indices are the same if there are no face deletes.

Parameters:

DWORD i

The index of the face in the input mesh.

Return Value:

The output mesh index of the same face. If the face was deleted in this MeshDelta, UNDEFINED is returned.

Basic Operations

These operations are the "building blocks" of MeshDeltas. All of them may be safely performed on MeshDeltas that are already quite complex. Those that accept DWORD indices require output mesh indices, as all operations are appended to the end of the existing delta.

Prototype:

void Move(int i, const Point3 & p);

Remarks:

Moves a single vertex. (Note that if the same vertex is moved twice, the new move is simply added to the old one – there is never more than one VertMove in the vMove array for a single input vertex.)

Parameters:

int i

The index of the vertex in the output mesh.

const Point3 & p

The vector to move the vertex by.

Prototype:

void Move(BitArray & sel, const Point3 & p);

Remarks:

Moves the specified vertices. (Note that if the same vertex is moved twice, the new move is simply added to the old one – there is never more than one VertMove in the vMove array for a single input vertex.)

Parameters:

BitArray & sel

Indicates which vertices should be moved. Vertices are indexed based on the output mesh.

const Point3 & p

The vector to move the vertices by.

Prototype:

void Move(VertMove *vm, int num);

Remarks:

Adds in the specified vertex moves. (Note that if the same vertex is moved twice, the new move is simply added to the old one – there is never more than one VertMove in the vMove array for a single input vertex.)

Parameters:

VertMove *vm

A pointer to an array of VertMoves to apply to this MeshDelta. Vertices are indexed based on the output mesh.

int num

The size of the VertMove array.

Prototype:

DWORD VCreate(Point3 *p, int num=1, BitArray *sel=NULL, BitArray *hide=NULL);

Remarks:

Creates new vertices.

Parameters:

Point3 *p

A pointer to an array of points representing the new vertices.

int num

The size of the point array.

BitArray *sel=NULL

If non-NULL, this points to a BitArray of size num that indicates which of these new vertices should be selected. (If NULL, none of the new vertices are selected.)

BitArray *hide=NULL

If non-NULL, this points to a BitArray of size num that indicates which of these new vertices should be hidden. (If NULL, none of the new vertices are hidden.)

Return Value:

The index (in the output mesh) of the first of these new vertices.

Prototype:

DWORD VClone(DWORD *v, int num=1);

Remarks:

Clones some vertices.

Parameters:

DWORD *v

A pointer to an array of indices of verts that should be cloned.

int num

The size of the array.

Return Value:

The index (in the output mesh) of the first of the clones.

Prototype:

DWORD VClone(DWORD *v, Point3 *off, int num=1);

Remarks:

Clones some vertices.

Parameters:

DWORD *v

A pointer to an array of ids of vertices that should be cloned.

Point3 *off

A pointer to an array of offsets for the clones.

int num

The size of the arrays.

Return Value:

The index (in the output mesh) of the first of the clones.

Prototype:

DWORD VClone(VertMove *vm, int num=1);

Remarks:

Clones some vertices.

Parameters:

VertMove *vm

A pointer to an array of VertMoves indicating which vertices should be cloned and what offsets the clones should use.

int num

The size of the vm array.

Return Value:

The index (in the output mesh) of the first of the clones.

Prototype:

DWORD VClone(DWORD v);

Remarks:

Clones a single vertex.

Parameters:

DWORD v

The index (in the output mesh) of the vertex you wish to clone.

Return Value:

The index (in the output mesh) of the clone.

Prototype:

DWORD VClone(DWORD v, Point3 off);

Remarks:

Clones and offsets a single vertex.

Parameters:

DWORD v

The index (in the output mesh) of the vertex you wish to clone.

Point3 off

The desired offset from the original vertex.

Return Value:

The index (in the output mesh) of the clone.

Prototype:

void VDelete(DWORD *v, int num=1);

Remarks:

Deletes the specified vertices.

Parameters:

DWORD *v

A pointer to an array of (output-based) ids of the vertices that should be deleted.

int num

The number of vertices to delete (the size of the v array).

Prototype:

void VDelete(BitArray & vdel);

Remarks:

Deletes the specified vertices.

Parameters:

BitArray & vdel

A BitArray, of size OutVNum, indicating which of the vertices should be deleted. Vertices in this array are indexed by output mesh order.

Prototype:

DWORD FCreate(Face *f, int num=1);

Remarks:

Creates new faces.

Note: MapDeltas must be kept up to date with all new face creations – see CreateDefaultMapFaces.

Parameters:

Face *f

A pointer to an array of faces to be added to the MeshDelta.

int num

The size of the face array.

Return Value:

The index (in the output mesh) of the first of these new faces.

Prototype:

DWORD FCreate(FaceCreate *f, int num=1);

Remarks:

Creates new faces. This is what's used to add in face creations in the all-important Compose method. It assumes that the "originals" in the array of FaceCreates are post-indexed, and uses FLut and extracts originals for creates-of-creates as appropriate.

Note: MapDeltas must be kept up to date with all new face creations – see CreateDefaultMapFaces.

Parameters:

FaceCreate *f

A pointer to an array of face create records to be added to the MeshDelta.

int num

The size of the face create array.

Return Value:

The index (in the output mesh) of the first of these new faces.

Prototype:

DWORD FCreateQuad(DWORD *v, DWORD smG=0, MtlID matID=0, int orig=UNDEFINED);

Remarks:

Creates 2 new faces, forming a quad.

Note: MapDeltas must be kept up to date with all new face creations – see CreateDefaultMapFaces.

Parameters:

DWORD *v

A pointer to an array of 4 vertices to be used as corners of the quad.

DWORD smG=0

The smoothing group desired for the new faces.

MtlID matID=0

The material ID desired for the new faces.

int orig=UNDEFINED

This optional parameter sets the map faces to undefined.

Return Value:

The index (in the output mesh) of the first of these 2 new faces.

Prototype:

DWORD FClone(Face & f, DWORD ff, DWORD remapFlags=0, DWORD *v=NULL);

Remarks:

Creates a new face by copying an existing face. The result is put into the fCreate array and treated thereafter like a face create – this is different from vertex clones, which are maintained separately from vertex creates.

Note: MapDeltas must be kept up to date with all new face creations – see CreateDefaultMapFaces.

Parameters:

Face & f

The face we wish to clone. (This is typically generated by the outFace method.)

DWORD ff

The (output-based) index of the face we’re cloning. (This is used to copy face and edge selection.)

DWORD remapFlags=0

DWORD *v=NULL

If we wish to remap any of the corners of this face while cloning, the appropriate flags and vertices should be passed in these last two arguments. v should point to an array of 3 vertex (output) indices, although the ones not marked as used by the remapFlags need not be set to anything in particular. See class FaceRemap for more information about face remapping.

Return Value:

The index (in the output mesh) of the new face.

Prototype:

DWORD CreateDefaultMapFaces(int num=1);

Remarks:

MapDeltas must always keep their faces in sync with the parent MeshDelta. If the developer creates new faces, but doesn’t want to go through the bother of figuring out exactly how the related map faces should look, this method may be used to create map faces with UNDEFINED verts. These can then be filled in automatically later. (See the MeshDelta FillInFaces method for details.)

For every face created in the MeshDelta, either CreateDefaultMapFaces should be called, or map faces should be created in every active map channel, using MapDelta::FCreate and related methods.

Parameters:

int num=1

The number of default faces we wish to create in each active map channel.

Prototype:

void FRemap(FaceRemap *f, int num=1);

Remarks:

Adds face remaps to this MeshDelta. If the face specified in each FaceRemap already has a remap record, the two are combined. If the face specified is a face created by this MeshDelta, the remap is applied directly to the fCreate entry instead of being stored in fRemap.

Parameters:

FaceRemap *f

A pointer to an array of FaceRemap that should be appended to this MeshDelta.

Note that the faces and vertices in each FaceRemap must be indexed by their positions after all of the current MeshDelta’s creates, clones, etc, but before any vertex or face deletes. Vertex index values of 0 through vnum-1 are considered to be the original mesh’s vertices; values above this are cloned or created vertices. Likewise, face index values of 0 through fnum-1 are considered to be the original mesh faces, while fnum through fnum+fCreate.Count()-1 are this MeshDelta’s face creates.

int num=1

The number of elements in the FaceRemap array.

Prototype:

void FRemap(DWORD f, DWORD flags, DWORD *v);

Remarks:

Adds a face remap to this MeshDelta. If the face specified already has a remap record, the two are combined. If the face specified is a face created by this MeshDelta, the remap is applied directly to the fCreate entry instead of being stored in fRemap.

Parameters:

DWORD f

The face to remap.

Note that this face must be indexed by its position after all of the current MeshDelta’s face creates, but before any face deletes. Face index values of 0 through fnum-1 are considered to be the original mesh faces, while fnum through fnum+fCreate.Count()-1 are this MeshDelta’s face creates.

DWORD flags

Face Remap flags – these indicate which vertices should be remapped. The possibilities are FR_V0 (1), FR_V1 (2), and FR_V2 (4). (See class FaceRemap for more information.)

DWORD *v

A pointer to the vertices to remap the face to use. Only the positions indicated in the remap flags need contain meaningful data.

Note that the vertices indicated here must be indexed by their positions after all of the current MeshDelta’s creates and clones, but before any vertex deletes – essesntially input-based indexing. Vertex index values of 0 through vnum-1 are considered to be the original mesh’s vertices; values of vnum through vnum+vCreate.Count()-1 are considered to be this MeshDelta’s newly created vertices; and values above this are cloned vertices.

Prototype:

void FChange(FaceChange *f, int num=1);

Remarks:

Appends some face changes to the current MeshDelta. Face changes can encompass changes to face material IDs, edge visibility, or face hiding. See class FaceChange for more information.

Parameters:

FaceChange *f

A pointer to an array of new face changes for this MeshDelta.

int num=1

The number of elements in the FaceChange array.

Prototype:

void FChange(DWORD f, DWORD flags, DWORD dat);

Remarks:

Changes the characteristics of one face.

Parameters:

DWORD f

The output-indexed face to change.

DWORD flags

DWORD dat

These two parameters describe the change desired. See class FaceChange for a description of these flags. flags indicates which characteristics should be set, and dat includes the on-or-off state of each flag we’re setting. So for example FChange (26, ATTRIB_EDGE_A| ATTRIB_EDGE_B, ATTRIB_EDGE_A) would set face 26 to have the first edge visible and the second invisible, without changing the existing visibility for the third edge.

Prototype:

void SetMatID(DWORD f, MtlID mt);

Remarks:

Sets the material ID for the specified face. If the face is created by this MeshDelta, the fCreate record is amended. If it’s an input face, a FaceChange record is created or amended.

Parameters:

DWORD f

The output-indexed face to change.

MtlID mt

The desired material ID.

Prototype:

void SetEdgeVis(DWORD f, DWORD ed, BOOL vis=TRUE);

Remarks:

Sets the edge visibility for the specified side of the specified face. If the face is created by this MeshDelta, the fCreate record is amended. If it’s an input face, a FaceChange record is created or amended.

Parameters:

DWORD f

The output-indexed face to change.

DWORD ed

The side of the face to change (0, 1, or 2).

BOOL vis=TRUE

The desired visibility.

Prototype:

void FSmooth(FaceSmooth *f, int num=1);

Remarks:

Adds smoothing group changes to this MeshDelta. See class FaceSmooth for more information.

Parameters:

FaceSmooth *f

A pointer to an array of smoothing change records. The face IDs in these records should be output-indexed.

int num=1

The number of elements in the FaceSmooth array.

Prototype:

void FSmooth(DWORD f, DWORD mask, DWORD val);

Remarks:

Changes the smoothing groups on the specified face.

Parameters:

DWORD f

The output-based index of the face to change.

DWORD mask

The smoothing groups to change.

DWORD val

The smoothing group values. For instance, FSmooth (32, 7, 2) would set smoothing group 2 and clear groups 1 and 3 for face 32, since mask has bits 0, 1, and 2 set but val only has bit 1 set.

Prototype:

void SetSmGroup(DWORD f, DWORD smG);

Remarks:

Sets the smoothing groups on the specified face.

Parameters:

DWORD f

The output-based index of the face to change.

DWORD smG

The smoothing groups to set. All bits not set in this parameter are cleared.

Prototype:

void FDelete(DWORD *f, int num=1);

Remarks:

Deletes the specified faces.

Parameters:

DWORD *f

A pointer to an array of output-based indices of faces we wish to delete. Note that all the elements should be based on the output before any deletions occur. So if you wanted to delete what are currently faces 3 and 5, you could pass an array with 3 and 5, you would not have to think, "Ah, 3 will be deleted, so I should use 4 instead of 5."

int num=1

The size of the array.

Prototype:

void FDelete(BitArray & fdel);

Remarks:

Deletes the specified faces.

Parameters:

BitArray & fdel

The faces to delete. The faces are indexed by their output mesh positions.

Advanced additive operations

The following are more complex operations, built out of the simple operations above. The mesh given is expected to be result of the current MeshDelta. They should all work no matter how complex the current MeshDelta is, but they have not been extensively tested on complex MeshDeltas. To see how most of these work, look at Editable Mesh or Edit Mesh, both of which have source in MAXSDK\SAMPLES.

Prototype:

void AutoSmooth(Mesh & m, BitArray sel, float angle, AdjFaceList *af=NULL, AdjEdgeList *ae=NULL);

Remarks:

Automatically generates smoothing groups for the selected faces. Existing smoothing groups are ignored. See the AutoSmooth feature in Edit Mesh for an example.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BitArray sel

The faces to AutoSmooth.

float angle

The maximum angle between faces that should be smoothed together.

AdjFaceList *af=NULL

A pointer to the adjacent face list for this mesh. If NULL, the method constructs its own AdjFaceList.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

void Bevel(Mesh & m, BitArray vset, float outline, Tab<Point3> *odir, float height, Tab<Point3> *hdir);

Remarks:

Moves the selected vertices along the directions given to produce the movement corresponding to the mouse drags of a Bevel operation in Editable Mesh. Note that this method only changes geometry.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BitArray vset

The set of vertices to move.

float outline

The amount of outlining to do in this Bevel move.

Tab<Point3> *odir

The outline direction for each vertex. This should be given by MeshTempData::OutlineDir. See the Edit Mesh source for details.

float height

The amount of extrusion to do in this Bevel move.

Tab<Point3> *hdir

The extrusion direction for each vertex. This should be given by MeshTempData::EdgeExtDir or FaceExtDir. See the Edit Mesh source for examples.

Prototype:

DWORD CreatePolygon(Mesh & m, int deg, int *v, DWORD smG=0, MtlID matID=0);

Remarks:

Create a polygon of any size. The polygon may be nonconvex, but should be (roughly) coplanar.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

int deg

The number of vertices used by this polygon (its degree).

int *v

The indices of the vertices in Mesh m that this polygon should use.

DWORD smG=0

The desired smoothing group for the new polygon.

MtlID matID=0

The desired material ID for the new polygon.

Prototype:

void DeleteVertSet(Mesh & m, BitArray sel);

Remarks:

Deletes the specified vertices, along with any faces that used them.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BitArray sel

The vertices to delete. Any face that uses any of the vertices selected here will also be deleted.

Prototype:

void DeleteEdgeSet(Mesh & m, BitArray sel);

Remarks:

Deletes all faces using the specified edges. (Doesn’t delete any verts.)

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BitArray sel

The edges to delete the faces of. Edges are indexed by face*3+side.

Prototype:

void DeleteFaceSet(Mesh & m, BitArray sel);

Remarks:

Deletes the specified faces. (Doesn’t delete any verts.)

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BitArray sel

The faces to delete.

Prototype:

void DeleteSelected(Mesh & m);

Remarks:

Deletes the current subobject selection. If m.selLevel is MESH_OBJECT, nothing is deleted. If it’s MESH_VERTEX, the faces using the selected vertices are also deleted.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

Prototype:

void DeleteIsoVerts(Mesh & m);

Remarks:

Deletes the vertices not in use by any faces.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

Prototype:

void FlipNormal(Mesh & m, DWORD face);

Remarks:

Flips the normal of the specified face (by switching the face’s v[0] and v[1]). (Related map faces are also flipped.)

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

DWORD face

The face to flip.

Prototype:

void MakeSelFacesPlanar(Mesh & m, BitArray sel);

Remarks:

Flattens the faces indicated into the same plane. The target plane is determined by the average of all the face centers and the average of all the face normals.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BitArray sel

The faces to make coplanar.

Prototype:

void MakeSelVertsPlanar(Mesh & m, BitArray sel);

Remarks:

Flattens the vertices indicated into the same plane. The target plane is determined by the average position and normal of the vertices.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BitArray sel

The vertices to make coplanar.

Prototype:

void MoveVertsToPlane(Mesh & m, BitArray sel, Point3 & N, float offset);

Remarks:

Moves the vertices indicated into the specified plane. (The target plane is defined as all points which, when DotProd’d with N, return offset.) All vertices are moved along the normal vector N.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BitArray sel

The vertices to move into the plane.

Point3 & N

The unit normal to the plane.

float offset

The offset of the plane (also its distance from the origin).

Prototype:

void RestrictMatIDs(Mesh & m, int numMats);

Remarks:

Like the old standalone method "FitMeshIDsToMaterial", this method limits the material IDs to values between 0 and numMats-1. This is useful eg in matching the number of material Ids to the number of materials used on this node.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

int numMats

The number of material ids allowed.

Prototype:

void SelectFacesByFlags(Mesh & m, BOOL onoff, DWORD flagmask, DWORD flags);

Remarks:

Sets or clears face selection depending on whether they match a pattern of flags. This is pretty much only useful for selecting or deselecting hidden faces:

 mdelta.SelectFacesByFlags(*mesh, FALSE, FACE_HIDDEN, FACE_HIDDEN); // deselects hidden faces.

Parameters:

Mesh & m

The mesh, which should match the output of the current MeshDelta, that should be affected.

BOOL onoff

Indicates whether faces should be selected or deselected if they match the flag pattern.

DWORD flagmask

Indicates whether faces should be selected or deselected if they match the flag pattern.

DWORD flags

Indicates whether faces should be selected or deselected if they match the flag pattern.

Advanced operations

The following will initialize to the mesh given: they can't be used to "add" ops to an existing MeshDelta. (To add these ops, make a new MeshDelta, call one of the following, and append it to your previous one with Compose.) To see how most of these work, look at Editable Mesh or Edit Mesh, both of which have source in MAXSDK\SAMPLES.

Prototype:

void AttachMesh(Mesh & m, Mesh & attachment, Matrix3 & relativeTransform, int matOffset);

Remarks:

Attaches another mesh to this one.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

Mesh & attachment

The mesh this MeshDelta should attach.

Matrix3 & relativeTransform

The transform taking the attachment mesh from its object space to ours.

int matOffset

The offset that should be applied to all the material IDs in the attachment.

Prototype:

void BreakVerts(Mesh & m, BitArray vset);

Remarks:

Splits the selected vertices into a separate vertex for every face that uses them.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray vset

The vertices that should be broken.

Prototype:

void ChamferEdges(Mesh & m, BitArray eset, MeshChamferData & mcd, AdjEdgeList *ae=NULL);

Remarks:

Performs the topological changes needed for an edge chamfer, and creates the information necessary to do the geometric changes.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray eset

The edges to chamfer.

MeshChamferData & mcd

A class in which the directions and limits of movement for all the vertices involved in the chamfer should be stored. See class MeshChamferData.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

void ChamferMove(Mesh & m, MeshChamferData & mcd, float amount, AdjEdgeList *ae=NULL);

Remarks:

Moves the relevant vertices to a specified chamfer value.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

MeshChamferData & mcd

A class in which the directions and limits of movement for all the vertices involved in the chamfer have been stored by a previous ChamferVertices or ChamferEdges call. See class MeshChamferData.

float amount

The amount (in object space units) of chamfering to do. For vertex chamfers, this indicates how far along the edges each point should move. For edge chamfers, it represents how far along each face each edge should move.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

void ChamferVertices(Mesh & m, BitArray vset, MeshChamferData & mcd, AdjEdgeList *ae=NULL);

Remarks:

Performs the topological changes needed for a vertex chamfer, and creates the information necessary to do the geometric changes.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray vset

The vertices that should be chamfered.

MeshChamferData & mcd

A class in which the directions and limits of movement for all the vertices involved in the chamfer should be stored. See class MeshChamferData.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

void CloneFaces(Mesh & m, BitArray fset);

Remarks:

Clones the specified faces, along with the vertices and mapping vertices they use.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray fset

The faces that should be cloned.

Prototype:

void CloneVerts(Mesh & m, BitArray vset);

Remarks:

Clones the specified vertices. More efficient on an initialized MeshDelta than VClone, which has to be able to cope with existing complex MeshDeltas.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray vset

The vertices that should be cloned.

Prototype:

void CollapseEdges(Mesh & m, BitArray ecol, AdjEdgeList *ae=NULL);

Remarks:

Collapses the edges indicated down to a point.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray ecol

The edges to collapse.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

DWORD Cut(Mesh & m, DWORD ed1, float prop1, DWORD ed2, float prop2, Point3 &norm, bool fixNeighbors=TRUE, bool split=FALSE);

Remarks:

Cuts the mesh from a point on one edge to a point on another, along a line drawn by looking at the mesh from a particular viewpoint. (See Edit Mesh’s Cut feature for an illustration.)

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

DWORD ed1

The edge that the cut starts on. The edge is indexed by face*3+side, so the start vertex is m.faces[ed1/3].v[ed1%3], and the end vertex is m.faces[ed1/3].v[(ed1+1)%3].

float prop1

The position on the edge to start the cut from. 0 means the start vertex of the edge, and 1 means the end vertex.

DWORD ed2

The edge that the cut should end on.

float prop2

The position on the edge to finish the cut on. 0 means the start vertex of the edge, and 1 means the end vertex.

Point3 &norm

The direction of view. The cut will take place on this "side" of the mesh, in the plane formed by this vector and the direction from the start to the end.

bool fixNeigbors=TRUE

Indicates whether the faces on the other side of each end of the cut should be split to prevent splits at the ends.

bool split=FALSE

Indicates whether the cut should actually split the mesh apart or just refine it by adding geometry.

Prototype:

void Detach(Mesh & m, Mesh *out, BitArray fset, BOOL faces, BOOL del, BOOL elem);

Remarks:

Detaches a subset of the geometry from the mesh given, either separating it as a new element or creating a new mesh with it.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

Mesh *out

The new mesh into which the detached portion can be put. (If elem is TRUE, this is not used and may be NULL.)

BitArray fset

The selection to detach. If faces is TRUE, this is a face selection. Otherwise, it’s a vertex selection.

BOOL faces

If TRUE, we should detach the selected faces; otherwise, we should detach the selected vertices.

BOOL del

Indicates whether the detached portion should be deleted from the original mesh.

BOOL elem

If TRUE, we’re actually just detaching to an element, and the out mesh will not be used.

Prototype:

void DivideEdge(Mesh & m, DWORD ed, float prop=.5f, AdjEdgeList *el=NULL, bool visDiag1=FALSE, bool fixNeighbors=TRUE, bool visDiag2=FALSE, bool split=FALSE);

Remarks:

Divides the specified edge, adding a point and dividing faces to match.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

DWORD ed

The edge to divide, indexed as face*3+side.

float prop=.5f

The proportion along the edge where the division should occur. 0 is the start vertex, m.faces[ed/3].v[ed%3], and 1 is the end vertex, m.faces[ed/3].v[(ed+1)%3].

AdjEdgeList *el=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList if needed.

bool visDiag1=FALSE

Indicates whether the diagonal connecting the new point on this edge with the far corner of face ed/3 should be visible.

bool fixNeighbors=TRUE

Indicates whether the face on the other side of this edge, that is, the face using this edge that isn’t ed/3, should be divided as well to prevent the introduction of a seam.

bool visDiag2=FALSE

Indicates whether the diagonal connecting the new point on this edge with the far corner of the face on the other side of the edge should be visible. (Not used if fixNeighbors is FALSE.)

bool split=FALSE

Indicates whether the method should create separate vertices for the two halves of the edge, splitting the mesh open along the diagonal(s).

Prototype:

void DivideEdges(Mesh & m, BitArray eset, AdjEdgeList *el=NULL);

Remarks:

Divides all the selected edges in half, creating new points and subdividing faces.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray eset

The edges to divide.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

void DivideFace(Mesh & m, DWORD f, float *bary=NULL);

Remarks:

Divides the selected face into 3, by introducing a new point on the face and splitting the original face along lines from the corners to the new point.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

DWORD f

The face to divide.

float *bary=NULL

A pointer to the barycentric coordinates of the new point on the face. If NULL, the center of the face is used.

Barycentric coordinates on a triangle are a set of three numbers between 0 and 1 that add up to 1. Any point on a triangle can be uniquely described by a set of these. The point corresponding to barycentric coordinates (a,b,c) on a face with corners A,B,C is a*A + b*B + c*C.

Prototype:

void DivideFaces(Mesh & m, BitArray fset, MeshOpProgress *mop=NULL);

Remarks:

Divides the selected faces into 3, by creating their center points and splitting the original faces along lines from the corners to the center.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray fset

The faces to divide.

MeshOpProgress *mop=NULL

If non-NULL, this points to an implementation of class MeshOpProgress which can be used to interrupt the algorithm if it’s taking too long. See class MeshOpProgress for details.

Prototype:

void EdgeTessellate(Mesh & m, BitArray fset, float tens, AdjEdgeList *ae=NULL, AdjFaceList *af=NULL, MeshOpProgress *mop=NULL);

Remarks:

Tessellates the mesh. This algorithm is exactly the one used in the Tessellate modifier, when operating on "Faces" (triangle icon) and in "Edge" type.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray fset

The faces to tessellate.

float tens

The tension for the edge tessellation. This value should be fairly small, between 0 and .5, and corresponds to the value in the Tessellate, Edit Mesh, or Editable Mesh UI’s divided by 400.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

AdjFaceList *af=NULL

A pointer to the adjacent face list for this mesh. If NULL, the method constructs its own AdjFaceList.

MeshOpProgress *mop=NULL

If non-NULL, this points to an implementation of class MeshOpProgress which can be used to interrupt the algorithm if it’s taking too long. See class MeshOpProgress for details.

Prototype:

void ExplodeFaces(Mesh & m, float thresh, bool useFaceSel=FALSE, AdjFaceList *af=NULL);

Remarks:

"Explodes" the mesh into separate elements.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

float thresh

The threshold angle between faces that indicates whether they should be in the same or different element.

bool useFaceSel=FALSE

Indicates whether the mesh’s current face selection should be used or if the whole mesh should be exploded.

AdjFaceList *af=NULL

A pointer to the adjacent face list for this mesh. If NULL, the method constructs its own AdjFaceList.

Prototype:

void ExtrudeEdges(Mesh & m, BitArray eset, Tab<Point3> *edir=NULL);

Remarks:

Performs the topological changes necessary to extrude the indicated edges. (The geometric component is handled later by the Bevel method.)

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray eset

The edges to extrude.

Tab<Point3> *edir=NULL

Fills in the directions for moving all the relevant vertices to handle the geometric part of the extrusion. See the Edit Mesh or Editable Mesh source in MAXSDK\SAMPLES\MODIFIERS and MAXSDK\SAMPLES\MESH\EDITABLEMESH to see how this is used.

Prototype:

void ExtrudeFaces(Mesh & m, BitArray fset, AdjEdgeList *el=NULL);

Remarks:

Performs the topological changes necessary to extrude the indicated faces. (The geometric component is handled later by the Bevel method.)

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray fset

The faces that should be extruded.

AdjEdgeList *el=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

void ResetVertWeights(Mesh & m);

Remarks:

Resets all the vertex weights to 1.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

Prototype:

void SetFaceColors(Mesh & m, BitArray fset, VertColor vc , int mp=0);

Remarks:

Sets the indicated faces to have vertex colors all equal to the color value specified. (This often involves creating new vertex color map vertices, so faces that neighbor the indicated faces are not affected.)

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray fset

The faces that should be affected.

VertColor vc

The desired color.

int mp=0

The map channel. Use 0 for normal vertex colors, MAP_SHADING for the illumination channel, and MAP_ALPHA for the alpha channel.

Prototype:

void SetVertColors(Mesh & m, BitArray vset, VertColor vc , int mp=0);

Remarks:

Sets all vertex color map vertices associated with the indicated vertices to the specified color.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray vset

The vertices that should be affected. If more than one map vertex is used at this vertex, all of them have their colors set.

VertColor vc

The desired color.

int mp=0

The map channel. Use 0 for normal vertex colors, MAP_SHADING for the illumination channel, and MAP_ALPHA for the alpha channel.

Prototype:

void SetFaceAlpha (Mesh &m, BitArray fset, float alpha, int mp=MAP_ALPHA);

Remarks:

This method is available in release 4.0 and later only.

Sets the indicated faces to have face alpha.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray fset

The faces that should be affected.

float alpha

The amount of alpha

int mp=MAP_ALPHA

The map channel. Use 0 for normal vertex colors, MAP_SHADING for the illumination channel, and MAP_ALPHA for the alpha channel.

Prototype:

void SetVertAlpha (Mesh &m, BitArray vset, float alpha, int mp=MAP_ALPHA);

Remarks:

This method is available in release 4.0 and later only.

Sets the indicated vertices to have face alpha.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray vset

The vertices that should be affected.

float alpha

The amount of alpha

int mp=MAP_ALPHA

The map channel. Use 0 for normal vertex colors, MAP_SHADING for the illumination channel, and MAP_ALPHA for the alpha channel.

Prototype:

void ResetVertCorners (Mesh & m);

Remarks:

This method is available in release 4.0 and later only.

This method resets the vertex corners.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

Prototype:

void SetVertWeights(Mesh & m, BitArray vset, float weight);

Remarks:

Sets the weights of the specified vertices. (These weight values are only used in MeshSmooth NURMS mode as of 3ds max 3.0.)

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray vset

The vertices that should have their weights set.

float weight

The weight to set.

Prototype:

void Slice(Mesh & m, Point3 N, float off, bool sep=FALSE, bool remove=FALSE, BitArray *fslice=NULL, AdjEdgeList *ae=NULL);

Remarks:

Slices the mesh along the specified slicing plane.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

Point3 N

The normal of the slice plane.

float off

These parameters define the slicing plane as all points p satisfying the equation DotProd(p,N) = off. N should be normalized.

bool sep=FALSE

Indicates whether the slice should separate the mesh into two separate elements (if TRUE) or just refine the existing mesh by splitting faces (if FALSE).

bool remove=FALSE

Indicates whether the slice should remove the portion of the mesh "below" the slicing plane, where "below" is defined as the area where DotProd (p,N) – off < 0. If remove is TRUE, sep is ignored.

BitArray *fslice=NULL

A bit array containing the list of faces to slice.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

void TurnEdge(Mesh & m, DWORD ed, AdjEdgeList *el=NULL);

Remarks:

"Turns" the specified edge. Only works on edges that have a face on both sides. These two faces are considered as a quad, where this edge is the diagonal, and remapped so that the diagonal flows the other way, between the vertices that were opposite this edge on each face.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

DWORD ed

The edge to turn, indexed as face*3+side.

AdjEdgeList *ae=NULL

A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own AdjEdgeList.

Prototype:

BOOL WeldByThreshold(Mesh & m, BitArray vset, float thresh);

Remarks:

Welds all vertices that are sufficiently close together.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray vset

The vertices that are candidates for being welded.

float thresh

The maximum distance (in object space units) between two vertices that will allow them to be welded.

Return Value:

Returns TRUE if any vertices were welded, FALSE if none were within threshold.

Prototype:

void WeldVertSet(Mesh & m, BitArray vset, Point3 *weldPoint=NULL);

Remarks:

Welds the specified vertices together into one vertex, no matter how far apart they are.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray vset

The vertices that should be welded.

Point3 *weldPoint=NULL

If non-NULL, this points to the location we’d like to put the weld result. (If NULL, the result is put at the average location of the selected vertices.)

Prototype:

void PropagateFacing(Mesh & m, BitArray & fset, int face, AdjFaceList & af, BitArray & done, BOOL bias=1);

Remarks:

This method is designed for internal use, in UnifyNormals, but may also be called directly.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray fset

The faces that should be affected.

int face

The starting face to propagate normal directions from.

AdjFaceList & af

The adjacent face list corresponding to the mesh. Required, can’t be made locally, for efficiency’s sake.

BitArray & done

Keeps track of which faces have had their normals unified. Faces that are set here when the call is made will not be processed, and will not be crossed to reach other faces. Faces that are still clear upon completion were not processed, probably because they were on a separate element from "face".

BOOL bias=1

Used to keep track of whether the current face has been oriented correctly. For example, if the starting face was not selected in fset, and therefore doesn’t have the right orientation, but you still want selected faces in the same element to be corrected, you would submit FALSE here.

Prototype:

void UnifyNormals(Mesh & m, BitArray fset, AdjFaceList *af=NULL);

Remarks:

Unifies normals on selected faces, making the normals consistent from face to face.

Parameters:

Mesh & m

The mesh this MeshDelta should be based on.

BitArray fset

The faces that should be affected. Nonselected faces can be traversed by the algorithm, but they will not be corrected if their normals are pointing the "wrong" way.

AdjFaceList *af=NULL

A pointer to the adjacent face list corresponding to the mesh. If NULL, an adjacent face list is computed by the method.

I/O, Debugging

Prototype:

IOResult Save(ISave *save);

Remarks:

Saves the MeshDelta to a 3ds max file.

Prototype:

IOResult Load(ILoad *load);

Remarks:

Loads the MeshDelta from a 3ds max file.

Prototype:

void MyDebugPrint(bool lut=FALSE, bool mp=FALSE);

Remarks:

Prints out the MeshDelta to the DebugPrint window in Developer Studio.

Parameters:

bool lut=FALSE

If TRUE, the vertex and face lookup tables are printed out.

bool mp=FALSE

Active map deltas are also printed out if this is TRUE.