<commit_before>// Copyright 2016 Alex Regueiro
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use ffi;
use {Error, DB};

use libc::{c_int, uint32_t};
use std::ffi::CString;
use std::path::Path;

pub struct BackupEngine {
    inner: *mut ffi::rocksdb_backup_engine_t,
}

pub struct BackupEngineOptions {
    inner: *mut ffi::rocksdb_options_t,
}

pub struct RestoreOptions {
    inner: *mut ffi::rocksdb_restore_options_t,
}

impl BackupEngine {
    /// Open a backup engine with the specified options.
    pub fn open<P: AsRef<Path>>(
        opts: &BackupEngineOptions,
        path: P,
    ) -> Result<BackupEngine, Error> {
        let path = path.as_ref();
        let cpath = match CString::new(path.to_string_lossy().as_bytes()) {
            Ok(c) => c,
            Err(_) => {
                return Err(Error::new(
                    "Failed to convert path to CString \
                     when opening backup engine"
                        .to_owned(),
                ));
            }
        };

        let be: *mut ffi::rocksdb_backup_engine_t;
        unsafe { be = ffi_try!(ffi::rocksdb_backup_engine_open(opts.inner, cpath.as_ptr(),)) }

        if be.is_null() {
            return Err(Error::new("Could not initialize backup engine.".to_owned()));
        }

        Ok(BackupEngine { inner: be })
    }

    pub fn create_new_backup(&mut self, db: &DB) -> Result<(), Error> {
        unsafe {
            ffi_try!(ffi::rocksdb_backup_engine_create_new_backup(
                self.inner, db.inner,
            ));
            Ok(())
        }
    }

    pub fn purge_old_backups(&mut self, num_backups_to_keep: usize) -> Result<(), Error> {
        unsafe {
            ffi_try!(ffi::rocksdb_backup_engine_purge_old_backups(
                self.inner,
                num_backups_to_keep as uint32_t,
            ));
            Ok(())
        }
    }

    /// Restore from the latest backup
    ///
    /// # Arguments
    ///
    /// * `db_dir` - A path to the database directory
    /// * `wal_dir` - A path to the wal directory
    /// * `opts` - Restore options
    ///
    /// # Example
    ///
    /// ```ignore
    /// use rocksdb::backup::{BackupEngine, BackupEngineOptions};
    /// let backup_opts = BackupEngineOptions::default();
    /// let mut backup_engine = BackupEngine::open(&backup_opts, &backup_path).unwrap();
    /// let mut restore_option = rocksdb::backup::RestoreOptions::default();
    /// restore_option.set_keep_log_files(true); /// true to keep log files
    /// if let Err(e) = backup_engine.restore_from_latest_backup(&db_path, &wal_dir, &restore_option) {
    ///     error!("Failed to restore from the backup. Error:{:?}", e);
    ///     return Err(e.to_string());
    ///  }
    /// ```

    pub fn restore_from_latest_backup<D: AsRef<Path>, W: AsRef<Path>>(

        &mut self,
        db_dir: D,
        wal_dir: W,
        opts: &RestoreOptions,
    ) -> Result<(), Error> {
        let db_dir = db_dir.as_ref();
        let c_db_dir = match CString::new(db_dir.to_string_lossy().as_bytes()) {
            Ok(c) => c,
            Err(_) => {
                return Err(Error::new(
                    "Failed to convert db_dir to CString \
                     when restoring from latest backup"
                        .to_owned(),
                ));
            }
        };

        let wal_dir = wal_dir.as_ref();
        let c_wal_dir = match CString::new(wal_dir.to_string_lossy().as_bytes()) {
            Ok(c) => c,
            Err(_) => {
                return Err(Error::new(
                    "Failed to convert wal_dir to CString \
                     when restoring from latest backup"
                        .to_owned(),
                ));
            }
        };

        unsafe {
            ffi_try!(ffi::rocksdb_backup_engine_restore_db_from_latest_backup(
                self.inner,
                c_db_dir.as_ptr(),
                c_wal_dir.as_ptr(),
                opts.inner,
            ));
        }
        Ok(())
    }
}

impl BackupEngineOptions {
    //
}

impl RestoreOptions {
    pub fn set_keep_log_files(&mut self, keep_log_files: bool) {
        unsafe {
            ffi::rocksdb_restore_options_set_keep_log_files(self.inner, keep_log_files as c_int);
        }
    }
}

impl Default for BackupEngineOptions {
    fn default() -> BackupEngineOptions {
        unsafe {
            let opts = ffi::rocksdb_options_create();
            if opts.is_null() {
                panic!("Could not create RocksDB backup options".to_owned());
            }
            BackupEngineOptions { inner: opts }
        }
    }
}

impl Default for RestoreOptions {
    fn default() -> RestoreOptions {
        unsafe {
            let opts = ffi::rocksdb_restore_options_create();
            if opts.is_null() {
                panic!("Could not create RocksDB restore options".to_owned());
            }
            RestoreOptions { inner: opts }
        }
    }
}

impl Drop for BackupEngine {
    fn drop(&mut self) {
        unsafe {
            ffi::rocksdb_backup_engine_close(self.inner);
        }
    }
}

impl Drop for BackupEngineOptions {
    fn drop(&mut self) {
        unsafe {
            ffi::rocksdb_options_destroy(self.inner);
        }
    }
}

impl Drop for RestoreOptions {
    fn drop(&mut self) {
        unsafe {
            ffi::rocksdb_restore_options_destroy(self.inner);
        }
    }
}

#[test]
fn backup_restore() {

    use db::DBVector;
    // create backup
    let path = "_rust_rocksdb_backup_restore_test";
    {
        let db = DB::open_default(path).unwrap();
        let p = db.put(b"k1", b"v1111");
        assert!(p.is_ok());
        let r: Result<Option<DBVector>, Error> = db.get(b"k1");
        assert!(r.unwrap().unwrap().to_utf8().unwrap() == "v1111");

        let backup_path = "_rust_rocksdb_backup_path";
        {
            let backup_opts = BackupEngineOptions::default();
            let mut backup_engine = BackupEngine::open(&backup_opts, &backup_path).unwrap();

            let r = backup_engine.create_new_backup(&db);
            assert!(r.is_ok());

            let restore_path = "_rust_rocksdb_restore_from_backup_path";
            {
                let mut restore_option = RestoreOptions::default();
                restore_option.set_keep_log_files(true); // true to keep log files
                let restore_status = backup_engine.restore_from_latest_backup(&restore_path, &restore_path, &restore_option);
                assert!(restore_status.is_ok());

                let db = DB::open_default(restore_path).unwrap();

                let r: Result<Option<DBVector>, Error> = db.get(b"k1");
                assert!(r.unwrap().unwrap().to_utf8().unwrap() == "v1111");
            }
        }
    }

}
<commit_msg>cargo fmt check<commit_after>// Copyright 2016 Alex Regueiro
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use ffi;
use {Error, DB};

use libc::{c_int, uint32_t};
use std::ffi::CString;
use std::path::Path;

pub struct BackupEngine {
    inner: *mut ffi::rocksdb_backup_engine_t,
}

pub struct BackupEngineOptions {
    inner: *mut ffi::rocksdb_options_t,
}

pub struct RestoreOptions {
    inner: *mut ffi::rocksdb_restore_options_t,
}

impl BackupEngine {
    /// Open a backup engine with the specified options.
    pub fn open<P: AsRef<Path>>(
        opts: &BackupEngineOptions,
        path: P,
    ) -> Result<BackupEngine, Error> {
        let path = path.as_ref();
        let cpath = match CString::new(path.to_string_lossy().as_bytes()) {
            Ok(c) => c,
            Err(_) => {
                return Err(Error::new(
                    "Failed to convert path to CString \
                     when opening backup engine"
                        .to_owned(),
                ));
            }
        };

        let be: *mut ffi::rocksdb_backup_engine_t;
        unsafe { be = ffi_try!(ffi::rocksdb_backup_engine_open(opts.inner, cpath.as_ptr(),)) }

        if be.is_null() {
            return Err(Error::new("Could not initialize backup engine.".to_owned()));
        }

        Ok(BackupEngine { inner: be })
    }

    pub fn create_new_backup(&mut self, db: &DB) -> Result<(), Error> {
        unsafe {
            ffi_try!(ffi::rocksdb_backup_engine_create_new_backup(
                self.inner, db.inner,
            ));
            Ok(())
        }
    }

    pub fn purge_old_backups(&mut self, num_backups_to_keep: usize) -> Result<(), Error> {
        unsafe {
            ffi_try!(ffi::rocksdb_backup_engine_purge_old_backups(
                self.inner,
                num_backups_to_keep as uint32_t,
            ));
            Ok(())
        }
    }

    /// Restore from the latest backup
    ///
    /// # Arguments
    ///
    /// * `db_dir` - A path to the database directory
    /// * `wal_dir` - A path to the wal directory
    /// * `opts` - Restore options
    ///
    /// # Example
    ///
    /// ```ignore
    /// use rocksdb::backup::{BackupEngine, BackupEngineOptions};
    /// let backup_opts = BackupEngineOptions::default();
    /// let mut backup_engine = BackupEngine::open(&backup_opts, &backup_path).unwrap();
    /// let mut restore_option = rocksdb::backup::RestoreOptions::default();
    /// restore_option.set_keep_log_files(true); /// true to keep log files
    /// if let Err(e) = backup_engine.restore_from_latest_backup(&db_path, &wal_dir, &restore_option) {
    ///     error!("Failed to restore from the backup. Error:{:?}", e);
    ///     return Err(e.to_string());
    ///  }
    /// ```

    pub fn restore_from_latest_backup<D: AsRef<Path>, W: AsRef<Path>>(
        &mut self,
        db_dir: D,
        wal_dir: W,
        opts: &RestoreOptions,
    ) -> Result<(), Error> {
        let db_dir = db_dir.as_ref();
        let c_db_dir = match CString::new(db_dir.to_string_lossy().as_bytes()) {
            Ok(c) => c,
            Err(_) => {
                return Err(Error::new(
                    "Failed to convert db_dir to CString \
                     when restoring from latest backup"
                        .to_owned(),
                ));
            }
        };

        let wal_dir = wal_dir.as_ref();
        let c_wal_dir = match CString::new(wal_dir.to_string_lossy().as_bytes()) {
            Ok(c) => c,
            Err(_) => {
                return Err(Error::new(
                    "Failed to convert wal_dir to CString \
                     when restoring from latest backup"
                        .to_owned(),
                ));
            }
        };

        unsafe {
            ffi_try!(ffi::rocksdb_backup_engine_restore_db_from_latest_backup(
                self.inner,
                c_db_dir.as_ptr(),
                c_wal_dir.as_ptr(),
                opts.inner,
            ));
        }
        Ok(())
    }
}

impl BackupEngineOptions {
    //
}

impl RestoreOptions {
    pub fn set_keep_log_files(&mut self, keep_log_files: bool) {
        unsafe {
            ffi::rocksdb_restore_options_set_keep_log_files(self.inner, keep_log_files as c_int);
        }
    }
}

impl Default for BackupEngineOptions {
    fn default() -> BackupEngineOptions {
        unsafe {
            let opts = ffi::rocksdb_options_create();
            if opts.is_null() {
                panic!("Could not create RocksDB backup options".to_owned());
            }
            BackupEngineOptions { inner: opts }
        }
    }
}

impl Default for RestoreOptions {
    fn default() -> RestoreOptions {
        unsafe {
            let opts = ffi::rocksdb_restore_options_create();
            if opts.is_null() {
                panic!("Could not create RocksDB restore options".to_owned());
            }
            RestoreOptions { inner: opts }
        }
    }
}

impl Drop for BackupEngine {
    fn drop(&mut self) {
        unsafe {
            ffi::rocksdb_backup_engine_close(self.inner);
        }
    }
}

impl Drop for BackupEngineOptions {
    fn drop(&mut self) {
        unsafe {
            ffi::rocksdb_options_destroy(self.inner);
        }
    }
}

impl Drop for RestoreOptions {
    fn drop(&mut self) {
        unsafe {
            ffi::rocksdb_restore_options_destroy(self.inner);
        }
    }
}

#[test]
fn backup_restore() {
    use db::DBVector;
    // create backup
    let path = "_rust_rocksdb_backup_restore_test";
    {
        let db = DB::open_default(path).unwrap();
        let p = db.put(b"k1", b"v1111");
        assert!(p.is_ok());
        let r: Result<Option<DBVector>, Error> = db.get(b"k1");
        assert!(r.unwrap().unwrap().to_utf8().unwrap() == "v1111");

        let backup_path = "_rust_rocksdb_backup_path";
        {
            let backup_opts = BackupEngineOptions::default();
            let mut backup_engine = BackupEngine::open(&backup_opts, &backup_path).unwrap();

            let r = backup_engine.create_new_backup(&db);
            assert!(r.is_ok());

            let restore_path = "_rust_rocksdb_restore_from_backup_path";
            {
                let mut restore_option = RestoreOptions::default();
                restore_option.set_keep_log_files(true); // true to keep log files
                let restore_status = backup_engine.restore_from_latest_backup(
                    &restore_path,
                    &restore_path,
                    &restore_option,
                );
                assert!(restore_status.is_ok());

                let db = DB::open_default(restore_path).unwrap();

                let r: Result<Option<DBVector>, Error> = db.get(b"k1");
                assert!(r.unwrap().unwrap().to_utf8().unwrap() == "v1111");
            }
        }
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
enum State {
    Init,
    Space,
    SpaceFinal,
    Text,
    TextFinal
}

#[derive(Debug)]
pub struct PuncAcc {
    i: usize,
    pub start: usize,
    state: State
}

impl PuncAcc {
    pub fn new() -> PuncAcc {
        PuncAcc{start:0, i:0, state:State::Init}
    }

    fn is_space(&self, ch: char) -> bool {
        match ch {
            '"' => true,
            ' ' => true,
            '\n' => true,
            '\t' => true,
            '\r' => true,
            _ => false
        }
    }

    fn to_text_state(&mut self, nch: Option<char>) -> State {
        match nch {
            Some(_nch) => if self.is_space(_nch) {
                State::TextFinal
            } else {
                State::Text
            },
            None => State::TextFinal
        }
    }

    fn to_space_state(&mut self, nch: Option<char>) -> State {
        match nch {
            Some(_nch) => if self.is_space(_nch) {
                State::Space
            } else {
                State::SpaceFinal
            },
            None => State::SpaceFinal
        }
    }

    fn to_another_state(&mut self, ch: char, nch: Option<char>) -> State {
        if self.is_space(ch) {
            self.to_space_state(nch)
        } else {
            self.to_text_state(nch)
        }
    }

    pub fn transit(&mut self, ch: char, nch: Option<char>) {
        match self.state {
            State::Init => {
                self.start = self.i;
                self.state = self.to_another_state(ch, nch)
            },
            State::Text => { self.state = self.to_another_state(ch, nch); },
            State::TextFinal => {
                self.start = self.i;
                self.state = self.to_space_state(nch);
            }
            State::SpaceFinal => {
                self.start = self.i;
                self.state = self.to_text_state(nch)
            }
            State::Space => if !self.is_space(ch) {
                self.state = self.to_another_state(ch, nch);
            }
        };
        self.i += 1;
    }

    pub fn is_text_final(&self) -> bool {
        self.state == State::TextFinal
    }

    pub fn is_space_final(&self) -> bool {
        self.state == State::SpaceFinal
    }
}<commit_msg>refactor and add more puncuations<commit_after>use std::collections::HashSet;

#[derive(Debug, PartialEq)]
enum State {
    Init,
    Space,
    SpaceFinal,
    Text,
    TextFinal
}

#[derive(Debug)]
pub struct PuncAcc {
    i: usize,
    pub start: usize,
    state: State,
    split_char: HashSet<char>
}

impl PuncAcc {
    pub fn new() -> PuncAcc {
        let mut split_char = HashSet::new();
        split_char.insert('"');
        split_char.insert('[');
        split_char.insert(']');
        split_char.insert('(');
        split_char.insert(')');
        split_char.insert(':');
        split_char.insert(' ');
        split_char.insert('\n');
        split_char.insert('\t');
        split_char.insert('\r');
        PuncAcc{start:0, i:0, state:State::Init, split_char: split_char}
    }

    fn is_split_char(&self, ch: char) -> bool {
        self.split_char.contains(&ch)
    }

    fn to_text_state(&mut self, nch: Option<char>) -> State {
        match nch {
            Some(_nch) => if self.is_split_char(_nch) {
                State::TextFinal
            } else {
                State::Text
            },
            None => State::TextFinal
        }
    }

    fn to_space_state(&mut self, nch: Option<char>) -> State {
        match nch {
            Some(_nch) => if self.is_split_char(_nch) {
                State::Space
            } else {
                State::SpaceFinal
            },
            None => State::SpaceFinal
        }
    }

    fn to_another_state(&mut self, ch: char, nch: Option<char>) -> State {
        if self.is_split_char(ch) {
            self.to_space_state(nch)
        } else {
            self.to_text_state(nch)
        }
    }

    pub fn transit(&mut self, ch: char, nch: Option<char>) {
        match self.state {
            State::Init => {
                self.start = self.i;
                self.state = self.to_another_state(ch, nch)
            },
            State::Text => { self.state = self.to_another_state(ch, nch); },
            State::TextFinal => {
                self.start = self.i;
                self.state = self.to_space_state(nch);
            }
            State::SpaceFinal => {
                self.start = self.i;
                self.state = self.to_text_state(nch)
            }
            State::Space => if !self.is_split_char(ch) {
                self.state = self.to_another_state(ch, nch);
            }
        };
        self.i += 1;
    }

    pub fn is_text_final(&self) -> bool {
        self.state == State::TextFinal
    }

    pub fn is_space_final(&self) -> bool {
        self.state == State::SpaceFinal
    }
}<|endoftext|>


<commit_before>extern crate core;

use std::mem;
use std::fmt::Debug;
use std::vec::Vec;
use std::boxed::Box;
use std::collections::HashMap;
use std::collections::hash_map::Values;
use self::core::ops::RangeFull;

#[derive(Debug)]
pub struct QuadTree<S, T: Debug> {
    root: Node<S, T>
}

impl<S: Span<S, T> + Debug, T: Debug + Clone + PartialEq> QuadTree<S, T> {
    pub fn new(span: S) -> QuadTree<S, T> {
        return QuadTree { root: Node::new(span) };
    }

    pub fn add(&mut self, t: T) {
        self.ensure_contains(&t);
        self.root.add(t);
    }

    pub fn print(&self) {
        print!("root: ");
        self.root.print(1);
    }

    fn ensure_contains(&mut self, t: &T) {
        while !self.root.span.contains(&t) {
            let new_span = self.root.span.expand(&self.root.span.dir_of(&t).unwrap());
            let mut new_root = Node::new(new_span);
            for (dir, span) in new_root.span.split() {
                if span == self.root.span {
                    mem::swap(&mut self.root, &mut new_root);
                    self.root.size = new_root.size;
                    self.root.children.insert(dir.clone(), Child::Inner(Box::new(new_root)));
                    break;
                }
                // unreachable!();
            }
        }
    }

    pub fn scan(&self, span: &S) -> Vec<T> {
        return self.root.scan(span);
    }

    pub fn contains(&self, t: &T) -> bool {
        return self.root.contains(t);
    }

    pub fn size(&self) -> usize {
        return self.root.size;
    }

    pub fn size_actual(&self) -> usize {
        return self.root.size();
    }

    pub fn remove(&mut self, t: &T) -> usize {
        return self.root.remove(t);
    }

    /// Not implemented!
    pub fn nearest<F>(&self, t: &T, norm: F) where F: Fn(&T, &T) -> f32 {
        unimplemented!();
    }

    /// Not implemented!
    pub fn nearest_n<F>(&self, t: &T, n: i32, norm: F) where F: Fn(&T, &T) -> f32 {
        unimplemented!();
    }

    /// Not implemented!
    pub fn smallest_span(&self) -> S {
        unimplemented!();
    }

    /// Not implemented!
    pub fn replace_with(&self, old: &T, new: T) -> bool {
        unimplemented!();
    }

    /// Not implemented!
    pub fn rebalance(&self) {
        unimplemented!();
    }
}

#[derive(Debug)]
struct Node<S, T: Sized + Debug> {
    span: S,
    children: HashMap<Dir, Child<S, T>>,
    size: usize
}

impl<S: Span<S, T> + Debug, T: Debug + Clone + PartialEq> Node<S, T> {

    fn new(span: S) -> Node<S, T> {
        return Node {
            span: span,
            children: HashMap::new(),
            size: 0
        };
    }

    fn add(&mut self, t: T) {
        self.size += 1;
        let mut sub_spans = self.span.split();
        for (key, span) in sub_spans.drain() {
            if span.contains(&t) {
                let old_child = self.children.remove(&key);
                let new_child = self.new_child(span, old_child, t);
                self.children.insert(key, new_child);
                return;
            }
        }
        unreachable!("Tried to add {:?} to node with span {:?}", t, self.span);
    }

    fn new_child(&self, span: S, child: Option<Child<S, T>>, t: T) -> Child<S, T> {
        return match child {
            None => Child::Leaf(span, vec![t]),
            Some(c) => {
                match c {
                    Child::Leaf(span, mut v) => {
                        if v.len() > 1 && self.span.can_split() {
                            let mut new_node = Node::new(span);
                            for old_t in v.drain(RangeFull) {
                                new_node.add(old_t);
                            }
                            new_node.add(t);
                            Child::Inner(Box::new(new_node))
                        } else {
                            v.push(t);
                            Child::Leaf(span, v)
                        }
                    },
                    Child::Inner(mut b) => {
                        b.as_mut().add(t);
                        Child::Inner(b)
                    }
                }
            }
        };
    }

    fn print(&self, depth: usize) {
        println!("Node ({}) {:?}", self.size, self.span);
        let mut indent = String::new();
        for _ in 0..depth {
            indent.push_str(".   ");
        }
        for (key, child) in self.children.iter() {
            print!("{}{:?}: ", indent, key);
            match child {
                &Child::Inner(ref b) => b.as_ref().print(depth + 1),
                &Child::Leaf(_, ref v) => println!("{:?}", v),
            };
        }
    }

    fn scan(&self, span: &S) -> Vec<T> {
        if !self.span.overlaps(span) {
            return Vec::new();
        }
        let mut result: Vec<T> = Vec::new();
        for (_, child) in &self.children {
            match child {
                &Child::Leaf(_, ref v) => {
                    for t in v.iter().filter(|t| span.contains(&t)) {
                        result.push(t.clone());
                    }
                },
                &Child::Inner(ref b) => {
                    for t in b.as_ref().scan(span) {
                        result.push(t.clone());
                    }
                }
            };
        }
        return result;
    }

    fn contains(&self, t: &T) -> bool {
        if !self.span.contains(t) {
            return false;
        }
        for (_, child) in &self.children {
            match child {
                &Child::Leaf(_, ref v) => {
                    if v.contains(t) {
                        return true;
                    }
                },
                &Child::Inner(ref b) => {
                    if b.as_ref().contains(t) {
                        return true;
                    }
                }
            };
        }
        return false;
    }

    fn remove(&mut self, t: &T) -> usize {
        if !self.span.contains(t) {
            return 0;
        }

        for (_, child) in self.children.iter_mut() {
            let removed = match child {
                &mut Child::Leaf(_, ref mut v) => {
                    let mut i = 0;
                    let mut removed = 0;
                    while i < v.len() {
                        if v.get(i).unwrap() == t {
                            v.remove(i);
                            removed += 1;
                        } else {
                            i += 1;
                        }
                    }
                    removed
                },
                &mut Child::Inner(ref mut b) => {
                    b.as_mut().remove(t)
                }
            };
            if removed > 0 {
                return removed;
            }
        }
         return 0;
    }

    fn size(&self) -> usize {
        let mut result = 0;
        for (_, child) in &self.children {
            result += match child {
                &Child::Leaf(_, ref v) => v.len(),
                &Child::Inner(ref b) => b.as_ref().size()
            }
        };
        return result;
    }
}

#[derive(Debug)]
enum Child<S, T: Sized + Debug> {
    Inner(Box<Node<S, T>>),
    Leaf(S, Vec<T>)
}

#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Dir { N, S, E, W, NE, NW, SE, SW }

pub trait Span<S: Span<S, T>, T>: Clone + Eq + PartialEq {

    /// The direction of `t` in relation to `self`, or `None` if
    /// `self` `contains` `t`.
    fn dir_of(&self, t: &T) -> Option<Dir>;

    /// The span of equal size to the north of `self`.
    fn north_span(&self) -> S;

    /// The span of equal size to the south of `self`.
    fn south_span(&self) -> S;

    /// The span of equal size to the east of `self`.
    fn east_span(&self) -> S;

    /// The span of equal size to the west of `self`.
    fn west_span(&self) -> S;

    /// Returns the `S` in the given direction.
    fn span_at(&self, dir: &Dir) -> S {
        return match dir {
            &Dir::N => self.north_span(),
            &Dir::S => self.south_span(),
            &Dir::E => self.east_span(),
            &Dir::W => self.west_span(),
            &Dir::NE => self.north_span().east_span(),
            &Dir::NW => self.north_span().west_span(),
            &Dir::SE => self.south_span().east_span(),
            &Dir::SW => self.south_span().west_span()
        };
    }

    /// Returns a new `S` with double the size of `self` expanded
    /// in the direction `dir`.
    fn expand(&self, dir: &Dir) -> S;

    /// Returns a partition of `self` with four blocks.
    /// The partition of the result of `expand` must contain the
    /// original `S`.
    fn split(&self) -> HashMap<Dir, S>;

    /// Returns true if the span can be split, e.g., if the span is
    /// represented by integers and the width and height is larger than `1`.
    fn can_split(&self) -> bool;

    /// Not implemented!
    fn merge(spans: Values<Dir, S>) -> S;

    /// Returns `true` if `self` overlaps with `other`, otherwise `false`.
    /// Used for `QuadTree.scan`.
    fn overlaps(&self, other: &S) -> bool;

    /// Returns `true` if `self` contains `t`, otherwise `false`.
    fn contains(&self, t: &T) -> bool {
        return self.dir_of(t) == None;
    }
}
<commit_msg>Added comment on what variable size in Node was<commit_after>extern crate core;

use std::mem;
use std::fmt::Debug;
use std::vec::Vec;
use std::boxed::Box;
use std::collections::HashMap;
use std::collections::hash_map::Values;
use self::core::ops::RangeFull;

#[derive(Debug)]
pub struct QuadTree<S, T: Debug> {
    root: Node<S, T>
}

impl<S: Span<S, T> + Debug, T: Debug + Clone + PartialEq> QuadTree<S, T> {
    pub fn new(span: S) -> QuadTree<S, T> {
        return QuadTree { root: Node::new(span) };
    }

    pub fn add(&mut self, t: T) {
        self.ensure_contains(&t);
        self.root.add(t);
    }

    pub fn print(&self) {
        print!("root: ");
        self.root.print(1);
    }

    fn ensure_contains(&mut self, t: &T) {
        while !self.root.span.contains(&t) {
            let new_span = self.root.span.expand(&self.root.span.dir_of(&t).unwrap());
            let mut new_root = Node::new(new_span);
            for (dir, span) in new_root.span.split() {
                if span == self.root.span {
                    mem::swap(&mut self.root, &mut new_root);
                    self.root.size = new_root.size;
                    self.root.children.insert(dir.clone(), Child::Inner(Box::new(new_root)));
                    break;
                }
                // unreachable!();
            }
        }
    }

    pub fn scan(&self, span: &S) -> Vec<T> {
        return self.root.scan(span);
    }

    pub fn contains(&self, t: &T) -> bool {
        return self.root.contains(t);
    }

    pub fn size(&self) -> usize {
        return self.root.size;
    }

    pub fn size_actual(&self) -> usize {
        return self.root.size();
    }

    pub fn remove(&mut self, t: &T) -> usize {
        return self.root.remove(t);
    }

    /// Not implemented!
    pub fn nearest<F>(&self, t: &T, norm: F) where F: Fn(&T, &T) -> f32 {
        unimplemented!();
    }

    /// Not implemented!
    pub fn nearest_n<F>(&self, t: &T, n: i32, norm: F) where F: Fn(&T, &T) -> f32 {
        unimplemented!();
    }

    /// Not implemented!
    pub fn smallest_span(&self) -> S {
        unimplemented!();
    }

    /// Not implemented!
    pub fn replace_with(&self, old: &T, new: T) -> bool {
        unimplemented!();
    }

    /// Not implemented!
    pub fn rebalance(&self) {
        unimplemented!();
    }
}

#[derive(Debug)]
struct Node<S, T: Sized + Debug> {
    span: S,
    children: HashMap<Dir, Child<S, T>>,
    size: usize     // number of elements contained in the span
}

impl<S: Span<S, T> + Debug, T: Debug + Clone + PartialEq> Node<S, T> {

    fn new(span: S) -> Node<S, T> {
        return Node {
            span: span,
            children: HashMap::new(),
            size: 0
        };
    }

    fn add(&mut self, t: T) {
        self.size += 1;
        let mut sub_spans = self.span.split();
        for (key, span) in sub_spans.drain() {
            if span.contains(&t) {
                let old_child = self.children.remove(&key);
                let new_child = self.new_child(span, old_child, t);
                self.children.insert(key, new_child);
                return;
            }
        }
        unreachable!("Tried to add {:?} to node with span {:?}", t, self.span);
    }

    fn new_child(&self, span: S, child: Option<Child<S, T>>, t: T) -> Child<S, T> {
        return match child {
            None => Child::Leaf(span, vec![t]),
            Some(c) => {
                match c {
                    Child::Leaf(span, mut v) => {
                        if v.len() > 1 && self.span.can_split() {
                            let mut new_node = Node::new(span);
                            for old_t in v.drain(RangeFull) {
                                new_node.add(old_t);
                            }
                            new_node.add(t);
                            Child::Inner(Box::new(new_node))
                        } else {
                            v.push(t);
                            Child::Leaf(span, v)
                        }
                    },
                    Child::Inner(mut b) => {
                        b.as_mut().add(t);
                        Child::Inner(b)
                    }
                }
            }
        };
    }

    fn print(&self, depth: usize) {
        println!("Node ({}) {:?}", self.size, self.span);
        let mut indent = String::new();
        for _ in 0..depth {
            indent.push_str(".   ");
        }
        for (key, child) in self.children.iter() {
            print!("{}{:?}: ", indent, key);
            match child {
                &Child::Inner(ref b) => b.as_ref().print(depth + 1),
                &Child::Leaf(_, ref v) => println!("{:?}", v),
            };
        }
    }

    fn scan(&self, span: &S) -> Vec<T> {
        if !self.span.overlaps(span) {
            return Vec::new();
        }
        let mut result: Vec<T> = Vec::new();
        for (_, child) in &self.children {
            match child {
                &Child::Leaf(_, ref v) => {
                    for t in v.iter().filter(|t| span.contains(&t)) {
                        result.push(t.clone());
                    }
                },
                &Child::Inner(ref b) => {
                    for t in b.as_ref().scan(span) {
                        result.push(t.clone());
                    }
                }
            };
        }
        return result;
    }

    fn contains(&self, t: &T) -> bool {
        if !self.span.contains(t) {
            return false;
        }
        for (_, child) in &self.children {
            match child {
                &Child::Leaf(_, ref v) => {
                    if v.contains(t) {
                        return true;
                    }
                },
                &Child::Inner(ref b) => {
                    if b.as_ref().contains(t) {
                        return true;
                    }
                }
            };
        }
        return false;
    }

    fn remove(&mut self, t: &T) -> usize {
        if !self.span.contains(t) {
            return 0;
        }

        for (_, child) in self.children.iter_mut() {
            let removed = match child {
                &mut Child::Leaf(_, ref mut v) => {
                    let mut i = 0;
                    let mut removed = 0;
                    while i < v.len() {
                        if v.get(i).unwrap() == t {
                            v.remove(i);
                            removed += 1;
                        } else {
                            i += 1;
                        }
                    }
                    removed
                },
                &mut Child::Inner(ref mut b) => {
                    b.as_mut().remove(t)
                }
            };
            if removed > 0 {
                return removed;
            }
        }
         return 0;
    }

    fn size(&self) -> usize {
        let mut result = 0;
        for (_, child) in &self.children {
            result += match child {
                &Child::Leaf(_, ref v) => v.len(),
                &Child::Inner(ref b) => b.as_ref().size()
            }
        };
        return result;
    }
}

#[derive(Debug)]
enum Child<S, T: Sized + Debug> {
    Inner(Box<Node<S, T>>),
    Leaf(S, Vec<T>)
}

#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Dir { N, S, E, W, NE, NW, SE, SW }

pub trait Span<S: Span<S, T>, T>: Clone + Eq + PartialEq {

    /// The direction of `t` in relation to `self`, or `None` if
    /// `self` `contains` `t`.
    fn dir_of(&self, t: &T) -> Option<Dir>;

    /// The span of equal size to the north of `self`.
    fn north_span(&self) -> S;

    /// The span of equal size to the south of `self`.
    fn south_span(&self) -> S;

    /// The span of equal size to the east of `self`.
    fn east_span(&self) -> S;

    /// The span of equal size to the west of `self`.
    fn west_span(&self) -> S;

    /// Returns the `S` in the given direction.
    fn span_at(&self, dir: &Dir) -> S {
        return match dir {
            &Dir::N => self.north_span(),
            &Dir::S => self.south_span(),
            &Dir::E => self.east_span(),
            &Dir::W => self.west_span(),
            &Dir::NE => self.north_span().east_span(),
            &Dir::NW => self.north_span().west_span(),
            &Dir::SE => self.south_span().east_span(),
            &Dir::SW => self.south_span().west_span()
        };
    }

    /// Returns a new `S` with double the size of `self` expanded
    /// in the direction `dir`.
    fn expand(&self, dir: &Dir) -> S;

    /// Returns a partition of `self` with four blocks.
    /// The partition of the result of `expand` must contain the
    /// original `S`.
    fn split(&self) -> HashMap<Dir, S>;

    /// Returns true if the span can be split, e.g., if the span is
    /// represented by integers and the width and height is larger than `1`.
    fn can_split(&self) -> bool;

    /// Not implemented!
    fn merge(spans: Values<Dir, S>) -> S;

    /// Returns `true` if `self` overlaps with `other`, otherwise `false`.
    /// Used for `QuadTree.scan`.
    fn overlaps(&self, other: &S) -> bool;

    /// Returns `true` if `self` contains `t`, otherwise `false`.
    fn contains(&self, t: &T) -> bool {
        return self.dir_of(t) == None;
    }
}
<|endoftext|>


<commit_before>use std::f32;
use std::ops::Index;
use std::cmp::PartialOrd;
use {Vector, Point, lerp};
use na::Point3;
use ray::Ray;
use stats;
use num::Bounded;
use na::BaseNum;

pub type Bounds3f = Bounds3<f32>;

/// Axis Aligned Bounding Box
#[derive(Debug, Copy, Clone)]
pub struct Bounds3<T> {
    pub p_min: Point3<T>,
    pub p_max: Point3<T>,
}

impl<T> Bounds3<T>
    where T: BaseNum + Bounded + PartialOrd + Into<f32>
{
    pub fn new() -> Bounds3<T> {
        let min = T::min_value();
        let max = T::max_value();
        Bounds3 {
            p_min: Point3::new(max, max, max),
            p_max: Point3::new(min, min, min),
        }
    }

    pub fn from_point(point: &Point3<T>) -> Bounds3<T> {
        Bounds3 {
            p_min: *point,
            p_max: *point,
        }
    }

    pub fn from_points(min: &Point3<T>, max: &Point3<T>) -> Bounds3<T> {
        assert!(min.x <= max.x && min.y <= max.y && min.z <= max.z,
                "Invalid bounds");
        Bounds3 {
            p_min: *min,
            p_max: *max,
        }
    }

    pub fn corner(&self, corner: usize) -> Point3<T> {
        Point3::new(self[corner & 1].x,
                    self[if corner & 2 != 0 { 1 } else { 0 }].y,
                    self[if corner & 4 != 0 { 1 } else { 0 }].y)
    }

    pub fn extend(&mut self, p: Point3<T>) {
        if p.x < self.p_min.x {
            self.p_min.x = p.x
        }
        if p.y < self.p_min.y {
            self.p_min.y = p.y
        }
        if p.z < self.p_min.z {
            self.p_min.z = p.z
        }
        if p.x > self.p_max.x {
            self.p_max.x = p.x
        }
        if p.y > self.p_max.y {
            self.p_max.y = p.y
        }
        if p.z > self.p_max.z {
            self.p_max.z = p.z
        }
    }

    pub fn maximum_extent(&self) -> Axis {
        let v = self.p_max - self.p_min;
        if v.x > v.y {
            if v.x > v.z { Axis::X } else { Axis::Z }
        } else if v.y > v.z {
            Axis::Y
        } else {
            Axis::Z
        }
    }

    pub fn union(bbox1: &Bounds3<T>, bbox2: &Bounds3<T>) -> Bounds3<T> {
        let min = Point3::new(min(bbox1.p_min.x, bbox2.p_min.x),
                              min(bbox1.p_min.y, bbox2.p_min.y),
                              min(bbox1.p_min.z, bbox2.p_min.z));
        let max = Point3::new(max(bbox1.p_max.x, bbox2.p_max.x),
                              max(bbox1.p_max.y, bbox2.p_max.y),
                              max(bbox1.p_max.z, bbox2.p_max.z));

        Bounds3 {
            p_min: min,
            p_max: max,
        }
    }

    pub fn union_point(bbox: &Bounds3<T>, p: &Point3<T>) -> Bounds3<T> {
        let mut b = *bbox;
        b.extend(*p);
        b
    }

    pub fn intersect_p(&self, ray: &mut Ray) -> bool {
        let invdir = Vector::new(1.0 / ray.d.x, 1.0 / ray.d.y, 1.0 / ray.d.z);
        let sign = [(ray.d.x < 0.0) as usize, (ray.d.y < 0.0) as usize, (ray.d.z < 0.0) as usize];

        self.intersect_p_fast(ray, &invdir, &sign)
    }

    pub fn intersect_p_fast(&self,
                            ray: &mut Ray,
                            inv_dir: &Vector,
                            dir_is_neg: &[usize; 3])
                            -> bool {
        stats::inc_fast_bbox_isect();
        // Check intersection with X and Y slab
        let mut tmin = (self[dir_is_neg[0]].x.into() - ray.o.x) * inv_dir.x;
        let mut tmax = (self[1 - dir_is_neg[0]].x.into() - ray.o.x) * inv_dir.x;
        let tymin = (self[dir_is_neg[1]].y.into() - ray.o.y) * inv_dir.y;
        let tymax = (self[1 - dir_is_neg[1]].y.into() - ray.o.y) * inv_dir.y;
        if (tmin > tymax) || (tymin > tmax) {
            return false;
        }
        if tymin > tmin {
            tmin = tymin;
        }
        if tymax < tmax {
            tmax = tymax;
        }
        // Check intersection with Z slab
        let tzmin = (self[dir_is_neg[2]].z.into() - ray.o.z) * inv_dir.z;
        let tzmax = (self[1 - dir_is_neg[2]].z.into() - ray.o.z) * inv_dir.z;
        if (tmin > tzmax) || (tzmin > tmax) {
            return false;
        }
        if tzmin > tmin {
            tmin = tzmin;
        }
        if tzmax < tmax {
            tmax = tzmax;
        }

        tmin < ray.t_max && tmax > ray.t_min
    }

    /// Linearly interpolate a point inside the bounds
    pub fn lerp(&self, t: &Point3<T>) -> Point3<T> {
        Point3::new(lerp(t.x, self.p_min.x, self.p_max.x),
                    lerp(t.y, self.p_min.y, self.p_max.y),
                    lerp(t.z, self.p_min.z, self.p_max.z))
    }
}

impl<T> Index<usize> for Bounds3<T> {
    type Output = Point3<T>;

    fn index(&self, i: usize) -> &Point3<T> {
        match i {
            0 => &self.p_min,
            1 => &self.p_max,
            _ => panic!("Invalid index!"),
        }
    }
}

fn min<T: PartialOrd>(a: T, b: T) -> T {
    if a.lt(&b) { a } else { b }
}

fn max<T: PartialOrd>(a: T, b: T) -> T {
    if a.gt(&b) { a } else { b }
}

#[derive(Copy, Clone, Debug)]
pub enum Axis {
    X,
    Y,
    Z,
}

impl Index<Axis> for Point3<f32> {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        match axis {
            Axis::X => &self.x,
            Axis::Y => &self.y,
            Axis::Z => &self.z,
        }
    }
}
<commit_msg>Add Bounds::bounding_sphere<commit_after>use std::f32;
use std::ops::Index;
use std::cmp::PartialOrd;
use {Vector, Point, lerp};
use na::{Point3, Norm};
use ray::Ray;
use stats;
use num::Bounded;
use na::BaseNum;

pub type Bounds3f = Bounds3<f32>;

/// Axis Aligned Bounding Box
#[derive(Debug, Copy, Clone)]
pub struct Bounds3<T> {
    pub p_min: Point3<T>,
    pub p_max: Point3<T>,
}

impl<T> Bounds3<T>
    where T: BaseNum + Bounded + PartialOrd + Into<f32>
{
    pub fn new() -> Bounds3<T> {
        let min = T::min_value();
        let max = T::max_value();
        Bounds3 {
            p_min: Point3::new(max, max, max),
            p_max: Point3::new(min, min, min),
        }
    }

    pub fn from_point(point: &Point3<T>) -> Bounds3<T> {
        Bounds3 {
            p_min: *point,
            p_max: *point,
        }
    }

    pub fn from_points(min: &Point3<T>, max: &Point3<T>) -> Bounds3<T> {
        assert!(min.x <= max.x && min.y <= max.y && min.z <= max.z,
                "Invalid bounds");
        Bounds3 {
            p_min: *min,
            p_max: *max,
        }
    }

    pub fn corner(&self, corner: usize) -> Point3<T> {
        Point3::new(self[corner & 1].x,
                    self[if corner & 2 != 0 { 1 } else { 0 }].y,
                    self[if corner & 4 != 0 { 1 } else { 0 }].y)
    }

    pub fn extend(&mut self, p: Point3<T>) {
        if p.x < self.p_min.x {
            self.p_min.x = p.x
        }
        if p.y < self.p_min.y {
            self.p_min.y = p.y
        }
        if p.z < self.p_min.z {
            self.p_min.z = p.z
        }
        if p.x > self.p_max.x {
            self.p_max.x = p.x
        }
        if p.y > self.p_max.y {
            self.p_max.y = p.y
        }
        if p.z > self.p_max.z {
            self.p_max.z = p.z
        }
    }

    pub fn maximum_extent(&self) -> Axis {
        let v = self.p_max - self.p_min;
        if v.x > v.y {
            if v.x > v.z { Axis::X } else { Axis::Z }
        } else if v.y > v.z {
            Axis::Y
        } else {
            Axis::Z
        }
    }

    pub fn union(bbox1: &Bounds3<T>, bbox2: &Bounds3<T>) -> Bounds3<T> {
        let min = Point3::new(min(bbox1.p_min.x, bbox2.p_min.x),
                              min(bbox1.p_min.y, bbox2.p_min.y),
                              min(bbox1.p_min.z, bbox2.p_min.z));
        let max = Point3::new(max(bbox1.p_max.x, bbox2.p_max.x),
                              max(bbox1.p_max.y, bbox2.p_max.y),
                              max(bbox1.p_max.z, bbox2.p_max.z));

        Bounds3 {
            p_min: min,
            p_max: max,
        }
    }

    pub fn union_point(bbox: &Bounds3<T>, p: &Point3<T>) -> Bounds3<T> {
        let mut b = *bbox;
        b.extend(*p);
        b
    }

    pub fn intersect_p(&self, ray: &mut Ray) -> bool {
        let invdir = Vector::new(1.0 / ray.d.x, 1.0 / ray.d.y, 1.0 / ray.d.z);
        let sign = [(ray.d.x < 0.0) as usize, (ray.d.y < 0.0) as usize, (ray.d.z < 0.0) as usize];

        self.intersect_p_fast(ray, &invdir, &sign)
    }

    pub fn intersect_p_fast(&self,
                            ray: &mut Ray,
                            inv_dir: &Vector,
                            dir_is_neg: &[usize; 3])
                            -> bool {
        stats::inc_fast_bbox_isect();
        // Check intersection with X and Y slab
        let mut tmin = (self[dir_is_neg[0]].x.into() - ray.o.x) * inv_dir.x;
        let mut tmax = (self[1 - dir_is_neg[0]].x.into() - ray.o.x) * inv_dir.x;
        let tymin = (self[dir_is_neg[1]].y.into() - ray.o.y) * inv_dir.y;
        let tymax = (self[1 - dir_is_neg[1]].y.into() - ray.o.y) * inv_dir.y;
        if (tmin > tymax) || (tymin > tmax) {
            return false;
        }
        if tymin > tmin {
            tmin = tymin;
        }
        if tymax < tmax {
            tmax = tymax;
        }
        // Check intersection with Z slab
        let tzmin = (self[dir_is_neg[2]].z.into() - ray.o.z) * inv_dir.z;
        let tzmax = (self[1 - dir_is_neg[2]].z.into() - ray.o.z) * inv_dir.z;
        if (tmin > tzmax) || (tzmin > tmax) {
            return false;
        }
        if tzmin > tmin {
            tmin = tzmin;
        }
        if tzmax < tmax {
            tmax = tzmax;
        }

        tmin < ray.t_max && tmax > ray.t_min
    }

    /// Linearly interpolate a point inside the bounds
    pub fn lerp(&self, t: &Point3<T>) -> Point3<T> {
        Point3::new(lerp(t.x, self.p_min.x, self.p_max.x),
                    lerp(t.y, self.p_min.y, self.p_max.y),
                    lerp(t.z, self.p_min.z, self.p_max.z))
    }

    pub fn inside(&self, p: &Point3<T>) -> bool {
        p.x >= self.p_min.x && p.x <= self.p_max.x && p.y >= self.p_min.y &&
        p.y <= self.p_max.y && p.z >= self.p_min.z && p.z <= self.p_max.z
    }
}

impl Bounds3<f32> {
    /// Compute the bounding sphere of the current bounding box, and returns its center and radius.
    pub fn bounding_sphere(&self) -> (Point, f32) {
        let center = Point::new((self.p_min.x + self.p_max.x) / 2.0,
                                (self.p_min.y + self.p_max.y) / 2.0,
                                (self.p_min.z + self.p_max.z) / 2.0);
        let radius = if self.inside(&center) {
            (self.p_max - center).norm()
        } else {
            0.0
        };

        (center, radius)
    }
}

impl<T> Index<usize> for Bounds3<T> {
    type Output = Point3<T>;

    fn index(&self, i: usize) -> &Point3<T> {
        match i {
            0 => &self.p_min,
            1 => &self.p_max,
            _ => panic!("Invalid index!"),
        }
    }
}

fn min<T: PartialOrd>(a: T, b: T) -> T {
    if a.lt(&b) { a } else { b }
}

fn max<T: PartialOrd>(a: T, b: T) -> T {
    if a.gt(&b) { a } else { b }
}

#[derive(Copy, Clone, Debug)]
pub enum Axis {
    X,
    Y,
    Z,
}

impl Index<Axis> for Point3<f32> {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        match axis {
            Axis::X => &self.x,
            Axis::Y => &self.y,
            Axis::Z => &self.z,
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::iter::IntoIterator;
use std::sync::Arc;

use bsp;
use engine;

use vulkano::buffer::BufferAccess;
use vulkano::buffer::BufferSlice;
use vulkano::buffer::BufferUsage;
use vulkano::buffer::ImmutableBuffer;
use vulkano::command_buffer::AutoCommandBuffer;
use vulkano::command_buffer::AutoCommandBufferBuilder;
use vulkano::command_buffer::DynamicState;
use vulkano::descriptor::PipelineLayoutAbstract;
use vulkano::descriptor::descriptor_set::FixedSizeDescriptorSetsPool;
use vulkano::device::Device;
use vulkano::device::Queue;
use vulkano::format::R8G8B8A8Unorm;
use vulkano::framebuffer::RenderPassAbstract;
use vulkano::framebuffer::Subpass;
use vulkano::image::Dimensions;
use vulkano::image::ImmutableImage;
use vulkano::image::ImageViewAccess;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::pipeline::GraphicsPipelineAbstract;
use vulkano::pipeline::viewport::Viewport;
use vulkano::sampler::Sampler;
use vulkano::sync::GpuFuture;

//   | +z                 | -y
//   |                    |
//   |_____ -y Quake ->   |_____ +x Vulkan
//   /                    /
//  /                    /
// / +x                 / -z
//
// Quake  [x, y, z] <-> [-z, -x, -y] Vulkan
// Vulkan [x, y, z] <-> [ y, -z, -x] Quake

mod vs {
    #[derive(VulkanoShader)]
    #[ty = "vertex"]
    #[src = "
    #version 450

    layout (location = 0) in vec3 v_position;

    layout (location = 0) out vec2 f_texcoord;

    layout (push_constant) uniform PushConstants {
        mat4 u_projection;
        vec3 s_vector;
        float s_offset;
        vec3 t_vector;
        float t_offset;
        float tex_w;
        float tex_h;
    } push_constants;

    vec3 quake_to_vulkan(vec3 v) {
        return vec3(-v.y, -v.z, -v.x);
    }

    void main() {
        f_texcoord = vec2(
            (dot(v_position, push_constants.s_vector) + push_constants.s_offset)
                / push_constants.tex_w,
            (dot(v_position, push_constants.t_vector) + push_constants.t_offset)
                / push_constants.tex_h
        );
        gl_Position = push_constants.u_projection * vec4(quake_to_vulkan(v_position), 1.0);
    }
    "]
    struct Dummy;
}

mod fs {
    #[derive(VulkanoShader)]
    #[ty = "fragment"]
    #[src = "
    #version 450

    layout (location = 0) in vec2 f_texcoord;

    layout (location = 0) out vec4 out_color;

    layout (set = 0, binding = 0) uniform sampler2D u_sampler;

    layout (push_constant) uniform PushConstants {
        mat4 u_projection;
        vec3 s_vector;
        float s_offset;
        vec3 t_vector;
        float t_offset;
        float tex_w;
        float tex_h;
    } push_constants;

    void main() {
        out_color = texture(u_sampler, f_texcoord);
    }"]
    struct Dummy;
}

type VkBspPlane = bsp::BspPlane;

struct VkBspTexture {
    img: Arc<ImmutableImage<R8G8B8A8Unorm>>,
    next: Option<usize>,
}

struct VkBspVertex {
    v_position: [f32; 3],
}
impl_vertex!(VkBspVertex, v_position);

type VkBspNodeChild = bsp::BspNodeChild;
type VkBspNode = bsp::BspNode;
type VkBspTexInfo = bsp::BspTexInfo;
type VkBspFaceSide = bsp::BspFaceSide;

struct VkBspFace {
    plane_id: usize,
    side: VkBspFaceSide,
    index_slice: Arc<BufferSlice<[u32], Arc<ImmutableBuffer<[u32]>>>>,
    texinfo_id: usize,
    light_styles: [u8; bsp::MAX_LIGHTSTYLES],
    lightmap_id: Option<usize>,
}

type VkBspClipNodeCollision = bsp::BspClipNodeCollision;
type VkBspClipNode = bsp::BspClipNode;
type VkBspLeaf = bsp::BspLeaf;
type VkBspModel = bsp::BspModel;

pub struct VkBsp {
    entities: Vec<HashMap<String, String>>,
    planes: Vec<VkBspPlane>,
    textures: Vec<VkBspTexture>,
    vertex_buffer: Arc<ImmutableBuffer<[VkBspVertex]>>,
    index_buffer: Arc<ImmutableBuffer<[u32]>>,
    visibility: Vec<u8>,
    nodes: Vec<VkBspNode>,
    texinfo: Vec<VkBspTexInfo>,
    faces: Vec<VkBspFace>,
    lightmaps: Vec<u8>,
    clipnodes: Vec<VkBspClipNode>,
    leaves: Vec<VkBspLeaf>,
    facelist: Vec<usize>,
    queue: Arc<Queue>,
    pipeline: Arc<GraphicsPipelineAbstract + Send + Sync>,
    vertex_shader: vs::Shader,
    fragment_shader: fs::Shader,
    sampler: Arc<Sampler>,
}

impl VkBsp {
    pub fn new<R>(
        bsp: bsp::Bsp,
        queue: Arc<Queue>,
        subpass: Subpass<R>,
        sampler: Arc<Sampler>,
    ) -> Result<VkBsp, bsp::BspError>
    where
        R: RenderPassAbstract + Send + Sync + 'static,
    {
        let device = queue.device();
        let mut textures: Vec<VkBspTexture> = Vec::new();

        for tex in bsp.textures.iter() {
            let rgba = engine::indexed_to_rgba(&tex.mipmaps[0]);

            // TODO: currently does not support mipmaps
            let (img, img_future) = ImmutableImage::from_iter(
                rgba.into_iter(),
                Dimensions::Dim2d {
                    width: tex.width as u32,
                    height: tex.height as u32,
                },
                R8G8B8A8Unorm,
                queue.clone(),
            ).unwrap();

            // TODO: chain these futures
            img_future.flush().expect(
                "Failed to flush texture creation operations",
            );

            textures.push(VkBspTexture {
                img: img,
                next: tex.next,
            });
        }

        let (vertex_buffer, vb_future) =
            ImmutableBuffer::from_iter(
                bsp.vertices.iter().map(|&v| VkBspVertex { v_position: v }),
                BufferUsage::vertex_buffer(),
                queue.clone(),
            ).unwrap();

        vb_future.flush().expect(
            "Failed to flush vertex buffer creation",
        );

        let (index_buffer, ib_future) = ImmutableBuffer::from_iter(
            bsp.edgelist.iter().map(|ref e| {
                bsp.edges[e.index].vertex_ids[match e.direction {
                                                  bsp::BspEdgeDirection::Forward => 0,
                                                  bsp::BspEdgeDirection::Backward => 1,
                                              }] as u32
            }),
            BufferUsage::index_buffer(),
            queue.clone(),
        ).unwrap();

        ib_future.flush().expect(
            "Failed to flush index buffer creation",
        );

        let mut faces = Vec::new();
        for face in bsp.faces.iter() {
            faces.push(VkBspFace {
                plane_id: face.plane_id,
                side: face.side,
                index_slice: Arc::new(
                    BufferSlice::from(index_buffer.clone().into_buffer_slice())
                        .slice(face.edge_id..face.edge_id + face.edge_count)
                        .unwrap(),
                ),
                texinfo_id: face.texinfo_id,
                light_styles: face.light_styles,
                lightmap_id: face.lightmap_id,
            });
        }

        let vertex_shader = vs::Shader::load(device.clone()).unwrap();
        let fragment_shader = fs::Shader::load(device.clone()).unwrap();

        let pipeline = Arc::new(
            GraphicsPipeline::start()
                .vertex_input_single_buffer::<VkBspVertex>()
                .vertex_shader(vertex_shader.main_entry_point(), ())
                .triangle_fan()
                .viewports_dynamic_scissors_irrelevant(1)
                .fragment_shader(fragment_shader.main_entry_point(), ())
                .depth_stencil_simple_depth()
                .front_face_clockwise()
                .cull_mode_back()
                .render_pass(subpass)
                .build(device.clone())
                .expect("Failed to create graphics pipeline"),
        );

        Ok(VkBsp {
            entities: bsp.entities,
            planes: bsp.planes,
            textures: textures,
            vertex_buffer: vertex_buffer.clone(),
            index_buffer: index_buffer.clone(),
            visibility: bsp.visibility,
            nodes: bsp.nodes,
            texinfo: bsp.texinfo,
            faces: faces,
            lightmaps: bsp.lightmaps,
            clipnodes: bsp.clipnodes,
            leaves: bsp.leaves,
            facelist: bsp.facelist,
            queue: queue.clone(),
            pipeline: pipeline,
            vertex_shader: vs::Shader::load(device.clone()).unwrap(),
            fragment_shader: fs::Shader::load(device.clone()).unwrap(),
            sampler: sampler.clone(),
        })
    }

    pub fn draw_naive<R>(
        &mut self,
        viewport_dimensions: [u32; 2],
        projection_matrix: [[f32; 4]; 4],
        render_pass: Subpass<R>,
    ) -> AutoCommandBuffer
    where
        R: RenderPassAbstract + Clone + Send + Sync + 'static,
    {
        let mut push_constants = vs::ty::PushConstants {
            u_projection: [[0.0; 4]; 4],
            s_vector: [0.0; 3],
            s_offset: 0.0,
            t_vector: [0.0; 3],
            t_offset: 0.0,
            tex_w: 0.0,
            tex_h: 0.0,
        };

        let dynamic_state = DynamicState {
            line_width: None,
            viewports: Some(vec![
                Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [viewport_dimensions[0] as f32, viewport_dimensions[1] as f32],
                    depth_range: 0.0..1.0,
                },
            ]),
            scissors: None,
        };

        let mut cmd_buf_builder = AutoCommandBufferBuilder::secondary_graphics_one_time_submit(
            self.queue.device().clone(),
            self.queue.family(),
            render_pass,
        ).unwrap();

        let mut descriptor_pool = FixedSizeDescriptorSetsPool::new(self.pipeline.clone(), 0);

        for face in self.faces.iter() {
            let texinfo = &self.texinfo[face.texinfo_id];
            let tex_dimensions = &self.textures[texinfo.tex_id].img.dimensions();
            push_constants.u_projection = projection_matrix;
            push_constants.s_vector = texinfo.s_vector;
            push_constants.s_offset = texinfo.s_offset;
            push_constants.t_vector = texinfo.t_vector;
            push_constants.t_offset = texinfo.t_offset;
            push_constants.tex_w = tex_dimensions.width() as f32;
            push_constants.tex_h = tex_dimensions.height() as f32;

            let descriptor_set = descriptor_pool
                .next()
                .add_sampled_image(
                    self.textures[texinfo.tex_id].img.clone(),
                    self.sampler.clone(),
                )
                .unwrap()
                .build()
                .unwrap();

            cmd_buf_builder = cmd_buf_builder
                .draw_indexed(
                    self.pipeline.clone(),
                    dynamic_state.clone(),
                    vec![self.vertex_buffer.clone()],
                    face.index_slice.clone(),
                    descriptor_set,
                    push_constants,
                )
                .unwrap()
                .end_render_pass()
                .unwrap();
        }

        cmd_buf_builder.build().unwrap()
    }
}
<commit_msg>Remove unused imports in bsp/vk.rs<commit_after>use std::collections::HashMap;
use std::iter::IntoIterator;
use std::sync::Arc;

use bsp;
use engine;

use vulkano::buffer::BufferAccess;
use vulkano::buffer::BufferSlice;
use vulkano::buffer::BufferUsage;
use vulkano::buffer::ImmutableBuffer;
use vulkano::command_buffer::AutoCommandBuffer;
use vulkano::command_buffer::AutoCommandBufferBuilder;
use vulkano::command_buffer::DynamicState;
use vulkano::descriptor::descriptor_set::FixedSizeDescriptorSetsPool;
use vulkano::device::Queue;
use vulkano::format::R8G8B8A8Unorm;
use vulkano::framebuffer::RenderPassAbstract;
use vulkano::framebuffer::Subpass;
use vulkano::image::Dimensions;
use vulkano::image::ImmutableImage;
use vulkano::image::ImageViewAccess;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::pipeline::GraphicsPipelineAbstract;
use vulkano::pipeline::viewport::Viewport;
use vulkano::sampler::Sampler;
use vulkano::sync::GpuFuture;

//   | +z                 | -y
//   |                    |
//   |_____ -y Quake ->   |_____ +x Vulkan
//   /                    /
//  /                    /
// / +x                 / -z
//
// Quake  [x, y, z] <-> [-z, -x, -y] Vulkan
// Vulkan [x, y, z] <-> [ y, -z, -x] Quake

mod vs {
    #[derive(VulkanoShader)]
    #[ty = "vertex"]
    #[src = "
    #version 450

    layout (location = 0) in vec3 v_position;

    layout (location = 0) out vec2 f_texcoord;

    layout (push_constant) uniform PushConstants {
        mat4 u_projection;
        vec3 s_vector;
        float s_offset;
        vec3 t_vector;
        float t_offset;
        float tex_w;
        float tex_h;
    } push_constants;

    vec3 quake_to_vulkan(vec3 v) {
        return vec3(-v.y, -v.z, -v.x);
    }

    void main() {
        f_texcoord = vec2(
            (dot(v_position, push_constants.s_vector) + push_constants.s_offset)
                / push_constants.tex_w,
            (dot(v_position, push_constants.t_vector) + push_constants.t_offset)
                / push_constants.tex_h
        );
        gl_Position = push_constants.u_projection * vec4(quake_to_vulkan(v_position), 1.0);
    }
    "]
    struct Dummy;
}

mod fs {
    #[derive(VulkanoShader)]
    #[ty = "fragment"]
    #[src = "
    #version 450

    layout (location = 0) in vec2 f_texcoord;

    layout (location = 0) out vec4 out_color;

    layout (set = 0, binding = 0) uniform sampler2D u_sampler;

    layout (push_constant) uniform PushConstants {
        mat4 u_projection;
        vec3 s_vector;
        float s_offset;
        vec3 t_vector;
        float t_offset;
        float tex_w;
        float tex_h;
    } push_constants;

    void main() {
        out_color = texture(u_sampler, f_texcoord);
    }"]
    struct Dummy;
}

type VkBspPlane = bsp::BspPlane;

struct VkBspTexture {
    img: Arc<ImmutableImage<R8G8B8A8Unorm>>,
    next: Option<usize>,
}

struct VkBspVertex {
    v_position: [f32; 3],
}
impl_vertex!(VkBspVertex, v_position);

type VkBspNodeChild = bsp::BspNodeChild;
type VkBspNode = bsp::BspNode;
type VkBspTexInfo = bsp::BspTexInfo;
type VkBspFaceSide = bsp::BspFaceSide;

struct VkBspFace {
    plane_id: usize,
    side: VkBspFaceSide,
    index_slice: Arc<BufferSlice<[u32], Arc<ImmutableBuffer<[u32]>>>>,
    texinfo_id: usize,
    light_styles: [u8; bsp::MAX_LIGHTSTYLES],
    lightmap_id: Option<usize>,
}

type VkBspClipNodeCollision = bsp::BspClipNodeCollision;
type VkBspClipNode = bsp::BspClipNode;
type VkBspLeaf = bsp::BspLeaf;
type VkBspModel = bsp::BspModel;

pub struct VkBsp {
    entities: Vec<HashMap<String, String>>,
    planes: Vec<VkBspPlane>,
    textures: Vec<VkBspTexture>,
    vertex_buffer: Arc<ImmutableBuffer<[VkBspVertex]>>,
    index_buffer: Arc<ImmutableBuffer<[u32]>>,
    visibility: Vec<u8>,
    nodes: Vec<VkBspNode>,
    texinfo: Vec<VkBspTexInfo>,
    faces: Vec<VkBspFace>,
    lightmaps: Vec<u8>,
    clipnodes: Vec<VkBspClipNode>,
    leaves: Vec<VkBspLeaf>,
    facelist: Vec<usize>,
    queue: Arc<Queue>,
    pipeline: Arc<GraphicsPipelineAbstract + Send + Sync>,
    vertex_shader: vs::Shader,
    fragment_shader: fs::Shader,
    sampler: Arc<Sampler>,
}

impl VkBsp {
    pub fn new<R>(
        bsp: bsp::Bsp,
        queue: Arc<Queue>,
        subpass: Subpass<R>,
        sampler: Arc<Sampler>,
    ) -> Result<VkBsp, bsp::BspError>
    where
        R: RenderPassAbstract + Send + Sync + 'static,
    {
        let device = queue.device();
        let mut textures: Vec<VkBspTexture> = Vec::new();

        for tex in bsp.textures.iter() {
            let rgba = engine::indexed_to_rgba(&tex.mipmaps[0]);

            // TODO: currently does not support mipmaps
            let (img, img_future) = ImmutableImage::from_iter(
                rgba.into_iter(),
                Dimensions::Dim2d {
                    width: tex.width as u32,
                    height: tex.height as u32,
                },
                R8G8B8A8Unorm,
                queue.clone(),
            ).unwrap();

            // TODO: chain these futures
            img_future.flush().expect(
                "Failed to flush texture creation operations",
            );

            textures.push(VkBspTexture {
                img: img,
                next: tex.next,
            });
        }

        let (vertex_buffer, vb_future) =
            ImmutableBuffer::from_iter(
                bsp.vertices.iter().map(|&v| VkBspVertex { v_position: v }),
                BufferUsage::vertex_buffer(),
                queue.clone(),
            ).unwrap();

        vb_future.flush().expect(
            "Failed to flush vertex buffer creation",
        );

        let (index_buffer, ib_future) = ImmutableBuffer::from_iter(
            bsp.edgelist.iter().map(|ref e| {
                bsp.edges[e.index].vertex_ids[match e.direction {
                                                  bsp::BspEdgeDirection::Forward => 0,
                                                  bsp::BspEdgeDirection::Backward => 1,
                                              }] as u32
            }),
            BufferUsage::index_buffer(),
            queue.clone(),
        ).unwrap();

        ib_future.flush().expect(
            "Failed to flush index buffer creation",
        );

        let mut faces = Vec::new();
        for face in bsp.faces.iter() {
            faces.push(VkBspFace {
                plane_id: face.plane_id,
                side: face.side,
                index_slice: Arc::new(
                    BufferSlice::from(index_buffer.clone().into_buffer_slice())
                        .slice(face.edge_id..face.edge_id + face.edge_count)
                        .unwrap(),
                ),
                texinfo_id: face.texinfo_id,
                light_styles: face.light_styles,
                lightmap_id: face.lightmap_id,
            });
        }

        let vertex_shader = vs::Shader::load(device.clone()).unwrap();
        let fragment_shader = fs::Shader::load(device.clone()).unwrap();

        let pipeline = Arc::new(
            GraphicsPipeline::start()
                .vertex_input_single_buffer::<VkBspVertex>()
                .vertex_shader(vertex_shader.main_entry_point(), ())
                .triangle_fan()
                .viewports_dynamic_scissors_irrelevant(1)
                .fragment_shader(fragment_shader.main_entry_point(), ())
                .depth_stencil_simple_depth()
                .front_face_clockwise()
                .cull_mode_back()
                .render_pass(subpass)
                .build(device.clone())
                .expect("Failed to create graphics pipeline"),
        );

        Ok(VkBsp {
            entities: bsp.entities,
            planes: bsp.planes,
            textures: textures,
            vertex_buffer: vertex_buffer.clone(),
            index_buffer: index_buffer.clone(),
            visibility: bsp.visibility,
            nodes: bsp.nodes,
            texinfo: bsp.texinfo,
            faces: faces,
            lightmaps: bsp.lightmaps,
            clipnodes: bsp.clipnodes,
            leaves: bsp.leaves,
            facelist: bsp.facelist,
            queue: queue.clone(),
            pipeline: pipeline,
            vertex_shader: vs::Shader::load(device.clone()).unwrap(),
            fragment_shader: fs::Shader::load(device.clone()).unwrap(),
            sampler: sampler.clone(),
        })
    }

    pub fn draw_naive<R>(
        &mut self,
        viewport_dimensions: [u32; 2],
        projection_matrix: [[f32; 4]; 4],
        render_pass: Subpass<R>,
    ) -> AutoCommandBuffer
    where
        R: RenderPassAbstract + Clone + Send + Sync + 'static,
    {
        let mut push_constants = vs::ty::PushConstants {
            u_projection: [[0.0; 4]; 4],
            s_vector: [0.0; 3],
            s_offset: 0.0,
            t_vector: [0.0; 3],
            t_offset: 0.0,
            tex_w: 0.0,
            tex_h: 0.0,
        };

        let dynamic_state = DynamicState {
            line_width: None,
            viewports: Some(vec![
                Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [viewport_dimensions[0] as f32, viewport_dimensions[1] as f32],
                    depth_range: 0.0..1.0,
                },
            ]),
            scissors: None,
        };

        let mut cmd_buf_builder = AutoCommandBufferBuilder::secondary_graphics_one_time_submit(
            self.queue.device().clone(),
            self.queue.family(),
            render_pass,
        ).unwrap();

        let mut descriptor_pool = FixedSizeDescriptorSetsPool::new(self.pipeline.clone(), 0);

        for face in self.faces.iter() {
            let texinfo = &self.texinfo[face.texinfo_id];
            let tex_dimensions = &self.textures[texinfo.tex_id].img.dimensions();
            push_constants.u_projection = projection_matrix;
            push_constants.s_vector = texinfo.s_vector;
            push_constants.s_offset = texinfo.s_offset;
            push_constants.t_vector = texinfo.t_vector;
            push_constants.t_offset = texinfo.t_offset;
            push_constants.tex_w = tex_dimensions.width() as f32;
            push_constants.tex_h = tex_dimensions.height() as f32;

            let descriptor_set = descriptor_pool
                .next()
                .add_sampled_image(
                    self.textures[texinfo.tex_id].img.clone(),
                    self.sampler.clone(),
                )
                .unwrap()
                .build()
                .unwrap();

            cmd_buf_builder = cmd_buf_builder
                .draw_indexed(
                    self.pipeline.clone(),
                    dynamic_state.clone(),
                    vec![self.vertex_buffer.clone()],
                    face.index_slice.clone(),
                    descriptor_set,
                    push_constants,
                )
                .unwrap()
                .end_render_pass()
                .unwrap();
        }

        cmd_buf_builder.build().unwrap()
    }
}
<|endoftext|>