aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2016-06-13 23:09:21 -0400
committerbnewbold <bnewbold@robocracy.org>2016-06-13 23:09:21 -0400
commit4fb57de0201eaecdafffdcc285e7dc3ef9d4f6d8 (patch)
tree4e54dd2c8c394628ae271965d83a1723a63cecb5
parenta1879491613bfb355f7fd2fa0aa85105a3a6cc8a (diff)
downloadexuberant-hacks-4fb57de0201eaecdafffdcc285e7dc3ef9d4f6d8.zip
exuberant-hacks-4fb57de0201eaecdafffdcc285e7dc3ef9d4f6d8.tar.gz
refactor into library
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/bin/cow_model/mod.rs1
-rw-r--r--src/bin/exuberantbovines.rs214
-rw-r--r--src/lib.rs59
5 files changed, 161 insertions, 117 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 31505f1..5897394 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,5 +1,5 @@
[root]
-name = "exuberantbovines"
+name = "exuberant"
version = "0.1.0"
dependencies = [
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index 19775a6..5aa372f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "exuberantbovines"
+name = "exuberant"
version = "0.1.0"
authors = ["bnewbold <bnewbold@robocracy.org>"]
diff --git a/src/bin/cow_model/mod.rs b/src/bin/cow_model/mod.rs
index c0fdb01..41e8aab 100644
--- a/src/bin/cow_model/mod.rs
+++ b/src/bin/cow_model/mod.rs
@@ -7,6 +7,7 @@ mod cow_horns;
mod cow_tail;
mod cow_udder;
+pub use self::cow_vertex::Vertex;
pub use self::cow_face::COW_FACE_VERTICES;
pub use self::cow_hide::COW_HIDE_VERTICES;
pub use self::cow_hoofs::COW_HOOFS_VERTICES;
diff --git a/src/bin/exuberantbovines.rs b/src/bin/exuberantbovines.rs
index 1fdf7a0..799fff5 100644
--- a/src/bin/exuberantbovines.rs
+++ b/src/bin/exuberantbovines.rs
@@ -1,109 +1,119 @@
-extern crate exuberantbovines;
+extern crate exuberant;
extern crate getopts;
#[macro_use]
extern crate glium;
-use exuberantbovines::{generic_main, util};
+use exuberant::ExuberantHack;
use getopts::Options;
-use glium::glutin::os::unix::WindowBuilderExt;
+use glium::Surface;
mod cow_model;
-
-fn run(window_id: Option<u64>) {
-
- use glium::{DisplayBuild, Surface};
-
- let mut t: f32 = 0.0;
- let mut z: f32;
-
- let win_builder: glium::glutin::WindowBuilder = match window_id {
- Some(id) =>
- glium::glutin::WindowBuilder::new()
- .from_existing_window(id),
- None => glium::glutin::WindowBuilder::new()
- .with_title(format!("Exuberant Cow!"))
- .with_depth_buffer(24),
- };
- let display = win_builder.build_glium().unwrap();
-
- let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
-
- let face_vertices = glium::VertexBuffer::new(
- &display, &cow_model::COW_FACE_VERTICES).unwrap();
- let hide_vertices = glium::VertexBuffer::new(
- &display, &cow_model::COW_HIDE_VERTICES).unwrap();
- let hoofs_vertices = glium::VertexBuffer::new(
- &display, &cow_model::COW_HOOFS_VERTICES).unwrap();
- let horns_vertices = glium::VertexBuffer::new(
- &display, &cow_model::COW_HORNS_VERTICES).unwrap();
- let tail_vertices = glium::VertexBuffer::new(
- &display, &cow_model::COW_TAIL_VERTICES).unwrap();
- let udder_vertices = glium::VertexBuffer::new(
- &display, &cow_model::COW_UDDER_VERTICES).unwrap();
-
- let vertex_shader_src = r#"
- #version 140
-
- uniform mat4 perspective;
- uniform mat4 view;
- uniform mat4 model;
-
- in vec3 position;
- in vec3 normal;
-
- out vec3 v_normal;
- out vec3 v_position;
-
- void main() {
- mat4 modelview = view * model;
- v_normal = transpose(inverse(mat3(modelview))) * normal;
- gl_Position = perspective * modelview * vec4(position, 1.0);
- v_position = gl_Position.xyz / gl_Position.w;
- }
- "#;
- let fragment_shader_src = r#"
- #version 140
+struct ExuberantBovines {
+ t: f64,
+ display: glium::Display,
+ program: glium::Program,
+ model_vertices: Vec<glium::VertexBuffer<cow_model::Vertex>>,
+}
+
+impl ExuberantBovines {
+
+ pub fn new(display: glium::Display) -> ExuberantBovines {
+
+ let face_vertices = glium::VertexBuffer::new(
+ &display, &cow_model::COW_FACE_VERTICES).unwrap();
+ let hide_vertices = glium::VertexBuffer::new(
+ &display, &cow_model::COW_HIDE_VERTICES).unwrap();
+ let hoofs_vertices = glium::VertexBuffer::new(
+ &display, &cow_model::COW_HOOFS_VERTICES).unwrap();
+ let horns_vertices = glium::VertexBuffer::new(
+ &display, &cow_model::COW_HORNS_VERTICES).unwrap();
+ let tail_vertices = glium::VertexBuffer::new(
+ &display, &cow_model::COW_TAIL_VERTICES).unwrap();
+ let udder_vertices = glium::VertexBuffer::new(
+ &display, &cow_model::COW_UDDER_VERTICES).unwrap();
+
+ let vertex_shader_src = r#"
+ #version 140
+
+ uniform mat4 perspective;
+ uniform mat4 view;
+ uniform mat4 model;
+
+ in vec3 position;
+ in vec3 normal;
+
+ out vec3 v_normal;
+ out vec3 v_position;
+
+ void main() {
+ mat4 modelview = view * model;
+ v_normal = transpose(inverse(mat3(modelview))) * normal;
+ gl_Position = perspective * modelview * vec4(position, 1.0);
+ v_position = gl_Position.xyz / gl_Position.w;
+ }
+ "#;
- uniform vec3 u_light;
+ let fragment_shader_src = r#"
+ #version 140
- in vec3 v_normal;
- in vec3 v_position;
+ uniform vec3 u_light;
- out vec4 color;
+ in vec3 v_normal;
+ in vec3 v_position;
- const vec3 ambient_color = vec3(0.63, 0.43, 0.36);
- const vec3 diffuse_color = vec3(0.5, 0.5, 0.5);
- const vec3 specular_color = vec3(0.0, 0.0, 0.0);
+ out vec4 color;
- void main() {
- float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0);
+ const vec3 ambient_color = vec3(0.63, 0.43, 0.36);
+ const vec3 diffuse_color = vec3(0.5, 0.5, 0.5);
+ const vec3 specular_color = vec3(0.0, 0.0, 0.0);
- vec3 camera_dir = normalize(-v_position);
- vec3 half_direction = normalize(normalize(u_light) + camera_dir);
- float specular = pow(max(dot(half_direction, normalize(v_normal)), 0.0), 16.);
- color = vec4(ambient_color +
- diffuse * diffuse_color +
- specular * specular_color, 1.0);
- }
- "#;
+ void main() {
+ float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0);
+
+ vec3 camera_dir = normalize(-v_position);
+ vec3 half_direction = normalize(normalize(u_light) + camera_dir);
+ float specular = pow(max(dot(half_direction, normalize(v_normal)), 0.0), 16.);
+ color = vec4(ambient_color +
+ diffuse * diffuse_color +
+ specular * specular_color, 1.0);
+ }
+ "#;
+
+
+ let program = glium::Program::from_source(
+ &display,
+ vertex_shader_src,
+ fragment_shader_src,
+ None).unwrap();
+
+ return ExuberantBovines {
+ display: display,
+ program: program,
+ t: 0.0,
+ model_vertices: vec![face_vertices,
+ hide_vertices,
+ hoofs_vertices,
+ horns_vertices,
+ tail_vertices,
+ udder_vertices],
+ };
+ }
+}
+impl ExuberantHack for ExuberantBovines {
- let program = glium::Program::from_source(
- &display,
- vertex_shader_src,
- fragment_shader_src,
- None).unwrap();
+ fn draw_frame(&mut self) -> Result<(), String> {
- loop {
+ let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
- t += 0.03;
- z = 0.5 * t.sin();
+ self.t += 0.03;
+ let z: f32 = 0.5 * self.t.sin() as f32;
// Drawing Pipeline
- let mut target = display.draw();
+ let mut target = self.display.draw();
let (width, height) = target.get_dimensions();
let aspect_ratio = height as f32 / width as f32;
@@ -124,7 +134,7 @@ fn run(window_id: Option<u64>) {
let light = [-1.0, 0.4, 0.9f32];
- let view = util::view_matrix(&[2.0, -1.0, 1.0], &[-2.0, 1.0, 1.0], &[0.0, 1.0, 0.0]);
+ let view = exuberant::util::view_matrix(&[2.0, -1.0, 1.0], &[-2.0, 1.0, 1.0], &[0.0, 1.0, 0.0]);
let uniforms = uniform! {
model: [
[ 0.3, 0.0, 0.0, 0.0 ],
@@ -150,42 +160,36 @@ fn run(window_id: Option<u64>) {
.. Default::default()
};
- for part_vertices in vec![&face_vertices,
- &hide_vertices,
- &hoofs_vertices,
- &horns_vertices,
- &tail_vertices,
- &udder_vertices] {
+ for part_vertices in &self.model_vertices {
target.draw(part_vertices,
&indices,
- &program,
+ &self.program,
&uniforms,
&params).unwrap();
}
- target.finish().unwrap();
-
- for ev in display.poll_events() {
- match ev {
- glium::glutin::Event::Closed => return,
- _ => ()
- }
- }
- // XXX: sleep here for 10ms
+ target.finish().or(Err("Failure rendering".to_string()))
}
+ fn get_display(&self) -> &glium::Display {
+ &self.display
+ }
}
fn main() {
let mut opts = Options::new();
- opts.optflag("", "wire", "wireframe mode (IGNORED)");
opts.optopt("c", "count", "how many cows? (1 to 9) (IGNORED)", "NUM");
- opts.optopt("", "delay", "inter-frame delay (0 to 100000) (IGNORED)", "NUM");
opts.optopt("s", "speed", "how fast? ratio, with 1.0 as normal (IGNORED)", "NUM");
+ opts.optflag("", "wireframe", "wireframe mode (IGNORED)");
+
+ let conf = exuberant::main_helper(opts);
+ let dislpay = exuberant::make_display(&conf);
+ let mut hack = ExuberantBovines::new(dislpay);
- let (_, window_id) = generic_main(opts);
- run(window_id)
+ // Here is where you would configure the hack based on command line options
+ // Ok, actually run it (loops forever)
+ exuberant::run(&mut hack, &conf);
}
diff --git a/src/lib.rs b/src/lib.rs
index c0f537d..c73fc0c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,21 +6,45 @@ extern crate image;
extern crate getopts;
use std::env;
-use std::u64;
use std::process::exit;
use getopts::{Options, Matches};
use glium::glutin::os::unix::WindowBuilderExt;
+use glium::{DisplayBuild, Display};
pub mod util;
-fn print_usage(program: &str, opts: Options) {
+pub trait ExuberantHack {
+ fn draw_frame(&mut self) -> Result<(), String>;
+ fn get_display(&self) -> &Display;
+}
+
+/// Prints usage/help info for an individual hack
+pub fn print_usage(opts: &Options) {
+ let args: Vec<String> = env::args().collect();
+ let program = args[0].clone();
let brief = format!("Usage: {} [options]", program);
print!("{}", opts.usage(&brief));
}
-pub fn generic_main(mut opts: Options) -> (Matches, Option<u64>) {
+/// Executes a hack
+pub fn run(hack: &mut ExuberantHack, conf: &Matches) {
+
+ loop {
+ hack.draw_frame().ok();
+ for ev in hack.get_display().poll_events() {
+ match ev {
+ glium::glutin::Event::Closed => return,
+ _ => ()
+ }
+ }
+ // XXX: sleep here for 10ms
+ }
+}
+
+/// Adds and parses most command-line options.
+/// This function handles all the generic stuff, like --window-id and --help.
+pub fn main_helper(mut opts: Options) -> Matches {
let args: Vec<String> = env::args().collect();
- let program = args[0].clone();
// Turn, eg, "-root" into "--root"
let args = util::convert_xscreensaver_args(args);
@@ -29,13 +53,14 @@ pub fn generic_main(mut opts: Options) -> (Matches, Option<u64>) {
opts.optflag("h", "help", "print this help menu");
opts.optflag("", "window", "run in a window (IGNORED)");
opts.optflag("", "root", "run in root window (IGNORED)");
- opts.optflag("", "fps", "show frames per second (IGNORED)");
opts.optopt("", "window-id", "X window id number", "NUM");
+ opts.optflag("", "fps", "show frames per second (IGNORED)");
+ opts.optopt("", "delay", "inter-frame delay (0 to 100000) (IGNORED)", "NUM");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(f) => {
- print_usage(&program, opts);
+ print_usage(&opts);
println!("");
println!("{}", f.to_string());
exit(-1);
@@ -43,14 +68,19 @@ pub fn generic_main(mut opts: Options) -> (Matches, Option<u64>) {
};
if matches.opt_present("help") {
- print_usage(&program, opts);
+ print_usage(&opts);
exit(0);
}
+ matches
+}
+
+pub fn make_display(conf: &Matches) -> glium::Display {
+
// if no "--window-id", try environment variable (arg has priority though)
let window_id_string: Option<String> =
- matches.opt_str("window-id")
- .or(env::var("XSCREENSAVER_WINDOW").ok());
+ conf.opt_str("window-id")
+ .or(env::var("XSCREENSAVER_WINDOW").ok());
let window_id = window_id_string.map(|id| match util::dechex2u64(&id) {
Ok(y) => y,
@@ -63,5 +93,14 @@ pub fn generic_main(mut opts: Options) -> (Matches, Option<u64>) {
println!("Drawing on existing X window: 0x{:07X}", window_id.unwrap());
}
- (matches, window_id)
+ let win_builder: glium::glutin::WindowBuilder = match window_id {
+ Some(id) =>
+ glium::glutin::WindowBuilder::new()
+ .from_existing_window(id),
+ None => glium::glutin::WindowBuilder::new()
+ .with_title(format!("Exuberant Cow!"))
+ .with_depth_buffer(24),
+ };
+ let display = win_builder.build_glium().unwrap();
+ display
}