sebastien 6 years ago
parent
commit
42ad4b4059

File diff suppressed because it is too large
+ 3303 - 3282
Playground/babylon.d.txt


File diff suppressed because it is too large
+ 3316 - 3295
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.js


+ 18 - 11
dist/preview release/babylon.max.js

@@ -7710,8 +7710,11 @@ var BABYLON;
          * @returns the current matrix
          */
         Matrix.prototype.addToRef = function (other, result) {
+            var m = this._m;
+            var resultM = result._m;
+            var otherM = other.m;
             for (var index = 0; index < 16; index++) {
-                result._m[index] = this._m[index] + other._m[index];
+                resultM[index] = m[index] + otherM[index];
             }
             result._markAsUpdated();
             return this;
@@ -7722,8 +7725,10 @@ var BABYLON;
          * @returns the current updated matrix
          */
         Matrix.prototype.addToSelf = function (other) {
+            var m = this._m;
+            var otherM = other.m;
             for (var index = 0; index < 16; index++) {
-                this._m[index] += other._m[index];
+                m[index] += otherM[index];
             }
             this._markAsUpdated();
             return this;
@@ -8579,8 +8584,11 @@ var BABYLON;
          * @param result defines the Matrix object where to store data
          */
         Matrix.LerpToRef = function (startValue, endValue, gradient, result) {
+            var resultM = result._m;
+            var startM = startValue.m;
+            var endM = endValue.m;
             for (var index = 0; index < 16; index++) {
-                result._m[index] = startValue._m[index] * (1.0 - gradient) + endValue._m[index] * gradient;
+                resultM[index] = startM[index] * (1.0 - gradient) + endM[index] * gradient;
             }
             result._markAsUpdated();
         };
@@ -8964,10 +8972,8 @@ var BABYLON;
          * @returns a new Float32Array array with 4 elements : the 2x2 matrix extracted from the given matrix
          */
         Matrix.GetAsMatrix2x2 = function (matrix) {
-            return new Float32Array([
-                matrix._m[0], matrix._m[1],
-                matrix._m[4], matrix._m[5]
-            ]);
+            var m = matrix.m;
+            return new Float32Array([m[0], m[1], m[4], m[5]]);
         };
         /**
          * Extracts a 3x3 matrix from a given matrix and store the result in a Float32Array
@@ -8975,10 +8981,11 @@ var BABYLON;
          * @returns a new Float32Array array with 9 elements : the 3x3 matrix extracted from the given matrix
          */
         Matrix.GetAsMatrix3x3 = function (matrix) {
+            var m = matrix.m;
             return new Float32Array([
-                matrix._m[0], matrix._m[1], matrix._m[2],
-                matrix._m[4], matrix._m[5], matrix._m[6],
-                matrix._m[8], matrix._m[9], matrix._m[10]
+                m[0], m[1], m[2],
+                m[4], m[5], m[6],
+                m[8], m[9], m[10]
             ]);
         };
         /**
@@ -8998,7 +9005,7 @@ var BABYLON;
          */
         Matrix.TransposeToRef = function (matrix, result) {
             var rm = result._m;
-            var mm = matrix._m;
+            var mm = matrix.m;
             rm[0] = mm[0];
             rm[1] = mm[4];
             rm[2] = mm[8];

+ 18 - 11
dist/preview release/babylon.no-module.max.js

@@ -7677,8 +7677,11 @@ var BABYLON;
          * @returns the current matrix
          */
         Matrix.prototype.addToRef = function (other, result) {
+            var m = this._m;
+            var resultM = result._m;
+            var otherM = other.m;
             for (var index = 0; index < 16; index++) {
-                result._m[index] = this._m[index] + other._m[index];
+                resultM[index] = m[index] + otherM[index];
             }
             result._markAsUpdated();
             return this;
@@ -7689,8 +7692,10 @@ var BABYLON;
          * @returns the current updated matrix
          */
         Matrix.prototype.addToSelf = function (other) {
+            var m = this._m;
+            var otherM = other.m;
             for (var index = 0; index < 16; index++) {
-                this._m[index] += other._m[index];
+                m[index] += otherM[index];
             }
             this._markAsUpdated();
             return this;
@@ -8546,8 +8551,11 @@ var BABYLON;
          * @param result defines the Matrix object where to store data
          */
         Matrix.LerpToRef = function (startValue, endValue, gradient, result) {
+            var resultM = result._m;
+            var startM = startValue.m;
+            var endM = endValue.m;
             for (var index = 0; index < 16; index++) {
-                result._m[index] = startValue._m[index] * (1.0 - gradient) + endValue._m[index] * gradient;
+                resultM[index] = startM[index] * (1.0 - gradient) + endM[index] * gradient;
             }
             result._markAsUpdated();
         };
@@ -8931,10 +8939,8 @@ var BABYLON;
          * @returns a new Float32Array array with 4 elements : the 2x2 matrix extracted from the given matrix
          */
         Matrix.GetAsMatrix2x2 = function (matrix) {
-            return new Float32Array([
-                matrix._m[0], matrix._m[1],
-                matrix._m[4], matrix._m[5]
-            ]);
+            var m = matrix.m;
+            return new Float32Array([m[0], m[1], m[4], m[5]]);
         };
         /**
          * Extracts a 3x3 matrix from a given matrix and store the result in a Float32Array
@@ -8942,10 +8948,11 @@ var BABYLON;
          * @returns a new Float32Array array with 9 elements : the 3x3 matrix extracted from the given matrix
          */
         Matrix.GetAsMatrix3x3 = function (matrix) {
+            var m = matrix.m;
             return new Float32Array([
-                matrix._m[0], matrix._m[1], matrix._m[2],
-                matrix._m[4], matrix._m[5], matrix._m[6],
-                matrix._m[8], matrix._m[9], matrix._m[10]
+                m[0], m[1], m[2],
+                m[4], m[5], m[6],
+                m[8], m[9], m[10]
             ]);
         };
         /**
@@ -8965,7 +8972,7 @@ var BABYLON;
          */
         Matrix.TransposeToRef = function (matrix, result) {
             var rm = result._m;
-            var mm = matrix._m;
+            var mm = matrix.m;
             rm[0] = mm[0];
             rm[1] = mm[4];
             rm[2] = mm[8];

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.worker.js


+ 18 - 11
dist/preview release/es6.js

@@ -7677,8 +7677,11 @@ var BABYLON;
          * @returns the current matrix
          */
         Matrix.prototype.addToRef = function (other, result) {
+            var m = this._m;
+            var resultM = result._m;
+            var otherM = other.m;
             for (var index = 0; index < 16; index++) {
-                result._m[index] = this._m[index] + other._m[index];
+                resultM[index] = m[index] + otherM[index];
             }
             result._markAsUpdated();
             return this;
@@ -7689,8 +7692,10 @@ var BABYLON;
          * @returns the current updated matrix
          */
         Matrix.prototype.addToSelf = function (other) {
+            var m = this._m;
+            var otherM = other.m;
             for (var index = 0; index < 16; index++) {
-                this._m[index] += other._m[index];
+                m[index] += otherM[index];
             }
             this._markAsUpdated();
             return this;
@@ -8546,8 +8551,11 @@ var BABYLON;
          * @param result defines the Matrix object where to store data
          */
         Matrix.LerpToRef = function (startValue, endValue, gradient, result) {
+            var resultM = result._m;
+            var startM = startValue.m;
+            var endM = endValue.m;
             for (var index = 0; index < 16; index++) {
-                result._m[index] = startValue._m[index] * (1.0 - gradient) + endValue._m[index] * gradient;
+                resultM[index] = startM[index] * (1.0 - gradient) + endM[index] * gradient;
             }
             result._markAsUpdated();
         };
@@ -8931,10 +8939,8 @@ var BABYLON;
          * @returns a new Float32Array array with 4 elements : the 2x2 matrix extracted from the given matrix
          */
         Matrix.GetAsMatrix2x2 = function (matrix) {
-            return new Float32Array([
-                matrix._m[0], matrix._m[1],
-                matrix._m[4], matrix._m[5]
-            ]);
+            var m = matrix.m;
+            return new Float32Array([m[0], m[1], m[4], m[5]]);
         };
         /**
          * Extracts a 3x3 matrix from a given matrix and store the result in a Float32Array
@@ -8942,10 +8948,11 @@ var BABYLON;
          * @returns a new Float32Array array with 9 elements : the 3x3 matrix extracted from the given matrix
          */
         Matrix.GetAsMatrix3x3 = function (matrix) {
+            var m = matrix.m;
             return new Float32Array([
-                matrix._m[0], matrix._m[1], matrix._m[2],
-                matrix._m[4], matrix._m[5], matrix._m[6],
-                matrix._m[8], matrix._m[9], matrix._m[10]
+                m[0], m[1], m[2],
+                m[4], m[5], m[6],
+                m[8], m[9], m[10]
             ]);
         };
         /**
@@ -8965,7 +8972,7 @@ var BABYLON;
          */
         Matrix.TransposeToRef = function (matrix, result) {
             var rm = result._m;
-            var mm = matrix._m;
+            var mm = matrix.m;
             rm[0] = mm[0];
             rm[1] = mm[4];
             rm[2] = mm[8];

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


File diff suppressed because it is too large
+ 1 - 5
dist/preview release/inspector/babylon.inspector.bundle.js.map


+ 159 - 2
dist/preview release/viewer/babylon.viewer.d.ts

@@ -515,10 +515,167 @@ declare module BabylonViewer {
     }
 }
 declare module BabylonViewer {
+    /**
+        * The current state of the model
+        */
+    export enum ModelState {
+            INIT = 0,
+            LOADING = 1,
+            LOADED = 2,
+            ENTRY = 3,
+            ENTRYDONE = 4,
+            COMPLETE = 5,
+            CANCELED = 6,
+            ERROR = 7
+    }
+    /**
+        * The viewer model is a container for all assets representing a sngle loaded model.
+        */
+    export class ViewerModel implements BABYLON.IDisposable {
+            /**
+                * The loader used to load this model.
+                */
+            loader: BABYLON.ISceneLoaderPlugin | BABYLON.ISceneLoaderPluginAsync;
+            /**
+                * This model's root mesh (the parent of all other meshes).
+                * This mesh does not(!) exist in the meshes array.
+                */
+            rootMesh: BABYLON.AbstractMesh;
+            /**
+                * ParticleSystems connected to this model
+                */
+            particleSystems: Array<BABYLON.IParticleSystem>;
+            /**
+                * Skeletons defined in this model
+                */
+            skeletons: Array<BABYLON.Skeleton>;
+            /**
+                * The current model animation.
+                * On init, this will be undefined.
+                */
+            currentAnimation: IModelAnimation;
+            /**
+                * Observers registered here will be executed when the model is done loading
+                */
+            onLoadedObservable: BABYLON.Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed when the loader notified of a progress event
+                */
+            onLoadProgressObservable: BABYLON.Observable<BABYLON.SceneLoaderProgressEvent>;
+            /**
+                * Observers registered here will be executed when the loader notified of an error.
+                */
+            onLoadErrorObservable: BABYLON.Observable<{
+                    message: string;
+                    exception: any;
+            }>;
+            /**
+                * Will be executed after the model finished loading and complete, including entry animation and lod
+                */
+            onCompleteObservable: BABYLON.Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed every time the model is being configured.
+                * This can be used to extend the model's configuration without extending the class itself
+                */
+            onAfterConfigure: BABYLON.Observable<ViewerModel>;
+            /**
+                * The current model state (loaded, error, etc)
+                */
+            state: ModelState;
+            /**
+                * A loadID provided by the modelLoader, unique to ths (Abstract)Viewer instance.
+                */
+            loadId: number;
+            loadInfo: BABYLON.GLTF2.IAsset;
+            constructor(_observablesManager: ObservablesManager, modelConfiguration: IModelConfiguration, _configurationContainer?: ConfigurationContainer | undefined);
+            shadowsRenderedAfterLoad: boolean;
+            getViewerId(): string | undefined;
+            /**
+             * Set whether this model is enabled or not.
+             */
+            enabled: boolean;
+            loaderDone: boolean;
+            /**
+                * Add a mesh to this model.
+                * Any mesh that has no parent will be provided with the root mesh as its new parent.
+                *
+                * @param mesh the new mesh to add
+                * @param triggerLoaded should this mesh trigger the onLoaded observable. Used when adding meshes manually.
+                */
+            addMesh(mesh: BABYLON.AbstractMesh, triggerLoaded?: boolean): Promise<ViewerModel> | undefined;
+            /**
+                * get the list of meshes (excluding the root mesh)
+                */
+            readonly meshes: BABYLON.AbstractMesh[];
+            /**
+             * (Re-)set the model's entire configuration
+             * @param newConfiguration the new configuration to replace the new one
+             */
+            configuration: IModelConfiguration;
+            /**
+                * Update the current configuration with new values.
+                * Configuration will not be overwritten, but merged with the new configuration.
+                * Priority is to the new configuration
+                * @param newConfiguration the configuration to be merged into the current configuration;
+                */
+            updateConfiguration(newConfiguration: Partial<IModelConfiguration>): void;
+            /**
+                * Add a new animation group to this model.
+                * @param animationGroup the new animation group to be added
+                */
+            addAnimationGroup(animationGroup: BABYLON.AnimationGroup): void;
+            /**
+                * Get the ModelAnimation array
+                */
+            getAnimations(): Array<IModelAnimation>;
+            /**
+                * Get the animations' names. Using the names you can play a specific animation.
+                */
+            getAnimationNames(): Array<string>;
+            /**
+                * Get an animation by the provided name. Used mainly when playing n animation.
+                * @param name the name of the animation to find
+                */
+            protected _getAnimationByName(name: string): BABYLON.Nullable<IModelAnimation>;
+            /**
+                * Choose an initialized animation using its name and start playing it
+                * @param name the name of the animation to play
+                * @returns The model aniamtion to be played.
+                */
+            playAnimation(name: string): IModelAnimation;
+            setCurrentAnimationByName(name: string): IModelAnimation;
+            /**
+                * Apply a material configuration to a material
+                * @param material BABYLON.Material to apply configuration to
+                * @hidden
+                */
+            _applyModelMaterialConfiguration(material: BABYLON.Material): void;
+            /**
+             * Begin @animations with the specified @easingFunction
+             * @param animations The BABYLON Animations to begin
+             * @param duration of transition, in seconds
+             * @param easingFunction An easing function to apply
+             * @param easingMode A easing mode to apply to the easingFunction
+             * @param onAnimationEnd Call back trigger at the end of the animation.
+             */
+            transitionTo(animations: BABYLON.Animation[], duration: number, easingFunction: any, easingMode: number | undefined, onAnimationEnd: () => void): void;
+            /**
+                * Stops and removes all animations that have been applied to the model
+                */
+            stopAllAnimations(): void;
+            /**
+                * Will remove this model from the viewer (but NOT dispose it).
+                */
+            remove(): void;
+            /**
+                * Dispose this model, including all of its associated assets.
+                */
+            dispose(): void;
+    }
 }
 declare module BabylonViewer {
     /**
-        * Animation play mode enum - is the animation looping or playing once
+        * BABYLON.Animation play mode enum - is the animation looping or playing once
         */
     export const enum AnimationPlayMode {
             ONCE = 0,
@@ -600,7 +757,7 @@ declare module BabylonViewer {
                 */
             readonly currentFrame: number;
             /**
-                * Animation's FPS value
+                * BABYLON.Animation's FPS value
                 */
             readonly fps: number;
             /**

File diff suppressed because it is too large
+ 2 - 2
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 3 - 3
dist/preview release/viewer/babylon.viewer.max.js


+ 163 - 1
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -567,7 +567,169 @@ declare module 'babylonjs-viewer/loader/modelLoader' {
 }
 
 declare module 'babylonjs-viewer/model/viewerModel' {
-    
+    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, AbstractMesh, Observable, SceneLoaderProgressEvent, IParticleSystem, Skeleton, IDisposable, Nullable, Animation, Material } from "babylonjs";
+    import { GLTF2 } from "babylonjs-loaders";
+    import { IModelConfiguration } from "babylonjs-viewer/configuration/interfaces/modelConfiguration";
+    import { IModelAnimation } from "babylonjs-viewer/model/modelAnimation";
+    import { ObservablesManager } from "babylonjs-viewer/managers/observablesManager";
+    import { ConfigurationContainer } from "babylonjs-viewer/configuration/configurationContainer";
+    /**
+        * The current state of the model
+        */
+    export enum ModelState {
+            INIT = 0,
+            LOADING = 1,
+            LOADED = 2,
+            ENTRY = 3,
+            ENTRYDONE = 4,
+            COMPLETE = 5,
+            CANCELED = 6,
+            ERROR = 7
+    }
+    /**
+        * The viewer model is a container for all assets representing a sngle loaded model.
+        */
+    export class ViewerModel implements IDisposable {
+            /**
+                * The loader used to load this model.
+                */
+            loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync;
+            /**
+                * This model's root mesh (the parent of all other meshes).
+                * This mesh does not(!) exist in the meshes array.
+                */
+            rootMesh: AbstractMesh;
+            /**
+                * ParticleSystems connected to this model
+                */
+            particleSystems: Array<IParticleSystem>;
+            /**
+                * Skeletons defined in this model
+                */
+            skeletons: Array<Skeleton>;
+            /**
+                * The current model animation.
+                * On init, this will be undefined.
+                */
+            currentAnimation: IModelAnimation;
+            /**
+                * Observers registered here will be executed when the model is done loading
+                */
+            onLoadedObservable: Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed when the loader notified of a progress event
+                */
+            onLoadProgressObservable: Observable<SceneLoaderProgressEvent>;
+            /**
+                * Observers registered here will be executed when the loader notified of an error.
+                */
+            onLoadErrorObservable: Observable<{
+                    message: string;
+                    exception: any;
+            }>;
+            /**
+                * Will be executed after the model finished loading and complete, including entry animation and lod
+                */
+            onCompleteObservable: Observable<ViewerModel>;
+            /**
+                * Observers registered here will be executed every time the model is being configured.
+                * This can be used to extend the model's configuration without extending the class itself
+                */
+            onAfterConfigure: Observable<ViewerModel>;
+            /**
+                * The current model state (loaded, error, etc)
+                */
+            state: ModelState;
+            /**
+                * A loadID provided by the modelLoader, unique to ths (Abstract)Viewer instance.
+                */
+            loadId: number;
+            loadInfo: GLTF2.IAsset;
+            constructor(_observablesManager: ObservablesManager, modelConfiguration: IModelConfiguration, _configurationContainer?: ConfigurationContainer | undefined);
+            shadowsRenderedAfterLoad: boolean;
+            getViewerId(): string | undefined;
+            /**
+             * Set whether this model is enabled or not.
+             */
+            enabled: boolean;
+            loaderDone: boolean;
+            /**
+                * Add a mesh to this model.
+                * Any mesh that has no parent will be provided with the root mesh as its new parent.
+                *
+                * @param mesh the new mesh to add
+                * @param triggerLoaded should this mesh trigger the onLoaded observable. Used when adding meshes manually.
+                */
+            addMesh(mesh: AbstractMesh, triggerLoaded?: boolean): Promise<ViewerModel> | undefined;
+            /**
+                * get the list of meshes (excluding the root mesh)
+                */
+            readonly meshes: AbstractMesh[];
+            /**
+             * (Re-)set the model's entire configuration
+             * @param newConfiguration the new configuration to replace the new one
+             */
+            configuration: IModelConfiguration;
+            /**
+                * Update the current configuration with new values.
+                * Configuration will not be overwritten, but merged with the new configuration.
+                * Priority is to the new configuration
+                * @param newConfiguration the configuration to be merged into the current configuration;
+                */
+            updateConfiguration(newConfiguration: Partial<IModelConfiguration>): void;
+            /**
+                * Add a new animation group to this model.
+                * @param animationGroup the new animation group to be added
+                */
+            addAnimationGroup(animationGroup: AnimationGroup): void;
+            /**
+                * Get the ModelAnimation array
+                */
+            getAnimations(): Array<IModelAnimation>;
+            /**
+                * Get the animations' names. Using the names you can play a specific animation.
+                */
+            getAnimationNames(): Array<string>;
+            /**
+                * Get an animation by the provided name. Used mainly when playing n animation.
+                * @param name the name of the animation to find
+                */
+            protected _getAnimationByName(name: string): Nullable<IModelAnimation>;
+            /**
+                * Choose an initialized animation using its name and start playing it
+                * @param name the name of the animation to play
+                * @returns The model aniamtion to be played.
+                */
+            playAnimation(name: string): IModelAnimation;
+            setCurrentAnimationByName(name: string): IModelAnimation;
+            /**
+                * Apply a material configuration to a material
+                * @param material Material to apply configuration to
+                * @hidden
+                */
+            _applyModelMaterialConfiguration(material: Material): void;
+            /**
+             * Begin @animations with the specified @easingFunction
+             * @param animations The BABYLON Animations to begin
+             * @param duration of transition, in seconds
+             * @param easingFunction An easing function to apply
+             * @param easingMode A easing mode to apply to the easingFunction
+             * @param onAnimationEnd Call back trigger at the end of the animation.
+             */
+            transitionTo(animations: Animation[], duration: number, easingFunction: any, easingMode: number | undefined, onAnimationEnd: () => void): void;
+            /**
+                * Stops and removes all animations that have been applied to the model
+                */
+            stopAllAnimations(): void;
+            /**
+                * Will remove this model from the viewer (but NOT dispose it).
+                */
+            remove(): void;
+            /**
+                * Dispose this model, including all of its associated assets.
+                */
+            dispose(): void;
+    }
 }
 
 declare module 'babylonjs-viewer/model/modelAnimation' {

+ 3 - 2
dist/preview release/what's new.md

@@ -80,6 +80,7 @@
 - Fixed `Matrix.toNormalMatrix`function ([barroij](https://github.com/barroij))
 - Add missing effect layer to asset container ([TrevorDev](https://github.com/TrevorDev))
 - Fixed effect layer compatibility with multi materials ([Sebavan](https://github.com/Sebavan))
+- Added a `DeepImmutable<T>` type to specifiy that a referenced object should be considered recursively immutable, meaning that all its properties are `readonly` and that if a property is a reference to an object, this object is also recursively immutable. ([barroij](https://github.com/barroij))
 
 ### Viewer
 
@@ -90,8 +91,8 @@
 - `Database.IDBStorageEnabled` is now false by default ([Deltakosh](https://github.com/deltakosh))
 - `Database.openAsync` was renamed by `Database.open` ([Deltakosh](https://github.com/deltakosh))
 - `scene.database` was renamed to `scene.offlineProvider` ([Deltakosh](https://github.com/deltakosh))
-- `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `Readonly<Matrix>` ([barroij](https://github.com/barroij))
-- `Matrix`'s accessor `m` and method `toArray` and `asArray` now returns a `Readonly<Float32Array>` as the matrix underlying array is not supposed to be modified manually from the outside of the class ([barroij](https://github.com/barroij))
+- `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `DeepImmutable<Matrix>` ([barroij](https://github.com/barroij))
+- `Matrix`'s accessor `m` and method `toArray` and `asArray` now returns a `DeepImmutable<Float32Array>` as the matrix underlying array is not supposed to be modified manually from the outside of the class ([barroij](https://github.com/barroij))
 - Removed some deprecated (flagged since 3.0) properties and functions ([Deltakosh](https://github.com/deltakosh))
   - `scene.getInterFramePerfCounter()`: use SceneInstrumentation class instead
   - `scene.interFramePerfCounter`: use SceneInstrumentation class instead

+ 5 - 5
src/Animations/runtimeAnimation.ts

@@ -7,19 +7,19 @@ import { Scene } from "scene";
     // Static values to help the garbage collector
 
     // Quaternion
-    const _staticOffsetValueQuaternion: Readonly<Quaternion> = Object.freeze(new Quaternion(0, 0, 0, 0));
+    const _staticOffsetValueQuaternion: DeepImmutable<Quaternion> = Object.freeze(new Quaternion(0, 0, 0, 0));
 
     // Vector3
-    const _staticOffsetValueVector3: Readonly<Vector3> = Object.freeze(Vector3.Zero());
+    const _staticOffsetValueVector3: DeepImmutable<Vector3> = Object.freeze(Vector3.Zero());
 
     // Vector2
-    const _staticOffsetValueVector2: Readonly<Vector2> = Object.freeze(Vector2.Zero());
+    const _staticOffsetValueVector2: DeepImmutable<Vector2> = Object.freeze(Vector2.Zero());
 
     // Size
-    const _staticOffsetValueSize: Readonly<Size> = Object.freeze(Size.Zero());
+    const _staticOffsetValueSize: DeepImmutable<Size> = Object.freeze(Size.Zero());
 
     // Color3
-    const _staticOffsetValueColor3: Readonly<Color3> = Object.freeze(Color3.Black());
+    const _staticOffsetValueColor3: DeepImmutable<Color3> = Object.freeze(Color3.Black());
 
     /**
      * Defines a runtime animation

+ 14 - 14
src/Culling/boundingBox.ts

@@ -53,7 +53,7 @@ import { ICullable } from "./boundingInfo";
          */
         public readonly maximum: Vector3 = Vector3.Zero();
 
-        private _worldMatrix: Readonly<Matrix>;
+        private _worldMatrix: DeepImmutable<Matrix>;
         private static readonly TmpVector3 = Tools.BuildArray(3, Vector3.Zero);
 
         /**
@@ -67,7 +67,7 @@ import { ICullable } from "./boundingInfo";
          * @param max defines the maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        constructor(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        constructor(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.reConstruct(min, max, worldMatrix);
         }
 
@@ -79,7 +79,7 @@ import { ICullable } from "./boundingInfo";
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        public reConstruct(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
             const vectors = this.vectors;
 
@@ -126,12 +126,12 @@ import { ICullable } from "./boundingInfo";
          * Gets the world matrix of the bounding box
          * @returns a matrix
          */
-        public getWorldMatrix(): Readonly<Matrix> {
+        public getWorldMatrix(): DeepImmutable<Matrix> {
             return this._worldMatrix;
         }
 
         /** @hidden */
-        public _update(world: Readonly<Matrix>): void {
+        public _update(world: DeepImmutable<Matrix>): void {
             const minWorld = this.minimumWorld;
             const maxWorld = this.maximumWorld;
             const directions = this.directions;
@@ -177,7 +177,7 @@ import { ICullable } from "./boundingInfo";
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an intersection
          */
-        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             return BoundingBox.IsInFrustum(this.vectorsWorld, frustumPlanes);
         }
 
@@ -186,7 +186,7 @@ import { ICullable } from "./boundingInfo";
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an inclusion
          */
-        public isCompletelyInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public isCompletelyInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             return BoundingBox.IsCompletelyInFrustum(this.vectorsWorld, frustumPlanes);
         }
 
@@ -195,7 +195,7 @@ import { ICullable } from "./boundingInfo";
          * @param point defines the point to test
          * @returns true if the point is inside the bounding box
          */
-        public intersectsPoint(point: Readonly<Vector3>): boolean {
+        public intersectsPoint(point: DeepImmutable<Vector3>): boolean {
             const min = this.minimumWorld;
             const max = this.maximumWorld;
             const minX = min.x, minY = min.y, minZ = min.z, maxX = max.x, maxY = max.y, maxZ = max.z;
@@ -222,7 +222,7 @@ import { ICullable } from "./boundingInfo";
          * @param sphere defines the sphere to test
          * @returns true if there is an intersection
          */
-        public intersectsSphere(sphere: Readonly<BoundingSphere>): boolean {
+        public intersectsSphere(sphere: DeepImmutable<BoundingSphere>): boolean {
             return BoundingBox.IntersectsSphere(this.minimumWorld, this.maximumWorld, sphere.centerWorld, sphere.radiusWorld);
         }
 
@@ -232,7 +232,7 @@ import { ICullable } from "./boundingInfo";
          * @param max defines the max vector to use
          * @returns true if there is an intersection
          */
-        public intersectsMinMax(min: Readonly<Vector3>, max: Readonly<Vector3>): boolean {
+        public intersectsMinMax(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>): boolean {
             const myMin = this.minimumWorld;
             const myMax = this.maximumWorld;
             const myMinX = myMin.x, myMinY = myMin.y, myMinZ = myMin.z, myMaxX = myMax.x, myMaxY = myMax.y, myMaxZ = myMax.z;
@@ -260,7 +260,7 @@ import { ICullable } from "./boundingInfo";
          * @param box1 defines the second box to test
          * @returns true if there is an intersection
          */
-        public static Intersects(box0: BoundingBox, box1: BoundingBox): boolean {
+        public static Intersects(box0: DeepImmutable<BoundingBox>, box1: DeepImmutable<BoundingBox>): boolean {
             return box0.intersectsMinMax(box1.minimumWorld, box1.maximumWorld);
         }
 
@@ -272,7 +272,7 @@ import { ICullable } from "./boundingInfo";
          * @param sphereRadius defines the sphere radius
          * @returns true if there is an intersection
          */
-        public static IntersectsSphere(minPoint: Readonly<Vector3>, maxPoint: Readonly<Vector3>, sphereCenter: Readonly<Vector3>, sphereRadius: number): boolean {
+        public static IntersectsSphere(minPoint: DeepImmutable<Vector3>, maxPoint: DeepImmutable<Vector3>, sphereCenter: DeepImmutable<Vector3>, sphereRadius: number): boolean {
             const vector = BoundingBox.TmpVector3[0];
             Vector3.ClampToRef(sphereCenter, minPoint, maxPoint, vector);
             var num = Vector3.DistanceSquared(sphereCenter, vector);
@@ -285,7 +285,7 @@ import { ICullable } from "./boundingInfo";
          * @param frustumPlanes defines the frustum planes to test
          * @return true if there is an inclusion
          */
-        public static IsCompletelyInFrustum(boundingVectors: Array<Readonly<Vector3>>, frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public static IsCompletelyInFrustum(boundingVectors: Array<DeepImmutable<Vector3>>, frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             for (var p = 0; p < 6; ++p) {
                 const frustumPlane = frustumPlanes[p];
                 for (var i = 0; i < 8; ++i) {
@@ -303,7 +303,7 @@ import { ICullable } from "./boundingInfo";
          * @param frustumPlanes defines the frustum planes to test
          * @return true if there is an intersection
          */
-        public static IsInFrustum(boundingVectors: Array<Readonly<Vector3>>, frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public static IsInFrustum(boundingVectors: Array<DeepImmutable<Vector3>>, frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             for (var p = 0; p < 6; ++p) {
                 let canReturnFalse = true;
                 const frustumPlane = frustumPlanes[p];

+ 10 - 10
src/Culling/boundingInfo.ts

@@ -8,7 +8,7 @@ import { BoundingSphere } from "./boundingSphere";
 
     const _result0 = { min: 0, max: 0};
     const _result1 = { min: 0, max: 0};
-    const computeBoxExtents = (axis: Readonly<Vector3>, box: Readonly<BoundingBox>, result: {min: number, max: number}) => {
+    const computeBoxExtents = (axis: DeepImmutable<Vector3>, box: DeepImmutable<BoundingBox>, result: {min: number, max: number}) => {
         const p = Vector3.Dot(box.centerWorld, axis);
 
         const r0 = Math.abs(Vector3.Dot(box.directions[0], axis)) * box.extendSize.x;
@@ -20,7 +20,7 @@ import { BoundingSphere } from "./boundingSphere";
         result.max = p + r;
     };
 
-    const axisOverlap = (axis: Vector3, box0: BoundingBox, box1: BoundingBox): boolean => {
+    const axisOverlap = (axis: DeepImmutable<Vector3>, box0: DeepImmutable<BoundingBox>, box1: DeepImmutable<BoundingBox>): boolean => {
         computeBoxExtents(axis, box0, _result0);
         computeBoxExtents(axis, box1, _result1);
         return !(_result0.min > _result1.max || _result1.min > _result0.max);
@@ -69,7 +69,7 @@ import { BoundingSphere } from "./boundingSphere";
          * @param maximum max vector of the bounding box/sphere
          * @param worldMatrix defines the new world matrix
          */
-        constructor(minimum: Readonly<Vector3>, maximum: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        constructor(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.boundingBox = new BoundingBox(minimum, maximum, worldMatrix);
             this.boundingSphere = new BoundingSphere(minimum, maximum, worldMatrix);
         }
@@ -80,7 +80,7 @@ import { BoundingSphere } from "./boundingSphere";
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        public reConstruct(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.boundingBox.reConstruct(min, max, worldMatrix);
             this.boundingSphere.reConstruct(min, max, worldMatrix);
         }
@@ -115,7 +115,7 @@ import { BoundingSphere } from "./boundingSphere";
          * Updates the bounding sphere and box
          * @param world world matrix to be used to update
          */
-        public update(world: Readonly<Matrix>) {
+        public update(world: DeepImmutable<Matrix>) {
             if (this._isLocked) {
                 return;
             }
@@ -129,7 +129,7 @@ import { BoundingSphere } from "./boundingSphere";
          * @param extend New extend of the bounding info
          * @returns the current bounding info
          */
-        public centerOn(center: Readonly<Vector3>, extend: Readonly<Vector3>): BoundingInfo {
+        public centerOn(center: DeepImmutable<Vector3>, extend: DeepImmutable<Vector3>): BoundingInfo {
 
             const minimum = BoundingInfo.TmpVector3[0].copyFrom(center).subtractInPlace(extend);
             const maximum = BoundingInfo.TmpVector3[1].copyFrom(center).addInPlace(extend);
@@ -158,7 +158,7 @@ import { BoundingSphere } from "./boundingSphere";
          * @param strategy defines the strategy to use for the culling (default is Scene.CULLINGSTRATEGY_STANDARD)
          * @returns true if the bounding info is in the frustum planes
          */
-        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>, strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
+        public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>, strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
             if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
                 return false;
             }
@@ -184,7 +184,7 @@ import { BoundingSphere } from "./boundingSphere";
          * @param frustumPlanes Camera near/planes
          * @returns true if the object is in frustum otherwise false
          */
-        public isCompletelyInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public isCompletelyInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             return this.boundingBox.isCompletelyInFrustum(frustumPlanes);
         }
         /** @hidden */
@@ -198,7 +198,7 @@ import { BoundingSphere } from "./boundingSphere";
          * @param point the point to check intersection with
          * @returns if the point intersects
          */
-        public intersectsPoint(point: Readonly<Vector3>): boolean {
+        public intersectsPoint(point: DeepImmutable<Vector3>): boolean {
             if (!this.boundingSphere.centerWorld) {
                 return false;
             }
@@ -221,7 +221,7 @@ import { BoundingSphere } from "./boundingSphere";
          * @param precise if the intersection should be done using OBB
          * @returns if the bounding info intersects
          */
-        public intersects(boundingInfo: Readonly<BoundingInfo>, precise: boolean): boolean {
+        public intersects(boundingInfo: DeepImmutable<BoundingInfo>, precise: boolean): boolean {
             if (!BoundingSphere.Intersects(this.boundingSphere, boundingInfo.boundingSphere)) {
                 return false;
             }

+ 8 - 8
src/Culling/boundingSphere.ts

@@ -30,7 +30,7 @@ import { Matrix, Vector3, Plane } from "Math/math";
          */
         public readonly maximum = Vector3.Zero();
 
-        private _worldMatrix: Readonly<Matrix>;
+        private _worldMatrix: DeepImmutable<Matrix>;
         private static readonly TmpVector3 = Tools.BuildArray(3, Vector3.Zero);
 
         /**
@@ -39,7 +39,7 @@ import { Matrix, Vector3, Plane } from "Math/math";
          * @param max defines the maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        constructor(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        constructor(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.reConstruct(min, max, worldMatrix);
         }
 
@@ -49,7 +49,7 @@ import { Matrix, Vector3, Plane } from "Math/math";
          * @param max defines the new maximum vector (in local space)
          * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Readonly<Vector3>, max: Readonly<Vector3>, worldMatrix?: Readonly<Matrix>) {
+        public reConstruct(min: DeepImmutable<Vector3>, max: DeepImmutable<Vector3>, worldMatrix?: DeepImmutable<Matrix>) {
             this.minimum.copyFrom(min);
             this.maximum.copyFrom(max);
 
@@ -82,13 +82,13 @@ import { Matrix, Vector3, Plane } from "Math/math";
          * Gets the world matrix of the bounding box
          * @returns a matrix
          */
-        public getWorldMatrix(): Readonly<Matrix> {
+        public getWorldMatrix(): DeepImmutable<Matrix> {
             return this._worldMatrix;
         }
 
         // Methods
         /** @hidden */
-        public _update(worldMatrix: Readonly<Matrix>): void {
+        public _update(worldMatrix: DeepImmutable<Matrix>): void {
             if (!worldMatrix.isIdentity()) {
                 Vector3.TransformCoordinatesToRef(this.center, worldMatrix, this.centerWorld);
                 const tempVector = BoundingSphere.TmpVector3[0];
@@ -106,7 +106,7 @@ import { Matrix, Vector3, Plane } from "Math/math";
          * @param frustumPlanes defines the frustum planes to test
          * @returns true if there is an intersection
          */
-        public isInFrustum(frustumPlanes: Array<Readonly<Plane>>): boolean {
+        public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
             for (var i = 0; i < 6; i++) {
                 if (frustumPlanes[i].dotCoordinate(this.centerWorld) <= -this.radiusWorld) {
                     return false;
@@ -121,7 +121,7 @@ import { Matrix, Vector3, Plane } from "Math/math";
          * @param point defines the point to test
          * @returns true if the point is inside the bounding sphere
          */
-        public intersectsPoint(point: Readonly<Vector3>): boolean {
+        public intersectsPoint(point: DeepImmutable<Vector3>): boolean {
             const squareDistance = Vector3.DistanceSquared(this.centerWorld, point);
             if (this.radiusWorld * this.radiusWorld < squareDistance) {
                 return false;
@@ -137,7 +137,7 @@ import { Matrix, Vector3, Plane } from "Math/math";
          * @param sphere1 sphere 1
          * @returns true if the speres intersect
          */
-        public static Intersects(sphere0: Readonly<BoundingSphere>, sphere1: Readonly<BoundingSphere>): boolean {
+        public static Intersects(sphere0: DeepImmutable<BoundingSphere>, sphere1: DeepImmutable<BoundingSphere>): boolean {
             const squareDistance = Vector3.DistanceSquared(sphere0.centerWorld, sphere1.centerWorld);
             const radiusSum = sphere0.radiusWorld + sphere1.radiusWorld;
 

+ 14 - 14
src/Culling/ray.ts

@@ -34,7 +34,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param intersectionTreshold extra extend to be added to the box in all direction
          * @returns if the box was hit
          */
-        public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3, intersectionTreshold: number = 0): boolean {
+        public intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold: number = 0): boolean {
             const newMinimum = Ray.TmpVector3[0].copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
             const newMaximum = Ray.TmpVector3[1].copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
             var d = 0.0;
@@ -134,7 +134,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          */
-        public intersectsBox(box: BoundingBox, intersectionTreshold: number = 0): boolean {
+        public intersectsBox(box: DeepImmutable<BoundingBox>, intersectionTreshold: number = 0): boolean {
             return this.intersectsBoxMinMax(box.minimum, box.maximum, intersectionTreshold);
         }
 
@@ -144,7 +144,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param intersectionTreshold extra extend to be added to the BoundingSphere in all direction
          * @returns true if it hits the sphere
          */
-        public intersectsSphere(sphere: BoundingSphere, intersectionTreshold: number = 0): boolean {
+        public intersectsSphere(sphere: DeepImmutable<BoundingSphere>, intersectionTreshold: number = 0): boolean {
             var x = sphere.center.x - this.origin.x;
             var y = sphere.center.y - this.origin.y;
             var z = sphere.center.z - this.origin.z;
@@ -173,7 +173,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param vertex2 triangle vertex
          * @returns intersection information if hit
          */
-        public intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): Nullable<IntersectionInfo> {
+        public intersectsTriangle(vertex0: DeepImmutable<Vector3>, vertex1: DeepImmutable<Vector3>, vertex2: DeepImmutable<Vector3>): Nullable<IntersectionInfo> {
             const edge1 = Ray.TmpVector3[0];
             const edge2 = Ray.TmpVector3[1];
             const pvec = Ray.TmpVector3[2];
@@ -221,7 +221,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param plane the plane to check
          * @returns the distance away it was hit
          */
-        public intersectsPlane(plane: Plane): Nullable<number> {
+        public intersectsPlane(plane: DeepImmutable<Plane>): Nullable<number> {
             var distance: number;
             var result1 = Vector3.Dot(plane.normal, this.direction);
             if (Math.abs(result1) < 9.99999997475243E-07) {
@@ -248,7 +248,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param fastCheck if only the bounding box should checked
          * @returns picking info of the intersecton
          */
-        public intersectsMesh(mesh: AbstractMesh, fastCheck?: boolean): PickingInfo {
+        public intersectsMesh(mesh: DeepImmutable<AbstractMesh>, fastCheck?: boolean): PickingInfo {
 
             var tm = Tmp.Matrix[0];
 
@@ -271,7 +271,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param results array to store result in
          * @returns Array of picking infos
          */
-        public intersectsMeshes(meshes: Array<AbstractMesh>, fastCheck?: boolean, results?: Array<PickingInfo>): Array<PickingInfo> {
+        public intersectsMeshes(meshes: Array<DeepImmutable<AbstractMesh>>, fastCheck?: boolean, results?: Array<PickingInfo>): Array<PickingInfo> {
 
             if (results) {
                 results.length = 0;
@@ -293,7 +293,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
 
         }
 
-        private _comparePickingInfo(pickingInfoA: PickingInfo, pickingInfoB: PickingInfo): number {
+        private _comparePickingInfo(pickingInfoA: DeepImmutable<PickingInfo>, pickingInfoB: DeepImmutable<PickingInfo>): number {
 
             if (pickingInfoA.distance < pickingInfoB.distance) {
                 return -1;
@@ -315,7 +315,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param threshold the tolerance margin, if the ray doesn't intersect the segment but is close to the given threshold, the intersection is successful
          * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
          */
-        intersectionSegment(sega: Vector3, segb: Vector3, threshold: number): number {
+        intersectionSegment(sega: DeepImmutable<Vector3>, segb: DeepImmutable<Vector3>, threshold: number): number {
             const o = this.origin;
             const u =  Tmp.Vector3[0];
             const rsegb  = Tmp.Vector3[1];
@@ -413,7 +413,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param projection projection matrix
          * @returns this ray updated
          */
-        public update(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Readonly<Matrix>, view: Readonly<Matrix>, projection: Readonly<Matrix>): Ray {
+        public update(x: number, y: number, viewportWidth: number, viewportHeight: number, world: DeepImmutable<Matrix>, view: DeepImmutable<Matrix>, projection: DeepImmutable<Matrix>): Ray {
             Vector3.UnprojectRayToRef(x, y, viewportWidth, viewportHeight, world, view, projection, this);
             return this;
         }
@@ -438,7 +438,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param projection projection matrix
          * @returns new ray
          */
-        public static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
+        public static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: DeepImmutable<Matrix>, view: DeepImmutable<Matrix>, projection: DeepImmutable<Matrix>): Ray {
             let result = Ray.Zero();
 
             return result.update(x, y, viewportWidth, viewportHeight, world, view, projection);
@@ -452,7 +452,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
         * @param world a matrix to transform the ray to. Default is the identity matrix.
         * @returns the new ray
         */
-        public static CreateNewFromTo(origin: Vector3, end: Vector3, world: Readonly<Matrix> = Matrix.IdentityReadOnly): Ray {
+        public static CreateNewFromTo(origin: DeepImmutable<Vector3>, end: DeepImmutable<Vector3>, world: DeepImmutable<Matrix> = Matrix.IdentityReadOnly): Ray {
             var direction = end.subtract(origin);
             var length = Math.sqrt((direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z));
             direction.normalize();
@@ -466,7 +466,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param matrix matrix to apply
          * @returns the resulting new ray
          */
-        public static Transform(ray: Ray, matrix: Readonly<Matrix>): Ray {
+        public static Transform(ray: DeepImmutable<Ray>, matrix: DeepImmutable<Matrix>): Ray {
             var result = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0));
             Ray.TransformToRef(ray, matrix, result);
 
@@ -479,7 +479,7 @@ import { BoundingBox, BoundingSphere } from "Culling";
          * @param matrix matrix to apply
          * @param result ray to store result in
          */
-        public static TransformToRef(ray: Ray, matrix: Readonly<Matrix>, result: Ray): void {
+        public static TransformToRef(ray: DeepImmutable<Ray>, matrix: DeepImmutable<Matrix>, result: Ray): void {
             Vector3.TransformCoordinatesToRef(ray.origin, matrix, result.origin);
             Vector3.TransformNormalToRef(ray.direction, matrix, result.direction);
             result.length = ray.length;

File diff suppressed because it is too large
+ 237 - 230
src/Math/math.ts


+ 1 - 1
src/Mesh/transformNode.ts

@@ -315,7 +315,7 @@ import { Bone } from "Bones/bone";
          * @param postMultiplyPivotMatrix defines if the pivot matrix must be cancelled in the world matrix. When this parameter is set to true (default), the inverse of the pivot matrix is also applied at the end to cancel the transformation effect
          * @returns the current TransformNode
         */
-        public setPivotMatrix(matrix: Readonly<Matrix>, postMultiplyPivotMatrix = true): TransformNode {
+        public setPivotMatrix(matrix: DeepImmutable<Matrix>, postMultiplyPivotMatrix = true): TransformNode {
             this._pivotMatrix.copyFrom(matrix);
             this._cache.pivotMatrixUpdated = true;
             this._postMultiplyPivotMatrix = postMultiplyPivotMatrix;

+ 34 - 0
src/types.ts

@@ -25,3 +25,37 @@
      * Alias for types that can be used by a Buffer or VertexBuffer.
      */
     export type DataArray = number[] | ArrayBuffer | ArrayBufferView;
+
+    /**
+     * Alias type for primitive types
+     * @ignorenaming
+     */
+    type Primitive = undefined | null | boolean | string | number | Function;
+
+    /**
+     * Type modifier to make all the properties of an object Readonly
+     */
+    export type Immutable<T> = T extends Primitive
+      ? T
+      : T extends Array<infer U>
+        ? ReadonlyArray<U>
+        : /* T extends Map<infer K, infer V> ? ReadonlyMap<K, V> : // es2015+ only */
+          DeepImmutable<T>;
+
+    /**
+     * Type modifier to make all the properties of an object Readonly recursively
+     */
+    export type DeepImmutable<T> = T extends Primitive
+      ? T
+      : T extends Array<infer U>
+        ? DeepImmutableArray<U>
+        : /* T extends Map<infer K, infer V> ? DeepImmutableMap<K, V> : // es2015+ only */
+          DeepImmutableObject<T>;
+
+    /** @hidden */
+    interface DeepImmutableArray<T> extends ReadonlyArray<DeepImmutable<T>> {}
+    /** @hidden */
+    /* interface DeepImmutableMap<K, V> extends ReadonlyMap<DeepImmutable<K>, DeepImmutable<V>> {} // es2015+ only */
+    /** @hidden */
+    type DeepImmutableObject<T> = { readonly [K in keyof T]: DeepImmutable<T[K]> };
+}