[Closed] Scaling Vertices
Does anyone know how I can scale the selected vertices in an edit mesh?
I’ve tried a number of things but just about the only thing I’ve managed to do on the vertex level is move the vertices.
s = $.selectedVerts
move s [2,2,2]
Surprise! Both scaling and rotation at sub-object level are actually translations of vertices!
Knowing the center of scaling (assuming you know it), for each vertex you take the current vertex position, subtract the center position and multiply the resulting vector by the scale factor. The resulting vector can then be added to the center again and will represent the point in space your vertex would end up after the scaling. Alternatively, you could build a scaling matrix with position at the center and transform each vertex by it.
(
theMesh = sphere pos:[10,20,30] radius:50 segs:32 --create a sphere
convertToMesh theMesh --collapse
setVertSelection theMesh #{1..97} --select some vertices on top
theCoordCenter = [40,50,60] --this will be the ref. coordinate center
theVerts = getVertSelection theMesh --get the SO selection
for v in theVerts do --for each vertex
(
theVert = getVert theMesh v --get the vertex position in world space
theVector = (theVert - theCoordCenter)*[2.0,2.0,2.0] --scale the vector 2x rel. to center
setVert theMesh v (theCoordCenter + theVector) --assign back the scaled vertex
)
update theMesh --refresh
)
Here is the matrix method:
(
theMesh = sphere pos:[10,20,30] radius:50 segs:32 --create a sphere
convertToMesh theMesh --collapse
setVertSelection theMesh #{1..97} --select some vertices on top
theCoordCenter = Point pos:[40,50,60] --create a ref.coordsys
theVerts = getVertSelection theMesh --get the SO selection
theScaleMatrix = scaleMatrix [2.0,2.0,2.0] --define the scaling as 2x along X, Y and Z
theCoordSysMatrix = theCoordCenter.transform --get the coordsys trnasformation
for v in theVerts do --for each vertex
(
theVert = getVert theMesh v --get the vertex position in world space
theVert *= (inverse theCoordSysMatrix) --convert into new coordinate space
theVert *= theScaleMatrix --scale in that space relatively to the Point01
theVert *= theCoordSysMatrix --convert out of coord. space into world space
setVert theMesh v theVert --set the vertex to the new scaled position
)
update theMesh --refresh
)
You can use non-uniform scaling factors like [2.0,3.0,4.0] to scale differently along each axis.
just whipped this up then:
fn scaleVertsEMesh obj amount =
(
verts = (getVertSelection obj) as array
cnt = verts.count
if verts.count > 1 then
(
mid = [0,0,0]
for v in verts do mid += getVert obj v
mid /= cnt
vectors = for v in verts collect ( normalize ((getVert obj v) - mid) )
for v = 1 to cnt do
(
newPos = (getVert obj verts[v]) + (vectors[v] * amount)
setVert obj verts[v] newPos
)
update obj
)
)
scaleVertsEMesh $Box01 [2,0,0]
There could be more error checking but it should give you an idea.
Cool, they worked. Gravey’s sort of inflated the object. Bobo’s scaled as max normally does.
Is there any way to do these scale operations in the Edit Mesh modifier and keep the stack? Right now they only work if you collapse. The setVert method complains and the help file even collapses the stack in their example.
SnapshotAsMesh didn’t seem to help much either.
Nor $.mesh
The Edit Mesh is not scriptable at all.
You can, of course, add an XForm modifier to the SO selection anywhere on the stack (using modPanel.addModToSelection()) and scale its gizmo…
for v in theVerts do --for each vertex
(
theVert = getVert theMesh v --get the vertex position in world space
theVert *= (inverse theCoordSysMatrix) --convert into new coordinate space
theVert *= theScaleMatrix --scale in that space relatively to the Point01
theVert *= theCoordSysMatrix --convert out of coord. space into world space
setVert theMesh v theVert --set the vertex to the new scaled position
)
Can you multiply these matrices together, and then apply the result to the vertex?
Of course, you can do that, and it will speed up calculations a lot because the matrix multiplications can be taken out of the loop and only the vertex scaling would happen inside:
(
theMesh = sphere pos:[10,20,30] radius:50 segs:32 --create a sphere
convertToMesh theMesh --collapse
setVertSelection theMesh #{1..97} --select some vertices on top
theCoordCenter = Point pos:[40,50,60] --create a ref.coordsys
theVerts = getVertSelection theMesh --get the SO selection
--Now build a matrix to scale every vertex 2x:
theTM = (inverse theCoordCenter.transform) * (scaleMatrix [2.0,2.0,2.0]) * theCoordCenter.transform
for v in theVerts do --for each vertex, scale by the matrix and set the vertex
setVert theMesh v ((getVert theMesh v)*theTM)
redrawViews()
)
The main reason for my initial code was to have more room for comments so people would understand WHY they have to multiply the value by 3 matrices. You must admit it was easier to read…
The update() call was actually not necessary as we are not changing topology.
RedrawViews() takes care of refreshing the viewports to show the scaled vertices.
Sure … I partly asked the question because I can never remember the order you do the multiplications in.