#![feature(more_float_constants)]
use std::time;
use env_logger;
use glium;
use line_2d;
use log;
use winit;
use gl_utils::*;
use gl_utils::render::resource::demo;
const LOG_LEVEL : log::LevelFilter = log::LevelFilter::Info;
const INITIAL_2D_ZOOM : f32 = 1.0;
const INITIAL_3D_POSITION : [f32; 3] = [0.0, -3.0, 2.0];
const INITIAL_CLEAR_COLOR : [f32; 4] = [0.0, 0.0, 0.0, 1.0];
const DRAWING_TEXTURE_INDEX : usize = 0;
fn main() {
use std::f32::consts::{FRAC_PI_4, PI, SQRT_3};
use math::num::Inv;
println!("gl-utils demo main...");
env_logger::Builder::new().filter_level (LOG_LEVEL).parse_default_env().init();
log::info!("logging initialized");
let (mut events_loop, window, _gl_config, glium_display) =
init::glium_init_gl33core ("gl-utils demo window");
{ use glium::backend::Facade;
let context = glium_display.get_context();
log::info!("opengl version: {:?}", context.get_opengl_version());
log::info!("opengl profile: {:?}", context.get_opengl_profile());
log::info!("supported glsl version: {:?}", context.get_supported_glsl_version());
context.get_free_video_memory().map_or_else(
|| log::warn!("could not get free video memory"),
|nbytes| log::info!("free video memory: {}MB", nbytes/1_000_000))
}
Render::<render::resource::Default>::report_sizes();
let load_mesh_path = std::path::Path::new ("box.gltf");
let mesh = Mesh::load_gltf (load_mesh_path);
log::info!("loaded mesh ({}): {:?}", load_mesh_path.display(), mesh);
let write_mesh_path = std::path::Path::new ("sphere.gltf");
Mesh::from (mesh::Lines3d::sphere (0, 12, 24)).write_gltf (write_mesh_path);
log::info!("wrote sphere mesh: {}", write_mesh_path.display());
let mut app = demo::App::new (glium_display, window);
app.render.clear_color = INITIAL_CLEAR_COLOR;
app.render.camera3d_position_set (INITIAL_3D_POSITION.into());
app.render.camera2d_zoom_set (INITIAL_2D_ZOOM);
let (width, height) = app.render.glium_display.get_framebuffer_dimensions();
let mut drawing : Vec <Vec <(f32, f32, f32, f32)>> =
vec![vec![(0.0, 0.0, 0.0, 0.0); width as usize]; height as usize];
let drawing_texture = glium::texture::Texture2d::new (
&app.render.glium_display, drawing.clone()).unwrap();
assert!(app.render.resource.textures_anysize
.insert (DRAWING_TEXTURE_INDEX, drawing_texture).is_none());
assert!(app.render.resource.draw2d.rectangle_anysize_vertices.insert (
DRAWING_TEXTURE_INDEX,
glium::VertexBuffer::new (&app.render.glium_display, &[
vertex::Vert2dRectUv {
bottom_left: [-(width as f32) / 2.0, -(height as f32) / 2.0],
dimensions: [width as f32, height as f32],
uv: [0.0, 0.0]
}
]).unwrap()
).is_none());
let mut frame = 0;
let mut fps = 0;
let mut last_t = time::Instant::now();
let mut prev_mouse_position = app.mouse_position;
let mut drawing_state = false;
let mut cube_orientation = math::Rotation3::from_angle_x (FRAC_PI_4.into());
let cube_rotation = math::Rotation3::from_axis_angle (
cube_orientation.inv() * math::Vector3::unit_z(), (PI / 100.0).into());
println!("start time: {last_t:?}");
while app.running {
use winit::platform::pump_events::EventLoopExtPumpEvents;
events_loop.pump_app_events (Some (time::Duration::ZERO), &mut app);
match app.mouse_button_event {
Some (winit::event::ElementState::Pressed) => drawing_state = true,
Some (winit::event::ElementState::Released) => drawing_state = false,
None => {}
}
let (width, height) = app.render.glium_display.get_framebuffer_dimensions();
drawing.iter_mut()
.for_each (|line| line.resize (width as usize, (0.0, 0.0, 0.0, 0.0)));
drawing.resize_with (
height as usize, || vec![(0.0, 0.0, 0.0, 0.0); width as usize]);
if drawing_state {
let start = line_2d::ICoord::new (
prev_mouse_position.0 as i32, prev_mouse_position.1 as i32);
let end = line_2d::ICoord::new (
app.mouse_position.0 as i32, app.mouse_position.1 as i32);
if start != end {
let segment = line_2d::LineSegment::new (start, end);
for coord in segment.iter() {
drawing[coord.y as usize][coord.x as usize] = (1.0, 1.0, 0.0, 1.0);
let drawing_texture = app.render.resource.textures_anysize
.get_mut (DRAWING_TEXTURE_INDEX).unwrap();
let bottom = drawing_texture.height() - coord.y as u32;
let rect = glium::Rect {
left: coord.x as u32, bottom, width: 1, height: 1
};
drawing_texture.write (rect, vec![vec![(1.0, 1.0, 0.0, 1.0)]]);
}
} else {
let drawing_texture = app.render.resource.textures_anysize
.get_mut (DRAWING_TEXTURE_INDEX).unwrap();
let bottom = drawing_texture.height() - app.mouse_position.1 as u32;
let rect = glium::Rect {
left: app.mouse_position.0 as u32, bottom, width: 1, height: 1
};
drawing_texture.write (rect, vec![vec![(1.0, 1.0, 0.0, 1.0)]]);
}
}
prev_mouse_position = app.mouse_position;
assert!(app.render.resource.draw2d.rectangle_anysize_vertices.insert (
DRAWING_TEXTURE_INDEX,
glium::VertexBuffer::new (&app.render.glium_display, &[
vertex::Vert2dRectUv {
bottom_left: [-(width as f32) / 2.0, -(height as f32) / 2.0],
dimensions: [width as f32, height as f32],
uv: [0.0, 0.0]
}
]).unwrap()
).is_some());
cube_orientation *= cube_rotation;
let cube_z = (1.0 - 6.0f32.sqrt() / 6.0)
* (2.0 * PI * ((frame % 150) as f32 / 150.0)).sin();
app.render.resource.draw3d.instance_vertices_mesh_write (
render::resource::draw3d::MeshId::Cube as usize,
&[vertex::Vert3dOrientationScaleColor {
position: [-1.5, 2.5, 1.0 + cube_z],
orientation: cube_orientation.into_col_arrays(),
scale: [SQRT_3 / 6.0; 3],
color: color::rgba_u8_to_rgba_f32 (color::CYAN)
}][..]);
app.render.do_frame (None);
frame += 1;
let t = time::Instant::now();
if (t - last_t).as_secs() >= 1 {
let [_tile_width, tile_height] = app.render.resource.tile_dimensions (
render::resource::DefaultTilesetId::EasciiAcorn128);
let tile_range = app.render.resource.draw2d
.viewport_resources_get (render::resource::OVERLAY_VIEWPORT).unwrap()
.draw_indices[0].draw_tiles.as_ref().unwrap().vertex_range.clone();
let fps_row = ((height / tile_height) - 1) as i32;
let tiles = tile::vertices (&format!("FPS: {fps:<6}"), (fps_row, 0));
app.render.resource.draw2d.tile_2d_vertices.slice (
tile_range.start as usize .. tile_range.end as usize
).unwrap().write (&tiles);
last_t = t;
fps = 0;
} else {
fps += 1;
}
}
println!("...gl-utils demo main");
}