diff --git a/.cargo/config.toml b/.cargo/config.toml index ae0e944..3926aa5 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1 +1,4 @@ [alias] + +[build] +rustflags = ["-Ctarget-cpu=native"] diff --git a/Cargo.lock b/Cargo.lock index a86f202..a0be063 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2188,6 +2188,16 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tobj" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04aca6092e5978e708ee784e8ab9b5cf3cdb598b28f99a2f257446e7081a7025" +dependencies = [ + "ahash", + "tokio", +] + [[package]] name = "tokio" version = "1.44.1" @@ -2195,6 +2205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", + "bytes", "parking_lot", "pin-project-lite", "tokio-macros", @@ -2291,6 +2302,12 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -3181,6 +3198,7 @@ dependencies = [ name = "zenyx" version = "0.1.0" dependencies = [ + "ahash", "anyhow", "backtrace", "bytemuck", @@ -3196,9 +3214,11 @@ dependencies = [ "regex", "rustyline", "thiserror 2.0.12", + "tobj", "tokio", "tracing", "tracing-subscriber", + "typenum", "wgpu", "winit", ] diff --git a/Cargo.toml b/Cargo.toml index cb0f4ce..28987ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,12 +27,7 @@ codegen-units = 512 strip = "symbols" debug-assertions = true -[profile.dev.build-override] -opt-level = 0 -debug = false -overflow-checks = false -incremental = true -codegen-units = 512 + [workspace.dependencies] lazy_static = "1.5.0" @@ -40,3 +35,6 @@ parking_lot = "0.12.3" [profile.release] debug-assertions = false +lto = true +codegen-units = 1 +panic = "abort" diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 32e799f..47ebe62 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -17,7 +17,7 @@ parking_lot.workspace = true regex = "1.11.1" rustyline = { version = "15.0.0", features = ["derive", "rustyline-derive"] } thiserror = "2.0.11" -tokio = { version = "1.44.1", features = ["macros", "parking_lot","rt-multi-thread"] } +tokio = { version = "1.44.1", features = ["fs", "macros", "parking_lot", "rt-multi-thread"] } wgpu = "24.0.3" winit = "0.30.9" bytemuck = "1.21.0" @@ -25,6 +25,9 @@ futures = "0.3.31" cgmath = "0.18.0" tracing = "0.1.41" tracing-subscriber = "0.3.19" +typenum = { version = "1.18.0", features = ["const-generics"] } +tobj = { version = "4.0.3", features = ["tokio"] } +ahash = "0.8.11" [profile.dev] diff --git a/engine/src/bint.rs b/engine/src/bint.rs new file mode 100644 index 0000000..28563de --- /dev/null +++ b/engine/src/bint.rs @@ -0,0 +1,334 @@ +use std::{ + cmp::Ordering, + convert::From, + fmt, + hash::{Hash, Hasher}, + ops::{ + Add, AddAssign, BitAnd, BitOr, BitXor, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, + Rem, RemAssign, Shl, Shr, Sub, SubAssign, + }, + str::FromStr, +}; + +#[derive(Debug, Clone, Copy)] +pub struct BigInt { + bytes: [u8; N], + len: usize, +} + +impl BigInt { + pub fn from_bytes(bytes: &[u8]) -> Self { + debug_assert!(bytes.len() != 0); + let mut len = bytes.len(); + while len > 1 && bytes[len - 1] == 0 { + len -= 1; + } + let mut arr = [0u8; N]; + arr[..len].copy_from_slice(&bytes[..len]); + BigInt { bytes: arr, len } + } + + pub fn from_u64(value: u64) -> Self { + Self::from_bytes(&value.to_le_bytes()) + } + + fn trim_zeros(mut self) -> Self { + while self.len > 1 && self.bytes[self.len - 1] == 0 { + self.len -= 1; + } + self + } + + pub fn max_value() -> Self { + let mut arr = [0u8; N]; + arr.fill(255); + BigInt { bytes: arr, len: N } + } + pub fn div_rem(&self, other: &Self) -> (Self, Self) { + let mut quotient = BigInt::from(0); + let mut remainder = self.clone(); + let divisor = other.clone(); + + while remainder >= divisor { + let mut multiple = divisor.clone(); + let mut temp_quotient = BigInt::from(1); + while multiple + multiple <= remainder { + multiple = multiple + multiple; + temp_quotient = temp_quotient + temp_quotient; + } + remainder = remainder - multiple; + quotient = quotient + temp_quotient; + } + (quotient.trim_zeros(), remainder.trim_zeros()) + } +} + +impl Add for BigInt { + type Output = Self; + fn add(self, rhs: Self) -> Self { + let mut result = [0u8; N]; + let mut carry = 0u16; + let max_len = self.len.max(rhs.len); + let mut res_len = 0; + + for i in 0..max_len { + let a = self.bytes.get(i).copied().unwrap_or(0) as u16; + let b = rhs.bytes.get(i).copied().unwrap_or(0) as u16; + let sum = a + b + carry; + result[i] = (sum % 256) as u8; + carry = sum / 256; + res_len = i + 1; + } + + if carry > 0 { + result[res_len] = carry as u8; + res_len += 1; + } + + BigInt { + bytes: result, + len: res_len, + } + .trim_zeros() + } +} + +impl AddAssign for BigInt { + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs; + } +} + +impl Sub for BigInt { + type Output = Self; + fn sub(self, rhs: Self) -> Self { + let mut result = [0u8; N]; + let mut borrow = 0i16; + let mut res_len = 0; + + for i in 0..self.len { + let a = self.bytes[i] as i16; + let b = rhs.bytes.get(i).copied().unwrap_or(0) as i16; + let mut diff = a - b - borrow; + borrow = 0; + + if diff < 0 { + diff += 256; + borrow = 1; + } + + result[i] = diff as u8; + res_len = i + 1; + } + + BigInt { + bytes: result, + len: res_len, + } + .trim_zeros() + } +} + +impl SubAssign for BigInt { + fn sub_assign(&mut self, rhs: Self) { + *self = *self - rhs; + } +} + +impl Mul for BigInt { + type Output = Self; + fn mul(self, rhs: Self) -> Self { + let mut result = BigInt { + bytes: [0; N], + len: 0, + }; + + for i in 0..self.len { + let mut carry = 0u16; + for j in 0..rhs.len { + let idx = i + j; + if idx >= N { + panic!("Multiplication overflow"); + } + let product = + self.bytes[i] as u16 * rhs.bytes[j] as u16 + carry + result.bytes[idx] as u16; + result.bytes[idx] = (product % 256) as u8; + carry = product / 256; + } + let mut k = i + rhs.len; + while carry > 0 && k < N { + let sum = result.bytes[k] as u16 + carry; + result.bytes[k] = (sum % 256) as u8; + carry = sum / 256; + k += 1; + } + result.len = result.len.max(k); + } + + result.trim_zeros() + } +} + +impl MulAssign for BigInt { + fn mul_assign(&mut self, rhs: Self) { + *self = *self * rhs; + } +} + +impl Div for BigInt { + type Output = Self; + fn div(self, rhs: Self) -> Self { + self.div_rem(&rhs).0 + } +} + +impl DivAssign for BigInt { + fn div_assign(&mut self, rhs: Self) { + *self = *self / rhs; + } +} + +impl Rem for BigInt { + type Output = Self; + fn rem(self, rhs: Self) -> Self { + self.div_rem(&rhs).1 + } +} + +impl RemAssign for BigInt { + fn rem_assign(&mut self, rhs: Self) { + *self = *self % rhs; + } +} + +impl PartialEq for BigInt { + fn eq(&self, other: &Self) -> bool { + self.bytes[..self.len] == other.bytes[..other.len] + } +} + +impl Eq for BigInt {} + +impl Hash for BigInt { + fn hash(&self, state: &mut H) { + self.bytes[..self.len].hash(state); + } +} + +impl PartialOrd for BigInt { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for BigInt { + fn cmp(&self, other: &Self) -> Ordering { + if self.len != other.len { + return self.len.cmp(&other.len); + } + for i in (0..self.len).rev() { + match self.bytes[i].cmp(&other.bytes[i]) { + Ordering::Equal => continue, + ord => return ord, + } + } + Ordering::Equal + } +} + +impl Deref for BigInt { + type Target = [u8]; + fn deref(&self) -> &[u8] { + &self.bytes[..self.len] + } +} + +impl DerefMut for BigInt { + fn deref_mut(&mut self) -> &mut [u8] { + &mut self.bytes[..self.len] + } +} + +macro_rules! impl_from_int { + ($($t:ty),*) => {$( + impl From<$t> for BigInt { + fn from(value: $t) -> Self { + let bytes = value.to_le_bytes(); + Self::from_bytes(&bytes) + } + } + )*}; +} + +impl_from_int!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128); + +impl FromStr for BigInt { + type Err = &'static str; + fn from_str(s: &str) -> Result { + let mut result = BigInt::from(0u8); + for c in s.chars() { + if !c.is_digit(10) { + return Err("Invalid digit"); + } + let digit = c.to_digit(10).unwrap() as u8; + result = result * BigInt::from(10u8) + BigInt::from(digit); + } + Ok(result) + } +} + +impl fmt::Display for BigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.len == 0 { + return write!(f, "0"); + } + let mut digits = Vec::new(); + let mut bytes = self.bytes[..self.len].to_vec(); + + while !bytes.is_empty() { + let mut remainder = 0u16; + for byte in bytes.iter_mut().rev() { + let value = *byte as u16 + remainder * 256; + *byte = (value / 10) as u8; + remainder = value % 10; + } + digits.push(remainder as u8); + while !bytes.is_empty() && bytes[bytes.len() - 1] == 0 { + bytes.pop(); + } + } + + digits.reverse(); + let s = digits + .iter() + .map(|d| char::from_digit(*d as u32, 10).unwrap()) + .collect::(); + write!(f, "{}", s) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +struct Dint { + bytes: Vec, +} + +impl Deref for Dint { + type Target = [u8]; + fn deref(&self) -> &[u8] { + &self.bytes + } +} + +impl DerefMut for Dint { + fn deref_mut(&mut self) -> &mut [u8] { + &mut self.bytes + } +} + +pub fn main() { + type TheInt = BigInt<2>; + let mut test: TheInt = TheInt::max_value(); + let thing = BigInt::<9>::max_value(); + test /= 2.into(); + println!("{test}") +} diff --git a/engine/src/core/panic.rs b/engine/src/core/panic.rs index 3091ff4..db207f6 100644 --- a/engine/src/core/panic.rs +++ b/engine/src/core/panic.rs @@ -1,3 +1,4 @@ +use std::error::Error; use std::fmt::Write as FmtWrite; use std::mem; @@ -8,50 +9,43 @@ use regex::Regex; static INIT: parking_lot::Once = Once::new(); pub fn set_panic_hook() { - use std::io::Write; - - use colored::Colorize; - - use crate::workspace; - INIT.call_once(|| { let default_hook = std::panic::take_hook(); std::panic::set_hook(Box::new(move |info| { - let log_path = workspace::get_working_dir().unwrap_or_else(|_| { + if let Err(e) = process_panic(info) { + eprintln!("Error in panic hook: {}", e); default_hook(info); - std::process::exit(0); - }); - if !log_path.exists() { - std::fs::create_dir_all(&log_path).unwrap_or_else(|_| { - default_hook(info); - std::process::exit(0); - }); } - let log_path = log_path.join("panic.log"); + std::process::exit(0); + })); + }); +} - let mut file = std::fs::File::create(&log_path).unwrap_or_else(|_| { - default_hook(info); - std::process::exit(0); - }); - let payload = info.payload(); - let payload_str = if let Some(s) = payload.downcast_ref::<&str>() { - *s - } else if let Some(s) = payload.downcast_ref::() { - s - } else { - "" - }; +fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box> { + use crate::workspace; + use colored::Colorize; + use std::io::Write; - writeln!(file, "{}", payload_str).unwrap_or_else(|_| { - default_hook(info); - std::process::exit(0); - }); - writeln!(file, "{}", render_backtrace().sanitize_path()).unwrap_or_else(|_| { - default_hook(info); - std::process::exit(0); - }); + let log_dir = workspace::get_working_dir()?; + if !log_dir.exists() { + std::fs::create_dir_all(&log_dir)?; + } + let log_path = log_dir.join("panic.log"); - let panic_msg = format!( + let mut file = std::fs::File::create(&log_path)?; + let payload = info.payload(); + let payload_str = if let Some(s) = payload.downcast_ref::<&str>() { + *s + } else if let Some(s) = payload.downcast_ref::() { + s + } else { + "" + }; + + writeln!(file, "{}", payload_str)?; + writeln!(file, "{}", render_backtrace().sanitize_path())?; + + let panic_msg = format!( "Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report. We have generated a report file at \"{}\". Submit an issue or email with the subject of \"Zenyx Crash Report\" and include the report as an attachment. @@ -63,11 +57,12 @@ https://github.com/Zenyx-Engine/Zenyx/issues We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports. Thank you kindly!", log_path.display()); - println!("{}", panic_msg.red().bold()); - println!("\nFor future reference, the error summary is as follows:\n{}", payload_str.red().bold()); - std::process::exit(0); - })); - }); + println!("{}", panic_msg.red().bold()); + println!( + "\nFor future reference, the error summary is as follows:\n{}", + payload_str.red().bold() + ); + Ok(()) } fn render_backtrace() -> String { @@ -130,7 +125,7 @@ trait Sanitize { impl Sanitize for str { fn sanitize_path(&self) -> String { let username_pattern = r"(?i)(/home/|/Users/|\\Users\\)([^/\\]+)"; - let re = Regex::new(username_pattern).expect("Failed to sanitize path, aborting operation"); + let re = Regex::new(username_pattern).expect("Failed to compile regex for sanitization"); re.replace_all(self, "${1}").to_string() } } diff --git a/engine/src/core/render/ctx.rs b/engine/src/core/render/ctx.rs index cc65270..86748df 100644 --- a/engine/src/core/render/ctx.rs +++ b/engine/src/core/render/ctx.rs @@ -1,14 +1,16 @@ +use std::borrow::Cow; +use std::mem::offset_of; use std::sync::Arc; use std::time::Instant; -use std::{backtrace::Backtrace, borrow::Cow}; -use cgmath::{Matrix4, Point3, Rad, Vector3, perspective}; +use cgmath::{Deg, Matrix4, Point3, Rad, SquareMatrix, Vector3, perspective}; use futures::executor::block_on; use thiserror::Error; use tracing::{error, trace}; use wgpu::TextureUsages; use wgpu::{Backends, InstanceDescriptor, util::DeviceExt}; use winit::window::Window; + #[derive(Debug, Error)] #[error(transparent)] pub enum ContextErrorKind { @@ -127,13 +129,21 @@ impl From for RenderContextError { } } -const CUBE_SHADER: &str = r" -struct Uniforms { - mvp: mat4x4, +const SHADER_SRC: &str = r#" +struct CameraUniform { + view: mat4x4, + proj: mat4x4, +}; + +struct ModelUniform { + model: mat4x4, }; @group(0) @binding(0) -var u: Uniforms; +var camera: CameraUniform; + +@group(1) @binding(0) +var model: ModelUniform; struct VertexInput { @location(0) position: vec3, @@ -148,27 +158,27 @@ struct VertexOutput { @vertex fn vs_main(input: VertexInput) -> VertexOutput { var output: VertexOutput; - output.clip_position = u.mvp * vec4(input.position, 1.0); + let model_pos = model.model * vec4(input.position, 1.0); + output.clip_position = camera.proj * camera.view * model_pos; output.normal = input.normal; return output; } - @fragment fn fs_main(input: VertexOutput) -> @location(0) vec4 { let ambient: f32 = 0.2; let light_dir = normalize(vec3(0.5, 1.0, 0.5)); let diffuse = clamp(dot(normalize(input.normal), light_dir), 0.0, 1.0); - // Mix ambient light to ensure no face is completely dark. let brightness = ambient + (1.0 - ambient) * diffuse; return vec4(0.7 * brightness, 0.7 * brightness, 0.9 * brightness, 1.0); } -"; +"#; + #[repr(C)] #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -struct Vertex { - position: [f32; 3], - normal: [f32; 3], +pub struct Vertex { + pub position: [f32; 3], + pub normal: [f32; 3], } impl Vertex { @@ -179,7 +189,7 @@ impl Vertex { format: wgpu::VertexFormat::Float32x3, }, wgpu::VertexAttribute { - offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, + offset: offset_of!(Vertex, normal) as u64, shader_location: 1, format: wgpu::VertexFormat::Float32x3, }, @@ -194,170 +204,165 @@ impl Vertex { } } -static CUBE_VERTICES: &[Vertex] = &[ - Vertex { - position: [-0.5, -0.5, 0.5], - normal: [0.0, 0.0, 1.0], - }, - Vertex { - position: [0.5, -0.5, 0.5], - normal: [0.0, 0.0, 1.0], - }, - Vertex { - position: [0.5, 0.5, 0.5], - normal: [0.0, 0.0, 1.0], - }, - Vertex { - position: [0.5, 0.5, 0.5], - normal: [0.0, 0.0, 1.0], - }, - Vertex { - position: [-0.5, 0.5, 0.5], - normal: [0.0, 0.0, 1.0], - }, - Vertex { - position: [-0.5, -0.5, 0.5], - normal: [0.0, 0.0, 1.0], - }, - Vertex { - position: [0.5, -0.5, -0.5], - normal: [0.0, 0.0, -1.0], - }, - Vertex { - position: [-0.5, -0.5, -0.5], - normal: [0.0, 0.0, -1.0], - }, - Vertex { - position: [-0.5, 0.5, -0.5], - normal: [0.0, 0.0, -1.0], - }, - Vertex { - position: [-0.5, 0.5, -0.5], - normal: [0.0, 0.0, -1.0], - }, - Vertex { - position: [0.5, 0.5, -0.5], - normal: [0.0, 0.0, -1.0], - }, - Vertex { - position: [0.5, -0.5, -0.5], - normal: [0.0, 0.0, -1.0], - }, - Vertex { - position: [0.5, -0.5, 0.5], - normal: [1.0, 0.0, 0.0], - }, - Vertex { - position: [0.5, -0.5, -0.5], - normal: [1.0, 0.0, 0.0], - }, - Vertex { - position: [0.5, 0.5, -0.5], - normal: [1.0, 0.0, 0.0], - }, - Vertex { - position: [0.5, 0.5, -0.5], - normal: [1.0, 0.0, 0.0], - }, - Vertex { - position: [0.5, 0.5, 0.5], - normal: [1.0, 0.0, 0.0], - }, - Vertex { - position: [0.5, -0.5, 0.5], - normal: [1.0, 0.0, 0.0], - }, - Vertex { - position: [-0.5, -0.5, -0.5], - normal: [-1.0, 0.0, 0.0], - }, - Vertex { - position: [-0.5, -0.5, 0.5], - normal: [-1.0, 0.0, 0.0], - }, - Vertex { - position: [-0.5, 0.5, 0.5], - normal: [-1.0, 0.0, 0.0], - }, - Vertex { - position: [-0.5, 0.5, 0.5], - normal: [-1.0, 0.0, 0.0], - }, - Vertex { - position: [-0.5, 0.5, -0.5], - normal: [-1.0, 0.0, 0.0], - }, - Vertex { - position: [-0.5, -0.5, -0.5], - normal: [-1.0, 0.0, 0.0], - }, - Vertex { - position: [-0.5, 0.5, 0.5], - normal: [0.0, 1.0, 0.0], - }, - Vertex { - position: [0.5, 0.5, 0.5], - normal: [0.0, 1.0, 0.0], - }, - Vertex { - position: [0.5, 0.5, -0.5], - normal: [0.0, 1.0, 0.0], - }, - Vertex { - position: [0.5, 0.5, -0.5], - normal: [0.0, 1.0, 0.0], - }, - Vertex { - position: [-0.5, 0.5, -0.5], - normal: [0.0, 1.0, 0.0], - }, - Vertex { - position: [-0.5, 0.5, 0.5], - normal: [0.0, 1.0, 0.0], - }, - Vertex { - position: [-0.5, -0.5, -0.5], - normal: [0.0, -1.0, 0.0], - }, - Vertex { - position: [0.5, -0.5, -0.5], - normal: [0.0, -1.0, 0.0], - }, - Vertex { - position: [0.5, -0.5, 0.5], - normal: [0.0, -1.0, 0.0], - }, - Vertex { - position: [0.5, -0.5, 0.5], - normal: [0.0, -1.0, 0.0], - }, - Vertex { - position: [-0.5, -0.5, 0.5], - normal: [0.0, -1.0, 0.0], - }, - Vertex { - position: [-0.5, -0.5, -0.5], - normal: [0.0, -1.0, 0.0], - }, -]; +#[repr(C)] +#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct CameraUniform { + view: [[f32; 4]; 4], + proj: [[f32; 4]; 4], +} -pub struct WgpuCtx<'window> { +#[repr(C)] +#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct ModelUniform { + model: [[f32; 4]; 4], +} + +struct Camera { + uniform_buffer: wgpu::Buffer, + bind_group: wgpu::BindGroup, + view: Matrix4, + proj: Matrix4, +} + +impl Camera { + fn new( + device: &wgpu::Device, + bind_group_layout: &wgpu::BindGroupLayout, + width: u32, + height: u32, + ) -> Self { + let view = Matrix4::look_at_rh( + Point3::new(0.0, 0.0, 3.0), + Point3::new(0.0, 0.0, 0.0), + Vector3::unit_y(), + ); + let aspect = width as f32 / height as f32; + let proj = perspective(Rad::from(Deg(45.0)), aspect, 0.1, 100.0); + + let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Camera Uniform Buffer"), + size: std::mem::size_of::() as u64, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("Camera Bind Group"), + layout: bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: uniform_buffer.as_entire_binding(), + }], + }); + + Self { + uniform_buffer, + bind_group, + view, + proj, + } + } + + fn resize(&mut self, width: u32, height: u32) { + let aspect = width as f32 / height as f32; + self.proj = perspective(Rad::from(Deg(45.0)), aspect, 0.1, 100.0); + } + + fn update(&self, queue: &wgpu::Queue) { + let view_array: [[f32; 4]; 4] = self.view.into(); + let proj_array: [[f32; 4]; 4] = self.proj.into(); + let uniform = CameraUniform { + view: view_array, + proj: proj_array, + }; + queue.write_buffer(&self.uniform_buffer, 0, bytemuck::bytes_of(&uniform)); + } +} + +struct Model { + vertex_buffer: wgpu::Buffer, + index_buffer: wgpu::Buffer, + uniform_buffer: wgpu::Buffer, + bind_group: wgpu::BindGroup, + index_count: u32, // Changed from vertex_count to index_count + transform: Matrix4, +} + +impl Model { + fn new( + device: &wgpu::Device, + vertices: &[Vertex], + indices: &[u32], + bind_group_layout: &wgpu::BindGroupLayout, + ) -> Self { + let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(vertices), + usage: wgpu::BufferUsages::VERTEX, + }); + + let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Index Buffer"), + contents: bytemuck::cast_slice(indices), // Use proper indices + usage: wgpu::BufferUsages::INDEX, + }); + + let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Model Uniform Buffer"), + size: std::mem::size_of::() as u64, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("Model Bind Group"), + layout: bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: uniform_buffer.as_entire_binding(), + }], + }); + Self { + vertex_buffer, + index_buffer, + uniform_buffer, + bind_group, + index_count: indices.len() as u32, + transform: Matrix4::identity(), + } + } + + fn update(&self, queue: &wgpu::Queue) { + let model_array: [[f32; 4]; 4] = self.transform.into(); + let uniform = ModelUniform { model: model_array }; + queue.write_buffer(&self.uniform_buffer, 0, bytemuck::bytes_of(&uniform)); + } + + fn set_transform(&mut self, transform: Matrix4) { + self.transform = transform; + } +} + +pub struct Renderer<'window> { device: wgpu::Device, queue: wgpu::Queue, surface: wgpu::Surface<'window>, surface_config: wgpu::SurfaceConfiguration, - adapter: wgpu::Adapter, + camera: Camera, + models: Vec, render_pipeline: wgpu::RenderPipeline, - uniform_buffer: wgpu::Buffer, - vertex_buffer: wgpu::Buffer, - start_time: Instant, + depth_texture: wgpu::Texture, + depth_texture_view: wgpu::TextureView, + camera_bind_group_layout: wgpu::BindGroupLayout, + model_bind_group_layout: wgpu::BindGroupLayout, bg_color: wgpu::Color, + start_time: Instant, last_frame_instant: Instant, frame_count: u32, } -impl<'window> WgpuCtx<'window> { - pub async fn new(window: Arc) -> Result, RenderContextError> { +impl<'window> Renderer<'window> { + pub async fn new(window: Arc) -> Result { let instance = wgpu::Instance::new(&InstanceDescriptor { backends: Backends::from_comma_list("dx12,metal,opengl,webgpu"), ..Default::default() @@ -381,86 +386,97 @@ impl<'window> WgpuCtx<'window> { None, ) })?; + let (device, queue) = adapter .request_device(&wgpu::DeviceDescriptor::default(), None) .await .ctx_err(ContextErrorKind::DeviceRequest, "Device configuration")?; + let size = window.inner_size(); let width = size.width.max(1); let height = size.height.max(1); - let surface_config = wgpu::SurfaceConfiguration { - width: width.max(1), - height: height.max(1), - format: wgpu::TextureFormat::Rgba8UnormSrgb, - present_mode: wgpu::PresentMode::AutoNoVsync, - alpha_mode: wgpu::CompositeAlphaMode::Auto, - view_formats: Vec::new(), - usage: TextureUsages::RENDER_ATTACHMENT, - desired_maximum_frame_latency: 3, - }; - surface.configure(&device, &surface_config); - let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("Uniform Buffer"), - size: 64, - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Cube Vertex Buffer"), - contents: bytemuck::cast_slice(CUBE_VERTICES), - usage: wgpu::BufferUsages::VERTEX, - }); - let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("Cube Shader"), - source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(CUBE_SHADER)), - }); - let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("Uniform Bind Group Layout"), - entries: &[wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: wgpu::BufferSize::new(64), - }, - count: None, - }], - }); + + let camera_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Camera Bind Group Layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: wgpu::BufferSize::new( + std::mem::size_of::() as u64, + ), + }, + count: None, + }], + }); + + let model_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Model Bind Group Layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: wgpu::BufferSize::new( + std::mem::size_of::() as u64, + ), + }, + count: None, + }], + }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Cube Pipeline Layout"), - bind_group_layouts: &[&bind_group_layout], + label: Some("Pipeline Layout"), + bind_group_layouts: &[&camera_bind_group_layout, &model_bind_group_layout], push_constant_ranges: &[], }); + + let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("Main Shader"), + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(SHADER_SRC)), + }); + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Cube Render Pipeline"), + label: Some("Main Pipeline"), layout: Some(&pipeline_layout), vertex: wgpu::VertexState { module: &shader, entry_point: Some("vs_main"), buffers: &[Vertex::desc()], - compilation_options: wgpu::PipelineCompilationOptions::default(), + compilation_options: Default::default(), }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: Some("fs_main"), targets: &[Some(wgpu::ColorTargetState { - format: surface_config.format, - blend: Some(wgpu::BlendState::ALPHA_BLENDING), + format: surface.get_capabilities(&adapter).formats[0], + blend: Some(wgpu::BlendState::REPLACE), write_mask: wgpu::ColorWrites::ALL, })], - compilation_options: wgpu::PipelineCompilationOptions::default(), + compilation_options: Default::default(), }), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), + // cull_mode: , polygon_mode: wgpu::PolygonMode::Fill, unclipped_depth: false, conservative: false, }, - depth_stencil: None, + depth_stencil: Some(wgpu::DepthStencilState { + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }), multisample: wgpu::MultisampleState { count: 1, mask: !0, @@ -469,15 +485,40 @@ impl<'window> WgpuCtx<'window> { multiview: None, cache: None, }); - Ok(WgpuCtx { + + + let camera = Camera::new(&device, &camera_bind_group_layout, width, height); + + let surface_caps = surface.get_capabilities(&adapter); + let surface_config = wgpu::SurfaceConfiguration { + width, + height, + format: surface_caps.formats[0], + present_mode: wgpu::PresentMode::AutoNoVsync, + alpha_mode: wgpu::CompositeAlphaMode::Auto, + view_formats: vec![], + usage: TextureUsages::RENDER_ATTACHMENT, + desired_maximum_frame_latency: 3, + }; + surface.configure(&device, &surface_config); + let (depth_texture, depth_texture_view) = create_depth_texture( + &device, + surface_config.width, + surface_config.height, + // surface_config.format, + ); + + + Ok(Self { device, queue, surface, surface_config, - adapter, + camera, + models: Vec::new(), render_pipeline, - uniform_buffer, - vertex_buffer, + camera_bind_group_layout, + model_bind_group_layout, bg_color: wgpu::Color { r: 0.1, g: 0.1, @@ -487,79 +528,101 @@ impl<'window> WgpuCtx<'window> { start_time: Instant::now(), last_frame_instant: Instant::now(), frame_count: 0, + depth_texture, + depth_texture_view, }) } - pub fn new_blocking(window: Arc) -> Result, RenderContextError> { + pub fn new_blocking(window: Arc) -> Result { block_on(Self::new(window)) } + pub fn add_model(&mut self, vertices: &[Vertex], indicies: &[u32]) { + let model = Model::new( + &self.device, + vertices, + indicies, + &self.model_bind_group_layout, + ); + self.models.push(model); + } + pub fn resize(&mut self, new_size: (u32, u32)) { let (width, height) = new_size; + let (depth_texture,depth_view) = create_depth_texture(&self.device, width, height); self.surface_config.width = width.max(1); self.surface_config.height = height.max(1); self.surface.configure(&self.device, &self.surface_config); + self.depth_texture = depth_texture; + self.depth_texture_view = depth_view; + self.camera.resize(width, height); } pub fn draw(&mut self) { - let elapsed = self.start_time.elapsed().as_secs_f32() * 0.80f32; - let model = Matrix4::from_angle_x(Rad(elapsed)) * Matrix4::from_angle_y(Rad(elapsed)); - let view = Matrix4::look_at_rh( - Point3::new(0.0, 0.0, 3.0), - Point3::new(0.0, 0.0, 0.0), - Vector3::unit_y(), - ); - let aspect = self.surface_config.width as f32 / self.surface_config.height as f32; - let proj = perspective(Rad(std::f32::consts::FRAC_PI_4), aspect, 0.1, 100.0); - let mvp = proj * view * model; - let mvp_array: [[f32; 4]; 4] = [ - [mvp.x.x, mvp.x.y, mvp.x.z, mvp.x.w], - [mvp.y.x, mvp.y.y, mvp.y.z, mvp.y.w], - [mvp.z.x, mvp.z.y, mvp.z.z, mvp.z.w], - [mvp.w.x, mvp.w.y, mvp.w.z, mvp.w.w], - ]; - self.queue - .write_buffer(&self.uniform_buffer, 0, bytemuck::bytes_of(&mvp_array)); + let elapsed = self.start_time.elapsed().as_secs_f32(); + + self.camera.update(&self.queue); + + for (i, model) in self.models.iter_mut().enumerate() { + let angle = Rad(elapsed * 0.8 + i as f32 * 0.3); + model.set_transform(Matrix4::from_angle_x(angle) * Matrix4::from_angle_y(angle)); + model.update(&self.queue); + } + let surface_texture = self .surface .get_current_texture() - .expect("Failed to get surface texture"); - let view_texture = surface_texture + .ctx_err( + ContextErrorKind::SurfaceTexture, + "Surface texture acquisition", + ) + .unwrap(); + + let view = surface_texture .texture .create_view(&wgpu::TextureViewDescriptor::default()); + let mut encoder = self .device .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Cube Command Encoder"), + label: Some("Render Encoder"), }); + { let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("Cube Render Pass"), + label: Some("Main Render Pass"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view_texture, + view: &view, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(self.bg_color), store: wgpu::StoreOp::Store, }, })], - depth_stencil_attachment: None, - timestamp_writes: None, + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &self.depth_texture_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: wgpu::StoreOp::Store, + }), + stencil_ops: None, + }), occlusion_query_set: None, + timestamp_writes: None, }); + render_pass.set_pipeline(&self.render_pipeline); - let bind_group = self.device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("Uniform Bind Group"), - layout: &self.render_pipeline.get_bind_group_layout(0), - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: self.uniform_buffer.as_entire_binding(), - }], - }); - render_pass.set_bind_group(0, &bind_group, &[]); - render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); - render_pass.draw(0..36, 0..1); + render_pass.set_bind_group(0, &self.camera.bind_group, &[]); + + for model in &self.models { + render_pass.set_bind_group(1, &model.bind_group, &[]); + render_pass.set_vertex_buffer(0, model.vertex_buffer.slice(..)); + render_pass + .set_index_buffer(model.index_buffer.slice(..), wgpu::IndexFormat::Uint32); + render_pass.draw_indexed(0..model.index_count, 0, 0..1); + } } + self.queue.submit(Some(encoder.finish())); surface_texture.present(); @@ -573,10 +636,38 @@ impl<'window> WgpuCtx<'window> { } } - pub fn change_bg_color(&mut self, color: wgpu::Color) { + pub fn set_bg_color(&mut self, color: wgpu::Color) { self.bg_color = color; } + pub fn bg_color(&self) -> wgpu::Color { - self.bg_color.clone() + self.bg_color } } +fn create_depth_texture( + device: &wgpu::Device, + width: u32, + height: u32, + // format: wgpu::TextureFormat, +) -> (wgpu::Texture, wgpu::TextureView) { + let size = wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }; + + let desc = wgpu::TextureDescriptor { + label: Some("Depth Texture"), + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth32Float, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: &[], + }; + + let texture = device.create_texture(&desc); + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + (texture, view) +} \ No newline at end of file diff --git a/engine/src/core/render/mod.rs b/engine/src/core/render/mod.rs index 079c2cf..43b0a6f 100644 --- a/engine/src/core/render/mod.rs +++ b/engine/src/core/render/mod.rs @@ -2,7 +2,8 @@ use std::collections::HashMap; use std::ops::Deref; use std::sync::Arc; -use ctx::WgpuCtx; +use ctx::{Renderer, Vertex}; +use tobj::LoadOptions; use tracing::{debug, error, info, trace, warn}; use wgpu::rwh::HasWindowHandle; use winit::application::ApplicationHandler; @@ -15,7 +16,7 @@ pub mod ctx; struct WindowContext<'window> { window: Arc, - ctx: WgpuCtx<'window>, + ctx: Renderer<'window>, main_window: bool, } impl Deref for WindowContext<'_> { @@ -35,6 +36,161 @@ impl WindowContext<'_> { pub struct App<'window> { windows: HashMap>, } +static CUBE_VERTICES: &[Vertex] = &[ + Vertex { + position: [-0.5, -0.5, 0.5], + normal: [0.0, 0.0, 1.0], + }, + Vertex { + position: [0.5, -0.5, 0.5], + normal: [0.0, 0.0, 1.0], + }, + Vertex { + position: [0.5, 0.5, 0.5], + normal: [0.0, 0.0, 1.0], + }, + Vertex { + position: [0.5, 0.5, 0.5], + normal: [0.0, 0.0, 1.0], + }, + Vertex { + position: [-0.5, 0.5, 0.5], + normal: [0.0, 0.0, 1.0], + }, + Vertex { + position: [-0.5, -0.5, 0.5], + normal: [0.0, 0.0, 1.0], + }, + Vertex { + position: [0.5, -0.5, -0.5], + normal: [0.0, 0.0, -1.0], + }, + Vertex { + position: [-0.5, -0.5, -0.5], + normal: [0.0, 0.0, -1.0], + }, + Vertex { + position: [-0.5, 0.5, -0.5], + normal: [0.0, 0.0, -1.0], + }, + Vertex { + position: [-0.5, 0.5, -0.5], + normal: [0.0, 0.0, -1.0], + }, + Vertex { + position: [0.5, 0.5, -0.5], + normal: [0.0, 0.0, -1.0], + }, + Vertex { + position: [0.5, -0.5, -0.5], + normal: [0.0, 0.0, -1.0], + }, + Vertex { + position: [0.5, -0.5, 0.5], + normal: [1.0, 0.0, 0.0], + }, + Vertex { + position: [0.5, -0.5, -0.5], + normal: [1.0, 0.0, 0.0], + }, + Vertex { + position: [0.5, 0.5, -0.5], + normal: [1.0, 0.0, 0.0], + }, + Vertex { + position: [0.5, 0.5, -0.5], + normal: [1.0, 0.0, 0.0], + }, + Vertex { + position: [0.5, 0.5, 0.5], + normal: [1.0, 0.0, 0.0], + }, + Vertex { + position: [0.5, -0.5, 0.5], + normal: [1.0, 0.0, 0.0], + }, + Vertex { + position: [-0.5, -0.5, -0.5], + normal: [-1.0, 0.0, 0.0], + }, + Vertex { + position: [-0.5, -0.5, 0.5], + normal: [-1.0, 0.0, 0.0], + }, + Vertex { + position: [-0.5, 0.5, 0.5], + normal: [-1.0, 0.0, 0.0], + }, + Vertex { + position: [-0.5, 0.5, 0.5], + normal: [-1.0, 0.0, 0.0], + }, + Vertex { + position: [-0.5, 0.5, -0.5], + normal: [-1.0, 0.0, 0.0], + }, + Vertex { + position: [-0.5, -0.5, -0.5], + normal: [-1.0, 0.0, 0.0], + }, + Vertex { + position: [-0.5, 0.5, 0.5], + normal: [0.0, 1.0, 0.0], + }, + Vertex { + position: [0.5, 0.5, 0.5], + normal: [0.0, 1.0, 0.0], + }, + Vertex { + position: [0.5, 0.5, -0.5], + normal: [0.0, 1.0, 0.0], + }, + Vertex { + position: [0.5, 0.5, -0.5], + normal: [0.0, 1.0, 0.0], + }, + Vertex { + position: [-0.5, 0.5, -0.5], + normal: [0.0, 1.0, 0.0], + }, + Vertex { + position: [-0.5, 0.5, 0.5], + normal: [0.0, 1.0, 0.0], + }, + Vertex { + position: [-0.5, -0.5, -0.5], + normal: [0.0, -1.0, 0.0], + }, + Vertex { + position: [0.5, -0.5, -0.5], + normal: [0.0, -1.0, 0.0], + }, + Vertex { + position: [0.5, -0.5, 0.5], + normal: [0.0, -1.0, 0.0], + }, + Vertex { + position: [0.5, -0.5, 0.5], + normal: [0.0, -1.0, 0.0], + }, + Vertex { + position: [-0.5, -0.5, 0.5], + normal: [0.0, -1.0, 0.0], + }, + Vertex { + position: [-0.5, -0.5, -0.5], + normal: [0.0, -1.0, 0.0], + }, +]; +const CUBE_INDICES: &[u32] = &[ + 0, 1, 2, 2, 3, 0, + 4, 5, 6, 6, 7, 4, + 8, 9, 10, 10, 11, 8, + 12, 13, 14, 14, 15, 12, + 16, 17, 18, 18, 19, 16, + 20, 21, 22, 22, 23, 20, +]; + impl App<'_> { fn create_main_window(&mut self, event_loop: &ActiveEventLoop) { @@ -43,8 +199,45 @@ impl App<'_> { Ok(window) => { let window = Arc::new(window); let window_id = window.id(); - match WgpuCtx::new_blocking(window.clone()) { - Ok(wgpu_ctx) => { + match Renderer::new_blocking(window.clone()) { + Ok(mut wgpu_ctx) => { + let obj = match tobj::load_obj( + "test.obj", + &LoadOptions { + triangulate: true, + single_index: true, + ..Default::default() + }, + ) { + Ok(obj) => obj, + Err(e) => { + error!("{e}"); + panic!() + } + }; + let mesh = obj.0.get(0).unwrap().mesh.clone(); + + let vertices: Vec = (0..mesh.positions.len() / 3) + .map(|i| Vertex { + position: [ + mesh.positions[i * 3], + mesh.positions[i * 3 + 1], + mesh.positions[i * 3 + 2], + ], + normal: if !mesh.normals.is_empty() { + [ + mesh.normals[i * 3], + mesh.normals[i * 3 + 1], + mesh.normals[i * 3 + 2], + ] + } else { + [0.0; 3] + }, + }) + .collect(); + + wgpu_ctx.add_model(&vertices, &mesh.indices); + // wgpu_ctx.add_model(CUBE_VERTICES,CUBE_INDICES); self.windows.insert( window_id, WindowContext { @@ -101,7 +294,7 @@ impl App<'_> { wgpu::Color::BLACK => wgpu::Color::WHITE, _ => wgpu::Color::WHITE, }; - window_context.ctx.change_bg_color(new_color); + window_context.ctx.set_bg_color(new_color); debug!("Toggled background color for window {:?}", window_id); } else { warn!("No window context for toggling background: {:?}", window_id); @@ -111,7 +304,7 @@ impl App<'_> { fn spawn_child_window(&mut self, event_loop: &ActiveEventLoop) { if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) { let title = format!("Zenyx - New Window {}", self.windows.len()); - //TODO: Verify that this is safe instead of matching on it + // TODO: Verify that this is safe instead of matching on it let win_attr = unsafe { let base = Window::default_attributes().with_title(title); match main_ctx.window_handle() { @@ -123,8 +316,9 @@ impl App<'_> { Ok(window) => { let window = Arc::new(window); let window_id = window.id(); - match WgpuCtx::new_blocking(window.clone()) { - Ok(wgpu_ctx) => { + match Renderer::new_blocking(window.clone()) { + Ok(mut wgpu_ctx) => { + wgpu_ctx.add_model(CUBE_VERTICES,CUBE_INDICES); self.windows.insert( window_id, WindowContext { diff --git a/engine/src/main.rs b/engine/src/main.rs index 8fddb28..ff47bb2 100644 --- a/engine/src/main.rs +++ b/engine/src/main.rs @@ -7,6 +7,7 @@ use tracing::{debug, error, info, warn}; use tracing::{level_filters::LevelFilter, subscriber::set_global_default}; use tracing_subscriber::{layer::Filter, util::SubscriberInitExt}; use winit::event_loop::EventLoop; +pub mod bint; pub mod core; fn init_logger() { @@ -26,6 +27,7 @@ fn init_logger() { #[tokio::main(flavor = "current_thread")] async fn main() -> anyhow::Result<()> { init_logger(); + // bint::main(); if !cfg!(debug_assertions) { info!("{}", "Debug mode disabled".bright_blue()); set_panic_hook(); diff --git a/test.mtl b/test.mtl new file mode 100644 index 0000000..4704186 --- /dev/null +++ b/test.mtl @@ -0,0 +1,2 @@ +# Blender 4.2.3 LTS MTL File: 'None' +# www.blender.org diff --git a/test.obj b/test.obj new file mode 100644 index 0000000..e5e04ec --- /dev/null +++ b/test.obj @@ -0,0 +1,2066 @@ +# Blender 4.2.3 LTS +# www.blender.org +mtllib test.mtl +o Suzanne +v 0.437500 0.164062 0.765625 +v -0.437500 0.164062 0.765625 +v 0.500000 0.093750 0.687500 +v -0.500000 0.093750 0.687500 +v 0.546875 0.054688 0.578125 +v -0.546875 0.054688 0.578125 +v 0.351562 -0.023438 0.617188 +v -0.351562 -0.023438 0.617188 +v 0.351562 0.031250 0.718750 +v -0.351562 0.031250 0.718750 +v 0.351562 0.132812 0.781250 +v -0.351562 0.132812 0.781250 +v 0.273438 0.164062 0.796875 +v -0.273438 0.164062 0.796875 +v 0.203125 0.093750 0.742188 +v -0.203125 0.093750 0.742188 +v 0.156250 0.054688 0.648438 +v -0.156250 0.054688 0.648438 +v 0.078125 0.242188 0.656250 +v -0.078125 0.242188 0.656250 +v 0.140625 0.242188 0.742188 +v -0.140625 0.242188 0.742188 +v 0.242188 0.242188 0.796875 +v -0.242188 0.242188 0.796875 +v 0.273438 0.328125 0.796875 +v -0.273438 0.328125 0.796875 +v 0.203125 0.390625 0.742188 +v -0.203125 0.390625 0.742188 +v 0.156250 0.437500 0.648438 +v -0.156250 0.437500 0.648438 +v 0.351562 0.515625 0.617188 +v -0.351562 0.515625 0.617188 +v 0.351562 0.453125 0.718750 +v -0.351562 0.453125 0.718750 +v 0.351562 0.359375 0.781250 +v -0.351562 0.359375 0.781250 +v 0.437500 0.328125 0.765625 +v -0.437500 0.328125 0.765625 +v 0.500000 0.390625 0.687500 +v -0.500000 0.390625 0.687500 +v 0.546875 0.437500 0.578125 +v -0.546875 0.437500 0.578125 +v 0.625000 0.242188 0.562500 +v -0.625000 0.242188 0.562500 +v 0.562500 0.242188 0.671875 +v -0.562500 0.242188 0.671875 +v 0.468750 0.242188 0.757812 +v -0.468750 0.242188 0.757812 +v 0.476562 0.242188 0.773438 +v -0.476562 0.242188 0.773438 +v 0.445312 0.335938 0.781250 +v -0.445312 0.335938 0.781250 +v 0.351562 0.375000 0.804688 +v -0.351562 0.375000 0.804688 +v 0.265625 0.335938 0.820312 +v -0.265625 0.335938 0.820312 +v 0.226562 0.242188 0.820312 +v -0.226562 0.242188 0.820312 +v 0.265625 0.156250 0.820312 +v -0.265625 0.156250 0.820312 +v 0.351562 0.242188 0.828125 +v -0.351562 0.242188 0.828125 +v 0.351562 0.117188 0.804688 +v -0.351562 0.117188 0.804688 +v 0.445312 0.156250 0.781250 +v -0.445312 0.156250 0.781250 +v 0.000000 0.429688 0.742188 +v 0.000000 0.351562 0.820312 +v 0.000000 -0.679688 0.734375 +v 0.000000 -0.320312 0.781250 +v 0.000000 -0.187500 0.796875 +v 0.000000 -0.773438 0.718750 +v 0.000000 0.406250 0.601562 +v 0.000000 0.570312 0.570312 +v 0.000000 0.898438 -0.546875 +v 0.000000 0.562500 -0.851562 +v 0.000000 0.070312 -0.828125 +v 0.000000 -0.382812 -0.351562 +v 0.203125 -0.187500 0.562500 +v -0.203125 -0.187500 0.562500 +v 0.312500 -0.437500 0.570312 +v -0.312500 -0.437500 0.570312 +v 0.351562 -0.695312 0.570312 +v -0.351562 -0.695312 0.570312 +v 0.367188 -0.890625 0.531250 +v -0.367188 -0.890625 0.531250 +v 0.328125 -0.945312 0.523438 +v -0.328125 -0.945312 0.523438 +v 0.179688 -0.968750 0.554688 +v -0.179688 -0.968750 0.554688 +v 0.000000 -0.984375 0.578125 +v 0.437500 -0.140625 0.531250 +v -0.437500 -0.140625 0.531250 +v 0.632812 -0.039062 0.539062 +v -0.632812 -0.039062 0.539062 +v 0.828125 0.148438 0.445312 +v -0.828125 0.148438 0.445312 +v 0.859375 0.429688 0.593750 +v -0.859375 0.429688 0.593750 +v 0.710938 0.484375 0.625000 +v -0.710938 0.484375 0.625000 +v 0.492188 0.601562 0.687500 +v -0.492188 0.601562 0.687500 +v 0.320312 0.757812 0.734375 +v -0.320312 0.757812 0.734375 +v 0.156250 0.718750 0.757812 +v -0.156250 0.718750 0.757812 +v 0.062500 0.492188 0.750000 +v -0.062500 0.492188 0.750000 +v 0.164062 0.414062 0.773438 +v -0.164062 0.414062 0.773438 +v 0.125000 0.304688 0.765625 +v -0.125000 0.304688 0.765625 +v 0.203125 0.093750 0.742188 +v -0.203125 0.093750 0.742188 +v 0.375000 0.015625 0.703125 +v -0.375000 0.015625 0.703125 +v 0.492188 0.062500 0.671875 +v -0.492188 0.062500 0.671875 +v 0.625000 0.187500 0.648438 +v -0.625000 0.187500 0.648438 +v 0.640625 0.296875 0.648438 +v -0.640625 0.296875 0.648438 +v 0.601562 0.375000 0.664062 +v -0.601562 0.375000 0.664062 +v 0.429688 0.437500 0.718750 +v -0.429688 0.437500 0.718750 +v 0.250000 0.468750 0.757812 +v -0.250000 0.468750 0.757812 +v 0.000000 -0.765625 0.734375 +v 0.109375 -0.718750 0.734375 +v -0.109375 -0.718750 0.734375 +v 0.117188 -0.835938 0.710938 +v -0.117188 -0.835938 0.710938 +v 0.062500 -0.882812 0.695312 +v -0.062500 -0.882812 0.695312 +v 0.000000 -0.890625 0.687500 +v 0.000000 -0.195312 0.750000 +v 0.000000 -0.140625 0.742188 +v 0.101562 -0.148438 0.742188 +v -0.101562 -0.148438 0.742188 +v 0.125000 -0.226562 0.750000 +v -0.125000 -0.226562 0.750000 +v 0.085938 -0.289062 0.742188 +v -0.085938 -0.289062 0.742188 +v 0.398438 -0.046875 0.671875 +v -0.398438 -0.046875 0.671875 +v 0.617188 0.054688 0.625000 +v -0.617188 0.054688 0.625000 +v 0.726562 0.203125 0.601562 +v -0.726562 0.203125 0.601562 +v 0.742188 0.375000 0.656250 +v -0.742188 0.375000 0.656250 +v 0.687500 0.414062 0.726562 +v -0.687500 0.414062 0.726562 +v 0.437500 0.546875 0.796875 +v -0.437500 0.546875 0.796875 +v 0.312500 0.640625 0.835938 +v -0.312500 0.640625 0.835938 +v 0.203125 0.617188 0.851562 +v -0.203125 0.617188 0.851562 +v 0.101562 0.429688 0.843750 +v -0.101562 0.429688 0.843750 +v 0.125000 -0.101562 0.812500 +v -0.125000 -0.101562 0.812500 +v 0.210938 -0.445312 0.710938 +v -0.210938 -0.445312 0.710938 +v 0.250000 -0.703125 0.687500 +v -0.250000 -0.703125 0.687500 +v 0.265625 -0.820312 0.664062 +v -0.265625 -0.820312 0.664062 +v 0.234375 -0.914062 0.632812 +v -0.234375 -0.914062 0.632812 +v 0.164062 -0.929688 0.632812 +v -0.164062 -0.929688 0.632812 +v 0.000000 -0.945312 0.640625 +v 0.000000 0.046875 0.726562 +v 0.000000 0.210938 0.765625 +v 0.328125 0.476562 0.742188 +v -0.328125 0.476562 0.742188 +v 0.164062 0.140625 0.750000 +v -0.164062 0.140625 0.750000 +v 0.132812 0.210938 0.757812 +v -0.132812 0.210938 0.757812 +v 0.117188 -0.687500 0.734375 +v -0.117188 -0.687500 0.734375 +v 0.078125 -0.445312 0.750000 +v -0.078125 -0.445312 0.750000 +v 0.000000 -0.445312 0.750000 +v 0.000000 -0.328125 0.742188 +v 0.093750 -0.273438 0.781250 +v -0.093750 -0.273438 0.781250 +v 0.132812 -0.226562 0.796875 +v -0.132812 -0.226562 0.796875 +v 0.109375 -0.132812 0.781250 +v -0.109375 -0.132812 0.781250 +v 0.039062 -0.125000 0.781250 +v -0.039062 -0.125000 0.781250 +v 0.000000 -0.203125 0.828125 +v 0.046875 -0.148438 0.812500 +v -0.046875 -0.148438 0.812500 +v 0.093750 -0.156250 0.812500 +v -0.093750 -0.156250 0.812500 +v 0.109375 -0.226562 0.828125 +v -0.109375 -0.226562 0.828125 +v 0.078125 -0.250000 0.804688 +v -0.078125 -0.250000 0.804688 +v 0.000000 -0.289062 0.804688 +v 0.257812 -0.312500 0.554688 +v -0.257812 -0.312500 0.554688 +v 0.164062 -0.242188 0.710938 +v -0.164062 -0.242188 0.710938 +v 0.179688 -0.312500 0.710938 +v -0.179688 -0.312500 0.710938 +v 0.234375 -0.250000 0.554688 +v -0.234375 -0.250000 0.554688 +v 0.000000 -0.875000 0.687500 +v 0.046875 -0.867188 0.687500 +v -0.046875 -0.867188 0.687500 +v 0.093750 -0.820312 0.710938 +v -0.093750 -0.820312 0.710938 +v 0.093750 -0.742188 0.726562 +v -0.093750 -0.742188 0.726562 +v 0.000000 -0.781250 0.656250 +v 0.093750 -0.750000 0.664062 +v -0.093750 -0.750000 0.664062 +v 0.093750 -0.812500 0.640625 +v -0.093750 -0.812500 0.640625 +v 0.046875 -0.851562 0.632812 +v -0.046875 -0.851562 0.632812 +v 0.000000 -0.859375 0.632812 +v 0.171875 0.218750 0.781250 +v -0.171875 0.218750 0.781250 +v 0.187500 0.156250 0.773438 +v -0.187500 0.156250 0.773438 +v 0.335938 0.429688 0.757812 +v -0.335938 0.429688 0.757812 +v 0.273438 0.421875 0.773438 +v -0.273438 0.421875 0.773438 +v 0.421875 0.398438 0.773438 +v -0.421875 0.398438 0.773438 +v 0.562500 0.351562 0.695312 +v -0.562500 0.351562 0.695312 +v 0.585938 0.289062 0.687500 +v -0.585938 0.289062 0.687500 +v 0.578125 0.195312 0.679688 +v -0.578125 0.195312 0.679688 +v 0.476562 0.101562 0.718750 +v -0.476562 0.101562 0.718750 +v 0.375000 0.062500 0.742188 +v -0.375000 0.062500 0.742188 +v 0.226562 0.109375 0.781250 +v -0.226562 0.109375 0.781250 +v 0.179688 0.296875 0.781250 +v -0.179688 0.296875 0.781250 +v 0.210938 0.375000 0.781250 +v -0.210938 0.375000 0.781250 +v 0.234375 0.359375 0.757812 +v -0.234375 0.359375 0.757812 +v 0.195312 0.296875 0.757812 +v -0.195312 0.296875 0.757812 +v 0.242188 0.125000 0.757812 +v -0.242188 0.125000 0.757812 +v 0.375000 0.085938 0.726562 +v -0.375000 0.085938 0.726562 +v 0.460938 0.117188 0.703125 +v -0.460938 0.117188 0.703125 +v 0.546875 0.210938 0.671875 +v -0.546875 0.210938 0.671875 +v 0.554688 0.281250 0.671875 +v -0.554688 0.281250 0.671875 +v 0.531250 0.335938 0.679688 +v -0.531250 0.335938 0.679688 +v 0.414062 0.390625 0.750000 +v -0.414062 0.390625 0.750000 +v 0.281250 0.398438 0.765625 +v -0.281250 0.398438 0.765625 +v 0.335938 0.406250 0.750000 +v -0.335938 0.406250 0.750000 +v 0.203125 0.171875 0.750000 +v -0.203125 0.171875 0.750000 +v 0.195312 0.226562 0.750000 +v -0.195312 0.226562 0.750000 +v 0.109375 0.460938 0.609375 +v -0.109375 0.460938 0.609375 +v 0.195312 0.664062 0.617188 +v -0.195312 0.664062 0.617188 +v 0.335938 0.687500 0.593750 +v -0.335938 0.687500 0.593750 +v 0.484375 0.554688 0.554688 +v -0.484375 0.554688 0.554688 +v 0.679688 0.453125 0.492188 +v -0.679688 0.453125 0.492188 +v 0.796875 0.406250 0.460938 +v -0.796875 0.406250 0.460938 +v 0.773438 0.164062 0.375000 +v -0.773438 0.164062 0.375000 +v 0.601562 0.000000 0.414062 +v -0.601562 0.000000 0.414062 +v 0.437500 -0.093750 0.468750 +v -0.437500 -0.093750 0.468750 +v 0.000000 0.898438 0.289062 +v 0.000000 0.984375 -0.078125 +v 0.000000 -0.195312 -0.671875 +v 0.000000 -0.460938 0.187500 +v 0.000000 -0.976562 0.460938 +v 0.000000 -0.804688 0.343750 +v 0.000000 -0.570312 0.320312 +v 0.000000 -0.484375 0.281250 +v 0.851562 0.234375 0.054688 +v -0.851562 0.234375 0.054688 +v 0.859375 0.320312 -0.046875 +v -0.859375 0.320312 -0.046875 +v 0.773438 0.265625 -0.437500 +v -0.773438 0.265625 -0.437500 +v 0.460938 0.437500 -0.703125 +v -0.460938 0.437500 -0.703125 +v 0.734375 -0.046875 0.070312 +v -0.734375 -0.046875 0.070312 +v 0.593750 -0.125000 -0.164062 +v -0.593750 -0.125000 -0.164062 +v 0.640625 -0.007812 -0.429688 +v -0.640625 -0.007812 -0.429688 +v 0.335938 0.054688 -0.664062 +v -0.335938 0.054688 -0.664062 +v 0.234375 -0.351562 0.406250 +v -0.234375 -0.351562 0.406250 +v 0.179688 -0.414062 0.257812 +v -0.179688 -0.414062 0.257812 +v 0.289062 -0.710938 0.382812 +v -0.289062 -0.710938 0.382812 +v 0.250000 -0.500000 0.390625 +v -0.250000 -0.500000 0.390625 +v 0.328125 -0.914062 0.398438 +v -0.328125 -0.914062 0.398438 +v 0.140625 -0.757812 0.367188 +v -0.140625 -0.757812 0.367188 +v 0.125000 -0.539062 0.359375 +v -0.125000 -0.539062 0.359375 +v 0.164062 -0.945312 0.437500 +v -0.164062 -0.945312 0.437500 +v 0.218750 -0.281250 0.429688 +v -0.218750 -0.281250 0.429688 +v 0.210938 -0.226562 0.468750 +v -0.210938 -0.226562 0.468750 +v 0.203125 -0.171875 0.500000 +v -0.203125 -0.171875 0.500000 +v 0.210938 -0.390625 0.164062 +v -0.210938 -0.390625 0.164062 +v 0.296875 -0.312500 -0.265625 +v -0.296875 -0.312500 -0.265625 +v 0.343750 -0.148438 -0.539062 +v -0.343750 -0.148438 -0.539062 +v 0.453125 0.867188 -0.382812 +v -0.453125 0.867188 -0.382812 +v 0.453125 0.929688 -0.070312 +v -0.453125 0.929688 -0.070312 +v 0.453125 0.851562 0.234375 +v -0.453125 0.851562 0.234375 +v 0.460938 0.523438 0.429688 +v -0.460938 0.523438 0.429688 +v 0.726562 0.406250 0.335938 +v -0.726562 0.406250 0.335938 +v 0.632812 0.453125 0.281250 +v -0.632812 0.453125 0.281250 +v 0.640625 0.703125 0.054688 +v -0.640625 0.703125 0.054688 +v 0.796875 0.562500 0.125000 +v -0.796875 0.562500 0.125000 +v 0.796875 0.617188 -0.117188 +v -0.796875 0.617188 -0.117188 +v 0.640625 0.750000 -0.195312 +v -0.640625 0.750000 -0.195312 +v 0.640625 0.679688 -0.445312 +v -0.640625 0.679688 -0.445312 +v 0.796875 0.539062 -0.359375 +v -0.796875 0.539062 -0.359375 +v 0.617188 0.328125 -0.585938 +v -0.617188 0.328125 -0.585938 +v 0.484375 0.023438 -0.546875 +v -0.484375 0.023438 -0.546875 +v 0.820312 0.328125 -0.203125 +v -0.820312 0.328125 -0.203125 +v 0.406250 -0.171875 0.148438 +v -0.406250 -0.171875 0.148438 +v 0.429688 -0.195312 -0.210938 +v -0.429688 -0.195312 -0.210938 +v 0.890625 0.406250 -0.234375 +v -0.890625 0.406250 -0.234375 +v 0.773438 -0.140625 -0.125000 +v -0.773438 -0.140625 -0.125000 +v 1.039062 -0.101562 -0.328125 +v -1.039062 -0.101562 -0.328125 +v 1.281250 0.054688 -0.429688 +v -1.281250 0.054688 -0.429688 +v 1.351562 0.320312 -0.421875 +v -1.351562 0.320312 -0.421875 +v 1.234375 0.507812 -0.421875 +v -1.234375 0.507812 -0.421875 +v 1.023438 0.476562 -0.312500 +v -1.023438 0.476562 -0.312500 +v 1.015625 0.414062 -0.289062 +v -1.015625 0.414062 -0.289062 +v 1.187500 0.437500 -0.390625 +v -1.187500 0.437500 -0.390625 +v 1.265625 0.289062 -0.406250 +v -1.265625 0.289062 -0.406250 +v 1.210938 0.078125 -0.406250 +v -1.210938 0.078125 -0.406250 +v 1.031250 -0.039062 -0.304688 +v -1.031250 -0.039062 -0.304688 +v 0.828125 -0.070312 -0.132812 +v -0.828125 -0.070312 -0.132812 +v 0.921875 0.359375 -0.218750 +v -0.921875 0.359375 -0.218750 +v 0.945312 0.304688 -0.289062 +v -0.945312 0.304688 -0.289062 +v 0.882812 -0.023438 -0.210938 +v -0.882812 -0.023438 -0.210938 +v 1.039062 0.000000 -0.367188 +v -1.039062 0.000000 -0.367188 +v 1.187500 0.093750 -0.445312 +v -1.187500 0.093750 -0.445312 +v 1.234375 0.250000 -0.445312 +v -1.234375 0.250000 -0.445312 +v 1.171875 0.359375 -0.437500 +v -1.171875 0.359375 -0.437500 +v 1.023438 0.343750 -0.359375 +v -1.023438 0.343750 -0.359375 +v 0.843750 0.289062 -0.210938 +v -0.843750 0.289062 -0.210938 +v 0.835938 0.171875 -0.273438 +v -0.835938 0.171875 -0.273438 +v 0.757812 0.093750 -0.273438 +v -0.757812 0.093750 -0.273438 +v 0.820312 0.085938 -0.273438 +v -0.820312 0.085938 -0.273438 +v 0.843750 0.015625 -0.273438 +v -0.843750 0.015625 -0.273438 +v 0.812500 -0.015625 -0.273438 +v -0.812500 -0.015625 -0.273438 +v 0.726562 0.000000 -0.070312 +v -0.726562 0.000000 -0.070312 +v 0.718750 -0.023438 -0.171875 +v -0.718750 -0.023438 -0.171875 +v 0.718750 0.039062 -0.187500 +v -0.718750 0.039062 -0.187500 +v 0.796875 0.203125 -0.210938 +v -0.796875 0.203125 -0.210938 +v 0.890625 0.242188 -0.265625 +v -0.890625 0.242188 -0.265625 +v 0.890625 0.234375 -0.320312 +v -0.890625 0.234375 -0.320312 +v 0.812500 -0.015625 -0.320312 +v -0.812500 -0.015625 -0.320312 +v 0.851562 0.015625 -0.320312 +v -0.851562 0.015625 -0.320312 +v 0.828125 0.078125 -0.320312 +v -0.828125 0.078125 -0.320312 +v 0.765625 0.093750 -0.320312 +v -0.765625 0.093750 -0.320312 +v 0.843750 0.171875 -0.320312 +v -0.843750 0.171875 -0.320312 +v 1.039062 0.328125 -0.414062 +v -1.039062 0.328125 -0.414062 +v 1.187500 0.343750 -0.484375 +v -1.187500 0.343750 -0.484375 +v 1.257812 0.242188 -0.492188 +v -1.257812 0.242188 -0.492188 +v 1.210938 0.085938 -0.484375 +v -1.210938 0.085938 -0.484375 +v 1.046875 0.000000 -0.421875 +v -1.046875 0.000000 -0.421875 +v 0.882812 -0.015625 -0.265625 +v -0.882812 -0.015625 -0.265625 +v 0.953125 0.289062 -0.343750 +v -0.953125 0.289062 -0.343750 +v 0.890625 0.109375 -0.328125 +v -0.890625 0.109375 -0.328125 +v 0.937500 0.062500 -0.335938 +v -0.937500 0.062500 -0.335938 +v 1.000000 0.125000 -0.367188 +v -1.000000 0.125000 -0.367188 +v 0.960938 0.171875 -0.351562 +v -0.960938 0.171875 -0.351562 +v 1.015625 0.234375 -0.375000 +v -1.015625 0.234375 -0.375000 +v 1.054688 0.187500 -0.382812 +v -1.054688 0.187500 -0.382812 +v 1.109375 0.210938 -0.390625 +v -1.109375 0.210938 -0.390625 +v 1.085938 0.273438 -0.390625 +v -1.085938 0.273438 -0.390625 +v 1.023438 0.437500 -0.484375 +v -1.023438 0.437500 -0.484375 +v 1.250000 0.468750 -0.546875 +v -1.250000 0.468750 -0.546875 +v 1.367188 0.296875 -0.500000 +v -1.367188 0.296875 -0.500000 +v 1.312500 0.054688 -0.531250 +v -1.312500 0.054688 -0.531250 +v 1.039062 -0.085938 -0.492188 +v -1.039062 -0.085938 -0.492188 +v 0.789062 -0.125000 -0.328125 +v -0.789062 -0.125000 -0.328125 +v 0.859375 0.382812 -0.382812 +v -0.859375 0.382812 -0.382812 +vn 0.6650 -0.2008 0.7194 +vn -0.6650 -0.2008 0.7194 +vn 0.8294 -0.3036 0.4689 +vn -0.8294 -0.3036 0.4689 +vn 0.4155 -0.7933 0.4449 +vn -0.4155 -0.7933 0.4449 +vn 0.3600 -0.5089 0.7820 +vn -0.3600 -0.5089 0.7820 +vn -0.0787 -0.5394 0.8384 +vn 0.0787 -0.5394 0.8384 +vn -0.2696 -0.8413 0.4685 +vn 0.2696 -0.8413 0.4685 +vn -0.7707 -0.3352 0.5420 +vn 0.7707 -0.3352 0.5420 +vn -0.4689 -0.1940 0.8617 +vn 0.4689 -0.1940 0.8617 +vn -0.4767 0.1907 0.8581 +vn 0.4767 0.1907 0.8581 +vn -0.7672 0.3264 0.5521 +vn 0.7672 0.3264 0.5521 +vn -0.2519 0.8173 0.5182 +vn 0.2519 0.8173 0.5182 +vn -0.0949 0.5696 0.8164 +vn 0.0949 0.5696 0.8164 +vn 0.3667 0.5370 0.7597 +vn -0.3667 0.5370 0.7597 +vn 0.4141 0.7672 0.4898 +vn -0.4141 0.7672 0.4898 +vn 0.8277 0.2952 0.4771 +vn -0.8277 0.2952 0.4771 +vn 0.6713 0.1971 0.7145 +vn -0.6713 0.1971 0.7145 +vn 0.8111 0.3244 -0.4867 +vn -0.8111 0.3244 -0.4867 +vn 0.2052 0.8206 -0.5334 +vn -0.2052 0.8206 -0.5334 +vn -0.4223 0.7806 -0.4607 +vn 0.4223 0.7806 -0.4607 +vn -0.8241 0.3225 -0.4658 +vn 0.8241 0.3225 -0.4658 +vn -0.8137 -0.3487 -0.4650 +vn 0.8137 -0.3487 -0.4650 +vn -0.4223 -0.7806 -0.4607 +vn 0.4223 -0.7806 -0.4607 +vn 0.2052 -0.8206 -0.5334 +vn -0.2052 -0.8206 -0.5334 +vn 0.7995 -0.3510 -0.4875 +vn -0.7995 -0.3510 -0.4875 +vn 0.4000 -0.0623 0.9144 +vn -0.4000 -0.0623 0.9144 +vn 0.3069 -0.1754 0.9354 +vn -0.3069 -0.1754 0.9354 +vn 0.0945 -0.1835 0.9785 +vn -0.0945 -0.1835 0.9785 +vn -0.0624 -0.0283 0.9977 +vn 0.0624 -0.0283 0.9977 +vn -0.0624 0.0260 0.9977 +vn 0.0624 0.0260 0.9977 +vn 0.0996 0.1729 0.9799 +vn -0.0996 0.1729 0.9799 +vn 0.3036 0.1656 0.9383 +vn -0.3036 0.1656 0.9383 +vn 0.4002 0.0572 0.9147 +vn -0.4002 0.0572 0.9147 +vn 0.1231 -0.8616 0.4924 +vn -0.1231 -0.8616 0.4924 +vn 0.2190 -0.8647 0.4520 +vn -0.2190 -0.8647 0.4520 +vn 0.5902 -0.4550 0.6668 +vn -0.5902 -0.4550 0.6668 +vn 0.7689 -0.0506 0.6374 +vn -0.7689 -0.0506 0.6374 +vn 0.7796 0.0900 0.6197 +vn -0.7796 0.0900 0.6197 +vn 0.3241 -0.8188 0.4739 +vn -0.3241 -0.8188 0.4739 +vn 0.3857 -0.6629 0.6417 +vn -0.3857 -0.6629 0.6417 +vn 0.6895 -0.4193 0.5906 +vn -0.6895 -0.4193 0.5906 +vn 0.6588 -0.3634 0.6588 +vn -0.6588 -0.3634 0.6588 +vn 0.5465 0.3707 0.7509 +vn -0.5465 0.3707 0.7509 +vn 0.5064 0.6464 0.5706 +vn -0.5064 0.6464 0.5706 +vn 0.6092 0.5167 0.6015 +vn -0.6092 0.5167 0.6015 +vn -0.0441 0.6610 0.7491 +vn 0.0441 0.6610 0.7491 +vn -0.7246 0.3187 0.6110 +vn 0.7246 0.3187 0.6110 +vn -0.5880 0.5554 0.5880 +vn 0.5880 0.5554 0.5880 +vn 0.5361 -0.3909 0.7482 +vn -0.5361 -0.3909 0.7482 +vn 0.2207 -0.4690 0.8552 +vn -0.2207 -0.4690 0.8552 +vn -0.0794 -0.5321 0.8429 +vn 0.0794 -0.5321 0.8429 +vn -0.0825 -0.6575 0.7490 +vn 0.0825 -0.6575 0.7490 +vn 0.0457 -0.5667 0.8226 +vn -0.0457 -0.5667 0.8226 +vn 0.2784 -0.2130 0.9365 +vn -0.2784 -0.2130 0.9365 +vn 0.3813 -0.1824 0.9063 +vn -0.3813 -0.1824 0.9063 +vn 0.3357 -0.2878 0.8969 +vn -0.3357 -0.2878 0.8969 +vn 0.3762 0.0603 0.9246 +vn -0.3762 0.0603 0.9246 +vn -0.1352 0.2680 0.9539 +vn 0.1352 0.2680 0.9539 +vn 0.3961 -0.4321 0.8102 +vn -0.3961 -0.4321 0.8102 +vn 0.1856 -0.2474 0.9510 +vn -0.1856 -0.2474 0.9510 +vn 0.0099 -0.1948 0.9808 +vn -0.0099 -0.1948 0.9808 +vn 0.0721 -0.6966 0.7138 +vn -0.0721 -0.6966 0.7138 +vn 0.1863 -0.5723 0.7986 +vn -0.1863 -0.5723 0.7986 +vn 0.3157 -0.2708 0.9094 +vn -0.3157 -0.2708 0.9094 +vn 0.3063 -0.0265 0.9516 +vn -0.3063 -0.0265 0.9516 +vn 0.3266 -0.1306 0.9361 +vn -0.3266 -0.1306 0.9361 +vn -0.0137 0.0574 0.9983 +vn 0.0137 0.0574 0.9983 +vn -0.0026 -0.0656 0.9978 +vn 0.0026 -0.0656 0.9978 +vn -0.0000 -0.0000 1.0000 +vn 0.8174 -0.5744 -0.0442 +vn -0.8174 -0.5744 -0.0442 +vn 0.9494 0.2297 -0.2144 +vn -0.9494 0.2297 -0.2144 +vn 0.0825 0.9073 -0.4124 +vn -0.0825 0.9073 -0.4124 +vn -0.8836 0.3555 0.3047 +vn 0.8836 0.3555 0.3047 +vn 0.4207 -0.8797 0.2218 +vn -0.4207 -0.8797 0.2218 +vn 0.2873 -0.5747 0.7663 +vn -0.2873 -0.5747 0.7663 +vn -0.6542 0.6019 0.4580 +vn 0.6542 0.6019 0.4580 +vn 0.1052 0.7892 0.6051 +vn -0.1052 0.7892 0.6051 +vn 0.7582 0.2916 0.5832 +vn -0.7582 0.2916 0.5832 +vn 0.3889 -0.7130 0.5834 +vn -0.3889 -0.7130 0.5834 +vn 0.0463 0.2314 0.9718 +vn -0.0463 0.2314 0.9718 +vn 0.0335 -0.4018 0.9151 +vn -0.0335 -0.4018 0.9151 +vn -0.4452 -0.1610 0.8809 +vn 0.4452 -0.1610 0.8809 +vn -0.2182 -0.4364 0.8729 +vn 0.2182 -0.4364 0.8729 +vn 0.4341 -0.1290 0.8916 +vn -0.4341 -0.1290 0.8916 +vn 0.3008 0.0501 0.9524 +vn -0.3008 0.0501 0.9524 +vn 0.8123 0.3010 0.4996 +vn -0.8123 0.3010 0.4996 +vn 0.8753 0.2574 0.4093 +vn -0.8753 0.2574 0.4093 +vn 0.9385 0.1601 0.3060 +vn -0.9385 0.1601 0.3060 +vn 0.2237 -0.6539 0.7227 +vn -0.2237 -0.6539 0.7227 +vn -0.1536 -0.1997 0.9677 +vn 0.1536 -0.1997 0.9677 +vn -0.2733 -0.1025 0.9565 +vn 0.2733 -0.1025 0.9565 +vn -0.0976 0.1952 0.9759 +vn 0.0976 0.1952 0.9759 +vn -0.1582 0.9494 0.2713 +vn 0.1582 0.9494 0.2713 +vn -0.6934 0.7082 0.1328 +vn 0.6934 0.7082 0.1328 +vn -1.0000 -0.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn 0.3051 -0.9450 0.1181 +vn -0.3051 -0.9450 0.1181 +vn 0.0298 -0.2981 0.9541 +vn -0.0298 -0.2981 0.9541 +vn 0.1353 -0.3479 0.9277 +vn -0.1353 -0.3479 0.9277 +vn -0.5085 -0.2755 0.8158 +vn 0.5085 -0.2755 0.8158 +vn -0.3843 -0.0419 0.9223 +vn 0.3843 -0.0419 0.9223 +vn -0.2083 0.0374 0.9774 +vn 0.2083 0.0374 0.9774 +vn -0.5721 -0.4767 0.6674 +vn 0.5721 -0.4767 0.6674 +vn -0.1369 -0.7531 0.6435 +vn 0.1369 -0.7531 0.6435 +vn 0.4088 -0.6071 0.6814 +vn -0.4088 -0.6071 0.6814 +vn 0.5740 -0.4130 0.7070 +vn -0.5740 -0.4130 0.7070 +vn 0.5665 -0.0968 0.8183 +vn -0.5665 -0.0968 0.8183 +vn 0.5703 0.1180 0.8129 +vn -0.5703 0.1180 0.8129 +vn 0.4823 0.5621 0.6719 +vn -0.4823 0.5621 0.6719 +vn 0.2604 0.6114 0.7473 +vn -0.2604 0.6114 0.7473 +vn 0.1640 0.3607 0.9182 +vn -0.1640 0.3607 0.9182 +vn -0.0178 0.2495 0.9682 +vn 0.0178 0.2495 0.9682 +vn 0.3273 -0.4166 0.8481 +vn -0.3273 -0.4166 0.8481 +vn 0.2811 -0.2610 0.9235 +vn -0.2811 -0.2610 0.9235 +vn -0.2542 -0.6514 0.7149 +vn 0.2542 -0.6514 0.7149 +vn -0.0260 -0.8455 0.5333 +vn 0.0260 -0.8455 0.5333 +vn -0.3518 -0.2606 0.8991 +vn 0.3518 -0.2606 0.8991 +vn -0.3523 -0.0110 0.9358 +vn 0.3523 -0.0110 0.9358 +vn -0.1317 0.4608 0.8777 +vn 0.1317 0.4608 0.8777 +vn -0.0342 0.6159 0.7870 +vn 0.0342 0.6159 0.7870 +vn 0.3603 0.5836 0.7277 +vn -0.3603 0.5836 0.7277 +vn 0.4988 0.5300 0.6858 +vn -0.4988 0.5300 0.6858 +vn 0.6667 -0.3333 0.6667 +vn -0.6667 -0.3333 0.6667 +vn 0.8165 -0.0731 0.5727 +vn -0.8165 -0.0731 0.5727 +vn 0.7840 0.1161 0.6098 +vn -0.7840 0.1161 0.6098 +vn -0.5306 0.8111 -0.2461 +vn 0.5306 0.8111 -0.2461 +vn -0.8511 0.3695 -0.3730 +vn 0.8511 0.3695 -0.3730 +vn -0.2446 0.8675 -0.4331 +vn 0.2446 0.8675 -0.4331 +vn 0.5924 0.7465 -0.3030 +vn -0.5924 0.7465 -0.3030 +vn 0.3685 0.8758 -0.3118 +vn -0.3685 0.8758 -0.3118 +vn 0.2821 0.9151 -0.2880 +vn -0.2821 0.9151 -0.2880 +vn 0.8561 0.1340 -0.4991 +vn -0.8561 0.1340 -0.4991 +vn 0.5342 -0.7233 -0.4376 +vn -0.5342 -0.7233 -0.4376 +vn 0.3849 -0.8131 -0.4368 +vn -0.3849 -0.8131 -0.4368 +vn 0.2335 -0.5806 -0.7800 +vn -0.2335 -0.5806 -0.7800 +vn 0.2449 -0.0583 -0.9678 +vn -0.2449 -0.0583 -0.9678 +vn 0.1163 -0.4535 -0.8837 +vn -0.1163 -0.4535 -0.8837 +vn 0.1152 -0.9836 -0.1388 +vn -0.1152 -0.9836 -0.1388 +vn 0.1184 -0.9669 -0.2260 +vn -0.1184 -0.9669 -0.2260 +vn 0.9597 -0.0085 -0.2808 +vn -0.9597 -0.0085 -0.2808 +vn 0.9319 0.1629 -0.3242 +vn -0.9319 0.1629 -0.3242 +vn 0.1626 0.0207 -0.9865 +vn -0.1626 0.0207 -0.9865 +vn -0.0188 -0.2177 -0.9758 +vn 0.0188 -0.2177 -0.9758 +vn 0.7538 -0.2926 -0.5884 +vn -0.7538 -0.2926 -0.5884 +vn 0.9196 0.1379 -0.3678 +vn -0.9196 0.1379 -0.3678 +vn 0.9297 0.3127 -0.1944 +vn -0.9297 0.3127 -0.1944 +vn 0.9120 0.3376 -0.2329 +vn -0.9120 0.3376 -0.2329 +vn 0.9407 0.3338 -0.0607 +vn -0.9407 0.3338 -0.0607 +vn 0.1761 -0.8805 -0.4402 +vn -0.1761 -0.8805 -0.4402 +vn 0.3708 -0.4733 -0.7991 +vn -0.3708 -0.4733 -0.7991 +vn 0.3107 -0.8284 -0.4660 +vn -0.3107 -0.8284 -0.4660 +vn 0.2793 -0.9515 -0.1287 +vn -0.2793 -0.9515 -0.1287 +vn 0.3139 -0.9321 -0.1807 +vn -0.3139 -0.9321 -0.1807 +vn 0.9762 -0.2083 -0.0609 +vn -0.9762 -0.2083 -0.0609 +vn 0.8267 -0.5066 0.2447 +vn -0.8267 -0.5066 0.2447 +vn 0.3449 -0.1158 -0.9315 +vn -0.3449 -0.1158 -0.9315 +vn 0.1203 0.9644 0.2355 +vn -0.1203 0.9644 0.2355 +vn 0.1275 0.9744 -0.1851 +vn -0.1275 0.9744 -0.1851 +vn 0.3492 0.5947 -0.7241 +vn -0.3492 0.5947 -0.7241 +vn 0.4153 0.8981 -0.1449 +vn -0.4153 0.8981 -0.1449 +vn 0.1845 0.7036 0.6863 +vn -0.1845 0.7036 0.6863 +vn 0.6056 0.7794 0.1608 +vn -0.6056 0.7794 0.1608 +vn 0.7033 0.6806 -0.2053 +vn -0.7033 0.6806 -0.2053 +vn 0.6679 0.2007 -0.7166 +vn -0.6679 0.2007 -0.7166 +vn 0.4948 0.4342 -0.7528 +vn -0.4948 0.4342 -0.7528 +vn 0.6423 0.7459 -0.1761 +vn -0.6423 0.7459 -0.1761 +vn 0.7182 0.6788 0.1530 +vn -0.7182 0.6788 0.1530 +vn 0.7388 0.3972 0.5444 +vn -0.7388 0.3972 0.5444 +vn 0.3428 0.9261 -0.1579 +vn -0.3428 0.9261 -0.1579 +vn 0.2270 0.5740 0.7867 +vn -0.2270 0.5740 0.7867 +vn -0.1722 0.1046 -0.9795 +vn 0.1722 0.1046 -0.9795 +vn 0.0425 0.9150 0.4013 +vn -0.0425 0.9150 0.4013 +vn -0.1616 0.1847 0.9694 +vn 0.1616 0.1847 0.9694 +vn 0.9791 0.1973 0.0483 +vn -0.9791 0.1973 0.0483 +vn 0.9470 0.0918 0.3079 +vn -0.9470 0.0918 0.3079 +vn 0.9794 0.1905 -0.0661 +vn -0.9794 0.1905 -0.0661 +vn 0.9938 0.0312 -0.1070 +vn -0.9938 0.0312 -0.1070 +vn 0.7116 -0.7008 0.0501 +vn -0.7116 -0.7008 0.0501 +vn 0.3722 -0.9243 0.0847 +vn -0.3722 -0.9243 0.0847 +vn 0.4465 -0.8644 0.2310 +vn -0.4465 -0.8644 0.2310 +vn 0.6066 -0.7578 0.2405 +vn -0.6066 -0.7578 0.2405 +vn 0.7325 -0.6368 0.2407 +vn -0.7325 -0.6368 0.2407 +vn 0.2637 -0.4499 0.8533 +vn -0.2637 -0.4499 0.8533 +vn 0.5568 -0.3181 -0.7673 +vn -0.5568 -0.3181 -0.7673 +vn 0.5004 -0.2807 -0.8190 +vn -0.5004 -0.2807 -0.8190 +vn 0.3190 -0.8494 -0.4205 +vn -0.3190 -0.8494 -0.4205 +vn 0.7198 -0.6356 -0.2793 +vn -0.7198 -0.6356 -0.2793 +vn 0.4972 -0.4408 -0.7473 +vn -0.4972 -0.4408 -0.7473 +vn 0.3506 0.3807 0.8557 +vn -0.3506 0.3807 0.8557 +vn 0.4566 0.1715 0.8730 +vn -0.4566 0.1715 0.8730 +vn 0.2583 0.1055 0.9603 +vn -0.2583 0.1055 0.9603 +vn 0.2455 -0.0802 0.9661 +vn -0.2455 -0.0802 0.9661 +vn 0.4643 -0.0599 0.8837 +vn -0.4643 -0.0599 0.8837 +vn 0.6225 -0.3045 0.7210 +vn -0.6225 -0.3045 0.7210 +vn 0.4500 0.6590 0.6027 +vn -0.4500 0.6590 0.6027 +vn -0.2667 0.8309 0.4884 +vn 0.2667 0.8309 0.4884 +vn -0.8284 0.2291 0.5111 +vn 0.8284 0.2291 0.5111 +vn -0.5251 -0.3566 0.7727 +vn 0.5251 -0.3566 0.7727 +vn 0.4546 -0.5665 0.6873 +vn -0.4546 -0.5665 0.6873 +vn 0.6996 -0.4497 0.5552 +vn -0.6996 -0.4497 0.5552 +vn 0.7220 -0.6827 -0.1126 +vn -0.7220 -0.6827 -0.1126 +vn -0.1919 0.2860 0.9388 +vn 0.1919 0.2860 0.9388 +vn 0.9048 -0.3734 -0.2047 +vn -0.9048 -0.3734 -0.2047 +vn 0.1034 0.1551 0.9825 +vn -0.1034 0.1551 0.9825 +vn 0.0841 0.9318 0.3530 +vn -0.0841 0.9318 0.3530 +vn 0.6446 -0.0883 0.7594 +vn -0.6446 -0.0883 0.7594 +vn 0.4309 0.4740 0.7678 +vn -0.4309 0.4740 0.7678 +vn 0.8032 -0.4847 0.3462 +vn -0.8032 -0.4847 0.3462 +vn 0.5811 -0.4128 0.7014 +vn -0.5811 -0.4128 0.7014 +vn 0.5910 -0.4305 0.6822 +vn -0.5910 -0.4305 0.6822 +vn 0.9818 -0.1804 -0.0591 +vn -0.9818 -0.1804 -0.0591 +vn 0.9105 -0.3965 -0.1175 +vn -0.9105 -0.3965 -0.1175 +vn 0.9972 -0.0181 -0.0725 +vn -0.9972 -0.0181 -0.0725 +vn 0.7313 -0.6543 0.1925 +vn -0.7313 -0.6543 0.1925 +vn 0.7867 -0.6079 0.1073 +vn -0.7867 -0.6079 0.1073 +vn 0.7022 -0.7022 0.1170 +vn -0.7022 -0.7022 0.1170 +vn 0.1840 0.9816 -0.0511 +vn -0.1840 0.9816 -0.0511 +vn 0.9352 0.3301 0.1284 +vn -0.9352 0.3301 0.1284 +vn 0.6633 -0.7463 0.0553 +vn -0.6633 -0.7463 0.0553 +vn -0.0085 0.9970 0.0767 +vn 0.0085 0.9970 0.0767 +vn 0.6237 -0.7061 0.3354 +vn -0.6237 -0.7061 0.3354 +vn 0.2733 -0.8925 0.3587 +vn -0.2733 -0.8925 0.3587 +vn -0.8328 -0.5080 -0.2200 +vn 0.8328 -0.5080 -0.2200 +vn -0.8339 0.2377 -0.4981 +vn 0.8339 0.2377 -0.4981 +vn -0.5655 0.7847 -0.2539 +vn 0.5655 0.7847 -0.2539 +vn -0.0560 0.9962 0.0672 +vn 0.0560 0.9962 0.0672 +vn 0.1445 0.0222 0.9893 +vn -0.1445 0.0222 0.9893 +vn 0.3275 0.0645 0.9427 +vn -0.3275 0.0645 0.9427 +vn 0.3127 0.0232 0.9496 +vn -0.3127 0.0232 0.9496 +vn 0.1710 0.0274 0.9849 +vn -0.1710 0.0274 0.9849 +vn 0.3487 0.2849 0.8929 +vn -0.3487 0.2849 0.8929 +vn 0.4006 -0.0343 0.9156 +vn -0.4006 -0.0343 0.9156 +vn 0.2572 -0.0603 0.9645 +vn -0.2572 -0.0603 0.9645 +vn 0.0637 -0.0106 0.9979 +vn -0.0637 -0.0106 0.9979 +vn -0.3637 0.7039 0.6101 +vn 0.3637 0.7039 0.6101 +vn 0.6299 0.0355 0.7759 +vn -0.6299 0.0355 0.7759 +vn 0.4472 -0.2002 0.8717 +vn -0.4472 -0.2002 0.8717 +vn 0.5072 -0.2141 0.8348 +vn -0.5072 -0.2141 0.8348 +vn 0.5258 0.2619 0.8093 +vn -0.5258 0.2619 0.8093 +vn 0.2980 0.5802 0.7580 +vn -0.2980 0.5802 0.7580 +vn 0.0930 -0.9924 -0.0805 +vn -0.0930 -0.9924 -0.0805 +vn 0.5006 -0.8657 0.0080 +vn -0.5006 -0.8657 0.0080 +vn 0.9285 -0.2497 0.2748 +vn -0.9285 -0.2497 0.2748 +vn 0.8393 0.5424 -0.0378 +vn -0.8393 0.5424 -0.0378 +vn -0.2355 0.9367 -0.2589 +vn 0.2355 0.9367 -0.2589 +vn -0.4499 0.8838 -0.1285 +vn 0.4499 0.8838 -0.1285 +vn -0.5384 -0.0098 -0.8427 +vn 0.5384 -0.0098 -0.8427 +vn -0.1910 -0.0241 -0.9813 +vn 0.1910 -0.0241 -0.9813 +vn 0.4046 0.0266 -0.9141 +vn -0.4046 0.0266 -0.9141 +vn -0.7819 0.6231 0.0197 +vn 0.7819 0.6231 0.0197 +vn 0.5428 -0.2063 -0.8142 +vn -0.5428 -0.2063 -0.8142 +vn -0.2474 -0.9231 -0.2945 +vn 0.2474 -0.9231 -0.2945 +vt 0.843250 0.588863 +vt 0.833697 0.611927 +vt 0.794218 0.611927 +vt 0.815334 0.560948 +vt 0.866314 0.937441 +vt 0.866314 0.897962 +vt 0.889378 0.888409 +vt 0.917293 0.916324 +vt 0.746541 0.611927 +vt 0.781622 0.527235 +vt 0.866314 0.985118 +vt 0.951006 0.950037 +vt 0.815334 0.662907 +vt 0.781622 0.696619 +vt 0.781622 0.950037 +vt 0.815334 0.916325 +vt 0.843250 0.634991 +vt 0.843250 0.888409 +vt 0.866314 0.644544 +vt 0.866314 0.684023 +vt 0.794218 0.865345 +vt 0.833697 0.865345 +vt 0.866314 0.731700 +vt 0.746541 0.865345 +vt 0.917293 0.662907 +vt 0.951006 0.696619 +vt 0.781622 0.780653 +vt 0.815334 0.814366 +vt 0.889378 0.634991 +vt 0.843250 0.842281 +vt 0.898931 0.611927 +vt 0.938410 0.611927 +vt 0.866314 0.793249 +vt 0.866314 0.832728 +vt 0.986087 0.611927 +vt 0.866314 0.745572 +vt 0.917294 0.560947 +vt 0.951006 0.527235 +vt 0.951006 0.780653 +vt 0.917294 0.814365 +vt 0.889378 0.588863 +vt 0.889378 0.842281 +vt 0.866314 0.579310 +vt 0.866314 0.539831 +vt 0.938410 0.865345 +vt 0.898931 0.865345 +vt 0.866314 0.492154 +vt 0.986087 0.865345 +vt 0.866314 0.585461 +vt 0.847600 0.593213 +vt 0.892780 0.865345 +vt 0.885028 0.884059 +vt 0.885028 0.593213 +vt 0.885028 0.846631 +vt 0.892780 0.611927 +vt 0.866314 0.838879 +vt 0.885028 0.630641 +vt 0.847600 0.846631 +vt 0.866314 0.638393 +vt 0.839848 0.865345 +vt 0.847600 0.630641 +vt 0.847600 0.884059 +vt 0.839848 0.611927 +vt 0.866314 0.891811 +vt 0.866314 0.611927 +vt 0.866314 0.865345 +vt 0.520711 0.060503 +vt 0.517028 0.068490 +vt 0.500000 0.064527 +vt 0.500000 0.054411 +vt 0.482972 0.068490 +vt 0.479289 0.060503 +vt 0.530457 0.065062 +vt 0.522612 0.070678 +vt 0.477388 0.070678 +vt 0.469543 0.065062 +vt 0.532878 0.067822 +vt 0.526301 0.079422 +vt 0.473699 0.079422 +vt 0.467122 0.067822 +vt 0.544695 0.083023 +vt 0.529228 0.091098 +vt 0.470772 0.091098 +vt 0.455305 0.083023 +vt 0.565647 0.115495 +vt 0.537536 0.127779 +vt 0.462464 0.127779 +vt 0.434353 0.115495 +vt 0.586916 0.172042 +vt 0.626605 0.208159 +vt 0.600470 0.238288 +vt 0.535885 0.215568 +vt 0.399530 0.238288 +vt 0.373395 0.208159 +vt 0.413084 0.172042 +vt 0.464115 0.215568 +vt 0.650908 0.240294 +vt 0.636962 0.261221 +vt 0.363038 0.261221 +vt 0.349092 0.240294 +vt 0.689501 0.268805 +vt 0.655896 0.284413 +vt 0.344104 0.284413 +vt 0.310499 0.268805 +vt 0.684517 0.317795 +vt 0.659507 0.313152 +vt 0.340493 0.313152 +vt 0.315483 0.317795 +vt 0.671357 0.334694 +vt 0.649107 0.322437 +vt 0.350893 0.322437 +vt 0.328643 0.334694 +vt 0.636775 0.370732 +vt 0.613636 0.353108 +vt 0.386364 0.353108 +vt 0.363225 0.370732 +vt 0.602261 0.395588 +vt 0.594178 0.371277 +vt 0.405822 0.371277 +vt 0.397739 0.395588 +vt 0.581044 0.398468 +vt 0.577351 0.373341 +vt 0.422649 0.373341 +vt 0.418956 0.398468 +vt 0.532016 0.387365 +vt 0.539817 0.354339 +vt 0.460183 0.354339 +vt 0.467984 0.387365 +vt 0.500000 0.382860 +vt 0.500000 0.340417 +vt 0.559135 0.334326 +vt 0.579057 0.335646 +vt 0.420943 0.335646 +vt 0.440865 0.334326 +vt 0.592090 0.332885 +vt 0.407910 0.332885 +vt 0.606163 0.325516 +vt 0.393837 0.325516 +vt 0.628251 0.311636 +vt 0.371749 0.311636 +vt 0.635551 0.300507 +vt 0.364449 0.300507 +vt 0.631484 0.283889 +vt 0.368516 0.283889 +vt 0.611331 0.264411 +vt 0.388669 0.264411 +vt 0.592372 0.254897 +vt 0.407628 0.254897 +vt 0.559669 0.267717 +vt 0.440331 0.267717 +vt 0.550878 0.277832 +vt 0.500000 0.252445 +vt 0.449122 0.277832 +vt 0.544001 0.314523 +vt 0.455999 0.314523 +vt 0.500000 0.295691 +vt 0.543637 0.293371 +vt 0.456363 0.293371 +vt 0.506819 0.075382 +vt 0.500000 0.073497 +vt 0.493181 0.075382 +vt 0.511782 0.080633 +vt 0.488218 0.080633 +vt 0.512172 0.093457 +vt 0.487828 0.093457 +vt 0.514257 0.133422 +vt 0.513874 0.097191 +vt 0.486126 0.097191 +vt 0.485743 0.133422 +vt 0.520226 0.164615 +vt 0.500000 0.157864 +vt 0.500000 0.134352 +vt 0.479774 0.164615 +vt 0.500000 0.100063 +vt 0.500000 0.091346 +vt 0.530258 0.180239 +vt 0.521901 0.181560 +vt 0.517666 0.172353 +vt 0.482334 0.172353 +vt 0.478099 0.181560 +vt 0.469742 0.180239 +vt 0.523673 0.198817 +vt 0.518957 0.194728 +vt 0.481043 0.194728 +vt 0.476327 0.198817 +vt 0.500000 0.203867 +vt 0.508211 0.197295 +vt 0.491789 0.197295 +vt 0.500000 0.197278 +vt 0.500000 0.192167 +vt 0.500000 0.165170 +vt 0.513538 0.176949 +vt 0.500000 0.171718 +vt 0.486462 0.176949 +vt 0.500000 0.186182 +vt 0.508818 0.192407 +vt 0.491182 0.192407 +vt 0.515232 0.190709 +vt 0.484768 0.190709 +vt 0.516908 0.181873 +vt 0.483092 0.181873 +vt 0.544209 0.172814 +vt 0.455791 0.172814 +vt 0.541327 0.154899 +vt 0.458673 0.154899 +vt 0.578661 0.139176 +vt 0.421339 0.139176 +vt 0.583245 0.154155 +vt 0.416755 0.154155 +vt 0.500000 0.089977 +vt 0.509911 0.090724 +vt 0.490089 0.090724 +vt 0.509713 0.082236 +vt 0.490287 0.082236 +vt 0.505196 0.077083 +vt 0.494804 0.077083 +vt 0.500000 0.075473 +vt 0.503445 0.080840 +vt 0.500000 0.080320 +vt 0.496555 0.080840 +vt 0.506660 0.083289 +vt 0.493340 0.083289 +vt 0.506822 0.086791 +vt 0.493178 0.086791 +vt 0.500000 0.085637 +vt 0.562361 0.284338 +vt 0.559190 0.294882 +vt 0.437639 0.284338 +vt 0.440810 0.294882 +vt 0.563180 0.307151 +vt 0.436820 0.307151 +vt 0.570458 0.318697 +vt 0.429542 0.318697 +vt 0.569243 0.278245 +vt 0.430757 0.278245 +vt 0.589914 0.271772 +vt 0.410086 0.271772 +vt 0.602190 0.277180 +vt 0.397810 0.277180 +vt 0.617110 0.287175 +vt 0.382890 0.287175 +vt 0.618074 0.299197 +vt 0.381926 0.299197 +vt 0.615871 0.307438 +vt 0.384129 0.307438 +vt 0.598424 0.313725 +vt 0.401576 0.313725 +vt 0.590828 0.319797 +vt 0.409172 0.319797 +vt 0.582130 0.320991 +vt 0.417870 0.320991 +vt 0.578615 0.309394 +vt 0.583998 0.312892 +vt 0.421385 0.309394 +vt 0.416002 0.312892 +vt 0.589656 0.312336 +vt 0.410344 0.312336 +vt 0.596347 0.309249 +vt 0.403653 0.309249 +vt 0.606014 0.302517 +vt 0.393986 0.302517 +vt 0.607735 0.297520 +vt 0.392265 0.297520 +vt 0.606985 0.291216 +vt 0.393015 0.291216 +vt 0.598275 0.283083 +vt 0.401725 0.283083 +vt 0.589866 0.280167 +vt 0.410134 0.280167 +vt 0.576352 0.284624 +vt 0.423648 0.284624 +vt 0.572831 0.289915 +vt 0.427169 0.289915 +vt 0.573307 0.303342 +vt 0.426693 0.303342 +vt 0.572447 0.295716 +vt 0.427553 0.295716 +vt 0.529647 0.428636 +vt 0.500000 0.428636 +vt 0.470353 0.428636 +vt 0.584616 0.428636 +vt 0.415384 0.428636 +vt 0.622301 0.417889 +vt 0.377699 0.417889 +vt 0.666214 0.388954 +vt 0.333786 0.388954 +vt 0.701481 0.344467 +vt 0.298519 0.344467 +vt 0.712163 0.315527 +vt 0.287837 0.315527 +vt 0.704305 0.260225 +vt 0.295695 0.260225 +vt 0.672947 0.224880 +vt 0.327053 0.224880 +vt 0.640497 0.198841 +vt 0.359503 0.198841 +vt 0.603553 0.023452 +vt 0.625128 0.029461 +vt 0.635753 0.082198 +vt 0.598617 0.056841 +vt 0.364247 0.082198 +vt 0.374872 0.029461 +vt 0.396447 0.023452 +vt 0.401383 0.056841 +vt 0.546781 0.009442 +vt 0.556354 0.040906 +vt 0.453219 0.009442 +vt 0.443646 0.040906 +vt 0.500000 0.033223 +vt 0.527159 0.049514 +vt 0.472841 0.049514 +vt 0.537222 0.060794 +vt 0.462778 0.060794 +vt 0.558499 0.065137 +vt 0.441501 0.065137 +vt 0.588127 0.085177 +vt 0.411873 0.085177 +vt 0.607239 0.113940 +vt 0.392761 0.113940 +vt 0.612663 0.133675 +vt 0.605467 0.151503 +vt 0.394533 0.151503 +vt 0.387337 0.133675 +vt 0.600708 0.162985 +vt 0.399292 0.162985 +vt 0.922374 0.064228 +vt 0.859647 0.117994 +vt 0.823287 0.101559 +vt 0.861342 0.027230 +vt 0.176713 0.101559 +vt 0.140353 0.117994 +vt 0.077626 0.064228 +vt 0.138658 0.027230 +vt 0.765863 0.087001 +vt 0.774604 0.010837 +vt 0.234137 0.087001 +vt 0.225396 0.010837 +vt 0.661952 0.087561 +vt 0.647010 0.028716 +vt 0.338048 0.087561 +vt 0.352990 0.028716 +vt 0.743592 0.198572 +vt 0.766410 0.233065 +vt 0.256408 0.198572 +vt 0.233590 0.233065 +vt 0.987633 0.154243 +vt 0.889478 0.177602 +vt 0.110522 0.177602 +vt 0.012367 0.154243 +vt 0.899807 0.420886 +vt 0.844317 0.347370 +vt 0.881169 0.309153 +vt 0.958963 0.357385 +vt 0.118831 0.309153 +vt 0.155683 0.347370 +vt 0.100193 0.420886 +vt 0.041037 0.357385 +vt 0.903302 0.261367 +vt 0.999860 0.253531 +vt 0.096698 0.261367 +vt 0.000140 0.253531 +vt 0.724763 0.340212 +vt 0.744725 0.304629 +vt 0.766113 0.319494 +vt 0.255275 0.304629 +vt 0.275237 0.340212 +vt 0.233887 0.319494 +vt 0.793427 0.280495 +vt 0.826663 0.297810 +vt 0.206573 0.280495 +vt 0.173337 0.297810 +vt 0.823620 0.254612 +vt 0.855331 0.267956 +vt 0.176380 0.254612 +vt 0.144669 0.267956 +vt 0.835860 0.225225 +vt 0.868309 0.233525 +vt 0.164140 0.225225 +vt 0.131691 0.233525 +vt 0.813499 0.190705 +vt 0.851288 0.181145 +vt 0.148712 0.181145 +vt 0.186501 0.190705 +vt 0.772263 0.374010 +vt 0.227737 0.374010 +vt 0.744519 0.390057 +vt 0.255481 0.390057 +vt 0.824765 0.470987 +vt 0.175235 0.470987 +vt 0.792141 0.464714 +vt 0.742181 0.461543 +vt 0.726855 0.432574 +vt 0.273145 0.432574 +vt 0.257819 0.461543 +vt 0.207859 0.464714 +vt 0.795638 0.489991 +vt 0.204362 0.489991 +vt 0.786137 0.227788 +vt 0.213863 0.227788 +vt 0.802950 0.203415 +vt 0.197050 0.203415 +vt 0.769334 0.128771 +vt 0.691484 0.146686 +vt 0.230666 0.128771 +vt 0.308516 0.146686 +vt 0.780113 0.169386 +vt 0.219887 0.169386 +vt 0.803789 0.171181 +vt 0.830917 0.139518 +vt 0.169083 0.139518 +vt 0.196211 0.171181 +vt 0.574628 0.959188 +vt 0.464516 0.959188 +vt 0.477326 0.891852 +vt 0.545439 0.884582 +vt 0.272900 0.891852 +vt 0.285710 0.959188 +vt 0.175598 0.959188 +vt 0.204787 0.884582 +vt 0.605134 0.846978 +vt 0.715894 0.897069 +vt 0.145092 0.846978 +vt 0.034332 0.897069 +vt 0.605360 0.784410 +vt 0.683874 0.757011 +vt 0.144866 0.784410 +vt 0.066352 0.757011 +vt 0.574835 0.744212 +vt 0.617867 0.719156 +vt 0.175391 0.744212 +vt 0.132359 0.719156 +vt 0.534996 0.712528 +vt 0.568728 0.682132 +vt 0.215230 0.712528 +vt 0.181498 0.682132 +vt 0.483006 0.686791 +vt 0.508539 0.641024 +vt 0.267220 0.686791 +vt 0.241687 0.641024 +vt 0.513415 0.736977 +vt 0.478880 0.719593 +vt 0.271346 0.719593 +vt 0.236811 0.736977 +vt 0.541117 0.760754 +vt 0.209109 0.760754 +vt 0.557599 0.789442 +vt 0.192627 0.789442 +vt 0.553841 0.821849 +vt 0.196385 0.821849 +vt 0.524671 0.842380 +vt 0.225555 0.842380 +vt 0.485193 0.845321 +vt 0.265033 0.845321 +vt 0.786150 0.181127 +vt 0.770208 0.191225 +vt 0.213850 0.181127 +vt 0.229792 0.191225 +vt 0.408153 0.587507 +vt 0.409610 0.674022 +vt 0.342073 0.587507 +vt 0.340616 0.674022 +vt 0.400301 0.910556 +vt 0.414155 0.878318 +vt 0.336071 0.878318 +vt 0.349925 0.910556 +vt 0.443630 0.713731 +vt 0.306596 0.713731 +vt 0.429725 0.728622 +vt 0.392812 0.710774 +vt 0.357414 0.710774 +vt 0.320501 0.728622 +vt 0.422979 0.754609 +vt 0.432640 0.746527 +vt 0.327247 0.754609 +vt 0.317586 0.746527 +vt 0.427719 0.796173 +vt 0.391578 0.815187 +vt 0.358648 0.815187 +vt 0.322507 0.796173 +vt 0.448277 0.830976 +vt 0.301949 0.830976 +vt 0.797710 0.195652 +vt 0.802580 0.199758 +vt 0.197420 0.199758 +vt 0.202290 0.195652 +vt 0.789609 0.184671 +vt 0.210391 0.184671 +vt 0.466042 0.804091 +vt 0.490498 0.816075 +vt 0.284184 0.804091 +vt 0.259728 0.816075 +vt 0.448042 0.783921 +vt 0.302184 0.783921 +vt 0.438745 0.764960 +vt 0.311481 0.764960 +vt 0.445216 0.756351 +vt 0.305010 0.756351 +vt 0.449819 0.743458 +vt 0.300407 0.743458 +vt 0.456307 0.732687 +vt 0.293919 0.732687 +vt 0.475471 0.740871 +vt 0.274755 0.740871 +vt 0.514211 0.817769 +vt 0.236015 0.817769 +vt 0.527961 0.808598 +vt 0.222265 0.808598 +vt 0.530079 0.790754 +vt 0.220147 0.790754 +vt 0.518620 0.772385 +vt 0.231606 0.772385 +vt 0.498668 0.755033 +vt 0.251558 0.755033 +vt 0.468029 0.756171 +vt 0.459660 0.770459 +vt 0.282197 0.756171 +vt 0.290566 0.770459 +vt 0.487167 0.769899 +vt 0.477354 0.785393 +vt 0.263059 0.769899 +vt 0.272872 0.785393 +vt 0.504617 0.782999 +vt 0.496545 0.797122 +vt 0.245609 0.782999 +vt 0.253681 0.797122 +vt 0.516137 0.792591 +vt 0.513713 0.804019 +vt 0.234089 0.792591 +vt 0.236513 0.804019 +vt 0.574269 0.607668 +vt 0.613510 0.655816 +vt 0.175957 0.607668 +vt 0.136716 0.655816 +vt 0.644031 0.693270 +vt 0.106195 0.693270 +vt 0.668163 0.712097 +vt 0.082063 0.712097 +vt 0.727131 0.698475 +vt 0.676584 0.686010 +vt 0.023095 0.698475 +vt 0.073642 0.686010 +vt 0.729804 0.624370 +vt 0.667013 0.640198 +vt 0.020422 0.624370 +vt 0.083213 0.640198 +vt 0.721292 0.572934 +vt 0.648152 0.594596 +vt 0.028934 0.572934 +vt 0.102074 0.594596 +vt 0.630034 0.557583 +vt 0.717709 0.538143 +vt 0.032517 0.538143 +vt 0.120192 0.557583 +vt 0.526877 0.539235 +vt 0.223349 0.539235 +s 0 +f 47/1/1 1/2/1 3/3/1 45/4/1 +f 4/5/2 2/6/2 48/7/2 46/8/2 +f 45/4/3 3/3/3 5/9/3 43/10/3 +f 6/11/4 4/5/4 46/8/4 44/12/4 +f 3/3/5 9/13/5 7/14/5 5/9/5 +f 8/15/6 10/16/6 4/5/6 6/11/6 +f 1/2/7 11/17/7 9/13/7 3/3/7 +f 10/16/8 12/18/8 2/6/8 4/5/8 +f 11/17/9 13/19/9 15/20/9 9/13/9 +f 16/21/10 14/22/10 12/18/10 10/16/10 +f 9/13/11 15/20/11 17/23/11 7/14/11 +f 18/24/12 16/21/12 10/16/12 8/15/12 +f 15/20/13 21/25/13 19/26/13 17/23/13 +f 20/27/14 22/28/14 16/21/14 18/24/14 +f 13/19/15 23/29/15 21/25/15 15/20/15 +f 22/28/16 24/30/16 14/22/16 16/21/16 +f 23/29/17 25/31/17 27/32/17 21/25/17 +f 28/33/18 26/34/18 24/30/18 22/28/18 +f 21/25/19 27/32/19 29/35/19 19/26/19 +f 30/36/20 28/33/20 22/28/20 20/27/20 +f 27/32/21 33/37/21 31/38/21 29/35/21 +f 32/39/22 34/40/22 28/33/22 30/36/22 +f 25/31/23 35/41/23 33/37/23 27/32/23 +f 34/40/24 36/42/24 26/34/24 28/33/24 +f 35/41/25 37/43/25 39/44/25 33/37/25 +f 40/45/26 38/46/26 36/42/26 34/40/26 +f 33/37/27 39/44/27 41/47/27 31/38/27 +f 42/48/28 40/45/28 34/40/28 32/39/28 +f 39/44/29 45/4/29 43/10/29 41/47/29 +f 44/12/30 46/8/30 40/45/30 42/48/30 +f 37/43/31 47/1/31 45/4/31 39/44/31 +f 46/8/32 48/7/32 38/46/32 40/45/32 +f 47/1/33 37/43/33 51/49/33 49/50/33 +f 52/51/34 38/46/34 48/7/34 50/52/34 +f 37/43/35 35/41/35 53/53/35 51/49/35 +f 54/54/36 36/42/36 38/46/36 52/51/36 +f 35/41/37 25/31/37 55/55/37 53/53/37 +f 56/56/38 26/34/38 36/42/38 54/54/38 +f 25/31/39 23/29/39 57/57/39 55/55/39 +f 58/58/40 24/30/40 26/34/40 56/56/40 +f 23/29/41 13/19/41 59/59/41 57/57/41 +f 60/60/42 14/22/42 24/30/42 58/58/42 +f 13/19/43 11/17/43 63/61/43 59/59/43 +f 64/62/44 12/18/44 14/22/44 60/60/44 +f 11/17/45 1/2/45 65/63/45 63/61/45 +f 66/64/46 2/6/46 12/18/46 64/62/46 +f 1/2/47 47/1/47 49/50/47 65/63/47 +f 50/52/48 48/7/48 2/6/48 66/64/48 +f 61/65/49 65/63/49 49/50/49 +f 50/52/50 66/64/50 62/66/50 +f 63/61/51 65/63/51 61/65/51 +f 62/66/52 66/64/52 64/62/52 +f 61/65/53 59/59/53 63/61/53 +f 64/62/54 60/60/54 62/66/54 +f 61/65/55 57/57/55 59/59/55 +f 60/60/56 58/58/56 62/66/56 +f 61/65/57 55/55/57 57/57/57 +f 58/58/58 56/56/58 62/66/58 +f 61/65/59 53/53/59 55/55/59 +f 56/56/60 54/54/60 62/66/60 +f 61/65/61 51/49/61 53/53/61 +f 54/54/62 52/51/62 62/66/62 +f 61/65/63 49/50/63 51/49/63 +f 52/51/64 50/52/64 62/66/64 +f 89/67/65 174/68/65 176/69/65 91/70/65 +f 176/69/66 175/71/66 90/72/66 91/70/66 +f 87/73/67 172/74/67 174/68/67 89/67/67 +f 175/71/68 173/75/68 88/76/68 90/72/68 +f 85/77/69 170/78/69 172/74/69 87/73/69 +f 173/75/70 171/79/70 86/80/70 88/76/70 +f 83/81/71 168/82/71 170/78/71 85/77/71 +f 171/79/72 169/83/72 84/84/72 86/80/72 +f 81/85/73 166/86/73 168/82/73 83/81/73 +f 169/83/74 167/87/74 82/88/74 84/84/74 +f 79/89/75 92/90/75 146/91/75 164/92/75 +f 147/93/76 93/94/76 80/95/76 165/96/76 +f 92/90/77 94/97/77 148/98/77 146/91/77 +f 149/99/78 95/100/78 93/94/78 147/93/78 +f 94/97/79 96/101/79 150/102/79 148/98/79 +f 151/103/80 97/104/80 95/100/80 149/99/80 +f 96/101/81 98/105/81 152/106/81 150/102/81 +f 153/107/82 99/108/82 97/104/82 151/103/82 +f 98/105/83 100/109/83 154/110/83 152/106/83 +f 155/111/84 101/112/84 99/108/84 153/107/84 +f 100/109/85 102/113/85 156/114/85 154/110/85 +f 157/115/86 103/116/86 101/112/86 155/111/86 +f 102/113/87 104/117/87 158/118/87 156/114/87 +f 159/119/88 105/120/88 103/116/88 157/115/88 +f 104/117/89 106/121/89 160/122/89 158/118/89 +f 161/123/90 107/124/90 105/120/90 159/119/90 +f 106/121/91 108/125/91 162/126/91 160/122/91 +f 163/127/92 109/128/92 107/124/92 161/123/92 +f 108/125/93 67/129/93 68/130/93 162/126/93 +f 68/130/94 67/129/94 109/128/94 163/127/94 +f 110/131/95 128/132/95 160/122/95 162/126/95 +f 161/123/96 129/133/96 111/134/96 163/127/96 +f 128/132/97 179/135/97 158/118/97 160/122/97 +f 159/119/98 180/136/98 129/133/98 161/123/98 +f 126/137/99 156/114/99 158/118/99 179/135/99 +f 159/119/100 157/115/100 127/138/100 180/136/100 +f 124/139/101 154/110/101 156/114/101 126/137/101 +f 157/115/102 155/111/102 125/140/102 127/138/102 +f 122/141/103 152/106/103 154/110/103 124/139/103 +f 155/111/104 153/107/104 123/142/104 125/140/104 +f 120/143/105 150/102/105 152/106/105 122/141/105 +f 153/107/106 151/103/106 121/144/106 123/142/106 +f 118/145/107 148/98/107 150/102/107 120/143/107 +f 151/103/108 149/99/108 119/146/108 121/144/108 +f 116/147/109 146/91/109 148/98/109 118/145/109 +f 149/99/110 147/93/110 117/148/110 119/146/110 +f 114/149/111 164/92/111 146/91/111 116/147/111 +f 147/93/112 165/96/112 115/150/112 117/148/112 +f 114/149/113 181/151/113 177/152/113 164/92/113 +f 177/152/114 182/153/114 115/150/114 165/96/114 +f 110/131/115 162/126/115 68/130/115 112/154/115 +f 68/130/116 163/127/116 111/134/116 113/155/116 +f 112/154/117 68/130/117 178/156/117 183/157/117 +f 178/156/118 68/130/118 113/155/118 184/158/118 +f 177/152/119 181/151/119 183/157/119 178/156/119 +f 184/158/120 182/153/120 177/152/120 178/156/120 +f 135/159/121 137/160/121 176/69/121 174/68/121 +f 176/69/122 137/160/122 136/161/122 175/71/122 +f 133/162/123 135/159/123 174/68/123 172/74/123 +f 175/71/124 136/161/124 134/163/124 173/75/124 +f 131/164/125 133/162/125 172/74/125 170/78/125 +f 173/75/126 134/163/126 132/165/126 171/79/126 +f 166/86/127 187/166/127 185/167/127 168/82/127 +f 186/168/128 188/169/128 167/87/128 169/83/128 +f 131/164/129 170/78/129 168/82/129 185/167/129 +f 169/83/130 171/79/130 132/165/130 186/168/130 +f 144/170/131 190/171/131 189/172/131 187/166/131 +f 189/172/132 190/171/132 145/173/132 188/169/132 +f 185/167/133 187/166/133 189/172/133 69/174/133 +f 189/172/134 188/169/134 186/168/134 69/174/134 +f 130/175/135 131/164/135 185/167/135 69/174/135 +f 186/168/135 132/165/135 130/175/135 69/174/135 +f 142/176/136 193/177/136 191/178/136 144/170/136 +f 192/179/137 194/180/137 143/181/137 145/173/137 +f 140/182/138 195/183/138 193/177/138 142/176/138 +f 194/180/139 196/184/139 141/185/139 143/181/139 +f 139/186/140 197/187/140 195/183/140 140/182/140 +f 196/184/141 198/188/141 139/186/141 141/185/141 +f 138/189/142 71/190/142 197/187/142 139/186/142 +f 198/188/143 71/190/143 138/189/143 139/186/143 +f 190/171/144 144/170/144 191/178/144 70/191/144 +f 192/179/145 145/173/145 190/171/145 70/191/145 +f 70/191/146 191/178/146 206/192/146 208/193/146 +f 207/194/147 192/179/147 70/191/147 208/193/147 +f 71/190/148 199/195/148 200/196/148 197/187/148 +f 201/197/149 199/195/149 71/190/149 198/188/149 +f 197/187/150 200/196/150 202/198/150 195/183/150 +f 203/199/151 201/197/151 198/188/151 196/184/151 +f 195/183/152 202/198/152 204/200/152 193/177/152 +f 205/201/153 203/199/153 196/184/153 194/180/153 +f 193/177/154 204/200/154 206/192/154 191/178/154 +f 207/194/155 205/201/155 194/180/155 192/179/155 +f 199/195/156 204/200/156 202/198/156 200/196/156 +f 203/199/157 205/201/157 199/195/157 201/197/157 +f 199/195/158 208/193/158 206/192/158 204/200/158 +f 207/194/159 208/193/159 199/195/159 205/201/159 +f 139/186/160 140/182/160 164/92/160 177/152/160 +f 165/96/161 141/185/161 139/186/161 177/152/161 +f 140/182/162 142/176/162 211/202/162 164/92/162 +f 212/203/163 143/181/163 141/185/163 165/96/163 +f 142/176/164 144/170/164 213/204/164 211/202/164 +f 214/205/165 145/173/165 143/181/165 212/203/165 +f 144/170/166 187/166/166 166/86/166 213/204/166 +f 167/87/167 188/169/167 145/173/167 214/205/167 +f 81/85/168 209/206/168 213/204/168 166/86/168 +f 214/205/169 210/207/169 82/88/169 167/87/169 +f 209/206/170 215/208/170 211/202/170 213/204/170 +f 212/203/171 216/209/171 210/207/171 214/205/171 +f 79/89/172 164/92/172 211/202/172 215/208/172 +f 212/203/173 165/96/173 80/95/173 216/209/173 +f 131/164/174 130/175/174 72/210/174 222/211/174 +f 72/210/175 130/175/175 132/165/175 223/212/175 +f 133/162/176 131/164/176 222/211/176 220/213/176 +f 223/212/177 132/165/177 134/163/177 221/214/177 +f 135/159/178 133/162/178 220/213/178 218/215/178 +f 221/214/179 134/163/179 136/161/179 219/216/179 +f 137/160/180 135/159/180 218/215/180 217/217/180 +f 219/216/181 136/161/181 137/160/181 217/217/181 +f 217/217/182 218/215/182 229/218/182 231/219/182 +f 230/220/183 219/216/183 217/217/183 231/219/183 +f 218/215/184 220/213/184 227/221/184 229/218/184 +f 228/222/185 221/214/185 219/216/185 230/220/185 +f 220/213/186 222/211/186 225/223/186 227/221/186 +f 226/224/187 223/212/187 221/214/187 228/222/187 +f 222/211/188 72/210/188 224/225/188 225/223/188 +f 224/225/189 72/210/189 223/212/189 226/224/189 +f 224/225/190 231/219/190 229/218/190 225/223/190 +f 230/220/191 231/219/191 224/225/191 226/224/191 +f 225/223/192 229/218/192 227/221/192 +f 228/222/193 230/220/193 226/224/193 +f 183/157/194 181/151/194 234/226/194 232/227/194 +f 235/228/195 182/153/195 184/158/195 233/229/195 +f 112/154/196 183/157/196 232/227/196 254/230/196 +f 233/229/197 184/158/197 113/155/197 255/231/197 +f 110/131/198 112/154/198 254/230/198 256/232/198 +f 255/231/199 113/155/199 111/134/199 257/233/199 +f 181/151/200 114/149/200 252/234/200 234/226/200 +f 253/235/201 115/150/201 182/153/201 235/228/201 +f 114/149/202 116/147/202 250/236/202 252/234/202 +f 251/237/203 117/148/203 115/150/203 253/235/203 +f 116/147/204 118/145/204 248/238/204 250/236/204 +f 249/239/205 119/146/205 117/148/205 251/237/205 +f 118/145/206 120/143/206 246/240/206 248/238/206 +f 247/241/207 121/144/207 119/146/207 249/239/207 +f 120/143/208 122/141/208 244/242/208 246/240/208 +f 245/243/209 123/142/209 121/144/209 247/241/209 +f 122/141/210 124/139/210 242/244/210 244/242/210 +f 243/245/211 125/140/211 123/142/211 245/243/211 +f 124/139/212 126/137/212 240/246/212 242/244/212 +f 241/247/213 127/138/213 125/140/213 243/245/213 +f 126/137/214 179/135/214 236/248/214 240/246/214 +f 237/249/215 180/136/215 127/138/215 241/247/215 +f 179/135/216 128/132/216 238/250/216 236/248/216 +f 239/251/217 129/133/217 180/136/217 237/249/217 +f 128/132/218 110/131/218 256/232/218 238/250/218 +f 257/233/219 111/134/219 129/133/219 239/251/219 +f 238/250/220 256/232/220 258/252/220 276/253/220 +f 259/254/221 257/233/221 239/251/221 277/255/221 +f 236/248/222 238/250/222 276/253/222 278/256/222 +f 277/255/223 239/251/223 237/249/223 279/257/223 +f 240/246/224 236/248/224 278/256/224 274/258/224 +f 279/257/225 237/249/225 241/247/225 275/259/225 +f 242/244/226 240/246/226 274/258/226 272/260/226 +f 275/259/227 241/247/227 243/245/227 273/261/227 +f 244/242/228 242/244/228 272/260/228 270/262/228 +f 273/261/229 243/245/229 245/243/229 271/263/229 +f 246/240/230 244/242/230 270/262/230 268/264/230 +f 271/263/231 245/243/231 247/241/231 269/265/231 +f 248/238/232 246/240/232 268/264/232 266/266/232 +f 269/265/233 247/241/233 249/239/233 267/267/233 +f 250/236/234 248/238/234 266/266/234 264/268/234 +f 267/267/235 249/239/235 251/237/235 265/269/235 +f 252/234/236 250/236/236 264/268/236 262/270/236 +f 265/269/237 251/237/237 253/235/237 263/271/237 +f 234/226/238 252/234/238 262/270/238 280/272/238 +f 263/271/239 253/235/239 235/228/239 281/273/239 +f 256/232/240 254/230/240 260/274/240 258/252/240 +f 261/275/241 255/231/241 257/233/241 259/254/241 +f 254/230/242 232/227/242 282/276/242 260/274/242 +f 283/277/243 233/229/243 255/231/243 261/275/243 +f 232/227/244 234/226/244 280/272/244 282/276/244 +f 281/273/245 235/228/245 233/229/245 283/277/245 +f 67/129/246 108/125/246 284/278/246 73/279/246 +f 285/280/247 109/128/247 67/129/247 73/279/247 +f 108/125/248 106/121/248 286/281/248 284/278/248 +f 287/282/249 107/124/249 109/128/249 285/280/249 +f 106/121/250 104/117/250 288/283/250 286/281/250 +f 289/284/251 105/120/251 107/124/251 287/282/251 +f 104/117/252 102/113/252 290/285/252 288/283/252 +f 291/286/253 103/116/253 105/120/253 289/284/253 +f 102/113/254 100/109/254 292/287/254 290/285/254 +f 293/288/255 101/112/255 103/116/255 291/286/255 +f 100/109/256 98/105/256 294/289/256 292/287/256 +f 295/290/257 99/108/257 101/112/257 293/288/257 +f 98/105/258 96/101/258 296/291/258 294/289/258 +f 297/292/259 97/104/259 99/108/259 295/290/259 +f 96/101/260 94/97/260 298/293/260 296/291/260 +f 299/294/261 95/100/261 97/104/261 297/292/261 +f 94/97/262 92/90/262 300/295/262 298/293/262 +f 301/296/263 93/94/263 95/100/263 299/294/263 +f 308/297/264 309/298/264 328/299/264 338/300/264 +f 329/301/265 309/302/265 308/303/265 339/304/265 +f 307/305/266 308/297/266 338/300/266 336/306/266 +f 339/304/267 308/303/267 307/307/267 337/308/267 +f 306/309/268 307/305/268 336/306/268 340/310/268 +f 337/308/269 307/307/269 306/309/269 341/311/269 +f 89/67/270 91/70/270 306/309/270 340/310/270 +f 306/309/271 91/70/271 90/72/271 341/311/271 +f 87/73/272 89/67/272 340/310/272 334/312/272 +f 341/311/273 90/72/273 88/76/273 335/313/273 +f 85/77/274 87/73/274 334/312/274 330/314/274 +f 335/313/275 88/76/275 86/80/275 331/315/275 +f 83/81/276 85/77/276 330/314/276 332/316/276 +f 331/315/277 86/80/277 84/84/277 333/317/277 +f 330/314/278 336/306/278 338/300/278 332/316/278 +f 339/304/279 337/308/279 331/315/279 333/317/279 +f 330/314/280 334/312/280 340/310/280 336/306/280 +f 341/311/281 335/313/281 331/315/281 337/308/281 +f 326/318/282 332/316/282 338/300/282 328/299/282 +f 339/304/283 333/317/283 327/319/283 329/301/283 +f 81/85/284 83/81/284 332/316/284 326/318/284 +f 333/317/285 84/84/285 82/88/285 327/319/285 +f 209/206/286 342/320/286 344/321/286 215/208/286 +f 345/322/287 343/323/287 210/207/287 216/209/287 +f 81/85/288 326/318/288 342/320/288 209/206/288 +f 343/323/289 327/319/289 82/88/289 210/207/289 +f 79/89/290 215/208/290 344/321/290 346/324/290 +f 345/322/291 216/209/291 80/95/291 347/325/291 +f 79/89/292 346/324/292 300/295/292 92/90/292 +f 301/296/293 347/325/293 80/95/293 93/94/293 +f 77/326/294 324/327/294 352/328/294 304/329/294 +f 353/330/295 325/331/295 77/332/295 304/333/295 +f 304/329/296 352/328/296 350/334/296 78/335/296 +f 351/336/297 353/330/297 304/333/297 78/337/297 +f 78/335/298 350/334/298 348/338/298 305/339/298 +f 349/340/299 351/336/299 78/337/299 305/341/299 +f 305/339/300 348/338/300 328/299/300 309/298/300 +f 329/301/301 349/340/301 305/341/301 309/302/301 +f 326/318/302 328/299/302 348/338/302 342/320/302 +f 349/340/303 329/301/303 327/319/303 343/323/303 +f 296/291/304 298/293/304 318/342/304 310/343/304 +f 319/344/305 299/294/305 297/292/305 311/345/305 +f 76/346/306 316/347/306 324/327/306 77/326/306 +f 325/331/307 317/348/307 76/349/307 77/332/307 +f 302/350/308 358/351/308 356/352/308 303/353/308 +f 357/354/309 359/355/309 302/356/309 303/357/309 +f 303/353/310 356/352/310 354/358/310 75/359/310 +f 355/360/311 357/354/311 303/357/311 75/361/311 +f 75/359/312 354/358/312 316/347/312 76/346/312 +f 317/348/313 355/360/313 75/361/313 76/349/313 +f 292/362/314 294/289/314 362/363/314 364/364/314 +f 363/365/315 295/290/315 293/366/315 365/367/315 +f 364/364/316 362/363/316 368/368/316 366/369/316 +f 369/370/317 363/365/317 365/367/317 367/371/317 +f 366/369/318 368/368/318 370/372/318 372/373/318 +f 371/374/319 369/370/319 367/371/319 373/375/319 +f 372/373/320 370/372/320 376/376/320 374/377/320 +f 377/378/321 371/374/321 373/375/321 375/379/321 +f 314/380/322 378/381/322 374/377/322 376/376/322 +f 375/379/323 379/382/323 315/383/323 377/378/323 +f 316/347/324 354/358/324 374/377/324 378/381/324 +f 375/379/325 355/360/325 317/348/325 379/382/325 +f 354/358/326 356/352/326 372/373/326 374/377/326 +f 373/375/327 357/354/327 355/360/327 375/379/327 +f 356/352/328 358/351/328 366/369/328 372/373/328 +f 367/371/329 359/355/329 357/354/329 373/375/329 +f 358/351/330 360/384/330 364/364/330 366/369/330 +f 365/367/331 361/385/331 359/355/331 367/371/331 +f 290/386/332 292/362/332 364/364/332 360/384/332 +f 365/367/333 293/366/333 291/387/333 361/385/333 +f 74/388/334 360/384/334 358/351/334 302/350/334 +f 359/355/335 361/385/335 74/389/335 302/356/335 +f 284/390/336 286/391/336 288/392/336 290/386/336 +f 289/393/337 287/394/337 285/395/337 291/387/337 +f 284/390/338 290/386/338 360/384/338 74/388/338 +f 361/385/339 291/387/339 285/395/339 74/389/339 +f 73/396/340 284/390/340 74/388/340 +f 74/389/341 285/395/341 73/397/341 +f 294/289/342 296/291/342 310/343/342 362/363/342 +f 311/345/343 297/292/343 295/290/343 363/365/343 +f 310/343/344 312/398/344 368/368/344 362/363/344 +f 369/370/345 313/399/345 311/345/345 363/365/345 +f 312/398/346 382/400/346 370/372/346 368/368/346 +f 371/374/347 383/401/347 313/399/347 369/370/347 +f 314/380/348 376/376/348 370/372/348 382/400/348 +f 371/374/349 377/378/349 315/383/349 383/401/349 +f 348/338/350 350/334/350 386/402/350 384/403/350 +f 387/404/351 351/336/351 349/340/351 385/405/351 +f 318/342/352 384/403/352 386/402/352 320/406/352 +f 387/404/353 385/405/353 319/344/353 321/407/353 +f 298/293/354 300/295/354 384/403/354 318/342/354 +f 385/405/355 301/296/355 299/294/355 319/344/355 +f 300/295/356 344/321/356 342/320/356 384/403/356 +f 343/323/357 345/322/357 301/296/357 385/405/357 +f 342/320/358 348/338/358 384/403/358 +f 385/405/359 349/340/359 343/323/359 +f 300/295/360 346/324/360 344/321/360 +f 345/322/361 347/325/361 301/296/361 +f 314/380/362 322/408/362 380/409/362 378/381/362 +f 381/410/363 323/411/363 315/383/363 379/382/363 +f 316/347/364 378/381/364 380/409/364 324/327/364 +f 381/410/365 379/382/365 317/348/365 325/331/365 +f 320/406/366 386/402/366 380/409/366 322/408/366 +f 381/410/367 387/404/367 321/407/367 323/411/367 +f 350/334/368 352/328/368 380/409/368 386/402/368 +f 381/410/369 353/330/369 351/336/369 387/404/369 +f 324/327/370 380/409/370 352/328/370 +f 353/330/371 381/410/371 325/331/371 +f 400/412/372 388/413/372 414/414/372 402/415/372 +f 415/416/373 389/417/373 401/418/373 403/419/373 +f 400/412/374 402/415/374 404/420/374 398/421/374 +f 405/422/375 403/419/375 401/418/375 399/423/375 +f 398/421/376 404/420/376 406/424/376 396/425/376 +f 407/426/377 405/422/377 399/423/377 397/427/377 +f 396/425/378 406/424/378 408/428/378 394/429/378 +f 409/430/379 407/426/379 397/427/379 395/431/379 +f 394/429/380 408/428/380 410/432/380 392/433/380 +f 411/434/381 409/430/381 395/431/381 393/435/381 +f 392/433/382 410/432/382 412/436/382 390/437/382 +f 413/438/383 411/434/383 393/435/383 391/439/383 +f 410/432/384 420/440/384 418/441/384 412/436/384 +f 419/442/385 421/443/385 411/434/385 413/438/385 +f 408/428/386 422/444/386 420/440/386 410/432/386 +f 421/443/387 423/445/387 409/430/387 411/434/387 +f 406/424/388 424/446/388 422/444/388 408/428/388 +f 423/445/389 425/447/389 407/426/389 409/430/389 +f 404/420/390 426/448/390 424/446/390 406/424/390 +f 425/447/391 427/449/391 405/422/391 407/426/391 +f 402/415/392 428/450/392 426/448/392 404/420/392 +f 427/449/393 429/451/393 403/419/393 405/422/393 +f 402/415/394 414/414/394 416/452/394 428/450/394 +f 417/453/395 415/416/395 403/419/395 429/451/395 +f 318/342/396 320/406/396 444/454/396 442/455/396 +f 445/456/397 321/407/397 319/344/397 443/457/397 +f 320/458/398 390/437/398 412/436/398 444/459/398 +f 413/438/399 391/439/399 321/460/399 445/461/399 +f 310/343/400 318/342/400 442/455/400 312/398/400 +f 443/457/401 319/344/401 311/345/401 313/399/401 +f 382/462/402 430/463/402 414/414/402 388/413/402 +f 415/416/403 431/464/403 383/465/403 389/417/403 +f 412/436/404 418/441/404 440/466/404 444/459/404 +f 441/467/405 419/442/405 413/438/405 445/461/405 +f 438/468/406 446/469/406 444/459/406 440/466/406 +f 445/461/407 447/470/407 439/471/407 441/467/407 +f 434/472/408 446/469/408 438/468/408 436/473/408 +f 439/471/409 447/470/409 435/474/409 437/475/409 +f 432/476/410 448/477/410 446/469/410 434/472/410 +f 447/470/411 449/478/411 433/479/411 435/474/411 +f 430/463/412 448/477/412 432/476/412 450/480/412 +f 433/479/413 449/478/413 431/464/413 451/481/413 +f 414/414/414 430/463/414 450/480/414 416/452/414 +f 451/481/415 431/464/415 415/416/415 417/453/415 +f 312/398/416 448/482/416 430/483/416 382/400/416 +f 431/484/417 449/485/417 313/399/417 383/401/417 +f 312/398/418 442/455/418 446/486/418 448/482/418 +f 447/487/419 443/457/419 313/399/419 449/485/419 +f 442/455/420 444/454/420 446/486/420 +f 447/487/421 445/456/421 443/457/421 +f 416/452/422 450/480/422 452/488/422 476/489/422 +f 453/490/423 451/481/423 417/453/423 477/491/423 +f 450/480/424 432/476/424 462/492/424 452/488/424 +f 463/493/425 433/479/425 451/481/425 453/490/425 +f 432/476/426 434/472/426 460/494/426 462/492/426 +f 461/495/427 435/474/427 433/479/427 463/493/427 +f 434/472/428 436/473/428 458/496/428 460/494/428 +f 459/497/429 437/475/429 435/474/429 461/495/429 +f 436/473/430 438/468/430 456/498/430 458/496/430 +f 457/499/431 439/471/431 437/475/431 459/497/431 +f 438/468/432 440/466/432 454/500/432 456/498/432 +f 455/501/433 441/467/433 439/471/433 457/499/433 +f 440/466/434 418/441/434 474/502/434 454/500/434 +f 475/503/435 419/442/435 441/467/435 455/501/435 +f 428/450/436 416/452/436 476/489/436 464/504/436 +f 477/491/437 417/453/437 429/451/437 465/505/437 +f 426/448/438 428/450/438 464/504/438 466/506/438 +f 465/505/439 429/451/439 427/449/439 467/507/439 +f 424/446/440 426/448/440 466/506/440 468/508/440 +f 467/507/441 427/449/441 425/447/441 469/509/441 +f 422/444/442 424/446/442 468/508/442 470/510/442 +f 469/509/443 425/447/443 423/445/443 471/511/443 +f 420/440/444 422/444/444 470/510/444 472/512/444 +f 471/511/445 423/445/445 421/443/445 473/513/445 +f 418/441/446 420/440/446 472/512/446 474/502/446 +f 473/513/447 421/443/447 419/442/447 475/503/447 +f 458/496/448 456/498/448 480/514/448 478/515/448 +f 481/516/449 457/499/449 459/497/449 479/517/449 +f 478/515/450 480/514/450 482/518/450 484/519/450 +f 483/520/451 481/516/451 479/517/451 485/521/451 +f 484/519/452 482/518/452 488/522/452 486/523/452 +f 489/524/453 483/520/453 485/521/453 487/525/453 +f 486/523/454 488/522/454 490/526/454 492/527/454 +f 491/528/455 489/524/455 487/525/455 493/529/455 +f 464/504/456 476/489/456 486/523/456 492/527/456 +f 487/525/457 477/491/457 465/505/457 493/529/457 +f 452/488/458 484/519/458 486/523/458 476/489/458 +f 487/525/459 485/521/459 453/490/459 477/491/459 +f 452/488/460 462/492/460 478/515/460 484/519/460 +f 479/517/461 463/493/461 453/490/461 485/521/461 +f 458/496/462 478/515/462 462/492/462 460/494/462 +f 463/493/463 479/517/463 459/497/463 461/495/463 +f 454/500/464 474/502/464 480/514/464 456/498/464 +f 481/516/465 475/503/465 455/501/465 457/499/465 +f 472/512/466 482/518/466 480/514/466 474/502/466 +f 481/516/467 483/520/467 473/513/467 475/503/467 +f 470/510/468 488/522/468 482/518/468 472/512/468 +f 483/520/469 489/524/469 471/511/469 473/513/469 +f 468/508/470 490/526/470 488/522/470 470/510/470 +f 489/524/471 491/528/471 469/509/471 471/511/471 +f 466/506/472 492/527/472 490/526/472 468/508/472 +f 491/528/473 493/529/473 467/507/473 469/509/473 +f 464/504/474 492/527/474 466/506/474 +f 467/507/475 493/529/475 465/505/475 +f 392/433/476 390/437/476 504/530/476 502/531/476 +f 505/532/477 391/439/477 393/435/477 503/533/477 +f 394/429/478 392/433/478 502/531/478 500/534/478 +f 503/533/479 393/435/479 395/431/479 501/535/479 +f 396/425/480 394/429/480 500/534/480 498/536/480 +f 501/535/481 395/431/481 397/427/481 499/537/481 +f 398/538/482 396/425/482 498/536/482 496/539/482 +f 499/537/483 397/427/483 399/540/483 497/541/483 +f 400/542/484 398/538/484 496/539/484 494/543/484 +f 497/541/485 399/540/485 401/544/485 495/545/485 +f 388/546/486 400/542/486 494/543/486 506/547/486 +f 495/545/487 401/544/487 389/548/487 507/549/487 +f 494/543/488 502/531/488 504/530/488 506/547/488 +f 505/532/489 503/533/489 495/545/489 507/549/489 +f 494/543/490 496/539/490 500/534/490 502/531/490 +f 501/535/491 497/541/491 495/545/491 503/533/491 +f 496/539/492 498/536/492 500/534/492 +f 501/535/493 499/537/493 497/541/493 +f 314/550/494 382/551/494 388/546/494 506/547/494 +f 389/548/495 383/552/495 315/553/495 507/549/495 +f 314/550/496 506/547/496 504/530/496 322/554/496 +f 505/532/497 507/549/497 315/553/497 323/555/497 +f 320/458/498 322/554/498 504/530/498 390/437/498 +f 505/532/499 323/555/499 321/460/499 391/439/499