Editable_Poly Topics:
Editable_Poly Mapping Methods(polyOp struct)
A
suite of methods provide the ability for a script to invoke
Editable Poly Modify panel modes and operations, corresponding to
buttons available at various sub-object levels. These methods
reside in the polyOp
and polyOps
global structures. These
methods effectively "push the button" in the Modify panel. In order
to use these methods, the node must be selected and the Modify
panel open. In the description of these methods, the first
argument
The follow methods invoke one of the 'user-interaction' button operations in the Editable Poly Modify panel, acting on the currently selected sub-objects. These methods highlight the corresponding button in the Geometry rollout and start the operation, at which point the user interactively completes the operation. These methods return after starting the operation, and before the user completes the operation, so care should be taken to ensure that your script does not interfere with the operation. Invoking any of these methods is the same as clicking on the associated button in the Modify panel. Calling a method when the operation is already in effect (either due to a user action or a MAXScript command) causes the operation to be terminated and the highlight is removed from the button.
Many
of the polyOp methods take as an argument
#all - all SO elements of that type
#selection - the current SO selection of that type
#none - none of the SO elements of that type
An array of integers, where each integer value specifies a SO element index
A bitarray, where each bit specifies a SO element index
A value convertable to an integer that specifies a SO element index
A VertexSelection, EdgeSelection, or FaceSelection value. The value type must match the specified SO type.
All
polyOp methods take as an argument
Editable polys can have "dead" vertices, edges, and faces. These are SO elements that have been deleted from the poly, but have not yet been removed from the corresponding lists of SO elements. SO elements may be marked as dead in the process of performing certain operations on the poly, but the SO element lists are normally collapsed (that is, all dead SO elements removed) at the end of the operation. Thus, normally there should not be any dead SO elements present in the poly. If you flag a SO element as dead using one of the polyOp methods, you should also call collapseDeadStructs to collapse the SO element lists.
Other than methods that get/set SO element flags, dead SO elements are normally ignored by the polyOp methods. If a method returns a value other than OK, takes a single SO element index, and that SO element is dead, a value of UNDEFINED is normally returned.
polyOp.getVertSelection
Returns the current vertex selection as a bitarray
polyOp.setVertSelection
Sets
the current vertex selection based on
polyOp.getEdgeSelection
Returns the current edge selection as a bitarray
polyOp.setEdgeSelection
Sets
the current edge selection based on
polyOp.getFaceSelection
Returns the current face selection as a bitarray
polyOp.setFaceSelection
Sets
the current face selection based on
Each vertex in a poly contains a 32 bit flag variable. This method returns a bitarray of the vertices that have specific bits in this flag variable set, where the bits being tested are based on a combination of <flag> and <maskflag>.
The default value for <maskflag> is 0.
Internally, if <maskflag> is 0 then <maskflag> is set to the <flag> value, otherwise <flag> is set to the bitwise-AND of <flag> and <maskflag>. Bit 2 of <maskflag> is then set, which prevents dead vertices from being included in the resulting bitarray unless this bit was set in <mask>. Each bit in the resulting bitarray is set if the bitwise-AND of the flag variable and <maskflag> is equal to the bitwise-AND of <flag> and <maskflag>.
The vertex level flags are:
bit 1: vertex is selected
bit 2: vertex is dead
bit 3: reserved
bit 4: indicates the vertex faces "backwards" in the current viewport
bit 5-24: reserved
bit 25-32: available for general use
Example:
theObj = plane isSelected:true
convertto theObj editable_poly
?
nVerts = theObj.numverts
?
bit30 = bit.set 0 30 true
bit31 = bit.set 0 31 true
bit32 = bit.set 0 32 true
?
-- set a bit on first 3/4 or so verts
(
flagsToSet = bit30
flagsToMask = 0
vertexSet = #{1..(3*nVerts/4)}
theObj.setVertexFlags vertexSet flagsToSet flagMask:flagsToMask generateUndoRecord:true
ok
)
-- and another on middle block
(
flagsToSet = bit31
flagsToMask = 0
vertexSet = #{(nVerts/3)..(nVerts-4)}
theObj.setVertexFlags vertexSet flagsToSet flagMask:flagsToMask generateUndoRecord:true
ok
)
-- set a bit on last 2 verts
(
flagsToSet = bit32
flagsToMask = 0
vertexSet = #{(nVerts-2)..nVerts}
theObj.setVertexFlags vertexSet flagsToSet flagMask:flagsToMask generateUndoRecord:true
ok
)
?
(
-- get verts with bit30, 31, 32 set
format "30: %\n" (polyOp.getVertsByFlag theObj bit30)
format "31: %\n" (polyOp.getVertsByFlag theObj bit31)
format "32: %\n" (polyOp.getVertsByFlag theObj bit32)
?
-- get verts with bit30 set, but not bit31
format "30 and !31: %\n" (polyOp.getVertsByFlag theObj bit30 mask:(bit30+bit31))
?
-- get
verts with bit31 not set, doesn't matter
what the
-- value is as long as it's not bit31
format "!31: %\n" (polyOp.getVertsByFlag theObj bit30 mask:(bit31))
?
-- get verts with bit30 and bit31 set
format "30 and 31: %\n" (polyOp.getVertsByFlag theObj (bit30+bit31))
?
-- get verts with neither bit31 or bit32 set, doesn't matter what
-- the
format "!(31 or 32): %\n" (polyOp.getVertsByFlag theObj bit30 mask:(bit31+bit32))
)
?
Returns the flags bits for the vertex as an integer.
polyOp.setVertFlags
Sets
the flag bits on the specified vertices to the bits in
Example:
p=convertToPoly (plane())
p.selectedVerts = #{10..20}
i=1 -- selected bit
j=bit.set 0 30 true -- bit 30 set
oldflags = for k = 1 to p.numverts collect polyop.getVertFlags p k
theSet=#{5..15}
polyop.setvertflags p theSet j mask:i
for k = 1 to p.numverts do
(
nf=polyop.getVertFlags p k
format "% : % : %\n" k nf oldflags[k]
oldflags[k]=nf
)
j=bit.set 0 1 true -- bit 1 set
polyop.setvertflags p theSet j
for k = 1 to p.numverts do
(
nf=polyop.getVertFlags p k
format "% : % : %\n" k nf oldflags[k]
)
Each edge in a poly contains a 32 bit flag variable. This method returns a bitarray of the edges that have specific bits in this flag variable set, where the bits being tested are based on a combination of <flag> and <maskflag>.
The default value for <maskflag> is 0.
Internally, if <maskflag> is 0 then <maskflag> is set to the <flag> value, otherwise <flag> is set to the bitwise-AND of <flag> and <maskflag>. Bit 2 of <maskflag> is then set, which prevents dead edges from being included in the resulting bitarray unless this bit was set in <mask>. Each bit in the resulting bitarray is set if the bitwise-AND of the flag variable and <maskflag> is equal to the bitwise-AND of <flag> and <maskflag>.
The edge level flags are:
bit 1: edge is selected
bit 2: edge is dead
bit 3: reserved
bit 4: indicates the vertex faces "backwards" in the current viewport
bit 5-24: reserved
bit 25-32: available for general use
polyOp.getEdgeFlags
Returns the flags bits for the edge as an integer.
polyOp.setEdgeFlags
Sets
the flag bits on the specified edges to the bits in
Each face in a poly contains a 32 bit flag variable. This method returns a bitarray of the faces that have specific bits in this flag variable set, where the bits being tested are based on a combination of <flag> and <maskflag>.
The default value for <maskflag> is 0.
Internally, if <maskflag> is 0 then <maskflag> is set to the <flag> value, otherwise <flag> is set to the bitwise-AND of <flag> and <maskflag>. Bit 2 of <maskflag> is then set, which prevents dead faces from being included in the resulting bitarray unless this bit was set in <mask>. Each bit in the resulting bitarray is set if the bitwise-AND of the flag variable and <maskflag> is equal to the bitwise-AND of <flag> and <maskflag>.
The face level flags are:
bit 1: face is selected
bit 2: face is dead
bit 3: reserved
bit 4: indicates the vertex faces "backwards" in the current viewport
bit 5-24: reserved
bit 25-32: available for general use
polyOp.getFaceFlags
Returns the flags bits for the face as an integer.
polyOp.setFaceFlags
Sets
the flag bits on the specified faces to the bits in
?
polyOp.getNumVerts
Returns the number of vertices in the poly. Includes any dead vertices.
polyOp.getNumEdges
Returns the number of edges in the poly. Includes any dead edges.
polyOp.getNumFaces
Returns the number of faces in the poly. Includes any dead faces.
polyOp.getHiddenVerts
Bits in the result bitarray are set if the corresponding vertex is hidden.
polyOp.setHiddenVerts
Hides the corresponding vertices in the poly
polyOp.getHiddenFaces
Bits in the result bitarray are set if the corresponding face is hidden.
polyOp.setHiddenFaces
Hides the corresponding faces in the poly
polyOp.unHideAllFaces
Unhides all faces in the poly.
polyOp.unHideAllVerts
Unhides all vertices in the poly.
polyOp.getEdgeVis
Returns true if the specified edge is visible, false otherwise.
polyOp.setEdgeVis
Sets the visibility of the specified edges.
polyOp.getOpenEdges
Bits in the result bitarray are set if the corresponding edge is open (used by only 1 ace).
polyOp.getBorderFromEdge
Bits in the result bitarray are set for open edges in the poly that are connected via open edges to the specified edge.
All one-sided edges in polys can be grouped into chains, end to end, that represent boundaries of the poly. For instance, in a box with one side deleted, all the one-sided edges are part of the chain that goes around the hole. If the specified edge isn't open, the resulting bitarray is empty.
polyOp.getFaceVerts
Returns the face's vertices as an array. The order of the vertices in the array corresponds to the order of the vertices in the face.
polyOp.getFaceEdges
Returns the face's edges as an array. The order of the edges in the array corresponds to the order of the edges in the face.
polyOp.getFaceDeg
Returns the number of vertices in the specified face.
polyOp.getEdgeVerts
Returns the edge's vertices as a 2 element array.
polyOp.getEdgeFaces
Returns the faces using the specified edge. Normally a 1 element (open edge) or 2 element array.
polyOp.getDeadVerts
Returns the current dead vertices selection as a bitarray. Normally this will return an empty bitarray.
polyOp.getDeadEdges
Returns the current dead edges selection as a bitarray. Normally this will return an empty bitarray.
polyOp.getDeadFaces
Returns the current dead faces selection as a bitarray. Normally this will return an empty bitarray.
polyOp.GetHasDeadStructs
Bit 1 in the return value is set if the poly has any dead vertices, bit 2 if any dead edges, and bit 3 if any dead faces.
polyOp.isFaceDead
Returns true if the specified face is dead.
polyOp.isEdgeDead
Returns true if the specified edge is dead.
polyOp.isVertDead
Returns true if the specified vertex is dead.
polyOp.CollapseDeadStructs
Removes all dead SO elements from the poly.
polyOp.getFaceMatID
Returns the material ID assigned to the face
polyOp.setFaceMatID
Assigns the material ID to the face
polyOp.getVert
Returns the position of
the specified vertex. If
polyOp.setVert
Sets
the position of the specified vertices. If
polyOp.moveVert
Moves
the specified vertices by
polyOp.isMeshFilledIn
Returns true if all topological links, such as the list of edges, are complete for the poly.
polyOp.fillInMesh
Recomputes the internal MNEdges and MNFace::edg, MNVert::edg, and MNVert::fac lists based on the information in the MNFace::vtx lists.
polyOp.getEdgesUsingVert
Bits
in the result bitarray are set if the corresponding edge uses one
of the vertices in
polyOp.getFacesUsingVert
Bits
in the result bitarray are set if the corresponding face uses one
of the vertices in
polyOp.getVertsUsingEdge
Bits
in the result bitarray are set if the corresponding vertex uses one
of the edges in
polyOp.getFacesUsingEdge
Bits
in the result bitarray are set if the corresponding face uses one
of the edges in
polyOp.getVertsUsingFace
Bits
in the result bitarray are set if the corresponding vertex uses one
of the faces in
polyOp.getEdgesUsingFace
Bits
in the result bitarray are set if the corresponding edge uses one
of the faces in
polyOp.getElementsUsingFace
Bits
in the result bitarray are set for all faces in the same "element",
or connected component, with faces in
If
polyOp.getVertsUsedOnlyByFaces
Bits
in the result bitarray are set if the corresponding vertex is only
used by faces in
polyOp.getFaceCenter
Returns the center of the
face by taking the average of all its vertices. If
polyOp.getSafeFaceCenter
Returns the "safe" center of the face, if possible. For non-convex faces, the average point found using getFaceCenter is unsuitable for some applications because it can lie outside the face completely, or in a region where it cannot see all the face's vertices (i.e., line segments from the center to the corner pass outside of the face.). If a safe center cannot be found, a value of UNDEFINED is returned.
This routine provides a better solution in some cases by finding the center of the convex hull of the face. The convex hull is defined as the region in a face with a clear line-of-sight to all the corners. Some faces, such as the top face in an extruded letter M, have an empty convex hull, in which case this routine fails and merely provides the regular center given by ComputeCenter.
If
polyOp.getFaceNormal
Returns the face normal of
the face. If
polyOp.getFaceArea
Returns the area of the specified face.
polyOp.attach
Attaches
, converted to a
polymesh if necessary, to
polyOp.deleteVerts
Deletes the specified vertices.
polyOp.deleteFaces
Deletes the specified
faces. If
polyOp.deleteEdges
Deletes the specified
edges. If
The behavior of the methods PolyOp.deleteEdges, PolyOp.deleteVerts and PolyOp.deleteFaces changed in 3ds Max 5. Now when using these methods, all sub-object elements that use the deleted elements are also deleted. What used to be the (internal) Delete method is now the (internal) Remove method. This new method isn't exposed through the polyOp structure, so you will need to work through the EditablePoly interface, Remove method.
An example replacement function which will work in both version 4 and higher is:
Example:
fn polyop_deleteEdges obj which delIsoVerts:=
(?
if (MaxVersion())[1] >= 5000 then
(
local bit30 = bit.set 0 30 true
polyop.setEdgeFlags obj which bit30
obj.EditablePoly.remove selLevel:#edge flag:bit30
if delIsoVerts == true do polyop.deleteIsoVerts obj
)
else
polyop.deleteEdges obj which delIsoVerts:delIsoVerts
)
polyOp.deleteIsoVerts
Deletes any vertices not used by any faces.
polyOp.weldVertsByThreshold
Welds the specified vertices that are within the threshold distance. The threshold distance is a property (weldThreshold) of the editable poly. Only vertices on a border can be welded.
polyOp.weldVerts
Welds the two specified vertices, with the resulting vertex positioned at the specified location. Only vertices on a border can be welded.
If
If
polyOp.weldEdgesByThreshold
Welds the vertices associated with the specified edges that are within the threshold distance. The threshold distance is a property (weldThreshold) of the editable poly. Only vertices on a border can be welded.
polyOp.weldEdges
Welds the vertices associated with the specified edges. Only vertices on a border can be welded.
polyOp.createVert
Creates a vertex as the
specified position. If
polyOp.createEdge
Creates an edge using the two specified vertices. The vertices must be used by a common face. Returns the index of the created edge or undefined if no edge was created.
polyOp.createPolygon
Creates a face using the specified vertices. The order of the vertices in the face is the order in the vertex array. For each successive vertex pair, at most 1 edge may exist between the vertices, and that edge must not go from the first to second vertex. The default triangulation for a face with the specified number of vertices is used; if the face is not convex, this triangulation may be inappropriate.
If this is the case, call retriangulate() on this face after it's created. This returns the index of the created face or undefined if no face was created.
polyOp.autoSmooth
Performs an auto smooth of the poly. The face smoothing threshold angle is a property (autoSmoothThreshold) of the editable poly.
polyOp.flipNormals
Flips the normal of the specified faces.
polyOp.retriangulate
Retriangulates the specified faces.
polyOp.setDiagonal
Sets a diagonal of the face between the two vertices. The face must have a degree greater than 3 and the two vertices must not be connected by an edge.
polyOp.forceSubdivision
Forces an update of the surface subdivision at the next viewport redraw. Use when NURMS Subdivision is on and Update Options is Manually.
polyOp.meshSmoothByVert
Smooths the faces associated with the specified vertices. Uses the smoothness, separateBySmoothing, and separateByMaterial properties of the editable poly.
polyOp.meshSmoothByFace
Smooths the specified faces. Uses the smoothness, separateBySmoothing, and separateByMaterial properties of the editable poly.
polyOp.meshSmoothByEdge
Smooths the faces associated with the specified edges. Uses the smoothness, separateBySmoothing, and separateByMaterial properties of the editable poly.
polyOp.setFaceSmoothGroup
Sets
the smoothing groups for the specified faces. The state of each bit
in
polyOp.getFaceSmoothGroup
Returns the smoothing group data for the specified face as an integer. The state of each bit in the result specifies whether the face belongs to the corresponding smoothing group.
polyOp.breakVerts
For
each vertex in
polyOp.divideEdge
Divides the specified edge at the specified fractional distance along the edge. The return value is the index of the new vertex or undefined if no vertex was created.
polyOp.divideFace
Divides the specified
face, with the new vertex being created at the closest point on the
face to the specified position. If the specified position is
outside the face, the vertex will be created at the center of the
face. If
polyOp.splitEdges
Splits the specified edges at their middle.
polyOp.collapseVerts
Collapses each cluster of vertices in the specificed vertices to a single vertex. A vertex cluster is a set of vertices that are directly connected to one another.
polyOp.collapseFaces
Collapses the vertices associated with each cluster of faces in the specificed faces to a single vertex. A face cluster is a set of faces that are directly connected to one another.
polyOp.collapseEdges
Collapses the vertices associated with each cluster of edges in the specificed edges to a single vertex. An edge cluster is a set of edges that are directly connected to one another.
polyOp.propagateFlags
<>
poly>
where toSOLevel/fromSOLevel = {#object | #vertex | #edge | #face}
Propogates component
flags. For each
If
polyOp.tessellateByVert
Tessellates the faces used by the specified vertices. Uses the tesselateBy and tessTension properties of the editable poly.
polyOp.tessellateByFace
Tessellates the specified faces. Uses the tesselateBy and tessTension properties of the editable poly.
polyOp.tessellateByEdge
Tessellates the faces used by the specified edges. Uses the tesselateBy and tessTension properties of the editable poly.
polyOp.detachFaces
delete:
name:
Detaches the specified
faces. If
--The following script explodes an EditablePoly object to elements,
--each polygon becomes one element
macroScript PolyToElements category:"Help_Examples"
(
on isEnabled return
selection.count == 1 and classof selection[1].baseobject == Editable_Poly
?
on execute do
(
obj = selection[1]
for p = polyop.getNumFaces obj to 1 by -1 do
polyOp.detachFaces obj #{p}
)
)
polyOp.detachEdges
asNode:
Detaches the faces used by
the specified edges. If
polyOp.detachVerts
asNode:
Detaches the faces used by
the specified vertices. If
polyOp.resetSlicePlane
Resets the slice plane.
polyOp.getSlicePlane
Returns the location and
direction of the slice plane as a Ray value. If
polyOp.setSlicePlane
node:
Sets
the slice plane to the location and direction as specified
by
polyOp.slice
node:
Slices the poly based on
the plane and direction as specified by
polyOp.inSlicePlaneMode
Returns true if the editable poly is in slice mode, false otherwise.
polyOp.cutVert
If
Returns the index of the new vertex if created, or undefined if no vertex was created.
polyOp.cutFace
If
Returns the index of the new vertex if created, or undefined if no vertex was created.
polyOp.cutEdge
If
Returns the index of the new vertex if created, or undefined if no vertex was created.
polyOp.capHolesByVert
Finds any borders that use one or more of the specified vertices, and builds faces to cap the holes. Returns true if one or more holes were capped.
polyOp.capHolesByFace
Finds any borders that use one or more of the vertices associated with the specified faces, and builds faces to cap the holes. Returns true if one or more holes were capped.
polyOp.capHolesByEdge
Finds any borders that use one or more of the vertices associated with the specified edges, and builds faces to cap the holes. Returns true if one or more holes were capped.
polyOp.makeVertsPlanar
Moves the specified vertices so that they are planar.
polyOp.moveVertsToPlane
node:
Moves the specified vertices into the specified plane. The target plane is defined as all points which, when DotProducted with N, return offset. All vertices are moved along the normal vector N.
polyOp.makeEdgesPlanar
Moves the vertices associated with the specified edges so that they are planar.
polyOp.moveEdgesToPlane
node:
Moves the vertices associated with the specified edges 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.
polyOp.makeFacesPlanar
Moves the vertices associated with the specified faces so that they are planar.
polyOp.moveFacesToPlane
Moves the vertices associated with the specified faces 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.
polyOp.createShape
smooth:
Creates a shape node from
the specified edges. If
?
polyOp.extrudeFaces
Extrudes the specified faces by the specified amount. Uses the extrustionType property of the Editable Poly.
polyOp.bevelFaces
Bevels the specified
faces. Extrudes the specified faces the specified height, and then
scales the new top faces by
polyOp.chamferVerts
Chamfers the specified vertices by the specified amount.
polyOp.chamferEdges
Chamfers the specified edges by the specified amount.
Editable_Poly Topics: