#[macro_use]
|
#[macro_use]
|
extern crate glium;
|
extern crate glium;
|
extern crate rand;
|
extern crate rand;
|
extern crate time;
|
extern crate time;
|
|
|
fn main() {
|
fn main() {
|
use rand::Rng;
|
use rand::Rng;
|
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
use glium::DisplayBuild;
|
use glium::DisplayBuild;
|
let builder = glium::glutin::WindowBuilder::new();
|
let builder = glium::glutin::WindowBuilder::new();
|
let window = builder
|
let window = builder
|
.with_dimensions(1024,1024)
|
.with_dimensions(1024,1024)
|
.with_title("GLscope")
|
.with_title("GLscope")
|
.with_vsync()
|
.with_vsync()
|
.build_glium()
|
.build_glium()
|
.unwrap();
|
.unwrap();
|
let mut now: f32;
|
let mut now: f32;
|
|
|
// 2D vertex type for plot points
|
// 2D vertex type for plot points
|
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Debug)]
|
struct Vertex {
|
struct Vertex {
|
position: [f32; 2],
|
position: [f32; 2],
|
time: f32 // Suggest using microseconds
|
time: f32 // Suggest using microseconds
|
}
|
}
|
implement_vertex!(Vertex, position, time);
|
implement_vertex!(Vertex, position, time);
|
// Note: need to transform -1023..1023 to -1..1
|
// Note: need to transform -1023..1023 to -1..1
|
// Could extend PDP-1 display instruction to 18 bit
|
// Could extend PDP-1 display instruction to 18 bit
|
|
|
// TODO: Set up OpenGL stuff to draw something
|
// TODO: Set up OpenGL stuff to draw something
|
//window.make_current().expect("Couldn't make context current");
|
//window.make_current().expect("Couldn't make context current");
|
let mut frame = window.draw();
|
let mut frame = window.draw();
|
use glium::Surface;
|
use glium::Surface;
|
// So far, so good. I can clear the image.
|
// So far, so good. I can clear the image.
|
// I can also plot points, using two shaders.
|
// I can also plot points, using two shaders.
|
// Those can be blended (additive in this case).
|
// Those can be blended (additive in this case).
|
// Time to extend the vertices with a timestamp for age?
|
// Time to extend the vertices with a timestamp for age?
|
|
|
// Set up a random array of points
|
// Set up a random array of points
|
/*
|
/*
|
let mut shape: Vec = Vec::new();
|
let mut shape: Vec = Vec::new();
|
for t in 0..20000 {
|
for t in 0..20000 {
|
shape.push(Vertex {
|
shape.push(Vertex {
|
position: [rng.next_f32()*2.0-1.0,
|
position: [rng.next_f32()*2.0-1.0,
|
rng.next_f32()*2.0-1.0],
|
rng.next_f32()*2.0-1.0],
|
time: t as f32 });
|
time: t as f32 });
|
}*/
|
}*/
|
let vbmax = 20000;
|
let vbmax = 20000;
|
let mut vbindex = 0;
|
let mut vbindex = 0;
|
// TODO: streaming suited vertexbuffer.
|
// TODO: streaming suited vertexbuffer.
|
// Docs say to use dynamic, persistent might be GL4?
|
// Docs say to use dynamic, persistent might be GL4?
|
let mut vertex_buffer : glium::VertexBuffer =
|
let mut vertex_buffer : glium::VertexBuffer =
|
glium::VertexBuffer::empty_dynamic(&window, vbmax).unwrap();
|
glium::VertexBuffer::empty_dynamic(&window, vbmax).unwrap();
|
// Possible todo: add line support, perhaps modulated
|
// Possible todo: add line support, perhaps modulated
|
// by beam trace speed.
|
// by beam trace speed.
|
let indices = glium::index::NoIndices(
|
let indices = glium::index::NoIndices(
|
glium::index::PrimitiveType::Points);
|
glium::index::PrimitiveType::Points);
|
|
|
let vertex_shader_src = r#"
|
let vertex_shader_src = r#"
|
#version 140
|
#version 140
|
in vec2 position;
|
in vec2 position;
|
in float time;
|
in float time;
|
out float age;
|
out float age;
|
uniform float now;
|
uniform float now;
|
void main() {
|
void main() {
|
age = now-time;
|
age = now-time;
|
if (age >= 0) {
|
if (age >= 0) {
|
gl_Position = vec4(position, 0.0, 1.0);
|
gl_Position = vec4(position, 0.0, 1.0);
|
}
|
}
|
}
|
}
|
"#;
|
"#;
|
|
|
// Should use a uniform to indicate current time
|
// Should use a uniform to indicate current time
|
// Possibly add a timestamp per lit dot?
|
// Possibly add a timestamp per lit dot?
|
let fragment_shader_src = r#"
|
let fragment_shader_src = r#"
|
#version 140
|
#version 140
|
in float age;
|
in float age;
|
out vec4 color;
|
out vec4 color;
|
void main() {
|
void main() {
|
float intensity = 1e1*exp(-8e-6*age);
|
float intensity = 1e1*exp(-8e-6*age);
|
color = vec4(intensity, intensity, intensity, 1.0);
|
color = vec4(intensity, intensity, intensity, 1.0);
|
}
|
}
|
"#;
|
"#;
|
let program =
|
let program =
|
glium::Program::from_source(&window,
|
glium::Program::from_source(&window,
|
vertex_shader_src,
|
vertex_shader_src,
|
fragment_shader_src,
|
fragment_shader_src,
|
None).unwrap();
|
None).unwrap();
|
let drawparams = glium::DrawParameters {
|
let drawparams = glium::DrawParameters {
|
blend: glium::Blend {
|
blend: glium::Blend {
|
color: glium::BlendingFunction::Addition {
|
color: glium::BlendingFunction::Addition {
|
source: glium::LinearBlendingFactor::One,
|
source: glium::LinearBlendingFactor::One,
|
destination: glium::LinearBlendingFactor::One },
|
destination: glium::LinearBlendingFactor::One },
|
.. Default::default() },
|
.. Default::default() },
|
.. Default::default()
|
.. Default::default()
|
};
|
};
|
|
|
let t0 = time::get_time();
|
let t0 = time::get_time();
|
|
|
use std::sync::mpsc::{channel, Receiver};
|
use std::sync::mpsc::{channel, Receiver};
|
let verts : Receiver = (|| {
|
let verts : Receiver = {
|
use std::thread::spawn;
|
use std::thread::spawn;
|
|
|
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
spawn(move || {
|
spawn(move || {
|
loop {
|
loop {
|
let now = (time::get_time() - t0)
|
|
.num_microseconds().unwrap() as f32;
|
|
let mut str = String::new();
|
let mut str = String::new();
|
std::io::stdin().read_line(&mut str).unwrap();
|
std::io::stdin().read_line(&mut str).unwrap();
|
|
let now = (time::get_time() - t0)
|
|
.num_microseconds().unwrap() as f32;
|
// FIXME: Parse line.
|
// FIXME: Parse line.
|
let mut words = str.split_whitespace();
|
let mut words = str.split_whitespace();
|
let x = words.next().unwrap().parse().unwrap();
|
let x = words.next().unwrap().parse().unwrap();
|
let y = words.next().unwrap().parse().unwrap();
|
let y = words.next().unwrap().parse().unwrap();
|
let v = Vertex {position: [x, y], time: now };
|
let v = Vertex {position: [x, y], time: now };
|
tx.send(v).unwrap();
|
tx.send(v).unwrap();
|
//println!("Vertex: {:?}", [x,y]);
|
//println!("Vertex: {:?}", v);
|
}
|
}
|
});
|
});
|
rx
|
rx
|
})();
|
};
|
|
|
loop {
|
loop {
|
for event in window.poll_events() {
|
for event in window.poll_events() {
|
// Simplest nowait: use poll_events()
|
// Simplest nowait: use poll_events()
|
match event {
|
match event {
|
glium::glutin::Event::Closed => {
|
glium::glutin::Event::Closed => {
|
frame.finish().unwrap();
|
frame.finish().unwrap();
|
return;
|
return;
|
},
|
},
|
_ => ()
|
_ => ()
|
}
|
}
|
}
|
}
|
|
|
now = (time::get_time() - t0).num_microseconds().unwrap()
|
now = (time::get_time() - t0).num_microseconds().unwrap()
|
as f32;
|
as f32;
|
|
|
// Inject new points
|
// Inject new points
|
{
|
{
|
let mut wvb = vertex_buffer.map_write();
|
let mut wvb = vertex_buffer.map_write();
|
// Add 21 random points per frame
|
// Add 21 random points per frame
|
for _ in 0..20 {
|
for _ in 0..20 {
|
wvb.set(vbindex, Vertex {
|
wvb.set(vbindex, Vertex {
|
position: [rng.next_f32()*2.0-1.0,
|
position: [rng.next_f32()*2.0-1.0,
|
rng.next_f32()*2.0-1.0],
|
rng.next_f32()*2.0-1.0],
|
time: now });
|
time: now });
|
vbindex = (vbindex+1) % vbmax;
|
vbindex = (vbindex+1) % vbmax;
|
}
|
}
|
// TODO: Read points from e.g. stdin
|
// TODO: Read points from e.g. stdin
|
for v in verts.try_iter() {
|
for v in verts.try_iter() {
|
//println!("Vertex: {:?} {} {}",
|
//println!("Vertex: {:?} {} {}",
|
// v.position, v.time, now);
|
// v.position, v.time, now);
|
wvb.set(vbindex, v);
|
wvb.set(vbindex, v);
|
vbindex = (vbindex+1) % vbmax;
|
vbindex = (vbindex+1) % vbmax;
|
}
|
}
|
}
|
}
|
|
|
// Closing the window closes the program.
|
// Closing the window closes the program.
|
frame.clear_color(0.0, 0.0, 0.0, 1.0);
|
frame.clear_color(0.0, 0.0, 0.0, 1.0);
|
frame.draw(&vertex_buffer, &indices, &program,
|
frame.draw(&vertex_buffer, &indices, &program,
|
//&glium::uniforms::EmptyUniforms,
|
//&glium::uniforms::EmptyUniforms,
|
&uniform! { now: now },
|
&uniform! { now: now },
|
&drawparams).unwrap();
|
&drawparams).unwrap();
|
|
|
window.swap_buffers().unwrap();
|
window.swap_buffers().unwrap();
|
}
|
}
|
}
|
}
|
|
|