Quaternions are now Transmutable.

This implements Transmutable for Quaternions and creates a
test and example for this conversion.
This commit is contained in:
Jason Travis Smith 2016-01-07 05:51:53 -05:00
parent aa4bb78f66
commit 1374ff5e4a
3 changed files with 188 additions and 10 deletions

View File

@ -0,0 +1,89 @@
#![feature(convert)]
extern crate alchemy;
extern crate sigils;
use alchemy::F64_BYTES;
use alchemy::{Endianess, Transmutable};
use sigils::quaternion::Quaternion;
/// The size of 4 f64 Real numbers.
/// This would be different if the contained type
/// was something different, like an f32.
const SIZE_OF_QUATERNION: usize = F64_BYTES * 4;
/// This just help pretty up the printing of an array of bytes.
fn stringify_array(buffer: &[u8]) -> String
{
let mut result: String;
let mut count: usize;
// Create a new string that starts with just
// the array opening bracket.
result = String::new();
result.push_str("[");
// Loop through the buffer keeping track
// of our place in it.
count = 0usize;
for byte in buffer
{
// Handle priting the last value differently.
if count >= buffer.len() - 1
{
result.push_str(byte.to_string().as_str());
}
else
{
result.push_str(byte.to_string().as_str());
result.push_str(", ");
}
// Mark that we are going to look at
// the next byte in the array.
count += 1;
}
// Add the array closing bracket and
// return the new String.
result.push_str("]");
result
}
pub fn main()
{
let quat: Quaternion<f64>;
let final_quat: Quaternion<f64>;
let endianess: Endianess;
let mut buffer: [u8; SIZE_OF_QUATERNION];
// Initialize the variables.
quat = Quaternion::<f64>::from_values(6.29f64, 1.9f64, 8.5f64, 7.11f64);
buffer = [0u8; SIZE_OF_QUATERNION];
endianess = Endianess::PLATFORM;
println!("Transmuting a Quaternion:");
println!("Converting the value [{1}, <{2}, {3}, {4}>] {0}",
"into and out of an array of bytes.",
quat.scalar, quat.vector.x, quat.vector.y, quat.vector.z);
println!("Buffer starts as: {}", stringify_array(&buffer));
// Convert the Vector2 into an array of bytes.
quat.to_bytes(&mut buffer, endianess);
println!("Buffer contains: {}", stringify_array(&buffer));
// Convert the array of bytes into a Vector2.
final_quat = Quaternion::from_bytes(&buffer, endianess);
println!("The buffer converts back to: [{}, <{}, {}, {}>]",
final_quat.scalar, final_quat.vector.x,
final_quat.vector.y, final_quat.vector.z);
}

View File

@ -1,5 +1,6 @@
use sigils::{Zero, Number}; use sigils::{Zero, Number, Real};
use sigils::vector::{Vector, Vector2, Vector3, Vector4}; use sigils::vector::{Vector, Vector2, Vector3, Vector4};
use sigils::quaternion::Quaternion;
use ::byte_sized::ByteSized; use ::byte_sized::ByteSized;
use ::converter::Converter; use ::converter::Converter;
@ -502,3 +503,49 @@ impl<T> Transmutable for Vector4<T> where T: Number + ByteSized + Transmutable
vec vec
} }
} }
impl<T> Transmutable for Quaternion<T>
where T: Real + ByteSized + Transmutable
{
fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess)
{
let byte_size: usize;
let num_bytes: usize;
// Determine the number of bytes requires to
// represent a Quaternion.
byte_size = T::get_byte_size();
num_bytes = byte_size * 4usize;
// Make sure that there is enough space to store
// the bytes from this type.
assert!(buffer.len() >= num_bytes);
// Convert this to bytes and add it to the buffer.
self.scalar.to_bytes(&mut buffer[0..byte_size], endianess);
self.vector.to_bytes(&mut buffer[byte_size..num_bytes], endianess);
}
fn from_bytes(buffer: &[u8], endianess: Endianess) -> Quaternion<T>
{
let byte_size: usize;
let num_bytes: usize;
let mut quat: Quaternion<T>;
// Determine the number of bytes requires to
// represent a Quaternion.
quat = Quaternion::<T>::zero();
byte_size = T::get_byte_size();
num_bytes = byte_size * 4usize;
// Make sure that there is enough data to read
// the bytes for this type.
assert!(buffer.len() >= num_bytes);
// Convert the given bytes to this type and return it.
quat.scalar = T::from_bytes(&buffer[0..byte_size], endianess);
quat.vector =
Vector3::<T>::from_bytes(&buffer[byte_size..num_bytes], endianess);
quat
}
}

View File

@ -5,9 +5,10 @@ extern crate sigils;
macro_rules! transmutation_test macro_rules! transmutation_vector_test
{ {
($modName: ident, $varType: ident, $numBytes: expr, [$($var: ident)*]) => ($modName: ident, $varType: ident, $dataType:ty,
$numBytes: expr, [$($var: ident)*]) =>
{ {
mod $modName mod $modName
{ {
@ -22,16 +23,16 @@ macro_rules! transmutation_test
#[test] #[test]
pub fn transmutation() pub fn transmutation()
{ {
let mut vec: $varType<u64>; let mut vec: $varType<$dataType>;
let final_vec: $varType<u64>; let final_vec: $varType<$dataType>;
let endianess: Endianess; let endianess: Endianess;
let mut rng: ThreadRng; let mut rng: ThreadRng;
let mut buffer: [u8; $numBytes]; let mut buffer: [u8; $numBytes];
// Initialize the variables. // Initialize the variables.
rng = thread_rng(); rng = thread_rng();
vec = $varType::<u64>::zero(); vec = $varType::<$dataType>::zero();
$(vec.$var = rng.next_u64();)* $(vec.$var = rng.gen();)*
buffer = [0u8; $numBytes]; buffer = [0u8; $numBytes];
endianess = Endianess::PLATFORM; endianess = Endianess::PLATFORM;
@ -45,6 +46,47 @@ macro_rules! transmutation_test
} }
transmutation_test!(vec2, Vector2, 16, [x y]); transmutation_vector_test!(vec2, Vector2, u64, 16, [x y]);
transmutation_test!(vec3, Vector3, 24, [x y z]); transmutation_vector_test!(vec3, Vector3, u32, 12, [x y z]);
transmutation_test!(vec4, Vector4, 32, [x y z w]); transmutation_vector_test!(vec4, Vector4, u16, 8, [x y z w]);
mod quat
{
use rand::{thread_rng, Rng, ThreadRng};
use alchemy::{Endianess, Transmutable};
use sigils::Zero;
use sigils::quaternion::Quaternion;
#[test]
pub fn transmutation()
{
let mut quat: Quaternion<f64>;
let final_quat: Quaternion<f64>;
let endianess: Endianess;
let mut rng: ThreadRng;
let mut buffer: [u8; 32];
// Initialize the variables.
rng = thread_rng();
quat = Quaternion::<f64>::zero();
quat.scalar = rng.gen();
quat.vector.x = rng.gen();
quat.vector.y = rng.gen();
quat.vector.z = rng.gen();
buffer = [0u8; 32];
endianess = Endianess::PLATFORM;
quat.to_bytes(&mut buffer, endianess);
final_quat = Quaternion::from_bytes(&buffer, endianess);
assert_eq!(quat.scalar, final_quat.scalar);
assert_eq!(quat.vector.x, final_quat.vector.x);
assert_eq!(quat.vector.y, final_quat.vector.y);
assert_eq!(quat.vector.z, final_quat.vector.z);
}
}