[Closed] Mesh Transform
I see a lot of people use this founction to move vertexes in trimesh:
fn TransformMesh TheMesh TheTM =
(
for i=1 to TheMesh.numverts do
(
setvert TheMesh i ((getvert TheMesh i)*TheTM)
)
TheMesh
)
I think Standard transform functions(Move,Rotate,Scale) are much faster than this functuion. This is my compare example:
plugin SimpleObject TestObjects
name:"Door"
classID:#(145345,543411)
category:"TestObjects"
(
parameters main rollout:params
(
Length type:#worldUnits ui:Length default:0
Width type:#worldUnits ui:Width default:0
Height type:#worldUnits ui:Height default:0
Thickness type:#worldUnits ui:Thickness default:1.6
DoorsOpen type:#float ui:DoorsOpen default:0
)
rollout params "Parameters"
(
spinner Length "Length" type:#worldunits range:[0,1e9,0]
spinner Width "Width" type:#worldunits range:[0,1e9,0]
spinner Height "Height" type:#worldunits range:[0,1e9,0]
spinner Thickness "Thickness" type:#worldunits range:[0,1e9,0]
spinner DoorsOpen "Open" type:#float range:[0,180,0]
)
fn TransformMesh TheMesh TheTM =
(
for i=1 to TheMesh.numverts do
(
setvert TheMesh i ((getvert TheMesh i)*TheTM)
)
TheMesh
)
fn BuildMesh =
(
AllMeshes = trimesh()
print "/////////////////////////////////////////"
TS = timestamp()
for i=1 to 1000 do
(
Obj = createInstance box Length:Thickness Width:(Width/2) Height:Height
Msh = Obj.mesh
PivotOffset = [Width/4,0,0]
Msh = move Msh PivotOffset
Msh = rotate Msh (eulerangles 0 0 -DoorsOpen)
Msh = move Msh ([Width/4,-Length*i/10,0]-PivotOffset)
meshop.attach AllMeshes Msh
)
format "Standard Transform => %
" ((timestamp()-TS)/1000.0)
TS = timestamp()
for i=1 to 1000 do
(
Obj = createInstance box Length:Thickness Width:(Width/2) Height:Height
Msh = Obj.mesh
PivotOffset = [Width/4,0,0]
TheTM = matrix3 1
TheTM.row4 = PivotOffset
TheTM*= rotatezmatrix (-DoorsOpen)
translate TheTM ([Width/4,-Length*-i/10,0]+(-1*PivotOffset))
TransformMesh Msh TheTM
meshop.attach AllMeshes Msh
)
format "Vertex Transform => %
" ((timestamp()-TS)/1000.0)
print "/////////////////////////////////////////"
setmesh mesh AllMeshes
free Msh
free AllMeshes
)
on buildMesh do
(
BuildMesh()
)
tool create
(
on mousePoint click do
(
case click of
(
1: nodeTM.translation = gridPoint
3: #stop
)
)
on mouseMove click do
(
case click of
(
2: (Width = abs gridDist.x; Length = abs gridDist.y)
3: Height = abs gridDist.z
)
)
)
)
Have you tried what the results are if you put the “Vertex Transform” routine before the “Standard Transform” routine?
Sorry!, my example was not true, just remove or comment a section (reset the max), then test it again:
plugin SimpleObject TestObjects
name:"Door"
classID:#(145345,543411)
category:"TestObjects"
(
parameters main rollout:params
(
Length type:#worldUnits ui:Length default:0
Width type:#worldUnits ui:Width default:0
Height type:#worldUnits ui:Height default:0
Thickness type:#worldUnits ui:Thickness default:1.6
DoorsOpen type:#float ui:DoorsOpen default:0
)
rollout params "Parameters"
(
spinner Length "Length" type:#worldunits range:[0,1e9,0]
spinner Width "Width" type:#worldunits range:[0,1e9,0]
spinner Height "Height" type:#worldunits range:[0,1e9,0]
spinner Thickness "Thickness" type:#worldunits range:[0,1e9,0]
spinner DoorsOpen "Open" type:#float range:[0,180,0]
)
fn TransformMesh TheMesh TheTM =
(
for i=1 to TheMesh.numverts do
(
setvert TheMesh i ((getvert TheMesh i)*TheTM)
)
TheMesh
)
fn BuildMesh_TM =
(
AllMeshes = trimesh()
TS = timestamp()
for i=1 to 2000 do
(
Obj = createInstance box Length:Thickness Width:(Width/2) Height:Height
Msh = Obj.mesh
PivotOffset = [Width/4,0,0]
TheTM = matrix3 1
TheTM.row4 = PivotOffset
TheTM*= rotatezmatrix (-DoorsOpen)
translate TheTM ([Width/4,-Length*-i/10,0]+(-1*PivotOffset))
TransformMesh Msh TheTM
meshop.attach AllMeshes Msh
)
format "Vertex Transform => %
" ((timestamp()-TS)/1000.0)
setmesh mesh AllMeshes
free Msh
free AllMeshes
)
fn BuildMesh_Standard =
(
AllMeshes = trimesh()
TS = timestamp()
for i=1 to 2000 do
(
Obj = createInstance box Length:Thickness Width:(Width/2) Height:Height
Msh = Obj.mesh
PivotOffset = [Width/4,0,0]
Msh = move Msh PivotOffset
Msh = rotate Msh (eulerangles 0 0 -DoorsOpen)
Msh = move Msh ([Width/4,-Length*i/10,0]-PivotOffset)
meshop.attach AllMeshes Msh
)
format "Standard Transform => %
" ((timestamp()-TS)/1000.0)
setmesh mesh AllMeshes
free Msh
free AllMeshes
)
on buildMesh do
(
BuildMesh_TM()
-- BuildMesh_Standard()
)
tool create
(
on mousePoint click do
(
case click of
(
1: nodeTM.translation = gridPoint
3: #stop
)
)
on mouseMove click do
(
case click of
(
2: (Width = abs gridDist.x; Length = abs gridDist.y)
3: Height = abs gridDist.z
)
)
)
)
Result for me:
Standard Transform => 0.766
Vertex Transform => 0.953
Now I can say it’s a little faster
first of all it would be faster to calculate destination positions and apply all them as an array
meshop.setVert <Mesh mesh> <vertlist> {<point3 pos> | <point3 pos_array>}
the second is that meshop.attach is a slow function, and if you want to test a ‘transform’ performance don’t combine it with attach
You might need to put gc light:on at the end of the rutine to free the memory.
Sometimes it can be faster to do build the mesh yourself:
plugin SimpleObject TestObjects
name:"Door"
classID:#(145345,543411)
category:"TestObjects"
(
parameters main rollout:params
(
Length type:#worldUnits ui:Length default:0
Width type:#worldUnits ui:Width default:0
Height type:#worldUnits ui:Height default:0
Thickness type:#worldUnits ui:Thickness default:1.6
DoorsOpen type:#float ui:DoorsOpen default:0
ammount type:#integer ui:sp_amount default:2000
)
rollout params "Parameters"
(
spinner Length "Length" type:#worldunits range:[0,1e9,0]
spinner Width "Width" type:#worldunits range:[0,1e9,0]
spinner Height "Height" type:#worldunits range:[0,1e9,0]
spinner Thickness "Thickness" type:#worldunits range:[0,1e9,0]
spinner DoorsOpen "Open" type:#float range:[0,180,0]
spinner sp_amount "Ammount:" type:#integer range:[1,10000,1]
)
on buildMesh do
(
st = timestamp(); sh = heapfree
verts = #()
faces = #()
masterVerts = #([0,0,0],[1,0,0],[0,1,0],[1,1,0],[0,0,1],[1,0,1],[0,1,1],[1,1,1])
matIDs = #()
tm = matrix3 1
prerotatez tm -doorsopen
prescale tm [width/2.0, thickness, height]
for j = 1 to masterVerts.count do masterVerts[j] *= tm
for j = 1 to ammount*8 by 8 do
(
offset = [0, -length*(j/8)/10.0, 0]
for i = 1 to 8 do append verts (masterVerts[i]+offset)
append faces [j , j+2 , j+3]
append faces [j+3 , j+1 , j ]
append faces [j+4 , j+5 , j+7]
append faces [j+7 , j+6 , j+4]
append faces [j , j+1 , j+5]
append faces [j+5 , j+4 , j ]
append faces [j+1 , j+3 , j+7]
append faces [j+7 , j+5 , j+1]
append faces [j+3 , j+2 , j+6]
append faces [j+6 , j+7 , j+3]
append faces [j+2 , j , j+4]
append faces [j+4 , j+6 , j+2]
join matIDs #(2,2,1,1,5,5,4,4,6,6,3,3)
)
setmesh mesh vertices:verts faces:faces materialIDs:matIDs
for j = 1 to mesh.numfaces do
(
setEdgeVis mesh j 3 false
setFaceSmoothGroup mesh j 0
)
free verts
free faces
free matIDs
gc light:on
format "time:% ram:%
" (timestamp()-st) (sh-heapfree)
)
tool create
(
on mousePoint click do
(
case click of
(
1: nodeTM.translation = gridPoint
3: #stop
)
)
on mouseMove click do
(
case click of
(
2: (Width = abs gridDist.x; Length = abs gridDist.y)
3: Height = abs gridDist.z
)
)
)
)
And it can still be optimized.
it’s faster to make one set of identical faces and clone this time ‘amount’ times.
You mean using meshop.cloneFaces() ? I don’t think so. You still would need to move the vertices.
the bottleneck is not a transforming but an attaching. the attaching would be much faster with using ‘fast’ attach method showed many times on this forum.
it’s an example of my tool works. it paints, resizes, transforms thousands of objects in real-time update
read the mxs help about meshop.attach … by specifying target or source node you can attach and transform at the same time.
meshop.attach uses AttachMesh MeshDelta method. as an option the relative transform can be specified. i don’t understand why this option is not exposed in mxs directly, but only used when you specify a source or target node
but as i said you can pass any ‘dummy’ node to the attach method to control attaching with a specified transform
delete objects
(
num = 16
m = (box()).mesh
n = mesh vertices:#() faces:#()
p = point()
tm = transmatrix [100,0,0]
for k=0 to num-1 do
(
p.transform = tm
meshop.attach n.mesh (copy m) targetnode:p
tm = prerotateZ tm (360.0/num)
)
update m
)
or using source (which is more correct):
delete objects
(
num = 16
m = (box()).mesh
n = mesh vertices:#() faces:#()
p = point()
tm = transmatrix [100,0,0]
for k=0 to num-1 do
(
p.transform = inverse tm
meshop.attach n.mesh (copy m) [B]sourcenode:p deletesourcenode:off[/B]
tm = prerotateZ tm (360.0/num)
)
update m
)