Skip to content
Permalink
4bad6d3267
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
7569 lines (6842 sloc) 281 KB
import { DeepImmutable, Nullable, FloatArray, float } from "../types";
import { ArrayTools } from "../Misc/arrayTools";
import { Scalar } from "./math.scalar";
/**
* Constant used to convert a value to gamma space
* @ignorenaming
*/
export const ToGammaSpace = 1 / 2.2;
/**
* Constant used to convert a value to linear space
* @ignorenaming
*/
export const ToLinearSpace = 2.2;
/**
* Constant used to define the minimal number value in Babylon.js
* @ignorenaming
*/
let Epsilon = 0.001;
export { Epsilon };
/**
* Class used to hold a RBG color
*/
export class Color3 {
/**
* Creates a new Color3 object from red, green, blue values, all between 0 and 1
* @param r defines the red component (between 0 and 1, default is 0)
* @param g defines the green component (between 0 and 1, default is 0)
* @param b defines the blue component (between 0 and 1, default is 0)
*/
constructor(
/**
* Defines the red component (between 0 and 1, default is 0)
*/
public r: number = 0,
/**
* Defines the green component (between 0 and 1, default is 0)
*/
public g: number = 0,
/**
* Defines the blue component (between 0 and 1, default is 0)
*/
public b: number = 0) {
}
/**
* Creates a string with the Color3 current values
* @returns the string representation of the Color3 object
*/
public toString(): string {
return "{R: " + this.r + " G:" + this.g + " B:" + this.b + "}";
}
/**
* Returns the string "Color3"
* @returns "Color3"
*/
public getClassName(): string {
return "Color3";
}
/**
* Compute the Color3 hash code
* @returns an unique number that can be used to hash Color3 objects
*/
public getHashCode(): number {
let hash = (this.r * 255) || 0;
hash = (hash * 397) ^ ((this.g * 255) || 0);
hash = (hash * 397) ^ ((this.b * 255) || 0);
return hash;
}
// Operators
/**
* Stores in the given array from the given starting index the red, green, blue values as successive elements
* @param array defines the array where to store the r,g,b components
* @param index defines an optional index in the target array to define where to start storing values
* @returns the current Color3 object
*/
public toArray(array: FloatArray, index: number = 0): Color3 {
array[index] = this.r;
array[index + 1] = this.g;
array[index + 2] = this.b;
return this;
}
/**
* Returns a new Color4 object from the current Color3 and the given alpha
* @param alpha defines the alpha component on the new Color4 object (default is 1)
* @returns a new Color4 object
*/
public toColor4(alpha: number = 1): Color4 {
return new Color4(this.r, this.g, this.b, alpha);
}
/**
* Returns a new array populated with 3 numeric elements : red, green and blue values
* @returns the new array
*/
public asArray(): number[] {
var result = new Array<number>();
this.toArray(result, 0);
return result;
}
/**
* Returns the luminance value
* @returns a float value
*/
public toLuminance(): number {
return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
}
/**
* Multiply each Color3 rgb values by the given Color3 rgb values in a new Color3 object
* @param otherColor defines the second operand
* @returns the new Color3 object
*/
public multiply(otherColor: DeepImmutable<Color3>): Color3 {
return new Color3(this.r * otherColor.r, this.g * otherColor.g, this.b * otherColor.b);
}
/**
* Multiply the rgb values of the Color3 and the given Color3 and stores the result in the object "result"
* @param otherColor defines the second operand
* @param result defines the Color3 object where to store the result
* @returns the current Color3
*/
public multiplyToRef(otherColor: DeepImmutable<Color3>, result: Color3): Color3 {
result.r = this.r * otherColor.r;
result.g = this.g * otherColor.g;
result.b = this.b * otherColor.b;
return this;
}
/**
* Determines equality between Color3 objects
* @param otherColor defines the second operand
* @returns true if the rgb values are equal to the given ones
*/
public equals(otherColor: DeepImmutable<Color3>): boolean {
return otherColor && this.r === otherColor.r && this.g === otherColor.g && this.b === otherColor.b;
}
/**
* Determines equality between the current Color3 object and a set of r,b,g values
* @param r defines the red component to check
* @param g defines the green component to check
* @param b defines the blue component to check
* @returns true if the rgb values are equal to the given ones
*/
public equalsFloats(r: number, g: number, b: number): boolean {
return this.r === r && this.g === g && this.b === b;
}
/**
* Multiplies in place each rgb value by scale
* @param scale defines the scaling factor
* @returns the updated Color3
*/
public scale(scale: number): Color3 {
return new Color3(this.r * scale, this.g * scale, this.b * scale);
}
/**
* Multiplies the rgb values by scale and stores the result into "result"
* @param scale defines the scaling factor
* @param result defines the Color3 object where to store the result
* @returns the unmodified current Color3
*/
public scaleToRef(scale: number, result: Color3): Color3 {
result.r = this.r * scale;
result.g = this.g * scale;
result.b = this.b * scale;
return this;
}
/**
* Scale the current Color3 values by a factor and add the result to a given Color3
* @param scale defines the scale factor
* @param result defines color to store the result into
* @returns the unmodified current Color3
*/
public scaleAndAddToRef(scale: number, result: Color3): Color3 {
result.r += this.r * scale;
result.g += this.g * scale;
result.b += this.b * scale;
return this;
}
/**
* Clamps the rgb values by the min and max values and stores the result into "result"
* @param min defines minimum clamping value (default is 0)
* @param max defines maximum clamping value (default is 1)
* @param result defines color to store the result into
* @returns the original Color3
*/
public clampToRef(min: number = 0, max: number = 1, result: Color3): Color3 {
result.r = Scalar.Clamp(this.r, min, max);
result.g = Scalar.Clamp(this.g, min, max);
result.b = Scalar.Clamp(this.b, min, max);
return this;
}
/**
* Creates a new Color3 set with the added values of the current Color3 and of the given one
* @param otherColor defines the second operand
* @returns the new Color3
*/
public add(otherColor: DeepImmutable<Color3>): Color3 {
return new Color3(this.r + otherColor.r, this.g + otherColor.g, this.b + otherColor.b);
}
/**
* Stores the result of the addition of the current Color3 and given one rgb values into "result"
* @param otherColor defines the second operand
* @param result defines Color3 object to store the result into
* @returns the unmodified current Color3
*/
public addToRef(otherColor: DeepImmutable<Color3>, result: Color3): Color3 {
result.r = this.r + otherColor.r;
result.g = this.g + otherColor.g;
result.b = this.b + otherColor.b;
return this;
}
/**
* Returns a new Color3 set with the subtracted values of the given one from the current Color3
* @param otherColor defines the second operand
* @returns the new Color3
*/
public subtract(otherColor: DeepImmutable<Color3>): Color3 {
return new Color3(this.r - otherColor.r, this.g - otherColor.g, this.b - otherColor.b);
}
/**
* Stores the result of the subtraction of given one from the current Color3 rgb values into "result"
* @param otherColor defines the second operand
* @param result defines Color3 object to store the result into
* @returns the unmodified current Color3
*/
public subtractToRef(otherColor: DeepImmutable<Color3>, result: Color3): Color3 {
result.r = this.r - otherColor.r;
result.g = this.g - otherColor.g;
result.b = this.b - otherColor.b;
return this;
}
/**
* Copy the current object
* @returns a new Color3 copied the current one
*/
public clone(): Color3 {
return new Color3(this.r, this.g, this.b);
}
/**
* Copies the rgb values from the source in the current Color3
* @param source defines the source Color3 object
* @returns the updated Color3 object
*/
public copyFrom(source: DeepImmutable<Color3>): Color3 {
this.r = source.r;
this.g = source.g;
this.b = source.b;
return this;
}
/**
* Updates the Color3 rgb values from the given floats
* @param r defines the red component to read from
* @param g defines the green component to read from
* @param b defines the blue component to read from
* @returns the current Color3 object
*/
public copyFromFloats(r: number, g: number, b: number): Color3 {
this.r = r;
this.g = g;
this.b = b;
return this;
}
/**
* Updates the Color3 rgb values from the given floats
* @param r defines the red component to read from
* @param g defines the green component to read from
* @param b defines the blue component to read from
* @returns the current Color3 object
*/
public set(r: number, g: number, b: number): Color3 {
return this.copyFromFloats(r, g, b);
}
/**
* Compute the Color3 hexadecimal code as a string
* @returns a string containing the hexadecimal representation of the Color3 object
*/
public toHexString(): string {
var intR = (this.r * 255) | 0;
var intG = (this.g * 255) | 0;
var intB = (this.b * 255) | 0;
return "#" + Scalar.ToHex(intR) + Scalar.ToHex(intG) + Scalar.ToHex(intB);
}
/**
* Computes a new Color3 converted from the current one to linear space
* @returns a new Color3 object
*/
public toLinearSpace(): Color3 {
var convertedColor = new Color3();
this.toLinearSpaceToRef(convertedColor);
return convertedColor;
}
/**
* Converts current color in rgb space to HSV values
* @returns a new color3 representing the HSV values
*/
public toHSV(): Color3 {
let result = new Color3();
this.toHSVToRef(result);
return result;
}
/**
* Converts current color in rgb space to HSV values
* @param result defines the Color3 where to store the HSV values
*/
public toHSVToRef(result: Color3) {
var r = this.r;
var g = this.g;
var b = this.b;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var h = 0;
var s = 0;
var v = max;
var dm = max - min;
if (max !== 0) {
s = dm / max;
}
if (max != min) {
if (max == r) {
h = (g - b) / dm;
if (g < b) {
h += 6;
}
} else if (max == g) {
h = (b - r) / dm + 2;
} else if (max == b) {
h = (r - g) / dm + 4;
}
h *= 60;
}
result.r = h;
result.g = s;
result.b = v;
}
/**
* Converts the Color3 values to linear space and stores the result in "convertedColor"
* @param convertedColor defines the Color3 object where to store the linear space version
* @returns the unmodified Color3
*/
public toLinearSpaceToRef(convertedColor: Color3): Color3 {
convertedColor.r = Math.pow(this.r, ToLinearSpace);
convertedColor.g = Math.pow(this.g, ToLinearSpace);
convertedColor.b = Math.pow(this.b, ToLinearSpace);
return this;
}
/**
* Computes a new Color3 converted from the current one to gamma space
* @returns a new Color3 object
*/
public toGammaSpace(): Color3 {
var convertedColor = new Color3();
this.toGammaSpaceToRef(convertedColor);
return convertedColor;
}
/**
* Converts the Color3 values to gamma space and stores the result in "convertedColor"
* @param convertedColor defines the Color3 object where to store the gamma space version
* @returns the unmodified Color3
*/
public toGammaSpaceToRef(convertedColor: Color3): Color3 {
convertedColor.r = Math.pow(this.r, ToGammaSpace);
convertedColor.g = Math.pow(this.g, ToGammaSpace);
convertedColor.b = Math.pow(this.b, ToGammaSpace);
return this;
}
// Statics
private static _BlackReadOnly = Color3.Black() as DeepImmutable<Color3>;
/**
* Convert Hue, saturation and value to a Color3 (RGB)
* @param hue defines the hue
* @param saturation defines the saturation
* @param value defines the value
* @param result defines the Color3 where to store the RGB values
*/
public static HSVtoRGBToRef(hue: number, saturation: number, value: number, result: Color3) {
var chroma = value * saturation;
var h = hue / 60;
var x = chroma * (1 - Math.abs((h % 2) - 1));
var r = 0;
var g = 0;
var b = 0;
if (h >= 0 && h <= 1) {
r = chroma;
g = x;
} else if (h >= 1 && h <= 2) {
r = x;
g = chroma;
} else if (h >= 2 && h <= 3) {
g = chroma;
b = x;
} else if (h >= 3 && h <= 4) {
g = x;
b = chroma;
} else if (h >= 4 && h <= 5) {
r = x;
b = chroma;
} else if (h >= 5 && h <= 6) {
r = chroma;
b = x;
}
var m = value - chroma;
result.set((r + m), (g + m), (b + m));
}
/**
* Creates a new Color3 from the string containing valid hexadecimal values
* @param hex defines a string containing valid hexadecimal values
* @returns a new Color3 object
*/
public static FromHexString(hex: string): Color3 {
if (hex.substring(0, 1) !== "#" || hex.length !== 7) {
return new Color3(0, 0, 0);
}
var r = parseInt(hex.substring(1, 3), 16);
var g = parseInt(hex.substring(3, 5), 16);
var b = parseInt(hex.substring(5, 7), 16);
return Color3.FromInts(r, g, b);
}
/**
* Creates a new Color3 from the starting index of the given array
* @param array defines the source array
* @param offset defines an offset in the source array
* @returns a new Color3 object
*/
public static FromArray(array: DeepImmutable<ArrayLike<number>>, offset: number = 0): Color3 {
return new Color3(array[offset], array[offset + 1], array[offset + 2]);
}
/**
* Creates a new Color3 from integer values (< 256)
* @param r defines the red component to read from (value between 0 and 255)
* @param g defines the green component to read from (value between 0 and 255)
* @param b defines the blue component to read from (value between 0 and 255)
* @returns a new Color3 object
*/
public static FromInts(r: number, g: number, b: number): Color3 {
return new Color3(r / 255.0, g / 255.0, b / 255.0);
}
/**
* Creates a new Color3 with values linearly interpolated of "amount" between the start Color3 and the end Color3
* @param start defines the start Color3 value
* @param end defines the end Color3 value
* @param amount defines the gradient value between start and end
* @returns a new Color3 object
*/
public static Lerp(start: DeepImmutable<Color3>, end: DeepImmutable<Color3>, amount: number): Color3 {
var result = new Color3(0.0, 0.0, 0.0);
Color3.LerpToRef(start, end, amount, result);
return result;
}
/**
* Creates a new Color3 with values linearly interpolated of "amount" between the start Color3 and the end Color3
* @param left defines the start value
* @param right defines the end value
* @param amount defines the gradient factor
* @param result defines the Color3 object where to store the result
*/
public static LerpToRef(left: DeepImmutable<Color3>, right: DeepImmutable<Color3>, amount: number, result: Color3): void {
result.r = left.r + ((right.r - left.r) * amount);
result.g = left.g + ((right.g - left.g) * amount);
result.b = left.b + ((right.b - left.b) * amount);
}
/**
* Returns a Color3 value containing a red color
* @returns a new Color3 object
*/
public static Red(): Color3 { return new Color3(1, 0, 0); }
/**
* Returns a Color3 value containing a green color
* @returns a new Color3 object
*/
public static Green(): Color3 { return new Color3(0, 1, 0); }
/**
* Returns a Color3 value containing a blue color
* @returns a new Color3 object
*/
public static Blue(): Color3 { return new Color3(0, 0, 1); }
/**
* Returns a Color3 value containing a black color
* @returns a new Color3 object
*/
public static Black(): Color3 { return new Color3(0, 0, 0); }
/**
* Gets a Color3 value containing a black color that must not be updated
*/
public static get BlackReadOnly(): DeepImmutable<Color3> {
return Color3._BlackReadOnly;
}
/**
* Returns a Color3 value containing a white color
* @returns a new Color3 object
*/
public static White(): Color3 { return new Color3(1, 1, 1); }
/**
* Returns a Color3 value containing a purple color
* @returns a new Color3 object
*/
public static Purple(): Color3 { return new Color3(0.5, 0, 0.5); }
/**
* Returns a Color3 value containing a magenta color
* @returns a new Color3 object
*/
public static Magenta(): Color3 { return new Color3(1, 0, 1); }
/**
* Returns a Color3 value containing a yellow color
* @returns a new Color3 object
*/
public static Yellow(): Color3 { return new Color3(1, 1, 0); }
/**
* Returns a Color3 value containing a gray color
* @returns a new Color3 object
*/
public static Gray(): Color3 { return new Color3(0.5, 0.5, 0.5); }
/**
* Returns a Color3 value containing a teal color
* @returns a new Color3 object
*/
public static Teal(): Color3 { return new Color3(0, 1.0, 1.0); }
/**
* Returns a Color3 value containing a random color
* @returns a new Color3 object
*/
public static Random(): Color3 { return new Color3(Math.random(), Math.random(), Math.random()); }
}
/**
* Class used to hold a RBGA color
*/
export class Color4 {
/**
* Creates a new Color4 object from red, green, blue values, all between 0 and 1
* @param r defines the red component (between 0 and 1, default is 0)
* @param g defines the green component (between 0 and 1, default is 0)
* @param b defines the blue component (between 0 and 1, default is 0)
* @param a defines the alpha component (between 0 and 1, default is 1)
*/
constructor(
/**
* Defines the red component (between 0 and 1, default is 0)
*/
public r: number = 0,
/**
* Defines the green component (between 0 and 1, default is 0)
*/
public g: number = 0,
/**
* Defines the blue component (between 0 and 1, default is 0)
*/
public b: number = 0,
/**
* Defines the alpha component (between 0 and 1, default is 1)
*/
public a: number = 1) {
}
// Operators
/**
* Adds in place the given Color4 values to the current Color4 object
* @param right defines the second operand
* @returns the current updated Color4 object
*/
public addInPlace(right: DeepImmutable<Color4>): Color4 {
this.r += right.r;
this.g += right.g;
this.b += right.b;
this.a += right.a;
return this;
}
/**
* Creates a new array populated with 4 numeric elements : red, green, blue, alpha values
* @returns the new array
*/
public asArray(): number[] {
var result = new Array<number>();
this.toArray(result, 0);
return result;
}
/**
* Stores from the starting index in the given array the Color4 successive values
* @param array defines the array where to store the r,g,b components
* @param index defines an optional index in the target array to define where to start storing values
* @returns the current Color4 object
*/
public toArray(array: number[], index: number = 0): Color4 {
array[index] = this.r;
array[index + 1] = this.g;
array[index + 2] = this.b;
array[index + 3] = this.a;
return this;
}
/**
* Determines equality between Color4 objects
* @param otherColor defines the second operand
* @returns true if the rgba values are equal to the given ones
*/
public equals(otherColor: DeepImmutable<Color4>): boolean {
return otherColor && this.r === otherColor.r && this.g === otherColor.g && this.b === otherColor.b && this.a === otherColor.a;
}
/**
* Creates a new Color4 set with the added values of the current Color4 and of the given one
* @param right defines the second operand
* @returns a new Color4 object
*/
public add(right: DeepImmutable<Color4>): Color4 {
return new Color4(this.r + right.r, this.g + right.g, this.b + right.b, this.a + right.a);
}
/**
* Creates a new Color4 set with the subtracted values of the given one from the current Color4
* @param right defines the second operand
* @returns a new Color4 object
*/
public subtract(right: DeepImmutable<Color4>): Color4 {
return new Color4(this.r - right.r, this.g - right.g, this.b - right.b, this.a - right.a);
}
/**
* Subtracts the given ones from the current Color4 values and stores the results in "result"
* @param right defines the second operand
* @param result defines the Color4 object where to store the result
* @returns the current Color4 object
*/
public subtractToRef(right: DeepImmutable<Color4>, result: Color4): Color4 {
result.r = this.r - right.r;
result.g = this.g - right.g;
result.b = this.b - right.b;
result.a = this.a - right.a;
return this;
}
/**
* Creates a new Color4 with the current Color4 values multiplied by scale
* @param scale defines the scaling factor to apply
* @returns a new Color4 object
*/
public scale(scale: number): Color4 {
return new Color4(this.r * scale, this.g * scale, this.b * scale, this.a * scale);
}
/**
* Multiplies the current Color4 values by scale and stores the result in "result"
* @param scale defines the scaling factor to apply
* @param result defines the Color4 object where to store the result
* @returns the current unmodified Color4
*/
public scaleToRef(scale: number, result: Color4): Color4 {
result.r = this.r * scale;
result.g = this.g * scale;
result.b = this.b * scale;
result.a = this.a * scale;
return this;
}
/**
* Scale the current Color4 values by a factor and add the result to a given Color4
* @param scale defines the scale factor
* @param result defines the Color4 object where to store the result
* @returns the unmodified current Color4
*/
public scaleAndAddToRef(scale: number, result: Color4): Color4 {
result.r += this.r * scale;
result.g += this.g * scale;
result.b += this.b * scale;
result.a += this.a * scale;
return this;
}
/**
* Clamps the rgb values by the min and max values and stores the result into "result"
* @param min defines minimum clamping value (default is 0)
* @param max defines maximum clamping value (default is 1)
* @param result defines color to store the result into.
* @returns the cuurent Color4
*/
public clampToRef(min: number = 0, max: number = 1, result: Color4): Color4 {
result.r = Scalar.Clamp(this.r, min, max);
result.g = Scalar.Clamp(this.g, min, max);
result.b = Scalar.Clamp(this.b, min, max);
result.a = Scalar.Clamp(this.a, min, max);
return this;
}
/**
* Multipy an Color4 value by another and return a new Color4 object
* @param color defines the Color4 value to multiply by
* @returns a new Color4 object
*/
public multiply(color: Color4): Color4 {
return new Color4(this.r * color.r, this.g * color.g, this.b * color.b, this.a * color.a);
}
/**
* Multipy a Color4 value by another and push the result in a reference value
* @param color defines the Color4 value to multiply by
* @param result defines the Color4 to fill the result in
* @returns the result Color4
*/
public multiplyToRef(color: Color4, result: Color4): Color4 {
result.r = this.r * color.r;
result.g = this.g * color.g;
result.b = this.b * color.b;
result.a = this.a * color.a;
return result;
}
/**
* Creates a string with the Color4 current values
* @returns the string representation of the Color4 object
*/
public toString(): string {
return "{R: " + this.r + " G:" + this.g + " B:" + this.b + " A:" + this.a + "}";
}
/**
* Returns the string "Color4"
* @returns "Color4"
*/
public getClassName(): string {
return "Color4";
}
/**
* Compute the Color4 hash code
* @returns an unique number that can be used to hash Color4 objects
*/
public getHashCode(): number {
let hash = (this.r * 255) || 0;
hash = (hash * 397) ^ ((this.g * 255) || 0);
hash = (hash * 397) ^ ((this.b * 255) || 0);
hash = (hash * 397) ^ ((this.a * 255) || 0);
return hash;
}
/**
* Creates a new Color4 copied from the current one
* @returns a new Color4 object
*/
public clone(): Color4 {
return new Color4(this.r, this.g, this.b, this.a);
}
/**
* Copies the given Color4 values into the current one
* @param source defines the source Color4 object
* @returns the current updated Color4 object
*/
public copyFrom(source: Color4): Color4 {
this.r = source.r;
this.g = source.g;
this.b = source.b;
this.a = source.a;
return this;
}
/**
* Copies the given float values into the current one
* @param r defines the red component to read from
* @param g defines the green component to read from
* @param b defines the blue component to read from
* @param a defines the alpha component to read from
* @returns the current updated Color4 object
*/
public copyFromFloats(r: number, g: number, b: number, a: number): Color4 {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
return this;
}
/**
* Copies the given float values into the current one
* @param r defines the red component to read from
* @param g defines the green component to read from
* @param b defines the blue component to read from
* @param a defines the alpha component to read from
* @returns the current updated Color4 object
*/
public set(r: number, g: number, b: number, a: number): Color4 {
return this.copyFromFloats(r, g, b, a);
}
/**
* Compute the Color4 hexadecimal code as a string
* @returns a string containing the hexadecimal representation of the Color4 object
*/
public toHexString(): string {
var intR = (this.r * 255) | 0;
var intG = (this.g * 255) | 0;
var intB = (this.b * 255) | 0;
var intA = (this.a * 255) | 0;
return "#" + Scalar.ToHex(intR) + Scalar.ToHex(intG) + Scalar.ToHex(intB) + Scalar.ToHex(intA);
}
/**
* Computes a new Color4 converted from the current one to linear space
* @returns a new Color4 object
*/
public toLinearSpace(): Color4 {
var convertedColor = new Color4();
this.toLinearSpaceToRef(convertedColor);
return convertedColor;
}
/**
* Converts the Color4 values to linear space and stores the result in "convertedColor"
* @param convertedColor defines the Color4 object where to store the linear space version
* @returns the unmodified Color4
*/
public toLinearSpaceToRef(convertedColor: Color4): Color4 {
convertedColor.r = Math.pow(this.r, ToLinearSpace);
convertedColor.g = Math.pow(this.g, ToLinearSpace);
convertedColor.b = Math.pow(this.b, ToLinearSpace);
convertedColor.a = this.a;
return this;
}
/**
* Computes a new Color4 converted from the current one to gamma space
* @returns a new Color4 object
*/
public toGammaSpace(): Color4 {
var convertedColor = new Color4();
this.toGammaSpaceToRef(convertedColor);
return convertedColor;
}
/**
* Converts the Color4 values to gamma space and stores the result in "convertedColor"
* @param convertedColor defines the Color4 object where to store the gamma space version
* @returns the unmodified Color4
*/
public toGammaSpaceToRef(convertedColor: Color4): Color4 {
convertedColor.r = Math.pow(this.r, ToGammaSpace);
convertedColor.g = Math.pow(this.g, ToGammaSpace);
convertedColor.b = Math.pow(this.b, ToGammaSpace);
convertedColor.a = this.a;
return this;
}
// Statics
/**
* Creates a new Color4 from the string containing valid hexadecimal values
* @param hex defines a string containing valid hexadecimal values
* @returns a new Color4 object
*/
public static FromHexString(hex: string): Color4 {
if (hex.substring(0, 1) !== "#" || hex.length !== 9) {
return new Color4(0.0, 0.0, 0.0, 0.0);
}
var r = parseInt(hex.substring(1, 3), 16);
var g = parseInt(hex.substring(3, 5), 16);
var b = parseInt(hex.substring(5, 7), 16);
var a = parseInt(hex.substring(7, 9), 16);
return Color4.FromInts(r, g, b, a);
}
/**
* Creates a new Color4 object set with the linearly interpolated values of "amount" between the left Color4 object and the right Color4 object
* @param left defines the start value
* @param right defines the end value
* @param amount defines the gradient factor
* @returns a new Color4 object
*/
public static Lerp(left: DeepImmutable<Color4>, right: DeepImmutable<Color4>, amount: number): Color4 {
var result = new Color4(0.0, 0.0, 0.0, 0.0);
Color4.LerpToRef(left, right, amount, result);
return result;
}
/**
* Set the given "result" with the linearly interpolated values of "amount" between the left Color4 object and the right Color4 object
* @param left defines the start value
* @param right defines the end value
* @param amount defines the gradient factor
* @param result defines the Color4 object where to store data
*/
public static LerpToRef(left: DeepImmutable<Color4>, right: DeepImmutable<Color4>, amount: number, result: Color4): void {
result.r = left.r + (right.r - left.r) * amount;
result.g = left.g + (right.g - left.g) * amount;
result.b = left.b + (right.b - left.b) * amount;
result.a = left.a + (right.a - left.a) * amount;
}
/**
* Creates a new Color4 from a Color3 and an alpha value
* @param color3 defines the source Color3 to read from
* @param alpha defines the alpha component (1.0 by default)
* @returns a new Color4 object
*/
public static FromColor3(color3: DeepImmutable<Color3>, alpha: number = 1.0): Color4 {
return new Color4(color3.r, color3.g, color3.b, alpha);
}
/**
* Creates a new Color4 from the starting index element of the given array
* @param array defines the source array to read from
* @param offset defines the offset in the source array
* @returns a new Color4 object
*/
public static FromArray(array: DeepImmutable<ArrayLike<number>>, offset: number = 0): Color4 {
return new Color4(array[offset], array[offset + 1], array[offset + 2], array[offset + 3]);
}
/**
* Creates a new Color3 from integer values (< 256)
* @param r defines the red component to read from (value between 0 and 255)
* @param g defines the green component to read from (value between 0 and 255)
* @param b defines the blue component to read from (value between 0 and 255)
* @param a defines the alpha component to read from (value between 0 and 255)
* @returns a new Color3 object
*/
public static FromInts(r: number, g: number, b: number, a: number): Color4 {
return new Color4(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
}
/**
* Check the content of a given array and convert it to an array containing RGBA data
* If the original array was already containing count * 4 values then it is returned directly
* @param colors defines the array to check
* @param count defines the number of RGBA data to expect
* @returns an array containing count * 4 values (RGBA)
*/
public static CheckColors4(colors: number[], count: number): number[] {
// Check if color3 was used
if (colors.length === count * 3) {
var colors4 = [];
for (var index = 0; index < colors.length; index += 3) {
var newIndex = (index / 3) * 4;
colors4[newIndex] = colors[index];
colors4[newIndex + 1] = colors[index + 1];
colors4[newIndex + 2] = colors[index + 2];
colors4[newIndex + 3] = 1.0;
}
return colors4;
}
return colors;
}
}
/**
* Class representing a vector containing 2 coordinates
*/
export class Vector2 {
/**
* Creates a new Vector2 from the given x and y coordinates
* @param x defines the first coordinate
* @param y defines the second coordinate
*/
constructor(
/** defines the first coordinate */
public x: number = 0,
/** defines the second coordinate */
public y: number = 0) {
}
/**
* Gets a string with the Vector2 coordinates
* @returns a string with the Vector2 coordinates
*/
public toString(): string {
return "{X: " + this.x + " Y:" + this.y + "}";
}
/**
* Gets class name
* @returns the string "Vector2"
*/
public getClassName(): string {
return "Vector2";
}
/**
* Gets current vector hash code
* @returns the Vector2 hash code as a number
*/
public getHashCode(): number {
let hash = this.x || 0;
hash = (hash * 397) ^ (this.y || 0);
return hash;
}
// Operators
/**
* Sets the Vector2 coordinates in the given array or Float32Array from the given index.
* @param array defines the source array
* @param index defines the offset in source array
* @returns the current Vector2
*/
public toArray(array: FloatArray, index: number = 0): Vector2 {
array[index] = this.x;
array[index + 1] = this.y;
return this;
}
/**
* Copy the current vector to an array
* @returns a new array with 2 elements: the Vector2 coordinates.
*/
public asArray(): number[] {
var result = new Array<number>();
this.toArray(result, 0);
return result;
}
/**
* Sets the Vector2 coordinates with the given Vector2 coordinates
* @param source defines the source Vector2
* @returns the current updated Vector2
*/
public copyFrom(source: DeepImmutable<Vector2>): Vector2 {
this.x = source.x;
this.y = source.y;
return this;
}
/**
* Sets the Vector2 coordinates with the given floats
* @param x defines the first coordinate
* @param y defines the second coordinate
* @returns the current updated Vector2
*/
public copyFromFloats(x: number, y: number): Vector2 {
this.x = x;
this.y = y;
return this;
}
/**
* Sets the Vector2 coordinates with the given floats
* @param x defines the first coordinate
* @param y defines the second coordinate
* @returns the current updated Vector2
*/
public set(x: number, y: number): Vector2 {
return this.copyFromFloats(x, y);
}
/**
* Add another vector with the current one
* @param otherVector defines the other vector
* @returns a new Vector2 set with the addition of the current Vector2 and the given one coordinates
*/
public add(otherVector: DeepImmutable<Vector2>): Vector2 {
return new Vector2(this.x + otherVector.x, this.y + otherVector.y);
}
/**
* Sets the "result" coordinates with the addition of the current Vector2 and the given one coordinates
* @param otherVector defines the other vector
* @param result defines the target vector
* @returns the unmodified current Vector2
*/
public addToRef(otherVector: DeepImmutable<Vector2>, result: Vector2): Vector2 {
result.x = this.x + otherVector.x;
result.y = this.y + otherVector.y;
return this;
}
/**
* Set the Vector2 coordinates by adding the given Vector2 coordinates
* @param otherVector defines the other vector
* @returns the current updated Vector2
*/
public addInPlace(otherVector: DeepImmutable<Vector2>): Vector2 {
this.x += otherVector.x;
this.y += otherVector.y;
return this;
}
/**
* Gets a new Vector2 by adding the current Vector2 coordinates to the given Vector3 x, y coordinates
* @param otherVector defines the other vector
* @returns a new Vector2
*/
public addVector3(otherVector: Vector3): Vector2 {
return new Vector2(this.x + otherVector.x, this.y + otherVector.y);
}
/**
* Gets a new Vector2 set with the subtracted coordinates of the given one from the current Vector2
* @param otherVector defines the other vector
* @returns a new Vector2
*/
public subtract(otherVector: Vector2): Vector2 {
return new Vector2(this.x - otherVector.x, this.y - otherVector.y);
}
/**
* Sets the "result" coordinates with the subtraction of the given one from the current Vector2 coordinates.
* @param otherVector defines the other vector
* @param result defines the target vector
* @returns the unmodified current Vector2
*/
public subtractToRef(otherVector: DeepImmutable<Vector2>, result: Vector2): Vector2 {
result.x = this.x - otherVector.x;
result.y = this.y - otherVector.y;
return this;
}
/**
* Sets the current Vector2 coordinates by subtracting from it the given one coordinates
* @param otherVector defines the other vector
* @returns the current updated Vector2
*/
public subtractInPlace(otherVector: DeepImmutable<Vector2>): Vector2 {
this.x -= otherVector.x;
this.y -= otherVector.y;
return this;
}
/**
* Multiplies in place the current Vector2 coordinates by the given ones
* @param otherVector defines the other vector
* @returns the current updated Vector2
*/
public multiplyInPlace(otherVector: DeepImmutable<Vector2>): Vector2 {
this.x *= otherVector.x;
this.y *= otherVector.y;
return this;
}
/**
* Returns a new Vector2 set with the multiplication of the current Vector2 and the given one coordinates
* @param otherVector defines the other vector
* @returns a new Vector2
*/
public multiply(otherVector: DeepImmutable<Vector2>): Vector2 {
return new Vector2(this.x * otherVector.x, this.y * otherVector.y);
}
/**
* Sets "result" coordinates with the multiplication of the current Vector2 and the given one coordinates
* @param otherVector defines the other vector
* @param result defines the target vector
* @returns the unmodified current Vector2
*/
public multiplyToRef(otherVector: DeepImmutable<Vector2>, result: Vector2): Vector2 {
result.x = this.x * otherVector.x;
result.y = this.y * otherVector.y;
return this;
}
/**
* Gets a new Vector2 set with the Vector2 coordinates multiplied by the given floats
* @param x defines the first coordinate
* @param y defines the second coordinate
* @returns a new Vector2
*/
public multiplyByFloats(x: number, y: number): Vector2 {
return new Vector2(this.x * x, this.y * y);
}
/**
* Returns a new Vector2 set with the Vector2 coordinates divided by the given one coordinates
* @param otherVector defines the other vector
* @returns a new Vector2
*/
public divide(otherVector: Vector2): Vector2 {
return new Vector2(this.x / otherVector.x, this.y / otherVector.y);
}
/**
* Sets the "result" coordinates with the Vector2 divided by the given one coordinates
* @param otherVector defines the other vector
* @param result defines the target vector
* @returns the unmodified current Vector2
*/
public divideToRef(otherVector: DeepImmutable<Vector2>, result: Vector2): Vector2 {
result.x = this.x / otherVector.x;
result.y = this.y / otherVector.y;
return this;
}
/**
* Divides the current Vector2 coordinates by the given ones
* @param otherVector defines the other vector
* @returns the current updated Vector2
*/
public divideInPlace(otherVector: DeepImmutable<Vector2>): Vector2 {
return this.divideToRef(otherVector, this);
}
/**
* Gets a new Vector2 with current Vector2 negated coordinates
* @returns a new Vector2
*/
public negate(): Vector2 {
return new Vector2(-this.x, -this.y);
}
/**
* Multiply the Vector2 coordinates by scale
* @param scale defines the scaling factor
* @returns the current updated Vector2
*/
public scaleInPlace(scale: number): Vector2 {
this.x *= scale;
this.y *= scale;
return this;
}
/**
* Returns a new Vector2 scaled by "scale" from the current Vector2
* @param scale defines the scaling factor
* @returns a new Vector2
*/
public scale(scale: number): Vector2 {
let result = new Vector2(0, 0);
this.scaleToRef(scale, result);
return result;
}
/**
* Scale the current Vector2 values by a factor to a given Vector2
* @param scale defines the scale factor
* @param result defines the Vector2 object where to store the result
* @returns the unmodified current Vector2
*/
public scaleToRef(scale: number, result: Vector2): Vector2 {
result.x = this.x * scale;
result.y = this.y * scale;
return this;
}
/**
* Scale the current Vector2 values by a factor and add the result to a given Vector2
* @param scale defines the scale factor
* @param result defines the Vector2 object where to store the result
* @returns the unmodified current Vector2
*/
public scaleAndAddToRef(scale: number, result: Vector2): Vector2 {
result.x += this.x * scale;
result.y += this.y * scale;
return this;
}
/**
* Gets a boolean if two vectors are equals
* @param otherVector defines the other vector
* @returns true if the given vector coordinates strictly equal the current Vector2 ones
*/
public equals(otherVector: DeepImmutable<Vector2>): boolean {
return otherVector && this.x === otherVector.x && this.y === otherVector.y;
}
/**
* Gets a boolean if two vectors are equals (using an epsilon value)
* @param otherVector defines the other vector
* @param epsilon defines the minimal distance to consider equality
* @returns true if the given vector coordinates are close to the current ones by a distance of epsilon.
*/
public equalsWithEpsilon(otherVector: DeepImmutable<Vector2>, epsilon: number = Epsilon): boolean {
return otherVector && Scalar.WithinEpsilon(this.x, otherVector.x, epsilon) && Scalar.WithinEpsilon(this.y, otherVector.y, epsilon);
}
/**
* Gets a new Vector2 from current Vector2 floored values
* @returns a new Vector2
*/
public floor(): Vector2 {
return new Vector2(Math.floor(this.x), Math.floor(this.y));
}
/**
* Gets a new Vector2 from current Vector2 floored values
* @returns a new Vector2
*/
public fract(): Vector2 {
return new Vector2(this.x - Math.floor(this.x), this.y - Math.floor(this.y));
}
// Properties
/**
* Gets the length of the vector
* @returns the vector length (float)
*/
public length(): number {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
/**
* Gets the vector squared length
* @returns the vector squared length (float)
*/
public lengthSquared(): number {
return (this.x * this.x + this.y * this.y);
}
// Methods
/**
* Normalize the vector
* @returns the current updated Vector2
*/
public normalize(): Vector2 {
var len = this.length();
if (len === 0) {
return this;
}
var num = 1.0 / len;
this.x *= num;
this.y *= num;
return this;
}
/**
* Gets a new Vector2 copied from the Vector2
* @returns a new Vector2
*/
public clone(): Vector2 {
return new Vector2(this.x, this.y);
}
// Statics
/**
* Gets a new Vector2(0, 0)
* @returns a new Vector2
*/
public static Zero(): Vector2 {
return new Vector2(0, 0);
}
/**
* Gets a new Vector2(1, 1)
* @returns a new Vector2
*/
public static One(): Vector2 {
return new Vector2(1, 1);
}
/**
* Gets a new Vector2 set from the given index element of the given array
* @param array defines the data source
* @param offset defines the offset in the data source
* @returns a new Vector2
*/
public static FromArray(array: DeepImmutable<ArrayLike<number>>, offset: number = 0): Vector2 {
return new Vector2(array[offset], array[offset + 1]);
}
/**
* Sets "result" from the given index element of the given array
* @param array defines the data source
* @param offset defines the offset in the data source
* @param result defines the target vector
*/
public static FromArrayToRef(array: DeepImmutable<ArrayLike<number>>, offset: number, result: Vector2): void {
result.x = array[offset];
result.y = array[offset + 1];
}
/**
* Gets a new Vector2 located for "amount" (float) on the CatmullRom spline defined by the given four Vector2
* @param value1 defines 1st point of control
* @param value2 defines 2nd point of control
* @param value3 defines 3rd point of control
* @param value4 defines 4th point of control
* @param amount defines the interpolation factor
* @returns a new Vector2
*/
public static CatmullRom(value1: DeepImmutable<Vector2>, value2: DeepImmutable<Vector2>, value3: DeepImmutable<Vector2>, value4: DeepImmutable<Vector2>, amount: number): Vector2 {
var squared = amount * amount;
var cubed = amount * squared;
var x = 0.5 * ((((2.0 * value2.x) + ((-value1.x + value3.x) * amount)) +
(((((2.0 * value1.x) - (5.0 * value2.x)) + (4.0 * value3.x)) - value4.x) * squared)) +
((((-value1.x + (3.0 * value2.x)) - (3.0 * value3.x)) + value4.x) * cubed));
var y = 0.5 * ((((2.0 * value2.y) + ((-value1.y + value3.y) * amount)) +
(((((2.0 * value1.y) - (5.0 * value2.y)) + (4.0 * value3.y)) - value4.y) * squared)) +
((((-value1.y + (3.0 * value2.y)) - (3.0 * value3.y)) + value4.y) * cubed));
return new Vector2(x, y);
}
/**
* Returns a new Vector2 set with same the coordinates than "value" ones if the vector "value" is in the square defined by "min" and "max".
* If a coordinate of "value" is lower than "min" coordinates, the returned Vector2 is given this "min" coordinate.
* If a coordinate of "value" is greater than "max" coordinates, the returned Vector2 is given this "max" coordinate
* @param value defines the value to clamp
* @param min defines the lower limit
* @param max defines the upper limit
* @returns a new Vector2
*/
public static Clamp(value: DeepImmutable<Vector2>, min: DeepImmutable<Vector2>, max: DeepImmutable<Vector2>): Vector2 {
var x = value.x;
x = (x > max.x) ? max.x : x;
x = (x < min.x) ? min.x : x;
var y = value.y;
y = (y > max.y) ? max.y : y;
y = (y < min.y) ? min.y : y;
return new Vector2(x, y);
}
/**
* Returns a new Vector2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value3", "tangent1", "tangent2"
* @param value1 defines the 1st control point
* @param tangent1 defines the outgoing tangent
* @param value2 defines the 2nd control point
* @param tangent2 defines the incoming tangent
* @param amount defines the interpolation factor
* @returns a new Vector2
*/
public static Hermite(value1: DeepImmutable<Vector2>, tangent1: DeepImmutable<Vector2>, value2: DeepImmutable<Vector2>, tangent2: DeepImmutable<Vector2>, amount: number): Vector2 {
var squared = amount * amount;
var cubed = amount * squared;
var part1 = ((2.0 * cubed) - (3.0 * squared)) + 1.0;
var part2 = (-2.0 * cubed) + (3.0 * squared);
var part3 = (cubed - (2.0 * squared)) + amount;
var part4 = cubed - squared;
var x = (((value1.x * part1) + (value2.x * part2)) + (tangent1.x * part3)) + (tangent2.x * part4);
var y = (((value1.y * part1) + (value2.y * part2)) + (tangent1.y * part3)) + (tangent2.y * part4);
return new Vector2(x, y);
}
/**
* Returns a new Vector2 located for "amount" (float) on the linear interpolation between the vector "start" adn the vector "end".
* @param start defines the start vector
* @param end defines the end vector
* @param amount defines the interpolation factor
* @returns a new Vector2
*/
public static Lerp(start: DeepImmutable<Vector2>, end: DeepImmutable<Vector2>, amount: number): Vector2 {
var x = start.x + ((end.x - start.x) * amount);
var y = start.y + ((end.y - start.y) * amount);
return new Vector2(x, y);
}
/**
* Gets the dot product of the vector "left" and the vector "right"
* @param left defines first vector
* @param right defines second vector
* @returns the dot product (float)
*/
public static Dot(left: DeepImmutable<Vector2>, right: DeepImmutable<Vector2>): number {
return left.x * right.x + left.y * right.y;
}
/**
* Returns a new Vector2 equal to the normalized given vector
* @param vector defines the vector to normalize
* @returns a new Vector2
*/
public static Normalize(vector: DeepImmutable<Vector2>): Vector2 {
var newVector = vector.clone();
newVector.normalize();
return newVector;
}
/**
* Gets a new Vector2 set with the minimal coordinate values from the "left" and "right" vectors
* @param left defines 1st vector
* @param right defines 2nd vector
* @returns a new Vector2
*/
public static Minimize(left: DeepImmutable<Vector2>, right: DeepImmutable<Vector2>): Vector2 {
var x = (left.x < right.x) ? left.x : right.x;
var y = (left.y < right.y) ? left.y : right.y;
return new Vector2(x, y);
}
/**
* Gets a new Vecto2 set with the maximal coordinate values from the "left" and "right" vectors
* @param left defines 1st vector
* @param right defines 2nd vector
* @returns a new Vector2
*/
public static Maximize(left: DeepImmutable<Vector2>, right: DeepImmutable<Vector2>): Vector2 {
var x = (left.x > right.x) ? left.x : right.x;
var y = (left.y > right.y) ? left.y : right.y;
return new Vector2(x, y);
}
/**
* Gets a new Vector2 set with the transformed coordinates of the given vector by the given transformation matrix
* @param vector defines the vector to transform
* @param transformation defines the matrix to apply
* @returns a new Vector2
*/
public static Transform(vector: DeepImmutable<Vector2>, transformation: DeepImmutable<Matrix>): Vector2 {
let r = Vector2.Zero();
Vector2.TransformToRef(vector, transformation, r);
return r;
}
/**
* Transforms the given vector coordinates by the given transformation matrix and stores the result in the vector "result" coordinates
* @param vector defines the vector to transform
* @param transformation defines the matrix to apply
* @param result defines the target vector
*/
public static TransformToRef(vector: DeepImmutable<Vector2>, transformation: DeepImmutable<Matrix>, result: Vector2) {
const m = transformation.m;
var x = (vector.x * m[0]) + (vector.y * m[4]) + m[12];
var y = (vector.x * m[1]) + (vector.y * m[5]) + m[13];
result.x = x;
result.y = y;
}
/**
* Determines if a given vector is included in a triangle
* @param p defines the vector to test
* @param p0 defines 1st triangle point
* @param p1 defines 2nd triangle point
* @param p2 defines 3rd triangle point
* @returns true if the point "p" is in the triangle defined by the vertors "p0", "p1", "p2"
*/
public static PointInTriangle(p: DeepImmutable<Vector2>, p0: DeepImmutable<Vector2>, p1: DeepImmutable<Vector2>, p2: DeepImmutable<Vector2>) {
let a = 1 / 2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
let sign = a < 0 ? -1 : 1;
let s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
let t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;
return s > 0 && t > 0 && (s + t) < 2 * a * sign;
}
/**
* Gets the distance between the vectors "value1" and "value2"
* @param value1 defines first vector
* @param value2 defines second vector
* @returns the distance between vectors
*/
public static Distance(value1: DeepImmutable<Vector2>, value2: DeepImmutable<Vector2>): number {
return Math.sqrt(Vector2.DistanceSquared(value1, value2));
}
/**
* Returns the squared distance between the vectors "value1" and "value2"
* @param value1 defines first vector
* @param value2 defines second vector
* @returns the squared distance between vectors
*/
public static DistanceSquared(value1: DeepImmutable<Vector2>, value2: DeepImmutable<Vector2>): number {
var x = value1.x - value2.x;
var y = value1.y - value2.y;
return (x * x) + (y * y);
}
/**
* Gets a new Vector2 located at the center of the vectors "value1" and "value2"
* @param value1 defines first vector
* @param value2 defines second vector
* @returns a new Vector2
*/
public static Center(value1: DeepImmutable<Vector2>, value2: DeepImmutable<Vector2>): Vector2 {
var center = value1.add(value2);
center.scaleInPlace(0.5);
return center;
}
/**
* Gets the shortest distance (float) between the point "p" and the segment defined by the two points "segA" and "segB".
* @param p defines the middle point
* @param segA defines one point of the segment
* @param segB defines the other point of the segment
* @returns the shortest distance
*/
public static DistanceOfPointFromSegment(p: DeepImmutable<Vector2>, segA: DeepImmutable<Vector2>, segB: DeepImmutable<Vector2>): number {
let l2 = Vector2.DistanceSquared(segA, segB);
if (l2 === 0.0) {
return Vector2.Distance(p, segA);
}
let v = segB.subtract(segA);
let t = Math.max(0, Math.min(1, Vector2.Dot(p.subtract(segA), v) / l2));
let proj = segA.add(v.multiplyByFloats(t, t));
return Vector2.Distance(p, proj);
}
}
/**
* Classed used to store (x,y,z) vector representation
* A Vector3 is the main object used in 3D geometry
* It can represent etiher the coordinates of a point the space, either a direction
* Reminder: js uses a left handed forward facing system
*/
export class Vector3 {
private static _UpReadOnly = Vector3.Up() as DeepImmutable<Vector3>;
private static _ZeroReadOnly = Vector3.Zero() as DeepImmutable<Vector3>;
/**
* Creates a new Vector3 object from the given x, y, z (floats) coordinates.
* @param x defines the first coordinates (on X axis)
* @param y defines the second coordinates (on Y axis)
* @param z defines the third coordinates (on Z axis)
*/
constructor(
/**
* Defines the first coordinates (on X axis)
*/
public x: number = 0,
/**
* Defines the second coordinates (on Y axis)
*/
public y: number = 0,
/**
* Defines the third coordinates (on Z axis)
*/
public z: number = 0
) {
}
/**
* Creates a string representation of the Vector3
* @returns a string with the Vector3 coordinates.
*/
public toString(): string {
return "{X: " + this.x + " Y:" + this.y + " Z:" + this.z + "}";
}
/**
* Gets the class name
* @returns the string "Vector3"
*/
public getClassName(): string {
return "Vector3";
}
/**
* Creates the Vector3 hash code
* @returns a number which tends to be unique between Vector3 instances
*/
public getHashCode(): number {
let hash = this.x || 0;
hash = (hash * 397) ^ (this.y || 0);
hash = (hash * 397) ^ (this.z || 0);
return hash;
}
// Operators
/**
* Creates an array containing three elements : the coordinates of the Vector3
* @returns a new array of numbers
*/
public asArray(): number[] {
var result: number[] = [];
this.toArray(result, 0);
return result;
}
/**
* Populates the given array or Float32Array from the given index with the successive coordinates of the Vector3
* @param array defines the destination array
* @param index defines the offset in the destination array
* @returns the current Vector3
*/
public toArray(array: FloatArray, index: number = 0): Vector3 {
array[index] = this.x;
array[index + 1] = this.y;
array[index + 2] = this.z;
return this;
}
/**
* Converts the current Vector3 into a quaternion (considering that the Vector3 contains Euler angles representation of a rotation)
* @returns a new Quaternion object, computed from the Vector3 coordinates
*/
public toQuaternion(): Quaternion {
return Quaternion.RotationYawPitchRoll(this.y, this.x, this.z);
}
/**
* Adds the given vector to the current Vector3
* @param otherVector defines the second operand
* @returns the current updated Vector3
*/
public addInPlace(otherVector: DeepImmutable<Vector3>): Vector3 {
return this.addInPlaceFromFloats(otherVector.x, otherVector.y, otherVector.z);
}
/**
* Adds the given coordinates to the current Vector3
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the current updated Vector3
*/
public addInPlaceFromFloats(x: number, y: number, z: number): Vector3 {
this.x += x;
this.y += y;
this.z += z;
return this;
}
/**
* Gets a new Vector3, result of the addition the current Vector3 and the given vector
* @param otherVector defines the second operand
* @returns the resulting Vector3
*/
public add(otherVector: DeepImmutable<Vector3>): Vector3 {
return new Vector3(this.x + otherVector.x, this.y + otherVector.y, this.z + otherVector.z);
}
/**
* Adds the current Vector3 to the given one and stores the result in the vector "result"
* @param otherVector defines the second operand
* @param result defines the Vector3 object where to store the result
* @returns the current Vector3
*/
public addToRef(otherVector: DeepImmutable<Vector3>, result: Vector3): Vector3 {
return result.copyFromFloats(this.x + otherVector.x, this.y + otherVector.y, this.z + otherVector.z);
}
/**
* Subtract the given vector from the current Vector3
* @param otherVector defines the second operand
* @returns the current updated Vector3
*/
public subtractInPlace(otherVector: DeepImmutable<Vector3>): Vector3 {
this.x -= otherVector.x;
this.y -= otherVector.y;
this.z -= otherVector.z;
return this;
}
/**
* Returns a new Vector3, result of the subtraction of the given vector from the current Vector3
* @param otherVector defines the second operand
* @returns the resulting Vector3
*/
public subtract(otherVector: DeepImmutable<Vector3>): Vector3 {
return new Vector3(this.x - otherVector.x, this.y - otherVector.y, this.z - otherVector.z);
}
/**
* Subtracts the given vector from the current Vector3 and stores the result in the vector "result".
* @param otherVector defines the second operand
* @param result defines the Vector3 object where to store the result
* @returns the current Vector3
*/
public subtractToRef(otherVector: DeepImmutable<Vector3>, result: Vector3): Vector3 {
return this.subtractFromFloatsToRef(otherVector.x, otherVector.y, otherVector.z, result);
}
/**
* Returns a new Vector3 set with the subtraction of the given floats from the current Vector3 coordinates
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the resulting Vector3
*/
public subtractFromFloats(x: number, y: number, z: number): Vector3 {
return new Vector3(this.x - x, this.y - y, this.z - z);
}
/**
* Subtracts the given floats from the current Vector3 coordinates and set the given vector "result" with this result
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @param result defines the Vector3 object where to store the result
* @returns the current Vector3
*/
public subtractFromFloatsToRef(x: number, y: number, z: number, result: Vector3): Vector3 {
return result.copyFromFloats(this.x - x, this.y - y, this.z - z);
}
/**
* Gets a new Vector3 set with the current Vector3 negated coordinates
* @returns a new Vector3
*/
public negate(): Vector3 {
return new Vector3(-this.x, -this.y, -this.z);
}
/**
* Multiplies the Vector3 coordinates by the float "scale"
* @param scale defines the multiplier factor
* @returns the current updated Vector3
*/
public scaleInPlace(scale: number): Vector3 {
this.x *= scale;
this.y *= scale;
this.z *= scale;
return this;
}
/**
* Returns a new Vector3 set with the current Vector3 coordinates multiplied by the float "scale"
* @param scale defines the multiplier factor
* @returns a new Vector3
*/
public scale(scale: number): Vector3 {
return new Vector3(this.x * scale, this.y * scale, this.z * scale);
}
/**
* Multiplies the current Vector3 coordinates by the float "scale" and stores the result in the given vector "result" coordinates
* @param scale defines the multiplier factor
* @param result defines the Vector3 object where to store the result
* @returns the current Vector3
*/
public scaleToRef(scale: number, result: Vector3): Vector3 {
return result.copyFromFloats(this.x * scale, this.y * scale, this.z * scale);
}
/**
* Scale the current Vector3 values by a factor and add the result to a given Vector3
* @param scale defines the scale factor
* @param result defines the Vector3 object where to store the result
* @returns the unmodified current Vector3
*/
public scaleAndAddToRef(scale: number, result: Vector3): Vector3 {
return result.addInPlaceFromFloats(this.x * scale, this.y * scale, this.z * scale);
}
/**
* Returns true if the current Vector3 and the given vector coordinates are strictly equal
* @param otherVector defines the second operand
* @returns true if both vectors are equals
*/
public equals(otherVector: DeepImmutable<Vector3>): boolean {
return otherVector && this.x === otherVector.x && this.y === otherVector.y && this.z === otherVector.z;
}
/**
* Returns true if the current Vector3 and the given vector coordinates are distant less than epsilon
* @param otherVector defines the second operand
* @param epsilon defines the minimal distance to define values as equals
* @returns true if both vectors are distant less than epsilon
*/
public equalsWithEpsilon(otherVector: DeepImmutable<Vector3>, epsilon: number = Epsilon): boolean {
return otherVector && Scalar.WithinEpsilon(this.x, otherVector.x, epsilon) && Scalar.WithinEpsilon(this.y, otherVector.y, epsilon) && Scalar.WithinEpsilon(this.z, otherVector.z, epsilon);
}
/**
* Returns true if the current Vector3 coordinates equals the given floats
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns true if both vectors are equals
*/
public equalsToFloats(x: number, y: number, z: number): boolean {
return this.x === x && this.y === y && this.z === z;
}
/**
* Multiplies the current Vector3 coordinates by the given ones
* @param otherVector defines the second operand
* @returns the current updated Vector3
*/
public multiplyInPlace(otherVector: DeepImmutable<Vector3>): Vector3 {
this.x *= otherVector.x;
this.y *= otherVector.y;
this.z *= otherVector.z;
return this;
}
/**
* Returns a new Vector3, result of the multiplication of the current Vector3 by the given vector
* @param otherVector defines the second operand
* @returns the new Vector3
*/
public multiply(otherVector: DeepImmutable<Vector3>): Vector3 {
return this.multiplyByFloats(otherVector.x, otherVector.y, otherVector.z);
}
/**
* Multiplies the current Vector3 by the given one and stores the result in the given vector "result"
* @param otherVector defines the second operand
* @param result defines the Vector3 object where to store the result
* @returns the current Vector3
*/
public multiplyToRef(otherVector: DeepImmutable<Vector3>, result: Vector3): Vector3 {
return result.copyFromFloats(this.x * otherVector.x, this.y * otherVector.y, this.z * otherVector.z);
}
/**
* Returns a new Vector3 set with the result of the mulliplication of the current Vector3 coordinates by the given floats
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the new Vector3
*/
public multiplyByFloats(x: number, y: number, z: number): Vector3 {
return new Vector3(this.x * x, this.y * y, this.z * z);
}
/**
* Returns a new Vector3 set with the result of the division of the current Vector3 coordinates by the given ones
* @param otherVector defines the second operand
* @returns the new Vector3
*/
public divide(otherVector: DeepImmutable<Vector3>): Vector3 {
return new Vector3(this.x / otherVector.x, this.y / otherVector.y, this.z / otherVector.z);
}
/**
* Divides the current Vector3 coordinates by the given ones and stores the result in the given vector "result"
* @param otherVector defines the second operand
* @param result defines the Vector3 object where to store the result
* @returns the current Vector3
*/
public divideToRef(otherVector: DeepImmutable<Vector3>, result: Vector3): Vector3 {
return result.copyFromFloats(this.x / otherVector.x, this.y / otherVector.y, this.z / otherVector.z);
}
/**
* Divides the current Vector3 coordinates by the given ones.
* @param otherVector defines the second operand
* @returns the current updated Vector3
*/
public divideInPlace(otherVector: Vector3): Vector3 {
return this.divideToRef(otherVector, this);
}
/**
* Updates the current Vector3 with the minimal coordinate values between its and the given vector ones
* @param other defines the second operand
* @returns the current updated Vector3
*/
public minimizeInPlace(other: DeepImmutable<Vector3>): Vector3 {
return this.minimizeInPlaceFromFloats(other.x, other.y, other.z);
}
/**
* Updates the current Vector3 with the maximal coordinate values between its and the given vector ones.
* @param other defines the second operand
* @returns the current updated Vector3
*/
public maximizeInPlace(other: DeepImmutable<Vector3>): Vector3 {
return this.maximizeInPlaceFromFloats(other.x, other.y, other.z);
}
/**
* Updates the current Vector3 with the minimal coordinate values between its and the given coordinates
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the current updated Vector3
*/
public minimizeInPlaceFromFloats(x: number, y: number, z: number): Vector3 {
if (x < this.x) { this.x = x; }
if (y < this.y) { this.y = y; }
if (z < this.z) { this.z = z; }
return this;
}
/**
* Updates the current Vector3 with the maximal coordinate values between its and the given coordinates.
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the current updated Vector3
*/
public maximizeInPlaceFromFloats(x: number, y: number, z: number): Vector3 {
if (x > this.x) { this.x = x; }
if (y > this.y) { this.y = y; }
if (z > this.z) { this.z = z; }
return this;
}
/**
* Due to float precision, scale of a mesh could be uniform but float values are off by a small fraction
* Check if is non uniform within a certain amount of decimal places to account for this
* @param epsilon the amount the values can differ
* @returns if the the vector is non uniform to a certain number of decimal places
*/
public isNonUniformWithinEpsilon(epsilon: number) {
let absX = Math.abs(this.x);
let absY = Math.abs(this.y);
if (!Scalar.WithinEpsilon(absX, absY, epsilon)) {
return true;
}
let absZ = Math.abs(this.z);
if (!Scalar.WithinEpsilon(absX, absZ, epsilon)) {
return true;
}
if (!Scalar.WithinEpsilon(absY, absZ, epsilon)) {
return true;
}
return false;
}
/**
* Gets a boolean indicating that the vector is non uniform meaning x, y or z are not all the same
*/
public get isNonUniform(): boolean {
let absX = Math.abs(this.x);
let absY = Math.abs(this.y);
if (absX !== absY) {
return true;
}
let absZ = Math.abs(this.z);
if (absX !== absZ) {
return true;
}
if (absY !== absZ) {
return true;
}
return false;
}
/**
* Gets a new Vector3 from current Vector3 floored values
* @returns a new Vector3
*/
public floor(): Vector3 {
return new Vector3(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z));
}
/**
* Gets a new Vector3 from current Vector3 floored values
* @returns a new Vector3
*/
public fract(): Vector3 {
return new Vector3(this.x - Math.floor(this.x), this.y - Math.floor(this.y), this.z - Math.floor(this.z));
}
// Properties
/**
* Gets the length of the Vector3
* @returns the length of the Vecto3
*/
public length(): number {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
}
/**
* Gets the squared length of the Vector3
* @returns squared length of the Vector3
*/
public lengthSquared(): number {
return (this.x * this.x + this.y * this.y + this.z * this.z);
}
/**
* Normalize the current Vector3.
* Please note that this is an in place operation.
* @returns the current updated Vector3
*/
public normalize(): Vector3 {
return this.normalizeFromLength(this.length());
}
/**
* Reorders the x y z properties of the vector in place
* @param order new ordering of the properties (eg. for vector 1,2,3 with "ZYX" will produce 3,2,1)
* @returns the current updated vector
*/
public reorderInPlace(order: string) {
order = order.toLowerCase();
if (order === "xyz") {
return this;
}
MathTmp.Vector3[0].copyFrom(this);
["x", "y", "z"].forEach((val, i) => {
(<any>this)[val] = (<any>MathTmp.Vector3[0])[order[i]];
});
return this;
}
/**
* Rotates the vector around 0,0,0 by a quaternion
* @param quaternion the rotation quaternion
* @param result vector to store the result
* @returns the resulting vector
*/
public rotateByQuaternionToRef(quaternion: Quaternion, result: Vector3) {
quaternion.toRotationMatrix(MathTmp.Matrix[0]);
Vector3.TransformCoordinatesToRef(this, MathTmp.Matrix[0], result);
return result;
}
/**
* Rotates a vector around a given point
* @param quaternion the rotation quaternion
* @param point the point to rotate around
* @param result vector to store the result
* @returns the resulting vector
*/
public rotateByQuaternionAroundPointToRef(quaternion: Quaternion, point: Vector3, result: Vector3) {
this.subtractToRef(point, MathTmp.Vector3[0]);
MathTmp.Vector3[0].rotateByQuaternionToRef(quaternion, MathTmp.Vector3[0]);
point.addToRef(MathTmp.Vector3[0], result);
return result;
}
/**
* Normalize the current Vector3 with the given input length.
* Please note that this is an in place operation.
* @param len the length of the vector
* @returns the current updated Vector3
*/
public normalizeFromLength(len: number): Vector3 {
if (len === 0 || len === 1.0) {
return this;
}
return this.scaleInPlace(1.0 / len);
}
/**
* Normalize the current Vector3 to a new vector
* @returns the new Vector3
*/
public normalizeToNew(): Vector3 {
const normalized = new Vector3(0, 0, 0);
this.normalizeToRef(normalized);
return normalized;
}
/**
* Normalize the current Vector3 to the reference
* @param reference define the Vector3 to update
* @returns the updated Vector3
*/
public normalizeToRef(reference: DeepImmutable<Vector3>): Vector3 {
var len = this.length();
if (len === 0 || len === 1.0) {
return reference.copyFromFloats(this.x, this.y, this.z);
}
return this.scaleToRef(1.0 / len, reference);
}
/**
* Creates a new Vector3 copied from the current Vector3
* @returns the new Vector3
*/
public clone(): Vector3 {
return new Vector3(this.x, this.y, this.z);
}
/**
* Copies the given vector coordinates to the current Vector3 ones
* @param source defines the source Vector3
* @returns the current updated Vector3
*/
public copyFrom(source: DeepImmutable<Vector3>): Vector3 {
return this.copyFromFloats(source.x, source.y, source.z);
}
/**
* Copies the given floats to the current Vector3 coordinates
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the current updated Vector3
*/
public copyFromFloats(x: number, y: number, z: number): Vector3 {
this.x = x;
this.y = y;
this.z = z;
return this;
}
/**
* Copies the given floats to the current Vector3 coordinates
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the current updated Vector3
*/
public set(x: number, y: number, z: number): Vector3 {
return this.copyFromFloats(x, y, z);
}
/**
* Copies the given float to the current Vector3 coordinates
* @param v defines the x, y and z coordinates of the operand
* @returns the current updated Vector3
*/
public setAll(v: number): Vector3 {
this.x = this.y = this.z = v;
return this;
}
// Statics
/**
* Get the clip factor between two vectors
* @param vector0 defines the first operand
* @param vector1 defines the second operand
* @param axis defines the axis to use
* @param size defines the size along the axis
* @returns the clip factor
*/
public static GetClipFactor(vector0: DeepImmutable<Vector3>, vector1: DeepImmutable<Vector3>, axis: DeepImmutable<Vector3>, size: number) {
var d0 = Vector3.Dot(vector0, axis) - size;
var d1 = Vector3.Dot(vector1, axis) - size;
var s = d0 / (d0 - d1);
return s;
}
/**
* Get angle between two vectors
* @param vector0 angle between vector0 and vector1
* @param vector1 angle between vector0 and vector1
* @param normal direction of the normal
* @return the angle between vector0 and vector1
*/
public static GetAngleBetweenVectors(vector0: DeepImmutable<Vector3>, vector1: DeepImmutable<Vector3>, normal: DeepImmutable<Vector3>): number {
const v0: Vector3 = vector0.normalizeToRef(MathTmp.Vector3[1]);
const v1: Vector3 = vector1.normalizeToRef(MathTmp.Vector3[2]);
const dot: number = Vector3.Dot(v0, v1);
const n = MathTmp.Vector3[3];
Vector3.CrossToRef(v0, v1, n);
if (Vector3.Dot(n, normal) > 0) {
return Math.acos(dot);
}
return -Math.acos(dot);
}
/**
* Returns a new Vector3 set from the index "offset" of the given array
* @param array defines the source array
* @param offset defines the offset in the source array
* @returns the new Vector3
*/
public static FromArray(array: DeepImmutable<ArrayLike<number>>, offset: number = 0): Vector3 {
return new Vector3(array[offset], array[offset + 1], array[offset + 2]);
}
/**
* Returns a new Vector3 set from the index "offset" of the given Float32Array
* This function is deprecated. Use FromArray instead
* @param array defines the source array
* @param offset defines the offset in the source array
* @returns the new Vector3
*/
public static FromFloatArray(array: DeepImmutable<Float32Array>, offset?: number): Vector3 {
return Vector3.FromArray(array, offset);
}
/**
* Sets the given vector "result" with the element values from the index "offset" of the given array
* @param array defines the source array
* @param offset defines the offset in the source array
* @param result defines the Vector3 where to store the result
*/
public static FromArrayToRef(array: DeepImmutable<ArrayLike<number>>, offset: number, result: Vector3): void {
result.x = array[offset];
result.y = array[offset + 1];
result.z = array[offset + 2];
}
/**
* Sets the given vector "result" with the element values from the index "offset" of the given Float32Array
* This function is deprecated. Use FromArrayToRef instead.
* @param array defines the source array
* @param offset defines the offset in the source array
* @param result defines the Vector3 where to store the result
*/
public static FromFloatArrayToRef(array: DeepImmutable<Float32Array>, offset: number, result: Vector3): void {
return Vector3.FromArrayToRef(array, offset, result);
}
/**
* Sets the given vector "result" with the given floats.
* @param x defines the x coordinate of the source
* @param y defines the y coordinate of the source
* @param z defines the z coordinate of the source
* @param result defines the Vector3 where to store the result
*/
public static FromFloatsToRef(x: number, y: number, z: number, result: Vector3): void {
result.copyFromFloats(x, y, z);
}
/**
* Returns a new Vector3 set to (0.0, 0.0, 0.0)
* @returns a new empty Vector3
*/
public static Zero(): Vector3 {
return new Vector3(0.0, 0.0, 0.0);
}
/**
* Returns a new Vector3 set to (1.0, 1.0, 1.0)
* @returns a new unit Vector3
*/
public static One(): Vector3 {
return new Vector3(1.0, 1.0, 1.0);
}
/**
* Returns a new Vector3 set to (0.0, 1.0, 0.0)
* @returns a new up Vector3
*/
public static Up(): Vector3 {
return new Vector3(0.0, 1.0, 0.0);
}
/**
* Gets a up Vector3 that must not be updated
*/
public static get UpReadOnly(): DeepImmutable<Vector3> {
return Vector3._UpReadOnly;
}
/**
* Gets a zero Vector3 that must not be updated
*/
public static get ZeroReadOnly(): DeepImmutable<Vector3> {
return Vector3._ZeroReadOnly;
}
/**
* Returns a new Vector3 set to (0.0, -1.0, 0.0)
* @returns a new down Vector3
*/
public static Down(): Vector3 {
return new Vector3(0.0, -1.0, 0.0);
}
/**
* Returns a new Vector3 set to (0.0, 0.0, 1.0)
* @returns a new forward Vector3
*/
public static Forward(): Vector3 {
return new Vector3(0.0, 0.0, 1.0);
}
/**
* Returns a new Vector3 set to (0.0, 0.0, -1.0)
* @returns a new forward Vector3
*/
public static Backward(): Vector3 {
return new Vector3(0.0, 0.0, -1.0);
}
/**
* Returns a new Vector3 set to (1.0, 0.0, 0.0)
* @returns a new right Vector3
*/
public static Right(): Vector3 {
return new Vector3(1.0, 0.0, 0.0);
}
/**