Created
July 8, 2013 09:10
-
-
Save dobkeratops/5947366 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[allow(default_methods)]; | |
| // TODO - parameterize the type f32 .. | |
| // eg Vec3<T> etc.. | |
| // | |
| #[deriving(Clone,ToStr)] | |
| pub use std::num::*; | |
| pub type VScalar=f32; | |
| pub struct Vec2 {x:VScalar, y:VScalar} | |
| #[deriving(Clone,ToStr)] | |
| pub struct Vec3 {x:VScalar, y:VScalar, z:VScalar} | |
| pub struct Vec4 {x:VScalar, y:VScalar, z:VScalar, w:VScalar} | |
| /* | |
| pub struct Vec3f {x:float,y:float,z:float} | |
| impl Vec3f { | |
| pub fn new2(x:float,y:float)->Vec3f { Vec3f{x:x,y:y,z:0.0} } | |
| } | |
| */ | |
| impl Vec2 { | |
| pub fn new(x:VScalar,y:VScalar)->Vec2 {Vec2{x:x,y:y}} | |
| pub fn crossToScalar(&self,other:&Vec2)->VScalar{self.x*other.y-self.y*other.x} | |
| } | |
| impl Vec3 { | |
| pub fn new(x:VScalar,y:VScalar,z:VScalar)->Vec3 {Vec3{x:x,y:y,z:z}} | |
| pub fn fromVec2(xy:Vec2,z:VScalar)->Vec3 {Vec3{x:xy.x,y:xy.y,z:z}} | |
| } | |
| impl Vec4 { | |
| pub fn new(x:VScalar,y:VScalar,z:VScalar,w:VScalar)->Vec4 {Vec4{x:x,y:y,z:z,w:w}} | |
| pub fn fromVec3(xyz:Vec3,w:VScalar)->Vec4 {Vec4{x:xyz.x,y:xyz.y,z:xyz.z,w:w}} | |
| pub fn fromVec2(xy:Vec2,z:VScalar,w:VScalar)->Vec4 {Vec4{x:xy.x,y:xy.y,z:z,w:w}} | |
| pub fn fromVec2Vec2(xy:Vec2,zw:Vec2)->Vec4 {Vec4{x:xy.x,y:xy.y,z:zw.x,w:zw.y}} | |
| } | |
| // Primitive operations | |
| // TODO move to the appropriate rust stdlib traits where possible | |
| pub trait VecOps:Clone { | |
| pub fn add(&self,b:&Self)->Self; | |
| pub fn sub(&self,b:&Self)->Self; | |
| pub fn scale(&self,f:VScalar)->Self; | |
| pub fn mul(&self,b:&Self)->Self; | |
| pub fn min(&self,b:&Self)->Self; | |
| pub fn max(&self,b:&Self)->Self; | |
| pub fn sumElems(&self)->VScalar;// {self.x+self.y+self.z} | |
| pub fn splat(v:VScalar)->Self; | |
| // pub fn zero()->Self; | |
| pub fn cross(&self,b:&Self)->Self; | |
| pub fn axis(i:int)->Self; | |
| pub fn fromXYZ(x:VScalar,y:VScalar,z:VScalar)->Self; | |
| pub fn x(&self)->VScalar; | |
| pub fn y(&self)->VScalar; | |
| pub fn z(&self)->VScalar; | |
| pub fn w(&self)->VScalar; | |
| // fn rsub(&self,&b:Self)->Self { b.sub(self)} | |
| pub fn xy(&self)->Vec2 { Vec2::new(self.x(),self.y())} | |
| pub fn xz(&self)->Vec2 { Vec2::new(self.x(),self.z())} | |
| pub fn yz(&self)->Vec2 { Vec2::new(self.y(),self.z())} | |
| pub fn xyz(&self)->Vec3 { Vec3::new(self.x(),self.y(),self.z())} | |
| pub fn dot(&self,b:&Self)->VScalar {self.mul(b).sumElems()} | |
| pub fn para(&self,vaxis:&Self)->Self { let dotp=self.dot(vaxis); vaxis.scale(dotp) } | |
| pub fn avr(&self,b:&Self)->Self {self.add(b).scale(0.5)} | |
| pub fn mad(&self,b:&Self,f:VScalar)->Self {self.add(&b.scale(f))} | |
| pub fn lerp(&self,b:&Self,f:VScalar)->Self {self.mad(&b.sub(self),f)} | |
| pub fn sqr(&self)->VScalar { self.dot(self)} | |
| pub fn length(&self)->VScalar { self.sqr().sqrt()} | |
| pub fn invlength(&self)->VScalar { self.sqr().rsqrt()} | |
| pub fn toLength(&self,length:VScalar)->Self { self.scale(length/self.sqr().sqrt())} | |
| pub fn normalize(&self)->Self { self.scale(self.sqr().rsqrt()) } | |
| pub fn perp(&self,axis:&Self)->Self { let vpara =self.para(axis); self.sub(&vpara)} | |
| pub fn paraPerp(&self,vaxis:&Self)->(Self,Self) { | |
| let vpara=self.para(vaxis); | |
| (vpara.clone(),self.sub(&vpara)) | |
| // ^^^^ CLONE STILL NEEDED HERE ? | |
| // - possible bug because the default impl hasn't been told Self:Clone | |
| // from the trait itself; | |
| // - VERIFIED that when this function is defined in the IMPL, | |
| // the .clone() is not needed. | |
| } | |
| pub fn crossToVec3(&self,b:&Self)->Vec3; | |
| } | |
| // Workaround - v*** free functions do similar things to the methods, | |
| // since default methods dont work across module boundaries yet | |
| pub fn vadd<V:VecOps>(a:&V,b:&V)->V { a.add(b)} | |
| pub fn vsub<V:VecOps>(a:&V,b:&V)->V { a.sub(b)} | |
| pub fn vmad<V:VecOps>(a:&V,b:&V,f:VScalar)->V { a.add(&b.scale(f))} | |
| pub fn vmul<V:VecOps>(a:&V,b:&V)->V { a.mul(b)} | |
| pub fn vsqr<V:VecOps>(a:&V)->VScalar { vmul(a,a).sumElems()} | |
| pub fn vlerp<V:VecOps>( a:&V,b:&V,f:VScalar)->V { vmad(a, &vsub(b,a), f) } | |
| pub fn vdot<V:VecOps>( a:&V,b:&V)->VScalar { a.mul(b).sumElems()} | |
| pub fn vlength<V:VecOps>( a:&V)->VScalar { a.mul(a).sumElems().sqrt()} | |
| pub fn vnormalize<V:VecOps>( a:&V)->V { a.scale(a.mul(a).sumElems().rsqrt()) } | |
| impl Zero for Vec2 { | |
| pub fn zero()->Vec2{Vec2{x:0.0,y:0.0}} | |
| pub fn is_zero(&self)->bool { self.x==0.0 && self.y==0.0 } | |
| } | |
| impl VecOps for Vec2 { | |
| // todo-trait VecPrimOps | |
| pub fn add(&self,b:&Vec2)->Vec2 {Vec2::new(self.x+b.x,self.y+b.y)} | |
| pub fn sub(&self,b:&Vec2)->Vec2 {Vec2::new(self.x-b.x,self.y-b.y)} | |
| pub fn min(&self,b:&Vec2)->Vec2 {Vec2::new(self.x.min(&b.x),self.y.min(&b.y))} | |
| pub fn max(&self,b:&Vec2)->Vec2 {Vec2::new(self.x.max(&b.x),self.y.max(&b.y))} | |
| pub fn scale(&self,f:VScalar)->Vec2 {Vec2::new(self.x*f,self.y*f)} | |
| pub fn mul(&self,b:&Vec2)->Vec2 {Vec2::new(self.x*b.x,self.y*b.y)} | |
| pub fn sumElems(&self)->VScalar {self.x+self.y} | |
| pub fn splat(v:VScalar)->Vec2{Vec2{x:v,y:v}} | |
| pub fn fromXYZ(x:VScalar,y:VScalar,z:VScalar)->Vec2{Vec2::new(x,y)} | |
| // todo .. not entirely happy with this interface. | |
| // cross product for a vector type returning its own type seems awkward | |
| // perhaps 'crossToSelf and crossToVec3' .. and 'cross' for vec3 only? | |
| pub fn cross(&self,other:&Vec2)->Vec2{Vec2{x:0.0,y:0.0}} | |
| pub fn crossToVec3(&self,b:&Vec2)->Vec3 {Vec3{x:0.0,y:0.0,z:self.crossToScalar(b)}} | |
| pub fn axis(i:int)->Vec2{ | |
| match i{ 0=>Vec2::new(1.0,0.0),1=>Vec2::new(0.0,1.0),_=>Vec2::new(0.0,0.0)} | |
| } | |
| pub fn x(&self)->VScalar { self.x} | |
| pub fn y(&self)->VScalar { self.y} | |
| pub fn z(&self)->VScalar { 0.0} | |
| pub fn w(&self)->VScalar { 0.0} | |
| } | |
| impl Zero for Vec3 { | |
| pub fn zero()->Vec3{Vec3{x:0.0,y:0.0,z:0.0}} | |
| pub fn is_zero(&self)->bool {self.x==0.0 && self.y==0.0 && self.z==0.0} | |
| } | |
| impl VecOps for Vec3 { | |
| // todo-trait VecPrimOps | |
| pub fn fromXYZ(x:VScalar,y:VScalar,z:VScalar)->Vec3{Vec3::new(x,y,z)} | |
| pub fn add(&self,b:&Vec3)->Vec3 {Vec3::new(self.x+b.x,self.y+b.y,self.z+b.z)} | |
| pub fn sub(&self,b:&Vec3)->Vec3 {Vec3::new(self.x-b.x,self.y-b.y,self.z-b.z)} | |
| pub fn min(&self,b:&Vec3)->Vec3 {Vec3::new( | |
| self.x.min(&b.x), | |
| self.y.min(&b.y), | |
| self.z.min(&b.z))} | |
| pub fn max(&self,b:&Vec3)->Vec3 {Vec3::new(self.x.max(&b.x),self.y.max(&b.y),self.z.max(&b.z))} | |
| pub fn scale(&self,f:VScalar)->Vec3 {Vec3::new(self.x*f,self.y*f,self.z*f)} | |
| pub fn mul(&self,b:&Vec3)->Vec3 {Vec3::new(self.x*b.x,self.y*b.y,self.z*b.z)} | |
| pub fn sumElems(&self)->VScalar {self.x+self.y+self.z} | |
| pub fn splat(v:VScalar)->Vec3{Vec3{x:v,y:v,z:v}} | |
| pub fn cross(&self,b:&Vec3)->Vec3 {Vec3::new(self.y*b.z-self.z*b.y,self.z*b.x-self.x*b.z,self.x*b.y-self.y*b.x)} | |
| pub fn crossToVec3(&self,b:&Vec3)->Vec3 {self.cross(b)} | |
| pub fn axis(i:int)->Vec3{ | |
| match i{ 0=>Vec3::new(1.0,0.0,0.0),1=>Vec3::new(0.0,1.0,0.0),2=>Vec3::new(0.0,0.0,1.0),_=>Vec3::new(0.0,0.0,0.0)} | |
| } | |
| pub fn x(&self)->VScalar { self.x} | |
| pub fn y(&self)->VScalar { self.y} | |
| pub fn z(&self)->VScalar { self.z} | |
| pub fn w(&self)->VScalar { 0.0} | |
| } | |
| impl Vec3 { | |
| pub fn vadd(self,b:Vec3)->Vec3{ | |
| Vec3::new(self.x+b.x,self.y+b.y,self.z+b.z) | |
| } | |
| pub fn vsub(self,b:Vec3)->Vec3{ | |
| Vec3::new(self.x-b.x,self.y-b.y,self.z-b.z) | |
| } | |
| pub fn vscale(self,f:VScalar)->Vec3{ | |
| Vec3::new(self.x*f,self.y*f,self.z*f) | |
| } | |
| pub fn vlerp(self,b:Vec3,f:VScalar)->Vec3{ | |
| self.vadd(self.vsub(b).vscale(f)) | |
| } | |
| } | |
| impl Zero for Vec4 { | |
| pub fn zero()->Vec4{Vec4{x:0.0,y:0.0,z:0.0,w:0.0}} | |
| pub fn is_zero(&self)->bool {self.x==0.0 && self.y==0.0 && self.z==0.0 && self.w==0.0} | |
| } | |
| impl VecOps for Vec4 { | |
| // todo-trait VecPrimOps | |
| pub fn fromXYZ(x:VScalar,y:VScalar,z:VScalar)->Vec4{Vec4::new(x,y,z,0.0)} | |
| pub fn add(&self,b:&Vec4)->Vec4 {Vec4::new(self.x+b.x,self.y+b.y,self.z+b.z,self.w+b.w)} | |
| pub fn sub(&self,b:&Vec4)->Vec4 {Vec4::new(self.x-b.x,self.y-b.y,self.z-b.z,self.w-b.w)} | |
| pub fn scale(&self,f:VScalar)->Vec4 {Vec4::new(self.x*f,self.y*f,self.z*f,self.w*f)} | |
| pub fn mul(&self,b:&Vec4)->Vec4 {Vec4::new(self.x*b.x,self.y*b.y,self.z*b.z,self.w*b.w)} | |
| pub fn sumElems(&self)->VScalar {self.x+self.y+self.z+self.w} | |
| pub fn splat(v:VScalar)->Vec4{Vec4{x:v,y:v,z:v,w:v}} | |
| // pub fn zero()->Vec4{Vec4{x:0.0,y:0.0,z:0.0,w:0.0}} | |
| pub fn min(&self,b:&Vec4)->Vec4 {Vec4::new( | |
| self.x.min(&b.x), | |
| self.y.min(&b.y), | |
| self.z.min(&b.z), | |
| self.w.min(&b.w))} | |
| pub fn max(&self,b:&Vec4)->Vec4 {Vec4::new( | |
| self.x.max(&b.x), | |
| self.y.max(&b.y), | |
| self.z.max(&b.z), | |
| self.w.max(&b.w))} | |
| pub fn cross(&self,b:&Vec4)->Vec4 {Vec4::new(self.y*b.z-self.z*b.y,self.z*b.x-self.x*b.z,self.x*b.y-self.y*b.x,0.0)} | |
| pub fn crossToVec3(&self,b:&Vec4)->Vec3 {self.cross(b).xyz()} | |
| pub fn axis(i:int)->Vec4{ | |
| match i{ 0=>Vec4::new(1.0,0.0,0.0,0.0),1=>Vec4::new(0.0,1.0,0.0,0.0),2=>Vec4::new(0.0,0.0,1.0,0.0),3=>Vec4::new(0.0,0.0,0.0,1.0),_=>Vec4::new(0.0,0.0,0.0,0.0)} | |
| } | |
| pub fn x(&self)->VScalar { self.x} | |
| pub fn y(&self)->VScalar { self.y} | |
| pub fn z(&self)->VScalar { self.z} | |
| pub fn w(&self)->VScalar { self.w} | |
| } | |
| /* | |
| fn repeated<T:Num+Ord>(count:T, myfunc:&fn(x:T)->T){ | |
| let mut i:T=count; | |
| while i>core::Zero::zero() { myfunc(i); i-=(1 as T)} | |
| } | |
| */ | |
| /* | |
| use core::io; | |
| let a:~[i32]=~[1,2,3,4,5,6]; | |
| let x=a.len(); | |
| let r=do a.map |x|{*x +1}; | |
| io::println(r[0].to_str()); | |
| io::println(lerp!(1.0f,2.0f by: 0.4f between: 0.3f,0.6f).to_str()); | |
| io::println(fooToStr(foo2{x:10.0,y:20.0})); | |
| */ | |
| macro_rules! lerp{ | |
| ($y0:expr:$y1:expr by $t:expr)=> | |
| ( | |
| $y0+($y1-$y0)*$t | |
| ); | |
| ($y0:expr,$y1:expr by: $x:expr between: $x0:expr,$x1:expr)=> | |
| ( | |
| $y0+($x*($y1-$y0)/($x1-$x0)) | |
| ) | |
| } | |
| // operations unique to Vec3 | |
| pub fn v3add(a:Vec3, b:Vec3)->Vec3{ | |
| Vec3{x:a.x+b.x,y:a.y+b.y,z:a.z+b.z} | |
| } | |
| pub fn v3sub(a:Vec3, b:Vec3)->Vec3{ | |
| Vec3{x:a.x-b.x,y:a.y-b.y,z:a.z-b.z} | |
| } | |
| pub fn v3scale(a:Vec3, f:VScalar)->Vec3{ | |
| Vec3{x:a.x*f,y:a.y*f,z:a.z*f} | |
| } | |
| pub fn v3lerp(a:Vec3,b:Vec3,f:VScalar)->Vec3 {v3add(a,v3scale(v3sub(b,a),f))} | |
| #[deriving(Clone,ToStr)] | |
| pub struct Range<T> { | |
| min:T,max:T | |
| } | |
| impl<T:VecOps> Range<T> { | |
| pub fn size(&self)->T { self.max.sub(&self.min) } | |
| pub fn centre(&self)->T { self.min.add(&self.max).scale(0.5) } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment