Compare commits
No commits in common. "dbf545107024893436778362684ca69d9a8a3a97" and "5f3bfd744eb310b2ec93143bc1acfca65718a446" have entirely different histories.
dbf5451070
...
5f3bfd744e
257
rtchallenge/Cargo.lock
generated
257
rtchallenge/Cargo.lock
generated
@ -1,35 +1,11 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
|
||||||
name = "addr2line"
|
|
||||||
version = "0.15.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a"
|
|
||||||
dependencies = [
|
|
||||||
"gimli",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "adler"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adler32"
|
name = "adler32"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ansi_term"
|
|
||||||
version = "0.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
|
||||||
dependencies = [
|
|
||||||
"winapi 0.3.9",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.41"
|
version = "1.0.41"
|
||||||
@ -44,7 +20,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"winapi 0.3.9",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -53,21 +29,6 @@ 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 = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "backtrace"
|
|
||||||
version = "0.3.60"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b7815ea54e4d821e791162e078acbebfd6d8c8939cd559c9335dceb1c8ca7282"
|
|
||||||
dependencies = [
|
|
||||||
"addr2line",
|
|
||||||
"cc",
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"miniz_oxide 0.4.4",
|
|
||||||
"object",
|
|
||||||
"rustc-demangle",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -107,12 +68,6 @@ dependencies = [
|
|||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.69"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -125,25 +80,9 @@ version = "2.33.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
|
||||||
"atty",
|
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"strsim",
|
|
||||||
"textwrap",
|
"textwrap",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
"vec_map",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "core_affinity"
|
|
||||||
version = "0.5.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f8a03115cc34fb0d7c321dd154a3914b3ca082ccc5c11d91bf7117dbbe7171f"
|
|
||||||
dependencies = [
|
|
||||||
"kernel32-sys",
|
|
||||||
"libc",
|
|
||||||
"num_cpus",
|
|
||||||
"winapi 0.2.8",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -273,60 +212,12 @@ version = "1.6.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "enum-utils"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed327f716d0d351d86c9fd3398d20ee39ad8f681873cc081da2ca1c10fed398a"
|
|
||||||
dependencies = [
|
|
||||||
"enum-utils-from-str",
|
|
||||||
"failure",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"serde_derive_internals",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "enum-utils-from-str"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d49be08bad6e4ca87b2b8e74146987d4e5cb3b7512efa50ef505b51a22227ee1"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "failure"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
|
||||||
dependencies = [
|
|
||||||
"backtrace",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gimli"
|
|
||||||
version = "0.24.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "1.7.1"
|
version = "1.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
|
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "heck"
|
|
||||||
version = "0.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-segmentation",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
@ -369,16 +260,6 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "kernel32-sys"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
|
||||||
dependencies = [
|
|
||||||
"winapi 0.2.8",
|
|
||||||
"winapi-build",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -424,16 +305,6 @@ dependencies = [
|
|||||||
"adler32",
|
"adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "miniz_oxide"
|
|
||||||
version = "0.4.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
|
||||||
dependencies = [
|
|
||||||
"adler",
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
@ -453,15 +324,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "object"
|
|
||||||
version = "0.25.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oorandom"
|
name = "oorandom"
|
||||||
version = "11.1.3"
|
version = "11.1.3"
|
||||||
@ -505,31 +367,7 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"deflate",
|
"deflate",
|
||||||
"miniz_oxide 0.3.7",
|
"miniz_oxide",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-error"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-error-attr",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-error-attr"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"version_check",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -601,24 +439,11 @@ name = "rtchallenge"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"core_affinity",
|
|
||||||
"criterion",
|
"criterion",
|
||||||
"enum-utils",
|
|
||||||
"num_cpus",
|
|
||||||
"png",
|
"png",
|
||||||
"rayon",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"structopt",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-demangle"
|
|
||||||
version = "0.1.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -660,9 +485,6 @@ name = "serde"
|
|||||||
version = "1.0.126"
|
version = "1.0.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
|
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
|
||||||
dependencies = [
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_cbor"
|
name = "serde_cbor"
|
||||||
@ -685,17 +507,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive_internals"
|
|
||||||
version = "0.25.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.64"
|
version = "1.0.64"
|
||||||
@ -707,36 +518,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strsim"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "structopt"
|
|
||||||
version = "0.3.22"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "69b041cdcb67226aca307e6e7be44c8806423d83e018bd662360a93dabce4d71"
|
|
||||||
dependencies = [
|
|
||||||
"clap",
|
|
||||||
"lazy_static",
|
|
||||||
"structopt-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "structopt-derive"
|
|
||||||
version = "0.4.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7813934aecf5f51a54775e00068c237de98489463968231a51746bbbc03f9c10"
|
|
||||||
dependencies = [
|
|
||||||
"heck",
|
|
||||||
"proc-macro-error",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.73"
|
version = "1.0.73"
|
||||||
@ -787,12 +568,6 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-segmentation"
|
|
||||||
version = "1.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
@ -805,18 +580,6 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "vec_map"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "version_check"
|
|
||||||
version = "0.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
@ -824,7 +587,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file",
|
"same-file",
|
||||||
"winapi 0.3.9",
|
"winapi",
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -892,12 +655,6 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@ -908,12 +665,6 @@ dependencies = [
|
|||||||
"winapi-x86_64-pc-windows-gnu",
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-build"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -926,7 +677,7 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@ -6,26 +6,13 @@ edition = "2018"
|
|||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[features]
|
|
||||||
disable_inverse_cache = []
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.41"
|
anyhow = "1.0.41"
|
||||||
core_affinity = "0.5.10"
|
|
||||||
criterion = "0.3.4"
|
criterion = "0.3.4"
|
||||||
enum-utils = "0.1.2"
|
|
||||||
num_cpus = "1.13.0"
|
|
||||||
png = "0.16.8"
|
png = "0.16.8"
|
||||||
rayon = "1.5.1"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0.64"
|
|
||||||
structopt = "0.3.22"
|
|
||||||
thiserror = "1.0.25"
|
thiserror = "1.0.25"
|
||||||
|
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "matrices"
|
name = "matrices"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
debug = true
|
|
||||||
|
|||||||
@ -20,9 +20,8 @@ fn main() -> Result<()> {
|
|||||||
let half = wall_size / 2.;
|
let half = wall_size / 2.;
|
||||||
let color = Color::new(1., 0., 0.);
|
let color = Color::new(1., 0., 0.);
|
||||||
let mut shape = Sphere::default();
|
let mut shape = Sphere::default();
|
||||||
shape.set_transform(
|
shape.transform =
|
||||||
Matrix4x4::shearing(1., 0., 0., 0., 0., 0.) * Matrix4x4::scaling(0.5, 1., 1.0),
|
Matrix4x4::shearing(1., 0., 0., 0., 0., 0.) * Matrix4x4::scaling(0.5, 1., 1.0);
|
||||||
);
|
|
||||||
|
|
||||||
for y in 0..h {
|
for y in 0..h {
|
||||||
let world_y = half - pixel_size * y as f32;
|
let world_y = half - pixel_size * y as f32;
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
use std::{f32::consts::PI, time::Instant};
|
use std::{f32::consts::PI, time::Instant};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use structopt::StructOpt;
|
|
||||||
|
|
||||||
use rtchallenge::{
|
use rtchallenge::{
|
||||||
camera::{Camera, RenderStrategy},
|
camera::Camera,
|
||||||
lights::PointLight,
|
lights::PointLight,
|
||||||
materials::Material,
|
materials::Material,
|
||||||
matrices::Matrix4x4,
|
matrices::Matrix4x4,
|
||||||
@ -15,19 +14,10 @@ use rtchallenge::{
|
|||||||
WHITE,
|
WHITE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// End of chapter 7 challenge.
|
|
||||||
#[derive(StructOpt, Debug)]
|
|
||||||
#[structopt(name = "eoc7")]
|
|
||||||
struct Opt {
|
|
||||||
#[structopt(long, default_value = "rayon")]
|
|
||||||
render_strategy: RenderStrategy,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let opt = Opt::from_args();
|
let width = 640;
|
||||||
let width = 1024;
|
let height = 480;
|
||||||
let height = 1024;
|
|
||||||
let light_position = Tuple::point(-10., 10., -10.);
|
let light_position = Tuple::point(-10., 10., -10.);
|
||||||
let light_color = WHITE;
|
let light_color = WHITE;
|
||||||
let light = PointLight::new(light_position, light_color);
|
let light = PointLight::new(light_position, light_color);
|
||||||
@ -35,11 +25,10 @@ fn main() -> Result<()> {
|
|||||||
let from = Tuple::point(0., 1.5, -5.);
|
let from = Tuple::point(0., 1.5, -5.);
|
||||||
let to = Tuple::point(0., 1., 0.);
|
let to = Tuple::point(0., 1., 0.);
|
||||||
let up = Tuple::point(0., 1., 0.);
|
let up = Tuple::point(0., 1., 0.);
|
||||||
camera.set_transform(view_transform(from, to, up));
|
camera.transform = view_transform(from, to, up);
|
||||||
camera.render_strategy = opt.render_strategy;
|
|
||||||
|
|
||||||
let mut floor = Sphere::default();
|
let mut floor = Sphere::default();
|
||||||
floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.));
|
floor.transform = Matrix4x4::scaling(10., 0.01, 10.);
|
||||||
floor.material = Material {
|
floor.material = Material {
|
||||||
color: Color::new(1., 0.9, 0.9),
|
color: Color::new(1., 0.9, 0.9),
|
||||||
specular: 0.,
|
specular: 0.,
|
||||||
@ -47,25 +36,21 @@ fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut left_wall = Sphere::default();
|
let mut left_wall = Sphere::default();
|
||||||
left_wall.set_transform(
|
left_wall.transform = Matrix4x4::translation(0., 0., 5.)
|
||||||
Matrix4x4::translation(0., 0., 5.)
|
|
||||||
* Matrix4x4::rotation_y(-PI / 4.)
|
* Matrix4x4::rotation_y(-PI / 4.)
|
||||||
* Matrix4x4::rotation_x(PI / 2.)
|
* Matrix4x4::rotation_x(PI / 2.)
|
||||||
* Matrix4x4::scaling(10., 0.01, 10.),
|
* Matrix4x4::scaling(10., 0.01, 10.);
|
||||||
);
|
|
||||||
left_wall.material = floor.material.clone();
|
left_wall.material = floor.material.clone();
|
||||||
|
|
||||||
let mut right_wall = Sphere::default();
|
let mut right_wall = Sphere::default();
|
||||||
right_wall.set_transform(
|
right_wall.transform = Matrix4x4::translation(0., 0., 5.)
|
||||||
Matrix4x4::translation(0., 0., 5.)
|
|
||||||
* Matrix4x4::rotation_y(PI / 4.)
|
* Matrix4x4::rotation_y(PI / 4.)
|
||||||
* Matrix4x4::rotation_x(PI / 2.)
|
* Matrix4x4::rotation_x(PI / 2.)
|
||||||
* Matrix4x4::scaling(10., 0.01, 10.),
|
* Matrix4x4::scaling(10., 0.01, 10.);
|
||||||
);
|
|
||||||
right_wall.material = floor.material.clone();
|
right_wall.material = floor.material.clone();
|
||||||
|
|
||||||
let mut middle = Sphere::default();
|
let mut middle = Sphere::default();
|
||||||
middle.set_transform(Matrix4x4::translation(-0.5, 1., 0.5));
|
middle.transform = Matrix4x4::translation(-0.5, 1., 0.5);
|
||||||
middle.material = Material {
|
middle.material = Material {
|
||||||
color: Color::new(0.1, 1., 0.5),
|
color: Color::new(0.1, 1., 0.5),
|
||||||
diffuse: 0.7,
|
diffuse: 0.7,
|
||||||
@ -74,7 +59,7 @@ fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut right = Sphere::default();
|
let mut right = Sphere::default();
|
||||||
right.set_transform(Matrix4x4::translation(1.5, 0.5, -0.5) * Matrix4x4::scaling(0.5, 0.5, 0.5));
|
right.transform = Matrix4x4::translation(1.5, 0.5, -0.5) * Matrix4x4::scaling(0.5, 0.5, 0.5);
|
||||||
right.material = Material {
|
right.material = Material {
|
||||||
color: Color::new(0.5, 1., 0.1),
|
color: Color::new(0.5, 1., 0.1),
|
||||||
diffuse: 0.7,
|
diffuse: 0.7,
|
||||||
@ -83,9 +68,8 @@ fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut left = Sphere::default();
|
let mut left = Sphere::default();
|
||||||
left.set_transform(
|
left.transform =
|
||||||
Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33),
|
Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33);
|
||||||
);
|
|
||||||
left.material = Material {
|
left.material = Material {
|
||||||
color: Color::new(1., 0.8, 0.1),
|
color: Color::new(1., 0.8, 0.1),
|
||||||
diffuse: 0.7,
|
diffuse: 0.7,
|
||||||
@ -102,6 +86,6 @@ fn main() -> Result<()> {
|
|||||||
let path = "/tmp/eoc7.png";
|
let path = "/tmp/eoc7.png";
|
||||||
println!("saving output to {}", path);
|
println!("saving output to {}", path);
|
||||||
image.write_to_file(path)?;
|
image.write_to_file(path)?;
|
||||||
println!("Render time {:.3} seconds", start.elapsed().as_secs_f32());
|
println!("Render time {:.2} seconds", start.elapsed().as_secs_f32());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,51 +1,13 @@
|
|||||||
use std::{
|
|
||||||
str::FromStr,
|
|
||||||
sync::{
|
|
||||||
mpsc::{sync_channel, Receiver, SyncSender},
|
|
||||||
{Arc, Mutex},
|
|
||||||
},
|
|
||||||
thread,
|
|
||||||
};
|
|
||||||
|
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
|
||||||
use serde::Deserialize;
|
|
||||||
use structopt::StructOpt;
|
|
||||||
|
|
||||||
use crate::{canvas::Canvas, matrices::Matrix4x4, rays::Ray, tuples::Tuple, world::World, BLACK};
|
use crate::{canvas::Canvas, matrices::Matrix4x4, rays::Ray, tuples::Tuple, world::World, BLACK};
|
||||||
|
|
||||||
#[derive(Copy, Clone, StructOpt, Debug, Deserialize)]
|
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
pub enum RenderStrategy {
|
|
||||||
Serial,
|
|
||||||
Rayon,
|
|
||||||
WorkerPool,
|
|
||||||
}
|
|
||||||
impl FromStr for RenderStrategy {
|
|
||||||
type Err = serde_json::error::Error;
|
|
||||||
fn from_str(s: &str) -> Result<RenderStrategy, serde_json::error::Error> {
|
|
||||||
Ok(serde_json::from_str(&format!("\"{}\"", s))?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
hsize: usize,
|
hsize: usize,
|
||||||
vsize: usize,
|
vsize: usize,
|
||||||
field_of_view: f32,
|
field_of_view: f32,
|
||||||
transform: Matrix4x4,
|
pub transform: Matrix4x4,
|
||||||
inverse_transform: Matrix4x4,
|
|
||||||
pixel_size: f32,
|
pixel_size: f32,
|
||||||
half_width: f32,
|
half_width: f32,
|
||||||
half_height: f32,
|
half_height: f32,
|
||||||
pub render_strategy: RenderStrategy,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Request {
|
|
||||||
Line { width: usize, y: usize },
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Response {
|
|
||||||
Line { y: usize, pixels: Canvas },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Camera {
|
impl Camera {
|
||||||
@ -88,11 +50,9 @@ impl Camera {
|
|||||||
vsize,
|
vsize,
|
||||||
field_of_view,
|
field_of_view,
|
||||||
transform: Matrix4x4::identity(),
|
transform: Matrix4x4::identity(),
|
||||||
inverse_transform: Matrix4x4::identity(),
|
|
||||||
pixel_size,
|
pixel_size,
|
||||||
half_height,
|
half_height,
|
||||||
half_width,
|
half_width,
|
||||||
render_strategy: RenderStrategy::WorkerPool,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn hsize(&self) -> usize {
|
pub fn hsize(&self) -> usize {
|
||||||
@ -107,10 +67,6 @@ impl Camera {
|
|||||||
pub fn transform(&self) -> Matrix4x4 {
|
pub fn transform(&self) -> Matrix4x4 {
|
||||||
self.transform
|
self.transform
|
||||||
}
|
}
|
||||||
pub fn set_transform(&mut self, t: Matrix4x4) {
|
|
||||||
self.transform = t;
|
|
||||||
self.inverse_transform = t.inverse();
|
|
||||||
}
|
|
||||||
pub fn pixel_size(&self) -> f32 {
|
pub fn pixel_size(&self) -> f32 {
|
||||||
self.pixel_size
|
self.pixel_size
|
||||||
}
|
}
|
||||||
@ -138,7 +94,7 @@ impl Camera {
|
|||||||
///
|
///
|
||||||
/// // Constructing a ray when the camera is transformed.
|
/// // Constructing a ray when the camera is transformed.
|
||||||
/// let mut c = Camera::new(201, 101, PI / 2.);
|
/// let mut c = Camera::new(201, 101, PI / 2.);
|
||||||
/// c.set_transform(Matrix4x4::rotation_y(PI / 4.) * Matrix4x4::translation(0., -2., 5.));
|
/// c.transform = Matrix4x4::rotation_y(PI / 4.) * Matrix4x4::translation(0., -2., 5.);
|
||||||
/// let r = c.ray_for_pixel(100, 50);
|
/// let r = c.ray_for_pixel(100, 50);
|
||||||
/// assert_eq!(r.origin, Tuple::point(0., 2., -5.));
|
/// assert_eq!(r.origin, Tuple::point(0., 2., -5.));
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
@ -146,7 +102,6 @@ impl Camera {
|
|||||||
/// Tuple::vector(2_f32.sqrt() / 2., 0., -2_f32.sqrt() / 2.)
|
/// Tuple::vector(2_f32.sqrt() / 2., 0., -2_f32.sqrt() / 2.)
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "disable_inverse_cache"))]
|
|
||||||
pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray {
|
pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray {
|
||||||
// The offset from the edge of the canvas to the pixel's corner.
|
// The offset from the edge of the canvas to the pixel's corner.
|
||||||
let xoffset = (px as f32 + 0.5) * self.pixel_size;
|
let xoffset = (px as f32 + 0.5) * self.pixel_size;
|
||||||
@ -159,27 +114,7 @@ impl Camera {
|
|||||||
|
|
||||||
// Using the camera matrix, transofmrm the canvas point and the origin,
|
// Using the camera matrix, transofmrm the canvas point and the origin,
|
||||||
// and then compute the ray's direction vector.
|
// and then compute the ray's direction vector.
|
||||||
// (Remember that the canvas is at z>=-1).
|
// (Remember that the canves is at z>=-1).
|
||||||
let pixel = self.inverse_transform * Tuple::point(world_x, world_y, -1.);
|
|
||||||
let origin = self.inverse_transform * Tuple::point(0., 0., 0.);
|
|
||||||
let direction = (pixel - origin).normalize();
|
|
||||||
|
|
||||||
Ray::new(origin, direction)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "disable_inverse_cache")]
|
|
||||||
pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray {
|
|
||||||
// The offset from the edge of the canvas to the pixel's corner.
|
|
||||||
let xoffset = (px as f32 + 0.5) * self.pixel_size;
|
|
||||||
let yoffset = (py as f32 + 0.5) * self.pixel_size;
|
|
||||||
|
|
||||||
// The untransformed coordinates of the pixle in world space.
|
|
||||||
// (Remember that the camera looks toward -z, so +x is to the left.)
|
|
||||||
let world_x = self.half_width - xoffset;
|
|
||||||
let world_y = self.half_height - yoffset;
|
|
||||||
|
|
||||||
// Using the camera matrix, transofmrm the canvas point and the origin,
|
|
||||||
// and then compute the ray's direction vector.
|
|
||||||
// (Remember that the canvas is at z>=-1).
|
|
||||||
let pixel = self.transform.inverse() * Tuple::point(world_x, world_y, -1.);
|
let pixel = self.transform.inverse() * Tuple::point(world_x, world_y, -1.);
|
||||||
let origin = self.transform.inverse() * Tuple::point(0., 0., 0.);
|
let origin = self.transform.inverse() * Tuple::point(0., 0., 0.);
|
||||||
let direction = (pixel - origin).normalize();
|
let direction = (pixel - origin).normalize();
|
||||||
@ -188,6 +123,7 @@ impl Camera {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Use camera to render an image of the given world.
|
/// Use camera to render an image of the given world.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::f32::consts::PI;
|
/// use std::f32::consts::PI;
|
||||||
@ -205,116 +141,11 @@ impl Camera {
|
|||||||
/// let from = Tuple::point(0., 0., -5.);
|
/// let from = Tuple::point(0., 0., -5.);
|
||||||
/// let to = Tuple::point(0., 0., 0.);
|
/// let to = Tuple::point(0., 0., 0.);
|
||||||
/// let up = Tuple::vector(0., 1., 0.);
|
/// let up = Tuple::vector(0., 1., 0.);
|
||||||
/// c.set_transform(view_transform(from, to, up));
|
/// c.transform = view_transform(from, to, up);
|
||||||
/// let image = c.render(&w);
|
/// let image = c.render(&w);
|
||||||
/// assert_eq!(image.get(5, 5), Color::new(0.38066, 0.47583, 0.2855));
|
/// assert_eq!(image.get(5, 5), Color::new(0.38066, 0.47583, 0.2855));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn render(&self, w: &World) -> Canvas {
|
pub fn render(&self, w: &World) -> Canvas {
|
||||||
use RenderStrategy::*;
|
|
||||||
|
|
||||||
match self.render_strategy {
|
|
||||||
Serial => self.render_serial(w),
|
|
||||||
Rayon => self.render_parallel_rayon(w),
|
|
||||||
WorkerPool => self.render_parallel_one_tread_per_core(w),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This render function spins up one thread per core, and pins the thread
|
|
||||||
/// to the core. It then sends work requests to the worker threads,
|
|
||||||
/// requesting a full line of the image by rendered. The main thread
|
|
||||||
/// collects results and stores them in the canvas returned to the user.
|
|
||||||
fn render_parallel_one_tread_per_core(&self, world: &World) -> Canvas {
|
|
||||||
let mut image = Canvas::new(self.hsize, self.vsize, BLACK);
|
|
||||||
let num_threads = num_cpus::get();
|
|
||||||
let (pixel_req_tx, pixel_req_rx) = sync_channel(2 * num_threads);
|
|
||||||
let (pixel_resp_tx, pixel_resp_rx) = sync_channel(2 * num_threads);
|
|
||||||
let pixel_req_rx = Arc::new(Mutex::new(pixel_req_rx));
|
|
||||||
|
|
||||||
// Create copy of world and camera we can share with all workers.
|
|
||||||
// It's probably okay to clone camera, but world could get large (think
|
|
||||||
// textures and high poly count models).
|
|
||||||
// TODO(wathiede): prevent second copy of world when they start getting
|
|
||||||
// large.
|
|
||||||
let world = Arc::new(world.clone());
|
|
||||||
let camera = Arc::new(self.clone());
|
|
||||||
|
|
||||||
let core_ids = core_affinity::get_core_ids().unwrap();
|
|
||||||
println!("Creating {} render threads", core_ids.len());
|
|
||||||
// Create a worker thread for each CPU core and pin the thread to the core.
|
|
||||||
let mut handles = core_ids
|
|
||||||
.into_iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, id)| {
|
|
||||||
let w = Arc::clone(&world);
|
|
||||||
let c = Arc::clone(&camera);
|
|
||||||
let pixel_req_rx = pixel_req_rx.clone();
|
|
||||||
let pixel_resp_tx = pixel_resp_tx.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
core_affinity::set_for_current(id);
|
|
||||||
render_worker(i, &c, &w, pixel_req_rx, &pixel_resp_tx);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
drop(pixel_req_rx);
|
|
||||||
drop(pixel_resp_tx);
|
|
||||||
|
|
||||||
// Send render requests over channels to worker threads.
|
|
||||||
let (w, h) = (camera.hsize, camera.vsize);
|
|
||||||
handles.push(thread::spawn(move || {
|
|
||||||
for y in 0..h {
|
|
||||||
pixel_req_tx
|
|
||||||
.send(Request::Line { width: w, y })
|
|
||||||
.expect("failed to send line request");
|
|
||||||
}
|
|
||||||
drop(pixel_req_tx);
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Read responses from channel and blit image data.
|
|
||||||
for resp in pixel_resp_rx {
|
|
||||||
match resp {
|
|
||||||
Response::Line { y, pixels } => {
|
|
||||||
for x in 0..camera.hsize {
|
|
||||||
image.set(x, y, pixels.get(x, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for all the threads to exit.
|
|
||||||
for thr in handles {
|
|
||||||
thr.join().expect("thread join");
|
|
||||||
}
|
|
||||||
image
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This renderer use rayon to split each row into a seperate thread. It
|
|
||||||
/// seems to have really bad performance (only ~6x speedup over serial), and
|
|
||||||
/// the flame graph looks a mess. A strength over
|
|
||||||
/// `render_parallel_one_tread_per_core` is that it doesn't require `Camera`
|
|
||||||
/// and `World` to be cloneable.
|
|
||||||
fn render_parallel_rayon(&self, w: &World) -> Canvas {
|
|
||||||
let image_mu = Mutex::new(Canvas::new(self.hsize, self.vsize, BLACK));
|
|
||||||
|
|
||||||
(0..self.vsize).into_par_iter().for_each(|y| {
|
|
||||||
let mut row_image = Canvas::new(self.hsize, 1, BLACK);
|
|
||||||
for x in 0..self.hsize {
|
|
||||||
let ray = self.ray_for_pixel(x, y);
|
|
||||||
let color = w.color_at(&ray);
|
|
||||||
row_image.set(x, 0, color);
|
|
||||||
}
|
|
||||||
// TODO(wathiede): create a row based setter for memcpying the row as a whole.
|
|
||||||
let mut image = image_mu.lock().expect("failed to lock image mutex");
|
|
||||||
for x in 0..self.hsize {
|
|
||||||
image.set(x, y, row_image.get(x, 0));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
image_mu
|
|
||||||
.into_inner()
|
|
||||||
.expect("failed to get image out of mutex")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reference render implementation from the book. Single threaded, nothing fancy.
|
|
||||||
fn render_serial(&self, w: &World) -> Canvas {
|
|
||||||
let mut image = Canvas::new(self.hsize, self.vsize, BLACK);
|
let mut image = Canvas::new(self.hsize, self.vsize, BLACK);
|
||||||
for y in 0..self.vsize {
|
for y in 0..self.vsize {
|
||||||
for x in 0..self.hsize {
|
for x in 0..self.hsize {
|
||||||
@ -326,34 +157,3 @@ impl Camera {
|
|||||||
image
|
image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_worker(
|
|
||||||
tid: usize,
|
|
||||||
c: &Camera,
|
|
||||||
w: &World,
|
|
||||||
input_chan: Arc<Mutex<Receiver<Request>>>,
|
|
||||||
output_chan: &SyncSender<Response>,
|
|
||||||
) {
|
|
||||||
loop {
|
|
||||||
let job = { input_chan.lock().unwrap().recv() };
|
|
||||||
match job {
|
|
||||||
Err(err) => {
|
|
||||||
eprintln!("Shutting down render_worker {}: {}", tid, err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Ok(req) => match req {
|
|
||||||
Request::Line { width, y } => {
|
|
||||||
let mut pixels = Canvas::new(width, 1, BLACK);
|
|
||||||
for x in 0..width {
|
|
||||||
let ray = c.ray_for_pixel(x, y);
|
|
||||||
let color = w.color_at(&ray);
|
|
||||||
pixels.set(x, 0, color);
|
|
||||||
}
|
|
||||||
output_chan
|
|
||||||
.send(Response::Line { y, pixels })
|
|
||||||
.expect("failed to send pixel response");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::tuples::{Color, Tuple};
|
use crate::tuples::{Color, Tuple};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct PointLight {
|
pub struct PointLight {
|
||||||
pub position: Tuple,
|
pub position: Tuple,
|
||||||
pub intensity: Color,
|
pub intensity: Color,
|
||||||
|
|||||||
@ -6,12 +6,11 @@ use crate::{
|
|||||||
tuples::{dot, Tuple},
|
tuples::{dot, Tuple},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq)]
|
||||||
/// Sphere represents the unit-sphere (radius of unit 1.) at the origin 0., 0., 0.
|
/// Sphere represents the unit-sphere (radius of unit 1.) at the origin 0., 0., 0.
|
||||||
pub struct Sphere {
|
pub struct Sphere {
|
||||||
// TODO(wathiede): cache inverse to speed up intersect.
|
// TODO(wathiede): cache inverse to speed up intersect.
|
||||||
transform: Matrix4x4,
|
pub transform: Matrix4x4,
|
||||||
inverse_transform: Matrix4x4,
|
|
||||||
pub material: Material,
|
pub material: Material,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,13 +21,13 @@ impl Default for Sphere {
|
|||||||
///
|
///
|
||||||
/// // A sphere's default transform is the identity matrix.
|
/// // A sphere's default transform is the identity matrix.
|
||||||
/// let s = Sphere::default();
|
/// let s = Sphere::default();
|
||||||
/// assert_eq!(s.transform(), Matrix4x4::identity());
|
/// assert_eq!(s.transform, Matrix4x4::identity());
|
||||||
///
|
///
|
||||||
/// // It can be changed by directly setting the transform member.
|
/// // It can be changed by directly setting the transform member.
|
||||||
/// let mut s = Sphere::default();
|
/// let mut s = Sphere::default();
|
||||||
/// let t = Matrix4x4::translation(2., 3., 4.);
|
/// let t = Matrix4x4::translation(2., 3., 4.);
|
||||||
/// s.set_transform ( t.clone());
|
/// s.transform = t.clone();
|
||||||
/// assert_eq!(s.transform(), t);
|
/// assert_eq!(s.transform, t);
|
||||||
///
|
///
|
||||||
/// // Default Sphere has the default material.
|
/// // Default Sphere has the default material.
|
||||||
/// assert_eq!(s.material, Material::default());
|
/// assert_eq!(s.material, Material::default());
|
||||||
@ -43,7 +42,6 @@ impl Default for Sphere {
|
|||||||
fn default() -> Sphere {
|
fn default() -> Sphere {
|
||||||
Sphere {
|
Sphere {
|
||||||
transform: Matrix4x4::identity(),
|
transform: Matrix4x4::identity(),
|
||||||
inverse_transform: Matrix4x4::identity(),
|
|
||||||
material: Material::default(),
|
material: Material::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +91,7 @@ impl Sphere {
|
|||||||
///
|
///
|
||||||
/// // Compute the normal on a translated sphere.
|
/// // Compute the normal on a translated sphere.
|
||||||
/// let mut s = Sphere::default();
|
/// let mut s = Sphere::default();
|
||||||
/// s.set_transform ( Matrix4x4::translation(0., 1., 0.));
|
/// s.transform = Matrix4x4::translation(0., 1., 0.);
|
||||||
/// let n = s.normal_at(Tuple::point(0., 1.70711, -0.70711));
|
/// let n = s.normal_at(Tuple::point(0., 1.70711, -0.70711));
|
||||||
/// assert_eq!(n, Tuple::vector(0., 0.70711, -0.70711));
|
/// assert_eq!(n, Tuple::vector(0., 0.70711, -0.70711));
|
||||||
|
|
||||||
@ -101,19 +99,10 @@ impl Sphere {
|
|||||||
/// use std::f32::consts::PI;
|
/// use std::f32::consts::PI;
|
||||||
///
|
///
|
||||||
/// let mut s = Sphere::default();
|
/// let mut s = Sphere::default();
|
||||||
/// s.set_transform ( Matrix4x4::scaling(1.,0.5,1.) * Matrix4x4::rotation_z(PI/5.));
|
/// s.transform = Matrix4x4::scaling(1.,0.5,1.) * Matrix4x4::rotation_z(PI/5.);
|
||||||
/// let n = s.normal_at(Tuple::point(0., 2_f32.sqrt()/2., -2_f32.sqrt()/2.));
|
/// let n = s.normal_at(Tuple::point(0., 2_f32.sqrt()/2., -2_f32.sqrt()/2.));
|
||||||
/// assert_eq!(n, Tuple::vector(0., 0.97014, -0.24254));
|
/// assert_eq!(n, Tuple::vector(0., 0.97014, -0.24254));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "disable_inverse_cache"))]
|
|
||||||
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
|
|
||||||
let object_point = self.inverse_transform * world_point;
|
|
||||||
let object_normal = object_point - Tuple::point(0., 0., 0.);
|
|
||||||
let mut world_normal = self.inverse_transform.transpose() * object_normal;
|
|
||||||
world_normal.w = 0.;
|
|
||||||
world_normal.normalize()
|
|
||||||
}
|
|
||||||
#[cfg(feature = "disable_inverse_cache")]
|
|
||||||
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
|
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
|
||||||
let object_point = self.transform.inverse() * world_point;
|
let object_point = self.transform.inverse() * world_point;
|
||||||
let object_normal = object_point - Tuple::point(0., 0., 0.);
|
let object_normal = object_point - Tuple::point(0., 0., 0.);
|
||||||
@ -121,14 +110,6 @@ impl Sphere {
|
|||||||
world_normal.w = 0.;
|
world_normal.w = 0.;
|
||||||
world_normal.normalize()
|
world_normal.normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform(&self) -> Matrix4x4 {
|
|
||||||
self.transform
|
|
||||||
}
|
|
||||||
pub fn set_transform(&mut self, t: Matrix4x4) {
|
|
||||||
self.transform = t;
|
|
||||||
self.inverse_transform = t.inverse();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Intersect a ray with a sphere.
|
/// Intersect a ray with a sphere.
|
||||||
@ -179,7 +160,7 @@ impl Sphere {
|
|||||||
/// // Intersect a scaled sphere with a ray.
|
/// // Intersect a scaled sphere with a ray.
|
||||||
/// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.));
|
/// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.));
|
||||||
/// let mut s = Sphere::default();
|
/// let mut s = Sphere::default();
|
||||||
/// s.set_transform(Matrix4x4::scaling(2., 2., 2.));
|
/// s.transform = Matrix4x4::scaling(2., 2., 2.);
|
||||||
/// let xs = intersect(&s, &r);
|
/// let xs = intersect(&s, &r);
|
||||||
/// assert_eq!(xs.len(), 2, "xs {:?}", xs);
|
/// assert_eq!(xs.len(), 2, "xs {:?}", xs);
|
||||||
/// assert_eq!(xs[0].t, 3., "xs {:?}", xs);
|
/// assert_eq!(xs[0].t, 3., "xs {:?}", xs);
|
||||||
@ -188,12 +169,12 @@ impl Sphere {
|
|||||||
/// // Intersect a translated sphere with a ray.
|
/// // Intersect a translated sphere with a ray.
|
||||||
/// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.));
|
/// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.));
|
||||||
/// let mut s = Sphere::default();
|
/// let mut s = Sphere::default();
|
||||||
/// s.set_transform(Matrix4x4::translation(5., 0., 0.));
|
/// s.transform = Matrix4x4::translation(5., 0., 0.);
|
||||||
/// let xs = intersect(&s, &r);
|
/// let xs = intersect(&s, &r);
|
||||||
/// assert_eq!(xs.len(), 0);
|
/// assert_eq!(xs.len(), 0);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn intersect<'s>(sphere: &'s Sphere, ray: &Ray) -> Intersections<'s> {
|
pub fn intersect<'s>(sphere: &'s Sphere, ray: &Ray) -> Intersections<'s> {
|
||||||
let ray = ray.transform(sphere.inverse_transform);
|
let ray = ray.transform(sphere.transform.inverse());
|
||||||
let sphere_to_ray = ray.origin - Tuple::point(0., 0., 0.);
|
let sphere_to_ray = ray.origin - Tuple::point(0., 0., 0.);
|
||||||
let a = dot(ray.direction, ray.direction);
|
let a = dot(ray.direction, ray.direction);
|
||||||
let b = 2. * dot(ray.direction, sphere_to_ray);
|
let b = 2. * dot(ray.direction, sphere_to_ray);
|
||||||
|
|||||||
@ -20,7 +20,7 @@ use crate::{
|
|||||||
/// assert_eq!(w.light, None);
|
/// assert_eq!(w.light, None);
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct World {
|
pub struct World {
|
||||||
// TODO(wathiede): make this a list of abstract Light traits.
|
// TODO(wathiede): make this a list of abstract Light traits.
|
||||||
pub light: Option<PointLight>,
|
pub light: Option<PointLight>,
|
||||||
@ -48,7 +48,7 @@ impl World {
|
|||||||
..Material::default()
|
..Material::default()
|
||||||
};
|
};
|
||||||
let mut s2 = Sphere::default();
|
let mut s2 = Sphere::default();
|
||||||
s2.set_transform(Matrix4x4::scaling(0.5, 0.5, 0.5));
|
s2.transform = Matrix4x4::scaling(0.5, 0.5, 0.5);
|
||||||
World {
|
World {
|
||||||
light: Some(light),
|
light: Some(light),
|
||||||
objects: vec![s1, s2],
|
objects: vec![s1, s2],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user