blossom
Version:
Modern, Cross-Platform Application Framework
1,233 lines (1,026 loc) • 39.1 kB
JavaScript
// ==========================================================================
// Project: Blossom - Modern, Cross-Platform Application Framework
// Copyright: ©2012 Fohr Motion Picture Studios. All rights reserved.
// License: Licensed under the GPLv3 license (see BLOSSOM-LICENSE).
// ==========================================================================
/*globals ArrayBuffer Float32Array sc_assert */
// offset is in floats, numElements is in floats
var sc_assert_valid_float32_buffer = function(buffer, offset, numElements) {
var bytesNeeded = numElements*Float32Array.BYTES_PER_ELEMENT,
offsetInBytes = offset*Float32Array.BYTES_PER_ELEMENT;
sc_assert(buffer && buffer.constructor === ArrayBuffer);
sc_assert(buffer.byteLength-offsetInBytes >= bytesNeeded);
};
SC.MakeFloat32ArrayBuffer = function(floatCount) {
return new ArrayBuffer(floatCount*Float32Array.BYTES_PER_ELEMENT);
};
// ..........................................................
// 2D Points
//
SC.MakePoint = function(point, y) {
var ret, x = point;
if (arguments.length === 2) {
ret = new Float32Array(2); // initialize from function arguments
ret[0] = x;
ret[1] = y;
} else if (point) {
sc_assert(point.length === 2 && point.constructor === Float32Array);
ret = new Float32Array(point); // initialize with existing point
} else {
ret = new Float32Array(2); // zero-initialized
}
return ret;
};
SC.ZERO_POINT = SC.MakePoint();
SC.PointApplyAffineTransformTo = function(point, transform, dest) {
var x = point[0], y = point[1];
dest[0]/*x*/ = x * transform[0]/*m11*/ + y * transform[2]/*m21*/ + transform[4]/*tx*/;
dest[1]/*y*/ = x * transform[1]/*m12*/ + y * transform[3]/*m22*/ + transform[5]/*ty*/;
};
// offset is in floats, not bytes
SC.MakePointFromBuffer = function(buffer, offset, point, y) {
var ret, x = point;
sc_assert_valid_float32_buffer(buffer, offset, 2);
offset = offset*Float32Array.BYTES_PER_ELEMENT;
if (arguments.length === 4) {
ret = new Float32Array(buffer, offset, 2); // initialize from function arguments
ret[0] = x;
ret[1] = y;
} else if (point) {
sc_assert(point.length === 2 && point.constructor === Float32Array);
ret = new Float32Array(buffer, offset, 2);
ret.set(point); // initialize with existing point
} else {
ret = new Float32Array(buffer, offset, 2);
ret.set(SC.ZERO_POINT); // zero-initialize
}
sc_assert(ret.length === 2);
return ret;
};
SC.IsPoint = function(point) {
return (point.length === 2 && point.constructor === Float32Array);
};
// ..........................................................
// 3D Points
//
SC.MakePoint3D = function(point, y, z) {
var ret, x = point;
if (arguments.length === 3) {
ret = new Float32Array(3); // initialize from function arguments
ret[0] = x;
ret[1] = y;
ret[2] = z;
} else if (point) {
sc_assert(point.length === 3 && point.constructor === Float32Array);
ret = new Float32Array(point); // initialize with existing point
} else {
ret = new Float32Array(3); // zero-initialized
}
return ret;
};
SC.ZERO_POINT_3D = SC.MakePoint3D();
SC.PointApplyTransform3DTo = function(point, transform, dest) {
throw "not implemented";
// var x = point[0], y = point[1];
// dest[0]/*x*/ = x * transform[0]/*m11*/ + y * transform[2]/*m21*/ + transform[4]/*tx*/;
// dest[1]/*y*/ = x * transform[1]/*m12*/ + y * transform[3]/*m22*/ + transform[5]/*ty*/;
};
// offset is in floats, not bytes
SC.MakePoint3DFromBuffer = function(buffer, offset, point, y, z) {
var ret, x = point;
sc_assert_valid_float32_buffer(buffer, offset, 2);
offset = offset*Float32Array.BYTES_PER_ELEMENT;
if (arguments.length === 5) {
ret = new Float32Array(buffer, offset, 3); // initialize from function arguments
ret[0] = x;
ret[1] = y;
ret[2] = z;
} else if (point) {
sc_assert(point.length === 3 && point.constructor === Float32Array);
ret = new Float32Array(buffer, offset, 3);
ret.set(point); // initialize with existing point
} else {
ret = new Float32Array(buffer, offset, 3);
ret.set(SC.ZERO_POINT_3D); // zero-initialize
}
sc_assert(ret.length === 3);
return ret;
};
SC.IsPoint3D = function(point) {
return (point.length === 3 && point.constructor === Float32Array);
};
// ..........................................................
// Sizes
//
SC.MakeSize = function(size, height) {
var ret, width = size;
if (arguments.length === 2) {
ret = new Float32Array(2); // initialize from function arguments
ret[0] = width;
ret[1] = height;
} else if (size) {
sc_assert(size.length === 2 && size.constructor === Float32Array);
ret = new Float32Array(size); // initialize with existing size
} else {
ret = new Float32Array(2); // zero-initialized
}
return ret;
};
SC.ZERO_SIZE = SC.MakeSize();
SC.SizeApplyAffineTransformTo = function(size, transform, dest) {
sc_assert(size !== dest);
dest[0]/*width*/ = size[0]/*width*/ * transform[0]/*m11*/ + size[1]/*height*/ * transform[2]/*m21*/;
dest[1]/*height*/ = size[0]/*width*/ * transform[1]/*m12*/ + size[1]/*height*/ * transform[3]/*m22*/;
};
// offset is in floats, not bytes
SC.MakeSizeFromBuffer = function(buffer, offset, size, height) {
var ret, width = size;
sc_assert_valid_float32_buffer(buffer, offset, 2);
offset = offset*Float32Array.BYTES_PER_ELEMENT;
if (arguments.length === 4) {
ret = new Float32Array(buffer, offset, 2); // initialize from function arguments
ret[0] = width;
ret[1] = height;
} else if (size) {
sc_assert(size.length === 2 && size.constructor === Float32Array);
ret = new Float32Array(buffer, offset, 2);
ret.set(size); // initialize with existing size
} else {
ret = new Float32Array(buffer, offset, 2);
ret.set(SC.ZERO_SIZE); // zero-initialize
}
sc_assert(ret.length === 2);
return ret;
};
SC.IsSize = function(size) {
return (size.length === 2 && size.constructor === Float32Array);
};
SC.EqualSize = function(size, size2) {
sc_assert(size.length === 2 && size.constructor === Float32Array);
sc_assert(size2.length === 2 && size2.constructor === Float32Array);
if (size === size2) return true;
else if (size[0] === size2[0] && size[1] === size2[1]) return true;
else return false;
};
// ..........................................................
// Rects
//
SC.MakeRect = function(rect, y, width, height) {
var ret, x = rect;
if (arguments.length === 4) {
ret = new Float32Array(4); // initialize from function arguments
ret[0] = x;
ret[1] = y;
ret[2] = width;
ret[3] = height;
} else if (rect) {
sc_assert(rect.length === 4 && rect.constructor === Float32Array);
ret = new Float32Array(rect); // initialize with existing rect
} else {
ret = new Float32Array(4); // zero-initialized
}
return ret;
};
SC.ZERO_RECT = SC.MakeRect();
SC.RectApplyAffineTransformTo = function(rect, transform, dest) {
sc_assert(rect !== dest);
dest[0]/*x*/ = rect[0]/*x*/ * transform[0]/*m11*/ + rect[1]/*y*/ * transform[2]/*m21*/ + transform[4]/*tx*/;
dest[1]/*y*/ = rect[0]/*x*/ * transform[1]/*m12*/ + rect[1]/*y*/ * transform[3]/*m22*/ + transform[5]/*ty*/;
dest[2]/*width*/ = rect[2]/*width*/ * transform[0]/*m11*/ + rect[3]/*height*/ * transform[2]/*m21*/;
dest[3]/*height*/ = rect[2]/*width*/ * transform[1]/*m12*/ + rect[3]/*height*/ * transform[3]/*m22*/;
};
// offset is in floats, not bytes
SC.MakeRectFromBuffer = function(buffer, offset, rect, y, width, height) {
var ret, x = rect;
sc_assert_valid_float32_buffer(buffer, offset, 4);
offset = offset*Float32Array.BYTES_PER_ELEMENT;
if (arguments.length === 6) {
ret = new Float32Array(buffer, offset, 4); // initialize from function arguments
ret[0] = x;
ret[1] = y;
ret[2] = width;
ret[3] = height;
} else if (rect) {
sc_assert(rect.length === 4 && rect.constructor === Float32Array);
ret = new Float32Array(buffer, offset, 4);
ret.set(rect); // initialize with existing rect
} else {
ret = new Float32Array(buffer, offset, 4);
ret.set(SC.ZERO_RECT); // zero-initialize
}
sc_assert(ret.length === 4);
return ret;
};
SC.ZERO_LAYOUT_VALUES = new Float32Array(8); // zero-initialized
// offset is in floats, not bytes
SC.MakeLayoutValuesFromBuffer = function(buffer, offset) {
var ret;
sc_assert_valid_float32_buffer(buffer, offset, 8);
offset = offset*Float32Array.BYTES_PER_ELEMENT;
ret = new Float32Array(buffer, offset, 8);
ret.set(SC.ZERO_LAYOUT_VALUES); // zero-initialize
sc_assert(ret.length === 8);
return ret;
};
SC.IsRect = function(rect) {
return (rect.length === 4 && rect.constructor === Float32Array);
};
SC.EqualRect = function(rect, rect2) {
sc_assert(rect.length === 4 && rect.constructor === Float32Array);
sc_assert(rect2.length === 4 && rect2.constructor === Float32Array);
if (rect === rect2) return true;
else if (rect[0] === rect2[0] && rect[1] === rect2[1] && rect[2] === rect2[2] && rect[3] === rect2[3]) return true;
else return false;
};
// ..........................................................
// Affine Transforms
//
SC.MakeAffineTransform = function(mat, m12,
m21, m22, tx, ty)
{
var ret, m11 = mat;
if (arguments.length === 6) {
ret = new Float32Array(6); // initialize from function arguments
ret[0] = m11; ret[1] = m12;
ret[2] = m21; ret[3] = m22;
ret[4] = tx;
ret[5] = ty;
} else if (mat) {
sc_assert(mat.length === 6 && mat.constructor === Float32Array);
ret = new Float32Array(mat); // initialize with existing affine transform
} else {
ret = new Float32Array(6); // zero-initialized
}
return ret;
};
SC.MakeIdentityAffineTransform = function() {
var ret = new Float32Array(6);
// A new Float32Array is already initialized to zero.
ret[0] = 1; /* ret[1] = 0; */
/* ret[2] = 0; */ ret[3] = 1;
// ret[4] = 0;
// ret[5] = 0;
return ret;
};
SC.AFFINE_TRANSFORM_ZERO = SC.MakeAffineTransform();
SC.AFFINE_TRANSFORM_IDENTITY = SC.MakeIdentityAffineTransform();
// offset is in floats, not bytes
SC.MakeAffineTransformFromBuffer = function(buffer, offset, mat, m12,
m21, m22, tx, ty)
{
var ret, m11 = mat;
sc_assert_valid_float32_buffer(buffer, offset, 6);
offset = offset*Float32Array.BYTES_PER_ELEMENT;
if (arguments.length === 8) {
ret = new Float32Array(buffer, offset); // initialize from function arguments
ret[0] = m11; ret[1] = m12;
ret[2] = m21; ret[3] = m22;
ret[4] = tx;
ret[5] = ty;
} else if (mat) {
sc_assert(mat.length === 6 && mat.constructor === Float32Array);
ret = new Float32Array(buffer, offset, 6);
ret.set(mat); // initialize with existing transform
} else {
ret = new Float32Array(buffer, offset, 6);
ret.set(SC.AFFINE_TRANSFORM_ZERO); // zero-initialize
}
sc_assert(ret.length === 6);
return ret;
};
SC.MakeIdentityAffineTransformFromBuffer = function(buffer, offset) {
var ret = SC.MakeAffineTransformFromBuffer(buffer, offset);
ret.set(SC.AFFINE_TRANSFORM_IDENTITY);
return ret;
};
SC.SetIdentityAffineTransform = function(mat) {
sc_assert(mat && mat.length === 6 && mat.constructor === Float32Array);
mat.set(SC.AFFINE_TRANSFORM_IDENTITY);
// Result:
// mat[0] = 1; mat[1] = 0;
// mat[2] = 0; mat[5] = 1;
// mat[4] = 0;
// mat[5] = 0;
};
SC.AffineTransformConcatTo = function(left, right, dest) {
var left_m11 = left[0]/*m11*/,
left_m12 = left[1]/*m12*/,
left_m21 = left[2]/*m21*/,
left_m22 = left[3]/*m22*/,
left_tx = left[4]/*tx*/,
left_ty = left[5]/*ty*/;
// Result:
// dest.m11 = left.m11 * right.m11 + left.m12 * right.m21;
// dest.m12 = left.m11 * right.m12 + left.m12 * right.m22;
// dest.m21 = left.m21 * right.m11 + left.m22 * right.m21;
// dest.m22 = left.m21 * right.m12 + left.m22 * right.m22;
// dest.tx = left.tx * right.m11 + left.ty * right.m21 + right.tx;
// dest.ty = left.tx * right.m12 + left.ty * right.m22 + right.ty;
dest[0] = left_m11 * right[0] + left_m12 * right[2];
dest[1] = left_m11 * right[1] + left_m12 * right[3];
dest[2] = left_m21 * right[0] + left_m22 * right[2];
dest[3] = left_m21 * right[1] + left_m22 * right[3];
dest[4] = left_tx * right[0] + left_tx * right[2] + right[4];
dest[5] = left_ty * right[1] + left_ty * right[3] + right[5];
};
SC.IsIdentityAffineTransform = function(mat) {
if (mat[0]/*m11*/ === 1.0 &&
mat[1]/*m12*/ === 0.0 &&
mat[2]/*m21*/ === 0.0 &&
mat[3]/*m22*/ === 1.0 &&
mat[4]/*tx*/ === 0.0 &&
mat[5]/*ty*/ === 0.0 ) return true;
else return false;
};
// src and dest must be different!
SC.AffineTransformInvertTo = function(src, dest) {
var determinant = 1 / (src[0]/*m11*/ * src[3]/*m22*/ - src[1]/*m12*/ * src[2]/*m21*/);
sc_assert(src !== dest);
dest[0]/*m11*/ = determinant * src[3]/*m22*/;
dest[1]/*m12*/ = -determinant * src[1]/*m12*/;
dest[2]/*m21*/ = -determinant * src[2]/*m21*/;
dest[3]/*m22*/ = determinant * src[0]/*m11*/;
dest[4]/*tx*/ = determinant * (src[2]/*m21*/ * src[5]/*ty*/ - src[3]/*m22*/ * src[4]/*tx*/);
dest[5]/*ty*/ = determinant * (src[1]/*m12*/ * src[4]/*tx*/ - src[0]/*m11*/ * src[5]/*ty*/);
};
sc_assert(SC.IsIdentityAffineTransform(SC.AFFINE_TRANSFORM_IDENTITY));
// ..........................................................
// 3D Transforms
//
SC.MakeTransform3D = function(mat, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44)
{
var ret, m11 = mat;
if (arguments.length === 16) {
ret = new Float32Array(16); // initialize from function arguments
ret[0] = m11; ret[1] = m12; ret[2] = m13; ret[3] = m14;
ret[4] = m21; ret[5] = m22; ret[6] = m23; ret[7] = m24;
ret[8] = m31; ret[9] = m32; ret[10] = m33; ret[11] = m34;
ret[12] = m41; ret[13] = m42; ret[14] = m43; ret[15] = m44;
} else if (mat) {
sc_assert(mat.length === 16 && mat.constructor === Float32Array);
ret = new Float32Array(mat); // initialize with existing transform3d
} else {
ret = new Float32Array(16); // zero-initialized
}
return ret;
};
SC.IsAffineTransform = function(mat) {
return (mat.length === 6 && mat.constructor === Float32Array);
};
SC.CopyAffineTransformTo = function(src, dest) {
sc_assert(src !== dest);
sc_assert(src.length === 6 && src.constructor === Float32Array);
sc_assert(dest.length === 6 && dest.constructor === Float32Array);
dest.set(src);
};
SC.MakeIdentityTransform3D = function() {
var ret = new Float32Array(16);
// A new Float32Array is already initialized to zero.
ret[0] = 1; /* ret[1] = 0; ret[2] = 0; ret[3] = 0; */
/* ret[4] = 0; */ ret[5] = 1; /* ret[6] = 0; ret[7] = 0; */
/* ret[8] = 0; ret[9] = 0; */ ret[10] = 1; /* ret[11] = 0; */
/* ret[12] = 0; ret[13] = 0; ret[14] = 0; */ ret[15] = 1;
return ret;
};
SC.TRANSFORM3D_ZERO = SC.MakeTransform3D();
SC.TRANSFORM3D_IDENTITY = SC.MakeIdentityTransform3D();
// offset is in floats, not bytes
SC.MakeTransform3DFromBuffer = function(buffer, offset, mat, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44)
{
var ret, m11 = mat;
sc_assert_valid_float32_buffer(buffer, offset, 16);
offset = offset*Float32Array.BYTES_PER_ELEMENT;
if (arguments.length === 18) {
ret = new Float32Array(buffer, offset, 16); // initialize from function arguments
ret[0] = m11; ret[1] = m12; ret[2] = m13; ret[3] = m14;
ret[4] = m21; ret[5] = m22; ret[6] = m23; ret[7] = m24;
ret[8] = m31; ret[9] = m32; ret[10] = m33; ret[11] = m34;
ret[12] = m41; ret[13] = m42; ret[14] = m43; ret[15] = m44;
} else if (mat) {
sc_assert(mat.length === 16 && mat.constructor === Float32Array);
ret = new Float32Array(buffer, offset, 16);
ret.set(mat); // initialize with existing transform3d
} else {
ret = new Float32Array(buffer, offset, 16);
ret.set(SC.TRANSFORM3D_ZERO); // zero-initialize
}
sc_assert(ret.length === 16);
return ret;
};
SC.MakeIdentityTransform3DFromBuffer = function(buffer, offset) {
var ret = SC.MakeTransform3DFromBuffer(buffer, offset);
ret.set(SC.TRANSFORM3D_IDENTITY);
return ret;
};
SC.SetIdentityTransform3D = function(mat) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
mat.set(SC.TRANSFORM3D_IDENTITY);
// Result:
// mat[0] = 1; mat[1] = 0; mat[2] = 0; mat[3] = 0;
// mat[4] = 0; mat[5] = 1; mat[6] = 0; mat[7] = 0;
// mat[8] = 0; mat[9] = 0; mat[10] = 1; mat[11] = 0;
// mat[12] = 0; mat[13] = 0; mat[14] = 0; mat[15] = 1;
};
SC.IsTransform3D = function(mat) {
return (mat.length === 16 && mat.constructor === Float32Array);
};
SC.CopyTransform3DTo = function(src, dest) {
sc_assert(src !== dest);
sc_assert(src.length === 16 && src.constructor === Float32Array);
sc_assert(dest.length === 16 && dest.constructor === Float32Array);
dest.set(src);
};
SC.Transform3DConcatTo = function(left, right, dest) {
var left_m11 = left[0] /*m11*/,
left_m12 = left[1] /*m12*/,
left_m13 = left[2] /*m13*/,
left_m14 = left[3] /*m14*/,
left_m21 = left[4] /*m21*/,
left_m22 = left[5] /*m22*/,
left_m23 = left[6] /*m23*/,
left_m24 = left[7] /*m24*/,
left_m31 = left[8] /*m31*/,
left_m32 = left[9] /*m32*/,
left_m33 = left[10]/*m33*/,
left_m34 = left[11]/*m34*/,
left_m41 = left[12]/*m41*/,
left_m42 = left[13]/*m42*/,
left_m43 = left[14]/*m43*/,
left_m44 = left[15]/*m44*/;
// Result:
// dest.m11 = left.m11 * right.m11 + left.m12 * right.m21 + left.m13 * right.m31 + left.m14 * right.m41;
// dest.m12 = left.m11 * right.m12 + left.m12 * right.m22 + left.m13 * right.m32 + left.m14 * right.m42;
// dest.m13 = left.m11 * right.m13 + left.m12 * right.m23 + left.m13 * right.m33 + left.m14 * right.m43;
// dest.m14 = left.m11 * right.m14 + left.m12 * right.m24 + left.m13 * right.m34 + left.m14 * right.m44;
// dest.m21 = left.m21 * right.m11 + left.m22 * right.m21 + left.m23 * right.m31 + left.m24 * right.m41;
// dest.m22 = left.m21 * right.m12 + left.m22 * right.m22 + left.m23 * right.m32 + left.m24 * right.m42;
// dest.m23 = left.m21 * right.m13 + left.m22 * right.m23 + left.m23 * right.m33 + left.m24 * right.m43;
// dest.m24 = left.m21 * right.m14 + left.m22 * right.m24 + left.m23 * right.m34 + left.m24 * right.m44;
// dest.m31 = left.m31 * right.m11 + left.m32 * right.m21 + left.m33 * right.m31 + left.m34 * right.m41;
// dest.m32 = left.m31 * right.m12 + left.m32 * right.m22 + left.m33 * right.m32 + left.m34 * right.m42;
// dest.m33 = left.m31 * right.m13 + left.m32 * right.m23 + left.m33 * right.m33 + left.m34 * right.m43;
// dest.m34 = left.m31 * right.m14 + left.m32 * right.m24 + left.m33 * right.m34 + left.m34 * right.m44;
// dest.m41 = left.m41 * right.m11 + left.m42 * right.m21 + left.m43 * right.m31 + left.m44 * right.m41;
// dest.m42 = left.m41 * right.m12 + left.m42 * right.m22 + left.m43 * right.m32 + left.m44 * right.m42;
// dest.m43 = left.m41 * right.m13 + left.m42 * right.m23 + left.m43 * right.m33 + left.m44 * right.m43;
// dest.m44 = left.m41 * right.m14 + left.m42 * right.m24 + left.m43 * right.m34 + left.m44 * right.m44;
dest[0] = left_m11 * right[0] + left_m12 * right[4] + left_m13 * right[8] + left_m14 * right[12];
dest[1] = left_m11 * right[1] + left_m12 * right[5] + left_m13 * right[9] + left_m14 * right[13];
dest[2] = left_m11 * right[2] + left_m12 * right[6] + left_m13 * right[10] + left_m14 * right[14];
dest[3] = left_m11 * right[3] + left_m12 * right[7] + left_m13 * right[11] + left_m14 * right[15];
dest[4] = left_m21 * right[0] + left_m22 * right[4] + left_m23 * right[8] + left_m24 * right[12];
dest[5] = left_m21 * right[1] + left_m22 * right[5] + left_m23 * right[9] + left_m24 * right[13];
dest[6] = left_m21 * right[2] + left_m22 * right[6] + left_m23 * right[10] + left_m24 * right[14];
dest[7] = left_m21 * right[3] + left_m22 * right[7] + left_m23 * right[11] + left_m24 * right[15];
dest[8] = left_m31 * right[0] + left_m32 * right[4] + left_m33 * right[8] + left_m34 * right[12];
dest[9] = left_m31 * right[1] + left_m32 * right[5] + left_m33 * right[9] + left_m34 * right[13];
dest[10] = left_m31 * right[2] + left_m32 * right[6] + left_m33 * right[10] + left_m34 * right[14];
dest[11] = left_m31 * right[3] + left_m32 * right[7] + left_m33 * right[11] + left_m34 * right[15];
dest[12] = left_m41 * right[0] + left_m42 * right[4] + left_m43 * right[8] + left_m44 * right[12];
dest[13] = left_m41 * right[1] + left_m42 * right[5] + left_m43 * right[9] + left_m44 * right[13];
dest[14] = left_m41 * right[2] + left_m42 * right[6] + left_m43 * right[10] + left_m44 * right[14];
dest[15] = left_m41 * right[3] + left_m42 * right[7] + left_m43 * right[11] + left_m44 * right[15];
};
SC.temporaryTransform3D = SC.MakeIdentityTransform3D();
// ..........................................................
// 3D Transforms - Rotation
//
SC.Transform3DRotateXTo = function(src, rad, dst) {
sc_assert(src && src.length === 16 && src.constructor === Float32Array);
sc_assert(dst && dst.length === 16 && dst.constructor === Float32Array);
sc_assert(typeof rad === 'number');
var tmp = SC.temporaryTransform3D;
tmp.set(SC.TRANSFORM3D_IDENTITY); // Bulk set the 1s and 0s
var cos = Math.cos(rad);
// tmp[0] = 1; tmp[1] = 0 ; tmp[2] = 0 ; tmp[3] = 0;
/* tmp[4] = 0;*/ tmp[5] = cos ; tmp[6] = Math.sin(-rad); // tmp[7] = 0;
/* tmp[8] = 0;*/ tmp[9] = Math.sin(rad); tmp[10] = cos ; // tmp[11] = 0;
// tmp[12] = 0; tmp[13] = 0 ; tmp[14] = 0 ; tmp[15] = 1;
SC.Transform3DConcatTo(src, tmp, dst);
};
SC.Transform3DRotateYTo = function(src, rad, dst) {
sc_assert(src && src.length === 16 && src.constructor === Float32Array);
sc_assert(dst && dst.length === 16 && dst.constructor === Float32Array);
sc_assert(typeof rad === 'number');
var tmp = SC.temporaryTransform3D;
tmp.set(SC.TRANSFORM3D_IDENTITY); // Bulk set the 1s and 0s
var cos = Math.cos(rad);
tmp[0] = cos ; /*tmp[1] = 0;*/ tmp[2] = Math.sin(rad); // tmp[3] = 0;
// tmp[4] = 0 ; tmp[5] = 1; tmp[6] = 0 ; tmp[7] = 0;
tmp[8] = Math.sin(-rad); /*tmp[9] = 0;*/ tmp[10] = cos ; // tmp[11] = 0;
// tmp[12] = 0 ; tmp[13] = 0; tmp[14] = 0 ; tmp[15] = 1;
SC.Transform3DConcatTo(src, tmp, dst);
};
SC.Transform3DRotateZTo = function(src, rad, dst) {
sc_assert(src && src.length === 16 && src.constructor === Float32Array);
sc_assert(dst && dst.length === 16 && dst.constructor === Float32Array);
sc_assert(typeof rad === 'number');
var tmp = SC.temporaryTransform3D;
tmp.set(SC.TRANSFORM3D_IDENTITY); // Bulk set the 1s and 0s
var cos = Math.cos(rad);
tmp[0] = cos ; tmp[1] = Math.sin(-rad); // tmp[2] = 0; tmp[3] = 0;
tmp[4] = Math.sin(rad); tmp[5] = cos ; // tmp[6] = 0; tmp[7] = 0;
// tmp[8] = 0 ; tmp[9] = 0 ; tmp[10] = 1; tmp[11] = 0;
// tmp[12] = 0 ; tmp[13] = 0 ; tmp[14] = 0; tmp[15] = 1;
SC.Transform3DConcatTo(src, tmp, dst);
};
SC.Transform3DRotateX = function(mat, rad) {
var ret = SC.MakeTransform3D();
SC.Transform3DRotateXTo(mat, rad, ret);
return ret;
};
SC.Transform3DRotateY = function(mat, rad) {
var ret = SC.MakeTransform3D();
SC.Transform3DRotateYTo(mat, rad, ret);
return ret;
};
SC.Transform3DRotateZ = function(mat, rad) {
var ret = SC.MakeTransform3D();
SC.Transform3DRotateZTo(mat, rad, ret);
return ret;
};
// ..........................................................
// 3D Transforms - Scaling
//
SC.Transform3DScaleX = function(mat, x) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof x === 'number');
var ret = SC.MakeTransform3D(mat);
ret[0] *= x;
return ret;
};
SC.Transform3DScaleY = function(mat, y) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof y === 'number');
var ret = SC.MakeTransform3D(mat);
ret[5] *= y;
return ret;
};
SC.Transform3DScaleZ = function(mat, z) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof z === 'number');
var ret = SC.MakeTransform3D(mat);
ret[10] *= z;
return ret;
};
SC.Transform3DScale = function(mat, x, y) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof x === 'number');
sc_assert(typeof y === 'number');
var ret = SC.MakeTransform3D(mat);
ret[0] *= x;
ret[5] *= y;
return ret;
};
SC.Transform3DScale3D = function(mat, x, y, z) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof x === 'number');
sc_assert(typeof y === 'number');
sc_assert(typeof z === 'number');
var ret = SC.MakeTransform3D(mat);
ret[0] *= x;
ret[5] *= y;
ret[10] *= y;
return ret;
};
SC.Transform3DScale3DTo = function(src, x, y, z, dst) {
sc_assert(src && src.length === 16 && src.constructor === Float32Array);
sc_assert(dst && dst.length === 16 && dst.constructor === Float32Array);
sc_assert(typeof x === 'number');
sc_assert(typeof y === 'number');
sc_assert(typeof z === 'number');
if (src !== dst) dst.set(src); // Bulk set
// And then just update the value in-place.
dst[0] *= x;
dst[5] *= y;
dst[10] *= z;
};
// ..........................................................
// 3D Transforms - Translation
//
SC.Transform3DTranslateX = function(mat, x) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof x === 'number');
var ret = SC.MakeTransform3D(mat);
ret[12] += x;
return ret;
};
SC.Transform3DTranslateY = function(mat, y) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof y === 'number');
var ret = SC.MakeTransform3D(mat);
ret[13] += y;
return ret;
};
SC.Transform3DTranslateZ = function(mat, z) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof z === 'number');
var ret = SC.MakeTransform3D(mat);
ret[14] += z;
return ret;
};
SC.Transform3DTranslate = function(mat, x, y) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof x === 'number');
sc_assert(typeof y === 'number');
var ret = SC.MakeTransform3D(mat);
ret[12] += x;
ret[13] += y;
return ret;
};
SC.Transform3DTranslate3D = function(mat, x, y, z) {
sc_assert(mat && mat.length === 16 && mat.constructor === Float32Array);
sc_assert(typeof x === 'number');
sc_assert(typeof y === 'number');
sc_assert(typeof z === 'number');
var ret = SC.MakeTransform3D(mat);
ret[12] += x;
ret[13] += y;
ret[14] += z;
return ret;
};
SC.Transform3DTranslate3DTo = function(src, x, y, z, dst) {
sc_assert(src && src.length === 16 && src.constructor === Float32Array);
sc_assert(dst && dst.length === 16 && dst.constructor === Float32Array);
sc_assert(typeof x === 'number');
sc_assert(typeof y === 'number');
sc_assert(typeof z === 'number');
if (src !== dst) dst.set(src); // Bulk set
// And then just update the value in-place.
dst[12] += x;
dst[13] += y;
dst[14] += z;
};
// ..........................................................
// Structure Getters and Setters
//
// Below are ways to access these structures using names, rather than
// indices. They are designed to match the equivalent structure in Cocoa/
// Core Animation.
//
// Note that it is more efficient to index into them, so Blossom's own code
// should always use the indices, not the getter/setters.
(function() {
var p = Float32Array.prototype;
Object.defineProperty(p, 'x', {
get: function() {
return this[0];
},
set: function(val) {
var old = this[0];
this[0] = val;
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'x', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('x', function() {
// return this[0];
// });
//
// Float32Array.prototype.__defineSetter__('x', function(val) {
// var old = this[0];
// this[0] = val;
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'x', old, val);
// });
Object.defineProperty(p, 'y', {
get: function() {
return this[1];
},
set: function(val) {
var old = this[1];
this[1] = val;
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'y', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('y', function() {
// return this[1];
// });
//
// Float32Array.prototype.__defineSetter__('y', function(val) {
// var old = this[1];
// this[1] = val;
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'y', old, val);
// });
Object.defineProperty(p, 'z', {
get: function() {
return this[2];
},
set: function(val) {
var old = this[2];
this[2] = val;
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'z', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('z', function() {
// return this[2];
// });
//
// Float32Array.prototype.__defineSetter__('z', function(val) {
// var old = this[2];
// this[2] = val;
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'z', old, val);
// });
Object.defineProperty(p, 'w', {
get: function() {
return this.length === 2 ? this[0] : this[2];
},
set: function(val) {
var old;
if (this.length === 2) {
old = this[0];
this[0] = val;
} else {
old = this[2];
this[2] = val;
}
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'width', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('w', function() {
// return this.length === 2 ? this[0] : this[2];
// });
//
// Float32Array.prototype.__defineSetter__('w', function(val) {
// var old;
// if (this.length === 2) {
// old = this[0];
// this[0] = val;
// } else {
// old = this[2];
// this[2] = val;
// }
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'width', old, val);
// });
Object.defineProperty(p, 'width', {
get: function() {
return this.length === 2 ? this[0] : this[2];
},
set: function(val) {
var old;
if (this.length === 2) {
old = this[0];
this[0] = val;
} else {
old = this[2];
this[2] = val;
}
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'width', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('width', function() {
// return this.length === 2 ? this[0] : this[2];
// });
//
// Float32Array.prototype.__defineSetter__('width', function(val) {
// var old;
// if (this.length === 2) {
// old = this[0];
// this[0] = val;
// } else {
// old = this[2];
// this[2] = val;
// }
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'width', old, val);
// });
Object.defineProperty(p, 'h', {
get: function() {
return this.length === 2 ? this[1] : this[3];
},
set: function(val) {
var old;
if (this.length === 2) {
old = this[1];
this[1] = val;
} else {
old = this[3];
this[3] = val;
}
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'height', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('h', function() {
// return this.length === 2 ? this[1] : this[3];
// });
//
// Float32Array.prototype.__defineSetter__('h', function(val) {
// var old;
// if (this.length === 2) {
// old = this[1];
// this[1] = val;
// } else {
// old = this[3];
// this[3] = val;
// }
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'height', old, val);
// });
Object.defineProperty(p, 'height', {
get: function() {
return this.length === 2 ? this[1] : this[3];
},
set: function(val) {
var old;
if (this.length === 2) {
old = this[1];
this[1] = val;
} else {
old = this[3];
this[3] = val;
}
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'height', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('height', function() {
// return this.length === 2 ? this[1] : this[3];
// });
//
// Float32Array.prototype.__defineSetter__('height', function(val) {
// var old;
// if (this.length === 2) {
// old = this[1];
// this[1] = val;
// } else {
// old = this[3];
// this[3] = val;
// }
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'height', old, val);
// });
// Allow structure access to SC.AffineTransform and SC.Transform3D members.
'm11 m12 m13 m14 m21 m22 m23 m24 m31 m32 m33 m34 m41 m42 m43 m44'.w().forEach(function(prop, idx) {
// The m21 and m22 props are defined below, but we leave them in here
// so the indexing for subsquent properties is correct.
if (prop === 'm21' || prop === 'm22') return;
Object.defineProperty(p, prop, {
get: function() {
return this[idx];
},
set: function(val) {
var old = this[idx];
this[idx] = val;
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, prop, old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__(prop, function() {
// return this[idx];
// });
//
// Float32Array.prototype.__defineSetter__(prop, function(val) {
// var old = this[idx];
// this[idx] = val;
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, prop, old, val);
// });
});
// The m21 and m22 members have different indices depending on array length.
Object.defineProperty(p, 'm21', {
get: function() {
return (this.length === 6) ? this[2] : this[4];
},
set: function(val) {
var old;
if (this.length === 6) {
old = this[2];
this[2] = val;
} else {
old = this[4];
this[4] = val;
}
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'm21', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('m21', function() {
// return (this.length === 6) ? this[2] : this[4];
// });
//
// Float32Array.prototype.__defineSetter__('m21', function(val) {
// var old;
// if (this.length === 6) {
// old = this[2];
// this[2] = val;
// } else {
// old = this[4];
// this[4] = val;
// }
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'm21', old, val);
// });
Object.defineProperty(p, 'm22', {
get: function() {
return (this.length === 6) ? this[3] : this[5];
},
set: function(val) {
var old;
if (this.length === 6) {
old = this[3];
this[3] = val;
} else {
old = this[5];
this[5] = val;
}
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'm22', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('m22', function() {
// return (this.length === 6) ? this[3] : this[5];
// });
//
// Float32Array.prototype.__defineSetter__('m22', function(val) {
// var old;
// if (this.length === 6) {
// old = this[3];
// this[3] = val;
// } else {
// old = this[5];
// this[5] = val;
// }
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'm22', old, val);
// });
Object.defineProperty(p, 'tx', {
get: function() {
return this[4];
},
set: function(val) {
var old = this[4];
this[4] = val;
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'tx', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('tx', function() {
// return this[4];
// });
//
// Float32Array.prototype.__defineSetter__('tx', function(val) {
// var old = this[4];
// this[4] = val;
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'tx', old, val);
// });
Object.defineProperty(p, 'ty', {
get: function() {
return this[5];
},
set: function(val) {
var old = this[5];
this[5] = val;
var owner = this.owner;
if (owner) owner.structureDidChange(this, this.keyName, 'ty', old, val);
},
enumerable: false,
configurable: false
});
// Float32Array.prototype.__defineGetter__('ty', function() {
// return this[5];
// });
//
// Float32Array.prototype.__defineSetter__('ty', function(val) {
// var old = this[5];
// this[5] = val;
// var owner = this.owner;
// if (owner) owner.structureDidChange(this, this.keyName, 'ty', old, val);
// });
})();