130 lines
4.6 KiB
Rust
130 lines
4.6 KiB
Rust
#![allow(unused_imports)]
|
|
#![allow(dead_code)]
|
|
|
|
use crate::display::Display;
|
|
use crate::display::DisplayCamera;
|
|
|
|
use log::debug;
|
|
|
|
use pathfinder_demo::Options;
|
|
use pathfinder_demo::BuildOptions;
|
|
use pathfinder_demo::SceneThreadProxy;
|
|
use pathfinder_demo::MainToSceneMsg;
|
|
use pathfinder_demo::SceneToMainMsg;
|
|
use pathfinder_demo::Camera;
|
|
use pathfinder_demo::CameraTransform3D;
|
|
use pathfinder_gl::GLDevice;
|
|
use pathfinder_renderer::gpu::renderer::Renderer;
|
|
use pathfinder_geometry::basic::point::Point2DI32;
|
|
use pathfinder_geometry::basic::point::Point2DF32;
|
|
use pathfinder_geometry::basic::point::Point3DF32;
|
|
use pathfinder_geometry::basic::rect::RectI32;
|
|
use pathfinder_geometry::basic::transform2d::Transform2DF32;
|
|
use pathfinder_geometry::basic::transform3d::Transform3DF32;
|
|
use pathfinder_geometry::basic::transform3d::Perspective;
|
|
use pathfinder_gpu::Device;
|
|
use pathfinder_simd::default::F32x4;
|
|
use pathfinder_svg::BuiltSVG;
|
|
use pathfinder_renderer::scene::Scene;
|
|
use pathfinder_renderer::builder::RenderTransform;
|
|
|
|
use std::error::Error;
|
|
use std::fmt;
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
use std::time::Instant;
|
|
|
|
use usvg;
|
|
|
|
pub struct ImmersiveDemo<D> {
|
|
display: D,
|
|
renderer: Renderer<GLDevice>,
|
|
scene_thread_proxy: SceneThreadProxy,
|
|
svg_size: Point2DF32,
|
|
svg_to_world: Option<Transform3DF32>,
|
|
}
|
|
|
|
static DEFAULT_SVG_VIRTUAL_PATH: &'static str = "svg/Ghostscript_Tiger.svg";
|
|
|
|
// SVG dimensions in metres
|
|
const MAX_SVG_HEIGHT: f32 = 1.0;
|
|
const MAX_SVG_WIDTH: f32 = 1.0;
|
|
const DEFAULT_SVG_DISTANCE: f32 = 1.5;
|
|
|
|
impl<D: Display> ImmersiveDemo<D> {
|
|
pub fn new(mut display: D) -> Result<Self, D::Error> {
|
|
display.make_current()?;
|
|
let resources = display.resource_loader();
|
|
let options = Options::get();
|
|
let svg_data = resources.slurp(DEFAULT_SVG_VIRTUAL_PATH)?;
|
|
let tree = usvg::Tree::from_data(&svg_data[..], &usvg::Options::default())?;
|
|
let svg = BuiltSVG::from_tree(tree);
|
|
let svg_size = svg.scene.view_box.size();
|
|
let scene_thread_proxy = SceneThreadProxy::new(svg.scene, options);
|
|
let _ = scene_thread_proxy.sender.send(MainToSceneMsg::SetDrawableSize(display.size()));
|
|
let device = GLDevice::new(display.gl_version());
|
|
let viewport = RectI32::new(Point2DI32::new(0, 0), display.size());
|
|
let renderer = Renderer::new(device, resources, viewport, display.size());
|
|
Ok(ImmersiveDemo {
|
|
display,
|
|
renderer,
|
|
scene_thread_proxy,
|
|
svg_size,
|
|
svg_to_world: None,
|
|
})
|
|
}
|
|
|
|
pub fn running(&self) -> bool {
|
|
self.display.running()
|
|
}
|
|
|
|
pub fn render_scene(&mut self) -> Result<(), D::Error> {
|
|
self.display.make_current()?;
|
|
let cameras = self.display.begin_frame()?;
|
|
|
|
debug!("PF rendering a frame");
|
|
let start = Instant::now();
|
|
|
|
let svg_size = self.svg_size;
|
|
let svg_to_world = self.svg_to_world.get_or_insert_with(|| {
|
|
let view: Transform3DF32 = cameras[0].view();
|
|
let svg_to_world_scale = f32::max(MAX_SVG_WIDTH / svg_size.x(), MAX_SVG_HEIGHT / svg_size.y());
|
|
let svg_width = svg_size.x() * svg_to_world_scale;
|
|
let svg_height = svg_size.y() * svg_to_world_scale;
|
|
Transform3DF32::from_uniform_scale(svg_to_world_scale)
|
|
.pre_mul(&Transform3DF32::from_translation(-svg_width / 2.0, -svg_height / 2.0, -DEFAULT_SVG_DISTANCE))
|
|
.pre_mul(&Transform3DF32::from_scale(1.0, -1.0, 1.0))
|
|
.pre_mul(&view.inverse())
|
|
});
|
|
|
|
let render_transforms = cameras.iter()
|
|
.map(|camera| RenderTransform::Perspective(
|
|
camera.perspective()
|
|
.post_mul(&camera.view())
|
|
.post_mul(&svg_to_world)
|
|
)).collect();
|
|
let msg = MainToSceneMsg::Build(BuildOptions {
|
|
render_transforms: render_transforms,
|
|
stem_darkening_font_size: None,
|
|
});
|
|
let _ = self.scene_thread_proxy.sender.send(msg);
|
|
|
|
if let Ok(reply) = self.scene_thread_proxy.receiver.recv() {
|
|
for (camera, scene) in cameras.iter_mut().zip(reply.render_scenes) {
|
|
debug!("PF rendering eye after {}ms", (Instant::now() - start).as_millis());
|
|
camera.make_current()?;
|
|
let bounds = camera.bounds();
|
|
let background = F32x4::new(0.0, 0.0, 0.0, 1.0);
|
|
self.renderer.device.clear(Some(background), Some(1.0), Some(0));
|
|
self.renderer.enable_depth();
|
|
self.renderer.set_viewport(bounds);
|
|
self.renderer.render_scene(&scene.built_scene);
|
|
}
|
|
}
|
|
|
|
debug!("PF rendered frame after {}ms", (Instant::now() - start).as_millis());
|
|
self.display.end_frame()?;
|
|
Ok(())
|
|
}
|
|
}
|