You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

458 lines
12KB

  1. use crate::{
  2. data::{read, vertex::Vertex},
  3. ffi,
  4. math::*,
  5. types::{Cast, StkStr},
  6. };
  7. use std::{
  8. collections::HashMap,
  9. io::{self, Read, Seek, SeekFrom},
  10. ops::Range,
  11. str::Utf8Error,
  12. };
  13. #[derive(thiserror::Error, Debug)]
  14. #[non_exhaustive]
  15. pub enum Err {
  16. #[error(transparent)]
  17. Io(#[from] io::Error),
  18. #[error("Bad magic number")]
  19. Magic,
  20. #[error("Incorrect number of poses")]
  21. NumPoses,
  22. #[error("Bad text offset")]
  23. TextOffset,
  24. #[error(transparent)]
  25. Utf8(#[from] Utf8Error),
  26. #[error("Bad parent joint")]
  27. Parent,
  28. #[error("Bad frame count")]
  29. FrameCount,
  30. #[error("Unknown vertex array type")]
  31. VaType,
  32. #[error("Unsupported vertex array format")]
  33. VaFormat,
  34. }
  35. struct Pose {
  36. par: usize,
  37. msk: u32,
  38. ofs: [f32; 10],
  39. scl: [f32; 10],
  40. }
  41. struct Joint {
  42. #[allow(dead_code)]
  43. nam: StkStr,
  44. mat: Mat4,
  45. inv: Mat4,
  46. }
  47. pub struct Mesh {
  48. mat: StkStr,
  49. vtx: Range<usize>,
  50. idx: Range<usize>,
  51. }
  52. /// Data to be uploaded to the GPU. Separate from Model so that it may
  53. /// be dropped after upload.
  54. pub struct ModelData {
  55. pub vtx: Vec<Vertex>,
  56. pub idx: Vec<u32>,
  57. }
  58. /// Run-time model data. Anything necessary for passing commands to
  59. /// the GPU.
  60. pub struct Model {
  61. meshes: HashMap<StkStr, Mesh>,
  62. frames: Vec<Vec<Mat4>>,
  63. num_frms: usize,
  64. }
  65. const FMT_I8: u32 = 0;
  66. const FMT_U8: u32 = 1;
  67. const FMT_I16: u32 = 2;
  68. const FMT_U16: u32 = 3;
  69. const FMT_I32: u32 = 4;
  70. const FMT_U32: u32 = 5;
  71. const FMT_F16: u32 = 6;
  72. const FMT_F32: u32 = 7;
  73. const FMT_F64: u32 = 8;
  74. const fn fmt_check(fm: u32) -> Result<(), Err> {
  75. match fm {
  76. | FMT_I8 | FMT_U8 | FMT_I16 | FMT_U16 | FMT_I32 | FMT_U32 | FMT_F16
  77. | FMT_F32 | FMT_F64 => Ok(()),
  78. | _ => Err(Err::VaFormat),
  79. }
  80. }
  81. fn fmt_size(fm: u32) -> usize {
  82. match fm {
  83. | FMT_I8 | FMT_U8 => 1,
  84. | FMT_I16 | FMT_U16 | FMT_F16 => 2,
  85. | FMT_I32 | FMT_U32 | FMT_F32 => 4,
  86. | FMT_F64 => 8,
  87. | _ => unsafe { std::hint::unreachable_unchecked() },
  88. }
  89. }
  90. fn fmt_read_abs(fm: u32, vec: &[u8], pos: usize) -> f32 {
  91. match fm {
  92. | FMT_I8 => read::i8x(vec, pos).into(),
  93. | FMT_U8 => read::u8x(vec, pos).into(),
  94. | FMT_I16 => read::i16le(vec, pos).into(),
  95. | FMT_U16 => read::u16le(vec, pos).into(),
  96. | FMT_I32 => read::i32le(vec, pos).cast(),
  97. | FMT_U32 => read::u32le(vec, pos).cast(),
  98. | FMT_F16 => read::f16le(vec, pos).to_f32(),
  99. | FMT_F32 => read::f32le(vec, pos),
  100. | FMT_F64 => read::f64le(vec, pos) as f32,
  101. | _ => unsafe { std::hint::unreachable_unchecked() },
  102. }
  103. }
  104. fn fmt_read_nrm(fm: u32, vec: &[u8], pos: usize) -> f32 {
  105. match fm {
  106. | FMT_I8 => f32::from(read::i8x(vec, pos)).abs() / 128.0,
  107. | FMT_U8 => f32::from(read::u8x(vec, pos)) / 255.0,
  108. | FMT_I16 => f32::from(read::i16le(vec, pos)).abs() / 32768.0,
  109. | FMT_U16 => f32::from(read::u16le(vec, pos)) / 65535.0,
  110. | FMT_I32 => (f64::from(read::i32le(vec, pos)) / 2147483648.0) as f32,
  111. | FMT_U32 => (f64::from(read::u32le(vec, pos)) / 4294967295.0) as f32,
  112. | FMT_F16 => f32::clamp(read::f16le(vec, pos).to_f32(), 0.0, 1.0),
  113. | FMT_F32 => f32::clamp(read::f32le(vec, pos), 0.0, 1.0),
  114. | FMT_F64 => f32::clamp(read::f64le(vec, pos) as f32, 0.0, 1.0),
  115. | _ => unsafe { std::hint::unreachable_unchecked() },
  116. }
  117. }
  118. impl Mesh {
  119. pub fn get_mat(&self) -> &str {
  120. &self.mat
  121. }
  122. pub const fn vtx_beg(&self) -> usize {
  123. self.vtx.start
  124. }
  125. pub const fn vtx_end(&self) -> usize {
  126. self.vtx.end
  127. }
  128. pub const fn vtx_len(&self) -> usize {
  129. self.vtx.end - self.vtx.start
  130. }
  131. pub const fn idx_beg(&self) -> usize {
  132. self.idx.start
  133. }
  134. pub const fn idx_end(&self) -> usize {
  135. self.idx.end
  136. }
  137. pub const fn idx_len(&self) -> usize {
  138. self.idx.end - self.idx.start
  139. }
  140. }
  141. impl Model {
  142. pub fn read<R>(rd: &mut R) -> Result<(Self, ModelData), Err>
  143. where
  144. R: Read + Seek,
  145. {
  146. fn from_stab(stab: &[u8], strn: usize) -> Result<&str, Err> {
  147. let strn = stab.get(strn..).ok_or(Err::TextOffset)?;
  148. ffi::cstr_from_slice(strn).ok_or(Err::TextOffset)
  149. }
  150. let mut head = [0; 124];
  151. rd.read_exact(&mut head)?;
  152. if &head[0..20] != b"INTERQUAKEMODEL\0\x02\0\0\0" {
  153. return Err(Err::Magic);
  154. }
  155. let num_text = read::u32le(&head, 28) as usize;
  156. let ofs_text = read::u32le(&head, 32).into();
  157. let num_mesh = read::u32le(&head, 36) as usize;
  158. let ofs_mesh = read::u32le(&head, 40).into();
  159. let num_vinf = read::u32le(&head, 44) as usize;
  160. let num_vert = read::u32le(&head, 48) as usize;
  161. let ofs_vinf = read::u32le(&head, 52).into();
  162. let num_tris = read::u32le(&head, 56) as usize;
  163. let ofs_tris = read::u32le(&head, 60).into();
  164. let num_join = read::u32le(&head, 68) as usize;
  165. let ofs_join = read::u32le(&head, 72).into();
  166. let num_pose = read::u32le(&head, 76) as usize;
  167. let ofs_pose = read::u32le(&head, 80).into();
  168. //let num_anim = read::u32le(&head, 84) as usize;
  169. //let ofs_anim = read::u32le(&head, 88).into();
  170. let num_frms = read::u32le(&head, 92) as usize;
  171. let num_frmc = read::u32le(&head, 96) as usize;
  172. let ofs_frms = read::u32le(&head, 100).into();
  173. //let ofs_bnds = read::u32le(&head, 104).into();
  174. if num_join != 0 && num_pose != 0 && num_pose != num_join {
  175. return Err(Err::NumPoses);
  176. }
  177. // collect vertex info
  178. let mut pos_v = Vec::with_capacity(num_vert);
  179. let mut tex_v = Vec::with_capacity(num_vert);
  180. let mut nrm_v = Vec::with_capacity(num_vert);
  181. let mut tan_v = Vec::with_capacity(num_vert);
  182. let mut idx_v = Vec::with_capacity(num_vert);
  183. let mut wgt_v = Vec::with_capacity(num_vert);
  184. let mut clr_v = Vec::with_capacity(num_vert);
  185. rd.seek(SeekFrom::Start(ofs_vinf))?;
  186. for array_def in read::hunk(rd, num_vinf * 20)?.chunks(20) {
  187. let ty = read::u32le(array_def, 0);
  188. //let fl = read::u32le(array_def, 4);
  189. let fm = read::u32le(array_def, 8);
  190. let sz = read::u32le(array_def, 12) as usize;
  191. let of = read::u32le(array_def, 16).into();
  192. fmt_check(fm)?;
  193. rd.seek(SeekFrom::Start(of))?;
  194. let obj_size = fmt_size(fm);
  195. let obj_blks = obj_size * sz;
  196. let hunk = read::hunk(rd, obj_blks * num_vert)?;
  197. let v2 = |v: &mut Vec<Vec3>, rd: fn(u32, &[u8], usize) -> f32| {
  198. if sz != 2 {
  199. Err(Err::VaFormat)
  200. } else {
  201. for vec in hunk.chunks(obj_blks) {
  202. let x = rd(fm, vec, 0);
  203. let y = rd(fm, vec, obj_size);
  204. v.push(Vec3::new(x, y, 0.0));
  205. }
  206. Ok(())
  207. }
  208. };
  209. let v3 = |v: &mut Vec<Vec3>, rd: fn(u32, &[u8], usize) -> f32| {
  210. if sz != 3 {
  211. Err(Err::VaFormat)
  212. } else {
  213. for vec in hunk.chunks(obj_blks) {
  214. let x = rd(fm, vec, 0);
  215. let y = rd(fm, vec, obj_size);
  216. let z = rd(fm, vec, obj_size * 2);
  217. v.push(Vec3::new(x, y, z));
  218. }
  219. Ok(())
  220. }
  221. };
  222. let v4 = |v: &mut Vec<Vec4>, rd: fn(u32, &[u8], usize) -> f32| {
  223. if sz != 4 {
  224. Err(Err::VaFormat)
  225. } else {
  226. for vec in hunk.chunks(obj_blks) {
  227. let x = rd(fm, vec, 0);
  228. let y = rd(fm, vec, obj_size);
  229. let z = rd(fm, vec, obj_size * 2);
  230. let w = rd(fm, vec, obj_size * 3);
  231. v.push(Vec4::new(x, y, z, w));
  232. }
  233. Ok(())
  234. }
  235. };
  236. match ty {
  237. | 0 => v3(&mut pos_v, fmt_read_abs)?,
  238. | 1 => v2(&mut tex_v, fmt_read_abs)?,
  239. | 2 => v3(&mut nrm_v, fmt_read_abs)?,
  240. | 3 => v4(&mut tan_v, fmt_read_abs)?,
  241. | 4 => v4(&mut idx_v, fmt_read_abs)?,
  242. | 5 => v4(&mut wgt_v, fmt_read_nrm)?,
  243. | 6 => v4(&mut clr_v, fmt_read_nrm)?,
  244. | _ => return Err(Err::VaType),
  245. }
  246. }
  247. // zip the vertex info
  248. let mut vert_dat = Vec::with_capacity(num_vert);
  249. for (pos, tex, nrm, tan, idx, wgt, clr) in crate::iter::OpenZip((
  250. pos_v.into_iter(),
  251. tex_v.into_iter(),
  252. nrm_v.into_iter(),
  253. tan_v.into_iter(),
  254. idx_v.into_iter(),
  255. wgt_v.into_iter(),
  256. clr_v.into_iter(),
  257. )) {
  258. vert_dat.push(Vertex {
  259. pos: pos.unwrap_or(Vec3::ZERO),
  260. tex: tex.unwrap_or(Vec3::ZERO),
  261. nrm: nrm.unwrap_or(Vec3::ZERO),
  262. tan: tan.unwrap_or(Vec4::ZERO),
  263. idx: idx.unwrap_or(Vec4::ZERO),
  264. wgt: wgt.unwrap_or(Vec4::ZERO),
  265. clr: clr.unwrap_or(Vec4::ONE),
  266. });
  267. }
  268. // collect index info
  269. let mut indx_dat = Vec::with_capacity(num_tris * 3);
  270. rd.seek(SeekFrom::Start(ofs_tris))?;
  271. for tri in read::hunk(rd, num_tris * 4 * 3)?.chunks(4 * 3) {
  272. indx_dat.push(read::u32le(tri, 0));
  273. indx_dat.push(read::u32le(tri, 4));
  274. indx_dat.push(read::u32le(tri, 8));
  275. }
  276. // collect text
  277. rd.seek(SeekFrom::Start(ofs_text))?;
  278. let stab = read::hunk(rd, num_text)?;
  279. // collect mesh info
  280. let mut meshes = HashMap::with_capacity(num_mesh);
  281. rd.seek(SeekFrom::Start(ofs_mesh))?;
  282. for mesh in read::hunk(rd, num_mesh * 4 * 6)?.chunks(4 * 6) {
  283. let nam = read::u32le(mesh, 0) as usize;
  284. let mat = read::u32le(mesh, 4) as usize;
  285. let vtx = read::u32le(mesh, 8) as usize;
  286. let vnu = read::u32le(mesh, 12) as usize;
  287. let idx = read::u32le(mesh, 16) as usize * 3;
  288. let inu = read::u32le(mesh, 20) as usize * 3;
  289. let nam = StkStr::new(from_stab(&stab, nam)?);
  290. let mat = StkStr::new(from_stab(&stab, mat)?);
  291. let vtx = vtx..vtx + vnu;
  292. let idx = idx..idx + inu;
  293. meshes.insert(nam, Mesh { mat, vtx, idx });
  294. }
  295. // collect joint info
  296. let mut joints: Vec<Joint> = Vec::with_capacity(num_join);
  297. rd.seek(SeekFrom::Start(ofs_join))?;
  298. for join in read::hunk(rd, num_join * 4 * 12)?.chunks(4 * 12) {
  299. let nam = read::u32le(join, 0) as usize;
  300. let par = read::u32le(join, 4) as usize;
  301. let trs = read::array(read::f32le, join, [0.0; 10], 4, 8);
  302. let nam = StkStr::new(from_stab(&stab, nam)?);
  303. let xlt = Vec3::new(trs[0], trs[1], trs[2]);
  304. let rot = Quat::from_xyzw(trs[3], trs[4], trs[5], trs[6]).normalize();
  305. let scl = Vec3::new(trs[7], trs[8], trs[9]);
  306. let mut mat = Mat4::from_scale_rotation_translation(scl, rot, xlt);
  307. let mut inv = mat.inverse();
  308. if par & 0x8000_0000 == 0 {
  309. let parent = joints.get(par).ok_or(Err::Parent)?;
  310. mat = parent.mat * mat;
  311. inv = inv * parent.inv;
  312. }
  313. joints.push(Joint { nam, mat, inv });
  314. }
  315. // collect frames
  316. let mut frames = Vec::with_capacity(num_frms * num_frmc);
  317. rd.seek(SeekFrom::Start(ofs_frms))?;
  318. for samp in read::hunk(rd, num_frms * num_frmc * 2)?.chunks(2) {
  319. frames.push(read::u16le(samp, 0));
  320. }
  321. // collect pose info
  322. let mut poses = Vec::with_capacity(num_pose);
  323. rd.seek(SeekFrom::Start(ofs_pose))?;
  324. for pose in read::hunk(rd, num_pose * 4 * 22)?.chunks(4 * 22) {
  325. let par = read::u32le(pose, 0) as usize;
  326. let msk = read::u32le(pose, 4);
  327. let ofs = read::array(read::f32le, pose, [0.0; 10], 4, 8);
  328. let scl = read::array(read::f32le, pose, [0.0; 10], 4, 48);
  329. poses.push(Pose { par, msk, ofs, scl });
  330. }
  331. // calculate frame matrices
  332. let mut frame = frames.iter();
  333. let mut frames = Vec::with_capacity(num_frms);
  334. for _ in 0..num_frms {
  335. let mut frame_mats = Vec::with_capacity(num_pose);
  336. for (pose, joint) in poses.iter().zip(joints.iter()) {
  337. let mut ofs = pose.ofs;
  338. for (i, off) in ofs.iter_mut().enumerate() {
  339. if pose.msk & 1 << i != 0 {
  340. let frm = f32::from(*frame.next().ok_or(Err::FrameCount)?);
  341. *off += frm * pose.scl[i];
  342. }
  343. }
  344. let xlt = Vec3::new(ofs[0], ofs[1], ofs[2]);
  345. let rot =
  346. Quat::from_xyzw(ofs[3], ofs[4], ofs[5], ofs[6]).normalize();
  347. let scl = Vec3::new(ofs[7], ofs[8], ofs[9]);
  348. let mut mat = Mat4::from_scale_rotation_translation(scl, rot, xlt);
  349. if pose.par & 0x8000_0000 == 0 {
  350. let parent = joints.get(pose.par).ok_or(Err::Parent)?;
  351. mat = parent.mat * mat * joint.inv;
  352. let parent = frame_mats.get(pose.par).ok_or(Err::Parent)?;
  353. mat = *parent * mat;
  354. } else {
  355. mat = mat * joint.inv;
  356. }
  357. frame_mats.push(mat);
  358. }
  359. frames.push(frame_mats);
  360. }
  361. Ok((
  362. Self { meshes, frames, num_frms },
  363. ModelData { vtx: vert_dat, idx: indx_dat },
  364. ))
  365. }
  366. pub fn frame(&self, joint: usize, frame: usize) -> Option<Mat4> {
  367. Some(*self.frames.get(frame)?.get(joint)?)
  368. }
  369. pub const fn num_frames(&self) -> usize {
  370. self.num_frms
  371. }
  372. }
  373. impl std::ops::Deref for Model {
  374. type Target = HashMap<StkStr, Mesh>;
  375. fn deref(&self) -> &Self::Target {
  376. &self.meshes
  377. }
  378. }
  379. // EOF