Published
Edited
Jul 16, 2019
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
a = vec3.create()
Insert cell
Insert cell
b = vec3create()
Insert cell
Insert cell
vec3 = ({
EPSILON,
create: vec3create,
clone: vec3clone,
angle: vec3angle,
fromValues: vec3fromValues,
copy: vec3copy,
set: vec3set,
equals: vec3equals,
exactEquals: vec3exactEquals,
add: vec3add,
subtract: vec3subtract,
sub: vec3sub,
multiply: vec3multiply,
mul: vec3mul,
divide: vec3divide,
div: vec3div,
min: vec3min,
max: vec3max,
floor: vec3floor,
ceil: vec3ceil,
round: vec3round,
scale: vec3scale,
scaleAndAdd: vec3scaleAndAdd,
distance: vec3distance,
dist: vec3dist,
squaredDistance: vec3squaredDistance,
sqrDist: vec3sqrDist,
length: vec3length,
len: vec3len,
squaredLength: vec3squaredLength,
sqrLen: vec3sqrLen,
negate: vec3negate,
inverse: vec3inverse,
normalize: vec3normalize,
dot: vec3dot,
cross: vec3cross,
lerp: vec3lerp,
random: vec3random,
transformMat4: vec3transformMat4,
transformMat3: vec3transformMat3,
transformQuat: vec3transformQuat,
rotateX: vec3rotateX,
rotateY: vec3rotateY,
rotateZ: vec3rotateZ,
forEach: vec3forEach,
})
Insert cell
EPSILON = 0.000001
Insert cell
/**
* Adds two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function vec3add(out, a, b) {
out[0] = a[0] + b[0]
out[1] = a[1] + b[1]
out[2] = a[2] + b[2]
return out
}
Insert cell
/**
* Get the angle between two 3D vectors
* @param {vec3} a The first operand
* @param {vec3} b The second operand
* @returns {Number} The angle in radians
*/
function vec3angle(a, b) {
var tempA = vec3fromValues(a[0], a[1], a[2])
var tempB = vec3fromValues(b[0], b[1], b[2])
vec3normalize(tempA, tempA)
vec3normalize(tempB, tempB)
var cosine = vec3dot(tempA, tempB)

if(cosine > 1.0){
return 0
} else {
return Math.acos(cosine)
}
}
Insert cell
/**
* Math.ceil the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to ceil
* @returns {vec3} out
*/
function vec3ceil(out, a) {
out[0] = Math.ceil(a[0])
out[1] = Math.ceil(a[1])
out[2] = Math.ceil(a[2])
return out
}
Insert cell
/**
* Creates a new vec3 initialized with values from an existing vector
*
* @param {vec3} a vector to clone
* @returns {vec3} a new 3D vector
*/
function vec3clone(a) {
var out = new Float32Array(3)
out[0] = a[0]
out[1] = a[1]
out[2] = a[2]
return out
}
Insert cell
/**
* Copy the values from one vec3 to another
*
* @param {vec3} out the receiving vector
* @param {vec3} a the source vector
* @returns {vec3} out
*/
function vec3copy(out, a) {
out[0] = a[0]
out[1] = a[1]
out[2] = a[2]
return out
}
Insert cell
/**
* Creates a new, empty vec3
*
* @returns {vec3} a new 3D vector
*/
function vec3create() {
var out = new Float32Array(3)
out[0] = 0
out[1] = 0
out[2] = 0
return out
}
Insert cell
/**
* Computes the cross product of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function vec3cross(out, a, b) {
var ax = a[0], ay = a[1], az = a[2],
bx = b[0], by = b[1], bz = b[2]

out[0] = ay * bz - az * by
out[1] = az * bx - ax * bz
out[2] = ax * by - ay * bx
return out
}
Insert cell
/**
* Calculates the euclidian distance between two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} distance between a and b
*/
function vec3distance(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2]
return Math.sqrt(x*x + y*y + z*z)
}
Insert cell
vec3dist = vec3distance
Insert cell
/**
* Divides two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function vec3divide(out, a, b) {
out[0] = a[0] / b[0]
out[1] = a[1] / b[1]
out[2] = a[2] / b[2]
return out
}
Insert cell
vec3div = vec3divide
Insert cell
/**
* Calculates the dot product of two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} dot product of a and b
*/
function vec3dot(a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
}
Insert cell
/**
* Returns whether or not the vectors have approximately the same elements in the same position.
*
* @param {vec3} a The first vector.
* @param {vec3} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function vec3equals(a, b) {
var a0 = a[0]
var a1 = a[1]
var a2 = a[2]
var b0 = b[0]
var b1 = b[1]
var b2 = b[2]
return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)))
}
Insert cell
/**
* Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
*
* @param {vec3} a The first vector.
* @param {vec3} b The second vector.
* @returns {Boolean} True if the vectors are equal, false otherwise.
*/
function vec3exactEquals(a, b) {
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2]
}
Insert cell
/**
* Math.floor the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to floor
* @returns {vec3} out
*/
function vec3floor(out, a) {
out[0] = Math.floor(a[0])
out[1] = Math.floor(a[1])
out[2] = Math.floor(a[2])
return out
}
Insert cell
/**
* Perform some operation over an array of vec3s.
*
* @param {Array} a the array of vectors to iterate over
* @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
* @param {Number} offset Number of elements to skip at the beginning of the array
* @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
* @param {Function} fn Function to call for each vector in the array
* @param {Object} [arg] additional argument to pass to fn
* @returns {Array} a
* @function
*/
vec3forEach = {
let vec = vec3create()
return function vec3forEach(a, stride, offset, count, fn, arg) {
var i, l
if(!stride) {
stride = 3
}

if(!offset) {
offset = 0
}
if(count) {
l = Math.min((count * stride) + offset, a.length)
} else {
l = a.length
}

for(i = offset; i < l; i += stride) {
vec[0] = a[i]
vec[1] = a[i+1]
vec[2] = a[i+2]
fn(vec, vec, arg)
a[i] = vec[0]
a[i+1] = vec[1]
a[i+2] = vec[2]
}
return a
}
}
Insert cell
/**
* Creates a new vec3 initialized with the given values
*
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} a new 3D vector
*/
function vec3fromValues(x, y, z) {
var out = new Float32Array(3)
out[0] = x
out[1] = y
out[2] = z
return out
}
Insert cell
/**
* Returns the inverse of the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to invert
* @returns {vec3} out
*/
function vec3inverse(out, a) {
out[0] = 1.0 / a[0]
out[1] = 1.0 / a[1]
out[2] = 1.0 / a[2]
return out
}
Insert cell
/**
* Calculates the length of a vec3
*
* @param {vec3} a vector to calculate length of
* @returns {Number} length of a
*/
function vec3length(a) {
var x = a[0],
y = a[1],
z = a[2]
return Math.sqrt(x*x + y*y + z*z)
}
Insert cell
vec3len = vec3length
Insert cell
/**
* Performs a linear interpolation between two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {Number} t interpolation amount between the two inputs
* @returns {vec3} out
*/
function vec3lerp(out, a, b, t) {
var ax = a[0],
ay = a[1],
az = a[2]
out[0] = ax + t * (b[0] - ax)
out[1] = ay + t * (b[1] - ay)
out[2] = az + t * (b[2] - az)
return out
}
Insert cell
/**
* Returns the maximum of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function vec3max(out, a, b) {
out[0] = Math.max(a[0], b[0])
out[1] = Math.max(a[1], b[1])
out[2] = Math.max(a[2], b[2])
return out
}
Insert cell
/**
* Returns the minimum of two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function vec3min(out, a, b) {
out[0] = Math.min(a[0], b[0])
out[1] = Math.min(a[1], b[1])
out[2] = Math.min(a[2], b[2])
return out
}
Insert cell
/**
* Multiplies two vec3's
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function vec3multiply(out, a, b) {
out[0] = a[0] * b[0]
out[1] = a[1] * b[1]
out[2] = a[2] * b[2]
return out
}
Insert cell
vec3mul = vec3multiply
Insert cell
/**
* Negates the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to negate
* @returns {vec3} out
*/
function vec3negate(out, a) {
out[0] = -a[0]
out[1] = -a[1]
out[2] = -a[2]
return out
}
Insert cell
/**
* Normalize a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to normalize
* @returns {vec3} out
*/
function vec3normalize(out, a) {
var x = a[0],
y = a[1],
z = a[2]
var len = x*x + y*y + z*z
if (len > 0) {
//TODO: evaluate use of glm_invsqrt here?
len = 1 / Math.sqrt(len)
out[0] = a[0] * len
out[1] = a[1] * len
out[2] = a[2] * len
}
return out
}
Insert cell
/**
* Generates a random vector with the given scale
*
* @param {vec3} out the receiving vector
* @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
* @returns {vec3} out
*/
function vec3random(out, scale) {
scale = scale || 1.0

var r = Math.random() * 2.0 * Math.PI
var z = (Math.random() * 2.0) - 1.0
var zScale = Math.sqrt(1.0-z*z) * scale

out[0] = Math.cos(r) * zScale
out[1] = Math.sin(r) * zScale
out[2] = z * scale
return out
}
Insert cell
/**
* Rotate a 3D vector around the x-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
function vec3rotateX(out, a, b, c){
var by = b[1]
var bz = b[2]

// Translate point to the origin
var py = a[1] - by
var pz = a[2] - bz

var sc = Math.sin(c)
var cc = Math.cos(c)

// perform rotation and translate to correct position
out[0] = a[0]
out[1] = by + py * cc - pz * sc
out[2] = bz + py * sc + pz * cc

return out
}
Insert cell
/**
* Rotate a 3D vector around the y-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
function vec3rotateY(out, a, b, c){
var bx = b[0]
var bz = b[2]

// translate point to the origin
var px = a[0] - bx
var pz = a[2] - bz
var sc = Math.sin(c)
var cc = Math.cos(c)
// perform rotation and translate to correct position
out[0] = bx + pz * sc + px * cc
out[1] = a[1]
out[2] = bz + pz * cc - px * sc
return out
}
Insert cell
/**
* Rotate a 3D vector around the z-axis
* @param {vec3} out The receiving vec3
* @param {vec3} a The vec3 point to rotate
* @param {vec3} b The origin of the rotation
* @param {Number} c The angle of rotation
* @returns {vec3} out
*/
function vec3rotateZ(out, a, b, c){
var bx = b[0]
var by = b[1]

//Translate point to the origin
var px = a[0] - bx
var py = a[1] - by
var sc = Math.sin(c)
var cc = Math.cos(c)

// perform rotation and translate to correct position
out[0] = bx + px * cc - py * sc
out[1] = by + px * sc + py * cc
out[2] = a[2]
return out
}
Insert cell
/**
* Math.round the components of a vec3
*
* @param {vec3} out the receiving vector
* @param {vec3} a vector to round
* @returns {vec3} out
*/
function vec3round(out, a) {
out[0] = Math.round(a[0])
out[1] = Math.round(a[1])
out[2] = Math.round(a[2])
return out
}
Insert cell
/**
* Scales a vec3 by a scalar number
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to scale
* @param {Number} b amount to scale the vector by
* @returns {vec3} out
*/
function vec3scale(out, a, b) {
out[0] = a[0] * b
out[1] = a[1] * b
out[2] = a[2] * b
return out
}
Insert cell
/**
* Adds two vec3's after scaling the second operand by a scalar value
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @param {Number} scale the amount to scale b by before adding
* @returns {vec3} out
*/
function vec3scaleAndAdd(out, a, b, scale) {
out[0] = a[0] + (b[0] * scale)
out[1] = a[1] + (b[1] * scale)
out[2] = a[2] + (b[2] * scale)
return out
}
Insert cell
/**
* Set the components of a vec3 to the given values
*
* @param {vec3} out the receiving vector
* @param {Number} x X component
* @param {Number} y Y component
* @param {Number} z Z component
* @returns {vec3} out
*/
function vec3set(out, x, y, z) {
out[0] = x
out[1] = y
out[2] = z
return out
}
Insert cell
/**
* Calculates the squared euclidian distance between two vec3's
*
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {Number} squared distance between a and b
*/
function vec3squaredDistance(a, b) {
var x = b[0] - a[0],
y = b[1] - a[1],
z = b[2] - a[2]
return x*x + y*y + z*z
}
Insert cell
vec3sqrDist = vec3squaredDistance
Insert cell
/**
* Calculates the squared length of a vec3
*
* @param {vec3} a vector to calculate squared length of
* @returns {Number} squared length of a
*/
function vec3squaredLength(a) {
var x = a[0],
y = a[1],
z = a[2]
return x*x + y*y + z*z
}
Insert cell
vec3sqrLen = vec3squaredLength
Insert cell
/**
* Subtracts vector b from vector a
*
* @param {vec3} out the receiving vector
* @param {vec3} a the first operand
* @param {vec3} b the second operand
* @returns {vec3} out
*/
function vec3subtract(out, a, b) {
out[0] = a[0] - b[0]
out[1] = a[1] - b[1]
out[2] = a[2] - b[2]
return out
}
Insert cell
vec3sub = vec3subtract
Insert cell
/**
* Transforms the vec3 with a mat3.
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {mat4} m the 3x3 matrix to transform with
* @returns {vec3} out
*/
function vec3transformMat3(out, a, m) {
var x = a[0], y = a[1], z = a[2]
out[0] = x * m[0] + y * m[3] + z * m[6]
out[1] = x * m[1] + y * m[4] + z * m[7]
out[2] = x * m[2] + y * m[5] + z * m[8]
return out
}
Insert cell
/**
* Transforms the vec3 with a mat4.
* 4th vector component is implicitly '1'
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {mat4} m matrix to transform with
* @returns {vec3} out
*/
function vec3transformMat4(out, a, m) {
var x = a[0], y = a[1], z = a[2],
w = m[3] * x + m[7] * y + m[11] * z + m[15]
w = w || 1.0
out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w
out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w
out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w
return out
}
Insert cell
/**
* Transforms the vec3 with a quat
*
* @param {vec3} out the receiving vector
* @param {vec3} a the vector to transform
* @param {quat} q quaternion to transform with
* @returns {vec3} out
*/
function vec3transformQuat(out, a, q) {
// benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations

var x = a[0], y = a[1], z = a[2],
qx = q[0], qy = q[1], qz = q[2], qw = q[3],

// calculate quat * vec
ix = qw * x + qy * z - qz * y,
iy = qw * y + qz * x - qx * z,
iz = qw * z + qx * y - qy * x,
iw = -qx * x - qy * y - qz * z

// calculate result * inverse quat
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx
return out
}
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more