ya2 · news · projects · code · about

retrieve test coordinates
[pmachines.git] / ya2 / build / models.py
1 '''Provides tools for building models.'''
2 from logging import info
3 from os import system, walk, makedirs
4 from os.path import exists, basename, dirname
5 from multiprocessing import Pool
6 from glob import glob
7 from hashlib import md5
8 from shutil import copyfile, move, rmtree
9 from ya2.build.mtprocesser import ProcesserMgr
10 from ya2.build.build import to_be_built
11
12
13 class ModelsBuilder():
14
15 def __init__(self):
16 self._cache_files = [] # for avoiding rebuilding the same file
17
18 def build(self, blend_path, cores):
19 '''Builds the models i.e. creates glTF and bam files from blend
20 ones.'''
21 args = []
22 for root, _, fnames in walk(blend_path):
23 for fname in [fname for fname in fnames if fname.endswith('.blend')]:
24 if '/prototypes/' not in root:
25 args += [(root, fname)]
26 with Pool() as p:
27 p.starmap(self._export_blend, args)
28 # caching is broken now: it is based on the previous
29 # non-multiprocessing approach
30 # i should evaluate if fix it or just change the blend_path for building
31 # only specific models
32 cache, lines = [], []
33 if exists('hash_cache.txt'):
34 with open('hash_cache.txt') as fhash:
35 lines = fhash.readlines()
36 for line in lines: # line's e.g. assets/path/to/gltf_or_png.ext 68ced1
37 line_spl = line.split()
38 hashval = line_spl[-1]
39 fname = ' '.join(line_spl[:-1])
40 if fname not in self._cache_files:
41 cache += [(fname, hashval)]
42 for cfile in self._cache_files:
43 cache += [(cfile, md5(open(cfile, 'rb').read()).hexdigest())]
44 cache = cache[-2048:]
45 with open('hash_cache.txt', 'w') as fhash:
46 fhash.write('\n'.join([' '.join(line) for line in cache]))
47
48 def _export_blend(self, root, fname):
49 '''Exports blend files to glTF and bam formats.'''
50 if self._export_gltf(root, fname):
51 self._export_bam(root, fname)
52
53 def _export_gltf(self, root, fname):
54 '''Exports glTF files from blend ones.'''
55 _fname = '%s/%s' % (root, fname)
56 pgltf = 'assets/models/gltf/'
57 new_dir = root.replace('assets/models/blend/', pgltf)
58 rmtree(new_dir, ignore_errors=True)
59 makedirs(new_dir)
60 #files_before = [basename(gname) for gname in glob('./*')]
61 cmd = 'blender %s --background --python ya2/build/blend2gltf.py '
62 cmd += '-- %s.gltf'
63 cmd = cmd % (_fname, new_dir + '/' + fname[:-6])
64 gltf_name = _fname.replace('assets/models/blend/', pgltf)
65 gltf_name = gltf_name.replace('.blend', '.gltf')
66 if not to_be_built(gltf_name, [_fname]):
67 return False
68 system(cmd)
69 self._cache_files += [_fname, gltf_name]
70 #files_after = [basename(gname) for gname in glob('./*')]
71 #new_files = [nnm for nnm in files_after if nnm not in files_before]
72 #new_dir = root.replace('assets/models/blend/', pgltf)
73 #rmtree(new_dir, ignore_errors=True)
74 #makedirs(new_dir)
75 #for mname in new_files:
76 # new_name = '%s/%s' % (new_dir, mname)
77 # move(mname, new_name)
78 # info('move %s %s' % (mname, new_name))
79 # # blender rewrites metal files: let's restore them
80 # metal_files = [fnm for fnm in glob(new_dir + '/*') if 'metal' in fnm]
81 # for metal_file in metal_files:
82 # src = metal_file.replace(pgltf, 'assets/models/')
83 # if not exists(src):
84 # src = metal_file.replace(pgltf, 'assets/models/prototypes/')
85 # src_split = src.split('/')
86 # src_tracks_idx = src_split.index('tracks')
87 # before = src_split[:src_tracks_idx]
88 # after = src_split[src_tracks_idx + 2:]
89 # src = '/'.join(before + after)
90 # copyfile(src, metal_file)
91 return True
92
93 def _export_bam(self, root, fname):
94 '''Exports bam files from glTF ones.'''
95 _fname = '%s/%s' % (root, fname)
96 gltf_name = (_fname[:-5] + 'gltf').replace('/blend/', '/gltf/', 1)
97 bam_name = (_fname[:-5] + 'bam').replace('/blend/', '/bam/', 1)
98 cmd_args = gltf_name, bam_name
99 # use dds files in place of png/jpg in gltf2bam
100 copyfile(gltf_name, gltf_name + '.tmp')
101 with open(gltf_name) as fgltf:
102 lines = fgltf.readlines()
103 deps = []
104 for line in lines:
105 if ('.png' in line or '.jpg' in line) and '"uri"' in line:
106 rln = line[line.index('"uri"') + 9:].rstrip(',\n"')
107 tname = '%s/%s' % (root, rln)
108 deps += [tname.replace('/models/blend/', '/models/gltf/', 1)]
109 for dep in deps:
110 tgt = dep.replace('/gltf/', '/bam/', 1)
111 tgt = tgt.replace('.png', '.dds').replace('.jpg', '.dds')
112 makedirs(dirname(tgt), exist_ok=True)
113 info('convert %s %s' % (dep, tgt))
114 system('convert %s %s' % (dep, tgt))
115 rpl = lambda lin: lin.replace('.png', '.dds').replace('.jpg', '.dds').replace('/png', '/dds').replace('/jpg', '/dds')
116 with open(gltf_name, 'w') as fgltf:
117 fgltf.write(''.join([rpl(line) for line in lines]))
118 makedirs(dirname(bam_name), exist_ok=True)
119 if to_be_built(bam_name, deps):
120 system('gltf2bam %s %s' % cmd_args)
121 self._cache_files += [bam_name] + deps