Skip to content

feat: P3D section faces and UVs, PAA blocks for GPUs - #45

Merged
TheWillard merged 1 commit into
mainfrom
feat/p3d-viewer-support
Nov 5, 2026
Merged

TheWillard merged 1 commit into
mainfrom
feat/p3d-viewer-support

Conversation

@TheWillard

@TheWillard TheWillard commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Fixes ODOL sections that failed to load, and adds what a renderer needs from P3D models and PAA textures: section face ranges, decoded UVs and BC blocks for GPUs. With this change all 6,682 models of Arma 3 load (v73), up from 6,648. The P3D viewer in arma.tools is built on it.

Format

  • LodSection, version 67 and up: after the stages comes an i32 flag and, when it is set, 11 f32s, not a 4x3 matrix of 12. Reading 12 put the next section 4 bytes off: 34 models failed with "failed to fill whole buffer" in stages, all of them collimator sights and weapons carrying them (ACO, ARCO, ...). The flag was always 0 or 1. What the floats mean is not known.
  • Section face ranges: face_lower_index and face_upper_index are byte offsets into the faces, with a face's vertex count and each of its vertex indices taking the size of an index: 4 bytes from version 69 (a triangle takes 16, a quad 20), 2 bytes before. Sections follow each other without gaps and cover all faces. Checked on every LOD of the test models (versions 40 to 75) and of Arma 3.

API

  • Lod::section_faces(): per section, its faces as a range of Lod::faces.
  • UVSet::uvs(): one [u, v] per vertex. Discretized sets (version 45 and up) map their i16s onto min..=max (in f64, the f32 result was off by 1e-4 on wide ranges), older ones are f32s, default-filled sets repeat their value.
  • Paa::from_reader_blocks(): like from_reader, but DXT1 and DXT5 mipmaps stay BC1 and BC3 blocks (LZO decompressed) instead of being decoded to RGBA, to upload them to a GPU as they are. Other formats decode as before.
  • Breaking: LodSection::unk_matrix_exists / unk_matrix: TransformMatrix are now has_unk_floats / unk_floats: Option<[f32; 11]>.
  • read_lods no longer prints Lod Index: n for every LOD.

Test data

rv-test-data-part-4.7z holds the ACO sight (acco_aco_f.p3d, 70 KB packed), encrypted like the other parts. aff-test-data-setup now extracts parts 1 to 4. A checkout that already extracted the test data won't get the new file: the setup skips non-empty test data folders, so delete tests/real_virtuality/test-data or extract part 4 by hand.

Testing

All tests pass. New:

  • section_faces: every LOD of every test model is covered by its sections without gaps.
  • uvs: every UV set has a coordinate per vertex, inside its range for discretized sets. Both kinds occur in the test models.
  • section_unk_floats: the ACO loads, has sections with the 11 floats, and its section ranges resolve.
  • paa_test::blocks: the blocks of DXT1 and DXT5 PAAs have the BC size of each mipmap and decode to what from_reader returns. blocks_other_formats: ARGB4444 decodes as before.

Outside the tests, all 6,682 P3Ds of the Arma 3 Addons folder load and their section ranges resolve.

- LodSection: the block after the stages (version 67 and up) is a flag
  and 11 floats, not a 4x3 matrix of 12. Reading 12 broke the next
  section: 34 of Arma 3's 6,682 models failed to load (collimator
  sights such as the ACO). All of them load now. The floats are kept as
  `unk_floats`, the flag was always 0 or 1.
- Lod::section_faces: the face ranges of the sections. Their offsets
  count bytes, with a face's vertex count and each vertex index taking
  the size of an index (4 bytes from version 69, 2 before). Checked
  against the test models (versions 40 to 75) and all of Arma 3.
- UVSet::uvs: the coordinates per vertex, from the discretized i16
  values (version 45 and up) or the floats before.
- Paa::from_reader_blocks: keeps DXT1 and DXT5 mipmaps as BC1 and BC3
  blocks instead of decoding them, to upload them to a GPU as they are.
- No more "Lod Index" printed for every LOD read.
- Test data: rv-test-data-part-4.7z with the ACO sight.
@codecov

codecov Bot commented Nov 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.82716% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...rma-file-formats/src/real_virtuality/paa/mipmap.rs 73.33% 4 Missing ⚠️
arma-file-formats/src/real_virtuality/p3d/lod.rs 97.91% 1 Missing ⚠️
Files with missing lines Coverage Δ
arma-file-formats/src/real_virtuality/p3d/odol.rs 48.78% <ø> (-0.62%) ⬇️
arma-file-formats/src/real_virtuality/paa/paa.rs 97.60% <100.00%> (+0.21%) ⬆️
arma-file-formats/src/real_virtuality/p3d/lod.rs 98.38% <97.91%> (-1.62%) ⬇️
...rma-file-formats/src/real_virtuality/paa/mipmap.rs 86.91% <73.33%> (-1.79%) ⬇️

... and 6 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@TheWillard
TheWillard merged commit 24c6f06 into main Nov 5, 2026
2 checks passed
@TheWillard
TheWillard deleted the feat/p3d-viewer-support branch November 5, 2026 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant