こんにちは。
今回は、別に説明や紹介ではなく初めての日記になります。
多分見てくれる人は少ないと思いますが、何もしてない春休みの最後の1週間前に2日で作ったので、春休みの存在意義として残させてください。
ちなみに高専なので春休みが1.5か月くらいあります。
何をしたか
こんな感じです。
コマンドを打ったら自動で3Dモデルが作られます。
そして自動でマイクラのモデルに変換してlitematicaの形式に出力して保存しています。
ちなみにポストのとおり、モデルが紫色になってしまします。
blenderでよくあるマテリアルエラーですかね。
作り方
結構ごり押しな作り方です。
マイクラの「建築を学習させて~」みたいなことはやっていません。
流れ的には、「fabricのMODからポストを送信する」→「Hunyuan3Dで作成」→「ObjToSchematic」で変換って感じです。
ではMODを作っていきましょーって思ったんですが
どこから書けばいいのかわからないので取りあえずメインのコードを書いていおきます。
package com.example;
import com.mojang.brigadier.arguments.StringArgumentType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.server.command.CommandManager;
import net.minecraft.text.Text;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class Create_model implements ModInitializer {
public static final String MOD_ID = "create_model";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
private final OkHttpClient client = new OkHttpClient();
@Override
public void onInitialize() {
LOGGER.info("Hello Fabric world!");
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(
CommandManager.literal("createmodel")
.then(CommandManager.argument("modelName", StringArgumentType.greedyString())
.executes(context -> {
String modelName = context.getArgument("modelName", String.class);
context.getSource().sendMessage(Text.literal("モデル名: " + modelName));
context.getSource().sendMessage(Text.literal("作成しています..."));
// JSONを作成
String json = "{\"text\":\"" + modelName + "\"}";
// HTTPリクエストを作成
RequestBody body = RequestBody.create(json, MediaType.parse("application/json"));
Request request = new Request.Builder()
.url("http://localhost:5000")
.post(body)
.build();
// HTTPリクエストを送信
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(130000);
} catch (InterruptedException e) {
e.printStackTrace();
}
context.getSource().sendMessage(Text.literal("完了しました!"));
return 1;
})
)
);
});
}
}
次にサーバー(?)側の処理を書こうとしたのですがファイルをなくしたので
リクエストを受け取る機能がないコードを書いておきます。
flaskとか使って使えるようにしてください。
import os
import time
import zipfile
from flask import Flask, request, jsonify
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import pyautogui
import easyocr
app = Flask(__name__)
download_dir = r"C:\Users\ユーザー名\Downloads"
chrome_options = Options()
prefs = {
"download.default_directory": download_dir,
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"safebrowsing.enabled": False,
"profile.default_content_settings.popups": 0,
"profile.content_settings.exceptions.automatic_downloads.*.setting": 1
}
chrome_options.add_experimental_option("prefs", prefs)
def run_text_generation(prompt):
driver = webdriver.Chrome(options=chrome_options)
driver.get("http://localhost:8080")
reader = easyocr.Reader(['en'])
time.sleep(1)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "Text Prompt" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(1)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "will be used to generate" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(1)
pyautogui.write(prompt)
time.sleep(2)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "Textured" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(130)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "Advanced" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
pyautogui.move(80, 0)
pyautogui.click()
break
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "glb" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "obj" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "Transform" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(10)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "Download" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(2)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "存" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
driver.quit()
return "Text generation process completed"
def run_mesh_generation():
new_download_dir = r"マイクラへのパス\data\instances\ai\instance\saves\New World\generated\minecraft\structures"
driver = webdriver.Chrome(options=chrome_options)
driver.get("http://192.168.0.218:8080")
reader = easyocr.Reader(['en','ja'])
time.sleep(1)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "chosen" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
pyautogui.move(120, 0)
pyautogui.click()
break
time.sleep(1)
file_path = r'.\Downloads\textured_mesh.obj'
pyautogui.write(file_path)
pyautogui.press("enter")
time.sleep(2)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "mesh" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(5)
for _ in range(50):
pyautogui.scroll(-500, x=400, y=500)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "Voxelise" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(3)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "Assign" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "Lite" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "nbt" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "structure" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(2)
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
ocr_result = reader.readtext("screenshot.png", detail=1)
for (bbox, text, prob) in ocr_result:
if "存" in text:
(x_min, y_min), (x_max, y_max) = bbox[0], bbox[2]
pyautogui.click((x_min + x_max) // 2, (y_min + y_max) // 2)
break
time.sleep(10)
for file_name in os.listdir(new_download_dir):
if file_name.endswith(".zip"):
zip_path = os.path.join(new_download_dir, file_name)
extract_path = os.path.join(new_download_dir, os.path.splitext(file_name)[0])
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(extract_path)
for file_name in os.listdir(extract_path):
file_path = os.path.join(extract_path, file_name)
if os.path.isfile(file_path):
destination_path = os.path.join(new_download_dir, file_name)
os.rename(file_path, destination_path)
os.rmdir(extract_path)
driver.quit()
return "Mesh generation process completed"
@app.route('/generate', methods=['POST'])
def generate():
data = request.get_json()
gen_type = data.get("type")
if gen_type == "text":
prompt = data.get("prompt", "a house")
result = run_text_generation(prompt)
elif gen_type == "mesh":
result = run_mesh_generation()
else:
return jsonify({"error": "Invalid type"}), 400
return jsonify({"result": result})
if __name__ == '__main__':
app.run(port=5000)
パスは適宜置き換えてください。
そしてhttps://github.com/YanWenKun/Hunyuan3D-2-WinPortable/releases からクローンして、実行してHunyuan3Dのサーバーを立てます。
次にhttps://github.com/LucasDower/ObjToSchematic こっちもクローンして起動しておきます。
ブラウザをOCRして無理やり操作しているので生成している間は触らないで下さい。
僕の場合は2画面なのでサブのほうに起動させていたので実質的に自動でした。
「a blue house」と実行した結果。


実用的かはどうなんだろ

とある高専生。
AIとネットが好き。
将来はAIの妹と火星に住みたい。
discord : r_nightcore
このサイトの管理者。
コメント