Vala プログラミング

Rust & Vala プログラミング

おながのブログ

Rust ImGui + Glium ( OpenGL )

ImGui のGUI(ボタン)から、Gliumで描画したtriangleの回転角をコントロールできる
ようにしています。
f:id:onagat12:20170325183824g:plain
(実行結果)
・ imgui ウィンドウ上の「+」ボタンと「ー」ボタンを押すと、回転角の値が増減します。

プログラム
### imgui-glium.rs

#[macro_use]
extern crate glium;
#[macro_use]
extern crate imgui;

use glium::glutin;
use glium::glutin::{ElementState, Event, MouseButton, MouseScrollDelta, TouchPhase};
use glium::{DisplayBuild, Surface};
use imgui::{ImGui, ImGuiSetCond_FirstUseEver};
use imgui::glium_renderer::Renderer;
use std::time::Instant;

fn main() {
    let display = glutin::WindowBuilder::new()
        .with_dimensions(600, 600)
        .with_title(format!("ImGui Glium Test"))
        .build_glium().unwrap();

    let mut imgui = ImGui::init();
    let mut renderer = Renderer::init(&mut imgui, &display).unwrap();

    let mut last_frame = Instant::now();
    let mut mouse_pos = (0, 0);
    let mut mouse_pressed = (false, false, false);
    let mut mouse_wheel = 0.0;

   #[derive(Copy, Clone)]
    struct Vertex {
        position: [f32; 2],
    }

    implement_vertex!(Vertex, position);

    let vertex1 = Vertex { position: [-0.5, -0.5] };
    let vertex2 = Vertex { position: [ 0.0,  0.5] };
    let vertex3 = Vertex { position: [ 0.5, -0.5] };
    let shape = vec![vertex1, vertex2, vertex3];

    let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
    let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

    let vertex_shader_src = r#"
        #version 140

        in vec2 position;

	uniform mat4 MVP;

        void main() {
            gl_Position = MVP * vec4(position, 0.0, 1.0);
        }
    "#;

    let fragment_shader_src = r#"
        #version 140

        out vec4 color;

        void main() {
            color = vec4(1.0, 0.0, 0.0, 1.0);
        }
    "#;

    let program = glium::Program::from_source(&display,
                           vertex_shader_src, fragment_shader_src, None).unwrap();

    let mut t: f32 = 0.0;

    loop {
        let mut target = display.draw();
        target.clear_color(0.2, 0.2, 0.2, 1.0);

        let uniform = uniform! {
	    MVP: [
	        [ t.cos(), t.sin(), 0.0, 0.0],
		[-t.sin(), t.cos(), 0.0, 0.0],
		[     0.0,     0.0, 1.0, 0.0],
		[     0.0,     0.0, 0.0, 1.0f32],
	    ],
	};
	target.draw(&vertex_buffer, &indices, &program, &uniform, &Default::default()).unwrap();

	let now = Instant::now();
	let delta = now - last_frame;
	let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0;
	last_frame = now;

	let scale = imgui.display_framebuffer_scale();
	imgui.set_mouse_pos(mouse_pos.0 as f32 / scale.0, mouse_pos.1 as f32 / scale.1);
	imgui.set_mouse_down(&[mouse_pressed.0, mouse_pressed.1, mouse_pressed.2, false, false]);
	imgui.set_mouse_wheel(mouse_wheel / scale.1);
	mouse_wheel = 0.0;

	let window = display.get_window().unwrap();
	let size_points = window.get_inner_size_points().unwrap();
	let size_pixels = window.get_inner_size_pixels().unwrap();

	let ui = imgui.frame(size_points, size_pixels, delta_s);

        // imgui ui
	ui.window(im_str!("Triangle"))
	    .position((10.0, 10.0), ImGuiSetCond_FirstUseEver)
	    .size((200.0, 100.0), ImGuiSetCond_FirstUseEver)
	    .build(|| {
                ui.text(im_str!("rotation"));
           	ui.separator();
		if ui.small_button(im_str!("+")) {
		    t += 0.02;
		}
		if ui.small_button(im_str!("-")) {
		    t -= 0.02;
		}
                ui.text(im_str!("rotation angle: {:.2} rad", t));
            });

	renderer.render(&mut target, ui).unwrap();
	target.finish().unwrap();

	for event in display.poll_events() {
	    match event {
	        Event::Closed => return,
		Event::MouseMoved(x, y) => mouse_pos = (x, y),
		Event::MouseInput(state, MouseButton::Left) =>
		    mouse_pressed.0 = state == ElementState::Pressed,
		Event::MouseInput(state, MouseButton::Right) =>
		    mouse_pressed.1 = state == ElementState::Pressed,
		Event::MouseInput(state, MouseButton::Middle) =>
		    mouse_pressed.2 = state == ElementState::Pressed,
		Event::MouseWheel(MouseScrollDelta::LineDelta(_, y), TouchPhase::Moved) =>
		    mouse_wheel = y,
		Event::MouseWheel(MouseScrollDelta::PixelDelta(_, y), TouchPhase::Moved) =>
		    mouse_wheel = y,
		_ => ()
	    }
	}
    }
}

### Cargo.toml

[package]
name = "test1"
version = "0.1.0"
authors = ["xxxxx"]

[dependencies]
glium = "*"
imgui = "*"
image = "*"