1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! Photon Garden Raytracer Impementation.
//!
//! Rustic Zen renders artworks from a scene definition by simulating individual
//! photons and tracing their path as they bounce through a 2D. space.
//!
//! Photons are generated by Lights and interact with Objects. Each interaction
//! results in either the photon being absorbed, or being allowed to continue with
//! a new direction, based on the rules defined by the Object's Material.
//!
//! # Example usage:
//! ```
//! extern crate rustic_zen;
//! use rustic_zen::prelude::*;
//! use rustic_zen::material::hqz_legacy;
//! use std::sync::Arc;
//!
//! fn main() {
//!     // Set up constants.
//!     let width: f64 = 1920.0;
//!     let height: f64 = 1080.0;
//!
//!     // Build a basic Material
//!     let m = hqz_legacy(0.3, 0.3, 0.3);
//!
//!     // Build a basic Object
//!     let o = Segment::line_from_points((0.0,(height * 0.75)), (width, (height * 0.75)), m);
//!
//!     // Build a basic Light
//!     let l = Light::new((width / 2.0, height / 2.0), 1.0, 0.0, 0.0, (360.0, 0.0), Sampler::new_blackbody(5800.0));
//!
//!     // Construct a renderer object and add the light and object to it.
//!     let s = Scene::new(width as usize, height as usize).with_object(o).with_light(l);
//!
//!     // Create an image to render into.
//!     let mut i = Arc::new(Image::new(width as usize, height as usize));
//!
//!     // Render Image
//!     println!("Tracing Rays");
//!     let rays = s.render(RenderConstraint::TimeMS(1000), 1, &mut i);
//!     // this call should probably be more like 5000 - 15000 ms and use your number of threads,
//!     // but this example is run by various CI tools, and tests can't take too long.
//!
//!     // Output the Image as a Vec<u8>
//!     println!("Serializing!");
//!     let data = i.to_rgba8(rays, 0.7, 1.2);
//!     
//!     // Do Export to a PNG or whatever you want here.
//! }
//! ```
//!
#![warn(missing_docs)]
pub mod geom;
pub mod image;
pub mod material;
pub mod sampler;
pub mod scene;

/// This prelude contains everything to quickstart using Rustic Zen.
pub mod prelude {
    pub use crate::geom::{Point, Vector};
    pub use crate::image::ExportImage;
    pub use crate::material;
    pub use crate::sampler::Sampler;
    pub use crate::scene::{Light, RenderConstraint, Scene, Segment};

    pub use crate::image::Image;
    #[cfg(feature = "gpu")]
    pub use crate::image::VulkanImage;

    pub use rand::prelude::*;
}

mod ray;
mod spectrum;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }

    // For reading and opening files
    use std::fs::File;
    use std::io::BufWriter;
    use std::path::Path;
    use std::sync::Arc;
    // To use encoder.set()
    use png::HasParameters;

    //Scene Parameters
    use crate::image::ExportImage;
    use crate::image::Image;
    use crate::material::hqz_legacy_default;
    use crate::sampler::Sampler;
    use crate::scene::Light;
    use crate::scene::RenderConstraint;
    use crate::scene::Scene;
    use crate::scene::Segment;

    #[test]
    fn png_test() {
        let width = 1024.0;
        let height = 1024.0;

        let l = Light::new(
            (512.0, 512.0),
            1.0,
            0.0,
            0.0,
            (360.0, 0.0),
            Sampler::new_blackbody(6900.0),
        );

        let r = Scene::new(width as usize, height as usize).with_light(l);

        let mut image = Arc::new(Image::new(width as usize, height as usize));

        let rays = r.render(RenderConstraint::TimeMS(1000), 1, &mut image);

        let data = image.to_rgba8(rays, 0.5, 0.5);
        //let data = image.dumb_to_rgb8();

        let path = Path::new(r"lib.png_test.png");
        let file = File::create(path).unwrap();
        let ref mut w = BufWriter::new(file);

        let mut encoder = png::Encoder::new(w, 1024, 1024);
        encoder.set(png::ColorType::RGBA).set(png::BitDepth::Eight);
        let mut writer = encoder.write_header().unwrap();
        writer.write_image_data(&data).unwrap(); // Save
    }

    #[test]
    fn png_test_2() {
        let width: f64 = 1024.0;
        let height: f64 = 1024.0;

        let o = Segment::line_from_points(
            (0.0, height * 0.75),
            (width, height * 0.75),
            hqz_legacy_default(),
        );

        let l = Light::new(
            (width / 2.0, height / 2.0),
            1.0,
            0.0,
            0.0,
            (360.0, 0.0),
            Sampler::new_blackbody(6900.0),
        );

        let r = Scene::new(width as usize, height as usize)
            .with_light(l)
            .with_object(o);

        let mut image = Arc::new(Image::new(width as usize, height as usize));

        let rays = r.render(RenderConstraint::TimeMS(1000), 2, &mut image);

        let data = image.to_rgba8(rays, 0.5, 0.5);

        let path = Path::new(r"lib.png_test_2.png");
        let file = File::create(path).unwrap();
        let ref mut w = BufWriter::new(file);

        let mut encoder = png::Encoder::new(w, 1024, 1024);
        encoder.set(png::ColorType::RGBA).set(png::BitDepth::Eight);
        let mut writer = encoder.write_header().unwrap();
        writer.write_image_data(&data).unwrap(); // Save
    }
}