Pārlūkot izejas kodu

Firs step toward nullEngine

David Catuhe 7 gadi atpakaļ
vecāks
revīzija
63f753c3b5

+ 6 - 0
.vscode/launch.json

@@ -2,6 +2,12 @@
     "version": "0.1.0",
     "configurations": [
         {
+            "name": "Launch nullEngine",
+            "type": "node",
+            "request": "launch",
+            "program": "${workspaceFolder}/tests/nullEngine/app.js"
+        },
+        {
             "name": "Launch sandbox (Chrome)",
             "type": "chrome",
             "request": "launch",

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1502 - 1453
dist/preview release/babylon.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 47 - 47
dist/preview release/babylon.js


+ 238 - 21
dist/preview release/babylon.max.js

@@ -5876,7 +5876,7 @@ var BABYLON;
         Tools.GetPointerPrefix = function () {
             var eventPrefix = "pointer";
             // Check if pointer events are supported
-            if (!window.PointerEvent && !navigator.pointerEnabled) {
+            if (Tools.IsWindowObjectExist() && !window.PointerEvent && !navigator.pointerEnabled) {
                 eventPrefix = "mouse";
             }
             return eventPrefix;
@@ -5886,7 +5886,12 @@ var BABYLON;
          * @param requester - the object that will request the next frame. Falls back to window.
          */
         Tools.QueueNewFrame = function (func, requester) {
-            if (requester === void 0) { requester = window; }
+            if (!Tools.IsWindowObjectExist()) {
+                return setTimeout(func, 16);
+            }
+            if (!requester) {
+                requester = window;
+            }
             if (requester.requestAnimationFrame) {
                 return requester.requestAnimationFrame(func);
             }
@@ -6026,7 +6031,7 @@ var BABYLON;
                     // In case of undefined state in some browsers.
                     if (request.readyState === (XMLHttpRequest.DONE || 4)) {
                         request.onreadystatechange = null; //some browsers have issues where onreadystatechange can be called multiple times with the same value
-                        if (request.status >= 200 && request.status < 300 || (navigator.isCocoonJS && (request.status === 0))) {
+                        if (request.status >= 200 && request.status < 300 || (!Tools.IsWindowObjectExist() && (request.status === 0))) {
                             callback(!useArrayBuffer ? request.responseText : request.response);
                         }
                         else {
@@ -6542,6 +6547,9 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Tools.IsWindowObjectExist = function () {
+            return (typeof window) !== "undefined";
+        };
         Object.defineProperty(Tools, "PerformanceNoneLogLevel", {
             get: function () {
                 return Tools._PerformanceNoneLogLevel;
@@ -6587,6 +6595,12 @@ var BABYLON;
         };
         Tools._StartUserMark = function (counterName, condition) {
             if (condition === void 0) { condition = true; }
+            if (!Tools._performance) {
+                if (!Tools.IsWindowObjectExist()) {
+                    return;
+                }
+                Tools._performance = window.performance;
+            }
             if (!condition || !Tools._performance.mark) {
                 return;
             }
@@ -6622,7 +6636,7 @@ var BABYLON;
         };
         Object.defineProperty(Tools, "Now", {
             get: function () {
-                if (window.performance && window.performance.now) {
+                if (Tools.IsWindowObjectExist() && window.performance && window.performance.now) {
                     return window.performance.now();
                 }
                 return new Date().getTime();
@@ -6753,7 +6767,6 @@ var BABYLON;
         Tools._PerformanceNoneLogLevel = 0;
         Tools._PerformanceUserMarkLogLevel = 1;
         Tools._PerformanceConsoleLogLevel = 2;
-        Tools._performance = window.performance;
         Tools.StartPerformanceCounter = Tools._StartPerformanceCounterDisabled;
         Tools.EndPerformanceCounter = Tools._EndPerformanceCounterDisabled;
         return Tools;
@@ -7793,6 +7806,9 @@ var BABYLON;
             };
             var canvas;
             Engine.Instances.push(this);
+            if (!canvasOrContext) {
+                return;
+            }
             options = options || {};
             if (canvasOrContext.getContext) {
                 canvas = canvasOrContext;
@@ -8766,7 +8782,7 @@ var BABYLON;
             }
             if (this._activeRenderLoops.length > 0) {
                 // Register new frame
-                var requester = window;
+                var requester = null;
                 if (this._vrDisplay && this._vrDisplay.isPresenting)
                     requester = this._vrDisplay;
                 this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction, requester);
@@ -16947,7 +16963,9 @@ var BABYLON;
             if (BABYLON.OutlineRenderer) {
                 this._outlineRenderer = new BABYLON.OutlineRenderer(this);
             }
-            this.attachControl();
+            if (BABYLON.Tools.IsWindowObjectExist()) {
+                this.attachControl();
+            }
             //simplification queue
             if (BABYLON.SimplificationQueue) {
                 this.simplificationQueue = new BABYLON.SimplificationQueue();
@@ -24812,11 +24830,13 @@ var BABYLON;
             });
         };
         Effect.prototype._loadVertexShader = function (vertex, callback) {
-            // DOM element ?
-            if (vertex instanceof HTMLElement) {
-                var vertexCode = BABYLON.Tools.GetDOMTextContent(vertex);
-                callback(vertexCode);
-                return;
+            if (BABYLON.Tools.IsWindowObjectExist()) {
+                // DOM element ?
+                if (vertex instanceof HTMLElement) {
+                    var vertexCode = BABYLON.Tools.GetDOMTextContent(vertex);
+                    callback(vertexCode);
+                    return;
+                }
             }
             // Base64 encoded ?
             if (vertex.substr(0, 7) === "base64:") {
@@ -24840,11 +24860,13 @@ var BABYLON;
             BABYLON.Tools.LoadFile(vertexShaderUrl + ".vertex.fx", callback);
         };
         Effect.prototype._loadFragmentShader = function (fragment, callback) {
-            // DOM element ?
-            if (fragment instanceof HTMLElement) {
-                var fragmentCode = BABYLON.Tools.GetDOMTextContent(fragment);
-                callback(fragmentCode);
-                return;
+            if (BABYLON.Tools.IsWindowObjectExist()) {
+                // DOM element ?
+                if (fragment instanceof HTMLElement) {
+                    var fragmentCode = BABYLON.Tools.GetDOMTextContent(fragment);
+                    callback(fragmentCode);
+                    return;
+                }
             }
             // Base64 encoded ?
             if (fragment.substr(0, 7) === "base64:") {
@@ -65490,8 +65512,7 @@ var BABYLON;
                 this._createInspector(config);
             }
         };
-        // Get protocol used - http or https
-        DebugLayer.InspectorURL = window.location.href.split('/')[0] + '//preview.babylonjs.com/inspector/babylon.inspector.bundle.js';
+        DebugLayer.InspectorURL = 'https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js';
         return DebugLayer;
     }());
     BABYLON.DebugLayer = DebugLayer;
@@ -73304,15 +73325,211 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    var NullEngineOptions = (function () {
+        function NullEngineOptions() {
+            this.renderWidth = 512;
+            this.renderHeight = 256;
+            this.textureSize = 512;
+        }
+        return NullEngineOptions;
+    }());
+    BABYLON.NullEngineOptions = NullEngineOptions;
     /**
      * The null engine class provides support for headless version of babylon.js.
      * This can be used in server side scenario or for testing purposes
      */
     var NullEngine = (function (_super) {
         __extends(NullEngine, _super);
-        function NullEngine() {
-            return _super.call(this, null) || this;
+        function NullEngine(options) {
+            if (options === void 0) { options = new NullEngineOptions(); }
+            var _this = _super.call(this, null) || this;
+            _this._options = options;
+            // Init caps
+            // We consider we are on a webgl1 capable device
+            _this._caps = new BABYLON.EngineCapabilities();
+            _this._caps.maxTexturesImageUnits = 16;
+            _this._caps.maxVertexTextureImageUnits = 16;
+            _this._caps.maxTextureSize = 512;
+            _this._caps.maxCubemapTextureSize = 512;
+            _this._caps.maxRenderTextureSize = 512;
+            _this._caps.maxVertexAttribs = 16;
+            _this._caps.maxVaryingVectors = 16;
+            _this._caps.maxFragmentUniformVectors = 16;
+            _this._caps.maxVertexUniformVectors = 16;
+            // Extensions
+            _this._caps.standardDerivatives = false;
+            _this._caps.astc = null;
+            _this._caps.s3tc = null;
+            _this._caps.pvrtc = null;
+            _this._caps.etc1 = null;
+            _this._caps.etc2 = null;
+            _this._caps.textureAnisotropicFilterExtension = null;
+            _this._caps.maxAnisotropy = 0;
+            _this._caps.uintIndices = false;
+            _this._caps.fragmentDepthSupported = false;
+            _this._caps.highPrecisionShaderSupported = true;
+            _this._caps.colorBufferFloat = false;
+            _this._caps.textureFloat = false;
+            _this._caps.textureFloatLinearFiltering = false;
+            _this._caps.textureFloatRender = false;
+            _this._caps.textureHalfFloat = false;
+            _this._caps.textureHalfFloatLinearFiltering = false;
+            _this._caps.textureHalfFloatRender = false;
+            _this._caps.textureLOD = false;
+            _this._caps.drawBuffersExtension = false;
+            _this._caps.depthTextureExtension = false;
+            _this._caps.vertexArrayObject = false;
+            _this._caps.instancedArrays = false;
+            BABYLON.Tools.Log("Babylon.js null engine (v" + BABYLON.Engine.Version + ") launched");
+            return _this;
         }
+        NullEngine.prototype.createVertexBuffer = function (vertices) {
+            return {
+                capacity: 0,
+                references: 1,
+                is32Bits: false
+            };
+        };
+        NullEngine.prototype.createIndexBuffer = function (indices) {
+            return {
+                capacity: 0,
+                references: 1,
+                is32Bits: false
+            };
+        };
+        NullEngine.prototype.clear = function (color, backBuffer, depth, stencil) {
+            if (stencil === void 0) { stencil = false; }
+        };
+        NullEngine.prototype.getRenderWidth = function (useScreen) {
+            if (useScreen === void 0) { useScreen = false; }
+            if (!useScreen && this._currentRenderTarget) {
+                return this._currentRenderTarget.width;
+            }
+            return this._options.renderWidth;
+        };
+        NullEngine.prototype.getRenderHeight = function (useScreen) {
+            if (useScreen === void 0) { useScreen = false; }
+            if (!useScreen && this._currentRenderTarget) {
+                return this._currentRenderTarget.height;
+            }
+            return this._options.renderHeight;
+        };
+        NullEngine.prototype.setViewport = function (viewport, requiredWidth, requiredHeight) {
+            var width = requiredWidth || this.getRenderWidth();
+            var height = requiredHeight || this.getRenderHeight();
+            var x = viewport.x || 0;
+            var y = viewport.y || 0;
+            this._cachedViewport = viewport;
+        };
+        NullEngine.prototype.createShaderProgram = function (vertexCode, fragmentCode, defines, context) {
+            return {};
+        };
+        NullEngine.prototype.getUniforms = function (shaderProgram, uniformsNames) {
+            return [];
+        };
+        NullEngine.prototype.getAttributes = function (shaderProgram, attributesNames) {
+            return [];
+        };
+        NullEngine.prototype.bindSamplers = function (effect) {
+            this._currentEffect = null;
+        };
+        NullEngine.prototype.enableEffect = function (effect) {
+            this._currentEffect = effect;
+            if (effect.onBind) {
+                effect.onBind(effect);
+            }
+            effect.onBindObservable.notifyObservers(effect);
+        };
+        NullEngine.prototype.setState = function (culling, zOffset, force, reverseSide) {
+            if (zOffset === void 0) { zOffset = 0; }
+            if (reverseSide === void 0) { reverseSide = false; }
+        };
+        NullEngine.prototype.setIntArray = function (uniform, array) {
+        };
+        NullEngine.prototype.setIntArray2 = function (uniform, array) {
+        };
+        NullEngine.prototype.setIntArray3 = function (uniform, array) {
+        };
+        NullEngine.prototype.setIntArray4 = function (uniform, array) {
+        };
+        NullEngine.prototype.setFloatArray = function (uniform, array) {
+        };
+        NullEngine.prototype.setFloatArray2 = function (uniform, array) {
+        };
+        NullEngine.prototype.setFloatArray3 = function (uniform, array) {
+        };
+        NullEngine.prototype.setFloatArray4 = function (uniform, array) {
+        };
+        NullEngine.prototype.setArray = function (uniform, array) {
+        };
+        NullEngine.prototype.setArray2 = function (uniform, array) {
+        };
+        NullEngine.prototype.setArray3 = function (uniform, array) {
+        };
+        NullEngine.prototype.setArray4 = function (uniform, array) {
+        };
+        NullEngine.prototype.setMatrices = function (uniform, matrices) {
+        };
+        NullEngine.prototype.setMatrix = function (uniform, matrix) {
+        };
+        NullEngine.prototype.setMatrix3x3 = function (uniform, matrix) {
+        };
+        NullEngine.prototype.setMatrix2x2 = function (uniform, matrix) {
+        };
+        NullEngine.prototype.setFloat = function (uniform, value) {
+        };
+        NullEngine.prototype.setFloat2 = function (uniform, x, y) {
+        };
+        NullEngine.prototype.setFloat3 = function (uniform, x, y, z) {
+        };
+        NullEngine.prototype.setBool = function (uniform, bool) {
+        };
+        NullEngine.prototype.setFloat4 = function (uniform, x, y, z, w) {
+        };
+        NullEngine.prototype.setColor3 = function (uniform, color3) {
+        };
+        NullEngine.prototype.setColor4 = function (uniform, color3, alpha) {
+        };
+        NullEngine.prototype.setAlphaMode = function (mode, noDepthWriteChange) {
+            if (noDepthWriteChange === void 0) { noDepthWriteChange = false; }
+            if (this._alphaMode === mode) {
+                return;
+            }
+            this._alphaState.alphaBlend = (mode !== BABYLON.Engine.ALPHA_DISABLE);
+            if (!noDepthWriteChange) {
+                this.setDepthWrite(mode === BABYLON.Engine.ALPHA_DISABLE);
+            }
+            this._alphaMode = mode;
+        };
+        NullEngine.prototype.bindBuffers = function (vertexBuffers, indexBuffer, effect) {
+        };
+        NullEngine.prototype.draw = function (useTriangles, indexStart, indexCount, instancesCount) {
+        };
+        NullEngine.prototype._createTexture = function () {
+            return {};
+        };
+        NullEngine.prototype.createTexture = function (urlArg, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallBack, format) {
+            if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
+            if (onLoad === void 0) { onLoad = null; }
+            if (onError === void 0) { onError = null; }
+            if (buffer === void 0) { buffer = null; }
+            var texture = new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_URL);
+            var url = String(urlArg);
+            texture.url = url;
+            texture.generateMipMaps = !noMipmap;
+            texture.samplingMode = samplingMode;
+            texture.invertY = invertY;
+            texture.baseWidth = this._options.textureSize;
+            texture.baseHeight = this._options.textureSize;
+            texture.width = this._options.textureSize;
+            texture.height = this._options.textureSize;
+            texture.format = format;
+            texture.isReady = true;
+            if (onLoad) {
+                onLoad();
+            }
+            return texture;
+        };
         return NullEngine;
     }(BABYLON.Engine));
     BABYLON.NullEngine = NullEngine;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1502 - 1453
dist/preview release/babylon.module.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 47 - 47
dist/preview release/babylon.worker.js


+ 1 - 2
src/Debug/babylon.debugLayer.ts

@@ -5,8 +5,7 @@ module BABYLON {
 
     export class DebugLayer {
         private _scene: Scene;
-        // Get protocol used - http or https
-        public static InspectorURL = window.location.href.split('/')[0] + '//preview.babylonjs.com/inspector/babylon.inspector.bundle.js';
+        public static InspectorURL = 'https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js';
         // The inspector instance
         private _inspector: any;
 

+ 6 - 6
src/Engine/babylon.engine.ts

@@ -675,24 +675,24 @@
         // States
         private _depthCullingState = new Internals._DepthCullingState();
         private _stencilState = new Internals._StencilState();
-        private _alphaState = new Internals._AlphaState();
-        private _alphaMode = Engine.ALPHA_DISABLE;
+        protected _alphaState = new Internals._AlphaState();
+        protected _alphaMode = Engine.ALPHA_DISABLE;
 
         // Cache
         private _internalTexturesCache = new Array<InternalTexture>();
         private _maxTextureChannels = 16;
         private _activeTexture: number;
         private _activeTexturesCache: { [key: string]: WebGLTexture } = {};
-        private _currentEffect: Effect;
+        protected _currentEffect: Effect;
         private _currentProgram: WebGLProgram;
         private _compiledEffects = {};
         private _vertexAttribArraysEnabled: boolean[] = [];
-        private _cachedViewport: Viewport;
+        protected _cachedViewport: Viewport;
         private _cachedVertexArrayObject: WebGLVertexArrayObject;
         private _cachedVertexBuffers: any;
         private _cachedIndexBuffer: WebGLBuffer;
         private _cachedEffectForVertexBuffers: Effect;
-        private _currentRenderTarget: InternalTexture;
+        protected _currentRenderTarget: InternalTexture;
         private _uintIndicesCurrentlySet = false;
         private _currentBoundBuffer = new Array<WebGLBuffer>();
         private _currentFramebuffer: WebGLFramebuffer;
@@ -1418,7 +1418,7 @@
 
             if (this._activeRenderLoops.length > 0) {
                 // Register new frame
-                var requester = window;
+                var requester = null;
                 if (this._vrDisplay && this._vrDisplay.isPresenting)
                     requester = this._vrDisplay;
                 this._frameHandler = Tools.QueueNewFrame(this._bindedRenderFunction, requester);

+ 202 - 2
src/Engine/babylon.nullEngine.ts

@@ -1,13 +1,24 @@
 module BABYLON {
+
+    export class NullEngineOptions {
+        public renderWidth = 512;
+        public renderHeight = 256;
+
+        public textureSize = 512;
+    }
    
     /**
      * The null engine class provides support for headless version of babylon.js.
      * This can be used in server side scenario or for testing purposes
      */
-    export class NullEngine extends Engine {     
-        public constructor() {
+    export class NullEngine extends Engine {  
+        private _options: NullEngineOptions;
+
+        public constructor(options: NullEngineOptions = new NullEngineOptions()) {
             super(null);
 
+            this._options = options;
+
             // Init caps
             // We consider we are on a webgl1 capable device
 
@@ -52,6 +63,195 @@
             this._caps.depthTextureExtension = false;
             this._caps.vertexArrayObject = false;
             this._caps.instancedArrays = false;
+
+            Tools.Log("Babylon.js null engine (v" + Engine.Version + ") launched");
+        }
+
+        public createVertexBuffer(vertices: number[] | Float32Array): WebGLBuffer {
+            return {
+                capacity: 0,
+                references: 1,
+                is32Bits: false
+            };
+        }
+
+        public createIndexBuffer(indices: IndicesArray): WebGLBuffer {
+            return {
+                capacity: 0,
+                references: 1,
+                is32Bits: false
+            };
+        }
+
+        public clear(color: Color4, backBuffer: boolean, depth: boolean, stencil: boolean = false): void {
+        }
+
+        public getRenderWidth(useScreen = false): number {
+            if (!useScreen && this._currentRenderTarget) {
+                return this._currentRenderTarget.width;
+            }
+
+            return this._options.renderWidth;
+        }
+
+        public getRenderHeight(useScreen = false): number {
+            if (!useScreen && this._currentRenderTarget) {
+                return this._currentRenderTarget.height;
+            }
+
+            return this._options.renderHeight;
+        }
+
+        public setViewport(viewport: Viewport, requiredWidth?: number, requiredHeight?: number): void {
+            var width = requiredWidth || this.getRenderWidth();
+            var height = requiredHeight || this.getRenderHeight();
+            var x = viewport.x || 0;
+            var y = viewport.y || 0;
+
+            this._cachedViewport = viewport;
+        }
+
+        public createShaderProgram(vertexCode: string, fragmentCode: string, defines: string, context?: WebGLRenderingContext): WebGLProgram {
+            return {};
+        }
+
+        public getUniforms(shaderProgram: WebGLProgram, uniformsNames: string[]): WebGLUniformLocation[] {
+            return [];
+        }
+
+        public getAttributes(shaderProgram: WebGLProgram, attributesNames: string[]): number[] {
+            return [];
+        }
+
+        public bindSamplers(effect: Effect): void {
+            this._currentEffect = null;
+        }
+
+        public enableEffect(effect: Effect): void {
+            this._currentEffect = effect;
+
+            if (effect.onBind) {
+                effect.onBind(effect);
+            }
+            effect.onBindObservable.notifyObservers(effect);
+        }   
+        
+        public setState(culling: boolean, zOffset: number = 0, force?: boolean, reverseSide = false): void {
+        }        
+        
+        public setIntArray(uniform: WebGLUniformLocation, array: Int32Array): void {
+        }
+
+        public setIntArray2(uniform: WebGLUniformLocation, array: Int32Array): void {
+        }
+
+        public setIntArray3(uniform: WebGLUniformLocation, array: Int32Array): void {
+        }
+
+        public setIntArray4(uniform: WebGLUniformLocation, array: Int32Array): void {
+        }
+
+        public setFloatArray(uniform: WebGLUniformLocation, array: Float32Array): void {
+        }
+
+        public setFloatArray2(uniform: WebGLUniformLocation, array: Float32Array): void {
+        }
+
+        public setFloatArray3(uniform: WebGLUniformLocation, array: Float32Array): void {
+        }
+
+        public setFloatArray4(uniform: WebGLUniformLocation, array: Float32Array): void {
+        }
+
+        public setArray(uniform: WebGLUniformLocation, array: number[]): void {
+        }
+
+        public setArray2(uniform: WebGLUniformLocation, array: number[]): void {
+        }
+
+        public setArray3(uniform: WebGLUniformLocation, array: number[]): void {
+        }
+
+        public setArray4(uniform: WebGLUniformLocation, array: number[]): void {
+        }
+
+        public setMatrices(uniform: WebGLUniformLocation, matrices: Float32Array): void {
+        }
+
+        public setMatrix(uniform: WebGLUniformLocation, matrix: Matrix): void {
+        }
+
+        public setMatrix3x3(uniform: WebGLUniformLocation, matrix: Float32Array): void {
+        }
+
+        public setMatrix2x2(uniform: WebGLUniformLocation, matrix: Float32Array): void {
+        }
+
+        public setFloat(uniform: WebGLUniformLocation, value: number): void {
+        }
+
+        public setFloat2(uniform: WebGLUniformLocation, x: number, y: number): void {
+        }
+
+        public setFloat3(uniform: WebGLUniformLocation, x: number, y: number, z: number): void {
+        }
+
+        public setBool(uniform: WebGLUniformLocation, bool: number): void {
+        }
+
+        public setFloat4(uniform: WebGLUniformLocation, x: number, y: number, z: number, w: number): void {
+        }
+
+        public setColor3(uniform: WebGLUniformLocation, color3: Color3): void {
+        }
+
+        public setColor4(uniform: WebGLUniformLocation, color3: Color3, alpha: number): void {
+        }
+
+        public setAlphaMode(mode: number, noDepthWriteChange: boolean = false): void {
+            if (this._alphaMode === mode) {
+                return;
+            }
+
+            this._alphaState.alphaBlend = (mode !== Engine.ALPHA_DISABLE);
+
+            if (!noDepthWriteChange) {
+                this.setDepthWrite(mode === Engine.ALPHA_DISABLE);
+            }
+            this._alphaMode = mode;
+        }        
+
+        public bindBuffers(vertexBuffers: { [key: string]: VertexBuffer; }, indexBuffer: WebGLBuffer, effect: Effect): void {
+        }
+
+        public draw(useTriangles: boolean, indexStart: number, indexCount: number, instancesCount?: number): void {
+        }
+
+        public _createTexture(): WebGLTexture {
+            return {};
+        }
+
+        public createTexture(urlArg: string, noMipmap: boolean, invertY: boolean, scene: Scene, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, buffer: ArrayBuffer | HTMLImageElement = null, fallBack?: InternalTexture, format?: number): InternalTexture {
+            var texture = new InternalTexture(this, InternalTexture.DATASOURCE_URL);
+            var url = String(urlArg); 
+
+            texture.url = url;
+            texture.generateMipMaps = !noMipmap;
+            texture.samplingMode = samplingMode;
+            texture.invertY = invertY;
+            texture.baseWidth = this._options.textureSize;
+            texture.baseHeight = this._options.textureSize;
+            texture.width = this._options.textureSize;
+            texture.height = this._options.textureSize;            
+            texture.format = format;
+
+            texture.isReady = true;            
+
+            if (onLoad) {
+                onLoad();
+            }
+
+            return texture;
         }
     }
 }

+ 14 - 10
src/Materials/babylon.effect.ts

@@ -268,11 +268,13 @@
         }
 
         public _loadVertexShader(vertex: any, callback: (data: any) => void): void {
-            // DOM element ?
-            if (vertex instanceof HTMLElement) {
-                var vertexCode = Tools.GetDOMTextContent(vertex);
-                callback(vertexCode);
-                return;
+            if (Tools.IsWindowObjectExist()) {
+                // DOM element ?
+                if (vertex instanceof HTMLElement) {
+                    var vertexCode = Tools.GetDOMTextContent(vertex);
+                    callback(vertexCode);
+                    return;
+                }
             }
 
             // Base64 encoded ?
@@ -301,11 +303,13 @@
         }
 
         public _loadFragmentShader(fragment: any, callback: (data: any) => void): void {
-            // DOM element ?
-            if (fragment instanceof HTMLElement) {
-                var fragmentCode = Tools.GetDOMTextContent(fragment);
-                callback(fragmentCode);
-                return;
+            if (Tools.IsWindowObjectExist()) {
+                // DOM element ?
+                if (fragment instanceof HTMLElement) {
+                    var fragmentCode = Tools.GetDOMTextContent(fragment);
+                    callback(fragmentCode);
+                    return;
+                }
             }
 
             // Base64 encoded ?

+ 24 - 5
src/Tools/babylon.tools.ts

@@ -314,7 +314,7 @@
             var eventPrefix = "pointer";
 
             // Check if pointer events are supported
-            if (!window.PointerEvent && !navigator.pointerEnabled) {
+            if (Tools.IsWindowObjectExist() && !window.PointerEvent && !navigator.pointerEnabled) {
                 eventPrefix = "mouse";
             }
 
@@ -325,7 +325,15 @@
          * @param func - the function to be called
          * @param requester - the object that will request the next frame. Falls back to window.
          */
-        public static QueueNewFrame(func, requester: any = window): number {
+        public static QueueNewFrame(func, requester?): number {
+            if (!Tools.IsWindowObjectExist()) {
+                return setTimeout(func, 16);
+            }
+
+            if (!requester) {
+                requester = window;
+            }
+
             if (requester.requestAnimationFrame) {
                 return requester.requestAnimationFrame(func);
             }
@@ -491,7 +499,7 @@
                     if (request.readyState === (XMLHttpRequest.DONE || 4)) {
                         request.onreadystatechange = null;//some browsers have issues where onreadystatechange can be called multiple times with the same value
 
-                        if (request.status >= 200 && request.status < 300 || (navigator.isCocoonJS && (request.status === 0))) {
+                        if (request.status >= 200 && request.status < 300 || (!Tools.IsWindowObjectExist() && (request.status === 0))) {
                             callback(!useArrayBuffer ? request.responseText : request.response);
                         } else { // Failed
                             let e = new Error("Error status: " + request.status + " - Unable to load " + loadUrl);
@@ -1065,12 +1073,16 @@
             }
         }
 
+        public static IsWindowObjectExist(): boolean {
+            return (typeof window) !== "undefined";
+        }
+
         // Performances
         private static _PerformanceNoneLogLevel = 0;
         private static _PerformanceUserMarkLogLevel = 1;
         private static _PerformanceConsoleLogLevel = 2;
 
-        private static _performance: Performance = window.performance;
+        private static _performance: Performance;
 
         static get PerformanceNoneLogLevel(): number {
             return Tools._PerformanceNoneLogLevel;
@@ -1108,6 +1120,13 @@
         }
 
         static _StartUserMark(counterName: string, condition = true): void {
+            if (!Tools._performance) {
+                if (!Tools.IsWindowObjectExist()) {
+                    return;
+                }
+                Tools._performance = window.performance;
+            }
+
             if (!condition || !Tools._performance.mark) {
                 return;
             }
@@ -1150,7 +1169,7 @@
         public static EndPerformanceCounter: (counterName: string, condition?: boolean) => void = Tools._EndPerformanceCounterDisabled;
 
         public static get Now(): number {
-            if (window.performance && window.performance.now) {
+            if (Tools.IsWindowObjectExist() && window.performance && window.performance.now) {
                 return window.performance.now();
             }
 

+ 3 - 1
src/babylon.scene.ts

@@ -821,7 +821,9 @@
                 this._outlineRenderer = new OutlineRenderer(this);
             }
 
-            this.attachControl();
+            if (Tools.IsWindowObjectExist()) {
+                this.attachControl();
+            }
 
             //simplification queue
             if (SimplificationQueue) {

+ 113 - 0
tests/nullEngine/app.js

@@ -0,0 +1,113 @@
+//var LOADERS = require("../../dist/preview release/loaders/babylonjs.loaders");
+var BABYLON = require("../../dist/preview release/babylon.max");
+global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
+
+var engine = new BABYLON.NullEngine();
+var scene = new BABYLON.Scene(engine);
+
+// //Create a light
+// var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(-60, 60, 80), scene);
+
+// //Create an Arc Rotate Camera - aimed negative z this time
+// var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, 1.0, 110, BABYLON.Vector3.Zero(), scene);
+
+// //Creation of 6 spheres
+// var sphere1 = BABYLON.Mesh.CreateSphere("Sphere1", 10.0, 9.0, scene);
+// var sphere2 = BABYLON.Mesh.CreateSphere("Sphere2", 2.0, 9.0, scene);//Only two segments
+// var sphere3 = BABYLON.Mesh.CreateSphere("Sphere3", 10.0, 9.0, scene);
+// var sphere4 = BABYLON.Mesh.CreateSphere("Sphere4", 10.0, 9.0, scene);
+// var sphere5 = BABYLON.Mesh.CreateSphere("Sphere5", 10.0, 9.0, scene);
+// var sphere6 = BABYLON.Mesh.CreateSphere("Sphere6", 10.0, 9.0, scene);
+
+// //Position the spheres
+// sphere1.position.x = 40;
+// sphere2.position.x = 25;
+// sphere3.position.x = 10;
+// sphere4.position.x = -5;
+// sphere5.position.x = -20;
+// sphere6.position.x = -35;
+
+// //Creation of a plane
+// var plane = BABYLON.Mesh.CreatePlane("plane", 120, scene);
+// plane.position.y = -5;
+// plane.rotation.x = Math.PI / 2;
+
+// //Creation of a material with wireFrame
+// var materialSphere1 = new BABYLON.StandardMaterial("texture1", scene);
+// materialSphere1.wireframe = true;
+
+// //Creation of a red material with alpha
+// var materialSphere2 = new BABYLON.StandardMaterial("texture2", scene);
+// materialSphere2.diffuseColor = new BABYLON.Color3(1, 0, 0); //Red
+// materialSphere2.alpha = 0.3;
+
+// //Creation of a material with an image texture
+// var materialSphere3 = new BABYLON.StandardMaterial("texture3", scene);
+// materialSphere3.diffuseTexture = new BABYLON.Texture("textures/misc.jpg", scene);
+
+// //Creation of a material with translated texture
+// var materialSphere4 = new BABYLON.StandardMaterial("texture4", scene);
+// materialSphere4.diffuseTexture = new BABYLON.Texture("textures/misc.jpg", scene);
+// materialSphere4.diffuseTexture.vOffset = 0.1;//Vertical offset of 10%
+// materialSphere4.diffuseTexture.uOffset = 0.4;//Horizontal offset of 40%
+
+// //Creation of a material with an alpha texture
+// var materialSphere5 = new BABYLON.StandardMaterial("texture5", scene);
+// materialSphere5.diffuseTexture = new BABYLON.Texture("textures/tree.png", scene);
+// materialSphere5.diffuseTexture.hasAlpha = true;//Has an alpha
+
+// //Creation of a material and show all the faces
+// var materialSphere6 = new BABYLON.StandardMaterial("texture6", scene);
+// materialSphere6.diffuseTexture = new BABYLON.Texture("textures/tree.png", scene);
+// materialSphere6.diffuseTexture.hasAlpha = true;//Have an alpha
+// materialSphere6.backFaceCulling = false;//Show all the faces of the element
+
+// //Creation of a repeated textured material
+// var materialPlane = new BABYLON.StandardMaterial("texturePlane", scene);
+// materialPlane.diffuseTexture = new BABYLON.Texture("textures/grass.jpg", scene);
+// materialPlane.diffuseTexture.uScale = 5.0;//Repeat 5 times on the Vertical Axes
+// materialPlane.diffuseTexture.vScale = 5.0;//Repeat 5 times on the Horizontal Axes
+// materialPlane.backFaceCulling = false;//Always show the front and the back of an element
+
+// //Apply the materials to meshes
+// sphere1.material = materialSphere1;
+// sphere2.material = materialSphere2;
+
+// sphere3.material = materialSphere3;
+// sphere4.material = materialSphere4;
+
+// sphere5.material = materialSphere5;
+// sphere6.material = materialSphere6;
+
+// plane.material = materialPlane;
+
+//Adding a light
+var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(20, 20, 100), scene);
+
+//Adding an Arc Rotate Camera
+var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 100, BABYLON.Vector3.Zero(), scene);
+
+// The first parameter can be used to specify which mesh to import. Here we import all meshes
+BABYLON.SceneLoader.ImportMesh("", "https://playground.babylonjs.com/scenes/", "skull.babylon", scene, function (newMeshes) {
+    // Set the target of the camera to the first imported mesh
+    camera.target = newMeshes[0];
+
+    console.log("Meshes loaded from babylon file: " + newMeshes.length);
+    for (var index = 0; index < newMeshes.length; index++) {
+        console.log(newMeshes[index].toString());
+    }
+
+    BABYLON.SceneLoader.ImportMesh("", "https://www.babylonjs.com/Assets/DamagedHelmet/glTF/", "DamagedHelmet.gltf", scene, function (meshes) {
+        console.log("Meshes loaded from gltf file: " + meshes.length);
+        for (var index = 0; index < meshes.length; index++) {
+            console.log(meshes[index].toString());
+        }
+    });
+
+    console.log("render started")
+    engine.runRenderLoop(function() {
+        scene.render();
+    })
+});
+    
+

+ 5 - 0
tests/nullEngine/package.json

@@ -0,0 +1,5 @@
+{
+  "devDependencies": {
+    "xmlhttprequest": "^1.8.0"
+  }
+}