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
>.
Meshes created by MAXScript are triMesh
values.
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)
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.
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.
$.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:
Smoothing group set to 1
Vertices are set to [1,1,1] (1-based, crashes if # verts is 0 at update. It is expected at this point)
Material ID is set to 1 (1-based)
For each map channel in use:
the map face verts are set to [1,1,1]
if keep is false, the number of map verts is set to 1, and its verts are set to [1,1,1] (1-based)
<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.
<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
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.
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 (meshop struct)
Vertex Data Methods (meshop struct)
Mapping Methods - General (meshop struct)
Subdivision Displacement Surface Properties Methods
Editable Mesh UI Property Methods (meshop struct)
Editable Mesh Modify Panel Command Modes and Operations (meshOps struct)