From 985db6b6040203b15aacea45d90dd0f1ea8cc998 Mon Sep 17 00:00:00 2001 From: Egor Larionov Date: Sat, 30 Sep 2017 01:38:03 -0700 Subject: [PATCH 1/8] Initial implementation of swizzle operators using a build script that generates a macro, which is included in macros.rs and subsequently used to implement swizzle operators in vectors and points --- build.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/macros.rs | 2 ++ 2 files changed, 66 insertions(+) create mode 100644 build.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..3c2e7dc --- /dev/null +++ b/build.rs @@ -0,0 +1,64 @@ +use std::fs::File; +use std::io::Write; +use std::path::Path; +use std::env; +use std::string::String; + +/// Generate the name of the swizzle function and what it returns. +/// NOTE: This function assumes that variables are in ASCII format +fn gen_swizzle_nth(variables: &'static str, mut i: usize) -> (String, String) { + let mut swizzle_impl = String::new(); + let mut swizzle = String::new(); + let n = variables.len(); + for _ in 0..n { + let c = variables.as_bytes()[i%n] as char; + swizzle.push(c); + swizzle_impl.push_str(&format!("self.{}, ", c)); + i = i/n; + } + (swizzle, swizzle_impl) +} + +/// This script generates the swizzle operators that are included in macros.rs +/// NOTE: This function assumes that variables are in ASCII format +fn gen_swizzle_functions(variables: &'static str) -> String { + let n = variables.len(); + let vec_type = format!("$vector_type{}", n); + let mut result = String::new(); + let nn = n.pow(n as u32); + for i in 0..nn { + let (swizzle_name, swizzle_impl) = gen_swizzle_nth(variables, i); + result.push_str( + &format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n", + swizzle_name, swizzle_impl, vec_type)); + } + result +} + +fn main() { + // The following scripts generates a macro for building swizzle operators for multidimensional + // vectors or points. + let out_dir = env::var("OUT_DIR").unwrap(); + let swizzle_file_path = Path::new(&out_dir).join("swizzle_operator_macro.rs"); + + let data = format!( +"/// Generate glm/glsl style swizzle operators +macro_rules! impl_swizzle_functions {{ + ($vector_type2:ident, $S:ident, xy) => {{ +{xy} + }}; + ($vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{ + impl_swizzle_functions!($vector_type2, $S, xy); +{xyz} + }}; + ($vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{ + impl_swizzle_functions!($vector_type2, $vector_type3, $S, xyz); +{xyzw} + }}; +}}", xy=gen_swizzle_functions("xy"), + xyz=gen_swizzle_functions("xyz"), + xyzw=gen_swizzle_functions("xyzw")); + let mut f = File::create(swizzle_file_path) + .expect("Unable to create file that defines the swizzle operator macro."); + f.write_all(data.as_bytes()).expect("Unable to write swizzle operator macro."); +} diff --git a/src/macros.rs b/src/macros.rs index 768c4fd..573c597 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -476,3 +476,5 @@ macro_rules! impl_mint_conversions { } } } + +include!(concat!(env!("OUT_DIR"), "/swizzle_operator_macro.rs")); From cc7047555d61f1468004f1fd40ac7972117880b2 Mon Sep 17 00:00:00 2001 From: Egor Larionov Date: Sat, 30 Sep 2017 14:41:17 -0700 Subject: [PATCH 2/8] Complete the list of generated swizzle operators. --- build.rs | 49 ++++++++++++++++++++++++++++--------------------- src/point.rs | 6 ++++++ src/vector.rs | 8 ++++++++ 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/build.rs b/build.rs index 3c2e7dc..9a7b93d 100644 --- a/build.rs +++ b/build.rs @@ -6,56 +6,63 @@ use std::string::String; /// Generate the name of the swizzle function and what it returns. /// NOTE: This function assumes that variables are in ASCII format -fn gen_swizzle_nth(variables: &'static str, mut i: usize) -> (String, String) { +fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize) -> Option<(String, String)> { + debug_assert!(i > 0); // zeroth permutation is empty let mut swizzle_impl = String::new(); let mut swizzle = String::new(); - let n = variables.len(); - for _ in 0..n { - let c = variables.as_bytes()[i%n] as char; + let n = variables.len()+1; + for _ in 0..variables.len() { + if i == 0 { break; } + if i % n == 0 { return None; } + let c = variables.as_bytes()[i%n - 1] as char; swizzle.push(c); swizzle_impl.push_str(&format!("self.{}, ", c)); i = i/n; } - (swizzle, swizzle_impl) + Some((swizzle, swizzle_impl)) } -/// This script generates the swizzle operators that are included in macros.rs /// NOTE: This function assumes that variables are in ASCII format fn gen_swizzle_functions(variables: &'static str) -> String { let n = variables.len(); - let vec_type = format!("$vector_type{}", n); let mut result = String::new(); - let nn = n.pow(n as u32); - for i in 0..nn { - let (swizzle_name, swizzle_impl) = gen_swizzle_nth(variables, i); - result.push_str( - &format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n", - swizzle_name, swizzle_impl, vec_type)); + let nn = (n+1).pow(n as u32); + for i in 1..nn { + if let Some((swizzle_name, swizzle_impl)) = gen_swizzle_nth(variables, i) { + let vec_type = format!("$vector_type{}", swizzle_name.len()); + result.push_str( + &format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n", + swizzle_name, swizzle_impl, vec_type)); + } } result } +/// This script generates the macro for building swizzle operators for multidimensional +/// vectors and points. This macro is included in macros.rs fn main() { - // The following scripts generates a macro for building swizzle operators for multidimensional - // vectors or points. + // save the file to output directory let out_dir = env::var("OUT_DIR").unwrap(); let swizzle_file_path = Path::new(&out_dir).join("swizzle_operator_macro.rs"); + // This is the string representing the generated macro let data = format!( "/// Generate glm/glsl style swizzle operators macro_rules! impl_swizzle_functions {{ - ($vector_type2:ident, $S:ident, xy) => {{ + ($vector_type1:ident, $S:ident, x) => {{ +{x} + }}; + ($vector_type1:ident, $vector_type2:ident, $S:ident, xy) => {{ {xy} }}; - ($vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{ - impl_swizzle_functions!($vector_type2, $S, xy); + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{ {xyz} }}; - ($vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{ - impl_swizzle_functions!($vector_type2, $vector_type3, $S, xyz); + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{ {xyzw} }}; -}}", xy=gen_swizzle_functions("xy"), +}}", x=gen_swizzle_functions("x"), + xy=gen_swizzle_functions("xy"), xyz=gen_swizzle_functions("xyz"), xyzw=gen_swizzle_functions("xyzw")); let mut f = File::create(swizzle_file_path) diff --git a/src/point.rs b/src/point.rs index 35550e3..9436c22 100644 --- a/src/point.rs +++ b/src/point.rs @@ -69,6 +69,8 @@ impl Point1 { pub fn new(x: S) -> Point1 { Point1 { x: x } } + + impl_swizzle_functions!(Point1, S, x); } impl Point2 { @@ -76,6 +78,8 @@ impl Point2 { pub fn new(x: S, y: S) -> Point2 { Point2 { x: x, y: y } } + + impl_swizzle_functions!(Point1, Point2, S, xy); } impl Point3 { @@ -83,6 +87,8 @@ impl Point3 { pub fn new(x: S, y: S, z: S) -> Point3 { Point3 { x: x, y: y, z: z } } + + impl_swizzle_functions!(Point1, Point2, Point3, S, xyz); } impl Point3 { diff --git a/src/vector.rs b/src/vector.rs index 1b395d1..7ebf06c 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -605,6 +605,8 @@ impl Vector1 { pub fn unit_x() -> Vector1 { Vector1::new(S::one()) } + + impl_swizzle_functions!(Vector1, S, x); } impl Vector2 { @@ -632,6 +634,8 @@ impl Vector2 { pub fn extend(self, z: S) -> Vector3 { Vector3::new(self.x, self.y, z) } + + impl_swizzle_functions!(Vector1, Vector2, S, xy); } impl Vector3 { @@ -674,6 +678,8 @@ impl Vector3 { pub fn truncate(self) -> Vector2 { Vector2::new(self.x, self.y) } + + impl_swizzle_functions!(Vector1, Vector2, Vector3, S, xyz); } impl Vector4 { @@ -718,6 +724,8 @@ impl Vector4 { _ => panic!("{:?} is out of range", n), } } + + impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xyzw); } /// Dot product of two vectors. From 76f00b7941d817c3ff85f2bc6537b1bf19c3491f Mon Sep 17 00:00:00 2001 From: Egor Larionov Date: Sat, 30 Sep 2017 15:09:03 -0700 Subject: [PATCH 3/8] Extend swizzles to increase the dimension of a vector. For example this is now valid: ``` let p2 = Point2::new(1.0, 2.0); let p3 = p2.xyx(); // producing Point3 { x:1.0, y:2.0, z:1.0 } ``` --- build.rs | 47 +++++++++++++++++++++++++++++++---------------- src/point.rs | 4 ++-- src/vector.rs | 6 +++--- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/build.rs b/build.rs index 9a7b93d..f3c7648 100644 --- a/build.rs +++ b/build.rs @@ -6,12 +6,12 @@ use std::string::String; /// Generate the name of the swizzle function and what it returns. /// NOTE: This function assumes that variables are in ASCII format -fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize) -> Option<(String, String)> { +fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize, upto: usize) -> Option<(String, String)> { debug_assert!(i > 0); // zeroth permutation is empty let mut swizzle_impl = String::new(); let mut swizzle = String::new(); let n = variables.len()+1; - for _ in 0..variables.len() { + for _ in 0..upto { if i == 0 { break; } if i % n == 0 { return None; } let c = variables.as_bytes()[i%n - 1] as char; @@ -22,13 +22,16 @@ fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize) -> Option<(String, Stri Some((swizzle, swizzle_impl)) } +/// A function that generates swizzle functions as a string. +/// `variables`: swizzle variables (e.g. "xyz") +/// `upto`: largest output vector size (e.g. for `variables = "xy"` and `upto = 4`, `xyxy()` is a +/// valid swizzle operator. /// NOTE: This function assumes that variables are in ASCII format -fn gen_swizzle_functions(variables: &'static str) -> String { - let n = variables.len(); +fn gen_swizzle_functions(variables: &'static str, upto: usize) -> String { let mut result = String::new(); - let nn = (n+1).pow(n as u32); + let nn = (variables.len()+1).pow(upto as u32); for i in 1..nn { - if let Some((swizzle_name, swizzle_impl)) = gen_swizzle_nth(variables, i) { + if let Some((swizzle_name, swizzle_impl)) = gen_swizzle_nth(variables, i, upto) { let vec_type = format!("$vector_type{}", swizzle_name.len()); result.push_str( &format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n", @@ -49,22 +52,34 @@ fn main() { let data = format!( "/// Generate glm/glsl style swizzle operators macro_rules! impl_swizzle_functions {{ - ($vector_type1:ident, $S:ident, x) => {{ -{x} + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, x) => {{ +{x3} }}; - ($vector_type1:ident, $vector_type2:ident, $S:ident, xy) => {{ -{xy} + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, xy) => {{ +{xy3} }}; ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{ -{xyz} +{xyz3} + }}; + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, x) => {{ +{x4} + }}; + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xy) => {{ +{xy4} + }}; + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyz) => {{ +{xyz4} }}; ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{ -{xyzw} +{xyzw4} }}; -}}", x=gen_swizzle_functions("x"), - xy=gen_swizzle_functions("xy"), - xyz=gen_swizzle_functions("xyz"), - xyzw=gen_swizzle_functions("xyzw")); +}}", x3=gen_swizzle_functions("x",3), + xy3=gen_swizzle_functions("xy",3), + xyz3=gen_swizzle_functions("xyz",3), + x4=gen_swizzle_functions("x",4), + xy4=gen_swizzle_functions("xy",4), + xyz4=gen_swizzle_functions("xyz",4), + xyzw4=gen_swizzle_functions("xyzw",4)); let mut f = File::create(swizzle_file_path) .expect("Unable to create file that defines the swizzle operator macro."); f.write_all(data.as_bytes()).expect("Unable to write swizzle operator macro."); diff --git a/src/point.rs b/src/point.rs index 9436c22..583e43d 100644 --- a/src/point.rs +++ b/src/point.rs @@ -70,7 +70,7 @@ impl Point1 { Point1 { x: x } } - impl_swizzle_functions!(Point1, S, x); + impl_swizzle_functions!(Point1, Point2, Point3, S, x); } impl Point2 { @@ -79,7 +79,7 @@ impl Point2 { Point2 { x: x, y: y } } - impl_swizzle_functions!(Point1, Point2, S, xy); + impl_swizzle_functions!(Point1, Point2, Point3, S, xy); } impl Point3 { diff --git a/src/vector.rs b/src/vector.rs index 7ebf06c..8d2ec86 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -606,7 +606,7 @@ impl Vector1 { Vector1::new(S::one()) } - impl_swizzle_functions!(Vector1, S, x); + impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, x); } impl Vector2 { @@ -635,7 +635,7 @@ impl Vector2 { Vector3::new(self.x, self.y, z) } - impl_swizzle_functions!(Vector1, Vector2, S, xy); + impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xy); } impl Vector3 { @@ -679,7 +679,7 @@ impl Vector3 { Vector2::new(self.x, self.y) } - impl_swizzle_functions!(Vector1, Vector2, Vector3, S, xyz); + impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xyz); } impl Vector4 { From b700a8db59f38c6f85b6376fafeb550d70c9f8ae Mon Sep 17 00:00:00 2001 From: Egor Larionov Date: Sat, 30 Sep 2017 15:18:31 -0700 Subject: [PATCH 4/8] Added sanity checks for the new swizzle operators --- tests/swizzle.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tests/swizzle.rs diff --git a/tests/swizzle.rs b/tests/swizzle.rs new file mode 100644 index 0000000..92b5b82 --- /dev/null +++ b/tests/swizzle.rs @@ -0,0 +1,59 @@ +// Copyright 2013-2017 The CGMath Developers. For a full listing of the authors, +// refer to the Cargo.toml 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. + +extern crate cgmath; + +use cgmath::{Point1, Point2, Point3, Vector1, Vector2, Vector3, Vector4}; + +// Sanity checks +#[test] +fn test_point() { + let p1 = Point1::new(1.0); + let p2 = Point2::new(1.0, 2.0); + let p3 = Point3::new(1.0, 2.0, 3.0); + assert_eq!(p1.x(), p1); + assert_eq!(p2.x(), p1); + assert_eq!(p2.y(), Point1::new(2.0)); + assert_eq!(p2.xx(), Point2::new(1.0, 1.0)); + assert_eq!(p2.xy(), p2); + assert_eq!(p2.yx(), Point2::new(2.0, 1.0)); + assert_eq!(p2.yy(), Point2::new(2.0, 2.0)); + assert_eq!(p3.x(), p1); + assert_eq!(p3.y(), Point1::new(2.0)); + assert_eq!(p3.xy(), p2); + assert_eq!(p3.zy(), Point2::new(3.0, 2.0)); + assert_eq!(p3.yyx(), Point3::new(2.0, 2.0, 1.0)); +} + +#[test] +fn test_vector() { + let p1 = Vector1::new(1.0); + let p2 = Vector2::new(1.0, 2.0); + let p3 = Vector3::new(1.0, 2.0, 3.0); + let p4 = Vector4::new(1.0, 2.0, 3.0, 4.0); + assert_eq!(p1.x(), p1); + assert_eq!(p2.x(), p1); + assert_eq!(p2.y(), Vector1::new(2.0)); + assert_eq!(p2.xx(), Vector2::new(1.0, 1.0)); + assert_eq!(p2.xy(), p2); + assert_eq!(p2.yx(), Vector2::new(2.0, 1.0)); + assert_eq!(p2.yy(), Vector2::new(2.0, 2.0)); + assert_eq!(p3.x(), p1); + assert_eq!(p3.y(), Vector1::new(2.0)); + assert_eq!(p3.xy(), p2); + assert_eq!(p3.zy(), Vector2::new(3.0, 2.0)); + assert_eq!(p3.yyx(), Vector3::new(2.0, 2.0, 1.0)); + assert_eq!(p4.xyxy(), Vector4::new(1.0, 2.0, 1.0, 2.0)); +} From 768b6b71f05ff21b57eb3dbcda58f2734a4a4ab4 Mon Sep 17 00:00:00 2001 From: Egor Larionov Date: Sat, 30 Sep 2017 16:37:07 -0700 Subject: [PATCH 5/8] Add a doc explanation to each swizzle function. --- build.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build.rs b/build.rs index f3c7648..42e5d0b 100644 --- a/build.rs +++ b/build.rs @@ -32,10 +32,12 @@ fn gen_swizzle_functions(variables: &'static str, upto: usize) -> String { let nn = (variables.len()+1).pow(upto as u32); for i in 1..nn { if let Some((swizzle_name, swizzle_impl)) = gen_swizzle_nth(variables, i, upto) { - let vec_type = format!("$vector_type{}", swizzle_name.len()); + let dim = format!("{}", swizzle_name.len()); result.push_str( - &format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n", - swizzle_name, swizzle_impl, vec_type)); + &format!(" + /// Swizzle operator that creates a new type with dimension {2} from variables `{0}`. + #[inline] pub fn {0}(&self) -> $vector_type{2}<$S> {{ $vector_type{2}::new({1}) }}\n", + swizzle_name, swizzle_impl, dim)); } } result From 12547b5bcbf121a617519fcc33ae4600a5009b91 Mon Sep 17 00:00:00 2001 From: Egor Larionov Date: Sun, 1 Oct 2017 13:26:47 -0700 Subject: [PATCH 6/8] Put the swizzle operators behind a feature flag "swizzle" to avoid increasing the binary size by approximately 20% by default. --- Cargo.toml | 1 + build.rs | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 29be582..d6b597a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ name = "cgmath" [features] unstable = [] +swizzle = [] [dependencies] approx = "0.1" diff --git a/build.rs b/build.rs index 42e5d0b..2f53369 100644 --- a/build.rs +++ b/build.rs @@ -6,6 +6,7 @@ use std::string::String; /// Generate the name of the swizzle function and what it returns. /// NOTE: This function assumes that variables are in ASCII format +#[cfg(feature = "swizzle")] fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize, upto: usize) -> Option<(String, String)> { debug_assert!(i > 0); // zeroth permutation is empty let mut swizzle_impl = String::new(); @@ -27,6 +28,7 @@ fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize, upto: usize) -> Option< /// `upto`: largest output vector size (e.g. for `variables = "xy"` and `upto = 4`, `xyxy()` is a /// valid swizzle operator. /// NOTE: This function assumes that variables are in ASCII format +#[cfg(feature = "swizzle")] fn gen_swizzle_functions(variables: &'static str, upto: usize) -> String { let mut result = String::new(); let nn = (variables.len()+1).pow(upto as u32); @@ -43,6 +45,12 @@ fn gen_swizzle_functions(variables: &'static str, upto: usize) -> String { result } +#[cfg(not(feature = "swizzle"))] +fn gen_swizzle_functions(_: &'static str, _: usize) -> String { + String::new() +} + + /// This script generates the macro for building swizzle operators for multidimensional /// vectors and points. This macro is included in macros.rs fn main() { @@ -75,13 +83,13 @@ macro_rules! impl_swizzle_functions {{ ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{ {xyzw4} }}; -}}", x3=gen_swizzle_functions("x",3), - xy3=gen_swizzle_functions("xy",3), - xyz3=gen_swizzle_functions("xyz",3), - x4=gen_swizzle_functions("x",4), - xy4=gen_swizzle_functions("xy",4), - xyz4=gen_swizzle_functions("xyz",4), - xyzw4=gen_swizzle_functions("xyzw",4)); +}}", x3 = gen_swizzle_functions("x", 3), + xy3 = gen_swizzle_functions("xy", 3), + xyz3 = gen_swizzle_functions("xyz", 3), + x4 = gen_swizzle_functions("x", 4), + xy4 = gen_swizzle_functions("xy", 4), + xyz4 = gen_swizzle_functions("xyz", 4), + xyzw4 = gen_swizzle_functions("xyzw", 4)); let mut f = File::create(swizzle_file_path) .expect("Unable to create file that defines the swizzle operator macro."); f.write_all(data.as_bytes()).expect("Unable to write swizzle operator macro."); From ae7a85305c75a50c276329d775d11b17a4c0a0b7 Mon Sep 17 00:00:00 2001 From: Egor Larionov Date: Sun, 1 Oct 2017 13:36:01 -0700 Subject: [PATCH 7/8] Guard the swizzle test by the "swizzle" feature flag. Also rename the swizzle tests with a "swizzle" postfix to easier see these in the test log. --- tests/swizzle.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/swizzle.rs b/tests/swizzle.rs index 92b5b82..d767347 100644 --- a/tests/swizzle.rs +++ b/tests/swizzle.rs @@ -13,13 +13,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![cfg(feature = "swizzle")] + extern crate cgmath; use cgmath::{Point1, Point2, Point3, Vector1, Vector2, Vector3, Vector4}; // Sanity checks #[test] -fn test_point() { +fn test_point_swizzle() { let p1 = Point1::new(1.0); let p2 = Point2::new(1.0, 2.0); let p3 = Point3::new(1.0, 2.0, 3.0); @@ -38,7 +40,7 @@ fn test_point() { } #[test] -fn test_vector() { +fn test_vector_swizzle() { let p1 = Vector1::new(1.0); let p2 = Vector2::new(1.0, 2.0); let p3 = Vector3::new(1.0, 2.0, 3.0); From 61da8e4720134faabbe0b70b94591e3c809ac12d Mon Sep 17 00:00:00 2001 From: Egor Larionov Date: Sun, 1 Oct 2017 14:23:07 -0700 Subject: [PATCH 8/8] Update README to describe the new swizzling feature --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index 833c03e..d5f8b8e 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,32 @@ vectors"), meaning when transforming a vector with a matrix, the matrix goes on the left. This is reflected in the fact that cgmath implements the multiplication operator for Matrix * Vector, but not Vector * Matrix. +## Features + +### Swizzling +This library offers an optional feature called +["swizzling"](https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)) +widely familiar to GPU programmers. To enable swizzle operators, pass the +`--features="swizzle"` option to cargo. Enabling this feature will increase +the size of the cgmath library by approximately 0.6MB. This isn't an +issue if the library is linked in the "normal" way by adding cgmath as a +dependency in Cargo.toml, which will link cgmath statically so all unused +swizzle operators will be optimized away by the compiler in release mode. + +#### Example +If we have +```rust +let v = Vector3::new(1.0, 2.0, 3.0); +``` +then `v.xyxz()` produces a +```rust +Vector4 { x: 1.0, y: 2.0, z: 1.0, w: 3.0 } +``` +and `v.zy()` produces a +```rust +Vector2 { x: 3.0, y: 2.0 } +``` + ## Limitations cgmath is _not_ an n-dimensional library and is aimed at computer graphics