Zum Hauptinhalt springen

Fahrzeug-3D — Modell-Quellen, Rendering & Markierungen am Modell (OP-R6-2)

Status: V-2 gebaut 2026-08-08 (0.161.0), Binding aktiv · Recherche-Provenienz 2026-07-04 · V-1 gebaut 2026-08-02 (0.160.0) — das renderer-neutrale Datenmodell (karosserieTyp + markierungen[] am Auftrag, §5), Karosserietyp-Auswahl bei der Annahme

  • markierung.setzen/entfernen-Handler stehen; V-2 gebaut 2026-08-08 (0.161.0) — sichtbarer Lazy- <model-viewer> (drehbar/zoombar) im Auftrag-Detail, Binding aktiv; V-3 (Markieren-per-Klick) offen; ehemals blockiert durch CC0-GLB-Assets + R2-Bucket taktano-models/Binding (PO-Deploy). (Ursprung: Nutzer-Frage „Gibt es eine Quelle für 3D-Modelle, die wir easy einbetten/drehen können — mit nummerierten Markierungen + Kommentaren/Fotos?") · Bezug: OP-R6-2 (Owning; fachlicher Rahmen Lastenheft §11.1, Aspekt 1 Fahrzeug-Visualisierung) · OP-R7-16 · OP-QS-3 · OP-R7-12 · OP-FEEDBACK-1 · Zielgruppe: IT-Dev/Architektur (primär) · Business/Management (§1–§3 reichen) · True North: Frage 2 (Fahrzeug-Standort) genauer — Markierungen am 3D-Modell zeigen, wo am Fahrzeug etwas ist/passiert (Vorschaden · Zone · Mangel) und machen die Bearbeitungs-Doku räumlich statt nur textuell

Kernaussage. Ja — und günstiger als gedacht. Fahrzeug-Besonderheiten und Schäden werden an einem drehbaren 3D-Modell mit nummerierten Hotspots (Kommentar/Foto) markiert: ein kleines Set generischer Karosserietyp-Modelle (CC0-lizenziert, GLB-Format, z. B. Quaternius/Poly Pizza/Kenney) plus Googles <model-viewer>-Web-Component liefert Drehen/Zoomen und nummerierte Markierungen (Hotspots) out of the box — im Web sofort, auf iOS später über dieselben Assets (GLB → USDZ, RealityKit/Quick Look). Das Markierungs-Datenmodell ist renderer-neutral (§5).

1. Einordnung — das ⚠-Aufwand-Flag relativiert sich​

Das ⚠-Aufwand-Flag aus OP-R6-2 („3D-Asset-Pipeline je Fahrzeugmodell = erheblich") relativiert sich: es galt für fahrzeuggenaue Modelle je Kunden-Pkw. Für den Markierungszweck (Vorschäden, Folierungs-Zonen, Arbeitsbereiche) genügt der Karosserietyp — und fahrzeuggenaue Marken-Modelle wären ohnehin lizenz-/markenrechtlich heikel (§3).

2. Modell-Quelle: generisches Karosserietyp-Set (CC0)​

Empfehlung: ein kuratiertes Set von ca. 7 Karosserietypen — Limousine · Kombi · SUV · Van/ Transporter · Coupé/Sportwagen · Kleinwagen · Pickup (erweiterbar, G-1-analog als Katalog). Bei der Annahme wird der Typ gewählt (später aus FIN/Beschreibung vorgeschlagen, OP-R7-16/OP-R6-2 Aspekt 2).

QuelleLizenzFormatEignung
Quaternius (u. a. Cars Bundle, 8 Modelle)CC0 (auch kommerziell frei)GLB/glTF, FBX✅ Erststufe: konsistenter Low-Poly-Stil, klein (< 1 MB/Modell)
Poly Pizza (Aggregator, CC0-Filter)je Asset (CC0 filterbar)glTF-Download✅ Ergänzung fehlender Typen
Kenney (Car Kit)CC0GLB u. a.✅ Alternative, gleicher Stil-Anspruch
TurboSquid / CGTrader / Fab (Sketchfab) — „generic car" ohne BrandingStandard-Lizenz (Kauf)div.🟡 nur falls später höherwertige neutrale Modelle gewünscht; Redistributions-Klausel beachten (§3)
Marken-genaue Modelle (z. B. „Porsche 911")Editorial/Brand-Restriktionendiv.⛔ nicht verwenden (§3)

Ablage: Assets im R2-Bucket taktano-models (Binding MODELLE_BUCKET in server/wrangler.toml aktiv seit V-2/2026-08-08 — Bucket + karosserie/*-GLBs bereitgestellt; jurisdiction = "eu", Muster OP-QS-2) — hinter Cloudflare Access, mit LICENSE.md je Asset (Quelle · Lizenz · Abrufdatum) als Compliance-Nachweis (OP-COMPLIANCE-1). Keine PII in den Assets → DSGVO-unkritisch; personenbezogen bleiben nur Markierungen/Fotos, die wie bisher als Auftragsdaten behandelt werden (Löschkonzept OP-CRUD-1).

3. Warum nicht fahrzeuggenaue Marken-Modelle?​

  1. Markenrecht: Design/Marke realer Fahrzeuge ist geschützt; Sketchfab führt solche Assets unter Editorial-Lizenz (kommerzielle Nutzung ausgeschlossen), TurboSquid verlangt je Marke Einzelfreigabe des Herstellers.
  2. Redistribution: Kauf-Lizenzen verbieten die Weitergabe in offenen Formaten — ein GLB, das der Browser lädt, ist technisch herunterladbar. CC0 hat dieses Problem nicht.
  3. Kein fachlicher Mehrwert: die Markierung „Kratzer hinten links über dem Radlauf" braucht die Karosserie-Form, nicht das exakte Modell. Modell-Besonderheiten sind Text-Wissen (OP-R6-2 Aspekt 2), keine Geometrie.

4. Rendering Web: <model-viewer> (einfachste tragfähige Lösung)​

@google/model-viewer (v4.3.1, aktiv gepflegt, Apache-2.0; nutzt three.js intern) statt eigenem three.js-/Babylon-Aufbau — Leitprinzip Einfachheit:

  • Drehen/Zoomen/Auto-Rotate: Attribute camera-controls, auto-rotate — null eigener Code.
  • Nummerierte Markierungen = Hotspots: Kind-Elemente mit slot="hotspot-<n>" + data-position/data-normal (Modellkoordinaten) — unsere runden Nummern-Badges (Muster feedback-marker-overlay.component.ts, OP-FEEDBACK-1) als Slot-Inhalt, Styling frei über --tk-*-Tokens.
  • Markierung setzen per Klick/Tap: positionAndNormalFromPoint(x, y) liefert 3D-Position + Normale unter dem Zeiger → direkt das Markierungs-Objekt (§5).
  • Angular 22: Web Component → CUSTOM_ELEMENTS_SCHEMA in der Standalone-Komponente; die Komponente fahrzeug-viewer ist statisch ins Auftrag-Detail importiert, aber die Renderer-Lib @google/model-viewer lädt lazy per dynamic import() beim Öffnen (eigener Chunk, nicht im Initial-Bundle) — kein loadComponent-Boundary nötig; die ~Hunderte-KB-3D-Runtime belastet so die Kern-Workspaces nicht.
  • Abgrenzung: three.js direkt nur, falls später Zonen-Flächen (Mesh-Painting statt Punkt-Marker) nötig werden — dann ist model-viewer durch die Datenmodell-Neutralität (§5) ersetzbar.

5. Markierungs-Datenmodell (renderer-neutral)​

Markierungen sind Daten am Auftrag, kein Renderer-Zustand — Position + Normale in Modellkoordinaten funktionieren identisch in model-viewer (Web), RealityKit (iOS) oder einem späteren Renderer:

// am Auftrag (operativ), analog maengel/protokoll — §4.9-konform (kein eigenes Fahrzeug-Objekt)
interface FahrzeugMarkierung {
id: string;
nummer: number; // stabil vergeben (1, 2, 3 …), springt bei Löschung nicht um
karosserieTyp: string; // Katalog-Key des angezeigten Modells
position: { x: number; y: number; z: number }; // Modellkoordinaten
normal: { x: number; y: number; z: number };
art: "vorschaden" | "mangel"; // Vorschaden (Annahme/Haftung) oder Mangel (Quality-Check, via mangelId)
kommentar?: string; // Freitext (Diktat/Voice später via OP-R7-12)
mangelId?: string; // Verknüpfung Mangel (OP-QS-1/OP-QS-3)
fotoIds?: string[]; // FotoAttachment-IDs (§4.10) — Foto „hängt am Ort"
erstelltUm?: number; // Aktor-Identität NICHT hier — nur im Access-geschützten D1-Audit (keine PII-at-rest)
}

Anschluss an Bestehendes: FotoAttachment (bewusst generisch gebaut), Mangel (bekommt damit den bisher fehlenden Ortsbezug), Offline-Foto-Queue + Upload-Pfad POST /api/foto/upload unverändert. nummer wird gespeichert (Referenz in Kommentaren/Gesprächen muss stabil bleiben — bewusste Ausnahme von „derived nie speichern", da nicht ableitbar nach Löschungen).

6. iOS-nativ später: gleiche Assets, gleiche Daten​

  • GLB bleibt Master. Je Karosserietyp einmalig nach USDZ konvertieren (Apple Reality Converter oder CLI usd_from_gltf) → beide Varianten im selben R2-Bucket.
  • Nativ: RealityKit/SceneKit rendern USDZ; Markierungen (Position/Normale) werden als Entities an denselben Koordinaten gesetzt — das Datenmodell (§5) ist die gemeinsame Sprache.
  • Zwischenschritt ohne App: model-viewer bringt einen AR-Modus mit (iOS Quick Look via USDZ, Android Scene Viewer/WebXR) — „AR vorbereiten" aus OP-R6-2 ist damit strukturell miterledigt.

7. Stufenplan (revidiert) & Aufwand​

OP-R6-2 sah „2D-Silhouette → generisches 3D → modellgenaues 3D → AR" vor. Da die generische 3D-Stufe mit CC0-GLB + model-viewer kaum teurer ist als eine 2D-Silhouette mit Zonen (die als eigenes SVG-Asset-Set auch erst entstehen müsste), kann Stufe 1 direkt generisches 3D sein; „modellgenaues 3D" entfällt bewusst (§3). Vorgeschlagene Slices:

Umsetzungshinweis (2026-08-02): Das Datenmodell (karosserieTyp + markierungen[] am Auftrag, §5) + Karosserietyp-Auswahl bei der Annahme wurden vorgezogen (V-1 unten, 0.160.0) — es trägt Vorschaden- und QS-Use-Case gemeinsam und ist ohne die Asset-/Bucket-Abhängigkeit lauffähig. Die Slice-Nummern unten sind entsprechend re-geschnitten: die reine Datenschicht ist raus aus V-2/V-3 und als V-1 erledigt.

SliceInhaltStatus / Abhängigkeit
V-1 ✅Datenmodell karosserieTyp (Katalog) + markierungen[] am Auftrag (§5), Schema-Migration v23, markierung.setzen/entfernen-Handler (Chronik+Audit), Karosserietyp-Auswahl bei der Annahme + Anzeige am Auftrag-Detailgebaut 0.160.0 (Server+Client, ohne Assets/Bucket)
V-1b ✅CC0-Karosserietyp-GLBs kuratieren (+ LICENSE.md) → R2 taktano-models (karosserie/<key>.glb), Binding aktivieren; GET /models/* bedient nur die Allowlist karosserie/·mediapipe/·nsfwjs/ (serveModellAsset), alle anderen Keys → 404erledigt (PO-Deploy 2026-08-08) — Aufbereitung via scripts/build-fahrzeug-modelle.mjs, Runbook Fahrzeug-Modelle-V1b.md (Bucket/Binding = Bildbewertung §7b)
V-2 ✅3D-Viewer-Komponente fahrzeug-viewer (statisch ins Auftrag-Detail importiert; nur die Renderer-Lib @google/model-viewer lädt lazy per dynamic import() beim Öffnen — kein loadComponent-Boundary), Drehen/Zoomen, lädt GLB je karosserieTyp aus /models/karosserie/<typ>.glb; per Toggle; Fallback + strukturierter Log (ClientObs/OTLP) bei fehlendem Typ/404. Binding MODELLE_BUCKET aktiviert.gebaut 0.161.0 (nach V-1b-Deploy)
V-3Markierungen: setzen per Klick (positionAndNormalFromPoint → markierung.setzen), Nummern-Badges, Kommentar + Foto-Verknüpfung; Sicht in Annahme + Auftrag-DetailV-2; Datenmodell + setzeMarkierung stehen (V-1)
V-4Mangel-Verknüpfung (mangelId bereits im Modell), Quality-Check-Sicht; später AR/USDZ + iOSV-3

Risiken/Kosten: model-viewer-Runtime nur im Lazy-Chunk (Bundle-Disziplin) · Low-Poly-Stil ist eine bewusste Ästhetik-Entscheidung (mit Design-Tokens einfärbbar, kein Fotorealismus — zum Markieren ein Vorteil) · Lizenz-Nachweis je Asset mitführen (§2).

8. Quellen (Recherche 07-04)​

modelviewer.dev · Annotations-Beispiele · web.dev zu model-viewer · Quaternius · Poly Pizza · Kenney · Sketchfab-Lizenzen · TurboSquid-Lizenz · usd_from_gltf · npm @google/model-viewer 4.3.1 (Stand 06/2026).


↩ Zurück zur Doku-Landkarte · Lesepfade · Register (alle OPs)