def setUp(self): self.meshes = { 'simple': ('tests/samples/staticmesh/evil_box/meshes/evil_box.staticmesh', 'tests/generated/staticmesh/edit/translate/evil_box/meshes/evil_box.staticmesh', 'tests/generated/staticmesh/edit/merge/evil_box/meshes/evil_box.staticmesh' ), 'lods': ('tests/samples/staticmesh/evil_box_lods/meshes/evil_box_lods.staticmesh', 'tests/generated/staticmesh/edit/translate/evil_box_lods/meshes/evil_box_lods.staticmesh', 'tests/generated/staticmesh/edit/merge/evil_box_lods/meshes/evil_box_lods.staticmesh' ), 'dest': ('tests/samples/staticmesh/evil_box_dest/meshes/evil_box_dest.staticmesh', 'tests/generated/staticmesh/edit/translate/evil_box_dest/meshes/evil_box_dest.staticmesh', 'tests/generated/staticmesh/edit/merge/evil_box_dest/meshes/evil_box_dest.staticmesh' ), } with VisibleMesh(self.meshes['simple'][0]) as vmesh: if len(vmesh.geoms) != 1: self.skipTest('invalid input mesh, expected 1 geom') with VisibleMesh(self.meshes['lods'][0]) as vmesh: if len(vmesh.geoms[0].lods) != 2: self.skipTest('invalid input mesh, expected 2 lods in geom0') with VisibleMesh(self.meshes['dest'][0]) as vmesh: if len(vmesh.geoms) != 2: self.skipTest('invalid input mesh, expected 2 geoms')
def test_can_read_materials(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(vmesh.geoms[0].lods[0].matnum, 1) self.assertEqual(vmesh.geoms[0].lods[0].materials[0].alphamode, 0) self.assertEqual(vmesh.geoms[0].lods[0].materials[0].fxfile, b'StaticMesh.fx') self.assertEqual(vmesh.geoms[0].lods[0].materials[0].technique, b'Base') self.assertEqual(vmesh.geoms[0].lods[0].materials[0].mapnum, 2) self.assertEqual( vmesh.geoms[0].lods[0].materials[0].maps[0], b'objects/staticobjects/test/evil_box/textures/evil_box_c.dds') self.assertEqual(vmesh.geoms[0].lods[0].materials[0].maps[1], b'Common\Textures\SpecularLUT_pow36.dds') # pylint: disable=W1401 self.assertEqual(vmesh.geoms[0].lods[0].materials[0].vstart, 0) self.assertEqual(vmesh.geoms[0].lods[0].materials[0].istart, 0) self.assertEqual(vmesh.geoms[0].lods[0].materials[0].inum, 36) self.assertEqual(vmesh.geoms[0].lods[0].materials[0].vnum, 25) self.assertEqual(vmesh.geoms[0].lods[0].materials[0].u4, 8064) # no idea what this shit is self.assertEqual(vmesh.geoms[0].lods[0].materials[0].u5, 65535) self.assertEqual(vmesh.geoms[0].lods[0].materials[0].mmin, (-0.5, 0.0, -0.5)) self.assertEqual(vmesh.geoms[0].lods[0].materials[0].mmax, (0.5, 1.0, 0.5))
def test_can_read_vertstride(self): with VisibleMesh(self.path_mesh) as vmesh: vertstride = 0 for attrib in vmesh.vertex_attributes: vertstride += len(D3DDECLTYPE( attrib.vartype)) * vmesh.vertformat self.assertEqual(vmesh.vertstride, (vertstride))
def test_can_read_header(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(vmesh.head.u1, 0) self.assertEqual(vmesh.head.version, 11) # statics usuallly being 11, old ones is 4 self.assertEqual(vmesh.head.u3, 0) self.assertEqual(vmesh.head.u4, 0) self.assertEqual(vmesh.head.u5, 0)
def test_edit_order_mesh_data_updated(self): def get_geom_vertices(vmesh, geomId): vertex_size = sum([ len(D3DDECLTYPE(v_attrib.vartype)) for v_attrib in vmesh.vertex_attributes if v_attrib.flag is USED ]) geom_lod0_material0_vstart = vmesh.geoms[geomId].lods[0].materials[ 0].vstart * vertex_size geom_lods_vnum = sum([ sum([material.vnum for material in lod.materials]) for lod in vmesh.geoms[geomId].lods ]) return list(vmesh.vertices[ geom_lod0_material0_vstart:geom_lod0_material0_vstart + geom_lods_vnum]) path_export = 'tests/generated/skinnedmesh/edit/ordered/kits/ru/meshes/ru_kits.skinnedmesh' with VisibleMesh(self.path_mesh) as vmesh: vertices_size_old = len(vmesh.vertices) vertices_geom2_vertices = get_geom_vertices(vmesh, 2) vmesh.change_geoms_order([ 0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 ]) # edited startpoints self.assertEqual( vmesh.geoms[1].lods[0].materials[0].vstart, vmesh.geoms[0].lods[0].materials[0].vstart + sum([lod.materials[0].vnum for lod in vmesh.geoms[0].lods])) self.assertEqual( vmesh.geoms[1].lods[0].materials[0].istart, vmesh.geoms[0].lods[0].materials[0].istart + sum([lod.materials[0].inum for lod in vmesh.geoms[0].lods])) # edited amount of vertices and indices self.assertEqual(vmesh.geoms[1].lods[0].materials[0].vnum, 5108) self.assertEqual(vmesh.geoms[1].lods[0].materials[0].inum, 10722) self.assertEqual(vmesh.geoms[1].lods[1].materials[0].vnum, 469) self.assertEqual(vmesh.geoms[1].lods[1].materials[0].inum, 741) self.assertEqual(vmesh.geoms[1].lods[2].materials[0].vnum, 176) self.assertEqual(vmesh.geoms[1].lods[2].materials[0].inum, 246) # edited vertices array correctly self.assertEqual(len(vmesh.vertices), vertices_size_old) vertices_geom1_vertices = get_geom_vertices(vmesh, 1) self.assertEqual(len(vertices_geom1_vertices), len(vertices_geom2_vertices) ) #check for numbers first for early exit self.assertListEqual(vertices_geom2_vertices, get_geom_vertices(vmesh, 1)) # edited indices array # TODO: indices update vmesh.export(path_export)
def test_can_read_bones_id(self): with VisibleMesh(self.path_mesh) as vmesh: bones = vmesh.geoms[0].lods[0].rigs[0].bones self.assertEqual(bones[0].id, 0) self.assertEqual(bones[1].id, 12) self.assertEqual(bones[2].id, 13) self.assertEqual(bones[3].id, 47) self.assertEqual(bones[4].id, 79) self.assertEqual(bones[5].id, 11)
def test_can_read_lod_table(self): # node deformation matrix? cant remember mock_node_matrix = [(1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0)] with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(vmesh.geoms[0].lods[0].min, (-0.5, 0, -0.5)) self.assertEqual(vmesh.geoms[0].lods[0].max, (0.5, 1.0, 0.5)) self.assertEqual(vmesh.geoms[0].lods[0].nodenum, 1) self.assertEqual(vmesh.geoms[0].lods[0].nodes[0], mock_node_matrix)
def setUp(self): self.path_mesh = 'tests/samples/skinnedmesh/kits/ru/meshes/ru_kits.skinnedmesh' with VisibleMesh(self.path_mesh) as vmesh: if len(vmesh.geoms) != 22: self.skipTest('invalid input mesh, expected 22 geoms') if vmesh.geoms[2].lods[0].materials[0].vstart != 6815: self.skipTest( 'invalid input mesh, expected 6815 vstart for geom2lod0material0' ) if vmesh.geoms[2].lods[0].materials[0].istart != 12477: self.skipTest( 'invalid input mesh, expected 12477 istart for geom2lod0material0' ) if vmesh.geoms[2].lods[0].materials[0].vnum != 5108: self.skipTest( 'invalid input mesh, expected 5108 vertices for geom2lod0material0' ) if vmesh.geoms[2].lods[0].materials[0].inum != 10722: self.skipTest( 'invalid input mesh, expected 10722 indices for geom2lod0material0' ) if vmesh.geoms[2].lods[1].materials[0].vstart != 11923: self.skipTest( 'invalid input mesh, expected 11923 vstart for geom2lod1material0' ) if vmesh.geoms[2].lods[1].materials[0].istart != 23199: self.skipTest( 'invalid input mesh, expected 23199 istart for geom2lod1material0' ) if vmesh.geoms[2].lods[1].materials[0].vnum != 469: self.skipTest( 'invalid input mesh, expected 469 vertices for geom2lod1material0' ) if vmesh.geoms[2].lods[1].materials[0].inum != 741: self.skipTest( 'invalid input mesh, expected 741 indices for geom2lod1material0' ) if vmesh.geoms[2].lods[2].materials[0].vstart != 12392: self.skipTest( 'invalid input mesh, expected 12392 vstart for geom2lod2material0' ) if vmesh.geoms[2].lods[2].materials[0].istart != 23940: self.skipTest( 'invalid input mesh, expected 23940 istart for geom2lod2material0' ) if vmesh.geoms[2].lods[2].materials[0].vnum != 176: self.skipTest( 'invalid input mesh, expected 176 vertices for geom2lod2material0' ) if vmesh.geoms[2].lods[2].materials[0].inum != 246: self.skipTest( 'invalid input mesh, expected 246 indices for geom2lod2material0' )
def test_can_read_vertex_block(self): mock_test_data = ( 0.5, 0.0, 0.5, # position 0.0, -1.0, 0.0 # normals ) with VisibleMesh(self.path_mesh) as vmesh: # no need to mock whole vertices array in test, reading first few self.assertEqual(vmesh.vertices[0:6], mock_test_data[0:6])
def test_can_read_vertex_attribute_table(self): mock_vertattrib = [ bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.FLOAT3, D3DDECLUSAGE.POSITION), bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.FLOAT3, D3DDECLUSAGE.NORMAL), bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.D3DCOLOR, D3DDECLUSAGE.BLENDINDICES), bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.FLOAT2, D3DDECLUSAGE.UV1), bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.FLOAT2, D3DDECLUSAGE.UV2), bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.FLOAT2, D3DDECLUSAGE.UV3), bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.FLOAT2, D3DDECLUSAGE.UV4), bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.FLOAT2, D3DDECLUSAGE.UV5), bf2mesh.visiblemesh._bf2vertattrib(USED, 0, D3DDECLTYPE.FLOAT3, D3DDECLUSAGE.TANGENT), bf2mesh.visiblemesh._bf2vertattrib(UNUSED, 0, D3DDECLTYPE.UNUSED, D3DDECLUSAGE.POSITION), ] # recalculating offset offset = 0 for id, vertattrib in enumerate(mock_vertattrib, 1): if vertattrib.flag == UNUSED: # TODO: think what'll happend if UNUSED in middle of array vertattrib.offset = 0 else: vertattrib.offset = offset # seems like offset size should be mapped to VisibleMesh.vertformat, but we reading it later from file size_previous = len( mock_vertattrib[id - 1].vartype) * struct.calcsize('f') offset += size_previous logging.debug('attrib [%d] = %d %d %d %d' % (id, vertattrib.flag, vertattrib.offset, vertattrib.vartype, vertattrib.usage)) with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(len(mock_vertattrib), len(vmesh.vertex_attributes)) for id in range(vmesh.vertattribnum): self.assertEqual(mock_vertattrib[id].flag, vmesh.vertex_attributes[id].flag) self.assertEqual(mock_vertattrib[id].offset, vmesh.vertex_attributes[id].offset) self.assertEqual(mock_vertattrib[id].vartype, vmesh.vertex_attributes[id].vartype) self.assertEqual(mock_vertattrib[id].usage, vmesh.vertex_attributes[id].usage)
def test_can_merge_staticmesh(self): #self.skipTest('NotImplemented') for staticmesh in self.meshes: path_mesh, path_export = self.meshes[staticmesh][0], self.meshes[ staticmesh][2] vmesh = VisibleMesh(path_mesh) vmesh2 = VisibleMesh(path_mesh) vmesh_old = VisibleMesh(path_mesh) # to compare later vmesh.merge(vmesh2) vmesh.export(path_export) for geomId, geom in enumerate(vmesh.geoms): for lodId, lod in enumerate(geom.lods): for materialId, material in enumerate(lod.materials): material2 = vmesh2.geoms[geomId].lods[lodId].materials[ materialId] material_old = vmesh_old.geoms[geomId].lods[ lodId].materials[materialId] self.assertEqual(material.vnum, material2.vnum + material_old.vnum) self.assertEqual(material.inum, material2.inum + material_old.inum)
def test_can_translate_staticmesh(self): offset = (0.0, 0.0, 1.5) for staticmesh in self.meshes: path_mesh, path_export = self.meshes[staticmesh][0], self.meshes[ staticmesh][1] with VisibleMesh(path_mesh) as vmesh: vertices_old = tuple(vmesh.vertices) vmesh.translate(offset) vmesh.export(path_export) for geomId, geom in enumerate(vmesh.geoms): for lodId, lod in enumerate(geom.lods): for materialId, material in enumerate(lod.materials): for vertId in range(material.vnum): _start = (material.vstart + vertId) * vmesh.vertex_size _end = _start + vmesh.vertex_size vertexBuffer = vmesh.vertices[_start:_end] vertex_OldBuffer = vertices_old[_start:_end] #print('%d -> %d' % (_start, _end)) vertex = self.Vertex() vertex_old = self.Vertex() for attrib in vmesh.vertex_attributes: if attrib.flag is UNUSED: continue _start = int(attrib.offset / vmesh.vertformat) _end = _start + len( D3DDECLTYPE(attrib.vartype)) setattr(vertex, D3DDECLUSAGE(attrib.usage).name, vertexBuffer[_start:_end]) setattr(vertex_old, D3DDECLUSAGE(attrib.usage).name, vertex_OldBuffer[_start:_end]) #print('[%d]new %s to %s' % (vertId, D3DDECLUSAGE(attrib.usage).name, vertexBuffer[_start:_end])) #print('[%d]old %s to %s' % (vertId, D3DDECLUSAGE(attrib.usage).name, vertex_OldBuffer[_start:_end])) self.assertEqual( tuple(a - b for a, b in zip( getattr(vertex, D3DDECLUSAGE.POSITION. name), offset)), getattr(vertex_old, D3DDECLUSAGE.POSITION.name))
def test_can_read_vertex_format(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(vmesh.vertformat, 4)
def test_can_read_vertattribnum(self): with VisibleMesh(self.path_mesh) as vmesh: # by default 3dsmax exporter gives 5 attribs + 4 empty UV maps self.assertEqual(vmesh.vertattribnum, 10)
def test_edit_order_raise_exception_if_new_order_num_not_equal(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertRaises(AttributeError, vmesh.change_geoms_order, [0, 1, 2])
def setUp(self): self.path_mesh = 'tests/samples/skinnedmesh/kits/ru/meshes/ru_kits.skinnedmesh' self.path_save = 'tests/generated/skinnedmesh/write/kits/ru/meshes/ru_kits.skinnedmesh' self.vmesh = VisibleMesh(self.path_mesh) self.vmesh.export(self.path_save) self.vmesh_save = VisibleMesh(self.path_save)
def test_can_read_bonenum(self): with VisibleMesh(self.path_mesh) as vmesh: rig = vmesh.geoms[0].lods[0].rigs[0] self.assertEqual(rig.bonenum, 6) self.assertEqual(len(rig.bones), 6)
def test_can_read_rignum(self): with VisibleMesh(self.path_mesh) as vmesh: lod = vmesh.geoms[0].lods[0] self.assertEqual(lod.rignum, 1) self.assertEqual(len(lod.rigs), 1)
def test_can_load_staticmesh(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertTrue(vmesh.isStaticMesh) self.assertTrue(vmesh.isLoaded)
def test_can_read_indexnum(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(vmesh.indexnum, 36)
def test_can_read_index_block(self): mock_test_data = (22, 23, 20, 20, 21, 22) with VisibleMesh(self.path_mesh) as vmesh: # no need to mock whole vertices array in test, reading first few self.assertEqual(vmesh.index[0:6], mock_test_data[0:6])
def test_can_read_vertnum(self): with VisibleMesh(self.path_mesh) as vmesh: # 3dsmax exported box have additional vertex, classical box should be 3*8=24 vertices self.assertEqual(vmesh.vertnum, 25)
def test_can_read_u1(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(vmesh.u1, 0)
def test_can_read_geomnum(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(vmesh.geomnum, 1)
def test_can_read_geom_table(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertTrue(len(vmesh.geoms) == vmesh.geomnum == 1) self.assertEqual(vmesh.geoms[0].lodnum, 1)
def setUp(self): self.path_mesh = 'tests/samples/staticmesh/evil_box/meshes/evil_box.staticmesh' self.path_save = 'tests/generated/staticmesh/write/evil_box/meshes/evil_box.staticmesh' self.vmesh = VisibleMesh(self.path_mesh) self.vmesh.export(self.path_save) self.vmesh_save = VisibleMesh(self.path_save)
def test_can_read_u2(self): with VisibleMesh(self.path_mesh) as vmesh: self.assertEqual(vmesh.u2, 8) # some weirdo bfp4f stuff