Welt-Texturen aus der .glb statt aus assets/textures/
Der Loader zieht jetzt die baseColorTexture jedes Materials aus dem BIN-Chunk und dekodiert sie (PNG, via png-Crate) → model::Texture mit Pixeln. Die Namenskonvention "Materialname = Dateiname" und der assets/textures/-Pfad für Welt-Texturen entfallen; assets/textures/ bleibt nur noch für UI/Fonts/Platzhalter. - engine::image: neuer, geteilter RGBA8-Image-Typ (aus tga.rs gezogen) plus PNG-Decoder. tga.rs liefert weiter denselben Typ. - gltf: material -> texture -> image -> bufferView auflösen, Bild aus BIN dekodieren; fehlt ein Glied, bleibt image None (Platzhalter). KHR_texture_transform (Blenders Mapping-Node) wird beim Laden in die UVs eingebacken. - model::Model: materials: Vec<String> -> textures: Vec<Texture>. - render: die Pixel je Schlüssel aus den Modellen sammeln (erstes Vorkommen gewinnt, Schlüssel ohne Bild -> Platzhalter). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0196AM4UyAJEXVtPvp5DdKr8
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
937fbd6ede
commit
fc3494466e
+24
-17
@@ -29,8 +29,8 @@ use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||
use winit::keyboard::{KeyCode, PhysicalKey};
|
||||
use winit::window::{CursorGrabMode, Window, WindowId};
|
||||
|
||||
use crate::engine::image::Image;
|
||||
use crate::engine::player;
|
||||
use crate::engine::tga::Image;
|
||||
use crate::engine::{assets, gltf, model, tga, wav};
|
||||
use crate::session::{FrameInput, Mode, Session};
|
||||
use gpu::Gpu;
|
||||
@@ -58,13 +58,26 @@ pub fn run(mut session: Session, maps_dir: &str) {
|
||||
// `Gpu` — die beiden bleiben getrennt.
|
||||
let models = load_models(maps_dir);
|
||||
|
||||
// Eine geteilte Texturliste über alle Modelle, damit ihre Meshes
|
||||
// denselben Index-Raum benutzen und zu einem Buffer verschmelzen können.
|
||||
// Eine geteilte Textur-Schlüsselliste über alle Modelle, damit ihre
|
||||
// Meshes denselben Index-Raum benutzen und zu einem Buffer verschmelzen.
|
||||
let mut tex_names: Vec<String> = Vec::new();
|
||||
for (_, m) in &models { tex_names.extend(props::texture_names(m)); }
|
||||
for (_, m) in &models { tex_names.extend(props::texture_keys(m)); }
|
||||
tex_names.sort_unstable();
|
||||
tex_names.dedup();
|
||||
let images: Vec<Image> = tex_names.iter().map(|n| load_texture(n)).collect();
|
||||
|
||||
// Die Pixel liegen in den `.glb` selbst; gleicher Schlüssel = eine Textur
|
||||
// (erstes Vorkommen gewinnt). Schlüssel ohne Bild treffen den Platzhalter
|
||||
// (Projekt-Asset, darf hart scheitern).
|
||||
let mut by_key: HashMap<&str, &Image> = HashMap::new();
|
||||
for (_, m) in &models {
|
||||
for t in &m.textures {
|
||||
if let Some(img) = &t.image { by_key.entry(props::texture_key(t)).or_insert(img); }
|
||||
}
|
||||
}
|
||||
let placeholder = placeholder();
|
||||
let images: Vec<Image> = tex_names.iter()
|
||||
.map(|k| by_key.get(k.as_str()).map_or_else(|| placeholder.clone(), |i| (*i).clone()))
|
||||
.collect();
|
||||
|
||||
let mut mesh = Mesh::default();
|
||||
for (_, m) in &models { mesh.append(props::build(m, &tex_names)); }
|
||||
@@ -186,18 +199,12 @@ fn load_sound(name: &str) -> Option<audio::Sound> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Welt-Textur laden. Autorinnen-Content: fehlt oder klemmt die Datei, wird
|
||||
/// gemeldet und der Platzhalter genommen — der selbst ist Projekt-Asset und
|
||||
/// darf hart scheitern.
|
||||
fn load_texture(name: &str) -> Image {
|
||||
match tga::load(&assets::path(&format!("assets/textures/{name}.tga"))) {
|
||||
Ok(img) => img,
|
||||
Err(e) => {
|
||||
eprintln!("[tex] {e} — Platzhalter");
|
||||
tga::load(&assets::path(&format!("assets/textures/{}.tga", props::FALLBACK_TEXTURE)))
|
||||
.expect("Platzhalter-Textur (Projekt-Asset)")
|
||||
}
|
||||
}
|
||||
/// Die Platzhalter-Textur für Schlüssel ohne eigenes Bild in der `.glb`.
|
||||
/// Projekt-Asset: fehlt sie, ist die Installation kaputt und es darf scheitern.
|
||||
fn placeholder() -> Image {
|
||||
let name = props::FALLBACK_TEXTURE;
|
||||
tga::load(&assets::path(&format!("assets/textures/{name}.tga")))
|
||||
.expect("Platzhalter-Textur (Projekt-Asset)")
|
||||
}
|
||||
|
||||
/// Aktueller Eingabezustand. Tasten als gehaltene Flags (nicht Events),
|
||||
|
||||
Reference in New Issue
Block a user