diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:20 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:20 +0100 |
commit | 58319f04f239ab4a81b4eb878ad987fe453fef9e (patch) | |
tree | b3245686b548b3d5f51bd61be609c1bee239d155 /stockton-levels | |
parent | ac3870a05701933d85c4a8b440d3c7dbc4959d33 (diff) |
feat(levels): coord system types and swizzling
the room is now the right way up! yay!
Diffstat (limited to 'stockton-levels')
24 files changed, 143 insertions, 31 deletions
diff --git a/stockton-levels/src/coords.rs b/stockton-levels/src/coords.rs new file mode 100644 index 0000000..613c932 --- /dev/null +++ b/stockton-levels/src/coords.rs @@ -0,0 +1,44 @@ +// Copyright (C) Oscar Shrimpton 2019 + +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. + +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. +//! Marker traits for different co-ordinate systems, and functions to swizzle between them + +use na::Vector3; +use na::base::Scalar; +use std::ops::Neg; + +pub trait CoordSystem {} + +/// X points East, Y points South, Z points downwards +pub struct Q3System; +impl CoordSystem for Q3System {} + +/// X points east, Y points downwards, Z points inwards +pub struct VulkanSystem; +impl CoordSystem for VulkanSystem {} + + +pub struct Swizzler; + +pub trait SwizzleFromTo<F: CoordSystem, T: CoordSystem> { + fn swizzle<U: Scalar + Copy + Neg<Output = U>>(vec: &mut Vector3<U>) -> (); +} + +impl SwizzleFromTo<Q3System, VulkanSystem> for Swizzler { + fn swizzle<U: Scalar + Copy + Neg<Output = U>>(vec: &mut Vector3<U>) -> () { + let temp = vec.y; + vec.y = vec.z; + vec.z = -temp; + } +}
\ No newline at end of file diff --git a/stockton-levels/src/features.rs b/stockton-levels/src/features.rs index 3f53308..6cecbff 100644 --- a/stockton-levels/src/features.rs +++ b/stockton-levels/src/features.rs @@ -15,7 +15,8 @@ //! Marker traits for different feature sets use crate::traits::*; +use crate::coords::CoordSystem; -pub trait MinBSPFeatures: HasBSPTree {} -impl<T> MinBSPFeatures for T - where T: HasBSPTree {}
\ No newline at end of file +pub trait MinBSPFeatures<S: CoordSystem>: HasBSPTree<S> {} +impl<T, S: CoordSystem> MinBSPFeatures<S> for T + where T: HasBSPTree<S> {}
\ No newline at end of file diff --git a/stockton-levels/src/lib.rs b/stockton-levels/src/lib.rs index aef802e..3026b9d 100644 --- a/stockton-levels/src/lib.rs +++ b/stockton-levels/src/lib.rs @@ -25,4 +25,5 @@ pub mod q3; pub mod types; pub mod traits; pub mod prelude; -pub mod features;
\ No newline at end of file +pub mod features; +pub mod coords;
\ No newline at end of file diff --git a/stockton-levels/src/prelude.rs b/stockton-levels/src/prelude.rs index 8834f03..32485b3 100644 --- a/stockton-levels/src/prelude.rs +++ b/stockton-levels/src/prelude.rs @@ -15,4 +15,5 @@ //! Common traits, etc. pub use crate::traits::*; -pub use crate::features::*;
\ No newline at end of file +pub use crate::features::*; +pub use crate::coords::*;
\ No newline at end of file diff --git a/stockton-levels/src/q3/brushes.rs b/stockton-levels/src/q3/brushes.rs index f8a979d..f82e57a 100644 --- a/stockton-levels/src/q3/brushes.rs +++ b/stockton-levels/src/q3/brushes.rs @@ -26,6 +26,7 @@ const SIDE_SIZE: usize = 4 * 2; use crate::helpers::slice_to_i32; use crate::types::{ParseError, Result}; use crate::traits::brushes::*; +use crate::coords::CoordSystem; use super::Q3BSPFile; /// Parse the brushes & brushsides lump from a bsp file. @@ -104,7 +105,7 @@ fn get_sides( } -impl HasBrushes for Q3BSPFile { +impl<T: CoordSystem> HasBrushes<T> for Q3BSPFile<T> { type BrushesIter<'a> = std::slice::Iter<'a, Brush>; fn brushes_iter<'a>(&'a self) -> Self::BrushesIter<'a> { diff --git a/stockton-levels/src/q3/effects.rs b/stockton-levels/src/q3/effects.rs index 0fddfb7..77ad1ed 100644 --- a/stockton-levels/src/q3/effects.rs +++ b/stockton-levels/src/q3/effects.rs @@ -21,6 +21,7 @@ use crate::helpers::slice_to_u32; use crate::types::{Result, ParseError}; use crate::traits::effects::*; use super::Q3BSPFile; +use crate::coords::CoordSystem; /// The size of one effect definition const EFFECT_SIZE: usize = 64 + 4 + 4; @@ -50,7 +51,7 @@ pub fn from_data(data: &[u8], n_brushes: u32) -> Result<Box<[Effect]>> { } -impl HasEffects for Q3BSPFile { +impl<T: CoordSystem> HasEffects<T> for Q3BSPFile<T> { type EffectsIter<'a> = std::slice::Iter<'a, Effect>; fn effects_iter<'a>(&'a self) -> Self::EffectsIter<'a> { diff --git a/stockton-levels/src/q3/entities.rs b/stockton-levels/src/q3/entities.rs index 9284fe4..4382ef2 100644 --- a/stockton-levels/src/q3/entities.rs +++ b/stockton-levels/src/q3/entities.rs @@ -21,6 +21,7 @@ use std::collections::HashMap; use crate::types::{Result, ParseError}; use crate::traits::entities::*; use super::Q3BSPFile; +use crate::coords::CoordSystem; const QUOTE: u8 = b'"'; const END_BRACKET: u8 = b'}'; @@ -99,7 +100,7 @@ pub fn from_data(data: &[u8]) -> Result<Box<[Entity]>> { Ok(entities.into_boxed_slice()) } -impl HasEntities for Q3BSPFile { +impl<T: CoordSystem> HasEntities for Q3BSPFile<T> { type EntitiesIter<'a> = std::slice::Iter<'a, Entity>; fn entities_iter<'a>(&'a self) -> Self::EntitiesIter<'a> { diff --git a/stockton-levels/src/q3/faces.rs b/stockton-levels/src/q3/faces.rs index 933f0d6..a53af6e 100644 --- a/stockton-levels/src/q3/faces.rs +++ b/stockton-levels/src/q3/faces.rs @@ -20,6 +20,7 @@ use crate::types::{Result, ParseError}; use na::Vector3; use crate::traits::faces::*; use super::Q3BSPFile; +use crate::coords::CoordSystem; const FACE_SIZE: usize = (4 * 8) + (4 * 2) + (4 * 2) + (4 * 3) + ((4 * 2) * 3) + (4 * 3) + (4 * 2); @@ -150,9 +151,9 @@ fn face_from_slice( } -impl HasFaces for Q3BSPFile { +impl<T: CoordSystem> HasFaces<T> for Q3BSPFile<T> { type FacesIter<'a> = std::slice::Iter<'a, Face>; - + fn faces_iter<'a>(&'a self) -> Self::FacesIter<'a> { self.faces.iter() } diff --git a/stockton-levels/src/q3/file.rs b/stockton-levels/src/q3/file.rs index 7c342d5..ecce783 100644 --- a/stockton-levels/src/q3/file.rs +++ b/stockton-levels/src/q3/file.rs @@ -18,9 +18,11 @@ // Trait implementations are stored in their own files. use bitvec::prelude::*; +use std::marker::PhantomData; use self::header::Header; use crate::types::Result; +use crate::coords::*; use super::*; use crate::traits::textures::Texture; @@ -36,7 +38,7 @@ use crate::traits::tree::BSPNode; use crate::traits::models::Model; /// A parsed Quake 3 BSP File. -pub struct Q3BSPFile { +pub struct Q3BSPFile<T: CoordSystem> { pub(crate) visdata: Box<[BitBox<Local, u8>]>, pub(crate) textures: Box<[Texture]>, pub(crate) entities: Box<[Entity]>, @@ -50,11 +52,12 @@ pub struct Q3BSPFile { pub(crate) faces: Box<[Face]>, pub(crate) models: Box<[Model]>, pub(crate) tree_root: BSPNode, + _phantom: PhantomData<T> } -impl Q3BSPFile { +impl Q3BSPFile<Q3System> { /// Parse `data` as a quake 3 bsp file. - pub fn new(data: &[u8]) -> Result<Q3BSPFile> { + pub fn parse_file(data: &[u8]) -> Result<Q3BSPFile<Q3System>> { let header = Header::from(data)?; let entities = entities::from_data(header.get_lump(&data, 0))?; @@ -94,7 +97,50 @@ impl Q3BSPFile { Ok(Q3BSPFile { visdata, textures, entities, planes, vertices, meshverts, light_maps, - light_vols, brushes, effects, faces, tree_root, models + light_vols, brushes, effects, faces, tree_root, models, + _phantom: PhantomData }) } } + +impl<T: CoordSystem> Q3BSPFile<T> { + pub fn swizzle_to<D: CoordSystem>(mut self) -> Q3BSPFile<D> + where Swizzler: SwizzleFromTo<T, D> { + + for vertex in self.vertices.iter_mut() { + Swizzler::swizzle(&mut vertex.normal); + Swizzler::swizzle(&mut vertex.position); + } + + for model in self.models.iter_mut() { + Swizzler::swizzle(&mut model.mins); + Swizzler::swizzle(&mut model.maxs); + } + + for face in self.faces.iter_mut() { + Swizzler::swizzle(&mut face.normal); + } + + for plane in self.planes.iter_mut() { + Swizzler::swizzle(&mut plane.normal); + } + + // TODO: Possibly don't need to move? + Q3BSPFile { + visdata: self.visdata, + textures: self.textures, + entities: self.entities, + planes: self.planes, + vertices: self.vertices, + meshverts: self.meshverts, + light_maps: self.light_maps, + light_vols: self.light_vols, + brushes: self.brushes, + effects: self.effects, + faces: self.faces, + tree_root: self.tree_root, + models: self.models, + _phantom: PhantomData + } + } +}
\ No newline at end of file diff --git a/stockton-levels/src/q3/light_maps.rs b/stockton-levels/src/q3/light_maps.rs index a03f164..8fc1c83 100644 --- a/stockton-levels/src/q3/light_maps.rs +++ b/stockton-levels/src/q3/light_maps.rs @@ -18,6 +18,7 @@ use crate::types::{Result, RGB, ParseError}; use crate::traits::light_maps::*; use super::Q3BSPFile; +use crate::coords::CoordSystem; /// The size of one LightMap const LIGHTMAP_SIZE: usize = 128 * 128 * 3; @@ -46,7 +47,7 @@ pub fn from_data(data: &[u8]) -> Result<Box<[LightMap]>> { Ok(maps.into_boxed_slice()) } -impl HasLightMaps for Q3BSPFile { +impl<T: CoordSystem> HasLightMaps for Q3BSPFile<T> { type LightMapsIter<'a> = std::slice::Iter<'a, LightMap>; fn lightmaps_iter<'a>(&'a self) -> Self::LightMapsIter<'a> { diff --git a/stockton-levels/src/q3/light_vols.rs b/stockton-levels/src/q3/light_vols.rs index 202c375..d5bbadf 100644 --- a/stockton-levels/src/q3/light_vols.rs +++ b/stockton-levels/src/q3/light_vols.rs @@ -20,6 +20,7 @@ use std::convert::TryInto; use crate::types::{Result, ParseError, RGB}; use crate::traits::light_vols::*; use super::Q3BSPFile; +use crate::coords::CoordSystem; const VOL_LENGTH: usize = (3 * 2) + 2; @@ -43,7 +44,7 @@ pub fn from_data(data: &[u8]) -> Result<Box<[LightVol]>> { } -impl HasLightVols for Q3BSPFile { +impl<T: CoordSystem> HasLightVols for Q3BSPFile<T> { type LightVolsIter<'a> = std::slice::Iter<'a, LightVol>; fn lightvols_iter<'a>(&'a self) -> Self::LightVolsIter<'a> { diff --git a/stockton-levels/src/q3/models.rs b/stockton-levels/src/q3/models.rs index cd901bc..75f42fa 100644 --- a/stockton-levels/src/q3/models.rs +++ b/stockton-levels/src/q3/models.rs @@ -17,6 +17,7 @@ use crate::helpers::{slice_to_u32, slice_to_vec3}; use crate::types::{Result, ParseError}; +use crate::coords::CoordSystem; use crate::traits::models::*; use super::Q3BSPFile; @@ -73,7 +74,7 @@ pub fn from_data( } -impl HasModels for Q3BSPFile { +impl<T: CoordSystem> HasModels<T> for Q3BSPFile<T> { type ModelsIter<'a> = std::slice::Iter<'a, Model>; fn models_iter<'a>(&'a self) -> Self::ModelsIter<'a> { diff --git a/stockton-levels/src/q3/planes.rs b/stockton-levels/src/q3/planes.rs index dd4f3aa..618a441 100644 --- a/stockton-levels/src/q3/planes.rs +++ b/stockton-levels/src/q3/planes.rs @@ -21,6 +21,7 @@ use crate::helpers::{slice_to_f32, slice_to_vec3}; use crate::types::{Result, ParseError}; use crate::traits::planes::*; use super::Q3BSPFile; +use crate::coords::CoordSystem; /// Parse a lump of planes. /// A lump is (data length / plane size) planes long @@ -45,7 +46,7 @@ pub fn from_data(data: &[u8]) -> Result<Box<[Plane]>> { Ok(planes.into_boxed_slice()) } -impl HasPlanes for Q3BSPFile { +impl<T: CoordSystem> HasPlanes<T> for Q3BSPFile<T> { type PlanesIter<'a> = std::slice::Iter<'a, Plane>; fn planes_iter<'a>(&'a self) -> Self::PlanesIter<'a> { diff --git a/stockton-levels/src/q3/textures.rs b/stockton-levels/src/q3/textures.rs index 78c3135..85093b5 100644 --- a/stockton-levels/src/q3/textures.rs +++ b/stockton-levels/src/q3/textures.rs @@ -21,6 +21,7 @@ use super::Q3BSPFile; use crate::traits::textures::*; use crate::helpers::slice_to_u32; use crate::types::{Result, ParseError}; +use crate::coords::CoordSystem; const TEXTURE_LUMP_SIZE: usize = 64 + 4 + 4; @@ -50,7 +51,7 @@ pub fn from_data(lump: &[u8]) -> Result<Box<[Texture]>> { Ok(textures.into_boxed_slice()) } -impl HasTextures for Q3BSPFile { +impl<T: CoordSystem> HasTextures for Q3BSPFile<T> { type TexturesIter<'a> = std::slice::Iter<'a, Texture>; fn textures_iter<'a>(&'a self) -> Self::TexturesIter<'a> { diff --git a/stockton-levels/src/q3/tree.rs b/stockton-levels/src/q3/tree.rs index e157d97..4d49e76 100644 --- a/stockton-levels/src/q3/tree.rs +++ b/stockton-levels/src/q3/tree.rs @@ -17,6 +17,7 @@ //! Parses the BSP tree into a usable format +use crate::coords::CoordSystem; use crate::helpers::{slice_to_u32, slice_to_i32, slice_to_vec3i}; use crate::types::{ParseError, Result}; use crate::traits::tree::*; @@ -161,7 +162,7 @@ fn compile_node( } } -impl HasBSPTree for Q3BSPFile { +impl<T: CoordSystem> HasBSPTree<T> for Q3BSPFile<T> { fn get_bsp_root<'a>(&'a self) -> &'a BSPNode { &self.tree_root } diff --git a/stockton-levels/src/q3/vertices.rs b/stockton-levels/src/q3/vertices.rs index 51a3590..d517ede 100644 --- a/stockton-levels/src/q3/vertices.rs +++ b/stockton-levels/src/q3/vertices.rs @@ -21,6 +21,7 @@ use super::Q3BSPFile; use crate::helpers::{slice_to_u32, slice_to_vec3}; use crate::types::{Result, ParseError, RGBA}; use crate::traits::vertices::*; +use crate::coords::CoordSystem; /// The size of one vertex const VERTEX_SIZE: usize = (4 * 3) + (2 * 2 * 4) + (4 * 3) + 4; @@ -64,7 +65,7 @@ pub fn meshverts_from_data(data: &[u8]) -> Result<Box<[MeshVert]>> { Ok(meshverts.into_boxed_slice()) } -impl HasVertices for Q3BSPFile { +impl<T: CoordSystem> HasVertices<T> for Q3BSPFile<T> { type VerticesIter<'a> = std::slice::Iter<'a, Vertex>; fn vertices_iter<'a>(&'a self) -> Self::VerticesIter<'a> { @@ -76,7 +77,7 @@ impl HasVertices for Q3BSPFile { } } -impl HasMeshVerts for Q3BSPFile { +impl<T: CoordSystem> HasMeshVerts<T> for Q3BSPFile<T> { type MeshVertsIter<'a> = std::slice::Iter<'a, MeshVert>; fn meshverts_iter<'a>(&'a self) -> Self::MeshVertsIter<'a> { diff --git a/stockton-levels/src/q3/visdata.rs b/stockton-levels/src/q3/visdata.rs index 39bfcf4..fd48415 100644 --- a/stockton-levels/src/q3/visdata.rs +++ b/stockton-levels/src/q3/visdata.rs @@ -22,6 +22,7 @@ use crate::types::{Result, ParseError}; use crate::traits::visdata::*; use crate::helpers::slice_to_i32; use super::file::Q3BSPFile; +use crate::coords::CoordSystem; /// Stores cluster-to-cluster visibility information. pub fn from_data(data: &[u8]) -> Result<Box<[BitBox<Local, u8>]>> { @@ -46,7 +47,7 @@ pub fn from_data(data: &[u8]) -> Result<Box<[BitBox<Local, u8>]>> { Ok(vecs.into_boxed_slice()) } -impl HasVisData for Q3BSPFile { +impl<T: CoordSystem> HasVisData for Q3BSPFile<T> { type VisibleIterator = IntoIter<ClusterId>; fn all_visible_from(&self, from: ClusterId) -> Self::VisibleIterator { diff --git a/stockton-levels/src/traits/brushes.rs b/stockton-levels/src/traits/brushes.rs index 6131824..30ab420 100644 --- a/stockton-levels/src/traits/brushes.rs +++ b/stockton-levels/src/traits/brushes.rs @@ -18,6 +18,7 @@ //! Parses the brushes & brushsides lumps from a bsp file use super::HasPlanes; +use crate::coords::CoordSystem; /// One brush record. Used for collision detection. /// "Each brush describes a convex volume as defined by its surrounding surfaces." @@ -35,7 +36,7 @@ pub struct BrushSide { pub is_opposing: bool, } -pub trait HasBrushes: HasPlanes { +pub trait HasBrushes<S: CoordSystem>: HasPlanes<S> { type BrushesIter<'a>: Iterator<Item = &'a Brush>; fn brushes_iter<'a>(&'a self) -> Self::BrushesIter<'a>; diff --git a/stockton-levels/src/traits/effects.rs b/stockton-levels/src/traits/effects.rs index d969dd1..dec2122 100644 --- a/stockton-levels/src/traits/effects.rs +++ b/stockton-levels/src/traits/effects.rs @@ -16,6 +16,7 @@ // along with stockton-bsp. If not, see <http://www.gnu.org/licenses/>. use super::HasBrushes; +use crate::coords::CoordSystem; /// One effect definition #[derive(Debug, Clone, PartialEq)] @@ -29,7 +30,7 @@ pub struct Effect { // todo: unknown: i32 } -pub trait HasEffects: HasBrushes { +pub trait HasEffects<S: CoordSystem>: HasBrushes<S> { type EffectsIter<'a>: Iterator<Item = &'a Effect>; fn effects_iter<'a>(&'a self) -> Self::EffectsIter<'a>; diff --git a/stockton-levels/src/traits/faces.rs b/stockton-levels/src/traits/faces.rs index cb97877..50d2b7d 100644 --- a/stockton-levels/src/traits/faces.rs +++ b/stockton-levels/src/traits/faces.rs @@ -19,6 +19,7 @@ use std::ops::Range; use na::{Vector2, Vector3}; use super::{HasEffects, HasTextures, HasLightMaps, HasMeshVerts}; +use crate::coords::CoordSystem; #[derive(Debug, Clone, Copy, PartialEq)] #[repr(i32)] @@ -47,7 +48,7 @@ pub struct Face { pub size: Vector2<u32>, } -pub trait HasFaces: HasTextures + HasEffects + HasLightMaps + HasMeshVerts { +pub trait HasFaces<S: CoordSystem>: HasTextures + HasEffects<S> + HasLightMaps + HasMeshVerts<S> { type FacesIter<'a>: Iterator<Item = &'a Face>; fn faces_iter<'a>(&'a self) -> Self::FacesIter<'a>; diff --git a/stockton-levels/src/traits/models.rs b/stockton-levels/src/traits/models.rs index 7d1b896..4f755f3 100644 --- a/stockton-levels/src/traits/models.rs +++ b/stockton-levels/src/traits/models.rs @@ -19,6 +19,7 @@ use na::Vector3; use std::ops::Range; use super::{HasFaces, HasBrushes}; +use crate::coords::CoordSystem; #[derive(Debug, Clone)] pub struct Model { @@ -28,7 +29,7 @@ pub struct Model { pub brushes_idx: Range<u32>, } -pub trait HasModels: HasFaces + HasBrushes { +pub trait HasModels<S: CoordSystem>: HasFaces<S> + HasBrushes<S> { type ModelsIter<'a>: Iterator<Item = &'a Model>; fn models_iter<'a>(&'a self) -> Self::ModelsIter<'a>; diff --git a/stockton-levels/src/traits/planes.rs b/stockton-levels/src/traits/planes.rs index 6a4e95a..c024815 100644 --- a/stockton-levels/src/traits/planes.rs +++ b/stockton-levels/src/traits/planes.rs @@ -17,6 +17,7 @@ use std::iter::Iterator; use na::Vector3; +use crate::coords::CoordSystem; /// The planes lump from a BSP file. /// Found at lump index 2 in a q3 bsp. @@ -35,7 +36,7 @@ pub struct Plane { pub dist: f32, } -pub trait HasPlanes { +pub trait HasPlanes<S: CoordSystem> { type PlanesIter<'a>: Iterator<Item = &'a Plane>; fn planes_iter<'a>(&'a self) -> Self::PlanesIter<'a>; diff --git a/stockton-levels/src/traits/tree.rs b/stockton-levels/src/traits/tree.rs index bdbe705..c56576a 100644 --- a/stockton-levels/src/traits/tree.rs +++ b/stockton-levels/src/traits/tree.rs @@ -19,6 +19,7 @@ use na::Vector3; use super::{HasFaces, HasBrushes, HasVisData}; +use crate::coords::CoordSystem; /// A node in a BSP tree. /// Either has two children *or* a leaf entry. @@ -46,6 +47,6 @@ pub struct BSPLeaf { pub brushes_idx: Box<[u32]>, } -pub trait HasBSPTree: HasFaces + HasBrushes + HasVisData { +pub trait HasBSPTree<S: CoordSystem>: HasFaces<S> + HasBrushes<S> + HasVisData { fn get_bsp_root<'a>(&'a self) -> &'a BSPNode; }
\ No newline at end of file diff --git a/stockton-levels/src/traits/vertices.rs b/stockton-levels/src/traits/vertices.rs index 2afa802..cea1806 100644 --- a/stockton-levels/src/traits/vertices.rs +++ b/stockton-levels/src/traits/vertices.rs @@ -16,6 +16,7 @@ // along with stockton-bsp. If not, see <http://www.gnu.org/licenses/>. use crate::helpers::{slice_to_f32}; +use crate::coords::CoordSystem; use crate::types::RGBA; use na::Vector3; @@ -50,14 +51,14 @@ impl TexCoord { /// A vertex offset, used to describe generalised triangle meshes pub type MeshVert = u32; -pub trait HasVertices { +pub trait HasVertices<S: CoordSystem> { type VerticesIter<'a>: Iterator<Item = &'a Vertex>; fn vertices_iter<'a>(&'a self) -> Self::VerticesIter<'a>; fn get_vertex<'a>(&'a self, index: u32) -> &'a Vertex; } -pub trait HasMeshVerts: HasVertices { +pub trait HasMeshVerts<S: CoordSystem>: HasVertices<S> { type MeshVertsIter<'a>: Iterator<Item = &'a MeshVert>; fn meshverts_iter<'a>(&'a self) -> Self::MeshVertsIter<'a>; |