Convert 16.16 fixed point curve export to fractional x/128 export
parent
9e1014bbd9
commit
18f1e20aa1
|
@ -1,6 +1,4 @@
|
|||
use std::error::Error;
|
||||
use fixed::FixedI32;
|
||||
use fixed::types::extra::U16;
|
||||
use flo_curves::*;
|
||||
use flo_curves::{bezier, Coord2};
|
||||
|
||||
|
@ -14,20 +12,19 @@ easing function is cubic bezier going from 0.0 to 1.0
|
|||
|
||||
140-120=20 increments
|
||||
0.0 is +0 and 1.0 is +20
|
||||
so e.g. if you read a 0.5 at the given increment it's 0.5 * 20 = +10
|
||||
|
||||
curves are exported from reskit sampled at 1/60 increments
|
||||
reskit accepts arguments for control points and exports 16.16 fixed point binary files
|
||||
so a 1 second animation is 60 increments, 2 seconds is 120, etc.
|
||||
|
||||
each iteration be like:
|
||||
1. take cubic bezier sample and post increment
|
||||
2. the value at this iteration is (final - beginning) * sample
|
||||
a. so example (140-120)*0.5 for a linear curve sampled right in the middle
|
||||
3. round the value to the nearest whole integer
|
||||
4. do not go back to 1 if we exhausted the curve
|
||||
|
||||
need fixed point arithmetic multiplication
|
||||
console has no floating point and fixed point will overflow 16-bit
|
||||
each curve tailored for use case. for camera motion:
|
||||
- generate the cubic bezier easing curve in my custom branch of reskit, converting 0.0-1.0 floating point spans to x/128 fractions equivalent to x/100 fractions.
|
||||
literal grade school shit i realised i wasted a weekend re-deriving from first principles. these fparts even export as single bytes, so that's 3 less bytes per point
|
||||
on the curve than if i were sticking with 16.16 fix. for a 1 second animation, 60 points are taken on the 0.0-1.0 curve, for a 2 second animation, 120 points are taken, etc.
|
||||
equivalent PAL framerate curves can be export in the same curve file.
|
||||
- the camera animates moves by setting a new destination point and performing interpolation of intermediate positions along the curve - just like css easing functions, or
|
||||
unity/unreal bezier curves. you restrict camera new position to +/- powers of two in any axis to eliminate mul[s/u].w. e.g. camera moves +2, +4, +8.... in the x direction.
|
||||
- for each axis, new position - current position = span of movement. so if you're starting at x = 30 and moving to x = 46, you're going +16 in the x direction
|
||||
- while the camera is animating, interpolate positions by reading the fractional on the curve for the current frame and doing fractional * span / 128. since new camera positions
|
||||
in any axis are kept power of two this can all be done using asl/asr. take the remainder with the and 2^127 trick and bump the resulting value up 1 if the modulo is >= 64
|
||||
- ✨ cubic bezier animated camera motion
|
||||
*/
|
||||
|
||||
|
||||
|
@ -48,15 +45,20 @@ pub fn get_cubic_bezier( p0: (f64, f64), c0: (f64, f64), c1: (f64, f64), p1: (f6
|
|||
);
|
||||
|
||||
let mut current_jiffy = 0.0;
|
||||
// (jiffies) of 16.16 fixed point integers: Each point in the curve at the given frame
|
||||
// For each point in curve: 1 byte fractional point in the curve at the given frame
|
||||
for i in 0..jiffies {
|
||||
let point = curve.point_at_pos( current_jiffy );
|
||||
let x = point.1;
|
||||
print_info( &format!( "at iteration {}, curve is {:?}, 16.16 format will be {}", i, point, x ) );
|
||||
|
||||
// Round and convert x to n/100 fraction, then equivalent n/128 fraction
|
||||
let x = ( ( x * 100.0 ).round() / 100.0 ) * 100.0; // only get last two decimal places, then convert to whole number
|
||||
let x = x * 128.0 / 100.0; // x / 100 = y / 128
|
||||
let x = x.round() as u8;
|
||||
|
||||
print_info( &format!( "at iteration {}, curve is {:?}, fractional format will be {}", i, point, x ) );
|
||||
current_jiffy += 1.0 / jiffies as f64;
|
||||
|
||||
let as_fixed = FixedI32::<U16>::from_num( x );
|
||||
result.extend( as_fixed.to_be_bytes() );
|
||||
result.push( x );
|
||||
}
|
||||
|
||||
Ok( result )
|
||||
|
|
Loading…
Reference in New Issue