Anyone know if there is a way to re-order a model's vertices in 3ds Max 2015 (or any version, really) so they are numbered in order from bottom to top on the up axis?
I am making foliage for iOS/Unity, and alpha blend is required (PVR GPU renders alpha test much slower than alpha blend). But the transparency sorting is terrible.
Good thing is, my foliage is being used in an iso 3d game, so it's mostly viewed from above. If I order my vertices from bottom to top, I get reasonably good sorting. Bad thing is, 3ds Max keeps messing with my vertex order. I can detach and re-attach, but detaching kills my custom vertex normals.
Is there any tool that will help me re-order the verts along a particular axis (up axis would be great)?
                    
                 
            
Replies
It's pretty straight forward, import, go to edit mode, press space bar to search a fonction, type "sort mesh elements" and there you can sort vertices or faces (depending on your selection) along x/y/z/view/camera, etc...
Then, in object mode again, you could for instance add a Normal Edit modifier and set it to radial or directionnal to quickly re-customize your normals.
Export fbx and it's done.
Great info man!
Obj in the other hand does break vertex color.
Be careful with fbx though, it has to be exported in binary mode from your app. Blender cannot open ascii fbx yet.
New verts will append either at the bottom or top of the index. In Maya it's the bottom. Always meant to try that function in Blender, looks handy. Just for funsies, you can also get hardcore picky and use retop tools to manually work in the order you need. (not recommended, but you can get nice blends between interpenetrating faces if you have the time. or even for two quads that look like a plus sign from the top)
I'm 99% sure that Blender maintains vert index with obj, check your in/out options; I know many who use it for doing morphs alongside other apps.
woah ninja edit: I missed the part where you mentioned detaching.
no one tells me anything! this sounds neat. ( that reordering vrts along an axis may facilitate accurate sorting behavior )
Could u clear up confusion on my part?
Is the height in "up" independent of the faces the vrt is a member of?
Is the vrt order done face by face or a whole object?
If a whole object...
Does it matter if vrts are coincidental?
Can this be done in Maya?
Order is whole object. There is another set of vertices which have a different material assignment with no transparency (tree trunk) but I could strip those out beforehand.
Some of the vertices are duplicated in the same location, but that was only because I was detaching and reattaching clumps of triangles and not welding them afterwards. Those could be welded if needed.
Maya is fine! This could be a very handy tool for people. Especially if alpha testing is deprecated over time, for alpha blending. But it's certainly useful now given how iOS gpu works.
Wouldn't those vrts that couldn't be differentiated by height affect sorting benefit then?
Maybe examine all the vertices connected to the same triangle, and reorder the coincident vertices based on the middles of the triangles?
( fn compareInt i1 i2 values: = values[i1] - values[i2]; fn comparePoint3_Z i1 i2 values: = ( v1 = values[i1]; v2 = values[i2]; if v1.z > v2.z then 1 else if v1.z < v2.z then -1 else 0; ) -- sorts mesh verts along the z axis of sorttm fn sortMeshVerts mObj sorttm = ( sorttm.translation = [0,0,0]; -- zero out the tranlation local isorttm = (inverse sorttm); -- collect the vert positions local verts = for v = 1 to mObj.numverts collect getvert mObj v * isorttm; local indices = #{1..mObj.numverts} as array; local vertorder = #{1..mObj.numverts} as array; -- sort the new indices qsort vertorder comparePoint3_Z values:verts; qsort indices compareInt values:vertorder; -- "reverse" sort to get the new indexing -- sort the actual verts restore them verts = for v = 1 to verts.count collect verts[vertorder[v]] *= sorttm; meshop.setvert mObj #all verts; -- change the verts and face indexing for f = 1 to mObj.numfaces do -- set the faces to new order ( face = getface mObj f; setface mObj f [indices[face.x],indices[face.y],indices[face.z]] ) mObj; -- return the sorted object ) sortedObj = SortMeshVerts (copy $) $Point01.transform; )edited for slicker method that protects custom normalanother performance edit one too many sorts !
last edit move the clone out of the function
You made 2 lil mistakes tho Also Point01 isn't defined.
( fn randomPtOnCone theta = ( h = cos theta; phi = 360.0 * random 0.0 1.0; z = h + ( 1 - h ) * random 0.0 1.0; sinT = sqrt (1 - z * z); [sinT * cos phi, sinT * sin phi, z]; ) fn compareInt i1 i2 values: = values[i1] - values[i2]; fn comparePoint3_Z i1 i2 values: = ( v1 = values[i1]; v2 = values[i2]; if v1.z > v2.z then 1 else if v1.z < v2.z then -1 else 0; ) -- sorts mesh verts along the z axis of sorttm fn sortMeshVerts mObj sorttm = ( sorttm.translation = [0,0,0]; -- zero out the tranlation local isorttm = inverse sorttm; -- collect the vert positions local verts = for v = 1 to mObj.numverts collect getvert mObj v * isorttm; local indices = #{1..mObj.numverts} as array; local vertorder = #{1..mObj.numverts} as array; -- sort the new indices qsort vertorder comparePoint3_Z values:verts; qsort indices compareInt values:vertorder; -- "reverse" sort to get the new indexing -- sort the actual verts restore them verts = for v = 1 to verts.count collect verts[vertorder[v]] *= sorttm; -- change the verts and face indexing meshop.setvert mObj #all verts; for f = 1 to mObj.numfaces do -- set the faces to new order ( face = getface mObj f; setface mObj f [indices[face.x],indices[face.y],indices[face.z]] ) mObj; -- return the sorted object ) delete objects; sph = Sphere radius:25.0 smooth:on segs:32; convertToMesh sph; sph.selectedverts = #{1}; pnt = point dir:((randomPtOnCone 180) * (matrixfromNormal [0,0,1])) axistripod:on cross:on size:60 wirecolor:(color 198 224 87); t = timestamp(); sortedObj = sortMeshVerts (copy sph) pnt.transform; format "%\n" (timestamp() - t); select sortedObj; max modify mode; subobjectLevel = 1; )-- Error occurred in anonymous codeblock; filename: ; position: 1464; line: 42
-- Frame:
-- comparePoint3_Z: comparePoint3_Z()
-- sortedObj: undefined
-- compareInt: compareInt()
-- sortMeshVerts: sortMeshVerts()
-- Unknown property: "transform" in undefined
And the highlight is here:
sortedObj = SortMeshVerts (copy $) $Point01.transform;
you could replace it with
to give a vertical sort
macroScript SortVertsZ category: "polycount" buttontext: "SortVertsZ" Icon: #("TrackBar",2) tooltip: "SortVertsZ" ( fn compareInt i1 i2 values: = values[i1] - values[i2]; fn comparePoint3_Z i1 i2 values: = ( v1 = values[i1]; v2 = values[i2]; if v1.z > v2.z then 1 else if v1.z < v2.z then -1 else 0; ) -- sorts mesh verts along the z axis of sorttm fn sortMeshVerts mObj sorttm = ( sorttm.translation = [0,0,0]; -- zero out the tranlation local isorttm = inverse sorttm; -- collect the vert positions local verts = for v = 1 to mObj.numverts collect getvert mObj v * isorttm; local indices = #{1..mObj.numverts} as array; local vertorder = #{1..mObj.numverts} as array; -- sort the new indices qsort vertorder comparePoint3_Z values:verts; qsort indices compareInt values:vertorder; -- "reverse" sort to get the new indexing -- sort the actual verts restore them verts = for v = 1 to verts.count collect verts[vertorder[v]] *= sorttm; -- change the verts and face indexing meshop.setvert mObj #all verts; for f = 1 to mObj.numfaces do -- set the faces to new order ( face = getface mObj f; setface mObj f [indices[face.x],indices[face.y],indices[face.z]] ) mObj; ) on execute do ( for i in selection where canConvertTo i Editable_mesh do ( sortObj = copy i; if convertToMesh sortObj != undefined then sortMeshVerts sortObj (MatrixFromNormal [0,0,1]); ) ) )I tried several tweaks to the script but nothing seemed to work properly, they always sorted from top to bottom, instead of bottom to top.
I just don't have the scripting chops to handle this properly
this line tells if it works upwards or downwards
this one should work the other way. (not tested)