Guest User

3D OrderBook Visualizer

a guest
Sep 4th, 2018
145
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Source from this site -- http://globalliquidity.io/live.html
  2.  
  3.  
  4.         var canvas = document.getElementById("renderCanvas");
  5.        
  6.         var scene;
  7.         var spsBid;
  8.         var spsAsk;
  9.         var spsBuys;
  10.         var spsSells;
  11.         var spsChart;
  12.         var pl;
  13.         var camera;    
  14.         var wavesOffsetX = -32;
  15.         var wavesOffsetY = 0;
  16.         var wavesOffsetZ = -10;  
  17.         var cellWidth = 2;
  18.         var cellHeight = 5;
  19.         var cellDepth = 5;
  20.         var slopeFactor = 2;
  21.         var sizePhasor = 0;
  22.         var sizeStep = 0.05;
  23.         var music;
  24.         var finalVolume = 0.5;
  25.         var currentVolume = 0;
  26.         var logo;
  27.         var defaultPipeline;
  28.         var plasticMaterial;
  29.         var bidMaterial;
  30.         var askMaterial;
  31.         var buyMaterial;
  32.         var sellMaterial;
  33.         var candleMaterial;
  34.         var frequency = 0.3;
  35.         var numRows = 25;
  36.         var numColumns = 50;
  37.         var offsetZ = 80;
  38.         var scrollOffsetZ = 0;
  39.         var gridOffsetZ = 0;
  40.         var overallOffsetZ = 0;
  41.         var frontBarHeightMultiplier = 0;
  42.        
  43.         var midOffset;
  44.         var priceShiftFactor = 1;
  45.         var dataLoaded = false;
  46.         var updateIndex = 0;
  47.         var bidUpdateIndex = 0;
  48.         var askUpdateIndex = 0;
  49.         var tempUpdateIndex = 0;
  50.  
  51.         var myGround;
  52.         var gridMaterial;
  53.         var gridOffsetX = 0;
  54.         var gridOffsetZ = 0;
  55.         var cellPercentage = 0.01;
  56.         var initialFrontPrice = 0;
  57.         var currentFrame = 0;
  58.         var originPrice = 0;
  59.         var currentMidPrice = 0;
  60.         var midPriceMarker;
  61.         var bidPriceMarker;
  62.         var askPriceMarker;
  63.         var spreadMarker;
  64.         var spreadLabel;
  65.         var lowPriceMarker;
  66.         var highPriceMarker;
  67.         var lastTradeMarker;
  68.         var nextLowestTenMarker;
  69.         var nextHighestTenMarker;
  70.         var midPriceText;
  71.         var midPriceTexture;
  72.         var bidPriceTexture;
  73.         var askPriceTexture;
  74.         var spreadLabelTexture;
  75.  
  76.         var lowPriceTexture;
  77.         var highPriceTexture;
  78.         var lastTradeTexture;
  79.  
  80.         var nextLowestTenTexture;
  81.         var nextHighestTenTexture;
  82.  
  83.         var cells = new Array();
  84.         var bidRows = new Array();
  85.         var askRows = new Array();
  86.         var midPrices = new Array();
  87.         var tradeHistory = new Array();
  88.  
  89.         //var tradeHistoryDeque = new Deque();
  90.  
  91.         var symbol = 'BTCUSD';
  92.         var exchange = 'Binance';
  93.  
  94.  
  95.         let host = 'wss://feed.cryptoquote.io';
  96.         //let cryptoquoteKey = process.argv[2] ||  'CHANGE_ME';
  97.         let cryptoquoteKey = "e1983f70-a7e9-11e8-8362-5b2454c11240"; //prod
  98.         //let cryptoquoteKey = "698780e0-ab0e-11e8-a69f-6bd267699e4a"; //dev
  99.  
  100.         var ws = null;
  101.         var bookUrl = "https://feed.cryptoquote.io/api/v1/book/btcusd.binance/100";    
  102.  
  103.         let book = {
  104.             bids: [],
  105.             asks: []
  106.         };
  107.  
  108.         var bookHistory = new Array();
  109.  
  110.         var cameraHolder;
  111.  
  112.         var tradeMarkerAlpha = 1.0;
  113.  
  114.         var chartData = new Array();
  115.         var gotChartData = false;
  116.  
  117.         var enableLogging = false;
  118.  
  119.         var exchangePanel = null;
  120.         var exchangeButton = null;
  121.  
  122.         var symbolPanel = null;
  123.         var symbolButton = null;
  124.  
  125.         var priceOffsetMultiplier = 1;
  126.         var quantityScaleFactor = 1;
  127.         var chartAmplitude = 2;
  128.  
  129.         var cameraTweenEnabled = true;
  130.  
  131.         var resetCamera = true;
  132.         var cameraAlphaFalloff = 0.05;
  133.  
  134.         var currentMomentum = 0;
  135.         var momentumFactor = 1;
  136.         var minMomentum = -2;
  137.         var maxMomentum = 2;
  138.  
  139.         var previousMidPrice = 0;
  140.         var midpriceMarkerColor = "grey";
  141.  
  142.         var currentCandlePrice = 0;
  143.         var lowestCandlePrice = 0;
  144.         var highestCandlePrice = 0;
  145.  
  146.         var highPriceLine;
  147.  
  148.         var screenAspectRatio = 0;
  149.  
  150.         var timeDamper = 0;
  151.  
  152.         var maxTradeScale = 5.0;
  153.         var finalTradeScale = 1.0;
  154.         var tradeAttackFalloff = 0.15;
  155.         var tradeDecayFalloff = 0.05;
  156.  
  157.         //const request = require('request-promise');
  158.  
  159.         function reset()
  160.         {
  161.             if (enableLogging)
  162.                 BABYLON.Tools.Log("reset");
  163.  
  164.             //ws.close();
  165.  
  166.             //if (enableLogging)
  167.             //    BABYLON.Tools.Log("Closed WebSocket Feed...");
  168.  
  169.             bookHistory.splice(0,bookHistory.length)
  170.             book.bids.splice(0,book.bids.length);
  171.             book.asks.splice(0,book.asks.length);
  172.             tradeHistory.splice(0,tradeHistory.length);
  173.             //bidRows = new Array();
  174.  
  175.              if (enableLogging)
  176.                 BABYLON.Tools.Log("Bid History Length: " + bookHistory.length);
  177.  
  178.            
  179.  
  180.             dataLoaded = false;
  181.             originPrice = 0;
  182.             cameraTweenEnabled = false;
  183.             subscribeToMarket();
  184.            
  185.  
  186.            
  187.         }
  188.  
  189.         function findChartHiAndLow()
  190.         {
  191.             var lowest = Number.POSITIVE_INFINITY;
  192.             var highest = Number.NEGATIVE_INFINITY;
  193.             var tmpHi;
  194.             var tmpLow;
  195.             var hi;
  196.             var low;
  197.             for (var i=0; i<128; i++) {
  198.                 tmp = chartData[i][4];
  199.                 if (tmp < lowest) lowest = tmp;
  200.                 if (tmp > highest) highest = tmp;
  201.             }
  202.  
  203.             highestCandlePrice = highest;
  204.             lowestCandlePrice = lowest;
  205.             currentCandlePrice = chartData[0][4];
  206.  
  207.              if (enableLogging)
  208.                 BABYLON.Tools.Log("Chart Range: " + highestCandlePrice + " : " + lowestCandlePrice);  
  209.  
  210.  
  211.         }
  212.  
  213.         function fetchChartData(symbol, exchange)
  214.         {
  215.             if (enableLogging)
  216.                 BABYLON.Tools.Log("Getting Chart Data");  
  217.             var url = "https://feed.cryptoquote.io/bars/minutes/1/" + symbol + "." + exchange + ".internal/now";
  218.  
  219.              if (enableLogging)
  220.                 BABYLON.Tools.Log("Chart Url: " + url);
  221.  
  222.             //alert(url);
  223.             fetch(url)
  224.                 .then(function (response) {
  225.                     return response.json();
  226.                 })
  227.                 .then(function (myJson) {
  228.                     //let data = [];
  229.                     chartData.splice(0,chartData.length);
  230.                     myJson.bars.bars.forEach((b) => {
  231.                         chartData.push([b.time, b.open, b.high, b.low, b.close])
  232.                     });
  233.                     gotChartData = true;
  234.                     buildChart();
  235.                     findChartHiAndLow();
  236.                     //buildChart(data, symbol);
  237.                 });
  238.         }
  239.  
  240.    
  241.         function fetchData(symbol, exchange)
  242.         {    
  243.             var url = "https://feed.cryptoquote.io/api/v1/book/" + symbol + "." + exchange + "/100";
  244.  
  245.              if (enableLogging)
  246.                 BABYLON.Tools.Log("Book Url: " + url);
  247.  
  248.             fetch(url)
  249.                 .then(function (response) {
  250.                     return response.json();
  251.                 })
  252.                 .then(function (b) {
  253.                    
  254.                     b.bids.forEach((bid) => {
  255.                         //alert(bid[0]);
  256.                         book.bids.push({ price: bid[0], size: Number(bid[1].size) });
  257.                        
  258.                     });
  259.                     book.bids = book.bids.sort(compBids);
  260.                     b.asks.forEach((ask) => {
  261.                         book.asks.push({ price: ask[0], size: Number(ask[1].size) });
  262.                     });
  263.                     book.asks = book.asks.sort(compAsks);
  264.  
  265.                    
  266.  
  267.                     if (ws == null)
  268.                         openWebSocket();
  269.  
  270.                     dataLoaded = true;
  271.                     setTimeout(enableCameraTween,1000);
  272.                     calculateCurrentMid();
  273.                 });
  274.         }
  275.  
  276.         function openWebSocket()
  277.         {
  278.             ws = new WebSocket(`${host}/v1/firehose/${cryptoquoteKey}?services=book`);
  279.  
  280.              ws.onmessage = function (event) {
  281.  
  282.             //if ( dataLoaded == false)
  283.                 //dataLoaded = true;
  284.             //alert(event.data);
  285.             var m = JSON.parse(event.data);
  286.             if (m.updateType === 'book_update' && m.exchange.name === exchange && m.symbol === symbol)
  287.             {
  288.                 addOrUpdatePrice(m.side, m.price, Number(m.size));
  289.                 //var font = "bold 88px monospace";
  290.                
  291.                 calculateCurrentMid();
  292.                // midPriceTexture.drawText(currentMidPrice.toString(), 40, 135, font, "white", "gray", true, true);
  293.                
  294.             }
  295.             else if (m.updateType === 'trade' && m.exchange.name === exchange && m.symbol === symbol )
  296.             {
  297.                 //alert(m);
  298.                 //alert('trade');
  299.                 var tradeData = new Array();
  300.  
  301.                 var priceAsNumber = Number(m.lastTradePrice);
  302.  
  303.                 //var currentFrontMidPrice = midPrices[numRows - 1] + updateIndex;
  304.                 //var font = "bold 88px monospace";
  305.  
  306.                 var quantityAtPriceAtTimeOfTrade = 0;
  307.  
  308.                 if (priceAsNumber > currentMidPrice)
  309.                 {
  310.                     //alert("hi");
  311.                     tradeData[0] = "b";
  312.  
  313.                     let i = book.asks.findIndex(p => p.price ===priceAsNumber);
  314.  
  315.                     if (i > -1)
  316.                     {
  317.                         quantityAtPriceAtTimeOfTrade = book.asks[i].size;
  318.                     }
  319.                 }
  320.                 else
  321.                 {
  322.                     tradeData[0] = "s";
  323.  
  324.                     let i = book.bids.findIndex(p => p.price ===priceAsNumber);
  325.  
  326.                     if (i > -1)
  327.                     {
  328.                         quantityAtPriceAtTimeOfTrade = book.bids[i].size;
  329.                     }
  330.                     //lastTradeTexture.drawText ( priceAsNumber, 40, 135, font, "blue", "white", true, true);
  331.                 }
  332.  
  333.                 tradeData[1] = m.lastTradePrice;
  334.                 tradeData[2] = m.lastTradeSize;
  335.                 tradeData[3] = currentMidPrice;
  336.                 tradeData[4] = quantityAtPriceAtTimeOfTrade;
  337.                 tradeData[5] = tempUpdateIndex;
  338.                 tradeData[6] = true;
  339.  
  340.                 //alert(m.lastTradePrice);
  341.                 tradeHistory.unshift(tradeData);
  342.                 tradeMarkerAlpha = 1.0;          
  343.             }
  344.         }
  345.         }
  346.  
  347.         function addOrUpdatePrice(side, price, size) {
  348.             let ary = (side === 'buy') ? book.bids : book.asks;
  349.  
  350.             let i = ary.findIndex(p => p.price === price);
  351.  
  352.             if (i > -1 && size === 0.0) {
  353.                 // delete this price level
  354.                 ary.splice(i, 1);
  355.             } else if (i > -1) {
  356.                 // replace size at this price level
  357.                 ary[i].size = size;
  358.             } else if (size > 0.0) {
  359.                 // add to book
  360.                 ary.push({ price, size });
  361.             }
  362.  
  363.             if (side === 'buy')
  364.                 ary = ary.sort(compBids);
  365.             else
  366.                 ary = ary.sort(compAsks);
  367.         }
  368.  
  369.         var calculateCurrentMid = function ()
  370.         {            
  371.             if (dataLoaded)
  372.             {
  373.                
  374.                 var insideBid = book.bids[0].price
  375.                 var insideAsk = book.asks[0].price;
  376.                 currentMidPrice = Number(insideAsk- ( (insideAsk - insideBid) / 2 )).toFixed(3);
  377.  
  378.                 if ( Math.abs(currentMidPrice - previousMidPrice) >= 0.05)
  379.                 {
  380.                     //if (enableLogging)
  381.                     //     BABYLON.Tools.Log("Previous: " + previousMidPrice + " Current: " + currentMidPrice);
  382.                
  383.                     previousMidPrice = currentMidPrice;
  384.                 }
  385.  
  386.                 if (originPrice == 0)
  387.                 {
  388.                     originPrice = currentMidPrice;
  389.                 }
  390.             }
  391.         }
  392.  
  393.  
  394.         var subscribeToMarket = function ()
  395.         {
  396.  
  397.             fetchData(symbol,exchange);
  398.             fetchChartData(symbol, exchange);
  399.         }
  400.  
  401.         var setOriginPrice = function (message)
  402.         {
  403.             var sides = message.split("|");;
  404.             var midPrice = sides[0].substr(1);
  405.             originPrice = midPrice;
  406.             alert(originPrice);
  407.         }
  408.  
  409.  
  410.         var processOrderMessage = function (message)
  411.         {
  412.             var sides = message.split("|");
  413.             //alert(sides[0]);
  414.             var midPrice = sides[0].substr(1);
  415.             var bidString = sides[1];
  416.             var askString = sides[2];
  417.  
  418.             var bidQuantities = bidString.split(",");
  419.             var askQuantities = askString.split(",");
  420.  
  421.             //alert(bidQuantities[0]);
  422.  
  423.             var bidArray = new Array();
  424.             var askArray = new Array();
  425.             for (var i = 0; i < numColumns; i++)
  426.             {      
  427.                 //alert(bidQuantities[i]);
  428.                
  429.                 //if (i == 0)
  430.                 //    bidArray.push(0);
  431.                 //else
  432.                 //    bidArray.push(bidQuantities[i]);
  433.  
  434.                 bidArray.push(bidQuantities[(numColumns - 1) - i]);
  435.  
  436.                 //if (i > 0)
  437.                 //    askArray.push(askQuantities[i] + askQuantities[i-1])
  438.                 //else
  439.                     askArray.push(askQuantities[i]);
  440.             }
  441.  
  442.             //alert("num bids: " + bidArray.length);
  443.            
  444.             //midPrices.push(midPrice);
  445.             bidRows.push(bidArray);
  446.             askRows.push(askArray);        
  447.  
  448.         }
  449.  
  450.         function cloneFrontRow()
  451.         {
  452.  
  453.             if (dataLoaded)
  454.             {
  455.                 let bookCopy = {
  456.                     bids: [],
  457.                     asks: []
  458.                 };
  459.  
  460.                 var bidArray = new Array();
  461.                 var askArray = new Array();
  462.  
  463.                 for (var i=0; i<book.bids.length-1; i++)
  464.                 {
  465.                     var price = book.bids[i].price;
  466.                     var size = book.bids[i].size;
  467.                     bidArray.push({ price,size });
  468.                 }
  469.  
  470.                 for (var j=0; j<book.asks.length-1; j++)
  471.                 {
  472.                     var price = book.asks[j].price;
  473.                     var size = book.asks[j].size;
  474.  
  475.                     askArray.push({ price,size });
  476.                 }
  477.                
  478.                 bookCopy.bids = bidArray;
  479.                 bookCopy.asks = askArray;
  480.  
  481.  
  482.                 bookHistory.unshift(bookCopy);
  483.  
  484.                 if (bookHistory >= numRows)
  485.                     bookHistory.pop();
  486.             }
  487.         }
  488.    
  489.         function lerp(v0, v1, t) {
  490.             return v0*(1-t)+v1*t
  491.         }
  492.  
  493.                        // custom position function for spsBid creation
  494.         var candlePositionFunction = function(particle, i, s)
  495.         {
  496.            
  497.  
  498.             var numCandles = chartData.length;          
  499.             //alert(numCandles);
  500.             if (i < numCandles)
  501.             {
  502.                 var candleData = chartData[i];
  503.                    
  504.                 particle.isVisible = true;
  505.                
  506.                 //particle.color = BABYLON.Color3.Blue();
  507.  
  508.                 var openPrice = candleData[1];
  509.                 var highPrice = candleData[2];
  510.                 var lowPrice = candleData[3];
  511.                 var closePrice = candleData[4];
  512.                
  513.  
  514.                 if (openPrice < closePrice)
  515.                         particle.color = BABYLON.Color3.Blue();
  516.                         //particle.color = new BABYLON.Color3(0,0.2,0);
  517.                     else
  518.                         particle.color = BABYLON.Color3.Purple();
  519.                         //particle.color =new BABYLON.Color3(0.2,0,0);
  520.            
  521.                 //particle.position.z = (tradeDepth * cellDepth)
  522.                 var frontCandleClosePrice = chartData[0][4];
  523.                 var candleOffsetY = (closePrice - frontCandleClosePrice);
  524.                 particle.scaling.y = Math.abs(openPrice - closePrice) * chartAmplitude;
  525.                 particle.position.x = -i * 2;
  526.                 particle.position.y =  candleOffsetY * chartAmplitude;
  527.  
  528.                 //if (enableLogging)
  529.                 //   BABYLON.Tools.Log("Positioning Candle: " + particle.position.x + "," + particle.position.y);
  530.             }
  531.             else
  532.             {
  533.                 particle.isVisible = false;
  534.             }      
  535.         };
  536.  
  537.         function buildChart()
  538.         {
  539.             if (enableLogging)
  540.                 BABYLON.Tools.Log("Building Chart");
  541.  
  542.             //alert("building cha")
  543.             var candleParticle = BABYLON.MeshBuilder.CreateBox("box", {height: 1, width: 2, depth: 1}, scene);
  544.  
  545.             if (spsChart != null)
  546.                 spsChart.dispose();
  547.  
  548.             spsChart = new BABYLON.SolidParticleSystem('spsChart', scene, {updatable: false});
  549.             spsChart.computeParticleTexture = false;        // prevents from computing particle.uvs
  550.             spsChart.computeParticleColor = true;          // prevents from computing particle.color
  551.             spsChart.computeParticleVertex = false;         // prevents from calling the custom updateParticleVertex() function
  552.  
  553.             spsChart.addShape(candleParticle, 100, {positionFunction: candlePositionFunction});
  554.            
  555.             var meshChart = spsChart.buildMesh();
  556.             candleParticle.dispose();
  557.             meshChart.parent = camera;
  558.             //spsChart.isAlwaysVisible = true;
  559.             spsChart.computeBoundingBox = true;
  560.             meshChart.position.x = 0;
  561.  
  562.             if (screenAspectRatio > 1)
  563.                 meshChart.position.y= 75;
  564.             else
  565.                 meshChart.position.y = 40;
  566.             meshChart.position.z = 200;  //-offsetZ;// - cellDepth * 0.5;
  567.             meshChart.scaling.x = 1;
  568.             meshChart.scaling.y = 1;
  569.             meshChart.scaling.z = 1;
  570.             meshChart.rotation.x = -0.1;
  571.             //meshChart.layerMask = 0x20000000;
  572.             meshChart.layerMask = 0x0FFFFFFF;
  573.  
  574.             var highPriceLine = BABYLON.MeshBuilder.CreateBox("box", {height: 1, width: 200, depth: 1}, scene);
  575.             highPriceLine.parent = meshChart;
  576.             highPriceLine.position.x = -100;
  577.             highPriceLine.position.y= 0;
  578.             highPriceLine.position.z = 2;  //-offsetZ;// - cellDepth * 0.5;
  579.             highPriceLine.material = plasticMaterial;
  580.             highPriceLine.position.y = (highestCandlePrice - currentCandlePrice);//* chartAmplitude ;
  581.  
  582.             var lowPriceLine = BABYLON.MeshBuilder.CreateBox("box", {height: 1, width: 200, depth: 1}, scene);
  583.             lowPriceLine.parent = meshChart;
  584.             lowPriceLine.position.x = -100;
  585.             lowPriceLine.position.y= 0;
  586.             lowPriceLine.position.z = 2;  //-offsetZ;// - cellDepth * 0.5;
  587.             lowPriceLine.material = plasticMaterial;
  588.             lowPriceLine.position.y = (lowestCandlePrice - currentCandlePrice) * chartAmplitude ;
  589.  
  590.             var recentTradeLine = BABYLON.MeshBuilder.CreateBox("box", {height: 1, width: 200, depth: 1}, scene);
  591.             recentTradeLine.parent = meshChart;
  592.             recentTradeLine.position.x = -100;
  593.             recentTradeLine.position.y= 0;
  594.             recentTradeLine.position.z = 2;  //-offsetZ;// - cellDepth * 0.5;
  595.             recentTradeLine.material = plasticMaterial;
  596.             recentTradeLine.position.y = 0;
  597.  
  598.            
  599.  
  600.  
  601.  
  602.  
  603.             spsChart.updateParticle = function (particle, i, si)
  604.             {    
  605.             }
  606.         }
  607.  
  608.          
  609.         function onTouchStart(event)
  610.         {
  611.             if (enableLogging)
  612.                 BABYLON.Tools.Log("touchstart");
  613.  
  614.             resetCamera = false;
  615.         }
  616.  
  617.         function onTouchStop(event)
  618.         {
  619.             if (enableLogging)
  620.                 BABYLON.Tools.Log("touchstop");
  621.  
  622.                  setTimeout(enableCameraHome,500);
  623.         }
  624.    
  625.         var createScene = function () {
  626.  
  627.             screenAspectRatio = canvas.height / canvas.width;
  628.  
  629.             if (enableLogging)
  630.                 BABYLON.Tools.Log("Screen Aspect: " + screenAspectRatio);
  631.            
  632.             //engine.switchFullscreen(true);
  633.             scene = new BABYLON.Scene(engine);
  634.             scene.clearColor = new BABYLON.Color3(0.01, 0.01, 0.02);
  635.  
  636.             cameraHolder = new BABYLON.TransformNode("root");
  637.  
  638.             camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2, -200, new BABYLON.Vector3(0, 15, 0), scene);
  639.             camera.parent = cameraHolder
  640.             camera.lowerAlphaLimit =  (Math.PI) + (Math.PI / 8);
  641.             camera.upperAlphaLimit = (Math.PI) * 2 - (Math.PI / 8);
  642.             camera.lowerBetaLimit = ((Math.PI /2) * 0.25);
  643.             camera.upperBetaLimit = (Math.PI /2) - ((Math.PI /2) * 0.025);
  644.             camera.lowerRadiusLimit = 35;
  645.             camera.upperRadiusLimit = 150;
  646.             camera.setPosition(new BABYLON.Vector3(0, 0, -45));        
  647.             //camera.alpha=  Math.PI + (Math.PI / 2) - (Math.PI / 16) ;
  648.             camera.beta = Math.PI / 2 - (Math.PI / 24);
  649.  
  650.             if (screenAspectRatio < 1)
  651.                 camera.fov = 1 * screenAspectRatio;
  652.             else
  653.                 camera.fov = 0.66 * screenAspectRatio;
  654.             //camera.layerMask =   0x0FFFFFFF;  
  655.  
  656.             //camera.setPosition(new BABYLON.Vector3(0, 0, -200));        
  657.                    
  658.             camera.attachControl(canvas, true);
  659.  
  660.             canvas.addEventListener("pointerdown",onTouchStart, false);
  661.             canvas.addEventListener("pointerup",onTouchStop, false);
  662.  
  663.             if (scene.activeCameras.length === 0){
  664.                 scene.activeCameras.push(scene.activeCamera);
  665.             }  
  666.  
  667.             var bgCamera = new BABYLON.ArcRotateCamera("BGCamera", Math.PI / 2 + Math.PI / 7, Math.PI / 2, 100,
  668.             new BABYLON.Vector3(0, 20, 1280),
  669.                 scene);
  670.             bgCamera.layerMask = 0x10000000;
  671.             scene.activeCameras.push(bgCamera);
  672.          
  673.             // Environment Texture
  674.             var hdrTexture = BABYLON.CubeTexture.CreateFromPrefilteredData("textures/gc256SpecularHDR.dds", scene);    
  675.             scene.imageProcessingConfiguration.exposure = 0.6;
  676.             scene.imageProcessingConfiguration.contrast = 1.6;
  677.  
  678.             // Skybox
  679.             var hdrSkybox = BABYLON.Mesh.CreateBox("hdrSkyBox", 1000.0, scene);
  680.             var hdrSkyboxMaterial = new BABYLON.PBRMaterial("skyBox", scene);
  681.             hdrSkyboxMaterial.backFaceCulling = false;
  682.             hdrSkyboxMaterial.reflectionTexture = hdrTexture.clone();
  683.             hdrSkyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
  684.             hdrSkyboxMaterial.microSurface = 1.0;
  685.             hdrSkyboxMaterial.disableLighting = true;
  686.             hdrSkybox.material = hdrSkyboxMaterial;
  687.             hdrSkybox.infiniteDistance = true;
  688.             hdrSkybox.rotation.y = (Math.PI /2) *1;
  689.             hdrSkybox.position.y = -70;
  690.             //hdrSkybox.layerMask =   0x10000000;
  691.        
  692.             //var light = new BABYLON.DirectionalLight("DirectionalLight", new BABYLON.Vector3(0.5, -0.5, 0), scene);
  693.             var light = new BABYLON.HemisphericLight("HemiLight", new BABYLON.Vector3(0, 1, 0.2), scene);
  694.             light.intensity = 0.33;
  695.  
  696.             myGround = BABYLON.MeshBuilder.CreateGround("myGround", {width: 512, height: 1024, subdivsions: 32}, scene);
  697.             gridMaterial =  new BABYLON.GridMaterial("groundMaterial", scene);
  698.             gridMaterial.majorUnitFrequency = 5;
  699.             gridMaterial.minorUnitVisibility  = 0.85;
  700.             gridMaterial.gridRatio = 2.5;
  701.             gridMaterial.lineColor = BABYLON.Color3.Blue();
  702.             myGround.material = gridMaterial;
  703.             //myGround.layerMask = 0x10000000;
  704.  
  705.             var metalBid = new BABYLON.PBRMaterial("metalBid", scene);
  706.             metalBid.reflectionTexture = hdrTexture;
  707.             metalBid.microSurface = 0.9;
  708.             metalBid.reflectivityColor = new BABYLON.Color3(0.65, 0.99, 0.685);
  709.             metalBid.albedoColor = new BABYLON.Color3(0.01, 0.5, 0.01);
  710.  
  711.             var metalAsk = new BABYLON.PBRMaterial("metalAsk", scene);
  712.             metalAsk.reflectionTexture = hdrTexture;
  713.             metalAsk.microSurface = 0.9;
  714.             metalAsk.reflectivityColor = new BABYLON.Color3(0.99, 0.685, 0.65);
  715.             metalAsk.albedoColor = new BABYLON.Color3(0.5, 0.01, 0.01);
  716.  
  717.             plasticMaterial = new BABYLON.PBRMaterial("plastic", scene);
  718.             plasticMaterial.albedoColor = BABYLON.Color3.White();
  719.             plasticMaterial.albedoColor =  new BABYLON.Color3(0, 0, 0.2);
  720.             plasticMaterial.normalTexture =  new BABYLON.Texture("/textures/gl_normal.png", scene);
  721.             plasticMaterial.microSurface = 0.75;
  722.             plasticMaterial.reflectivityColor = new BABYLON.Color3(0.215, 0.351, 0.727);
  723.             plasticMaterial.reflectionTexture = hdrTexture;  
  724.             plasticMaterial.useLogarithmicDepth = false;  
  725.  
  726.             candleMaterial = new BABYLON.StandardMaterial("candle", scene);
  727.             //candleMaterial.color = BABYLON.Color3.Blue();
  728.             candleMaterial.diffuseColor = BABYLON.Color3.Purple();
  729.            
  730.  
  731.  
  732.            
  733.             bidMaterial = new BABYLON.PBRMaterial("bid", scene);
  734.             bidMaterial.albedoColor = BABYLON.Color3.Blue();
  735.             //bidMaterial.albedoColor =  new BABYLON.Color3(0, 0.25, 0);
  736.             //bidMaterial.albedoColor =  new BABYLON.Color3(0, 0.25, 0);BABYLON.Color3.Blue();
  737.  
  738.             bidMaterial.normalTexture =  new BABYLON.Texture("/textures/gl_normal.png", scene);
  739.             bidMaterial.microSurface = 0.9;
  740.             bidMaterial.reflectivityColor = new BABYLON.Color3(0.0,0.4, 0.0);
  741.             bidMaterial.reflectionTexture = hdrTexture;
  742.             //bidMaterial.alpha = 0.8;    
  743.  
  744.             askMaterial = new BABYLON.PBRMaterial("ask", scene);
  745.             askMaterial.albedoColor = BABYLON.Color3.Purple();
  746.             //askMaterial.albedoColor =  new BABYLON.Color3(0.25, 0, 0.0);
  747.             askMaterial.normalTexture =  new BABYLON.Texture("/textures/gl_normal.png", scene);
  748.             askMaterial.microSurface = 0.9;
  749.             askMaterial.reflectivityColor = new BABYLON.Color3(0.4,0,0);
  750.             askMaterial.reflectionTexture = hdrTexture;  
  751.             //askMaterial.alpha = 0.8;  
  752.  
  753.             buyMaterial = new BABYLON.PBRMaterial("buy", scene);
  754.             buyMaterial.albedoColor =  new BABYLON.Color3(0, 0.75, 0);
  755.             buyMaterial.microSurface = 0.7;
  756.             buyMaterial.reflectivityColor = new BABYLON.Color3(0.15,0.7, 0.15);
  757.             buyMaterial.reflectionTexture = hdrTexture;      
  758.  
  759.             sellMaterial = new BABYLON.PBRMaterial("buy", scene);
  760.             sellMaterial.albedoColor =  new BABYLON.Color3(0.75, 0, 0.0);
  761.             sellMaterial.microSurface = 0.7;
  762.             sellMaterial.reflectivityColor = new BABYLON.Color3(0.7, 0.15, 0.15);
  763.             sellMaterial.reflectionTexture = hdrTexture;                    
  764.              
  765.             var leftBumper =   BABYLON.MeshBuilder.CreateCylinder("leftbumper", {diameter: 16, height: 1024, tessellation: 16}, scene);
  766.             leftBumper.position.x = -128;
  767.             leftBumper.position.y = 0;
  768.             leftBumper.position.z = 0;
  769.             leftBumper.rotation.x = (Math.PI / 2) * 3;
  770.             leftBumper.rotation.y = 0;
  771.             leftBumper.scaling.x = 1;
  772.             leftBumper.scaling.y = 1;
  773.             leftBumper.scaling.z = 1;
  774.             leftBumper.material = plasticMaterial;
  775.             leftBumper.parent = cameraHolder;
  776.             leftBumper.layerMask =   0x0FFFFFFF;
  777.            
  778.  
  779.             var rightBumper =   BABYLON.MeshBuilder.CreateCylinder("rightbumper", {diameter: 16, height: 1024, tessellation: 16}, scene);
  780.             rightBumper.position.x = 128;
  781.             rightBumper.position.y = 0;
  782.             rightBumper.position.z = 0;
  783.             rightBumper.rotation.x = (Math.PI / 2) * 3;
  784.             rightBumper.rotation.y = 0;
  785.             rightBumper.scaling.x = 1;
  786.             rightBumper.scaling.y = 1;
  787.             rightBumper.scaling.z = 1;
  788.             rightBumper.material = plasticMaterial;
  789.             rightBumper.parent = cameraHolder;
  790.             rightBumper.layerMask =   0x0FFFFFFF;
  791.            
  792.             /*
  793.             BABYLON.SceneLoader.ImportMesh("", "models/", "BTCUSD.babylon", scene, function (newMeshes) {
  794.             newMeshes[0].position.x = 0;
  795.             newMeshes[0].position.y = 0;
  796.             newMeshes[0].position.z = -20;
  797.             newMeshes[0].rotation.x = 0;//(Math.PI / 2) * 3;
  798.             newMeshes[0].rotation.y = 0;
  799.             newMeshes[0].scaling.x = 0.01;
  800.             newMeshes[0].scaling.y = 0.01;
  801.             newMeshes[0].scaling.z = 0.01;
  802.             newMeshes[0].material = plasticMaterial;
  803.             logo = newMeshes[0];
  804.             logo.parent = cameraHolder;
  805.             logo.layerMask =   0x0FFFFFFF;
  806.             //waterMaterial.addToRenderList(newMeshes[0]);
  807.             });  
  808.             */
  809.            
  810.             //var originBox = BABYLON.MeshBuilder.CreateBox("box", {height: 10, width: 10, depth: 10}, scene);
  811.  
  812.             var currentRow;
  813.             var currentColumn;
  814.             var scaleXFactor;
  815.  
  816.             pl = new BABYLON.PointLight("pl", new BABYLON.Vector3(0, 10, 10), scene);
  817.             pl.diffuse = new BABYLON.Color3(1, 1, 1);
  818.             pl.intensity = 0.75;
  819.                
  820.         // custom position function for spsBid creation
  821.         var bidPositionFunction = function(particle, i, s)
  822.         {
  823.             var currentRow = i / numColumns;
  824.             var currentColumn = i % numColumns;
  825.             particle.position.x =  currentColumn * cellWidth * -1;
  826.             particle.scaling.y = 1;
  827.             particle.position.y = particle.scaling.y * 0.5;
  828.             particle.position.z = currentRow * cellDepth * -1;
  829.         };
  830.        
  831.             //var particle = BABYLON.MeshBuilder.CreateCylinder("particle", {diameter: 3.2, height: 1, tessellation: 4}, scene);
  832.             var particle = BABYLON.MeshBuilder.CreateBox("box", {height: 1, width: 1, depth: 4.5}, scene);
  833.            
  834.             spsBid = new BABYLON.SolidParticleSystem('spsBid', scene, {updatable: true});
  835.            
  836.             var nb = numRows * numColumns;
  837.  
  838.             spsBid.addShape(particle, nb, {positionFunction: bidPositionFunction});
  839.             var mesh = spsBid.buildMesh();
  840.             //spsBid.isAlwaysVisible = true;
  841.             spsBid.computeBoundingBox =true;
  842.             mesh.position.x = -cellWidth * 0.5;
  843.             mesh.position.y= 0.1;
  844.             mesh.position.z= 0//offsetZ - cellDepth * 0.5;
  845.             mesh.material = bidMaterial;
  846.             //mesh.layerMask = 0x10000000;
  847.             mesh.layerMask =   0x0FFFFFFF;
  848.             //spsBid.layerMask = 0x10000000;   
  849.             //particle.dispose();
  850.  
  851.             //waterMaterial.addToRenderList(mesh);
  852.  
  853.             spsBid.computeParticleTexture = false;        // prevents from computing particle.uvs
  854.             spsBid.computeParticleColor = false;          // prevents from computing particle.color
  855.             spsBid.computeParticleVertex = false;         // prevents from calling the custom updateParticleVertex() function
  856.  
  857.             spsBid.beforeUpdateParticles = function ()
  858.             {
  859.                 //bidUpdateIndex = -1;
  860.             }
  861.            
  862.  
  863.             spsBid.updateParticle = function (particle, i, si)
  864.             {        
  865.                 var currentRow =  Math.floor(particle.idx / numColumns);// tempUpdateIndex;
  866.                 var currentColumn = particle.idx % numColumns;  
  867.                
  868.                 if (dataLoaded)
  869.                 {
  870.                     //var currentFrontMidPrice = currentMidPrice;
  871.  
  872.                     //if (bidRows.length >= numRows)
  873.                     //{
  874.                        // var currentRowMidPrice = midPrices[ currentRow - 1 + updateIndex];
  875.                         //var currentRowOffest = originPrice - currentRowMidPrice;
  876.  
  877.                         //var cellPriceWidth = cellPercentage * originPrice;
  878.                         //var currentRowOffest = ((originPrice - currentRowMidPrice) / cellPriceWidth) * cellWidth;
  879.  
  880.                         var cellQuantity = 0;
  881.                         var cellPrice = 0;
  882.                         var cellOffset = 0;
  883.                         if (currentRow == (numRows))
  884.                         {
  885.                             cellQuantity = book.bids[currentColumn].size;
  886.                             cellPrice = book.bids[currentColumn].price;
  887.                             var midPriceOffset = (currentMidPrice - originPrice);
  888.                             cellOffset = (cellPrice - currentMidPrice)  + midPriceOffset * cellWidth;
  889.                         }      
  890.                         else
  891.                         {
  892.                             if (dataLoaded)
  893.                             {
  894.                                 var historyLength = bookHistory.length;
  895.  
  896.                                 if ( currentRow < historyLength)
  897.                                 {
  898.                                         if (tempUpdateIndex > 0)
  899.                                         {
  900.                                             cellQuantity = bookHistory[currentRow].bids[currentColumn].size;
  901.                                             cellPrice = bookHistory[currentRow].bids[currentColumn].price;
  902.                                             var midPriceOffset = (currentMidPrice - originPrice);
  903.                                             cellOffset = ((cellPrice - currentMidPrice) * cellWidth) + midPriceOffset * cellWidth;
  904.                                         }
  905.                                        
  906.                                 }
  907.                                 else
  908.                                 {
  909.                                     particle.isVisible = false;
  910.                                 }
  911.                             }
  912.                         }
  913.  
  914.                         if (cellQuantity == 0)
  915.                         {
  916.                             particle.isVisible = false;
  917.                         }          
  918.                         else
  919.                         {
  920.                             particle.isVisible = true;
  921.                             particle.scaling.y =   cellQuantity * quantityScaleFactor;
  922.                             particle.position.x = cellOffset * priceOffsetMultiplier;
  923.                             particle.position.y = particle.scaling.y * 0.5;
  924.  
  925.                             if (currentRow == (0))
  926.                             {
  927.                                 particle.position.z = (currentRow * cellDepth);
  928.                             }
  929.                             else
  930.                             {
  931.                                 particle.position.z = -(cellDepth) + ((currentRow-1) * cellDepth) + (cellDepth + ( cellDepth * timeDamper));
  932.                             }
  933.                         }
  934.                        
  935.                     //}      
  936.                 }    
  937.              }
  938.  
  939.  
  940.              /////////////////
  941.  
  942.         var askPositionFunction = function(particle, i, s)
  943.         {
  944.             var currentRow = i / numColumns;
  945.             var currentColumn = i % numColumns;
  946.             particle.position.x =  -currentColumn * cellWidth;
  947.             particle.scaling.y = 1;
  948.             particle.position.y = particle.scaling.y * quantityScaleFactor;
  949.             particle.position.z = currentRow * cellDepth * -1;
  950.         };
  951.  
  952.  
  953.             spsAsk = new BABYLON.SolidParticleSystem('spsAsk', scene, {updatable: true});
  954.            
  955.             var nb = numRows * numColumns;
  956.  
  957.             spsAsk.addShape(particle, nb, {positionFunction: askPositionFunction});
  958.             var mesh = spsAsk.buildMesh();
  959.             spsAsk.isAlwaysVisible = false;
  960.             spsAsk.computeBoundingBox =true;
  961.             mesh.position.x = cellWidth * 0.5;
  962.             mesh.position.y= 0.1;
  963.             mesh.position.z= 0;
  964.             mesh.material = askMaterial;
  965.             //mesh.layerMask = 0x10000000;
  966.             mesh.layerMask =   0x0FFFFFFF;  
  967.             particle.dispose();
  968.  
  969.             //waterMaterial.addToRenderList(mesh);
  970.  
  971.             spsAsk.computeParticleTexture = false;        // prevents from computing particle.uvs
  972.             spsAsk.computeParticleColor = false;          // prevents from computing particle.color
  973.             spsAsk.computeParticleVertex = false;         // prevents from calling the custom updateParticleVertex() function
  974.  
  975.             spsAsk.beforeUpdateParticles = function ()
  976.             {
  977.                 //bidUpdateIndex = 0;
  978.             }
  979.  
  980.             spsAsk.updateParticle = function (particle, i, si)
  981.             {  
  982.                 var currentRow = Math.floor(particle.idx / numColumns);
  983.                 var currentColumn = particle.idx % numColumns;  
  984.                
  985.                 if (dataLoaded)
  986.                 {
  987.                     //var currentFrontMidPrice = midPrices[numRows - 1 + askUpdateIndex];
  988.  
  989.                  
  990.  
  991.                          var currentRowMidPrice = midPrices[ currentRow - 1 + askUpdateIndex];
  992.                         var cellPriceWidth = cellPercentage * originPrice;
  993.                         var currentRowOffest = ((originPrice - currentRowMidPrice) / cellPriceWidth) * cellWidth;
  994.  
  995.                         var cellQuantity = 0;
  996.                         var cellPrice = 0;
  997.                         var cellOffset = 0;
  998.  
  999.                         if (currentRow == (numRows))
  1000.                         {
  1001.                             cellQuantity = book.asks[currentColumn].size;
  1002.                             cellPrice = book.asks[currentColumn].price;
  1003.                             var midPriceOffset = (currentMidPrice - originPrice);
  1004.                             cellOffset = ((cellPrice - currentMidPrice) * cellWidth) + midPriceOffset * cellWidth;
  1005.                         }      
  1006.                         else
  1007.                         {
  1008.                             if (dataLoaded)
  1009.                             {
  1010.                                 var historyLength = bookHistory.length;
  1011.  
  1012.                                 //if (historyLength > 0)
  1013.                                     //alert(bookHistory.length);
  1014.  
  1015.                                 if ( currentRow < bookHistory.length)
  1016.                                 {
  1017.                                         cellQuantity = bookHistory[currentRow].asks[currentColumn].size;
  1018.                                         cellPrice = bookHistory[currentRow].asks[currentColumn].price;
  1019.                                         var midPriceOffset = (currentMidPrice - originPrice);
  1020.                                         cellOffset = ((cellPrice - currentMidPrice) * cellWidth) + midPriceOffset * cellWidth;
  1021.                                 }
  1022.                             }
  1023.                         }                  
  1024.  
  1025.                         if (cellQuantity == 0)
  1026.                         {
  1027.                             particle.isVisible = false;
  1028.                         }
  1029.                         else
  1030.                         {
  1031.                             particle.isVisible = true;
  1032.                         }      
  1033.  
  1034.                         //if (currentRow == (numRows))
  1035.                         //    particle.scaling.y = cellQuantity * quantityScaleFactor * frontBarHeightMultiplier;
  1036.                         //else
  1037.                             particle.scaling.y = cellQuantity * quantityScaleFactor;
  1038.                            
  1039.                     }                
  1040.                
  1041.  
  1042.                 particle.position.x = cellOffset * priceOffsetMultiplier;
  1043.                 particle.position.y = particle.scaling.y * 0.5;
  1044.  
  1045.                 if (currentRow == (0))
  1046.                 {
  1047.                     particle.position.z = (currentRow * cellDepth);
  1048.                 }
  1049.                 else
  1050.                 {
  1051.                     particle.position.z = -cellDepth + ((currentRow-1) * cellDepth) + (cellDepth + (cellDepth * timeDamper));
  1052.                 }
  1053.  
  1054.                 //particle.position.z = currentRow * cellDepth;// + (frontBarHeightMultiplier * cellDepth);
  1055.              }
  1056.  
  1057.  
  1058. //Grid SPS
  1059.  
  1060.             var gridPositionFunction = function(particle, i, s)
  1061.             {
  1062.                
  1063.             };
  1064.  
  1065.             var gridParticle = BABYLON.MeshBuilder.CreateBox("box", {height: 0.02, width: 0.4, depth: 250}, scene);
  1066.             spsGrid = new BABYLON.SolidParticleSystem('spsGrid', scene, {updatable: true});
  1067.            
  1068.             var nb = 11;
  1069.  
  1070.             spsGrid.addShape(gridParticle, nb, {positionFunction: gridPositionFunction});
  1071.             var mesh = spsGrid.buildMesh();
  1072.             spsGrid.isAlwaysVisible = false;
  1073.             spsGrid.computeBoundingBox =true;
  1074.             mesh.position.x = cellWidth * 0.5;
  1075.             mesh.position.y= -0.5;
  1076.             mesh.position.z= 112;
  1077.             mesh.material = plasticMaterial;
  1078.             //mesh.layerMask = 0x10000000;
  1079.             mesh.layerMask =   0x0FFFFFFF;  
  1080.             gridParticle.dispose();
  1081.  
  1082.             //waterMaterial.addToRenderList(mesh);
  1083.  
  1084.             spsGrid.computeParticleTexture = false;        // prevents from computing particle.uvs
  1085.             spsGrid.computeParticleColor = false;          // prevents from computing particle.color
  1086.             spsGrid.computeParticleVertex = false;         // prevents from calling the custom updateParticleVertex() function
  1087.  
  1088.             spsGrid.beforeUpdateParticles = function ()
  1089.             {
  1090.                 //bidUpdateIndex = 0;
  1091.             }
  1092.  
  1093.             spsGrid.updateParticle = function (particle, i, si)
  1094.             {                  
  1095.                 if (dataLoaded)
  1096.                 {
  1097.                         var nextLowestTen =  originPrice - (originPrice % 10);
  1098.  
  1099.                          if (enableLogging)
  1100.                                 BABYLON.Tools.Log("Distance From Ten: " + nextLowestTen);
  1101.  
  1102.                         var cellOffsetX = (-50 * cellWidth) + (nextLowestTen - originPrice ) * cellWidth + (particle.idx * 10) * cellWidth;
  1103.                        
  1104.                         particle.position.x =  cellOffsetX * priceOffsetMultiplier;
  1105.                         particle.position.y = particle.scaling.y * 0.5;
  1106.                 }
  1107.              }
  1108.  
  1109.  
  1110.             //TRADES SPS
  1111.  
  1112.             var tradePoolCount = 1000;
  1113.  
  1114.             // custom position function for spsBid creation
  1115.             var tradePositionFunction = function(particle, i, s)
  1116.             {
  1117.                 particle.isVisible = false;
  1118.                
  1119.             };
  1120.  
  1121.             //var tradeParticle = BABYLON.MeshBuilder.CreateSphere("particle", {diameter: 10}, scene);        
  1122.             //var tradeParticle = BABYLON.MeshBuilder.CreateCylinder("particle", {diameter: 3.75, height: 1, tessellation: 12}, scene);
  1123.             var tradeParticle = BABYLON.MeshBuilder.CreateBox("box", {height: 1, width: 1.25, depth: 4.7}, scene);
  1124.             //tradeParticle.scaling.x = 0;
  1125.             //tradeParticle.position.y = 100;
  1126.             spsBuys = new BABYLON.SolidParticleSystem('spsTrades', scene, {updatable: true});
  1127.             spsBuys.addShape(tradeParticle, tradePoolCount, {positionFunction: tradePositionFunction});
  1128.             var meshBuys = spsBuys.buildMesh();
  1129.             //spsBuys.isAlwaysVisible = true;
  1130.             spsBuys.computeBoundingBox = true;
  1131.             meshBuys.position.x = 0;
  1132.             meshBuys.position.y= 0.1;
  1133.             meshBuys.position.z = 0;  //-offsetZ;// - cellDepth * 0.5;
  1134.             meshBuys.material = buyMaterial;
  1135.             meshBuys.layerMask = 0x0FFFFFFF;    
  1136.            
  1137.             spsBuys.computeParticleTexture = false;        // prevents from computing particle.uvs
  1138.             spsBuys.computeParticleColor = false;          // prevents from computing particle.color
  1139.             spsBuys.computeParticleVertex = false;         // prevents from calling the custom updateParticleVertex() function
  1140.  
  1141.             spsBuys.updateParticle = function (particle, i, si)
  1142.             {    
  1143.                 if (dataLoaded)
  1144.                 {
  1145.                     var numTrades = tradeHistory.length;
  1146.  
  1147.                     if (particle.idx < numTrades)
  1148.                     {
  1149.                         var tradeData = tradeHistory[particle.idx];
  1150.  
  1151.                         var tradeGeneration = tradeData[5];
  1152.  
  1153.                         if ( (tempUpdateIndex - tradeGeneration) < numRows)
  1154.                         {
  1155.                             //alert(tradeGeneration);
  1156.                             if (tradeData[0] == "b")
  1157.                             {
  1158.                                 particle.isVisible = true;
  1159.  
  1160.                                 var tradePrice = tradeData[1];
  1161.                                 var tradeQuantity = tradeData[2];
  1162.                                 var tradeMidPrice = tradeData[3];
  1163.                                 var quantityUnderTrade = tradeData[4];    
  1164.                                 var tradeGeneration = tradeData[5];
  1165.              
  1166.                                 //var cellPriceWidth = cellPercentage * originPrice;      
  1167.                                
  1168.                                 var tradePriceOffset = (tradePrice - originPrice) * priceOffsetMultiplier * cellWidth + (cellWidth * 0.5);
  1169.                                 //var tradePriceOffset = ((originPrice - tradePrice) / cellPriceWidth) * cellWidth;
  1170.  
  1171.                                 var askSize = book.asks[0].size;
  1172.                    
  1173.                                 var tradeDepth = tempUpdateIndex - tradeGeneration;
  1174.                                 //particle.position.z = (tradeDepth * cellDepth)
  1175.                                 particle.position.x = tradePriceOffset;
  1176.  
  1177.                                 var scaledQuantity = tradeQuantity * quantityScaleFactor;
  1178.                                 //particle.scaling.y = scaledQuantity;
  1179.  
  1180.  
  1181.                                 var finalParticlePositionY = (quantityUnderTrade * quantityScaleFactor)  + 0.2 - (particle.scaling.y * 0.5);
  1182.                                 particle.position.y = finalParticlePositionY;
  1183.                                 //if (particle.position.y > finalParticlePositionY)
  1184.                                  //   particle.position.y = lerp(particle.position.y,finalParticlePositionY,0.1);
  1185.  
  1186.  
  1187.                                 if (currentRow == (0))
  1188.                                 {
  1189.                                     particle.position.z = (tradeDepth * cellDepth);
  1190.                                 }
  1191.                                 else
  1192.                                 {
  1193.                                     particle.position.z = -cellDepth + ((tradeDepth-1) * cellDepth) + (cellDepth + (cellDepth * timeDamper));
  1194.                                 }
  1195.  
  1196.                                 /*
  1197.                                 var attackFactor = 0.05;
  1198.                                 var decayFactor = 0.05;
  1199.  
  1200.                                 if ( (particle.scaling.x < (maxTradeScale)) && tradeData[6] == true )
  1201.                                 {
  1202.                                         if (tradeData[6] == true)
  1203.                                             particle.scaling.x = particle.scaling.x + (particle.scaling.x * attackFactor);//  lerp(particle.scaling.x,maxTradeScale,tradeAttackFalloff);
  1204.                                         //particle.scaling.y = scaledQuantity * attackFactor; // lerp(particle.scaling.y, maxTradeScale * scaledQuantity, tradeAttackFalloff);
  1205.                                         //particle.scaling.z = particle.scaling.z * attackFactor; //lerp(particle.scaling.x,maxTradeScale,tradeAttackFalloff);                        
  1206.  
  1207.                                     //particle.scaling.z = particle.scaling.x =  lerp(particle.scaling.x,maxTradeScale,tradeAttackFalloff);
  1208.                                 }                                
  1209.                                 else if (particle.scaling.x > finalTradeScale)
  1210.                                 {
  1211.                                     tradeHistory[particle.idx][6] = false;
  1212.                                     particle.scaling.x = particle.scaling.x - (particle.scaling.x * decayFactor);//lerp(particle.scaling.x,finalTradeScale,tradeDecayFalloff);
  1213.                                    //particle.scaling.y = lerp(particle.scaling.y, finalTradeScale * scaledQuantity, tradeDecayFalloff);
  1214.                                     //particle.scaling.z = lerp(particle.scaling.x,finalTradeScale,tradeDecayFalloff);
  1215.                                 }
  1216.                                 */
  1217.                             }
  1218.                             else
  1219.                             {
  1220.                                 particle.isVisible = false;
  1221.                             }
  1222.                         }
  1223.                         else
  1224.                         {
  1225.                             particle.isVisible = false
  1226.                         }
  1227.                     }
  1228.                     else
  1229.                     {
  1230.                         particle.isVisible = false;
  1231.                     }
  1232.                 }
  1233.                
  1234.              }
  1235.              
  1236.             spsSells = new BABYLON.SolidParticleSystem('spsTrades', scene, {updatable: true});
  1237.             spsSells.addShape(tradeParticle, tradePoolCount, {positionFunction: tradePositionFunction});
  1238.             var meshSells = spsSells.buildMesh();
  1239.             //spsSells.isAlwaysVisible = true;
  1240.             spsSells.computeBoundingBox = true;
  1241.             meshSells.position.x = 0;
  1242.             meshSells.position.y= 0.1;
  1243.             meshSells.position.z=  0;
  1244.             meshSells.material = sellMaterial;
  1245.             meshSells.layerMask = 0x0FFFFFFF;      
  1246.            
  1247.            
  1248.             spsSells.computeParticleTexture = false;        // prevents from computing particle.uvs
  1249.             spsSells.computeParticleColor = false;          // prevents from computing particle.color
  1250.             spsSells.computeParticleVertex = false;         // prevents from calling the custom updateParticleVertex() function
  1251.  
  1252.             spsSells.updateParticle = function (particle, i, si)
  1253.             {  
  1254.                 if (dataLoaded)
  1255.                 {
  1256.  
  1257.                
  1258.                     var numTrades = tradeHistory.length;
  1259.  
  1260.                     if (particle.idx < numTrades)
  1261.                     {
  1262.                         var tradeData = tradeHistory[particle.idx];
  1263.  
  1264.                         var tradeGeneration = tradeData[5];
  1265.  
  1266.                         if ( (tempUpdateIndex - tradeGeneration) < numRows)
  1267.                         {
  1268.  
  1269.                             if (tradeData[0] == "s")
  1270.                             {
  1271.                                 particle.isVisible = true;
  1272.  
  1273.                                 var tradePrice = tradeData[1];
  1274.                                 var tradeQuantity = tradeData[2];
  1275.                                 var tradeMidPrice = tradeData[3];
  1276.                                 var quantityUnderTrade = tradeData[4];    
  1277.                                 var tradeGeneration = tradeData[5];
  1278.  
  1279.                                 //var cellPriceWidth = cellPercentage * originPrice;      
  1280.  
  1281.                                 var tradePriceOffset = (tradePrice - originPrice) * priceOffsetMultiplier * cellWidth - (cellWidth * 0.5);
  1282.                                 //var tradePriceOffset = ((originPrice - tradePrice) / cellPriceWidth) * cellWidth;
  1283.  
  1284.                                 var askSize = book.asks[0].size;
  1285.  
  1286.                                 var tradeDepth = tempUpdateIndex - tradeGeneration;
  1287.                                 particle.position.x = tradePriceOffset;
  1288.                                 particle.scaling.y = tradeQuantity * quantityScaleFactor;
  1289.  
  1290.                                 //if (tradeDepth == 0)
  1291.                                 var finalParticlePositionY = (quantityUnderTrade * quantityScaleFactor)  + 0.2 - (particle.scaling.y * 0.5);
  1292.                                 particle.position.y = finalParticlePositionY;
  1293.  
  1294.  
  1295.                                 if (currentRow == (0))
  1296.                                 {
  1297.                                     particle.position.z = (cellDepth) + (tradeDepth * cellDepth);
  1298.                                 }
  1299.                                 else
  1300.                                 {
  1301.                                     particle.position.z = (-cellDepth) + ((tradeDepth-1) * cellDepth) + (cellDepth + (cellDepth * timeDamper));
  1302.                                 }
  1303.                             }
  1304.                             else
  1305.                             {
  1306.                                 particle.isVisible = false;
  1307.                             }
  1308.                         }
  1309.                         else
  1310.                         {
  1311.                             particle.isVisible = false;
  1312.                         }
  1313.                     }
  1314.                     else
  1315.                     {
  1316.                         particle.isVisible = false;
  1317.                     }
  1318.                 }
  1319.  
  1320.                 tradeParticle.dispose();
  1321.             }
  1322.  
  1323.  
  1324.            
  1325.  
  1326.  
  1327.             //GUI
  1328.             var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
  1329.             advancedTexture.layer.layerMask = 0x10000000;
  1330.             advancedTexture.renderScale = 1.5;
  1331.  
  1332.             var leftPanel = new BABYLON.GUI.StackPanel();
  1333.             leftPanel.width = "700px";
  1334.             leftPanel.isVertical = true;
  1335.             leftPanel.paddingLeft = "-10px";
  1336.             leftPanel.paddingTop = "20px";
  1337.             leftPanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1338.             leftPanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM;
  1339.             advancedTexture.addControl(leftPanel);
  1340.  
  1341.             var homeButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/HomeButton.png");
  1342.             homeButton.width = 0.5;
  1343.             homeButton.height = "160px";
  1344.             homeButton.alpha = 1;
  1345.             homeButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1346.             homeButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM;
  1347.             homeButton.cornerRadius = 20;
  1348.             homeButton.onPointerDownObservable.add(function(value) {
  1349.                    //colorPicker.isVisible = !colorPicker.isVisible;
  1350.                    //colorText.isVisible = !colorText.isVisible;
  1351.                    window.location = "./index.html";
  1352.            
  1353.             });
  1354.  
  1355.             leftPanel.addControl(homeButton);
  1356.  
  1357. ////Exchange GUI
  1358.  
  1359.             var topRightPanel = new BABYLON.GUI.StackPanel();
  1360.             topRightPanel.width = "350px";
  1361.             topRightPanel.isVertical = true;
  1362.             topRightPanel.paddingRight = "-10px";
  1363.             topRightPanel.paddingTop = "-20px";
  1364.             topRightPanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
  1365.             topRightPanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1366.             advancedTexture.addControl(topRightPanel);
  1367.  
  1368.             exchangeButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/BinanceButton.png");
  1369.             exchangeButton.width = 1;
  1370.             exchangeButton.height = "160px";
  1371.             exchangeButton.alpha = 1;
  1372.             exchangeButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
  1373.             exchangeButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1374.             exchangeButton.cornerRadius = 20;
  1375.             exchangeButton.onPointerDownObservable.add(function(value) {
  1376.                 if (exchangePanel.isVisible)
  1377.                     exchangePanel.isVisible = false;
  1378.                 else
  1379.                     exchangePanel.isVisible = true;
  1380.          
  1381.             });
  1382.  
  1383.             topRightPanel.addControl(exchangeButton);
  1384.  
  1385.            
  1386.             exchangePanel = new BABYLON.GUI.StackPanel();
  1387.             exchangePanel.isVisible = false;
  1388.             exchangePanel.width = "350px";
  1389.             exchangePanel.isVertical = true;
  1390.             exchangePanel.paddingRight = "-10";
  1391.             exchangePanel.paddingTop = "-20px";
  1392.             exchangePanel.left = "-360px";
  1393.             exchangePanel.top = "150px";
  1394.             exchangePanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
  1395.             exchangePanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1396.             advancedTexture.addControl(exchangePanel);
  1397.  
  1398.             var binanceButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/BinanceButton.png");
  1399.             binanceButton.width = 1;
  1400.             binanceButton.height = "160px";
  1401.             binanceButton.alpha = 1;
  1402.             binanceButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1403.             binanceButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1404.             //binanceButton.cornerRadius = 20;
  1405.             binanceButton.onPointerDownObservable.add(function(value) {
  1406.                 exchange = "Binance";
  1407.                 exchangePanel.isVisible = false;
  1408.                 exchangeButton.children[0].source = "textures/BinanceButton.png";
  1409.                reset();
  1410.          
  1411.             });
  1412.  
  1413.             exchangePanel.addControl(binanceButton);
  1414.  
  1415.             var coinbaseButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/CoinbaseButton.png");
  1416.             coinbaseButton.width = 1;
  1417.             coinbaseButton.height = "160px";
  1418.             coinbaseButton.alpha = 1;
  1419.             coinbaseButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1420.             coinbaseButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1421.             //binanceButton.cornerRadius = 20;
  1422.             coinbaseButton.onPointerDownObservable.add(function(value) {
  1423.                 exchange = "GDAX";
  1424.                 exchangePanel.isVisible = false;
  1425.                 exchangeButton.children[0].source = "textures/CoinbaseButton.png";
  1426.                reset();
  1427.          
  1428.             });
  1429.  
  1430.             exchangePanel.addControl(coinbaseButton);
  1431.  
  1432.             /*
  1433.             var huobiButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/HuobiButton.png");
  1434.             huobiButton.width = 1;
  1435.             huobiButton.height = "160px";
  1436.             huobiButton.alpha = 1;
  1437.             huobiButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1438.             huobiButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1439.             //binanceButton.cornerRadius = 20;
  1440.             huobiButton.onPointerDownObservable.add(function(value) {
  1441.                 exchange = "Huobi";
  1442.                 exchangePanel.isVisible = false;
  1443.                 exchangeButton.children[0].source = "textures/HuobiButton.png";
  1444.                reset();
  1445.          
  1446.             });
  1447.  
  1448.             exchangePanel.addControl(huobiButton);
  1449.  
  1450.             var bitstampButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/BitstampButton.png");
  1451.             bitstampButton.width = 1;
  1452.             bitstampButton.height = "160px";
  1453.             bitstampButton.alpha = 1;
  1454.             bitstampButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1455.             bitstampButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1456.             //binanceButton.cornerRadius = 20;
  1457.             bitstampButton.onPointerDownObservable.add(function(value) {
  1458.                 exchange = "Bitstamp";
  1459.                 exchangePanel.isVisible = false;
  1460.                 exchangeButton.children[0].source = "textures/BitstampButton.png";
  1461.                reset();
  1462.          
  1463.             });
  1464.  
  1465.             exchangePanel.addControl(bitstampButton);
  1466.             */
  1467.  
  1468. ///Symbol GUI
  1469.  
  1470.             var topLeftPanel = new BABYLON.GUI.StackPanel();
  1471.             topLeftPanel.width = "350px";
  1472.             topLeftPanel.isVertical = true;
  1473.             topLeftPanel.paddingRight = "-10px";
  1474.             topLeftPanel.paddingTop = "-20px";
  1475.             topLeftPanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1476.             topLeftPanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1477.             advancedTexture.addControl(topLeftPanel);
  1478.  
  1479.             symbolButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/BTCUSDButton.png");
  1480.             symbolButton.width = 1;
  1481.             symbolButton.height = "160px";
  1482.             symbolButton.alpha = 1;
  1483.             symbolButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
  1484.             symbolButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1485.             symbolButton.cornerRadius = 20;
  1486.             symbolButton.onPointerDownObservable.add(function(value) {
  1487.                 if (symbolPanel.isVisible)
  1488.                     symbolPanel.isVisible = false;
  1489.                 else
  1490.                     symbolPanel.isVisible = true;
  1491.          
  1492.             });
  1493.  
  1494.             topLeftPanel.addControl(symbolButton);
  1495.  
  1496.            
  1497.             symbolPanel = new BABYLON.GUI.StackPanel();
  1498.             symbolPanel.isVisible = false;
  1499.             symbolPanel.width = "350px";
  1500.             symbolPanel.isVertical = true;
  1501.             symbolPanel.paddingRight = "-10";
  1502.             symbolPanel.paddingTop = "-20px";
  1503.             symbolPanel.left = "360px";
  1504.             symbolPanel.top = "150px";
  1505.             symbolPanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1506.             symbolPanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1507.             advancedTexture.addControl(symbolPanel);
  1508.  
  1509.             var btcUsdButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/BTCUSDButton.png");
  1510.             btcUsdButton.width = 1;
  1511.             btcUsdButton.height = "160px";
  1512.             btcUsdButton.alpha = 1;
  1513.             btcUsdButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1514.             btcUsdButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1515.             //binanceButton.cornerRadius = 20;
  1516.             btcUsdButton.onPointerDownObservable.add(function(value) {
  1517.                 symbol = "BTCUSD";
  1518.                 priceOffsetMultiplier = 1;
  1519.                 quantityScaleFactor = 2;
  1520.                 chartAmplitude = 1;
  1521.                 symbolPanel.isVisible = false;
  1522.                 symbolButton.children[0].source = "textures/BTCUSDButton.png";
  1523.                reset();
  1524.          
  1525.             });
  1526.  
  1527.             symbolPanel.addControl(btcUsdButton);
  1528.  
  1529.             var ethUsdButton = BABYLON.GUI.Button.CreateImageOnlyButton("but", "textures/ETHUSDButton.png");
  1530.             ethUsdButton.width = 1;
  1531.             ethUsdButton.height = "160px";
  1532.             ethUsdButton.alpha = 1;
  1533.             ethUsdButton.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  1534.             ethUsdButton.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
  1535.             //binanceButton.cornerRadius = 20;
  1536.             ethUsdButton.onPointerDownObservable.add(function(value) {
  1537.                 symbol = "ETHUSD";
  1538.                 priceOffsetMultiplier = 20;
  1539.                 quantityScaleFactor = 0.2;
  1540.                 chartAmplitude = 10;
  1541.                 symbolPanel.isVisible = false;
  1542.                 symbolButton.children[0].source = "textures/ETHUSDButton.png";
  1543.                reset();
  1544.          
  1545.             });
  1546.  
  1547.             symbolPanel.addControl(ethUsdButton);
  1548.  
  1549.             midPriceMarker = BABYLON.MeshBuilder.CreateBox("box", {height: 0.01, width: 1.25, depth: 5}, scene);
  1550.             midPriceMarker.position.y = 0.1;
  1551.             midPriceMarker.position.z = -8.1;
  1552.             midPriceMarker.rotation.y = Math.PI/2;
  1553.             midPriceMarker.scaling.y = 0.01;
  1554.             midPriceMarker.scaling.x = 1;
  1555.             midPriceMarker.scaling.z = 1;
  1556.             midPriceTexture = new BABYLON.DynamicTexture(name, {width:256, height:128}, scene);
  1557.             midPriceTexture.hasAlpha = true;
  1558.             var ctx = midPriceTexture.getContext();
  1559.             ctx.fillStyle = 'transparent';
  1560.             var midPriceMaterial = new BABYLON.StandardMaterial("Midprice", scene);                    
  1561.             midPriceMaterial.diffuseTexture = midPriceTexture;
  1562.             midPriceMarker.material = midPriceMaterial;  
  1563.  
  1564.             var midPriceLine = BABYLON.MeshBuilder.CreateBox("box", {height: 0.02, width: 0.1, depth: 7}, scene);
  1565.             midPriceLine.position.y = -0.10;
  1566.             midPriceLine.rotation.y = Math.PI/2;
  1567.             midPriceLine.position.x = -3.2;
  1568.             midPriceLine.material = plasticMaterial;
  1569.             midPriceLine.parent = midPriceMarker;
  1570.  
  1571.             var spreadGradientMaterial = new BABYLON.StandardMaterial("grad", scene);
  1572.             spreadGradientMaterial.diffuseTexture = new  BABYLON.Texture("textures/BluePurpleGradient.png", scene);
  1573.  
  1574.             spreadMarker = BABYLON.MeshBuilder.CreatePlane("spread",1, scene);
  1575.             spreadMarker.parent = midPriceMarker;
  1576.             spreadMarker.material = spreadGradientMaterial;
  1577.             spreadMarker.position.y = .01;
  1578.             spreadMarker.position.x = -6.35;
  1579.             spreadMarker.rotation.x = Math.PI/2;
  1580.             spreadMarker.rotation.y = -Math.PI/2;
  1581.  
  1582.             spreadMarker.scaling.x = 1;
  1583.             //spreadMarker.position.y = 0;
  1584.  
  1585.             spreadLabel = BABYLON.MeshBuilder.CreateBox("box", {height: 0.001, width: 0.75, depth: 1.5}, scene);
  1586.             spreadLabel.parent = midPriceMarker;
  1587.             spreadLabel.position.y = 0.1;
  1588.             spreadLabel.position.x = -6.35;
  1589.             //spreadLabel.rotation.y = Math.PI/2;
  1590.             spreadLabel.scaling.x = 1;
  1591.             spreadLabel.scaling.z = 1;
  1592.             spreadLabelTexture = new BABYLON.DynamicTexture(name, {width:256, height:128}, scene);
  1593.             spreadLabelTexture.hasAlpha = true;
  1594.             //var ctx = spreadLabelTexture.getContext();
  1595.             //ctx.fillStyle = 'transparent';
  1596.             var spreadLabelMaterial = new BABYLON.StandardMaterial("SpreadLabel", scene);                    
  1597.             spreadLabelMaterial.diffuseTexture = spreadLabelTexture;
  1598.             spreadLabel.material = spreadLabelMaterial;  
  1599.  
  1600.             bidPriceMarker = BABYLON.MeshBuilder.CreateBox("box", {height: 0.01, width: 1.25, depth: 5}, scene);
  1601.             bidPriceMarker.position.y = 0.1;
  1602.             bidPriceMarker.position.z = -5;
  1603.             bidPriceMarker.rotation.y = Math.PI;
  1604.             bidPriceMarker.scaling.x = 1;
  1605.             bidPriceMarker.scaling.z = 1;
  1606.             bidPriceTexture = new BABYLON.DynamicTexture(name, {width:256, height:128}, scene);
  1607.             var bidPriceMaterial = new BABYLON.StandardMaterial("Bidprice", scene);                    
  1608.             bidPriceMaterial.diffuseTexture = bidPriceTexture;
  1609.             bidPriceMarker.material = bidPriceMaterial;
  1610.  
  1611.             askPriceMarker = BABYLON.MeshBuilder.CreateBox("box", {height: 0.01, width: 1.25, depth: 5}, scene);
  1612.             askPriceMarker.position.y = 0.05;
  1613.             askPriceMarker.position.z = -5;
  1614.             askPriceMarker.rotation.y = Math.PI;
  1615.             askPriceMarker.scaling.x = 1;
  1616.             askPriceMarker.scaling.z = 1;
  1617.             askPriceTexture = new BABYLON.DynamicTexture(name, {width:256, height:128}, scene);
  1618.             var askPriceMaterial = new BABYLON.StandardMaterial("Askprice", scene);                    
  1619.             askPriceMaterial.diffuseTexture = askPriceTexture;
  1620.             askPriceMarker.material = askPriceMaterial;
  1621.  
  1622.             lowPriceMarker = BABYLON.MeshBuilder.CreateBox("box", {height: 0.01, width: 1, depth: 2.5}, scene);
  1623.             lowPriceMarker.position.z = -14.25;
  1624.             lowPriceMarker.scaling.x = 1;
  1625.             lowPriceMarker.scaling.z = 1;
  1626.             lowPriceMarker.rotation.y = Math.PI;
  1627.             lowPriceTexture = new BABYLON.DynamicTexture(name, {width:250, height:128}, scene);
  1628.             var lowPriceMaterial = new BABYLON.StandardMaterial("Lowprice", scene);                    
  1629.             lowPriceMaterial.diffuseTexture = lowPriceTexture;
  1630.             lowPriceMarker.material = lowPriceMaterial;  
  1631.  
  1632.             highPriceMarker = BABYLON.MeshBuilder.CreateBox("box", {height: 0.01, width: 1, depth: 2.5}, scene);
  1633.             highPriceMarker.position.z = -14.25;
  1634.             highPriceMarker.scaling.x = 1;
  1635.             highPriceMarker.scaling.z = 1;
  1636.             highPriceMarker.rotation.y = Math.PI;
  1637.             highPriceTexture = new BABYLON.DynamicTexture(name, {width:256, height:128}, scene);
  1638.             var highPriceMaterial = new BABYLON.StandardMaterial("Highprice", scene);                    
  1639.             highPriceMaterial.diffuseTexture = highPriceTexture;
  1640.             highPriceMarker.material = highPriceMaterial;  
  1641.  
  1642.             lastTradeMarker = BABYLON.MeshBuilder.CreateBox("box", {height: 0.01, width: 1.25, depth: 5}, scene);
  1643.             //lastTradeMarker.position.y = 2;
  1644.             lastTradeMarker.position.z = -11.2;
  1645.             lastTradeMarker.rotation.y = Math.PI;
  1646.             lastTradeMarker.scaling.x = 1;
  1647.             lastTradeMarker.scaling.z = 1;
  1648.             lastTradeTexture = new BABYLON.DynamicTexture(name, {width:256, height:128}, scene);
  1649.             var lastTradeMaterial = new BABYLON.StandardMaterial("LastTrade", scene);                    
  1650.             lastTradeMaterial.diffuseTexture = lastTradeTexture;
  1651.             lastTradeMarker.material = lastTradeMaterial;
  1652.  
  1653.             /*
  1654.             var mynextLowestTenMarker = BABYLON.MeshBuilder.CreateBox("nextLowestTen", {height: 0.01, width: 1.5, depth: 5}, scene);
  1655.             mynextLowestTenMarker.position.y = 0.1;
  1656.             mynextLowestTenMarker.position.z = -15;
  1657.             mynextLowestTenMarker.rotation.y = Math.PI;
  1658.             //var myNextLowestTenTexture = new BABYLON.DynamicTexture(name, {width:512, height:256}, scene);
  1659.             var nextLowestTenMaterial = new BABYLON.StandardMaterial("NextLowestTen", scene);                    
  1660.             nextLowestTenMaterial.diffuseTexture = nextLowestTenMaterial;
  1661.             mynextLowestTenMarker.material = nextLowestTenMaterial;
  1662.            
  1663.             nextHighestTenMarker = BABYLON.MeshBuilder.CreateBox("box", {height: 0.01, width: 1.5, depth: 5}, scene);
  1664.             nextHighestTenMarker.position.y = 0.1;
  1665.             nextHighestTenMarker.position.z = -15;
  1666.             nextHighestTenMarker.rotation.y = Math.PI;
  1667.             nextHighestTenMarker.scaling.x = 1;
  1668.             nextHighestTenMarker.scaling.z = 1;
  1669.             nextHighestTenTexture = new BABYLON.DynamicTexture(name, {width:512, height:256}, scene);
  1670.             var nextHighestTenMaterial = new BABYLON.StandardMaterial("NextHighestTen", scene);                    
  1671.             nextHighestTenMaterial.diffuseTexture = nextHighestTenTexture;
  1672.             nextHighestTenMarker.material = nextHighestTenMaterial;
  1673.             */
  1674.  
  1675.  
  1676.  
  1677.  
  1678.  
  1679.  
  1680.             scene.registerBeforeRender(function ()
  1681.             {
  1682.  
  1683.                 if(dataLoaded)
  1684.                 {
  1685.  
  1686.                   timeDamper =  lerp(timeDamper,1.0, 0.0925);
  1687.  
  1688.                     if (frontBarHeightMultiplier > 0)
  1689.                         frontBarHeightMultiplier -= 0.01;
  1690.  
  1691.  
  1692.                     gridOffsetZ += 0.01667;
  1693.  
  1694.                     if (tradeMarkerAlpha > 0)
  1695.                         tradeMarkerAlpha -= 0.01;
  1696.  
  1697.                     gridMaterial.gridOffset = new BABYLON.Vector3(-gridOffsetX,0, -gridOffsetZ * cellDepth);
  1698.  
  1699.                     spsBid.setParticles();
  1700.                     spsAsk.setParticles();
  1701.                     spsBuys.setParticles();
  1702.                     spsSells.setParticles();
  1703.                     spsGrid.setParticles();
  1704.                     var updateIndex = tempUpdateIndex;
  1705.                     //var currentFrontMidPrice = 0;
  1706.                     var lowPrice = 0
  1707.                     var highPrice = 0;
  1708.                     var bidPrice = 0;
  1709.                     var askPrice = 0;
  1710.                    
  1711.        
  1712.                     //currentFrontMidPrice = midPrices[numRows - 1];// + 0;
  1713.                     lowPrice = book.bids[numColumns-1].price;
  1714.                     highPrice = book.asks[numColumns-1].price;
  1715.                     bidPrice = book.bids[0].price;
  1716.                     askPrice = book.asks[0].price;                      
  1717.                
  1718.                     var cellPriceWidth = cellPercentage * originPrice;
  1719.                    
  1720.                    
  1721.                     var midPriceOffset = (currentMidPrice-originPrice);
  1722.                     var midPriceMarkerOffsetX =   midPriceOffset * priceOffsetMultiplier * cellWidth;
  1723.  
  1724.                    
  1725.                     var lowPriceMarkerOffsetX = (lowPrice - originPrice)  * priceOffsetMultiplier * cellWidth;
  1726.                     var highPriceMarkerOffsetX =  (highPrice - originPrice)  * priceOffsetMultiplier * cellWidth;
  1727.  
  1728.                     var bidPriceMarkerOffsetX = (bidPrice - originPrice)  * priceOffsetMultiplier * cellWidth - (cellWidth *0.5);
  1729.                     var askPriceMarkerOffsetX =  (askPrice - originPrice) * priceOffsetMultiplier * cellWidth + cellWidth * 0.5;
  1730.  
  1731.                     var nextLowestTen =  originPrice -  (originPrice % 10);
  1732.                     var nextHighestTen =  nextLowestTen + 10;
  1733.  
  1734.  
  1735.  
  1736.                     var nextLowestTenMarkerOffsetX =  (nextLowestTen -  originPrice ) * cellWidth + (cellWidth / 2);
  1737.                     var nextHighestTenMarkerOffsetX =  (nextHighestTen - originPrice ) * cellWidth + (cellWidth / 2);
  1738.  
  1739.  
  1740.  
  1741.  
  1742.                     midPriceMarker.position.x = midPriceMarkerOffsetX ;
  1743.                     //midPriceMarker.position.y = 1;
  1744.                     lowPriceMarker.position.x = nextLowestTenMarkerOffsetX;
  1745.                     highPriceMarker.position.x = nextHighestTenMarkerOffsetX;
  1746.                     bidPriceMarker.position.x = bidPriceMarkerOffsetX;
  1747.                     askPriceMarker.position.x = askPriceMarkerOffsetX;
  1748.                     spreadMarker.scaling.x = askPriceMarkerOffsetX - bidPriceMarkerOffsetX;
  1749.                     //nextLowestTenMarker.position.x = nextLowestTenMarkerOffsetX;
  1750.  
  1751.  
  1752.                     var font = "bold 50px monospace";
  1753.  
  1754.                     if ( (currentMidPrice - previousMidPrice) >= 0.01)
  1755.                         midpriceMarkerColor = "blue";
  1756.                     else if (currentMidPrice < previousMidPrice)
  1757.                         midpriceMarkerColor = "purple";
  1758.                     else
  1759.                         midpriceMarkerColor = "black";
  1760.  
  1761.                    
  1762.                     midPriceTexture.drawText(currentMidPrice.toString(), 20, 80, font, "white", midpriceMarkerColor, true, true);
  1763.  
  1764.                     lowPriceTexture.drawText(nextLowestTen.toString(), 30, 80, font, "white", "purple", true, true);
  1765.                     highPriceTexture.drawText(nextHighestTen.toString(), 30, 80, font, "white", "blue", true, true);
  1766.  
  1767.                     //nextLowestTenTexture.drawText(nextLowestTen.toString(), 40, 135, font, "white", "purple", true, true);
  1768.  
  1769.  
  1770.                     var bidAskfont = "bold 50px monospace";
  1771.                     bidPriceTexture.drawText(bidPrice.toString(), 30, 80, bidAskfont, "white", "blue", true, true);
  1772.                     askPriceTexture.drawText(askPrice.toString(), 30, 80, bidAskfont, "white", "purple", true, true);
  1773.  
  1774.                     var spread = Math.abs( Number(askPrice - bidPrice).toFixed(2));
  1775.  
  1776.                     var spreadFont = "bold 100px monospace";
  1777.                     //spreadLabelTexture.clear();
  1778.                     spreadLabelTexture.drawText(spread.toString(), 30, 80, spreadFont, "white", "black", true, true);
  1779.  
  1780.                     //camera.setPosition(new BABYLON.Vector3(-midPriceMarkerOffsetX, 0, -200));
  1781.                    
  1782.                     if (cameraTweenEnabled)
  1783.                         cameraHolder.position.x =  lerp(cameraHolder.position.x,midPriceMarkerOffsetX, 0.05);// midPriceMarkerOffsetX;
  1784.                     else
  1785.                         cameraHolder.position.x = midPriceMarkerOffsetX;// midPriceMarkerOffsetX;
  1786.  
  1787.                     //logo.position.x = lerp(logo.position.x,midPriceMarkerOffsetX, 0.05);// midPriceMarkerOffsetX;
  1788.                    
  1789.                     if (tradeHistory.length > 0)
  1790.                     {
  1791.                         var lastTradeData = tradeHistory[0];
  1792.                         var tradeSide = lastTradeData[0];
  1793.                         var tradePrice =  Number(lastTradeData[1]).toFixed(2);
  1794.                         var tradeQuantity = Number(lastTradeData[2]).toFixed(2);
  1795.  
  1796.                         var lastTradeMarkerOffsetX = 0;
  1797.  
  1798.                         lastTradeMarker.material.alpha = tradeMarkerAlpha;
  1799.  
  1800.                         var tradeFont = "bold 50px monospace";
  1801.                         var message =  tradePrice.toString();// + "@"  + tradePrice.toString()
  1802.                         if (tradeSide === 'b')
  1803.                         {
  1804.                             lastTradeMarkerOffsetX = (tradePrice - originPrice)  * cellWidth + (cellWidth * 0.5);
  1805.                            
  1806.                             if (tradePrice > askPrice)
  1807.                                 lastTradeTexture.drawText(message, 30, 80, tradeFont, "white", "green", true, true);
  1808.                             else
  1809.                                 lastTradeTexture.drawText(message, 30, 80, tradeFont, "white", "blue", true, true);
  1810.  
  1811.                             //currentMomentum = currentMomentum + 0.05;
  1812.                             currentMomentum = Math.min(currentMomentum + (tradeQuantity * 0.1), maxMomentum);
  1813.                            
  1814.                             //lastTradeMarkerOffsetX = askPriceMarkerOffsetX;                  
  1815.                         }            
  1816.                         else
  1817.                         {
  1818.                             lastTradeMarkerOffsetX = (tradePrice - originPrice)  * cellWidth - (cellWidth * 0.5);
  1819.  
  1820.                             if (tradePrice < bidPrice)
  1821.                                 lastTradeTexture.drawText(message, 30, 80, tradeFont, "white", "red", true, true);
  1822.                             else
  1823.                                 lastTradeTexture.drawText(message, 30, 80, tradeFont, "white", "purple", true, true);
  1824.  
  1825.                             //currentMomentum = currentMomentum - 0.05;
  1826.                             currentMomentum = Math.max(currentMomentum - (tradeQuantity * 0.1), minMomentum);
  1827.                        
  1828.                             //lastTradeMarkerOffsetX = bidPriceMarkerOffsetX;
  1829.                         }
  1830.  
  1831.                           //if (enableLogging)
  1832.                           //  BABYLON.Tools.Log("Momentum: " + currentMomentum);
  1833.  
  1834.                        
  1835.  
  1836.                         lastTradeMarker.position.x = lastTradeMarkerOffsetX;//   lerp(lastTradeMarker.position.x,lastTradeMarkerOffsetX, 0.1);
  1837.                     }
  1838.                    
  1839.                     var cameraHomeAlpha =  Math.PI + (Math.PI / 2) - ( (Math.PI/128) * ( currentMomentum) );
  1840.  
  1841.                     if (resetCamera)
  1842.                         camera.alpha= lerp(camera.alpha,cameraHomeAlpha, cameraAlphaFalloff);// midPriceMarkerOffsetX;
  1843.  
  1844.                     currentMomentum = lerp(currentMomentum,0,0.02);
  1845.                 }
  1846.                 else
  1847.                 {
  1848.                     cameraHolder.position.x = (currentMidPrice-originPrice)  * priceOffsetMultiplier * cellWidth;
  1849.                 }  
  1850.  
  1851.  
  1852.                 });
  1853.            
  1854.  
  1855.             return scene;
  1856.         };
  1857.        
  1858.         var engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
  1859.         subscribeToMarket();
  1860.         var scene = createScene();
  1861.  
  1862.         engine.runRenderLoop(function () {
  1863.             if (scene) {
  1864.                 pl.position = camera.position;
  1865.                 // /logo.isVisible = false;
  1866.                 if (currentVolume < finalVolume)
  1867.                 {
  1868.  
  1869.                 }
  1870.                
  1871.                 if (midPrices.length > 1)
  1872.                 {
  1873.                     gridOffsetX = 0; //(midPrices[updateIndex] - midPrices[0]) * priceShiftFactor;
  1874.                     //alert(gridOffsetX);
  1875.                 }                
  1876.                 scene.render();
  1877.             }
  1878.         });
  1879.  
  1880.         // Resize
  1881.         window.addEventListener("resize", function () {
  1882.             engine.resize();
  1883.         });
  1884.  
  1885.  
  1886.         function compBids(a, b) {
  1887.             return b.price - a.price;
  1888.         }
  1889.  
  1890.         function compAsks(a, b) {
  1891.             return a.price - b.price;
  1892.         }
  1893.  
  1894.         setInterval(() =>
  1895.         {
  1896.             cloneFrontRow();
  1897.             midPrices.push(currentMidPrice);
  1898.              tempUpdateIndex ++;
  1899.             frontBarHeightMultiplier = 0;
  1900.             timeDamper = 0;
  1901.            
  1902.         }, 500);
  1903.  
  1904.         setInterval(() =>
  1905.         {
  1906.             fetchChartData(symbol,exchange);
  1907.         }, 10000);
  1908.  
  1909.         function enableCameraTween()
  1910.         {
  1911.             cameraTweenEnabled = true;
  1912.         }
  1913.  
  1914.         function enableCameraHome()
  1915.         {
  1916.             resetCamera = true;
  1917.         }
RAW Paste Data