The `vector` package is marked as `Compatible`, which means any game can use it.

This package contains classes implementing the subset of vector and matrix operations that are useful in 2D and 3D graphics.

This is simply a memory-efficient way to encapsulate many vectors. They can all be multiplied by matrices at the same time in parallel, as well. This class is only useful if you're writing low-level graphics routines instead of using someone else's.

*array*= SubCritical.Construct("VectorArray",*table*)- Construct a VectorArray from
*table*.*table*is an array of Vectors, all of the same size.

There are three Vector types. They are largely interchangeable; any Vector may, unless otherwise specified, participate in any binary operation with any other Vector, and may multiply any Matrix.

A Vector type takes the form Vec*N*, with 2 <= *N* <= 4. *VecN* is an *N*-element vector.

Actually, *all* vectors are 4-element. A 2-element vector is actually pretending to be a 4-element vector like {*x*,*y*,0,1}, and a 3-element vector a 4-element vector like {*x*,*y*,*z*,1}. Among other things, this means that if you only use Vec2 and Mat2x2, no extra work is done. And, you can use Vec3 and Mat3x4 to implement all the useful 3D affine and linear transforms you'd expect coming from OpenGL or Direct3D. (For that matter, you can use Vec2 and Mat2x4 and the third column of the matrix never even gets touched.)

*vec*= SubCritical.Construct("Vec*N*")*vec*= SubCritical.Construct("Vec2", x, y)*vec*= SubCritical.Construct("Vec3", x, y, z)*vec*= SubCritical.Construct("Vec4", x, y, z, w)- Create a Vector. If no elements are specified, the vector contains {0,0,0,1}; otherwise, exactly the right number of elements must be given.
*x*,*y*,... =*vec*()- If called as though it were a function, a Vector will return its elements. You can conveniently serialize an arbitrary Vector like this:
local serial_table = {vector:Identity(), vector()}

*-- Serialize the table, using (for instance) SCUtil.Dehydrate.**-- Later, when you've rehydrated the table:*local vector = SC.Construct(unpack(serial_table))- It's probably a good idea to make sure the first element of
*serial_table*starts with "Vec" for security reasons. *new_vector*=*old_vector_A*+*old_vector_B**new_vector*=*old_vector_A*-*old_vector_B*- These behave as the normal simple arithmetic operators, splatted across all the elements of each Vector. The returned Vector is same size as the larger of the two operand Vectors.
*is_equal*= (*vector_A*==*vector_B)*- Returns true if the two Vectors are the same order and element-for-element identical, false otherwise. (This will still return false even if the two Vectors are very, very close to equal.)
*dot_product*=*vector_A*..*vector_B*- Returns the dot product of the two Vectors.
*new_vector*=*old_vector*+*factor**new_vector*=*old_vector*-*factor**factor*is a single number, which is added to (or subtracted from) all the elements of*old_vector*.*new_vector*=*old_vector***scale_factor**scale_factor*is a single number, which is multiplied across all the elements of*old_vector*.*new_vector*=*old_vector*/*scale_factor**scale_factor*is a single number, which all the elements of*old_vector*are divided by.*new_vector*=*vector_A***vector_B*- Returns the component-wise product of the two vectors.
*new_vector*will be as small as necessary; multiply a Vec2 by a Vec3 and you get another Vec2. *new_vector*= -*old_vector*- This behaves as the normal unary negation operator, splatted across all the elements of the source Vector.
*x_coordinate*=*vec*[1]*y_coordinate*=*vec*.y*z_coordinate*=*vec*.Z- You can access individual elements of a Vector with the above notations. You can also assign to them, as long as you do not assign elements that do not exist (e.g. doing "vec.z = 1" on a Vec2).
*magnitude*=*vector*:Magnitude()*magnitude_squared*=*vector*:MagnitudeSquared()- Returns the
*magnitude*of the Vector. (The squared magnitude is simpler to calculate, and is useful in certain other calculations.) *angle*=*vec*:Angle() -- equivalent to AngleXY*angle*=*vec*:AngleXY() -- 2D angle -- The below functions are only defined on Vec3 and larger*angle*=*vec*:AngleXZ() -- 2D angle with Z mapped to Y*angle*=*vec*:AngleYZ() -- 2D angle with X and Y mapped to Y and Z- Returns the
*angle*the Vector "points" along. *new_vector*=*old_vector*:Normalize()- Returns a new Vector, in the same direction as the old one, but with unit magnitude. (If the magnitude of the old vector was zero, the new vector will be zero rather than NAN.)

There are no less than 9 different Matrix types. They are largely interchangeable; any Matrix may be multiplied by any other Matrix or by any Vector.

A Matrix type takes the form Mat*R*x*C*, with 2 <= *R* <= 4 and 2 <= *C* <= 4. *MatRxC* is an *R* row by *C* column matrix.

Actually, *all* matrices are 4x4. "Smaller" matrices are actually top-left aligned in a 4x4 matrix, with the unstored elements only "accessed" if needed (and, if so, assumed to be from the identity matrix). Among other things, this means that if you only use Vec2 and Mat2x2, no extra work is done. And, you can use Vec3 and Mat3x4 to implement all the useful 3D affine and linear transforms you'd expect coming from OpenGL or Direct3D.

*matrix*= SubCritical.Construct("Mat*R*x*C*", ...)*-- A two-dimensional rotation matrix:**matrix*= SubCritical.Construct("Mat2x2", math.cos(*theta*), math.sin(*theta*), -math.sin(*theta*), math.cos(*theta*))- Create a matrix. If no parameters are given, the matrix is the identity matrix; otherwise, exactly
*R*x*C*elements must be given in column-major order. *...*=*matrix*()- If called as though it were a function, a Matrix will return its elements, in column-major order. You can conveniently serialize an arbitrary Matrix like this:
local serial_table = {matrix:Identity(), matrix()}

*-- Serialize the table, using (for instance) SCUtil.Dehydrate.**-- Later, when you've rehydrated the table:*local matrix = SC.Construct(unpack(serial_table))- It's probably a good idea to make sure the first element of
*serial_table*starts with "Mat" for security reasons. *new_matrix*=*old_matrix_A***old_matrix_B*- Create a
*new_matrix*containing the product of*old_matrix_A*and*old_matrix_B*. No matter what type of matrix would mathematically have resulted from this, the*new_matrix*will always be as large in each dimension as the largest of the two old matrices. (3x4 * 4x4 = 4x4, 3x4 * 2x2 = 3x4, etc.) - As stated above, matrices are treated as though they were top-left-aligned in 4x4 matrices with the remaining elements hardwired to be the identity matrix. Between that and the above note on matrix dimensions, don't expect to multiply a 3x2 matrix with a 2x3 matrix and get a 3x3 matrix.
- If you have two matrices defining an affine or linear transformation, you end up with a third matrix that is equivalent to applying both transformations in order.
*new_vector*=*matrix***old_vector**new_vector_array*=*matrix***old_vector_array*- Create a
*new_vector*containing the product of*matrix*and*old_vector*(as a row vector). The resulting vector will always have the same number of elements as the*matrix*has rows. (This is useful because, for instance, all linear transformations from a 2D space into a 3D one fit into a*Mat3x2*, and multiplying said matrix by a*Vec2*will always result in a*Vec3*.) - Note that you must multiply the
*Matrix*by the*Vector*and not the other way around. - This can also be done to VectorArrays.
*coords*=*matrix*:MultiplyAndCompile(*array*, [*dx*,*dy*])*coords*=*matrix*:PerspectiveMultiplyAndCompile(*array*, [*dx*,*dy*])- These are, respectively, equivalent (but somewhat superior in speed and memory efficiency) to:
- Note that they must be VectorArrays and, in particular, can
*not*be tables of Vectors.

coords= SCUtil.CompileVectorArray(matrix*array,dx,dy)coords= SCUtil.PerspectiveCompileVectorArray(matrix*array,dx,dy)

*coords*= SCUtil.CompileVectors(*table*, [*dx*,*dy*])*coords*= SCUtil.CompileVectorArray(*array*, [*dx*,*dy*])*table*is a table full of Vectors, or*array*is a VectorArray.*coords*will be a CoordArray corresponding to those points, optionally offsetted by the provided*dx*and*dy*terms.*coords*= SCUtil.PerspectiveCompileVectors(*table*, [*dx*,*dy*])*coords*= SCUtil.PerspectiveCompileVectorArray(*array*, [*dx*,*dy*])*table*is a table full of Vectors of 3 or more elements, or*array*is a VectorArray of same.*coords*will be a CoordArray corresponding to those points, divided by their Z coordinates and then optionally offsetted by the provided*dx*and*dy*terms.*new_graphic*= SCUtil.ApplyColorMatrix(*old_graphic*,*matrix*[,*bias*)- Apply a color matrix to a Drawable and return the result in a new graphic.
*matrix*can be any combination of 3 or 4 rows and 3 or 4 columns. If given,*bias*can be any size of Vector; elements that are not present are assumed to be 0. - Example which inverts a graphic:

local matrix = SubCritical.Construct("Mat3x3", -1, 0, 0, 0, -1, 0, 0, 0, -1) local bias = SubCritical.Construct("Vec3", 1, 1, 1) inverted = SCUtil.ApplyColorMatrix(victim, matrix, bias)