Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
OpenSim (O)RM Map Generator
#1
OpenSim (O)RM Map Generator
ORM Materialien spiegeln die eigenschaft eines Materials wieder.
Beispiel: Jeans Stoff kann für mehrere Jeans, Schuhe oder Mobillar genutzt werden egal welche Farbe diese Objekte haben es zählt nur die Grundstruktur.

Funktion: Programm starten - Ordner auswählen der Texturen - von zum Beispiel freepbr enthält - dann generieren - und sie werden alle gespeichert.

Python Beispiel:
PHP-Code:
import os
import tkinter 
as tk
from tkinter import filedialog
messageboxttk
from PIL import Image
import glob
import threading

class ORMGeneratorGUI:
    
def __init__(selfroot):
        
self.root root
        self
.root.title("OpenSim (O)RM Map Generator")
        
self.root.geometry("600x400")
        
        
# Variablen
        
self.input_dir tk.StringVar()
        
self.output_dir tk.StringVar()
        
self.progress tk.DoubleVar()
        
self.status tk.StringVar(value="Bereit")
        
        
self.setup_ui()
    
    
def setup_ui(self):
        
# Hauptframe
        
main_frame ttk.Frame(self.rootpadding="10")
        
main_frame.grid(row=0column=0sticky="nsew")
        
        
# Root-Fenster Grid-Konfiguration
        
self.root.columnconfigure(0weight=1)
        
self.root.rowconfigure(0weight=1)
        
        
# Titel
        
title_label ttk.Label(main_frametext="OpenSim (O)RM Map Generator"
                               
font=("Arial"16"bold"))
        
title_label.grid(row=0column=0columnspan=3pady=(020))
        
        
# Eingabe-Verzeichnis Auswahl
        
ttk.Label(main_frametext="Eingabe-Verzeichnis:").grid(row=1column=0sticky=tk.Wpady=5)
        
ttk.Entry(main_frametextvariable=self.input_dirwidth=50).grid(row=1column=1padx=5pady=5)
        
ttk.Button(main_frametext="Durchsuchen"command=self.browse_input_dir).grid(row=1column=2pady=5)
        
        
# Ausgabe-Verzeichnis Auswahl
        
ttk.Label(main_frametext="Ausgabe-Verzeichnis:").grid(row=2column=0sticky=tk.Wpady=5)
        
ttk.Entry(main_frametextvariable=self.output_dirwidth=50).grid(row=2column=1padx=5pady=5)
        
ttk.Button(main_frametext="Durchsuchen"command=self.browse_output_dir).grid(row=2column=2pady=5)
        
        
# Optionen
        
options_frame ttk.LabelFrame(main_frametext="Optionen"padding="5")
        
options_frame.grid(row=3column=0columnspan=3sticky="ew"pady=10)
        
        
self.use_height_for_ao tk.BooleanVar(value=True)
        
ttk.Checkbutton(options_frametext="Height Map für AO verwenden (falls AO fehlt)"
                       
variable=self.use_height_for_ao).grid(row=0column=0sticky=tk.W)
        
        
self.overwrite_existing tk.BooleanVar(value=False)
        
ttk.Checkbutton(options_frametext="Existierende ORM-Maps überschreiben"
                       
variable=self.overwrite_existing).grid(row=1column=0sticky=tk.W)
        
        
# Fortschrittsbalken
        
ttk.Label(main_frametext="Fortschritt:").grid(row=4column=0sticky=tk.Wpady=(100))
        
progress_bar ttk.Progressbar(main_framevariable=self.progresslength=500)
        
progress_bar.grid(row=5column=0columnspan=3sticky="ew"pady=5)
        
        
# Status-Anzeige
        
status_label ttk.Label(main_frametextvariable=self.status)
        
status_label.grid(row=6column=0columnspan=3pady=5)
        
        
# Buttons
        
button_frame ttk.Frame(main_frame)
        
button_frame.grid(row=7column=0columnspan=3pady=20)
        
        
ttk.Button(button_frametext="ORM-Maps generieren"
                  
command=self.start_generation).pack(side=tk.LEFTpadx=5)
        
ttk.Button(button_frametext="Beenden"
                  
command=self.root.quit).pack(side=tk.LEFTpadx=5)
        
        
# Log-Ausgabe
        
log_frame ttk.LabelFrame(main_frametext="Log"padding="5")
        
log_frame.grid(row=8column=0columnspan=3sticky="nsew"pady=10)
        
        
self.log_text tk.Text(log_frameheight=8width=70)
        
scrollbar ttk.Scrollbar(log_frameorient=tk.VERTICALcommand=self.log_text.yview)
        
self.log_text.configure(yscrollcommand=scrollbar.set)
        
        
self.log_text.grid(row=0column=0sticky="nsew")
        
scrollbar.grid(row=0column=1sticky="ns")
        
        
# Grid-Konfiguration
        
main_frame.columnconfigure(1weight=1)
        
log_frame.columnconfigure(0weight=1)
        
log_frame.rowconfigure(0weight=1)
        
main_frame.rowconfigure(8weight=1)
    
    
def browse_input_dir(self):
        
directory filedialog.askdirectory(title="Eingabe-Verzeichnis auswählen")
        if 
directory:
            
self.input_dir.set(directory)
            
# Automatisch Output-Verzeichnis vorschlagen
            
if not self.output_dir.get():
                
self.output_dir.set(os.path.join(directory"ORM_Maps"))
    
    
def browse_output_dir(self):
        
directory filedialog.askdirectory(title="Ausgabe-Verzeichnis auswählen")
        if 
directory:
            
self.output_dir.set(directory)
    
    
def log(selfmessage):
        
self.log_text.insert(tk.ENDmessage "\n")
        
self.log_text.see(tk.END)
        
self.root.update_idletasks()
    
    
def start_generation(self):
        if 
not self.input_dir.get() or not self.output_dir.get():
            
messagebox.showerror("Fehler""Bitte Eingabe- und Ausgabe-Verzeichnis auswählen!")
            return
        
        
# In separatem Thread ausführen, um GUI nicht zu blockieren
        
thread threading.Thread(target=self.generate_orm_maps)
        
thread.daemon True
        thread
.start()
    
    
def generate_orm_maps(self):
        try:
            
input_dir self.input_dir.get()
            
output_dir self.output_dir.get()
            
            
self.status.set("Suche Texturen...")
            
self.progress.set(0)
            
self.log_text.delete(1.0tk.END)
            
            
# Alle Albedo-Texturen finden (case-insensitive und mit Unterordnern)
            
albedo_files = []
            for 
pattern in ["*_albedo.png""*_Albedo.png""*_ALBEDO.png"]:
                
albedo_files.extend(glob.glob(os.path.join(input_dirpattern)))
                
albedo_files.extend(glob.glob(os.path.join(input_dir"**"pattern), recursive=True))
            
            
# Duplikate entfernen
            
albedo_files = list(set(albedo_files))
            
            if 
not albedo_files:
                
self.log("Keine _albedo.png Dateien gefunden!")
                
self.log(f"Durchsuchtes Verzeichnis: {input_dir}")
                
                
# Zeige verfügbare PNG-Dateien zur Diagnose
                
all_pngs glob.glob(os.path.join(input_dir"*.png"))
                if 
all_pngs:
                    
self.log(f"\nGefundene PNG-Dateien ({len(all_pngs)}):")
                    for 
png in all_pngs[:5]:  # Zeige erste 5
                        
self.log(f"  - {os.path.basename(png)}")
                    if 
len(all_pngs) > 5:
                        
self.log(f"  ... und {len(all_pngs) - 5} weitere")
                
                
self.status.set("Fehler: Keine Texturen gefunden")
                return
            
            
self.log(f"Gefunden: {len(albedo_files)} Textur-Sets")
            
self.log("=" 50)
            
            
processed 0
            errors 
0
            
            
for ialbedo_file in enumerate(albedo_files):
                
base_name os.path.basename(albedo_file).replace("_albedo.png""")
                
                
# Fortschritt aktualisieren
                
progress_percent = (len(albedo_files)) * 100
                self
.progress.set(progress_percent)
                
self.status.set(f"Verarbeite: {base_name}")
                
                
# ORM-Map generieren
                
success self.create_single_orm_map(input_diroutput_dirbase_name)
                
                if 
success:
                    
processed += 1
                
else:
                    
errors += 1
            
            
# Abschluss
            
self.progress.set(100)
            
self.status.set("Fertig!")
            
self.log("=" 50)
            
self.log(f"Erfolgreich verarbeitet: {processed}")
            
self.log(f"Fehler: {errors}")
            
self.log(f"ORM-Maps gespeichert in: {output_dir}")
            
            
messagebox.showinfo("Fertig"f"Verarbeitung abgeschlossen!\nErfolgreich: {processed}\nFehler: {errors}")
            
        
except Exception as e:
            
self.log(f"FEHLER: {str(e)}")
            
self.status.set("Fehler aufgetreten")
            
messagebox.showerror("Fehler"f"Ein Fehler ist aufgetreten:\n{str(e)}")
    
    
def create_single_orm_map(selfinput_diroutput_dirbase_name):
        try:
            
# Datei-Pfade
            
ao_file os.path.join(input_dirf"{base_name}_ao.png")
            
roughness_file os.path.join(input_dirf"{base_name}_roughness.png")
            
metallic_file os.path.join(input_dirf"{base_name}_metallic.png")
            
height_file os.path.join(input_dirf"{base_name}_height.png")
            
            
# Output-Pfad
            
output_file os.path.join(output_dirf"{base_name}_ORM.png")
            
            
# Überspringen falls bereits existiert
            
if os.path.exists(output_file) and not self.overwrite_existing.get():
                
self.log(f"Übersprungen (existiert): {base_name}")
                return 
True
            
            
# Falls AO fehlt und Height Map verwendet werden soll
            
if self.use_height_for_ao.get() and not os.path.exists(ao_file) and os.path.exists(height_file):
                
self.log(f"  Verwende Height Map für AO: {base_name}")
                
ao_file height_file
            
            
# Überprüfen ob alle benötigten Dateien existieren
            
missing_files = []
            for 
file_path in [ao_fileroughness_filemetallic_file]:
                if 
not os.path.exists(file_path):
                    
missing_files.append(os.path.basename(file_path))
            
            if 
missing_files:
                
self.log(f"FEHLER {base_name}: Fehlende Dateien - {', '.join(missing_files)}")
                return 
False
            
            
# Bilder laden und verarbeiten
            
ao_img Image.open(ao_file).convert("L")
            
roughness_img Image.open(roughness_file).convert("L")
            
metallic_img Image.open(metallic_file).convert("L")
            
            
# Auf gemeinsame Größe bringen
            
sizes = [img.size for img in [ao_imgroughness_imgmetallic_img]]
            
target_size max(sizeskey=lambda xx[0] * x[1])
            
            if 
ao_img.size != target_size:
                
ao_img ao_img.resize(target_sizeImage.Resampling.LANCZOS)
            if 
roughness_img.size != target_size:
                
roughness_img roughness_img.resize(target_sizeImage.Resampling.LANCZOS)
            if 
metallic_img.size != target_size:
                
metallic_img metallic_img.resize(target_sizeImage.Resampling.LANCZOS)
            
            
# (O)RM Map kombinieren
            
orm_map Image.merge("RGB", (ao_imgroughness_imgmetallic_img))
            
            
# Speichern
            
os.makedirs(output_direxist_ok=True)
            
orm_map.save(output_file"PNG")
            
            
self.log(f"ERFOLG: {base_name} ({target_size[0]}x{target_size[1]})")
            return 
True
            
        except Exception 
as e:
            
self.log(f"FEHLER {base_name}: {str(e)}")
            return 
False

def main
():
    
root tk.Tk()
    
ORMGeneratorGUI(root)
    
root.mainloop()

if 
__name__ == "__main__":
    
main() 

Gemischt angezeigt kommt natürlich etwas heraus was merkwürdig aussieht und erst in RGB zerlegt sinn ergibt.
   
Ein Metaversum sind viele kleine Räume, die nahtlos aneinander passen,
sowie direkt sichtbar und begehbar sind, als wäre es aus einem Guss.



[-] The following 1 user says Thank You to Manfred Aabye for this post:
  • Bogus Curry
Zitieren


Nachrichten in diesem Thema
OpenSim (O)RM Map Generator - von Manfred Aabye - 30.11.2025, 14:53

Möglicherweise verwandte Themen…
Thema Verfasser Antworten Ansichten Letzter Beitrag
  OpenSim Viewer Webinterface Modernisierung Manfred Aabye 3 583 19.10.2025, 11:25
Letzter Beitrag: Manfred Aabye
  OpenSim Currency Server 2025 Manfred Aabye 7 2.446 29.07.2025, 16:00
Letzter Beitrag: Manfred Aabye
  Roth2 Ruth2 für OpenSim Manfred Aabye 0 794 16.04.2025, 18:05
Letzter Beitrag: Manfred Aabye
  Server-Tutorial: Linux und OpenSim Mareta Dagostino 52 103.917 30.12.2024, 22:27
Letzter Beitrag: Pius Noel
Question OpenSim 0.9.3.0 ist jetzt stabil Jupiter Rowland 3 1.738 14.11.2024, 21:16
Letzter Beitrag: Jupiter Rowland

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste