Fixed tests to compile; added Point homogeneous transform & test; added Transform inversion & test; Implemented Transform for AffineMatrix3
This commit is contained in:
parent
04b257e217
commit
364d959784
9 changed files with 135 additions and 44 deletions
|
@ -34,6 +34,7 @@ pub trait Rotation
|
|||
: Eq
|
||||
+ ApproxEq<S>
|
||||
{
|
||||
fn identity() -> Self;
|
||||
fn rotate_point(&self, point: &P) -> P;
|
||||
fn rotate_vec(&self, vec: &V) -> V;
|
||||
|
||||
|
@ -111,6 +112,9 @@ impl<S: Float> ToMat2<S> for Basis2<S> {
|
|||
}
|
||||
|
||||
impl<S: Float> Rotation<S, [S, ..2], Vec2<S>, Point2<S>> for Basis2<S> {
|
||||
#[inline]
|
||||
fn identity() -> Basis2<S> { Basis2{ mat: Mat2::identity() } }
|
||||
|
||||
#[inline]
|
||||
fn rotate_point(&self, _point: &Point2<S>) -> Point2<S> { fail!("Not yet implemented") }
|
||||
|
||||
|
@ -229,6 +233,9 @@ impl<S: Float> ToQuat<S> for Basis3<S> {
|
|||
}
|
||||
|
||||
impl<S: Float> Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Basis3<S> {
|
||||
#[inline]
|
||||
fn identity() -> Basis3<S> { Basis3{ mat: Mat3::identity() } }
|
||||
|
||||
#[inline]
|
||||
fn rotate_point(&self, _point: &Point3<S>) -> Point3<S> { fail!("Not yet implemented") }
|
||||
|
||||
|
@ -288,6 +295,9 @@ impl<S: Float> ToQuat<S> for Quat<S> {
|
|||
}
|
||||
|
||||
impl<S: Float> Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Quat<S> {
|
||||
#[inline]
|
||||
fn identity() -> Quat<S> { Quat::identity() }
|
||||
|
||||
#[inline]
|
||||
fn rotate_point(&self, _point: &Point3<S>) -> Point3<S> { fail!("Not yet implemented") }
|
||||
|
||||
|
@ -310,4 +320,4 @@ impl<S: Float> Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Quat<S> {
|
|||
fn invert_self(&mut self) { *self = self.invert() }
|
||||
}
|
||||
|
||||
impl<S: Float> Rotation3<S> for Quat<S> {}
|
||||
impl<S: Float> Rotation3<S> for Quat<S> {}
|
||||
|
|
|
@ -31,13 +31,23 @@ pub trait Transform
|
|||
P: Point<S,V,Slice>
|
||||
>
|
||||
{
|
||||
fn identity() -> Self;
|
||||
fn transform_vec(&self, vec: &V) -> V;
|
||||
fn transform_point(&self, point: &P) -> P;
|
||||
fn invert(&self) -> Option<Self>;
|
||||
|
||||
#[inline]
|
||||
fn transform_ray(&self, ray: &Ray<P,V>) -> Ray<P,V> {
|
||||
Ray::new( self.transform_point(&ray.origin), self.transform_vec(&ray.direction) )
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn invert_self(&mut self)-> bool {
|
||||
match self.invert() {
|
||||
Some(t) => {*self = t; true},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic transformation consisting of a rotation,
|
||||
|
@ -57,6 +67,15 @@ impl
|
|||
R: Rotation<S, Slice, V, P>
|
||||
>
|
||||
Transform<S, Slice, V, P> for Decomposed<S,V,R> {
|
||||
#[inline]
|
||||
fn identity() -> Decomposed<S,V,R> {
|
||||
Decomposed {
|
||||
scale: num::one(),
|
||||
rot: Rotation::identity(),
|
||||
disp: num::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transform_vec(&self, vec: &V) -> V {
|
||||
self.rot.rotate_vec( &vec.mul_s( self.scale.clone() ))
|
||||
|
@ -66,6 +85,23 @@ Transform<S, Slice, V, P> for Decomposed<S,V,R> {
|
|||
fn transform_point(&self, point: &P) -> P {
|
||||
self.rot.rotate_point( &point.mul_s( self.scale.clone() )).add_v( &self.disp )
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn invert(&self) -> Option<Decomposed<S,V,R>> {
|
||||
if self.scale.approx_eq( &num::zero() ) {
|
||||
None
|
||||
}else {
|
||||
let _1 : S = num::one();
|
||||
let s = _1 / self.scale;
|
||||
let r = self.rot.invert();
|
||||
let d = r.rotate_vec( &self.disp ).mul_s( -s );
|
||||
Some( Decomposed {
|
||||
scale: s,
|
||||
rot: r,
|
||||
disp: d,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Transform3<S>
|
||||
|
@ -92,6 +128,11 @@ pub struct AffineMatrix3<S> {
|
|||
|
||||
impl<S : Clone + Float>
|
||||
Transform<S, [S, ..3], Vec3<S>, Point3<S>> for AffineMatrix3<S> {
|
||||
#[inline]
|
||||
fn identity() -> AffineMatrix3<S> {
|
||||
AffineMatrix3 { mat: Mat4::identity() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transform_vec(&self, vec: &Vec3<S>) -> Vec3<S> {
|
||||
self.mat.mul_v( &vec.extend(num::zero()) ).truncate()
|
||||
|
@ -100,6 +141,11 @@ Transform<S, [S, ..3], Vec3<S>, Point3<S>> for AffineMatrix3<S> {
|
|||
#[inline]
|
||||
fn transform_point(&self, point: &Point3<S>) -> Point3<S> {
|
||||
Point3::from_homogeneous( &self.mat.mul_v( &point.to_homogeneous() ))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn invert(&self) -> Option<AffineMatrix3<S>> {
|
||||
self.mat.invert().map(|m| AffineMatrix3{ mat: m })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,4 +166,3 @@ impl<S: Float> Transform3D<S> {
|
|||
Transform3D( Decomposed { scale: scale, rot: rot, disp: disp })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ macro_rules! vec(
|
|||
#[inline]
|
||||
pub fn zero() -> $Self<$S> { $Self::from_value(zero()) }
|
||||
|
||||
/// The additive identity of the vector.
|
||||
/// The multiplicative identity of the vector.
|
||||
#[inline]
|
||||
pub fn ident() -> $Self<$S> { $Self::from_value(one()) }
|
||||
}
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
|
||||
use cgmath::matrix::*;
|
||||
use cgmath::vector::*;
|
||||
type float = f64;
|
||||
|
||||
pub mod mat2 {
|
||||
use cgmath::matrix::*;
|
||||
use cgmath::vector::*;
|
||||
type float = f64;
|
||||
|
||||
pub static A: Mat2<float> = Mat2 { x: Vec2 { x: 1.0, y: 3.0 },
|
||||
y: Vec2 { x: 2.0, y: 4.0 } };
|
||||
|
@ -34,6 +36,7 @@ pub mod mat2 {
|
|||
pub mod mat3 {
|
||||
use cgmath::matrix::*;
|
||||
use cgmath::vector::*;
|
||||
type float = f64;
|
||||
|
||||
pub static A: Mat3<float> = Mat3 { x: Vec3 { x: 1.0, y: 4.0, z: 7.0 },
|
||||
y: Vec3 { x: 2.0, y: 5.0, z: 8.0 },
|
||||
|
@ -55,6 +58,7 @@ pub mod mat3 {
|
|||
pub mod mat4 {
|
||||
use cgmath::matrix::*;
|
||||
use cgmath::vector::*;
|
||||
type float = f64;
|
||||
|
||||
pub static A: Mat4<float> = Mat4 { x: Vec4 { x: 1.0, y: 5.0, z: 9.0, w: 13.0 },
|
||||
y: Vec4 { x: 2.0, y: 6.0, z: 10.0, w: 14.0 },
|
||||
|
|
|
@ -18,11 +18,13 @@ use cgmath::point::*;
|
|||
|
||||
#[test]
|
||||
fn test_from_points() {
|
||||
assert_eq!(Plane::from_points(Point3::new(5f, 0f, 5f),
|
||||
Point3::new(5f, 5f, 5f),
|
||||
Point3::new(5f, 0f, -1f)), Some(Plane::from_abcd(-1f, 0f, 0f, 5f)));
|
||||
assert_eq!(Plane::from_points(Point3::new(5.0, 0.0, 5.0),
|
||||
Point3::new(5.0, 5.0, 5.0),
|
||||
Point3::new(5.0, 0.0, -1.0)),
|
||||
Some(Plane::from_abcd(-1.0, 0.0, 0.0, 5.0)));
|
||||
|
||||
assert_eq!(Plane::from_points(Point3::new(0f, 5f, -5f),
|
||||
Point3::new(0f, 5f, 0f),
|
||||
Point3::new(0f, 5f, 5f)), None); // The points are parallel
|
||||
assert_eq!(Plane::from_points(Point3::new(0.0, 5.0, -5.0),
|
||||
Point3::new(0.0, 5.0, 0.0),
|
||||
Point3::new(0.0, 5.0, 5.0)),
|
||||
None); // The points are parallel
|
||||
}
|
||||
|
|
|
@ -18,5 +18,5 @@ use cgmath::point::*;
|
|||
#[test]
|
||||
fn test_homogeneous() {
|
||||
let p = Point3::new(1.0, 2.0, 3.0);
|
||||
assert_eq!(p, Point3::from_homogeneous( &p.to_homogeneous() ));
|
||||
assert_approx_eq!(p, Point3::from_homogeneous( &p.to_homogeneous() ));
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[feature(globs)];
|
||||
|
||||
extern mod cgmath;
|
||||
|
||||
// pub mod array;
|
||||
|
@ -25,6 +27,7 @@ pub mod plane;
|
|||
pub mod point;
|
||||
// pub mod ray;
|
||||
// pub mod rotation;
|
||||
pub mod transform;
|
||||
|
||||
// pub mod projection;
|
||||
|
||||
|
|
27
src/tests/transform.rs
Normal file
27
src/tests/transform.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use cgmath::quaternion::*;
|
||||
use cgmath::transform::*;
|
||||
use cgmath::vector::*;
|
||||
|
||||
#[test]
|
||||
fn test_invert() {
|
||||
let v = Vec3::new(1.0, 2.0, 3.0);
|
||||
let t = Transform3D::new( 1.5, Quat::new(0.5,0.5,0.5,0.5), Vec3::new(6.0,-7.0,8.0) );
|
||||
let ti = t.invert().expect("Expected successful inversion");
|
||||
let vt = t.transform_vec( &v );
|
||||
assert_approx_eq!(v, ti.transform_vec( &vt ));
|
||||
}
|
|
@ -36,9 +36,9 @@ fn test_comp_add() {
|
|||
assert_eq!(Vec3::new(1, 2, 3).comp_add(), 6);
|
||||
assert_eq!(Vec4::new(1, 2, 3, 4).comp_add(), 10);
|
||||
|
||||
assert_eq!(Vec2::new(3f, 4f).comp_add(), 7f);
|
||||
assert_eq!(Vec3::new(4f, 5f, 6f).comp_add(), 15f);
|
||||
assert_eq!(Vec4::new(5f, 6f, 7f, 8f).comp_add(), 26f);
|
||||
assert_eq!(Vec2::new(3.0, 4.0).comp_add(), 7.0);
|
||||
assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_add(), 15.0);
|
||||
assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_add(), 26.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -47,9 +47,9 @@ fn test_comp_mul() {
|
|||
assert_eq!(Vec3::new(1, 2, 3).comp_mul(), 6);
|
||||
assert_eq!(Vec4::new(1, 2, 3, 4).comp_mul(), 24);
|
||||
|
||||
assert_eq!(Vec2::new(3f, 4f).comp_mul(), 12f);
|
||||
assert_eq!(Vec3::new(4f, 5f, 6f).comp_mul(), 120f);
|
||||
assert_eq!(Vec4::new(5f, 6f, 7f, 8f).comp_mul(), 1680f);
|
||||
assert_eq!(Vec2::new(3.0, 4.0).comp_mul(), 12.0);
|
||||
assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_mul(), 120.0);
|
||||
assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_mul(), 1680.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -58,9 +58,9 @@ fn test_comp_min() {
|
|||
assert_eq!(Vec3::new(1, 2, 3).comp_min(), 1);
|
||||
assert_eq!(Vec4::new(1, 2, 3, 4).comp_min(), 1);
|
||||
|
||||
assert_eq!(Vec2::new(3f, 4f).comp_min(), 3f);
|
||||
assert_eq!(Vec3::new(4f, 5f, 6f).comp_min(), 4f);
|
||||
assert_eq!(Vec4::new(5f, 6f, 7f, 8f).comp_min(), 5f);
|
||||
assert_eq!(Vec2::new(3.0, 4.0).comp_min(), 3.0);
|
||||
assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_min(), 4.0);
|
||||
assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_min(), 5.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -69,9 +69,9 @@ fn test_comp_max() {
|
|||
assert_eq!(Vec3::new(1, 2, 3).comp_max(), 3);
|
||||
assert_eq!(Vec4::new(1, 2, 3, 4).comp_max(), 4);
|
||||
|
||||
assert_eq!(Vec2::new(3f, 4f).comp_max(), 4f);
|
||||
assert_eq!(Vec3::new(4f, 5f, 6f).comp_max(), 6f);
|
||||
assert_eq!(Vec4::new(5f, 6f, 7f, 8f).comp_max(), 8f);
|
||||
assert_eq!(Vec2::new(3.0, 4.0).comp_max(), 4.0);
|
||||
assert_eq!(Vec3::new(4.0, 5.0, 6.0).comp_max(), 6.0);
|
||||
assert_eq!(Vec4::new(5.0, 6.0, 7.0, 8.0).comp_max(), 8.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -88,9 +88,9 @@ fn test_cross() {
|
|||
|
||||
#[test]
|
||||
fn test_is_perpendicular() {
|
||||
assert!(Vec2::new(1f, 0f).is_perpendicular(&Vec2::new(0f, 1f)));
|
||||
assert!(Vec3::new(0f, 1f, 0f).is_perpendicular(&Vec3::new(0f, 0f, 1f)));
|
||||
assert!(Vec4::new(1f, 0f, 0f, 0f).is_perpendicular(&Vec4::new(0f, 0f, 0f, 1f)));
|
||||
assert!(Vec2::new(1.0, 0.0).is_perpendicular(&Vec2::new(0.0, 1.0)));
|
||||
assert!(Vec3::new(0.0, 1.0, 0.0).is_perpendicular(&Vec3::new(0.0, 0.0, 1.0)));
|
||||
assert!(Vec4::new(1.0, 0.0, 0.0, 0.0).is_perpendicular(&Vec4::new(0.0, 0.0, 0.0, 1.0)));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -99,8 +99,8 @@ mod test_length {
|
|||
|
||||
#[test]
|
||||
fn test_vec2(){
|
||||
let (a, a_res) = (Vec2::new(3f, 4f), 5f); // (3, 4, 5) Pythagorean triple
|
||||
let (b, b_res) = (Vec2::new(5f, 12f), 13f); // (5, 12, 13) Pythagorean triple
|
||||
let (a, a_res) = (Vec2::new(3.0, 4.0), 5.0); // (3, 4, 5) Pythagorean triple
|
||||
let (b, b_res) = (Vec2::new(5.0, 12.0), 13.0); // (5, 12, 13) Pythagorean triple
|
||||
|
||||
assert_eq!(a.length2(), a_res * a_res);
|
||||
assert_eq!(b.length2(), b_res * b_res);
|
||||
|
@ -111,8 +111,8 @@ mod test_length {
|
|||
|
||||
#[test]
|
||||
fn test_vec3(){
|
||||
let (a, a_res) = (Vec3::new(2f, 3f, 6f), 7f); // (2, 3, 6, 7) Pythagorean quadruple
|
||||
let (b, b_res) = (Vec3::new(1f, 4f, 8f), 9f); // (1, 4, 8, 9) Pythagorean quadruple
|
||||
let (a, a_res) = (Vec3::new(2.0, 3.0, 6.0), 7.0); // (2, 3, 6, 7) Pythagorean quadruple
|
||||
let (b, b_res) = (Vec3::new(1.0, 4.0, 8.0), 9.0); // (1, 4, 8, 9) Pythagorean quadruple
|
||||
|
||||
assert_eq!(a.length2(), a_res * a_res);
|
||||
assert_eq!(b.length2(), b_res * b_res);
|
||||
|
@ -123,8 +123,8 @@ mod test_length {
|
|||
|
||||
#[test]
|
||||
fn test_vec4(){
|
||||
let (a, a_res) = (Vec4::new(1f, 2f, 4f, 10f), 11f); // (1, 2, 4, 10, 11) Pythagorean quintuple
|
||||
let (b, b_res) = (Vec4::new(1f, 2f, 8f, 10f), 13f); // (1, 2, 8, 10, 13) Pythagorean quintuple
|
||||
let (a, a_res) = (Vec4::new(1.0, 2.0, 4.0, 10.0), 11.0); // (1, 2, 4, 10, 11) Pythagorean quintuple
|
||||
let (b, b_res) = (Vec4::new(1.0, 2.0, 8.0, 10.0), 13.0); // (1, 2, 8, 10, 13) Pythagorean quintuple
|
||||
|
||||
assert_eq!(a.length2(), a_res * a_res);
|
||||
assert_eq!(b.length2(), b_res * b_res);
|
||||
|
@ -136,23 +136,23 @@ mod test_length {
|
|||
|
||||
#[test]
|
||||
fn test_angle() {
|
||||
assert_approx_eq!(Vec2::new(1f, 0f).angle(&Vec2::new(0f, 1f)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec2::new(10f, 0f).angle(&Vec2::new(0f, 5f)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec2::new(-1f, 0f).angle(&Vec2::new(0f, 1f)), -rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec2::new(1.0, 0.0).angle(&Vec2::new(0.0, 1.0)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec2::new(10.0, 0.0).angle(&Vec2::new(0.0, 5.0)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec2::new(-1.0, 0.0).angle(&Vec2::new(0.0, 1.0)), -rad(Real::frac_pi_2()));
|
||||
|
||||
assert_approx_eq!(Vec3::new(1f, 0f, 1f).angle(&Vec3::new(1f, 1f, 0f)), rad(Real::frac_pi_3()));
|
||||
assert_approx_eq!(Vec3::new(10f, 0f, 10f).angle(&Vec3::new(5f, 5f, 0f)), rad(Real::frac_pi_3()));
|
||||
assert_approx_eq!(Vec3::new(-1f, 0f, -1f).angle(&Vec3::new(1f, -1f, 0f)), rad(2f * Real::frac_pi_3()));
|
||||
assert_approx_eq!(Vec3::new(1.0, 0.0, 1.0).angle(&Vec3::new(1.0, 1.0, 0.0)), rad(Real::frac_pi_3()));
|
||||
assert_approx_eq!(Vec3::new(10.0, 0.0, 10.0).angle(&Vec3::new(5.0, 5.0, 0.0)), rad(Real::frac_pi_3()));
|
||||
assert_approx_eq!(Vec3::new(-1.0, 0.0, -1.0).angle(&Vec3::new(1.0, -1.0, 0.0)), rad(2.0 * Real::frac_pi_3()));
|
||||
|
||||
assert_approx_eq!(Vec4::new(1f, 0f, 1f, 0f).angle(&Vec4::new(0f, 1f, 0f, 1f)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec4::new(10f, 0f, 10f, 0f).angle(&Vec4::new(0f, 5f, 0f, 5f)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec4::new(-1f, 0f, -1f, 0f).angle(&Vec4::new(0f, 1f, 0f, 1f)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec4::new(1.0, 0.0, 1.0, 0.0).angle(&Vec4::new(0.0, 1.0, 0.0, 1.0)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec4::new(10.0, 0.0, 10.0, 0.0).angle(&Vec4::new(0.0, 5.0, 0.0, 5.0)), rad(Real::frac_pi_2()));
|
||||
assert_approx_eq!(Vec4::new(-1.0, 0.0, -1.0, 0.0).angle(&Vec4::new(0.0, 1.0, 0.0, 1.0)), rad(Real::frac_pi_2()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_normalize() {
|
||||
// TODO: test normalize_to, normalize_self, and normalize_self_to
|
||||
assert_approx_eq!(Vec2::new(3f, 4f).normalize(), Vec2::new(3f/5f, 4f/5f));
|
||||
assert_approx_eq!(Vec3::new(2f, 3f, 6f).normalize(), Vec3::new(2f/7f, 3f/7f, 6f/7f));
|
||||
assert_approx_eq!(Vec4::new(1f, 2f, 4f, 10f).normalize(), Vec4::new(1f/11f, 2f/11f, 4f/11f, 10f/11f));
|
||||
// TODO: test normalize_to, normalize_sel.0, and normalize_self_to
|
||||
assert_approx_eq!(Vec2::new(3.0, 4.0).normalize(), Vec2::new(3.0/5.0, 4.0/5.0));
|
||||
assert_approx_eq!(Vec3::new(2.0, 3.0, 6.0).normalize(), Vec3::new(2.0/7.0, 3.0/7.0, 6.0/7.0));
|
||||
assert_approx_eq!(Vec4::new(1.0, 2.0, 4.0, 10.0).normalize(), Vec4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue