Hausputz: UV-Doppel-Flip raus, tga::load → Result, hide_object entfernt
UVs laufen jetzt durchgehend in glTF-/tga-Konvention (der Flip-Hin-und- Zurück stammte vom gelöschten OBJ-Pfad). Kaputte Welt-Texturen fallen auf den Platzhalter statt zu panicken. Player::eye() statt vierfacher Augenpunkt-Rechnung. hide_object war ein irl3d-Demo-Relikt ohne Konsument. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+16
-9
@@ -101,7 +101,11 @@ pub fn run(mut session: Session) {
|
||||
// FONT_CGA, CURSORS, ORN). Decode (CPU) bleibt in run(); Fonts, Cursor und
|
||||
// Ornament sind weiß-auf-schwarz und bekommen ihre Alpha-Maske aus der
|
||||
// Luminanz.
|
||||
let load_keyed = |p: &str| ui::key_luminance(&tga::load(&assets::path(p)));
|
||||
// UI-Texturen sind Projekt-Assets (kein Autorinnen-Content) — fehlen sie,
|
||||
// ist die Installation kaputt, da darf es scheitern.
|
||||
let load_keyed = |p: &str| {
|
||||
ui::key_luminance(&tga::load(&assets::path(p)).expect("UI-Textur (Projekt-Asset)"))
|
||||
};
|
||||
// Font-Atlanten zuerst keyen, daraus die Glyph-Breiten messen (Font),
|
||||
// dann dieselben Bilder in die GPU-Texturliste übernehmen.
|
||||
let ega_img = load_keyed("assets/textures/fonts/oldschool-ega-8x14.tga");
|
||||
@@ -196,13 +200,17 @@ 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 {
|
||||
let path = assets::path(&format!("assets/textures/{name}.tga"));
|
||||
if std::path::Path::new(&path).exists() {
|
||||
tga::load(&path)
|
||||
} else {
|
||||
eprintln!("[tex] {name}: keine Datei unter {path} — Platzhalter");
|
||||
tga::load(&assets::path(&format!("assets/textures/{}.tga", props::FALLBACK_TEXTURE)))
|
||||
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)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,8 +495,7 @@ impl App {
|
||||
// Klick-Ziele (`signal`-Property). Steuert den Interakt-Cursor und
|
||||
// löst beim Klick unten das `use` aus.
|
||||
let aim: Option<String> = if play {
|
||||
let p = self.session.player.pos;
|
||||
let eye = [p[0], p[1] + player::EYE_HEIGHT, p[2]];
|
||||
let eye = self.session.player.eye();
|
||||
let dir = self.session.player.look_dir();
|
||||
self.session.pick(eye, dir, crate::session::INTERACT_REACH).map(str::to_string)
|
||||
} else {
|
||||
|
||||
+8
-9
@@ -8,11 +8,10 @@
|
||||
//! `assets/textures/{name}.tga` (macht der Aufrufer). Faces ohne Material
|
||||
//! (`""`) laufen unter [`FALLBACK_TEXTURE`].
|
||||
//!
|
||||
//! UVs: das Modell trägt den V-Ursprung unten links, unsere `tga::Image`s
|
||||
//! oben links — V wird hier gespiegelt (Achsen-Konvention ist Sache des
|
||||
//! Konsumenten, siehe engine::tga). Nur `visible`-Objekte werden
|
||||
//! ausgegeben; Collider-/Zonen-Volumen sind Sache von engine::collision
|
||||
//! und engine::trigger.
|
||||
//! UVs kommen unverändert durch (Modell und `tga::Image` teilen den
|
||||
//! Oben-links-Ursprung). Nur `visible`-Objekte werden ausgegeben;
|
||||
//! Collider-/Zonen-Volumen sind Sache von engine::collision und
|
||||
//! engine::trigger.
|
||||
|
||||
use crate::engine::model::Model;
|
||||
use crate::render::scene::{Batch, Mesh, Vertex};
|
||||
@@ -46,7 +45,7 @@ pub fn build(model: &Model, tex_names: &[String]) -> Mesh {
|
||||
if !o.visible { continue; }
|
||||
let base = verts.len() as u32;
|
||||
for (p, uv) in o.verts.iter().zip(&o.uvs) {
|
||||
verts.push(Vertex { pos: *p, uv: [uv[0], 1.0 - uv[1]] }); // V-Flip
|
||||
verts.push(Vertex { pos: *p, uv: *uv });
|
||||
}
|
||||
for (t, &m) in o.tris.iter().zip(&o.tri_mats) {
|
||||
let name = resolve(&model.materials[m]);
|
||||
@@ -93,7 +92,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_only_visible_objects_with_v_flip() {
|
||||
fn builds_only_visible_objects() {
|
||||
let m = sample();
|
||||
let names = texture_names(&m);
|
||||
assert_eq!(names, vec!["carpet".to_string()]);
|
||||
@@ -103,8 +102,8 @@ mod tests {
|
||||
assert_eq!(mesh.verts.len(), 3);
|
||||
assert_eq!(mesh.indices, vec![0, 1, 2]);
|
||||
assert_eq!(mesh.batches.len(), 1);
|
||||
// uv (1,1) → V-Flip → (1,0).
|
||||
assert_eq!(mesh.verts[2].uv, [1.0, 0.0]);
|
||||
// UVs unverändert (geteilte Oben-links-Konvention).
|
||||
assert_eq!(mesh.verts[2].uv, [1.0, 1.0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user