1
0
Fork 0
mirror of https://codeberg.org/icewind/vbsp.git synced 2026-06-03 18:54:05 +02:00

serde entity parsing

This commit is contained in:
Robin Appelman 2023-12-29 22:51:29 +01:00
commit f6e2a200ca
14 changed files with 682 additions and 1088 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
use crate::error::UnsupportedLumpVersion;
use crate::{lzma_decompress_with_header, BspError, FixedString, Vector};
use crate::{lzma_decompress_with_header, Angles, BspError, FixedString, Vector};
use binrw::{BinRead, BinReaderExt, BinResult, Endian};
use bitflags::bitflags;
use cgmath::{Deg, Quaternion, Rotation3};
use cgmath::Quaternion;
use std::borrow::Cow;
use std::io::{Cursor, Read, Seek};
use std::mem::size_of;
@ -121,7 +121,7 @@ pub struct StaticPropLumps {
#[derive(Debug, Clone)]
pub struct StaticPropLump {
pub origin: Vector,
angles: [f32; 3],
angles: Angles,
pub prop_type: u16,
pub first_leaf: u16,
pub leaf_count: u16,
@ -140,10 +140,7 @@ pub struct StaticPropLump {
impl StaticPropLump {
/// Get the rotation of the prop as quaternion
pub fn rotation(&self) -> Quaternion<f32> {
// angles are applied in roll, pitch, yaw order
Quaternion::from_angle_y(Deg(self.angles[1]))
* Quaternion::from_angle_x(Deg(self.angles[0]))
* Quaternion::from_angle_z(Deg(self.angles[2]))
self.angles.as_quaternion()
}
}
@ -209,7 +206,7 @@ impl From<StaticPropLumpFlagsV6> for StaticPropLumpFlags {
#[derive(BinRead)]
struct StaticPropLumpV6 {
pub origin: Vector,
pub angles: [f32; 3],
pub angles: Angles,
pub prop_type: u16,
pub first_leaf: u16,
pub leaf_count: u16,
@ -249,7 +246,7 @@ bitflags! {
#[derive(BinRead)]
struct StaticPropLumpV10 {
pub origin: Vector,
pub angles: [f32; 3],
pub angles: Angles,
pub prop_type: u16,
pub first_leaf: u16,
pub leaf_count: u16,

View file

@ -10,13 +10,17 @@ pub use self::game::*;
pub use self::prop::PropPlacement;
pub use self::vector::*;
use crate::bspfile::LumpType;
use crate::error::EntityParseError;
use crate::{BspResult, StringError};
use arrayvec::ArrayString;
use binrw::error::CustomError;
use binrw::{BinRead, BinResult, Endian};
use bitflags::bitflags;
use bv::BitVec;
use cgmath::{Deg, Quaternion, Rotation3};
use num_enum::{TryFromPrimitive, TryFromPrimitiveError};
use serde::de::{Error, Unexpected};
use serde::{Deserialize, Deserializer};
use std::borrow::Cow;
use std::cmp::min;
use std::fmt;
@ -24,6 +28,7 @@ use std::fmt::{Debug, Display, Formatter};
use std::io::{Cursor, Read, Seek};
use std::mem::{align_of, size_of};
use std::ops::Index;
use std::str::FromStr;
use std::sync::Mutex;
use zip::result::ZipError;
use zip::ZipArchive;
@ -531,3 +536,42 @@ where
err: Box::new(e),
})
}
#[derive(Debug, Copy, Clone, BinRead)]
pub struct Angles {
pitch: f32,
yaw: f32,
roll: f32,
}
impl<'de> Deserialize<'de> for Angles {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let str = <&str>::deserialize(deserializer)?;
str.parse()
.map_err(|_| D::Error::invalid_value(Unexpected::Other(str), &"a list of angles"))
}
}
impl FromStr for Angles {
type Err = EntityParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut floats = s.split(' ').map(f32::from_str);
let pitch = floats.next().ok_or(EntityParseError::ElementCount)??;
let yaw = floats.next().ok_or(EntityParseError::ElementCount)??;
let roll = floats.next().ok_or(EntityParseError::ElementCount)??;
Ok(Angles { pitch, yaw, roll })
}
}
impl Angles {
fn as_quaternion(&self) -> Quaternion<f32> {
// angles are applied in roll, pitch, yaw order
Quaternion::from_angle_y(Deg(self.yaw))
* Quaternion::from_angle_x(Deg(self.pitch))
* Quaternion::from_angle_z(Deg(self.roll))
}
}

View file

@ -1,5 +1,5 @@
use crate::{Handle, PropDynamic, PropDynamicOverride, StaticPropLump, Vector};
use cgmath::{Deg, Quaternion, Rotation3};
use cgmath::Quaternion;
#[derive(Debug, Clone)]
pub struct PropPlacement<'a> {
@ -22,17 +22,14 @@ impl<'a> Handle<'a, StaticPropLump> {
}
}
fn rotation(angles: [f32; 3]) -> Quaternion<f32> {
Quaternion::from_angle_y(Deg(angles[1]))
* Quaternion::from_angle_x(Deg(angles[0]))
* Quaternion::from_angle_z(Deg(angles[2]))
}
impl<'a> PropDynamic<'a> {
pub fn as_prop_placement(&self) -> PropPlacement<'a> {
if self.model.contains("slide_large") | self.model.contains("resup") {
// dbg!(self);
}
PropPlacement {
model: self.model,
rotation: rotation(self.angles),
rotation: self.angles.as_quaternion(),
scale: self.scale,
origin: self.origin,
skin: 0,
@ -44,7 +41,7 @@ impl<'a> PropDynamicOverride<'a> {
pub fn as_prop_placement(&self) -> PropPlacement<'a> {
PropPlacement {
model: self.model,
rotation: rotation(self.angles),
rotation: self.angles.as_quaternion(),
scale: self.scale,
origin: self.origin,
skin: 0,

View file

@ -1,12 +1,14 @@
use crate::error::EntityParseError;
use binrw::BinRead;
use cgmath::Vector3;
use serde::de::{Error, Unexpected};
use serde::{Deserialize, Deserializer};
use std::cmp::Ordering;
use std::fmt::Debug;
use std::ops::{Add, Mul, Sub};
use std::str::FromStr;
#[derive(Debug, Clone, Copy, BinRead)]
#[derive(Debug, Clone, Copy, BinRead, Default)]
pub struct Vector {
pub x: f32,
pub y: f32,
@ -110,3 +112,14 @@ impl From<Vector> for Vector3<f32> {
Vector3::new(v.x, v.y, v.z)
}
}
impl<'de> Deserialize<'de> for Vector {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let str = <&str>::deserialize(deserializer)?;
str.parse()
.map_err(|_| D::Error::invalid_value(Unexpected::Other(str), &"a vector"))
}
}