mirror of
https://codeberg.org/icewind/vbsp.git
synced 2026-06-03 18:54:05 +02:00
some more data implemented
This commit is contained in:
parent
cc93a2889e
commit
771ae67730
3 changed files with 175 additions and 175 deletions
|
|
@ -18,6 +18,7 @@ thiserror = "1.0"
|
||||||
lzma-rs = "0.1.3"
|
lzma-rs = "0.1.3"
|
||||||
binread = "1.0"
|
binread = "1.0"
|
||||||
parse-display = "0.1.2"
|
parse-display = "0.1.2"
|
||||||
|
static_assertions = "1.1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
bench = []
|
bench = []
|
||||||
|
|
|
||||||
|
|
@ -120,15 +120,15 @@ pub enum LumpType {
|
||||||
Unused1,
|
Unused1,
|
||||||
Unused2,
|
Unused2,
|
||||||
Unused3,
|
Unused3,
|
||||||
DisplayInfo,
|
DisplacementInfo,
|
||||||
OriginalFaces,
|
OriginalFaces,
|
||||||
PhysDisplay,
|
PhysDisplacement,
|
||||||
PhysCollide,
|
PhysCollide,
|
||||||
VertNormals,
|
VertNormals,
|
||||||
VertNormalIndices,
|
VertNormalIndices,
|
||||||
DisplayLightMapAlphas,
|
DisplacementLightMapAlphas,
|
||||||
DisplayVertices,
|
DisplacementVertices,
|
||||||
DisplayLightMapSamplePositions,
|
DisplacementLightMapSamplePositions,
|
||||||
GameLump,
|
GameLump,
|
||||||
LeafWaterData,
|
LeafWaterData,
|
||||||
Primitives,
|
Primitives,
|
||||||
|
|
@ -142,7 +142,7 @@ pub enum LumpType {
|
||||||
Overlays,
|
Overlays,
|
||||||
LeafMinimumDistanceToWater,
|
LeafMinimumDistanceToWater,
|
||||||
FaceMacroTextureInfo,
|
FaceMacroTextureInfo,
|
||||||
DisplayTris,
|
DisplacementTris,
|
||||||
PhysicsCollideSurface,
|
PhysicsCollideSurface,
|
||||||
WaterOverlays,
|
WaterOverlays,
|
||||||
LeafAmbientIndexHdr,
|
LeafAmbientIndexHdr,
|
||||||
|
|
@ -157,5 +157,5 @@ pub enum LumpType {
|
||||||
OverlayFades,
|
OverlayFades,
|
||||||
OverlaySystemLevels,
|
OverlaySystemLevels,
|
||||||
PhysLevel,
|
PhysLevel,
|
||||||
DisplayMultiBlend,
|
DisplacementMultiBlend,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
327
src/lib.rs
327
src/lib.rs
|
|
@ -16,10 +16,11 @@ use parse_display::Display;
|
||||||
use reader::LumpReader;
|
use reader::LumpReader;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
fmt,
|
fmt,
|
||||||
io::{self, Error, ErrorKind, Read},
|
io::{self, Error, ErrorKind, Read},
|
||||||
|
iter::once,
|
||||||
|
mem::size_of,
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
@ -240,74 +241,24 @@ impl<'a> Entity<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct SurfaceFlags: u32 {
|
#[derive(BinRead)]
|
||||||
const NODAMAGE = 0b0000_0000_0000_0000_0001; // Never give falling damage
|
pub struct TextureFlags: u32 {
|
||||||
const SLICK = 0b0000_0000_0000_0000_0010; // Affects game physics
|
const LIGHT = 0b0000_0000_0000_0000_0001; // value will hold the light strength
|
||||||
const SKY = 0b0000_0000_0000_0000_0100; // Lighting from environment map
|
const SKY2D = 0b0000_0000_0000_0000_0010; // don't draw, indicate we should skylight + draw 2d sky but don't draw the 3d skybox
|
||||||
const LADDER = 0b0000_0000_0000_0000_1000; // Climbable ladder
|
const SKY = 0b0000_0000_0000_0000_0100; // don't draw, but add the skybox
|
||||||
const NOIMPACT = 0b0000_0000_0000_0001_0000; // Don't make missile explosions
|
const WARP = 0b0000_0000_0000_0000_1000; // turbulent water warp
|
||||||
const NOMARKS = 0b0000_0000_0000_0010_0000; // Don't leave missile marks
|
const TRANS = 0b0000_0000_0000_0001_0000; // texture is translucent
|
||||||
const FLESH = 0b0000_0000_0000_0100_0000; // Make flesh sounds and effects
|
const NOPORTAL = 0b0000_0000_0000_0010_0000; // the surface can't have a portal placed on it
|
||||||
const NODRAW = 0b0000_0000_0000_1000_0000; // Don't generate a drawsurface at all
|
const TRIGGER = 0b0000_0000_0000_0100_0000; // xbox hack to work around elimination of trigger surfaces
|
||||||
const HINT = 0b0000_0000_0001_0000_0000; // Make a primary bsp splitter
|
const NODRAW = 0b0000_0000_0000_1000_0000; // don't bother referencing the texture
|
||||||
const SKIP = 0b0000_0000_0010_0000_0000; // Completely ignore, allowing non-closed brushes
|
const HINT = 0b0000_0000_0001_0000_0000; // make a primary bsp splitter
|
||||||
const NOLIGHTMAP = 0b0000_0000_0100_0000_0000; // Surface doesn't need a lightmap
|
const SKIP = 0b0000_0000_0010_0000_0000; // completely ignore, allowing non-closed brushes
|
||||||
const POINTLIGHT = 0b0000_0000_1000_0000_0000; // Generate lighting info at vertices
|
const NOLIGHT = 0b0000_0000_0100_0000_0000; // dont calculate light
|
||||||
const METALSTEPS = 0b0000_0001_0000_0000_0000; // Clanking footsteps
|
const BUMPLIGHT = 0b0000_0000_1000_0000_0000; // calculate thee light maps for the surface for bump mapping
|
||||||
const NOSTEPS = 0b0000_0010_0000_0000_0000; // No footstep sounds
|
const NOSHADOWS = 0b0000_0001_0000_0000_0000; // don't receive shadows
|
||||||
const NONSOLID = 0b0000_0100_0000_0000_0000; // Don't collide against curves with this set
|
const NODECALS = 0b0000_0010_0000_0000_0000; // don't receive decals
|
||||||
const LIGHTFILTER = 0b0000_1000_0000_0000_0000; // Act as a light filter during q3map -light
|
const NOCHOP = 0b0000_0100_0000_0000_0000; // don't subdivide patches on this surface
|
||||||
const ALPHASHADOW = 0b0001_0000_0000_0000_0000; // Do per-pixel light shadow casting in q3map
|
const HITBOX = 0b0000_1000_0000_0000_0000; // surface is part of a hitbox
|
||||||
const NODLIGHT = 0b0010_0000_0000_0000_0000; // Never add dynamic lights
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SurfaceFlags {
|
|
||||||
pub fn should_draw(&self) -> bool {
|
|
||||||
!self.intersects(Self::HINT | Self::SKIP | Self::NODRAW | Self::LIGHTFILTER)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct ContentFlags: u32 {
|
|
||||||
// An eye is never valid in a solid
|
|
||||||
const SOLID = 0b0000_0000_0000_0000_0000_0000_0000_0001;
|
|
||||||
const LAVA = 0b0000_0000_0000_0000_0000_0000_0000_1000;
|
|
||||||
const SLIME = 0b0000_0000_0000_0000_0000_0000_0001_0000;
|
|
||||||
const WATER = 0b0000_0000_0000_0000_0000_0000_0010_0000;
|
|
||||||
const FOG = 0b0000_0000_0000_0000_0000_0000_0100_0000;
|
|
||||||
const NOTTEAM1 = 0b0000_0000_0000_0000_0000_0000_1000_0000;
|
|
||||||
const NOTTEAM2 = 0b0000_0000_0000_0000_0000_0001_0000_0000;
|
|
||||||
const NOBOTCLIP = 0b0000_0000_0000_0000_0000_0010_0000_0000;
|
|
||||||
|
|
||||||
const AREAPORTAL = 0b0000_0000_0000_0000_1000_0000_0000_0000;
|
|
||||||
|
|
||||||
const PLAYERCLIP = 0b0000_0000_0000_0001_0000_0000_0000_0000;
|
|
||||||
const MONSTERCLIP = 0b0000_0000_0000_0010_0000_0000_0000_0000;
|
|
||||||
|
|
||||||
// Bot-specific contents types
|
|
||||||
const TELEPORTER = 0b0000_0000_0000_0100_0000_0000_0000_0000;
|
|
||||||
const JUMPPAD = 0b0000_0000_0000_1000_0000_0000_0000_0000;
|
|
||||||
const CLUSTERPORTAL = 0b0000_0000_0001_0000_0000_0000_0000_0000;
|
|
||||||
const DONOTENTER = 0b0000_0000_0010_0000_0000_0000_0000_0000;
|
|
||||||
const BOTCLIP = 0b0000_0000_0100_0000_0000_0000_0000_0000;
|
|
||||||
const MOVER = 0b0000_0000_1000_0000_0000_0000_0000_0000;
|
|
||||||
|
|
||||||
// Removed before bsping an entity
|
|
||||||
const ORIGIN = 0b0000_0001_0000_0000_0000_0000_0000_0000;
|
|
||||||
|
|
||||||
// Should never be on a brush, only in game
|
|
||||||
const BODY = 0b0000_0010_0000_0000_0000_0000_0000_0000;
|
|
||||||
const CORPSE = 0b0000_0100_0000_0000_0000_0000_0000_0000;
|
|
||||||
// Brushes not used for the bsp
|
|
||||||
const DETAIL = 0b0000_1000_0000_0000_0000_0000_0000_0000;
|
|
||||||
// Brushes used for the bsp
|
|
||||||
const STRUCTURAL = 0b0001_0000_0000_0000_0000_0000_0000_0000;
|
|
||||||
// Don't consume surface fragments inside
|
|
||||||
const TRANSLUCENT = 0b0010_0000_0000_0000_0000_0000_0000_0000;
|
|
||||||
const TRIGGER = 0b0100_0000_0000_0000_0000_0000_0000_0000;
|
|
||||||
// Don't leave bodies or items (death fog, lava)
|
|
||||||
const NODROP = 0b1000_0000_0000_0000_0000_0000_0000_0000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -350,44 +301,40 @@ impl BinRead for Name {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, BinRead)]
|
||||||
pub struct Texture {
|
pub struct Vector {
|
||||||
pub name: Name,
|
x: f32,
|
||||||
pub flags: SurfaceFlags,
|
y: f32,
|
||||||
pub contents: ContentFlags,
|
z: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinRead for Texture {
|
#[derive(Debug, Clone, BinRead)]
|
||||||
type Args = ();
|
pub struct TextureInfo {
|
||||||
|
pub texture_scale: [f32; 4],
|
||||||
|
pub texture_transform: [f32; 4],
|
||||||
|
pub light_map_scale: [f32; 4],
|
||||||
|
pub light_map_transform: [f32; 4],
|
||||||
|
pub flags: TextureFlags,
|
||||||
|
pub texture_data_index: i32,
|
||||||
|
}
|
||||||
|
|
||||||
fn read_options<R: binread::io::Read + binread::io::Seek>(
|
static_assertions::const_assert_eq!(size_of::<TextureInfo>(), 72);
|
||||||
reader: &mut R,
|
|
||||||
options: &ReadOptions,
|
|
||||||
args: Self::Args,
|
|
||||||
) -> BinResult<Self> {
|
|
||||||
let name = Name::read_options(reader, options, args)?;
|
|
||||||
let flags = SurfaceFlags::from_bits(u32::read_options(reader, options, args)?).ok_or_else(
|
|
||||||
|| binread::Error::NoVariantMatch {
|
|
||||||
pos: reader.seek(SeekFrom::Current(0)).unwrap() as usize,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
let contents = ContentFlags::from_bits(u32::read_options(reader, options, args)?)
|
|
||||||
.ok_or_else(|| binread::Error::NoVariantMatch {
|
|
||||||
pos: reader.seek(SeekFrom::Current(0)).unwrap() as usize,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(Texture {
|
#[derive(Debug, Clone, BinRead)]
|
||||||
name,
|
pub struct TextureData {
|
||||||
flags,
|
pub reflectivity: Vector,
|
||||||
contents,
|
pub name_string_table_id: i32,
|
||||||
})
|
pub width: i32,
|
||||||
}
|
pub height: i32,
|
||||||
|
pub view_width: i32,
|
||||||
|
pub view_height: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, BinRead)]
|
#[derive(Debug, Clone, BinRead)]
|
||||||
pub struct Plane {
|
pub struct Plane {
|
||||||
pub normal: [f32; 3],
|
pub normal: Vector,
|
||||||
pub dist: f32,
|
pub dist: f32,
|
||||||
|
pub ty: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, BinRead)]
|
#[derive(Debug, Clone, BinRead)]
|
||||||
|
|
@ -440,11 +387,37 @@ pub struct BrushSide {
|
||||||
|
|
||||||
#[derive(Debug, Clone, BinRead)]
|
#[derive(Debug, Clone, BinRead)]
|
||||||
pub struct Vertex {
|
pub struct Vertex {
|
||||||
pub position: [f32; 3],
|
pub position: Vector,
|
||||||
pub surface_texcoord: [f32; 2],
|
}
|
||||||
pub lightmap_texcoord: [f32; 2],
|
|
||||||
pub normal: [f32; 3],
|
#[derive(Debug, Clone, BinRead)]
|
||||||
pub color: [u8; 4],
|
pub struct Edge {
|
||||||
|
pub start_index: u16,
|
||||||
|
pub end_index: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum EdgeDirection {
|
||||||
|
FirstToLast,
|
||||||
|
LastToFirst,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, BinRead)]
|
||||||
|
pub struct SurfaceEdge {
|
||||||
|
edge: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SurfaceEdge {
|
||||||
|
pub fn edge_index(&self) -> usize {
|
||||||
|
self.edge.abs() as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn direction(&self) -> EdgeDirection {
|
||||||
|
if self.edge >= 0 {
|
||||||
|
EdgeDirection::FirstToLast
|
||||||
|
} else {
|
||||||
|
EdgeDirection::LastToFirst
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, BinRead)]
|
#[derive(Debug, Clone, BinRead)]
|
||||||
|
|
@ -461,22 +434,27 @@ pub struct Effect {
|
||||||
|
|
||||||
#[derive(Debug, Clone, BinRead)]
|
#[derive(Debug, Clone, BinRead)]
|
||||||
pub struct Face {
|
pub struct Face {
|
||||||
pub texture: u32,
|
pub plane_num: u16,
|
||||||
pub effect: u32,
|
pub side: u8,
|
||||||
pub face_type: FaceType,
|
pub on_node: u8,
|
||||||
pub vertex: u32,
|
pub first_edge: i32,
|
||||||
pub num_vertices: u32,
|
pub num_edges: i16,
|
||||||
pub mesh_vert: u32,
|
pub texture_info: i16,
|
||||||
pub num_mesh_verts: u32,
|
pub displacement_info: i16,
|
||||||
pub lm_index: u32,
|
pub surface_fog_volume_id: i16,
|
||||||
pub lm_start: [u32; 2],
|
pub styles: [u8; 4],
|
||||||
pub lm_size: [u32; 2],
|
pub light_offset: i32,
|
||||||
pub lm_origin: [f32; 3],
|
pub area: f32,
|
||||||
pub lm_vecs: [[f32; 3]; 2],
|
pub light_map_texture_min: [i32; 2],
|
||||||
pub normal: [f32; 3],
|
pub light_map_texture_size: [i32; 2],
|
||||||
pub size: [u32; 2],
|
pub original_face: i32,
|
||||||
|
pub primitive_count: u16,
|
||||||
|
pub first_primitive_index: u16,
|
||||||
|
pub smoothing_groups: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assertions::const_assert_eq!(size_of::<Face>(), 56);
|
||||||
|
|
||||||
const LIGHTMAP_SIZE: usize = 128;
|
const LIGHTMAP_SIZE: usize = 128;
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy, BinRead, Debug)]
|
#[derive(Default, Clone, Copy, BinRead, Debug)]
|
||||||
|
|
@ -647,7 +625,8 @@ impl<'a> IntoIterator for &'a mut Leaves {
|
||||||
pub struct Bsp {
|
pub struct Bsp {
|
||||||
pub header: Header,
|
pub header: Header,
|
||||||
pub entities: Entities,
|
pub entities: Entities,
|
||||||
pub textures: Vec<Texture>,
|
pub textures_data: Vec<TextureData>,
|
||||||
|
pub textures_info: Vec<TextureInfo>,
|
||||||
pub planes: Vec<Plane>,
|
pub planes: Vec<Plane>,
|
||||||
pub nodes: Vec<Node>,
|
pub nodes: Vec<Node>,
|
||||||
pub leaves: Leaves,
|
pub leaves: Leaves,
|
||||||
|
|
@ -657,6 +636,8 @@ pub struct Bsp {
|
||||||
pub brushes: Vec<Brush>,
|
pub brushes: Vec<Brush>,
|
||||||
pub brush_sides: Vec<BrushSide>,
|
pub brush_sides: Vec<BrushSide>,
|
||||||
pub vertices: Vec<Vertex>,
|
pub vertices: Vec<Vertex>,
|
||||||
|
pub edges: Vec<Edge>,
|
||||||
|
pub surface_edges: Vec<SurfaceEdge>,
|
||||||
pub faces: Vec<Face>,
|
pub faces: Vec<Face>,
|
||||||
pub vis_data: VisData,
|
pub vis_data: VisData,
|
||||||
}
|
}
|
||||||
|
|
@ -666,9 +647,12 @@ impl Bsp {
|
||||||
let bsp_file = BspFile::new(data)?;
|
let bsp_file = BspFile::new(data)?;
|
||||||
|
|
||||||
let entities = bsp_file.lump_reader(LumpType::Entities)?.read_entities()?;
|
let entities = bsp_file.lump_reader(LumpType::Entities)?.read_entities()?;
|
||||||
let textures = bsp_file
|
let textures_data = bsp_file
|
||||||
.lump_reader(LumpType::TextureData)?
|
.lump_reader(LumpType::TextureData)?
|
||||||
.read_vec(|r| r.read())?;
|
.read_vec(|r| r.read())?;
|
||||||
|
let textures_info = bsp_file
|
||||||
|
.lump_reader(LumpType::TextureInfo)?
|
||||||
|
.read_vec(|r| r.read())?;
|
||||||
let planes = bsp_file
|
let planes = bsp_file
|
||||||
.lump_reader(LumpType::Planes)?
|
.lump_reader(LumpType::Planes)?
|
||||||
.read_vec(|r| r.read())?;
|
.read_vec(|r| r.read())?;
|
||||||
|
|
@ -697,6 +681,12 @@ impl Bsp {
|
||||||
let vertices = bsp_file
|
let vertices = bsp_file
|
||||||
.lump_reader(LumpType::Vertices)?
|
.lump_reader(LumpType::Vertices)?
|
||||||
.read_vec(|r| r.read())?;
|
.read_vec(|r| r.read())?;
|
||||||
|
let edges = bsp_file
|
||||||
|
.lump_reader(LumpType::Edges)?
|
||||||
|
.read_vec(|r| r.read())?;
|
||||||
|
let surface_edges = bsp_file
|
||||||
|
.lump_reader(LumpType::SurfaceEdges)?
|
||||||
|
.read_vec(|r| r.read())?;
|
||||||
let faces = bsp_file
|
let faces = bsp_file
|
||||||
.lump_reader(LumpType::Faces)?
|
.lump_reader(LumpType::Faces)?
|
||||||
.read_vec(|r| r.read())?;
|
.read_vec(|r| r.read())?;
|
||||||
|
|
@ -706,7 +696,8 @@ impl Bsp {
|
||||||
Bsp {
|
Bsp {
|
||||||
header: bsp_file.header().clone(),
|
header: bsp_file.header().clone(),
|
||||||
entities,
|
entities,
|
||||||
textures,
|
textures_data,
|
||||||
|
textures_info,
|
||||||
planes,
|
planes,
|
||||||
nodes,
|
nodes,
|
||||||
leaves,
|
leaves,
|
||||||
|
|
@ -716,6 +707,8 @@ impl Bsp {
|
||||||
brushes,
|
brushes,
|
||||||
brush_sides,
|
brush_sides,
|
||||||
vertices,
|
vertices,
|
||||||
|
edges,
|
||||||
|
surface_edges,
|
||||||
faces,
|
faces,
|
||||||
vis_data,
|
vis_data,
|
||||||
}
|
}
|
||||||
|
|
@ -743,10 +736,6 @@ impl Bsp {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texture(&self, n: usize) -> Option<&Texture> {
|
|
||||||
self.textures.get(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn node(&self, n: usize) -> Option<Handle<'_, Node>> {
|
pub fn node(&self, n: usize) -> Option<Handle<'_, Node>> {
|
||||||
self.nodes.get(n).map(|node| Handle {
|
self.nodes.get(n).map(|node| Handle {
|
||||||
bsp: self,
|
bsp: self,
|
||||||
|
|
@ -764,25 +753,26 @@ impl Bsp {
|
||||||
|
|
||||||
pub fn leaf_at(&self, point: [f32; 3]) -> Option<Handle<'_, Leaf>> {
|
pub fn leaf_at(&self, point: [f32; 3]) -> Option<Handle<'_, Leaf>> {
|
||||||
let mut current = self.root_node()?;
|
let mut current = self.root_node()?;
|
||||||
|
None
|
||||||
|
|
||||||
loop {
|
// loop {
|
||||||
let plane = current.plane()?;
|
// let plane = current.plane()?;
|
||||||
let dot: f32 = point
|
// let dot: f32 = point
|
||||||
.iter()
|
// .iter()
|
||||||
.zip(plane.normal.iter())
|
// .zip(plane.normal.iter())
|
||||||
.map(|(a, b)| a * b)
|
// .map(|(a, b)| a * b)
|
||||||
.sum();
|
// .sum();
|
||||||
|
//
|
||||||
let [front, back] = current.children;
|
// let [front, back] = current.children;
|
||||||
|
//
|
||||||
let next = if dot < plane.dist { back } else { front };
|
// let next = if dot < plane.dist { back } else { front };
|
||||||
|
//
|
||||||
if next < 0 {
|
// if next < 0 {
|
||||||
return self.leaf((!next) as usize);
|
// return self.leaf((!next) as usize);
|
||||||
} else {
|
// } else {
|
||||||
current = self.node(next as usize)?;
|
// current = self.node(next as usize)?;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -804,31 +794,39 @@ impl<'a> Handle<'a, Model> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Handle<'a, TextureInfo> {
|
||||||
|
pub fn texture(&self) -> Option<&TextureData> {
|
||||||
|
self.bsp
|
||||||
|
.textures_data
|
||||||
|
.get(self.data.texture_data_index as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Handle<'a, Face> {
|
impl<'a> Handle<'a, Face> {
|
||||||
pub fn texture(&self) -> Option<&Texture> {
|
pub fn texture(&self) -> Option<Handle<TextureInfo>> {
|
||||||
self.bsp.texture(self.texture as _)
|
self.bsp
|
||||||
|
.textures_info
|
||||||
|
.get(self.texture_info as usize)
|
||||||
|
.map(|texture_info| Handle {
|
||||||
|
bsp: self.bsp,
|
||||||
|
data: texture_info,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vertices(&self) -> impl Iterator<Item = Cow<'a, Vertex>> {
|
pub fn vertices(&'a self) -> impl Iterator<Item = &'a Vertex> + 'a {
|
||||||
todo!();
|
(self.data.first_edge..(self.data.first_edge + self.data.num_edges as i32))
|
||||||
vec![].into_iter()
|
.flat_map(move |surface_edge| self.bsp.surface_edges.get(surface_edge as usize))
|
||||||
|
.flat_map(move |surface_edge| {
|
||||||
// match self.face_type {
|
self.bsp
|
||||||
// FaceType::Polygon | FaceType::Mesh => {
|
.edges
|
||||||
// let start = self.mesh_vert as usize;
|
.get(surface_edge.edge_index())
|
||||||
// let end = start + self.num_mesh_verts as usize;
|
.map(|edge| (edge, surface_edge.direction()))
|
||||||
// let bsp = self.bsp;
|
})
|
||||||
// let vertex = self.vertex;
|
.flat_map(|(edge, direction)| match direction {
|
||||||
//
|
EdgeDirection::FirstToLast => once(edge.start_index).chain(once(edge.end_index)),
|
||||||
// Either::Left(
|
EdgeDirection::LastToFirst => once(edge.end_index).chain(once(edge.start_index)),
|
||||||
// bsp.mesh_verts[start..end]
|
})
|
||||||
// .iter()
|
.flat_map(move |vert_index| self.bsp.vertices.get(vert_index as usize))
|
||||||
// .map(move |mv| Cow::Borrowed(&bsp.vertices[(mv.offset + vertex) as usize])),
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// // TODO
|
|
||||||
// _ => Either::Right(std::iter::empty()),
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -879,6 +877,7 @@ impl<'a> Handle<'a, Leaf> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Bsp;
|
use super::Bsp;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tf2_file() {
|
fn tf2_file() {
|
||||||
use std::fs::read;
|
use std::fs::read;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue