/// @macro {Struct.BBMOD_Vec3} A shorthand for `new BBMOD_Vec3(1, 0, 0)`. /// @see BBMOD_VEC3_RIGHT /// @see BBMOD_VEC3_UP /// @see BBMOD_Vec3 #macro BBMOD_VEC3_FORWARD new BBMOD_Vec3(1.0, 0.0, 0.0) /// @macro {Struct.BBMOD_Vec3} A shorthand for `new BBMOD_Vec3(0, 1, 0)`. /// @see BBMOD_VEC3_FORWARD /// @see BBMOD_VEC3_UP /// @see BBMOD_Vec3 #macro BBMOD_VEC3_RIGHT new BBMOD_Vec3(0.0, 1.0, 0.0) /// @macro {Struct.BBMOD_Vec3} A shorthand for `new BBMOD_Vec3(0, 0, 1)`. /// @see BBMOD_VEC3_RIGHT /// @see BBMOD_VEC3_FORWARD /// @see BBMOD_Vec3 #macro BBMOD_VEC3_UP new BBMOD_Vec3(0.0, 0.0, 1.0) /// @func BBMOD_Vec3([_x[, _y, _z]]) /// /// @desc A 3D vector. /// /// @param {Real} [_x] The first component of the vector. Defaults to 0. /// @param {Real} [_y] The second component of the vector. Defaults to `_x`. /// @param {Real} [_z] The third component of the vector. Defaults to `_x`. /// /// @see BBMOD_Vec2 /// @see BBMOD_Vec4 function BBMOD_Vec3(_x=0.0, _y=_x, _z=_x) constructor { if(is_instanceof(_x, __vec3)) { X = _x.x; Y = _x.y; Z = _x.z; } else if(is_instanceof(_x, BBMOD_Vec3)) { X = _x.X; Y = _x.Y; Z = _x.Z; } else if(is_array(_x)) { X = _x[0]; Y = _x[1]; Z = _x[2]; } else { X = _x; Y = _y; Z = _z; } /// @func Abs() /// /// @desc Creates a new vector where each component is equal to the absolute /// value of the original component. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// new BBMOD_Vec3(-1.0, 2.0, -3.0).Abs() // => BBMOD_Vec3(1.0, 2.0, 3.0) /// ``` static Abs = function () { gml_pragma("forceinline"); return new BBMOD_Vec3( abs(X), abs(Y), abs(Z) ); }; /// @func Add(_v) /// /// @desc Adds vectors and returns the result as a new vector. /// /// @param {Struct.BBMOD_Vec3} _v The other vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. static Add = function (_v) { gml_pragma("forceinline"); return new BBMOD_Vec3( X + _v.X, Y + _v.Y, Z + _v.Z ); }; /// @func Ceil() /// /// @desc Applies function `ceil` to each component of the vector and returns /// the result as a new vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// new BBMOD_Vec3(0.2, 1.6, 2.4).Ceil() // => BBMOD_Vec3(1.0, 2.0, 3.0) /// ``` static Ceil = function () { gml_pragma("forceinline"); return new BBMOD_Vec3( ceil(X), ceil(Y), ceil(Z) ); }; /// @func Clamp(_min, _max) /// /// @desc Clamps each component of the vector between corresponding /// components of `_min` and `_max` and returns the result as a new vector. /// /// @param {Struct.BBMOD_Vec3} _min A vector with minimum components. /// @param {Struct.BBMOD_Vec3} _max A vector with maximum components. /// /// @return {Struct.BBMOD_Vec3} The resulting vector. static Clamp = function (_min, _max) { gml_pragma("forceinline"); return new BBMOD_Vec3( clamp(X, _min.X, _max.X), clamp(Y, _min.Y, _max.Y), clamp(Z, _min.Z, _max.Z) ); }; /// @func ClampLength(_min, _max) /// /// @desc Clamps the length of the vector between `_min` and `_max` and /// returns the result as a new vector. /// /// @param {Real} _min The minimum length of the vector. /// @param {Real} _max The maximum length of the vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// // => BBMOD_Vec3(3.0, 0.0, 0.0): /// new BBMOD_Vec3(3.0, 0.0, 0.0).ClampLength(1.0, 5.0) /// // => BBMOD_Vec3(4.0, 0.0, 0.0): /// new BBMOD_Vec3(3.0, 0.0, 0.0).ClampLength(4.0, 5.0) /// // => BBMOD_Vec3(2.0, 0.0, 0.0): /// new BBMOD_Vec3(3.0, 0.0, 0.0).ClampLength(1.0, 2.0) /// ``` static ClampLength = function (_min, _max) { gml_pragma("forceinline"); var _length = sqrt( X * X + Y * Y + Z * Z ); var _newLength = clamp(_length, _min, _max); return new BBMOD_Vec3( (X / _length) * _newLength, (Y / _length) * _newLength, (Z / _length) * _newLength ); }; /// @func Clone() /// /// @desc Creates a clone of the vector. /// /// @return {Struct.BBMOD_Vec3} The creted vector. static Clone = function () { gml_pragma("forceinline"); return new BBMOD_Vec3( X, Y, Z ); }; /// @func Copy(_dest) /// /// @desc Copies components of the vector to the `_dest` vector. /// /// @param {Struct.BBMOD_Vec3} _dest The destination vector. /// /// @return {Struct.BBMOD_Vec3} Returns `self`. /// /// @example /// ```gml /// var _v1 = new BBMOD_Vec3(1.0, 2.0, 3.0); /// var _v2 = new BBMOD_Vec3(4.0, 5.0, 6.0); /// show_debug_message(_v2) // Prints { X: 4.0, Y: 5.0, Z: 6.0 } /// _v1.Copy(_v2); /// show_debug_message(_v2) // Prints { X: 1.0, Y: 2.0, Z: 3.0 } /// ``` static Copy = function (_dest) { gml_pragma("forceinline"); _dest.X = X; _dest.Y = Y; _dest.Z = Z; return self; }; /// @func Cross(_v) /// /// @desc Computes a cross product of this vector and vector `_v` and returns /// the result as a new vector. /// /// @param {Struct.BBMOD_Vec3} _v The other vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. static Cross = function (_v) { gml_pragma("forceinline"); return new BBMOD_Vec3( Y * _v.Z - Z * _v.Y, Z * _v.X - X * _v.Z, X * _v.Y - Y * _v.X ); }; /// @func Dot(_v) /// /// @desc Computes the dot product of this vector and vector `_v`. /// /// @param {Struct.BBMOD_Vec3} _v The other vector. /// /// @return {Real} The dot product of this vector and vector `_v`. static Dot = function (_v) { gml_pragma("forceinline"); return ( X * _v.X + Y * _v.Y + Z * _v.Z ); }; /// @func Equals(_v) /// /// @desc Checks whether this vectors equals to vector `_v`. /// /// @param {Struct.BBMOD_Vec3} _v The vector to compare to. /// /// @return {Bool} Returns `true` if the two vectors are equal. static Equals = function (_v) { gml_pragma("forceinline"); return ( X == _v.X && Y == _v.Y && Z == _v.Z ); }; /// @func Floor() /// /// @desc Applies function `floor` to each component of the vector and returns /// the result as a new vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// new BBMOD_Vec3(0.2, 1.6, 2.4).Floor() // => BBMOD_Vec3(0.0, 1.0, 2.0) /// ``` static Floor = function () { gml_pragma("forceinline"); return new BBMOD_Vec3( floor(X), floor(Y), floor(Z) ); }; /// @func Frac() /// /// @desc Applies function `frac` to each component of the vector and returns /// the result as a new vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// new BBMOD_Vec3(0.2, 1.6, 2.4).Frac() // => BBMOD_Vec3(0.2, 0.6, 0.4) /// ``` static Frac = function () { gml_pragma("forceinline"); return new BBMOD_Vec3( frac(X), frac(Y), frac(Z) ); }; /// @func FromArray(_array[, _index]) /// /// @desc Loads vector components from an array. /// /// @param {Array} _array The array to read the components from. /// @param {Real} [_index] The index to start reading the vector components /// from. Defaults to 0. /// /// @return {Struct.BBMOD_Vec3} Returns `self`. static FromArray = function (_array, _index=0) { gml_pragma("forceinline"); X = _array[_index]; Y = _array[_index + 1]; Z = _array[_index + 2]; return self; }; /// @func FromBarycentric(_v1, _v2, _v3, _f, _g) /// /// @desc Computes the vector components using a formula /// `_v1 + _f * (_v2 - _v1) + _g * (_v3 - _v1)`. /// /// @param {Struct.BBMOD_Vec3} _v1 The first point of a triangle. /// @param {Struct.BBMOD_Vec3} _v2 The second point of a triangle. /// @param {Struct.BBMOD_Vec3} _v3 The third point of a triangle. /// @param {Real} _f The weighting factor between `_v1` and `_v2`. /// @param {Real} _g The weighting factor between `_v1` and `_v3`. /// /// @return {Struct.BBMOD_Vec3} Returns `self`. static FromBarycentric = function (_v1, _v2, _v3, _f, _g) { gml_pragma("forceinline"); var _v1X = _v1.X; var _v1Y = _v1.Y; var _v1Z = _v1.Z; X = _v1X + _f * (_v2.X - _v1X) + _g * (_v3.X - _v1X); Y = _v1Y + _f * (_v2.Y - _v1Y) + _g * (_v3.Y - _v1Y); Z = _v1Z + _f * (_v2.Z - _v1Z) + _g * (_v3.Z - _v1Z); return self; }; /// @func FromBuffer(_buffer, _type) /// /// @desc Loads vector components from a buffer. /// /// @param {Id.Buffer} _buffer The buffer to read the components from. /// @param {Constant.BufferDataType} _type The type of each component. /// /// @return {Struct.BBMOD_Vec3} Returns `self`. static FromBuffer = function (_buffer, _type) { gml_pragma("forceinline"); X = buffer_read(_buffer, _type); Y = buffer_read(_buffer, _type); Z = buffer_read(_buffer, _type); return self; }; /// @func Length() /// /// @desc Computes the length of the vector. /// /// @return {Real} The length of the vector. static Length = function () { gml_pragma("forceinline"); return sqrt( X * X + Y * Y + Z * Z ); }; /// @func LengthSqr() /// /// @desc Computes a squared length of the vector. /// /// @return {Real} The squared length of the vector. static LengthSqr = function () { gml_pragma("forceinline"); return ( X * X + Y * Y + Z * Z ); }; /// @func Lerp(_v, _amount) /// /// @desc Linearly interpolates between vector `_v` by the given amount. /// /// @param {Struct.BBMOD_Vec3} _v The vector to interpolate with. /// @param {Real} _amount The interpolation factor. static Lerp = function (_v, _amount) { gml_pragma("forceinline"); return new BBMOD_Vec3( lerp(X, _v.X, _amount), lerp(Y, _v.Y, _amount), lerp(Z, _v.Z, _amount) ); }; /// @func MaxComponent() /// /// @desc Computes the greatest component of the vector. /// /// @return {Real} The greates component of the vector. static MaxComponent = function () { gml_pragma("forceinline"); return max( X, Y, Z, ); }; /// @func Maximize(_v) /// /// @desc Creates a new vector where each component is the maximum component /// from this vector and vector `_v`. /// /// @param {Struct.BBMOD_Vec3} _v The other vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// var _v1 = new BBMOD_Vec3(1.0, 4.0, 5.0); /// var _v2 = new BBMOD_Vec3(2.0, 3.0, 6.0); /// var _vMax = _v1.Maximize(_v2); // Equals to BBMOD_Vec3(2.0, 4.0, 6.0) /// ``` static Maximize = function (_v) { gml_pragma("forceinline"); return new BBMOD_Vec3( max(X, _v.X), max(Y, _v.Y), max(Z, _v.Z) ); }; /// @func MinComponent() /// /// @desc Computes the smallest component of the vector. /// /// @return {Real} The smallest component of the vector. static MinComponent = function () { gml_pragma("forceinline"); return min( X, Y, Z, ); }; /// @func Minimize(_v) /// /// @desc Creates a new vector where each component is the minimum component /// from this vector and vector `_v`. /// /// @param {Struct.BBMOD_Vec3} _v The other vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// var _v1 = new BBMOD_Vec3(1.0, 4.0, 5.0); /// var _v2 = new BBMOD_Vec3(2.0, 3.0, 6.0); /// var _vMin = _v1.Minimize(_v2); // Equals to BBMOD_Vec3(1.0, 3.0, 5.0) /// ``` static Minimize = function (_v) { gml_pragma("forceinline"); return new BBMOD_Vec3( min(X, _v.X), min(Y, _v.Y), min(Z, _v.Z) ); }; /// @func Mul(_v) /// /// @desc Multiplies the vector with vector `_v` and returns the result /// as a new vector. /// /// @param {Struct.BBMOD_Vec3} _v The other vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. static Mul = function (_v) { gml_pragma("forceinline"); return new BBMOD_Vec3( X * _v.X, Y * _v.Y, Z * _v.Z ); }; /// @func Normalize() /// /// @desc Normalizes the vector and returns the result as a new vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. static Normalize = function () { gml_pragma("forceinline"); var _lengthSqr = ( X * X + Y * Y + Z * Z ); if (_lengthSqr >= math_get_epsilon()) { var _n = 1.0 / sqrt(_lengthSqr); return new BBMOD_Vec3( X * _n, Y * _n, Z * _n ); } return new BBMOD_Vec3( X, Y, Z ); }; /// @func Orthonormalize(_v) /// /// @desc Orthonormalizes the vectors in-place using the Gram–Schmidt process. /// /// @param {Struct.BBMOD_Vec3} _v The other vector. /// /// @return {Bool} Returns `true` if the vectors were orthonormalized. static Orthonormalize = function (_v) { gml_pragma("forceinline"); var _v1 = Normalize(); var _proj = _v1.Scale(_v.Dot(_v1)); var _v2 = _v.Sub(_proj); if (_v2.Length() <= 0.0) { return false; } _v1.Copy(self); _v2.Normalize().Copy(_v); return true; }; /// @func Reflect(_v) /// /// @desc Reflects the vector from vector `_v` and returns the result /// as a new vector. /// /// @param {Struct.BBMOD_Vec3} _v The vector to reflect from. /// /// @return {Struct.BBMOD_Vec3} The created vector. static Reflect = function (_v) { gml_pragma("forceinline"); var _dot2 = ( X * _v.X + Y * _v.Y + Z * _v.Z ) * 2.0; return new BBMOD_Vec3( X - (_dot2 * _v.X), Y - (_dot2 * _v.Y), Z - (_dot2 * _v.Z) ); }; /// @func Round() /// /// @desc Applies function `round` to each component of the vector and returns /// the result as a new vector. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// new BBMOD_Vec3(0.2, 1.6, 2.4).Round() // => BBMOD_Vec3(0.0, 2.0, 2.0) /// ``` static Round = function () { gml_pragma("forceinline"); return new BBMOD_Vec3( round(X), round(Y), round(Z) ); }; /// @func Scale(_s) /// /// @desc Scales each component of the vector by `_s` and returns the result /// as a new vector. /// /// @param {Real} _s The value to scale the components by. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// new BBMOD_Vec3(1.0, 2.0, 3.0).Scale(2.0) // => BBMOD_Vec3(2.0, 4.0, 6.0) /// ``` static Scale = function (_s) { gml_pragma("forceinline") return new BBMOD_Vec3( X * _s, Y * _s, Z * _s ); }; /// @func Get(_index) /// /// @desc Retrieves vector component at given index (0 is X, 1 is Y, etc.). /// /// @param {Real} _index The index of the component. /// /// @return {Real} The value of the vector component at given index. /// /// @throws {BBMOD_OutOfRangeException} If an invalid index is passed. static Get = function (_index) { gml_pragma("forceinline"); switch (_index) { case 0: return X; case 1: return Y; case 2: return Z; } throw new BBMOD_OutOfRangeException(); }; /// @func Set([_x[, _y, _z]]) /// /// @desc Sets vector components in-place. /// /// @param {Real} [_x] The new value of the first component. Defaults to 0. /// @param {Real} [_y] The new value of the second component. Defaults to `_x`. /// @param {Real} [_z] The new value of the third component. Defaults to `_x`. /// /// @return {Struct.BBMOD_Vec3} Returns `self`. static Set = function (_x=0.0, _y=_x, _z=_x) { gml_pragma("forceinline"); X = _x; Y = _y; Z = _z; return self; }; /// @func SetIndex(_index, _value) /// /// @desc Sets vector component in-place. /// /// @param {Real} _index The index of the component, starting at 0. /// @param {Real} _value The new value of the component. /// /// @return {Struct.BBMOD_Vec3} Returns `self`. /// /// @throws {BBMOD_OutOfRangeException} If the given index is out of range /// of possible values. static SetIndex = function (_index, _value) { gml_pragma("forceinline"); switch (_index) { case 0: X = _value; break; case 1: Y = _value; break; case 2: Z = _value; break; default: throw new BBMOD_OutOfRangeException(); break; } return self; }; /// @func Sub(_v) /// /// @desc Subtracts vector `_v` from this vector and returns the result /// as a new vector. /// /// @param {Struct.BBMOD_Vec3} _v The vector to subtract from this one. /// /// @return {Struct.BBMOD_Vec3} The created vector. /// /// @example /// ```gml /// var _v1 = new BBMOD_Vec3(1.0, 2.0, 3.0); /// var _v2 = new BBMOD_Vec3(4.0, 5.0, 6.0); /// var _v3 = _v1.Sub(_v2); // Equals to BBMOD_Vec3(-3.0, -3.0, -3.0) /// ``` static Sub = function (_v) { gml_pragma("forceinline") return new BBMOD_Vec3( X - _v.X, Y - _v.Y, Z - _v.Z ); }; /// @func ToArray([_array[, _index]]) /// /// @desc Writes the components of the vector into the target array. /// /// @param {Array} [_array] The array to write to. If `undefined` a /// new one of required size is created. /// /// @param {Real} [_index] The starting index within the target array. /// Defaults to 0. /// /// @return {Array} The target array. static ToArray = function (_array=undefined, _index=0) { gml_pragma("forceinline"); _array ??= array_create(3, 0.0); _array[@ _index] = X; _array[@ _index + 1] = Y; _array[@ _index + 2] = Z; return _array; }; /// @func ToBuffer(_buffer, _type) /// /// @desc Writes the components of the vector into the buffer. /// /// @param {Id.Buffer} _buffer The buffer to write to. /// @param {Constant.BufferDataType} _type The type of the components. /// /// @return {Struct.BBMOD_Vec3} Returns `self`. static ToBuffer = function (_buffer, _type) { gml_pragma("forceinline"); buffer_write(_buffer, _type, X); buffer_write(_buffer, _type, Y); buffer_write(_buffer, _type, Z); return self; }; /// @func Transform(_matrix) /// /// @desc Transforms vector `(X, Y, Z, 1.0)` by a matrix and returns the result /// as a new vector. /// /// @param {Array} _matrix The matrix to transform the vector by. /// /// @return {Struct.BBMOD_Vec3} The created vector. static Transform = function (_matrix) { gml_pragma("forceinline") var _res = matrix_transform_vertex(_matrix, X, Y, Z); return new BBMOD_Vec3( _res[0], _res[1], _res[2] ); }; }