Editable_Mesh : GeometryClass and TriMesh : Value

Editable_Mesh is the class of node objects that are the result of collapsing a modifier stack to an editable mesh object. Many of the mesh operations in MAXScript that modify meshes only work on Editable_Mesh scene nodes.

The TriMesh class is a MAXScript value wrapper for the low-level 3ds Max SDK Mesh class used extensively in mesh-based objects and modifiers in 3ds Max. Meshes hold the actual vertex and face arrays, and so on, in a triangular mesh. For example, an Editable_Mesh object contains an instance of a Mesh. The prime purpose of the TriMesh class is to allow scripted primitive object plug-ins to access and build the Mesh object inside geometry objects. This class has a large range of mesh manipulation and construction functions, corresponding to the low-level mesh operations on Editable Mesh scene nodes.

The properties and methods described in this topic are applicable to both Editable_Mesh objects and TriMesh values, and are signified by a value type of < mesh >. The properties and methods applicable to just TriMesh values are signified by a value type of < trimesh >.

Warning:

Meshes created by MAXScript are triMesh values.

Note:

Only the update() function updates the mesh's internal caches and images in 3ds Max viewports. This is because updates can be computationally expensive and you do not want them performed on every function call. However, you must make sure to call the update() function after a series of changes and before the mesh is to be worked on in 3ds Max or by other functions in MAXScript.

Coordinates are given in the MAXScript working coordinate system.

If the update() function is called on an object that is selected and currently open in the Modify panel, it drops the current selection to avoid a potential crash in 3ds Max, which at the moment, does not support scripted changes to an object open in the Modify panel.

If you are creating or modifying a mesh, and have not yet run update() on the mesh, 3ds Max crashes if you minimize and then maximize the 3ds Max window. This is because only a partial mesh is created, and the internal 3ds Max mesh structure is left in an unstable state.

Constructors (Editable_Mesh)

editable_mesh... 

Creates an empty mesh.

mesh [ length:<integer> ] [ width:<integer> ]  [ lengthsegs:<integer> ] [ widthsegs:<integer> ] 

Creates a flat rectangular mesh with the given size and number of segments. The default length and width are 50, the default number of segments is 5.

mesh [ numverts:<number> ] [ numfaces:<number> ] 

Creates a mesh of the given geometry, but with no topology (no faces or edges). You have to individually place the vertices and create the faces from the vertices. The default number of vertices and faces are 36 and 50, respectively.

mesh [ mesh:<TriMesh>] 

Creates a mesh using the specified TriMesh value as the mesh source.

mesh vertices:<array_of_point3s> faces:<array_of_point3s> [ materialIDs:<array_of_integers> ] [ tverts:<array_of_point3s> ] 

Creates a mesh from an array of vertices and faces. Each Point3 value in the vertices array specifies the position of the vertex in the current coordinate system. Each Point3 value in the faces array specifies the three vertex indices that form the face. The materialIDs array specifies the material ID to be assigned to each face.

Each Point3 value in the tverts array specifies the UVW coordinates of the texture vertices. See Texture Mapping in the methods section for more information on texture vertices.

An example of mesh construction using this form of the constructor is:

EXAMPLE

   mesh vertices:#([0,0,0],[10,0,0],[0,10,0],[10,10,0]) \
   faces:#([1,2,3],[2,4,3]) materialIDS:#(1,2)
Note: The optional tverts array feature is currently broken. The texture vertices are set correctly, but no texture faces are built internally. Until this gets fixed, you can work around by building the texture faces yourself:

WORKAROUND EXAMPLE:

   mnode = mesh vertices:#([0,0,0],[10,0,0],[0,10,0],[10,10,0]) tverts:#([0,0,0],[10,0,0],[0,10,0],[10,10,0]) faces:#([1,2,3],[2,4,3])
   mmesh = mnode.mesh
   buildTVFaces mmesh
   for i = 1 to mmesh.numfaces do(setTVFace mmesh i (getFace mmesh i))
collapseStack <node> -- mapped 

Collapses the object space modifiers out of a stack, leaving a resultant base object corresponding to the evaluation result on top of the node(s)' stack. This means that the result is Editable_Meshonly when the result on top of the stack is Editable_Mesh. Some modifiers convert the object class implicitly, for example, a Box with MeshSmooth on top collapses to Editable_Poly because MeshSmooth implicitly converts the incoming geometry to polygons. Adding a MeshSelector a TurnToMesh modifier on top of the MeshSmooth modifier and then calling collapseStack() results in an Editable_Mesh base object.

EXAMPLE

   b = box() --create a box
   --> $Box:Box01 @ [0.000000,0.000000,0.000000]
   addModifier b (MeshSmooth()) --add meshSmooth modifier
   --> OK
   classof b --check the class - it was turned into Polygons!
   --> PolyMeshObject
   collapseStack b --collapse the stack of the box
   --> OK
   classof b --the result is Editable_Poly
   --> Editable_Poly
   addModifier b (Turn_To_Mesh()) --now add Turn To Mesh modifier
   --> OK
   classof b --the class is now Editable_Mesh and not Editable_Poly!
   --> Editable_mesh
   collapseStack b --collapse the stack
   --> OK
   classof b --as expected, the result is an Editable_Mesh!
   --> Editable_mesh

If there are no object space modifiers in the stack when this is called, no action is taken. So, if you want to force an object to be an editable mesh (for example, for the mesh operation listed below), you can apply a null modifier and then collapse the stack:

EXAMPLE

   b = box() --create a box
   --> $Box:Box03 @ [0.000000,0.000000,0.000000]
   collapseStack b --try to collapse the stack
   --> OK
   classof b --it is still a box - nothing to collapse!
   --> Box
   addModifier b (meshSelect()) --add a MeshSelect modifier
   --> OK
   collapseStack b --try to collapse the stack again
   --> OK
   classof b --this time it worked!
   --> Editable_mesh

collapseStack() does not collapse the effect of any world space modifiers (including bindings to SpaceWarps). The world space modifiers remain on the object's stack. To collapse an object with world space modifiers to a mesh use the snapshot() method.

snapshot <node> -- mapped

This function provides functionality similar to the SnapShot tool in 3ds Max. It generates a new node that contains a copy of the world-state mesh of the source < node > at the time that the snapshot is made. Any existing modifiers are collapsed out of the new node and the mesh snapshot accounts for any currently applied space warps.

convertToMesh <node> -- mapped

Converts appropriate scene object types into Editable Meshes. Similar to collapseStack() , it removes all object space modifiers that are present, but unlike collapseStack() it always replaces the base object with an editable mesh version, even if there are no modifiers present.

It can be applied to any object that an Edit Mesh modifier can work on such as, geometry and shapes, but not helpers, space warps, lights, and others.

convertTo <node> [ TriMeshGeometry | Mesh ] -- mapped

Converts appropriate scene object types into Editable Meshes. Operates in an identical manner to convertToMesh() .

Constructors (TriMesh)

TriMesh() 

Creates an empty TriMesh. Use the methods listed below to build the mesh.

<node>.mesh 

Extracts a copy of a node's world state if it is convertible to a mesh.

<editable_mesh_baseobject>.mesh 

Extracts a copy of base object's mesh.

<trimesh>.mesh 

Extracts a copy of another TriMesh's mesh.

Note: GeometryClass boolean operations also create editable_mesh objects.

Operators

The following operators perform boolean operations on meshes. These operations destructively modify the first operand mesh to contain the boolean result as do the same boolean < node > operations.

<mesh> + <mesh> -- union
<mesh> - <mesh> -- difference
<mesh> * <mesh> -- intersection

Properties

<mesh>.numverts Integer 

Get or set the number of vertices. When setting the number of vertices using the numVerts property or the setNumVerts method, the new vertices are initialized to [0.,0.,0.].

<mesh>.numfaces Integer 

Get or set the number of faces.

In versions prior to 3ds Max 7, the user was responsible for re-initializing the mesh to make it valid before calling update. In 3ds Max 7 and higher, the re-initializing is performed automatically when setting the .numfaces value or calling the setNumFaces function.

Note:
$.numfaces=300
--is equivalent to
setNumFaces $ 300 false
--The false argument means to not keep the existing topology

For all new faces, the following occurs:

<mesh>.numtverts Integer 

Get or set the number of texture vertices. When setting the number of texture vertices using the numTVerts property or setNumTVerts method, the new verts are initialized to [0.,0.,0.].

<mesh>.numcpvverts Integer 

Get or set the number of color-per-vertex vertices. When setting the number of CPV vertices using the numCPTVerts property or setNumCPVVerts method, the new verts are initialized to [0.,0.,0.].

<mesh>.mesh TriMesh 

Reading this property yields a copy of the mesh, taken after applying any modifiers, but before any space warps are applied. Assigning to this property sets the mesh to the TriMesh value given. You can use this property, along with copy() and the <node_or_baseobject>.mesh property to build a TriMesh from other objects'meshes.

Note: The following properties are not applicable to TriMeshes:
<mesh>.selectedVerts VertexArray 

Get the currently selected vertices of the Editable_Mesh object. See VertexSelection Values.

<mesh>.verts VertexArray 

Get all of the vertices of the Editable_Mesh object. See VertexSelection Values.

<mesh>.selectedFaces FaceArray 

Get the currently selected faces of the Editable_Mesh object. See FaceSelection Values.

<mesh>.Faces FaceArray 

Get all of the faces of the Editable_Mesh object. See FaceSelection Values.

<mesh>.selectedEdges EdgeArray 

Get the currently selected edges of the Editable_Mesh object. See EdgeSelection Values.

<mesh>.Edges EdgeArray 

Get all of the edges of the Editable_Mesh object. See EdgeSelection Values.

<mesh>.displacementMapping Boolean 

Get or set whether to perform displacement mapping for the Editable_Mesh object. There is no corresponding user interface element for this property.

<mesh>.subdivisionDisplacement Boolean 

Get or set whether to perform subdivision displacement for the Editable_Mesh object. This property corresponds to the Subdivision Displacement checkbox in the Surface Properties rollout.

<mesh>.splitMesh Boolean 

Get or set whether to split the mesh during subdivision displacement. This property corresponds to the Split Mesh checkbox in the Surface Properties rollout. Setting this property enables subdivisionDisplacement if it is set to false .

You can both read and assign to the above properties with the exception of the properties that return a VertexSelection, FaceSelection, or EdgeSelection. If you assign numbers to them to add room for more vertices or faces, the mesh loses all current topology/geometry (vertices, faces, and edges), assuming you want to rebuild it from scratch. If you want to retain the current topology/geometry, use the setNumVerts() , setNumTVerts() , and setNumFaces() methods that are described below.

Up to N vertex coordinates are available as properties on Editable_Mesh objects, where N is the number of vertices in the mesh. A vertex is available as a property once a controller is assigned to the vertex. Controllers can be assigned to vertices using the animateVertex() method described in Scripting Vertex and Control Point Animation . For example, if a sphere object is collapsed to an Editable_Mesh, and some of its vertices are animated, the properties for the vertices are similar to:

$Sphere01.vertex_209 Point3 value:[7.9,-40.0,0.0] -- animatable
$Sphere01.vertex_210 Point3 value:[-7.8,-39.3,-7.9] -- animatable
$Sphere01.vertex_211 Point3 value:[0.0,-40.0,-7.9] -- animatable

Methods

The following methods operate on the base object in a node if no object space modifiers are present. If object space modifiers are present, the mesh get operations access the world-state mesh, after the object space modifiers are applied. The mesh set operations only work on base object Editable Meshes and signal an error if there are object space modifiers present, informing you that the mesh is not changeable when modifiers are present. You can convert objects to Editable Meshes with the collapseStack() , snapshot() , and convertToMesh() methods. If there are no object space modifiers present, both get and set operations work on the base editable mesh object.

Because the mesh get operations require a mesh, the combination of base object and modifiers must yield a mesh at the top of the modifier stack. This excludes combinations such as, Patch base-objects and deformer modifiers like bend and twist because they pass a patch object and not a mesh up the stack. Applying an Edit Mesh modifier always forces the world-state object to be a mesh.

If world space modifiers are present, the mesh get operations access the world-state mesh after any object space modifiers are applied, but before the world space modifiers are applied. Currently, you cannot access the position of vertices as affected by world space modifiers. The mesh set operations work only when world space modifiers are applied to the object. Setting a vertices position in such a case sets its position before the world space modifiers are applied. You can create a new mesh object using the snapshot() method which accounts for the effects of world space modifiers.

The update() method makes any scripted changes to a base object mesh visible to 3ds Max and you must call this function at some point after modifying a mesh so that 3ds Max sees a valid mesh. Because this update can be a compute-intensive operation, it is made available as a separate function so you perform many changes on a mesh and then invoke the update just once to signal all the changes to 3ds Max.

All vertex and face indexes start at 1, following the other indexing conventions in MAXScript. All coordinates used are relative to the current working coordinate system.

General Methods

update <mesh> [ geometry:<boolean> ] [ topology:<boolean> ] [ normals:<boolean> ] -- mapped

The three optional keyword arguments provide control over the kind of update done to the mesh. If the geometry: argument is true , the geometry cache is rebuilt (normals and edge list) and the mesh's bounding box is invalidated. If the topology: argument is true , the edge and strip databases are rebuilt. If normals: is true , the face normals are computed. All flags default to true so that a simple call to update() causes a complete reconstruction of all the caches.

attach <mesh> <node> 

Corresponds to the mesh attach function in the Editable Mesh Modify panel allowing you to construct a mesh by adding complete objects to it. Extracts the mesh from <node> (first converting to a mesh, if needed), adds it to <mesh> which must be an Editable Mesh object, and then deletes <node> . The materials and material IDs in <node> are merged into <node> using the default settings for the attach operation in the Editable Mesh Modify panel. This method is not applicable to TriMeshes.

meshop.attach{<target_editable_mesh_node> | <target_mesh>} \ 
{<source_node> | <source_mesh>} \ 
targetNode:<node=unsupplied> \ 
sourceNode:<node=unsupplied> \ 
attachMat:<{#neither | #MatToID | #IDToMat}=#neither>\ 
condenseMat:<boolean=true> \ 
deleteSourceNode:<boolean=true> 

Attaches the source mesh to the target mesh. If the target or source is specified as a mesh rather than a node, the mesh is attached using the local coordinate system of the mesh, and no material correction is performed. To get around this, if the target or source is a mesh, the corresponding targetNode or sourceNode named parameter is checked to see if a node is specified and, if so, the transform and material for that node is used. If the source or target is specified as a node, the corresponding targetNode or sourceNode named parameter is not checked. The attachMat and condenseMat options correspond to the attach options in the editable mesh.

condenseMat is applicable only if attachMat:#IDToMat is specified. If deleteSourceNode:false is not specified, and the source was specified as a node, or as a mesh and a sourceNode was specified, the source node is deleted after the attach.

EXAMPLE

   meshop.attach $.baseobject $sphere02 targetNode:$
   meshop.attach $box01 $box02 attachMat:#IDToMat \
   condenseMat:true deleteSourceNode:false
meshopgetUIParam. <mesh> <param_name> 
meshop.getUIParam <node> [ <modifier_or_index> ] <param_name> 
meshop.setUIParam <mesh> <param_name> { <float> | <boolean> } 
meshop.setUIParam <node> [ <modifier_or_index> ] <param_name> { <number> | <boolean> } 

Get/set a user-interface value. The optional <modifier_or_index> identifies the Edit Mesh modifier on the given scene object to set the parameter value. These methods are UI-dependent, and require that the specified editable mesh or Edit Mesh modifier be currently displayed in the Modify panel. The valid param_name values, their meaning, and parameter value type are:

#SelByVert Selection - By Vertex (boolean)

#IgBack Selection - Ignore Backfacing (boolean)

#IgnoreVis Selection - Ignore Visibile Edges (boolean)

#PolyThresh Selection - Planar Threshold (number)

#SoftSel Soft Selection - Use Soft Selection (boolean)

#SSUseEDist Soft Selection - Edge Distance (boolean)

#SSEDist Soft Selection - Edge Distance (number) [note: if value has not changed, returns a value of 0]

#SSBack Soft Selection - Ignore Backfacing (boolean) [note: this is the inverse of the UI element]

#Falloff Soft Selection - Falloff (number)

#Pinch Soft Selection - Pinch (number)

#Bubble Soft Selection - Bubble (number)

#WeldDist Weld - Distance (number)

#WeldBoxSize Weld - Box Size in Pixels (number)

#ExtrudeType Extrude/Chamfer (boolean) [note: true - Group; false - Local]

#ShowVNormals Show Vertex Normals (boolean)

#ShowFNormals Show Face Normals (boolean)

#NormalSize Normal Scale (number)

<float>mesh_weld_overlapping_vertices <TriMesh>mesh

Welds the overlapping vertices of a TriMesh. Available in in 3ds Max 2017 and higher.

For example:

s = sphere segs:128 --create a sphere with 128 segments
--> $Sphere:Sphere001 @ [0.000000,0.000000,0.000000]

convertToMesh s --convert to Editable Mesh
--> $Editable_Mesh:Sphere001 @ [0.000000,0.000000,0.000000]

s.numverts --check the number of vertices
--> 8066

s1 = copy s --clone the sphere as a copy
--> $Editable_Mesh:Sphere002 @ [0.000000,0.000000,0.000000]

attach s s1 --attach the copy to the original
--> OK

s.numverts --check number of vertices again – it is doubled
--> 16132

mesh_weld_overlapping_vertices s.mesh --weld the overlapping vertices
--> 0.888889

s.numverts --check the number of vertices again...
--> 8066

Further Mesh-Related Topics:

Vertex Methods

Vertex Methods (meshop struct)

Vertex Data Methods (meshop struct)

Edge Methods

Edge Methods (meshop struct)

Face Methods

Face Methods (meshop struct)

Mesh Methods (meshop struct)

Mapping Methods - General (meshop struct)

Texture Vertex Methods

Color-Per-Vertex Methods

Subdivision Displacement Surface Properties Methods

Editable Mesh UI Property Methods (meshop struct)

Editable Mesh Modify Panel Command Modes and Operations (meshOps struct)