Cook meshes with primitive restart indices

This commit is contained in:
Jack Andersen 2018-05-05 10:55:59 -10:00
parent aa84d7c725
commit fda615f47e
2 changed files with 27 additions and 24 deletions

View File

@ -1,6 +1,20 @@
import bpy, bmesh, operator, struct import bpy, bmesh, operator, struct
from mathutils import Vector from mathutils import Vector
# Function to quantize normals to 15-bit precision
def quant_norm(n):
nf = n.copy()
for i in range(3):
nf[i] = int(nf[i] * 16384) / 16384.0
return nf.freeze()
# Function to quantize lightmap UVs to 15-bit precision
def quant_luv(n):
uf = n.copy()
for i in range(2):
uf[i] = int(uf[i] * 32768) / 32768.0
return uf.freeze()
# Class for building unique sets of vertex attributes for VBO generation # Class for building unique sets of vertex attributes for VBO generation
class VertPool: class VertPool:
@ -45,7 +59,7 @@ class VertPool:
if pf not in self.pos: if pf not in self.pos:
self.pos[pf] = len(self.pos) self.pos[pf] = len(self.pos)
if not rna_loops: if not rna_loops:
nf = v.normal.copy().freeze() nf = quant_norm(v.normal)
if nf not in self.norm: if nf not in self.norm:
self.norm[nf] = len(self.norm) self.norm[nf] = len(self.norm)
if dlay: if dlay:
@ -59,7 +73,7 @@ class VertPool:
material_slots[f.material_index].material['retro_lightmapped'] material_slots[f.material_index].material['retro_lightmapped']
for l in f.loops: for l in f.loops:
if rna_loops: if rna_loops:
nf = rna_loops[l.index].normal.copy().freeze() nf = quant_norm(rna_loops[l.index].normal)
if nf not in self.norm: if nf not in self.norm:
self.norm[nf] = len(self.norm) self.norm[nf] = len(self.norm)
for cl in range(len(clays)): for cl in range(len(clays)):
@ -69,7 +83,7 @@ class VertPool:
start_uvlay = 0 start_uvlay = 0
if use_luv and lightmapped: if use_luv and lightmapped:
start_uvlay = 1 start_uvlay = 1
uf = l[luvlay].uv.copy().freeze() uf = quant_luv(l[luvlay].uv)
if uf not in self.luv: if uf not in self.luv:
self.luv[uf] = len(self.luv) self.luv[uf] = len(self.luv)
for ul in range(start_uvlay, len(ulays)): for ul in range(start_uvlay, len(ulays)):
@ -128,9 +142,9 @@ class VertPool:
def get_norm_idx(self, loop): def get_norm_idx(self, loop):
if self.rna_loops: if self.rna_loops:
nf = self.rna_loops[loop.index].normal.copy().freeze() nf = quant_norm(self.rna_loops[loop.index].normal)
else: else:
nf = loop.vert.normal.copy().freeze() nf = quant_norm(loop.vert.normal)
return self.norm[nf] return self.norm[nf]
def get_skin_idx(self, vert): def get_skin_idx(self, vert):
@ -146,7 +160,7 @@ class VertPool:
def get_uv_idx(self, loop, uidx): def get_uv_idx(self, loop, uidx):
if self.luvlay is not None and uidx == 0: if self.luvlay is not None and uidx == 0:
if self.material_slots[loop.face.material_index].material['retro_lightmapped']: if self.material_slots[loop.face.material_index].material['retro_lightmapped']:
uf = loop[self.luvlay].uv.copy().freeze() uf = quant_luv(loop[self.luvlay].uv)
return self.luv[uf] return self.luv[uf]
uf = loop[self.ulays[uidx]].uv.copy().freeze() uf = loop[self.ulays[uidx]].uv.copy().freeze()
return self.uv[uf] return self.uv[uf]
@ -309,36 +323,26 @@ def write_out_surface(writebuf, output_mode, vert_pool, island_faces, mat_idx):
elif output_mode == 'TRISTRIPS': elif output_mode == 'TRISTRIPS':
prev_loop_emit = None prev_loop_emit = None
out_count = 0
while len(island_faces): while len(island_faces):
sel_lists_local = [] sel_lists_local = []
restore_out_count = out_count
for start_face in island_faces: for start_face in island_faces:
for l in start_face.loops: for l in start_face.loops:
out_count = restore_out_count
island_local = list(island_faces) island_local = list(island_faces)
if out_count & 1: prev_loop = l.link_loop_next
prev_loop = l.link_loop_prev loop = prev_loop.link_loop_next
loop = prev_loop.link_loop_prev sel_list = [l, prev_loop, loop]
sel_list = [l, prev_loop, loop]
prev_loop = loop
else:
prev_loop = l.link_loop_next
loop = prev_loop.link_loop_next
sel_list = [l, prev_loop, loop]
out_count += 3
island_local.remove(start_face) island_local.remove(start_face)
while True: while True:
if not prev_loop.edge.is_contiguous or prev_loop.edge.tag: if not prev_loop.edge.is_contiguous or prev_loop.edge.tag:
break break
loop, prev_loop = strip_next_loop(prev_loop, out_count) loop, prev_loop = strip_next_loop(prev_loop, len(sel_list))
face = loop.face face = loop.face
if face not in island_local: if face not in island_local:
break break
sel_list.append(loop) sel_list.append(loop)
island_local.remove(face) island_local.remove(face)
out_count += 1 sel_lists_local.append((sel_list, island_local))
sel_lists_local.append((sel_list, island_local, out_count))
max_count = 0 max_count = 0
max_sl = None max_sl = None
max_island_faces = None max_island_faces = None
@ -347,7 +351,6 @@ def write_out_surface(writebuf, output_mode, vert_pool, island_faces, mat_idx):
max_count = len(sl[0]) max_count = len(sl[0])
max_sl = sl[0] max_sl = sl[0]
max_island_faces = sl[1] max_island_faces = sl[1]
out_count = sl[2]
island_faces = max_island_faces island_faces = max_island_faces
if prev_loop_emit: if prev_loop_emit:
vert_pool.null_loop_out(writebuf) vert_pool.null_loop_out(writebuf)

2
hecl/extern/boo vendored

@ -1 +1 @@
Subproject commit 088cddfea765a47751e318e2ced31b678b1d406d Subproject commit 9031ace975330324e204cc9fb54d89daa768d7db