use rin_math::{
one, Pnt3, UnitQuat, Vec3, Vec4, Mat4, Mat3, Unit, vec3, vec4, pnt4, Rect, Deg, Rad, ToVec,
Isometry3, Rotation3, FastInverse, DualQuat
};
use rin_events::{Stream, TryIter, StreamExt};
use std::ops::{Deref, DerefMut};
use rin_graphics::{
self as graphics, CameraExt, ArcballCamera, NodeMut, Mesh, Vertex3D, CameraPerspective, CameraOrthographic
};
use rinecs::{Entities, Resources, System, Component, HierarchicalComponent, OneToNComponent, system};
#[cfg(feature="debug_geometry")]
use crate::geometry::Geometry;
use serde::Serialize as _;
use std::sync::Arc;
use std::cell::Cell;
use serde_derive::{Serialize, Deserialize};
#[derive(Clone, Component, Debug, Serialize, Deserialize)]
pub struct SkinningUpToDate(pub bool);
#[derive(Clone, Component, Debug, Serialize, Deserialize)]
pub struct PreviousTransformation(pub graphics::Node);
impl Default for PreviousTransformation{
fn default() -> PreviousTransformation{
PreviousTransformation(one())
}
}
impl PreviousTransformation{
pub fn new(pos: Pnt3, rot: UnitQuat, scale: Vec3) -> PreviousTransformation{
PreviousTransformation(graphics::Node::new(pos, rot, scale))
}
pub fn from_position(pos: Pnt3) -> PreviousTransformation{
PreviousTransformation(graphics::Node::new(pos, one(), vec3!(1.)))
}
}
#[cfg(feature="blender")]
impl<'a> From<&'a rinblender::Transformations> for PreviousTransformation {
fn from(trafo: &'a rinblender::Transformations) -> PreviousTransformation {
if let Some(parent_inv) = trafo.parent_inv {
PreviousTransformation( graphics::Node::with_preparent(parent_inv,
trafo.position, trafo.into_quat(), trafo.scale))
}else{
PreviousTransformation::new(trafo.position, trafo.into_quat(), trafo.scale)
}
}
}
#[derive(Clone,Debug,Copy,PartialEq,Eq, Serialize, Deserialize)]
#[allow(dead_code)]
#[repr(i16)]
pub enum RotMode {
Quat = 0,
EulerXYZ = 1,
EulerXZY = 2,
EulerYXZ = 3,
EulerYZX = 4,
EulerZXY = 5,
EulerZYX = 6,
AxisAngle = -1,
}
pub struct BoneParts;
bitflags::bitflags!{
#[derive(Serialize, Deserialize)]
pub struct BoneFlags: u16{
const NO_ROTATION_FROM_PARENT = 1 << 0;
const NO_SCALE_FROM_PARENT = 1 << 1;
const NO_TRANSLATION_FROM_PARENT = 1 << 2;
}
}
#[derive(HierarchicalComponent, Debug, Serialize, Deserialize)]
#[debug_custom]
pub struct Bone{
pub rest: graphics::Node,
pub original: graphics::Node,
pub animated: graphics::Node,
pub rot_mode: RotMode,
pub rest_mat: Mat4,
pub inv_rest_mat: Mat4,
pub animated_id: usize,
pub optimized_id: usize,
pub head: Pnt3,
pub tail: Pnt3,
pub head_radius: f32,
pub tail_radius: f32,
pub name: String,
pub has_changed: bool,
pub flags: BoneFlags,
pub used: bool,
}
impl Bone{
#[inline]
pub fn pose_mat(&self) -> Mat4{
self.animated.global_transformation()
}
#[inline]
pub fn local_mat(&self) -> Mat4{
self.pose_mat() * self.inv_rest_mat
}
#[inline]
pub fn global_head(&self) -> Pnt3{
(self.animated.global_transformation() * pnt4!(self.head, 1.0)).xyz()
}
#[inline]
pub fn global_tail(&self) -> Pnt3{
(self.animated.global_transformation() * pnt4!(self.tail, 1.0)).xyz()
}
pub fn to_dual_quaternion(&self) -> (DualQuat, Mat4){
let q = self.animated.global_orientation();
let t = self.animated.global_position();
let matrix = Isometry3::from_parts(t.to_vec().into(), q).to_homogeneous() * self.inv_rest_mat;
let rot = Mat3::from_columns(&[
matrix.column(0).xyz(),
matrix.column(1).xyz(),
matrix.column(2).xyz(),
]);
let rot = Rotation3::from_matrix_unchecked(rot);
let q = UnitQuat::from_rotation_matrix(&rot);
let t = matrix.column(3).xyz();
let scale = matrix.fast_orthonormal_inverse() * self.local_mat();
return (DualQuat::rigid_transformation(q, t), scale);
}
pub fn update_with_parent(&mut self, parent: Option<&Bone>) -> bool{
self.has_changed = if self.flags.is_empty(){
self.original.update_with_parent(parent.map(|p| &p.animated)) |
self.animated.update_with_parent(Some(&self.original))
}else{
let translation = if self.flags.contains(BoneFlags::NO_TRANSLATION_FROM_PARENT){
parent.map(|p| &p.rest)
}else{
parent.map(|p| &p.animated)
};
let orientation = if self.flags.contains(BoneFlags::NO_ROTATION_FROM_PARENT){
parent.map(|p| &p.rest)
}else{
parent.map(|p| &p.animated)
};
let scale = if self.flags.contains(BoneFlags::NO_SCALE_FROM_PARENT){
parent.map(|p| &p.rest)
}else{
parent.map(|p| &p.animated)
};
self.original.update_with_parent_parts(translation, orientation, scale) |
self.animated.update_with_parent(Some(&self.original))
};
self.has_changed
}
}
impl rinecs::DebugParameter for Bone{
fn debug<S: serde::Serializer>(&self, serializer: S) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>{
#[derive(Serialize)]
struct Position{
x: f32,
y: f32,
z: f32,
}
#[derive(Serialize)]
struct Orientation{
x: f32,
y: f32,
z: f32,
w: f32,
}
#[derive(Serialize)]
struct Scale{
x: f32,
y: f32,
z: f32,
}
#[derive(Serialize)]
struct Node{
position: Position,
orientation: Orientation,
scale: Scale,
global_position: Position,
global_orientation: Orientation,
global_scale: Scale,
}
#[derive(Serialize)]
struct _Bone<'a>{
original: Node,
animated: Node,
rot_mode: RotMode,
rest_mat: &'a Mat4,
inv_rest_mat: &'a Mat4,
animated_id: usize,
head: &'a Pnt3,
tail: &'a Pnt3,
head_radius: f32,
tail_radius: f32,
name: &'a str,
has_changed: bool,
flags: BoneFlags,
}
let p = self.original.position();
let q = self.original.orientation();
let s = self.original.scale();
let gp = self.original.global_position();
let gq = self.original.global_orientation();
let gs = self.original.global_scale();
let original = Node{
position: Position{
x: p[0], y: p[1], z: p[2]
},
orientation: Orientation{
x: q[0], y: q[1], z: q[2], w: q[3]
},
scale: Scale{
x: s.x, y: s.y, z: s.z
},
global_position: Position{
x: gp[0], y: gp[1], z: gp[2]
},
global_orientation: Orientation{
x: gq[0], y: gq[1], z: gq[2], w: gq[3]
},
global_scale: Scale{
x: gs.x, y: gs.y, z: gs.z
},
};
let p = self.animated.position();
let q = self.animated.orientation();
let s = self.animated.scale();
let gp = self.animated.global_position();
let gq = self.animated.global_orientation();
let gs = self.animated.global_scale();
let animated = Node{
position: Position{
x: p[0], y: p[1], z: p[2]
},
orientation: Orientation{
x: q[0], y: q[1], z: q[2], w: q[3]
},
scale: Scale{
x: s.x, y: s.y, z: s.z
},
global_position: Position{
x: gp[0], y: gp[1], z: gp[2]
},
global_orientation: Orientation{
x: gq[0], y: gq[1], z: gq[2], w: gq[3]
},
global_scale: Scale{
x: gs.x, y: gs.y, z: gs.z
},
};
_Bone{
original,
animated,
rot_mode: self.rot_mode,
rest_mat: &self.rest_mat,
inv_rest_mat: &self.inv_rest_mat,
animated_id: self.animated_id,
head: &self.head,
tail: &self.tail,
head_radius: self.head_radius,
tail_radius: self.tail_radius,
name: &self.name,
has_changed: self.has_changed,
flags: self.flags,
}.serialize(serializer)
}
}
#[derive(OneToNComponent, Debug, Serialize, Deserialize)]
pub struct RenderPlane {
camera_matrices: graphics::mvp::CameraMatrices,
clip_plane: Option<Vec4>,
bias: f32,
has_changed: bool,
draw_translucent: bool,
draw_debug: bool,
}
impl RenderPlane {
pub fn new<C: CameraExt>(camera: &C, viewport: Rect<i32>, clip_plane: Option<Vec4>, bias: f32) -> RenderPlane{
let camera_matrices = if let Some(clip) = clip_plane{
let clip_plane = vec4!(clip.xyz(), clip.w + bias);
graphics::mvp::CameraMatrices::with_camera_viewport_clip_plane(camera, viewport, clip_plane)
}else{
graphics::mvp::CameraMatrices::with_camera_viewport(camera, viewport)
};
RenderPlane{
camera_matrices,
clip_plane,
bias,
has_changed: false,
draw_translucent: true,
draw_debug: false,
}
}
pub fn biased_clip_plane(&self) -> Option<Vec4>{
self.clip_plane.map(|clip| vec4!(clip.xyz(), clip.w + self.bias))
}
pub fn camera_matrices(&self) -> &graphics::mvp::CameraMatrices{
&self.camera_matrices
}
pub fn update_camera_viewport<C: CameraExt>(&mut self, camera: &C, viewport: Rect<i32>){
self.has_changed = true;
let camera_matrices = if let Some(clip) = self.biased_clip_plane(){
graphics::mvp::CameraMatrices::with_camera_viewport_clip_plane(camera, viewport, clip)
}else{
graphics::mvp::CameraMatrices::with_camera_viewport(camera, viewport)
};
self.camera_matrices = camera_matrices;
}
pub fn update_camera_viewport_bias<C: CameraExt>(&mut self, camera: &C, viewport: Rect<i32>, bias: f32){
self.has_changed = true;
self.bias = bias;
let camera_matrices = if let Some(clip) = self.biased_clip_plane(){
graphics::mvp::CameraMatrices::with_camera_viewport_clip_plane(camera, viewport, clip)
}else{
graphics::mvp::CameraMatrices::with_camera_viewport(camera, viewport)
};
self.camera_matrices = camera_matrices;
}
pub fn set_clip_plane(&mut self, clip_plane: Vec4){
self.has_changed = true;
self.clip_plane = Some(clip_plane);
self.camera_matrices.set_clip_plane(self.biased_clip_plane().unwrap());
}
pub fn clip_plane(&self) -> Option<Vec4>{
self.clip_plane
}
pub fn bias(&self) -> f32{
self.bias
}
pub fn has_changed(&self) -> bool{
self.has_changed
}
pub fn reset_has_changed(&mut self){
self.has_changed = false;
}
pub fn set_draw_translucent(&mut self, draw_translucent: bool){
self.has_changed = true;
self.draw_translucent = draw_translucent;
}
pub fn draw_translucent(&self) -> bool{
self.draw_translucent
}
pub fn set_draw_debug(&mut self, draw_debug: bool){
self.has_changed = true;
self.draw_debug = draw_debug;
}
pub fn draw_debug(&self) -> bool{
self.draw_debug
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Viewport{
viewport: Rect<i32>,
changed: bool,
}
impl Viewport{
pub fn new(viewport: Rect<i32>) -> Viewport{
Viewport{
viewport,
changed: false,
}
}
pub fn rect(&self) -> &Rect<i32> {
&self.viewport
}
pub fn has_changed(&self) -> bool{
self.changed
}
}
impl Deref for Viewport {
type Target = Rect<i32>;
fn deref(&self) -> &Rect<i32>{
&self.viewport
}
}
impl DerefMut for Viewport {
fn deref_mut(&mut self) -> &mut Rect<i32>{
&mut self.viewport
}
}
pub struct Camera<C = ArcballCamera>{
camera: C,
changed: Arc<Cell<bool>>,
}
unsafe impl<C: CameraExt + Send + 'static> Send for Camera<C>{}
pub struct CameraChanged(Arc<Cell<bool>>);
unsafe impl Send for CameraChanged{}
impl CameraChanged{
pub fn has_changed(&self) -> bool{
self.0.get()
}
}
impl<C: CameraExt + Send + 'static> Camera<C>{
pub fn new(camera: C) -> (Camera<C>, CameraChanged){
let changed = Arc::new(Cell::new(false));
let camera = Camera{
camera,
changed: changed.clone(),
};
let changed = CameraChanged(changed);
(camera, changed)
}
pub fn has_changed(&self) -> bool{
self.changed.get()
}
pub fn frustum_geometry(&self) -> Mesh<Vertex3D>{
let mut frustum_corners = graphics::cuboid_wireframe(vec3!(2.));
let inv_proj_view = self.camera.projection_view().try_inverse().unwrap();
for corner in frustum_corners.iter_mut(){
let world_corner = inv_proj_view * vec4!(corner.position, 1.);
corner.position = world_corner.xyz() / world_corner.w
}
frustum_corners
}
}
impl<C: CameraExt> Camera<C>{
pub fn update(&mut self) -> bool{
self.changed.set(self.camera.update());
self.changed.get()
}
}
impl<C> Deref for Camera<C> {
type Target = C;
fn deref(&self) -> &C{
&self.camera
}
}
impl<C> DerefMut for Camera<C> {
fn deref_mut(&mut self) -> &mut C{
&mut self.camera
}
}
impl<C: graphics::NodeRef> graphics::NodeRef for Camera<C>{
fn node(&self) -> &graphics::Node{
self.camera.node()
}
}
impl<C: CameraExt> CameraExt for Camera<C>{
fn projection(&self) -> Mat4{
self.camera.projection()
}
fn view(&self) -> Mat4{
self.camera.view()
}
fn projection_view(&self) -> Mat4{
self.camera.projection_view()
}
fn fov(&self) -> Option<Deg<f32>>{
self.camera.fov()
}
fn hfov(&self) -> Option<Deg<f32>>{
self.camera.hfov()
}
fn focal_length(&self) -> Option<f32>{
self.camera.focal_length()
}
fn sensor_width_mm(&self) -> Option<f32> {
self.camera.sensor_width_mm()
}
fn width(&self) -> Option<f32>{
self.camera.width()
}
fn near_far_clip(&self) -> (f32, Option<f32>){
self.camera.near_far_clip()
}
fn near_clip(&self) -> f32{
self.camera.near_clip()
}
fn far_clip(&self) -> Option<f32>{
self.camera.far_clip()
}
fn set_near(&mut self, near: f32){
self.camera.set_near(near);
}
fn set_far(&mut self, far: f32){
self.camera.set_far(far);
}
fn set_near_far(&mut self, near: f32, far: f32){
self.camera.set_near_far(near,far);
}
fn set_aspect_ratio(&mut self, aspect: f32){
self.camera.set_aspect_ratio(aspect);
}
fn aspect_ratio(&self) -> f32{
self.camera.aspect_ratio()
}
fn target(&self) -> &Pnt3{
self.camera.target()
}
fn set_target(&mut self, target: Pnt3){
self.camera.set_target(target)
}
fn up(&self) -> &Unit<Vec3>{
self.camera.up()
}
fn update(&mut self) -> bool{
self.update()
}
fn enable_depth_clamp(&mut self){
self.camera.enable_depth_clamp();
}
fn disable_depth_clamp(&mut self){
self.camera.disable_depth_clamp();
}
fn depth_clamp(&self) -> bool{
self.camera.depth_clamp()
}
fn set_reversed_z(&mut self, reversed_z: bool){
self.camera.set_reversed_z(reversed_z);
}
fn reversed_z(&self) -> bool{
self.camera.reversed_z()
}
fn far_at_infinity(&self) -> bool{
self.camera.far_at_infinity()
}
}
impl<C: CameraPerspective + NodeMut> CameraPerspective for Camera<C>{
fn set_fov(&mut self, fov: Deg<f32>){
self.camera.set_fov(fov);
}
fn set_near_with_far_at_infinity(&mut self, near: f32){
self.camera.set_near_with_far_at_infinity(near)
}
}
impl<C: CameraOrthographic + NodeMut> CameraOrthographic for Camera<C>{
fn set_width(&mut self, width: f32){
self.camera.set_width(width)
}
}
impl<C: NodeMut> NodeMut for Camera<C>{
fn node_mut(&mut self) -> &mut graphics::Node{
self.camera.node_mut()
}
fn update_with_parent_parts(
&mut self,
parent_loc: Option<&graphics::Node>,
parent_orientation: Option<&graphics::Node>,
parent_scale: Option<&graphics::Node>) -> bool
{
self.camera.update_with_parent_parts(parent_loc, parent_orientation, parent_scale)
}
fn update_with_parent(&mut self, parent: Option<&graphics::Node>) -> bool{
self.camera.update_with_parent_parts(parent, parent, parent)
}
fn look_at(&mut self, at: &Pnt3, up: &Vec3) -> rin_util::Result<()>{
self.camera.look_at(at, up)
}
fn rotate(&mut self, angle: Rad<f32>, axis: &Unit<Vec3>){
self.camera.rotate(angle, axis)
}
fn append_orientation(&mut self, orientation: &UnitQuat){
self.camera.append_orientation(orientation)
}
fn tilt(&mut self, angle: Rad<f32>){
self.camera.tilt(angle)
}
fn pan(&mut self, angle: Rad<f32>){
self.camera.pan(angle)
}
fn roll(&mut self, angle: Rad<f32>){
self.camera.roll(angle)
}
fn set_scale(&mut self, _: Vec3){
}
fn translate(&mut self, t: &Vec3){
self.camera.translate(t)
}
fn set_position(&mut self, pos: Pnt3){
self.camera.set_position(pos)
}
fn set_angle_axis(&mut self, angle: Rad<f32>, axis: &Unit<Vec3>){
self.camera.set_angle_axis(angle, axis)
}
fn set_orientation(&mut self, orientation: UnitQuat){
self.camera.set_orientation(orientation)
}
}
pub struct CameraUpdater{
viewport: TryIter<'static, Rect<i32>>,
}
impl CameraUpdater{
pub fn new(viewport: Stream<'static, Rect<i32>>) -> CameraUpdater{
CameraUpdater{
viewport: viewport.dedup().try_iter()
}
}
}
pub struct CameraParts;
#[system(name = "camera updater")]
#[needs(CameraParts)]
#[updates(dyn CameraExt + Send, Viewport)]
#[cfg_attr(any(feature="desktop", feature="desktop_gles", feature="web"), needs("crate::events::Events"))]
impl System for CameraUpdater{
fn run(&mut self, _e: Entities, resources: Resources){
let mut camera = resources.as_trait_mut::<dyn CameraExt + Send>().unwrap();
let mut viewport = resources.get_mut::<Viewport>().unwrap();
if let Some(new_viewport) = self.viewport.by_ref().last() {
viewport.viewport = new_viewport;
viewport.changed = true;
camera.set_aspect_ratio(viewport.width as f32 / viewport.height as f32);
}else{
viewport.changed = false;
}
camera.update();
}
}