From 8646c40943f83d730a33897e93c3fec82a345110 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Thu, 10 Feb 2022 12:01:51 -0600 Subject: [PATCH] lod differentiation pre-gen commands --- app/__init__.py | 4 +++- app/commands.py | 56 +++++++++++++++++++++++++++++++++++++++++++++-- app/properties.py | 14 ++++-------- app/pylddlib.py | 23 ++++++++++--------- 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index e1879cc..ed5c7a2 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -12,7 +12,7 @@ from flask_wtf.csrf import CSRFProtect from flask_apscheduler import APScheduler from app.luclient import query_cdclient, register_luclient_jinja_helpers -from app.commands import init_db, init_accounts, load_property +from app.commands import init_db, init_accounts, load_property, gen_image_cache, gen_model_cache from app.models import Account, AccountInvitation # Instantiate Flask extensions @@ -65,6 +65,8 @@ def create_app(): app.cli.add_command(init_db) app.cli.add_command(init_accounts) app.cli.add_command(load_property) + app.cli.add_command(gen_image_cache) + app.cli.add_command(gen_model_cache) register_settings(app) register_extensions(app) diff --git a/app/commands.py b/app/commands.py index a9925a5..01cfc24 100644 --- a/app/commands.py +++ b/app/commands.py @@ -7,6 +7,12 @@ from app import db from app.models import Account, PlayKey, CharacterInfo, Property, PropertyContent, UGC import pathlib import zlib +import os +from wand import image +from wand.exceptions import BlobError as BE +import app.pylddlib as ldd +from multiprocessing import Pool +from functools import partial @click.command("init_db") @click.argument('drop_tables', nargs=1) @@ -89,6 +95,54 @@ def load_property(zone, player): ) new_prop_content.save() +@click.command("gen_image_cache") +def gen_image_cache(): + luclient = pathlib.Path('app/luclient/res') + files = [path for path in luclient.rglob("*.dds") if path.is_file()] + + for file in files: + cache = get_cache_file(file).with_suffix(".png") + if not cache.exists(): + try: + print(f"Convert {file.as_posix()} to {cache}") + cache.parent.mkdir(parents=True, exist_ok=True) + with image.Image(filename=str(file.as_posix())) as img: + img.compression = "no" + img.save(filename=str(cache.as_posix())) + except BE: + return print(f"Error on {file}") + +@click.command("gen_model_cache") +def gen_model_cache(): + luclient = pathlib.Path('app/luclient/res') + files = [path for path in luclient.rglob("*.lxfml") if path.is_file()] + pool = Pool(processes=4) + pool.map(partial(convert_lxfml_to_obj, lod=0), files) + pool.map(partial(convert_lxfml_to_obj, lod=1), files) + pool.map(partial(convert_lxfml_to_obj, lod=2), files) + +def convert_lxfml_to_obj(file, lod): + mtl = get_cache_file(file).with_suffix(f".lod{lod}.mtl") + if not mtl.exists(): + mtl.parent.mkdir(parents=True, exist_ok=True) + print(f"Convert LXFML {file.as_posix()} to obj and mtl @ {mtl}") + try: + ldd.main(str(file.as_posix()), str(mtl.with_suffix("").as_posix()), lod) # convert to OBJ + except Exception as e: + print(f"ERROR on {file}:\n {e}") + else: + # print(f"Already Exists: {file} with LOD {lod}") + return + +def get_cache_file(path): + # convert to list so that we can change elements + parts = list(path.parts) + + # replace part that matches src with dst + parts[parts.index("luclient")] = "cache" + del parts[parts.index("res")] + + return pathlib.Path(*parts) def find_or_create_account(name, email, password, gm_level=9): """ Find existing account or create new account """ @@ -119,5 +173,3 @@ def find_or_create_account(name, email, password, gm_level=9): db.session.add(play_key) db.session.commit() return # account - - diff --git a/app/properties.py b/app/properties.py index c90c5b3..ef4b936 100644 --- a/app/properties.py +++ b/app/properties.py @@ -367,19 +367,13 @@ def prebuilt(content, file_format): cache = f"app/cache/{filename}.{file_format}" - if os.path.exists(cache): - with open(cache, 'r') as file: - cache_data = file.read() - response = make_response(cache_data) - - else: + if not os.path.exists(cache): lxfml = f'app/luclient/res/BrickModels/{filename.split(".")[0]}.lxfml' ldd.main(lxfml, cache.split('.')[0]) # convert to OBJ - if os.path.exists(cache): - with open(cache, 'r') as file: - cache_data = file.read() - response = make_response(cache_data) + with open(cache, 'r') as file: + cache_data = file.read() + response = make_response(cache_data) else: raise(Exception("INVALID FILE FORMAT")) diff --git a/app/pylddlib.py b/app/pylddlib.py index 1054cb1..f482c8d 100644 --- a/app/pylddlib.py +++ b/app/pylddlib.py @@ -30,7 +30,7 @@ if sys.version_info < (3, 0): sys.setdefaultencoding('utf-8') PRIMITIVEPATH = '/Primitives/' -GEOMETRIEPATH = PRIMITIVEPATH + 'LOD0/' +GEOMETRIEPATH = PRIMITIVEPATH DECORATIONPATH = '/Decorations/' MATERIALNAMESPATH = '/MaterialNames/' @@ -238,10 +238,10 @@ class Scene: for childnode in node.childNodes: if childnode.nodeName == 'BrickSet': self.Version = str(childnode.getAttribute('version')) - elif node.nodeName == 'Cameras': - for childnode in node.childNodes: - if childnode.nodeName == 'Camera': - self.Scenecamera.append(SceneCamera(node=childnode)) + # elif node.nodeName == 'Cameras': + # for childnode in node.childNodes: + # if childnode.nodeName == 'Camera': + # self.Scenecamera.append(SceneCamera(node=childnode)) elif node.nodeName == 'Bricks': for childnode in node.childNodes: if childnode.nodeName == 'Brick': @@ -720,8 +720,10 @@ class Converter: start_time = time.time() out = open(filename + ".obj.tmp", "w+") + out.truncate(0) out.write("mtllib " + filename + ".mtl" + '\n\n') outtext = open(filename + ".mtl.tmp", "w+") + outtext.truncate(0) total = len(self.scene.Bricks) current = 0 @@ -823,13 +825,13 @@ class Converter: sys.stdout.write('%s\r' % (' ')) # print("--- %s seconds ---" % (time.time() - start_time)) -def setDBFolderVars(dbfolderlocation): +def setDBFolderVars(dbfolderlocation, lod): global PRIMITIVEPATH global GEOMETRIEPATH global DECORATIONPATH global MATERIALNAMESPATH PRIMITIVEPATH = os.path.join(dbfolderlocation, 'Primitives', '') - GEOMETRIEPATH = os.path.join(dbfolderlocation, 'brickprimitives', 'lod0', '') + GEOMETRIEPATH = os.path.join(dbfolderlocation, 'brickprimitives', f'lod{lod}', '') DECORATIONPATH = os.path.join(dbfolderlocation, 'Decorations', '') MATERIALNAMESPATH = os.path.join(dbfolderlocation, 'MaterialNames', '') # print(MATERIALNAMESPATH) @@ -880,7 +882,7 @@ def progress(count, total, status='', suffix = ''): sys.stdout.write('Progress: [%s] %s%s %s %s\r' % (bar, percents, '%', suffix, status)) sys.stdout.flush() -def main(lxf_filename, obj_filename): +def main(lxf_filename, obj_filename, lod="2"): # print("- - - pylddlib - - -") # print(" _ ") # print(" [_]") @@ -890,10 +892,11 @@ def main(lxf_filename, obj_filename): # print(" [=|=]") # print("") # print("- - - - - - - - - - - -") - + global GEOMETRIEPATH + GEOMETRIEPATH = GEOMETRIEPATH + f"LOD{lod}/" converter = Converter() # print("Found DB folder. Will use this instead of db.lif!") - setDBFolderVars(dbfolderlocation = "app/luclient/res/") + setDBFolderVars(dbfolderlocation = "app/luclient/res/", lod=lod) converter.LoadDBFolder(dbfolderlocation = "app/luclient/res/") converter.LoadScene(filename=lxf_filename) converter.Export(filename=obj_filename)