3D-Ansicht: neuer Darstellungsmodus "Schattiert mit Kanten" (BIM-Look)
Neuer RenderStyle::ShadedEdges in render3d: wie "shaded" (echte Bauteilfarben, beleuchtet), zusätzlich dunkle Modell-Kanten obenauf wie bei "hidden" — der typische Revit/ArchiCAD-Look, der bisher fehlte (nur reines Weiss+Kanten via "hidden" oder reine Bauteilfarben ohne Kanten via "shaded" waren möglich). Nutzt dieselbe tiefengebiaste Flächen-Pipeline wie "hidden", damit die Kanten sauber obenauf liegen (kein Z-Fighting). +6 Rust-Tests (--features render, 83/83 grün). Als neue Option "shaded-edges" in beiden Darstellungsart- Dropdowns der 3D-Oberleiste; Three.js-Fallback ignoriert den Wert graceful (fällt auf shaded zurück, bekommt bewusst keine neuen Features).
This commit is contained in:
@@ -46,6 +46,11 @@ pub enum RenderStyle {
|
|||||||
/// Hidden-Line: flach-weisse Flaechen (fuellen den Depth-Buffer) + dunkle
|
/// Hidden-Line: flach-weisse Flaechen (fuellen den Depth-Buffer) + dunkle
|
||||||
/// Kanten obenauf, tiefengetestet -> nur sichtbare Kanten erscheinen.
|
/// Kanten obenauf, tiefengetestet -> nur sichtbare Kanten erscheinen.
|
||||||
Hidden,
|
Hidden,
|
||||||
|
/// "Schattiert mit Kanten" (typischer BIM-Look, z. B. Revit/ArchiCAD): wie
|
||||||
|
/// `Shaded` (echte Bauteilfarben, beleuchtet), ZUSAETZLICH die dunklen
|
||||||
|
/// Modell-Kanten obenauf (wie bei `Hidden`, aber mit Material- statt
|
||||||
|
/// Weiss-Flaechen).
|
||||||
|
ShadedEdges,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderStyle {
|
impl RenderStyle {
|
||||||
@@ -56,18 +61,20 @@ impl RenderStyle {
|
|||||||
"textured" => RenderStyle::Textured,
|
"textured" => RenderStyle::Textured,
|
||||||
"wireframe" => RenderStyle::Wireframe,
|
"wireframe" => RenderStyle::Wireframe,
|
||||||
"hidden" => RenderStyle::Hidden,
|
"hidden" => RenderStyle::Hidden,
|
||||||
|
"shaded-edges" => RenderStyle::ShadedEdges,
|
||||||
_ => RenderStyle::Shaded,
|
_ => RenderStyle::Shaded,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `mode.x`-Wert fuer den Mesh-Shader (siehe shaders.rs): 0 = Material/shaded
|
/// `mode.x`-Wert fuer den Mesh-Shader (siehe shaders.rs): 0 = Material/shaded
|
||||||
/// (auch textured), 1 = weiss/Clay, 2 = flach-weisse Hidden-Line-Flaechen.
|
/// (auch textured/shaded-edges), 1 = weiss/Clay, 2 = flach-weisse
|
||||||
|
/// Hidden-Line-Flaechen.
|
||||||
fn mesh_mode(self) -> f32 {
|
fn mesh_mode(self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
RenderStyle::White => 1.0,
|
RenderStyle::White => 1.0,
|
||||||
RenderStyle::Hidden => 2.0,
|
RenderStyle::Hidden => 2.0,
|
||||||
// Shaded, Textured, Wireframe (Flaechen werden bei Wireframe eh nicht
|
// Shaded, Textured, Wireframe (Flaechen werden bei Wireframe eh nicht
|
||||||
// gezeichnet) -> Material.
|
// gezeichnet), ShadedEdges -> Material.
|
||||||
_ => 0.0,
|
_ => 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +86,19 @@ impl RenderStyle {
|
|||||||
|
|
||||||
/// Werden in diesem Stil Modell-Kanten gezeichnet?
|
/// Werden in diesem Stil Modell-Kanten gezeichnet?
|
||||||
fn draws_edges(self) -> bool {
|
fn draws_edges(self) -> bool {
|
||||||
matches!(self, RenderStyle::Wireframe | RenderStyle::Hidden)
|
matches!(
|
||||||
|
self,
|
||||||
|
RenderStyle::Wireframe | RenderStyle::Hidden | RenderStyle::ShadedEdges
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Braucht dieser Stil die leicht nach hinten gebiaste Flaechen-Pipeline,
|
||||||
|
/// damit die (tiefengetesteten) Kanten sauber obenauf liegen, statt mit den
|
||||||
|
/// Flaechen zu flackern (Z-Fighting)? Gilt fuer alle Stile, die BEIDES
|
||||||
|
/// zeichnen (Flaechen + Kanten) — bislang nur `Hidden`, jetzt auch
|
||||||
|
/// `ShadedEdges`.
|
||||||
|
fn needs_biased_face_pipeline(self) -> bool {
|
||||||
|
matches!(self, RenderStyle::Hidden | RenderStyle::ShadedEdges)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,7 +1362,7 @@ impl Renderer {
|
|||||||
pass.draw_indexed(0..t.index_count, 0, 0..1);
|
pass.draw_indexed(0..t.index_count, 0, 0..1);
|
||||||
}
|
}
|
||||||
} else if let Some(m) = &self.mesh {
|
} else if let Some(m) = &self.mesh {
|
||||||
let face_pipeline = if self.style == RenderStyle::Hidden {
|
let face_pipeline = if self.style.needs_biased_face_pipeline() {
|
||||||
&self.hidden_face_pipeline
|
&self.hidden_face_pipeline
|
||||||
} else {
|
} else {
|
||||||
&self.pipeline
|
&self.pipeline
|
||||||
@@ -1418,3 +1437,48 @@ impl Renderer {
|
|||||||
queue.submit(std::iter::once(encoder.finish()));
|
queue.submit(std::iter::once(encoder.finish()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod render_style_tests {
|
||||||
|
use super::RenderStyle;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shaded_edges_parses_from_api_string() {
|
||||||
|
assert_eq!(
|
||||||
|
RenderStyle::from_str_or_shaded("shaded-edges"),
|
||||||
|
RenderStyle::ShadedEdges
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown_style_falls_back_to_shaded() {
|
||||||
|
assert_eq!(RenderStyle::from_str_or_shaded("bogus"), RenderStyle::Shaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shaded_edges_uses_material_colors_like_shaded() {
|
||||||
|
// mode.x = 0.0 -> Material/Bauteilfarben, NICHT weiss (1.0) oder
|
||||||
|
// Hidden-Line-Flaechen (2.0) — der BIM-Look behaelt echte Farben.
|
||||||
|
assert_eq!(RenderStyle::ShadedEdges.mesh_mode(), 0.0);
|
||||||
|
assert_eq!(RenderStyle::Shaded.mesh_mode(), RenderStyle::ShadedEdges.mesh_mode());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shaded_edges_draws_both_faces_and_edges() {
|
||||||
|
assert!(RenderStyle::ShadedEdges.draws_faces());
|
||||||
|
assert!(RenderStyle::ShadedEdges.draws_edges());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shaded_edges_needs_biased_face_pipeline_like_hidden() {
|
||||||
|
assert!(RenderStyle::ShadedEdges.needs_biased_face_pipeline());
|
||||||
|
assert!(RenderStyle::Hidden.needs_biased_face_pipeline());
|
||||||
|
assert!(!RenderStyle::Shaded.needs_biased_face_pipeline());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn plain_shaded_style_unaffected_by_new_variant() {
|
||||||
|
assert!(!RenderStyle::Shaded.draws_edges());
|
||||||
|
assert!(RenderStyle::Shaded.draws_faces());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -389,6 +389,9 @@ impl WebModelRenderer {
|
|||||||
/// - `"wireframe"`— nur Modell-Kanten (Feature-Edges), keine Flaechen.
|
/// - `"wireframe"`— nur Modell-Kanten (Feature-Edges), keine Flaechen.
|
||||||
/// - `"hidden"` — Hidden-Line: flach-weisse Flaechen fuellen den Depth-
|
/// - `"hidden"` — Hidden-Line: flach-weisse Flaechen fuellen den Depth-
|
||||||
/// Buffer, dunkle Kanten liegen tiefengetestet obenauf (nur sichtbare).
|
/// Buffer, dunkle Kanten liegen tiefengetestet obenauf (nur sichtbare).
|
||||||
|
/// - `"shaded-edges"` — "Schattiert mit Kanten" (typischer BIM-Look): wie
|
||||||
|
/// `"shaded"` (echte Bauteilfarben), ZUSAETZLICH dunkle Modell-Kanten
|
||||||
|
/// obenauf wie bei `"hidden"`.
|
||||||
/// Unbekannte Werte fallen auf `"shaded"` zurueck. Wirkt erst beim naechsten
|
/// Unbekannte Werte fallen auf `"shaded"` zurueck. Wirkt erst beim naechsten
|
||||||
/// `render`. Loest `set_render_mode_white` ab (das bleibt kompatibel).
|
/// `render`. Loest `set_render_mode_white` ab (das bleibt kompatibel).
|
||||||
pub fn set_render_style(&mut self, style: &str) -> Result<(), JsValue> {
|
pub fn set_render_style(&mut self, style: &str) -> Result<(), JsValue> {
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ export const de = {
|
|||||||
"display.style.color": "Farbig",
|
"display.style.color": "Farbig",
|
||||||
"display.style.mono": "Schwarz-Weiss",
|
"display.style.mono": "Schwarz-Weiss",
|
||||||
"display.style.shaded": "Schattiert",
|
"display.style.shaded": "Schattiert",
|
||||||
|
"display.style.shadedEdges": "Schattiert mit Kanten",
|
||||||
"display.style.white": "Weiss",
|
"display.style.white": "Weiss",
|
||||||
"display.style.textured": "Texturiert",
|
"display.style.textured": "Texturiert",
|
||||||
"display.style.wireframe": "Drahtgitter",
|
"display.style.wireframe": "Drahtgitter",
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ export const en: Record<TranslationKey, string> = {
|
|||||||
"display.style.color": "Color",
|
"display.style.color": "Color",
|
||||||
"display.style.mono": "Black & white",
|
"display.style.mono": "Black & white",
|
||||||
"display.style.shaded": "Shaded",
|
"display.style.shaded": "Shaded",
|
||||||
|
"display.style.shadedEdges": "Shaded with edges",
|
||||||
"display.style.white": "White",
|
"display.style.white": "White",
|
||||||
"display.style.textured": "Textured",
|
"display.style.textured": "Textured",
|
||||||
"display.style.wireframe": "Wireframe",
|
"display.style.wireframe": "Wireframe",
|
||||||
|
|||||||
+7
-3
@@ -50,15 +50,17 @@ export type DetailLevel = "grob" | "mittel" | "fein";
|
|||||||
/**
|
/**
|
||||||
* Render-/Anzeigemodus der 3D-Ansicht: schattiert, einheitlich weiss (Clay-Look),
|
* Render-/Anzeigemodus der 3D-Ansicht: schattiert, einheitlich weiss (Clay-Look),
|
||||||
* texturiert (echte PBR-Materialien je Bauteil), Drahtgitter, Verdeckte Kanten
|
* texturiert (echte PBR-Materialien je Bauteil), Drahtgitter, Verdeckte Kanten
|
||||||
* (Hidden-Line). Wirkt nur in der Perspektive. Der Slot „section" (Schnitt-
|
* (Hidden-Line), Schattiert mit Kanten (typischer BIM-Look: Bauteilfarben +
|
||||||
* schraffur, Welle B) ist bewusst freigelassen.
|
* Modell-Kanten obenauf). Wirkt nur in der Perspektive. Der Slot „section"
|
||||||
|
* (Schnittschraffur, Welle B) ist bewusst freigelassen.
|
||||||
*/
|
*/
|
||||||
export type RenderMode =
|
export type RenderMode =
|
||||||
| "shaded"
|
| "shaded"
|
||||||
| "white"
|
| "white"
|
||||||
| "textured"
|
| "textured"
|
||||||
| "wireframe"
|
| "wireframe"
|
||||||
| "hidden";
|
| "hidden"
|
||||||
|
| "shaded-edges";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kanonischer Blickwinkel der 3D-Ansicht (Vectorworks/DOSSIER-Stil). „front"/
|
* Kanonischer Blickwinkel der 3D-Ansicht (Vectorworks/DOSSIER-Stil). „front"/
|
||||||
@@ -1591,6 +1593,7 @@ export function ViewRibbonTab({
|
|||||||
title={t("display.style.hint")}
|
title={t("display.style.hint")}
|
||||||
options={[
|
options={[
|
||||||
{ value: "shaded", label: t("display.style.shaded") },
|
{ value: "shaded", label: t("display.style.shaded") },
|
||||||
|
{ value: "shaded-edges", label: t("display.style.shadedEdges") },
|
||||||
{ value: "white", label: t("display.style.white") },
|
{ value: "white", label: t("display.style.white") },
|
||||||
{ value: "textured", label: t("display.style.textured") },
|
{ value: "textured", label: t("display.style.textured") },
|
||||||
{ value: "wireframe", label: t("display.style.wireframe") },
|
{ value: "wireframe", label: t("display.style.wireframe") },
|
||||||
@@ -1796,6 +1799,7 @@ export function Ribbon3dTab({
|
|||||||
title={t("display.style.hint")}
|
title={t("display.style.hint")}
|
||||||
options={[
|
options={[
|
||||||
{ value: "shaded", label: t("display.style.shaded") },
|
{ value: "shaded", label: t("display.style.shaded") },
|
||||||
|
{ value: "shaded-edges", label: t("display.style.shadedEdges") },
|
||||||
{ value: "white", label: t("display.style.white") },
|
{ value: "white", label: t("display.style.white") },
|
||||||
{ value: "textured", label: t("display.style.textured") },
|
{ value: "textured", label: t("display.style.textured") },
|
||||||
{ value: "wireframe", label: t("display.style.wireframe") },
|
{ value: "wireframe", label: t("display.style.wireframe") },
|
||||||
|
|||||||
Reference in New Issue
Block a user