mesh,gis,dds和tga均为二进制格式文件,关键数据、过滤等方法各不一样,并且只支持特定版本和固定方法,以下为规则举例。
1. mesh规则
mesh文件目前支持Nexo引擎为0x50004(327684)以下的版本,文件内容通过Struct以固定字节的方式解析出来,参考格式为:
Container:
header = Container:
file_mark = mesh (total 4)
version = 327684
file_version = 327684
file_version_mask = 0
patch_version = 0
mesh_type = skeletal (total 8)
bone_count = 25
bones = ListContainer:
24
11
bone_names = ListContainer:
98
has_bones_bi = True
bone_bounding_info = <LazyRangeContainer: 25 possible items, 0 cached>
bone_matrix = <LazyRangeContainer: 25 possible items, 0 cached>
has_bi = False
table_offset = 22516
data_table = Container:
block_count = 1
block_infos = ListContainer:
3170
pair_count = 1
data_pairs = ListContainer:
Container:
type = lod (total 3)
block_idx = 0
content = ListContainer:
Container:
sub_mesh_headers = ListContainer:
Container:
v_count = 229
tri_count = 314
uv_chnl_count = 2
has_color = False
lod_new_v = 1
v_count = 229
tri_count = 314
vb = <LazyRangeContainer: 229 possible items, 0 cached>
nb = <LazyRangeContainer: 229 possible items, 0 cached>
has_tangent = 1
tangent = <LazyRangeContainer: 229 possible items, 0 cached>
ib = <LazyRangeContainer: 942 possible items, 0 cached>
tb = ListContainer:
ListContainer:
<LazyRangeContainer: 229 possible items, 0 cached>
<LazyRangeContainer: 229 possible items, 0 cached>
cb = None
ref_bones = ListContainer:
1507350
4294967295
1441804
tail = ListContainer:
模型骨骼数不能超过80
xpath=.* .mesh
xpath=root/bone_count
condition=["满足表达式","d<80"]
2.gis规则
gis文件目前支持的内容也与引擎版本有关,目前屏蔽track功能扩展支持的版本,文件内容通过Struct以固定字节的方式解析出来,参考格式为:
Container:
header = Container:
file_mark = anim (total 4)
version = 50724865
file_version = 393217
file_version_mask = 3
anim_count = 5
bone_count = 3
bone_names = ListContainer:
b'bone001'
b'bone002'
b'root'
bone_trans = ListContainer:
Container:
pos = ListContainer:
0.0
4.044138431549072
-3.159993298140762e-07
rot = ListContainer:
1.4527657299368002e-08
-1.4527657299368002e-08
0.7071068286895752
0.7071068286895752
scale = ListContainer:
1.0
1.0
1.0
Container:
pos = ListContainer:
0.0
1.0272369384765625
-0.025091886520385742
rot = ListContainer:
0.5000001192092896
0.4999999403953552
-0.49999988079071045
-0.5000000596046448
scale = ListContainer:
1.0
1.0
1.0
Container:
pos = ListContainer:
0.0
0.0
0.0
rot = ListContainer:
0.0
0.0
0.0
1.0
scale = ListContainer:
1.0
1.0
1.0
seperate_storage = 0
base_size = None
anim = ListContainer:
Container:
name = obtain (total 6)
anim_root_name = root (total 4)
bone_count = 3
bone_names = ListContainer:
b'bone001'
b'bone002'
b'root'
sample_fps = 30
loop = False
has_scaled = True
prs_flags = 7
accum_flags = 0
pack_prs_flags = 6
bone_separate_flags = 0
keys_data = Container:
key_count = 16
key_times = ListContainer:
0.0
33.33333206176758
66.66666412353516
100.0
133.3333282470703
166.6666717529297
200.0
233.3333282470703
266.6666564941406
300.0
333.3333435058594
366.6666564941406
400.0
433.3333435058594
466.6666564941406
500.0
key_data = ListContainer:
Container:
has_pos_keys = True
has_rot_keys = True
has_scale_keys = True
euler_flags = False
position_key_count = 16
positions = <LazyRangeContainer: 16 possible items, 0 cached>
rot_key_count = 16
rot = <LazyRangeContainer: 16 possible items, 0 cached>
scale_key_count = 16
scales = <LazyRangeContainer: 16 possible items, 0 cached>
Container:
has_pos_keys = True
has_rot_keys = True
has_scale_keys = True
euler_flags = False
position_key_count = 16
positions = <LazyRangeContainer: 16 possible items, 0 cached>
rot_key_count = 16
rot = <LazyRangeContainer: 16 possible items, 0 cached>
scale_key_count = 16
scales = <LazyRangeContainer: 16 possible items, 0 cached>
Container:
has_pos_keys = False
has_rot_keys = False
has_scale_keys = False
euler_flags = False
position_key_count = 1
positions = <LazyRangeContainer: 1 possible items, 0 cached>
rot_key_count = 1
rot = <LazyRangeContainer: 1 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
pivot = Container:
has_pivot_track = False
track_data = None
Container:
name = idle (total 4)
anim_root_name = root (total 4)
bone_count = 3
bone_names = ListContainer:
b'bone001'
b'bone002'
b'root'
sample_fps = 30
loop = True
has_scaled = True
prs_flags = 7
accum_flags = 0
pack_prs_flags = 6
bone_separate_flags = 0
keys_data = Container:
key_count = 101
key_times = ListContainer:
0.0
33.33333206176758
66.66666412353516
key_data = ListContainer:
Container:
has_pos_keys = True
has_rot_keys = True
has_scale_keys = False
euler_flags = False
position_key_count = 101
positions = <LazyRangeContainer: 101 possible items, 0 cached>
rot_key_count = 101
rot = <LazyRangeContainer: 101 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
Container:
has_pos_keys = True
has_rot_keys = True
has_scale_keys = False
euler_flags = False
position_key_count = 101
positions = <LazyRangeContainer: 101 possible items, 0 cached>
rot_key_count = 101
rot = <LazyRangeContainer: 101 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
Container:
has_pos_keys = False
has_rot_keys = False
has_scale_keys = False
euler_flags = False
position_key_count = 1
positions = <LazyRangeContainer: 1 possible items, 0 cached>
rot_key_count = 1
rot = <LazyRangeContainer: 1 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
pivot = Container:
has_pivot_track = False
track_data = None
Container:
name = born (total 4)
anim_root_name = root (total 4)
bone_count = 3
bone_names = ListContainer:
b'bone001'
b'bone002'
b'root'
sample_fps = 30
loop = False
has_scaled = True
prs_flags = 7
accum_flags = 0
pack_prs_flags = 6
bone_separate_flags = 0
keys_data = Container:
key_count = 25
key_times = ListContainer:
0.0
33.54166793823242
66.875
key_data = ListContainer:
Container:
has_pos_keys = True
has_rot_keys = True
has_scale_keys = False
euler_flags = False
position_key_count = 25
positions = <LazyRangeContainer: 25 possible items, 0 cached>
rot_key_count = 25
rot = <LazyRangeContainer: 25 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
Container:
has_pos_keys = True
has_rot_keys = True
has_scale_keys = False
euler_flags = False
position_key_count = 25
positions = <LazyRangeContainer: 25 possible items, 0 cached>
rot_key_count = 25
rot = <LazyRangeContainer: 25 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
Container:
has_pos_keys = False
has_rot_keys = False
has_scale_keys = False
euler_flags = False
position_key_count = 1
positions = <LazyRangeContainer: 1 possible items, 0 cached>
rot_key_count = 1
rot = <LazyRangeContainer: 1 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
pivot = Container:
has_pivot_track = False
track_data = None
Container:
name = dead (total 4)
anim_root_name = root (total 4)
bone_count = 3
bone_names = ListContainer:
b'bone001'
b'bone002'
b'root'
sample_fps = 30
loop = False
has_scaled = True
prs_flags = 7
accum_flags = 0
pack_prs_flags = 6
bone_separate_flags = 0
keys_data = Container:
key_count = 29
key_times = ListContainer:
0.0
33.33333206176758
66.66666412353516
key_data = ListContainer:
Container:
has_pos_keys = True
has_rot_keys = True
has_scale_keys = False
euler_flags = False
position_key_count = 29
positions = <LazyRangeContainer: 29 possible items, 0 cached>
rot_key_count = 29
rot = <LazyRangeContainer: 29 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
Container:
has_pos_keys = True
has_rot_keys = True
has_scale_keys = False
euler_flags = False
position_key_count = 29
positions = <LazyRangeContainer: 29 possible items, 0 cached>
rot_key_count = 29
rot = <LazyRangeContainer: 29 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
Container:
has_pos_keys = False
has_rot_keys = False
has_scale_keys = False
euler_flags = False
position_key_count = 1
positions = <LazyRangeContainer: 1 possible items, 0 cached>
rot_key_count = 1
rot = <LazyRangeContainer: 1 possible items, 0 cached>
scale_key_count = 1
scales = <LazyRangeContainer: 1 possible items, 0 cached>
pivot = Container:
has_pivot_track = False
track_data = None
tail = (total 0)
文件在检查端也是转换成一个对象root数据。
相对于父gis文件,子gis如图所示,比较大的区别在于anime属性。
Container:
name = shd_start_fl (total 12)
root_name = biped root (total 10)
bone_count = 100
bone_name_id = ListContainer:
1701865826
100
0
0
0
0
0
.
.
sample_fps = 0
loop = True
has_scaled = True
prs_flags = 25968
accum_flags = 544350308
pack_prs_flags = 102
bone_separate_flags = 105
length = 4.5438147884045724e+30
keys_data_offset = 49
anim = Container:
name = \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00biped r finger11 (total 30)
anim_root_name = \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00biped r finger12 (total 30)
bone_count = 0
bone_names = ListContainer:
sample_fps = 0
loop = False
has_scaled = False
prs_flags = 0
accum_flags = 0
pack_prs_flags = 98
bone_separate_flags = 105
目前支持规则包含 root,root/bone_count,root/samplefps,分别对应root, root.anim下的keys_data.key_count,root.anim.sample_fps。以及支持自定义属性root/{} 对应找到root对象的数据 规则举例:
动作帧数不能大于5(父gis)
xpath=.* .gis
xpath=root/anim
condition=['满足表达式','d < 5']
filter = artfunc_checkgis_keycount
def checkgis_keycount(**pdict):
data = pdict.get('data',[])
try:
result = data[0][0].keys_data.key_count
except:
return [len(data)]
return [result]
3.dds规则(适用tga文件)
dds文件目前由第三方库支持解析,目前仅支持版本为pixel format 只能是 FOURCC 或者 RGB 格式,RGB 格式只能是 A8R8G8B8, A1R5G5B5, A4R4G4B4, R8G8B8, R5G6B5,FOURCC 格式只能是 DXT1, DXT2, DXT3, DXT4, DXT5,解析出来的主要属性如下:
root.size,文件的高度和宽度(1024,1024)
root.header_size, header 大小必须是124个字节, 可以用来检验文件格式是否符合要求
root.mode, 图像格式,如L,P,RGB,RGBA,CMYK,YCbCr,I,F等
root.mipmaps,minemap 层数
root.pfsize,pixel format 的大小, 必须是32字节
root.pfflags,pixel format 的值域标志位
root.fourcc,压缩格式, 也就是 DXTn 系列,需要 pfflags 的 DDPF_FOURCC 标志位有效
root.bitcount,表示RGB位数, 需要存在A通道
root.pixel_format,压缩格式,相比fourcc更详细
规则举例: 文件长宽不能超过1024 xpath=.*.dds$ xpath=root/size condition=['满足表达式',"int(d[0]) <= 1024 and int(d[1]) <= 1024"]