<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

/// Builds a `RenderPass` object whose template parameter is of indeterminate type.
#[macro_export]
macro_rules! single_pass_renderpass {
    (
        $device:expr,
        attachments: { $($a:tt)* },
        pass: {
            color: [$($color_atch:ident),*],
            depth_stencil: {$($depth_atch:ident)*}$(,)*
            $(resolve: [$($resolve_atch:ident),*])*$(,)*
        }
    ) => (
        ordered_passes_renderpass!(
            $device,
            attachments: { $($a)* },
            passes: [
                {
                    color: [$($color_atch),*],
                    depth_stencil: {$($depth_atch)*},
                    input: [],
                    resolve: [$($($resolve_atch),*)*]
                }
            ]
        )
    )
}

/// Builds a `RenderPass` object whose template parameter is of indeterminate type.
#[macro_export]
macro_rules! ordered_passes_renderpass {
    (
        $device:expr,
        attachments: {
            $(
                $atch_name:ident: {
                    load: $load:ident,
                    store: $store:ident,
                    format: $format:expr,
                    samples: $samples:expr,
                    $(initial_layout: $init_layout:expr,)*
                    $(final_layout: $final_layout:expr,)*
                }
            ),*
        },
        passes: [
            $(
                {
                    color: [$($color_atch:ident),*],
                    depth_stencil: {$($depth_atch:ident)*},
                    input: [$($input_atch:ident),*]$(,)*
                    $(resolve: [$($resolve_atch:ident),*])*$(,)*
                }
            ),*
        ]
    ) => ({
        use $crate::framebuffer::RenderPassDesc;

        mod scope {
            #![allow(non_camel_case_types)]
            #![allow(non_snake_case)]

            use $crate::format::ClearValue;
            use $crate::format::Format;
            use $crate::framebuffer::RenderPassDesc;
            use $crate::framebuffer::RenderPassDescClearValues;
            use $crate::framebuffer::AttachmentDescription;
            use $crate::framebuffer::PassDescription;
            use $crate::framebuffer::PassDependencyDescription;
            use $crate::image::ImageLayout;
            use $crate::sync::AccessFlagBits;
            use $crate::sync::PipelineStages;

            pub struct CustomRenderPassDesc {
                $(
                    pub $atch_name: (Format, u32),
                )*
            }

            #[allow(unsafe_code)]
            unsafe impl RenderPassDesc for CustomRenderPassDesc {
                #[inline]
                fn num_attachments(&self) -> usize {
                    num_attachments()
                }

                #[inline]
                fn attachment_desc(&self, id: usize) -> Option<AttachmentDescription> {
                    attachment(self, id)
                }

                #[inline]
                fn num_subpasses(&self) -> usize {
                    num_subpasses()
                }

                #[inline]
                fn subpass_desc(&self, id: usize) -> Option<PassDescription> {
                    subpass(id)
                }

                #[inline]
                fn num_dependencies(&self) -> usize {
                    num_dependencies()
                }

                #[inline]
                fn dependency_desc(&self, id: usize) -> Option<PassDependencyDescription> {
                    dependency(id)
                }
            }

            unsafe impl RenderPassDescClearValues<Vec<ClearValue>> for CustomRenderPassDesc {
                fn convert_clear_values(&self, values: Vec<ClearValue>) -> Box<Iterator<Item = ClearValue>> {
                    // FIXME: safety checks
                    Box::new(values.into_iter())
                }
            }

            #[inline]
            fn num_attachments() -> usize {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                #![allow(unused_variables)]
                let mut num = 0;
                $(let $atch_name = num; num += 1;)*
                num
            }

            #[inline]
            fn attachment(desc: &CustomRenderPassDesc, id: usize) -> Option<AttachmentDescription> {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]

                let mut num = 0;

                $({
                    if id == num {
                        let (initial_layout, final_layout) = attachment_layouts(num);

                        return Some($crate::framebuffer::AttachmentDescription {
                            format: desc.$atch_name.0,
                            samples: desc.$atch_name.1,
                            load: $crate::framebuffer::LoadOp::$load,
                            store: $crate::framebuffer::StoreOp::$store,
                            stencil_load: $crate::framebuffer::LoadOp::$load,
                            stencil_store: $crate::framebuffer::StoreOp::$store,
                            initial_layout: initial_layout,
                            final_layout: final_layout,
                        });
                    }

                    num += 1;
                })*

                None
            }

            #[inline]
            fn num_subpasses() -> usize {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                #![allow(unused_variables)]
                let mut num = 0;
                $($(let $color_atch = num;)* num += 1;)*
                num
            }

            #[inline]
            fn subpass(id: usize) -> Option<PassDescription> {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                #![allow(unused_variables)]

                let mut attachment_num = 0;
                $(
                    let $atch_name = attachment_num;
                    attachment_num += 1;
                )*

                let mut cur_pass_num = 0;

                $({
                    if id == cur_pass_num {
                        let mut depth = None;
                        $(
                            depth = Some(($depth_atch, ImageLayout::DepthStencilAttachmentOptimal));
                        )*

                        let mut desc = PassDescription {
                            color_attachments: vec![
                                $(
                                    ($color_atch, ImageLayout::ColorAttachmentOptimal)
                                ),*
                            ],
                            depth_stencil: depth,
                            input_attachments: vec![
                                $(
                                    ($input_atch, ImageLayout::ShaderReadOnlyOptimal)
                                ),*
                            ],
                            resolve_attachments: vec![
                                $($(
                                    ($resolve_atch, ImageLayout::TransferDstOptimal)
                                ),*)*
                            ],
                            preserve_attachments: (0 .. attachment_num).filter(|&a| {
                                $(if a == $color_atch { return false; })*
                                $(if a == $depth_atch { return false; })*
                                $(if a == $input_atch { return false; })*
                                $($(if a == $resolve_atch { return false; })*)*
                                true
                            }).collect()
                        };

                        assert!(desc.resolve_attachments.is_empty() ||
                                desc.resolve_attachments.len() == desc.color_attachments.len());
                        return Some(desc);
                    }

                    cur_pass_num += 1;
                })*

                None
            }

            #[inline]
            fn num_dependencies() -> usize {
                num_subpasses().saturating_sub(1)
            }

            #[inline]
            fn dependency(id: usize) -> Option<PassDependencyDescription> {
                let num_passes = num_subpasses();

                if id + 1 >= num_passes {
                    return None;
                }

                Some(PassDependencyDescription {
                    source_subpass: id,
                    destination_subpass: id + 1,
                    source_stages: PipelineStages { all_graphics: true, .. PipelineStages::none() },         // TODO: correct values
                    destination_stages: PipelineStages { all_graphics: true, .. PipelineStages::none() },         // TODO: correct values
                    source_access: AccessFlagBits::all(),         // TODO: correct values
                    destination_access: AccessFlagBits::all(),         // TODO: correct values
                    by_region: true,            // TODO: correct values
                })
            }

            /// Returns the initial and final layout of an attachment, given its num.
            ///
            /// The value always correspond to the first and last usages of an attachment.
            fn attachment_layouts(num: usize) -> (ImageLayout, ImageLayout) {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                #![allow(unused_variables)]

                let mut attachment_num = 0;
                $(
                    let $atch_name = attachment_num;
                    attachment_num += 1;
                )*

                let mut initial_layout = None;
                let mut final_layout = None;

                $({
                    $(
                        if $depth_atch == num {
                            if initial_layout.is_none() {
                                initial_layout = Some(ImageLayout::DepthStencilAttachmentOptimal);
                            }
                            final_layout = Some(ImageLayout::DepthStencilAttachmentOptimal);
                        }
                    )*

                    $(
                        if $color_atch == num {
                            if initial_layout.is_none() {
                                initial_layout = Some(ImageLayout::ColorAttachmentOptimal);
                            }
                            final_layout = Some(ImageLayout::ColorAttachmentOptimal);
                        }
                    )*

                    $($(
                        if $resolve_atch == num {
                            if initial_layout.is_none() {
                                initial_layout = Some(ImageLayout::TransferDstOptimal);
                            }
                            final_layout = Some(ImageLayout::TransferDstOptimal);
                        }
                    )*)*

                    $(
                        if $input_atch == num {
                            if initial_layout.is_none() {
                                initial_layout = Some(ImageLayout::ShaderReadOnlyOptimal);
                            }
                            final_layout = Some(ImageLayout::ShaderReadOnlyOptimal);
                        }
                    )*
                })*

                $(if $atch_name == num {
                    // If the clear OP is Clear or DontCare, default to the Undefined layout.
                    if initial_layout == Some(ImageLayout::DepthStencilAttachmentOptimal) ||
                        initial_layout == Some(ImageLayout::ColorAttachmentOptimal) ||
                        initial_layout == Some(ImageLayout::TransferDstOptimal)
                    {
                        if $crate::framebuffer::LoadOp::$load == $crate::framebuffer::LoadOp::Clear ||
                            $crate::framebuffer::LoadOp::$load == $crate::framebuffer::LoadOp::DontCare
                        {
                            initial_layout = Some(ImageLayout::Undefined);
                        }
                    }

                    $(initial_layout = Some($init_layout);)*
                    $(final_layout = Some($final_layout);)*
                })*
                (
                    initial_layout.expect(format!("Attachment {} is missing initial_layout, this is normally \
                        automatically determined but you can manually specify it for an individual \
                        attachment in the single_pass_renderpass! macro", attachment_num).as_ref()),
                    final_layout.expect(format!("Attachment {} is missing final_layout, this is normally \
                        automatically determined but you can manually specify it for an individual \
                        attachment in the single_pass_renderpass! macro", attachment_num).as_ref())
                )
            }
        }

        scope::CustomRenderPassDesc {
            $(
                $atch_name: ($format, $samples),
            )*
        }.build_render_pass($device)
    });
}

#[cfg(test)]
mod tests {
    use format::Format;

    #[test]
    fn single_pass_resolve() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = single_pass_renderpass!(device.clone(),
            attachments: {
                a: {
                    load: Clear,
                    store: DontCare,
                    format: Format::R8G8B8A8Unorm,
                    samples: 4,
                },
                b: {
                    load: DontCare,
                    store: Store,
                    format: Format::R8G8B8A8Unorm,
                    samples: 1,
                }
            },
            pass: {
                color: [a],
                depth_stencil: {},
                resolve: [b],
            }
        ).unwrap();
    }
}
<commit_msg>Allow single_pass_renderpass! to work without also using ordered_passes_renderpass in rust 2018 (#1101)<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

/// Builds a `RenderPass` object whose template parameter is of indeterminate type.
#[macro_export]
macro_rules! single_pass_renderpass {
    (
        $device:expr,
        attachments: { $($a:tt)* },
        pass: {
            color: [$($color_atch:ident),*],
            depth_stencil: {$($depth_atch:ident)*}$(,)*
            $(resolve: [$($resolve_atch:ident),*])*$(,)*
        }
    ) => (
        $crate::ordered_passes_renderpass!(
            $device,
            attachments: { $($a)* },
            passes: [
                {
                    color: [$($color_atch),*],
                    depth_stencil: {$($depth_atch)*},
                    input: [],
                    resolve: [$($($resolve_atch),*)*]
                }
            ]
        )
    )
}

/// Builds a `RenderPass` object whose template parameter is of indeterminate type.
#[macro_export]
macro_rules! ordered_passes_renderpass {
    (
        $device:expr,
        attachments: {
            $(
                $atch_name:ident: {
                    load: $load:ident,
                    store: $store:ident,
                    format: $format:expr,
                    samples: $samples:expr,
                    $(initial_layout: $init_layout:expr,)*
                    $(final_layout: $final_layout:expr,)*
                }
            ),*
        },
        passes: [
            $(
                {
                    color: [$($color_atch:ident),*],
                    depth_stencil: {$($depth_atch:ident)*},
                    input: [$($input_atch:ident),*]$(,)*
                    $(resolve: [$($resolve_atch:ident),*])*$(,)*
                }
            ),*
        ]
    ) => ({
        use $crate::framebuffer::RenderPassDesc;

        mod scope {
            #![allow(non_camel_case_types)]
            #![allow(non_snake_case)]

            use $crate::format::ClearValue;
            use $crate::format::Format;
            use $crate::framebuffer::RenderPassDesc;
            use $crate::framebuffer::RenderPassDescClearValues;
            use $crate::framebuffer::AttachmentDescription;
            use $crate::framebuffer::PassDescription;
            use $crate::framebuffer::PassDependencyDescription;
            use $crate::image::ImageLayout;
            use $crate::sync::AccessFlagBits;
            use $crate::sync::PipelineStages;

            pub struct CustomRenderPassDesc {
                $(
                    pub $atch_name: (Format, u32),
                )*
            }

            #[allow(unsafe_code)]
            unsafe impl RenderPassDesc for CustomRenderPassDesc {
                #[inline]
                fn num_attachments(&self) -> usize {
                    num_attachments()
                }

                #[inline]
                fn attachment_desc(&self, id: usize) -> Option<AttachmentDescription> {
                    attachment(self, id)
                }

                #[inline]
                fn num_subpasses(&self) -> usize {
                    num_subpasses()
                }

                #[inline]
                fn subpass_desc(&self, id: usize) -> Option<PassDescription> {
                    subpass(id)
                }

                #[inline]
                fn num_dependencies(&self) -> usize {
                    num_dependencies()
                }

                #[inline]
                fn dependency_desc(&self, id: usize) -> Option<PassDependencyDescription> {
                    dependency(id)
                }
            }

            unsafe impl RenderPassDescClearValues<Vec<ClearValue>> for CustomRenderPassDesc {
                fn convert_clear_values(&self, values: Vec<ClearValue>) -> Box<Iterator<Item = ClearValue>> {
                    // FIXME: safety checks
                    Box::new(values.into_iter())
                }
            }

            #[inline]
            fn num_attachments() -> usize {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                #![allow(unused_variables)]
                let mut num = 0;
                $(let $atch_name = num; num += 1;)*
                num
            }

            #[inline]
            fn attachment(desc: &CustomRenderPassDesc, id: usize) -> Option<AttachmentDescription> {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]

                let mut num = 0;

                $({
                    if id == num {
                        let (initial_layout, final_layout) = attachment_layouts(num);

                        return Some($crate::framebuffer::AttachmentDescription {
                            format: desc.$atch_name.0,
                            samples: desc.$atch_name.1,
                            load: $crate::framebuffer::LoadOp::$load,
                            store: $crate::framebuffer::StoreOp::$store,
                            stencil_load: $crate::framebuffer::LoadOp::$load,
                            stencil_store: $crate::framebuffer::StoreOp::$store,
                            initial_layout: initial_layout,
                            final_layout: final_layout,
                        });
                    }

                    num += 1;
                })*

                None
            }

            #[inline]
            fn num_subpasses() -> usize {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                #![allow(unused_variables)]
                let mut num = 0;
                $($(let $color_atch = num;)* num += 1;)*
                num
            }

            #[inline]
            fn subpass(id: usize) -> Option<PassDescription> {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                #![allow(unused_variables)]

                let mut attachment_num = 0;
                $(
                    let $atch_name = attachment_num;
                    attachment_num += 1;
                )*

                let mut cur_pass_num = 0;

                $({
                    if id == cur_pass_num {
                        let mut depth = None;
                        $(
                            depth = Some(($depth_atch, ImageLayout::DepthStencilAttachmentOptimal));
                        )*

                        let mut desc = PassDescription {
                            color_attachments: vec![
                                $(
                                    ($color_atch, ImageLayout::ColorAttachmentOptimal)
                                ),*
                            ],
                            depth_stencil: depth,
                            input_attachments: vec![
                                $(
                                    ($input_atch, ImageLayout::ShaderReadOnlyOptimal)
                                ),*
                            ],
                            resolve_attachments: vec![
                                $($(
                                    ($resolve_atch, ImageLayout::TransferDstOptimal)
                                ),*)*
                            ],
                            preserve_attachments: (0 .. attachment_num).filter(|&a| {
                                $(if a == $color_atch { return false; })*
                                $(if a == $depth_atch { return false; })*
                                $(if a == $input_atch { return false; })*
                                $($(if a == $resolve_atch { return false; })*)*
                                true
                            }).collect()
                        };

                        assert!(desc.resolve_attachments.is_empty() ||
                                desc.resolve_attachments.len() == desc.color_attachments.len());
                        return Some(desc);
                    }

                    cur_pass_num += 1;
                })*

                None
            }

            #[inline]
            fn num_dependencies() -> usize {
                num_subpasses().saturating_sub(1)
            }

            #[inline]
            fn dependency(id: usize) -> Option<PassDependencyDescription> {
                let num_passes = num_subpasses();

                if id + 1 >= num_passes {
                    return None;
                }

                Some(PassDependencyDescription {
                    source_subpass: id,
                    destination_subpass: id + 1,
                    source_stages: PipelineStages { all_graphics: true, .. PipelineStages::none() },         // TODO: correct values
                    destination_stages: PipelineStages { all_graphics: true, .. PipelineStages::none() },         // TODO: correct values
                    source_access: AccessFlagBits::all(),         // TODO: correct values
                    destination_access: AccessFlagBits::all(),         // TODO: correct values
                    by_region: true,            // TODO: correct values
                })
            }

            /// Returns the initial and final layout of an attachment, given its num.
            ///
            /// The value always correspond to the first and last usages of an attachment.
            fn attachment_layouts(num: usize) -> (ImageLayout, ImageLayout) {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                #![allow(unused_variables)]

                let mut attachment_num = 0;
                $(
                    let $atch_name = attachment_num;
                    attachment_num += 1;
                )*

                let mut initial_layout = None;
                let mut final_layout = None;

                $({
                    $(
                        if $depth_atch == num {
                            if initial_layout.is_none() {
                                initial_layout = Some(ImageLayout::DepthStencilAttachmentOptimal);
                            }
                            final_layout = Some(ImageLayout::DepthStencilAttachmentOptimal);
                        }
                    )*

                    $(
                        if $color_atch == num {
                            if initial_layout.is_none() {
                                initial_layout = Some(ImageLayout::ColorAttachmentOptimal);
                            }
                            final_layout = Some(ImageLayout::ColorAttachmentOptimal);
                        }
                    )*

                    $($(
                        if $resolve_atch == num {
                            if initial_layout.is_none() {
                                initial_layout = Some(ImageLayout::TransferDstOptimal);
                            }
                            final_layout = Some(ImageLayout::TransferDstOptimal);
                        }
                    )*)*

                    $(
                        if $input_atch == num {
                            if initial_layout.is_none() {
                                initial_layout = Some(ImageLayout::ShaderReadOnlyOptimal);
                            }
                            final_layout = Some(ImageLayout::ShaderReadOnlyOptimal);
                        }
                    )*
                })*

                $(if $atch_name == num {
                    // If the clear OP is Clear or DontCare, default to the Undefined layout.
                    if initial_layout == Some(ImageLayout::DepthStencilAttachmentOptimal) ||
                        initial_layout == Some(ImageLayout::ColorAttachmentOptimal) ||
                        initial_layout == Some(ImageLayout::TransferDstOptimal)
                    {
                        if $crate::framebuffer::LoadOp::$load == $crate::framebuffer::LoadOp::Clear ||
                            $crate::framebuffer::LoadOp::$load == $crate::framebuffer::LoadOp::DontCare
                        {
                            initial_layout = Some(ImageLayout::Undefined);
                        }
                    }

                    $(initial_layout = Some($init_layout);)*
                    $(final_layout = Some($final_layout);)*
                })*
                (
                    initial_layout.expect(format!("Attachment {} is missing initial_layout, this is normally \
                        automatically determined but you can manually specify it for an individual \
                        attachment in the single_pass_renderpass! macro", attachment_num).as_ref()),
                    final_layout.expect(format!("Attachment {} is missing final_layout, this is normally \
                        automatically determined but you can manually specify it for an individual \
                        attachment in the single_pass_renderpass! macro", attachment_num).as_ref())
                )
            }
        }

        scope::CustomRenderPassDesc {
            $(
                $atch_name: ($format, $samples),
            )*
        }.build_render_pass($device)
    });
}

#[cfg(test)]
mod tests {
    use format::Format;

    #[test]
    fn single_pass_resolve() {
        let (device, _) = gfx_dev_and_queue!();
        let _ = single_pass_renderpass!(device.clone(),
            attachments: {
                a: {
                    load: Clear,
                    store: DontCare,
                    format: Format::R8G8B8A8Unorm,
                    samples: 4,
                },
                b: {
                    load: DontCare,
                    store: Store,
                    format: Format::R8G8B8A8Unorm,
                    samples: 1,
                }
            },
            pass: {
                color: [a],
                depth_stencil: {},
                resolve: [b],
            }
        ).unwrap();
    }
}
<|endoftext|>


<commit_before>#![no_main]

use rust_decimal::{Decimal, MathematicalOps};

#[derive(Debug, arbitrary::Arbitrary)]
struct Data {
    a: Decimal,
    b: Decimal,
    exp_f64: f64,
    exp_i64: i64,
    exp_u64: u64,
}

libfuzzer_sys::fuzz_target!(|data: Data| {
    let fun = || {
        let _ = data.a.checked_add(data.b)?;
        let _ = data.a.checked_div(data.b)?;
        //let _ = data.a.checked_exp_with_tolerance(data.b)?;
        //let _ = data.a.checked_exp()?;
        //let _ = data.a.checked_mul(data.b)?;
        //let _ = data.a.checked_norm_pdf()?;
        //let _ = data.a.checked_powd(data.b)?;
        //let _ = data.a.checked_powf(data.exp_f64)?;
        //let _ = data.a.checked_powi(data.exp_i64)?;
        //let _ = data.a.checked_powu(data.exp_u64)?;
        //let _ = data.a.checked_sub(data.b)?;

        Some(())
    };
    let _ = fun();
});
<commit_msg>Update arithmetic.rs<commit_after>#![no_main]

use rust_decimal::Decimal;

#[derive(Debug, arbitrary::Arbitrary)]
struct Data {
    a: Decimal,
    b: Decimal,
    exp_f64: f64,
    exp_i64: i64,
    exp_u64: u64,
}

libfuzzer_sys::fuzz_target!(|data: Data| {
    let _ = data.a.checked_add(data.b);
    let _ = data.a.checked_div(data.b);
    //let _ = data.a.checked_exp_with_tolerance(data.b);
    //let _ = data.a.checked_exp();
    //let _ = data.a.checked_mul(data.b);
    //let _ = data.a.checked_norm_pdf();
    //let _ = data.a.checked_powd(data.b);
    //let _ = data.a.checked_powf(data.exp_f64);
    //let _ = data.a.checked_powi(data.exp_i64);
    //let _ = data.a.checked_powu(data.exp_u64);
    //let _ = data.a.checked_sub(data.b);
});
<|endoftext|>


<commit_before>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::String for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Show)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, theta: int) {
        // TODO theta = 60degrees use 3/4th and 1/4th
        // TODO theta = 0 SpinUp
        // TODO theta = 180 SpinDown
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let spin = match self.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            SpinSuper => SpinUp
        };
        friend.spin = spin;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    pub fn premeditated (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let detector;
        if rnd < 0.33 {
            detector = Detector::D12;
        } else if rnd >= 0.33 && rnd < 0.66 {
            detector = Detector::D3;
        } else {
            detector = Detector::D9;
        }

        println!("{}", detector);

        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

fn main () {

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    lhs.spooky(&mut rhs);

    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

    // premeditated should give +55.6% difference, spooky would give 50%

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;
    lhs.premeditated(&mut rhs, OddBall);
    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

}
<commit_msg>choose detectors independentally<commit_after>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::String for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Show)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, theta: isize) {
        // TODO theta = 60degrees use 3/4th and 1/4th
        // TODO theta = 0 SpinUp
        // TODO theta = 180 SpinDown
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let spin = match self.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            SpinSuper => SpinUp
        };
        friend.spin = spin;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    fn get_detector_direction () -> Detector {
        let rnd = random::<f32>();

        let detector;
        if rnd < 0.33 {
            detector = Detector::D12;
        } else if rnd >= 0.33 && rnd < 0.66 {
            detector = Detector::D3;
        } else {
            detector = Detector::D9;
        }
        println!("d1 {}", detector);

        return detector;
    }

    pub fn premeditated (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

fn main () {

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    lhs.spooky(&mut rhs);

    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

    // premeditated should give +55.6% difference, spooky would give 50%

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;
    lhs.premeditated(&mut rhs, OddBall);
    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

}
<|endoftext|>


<commit_before>use std::time::Duration;

use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};

// The benchmarks here verify that the complexity grows as O(*n*)
// where *n* is the number of characters in the text to be wrapped.

use lipsum::lipsum_words_from_seed;

const LINE_LENGTH: usize = 60;

/// Generate a lorem ipsum text with the given number of characters.
fn lorem_ipsum(length: usize) -> String {
    // The average word length in the lorem ipsum text is somewhere
    // between 6 and 7. So we conservatively divide by 5 to have a
    // long enough text that we can truncate below.
    let mut text = lipsum_words_from_seed(length / 5, 42);
    text.truncate(length);
    text
}

pub fn benchmark(c: &mut Criterion) {
    let mut group = c.benchmark_group("fill");
    let lengths = [
        0, 5, 10, 20, 30, 40, 50, 60, 80, 100, 200, 300, 400, 600, 800, 1200, 1600, 2400, 3200,
        4800, 6400,
    ];
    for length in lengths {
        let text = lorem_ipsum(length);
        let length_id = format!("{length:04}");

        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::new_optimal_fit())
            .word_separator(textwrap::WordSeparator::UnicodeBreakProperties);
        group.bench_with_input(
            BenchmarkId::new("optimal_fit_unicode", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );

        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::new_optimal_fit())
            .word_separator(textwrap::WordSeparator::AsciiSpace);
        group.bench_with_input(
            BenchmarkId::new("optimal_fit_ascii", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );

        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::FirstFit)
            .word_separator(textwrap::WordSeparator::AsciiSpace);
        group.bench_with_input(
            BenchmarkId::new("first_fit", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );

        group.bench_function(BenchmarkId::new("inplace", &length_id), |b| {
            b.iter_batched(
                || text.clone(),
                |mut text| textwrap::fill_inplace(&mut text, LINE_LENGTH),
                criterion::BatchSize::SmallInput,
            );
        });

        use hyphenation::{Language, Load, Standard};
        let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("la.standard.bincode");
        let dictionary = Standard::from_path(Language::Latin, &path).unwrap();
        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::new_optimal_fit())
            .word_separator(textwrap::WordSeparator::AsciiSpace)
            .word_splitter(textwrap::WordSplitter::Hyphenation(dictionary));
        group.bench_with_input(
            BenchmarkId::new("optimal_fit_ascii_hyphenation", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );
    }
    group.finish();
}

criterion_group!(
    name = benches;
    config = Criterion::default().warm_up_time(Duration::from_millis(500));
    targets = benchmark
);
criterion_main!(benches);
<commit_msg>Add missing `first_fit_unicode` benchmarks<commit_after>use std::time::Duration;

use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};

// The benchmarks here verify that the complexity grows as O(*n*)
// where *n* is the number of characters in the text to be wrapped.

use lipsum::lipsum_words_from_seed;

const LINE_LENGTH: usize = 60;

/// Generate a lorem ipsum text with the given number of characters.
fn lorem_ipsum(length: usize) -> String {
    // The average word length in the lorem ipsum text is somewhere
    // between 6 and 7. So we conservatively divide by 5 to have a
    // long enough text that we can truncate below.
    let mut text = lipsum_words_from_seed(length / 5, 42);
    text.truncate(length);
    text
}

pub fn benchmark(c: &mut Criterion) {
    let mut group = c.benchmark_group("fill");
    let lengths = [
        0, 5, 10, 20, 30, 40, 50, 60, 80, 100, 200, 300, 400, 600, 800, 1200, 1600, 2400, 3200,
        4800, 6400,
    ];
    for length in lengths {
        let text = lorem_ipsum(length);
        let length_id = format!("{length:04}");

        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::new_optimal_fit())
            .word_separator(textwrap::WordSeparator::UnicodeBreakProperties);
        group.bench_with_input(
            BenchmarkId::new("optimal_fit_unicode", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );

        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::new_optimal_fit())
            .word_separator(textwrap::WordSeparator::AsciiSpace);
        group.bench_with_input(
            BenchmarkId::new("optimal_fit_ascii", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );

        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::FirstFit)
            .word_separator(textwrap::WordSeparator::AsciiSpace);
        group.bench_with_input(
            BenchmarkId::new("first_fit_ascii", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );

        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::FirstFit)
            .word_separator(textwrap::WordSeparator::UnicodeBreakProperties);
        group.bench_with_input(
            BenchmarkId::new("first_fit_unicode", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );

        group.bench_function(BenchmarkId::new("inplace", &length_id), |b| {
            b.iter_batched(
                || text.clone(),
                |mut text| textwrap::fill_inplace(&mut text, LINE_LENGTH),
                criterion::BatchSize::SmallInput,
            );
        });

        use hyphenation::{Language, Load, Standard};
        let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("la.standard.bincode");
        let dictionary = Standard::from_path(Language::Latin, &path).unwrap();
        let options = textwrap::Options::new(LINE_LENGTH)
            .wrap_algorithm(textwrap::WrapAlgorithm::new_optimal_fit())
            .word_separator(textwrap::WordSeparator::AsciiSpace)
            .word_splitter(textwrap::WordSplitter::Hyphenation(dictionary));
        group.bench_with_input(
            BenchmarkId::new("optimal_fit_ascii_hyphenation", &length_id),
            &text,
            |b, text| {
                b.iter(|| textwrap::fill(text, &options));
            },
        );
    }
    group.finish();
}

criterion_group!(
    name = benches;
    config = Criterion::default().warm_up_time(Duration::from_millis(500));
    targets = benchmark
);
criterion_main!(benches);
<|endoftext|>


<commit_before>/*
    Example code is copied verbatim from:
    https://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/
*/

extern crate env_logger;
extern crate cgmath;
extern crate rand;
extern crate three;

use std::f32::consts::PI;
use cgmath::prelude::*;

struct Cloud {
    group: three::Group,
    meshes: Vec<three::Mesh>,
}

impl Cloud {
    fn new<R: rand::Rng>(rng: &mut R, factory: &mut three::Factory) -> Self {
        let mut cloud = Cloud {
            group: factory.group(),
            meshes: Vec::new()
        };
        let geo = three::Geometry::new_box(20.0, 20.0, 20.0);
        let material = three::Material::MeshLambert{ color: 0xFFFFFF };
        for i in 0 .. rng.gen_range(3, 6) {
            let mut m = factory.mesh(geo.clone(), material.clone());
            let rot: three::Orientation = rng.gen();
            *m.transform_mut() = three::Transform {
                scale: rng.gen_range(0.1, 1.0),
                rot: rot.normalize(),
                disp: cgmath::vec3(i as f32 * 15.0, rng.next_f32() * 10.0, rng.next_f32() * 10.0),
            };
            cloud.group.add(&m);
            cloud.meshes.push(m);
        }
        cloud
    }
}

struct Sky {
    group: three::Group,
    clouds: Vec<Cloud>,
}

impl Sky {
    fn new<R: rand::Rng>(rng: &mut R, factory: &mut three::Factory) -> Self {
        let mut sky = Sky {
            group: factory.group(),
            clouds: Vec::new(),
        };
        let num = 20i32;
        let step_angle = PI * 2.0 / num as f32;
        for i in 0 .. num {
            let mut c = Cloud::new(rng, factory);
            let angle = cgmath::Rad(i as f32 * step_angle);
            let dist = rng.gen_range(750.0, 950.0);
            *c.group.transform_mut() = three::Transform {
                scale: rng.gen_range(1.0, 3.0),
                rot: three::Orientation::from_angle_z(angle + cgmath::Rad::turn_div_4()),
                disp: cgmath::vec3(angle.cos() * dist,
                                   angle.sin() * dist,
                                   rng.gen_range(-800.0, -400.0)),
            };
            sky.group.add(&c.group);
            sky.clouds.push(c);
        }
        sky
    }
}

struct AirPlane {
    group: three::Group,
    _cockpit: three::Mesh,
    _engine: three::Mesh,
    _tail: three::Mesh,
    _wing: three::Mesh,
    propeller_group: three::Group,
    _propeller: three::Mesh,
    _blade: three::Mesh,
}

impl AirPlane {
    fn new(factory: &mut three::Factory) -> Self {
        let mut group = factory.group();

        let cockpit = {
            let mut geo = three::Geometry::new_box(80.0, 50.0, 50.0);
            for v in geo.vertices.iter_mut() {
                if v.x < 0.0 {
                    v.z += if v.y > 0.0 {-20.0} else {20.0};
                    v.y += if v.y > 0.0 {-10.0} else {30.0};
                }
            }
            factory.mesh(geo, three::Material::MeshLambert{ color: 0xFF0000 })
        };
        group.add(&cockpit);
        let mut engine = factory.mesh(
            three::Geometry::new_box(20.0, 50.0, 50.0),
            three::Material::MeshLambert{ color: 0xFFFFFF }
        );
        engine.transform_mut().disp.x = 40.0;
        group.add(&engine);
        let mut tail = factory.mesh(
            three::Geometry::new_box(15.0, 20.0, 5.0),
            three::Material::MeshLambert{ color: 0xFF0000 }
        );
        tail.transform_mut().disp = cgmath::vec3(-35.0, 25.0, 0.0);
        group.add(&tail);
        let wing = factory.mesh(
            three::Geometry::new_box(40.0, 8.0, 150.0),
            three::Material::MeshLambert{ color: 0xFF0000 }
        );
        group.add(&wing);

        let mut propeller_group = factory.group();
        propeller_group.transform_mut().disp = cgmath::vec3(50.0, 0.0, 0.0);
        group.add(&propeller_group);
        let propeller = factory.mesh(
            three::Geometry::new_box(20.0, 10.0, 10.0),
            three::Material::MeshLambert{ color: 0xa52a2a }
        );
        propeller_group.add(&propeller);
        let mut blade = factory.mesh(
            three::Geometry::new_box(1.0, 100.0, 20.0),
            three::Material::MeshLambert{ color: 0x23190f }
        );
        blade.transform_mut().disp = cgmath::vec3(8.0, 0.0, 0.0);
        propeller_group.add(&blade);

        AirPlane {
            group,
            _cockpit: cockpit,
            _engine: engine,
            _tail: tail,
            _wing: wing,
            propeller_group,
            _propeller: propeller,
            _blade: blade,
        }
    }

    fn update(&mut self, dt: f32, target: (f32, f32)) {
        self.propeller_group.transform_mut().rotate(0.3 * dt, 0.0, 0.0);
        self.group.transform_mut().disp =
            cgmath::vec3(0.0 + target.0 * 100.0, 100.0 + target.1 * 75.0, 0.0);
    }
}

fn main() {
    env_logger::init().unwrap();
    let mut rng = rand::thread_rng();

    let mut win = three::Window::new("Three-rs aviator example");
    win.scene.background = three::Background::Color(0xB0A090);

    let mut cam = win.factory.perspective_camera(60.0, 0.0, 1.0, 1000.0);
    cam.transform_mut().disp = three::Vector::new(0.0, 100.0, 200.0);

    //TODO: win.scene.fog = Some(three::Fog::new(...));
    //TODO: Phong materials
    //TODO: cast/receive shadows

    let hemi_light = win.factory.hemisphere_light(0xaaaaaa, 0x000000, 0.9);
    win.scene.add(&hemi_light);
    let mut dir_light = win.factory.directional_light(0xffffff, 0.9);
    dir_light.transform_mut().disp = cgmath::vec3(150.0, 350.0, 350.0);
    let shadow_map = win.factory.shadow_map(2048, 2048);
    //dir_light.set_shadow(shadow_map, cgmath::Ortho::new(-400.0, 400.0, -400.0, 400.0, 1.0, 1000.0));
    win.scene.add(&dir_light);
    let ambient_light = win.factory.ambient_light(0xdc8874, 0.5);
    win.scene.add(&ambient_light);

    let mut sea = {
        let geo = three::Geometry::new_cylinder(600.0, 600.0, 800.0, 40);
        let material = three::Material::MeshLambert{ color: 0x0000FF };
        win.factory.mesh(geo, material)
    };
    *sea.transform_mut() = three::Transform {
        scale: 1.0,
        rot: three::Orientation::from_angle_x(-cgmath::Rad::turn_div_4()),
        disp: cgmath::vec3(0.0, -600.0, 0.0),
    };
    win.scene.add(&sea);

    let mut sky = Sky::new(&mut rng, &mut win.factory);
    sky.group.transform_mut().disp.y = -600.0;
    win.scene.add(&sky.group);

    let mut airplane = AirPlane::new(&mut win.factory);
    *airplane.group.transform_mut() = three::Transform {
        scale: 0.25,
        rot: three::Orientation::one(),
        disp: cgmath::vec3(0.0, 100.0, 0.0),
    };
    win.scene.add(&airplane.group);

    while let Some(events) = win.update() {
        // assume the original velocities are given for 60fps
        let dt = events.time_delta * 60.0;

        airplane.update(dt, events.mouse_pos);

        sea.transform_mut().rotate(0.0, 0.0, 0.005 * dt);
        sky.group.transform_mut().rotate(0.0, 0.0, 0.01 * dt);

        win.render(&cam);
    }
}
<commit_msg>Aviator colors<commit_after>/*
    Example code is copied verbatim from:
    https://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/
*/

extern crate env_logger;
extern crate cgmath;
extern crate rand;
extern crate three;

use std::f32::consts::PI;
use cgmath::prelude::*;

const COLOR_BACKGROUND: three::Color = 0xf0e0b6;
const COLOR_RED: three::Color = 0xf25346;
const COLOR_WHITE: three::Color = 0xd8d0d1;
const COLOR_BROWN: three::Color = 0x59332e;
//const COLOR_PINK: three::Color = 0xF5986E;
const COLOR_BROWN_DARK: three::Color = 0x23190f;
const COLOR_BLUE: three::Color = 0x68c3c0;

struct Cloud {
    group: three::Group,
    meshes: Vec<three::Mesh>,
}

impl Cloud {
    fn new<R: rand::Rng>(rng: &mut R, factory: &mut three::Factory) -> Self {
        let mut cloud = Cloud {
            group: factory.group(),
            meshes: Vec::new()
        };
        let geo = three::Geometry::new_box(20.0, 20.0, 20.0);
        let material = three::Material::MeshLambert{ color: COLOR_WHITE };
        for i in 0 .. rng.gen_range(3, 6) {
            let mut m = factory.mesh(geo.clone(), material.clone());
            let rot: three::Orientation = rng.gen();
            *m.transform_mut() = three::Transform {
                scale: rng.gen_range(0.1, 1.0),
                rot: rot.normalize(),
                disp: cgmath::vec3(i as f32 * 15.0, rng.next_f32() * 10.0, rng.next_f32() * 10.0),
            };
            cloud.group.add(&m);
            cloud.meshes.push(m);
        }
        cloud
    }
}

struct Sky {
    group: three::Group,
    clouds: Vec<Cloud>,
}

impl Sky {
    fn new<R: rand::Rng>(rng: &mut R, factory: &mut three::Factory) -> Self {
        let mut sky = Sky {
            group: factory.group(),
            clouds: Vec::new(),
        };
        let num = 20i32;
        let step_angle = PI * 2.0 / num as f32;
        for i in 0 .. num {
            let mut c = Cloud::new(rng, factory);
            let angle = cgmath::Rad(i as f32 * step_angle);
            let dist = rng.gen_range(750.0, 950.0);
            *c.group.transform_mut() = three::Transform {
                scale: rng.gen_range(1.0, 3.0),
                rot: three::Orientation::from_angle_z(angle + cgmath::Rad::turn_div_4()),
                disp: cgmath::vec3(angle.cos() * dist,
                                   angle.sin() * dist,
                                   rng.gen_range(-800.0, -400.0)),
            };
            sky.group.add(&c.group);
            sky.clouds.push(c);
        }
        sky
    }
}

struct AirPlane {
    group: three::Group,
    _cockpit: three::Mesh,
    _engine: three::Mesh,
    _tail: three::Mesh,
    _wing: three::Mesh,
    propeller_group: three::Group,
    _propeller: three::Mesh,
    _blade: three::Mesh,
}

impl AirPlane {
    fn new(factory: &mut three::Factory) -> Self {
        let mut group = factory.group();

        let cockpit = {
            let mut geo = three::Geometry::new_box(80.0, 50.0, 50.0);
            for v in geo.vertices.iter_mut() {
                if v.x < 0.0 {
                    v.z += if v.y > 0.0 {-20.0} else {20.0};
                    v.y += if v.y > 0.0 {-10.0} else {30.0};
                }
            }
            factory.mesh(geo, three::Material::MeshLambert{ color: COLOR_RED })
        };
        group.add(&cockpit);
        let mut engine = factory.mesh(
            three::Geometry::new_box(20.0, 50.0, 50.0),
            three::Material::MeshLambert{ color: COLOR_WHITE }
        );
        engine.transform_mut().disp.x = 40.0;
        group.add(&engine);
        let mut tail = factory.mesh(
            three::Geometry::new_box(15.0, 20.0, 5.0),
            three::Material::MeshLambert{ color: COLOR_RED }
        );
        tail.transform_mut().disp = cgmath::vec3(-35.0, 25.0, 0.0);
        group.add(&tail);
        let wing = factory.mesh(
            three::Geometry::new_box(40.0, 8.0, 150.0),
            three::Material::MeshLambert{ color: COLOR_RED }
        );
        group.add(&wing);

        let mut propeller_group = factory.group();
        propeller_group.transform_mut().disp = cgmath::vec3(50.0, 0.0, 0.0);
        group.add(&propeller_group);
        let propeller = factory.mesh(
            three::Geometry::new_box(20.0, 10.0, 10.0),
            three::Material::MeshLambert{ color: COLOR_BROWN }
        );
        propeller_group.add(&propeller);
        let mut blade = factory.mesh(
            three::Geometry::new_box(1.0, 100.0, 20.0),
            three::Material::MeshLambert{ color: COLOR_BROWN_DARK }
        );
        blade.transform_mut().disp = cgmath::vec3(8.0, 0.0, 0.0);
        propeller_group.add(&blade);

        AirPlane {
            group,
            _cockpit: cockpit,
            _engine: engine,
            _tail: tail,
            _wing: wing,
            propeller_group,
            _propeller: propeller,
            _blade: blade,
        }
    }

    fn update(&mut self, dt: f32, target: (f32, f32)) {
        self.propeller_group.transform_mut().rotate(0.3 * dt, 0.0, 0.0);
        self.group.transform_mut().disp =
            cgmath::vec3(0.0 + target.0 * 100.0, 100.0 + target.1 * 75.0, 0.0);
    }
}

fn main() {
    env_logger::init().unwrap();
    let mut rng = rand::thread_rng();

    let mut win = three::Window::new("Three-rs aviator example");
    win.scene.background = three::Background::Color(COLOR_BACKGROUND);

    let mut cam = win.factory.perspective_camera(60.0, 0.0, 1.0, 1000.0);
    cam.transform_mut().disp = three::Vector::new(0.0, 100.0, 200.0);

    //TODO: win.scene.fog = Some(three::Fog::new(...));
    //TODO: Phong materials
    //TODO: cast/receive shadows

    let hemi_light = win.factory.hemisphere_light(0xaaaaaa, 0x000000, 0.9);
    win.scene.add(&hemi_light);
    let mut dir_light = win.factory.directional_light(0xffffff, 0.9);
    dir_light.transform_mut().disp = cgmath::vec3(150.0, 350.0, 350.0);
    let shadow_map = win.factory.shadow_map(2048, 2048);
    //dir_light.set_shadow(shadow_map, cgmath::Ortho::new(-400.0, 400.0, -400.0, 400.0, 1.0, 1000.0));
    win.scene.add(&dir_light);
    let ambient_light = win.factory.ambient_light(0xdc8874, 0.5);
    win.scene.add(&ambient_light);

    let mut sea = {
        let geo = three::Geometry::new_cylinder(600.0, 600.0, 800.0, 40);
        let material = three::Material::MeshLambert{ color: COLOR_BLUE };
        win.factory.mesh(geo, material)
    };
    *sea.transform_mut() = three::Transform {
        scale: 1.0,
        rot: three::Orientation::from_angle_x(-cgmath::Rad::turn_div_4()),
        disp: cgmath::vec3(0.0, -600.0, 0.0),
    };
    win.scene.add(&sea);

    let mut sky = Sky::new(&mut rng, &mut win.factory);
    sky.group.transform_mut().disp.y = -600.0;
    win.scene.add(&sky.group);

    let mut airplane = AirPlane::new(&mut win.factory);
    *airplane.group.transform_mut() = three::Transform {
        scale: 0.25,
        rot: three::Orientation::one(),
        disp: cgmath::vec3(0.0, 100.0, 0.0),
    };
    win.scene.add(&airplane.group);

    while let Some(events) = win.update() {
        // assume the original velocities are given for 60fps
        let dt = events.time_delta * 60.0;

        airplane.update(dt, events.mouse_pos);

        sea.transform_mut().rotate(0.0, 0.0, 0.005 * dt);
        sky.group.transform_mut().rotate(0.0, 0.0, 0.01 * dt);

        win.render(&cam);
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! 64-bit Interrupt Descriptor Table implementation.
//!
//! Refer to section 6.10 of the _Intel® 64 and IA-32 Architectures
//! Software Developer’s Manual_ for more information.
use core::mem;
use core::ptr;
use spin::Mutex;
use super::{Registers, DTable, DTablePtr, segment};

#[path = "../../x86_all/interrupts.rs"] mod interrupts_all;
#[path = "../../x86_all/pics.rs"] pub mod pics;
pub use self::interrupts_all::*;

//==------------------------------------------------------------------------==
// Interface into ASM interrupt handling
extern {
    /// Offset of the 64-bit GDT main code segment.
    /// Exported by `boot.asm`
    static gdt64_offset: u16;

    /// Array of interrupt handlers from ASM
    static interrupt_handlers: [*const u8; IDT_ENTRIES];
}

/// State stored when handling an interrupt.
#[allow(dead_code)]
#[repr(C, packed)]
pub struct InterruptCtx64 { /// callee-saved registers
                            pub registers: Registers
                          , /// interrupt ID number
                            pub int_id:  u32
                          , __pad_1: u32
                          , /// error number
                            pub err_no:  u32
                          , __pad_2: u32
                          }

impl InterruptContext for InterruptCtx64 {
    type Registers = Registers;
    // All these inline functions are basically just faking
    // object orientation in a way the Rust compiler understands
    #[inline] fn registers(&self) -> Self::Registers { self.registers }
    #[inline] fn err_no(&self) -> u32 { self.err_no }
    #[inline] fn int_id(&self) -> u32 { self.int_id }
}

//==------------------------------------------------------------------------==
// 64-bit implementation of the IDT gate trait

/// An IDT entry is called a gate.
///
/// Based on code from the OS Dev Wiki
/// http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure
///
/// Refer also to "6.14.1 64-Bit Mode IDT"  and "Table 3-2. System-Segment and
/// Gate-Descriptor Types" in the _Intel® 64 and IA-32 Architectures
/// Software Developer’s Manual_
#[repr(C, packed)]
#[derive(Copy,Clone)]
pub struct Gate64 { /// bits 0 - 15 of the offset
                    pub offset_lower: u16
                  , /// code segment selector (GDT or LDT)
                    pub selector: segment::Selector
                  , /// always zero
                    zero: u8
                  , /// indicates the gate's type and attributes.
                    /// the second half indicates the type:
                    ///   + `0b1100`: Call gate
                    ///   + `0b1110`: Interrupt gate
                    ///   + `0b1111`: Trap Gate
                    pub type_attr: GateType
                  , /// bits 16 - 31 of the offset
                    pub offset_mid: u16
                  , /// bits 32 - 63 of the offset
                    pub offset_upper: u32
                  , /// always zero (according to the spec, this is "reserved")
                    reserved: u32
                  }

impl Gate64 {
    /// Creates a new IDT gate marked as `absent`.
    ///
    /// This is basically just for filling the new IDT table
    /// with valid (but useless) gates upon init.
    ///
    /// This would be in the `Gate` trait, but this has to be a `const fn` so
    /// that it can be usedm in static initializers, and trait functions cannot
    /// be `const`.
    ///
    /// Actually triggering an absent interrupt will send a General Protection
    /// fault (13).
    const fn absent() -> Self {
        Gate64 { offset_lower: 0
               , selector: segment::Selector::from_raw(0)
               , zero: 0
               , type_attr: GateType::Absent
               , offset_mid: 0
               , offset_upper: 0
               , reserved: 0
               }
    }
}

impl Gate for Gate64 {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from_handler(handler: Handler) -> Self {
        unsafe { // trust me on this.
                 // `mem::transmute()` is glorious black magic
            let (low, mid, high): (u16, u16, u32)
                = mem::transmute(handler);

            Gate64 { offset_lower: low
                   , selector: segment::Selector::from_raw(gdt64_offset)
                   , zero: 0
                   // Bit 7 is the present bit
                   // Bits 4-0 indicate this is an interrupt gate
                   , type_attr: GateType::Interrupt
                   , offset_mid: mid
                   , offset_upper: high
                   , reserved: 0
                   }
        }
    }

    unsafe fn from_raw(handler: *const u8) -> Self {
        let (low, mid, high): (u16, u16, u32)
            = mem::transmute(handler as u64);

        Gate64 { offset_lower: low
               , selector: segment::Selector::from_raw(gdt64_offset)
               , zero: 0
               , type_attr: GateType::Interrupt
               , offset_mid: mid
               , offset_upper: high
               , reserved: 0
               }
    }
}

//==------------------------------------------------------------------------==
// 64-bit implementation of the IDT trait
struct Idt64([Gate64; IDT_ENTRIES]);

impl Idt for Idt64 {
    // type Ptr = IdtPtr<Self>;
    type Ctx = InterruptCtx64;
    type GateSize = Gate64;
    type PtrSize = u64;

    fn get_ptr(&self) -> DTablePtr<u64>{
        DTablePtr { limit: (mem::size_of::<Self::GateSize>() * IDT_ENTRIES)
                            as u16
                  , base: &self.0[0] as *const Gate64 as u64
                  }
    }

    /// Get the IDT pointer struct to pass to `lidt`
    // fn get_ptr(&self) -> DTablePtr<Self> {
    //     IdtPtr { limit: (mem::size_of::<Gate64>() * IDT_ENTRIES) as u16
    //            , base:  self as *const Idt64
    //            }
    // }

    /// Add an entry for the given handler at the given index
    fn add_gate(&mut self, index: usize, handler: Handler) {
        self.0[index] = Gate64::from_handler(handler)
    }

    /// Assembly interrupt handlers call into this
    #[no_mangle]
    unsafe extern "C" fn handle_interrupt(state: &Self::Ctx) {
        let id = state.int_id();
        match id {
            // interrupts 0 - 16 are CPU exceptions
            0x00...0x0f => Self::handle_cpu_exception(state)
            // System timer
          , 0x20 => { /* TODO: make this work */ }
            // Keyboard
          , 0x21 => { /* TODO: make this work */ }
          , _ => panic!("Unknown interrupt: #{} Sorry!", id)
        }
        // send the PICs the end interrupt signal
        pics::end_pic_interrupt(id as u8);
    }
}

impl DTable for Idt64 {
    #[inline] unsafe fn load(&self) {
        print!("Loading IDT...");
        asm!(  "lidt ($0)"
            :: "r"(&self.get_ptr())
            :  "memory" );
        println!("    [DONE]");
    }
}

impl Idt64 {
    fn add_handlers(&mut self) -> &mut Self {
        print!("Adding interrupt handlers to IDT...");
        for (i, &h_ptr) in interrupt_handlers.iter()
            .enumerate()
            .filter(|&(_, &h_ptr)| h_ptr != ptr::null() ) {
                unsafe { self.0[i] = Gate64::from_raw(h_ptr) }
        }
        println!("    [DONE]");
        self
    }
}

// impl IdtPtrOps for IdtPtr<Idt64> {
//     /// Load the IDT at the given location.
//     /// This just calls `lidt`.
//     unsafe fn load(&self) {
//         asm!(  "lidt ($0)"
//             :: "{rax}"(self)
//             :: "volatile" );
//     }
// }

/// Global Interrupt Descriptor Table instance
/// Our global IDT.
static IDT: Mutex<Idt64>
    = Mutex::new(Idt64([Gate64::absent(); IDT_ENTRIES]));

pub unsafe fn initialize() {
    pics::initialize();
    // TODO: load interrupts into IDT
    IDT.lock()
       .add_handlers()
       .load();                 // Load the IDT pointer
    println!("Triggering test interrupt.");
    asm!("int $0" :: "N" (0x80));
    println!("Test interrupt returned!");

    Idt64::enable_interrupts(); // enable interrupts
}
<commit_msg>Linux syscall interrupt no longer breaks everything<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! 64-bit Interrupt Descriptor Table implementation.
//!
//! Refer to section 6.10 of the _Intel® 64 and IA-32 Architectures
//! Software Developer’s Manual_ for more information.
use core::mem;
use core::ptr;
use spin::Mutex;
use super::{Registers, DTable, DTablePtr, segment};

#[path = "../../x86_all/interrupts.rs"] mod interrupts_all;
#[path = "../../x86_all/pics.rs"] pub mod pics;
pub use self::interrupts_all::*;

//==------------------------------------------------------------------------==
// Interface into ASM interrupt handling
extern {
    /// Offset of the 64-bit GDT main code segment.
    /// Exported by `boot.asm`
    static gdt64_offset: u16;

    /// Array of interrupt handlers from ASM
    static interrupt_handlers: [*const u8; IDT_ENTRIES];
}

/// State stored when handling an interrupt.
#[allow(dead_code)]
#[repr(C, packed)]
pub struct InterruptCtx64 { /// callee-saved registers
                            pub registers: Registers
                          , /// interrupt ID number
                            pub int_id:  u32
                          , __pad_1: u32
                          , /// error number
                            pub err_no:  u32
                          , __pad_2: u32
                          }

impl InterruptContext for InterruptCtx64 {
    type Registers = Registers;
    // All these inline functions are basically just faking
    // object orientation in a way the Rust compiler understands
    #[inline] fn registers(&self) -> Self::Registers { self.registers }
    #[inline] fn err_no(&self) -> u32 { self.err_no }
    #[inline] fn int_id(&self) -> u32 { self.int_id }
}

//==------------------------------------------------------------------------==
// 64-bit implementation of the IDT gate trait

/// An IDT entry is called a gate.
///
/// Based on code from the OS Dev Wiki
/// http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure
///
/// Refer also to "6.14.1 64-Bit Mode IDT"  and "Table 3-2. System-Segment and
/// Gate-Descriptor Types" in the _Intel® 64 and IA-32 Architectures
/// Software Developer’s Manual_
#[repr(C, packed)]
#[derive(Copy,Clone)]
pub struct Gate64 { /// bits 0 - 15 of the offset
                    pub offset_lower: u16
                  , /// code segment selector (GDT or LDT)
                    pub selector: segment::Selector
                  , /// always zero
                    zero: u8
                  , /// indicates the gate's type and attributes.
                    /// the second half indicates the type:
                    ///   + `0b1100`: Call gate
                    ///   + `0b1110`: Interrupt gate
                    ///   + `0b1111`: Trap Gate
                    pub type_attr: GateType
                  , /// bits 16 - 31 of the offset
                    pub offset_mid: u16
                  , /// bits 32 - 63 of the offset
                    pub offset_upper: u32
                  , /// always zero (according to the spec, this is "reserved")
                    reserved: u32
                  }

impl Gate64 {
    /// Creates a new IDT gate marked as `absent`.
    ///
    /// This is basically just for filling the new IDT table
    /// with valid (but useless) gates upon init.
    ///
    /// This would be in the `Gate` trait, but this has to be a `const fn` so
    /// that it can be usedm in static initializers, and trait functions cannot
    /// be `const`.
    ///
    /// Actually triggering an absent interrupt will send a General Protection
    /// fault (13).
    const fn absent() -> Self {
        Gate64 { offset_lower: 0
               , selector: segment::Selector::from_raw(0)
               , zero: 0
               , type_attr: GateType::Absent
               , offset_mid: 0
               , offset_upper: 0
               , reserved: 0
               }
    }
}

impl Gate for Gate64 {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from_handler(handler: Handler) -> Self {
        unsafe { // trust me on this.
                 // `mem::transmute()` is glorious black magic
            let (low, mid, high): (u16, u16, u32)
                = mem::transmute(handler);

            Gate64 { offset_lower: low
                   , selector: segment::Selector::from_raw(gdt64_offset)
                   , zero: 0
                   // Bit 7 is the present bit
                   // Bits 4-0 indicate this is an interrupt gate
                   , type_attr: GateType::Interrupt
                   , offset_mid: mid
                   , offset_upper: high
                   , reserved: 0
                   }
        }
    }

    unsafe fn from_raw(handler: *const u8) -> Self {
        let (low, mid, high): (u16, u16, u32)
            = mem::transmute(handler as u64);

        Gate64 { offset_lower: low
               , selector: segment::Selector::from_raw(gdt64_offset)
               , zero: 0
               , type_attr: GateType::Interrupt
               , offset_mid: mid
               , offset_upper: high
               , reserved: 0
               }
    }
}

//==------------------------------------------------------------------------==
// 64-bit implementation of the IDT trait
struct Idt64([Gate64; IDT_ENTRIES]);

impl Idt for Idt64 {
    // type Ptr = IdtPtr<Self>;
    type Ctx = InterruptCtx64;
    type GateSize = Gate64;
    type PtrSize = u64;

    fn get_ptr(&self) -> DTablePtr<u64>{
        DTablePtr { limit: (mem::size_of::<Self::GateSize>() * IDT_ENTRIES)
                            as u16
                  , base: &self.0[0] as *const Gate64 as u64
                  }
    }

    /// Get the IDT pointer struct to pass to `lidt`
    // fn get_ptr(&self) -> DTablePtr<Self> {
    //     IdtPtr { limit: (mem::size_of::<Gate64>() * IDT_ENTRIES) as u16
    //            , base:  self as *const Idt64
    //            }
    // }

    /// Add an entry for the given handler at the given index
    fn add_gate(&mut self, index: usize, handler: Handler) {
        self.0[index] = Gate64::from_handler(handler)
    }

    /// Assembly interrupt handlers call into this
    #[no_mangle]
    unsafe extern "C" fn handle_interrupt(state: &Self::Ctx) {
        let id = state.int_id();
        match id {
            // interrupts 0 - 16 are CPU exceptions
            0x00...0x0f => Self::handle_cpu_exception(state)
            // System timer
          , 0x20 => { /* TODO: make this work */ }
            // Keyboard
          , 0x21 => { /* TODO: make this work */ }
            // Loonix syscall vector
          , 0x80 => { // TODO: currently, we do nothing here, do we want
                      // our syscalls on this vector as well?
            }
          , _ => panic!("Unknown interrupt: #{} Sorry!", id)
        }
        // send the PICs the end interrupt signal
        pics::end_pic_interrupt(id as u8);
    }
}

impl DTable for Idt64 {
    #[inline] unsafe fn load(&self) {
        print!("Loading IDT...");
        asm!(  "lidt ($0)"
            :: "r"(&self.get_ptr())
            :  "memory" );
        println!("    [DONE]");
    }
}

impl Idt64 {
    fn add_handlers(&mut self) -> &mut Self {
        print!("Adding interrupt handlers to IDT...");
        for (i, &h_ptr) in interrupt_handlers.iter()
            .enumerate()
            .filter(|&(_, &h_ptr)| h_ptr != ptr::null() ) {
                unsafe { self.0[i] = Gate64::from_raw(h_ptr) }
        }
        println!("    [DONE]");
        self
    }
}

// impl IdtPtrOps for IdtPtr<Idt64> {
//     /// Load the IDT at the given location.
//     /// This just calls `lidt`.
//     unsafe fn load(&self) {
//         asm!(  "lidt ($0)"
//             :: "{rax}"(self)
//             :: "volatile" );
//     }
// }

/// Global Interrupt Descriptor Table instance
/// Our global IDT.
static IDT: Mutex<Idt64>
    = Mutex::new(Idt64([Gate64::absent(); IDT_ENTRIES]));

pub unsafe fn initialize() {
    pics::initialize();
    // TODO: load interrupts into IDT
    IDT.lock()
       .add_handlers()
       .load();                 // Load the IDT pointer
    print!("Testing interrupt handling...");
    asm!("int $0" :: "N" (0x80));
    println!("   [DONE]");

    Idt64::enable_interrupts(); // enable interrupts
}
<|endoftext|>


<commit_before>/*! Sprite display demo */

#![feature(collections)]
extern crate image;
extern crate calx;

use calx::{V2, V3, color_key, Projection, Rect, noise};
use calx::color::*;
use calx::backend::{CanvasBuilder, CanvasUtil, SpriteCache, SpriteKey, Event, Key};

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum Spr {
    Grass,
    Dirt,
    Brick,
    Guy1,
    Guy2,
}

impl SpriteKey for Spr { fn to_usize(self) -> usize { self as usize } }

fn build_sprites(builder: &mut CanvasBuilder) -> SpriteCache<Spr> {
    use Spr::*;

    let mut sprite_sheet = color_key(
        &image::load_from_memory(include_bytes!("assets/iso.png")).unwrap(),
        &CYAN);
    let mut ret = SpriteCache::new();
    ret.batch_add(builder, V2(-16, -24), V2(32, 40), &mut sprite_sheet,
                  vec![Grass, Dirt, Brick, Guy1, Guy2]);
    ret
}

struct Sprite {
    pub bounds: (V3<f32>, V3<f32>),
    pub spr: Spr,
    // Sort key, pos projected along camera vector.
    pub key: f32,
}

impl Sprite {
    pub fn new(pos: V3<f32>, height: u32, spr: Spr) -> Sprite {
        Sprite {
            bounds: (pos, pos + V3(1.0, 1.0, height as f32 / 2.0)),
            spr: spr,
            key: pos.dot(V3(1.0, 1.0, 1.0)),
        }
    }
}

fn heightmap(cell: V2<f32>) -> u32 {
    let n = (cell.0 as i32) + 3329 * (cell.1 as i32);
    ((noise(n) + 1.0) * 1.5).round() as u32 + 1
}

fn gen_sprites(cell: V2<f32>) -> Vec<Sprite> {
    let mut offset = V3(cell.0, cell.1, 0.0);

    let mut ret = Vec::new();
    for _ in 0..heightmap(cell) {
        ret.push(Sprite::new(offset, 1, Spr::Dirt));
        offset.2 += 0.5;
    }
    let top = ret.len() - 1;
    ret[top].spr = Spr::Grass;

    ret
}

fn main() {
    let screen_rect = Rect(V2(0.0f32, 0.0f32), V2(640.0f32, 360.0f32));

    let mut builder = CanvasBuilder::new();
    let mut player_x = 20.0;
    let mut player_y = 0.0;
    let cache = build_sprites(&mut builder);
    let mut ctx = builder.build();

    loop {
        match ctx.next_event() {
            Event::RenderFrame => {
                ctx.clear();
                let proj = Projection::new(V2(16.0, 8.0), V2(-16.0, 8.0), V2(0.0, 0.0)).unwrap();

                let mut sprites = Vec::new();
                for pt in proj.inv_project_rectangle(&screen_rect).iter() {
                    sprites.append(&mut gen_sprites(pt));
                }
                sprites.push(Sprite::new(V3(player_x, player_y, heightmap(V2(player_x, player_y)) as f32 / 2.0), 3, Spr::Guy1));

                sprites.sort_by(|x, y| x.key.partial_cmp(&y.key).unwrap());

                for spr in sprites.iter() {
                    let draw_pos =
                        proj.project(V2((spr.bounds.0).0, (spr.bounds.0).1)) +
                        V2(0.0, -16.0 * (spr.bounds.0).2);
                    ctx.draw_image(cache.get(spr.spr).unwrap(), draw_pos, 0.5, &WHITE, &BLACK);
                }
            }

            Event::Quit => { return; }

            Event::KeyPressed(Key::Escape) => { return; }

            Event::KeyPressed(Key::F12) => {
                ctx.save_screenshot(&"sprites");
            }

            Event::KeyPressed(k) => {
                match k {
                    Key::A => { player_x -= 1.0; }
                    Key::D => { player_x += 1.0; }
                    Key::W => { player_y -= 1.0; }
                    Key::S => { player_y += 1.0; }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}
<commit_msg>Scrolling world<commit_after>/*! Sprite display demo */

#![feature(collections)]
extern crate image;
extern crate calx;

use calx::{V2, V3, color_key, Projection, Rect, noise};
use calx::color::*;
use calx::backend::{CanvasBuilder, CanvasUtil, SpriteCache, SpriteKey, Event, Key};

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum Spr {
    Grass,
    Dirt,
    Brick,
    Guy1,
    Guy2,
}

impl SpriteKey for Spr { fn to_usize(self) -> usize { self as usize } }

fn build_sprites(builder: &mut CanvasBuilder) -> SpriteCache<Spr> {
    use Spr::*;

    let mut sprite_sheet = color_key(
        &image::load_from_memory(include_bytes!("assets/iso.png")).unwrap(),
        &CYAN);
    let mut ret = SpriteCache::new();
    ret.batch_add(builder, V2(-16, -24), V2(32, 40), &mut sprite_sheet,
                  vec![Grass, Dirt, Brick, Guy1, Guy2]);
    ret
}

struct Sprite {
    pub bounds: (V3<f32>, V3<f32>),
    pub spr: Spr,
    // Sort key, pos projected along camera vector.
    pub key: f32,
}

impl Sprite {
    pub fn new(pos: V3<f32>, height: u32, spr: Spr) -> Sprite {
        Sprite {
            bounds: (pos, pos + V3(1.0, 1.0, height as f32 / 2.0)),
            spr: spr,
            key: pos.dot(V3(1.0, 1.0, 1.0)),
        }
    }
}

fn heightmap(cell: V2<f32>) -> u32 {
    let n = (cell.0 as i32) + 3329 * (cell.1 as i32);
    ((noise(n) + 1.0) * 1.5).round() as u32 + 1
}

fn gen_sprites(cell: V2<f32>) -> Vec<Sprite> {
    let mut offset = V3(cell.0, cell.1, 0.0);

    let mut ret = Vec::new();
    for _ in 0..heightmap(cell) {
        ret.push(Sprite::new(offset, 1, Spr::Dirt));
        offset.2 += 0.5;
    }
    let top = ret.len() - 1;
    ret[top].spr = Spr::Grass;

    ret
}

fn main() {
    let screen_rect = Rect(V2(0.0f32, 0.0f32), V2(640.0f32, 360.0f32));

    let mut builder = CanvasBuilder::new();
    let mut player_x = 20.0;
    let mut player_y = 0.0;
    let cache = build_sprites(&mut builder);
    let mut ctx = builder.build();

    loop {
        match ctx.next_event() {
            Event::RenderFrame => {
                ctx.clear();
                let proj = Projection::new(V2(16.0, 8.0), V2(-16.0, 8.0), V2(0.0, 0.0)).unwrap();
                let proj = Projection::new(V2(16.0, 8.0), V2(-16.0, 8.0), proj.project(V2(-player_x, -player_y)) + V2(320.0, 180.0)).unwrap();

                let mut sprites = Vec::new();
                for pt in proj.inv_project_rectangle(&screen_rect).iter() {
                    sprites.append(&mut gen_sprites(pt));
                }
                sprites.push(Sprite::new(V3(player_x, player_y, heightmap(V2(player_x, player_y)) as f32 / 2.0), 3, Spr::Guy1));

                sprites.sort_by(|x, y| x.key.partial_cmp(&y.key).unwrap());

                for spr in sprites.iter() {
                    let draw_pos =
                        proj.project(V2((spr.bounds.0).0, (spr.bounds.0).1)) +
                        V2(0.0, -16.0 * (spr.bounds.0).2);
                    ctx.draw_image(cache.get(spr.spr).unwrap(), draw_pos, 0.5, &WHITE, &BLACK);
                }
            }

            Event::Quit => { return; }

            Event::KeyPressed(Key::Escape) => { return; }

            Event::KeyPressed(Key::F12) => {
                ctx.save_screenshot(&"sprites");
            }

            Event::KeyPressed(k) => {
                match k {
                    Key::A => { player_x -= 1.0; }
                    Key::D => { player_x += 1.0; }
                    Key::W => { player_y -= 1.0; }
                    Key::S => { player_y += 1.0; }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}
<|endoftext|>