Quaternions are now Transmutable.
This implements Transmutable for Quaternions and creates a test and example for this conversion.
This commit is contained in:
parent
aa4bb78f66
commit
1374ff5e4a
89
examples/convert_quaternion.rs
Normal file
89
examples/convert_quaternion.rs
Normal 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);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
use sigils::{Zero, Number};
|
||||
use sigils::{Zero, Number, Real};
|
||||
use sigils::vector::{Vector, Vector2, Vector3, Vector4};
|
||||
use sigils::quaternion::Quaternion;
|
||||
|
||||
use ::byte_sized::ByteSized;
|
||||
use ::converter::Converter;
|
||||
@ -502,3 +503,49 @@ impl<T> Transmutable for Vector4<T> where T: Number + ByteSized + Transmutable
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
@ -22,16 +23,16 @@ macro_rules! transmutation_test
|
||||
#[test]
|
||||
pub fn transmutation()
|
||||
{
|
||||
let mut vec: $varType<u64>;
|
||||
let final_vec: $varType<u64>;
|
||||
let mut vec: $varType<$dataType>;
|
||||
let final_vec: $varType<$dataType>;
|
||||
let endianess: Endianess;
|
||||
let mut rng: ThreadRng;
|
||||
let mut buffer: [u8; $numBytes];
|
||||
|
||||
// Initialize the variables.
|
||||
rng = thread_rng();
|
||||
vec = $varType::<u64>::zero();
|
||||
$(vec.$var = rng.next_u64();)*
|
||||
vec = $varType::<$dataType>::zero();
|
||||
$(vec.$var = rng.gen();)*
|
||||
buffer = [0u8; $numBytes];
|
||||
endianess = Endianess::PLATFORM;
|
||||
|
||||
@ -45,6 +46,47 @@ macro_rules! transmutation_test
|
||||
}
|
||||
|
||||
|
||||
transmutation_test!(vec2, Vector2, 16, [x y]);
|
||||
transmutation_test!(vec3, Vector3, 24, [x y z]);
|
||||
transmutation_test!(vec4, Vector4, 32, [x y z w]);
|
||||
transmutation_vector_test!(vec2, Vector2, u64, 16, [x y]);
|
||||
transmutation_vector_test!(vec3, Vector3, u32, 12, [x y z]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user