Skip to content

Commit

Permalink
Enable smooth groups for normals
Browse files Browse the repository at this point in the history
  • Loading branch information
1r3n33 committed Aug 3, 2020
1 parent 03b25ed commit a81f4a6
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 51 deletions.
38 changes: 27 additions & 11 deletions blend2niff/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def __init__(self):
self.vtx_color_groups = [] # All vertex color groups
self.tri_nv_groups = [] # All triangle normal groups
self.vtx_nv_groups = [] # All vertex normal groups
self.normal_indices_by_mesh = {} # vertex normal indices by Blender mesh
self.st_groups = [] # All vertex texture coord groups
self.tri_groups = [] # All triangle groups
self.tri_group_by_mesh = {} # NIFF2 triangle group by Blender mesh
Expand Down Expand Up @@ -215,8 +216,6 @@ def create_vector_groups(self, objs):
Also create default up normal.
Make sure to have the same number of tri_vector_groups & vtx_vector_groups.
This prevents nifftools/checknb2.exe from crashing.
Do not support smooth groups: 1 normal per vertex!
Indices are all aligned on both vertex coords and vertex normals.
"""
default_nv = [0.0, 1.0, 0.0] # up
default_tri_nv_group = niff2_tri_nv_group_builder(0, default_nv)
Expand All @@ -229,23 +228,36 @@ def create_vector_groups(self, objs):
for mesh in meshes:
mesh.calc_loop_triangles()
mesh.calc_normals_split()
vtx_normals = [float]*len(mesh.vertices)*3

# Collect unique normals in index_by_normal with undefined indices
index_by_normal = {}
for tri in mesh.loop_triangles:
for i in range(3):
vtx_index = tri.vertices[i]
loop_index = tri.loops[i]
normal = mesh.loops[loop_index].normal
vtx_normals[(vtx_index*3)+0] = normal[0]
vtx_normals[(vtx_index*3)+1] = normal[1]
vtx_normals[(vtx_index*3)+2] = normal[2]
normal = tuple(mesh.loops[loop_index].normal)
index_by_normal[normal] = -1

# Map keys to normals and set indices
normals = list(index_by_normal.keys())
for index, normal in zip(range(len(normals)), normals):
index_by_normal[normal] = index

# Create mesh normals indices
normal_indices = []
for tri in mesh.loop_triangles:
for i in range(3):
loop_index = tri.loops[i]
normal = tuple(mesh.loops[loop_index].normal)
normal_indices.append(index_by_normal[normal])
self.normal_indices_by_mesh[mesh] = normal_indices

# Create NIFF2 data
tri_nv_group = niff2_tri_nv_group_builder(
len(self.tri_nv_groups), default_nv)
self.tri_nv_groups.append(tri_nv_group)

vtx_nv_group = niff2_vtx_nv_group_builder(
len(self.vtx_nv_groups), vtx_normals)
len(self.vtx_nv_groups), [value for normal in normals for value in normal])
self.vtx_nv_groups.append(vtx_nv_group)

def create_st_groups(self):
Expand All @@ -269,9 +281,13 @@ def create_tri_groups(self, objs):
vtx_group = self.vtx_group_by_mesh[mesh]
vtx_indices = [
index for tri in mesh.loop_triangles for index in tri.vertices]
normal_indices = self.normal_indices_by_mesh[mesh]

tri_group = niff2_tri_group_builder(
len(self.tri_groups), tri_group_name.index(), vtx_group.index(), vtx_indices)
tri_group = niff2_tri_group_builder(len(self.tri_groups),
tri_group_name.index(),
vtx_group.index(),
vtx_indices,
normal_indices)

self.tri_groups.append(tri_group)
self.tri_group_by_mesh[mesh] = tri_group
Expand Down
29 changes: 19 additions & 10 deletions blend2niff/niff2/niff2_tri.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,11 @@ def niff2_tri_list_header_writer(tlh, tri_groups, buf):
# Tri Group
#
class Niff2TriGroup:
def __init__(self, index, name_index, vtx_group_index, vtx_indices):
def __init__(self, index, name_index, vtx_group_index, vtx_indices, normal_indices):
tris = []
for i in range(0, len(vtx_indices), 3):
tris.append(niff2_tri_node_builder(len(tris), vtx_indices[i:i+3]))
tris.append(niff2_tri_node_builder(
len(tris), vtx_indices[i:i+3], normal_indices[i:i+3]))

tri_size = sum(map(lambda tri: tri.tri_size, tris))

Expand All @@ -99,8 +100,16 @@ def index(self):
return self.this_tri_group_index


def niff2_tri_group_builder(tri_group_index, tri_group_name_index, vtx_group_index, vtx_indices):
return Niff2TriGroup(tri_group_index, tri_group_name_index, vtx_group_index, vtx_indices)
def niff2_tri_group_builder(tri_group_index,
tri_group_name_index,
vtx_group_index,
vtx_indices,
normal_indices):
return Niff2TriGroup(tri_group_index,
tri_group_name_index,
vtx_group_index,
vtx_indices,
normal_indices)


def niff2_tri_group_writer(tri_group, buf):
Expand Down Expand Up @@ -129,30 +138,30 @@ def niff2_tri_group_writer(tri_group, buf):
# Tri Node
#
class Niff2TriNode:
def __init__(self, index, vtx_indices):
def __init__(self, index, vtx_indices, normal_indices):
self.tri_tag = TAG_TRI
self.this_tri_index = index
self.tri_size = (19*4)
self.tri_nv_index = 0
self.tri_color_index = 0
self.vtx_index0 = vtx_indices[0]
self.st_index0 = 0
self.vtx_nv_index0 = vtx_indices[0]
self.vtx_nv_index0 = normal_indices[0]
self.vtx_color_index0 = vtx_indices[0]
self.vtx_index1 = vtx_indices[1]
self.st_index1 = 0
self.vtx_nv_index1 = vtx_indices[1]
self.vtx_nv_index1 = normal_indices[1]
self.vtx_color_index1 = vtx_indices[1]
self.vtx_index2 = vtx_indices[2]
self.st_index2 = 0
self.vtx_nv_index2 = vtx_indices[2]
self.vtx_nv_index2 = normal_indices[2]
self.vtx_color_index2 = vtx_indices[2]
self.nintendo_extension_block_size = 0
self.user_extension_block_size = 0


def niff2_tri_node_builder(index, vtx_indices):
return Niff2TriNode(index, vtx_indices)
def niff2_tri_node_builder(index, vtx_indices, normal_indices):
return Niff2TriNode(index, vtx_indices, normal_indices)


def niff2_tri_node_writer(tri, buf):
Expand Down
Binary file modified screenshots/nvfview-emu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 32 additions & 2 deletions tests/test_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,12 @@ def test_create_vector_groups(self):
exporter = Exporter()
exporter.create_vector_groups([not_a_mesh, mesh])

self.assertEqual(len(exporter.tri_nv_groups),
len(exporter.vtx_nv_groups))
self.assertEqual(
len(exporter.tri_nv_groups), len(exporter.vtx_nv_groups))
self.assertEqual(
not_a_mesh.data in exporter.normal_indices_by_mesh, False)
self.assertEqual(
exporter.normal_indices_by_mesh[mesh.data], [0, 1, 2])
self.assertEqual(exporter.tri_nv_groups[0].tri_nv_num, 1)
self.assertEqual(exporter.tri_nv_groups[1].tri_nv_num, 1)
self.assertEqual(exporter.vtx_nv_groups[0].vtx_nv_num, 1)
Expand All @@ -183,12 +187,18 @@ def test_create_tri_groups(self):

mesh.data.vertices = [vertex]*3

loop = MeshLoop()
loop.normal = [1.0, 2.0, 3.0]
mesh.data.loops = [loop]*3

tri = MeshLoopTriangle()
tri.vertices = [0, 1, 2]
tri.loops = [0, 1, 2]
mesh.data.loop_triangles = [tri]

exporter = Exporter()
exporter.create_vertex_groups([not_a_mesh, mesh])
exporter.create_vector_groups([not_a_mesh, mesh])
exporter.create_tri_groups([not_a_mesh, mesh])

self.assertEqual(len(exporter.tri_groups), 1)
Expand Down Expand Up @@ -223,23 +233,31 @@ def test_create_parts(self):

mesh.vertices = [vertex]*9

loop = MeshLoop()
loop.normal = [1.0, 2.0, 3.0]
mesh.loops = [loop]*3

tri_red = MeshLoopTriangle()
tri_red.vertices = [0, 1, 2]
tri_red.loops = [0, 1, 2]
tri_red.material_index = 0

tri_green = MeshLoopTriangle()
tri_green.vertices = [3, 4, 5]
tri_green.loops = [0, 1, 2]
tri_green.material_index = 1

tri_blue = MeshLoopTriangle()
tri_blue.vertices = [6, 7, 8]
tri_blue.loops = [0, 1, 2]
tri_blue.material_index = 2

mesh.loop_triangles = [tri_red, tri_green, tri_blue]

exporter = Exporter()
exporter.create_materials([obj])
exporter.create_vertex_groups([obj])
exporter.create_vector_groups([obj])
exporter.create_tri_groups([obj])
exporter.create_parts([obj])

Expand Down Expand Up @@ -275,15 +293,21 @@ def test_create_shapes(self):

mesh.vertices = [vertex]*3

loop = MeshLoop()
loop.normal = [1.0, 2.0, 3.0]
mesh.loops = [loop]*3

tri_red = MeshLoopTriangle()
tri_red.vertices = [0, 1, 2]
tri_red.loops = [0, 1, 2]
tri_red.material_index = 0

mesh.loop_triangles = [tri_red]

exporter = Exporter()
exporter.create_materials([obj])
exporter.create_vertex_groups([obj])
exporter.create_vector_groups([obj])
exporter.create_tri_groups([obj])
exporter.create_parts([obj])
exporter.create_shapes([obj])
Expand Down Expand Up @@ -345,15 +369,21 @@ def test_create_objects(self):

mesh.vertices = [vertex]*3

loop = MeshLoop()
loop.normal = [1.0, 2.0, 3.0]
mesh.loops = [loop]*3

tri_red = MeshLoopTriangle()
tri_red.vertices = [0, 1, 2]
tri_red.loops = [0, 1, 2]
tri_red.material_index = 0

mesh.loop_triangles = [tri_red]

exporter = Exporter()
exporter.create_materials([obj])
exporter.create_vertex_groups([obj])
exporter.create_vector_groups([obj])
exporter.create_tri_groups([obj])
exporter.create_parts([obj])
exporter.create_shapes([obj])
Expand Down
59 changes: 31 additions & 28 deletions tests/test_niff2_tri.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
class TestNiff2Tri(unittest.TestCase):

def test_niff2_tri_list_header_builder(self):
one_tri = niff2_tri_group_builder(1, 2, 3, [4, 5, 6])
two_tris = niff2_tri_group_builder(1, 2, 3, [4, 5, 6, 7, 8, 9])
one_tri = niff2_tri_group_builder(1, 2, 3, [4, 5, 6], [7, 8, 9])
two_tris = niff2_tri_group_builder(
1, 2, 3, [4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15])
tri_list_header = niff2_tri_list_header_builder([one_tri, two_tris])
self.assertEqual(tri_list_header.tri_list_tag, 0x00080000)
self.assertEqual(tri_list_header.tri_list_header_size, 32)
Expand All @@ -23,8 +24,9 @@ def test_niff2_tri_list_header_builder(self):
self.assertEqual(tri_list_header.user_extension_block_size, 0)

def test_niff2_tri_list_header_writer(self):
one_tri = niff2_tri_group_builder(1, 2, 3, [4, 5, 6])
two_tris = niff2_tri_group_builder(1, 2, 3, [4, 5, 6, 7, 8, 9])
one_tri = niff2_tri_group_builder(1, 2, 3, [4, 5, 6], [7, 8, 9])
two_tris = niff2_tri_group_builder(
1, 2, 3, [4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15])
tri_groups = [one_tri, two_tris]
tri_list_header = niff2_tri_list_header_builder(tri_groups)
buf = niff2_tri_list_header_writer(
Expand All @@ -39,12 +41,13 @@ def test_niff2_tri_list_header_writer(self):
0x00, 0x00, 0x00, 0xD0]
self.assertEqual(list(buf), byte_list)

@parameterized.expand([("one_tri", 1, 2, 3, [4, 5, 6], 132),
("two_tris", 1, 2, 3, [4, 5, 6, 7, 8, 9], 208)])
@parameterized.expand([
("one_tri", 1, 2, 3, [4, 5, 6], [7, 8, 9], 132),
("two_tris", 1, 2, 3, [4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15], 208)])
def test_niff2_tri_group_builder(self, _, index, name_index, vtx_group_index, vtx_indices,
expected_size):
normal_indices, expected_size):
tri_group = niff2_tri_group_builder(
index, name_index, vtx_group_index, vtx_indices)
index, name_index, vtx_group_index, vtx_indices, normal_indices)
self.assertEqual(tri_group.tri_group_tag, 0x00080100)
self.assertEqual(tri_group.this_tri_group_index, index)
self.assertEqual(tri_group.tri_group_header_size, 32)
Expand All @@ -63,7 +66,7 @@ def test_niff2_tri_group_builder(self, _, index, name_index, vtx_group_index, vt
self.assertEqual(tri_index, tri.this_tri_index)

def test_niff2_tri_group_writer(self):
tri_group = niff2_tri_group_builder(12, 34, 56, [7, 8, 9])
tri_group = niff2_tri_group_builder(12, 34, 56, [1, 2, 3], [4, 5, 6])
buf = niff2_tri_group_writer(tri_group, bytearray())
byte_list = [0x00, 0x08, 0x01, 0x00,
0x00, 0x00, 0x00, 0x0C,
Expand All @@ -84,47 +87,47 @@ def test_niff2_tri_group_writer(self):
0x00, 0x00, 0x00, 0x4C,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07,
0x00, 0x00, 0x00, 0x07,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x09,
0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x09,
0x00, 0x00, 0x00, 0x09,
0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00]
self.assertEqual(list(buf), byte_list)

@parameterized.expand([("default", 1, [2, 3, 4], 76)])
def test_niff2_tri_node_builder(self, _, index, vtx_indices, expected_size):
tri = niff2_tri_node_builder(index, vtx_indices)
@parameterized.expand([("default", 1, [2, 3, 4], [5, 6, 7], 76)])
def test_niff2_tri_node_builder(self, _, index, vtx_indices, normal_indices, expected_size):
tri = niff2_tri_node_builder(index, vtx_indices, normal_indices)
self.assertEqual(tri.tri_tag, 0x00080101)
self.assertEqual(tri.this_tri_index, index)
self.assertEqual(tri.tri_size, expected_size)
self.assertEqual(tri.tri_nv_index, 0)
self.assertEqual(tri.tri_color_index, 0)
self.assertEqual(tri.vtx_index0, 2)
self.assertEqual(tri.st_index0, 0)
self.assertEqual(tri.vtx_nv_index0, 2)
self.assertEqual(tri.vtx_nv_index0, 5)
self.assertEqual(tri.vtx_color_index0, 2)
self.assertEqual(tri.vtx_index1, 3)
self.assertEqual(tri.st_index1, 0)
self.assertEqual(tri.vtx_nv_index1, 3)
self.assertEqual(tri.vtx_nv_index1, 6)
self.assertEqual(tri.vtx_color_index1, 3)
self.assertEqual(tri.vtx_index2, 4)
self.assertEqual(tri.st_index2, 0)
self.assertEqual(tri.vtx_nv_index2, 4)
self.assertEqual(tri.vtx_nv_index2, 7)
self.assertEqual(tri.vtx_color_index2, 4)
self.assertEqual(tri.nintendo_extension_block_size, 0)
self.assertEqual(tri.user_extension_block_size, 0)

def test_niff2_tri_node_writer(self):
tri = niff2_tri_node_builder(123, [4, 5, 6])
tri = niff2_tri_node_builder(123, [4, 5, 6], [7, 8, 9])
buf = niff2_tri_node_writer(tri, bytearray())
byte_list = [0x00, 0x08, 0x01, 0x01,
0x00, 0x00, 0x00, 0x7B,
Expand All @@ -133,15 +136,15 @@ def test_niff2_tri_node_writer(self):
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x07,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x09,
0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00]
Expand Down

0 comments on commit a81f4a6

Please sign in to comment.