forked from 1b-agent/opencadstudio-upstream
feat(scene): integrate standard DWG data
This commit is contained in:
1 parent
731df4a725
commit
eb23715605
38 files changed
+8376
-618
No files matched your search
@@ -0,0 +1,278 @@
|
||||
use acadrust::objects::{
|
||||
ObjectType, VisualStyle, VisualStyleProperty, VisualStylePropertyValue,
|
||||
};
|
||||
use acadrust::{CadDocument, EntityType, Handle};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MeshVisualStyle {
|
||||
pub full_handle: Option<Handle>,
|
||||
pub face_handle: Option<Handle>,
|
||||
pub edge_handle: Option<Handle>,
|
||||
pub description: String,
|
||||
pub style_type: i16,
|
||||
pub face_lighting_model: i16,
|
||||
pub face_lighting_quality: i16,
|
||||
pub face_color_mode: i16,
|
||||
pub face_modifier: i32,
|
||||
pub face_opacity: f32,
|
||||
pub face_specular: f32,
|
||||
pub mono_color: Option<[f32; 4]>,
|
||||
pub edge_model: i32,
|
||||
pub edge_style: i32,
|
||||
pub edge_color: Option<[f32; 4]>,
|
||||
pub edge_opacity: f32,
|
||||
pub edge_width: f32,
|
||||
pub edge_overhang: i32,
|
||||
pub edge_jitter: i32,
|
||||
pub silhouette_color: Option<[f32; 4]>,
|
||||
pub silhouette_width: i32,
|
||||
pub halo_gap: i32,
|
||||
pub isoline_count: i32,
|
||||
pub hide_precision: bool,
|
||||
pub display_settings: i32,
|
||||
pub brightness: f32,
|
||||
pub shadow_type: i32,
|
||||
pub extended_lighting_model: i16,
|
||||
pub internal_use_only: bool,
|
||||
}
|
||||
|
||||
fn core_property(style: &VisualStyle, index: usize) -> Option<&VisualStyleProperty> {
|
||||
if style.properties.len() >= 28 {
|
||||
return style.properties.get(index);
|
||||
}
|
||||
if style.properties.len() == 24 {
|
||||
let legacy = match index {
|
||||
4 => 0,
|
||||
5 => 1,
|
||||
6 => 2,
|
||||
9 => 3,
|
||||
10 => 4,
|
||||
11 => 5,
|
||||
13 => 6,
|
||||
14 => 7,
|
||||
15 => 8,
|
||||
16 => 9,
|
||||
17 => 10,
|
||||
18 => 11,
|
||||
19 => 12,
|
||||
20 => 13,
|
||||
21 => 14,
|
||||
22 => 15,
|
||||
23 => 16,
|
||||
24 => 17,
|
||||
12 => 19,
|
||||
25 => 20,
|
||||
26 => 21,
|
||||
27 => 22,
|
||||
_ => return None,
|
||||
};
|
||||
return style.properties.get(legacy);
|
||||
}
|
||||
style.properties.get(index)
|
||||
}
|
||||
|
||||
fn property_double(style: &VisualStyle, index: usize, fallback: f64) -> f64 {
|
||||
let Some(property) = core_property(style, index) else {
|
||||
return fallback;
|
||||
};
|
||||
match property.value {
|
||||
VisualStylePropertyValue::Short(value) => value as f64,
|
||||
VisualStylePropertyValue::Long(value) => value as f64,
|
||||
VisualStylePropertyValue::Double(value) => value,
|
||||
VisualStylePropertyValue::Bool(value) => value as u8 as f64,
|
||||
_ => fallback,
|
||||
}
|
||||
}
|
||||
|
||||
fn property_long(style: &VisualStyle, index: usize, fallback: i32) -> i32 {
|
||||
property_double(style, index, fallback as f64) as i32
|
||||
}
|
||||
|
||||
fn property_bool(style: &VisualStyle, index: usize, fallback: bool) -> bool {
|
||||
property_double(style, index, fallback as u8 as f64) != 0.0
|
||||
}
|
||||
|
||||
fn property_color(style: &VisualStyle, index: usize) -> Option<[f32; 4]> {
|
||||
let property = core_property(style, index)?;
|
||||
if property.enabled == 0 {
|
||||
return None;
|
||||
}
|
||||
let VisualStylePropertyValue::Color(color) = &property.value else {
|
||||
return None;
|
||||
};
|
||||
if matches!(
|
||||
color,
|
||||
acadrust::types::Color::ByLayer | acadrust::types::Color::ByBlock
|
||||
) {
|
||||
return None;
|
||||
}
|
||||
Some(crate::scene::convert::tess_util::aci_to_rgba(color))
|
||||
}
|
||||
|
||||
impl MeshVisualStyle {
|
||||
fn from_dwg(handle: Handle, style: &VisualStyle) -> Self {
|
||||
Self {
|
||||
full_handle: Some(handle),
|
||||
face_handle: None,
|
||||
edge_handle: None,
|
||||
description: style.description.clone(),
|
||||
style_type: style.style_type,
|
||||
face_lighting_model: style.face_lighting_model,
|
||||
face_lighting_quality: style.face_lighting_quality,
|
||||
face_color_mode: style.face_color_mode,
|
||||
face_modifier: style.face_modifier,
|
||||
face_opacity: property_double(style, 4, 1.0).clamp(0.0, 1.0) as f32,
|
||||
face_specular: property_double(style, 5, 0.0).max(0.0) as f32,
|
||||
mono_color: property_color(style, 6),
|
||||
edge_model: style.edge_model,
|
||||
edge_style: style.edge_style,
|
||||
edge_color: property_color(style, 15),
|
||||
edge_opacity: property_double(style, 16, 1.0).clamp(0.0, 1.0) as f32,
|
||||
edge_width: property_double(style, 17, 1.0).max(0.0) as f32,
|
||||
edge_overhang: property_long(style, 18, 0),
|
||||
edge_jitter: property_long(style, 19, 0),
|
||||
silhouette_color: property_color(style, 20),
|
||||
silhouette_width: property_long(style, 21, 0),
|
||||
halo_gap: property_long(style, 22, 0),
|
||||
isoline_count: property_long(style, 23, 0),
|
||||
hide_precision: property_bool(style, 24, false),
|
||||
display_settings: property_long(style, 25, 0),
|
||||
brightness: property_double(style, 26, 0.0) as f32,
|
||||
shadow_type: if style.properties.len() == 24 {
|
||||
style
|
||||
.properties
|
||||
.get(23)
|
||||
.map_or(0, |property| match property.value {
|
||||
VisualStylePropertyValue::Short(value) => value as i32,
|
||||
VisualStylePropertyValue::Long(value) => value,
|
||||
VisualStylePropertyValue::Double(value) => value as i32,
|
||||
VisualStylePropertyValue::Bool(value) => value as i32,
|
||||
_ => 0,
|
||||
})
|
||||
} else {
|
||||
property_long(style, 27, 0)
|
||||
},
|
||||
extended_lighting_model: style.extended_lighting_model,
|
||||
internal_use_only: style.internal_use_only,
|
||||
}
|
||||
}
|
||||
|
||||
fn override_face(&mut self, handle: Handle, style: &VisualStyle) {
|
||||
let source = Self::from_dwg(handle, style);
|
||||
self.face_handle = Some(handle);
|
||||
self.face_lighting_model = source.face_lighting_model;
|
||||
self.face_lighting_quality = source.face_lighting_quality;
|
||||
self.face_color_mode = source.face_color_mode;
|
||||
self.face_modifier = source.face_modifier;
|
||||
self.face_opacity = source.face_opacity;
|
||||
self.face_specular = source.face_specular;
|
||||
self.mono_color = source.mono_color;
|
||||
self.brightness = source.brightness;
|
||||
self.extended_lighting_model = source.extended_lighting_model;
|
||||
}
|
||||
|
||||
fn override_edge(&mut self, handle: Handle, style: &VisualStyle) {
|
||||
let source = Self::from_dwg(handle, style);
|
||||
self.edge_handle = Some(handle);
|
||||
self.edge_model = source.edge_model;
|
||||
self.edge_style = source.edge_style;
|
||||
self.edge_color = source.edge_color;
|
||||
self.edge_opacity = source.edge_opacity;
|
||||
self.edge_width = source.edge_width;
|
||||
self.edge_overhang = source.edge_overhang;
|
||||
self.edge_jitter = source.edge_jitter;
|
||||
self.silhouette_color = source.silhouette_color;
|
||||
self.silhouette_width = source.silhouette_width;
|
||||
self.halo_gap = source.halo_gap;
|
||||
self.isoline_count = source.isoline_count;
|
||||
self.hide_precision = source.hide_precision;
|
||||
}
|
||||
|
||||
pub fn face_visible(&self) -> bool {
|
||||
self.face_lighting_model != 0 && self.face_color_mode != 0
|
||||
}
|
||||
|
||||
pub fn edges_visible(&self) -> bool {
|
||||
self.edge_model != 0
|
||||
}
|
||||
|
||||
pub fn face_color(&self, base: [f32; 4]) -> [f32; 4] {
|
||||
let mut color = match self.face_color_mode {
|
||||
3 | 4 => self.mono_color.unwrap_or(base),
|
||||
5 => {
|
||||
let tint = self.mono_color.unwrap_or(base);
|
||||
[
|
||||
(base[0] + tint[0]) * 0.5,
|
||||
(base[1] + tint[1]) * 0.5,
|
||||
(base[2] + tint[2]) * 0.5,
|
||||
base[3],
|
||||
]
|
||||
}
|
||||
6 => {
|
||||
let luminance = base[0] * 0.2126 + base[1] * 0.7152 + base[2] * 0.0722;
|
||||
[
|
||||
base[0] * 0.7 + luminance * 0.3,
|
||||
base[1] * 0.7 + luminance * 0.3,
|
||||
base[2] * 0.7 + luminance * 0.3,
|
||||
base[3],
|
||||
]
|
||||
}
|
||||
_ => base,
|
||||
};
|
||||
if self.face_modifier & 1 != 0 {
|
||||
color[3] *= self.face_opacity;
|
||||
}
|
||||
color
|
||||
}
|
||||
|
||||
pub fn edge_color(&self, base: [f32; 4]) -> [f32; 4] {
|
||||
let mut color = self.edge_color.unwrap_or(base);
|
||||
color[3] *= self.edge_opacity;
|
||||
color
|
||||
}
|
||||
}
|
||||
|
||||
fn visual_style(
|
||||
document: &CadDocument,
|
||||
handle: Option<Handle>,
|
||||
) -> Option<(Handle, &VisualStyle)> {
|
||||
let handle = handle.filter(|handle| handle.is_valid())?;
|
||||
match document.objects.get(&handle) {
|
||||
Some(ObjectType::VisualStyle(style)) => Some((handle, style)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_mesh_visual_style(
|
||||
document: &CadDocument,
|
||||
entity: &EntityType,
|
||||
) -> Option<MeshVisualStyle> {
|
||||
let common = entity.common();
|
||||
let full = visual_style(document, common.full_visual_style_handle);
|
||||
let face = visual_style(document, common.face_visual_style_handle);
|
||||
let edge = visual_style(document, common.edge_visual_style_handle);
|
||||
let mut result = full
|
||||
.map(|(handle, style)| MeshVisualStyle::from_dwg(handle, style))
|
||||
.or_else(|| {
|
||||
face.or(edge)
|
||||
.map(|(handle, style)| MeshVisualStyle::from_dwg(handle, style))
|
||||
})?;
|
||||
if full.is_none() {
|
||||
result.full_handle = None;
|
||||
}
|
||||
if let Some((handle, style)) = face {
|
||||
result.override_face(handle, style);
|
||||
}
|
||||
if let Some((handle, style)) = edge {
|
||||
result.override_edge(handle, style);
|
||||
}
|
||||
Some(result)
|
||||
}
|
||||
|
||||
pub fn apply_mesh_visual_style(
|
||||
set: &mut super::mesh_model::MeshLodSet,
|
||||
document: &CadDocument,
|
||||
entity: &EntityType,
|
||||
) {
|
||||
set.visual_style = resolve_mesh_visual_style(document, entity);
|
||||
}
|
||||
Reference in new issue
Block a user