I'm trying to write a custom exporter for Blender in Python. However, I'm having some trouble figuring out how I could use Python's native sort implementation to sort my vertices in the way I need.
Basically, I need to export the vertices in such a way where they can form a grid like this, assuming that V is a double.
V V V V V
V V V V V
V V V V V
V V V V V
The "engine" that I'm writing automatically retrieves the X and Z value of the coordinate based on where it is in the vertex map shown above. The V represents the Y coordinate. So this 5 by 5 map of vertices would create a 4 by 4 faced mesh.
However, in Blender, vertices appear to be ordered individually for each face of a mesh, rather in a format like mine. So, in order to export it, I need to order the coordinates first by depth (Y coordinate in Blender) and then by width (X coordinate in Blender). It would have to behave like a SQL query, where the first paramter given takes precedence in order compared to the second.
Here is what my code currently looks like
#!BPY
"""
Name: 'VaV Export'
Blender: 269
Group: 'Export'
Tooltip: 'Export to VaV file format'
"""
import Blender
import bpy
class Coordinate:
def __init__(self, posX, posY):
self.posX = posX
self.posY = posY
def sortX(self, other):
if posX < other.posX:
return 1
def sortY(self, other):
if posY < other.posY:
return 1
def write(filename):
out = open(filename, "w")
terraindata = bpy.data.meshes["Terrain"]
vertices = terraindata.vertices
vertices = sorted(vertices, key = lambda x: x.co.y, reverse = True)
vertices = sorted(vertices, key = lambda x: x.co.x, reverse = False)
print(vertices)
Blender.Window.FileSelector(write, "Export")
The first call to sorted() successfully orders it according to depth (Y). However, The 2nd call to sorted messes up the order (as expected). How could I amend this to allow both sorts to occur without the 2nd messing up the first?
Thanks for your time in advance!
@moose, @Amyth, to reverse to only one attribute, you can sort twice: first by the secondary s = sorted(s, key = operator. itemgetter(2)) then by the primary s = sorted(s, key = operator. itemgetter(1), reverse=True) Not ideal, but works.
How do you sort multiple keys in Python? Use a lambda function with a tuple to sort with two keys Call sorted(iterable, key: NoneType=None) with a collection as iterable . For key , create a lambda function that takes an element as a parameter and returns a 2-tuple of mapped to values.
Use sorted() and a lambda expression to sort a list by two fields. Call sorted(a_list, key = k) with k as lambda x: x[i], x[j] to sort list by the i -th element and then by the j -th element.
Use the Python List sort() method to sort a list in place. The sort() method sorts the string elements in alphabetical order and sorts the numeric elements from smallest to largest. Use the sort(reverse=True) to reverse the default sort order.
Change
vertices = sorted(vertices, key = lambda x: x.co.y, reverse = True)
to
vertices = sorted(vertices, key = lambda x: (x.co.y, x.co.x), reverse = True)
...and that should do it.
If I understand correctly, you want to order your vertices by decreasing y
coordinate, with coordinates with equal y
values ordered by increasing x
coordinate. If that's right, you can return a tuple (-x.co.y, x.co.x)
from your key
function to sorted
and Python will do both the whole sorting at once.
An alternative would be to take a page from radix sort and sort by least-significant coordinate (e.g. x
) first, then by the more significant coordinate (y
). This will work since Python's sort
is stable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With