Flat, round, designer-friendly pseudo-3D engine for canvas & SVG
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 187 lines 4.0 kB view raw
1/** 2 * Vector 3 */ 4 5( function( root, factory ) { 6 // module definition 7 if ( typeof module == 'object' && module.exports ) { 8 // CommonJS 9 module.exports = factory( require('./boilerplate') ); 10 } else { 11 // browser global 12 var Zdog = root.Zdog; 13 Zdog.Vector = factory( Zdog ); 14 } 15 16}( this, function factory( utils ) { 17 18function Vector( position ) { 19 this.set( position ); 20} 21 22var TAU = utils.TAU; 23 24// 'pos' = 'position' 25Vector.prototype.set = function( pos ) { 26 this.x = pos && pos.x || 0; 27 this.y = pos && pos.y || 0; 28 this.z = pos && pos.z || 0; 29 return this; 30}; 31 32// set coordinates without sanitizing 33// vec.write({ y: 2 }) only sets y coord 34Vector.prototype.write = function( pos ) { 35 if ( !pos ) { 36 return this; 37 } 38 this.x = pos.x != undefined ? pos.x : this.x; 39 this.y = pos.y != undefined ? pos.y : this.y; 40 this.z = pos.z != undefined ? pos.z : this.z; 41 return this; 42}; 43 44Vector.prototype.rotate = function( rotation ) { 45 if ( !rotation ) { 46 return; 47 } 48 this.rotateZ( rotation.z ); 49 this.rotateY( rotation.y ); 50 this.rotateX( rotation.x ); 51 return this; 52}; 53 54Vector.prototype.rotateZ = function( angle ) { 55 rotateProperty( this, angle, 'x', 'y' ); 56}; 57 58Vector.prototype.rotateX = function( angle ) { 59 rotateProperty( this, angle, 'y', 'z' ); 60}; 61 62Vector.prototype.rotateY = function( angle ) { 63 rotateProperty( this, angle, 'x', 'z' ); 64}; 65 66function rotateProperty( vec, angle, propA, propB ) { 67 if ( !angle || angle % TAU === 0 ) { 68 return; 69 } 70 var cos = Math.cos( angle ); 71 var sin = Math.sin( angle ); 72 var a = vec[ propA ]; 73 var b = vec[ propB ]; 74 vec[ propA ] = a * cos - b * sin; 75 vec[ propB ] = b * cos + a * sin; 76} 77 78Vector.prototype.isSame = function( pos ) { 79 if ( !pos ) { 80 return false; 81 } 82 return this.x === pos.x && this.y === pos.y && this.z === pos.z; 83}; 84 85Vector.prototype.add = function( pos ) { 86 if ( !pos ) { 87 return this; 88 } 89 this.x += pos.x || 0; 90 this.y += pos.y || 0; 91 this.z += pos.z || 0; 92 return this; 93}; 94 95Vector.prototype.subtract = function( pos ) { 96 if ( !pos ) { 97 return this; 98 } 99 this.x -= pos.x || 0; 100 this.y -= pos.y || 0; 101 this.z -= pos.z || 0; 102 return this; 103}; 104 105Vector.prototype.multiply = function( pos ) { 106 if ( pos == undefined ) { 107 return this; 108 } 109 // multiple all values by same number 110 if ( typeof pos == 'number' ) { 111 this.x *= pos; 112 this.y *= pos; 113 this.z *= pos; 114 } else { 115 // multiply object 116 this.x *= pos.x != undefined ? pos.x : 1; 117 this.y *= pos.y != undefined ? pos.y : 1; 118 this.z *= pos.z != undefined ? pos.z : 1; 119 } 120 return this; 121}; 122 123Vector.prototype.transform = function( translation, rotation, scale ) { 124 this.multiply( scale ); 125 this.rotate( rotation ); 126 this.add( translation ); 127 return this; 128}; 129 130Vector.prototype.lerp = function( pos, alpha ) { 131 this.x = utils.lerp( this.x, pos.x || 0, alpha ); 132 this.y = utils.lerp( this.y, pos.y || 0, alpha ); 133 this.z = utils.lerp( this.z, pos.z || 0, alpha ); 134 return this; 135}; 136 137Vector.prototype.magnitude = function() { 138 var sum = this.x * this.x + this.y * this.y + this.z * this.z; 139 return getMagnitudeSqrt( sum ); 140}; 141 142function getMagnitudeSqrt( sum ) { 143 // PERF: check if sum ~= 1 and skip sqrt 144 if ( Math.abs( sum - 1 ) < 0.00000001 ) { 145 return 1; 146 } 147 return Math.sqrt( sum ); 148} 149 150Vector.prototype.magnitude2d = function() { 151 var sum = this.x * this.x + this.y * this.y; 152 return getMagnitudeSqrt( sum ); 153}; 154 155Vector.prototype.copy = function() { 156 return new Vector( this ); 157}; 158 159function round( num ) { 160 return Math.round( num * 1000 ) / 1000; 161} 162 163Vector.prototype.toJSON = function() { 164 var x = this.x; 165 var y = this.y; 166 var z = this.z; 167 168 if ( x === y && y === z ) { 169 return x !== 0 ? round( x ) : undefined; 170 } 171 172 var obj = { x: x, y: y, z: z }; 173 var result = {}; 174 175 Object.keys( obj ).forEach( function( key ) { 176 var value = obj[ key ]; 177 if ( value !== 0 ) { 178 result[ key ] = round( value ); 179 } 180 }); 181 182 return Object.keys( result ).length ? result : undefined; 183}; 184 185return Vector; 186 187} ) );