self.weight = 0.0
+class Batch:
+ def __init__(self, pt):
+ self.primitive_type = pt
+ self.patch_size = 0
+ self.vertices = []
+
+
class Face:
def __init__(self, face):
self.index = face.index
self.use_uv = mesh.use_uv
self.tangent_uvtex = mesh.tangent_uvtex
self.use_strips = mesh.use_strips
+ self.use_patches = mesh.use_patches
+ self.use_lines = mesh.use_lines
self.vertex_groups = mesh.vertex_groups
# Clone basic data
# where they don't exist
edge_map = {e.key: e for e in self.edges}
for f in self.faces:
- if len(f.vertices)>4:
+ if len(f.vertices)>4 and not mesh.use.patches:
raise ValueError("Unsupported face on mesh {}: N-gon".format(self.name))
f.vertices = [self.vertices[i] for i in f.vertices]
v.edges.append(e)
# Store loose edges as lines
- if mesh.use_lines:
+ if mesh.use_lines and not mesh.use_patches:
self.lines = [Line(e) for e in self.edges if not e.faces]
else:
self.lines = []
if normal_prop and normal_prop.texture:
self.tangent_vecs = True
- self.vertex_sequence = []
+ self.batches = []
def transform(self, matrix):
for v in self.vertices:
self.lines += other.lines
def prepare_triangles(self, task):
+ if self.use_patches:
+ return
+
face_count = len(self.faces)
for i in range(face_count):
f = self.faces[i]
task.set_progress(i/len(self.vertices))
def prepare_sequence(self, task):
- subtask = task.task("Reordering faces", 0.5)
- self.reorder_faces(subtask)
+ if self.use_patches:
+ subtask = task.task("Reordering patches", 0.5)
+ self.reorder_patches(subtask)
+
+ subtask = task.task("Building sequence", 1.0)
+ self.build_patch_sequence(subtask)
+ else:
+ subtask = task.task("Reordering faces", 0.5)
+ self.reorder_faces(subtask)
+
+ subtask = task.task("Building sequence", 1.0)
+ if self.use_strips:
+ self.build_tristrip_sequence(subtask)
+ else:
+ self.build_triangle_sequence(subtask)
+
+ if self.use_lines:
+ self.build_line_sequence()
- subtask = task.task("Building sequence", 1.0)
+ self.reorder_vertices()
+
+ def build_tristrip_sequence(self, task):
sequence = None
for i, f in enumerate(self.faces):
if sequence:
sequence += to_add
if not sequence:
- sequence = f.vertices[:]
- self.vertex_sequence.append(sequence)
+ self.batches.append(Batch("TRIANGLE_STRIP"))
+ sequence = self.batches[-1].vertices
+ sequence += f.vertices
- subtask.set_progress(i/len(self.faces))
+ task.set_progress(i/len(self.faces))
- self.reorder_vertices()
+ def build_triangle_sequence(self, task):
+ batch = Batch("TRIANGLES")
+ for f in self.faces:
+ batch.vertices += f.vertices
+ self.batches.append(batch)
+
+ def build_line_sequence(self):
+ batch = Batch("LINES")
+ for l in self.lines:
+ batch.vertices += l.vertices
+ self.batches.append(batch)
+
+ def build_patch_sequence(self, task):
+ current_size = 0
+ sequence = None
+ for f in self.faces:
+ if len(f.vertices)!=current_size:
+ current_size = len(f.vertices)
+ self.batches.append(Batch("PATCHES"))
+ self.batches[-1].patch_size = current_size
+ sequence = self.batches[-1].vertices
+
+ sequence += f.vertices
def reorder_faces(self, task):
# Tom Forsyth's vertex cache optimization algorithm
for i, f in enumerate(self.faces):
f.index = i
+ def reorder_patches(self, task):
+ for f in self.faces:
+ f.flag = False
+
+ reordered_faces = []
+ n_processed = 0
+
+ while 1:
+ current_size = 0
+
+ for f in self.faces:
+ if f.flag:
+ continue
+
+ if not current_size:
+ current_size = len(f.vertices)
+ elif len(f.vertices)!=current_size:
+ continue
+
+ reordered_faces.append(f)
+ f.flag = True
+
+ n_processed += 1
+ task.set_progress(n_processed/len(self.faces))
+
+ if not current_size:
+ break
+
def reorder_vertices(self):
for v in self.vertices:
v.index = -1
reordered_vertices = []
- for s in self.vertex_sequence:
- for v in s:
+ for b in self.batches:
+ for v in b.vertices:
if v.index<0:
v.index = len(reordered_vertices)
reordered_vertices.append(v)