Add obj parsing

This commit is contained in:
hal8174 2024-10-02 23:43:13 +02:00
parent 0a70fbd8d4
commit 556f50274d
13 changed files with 1004 additions and 3 deletions

335
Cargo.lock generated
View file

@ -2,6 +2,15 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "addr2line"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375"
dependencies = [
"gimli",
]
[[package]] [[package]]
name = "adler" name = "adler"
version = "1.0.2" version = "1.0.2"
@ -78,6 +87,30 @@ dependencies = [
"arrayvec", "arrayvec",
] ]
[[package]]
name = "backtrace"
version = "0.3.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide 0.8.0",
"object",
"rustc-demangle",
"windows-targets 0.52.6",
]
[[package]]
name = "backtrace-ext"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
dependencies = [
"backtrace",
]
[[package]] [[package]]
name = "bit_field" name = "bit_field"
version = "0.10.2" version = "0.10.2"
@ -90,6 +123,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]] [[package]]
name = "bitstream-io" name = "bitstream-io"
version = "2.5.3" version = "2.5.3"
@ -211,6 +250,16 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "exr" name = "exr"
version = "1.72.0" version = "1.72.0"
@ -276,6 +325,12 @@ dependencies = [
"weezl", "weezl",
] ]
[[package]]
name = "gimli"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
[[package]] [[package]]
name = "half" name = "half"
version = "2.4.1" version = "2.4.1"
@ -358,6 +413,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "is_ci"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.12.1" version = "0.12.1"
@ -405,6 +466,12 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.12" version = "0.4.12"
@ -445,6 +512,37 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miette"
version = "7.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1"
dependencies = [
"backtrace",
"backtrace-ext",
"cfg-if",
"miette-derive",
"owo-colors",
"supports-color",
"supports-hyperlinks",
"supports-unicode",
"terminal_size",
"textwrap",
"thiserror",
"unicode-width",
]
[[package]]
name = "miette-derive"
version = "7.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "minimal-lexical" name = "minimal-lexical"
version = "0.2.1" version = "0.2.1"
@ -542,6 +640,15 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "object"
version = "0.36.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.20.1" version = "1.20.1"
@ -551,6 +658,12 @@ dependencies = [
"portable-atomic", "portable-atomic",
] ]
[[package]]
name = "owo-colors"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56"
[[package]] [[package]]
name = "paste" name = "paste"
version = "1.0.15" version = "1.0.15"
@ -569,7 +682,7 @@ version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"crc32fast", "crc32fast",
"fdeflate", "fdeflate",
"flate2", "flate2",
@ -759,6 +872,8 @@ dependencies = [
name = "ray-tracing-scene" name = "ray-tracing-scene"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"miette",
"nom",
"ray-tracing-core", "ray-tracing-core",
"ray-tracing-material", "ray-tracing-material",
] ]
@ -804,6 +919,25 @@ dependencies = [
"bytemuck", "bytemuck",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustix"
version = "0.38.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
dependencies = [
"bitflags 2.6.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@ -866,6 +1000,12 @@ version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "smawk"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.9.8" version = "0.9.8"
@ -875,6 +1015,27 @@ dependencies = [
"lock_api", "lock_api",
] ]
[[package]]
name = "supports-color"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8775305acf21c96926c900ad056abeef436701108518cf890020387236ac5a77"
dependencies = [
"is_ci",
]
[[package]]
name = "supports-hyperlinks"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c0a1e5168041f5f3ff68ff7d95dcb9c8749df29f6e7e89ada40dd4c9de404ee"
[[package]]
name = "supports-unicode"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.79" version = "2.0.79"
@ -905,12 +1066,33 @@ version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "terminal_size"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
dependencies = [
"rustix",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "tev_client" name = "tev_client"
version = "0.5.2" version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c845c2d56d4f732d09a32c9ea2cd3f01923be7a5f98d9f7f0a347205c3141036" checksum = "c845c2d56d4f732d09a32c9ea2cd3f01923be7a5f98d9f7f0a347205c3141036"
[[package]]
name = "textwrap"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
dependencies = [
"smawk",
"unicode-linebreak",
"unicode-width",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.64" version = "1.0.64"
@ -982,6 +1164,18 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-linebreak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]] [[package]]
name = "v_frame" name = "v_frame"
version = "0.3.8" version = "0.3.8"
@ -1066,6 +1260,145 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.20" version = "0.6.20"

View file

@ -1,7 +1,8 @@
use crate::prelude::*; use crate::prelude::*;
use std::fmt::Debug;
/// All calculations for the material are done a tangent space of the intersection. /// All calculations for the material are done a tangent space of the intersection.
pub trait Material<R: Rng>: Sync { pub trait Material<R: Rng>: Sync + Debug {
fn eval(&self, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color; fn eval(&self, w_in: Dir3, w_out: Dir3, rng: &mut R) -> Color;
fn sample(&self, w_in: Dir3, rng: &mut R) -> SampleResult { fn sample(&self, w_in: Dir3, rng: &mut R) -> SampleResult {

View file

@ -1,5 +1,6 @@
use ray_tracing_core::prelude::*; use ray_tracing_core::prelude::*;
#[derive(Debug)]
pub struct DefaultMaterial {} pub struct DefaultMaterial {}
impl<R: Rng> Material<R> for DefaultMaterial { impl<R: Rng> Material<R> for DefaultMaterial {

View file

@ -1,7 +1,8 @@
use ray_tracing_core::prelude::*; use ray_tracing_core::prelude::*;
#[derive(Debug)]
pub struct DiffuseMaterial { pub struct DiffuseMaterial {
pub(crate) albedo: Color, albedo: Color,
} }
impl DiffuseMaterial { impl DiffuseMaterial {

View file

@ -1,5 +1,6 @@
use ray_tracing_core::prelude::*; use ray_tracing_core::prelude::*;
#[derive(Debug)]
pub struct Mirror { pub struct Mirror {
color: Color, color: Color,
} }

View file

@ -4,5 +4,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
miette = { version = "7.2.0", features = ["fancy"] }
nom = "7.1.3"
ray-tracing-core = { path = "../ray-tracing-core" } ray-tracing-core = { path = "../ray-tracing-core" }
ray-tracing-material = { path = "../ray-tracing-material" } ray-tracing-material = { path = "../ray-tracing-material" }

View file

@ -0,0 +1,10 @@
use miette::Result;
use ray_tracing_scene::parse_obj::ObjData;
fn main() -> Result<()> {
let obj = ObjData::new("obj/cornell_box.obj")?;
dbg!(obj);
Ok(())
}

View file

@ -0,0 +1,43 @@
o box
# left side
v 0.5 -0.5 -0.5
v 0.5 -0.5 0.5
v 0.5 0.5 0.5
v 0.5 0.5 -0.5
f -4 -3 -2 -1
# right side
v -0.5 -0.5 -0.5
v -0.5 -0.5 0.5
v -0.5 0.5 0.5
v -0.5 0.5 -0.5
f -4 -3 -2 -1
# bottom side
v -0.5 -0.5 -0.5
v -0.5 -0.5 0.5
v 0.5 -0.5 0.5
v 0.5 -0.5 -0.5
f -4 -3 -2 -1
# top side
v -0.5 0.5 -0.5
v -0.5 0.5 0.5
v 0.5 0.5 0.5
v 0.5 0.5 -0.5
f -4 -3 -2 -1
# front side
v -0.5 -0.5 -0.5
v -0.5 0.5 -0.5
v 0.5 0.5 -0.5
v 0.5 -0.5 -0.5
f -4 -3 -2 -1
# back side
v -0.5 -0.5 0.5
v -0.5 0.5 0.5
v 0.5 0.5 0.5
v 0.5 -0.5 0.5
f -4 -3 -2 -1

View file

@ -0,0 +1,38 @@
# Blender 4.1.1
# www.blender.org
o box
v -0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v -0.500000 -0.500000 -0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 -0.500000 0.500000
v 0.500000 0.500000 0.500000
v 0.500000 -0.500000 -0.500000
v 0.500000 0.500000 -0.500000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/4/2 4/3/2 8/5/2 7/6/2
f 7/6/3 8/5/3 6/7/3 5/8/3
f 5/8/4 6/7/4 2/9/4 1/10/4
f 3/11/5 7/6/5 5/8/5 1/12/5
f 8/5/6 4/13/6 2/14/6 6/7/6

View file

@ -0,0 +1,27 @@
newmtl white
Ka 0 0 0
Kd 1 1 1
Ks 0 0 0
newmtl red
Ka 0 0 0
Kd 1 0 0
Ks 0 0 0
newmtl green
Ka 0 0 0
Kd 0 1 0
Ks 0 0 0
newmtl blue
Ka 0 0 0
Kd 0 0 1
Ks 0 0 0
newmtl light
Ka 20 20 20
Kd 1 1 1
Ks 0 0 0
newmtl glass
type glass

View file

@ -0,0 +1,140 @@
# original cornell box data
mtllib cornell_box.mtl
o floor
usemtl white
v 552.8 0.0 0.0
v 0.0 0.0 0.0
v 0.0 0.0 559.2
v 549.6 0.0 559.2
v 130.0 0.0 65.0
v 82.0 0.0 225.0
v 240.0 0.0 272.0
v 290.0 0.0 114.0
v 423.0 0.0 247.0
v 265.0 0.0 296.0
v 314.0 0.0 456.0
v 472.0 0.0 406.0
f 1 2 3 4
f 8 7 6 5
f 12 11 10 9
o light
usemtl light
v 343.0 548.0 227.0
v 343.0 548.0 332.0
v 213.0 548.0 332.0
v 213.0 548.0 227.0
#f -4 -3 -2 -1
o ceiling
usemtl white
v 556.0 548.8 0.0
v 556.0 548.8 559.2
v 0.0 548.8 559.2
v 0.0 548.8 0.0
f -4 -3 -2 -1
o back_wall
usemtl white
v 549.6 0.0 559.2
v 0.0 0.0 559.2
v 0.0 548.8 559.2
v 556.0 548.8 559.2
f -4 -3 -2 -1
o front_wall
usemtl blue
v 549.6 0.0 0
v 0.0 0.0 0
v 0.0 548.8 0
v 556.0 548.8 0
#f -1 -2 -3 -4
o green_wall
usemtl green
v 0.0 0.0 559.2
v 0.0 0.0 0.0
v 0.0 548.8 0.0
v 0.0 548.8 559.2
f -4 -3 -2 -1
o red_wall
usemtl red
v 552.8 0.0 0.0
v 549.6 0.0 559.2
v 556.0 548.8 559.2
v 556.0 548.8 0.0
f -4 -3 -2 -1
o short_block
usemtl glass
v 130.0 165.0 65.0
v 82.0 165.0 225.0
v 240.0 165.0 272.0
v 290.0 165.0 114.0
f -4 -3 -2 -1
v 290.0 0.0 114.0
v 290.0 165.0 114.0
v 240.0 165.0 272.0
v 240.0 0.0 272.0
f -4 -3 -2 -1
v 130.0 0.0 65.0
v 130.0 165.0 65.0
v 290.0 165.0 114.0
v 290.0 0.0 114.0
f -4 -3 -2 -1
v 82.0 0.0 225.0
v 82.0 165.0 225.0
v 130.0 165.0 65.0
v 130.0 0.0 65.0
f -4 -3 -2 -1
v 240.0 0.0 272.0
v 240.0 165.0 272.0
v 82.0 165.0 225.0
v 82.0 0.0 225.0
f -4 -3 -2 -1
o tall_block
usemtl white
v 423.0 330.0 247.0
v 265.0 330.0 296.0
v 314.0 330.0 456.0
v 472.0 330.0 406.0
f -4 -3 -2 -1
usemtl white
v 423.0 0.0 247.0
v 423.0 330.0 247.0
v 472.0 330.0 406.0
v 472.0 0.0 406.0
f -4 -3 -2 -1
v 472.0 0.0 406.0
v 472.0 330.0 406.0
v 314.0 330.0 456.0
v 314.0 0.0 456.0
f -4 -3 -2 -1
v 314.0 0.0 456.0
v 314.0 330.0 456.0
v 265.0 330.0 296.0
v 265.0 0.0 296.0
f -4 -3 -2 -1
v 265.0 0.0 296.0
v 265.0 330.0 296.0
v 423.0 330.0 247.0
v 423.0 0.0 247.0
f -4 -3 -2 -1

View file

@ -1,2 +1,3 @@
pub mod basic_scene; pub mod basic_scene;
pub mod parse_obj;
pub mod triangle_bvh; pub mod triangle_bvh;

View file

@ -0,0 +1,403 @@
use miette::{bail, miette, Context, IntoDiagnostic, LabeledSpan, Result, Severity};
use nom::{
branch::alt,
bytes::complete::{tag, take_till, take_till1},
character,
error::Error,
multi::{fill, many1},
number::complete::double,
Finish, IResult,
};
use ray_tracing_core::prelude::*;
use std::{collections::HashMap, path::Path};
#[derive(Debug)]
pub struct ObjData {
pub vertices: Vec<Pos3>,
pub normals: Vec<Dir3>,
pub texcoord: Vec<[Float; 2]>,
pub faces: Vec<Face>,
pub materials: Vec<ObjMaterial>,
}
#[derive(Debug)]
pub struct ObjMaterial {
name: String,
map: HashMap<String, String>,
}
#[derive(Debug)]
pub struct Face {
pub v: Vec<u32>,
pub t: Option<Vec<u32>>,
pub n: Option<Vec<u32>>,
pub mat: Option<u32>,
}
#[derive(Debug)]
pub struct RelativeFace {
pub v: Vec<i32>,
pub t: Option<Vec<i32>>,
pub n: Option<Vec<i32>>,
}
#[derive(Debug)]
enum Line<'a> {
Vertex(Pos3),
Normal(Dir3),
Texcoord([Float; 2]),
Face(RelativeFace),
Material(&'a str),
Mtllib(&'a str),
Empty,
}
fn remove_whitespace(i: &str) -> IResult<&str, ()> {
let (i, _) = take_till(|c| c != ' ')(i)?;
Ok((i, ()))
}
fn parse_float(i: &str) -> IResult<&str, Float> {
let (i, _) = remove_whitespace(i)?;
double(i).map(|(i, f)| (i, f as Float))
}
fn parse_vertex(i: &str) -> IResult<&str, Line> {
let mut v = [0.0; 3];
let (i, _) = fill(parse_float, &mut v)(i)?;
Ok((i, Line::Vertex(Pos3::new(v[0], v[1], v[2]))))
}
fn parse_normal(i: &str) -> IResult<&str, Line> {
let mut v = [0.0; 3];
let (i, _) = fill(parse_float, &mut v)(i)?;
Ok((i, Line::Normal(Dir3::new(v[0], v[1], v[2]))))
}
fn parse_texcoord(i: &str) -> IResult<&str, Line> {
let mut v = [0.0; 2];
let (i, _) = fill(parse_float, &mut v)(i)?;
Ok((i, Line::Texcoord(v)))
}
fn parse_identifier(i: &str) -> IResult<&str, &str> {
let (i, ()) = remove_whitespace(i)?;
alt((tag("#"), take_till(|c| c == ' ')))(i)
}
fn face_vertex_empty(i: &str) -> IResult<&str, i32> {
let (i, _) = remove_whitespace(i)?;
let (i, v) = character::complete::i32(i)?;
Ok((i, v))
}
fn face_vertex_normal(i: &str) -> IResult<&str, (i32, i32)> {
let (i, _) = remove_whitespace(i)?;
let (i, v) = character::complete::i32(i)?;
let (i, _) = tag("//")(i)?;
let (i, n) = character::complete::i32(i)?;
Ok((i, (v, n)))
}
fn face_vertex_tex(i: &str) -> IResult<&str, (i32, i32)> {
let (i, _) = remove_whitespace(i)?;
let (i, v) = character::complete::i32(i)?;
let (i, _) = tag("/")(i)?;
let (i, t) = character::complete::i32(i)?;
Ok((i, (v, t)))
}
fn face_vertex_normal_tex(i: &str) -> IResult<&str, (i32, i32, i32)> {
let (i, _) = remove_whitespace(i)?;
let (i, v) = character::complete::i32(i)?;
let (i, _) = tag("/")(i)?;
let (i, t) = character::complete::i32(i)?;
let (i, _) = tag("/")(i)?;
let (i, n) = character::complete::i32(i)?;
Ok((i, (v, t, n)))
}
fn parse_face(i: &str) -> IResult<&str, Line> {
if let Ok((i, s)) = many1(face_vertex_normal_tex)(i) {
if s.len() >= 3 {
Ok((
i,
Line::Face(RelativeFace {
v: s.iter().map(|t| t.0).collect(),
t: Some(s.iter().map(|t| t.1).collect()),
n: Some(s.iter().map(|t| t.2).collect()),
}),
))
} else {
Err(nom::Err::Error(Error {
input: i,
code: nom::error::ErrorKind::Tag,
}))
}
} else if let Ok((i, s)) = many1(face_vertex_normal)(i) {
if s.len() >= 3 {
Ok((
i,
Line::Face(RelativeFace {
v: s.iter().map(|t| t.0).collect(),
t: None,
n: Some(s.iter().map(|t| t.1).collect()),
}),
))
} else {
Err(nom::Err::Error(Error {
input: i,
code: nom::error::ErrorKind::Tag,
}))
}
} else if let Ok((i, s)) = many1(face_vertex_tex)(i) {
if s.len() >= 3 {
Ok((
i,
Line::Face(RelativeFace {
v: s.iter().map(|t| t.0).collect(),
t: Some(s.iter().map(|t| t.1).collect()),
n: None,
}),
))
} else {
Err(nom::Err::Error(Error {
input: i,
code: nom::error::ErrorKind::Tag,
}))
}
} else if let Ok((i, s)) = many1(face_vertex_empty)(i) {
if s.len() >= 3 {
Ok((
i,
Line::Face(RelativeFace {
v: s,
t: None,
n: None,
}),
))
} else {
Err(nom::Err::Error(Error {
input: i,
code: nom::error::ErrorKind::Tag,
}))
}
} else {
Err(nom::Err::Error(Error {
input: i,
code: nom::error::ErrorKind::Tag,
}))
}
}
fn parse_mtllib(i: &str) -> IResult<&str, Line> {
let (i, s) = take_till(|c| c == ' ')(i)?;
Ok((i, Line::Mtllib(s)))
}
fn parse_mtl(i: &str) -> IResult<&str, Line> {
let (i, s) = take_till(|c| c == ' ')(i)?;
Ok((i, Line::Material(s)))
}
fn parse_line(i: &str) -> IResult<&str, Line> {
let (i, ident) = parse_identifier(i)?;
let (i, _) = remove_whitespace(i)?;
match ident {
"v" => parse_vertex(i),
"#" | "" => Ok((i, Line::Empty)),
"f" => parse_face(i),
"o" => Ok((i, Line::Empty)),
"vn" => parse_normal(i),
"vt" => parse_texcoord(i),
"usemtl" => parse_mtl(i),
"mtllib" => parse_mtllib(i),
_ => Err(nom::Err::Failure(nom::error::Error {
input: i,
code: nom::error::ErrorKind::Fail,
})),
}
}
fn handle_relative(x: i32, len: i32) -> Result<u32> {
if x == 0 {
Err(miette!("Index cannot be 0"))
} else if x > 0 {
if x <= len {
Ok(x as u32 - 1)
} else {
Err(miette!("Index {x} out of bounds"))
}
} else if len + x >= 0 {
Ok((len + x) as u32)
} else {
Err(miette!("Index {x} out of bounds"))
}
}
enum MaterialsLine<'a> {
Material(&'a str),
KeyValue(&'a str, &'a str),
Empty,
}
fn parse_new_material(i: &str) -> IResult<&str, MaterialsLine> {
let (i, ident) = take_till1(|c| c == ' ')(i)?;
Ok((i, MaterialsLine::Material(ident)))
}
fn parse_line_material(i: &str) -> IResult<&str, MaterialsLine> {
let (i, ident) = parse_identifier(i)?;
let (i, _) = remove_whitespace(i)?;
match ident {
"newmtl" => parse_new_material(i),
"#" | "" => Ok((i, MaterialsLine::Empty)),
_ => Ok((i, MaterialsLine::KeyValue(ident, i))),
}
}
fn read_mtllib(path: impl AsRef<Path>) -> Result<Vec<ObjMaterial>> {
let string = std::fs::read_to_string(path.as_ref())
.into_diagnostic()
.with_context(|| format!("opening file {:?}", path.as_ref()))?;
let mut materials = Vec::new();
let mut current_material = None;
for (i, l) in string.lines().enumerate() {
let t = match parse_line_material(l).finish() {
Ok(t) => t.1,
Err(e) => {
return Err(miette!(
severity = Severity::Error,
code = e.code.description(),
labels = vec![LabeledSpan::at_offset(l.len() - e.input.len(), "here")],
"unable to parse line {}",
i + 1
)
.with_source_code(l.to_string()));
}
};
match t {
MaterialsLine::Material(name) => {
if let Some(m) = current_material.take() {
materials.push(m);
}
current_material = Some(ObjMaterial {
name: name.to_string(),
map: HashMap::new(),
});
}
MaterialsLine::KeyValue(k, v) => {
if let Some(m) = current_material.as_mut() {
m.map.insert(k.to_string(), v.to_string());
} else {
bail!("Material property appears multiple times in line {}", i + 1);
}
}
MaterialsLine::Empty => (),
}
}
if let Some(m) = current_material {
materials.push(m);
}
Ok(materials)
}
impl ObjData {
pub fn new(path: impl AsRef<Path>) -> Result<Self> {
let string = std::fs::read_to_string(path.as_ref())
.into_diagnostic()
.with_context(|| format!("opening file {:?}", path.as_ref()))?;
let mut vertices = Vec::new();
let mut normals = Vec::new();
let mut texcoord = Vec::new();
let mut faces = Vec::new();
let mut materials = Vec::new();
let mut materials_map = HashMap::new();
let mut current_material = None;
for (i, l) in string.lines().enumerate() {
let t = match parse_line(l).finish() {
Ok(t) => t.1,
Err(e) => {
return Err(miette!(
severity = Severity::Error,
code = e.code.description(),
labels = vec![LabeledSpan::at_offset(l.len() - e.input.len(), "here")],
"unable to parse line {}",
i + 1
)
.with_source_code(l.to_string()));
}
};
match t {
Line::Vertex(v) => vertices.push(v),
Line::Normal(n) => normals.push(n),
Line::Texcoord(t) => texcoord.push(t),
Line::Face(f) => faces.push(Face {
v: f.v
.iter()
.map(|&c| {
handle_relative(c, vertices.len() as i32)
.with_context(|| format!("In line {}", i + 1))
})
.collect::<Result<Vec<_>>>()?,
t: f.t
.map(|t| {
t.iter()
.map(|&c| {
handle_relative(c, texcoord.len() as i32)
.with_context(|| format!("In line {}", i + 1))
})
.collect::<Result<Vec<_>>>()
})
.transpose()?,
n: f.n
.map(|t| {
t.iter()
.map(|&c| {
handle_relative(c, normals.len() as i32)
.with_context(|| format!("In line {}", i + 1))
})
.collect::<Result<Vec<_>>>()
})
.transpose()?,
mat: current_material,
}),
Line::Material(s) => {
current_material = Some(
*materials_map
.get(s)
.ok_or(miette!("Unknown material \"{s}\" in line {}", i + 1))?,
);
}
Line::Mtllib(s) => {
for m in read_mtllib(path.as_ref().parent().ok_or(miette!("Unable "))?.join(s))?
{
materials_map.insert(m.name.clone(), materials.len() as u32);
materials.push(m);
}
}
Line::Empty => (),
}
}
Ok(Self {
vertices,
normals,
texcoord,
faces,
materials,
})
}
}