mirror of
https://github.com/lisk77/comet.git
synced 2025-10-24 13:58:49 +00:00
feat: added a Bezier struct for a general bezier curve implementation
This commit is contained in:
parent
30afffdf32
commit
d0e9a1b456
3 changed files with 130 additions and 145 deletions
|
|
@ -1,145 +1,27 @@
|
||||||
use num_traits::Pow;
|
use crate::Point;
|
||||||
|
|
||||||
use crate::point::{Point2, Point3};
|
pub struct Bezier<P: Point> {
|
||||||
use crate::vector::{Vec2, Vec3};
|
points: Vec<P>,
|
||||||
use crate::utilities::{lerp2, lerp3, fac};
|
degree: usize
|
||||||
|
|
||||||
pub trait ParameterCurve2 {
|
|
||||||
//fn arcLen(&self) -> f32;
|
|
||||||
fn getPoint(&self, t: f32) -> Point2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ParameterCurve3 {
|
impl<P: Point + Clone> Bezier<P> {
|
||||||
//fn arcLen(&self) -> f32;
|
pub fn new(points: Vec<P>) -> Self {
|
||||||
fn getPoint(&self, t: f32) -> Point3;
|
let degree = points.len() - 1;
|
||||||
}
|
|
||||||
|
|
||||||
/// A general Bézier Curve in 2D
|
Self {
|
||||||
/// WORK IN PROGRESS: DOES NOT WORK (use cBezier2 instead)
|
points,
|
||||||
#[repr(C)]
|
degree
|
||||||
pub struct Bezier2 {
|
|
||||||
points: Vec<Point2>,
|
|
||||||
degree: u8
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bezier2 {
|
|
||||||
pub fn new(points: Vec<Point2>) -> Self {
|
|
||||||
let n = points.len() as u8;
|
|
||||||
Self { points: points, degree: n }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// A general Bézier Curve in 3D
|
|
||||||
/// WORK IN PROGRESS: DOES NOT WORK (use cBezier3 instead)
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Bezier3 {
|
|
||||||
points: Vec<Point3>,
|
|
||||||
degree: u8
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bezier3 {
|
|
||||||
pub fn new(points: Vec<Point3>) -> Self {
|
|
||||||
let n = points.len() as u8;
|
|
||||||
Self { points: points, degree: n }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A cubic Bézier Curve in 2D
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct cBezier2 {
|
|
||||||
p0: Point2,
|
|
||||||
p1: Point2,
|
|
||||||
p2: Point2,
|
|
||||||
p3: Point2
|
|
||||||
}
|
|
||||||
|
|
||||||
impl cBezier2 {
|
|
||||||
pub fn new(p0: Point2, p1: Point2, p2: Point2, p3: Point2) -> Self {
|
|
||||||
Self { p0, p1, p2, p3 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ParameterCurve2 for cBezier2 {
|
|
||||||
fn getPoint(&self, t: f32) -> Point2 {
|
|
||||||
let tSquared = t * t;
|
|
||||||
let tCubed = tSquared * t;
|
|
||||||
let vP0 = Vec2::from_point(self.p0);
|
|
||||||
let vP1 = Vec2::from_point(self.p1);
|
|
||||||
let vP2 = Vec2::from_point(self.p2);
|
|
||||||
let vP3 = Vec2::from_point(self.p3);
|
|
||||||
|
|
||||||
Point2::from_vec(
|
|
||||||
vP0 * (-tCubed + 3.0 * tSquared - 3.0 * t + 1.0 ) +
|
|
||||||
vP1 * (3.0 * tCubed - 6.0 * tSquared + 3.0 * t ) +
|
|
||||||
vP2 * (-3.0 * tCubed + 3.0 * tSquared ) +
|
|
||||||
vP3 * tCubed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A cubic Bézier Curve in 3D
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct cBezier3 {
|
|
||||||
p0: Point3,
|
|
||||||
p1: Point3,
|
|
||||||
p2: Point3,
|
|
||||||
p3: Point3
|
|
||||||
}
|
|
||||||
|
|
||||||
impl cBezier3 {
|
|
||||||
pub fn new(p0: Point3, p1: Point3, p2: Point3, p3: Point3) -> Self {
|
|
||||||
Self { p0, p1, p2, p3 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ParameterCurve2 for Bezier2 {
|
|
||||||
fn getPoint(&self, t: f32) -> Point2 {
|
|
||||||
let n = self.points.len();
|
|
||||||
let mut points = self.points.clone();
|
|
||||||
|
|
||||||
for k in 1..n {
|
|
||||||
for i in 0..n - k {
|
|
||||||
points[i] = Point2::from_vec(lerp2(Vec2::from_point(points[i]), Vec2::from_point(points[i + 1]), t));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
points[0]
|
pub fn evaluate(&self, t: f32) -> P {
|
||||||
|
let mut new_points = self.points.clone();
|
||||||
|
for i in 0..self.degree {
|
||||||
|
for j in 0..(self.degree - i) {
|
||||||
|
new_points[j] = new_points[j].lerp(&new_points[j + 1], t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_points[0].clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParameterCurve3 for Bezier3 {
|
|
||||||
fn getPoint(&self, t: f32) -> Point3 {
|
|
||||||
let n = self.points.len();
|
|
||||||
let mut points = self.points.clone();
|
|
||||||
|
|
||||||
for k in 1..n {
|
|
||||||
for i in 0..n - k {
|
|
||||||
points[i] = Point3::from_vec(lerp3(Vec3::from_point(points[i]), Vec3::from_point(points[i + 1]), t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
points[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ParameterCurve3 for cBezier3 {
|
|
||||||
fn getPoint(&self, t: f32) -> Point3 {
|
|
||||||
let tSquared = t * t;
|
|
||||||
let tCubed = tSquared * t;
|
|
||||||
let vP0 = Vec3::from_point(self.p0);
|
|
||||||
let vP1 = Vec3::from_point(self.p1);
|
|
||||||
let vP2 = Vec3::from_point(self.p2);
|
|
||||||
let vP3 = Vec3::from_point(self.p3);
|
|
||||||
|
|
||||||
Point3::from_vec(
|
|
||||||
vP0 * (-tCubed + 3.0 * tSquared - 3.0 * t + 1.0 ) +
|
|
||||||
vP1 * (3.0 * tCubed - 6.0 * tSquared + 3.0 * t ) +
|
|
||||||
vP2 * (-3.0 * tCubed + 3.0 * tSquared ) +
|
|
||||||
vP3 * tCubed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
|
use crate::InnerSpace;
|
||||||
use crate::vector::{Vec2, Vec3};
|
use crate::vector::{Vec2, Vec3};
|
||||||
|
|
||||||
|
pub trait Point {
|
||||||
|
fn lerp(&self, other: &Self, t: f32) -> Self;
|
||||||
|
fn to_vec(&self) -> impl InnerSpace;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Point2 {
|
pub struct Point2 {
|
||||||
x: f32,
|
x: f32,
|
||||||
|
|
@ -22,10 +28,6 @@ impl Point2 {
|
||||||
Self { x: v.x(), y: v.y() }
|
Self { x: v.x(), y: v.y() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_vec(&self) -> Vec2 {
|
|
||||||
Vec2::new(self.x, self.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn x(&self) -> f32 {
|
pub fn x(&self) -> f32 {
|
||||||
self.x
|
self.x
|
||||||
}
|
}
|
||||||
|
|
@ -44,10 +46,6 @@ impl Point3 {
|
||||||
Self { x: v.x(), y: v.y(), z: v.z() }
|
Self { x: v.x(), y: v.y(), z: v.z() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_vec(&self) -> Vec3 {
|
|
||||||
Vec3::new(self.x, self.y, self.z)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn x(&self) -> f32 {
|
pub fn x(&self) -> f32 {
|
||||||
self.x
|
self.x
|
||||||
}
|
}
|
||||||
|
|
@ -60,3 +58,51 @@ impl Point3 {
|
||||||
self.z
|
self.z
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Point for Point2 {
|
||||||
|
fn lerp(&self, other: &Self, t: f32) -> Self {
|
||||||
|
let x = self.x + (other.x - self.x) * t;
|
||||||
|
let y = self.y + (other.y - self.y) * t;
|
||||||
|
Self { x, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_vec(&self) -> Vec2 {
|
||||||
|
Vec2::new(self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Point for Point3 {
|
||||||
|
fn lerp(&self, other: &Self, t: f32) -> Self {
|
||||||
|
let x = self.x + (other.x - self.x) * t;
|
||||||
|
let y = self.y + (other.y - self.y) * t;
|
||||||
|
let z = self.z + (other.z - self.z) * t;
|
||||||
|
Self { x, y, z }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_vec(&self) -> Vec3 {
|
||||||
|
Vec3::new(self.x, self.y, self.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Vec2> for Point2 {
|
||||||
|
fn into(self) -> Vec2 {
|
||||||
|
self.to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Vec3> for Point3 {
|
||||||
|
fn into(self) -> Vec3 {
|
||||||
|
self.to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec2> for Point2 {
|
||||||
|
fn from(v: Vec2) -> Self {
|
||||||
|
Self::from_vec(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec3> for Point3 {
|
||||||
|
fn from(v: Vec3) -> Self {
|
||||||
|
Self::from_vec(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,16 @@ use crate::point::{Point2, Point3};
|
||||||
use crate::quaternion::Quat;
|
use crate::quaternion::Quat;
|
||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
|
|
||||||
pub trait InnerSpace {
|
pub trait InnerSpace:
|
||||||
|
std::fmt::Debug +
|
||||||
|
Copy +
|
||||||
|
Clone +
|
||||||
|
Neg<Output = Self> +
|
||||||
|
Mul<f32, Output = Self> +
|
||||||
|
Div<f32, Output = Self> +
|
||||||
|
Add<Self, Output = Self> +
|
||||||
|
Sub<Self, Output = Self>
|
||||||
|
{
|
||||||
fn dot(&self, other: &Self) -> f32;
|
fn dot(&self, other: &Self) -> f32;
|
||||||
fn dist(&self, other: &Self) -> f32;
|
fn dist(&self, other: &Self) -> f32;
|
||||||
fn angle(&self, other: &Self) -> f32;
|
fn angle(&self, other: &Self) -> f32;
|
||||||
|
|
@ -93,6 +102,17 @@ impl SubAssign for Vec2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Neg for Vec2 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
x: -self.x,
|
||||||
|
y: -self.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<f32> for Vec2 {
|
impl Mul<f32> for Vec2 {
|
||||||
type Output = Vec2;
|
type Output = Vec2;
|
||||||
|
|
||||||
|
|
@ -505,6 +525,17 @@ impl Into<[f32;3]> for Vec3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<Vec3> for [f32;3] {
|
||||||
|
fn into(self) -> Vec3 {
|
||||||
|
Vec3 {
|
||||||
|
x: self[0],
|
||||||
|
y: self[1],
|
||||||
|
z: self[2],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
|
@ -793,6 +824,19 @@ impl SubAssign for Vec4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Neg for Vec4 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
x: -self.x,
|
||||||
|
y: -self.y,
|
||||||
|
z: -self.z,
|
||||||
|
w: -self.w,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<f32> for Vec4 {
|
impl Mul<f32> for Vec4 {
|
||||||
type Output = Vec4;
|
type Output = Vec4;
|
||||||
|
|
||||||
|
|
@ -828,6 +872,19 @@ impl MulAssign<f32> for Vec4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<f32> for Vec4 {
|
||||||
|
type Output = Vec4;
|
||||||
|
|
||||||
|
fn div(self, other: f32) -> Vec4 {
|
||||||
|
Vec4 {
|
||||||
|
x: self.x / other,
|
||||||
|
y: self.y / other,
|
||||||
|
z: self.z / other,
|
||||||
|
w: self.w / other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Into<[f32;4]> for Vec4 {
|
impl Into<[f32;4]> for Vec4 {
|
||||||
fn into(self) -> [f32;4] {
|
fn into(self) -> [f32;4] {
|
||||||
[self.x, self.y, self.z, self.w]
|
[self.x, self.y, self.z, self.w]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue