This commit is contained in:
parent
cc5c3d6dca
commit
e0f00392d2
|
@ -2,13 +2,216 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cmake"
|
||||||
|
version = "0.1.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cppmm-build"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28ab7d173fadeec5208c3ef3eb0aef0d3f419f5fa1450f01d2aa81ce8916e2ce"
|
||||||
|
dependencies = [
|
||||||
|
"cmake",
|
||||||
|
"quick-xml",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "1.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "imath-traits"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4659ab80c4ff995c16bd3973b6bb2e3ae7be0528b5f66cf860625b51855711ad"
|
||||||
|
dependencies = [
|
||||||
|
"half",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.150"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openexr"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "062f65fe94f0ee4e7aeb44d6c2b366fa90611ddb632e69c753ba3076731d606e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"half",
|
||||||
|
"imath-traits",
|
||||||
|
"openexr-sys",
|
||||||
|
"paste",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openexr-sys"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71b018f0a60798b0dbabeb2214ea3f8b68c3ac5e0aadd3036dd90a7c3f72c003"
|
||||||
|
dependencies = [
|
||||||
|
"cppmm-build",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pointcache"
|
name = "pointcache"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.70"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-xml"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.39"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tools"
|
name = "tools"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"half",
|
||||||
|
"imath-traits",
|
||||||
|
"openexr",
|
||||||
"pointcache",
|
"pointcache",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
26
src/lib.rs
26
src/lib.rs
|
@ -8,7 +8,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait PointCache {
|
pub trait PointCache {
|
||||||
type Frame;
|
type Frame: Frame;
|
||||||
fn read(
|
fn read(
|
||||||
infile: File,
|
infile: File,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
|
@ -22,14 +22,22 @@ pub trait PointCache {
|
||||||
) -> Result<(), Box<dyn Error>>;
|
) -> Result<(), Box<dyn Error>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Frame {
|
||||||
|
fn point_idx(&self) -> usize;
|
||||||
|
fn point(&self) -> Point;
|
||||||
|
fn with_point(self, point: Point) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MDDSeekableFile;
|
pub struct MDDSeekableFile;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
pub z: f32,
|
pub z: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MDDFrame {
|
pub struct MDDFrame {
|
||||||
pub frame_idx: usize,
|
pub frame_idx: usize,
|
||||||
|
@ -38,8 +46,20 @@ pub struct MDDFrame {
|
||||||
pub point: Point,
|
pub point: Point,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Frame for MDDFrame {
|
||||||
|
fn point_idx(&self) -> usize {
|
||||||
|
self.point_idx
|
||||||
|
}
|
||||||
|
fn point(&self) -> Point {
|
||||||
|
self.point
|
||||||
|
}
|
||||||
|
fn with_point(self, point: Point) -> Self {
|
||||||
|
MDDFrame { point, ..self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MDDSeekableFile {
|
impl MDDSeekableFile {
|
||||||
fn read_header(infile: &mut File) -> Result<(i32, i32), Box<dyn Error>> {
|
pub fn read_header(infile: &mut File) -> Result<(i32, i32), Box<dyn Error>> {
|
||||||
infile.seek(SeekFrom::Start(0))?;
|
infile.seek(SeekFrom::Start(0))?;
|
||||||
let mut buff = [0u8; size_of::<i32>()];
|
let mut buff = [0u8; size_of::<i32>()];
|
||||||
infile.read_exact(&mut buff)?;
|
infile.read_exact(&mut buff)?;
|
||||||
|
|
|
@ -5,3 +5,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pointcache = { path = ".." }
|
pointcache = { path = ".." }
|
||||||
|
openexr = "0.11.0"
|
||||||
|
half = "1.8.2"
|
||||||
|
imath-traits = "0.4.0"
|
||||||
|
|
|
@ -1,29 +1,174 @@
|
||||||
use std::fs::File;
|
// Openexr library is too complex to go off documentation alone and no projects on github using library. Seek out test cases
|
||||||
|
|
||||||
use pointcache::{MDDSeekableFile, PointCache, MDDFrame, Point};
|
use imath_traits::Zero;
|
||||||
|
use openexr::core::channel_list::{CHANNEL_FLOAT, CHANNEL_UINT};
|
||||||
|
use openexr::core::frame_buffer::{FrameBuffer, Slice};
|
||||||
|
use openexr::core::header::Header;
|
||||||
|
use openexr::core::output_file::OutputFile;
|
||||||
|
use openexr::core::PixelType;
|
||||||
|
use openexr::rgba::{Rgba, RgbaChannels, RgbaOutputFile};
|
||||||
|
use openexr::tiled::TiledOutputFile;
|
||||||
|
use pointcache::{MDDFrame, MDDSeekableFile, Point, PointCache};
|
||||||
|
use std::default;
|
||||||
|
use std::{error::Error, fs::File};
|
||||||
|
|
||||||
|
// https://github.com/vfx-rs/openexr-rs/blob/25826b4f89bc768b565ba150d6f9c76876ad6bc3/src/core/output_file.rs#L275
|
||||||
|
|
||||||
|
// Godot doesn't seem to support Uint images, using f32 instead
|
||||||
|
fn write_mask_image(
|
||||||
|
filename: &str,
|
||||||
|
pixels: &Vec<f32>,
|
||||||
|
vertex_total: usize,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
let width = vertex_total;
|
||||||
|
let height: usize = 1;
|
||||||
|
let mut header = Header::from_dimensions(width as i32, height as i32);
|
||||||
|
|
||||||
|
header.channels_mut().insert("R", &CHANNEL_FLOAT);
|
||||||
|
|
||||||
|
let mut frame_buffer = FrameBuffer::new();
|
||||||
|
|
||||||
|
frame_buffer.insert(
|
||||||
|
"R",
|
||||||
|
&Slice::builder(
|
||||||
|
PixelType::Float,
|
||||||
|
&pixels[0] as *const _ as *const u8,
|
||||||
|
width as i64,
|
||||||
|
height as i64,
|
||||||
|
)
|
||||||
|
.build()?,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut file = OutputFile::new(filename, &header, 1)?;
|
||||||
|
file.set_frame_buffer(&frame_buffer)?;
|
||||||
|
unsafe { file.write_pixels(height as i32)? };
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_point_image(
|
||||||
|
filename: &str,
|
||||||
|
pixels: &Vec<Point>,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut header = Header::from_dimensions(width as i32, height as i32);
|
||||||
|
|
||||||
|
header.channels_mut().insert("R", &CHANNEL_FLOAT);
|
||||||
|
header.channels_mut().insert("G", &CHANNEL_FLOAT);
|
||||||
|
header.channels_mut().insert("B", &CHANNEL_FLOAT);
|
||||||
|
|
||||||
|
let mut frame_buffer = FrameBuffer::new();
|
||||||
|
|
||||||
|
[
|
||||||
|
("R", &pixels[0].x),
|
||||||
|
("G", &pixels[0].y),
|
||||||
|
("B", &pixels[0].z),
|
||||||
|
]
|
||||||
|
.map(|(name, spot)| {
|
||||||
|
frame_buffer.insert(
|
||||||
|
name,
|
||||||
|
&Slice::builder(
|
||||||
|
PixelType::Float,
|
||||||
|
spot as *const _ as *const u8,
|
||||||
|
width as i64,
|
||||||
|
height as i64,
|
||||||
|
)
|
||||||
|
.x_stride(std::mem::size_of::<Point>())
|
||||||
|
.build()?,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Result<(), openexr::Error>>()?;
|
||||||
|
|
||||||
|
let mut file = OutputFile::new(filename, &header, 1)?;
|
||||||
|
file.set_frame_buffer(&frame_buffer)?;
|
||||||
|
unsafe { file.write_pixels(height as i32)? };
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum PointState {
|
||||||
|
Unseen,
|
||||||
|
OneValue(Point),
|
||||||
|
Varying(usize),
|
||||||
|
}
|
||||||
|
use PointState::*;
|
||||||
|
impl PointState {
|
||||||
|
fn mask_value(&self) -> f32 {
|
||||||
|
match *self {
|
||||||
|
Unseen => panic!(),
|
||||||
|
OneValue(_) => -1.0,
|
||||||
|
Varying(idx) => idx as f32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let file_a = std::env::args().nth(1).expect("Need three files");
|
let mdd_filename = std::env::args()
|
||||||
let file_b = std::env::args().nth(1).expect("Need three files");
|
.nth(1)
|
||||||
let file_c = std::env::args().nth(1).expect("Need three files");
|
.expect("expected first argument to be a file path to an .mdd file");
|
||||||
|
let path = std::env::args()
|
||||||
|
.nth(2)
|
||||||
|
.expect("expected second argument to be an output directory");
|
||||||
|
|
||||||
let file_a = File::open(file_a).unwrap();
|
let mut mdd_file = File::open(mdd_filename).expect("Mdd filename is not valid");
|
||||||
let file_b = File::open(file_b).unwrap();
|
|
||||||
let file_c = File::create(file_c).unwrap();
|
|
||||||
|
|
||||||
let mut file_b = MDDSeekableFile::read(file_b).unwrap();
|
let (total_frames, total_points) = MDDSeekableFile::read_header(&mut mdd_file).unwrap();
|
||||||
|
|
||||||
MDDSeekableFile::map_to(file_a, file_c, |frame| {
|
let mut mask_last: Vec<PointState> = vec![Unseen; total_points as usize];
|
||||||
let frame_b = file_b.next().unwrap()?;
|
|
||||||
Ok(MDDFrame {
|
let pc = MDDSeekableFile::read(mdd_file.try_clone().unwrap()).unwrap();
|
||||||
point: Point {
|
let mut total_varying = 0;
|
||||||
x: frame_b.point.x - frame.point.x,
|
for frame in pc {
|
||||||
y: frame_b.point.y - frame.point.y,
|
let MDDFrame {
|
||||||
z: frame_b.point.z - frame.point.z,
|
point, point_idx, ..
|
||||||
},
|
} = frame.unwrap();
|
||||||
..frame
|
match mask_last[point_idx] {
|
||||||
})
|
Unseen => mask_last[point_idx] = OneValue(point),
|
||||||
}).unwrap();
|
OneValue(old_point) => {
|
||||||
|
if point != old_point {
|
||||||
|
mask_last[point_idx] = Varying(total_varying);
|
||||||
|
total_varying += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Varying(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mask: Vec<f32> = mask_last.iter().map(PointState::mask_value).collect();
|
||||||
|
|
||||||
|
// write_mask_image(
|
||||||
|
// "/home/rat/cow/godot/vertex_animation/mask.exr",
|
||||||
|
// &pixels.collect(),
|
||||||
|
// width as usize,
|
||||||
|
// )
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
|
let mut pixels: Vec<Point> = Vec::with_capacity(total_varying * (total_frames as usize));
|
||||||
|
|
||||||
|
let pc = MDDSeekableFile::read(mdd_file.try_clone().unwrap()).unwrap();
|
||||||
|
|
||||||
|
pixels.extend(pc.filter_map(|frame| {
|
||||||
|
let MDDFrame {
|
||||||
|
point_idx, point, ..
|
||||||
|
} = frame.unwrap();
|
||||||
|
match mask_last[point_idx] {
|
||||||
|
Unseen => panic!(),
|
||||||
|
OneValue(_) => None,
|
||||||
|
Varying(_) => Some(point),
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
assert!(pixels.len() == total_varying * (total_frames as usize));
|
||||||
|
|
||||||
|
write_point_image(
|
||||||
|
"/home/rat/cow/godot/vertex_animation/test.exr",
|
||||||
|
&pixels,
|
||||||
|
total_varying,
|
||||||
|
total_frames as usize,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue