3dupdate
diff --git a/build/parser/bodymovin_parser.jsx b/build/parser/bodymovin_parser.jsx
index a953628..41b8f0c 100644
--- a/build/parser/bodymovin_parser.jsx
+++ b/build/parser/bodymovin_parser.jsx
@@ -579,7 +579,7 @@
             var layerInfo = pendingItem.lInfo;
             var frameRate = pendingItem.frameRate;
             var lType = extrasInstance.layerType(layerInfo);
-            if(lType == 'AudioLayer' || lType == 'CameraLayer' || layerInfo.enabled == false){
+            if(lType == 'AudioLayer' || layerInfo.enabled == false){
                 //TODO add audios
                 layerOb.enabled = false;
                 analyzeNextLayer();
@@ -598,7 +598,7 @@
 
             EffectsParser.createEffects(layerInfo,layerOb);
 
-            if(layerInfo.mask.numProperties>0){
+            if(layerInfo.mask && layerInfo.mask.numProperties>0){
                 setMasks(layerInfo.mask,layerOb);
                 layerOb.hasMask = true;
             }
@@ -640,10 +640,28 @@
             }else{
                 layerOb.ks.o = extrasInstance.roundNumber(layerInfo.transform.opacity.valueAtTime(0,false),3);
             }
-            if(layerInfo.transform.rotation.numKeys>1){
-                extrasInstance.convertToBezierValues(layerInfo.transform.rotation, frameRate, layerOb.ks,'r');
+            if(layerInfo.transform.rotation){
+                if(layerInfo.transform.rotation.numKeys>1){
+                    extrasInstance.convertToBezierValues(layerInfo.transform.rotation, frameRate, layerOb.ks,'r');
+                }else{
+                    layerOb.ks.r = extrasInstance.roundNumber(layerInfo.transform.rotation.valueAtTime(0,false),3);
+                }
             }else{
-                layerOb.ks.r = extrasInstance.roundNumber(layerInfo.transform.rotation.valueAtTime(0,false),3);
+                if(layerInfo.transform.xRotation.numKeys>1){
+                    extrasInstance.convertToBezierValues(layerInfo.transform.xRotation, frameRate, layerOb.ks,'rx');
+                }else{
+                    layerOb.ks.rx = extrasInstance.roundNumber(layerInfo.transform.xRotation.valueAtTime(0,false),3);
+                }
+                if(layerInfo.transform.yRotation.numKeys>1){
+                    extrasInstance.convertToBezierValues(layerInfo.transform.yRotation, frameRate, layerOb.ks,'ry');
+                }else{
+                    layerOb.ks.ry = extrasInstance.roundNumber(layerInfo.transform.yRotation.valueAtTime(0,false),3);
+                }
+                if(layerInfo.transform.zRotation.numKeys>1){
+                    extrasInstance.convertToBezierValues(layerInfo.transform.zRotation, frameRate, layerOb.ks,'rz');
+                }else{
+                    layerOb.ks.rz = extrasInstance.roundNumber(layerInfo.transform.zRotation.valueAtTime(0,false),3);
+                }
             }
             if(layerInfo.transform.position.numKeys>1){
                 extrasInstance.convertToBezierValues(layerInfo.transform.position, frameRate, layerOb.ks,'p');
@@ -820,14 +838,18 @@
         adjustNextHelperSpeed();
     }
 
-    function createLayers(compo, layersData, frameRate){
+    function createLayers(compo, layersData, frameRate,isMain){
         var i, len = compo.layers.length;
         for(i = 0;i<len;i++){
             var layerOb = {};
             var layerInfo = compo.layers[i+1];
             var lType = extrasInstance.layerType(layerInfo);
             layersData.push(layerOb);
-            if(lType == 'AudioLayer' || lType == 'CameraLayer' || layerInfo.enabled == false){
+            if(lType == 'CameraLayer' && isMain){
+                layerOb.isCamera = true;
+                layerOb.pe = layerInfo.property('Camera Options').property('Zoom').value;
+            }
+            if(lType == 'AudioLayer' || (lType == 'CameraLayer' && !isMain) || layerInfo.enabled == false){
                 //TODO add audios
                 layerOb.enabled = false;
                 continue;
@@ -835,7 +857,7 @@
             pendingLayers.push({lInfo:layerInfo,lOb:layerOb,frameRate:frameRate});
             if(lType=='PreCompLayer'){
                 layerOb.layers = [];
-                createLayers(layerInfo.source,layerOb.layers,layerInfo.source.frameRate);
+                createLayers(layerInfo.source,layerOb.layers,layerInfo.source.frameRate,false);
             }
 
         }
@@ -852,12 +874,12 @@
         return {width:0,height:0};
     }
 
-    function traverseAnimation(compo,layersData, frameNum, time){
+    function traverseAnimation(compo,layersData, frameNum, time, isMain){
         var i, len = compo.layers.length;
         for(i = 0;i<len;i++){
             var layerInfo = compo.layers[i+1];
             var lType = extrasInstance.layerType(layerInfo);
-            if(lType == 'AudioLayer' || lType == 'CameraLayer' || layerInfo.enabled == false){
+            if(lType == 'AudioLayer' || (lType == 'CameraLayer' && !isMain) || layerInfo.enabled == false){
                 //TODO add audios
                 continue;
             }
@@ -913,7 +935,7 @@
             }
             if(lType == 'PreCompLayer'){
                 var compoInTime = -layerInfo.startTime;
-                traverseAnimation(layerInfo.source,layerOb.layers, frameNum, time+compoInTime);
+                traverseAnimation(layerInfo.source,layerOb.layers, frameNum, time+compoInTime, false);
             }
             //THIS IS REPLACED WITH THE KEYFRAMES. LEAVE THIS FOR NOW.
             /*if(layerOb.lastData.an == null || extrasInstance.compareObjects(animData,layerOb.lastData.an)==false){
@@ -925,7 +947,7 @@
     }
 
     function iterateComposition(){
-        createLayers(mainComp, mainLayers, mainComp.frameRate);
+        createLayers(mainComp, mainLayers, mainComp.frameRate,true);
         // TO TRAVERSE LAYER BY LAYER. NEEDED FOR TIME REMAP?
         /*renderCompo(mainComp, mainLayers);
          AssetsManager.createAssetsDataForExport();
@@ -1056,7 +1078,7 @@
     function renderFrame(){
         currentTime = (currentRenderFrame+firstFrame)/frameRate;
         zCount = 0;
-        traverseAnimation(mainComp,mainLayers, currentRenderFrame,currentTime);
+        traverseAnimation(mainComp,mainLayers, currentRenderFrame,currentTime,true);
     }
 
     function setCallback(cb){
@@ -1078,7 +1100,7 @@
     var registeredEffects = {};
 
     function createEffects(layerInfo,layerOb){
-        if(layerInfo.effect.numProperties>0){
+        if(layerInfo.effect && layerInfo.effect.numProperties>0){
             layerOb.eff = [];
             var i, len = layerInfo.effect.numProperties, name;
             for(i=0;i<len;i++){
@@ -2459,8 +2481,8 @@
         if(!renderCancelled){
             var dataFile = new File(exportFolder.fullName+'/data.json');
             dataFile.open('w','TEXT','????');
-            dataFile.write(JSON.stringify(compositionData)); //DO NOT ERASE, JSON UNFORMATTED
-            //dataFile.write(JSON.stringify(compositionData, null, '  ')); //DO NOT ERASE, JSON FORMATTED
+            //dataFile.write(JSON.stringify(compositionData)); //DO NOT ERASE, JSON UNFORMATTED
+            dataFile.write(JSON.stringify(compositionData, null, '  ')); //DO NOT ERASE, JSON FORMATTED
             dataFile.close();
         }
         currentCompositionData.rendered = true;
diff --git a/parser/CompConverter.js b/parser/CompConverter.js
index e064ef6..c493c93 100644
--- a/parser/CompConverter.js
+++ b/parser/CompConverter.js
@@ -16,8 +16,8 @@
         if(!renderCancelled){
             var dataFile = new File(exportFolder.fullName+'/data.json');
             dataFile.open('w','TEXT','????');
-            dataFile.write(JSON.stringify(compositionData)); //DO NOT ERASE, JSON UNFORMATTED
-            //dataFile.write(JSON.stringify(compositionData, null, '  ')); //DO NOT ERASE, JSON FORMATTED
+            //dataFile.write(JSON.stringify(compositionData)); //DO NOT ERASE, JSON UNFORMATTED
+            dataFile.write(JSON.stringify(compositionData, null, '  ')); //DO NOT ERASE, JSON FORMATTED
             dataFile.close();
         }
         currentCompositionData.rendered = true;
diff --git a/parser/DOMAnimationManager.js b/parser/DOMAnimationManager.js
index 4f67c36..aba8a3d 100644
--- a/parser/DOMAnimationManager.js
+++ b/parser/DOMAnimationManager.js
@@ -170,7 +170,7 @@
             var layerInfo = pendingItem.lInfo;
             var frameRate = pendingItem.frameRate;
             var lType = extrasInstance.layerType(layerInfo);
-            if(lType == 'AudioLayer' || lType == 'CameraLayer' || layerInfo.enabled == false){
+            if(lType == 'AudioLayer' || layerInfo.enabled == false){
                 //TODO add audios
                 layerOb.enabled = false;
                 analyzeNextLayer();
@@ -189,7 +189,7 @@
 
             EffectsParser.createEffects(layerInfo,layerOb);
 
-            if(layerInfo.mask.numProperties>0){
+            if(layerInfo.mask && layerInfo.mask.numProperties>0){
                 setMasks(layerInfo.mask,layerOb);
                 layerOb.hasMask = true;
             }
@@ -231,10 +231,28 @@
             }else{
                 layerOb.ks.o = extrasInstance.roundNumber(layerInfo.transform.opacity.valueAtTime(0,false),3);
             }
-            if(layerInfo.transform.rotation.numKeys>1){
-                extrasInstance.convertToBezierValues(layerInfo.transform.rotation, frameRate, layerOb.ks,'r');
+            if(layerInfo.transform.rotation){
+                if(layerInfo.transform.rotation.numKeys>1){
+                    extrasInstance.convertToBezierValues(layerInfo.transform.rotation, frameRate, layerOb.ks,'r');
+                }else{
+                    layerOb.ks.r = extrasInstance.roundNumber(layerInfo.transform.rotation.valueAtTime(0,false),3);
+                }
             }else{
-                layerOb.ks.r = extrasInstance.roundNumber(layerInfo.transform.rotation.valueAtTime(0,false),3);
+                if(layerInfo.transform.xRotation.numKeys>1){
+                    extrasInstance.convertToBezierValues(layerInfo.transform.xRotation, frameRate, layerOb.ks,'rx');
+                }else{
+                    layerOb.ks.rx = extrasInstance.roundNumber(layerInfo.transform.xRotation.valueAtTime(0,false),3);
+                }
+                if(layerInfo.transform.yRotation.numKeys>1){
+                    extrasInstance.convertToBezierValues(layerInfo.transform.yRotation, frameRate, layerOb.ks,'ry');
+                }else{
+                    layerOb.ks.ry = extrasInstance.roundNumber(layerInfo.transform.yRotation.valueAtTime(0,false),3);
+                }
+                if(layerInfo.transform.zRotation.numKeys>1){
+                    extrasInstance.convertToBezierValues(layerInfo.transform.zRotation, frameRate, layerOb.ks,'rz');
+                }else{
+                    layerOb.ks.rz = extrasInstance.roundNumber(layerInfo.transform.zRotation.valueAtTime(0,false),3);
+                }
             }
             if(layerInfo.transform.position.numKeys>1){
                 extrasInstance.convertToBezierValues(layerInfo.transform.position, frameRate, layerOb.ks,'p');
@@ -411,14 +429,18 @@
         adjustNextHelperSpeed();
     }
 
-    function createLayers(compo, layersData, frameRate){
+    function createLayers(compo, layersData, frameRate,isMain){
         var i, len = compo.layers.length;
         for(i = 0;i<len;i++){
             var layerOb = {};
             var layerInfo = compo.layers[i+1];
             var lType = extrasInstance.layerType(layerInfo);
             layersData.push(layerOb);
-            if(lType == 'AudioLayer' || lType == 'CameraLayer' || layerInfo.enabled == false){
+            if(lType == 'CameraLayer' && isMain){
+                layerOb.isCamera = true;
+                layerOb.pe = layerInfo.property('Camera Options').property('Zoom').value;
+            }
+            if(lType == 'AudioLayer' || (lType == 'CameraLayer' && !isMain) || layerInfo.enabled == false){
                 //TODO add audios
                 layerOb.enabled = false;
                 continue;
@@ -426,7 +448,7 @@
             pendingLayers.push({lInfo:layerInfo,lOb:layerOb,frameRate:frameRate});
             if(lType=='PreCompLayer'){
                 layerOb.layers = [];
-                createLayers(layerInfo.source,layerOb.layers,layerInfo.source.frameRate);
+                createLayers(layerInfo.source,layerOb.layers,layerInfo.source.frameRate,false);
             }
 
         }
@@ -443,12 +465,12 @@
         return {width:0,height:0};
     }
 
-    function traverseAnimation(compo,layersData, frameNum, time){
+    function traverseAnimation(compo,layersData, frameNum, time, isMain){
         var i, len = compo.layers.length;
         for(i = 0;i<len;i++){
             var layerInfo = compo.layers[i+1];
             var lType = extrasInstance.layerType(layerInfo);
-            if(lType == 'AudioLayer' || lType == 'CameraLayer' || layerInfo.enabled == false){
+            if(lType == 'AudioLayer' || (lType == 'CameraLayer' && !isMain) || layerInfo.enabled == false){
                 //TODO add audios
                 continue;
             }
@@ -504,7 +526,7 @@
             }
             if(lType == 'PreCompLayer'){
                 var compoInTime = -layerInfo.startTime;
-                traverseAnimation(layerInfo.source,layerOb.layers, frameNum, time+compoInTime);
+                traverseAnimation(layerInfo.source,layerOb.layers, frameNum, time+compoInTime, false);
             }
             //THIS IS REPLACED WITH THE KEYFRAMES. LEAVE THIS FOR NOW.
             /*if(layerOb.lastData.an == null || extrasInstance.compareObjects(animData,layerOb.lastData.an)==false){
@@ -516,7 +538,7 @@
     }
 
     function iterateComposition(){
-        createLayers(mainComp, mainLayers, mainComp.frameRate);
+        createLayers(mainComp, mainLayers, mainComp.frameRate,true);
         // TO TRAVERSE LAYER BY LAYER. NEEDED FOR TIME REMAP?
         /*renderCompo(mainComp, mainLayers);
          AssetsManager.createAssetsDataForExport();
@@ -647,7 +669,7 @@
     function renderFrame(){
         currentTime = (currentRenderFrame+firstFrame)/frameRate;
         zCount = 0;
-        traverseAnimation(mainComp,mainLayers, currentRenderFrame,currentTime);
+        traverseAnimation(mainComp,mainLayers, currentRenderFrame,currentTime,true);
     }
 
     function setCallback(cb){
diff --git a/parser/EffectsParser.js b/parser/EffectsParser.js
index d625079..ed11b4b 100644
--- a/parser/EffectsParser.js
+++ b/parser/EffectsParser.js
@@ -4,7 +4,7 @@
     var registeredEffects = {};
 
     function createEffects(layerInfo,layerOb){
-        if(layerInfo.effect.numProperties>0){
+        if(layerInfo.effect && layerInfo.effect.numProperties>0){
             layerOb.eff = [];
             var i, len = layerInfo.effect.numProperties, name;
             for(i=0;i<len;i++){
diff --git a/player/index.html b/player/index.html
index a3aebe2..030e5cd 100644
--- a/player/index.html
+++ b/player/index.html
@@ -2,6 +2,7 @@
 <meta charset="UTF-8">
 <head>
     <!-- build:js bodymovin.js -->
+    <script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
     <script src="js/main.js"></script>
     <script src="js/3rd_party/transformation-matrix.js"></script>
     <script src="js/utils/MatrixManager.js"></script>
@@ -13,6 +14,7 @@
     <script src="js/utils/DataManager.js"></script>
     <script src="js/renderers/SVGRenderer.js"></script>
     <script src="js/renderers/CanvasRenderer.js"></script>
+    <script src="js/renderers/DOMRenderer.js"></script>
     <script src="js/mask.js"></script>
     <script src="js/elements/BaseElement.js"></script>
     <script src="js/elements/CompElement.js"></script>
@@ -29,13 +31,50 @@
     <script src="js/elements/canvasElements/CVSolidElement.js"></script>
     <script src="js/elements/canvasElements/CVTextElement.js"></script>
     <script src="js/elements/canvasElements/CVMaskElement.js"></script>
+    <script src="js/elements/domElements/DBaseElement.js"></script>
+    <script src="js/elements/domElements/DImageElement.js"></script>
+    <script src="js/elements/domElements/DShapeElement.js"></script>
+    <script src="js/elements/domElements/DSolidElement.js"></script>
+    <script src="js/elements/domElements/DCompElement.js"></script>
     <script src="js/animation/AnimationManager.js"></script>
     <script src="js/animation/AnimationItem.js"></script>
      <script src="js/module.js"></script>
+    <script src="js/3rd_party/sylvester.js"></script>
     <!-- endbuild -->
 </head>
 <body style="background-color:#666; margin: 0px;height: 100%; font-family: sans-serif;font-size: 10px">
-<div style="width:510px;height:676px;background-color:#000;display:inline-block" class="bodymovin" data-bm-path="exports/mcangel" data-bm-type="canvas" data-bm-loop="true" data-bm-prerender="true"></div>
-<div style="width:510px;height:676px;background-color:#000;display:inline-block" class="bodymovin" data-bm-path="exports/mcangel" data-bm-type="svg" data-bm-loop="true" data-bm-prerender="true"></div>
+<div style="width:600px;height:795px" class="bodymovin" data-bm-path="exports/cameraComp" data-bm-type="threed" data-bm-loop="true" data-bm-prerender="true"></div>
+<script>
+    var pathsArray = [];
+    var uniquePaths = [];
+    var nanCount = 0;
+    function getUniquePaths(){
+        $.each(pathsArray, function(i, el){
+            if($.inArray(el, uniquePaths) === -1) uniquePaths.push(el);
+        });
+    }
+
+    function count() {
+        pathsArray.sort();
+
+        var current = null;
+        var cnt = 0;
+        for (var i = 0; i < pathsArray.length; i++) {
+            if (pathsArray[i] != current) {
+                if (cnt > 1) {
+                    document.write(current + ' comes --> ' + cnt + ' times<br>');
+                }
+                current = pathsArray[i];
+                cnt = 1;
+            } else {
+                cnt++;
+            }
+        }
+        if (cnt > 0) {
+            document.write(current + ' comes --> ' + cnt + ' times');
+        }
+
+    }
+</script>
 </body>
 </html>
diff --git a/player/js/3rd_party/transformation-matrix.js b/player/js/3rd_party/transformation-matrix.js
index 7378e9c..12c6ce1 100644
--- a/player/js/3rd_party/transformation-matrix.js
+++ b/player/js/3rd_party/transformation-matrix.js
@@ -27,27 +27,32 @@
  * @constructor
  */
 
-function Matrix(context) {
+function Matrix(dimension) {
 
     var me = this;
     me._t = me.transform;
+    me.dimension = dimension;
 
-    me.a = me.d = 1;
-    me.b = me.c = me.e = me.f = 0;
+    if(dimension == '2d'){
+        me.a = me.d = 1;
+        me.b = me.c = me.e = me.f = 0;
+        me.props = [1,0,0,1,0,0];
+        me.a1 = me.b1 = me.c1 = me.d1 = me.e1 = me.f1 = 0;
+    }else{
+        me.a = me.f = me.k = me.p = 1;
+        me.b = me.c = me.d = me.e = me.g = me.h = me.i = me.j = me.l = me.m = me.n = me.o = 0;
+        me.props = [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];
+        me.a1 = me.b1 = me.c1 = me.d1 = me.e1 = me.f1 = me.g1 = me.h1 = me.i1 = me.j1 = me.k1 = me.l1 = me.m1 = me.n1 = me.o1 = me.p1 = 0;
+    }
 
-    me.props = [1,0,0,1,0,0];
 
     me.cssParts = ['matrix(','',')'];
+    me.cssParts3d = ['matrix3d(','',')'];
 
-    me.a1 = me.b1 = me.c1 = me.d1 = me.e1 = me.f1 = 0;
-
-    me.context = context;
 
     me.cos = me.sin = 0;
 
 
-    // reset canvas transformations (if any) to enable 100% sync.
-    if (context) context.setTransform(1, 0, 0, 1, 0, 0);
 }
 Matrix.prototype = {
 
@@ -101,7 +106,11 @@
      * Short-hand to reset current matrix to an identity matrix.
      */
     reset: function() {
-        return this.setTransform(1, 0, 0, 1, 0, 0);
+        if(this.dimension == '2d'){
+            return this.setTransform(1, 0, 0, 1, 0, 0);
+        }else{
+            return this.setTransform(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+        }
     },
 
     /**
@@ -118,6 +127,44 @@
     },
 
     /**
+     * Rotates current matrix accumulative by angle.
+     * @param {number} angle - angle in radians
+     */
+    rotateX: function(angle) {
+        if(angle == 0){
+            return this;
+        }
+        this.cos = Math.cos(angle);
+        this.sin = Math.sin(angle);
+        return this._t(1, 0, 0, 0
+            , 0, this.cos, -this.sin, 0
+            , 0, this.sin,  this.cos, 0
+            , 0, 0, 0, 1);
+    },
+    rotateY: function(angle) {
+        if(angle == 0){
+            return this;
+        }
+        this.cos = Math.cos(angle);
+        this.sin = Math.sin(angle);
+        return this._t(this.cos,  0,  this.sin, 0
+            , 0, 1, 0, 0
+            , -this.sin,  0,  this.cos, 0
+            , 0, 0, 0, 1);
+    },
+    rotateZ: function(angle) {
+        if(angle == 0){
+            return this;
+        }
+        this.cos = Math.cos(angle);
+        this.sin = Math.sin(angle);
+        return this._t(this.cos, -this.sin,  0, 0
+            , this.sin,  this.cos, 0, 0
+            , 0,  0,  1, 0
+            , 0, 0, 0, 1);
+    },
+
+    /**
      * Converts a vector given as x and y to angle, and
      * rotates (accumulative).
      * @param x
@@ -149,11 +196,14 @@
      * @param {number} sx - scale factor x (1 does nothing)
      * @param {number} sy - scale factor y (1 does nothing)
      */
-    scale: function(sx, sy) {
-        if(sx == 1 && sy == 1){
+    scale: function(sx, sy, sz) {
+        if(sx == 1 && sy == 1 && (sz == 1 || sz == null)){
             return this;
         }
-        return this._t(sx, 0, 0, sy, 0, 0);
+        if(this.dimension == '2d'){
+            return this._t(sx, 0, 0, sy, 0, 0);
+        }
+        return this._t(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
     },
 
     /**
@@ -161,7 +211,10 @@
      * @param {number} sx - scale factor x (1 does nothing)
      */
     scaleX: function(sx) {
-        return this._t(sx, 0, 0, 1, 0, 0);
+        if(this.dimension == '2d'){
+            return this._t(sx, 0, 0, 1, 0, 0);
+        }
+        return this._t(sx, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
     },
 
     /**
@@ -169,7 +222,18 @@
      * @param {number} sy - scale factor y (1 does nothing)
      */
     scaleY: function(sy) {
-        return this._t(1, 0, 0, sy, 0, 0);
+        if(this.dimension == '2d'){
+            return this._t(1, 0, 0, sy, 0, 0);
+        }
+        return this._t(1, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+    },
+
+    /**
+     * Scales current matrix on y axis accumulative.
+     * @param {number} sy - scale factor y (1 does nothing)
+     */
+    scaleZ: function(sz) {
+        return this._t(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1);
     },
 
     /**
@@ -231,14 +295,26 @@
      * @param {number} e - translate x
      * @param {number} f - translate y
      */
-    setTransform: function(a, b, c, d, e, f) {
+    setTransform: function(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {
         this.props[0] = a;
         this.props[1] = b;
         this.props[2] = c;
         this.props[3] = d;
         this.props[4] = e;
         this.props[5] = f;
-        return this._x();
+        if(this.dimension == '3d'){
+            this.props[6] = g;
+            this.props[7] = h;
+            this.props[8] = i;
+            this.props[9] = j;
+            this.props[10] = k;
+            this.props[11] = l;
+            this.props[12] = m;
+            this.props[13] = n;
+            this.props[14] = o;
+            this.props[15] = p;
+        }
+        return this;
     },
 
     /**
@@ -246,8 +322,11 @@
      * @param {number} tx - translation for x
      * @param {number} ty - translation for y
      */
-    translate: function(tx, ty) {
-        return this._t(1, 0, 0, 1, tx, ty);
+    translate: function(tx, ty, tz) {
+        if(this.dimension == '2d'){
+            return this._t(1, 0, 0, 1, tx, ty);
+        }
+        return this._t(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1);
     },
 
     /**
@@ -255,7 +334,10 @@
      * @param {number} tx - translation for x
      */
     translateX: function(tx) {
-        return this._t(1, 0, 0, 1, tx, 0);
+        if(this.dimension == '2d'){
+            return this._t(1, 0, 0, 1, tx, 0);
+        }
+        return this._t(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, 0, 0, 1);
     },
 
     /**
@@ -263,7 +345,18 @@
      * @param {number} ty - translation for y
      */
     translateY: function(ty) {
-        return this._t(1, 0, 0, 1, 0, ty);
+        if(this.dimension == '2d'){
+            return this._t(1, 0, 0, 1, 0, ty);
+        }
+        return this._t(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, ty, 0, 1);
+    },
+
+    /**
+     * Translate current matrix on z axis accumulative.
+     * @param {number} tz - translation for z
+     */
+    translateY: function(ty) {
+        return this._t(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, tz, 1);
     },
 
     /**
@@ -275,26 +368,65 @@
      * @param {number} e2 - translate x
      * @param {number} f2 - translate y
      */
-    transform: function(a2, b2, c2, d2, e2, f2) {
-
+    transform: function(a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2, p2) {
         this.a1 = this.props[0];
         this.b1 = this.props[1];
         this.c1 = this.props[2];
         this.d1 = this.props[3];
         this.e1 = this.props[4];
         this.f1 = this.props[5];
+        if(this.dimension == '3d'){
+            this.g1 = this.props[6];
+            this.h1 = this.props[7];
+            this.i1 = this.props[8];
+            this.j1 = this.props[9];
+            this.k1 = this.props[10];
+            this.l1 = this.props[11];
+            this.m1 = this.props[12];
+            this.n1 = this.props[13];
+            this.o1 = this.props[14];
+            this.p1 = this.props[15];
+        }
 
         /* matrix order (canvas compatible):
          * ace
          * bdf
          * 001
          */
-        this.props[0] = this.a1 * a2 + this.c1 * b2;
+        if(this.dimension == '2d'){
+             this.props[0] = this.a1 * a2 + this.c1 * b2;
+             this.props[1] = this.b1 * a2 + this.d1 * b2;
+             this.props[2] = this.a1 * c2 + this.c1 * d2;
+             this.props[3] = this.b1 * c2 + this.d1 * d2;
+             this.props[4] = this.a1 * e2 + this.c1 * f2 + this.e1;
+             this.props[5] = this.b1 * e2 + this.d1 * f2 + this.f1;
+        }else{
+             this.props[0] = this.a1 * a2 + this.b1 * e2 + this.c1 * i2 + this.d1 * m2;
+             this.props[1] = this.a1 * b2 + this.b1 * f2 + this.c1 * j2 + this.d1 * n2 ;
+             this.props[2] = this.a1 * c2 + this.b1 * g2 + this.c1 * k2 + this.d1 * o2 ;
+             this.props[3] = this.a1 * d2 + this.b1 * h2 + this.c1 * l2 + this.d1 * p2 ;
+
+             this.props[4] = this.e1 * a2 + this.f1 * e2 + this.g1 * i2 + this.h1 * m2 ;
+             this.props[5] = this.e1 * b2 + this.f1 * f2 + this.g1 * j2 + this.h1 * n2 ;
+             this.props[6] = this.e1 * c2 + this.f1 * g2 + this.g1 * k2 + this.h1 * o2 ;
+             this.props[7] = this.e1 * d2 + this.f1 * h2 + this.g1 * l2 + this.h1 * p2 ;
+
+         this.props[8] = this.i1 * a2 + this.j1 * e2 + this.k1 * i2 + this.l1 * m2 ;
+         this.props[9] = this.i1 * b2 + this.j1 * f2 + this.k1 * j2 + this.l1 * n2 ;
+         this.props[10] = this.i1 * c2 + this.j1 * g2 + this.k1 * k2 + this.l1 * o2 ;
+         this.props[11] = this.i1 * d2 + this.j1 * h2 + this.k1 * l2 + this.l1 * p2 ;
+
+         this.props[12] = this.m1 * a2 + this.n1 * e2 + this.o1 * i2 + this.p1 * m2 ;
+         this.props[13] = this.m1 * b2 + this.n1 * f2 + this.o1 * j2 + this.p1 * n2 ;
+         this.props[14] = this.m1 * c2 + this.n1 * g2 + this.o1 * k2 + this.p1 * o2 ;
+         this.props[15] = this.m1 * d2 + this.n1 * h2 + this.o1 * l2 + this.p1 * p2 ;
+        }
+        /*this.props[0] = this.a1 * a2 + this.c1 * b2;
         this.props[1] = this.b1 * a2 + this.d1 * b2;
         this.props[2] = this.a1 * c2 + this.c1 * d2;
         this.props[3] = this.b1 * c2 + this.d1 * d2;
         this.props[4] = this.a1 * e2 + this.c1 * f2 + this.e1;
-        this.props[5] = this.b1 * e2 + this.d1 * f2 + this.f1;
+        this.props[5] = this.b1 * e2 + this.d1 * f2 + this.f1;*/
 
         return this._x();
     },
@@ -685,7 +817,10 @@
      * @returns {Array}
      */
     toArray: function() {
-        return [this.props[0],this.props[1],this.props[2],this.props[3],this.props[4],this.props[5]];
+        if(this.dimension == '2d'){
+            return [this.props[0],this.props[1],this.props[2],this.props[3],this.props[4],this.props[5]];
+        }
+        return [this.props[0],this.props[1],this.props[2],this.props[3],this.props[4],this.props[5],this.props[6],this.props[7],this.props[8],this.props[9],this.props[10],this.props[11],this.props[12],this.props[13],this.props[14],this.props[15]];
     },
 
     /**
@@ -693,9 +828,12 @@
      * @returns {string}
      */
     toCSS: function() {
-        this.cssParts[1] = this.props.join(',');
-        return this.cssParts.join('');
-        //return "matrix(" + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ")";
+        if(this.dimension == '2d'){
+            this.cssParts[1] = this.props.join(',');
+            return this.cssParts.join('');
+        }
+        this.cssParts3d[1] = this.props.join(',');
+        return this.cssParts3d.join('');
     },
 
     /**
@@ -731,8 +869,6 @@
      * @private
      */
     _x: function() {
-        if (this.context)
-            this.context.setTransform(this.a, this.b, this.c, this.d, this.e, this.f);
         return this;
     }
 };
\ No newline at end of file
diff --git a/player/js/animation/AnimationItem.js b/player/js/animation/AnimationItem.js
index 22a3c0c..4ab8ef2 100644
--- a/player/js/animation/AnimationItem.js
+++ b/player/js/animation/AnimationItem.js
@@ -42,6 +42,10 @@
             break;
         case 'svg':
             this.renderer = new SVGRenderer(this, params.renderer);
+            break;
+        case 'threed':
+            this.renderer = new DOMRenderer(this, params.renderer);
+            break;
     }
     this.animType = animType;
 
@@ -135,11 +139,13 @@
     this.checkLoaded();
 };
 
+var startTime = durationTime = 0;
 AnimationItem.prototype.checkLoaded = function () {
     this.renderer.buildStage(this.container, this.layers);
     if (this.pendingElements == 0) {
         if(this.prerenderFramesFlag){
             this.prerenderFrames(0);
+            startTime = Date.now();
             dataManager.renderFrame(this.animationID,this.currentFrame);
             this.renderer.renderFrame(this.currentFrame);
         }else{
@@ -151,12 +157,12 @@
         }
     }
 };
-
 AnimationItem.prototype.prerenderFrames = function(count){
     if(!count){
         count = 0;
     }
     if(this.renderedFrameCount === this.totalFrames){
+        durationTime = Date.now() - startTime;
         //TODO Need polyfill for ios 5.1
         this.isLoaded = true;
         this.gotoFrame();
@@ -166,7 +172,7 @@
     }else{
         dataManager.renderFrame(this.animationID,this.renderedFrameCount);
         this.renderedFrameCount+=1;
-        if(count > 5){
+        if(count > 4){
             setTimeout(this.prerenderFrames.bind(this),0);
         }else{
             count += 1;
diff --git a/player/js/elements/canvasElements/CVMaskElement.js b/player/js/elements/canvasElements/CVMaskElement.js
index 7de209f..2cd4ea8 100644
--- a/player/js/elements/canvasElements/CVMaskElement.js
+++ b/player/js/elements/canvasElements/CVMaskElement.js
@@ -17,7 +17,7 @@
     this.ctx.beginPath();
     for (i = 0; i < len; i++) {
         if (this.masksProperties[i].inv) {
-            this.createInvertedMask(this.masksProperties[i], this.frameNum);
+            this.createInvertedMask(this.ctx,this.masksProperties[i].pathVertices[this.frameNum][0]);
         } else {
             this.drawShape(this.ctx, this.data.masksProperties[i].paths[this.frameNum].pathNodes);
         }
@@ -26,6 +26,25 @@
     this.ctx.clip();
 };
 
+CVMaskElement.prototype.createInvertedMask = function (ctx, data) {
+    ctx.beginPath();
+    var w = ctx.canvas.width;
+    var h = ctx.canvas.height;
+    var j, jLen = data.v.length;
+    ctx.moveTo(0,0);
+    ctx.lineTo(w,0);
+    ctx.lineTo(w,h);
+    ctx.lineTo(0,h);
+    ctx.lineTo(0,0);
+    ctx.moveTo(data.v[0][0], data.v[0][1]);
+    for (j = 1; j < jLen; j++) {
+        ctx.bezierCurveTo(data.o[j - 1][0], data.o[j - 1][1], data.i[j][0], data.i[j][1], data.v[j][0], data.v[j][1]);
+    }
+    ctx.bezierCurveTo(data.o[j - 1][0], data.o[j - 1][1], data.i[0][0], data.i[0][1], data.v[0][0], data.v[0][1]);
+    ctx.closePath();
+    ctx.clip();
+};
+
 CVMaskElement.prototype.drawShape = function (ctx, data) {
     var j, jLen = data.v.length;
     ctx.moveTo(data.v[0][0], data.v[0][1]);
@@ -37,4 +56,4 @@
 
 CVMaskElement.prototype.createInvertedMask = function(){
 
-}
\ No newline at end of file
+}
diff --git a/player/js/elements/domElements/DBaseElement.js b/player/js/elements/domElements/DBaseElement.js
new file mode 100644
index 0000000..9f92847
--- /dev/null
+++ b/player/js/elements/domElements/DBaseElement.js
@@ -0,0 +1,158 @@
+var DBaseElement = function (data, animationItem){
+    this.animationItem = animationItem;
+    this.data = data;
+    this.transformChanged = false;
+    this.forceRender = false;
+    this.init();
+};
+
+DBaseElement.prototype.init = function(){
+    this.createElements();
+    if(this.data.hasMask){
+        this.addMasks(this.data);
+    }
+    if(this.data.eff){
+        this.createEffectsManager(this.data);
+    }
+};
+
+DBaseElement.prototype.createElements = function(){
+    this.layerElement = document.createElementNS(svgNS,'svg');
+    this.layerElement.style.position = 'absolute';
+    this.layerElement.style.top = 0;
+    this.layerElement.style.left = 0;
+    this.layerElement.style.backfaceVisibility  = this.layerElement.style.webkitBackfaceVisibility = 'hidden';
+    this.layerElement.style.transformOrigin = "0 0";
+    this.layerElement.setAttribute('id',this.data.layerName);
+
+
+    this.maskingGroup = this.layerElement;
+
+    this.maskedElement = this.layerElement;
+    this.mainElement = this.layerElement;
+
+};
+
+DBaseElement.prototype.prepareFrame = function(num){
+    this.currentAnimData = this.data.renderedData[num].an;
+    if(this.data.renderedFrame.tr !== this.currentAnimData.matrixValue){
+        this.transformChanged = true;
+        this.data.renderedFrame.tr = this.currentAnimData.matrixValue;
+    }else{
+        this.transformChanged = false;
+    }
+};
+
+DBaseElement.prototype.renderFrame = function(num){
+    if(this.data.inPoint - this.data.startTime <= num && this.data.outPoint - this.data.startTime > num)
+    {
+        if(this.isVisible !== true){
+            this.isVisible = true;
+            this.forceRender = true;
+            this.mainElement.style.opacity=1;
+        }
+    }else{
+        if(this.isVisible !== false){
+            this.isVisible = false;
+            this.mainElement.style.opacity=0;
+        }
+    }
+
+    if(this.data.eff){
+        this.effectsManager.renderFrame(num,this.currentAnimData.mk);
+    }
+
+    if(num === this.data.renderedFrame.num){
+        return this.isVisible;
+    }
+
+    if(this.data.hasMask){
+        this.maskManager.renderFrame(num);
+    }
+
+    if(this.data.renderedFrame.o !== this.currentAnimData.tr.o){
+        this.data.renderedFrame.o = this.currentAnimData.tr.o;
+        if(this.isVisible){
+            this.layerElement.style.opacity = this.currentAnimData.tr.o;
+        }
+    }
+
+    var transformValue = '';
+
+
+    if(this.data.parents){
+        var changedFlag = false;
+        var i = 0, len = this.data.parents.length, parentAnimData;
+        if(!this.transformChanged){
+            while(i<len){
+                if(this.data.parents[i].elem.element.transformChanged){
+                    changedFlag = true;
+                    break;
+                }
+                i+=1;
+            }
+        }else{
+            changedFlag = true;
+        }
+        if(changedFlag){
+            for(i=len-1;i>=0;i-=1){
+                parentAnimData = this.data.parents[i].elem.element.currentAnimData;
+                transformValue += parentAnimData.matrixValue + ' ';
+            }
+            transformValue += this.currentAnimData.matrixValue;
+            if(this.isVisible){
+                this.layerElement.style.transform = transformValue;
+            }
+            this.fullTransform = transformValue;
+        }
+    }else if(this.transformChanged){
+        transformValue += this.currentAnimData.matrixValue;
+        if(this.isVisible){
+            this.layerElement.style.transform = transformValue;
+        }
+        this.fullTransform = transformValue;
+    }
+    if(this.forceRender){
+        this.forceRender = false;
+        this.layerElement.style.opacity = this.currentAnimData.tr.o;
+        this.layerElement.style.transform = this.fullTransform;
+    }
+
+
+    return this.isVisible;
+};
+
+DBaseElement.prototype.getDomElement = function(){
+    return this.layerElement;
+};
+DBaseElement.prototype.setMainElement = function(value){
+    this.mainElement = value;
+};
+DBaseElement.prototype.getMaskManager = function(){
+    return this.maskManager;
+};
+DBaseElement.prototype.addMasks = function(data){
+    var params = {
+        'data':{value:data},
+        'element':{value:this}
+    };
+    this.maskManager = createElement(MaskElement,null,params);
+};
+DBaseElement.prototype.createEffectsManager = function(data){
+    var params = {
+        'effects':{value:data.eff},
+        'element':{value:this}
+    };
+    this.effectsManager = createElement(EffectsManager,null,params);
+};
+DBaseElement.prototype.getType = function(){
+    return this.type;
+};
+
+DBaseElement.prototype.getLayerSize = function(){
+    if(this.data.type == 'TextLayer'){
+        return {w:this.data.textData.width,h:this.data.textData.height};
+    }else{
+        return {w:this.data.width,h:this.data.height};
+    }
+};
diff --git a/player/js/elements/domElements/DCompElement.js b/player/js/elements/domElements/DCompElement.js
new file mode 100644
index 0000000..fe0be5e
--- /dev/null
+++ b/player/js/elements/domElements/DCompElement.js
@@ -0,0 +1,80 @@
+function DCompElement(data, animationItem){
+    this.layers = data.layers;
+    data.threeDComp = false;
+    this.parent.constructor.call(this,data, animationItem);
+}
+createElement(DBaseElement, DCompElement);
+
+DCompElement.prototype.createElements = function(){
+    var i = 0, len = this.layers.length;
+    while(i<len){
+        if(this.layers[i].threeD){
+            this.data.threeDComp = true;
+            break;
+        }
+        i+=1;
+    }
+    if(this.data.threeDComp){
+        this.layerElement = document.createElement('div');
+        this.layerElement.style.position = 'absolute';
+        this.layerElement.style.top = 0;
+        this.layerElement.style.left = 0;
+        this.layerElement.style.backfaceVisibility  = this.layerElement.style.webkitBackfaceVisibility = 'hidden';
+        this.layerElement.style.transformStyle = this.animationItem.container.style.webkitTransformStyle = "preserve-3d";
+        this.layerElement.style.transformOrigin = "0 0";
+        this.layerElement.setAttribute('id',this.data.layerName);
+    }else{
+        this.layerElement = document.createElement('canvas');
+        this.layerElement.style.position = 'absolute';
+        this.layerElement.style.top = 0;
+        this.layerElement.style.left = 0;
+        this.layerElement.style.backfaceVisibility  = this.layerElement.style.webkitBackfaceVisibility = 'hidden';
+        this.layerElement.style.transformStyle = this.animationItem.container.style.webkitTransformStyle = "preserve-3d";
+        this.layerElement.style.transformOrigin = "0 0";
+        this.layerElement.setAttribute('width',this.data.width);
+        this.layerElement.setAttribute('height',this.data.height);
+        this.layerElement.setAttribute('id',this.data.layerName);
+
+        var rendererParams = {
+            clearCanvas: true,
+            context: this.layerElement.getContext('2d'),
+            scaleMode: 'fit'
+        };
+        this.renderer = new CanvasRenderer(this,rendererParams);
+        this.data.compWidth = this.data.width;
+        this.data.compHeight = this.data.height;
+        this.renderer.configAnimation({animation:this.data});
+        this.renderer.buildItems(this.data.layers);
+        this.renderer.buildStage(this.layerElement, this.data.layers);
+    }
+
+
+    this.maskingGroup = this.layerElement;
+
+    this.maskedElement = this.layerElement;
+    this.mainElement = this.layerElement;
+};
+
+DCompElement.prototype.getComposingElement = function(){
+    return this.layerElement;
+};
+
+DCompElement.prototype.renderFrame = function(num){
+    var renderParent = this.parent.renderFrame.call(this,num);
+    if(renderParent===false){
+        return;
+    }
+
+    var timeRemapped = this.data.tm ? this.data.tm[num] < 0 ? 0 : this.data.tm[num] : num;
+    if(this.data.threeDComp){
+        var i,len = this.layers.length;
+        for( i = 0; i < len; i+=1 ){
+            this.layers[i].element.prepareFrame(timeRemapped - this.layers[i].startTime);
+        }
+        for( i = 0; i < len; i+=1 ){
+            this.layers[i].element.renderFrame(timeRemapped - this.layers[i].startTime);
+        }
+    }else{
+        this.renderer.renderFrame(timeRemapped)
+    }
+};
\ No newline at end of file
diff --git a/player/js/elements/domElements/DImageElement.js b/player/js/elements/domElements/DImageElement.js
new file mode 100644
index 0000000..b978d40
--- /dev/null
+++ b/player/js/elements/domElements/DImageElement.js
@@ -0,0 +1,24 @@
+function DImageElement(data, animationItem){
+    this.animationItem = animationItem;
+    this.assets = this.animationItem.getAssets();
+    this.path = this.animationItem.getPath();
+    this.parent.constructor.call(this,data, animationItem);
+}
+createElement(DBaseElement, DImageElement);
+
+DImageElement.prototype.createElements = function(){
+    console.log('innnit',this);
+
+    var self = this;
+
+    var imageLoaded = function(){
+        self.animationItem.elementLoaded();
+    };
+
+    var img = new Image();
+    img.addEventListener('load', imageLoaded, false);
+    img.src = this.path+this.assets[this.data.assetId].path;
+    this.mainElement = img;
+    styleDiv(this.mainElement);
+
+};
\ No newline at end of file
diff --git a/player/js/elements/domElements/DShapeElement.js b/player/js/elements/domElements/DShapeElement.js
new file mode 100644
index 0000000..12afb32
--- /dev/null
+++ b/player/js/elements/domElements/DShapeElement.js
@@ -0,0 +1,47 @@
+function DShapeElement(data, animationItem){
+    this.shapes = [];
+    this.parent.constructor.call(this,data, animationItem);
+}
+createElement(DBaseElement, DShapeElement);
+
+DShapeElement.prototype.createElements = function(){
+    //TODO check if I can use symbol so i can set its viewBox
+
+    this.parent.createElements.call(this);
+
+    this.layerElement.setAttribute('width',2000);
+    this.layerElement.setAttribute('height',2000);
+    this.layerElement.setAttribute('viewBox',-this.data.compWidth/2 + ' '+ -this.data.compHeight/2+' '+2000+' '+2000);
+    this.layerElement.setAttribute('preserveAspectRatio','xMidYMid meet');
+
+    var i, len = this.data.shapes.length;
+    var shapeItem;
+    for(i=len-1;i>=0;i--){
+        if(this.data.trim){
+            this.data.shapes[i].trim = this.data.trim;
+        }
+        shapeItem = new ShapeItemElement(this.data.shapes[i]);
+        this.layerElement.appendChild(shapeItem.getElement());
+        this.shapes.push(shapeItem);
+    }
+};
+
+DShapeElement.prototype.renderFrame = function(num){
+    var renderParent = this.parent.renderFrame.call(this,num);
+    this.layerElement.style.transform = this.fullTransform + ' translate('+ -this.data.compWidth/2 +'px, '+ -this.data.compHeight/2 +'px )';
+    if(renderParent===false){
+        return;
+    }
+
+    this.renderShapes(num);
+};
+
+DShapeElement.prototype.renderShapes = function(num){
+    var i,len = this.data.shapes.length,shapeData;
+    var shapeItem;
+    for(i=len-1;i>=0;i--){
+        shapeData = this.data.shapes[i];
+        shapeItem = this.shapes[len - 1 - i];
+        shapeItem.renderShape(num);
+    }
+};
\ No newline at end of file
diff --git a/player/js/elements/domElements/DSolidElement.js b/player/js/elements/domElements/DSolidElement.js
new file mode 100644
index 0000000..abec891
--- /dev/null
+++ b/player/js/elements/domElements/DSolidElement.js
@@ -0,0 +1,19 @@
+function DSolidElement(data, animationItem){
+    this.parent.constructor.call(this,data, animationItem);
+}
+createElement(DBaseElement, DSolidElement);
+
+DSolidElement.prototype.createElements = function(){
+    this.parent.createElements.call(this);
+    this.layerElement.setAttribute('width',this.data.width);
+    this.layerElement.setAttribute('height',this.data.height);
+    var rect = document.createElementNS(svgNS,'rect');
+    rect.setAttribute('width',this.data.width);
+    rect.setAttribute('height',this.data.height);
+    rect.setAttribute('fill',this.data.color);
+    this.layerElement.appendChild(rect);
+    styleUnselectableDiv(rect);
+
+    this.maskingGroup = this.svgElem;
+    this.maskedElement = rect;
+};
\ No newline at end of file
diff --git a/player/js/module.js b/player/js/module.js
index eb768bf..328160c 100644
--- a/player/js/module.js
+++ b/player/js/module.js
@@ -63,7 +63,8 @@
     function checkReady(){
         if (document.readyState === "complete") {
             clearInterval(readyStateCheckInterval);
-                searchAnimations();
+            setTimeout(searchAnimations,300);
+                //searchAnimations();
         }
     }
 
diff --git a/player/js/renderers/CanvasRenderer.js b/player/js/renderers/CanvasRenderer.js
index 3d391fb..044f319 100644
--- a/player/js/renderers/CanvasRenderer.js
+++ b/player/js/renderers/CanvasRenderer.js
@@ -27,7 +27,7 @@
             console.log('NO TYPE: ',layers[i]);
         }
     }
-}
+};
 
 CanvasRenderer.prototype.createBase = function (data) {
     data.element = new CVBaseElement(data, this);
diff --git a/player/js/renderers/DOMRenderer.js b/player/js/renderers/DOMRenderer.js
new file mode 100644
index 0000000..2fad1b6
--- /dev/null
+++ b/player/js/renderers/DOMRenderer.js
@@ -0,0 +1,127 @@
+function DOMRenderer(animationItem){
+    this.animationItem = animationItem;
+    this.layers = null;
+    this.camera = null;
+}
+
+DOMRenderer.prototype.buildItems = function(layers){
+    var count = 0, i, len = layers.length;
+    for (i = 0; i < len; i++) {
+        if (layers[i].type == 'StillLayer') {
+            count++;
+            this.createImage(layers[i]);
+        } else if (layers[i].type == 'PreCompLayer') {
+            this.createComp(layers[i]);
+        } else if (layers[i].type == 'SolidLayer') {
+            this.createSolid(layers[i]);
+        } else if (layers[i].type == 'ShapeLayer') {
+            this.createShape(layers[i]);
+        } else if (layers[i].type == 'TextLayer') {
+            this.createText(layers[i]);
+        } else{
+            this.createBase(layers[i]);
+            //console.log('NO TYPE: ',layers[i]);
+        }
+    }
+};
+
+DOMRenderer.prototype.createBase = function (data) {
+    data.element = new DBaseElement(data, this);
+};
+
+DOMRenderer.prototype.createShape = function (data) {
+    data.element = new DShapeElement(data, this.animationItem);
+};
+
+DOMRenderer.prototype.createText = function (data) {
+    data.element = new DTextElement(data, this.animationItem);
+};
+
+DOMRenderer.prototype.createImage = function (data) {
+    data.element = new DImageElement(data, this.animationItem);
+};
+
+DOMRenderer.prototype.createComp = function (data) {
+    data.element = new DCompElement(data, this.animationItem);
+    if(data.threeDComp){
+        this.buildItems(data.layers);
+    }
+};
+
+DOMRenderer.prototype.createSolid = function (data) {
+    data.element = new DSolidElement(data, this.animationItem);
+};
+
+DOMRenderer.prototype.configAnimation = function(animData){
+    this.layers = animData.animation.layers;
+    var i = 0, len = this.layers.length;
+    while(i<len){
+        if(this.layers[i].type == 'CameraLayer'){
+            this.camera = this.layers[i];
+            break;
+        }
+        i += 1;
+    }
+    this.animationItem.wrapper.style.overflow = 'hidden';
+    this.animationItem.wrapper.style.perspective = this.camera.pe+'px';
+    this.animationItem.wrapper.style.transformStyle = this.animationItem.wrapper.style.webkitTransformStyle = "preserve-3d";
+    this.animationItem.wrapper.style.transformOrigin = this.animationItem.wrapper.style.mozTransformOrigin = this.animationItem.wrapper.style.webkitTransformOrigin = this.animationItem.wrapper.style['-webkit-transform'] = "0 0 0";
+    this.animationItem.container = document.createElement('div');
+    this.animationItem.container.style.transformOrigin = this.animationItem.container.style.mozTransformOrigin = this.animationItem.container.style.webkitTransformOrigin = this.animationItem.container.style['-webkit-transform'] = "450px 275px "+this.camera.pe+"px";
+    this.animationItem.container.style.transformStyle = this.animationItem.container.style.webkitTransformStyle = "preserve-3d";
+    this.animationItem.container.style.transform = 'matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)';
+    this.animationItem.container.style.position = 'absolute';
+    this.animationItem.container.style.backfaceVisibility  = this.animationItem.container.style.webkitBackfaceVisibility = 'hidden';
+    this.animationItem.container.style.top = 0;
+    this.animationItem.container.style.left = 0;
+    this.animationItem.wrapper.appendChild(this.animationItem.container);
+};
+
+DOMRenderer.prototype.buildStage = function (container, layers) {
+    var i, len = layers.length, layerData;
+    for (i = len - 1; i >= 0; i--) {
+        layerData = layers[i];
+        if (layerData.parent) {
+            layerData.parentHierarchy = [];
+            this.buildItemHierarchy(layerData, layers, layerData.parent);
+        }
+        if (layerData.type == 'PreCompLayer' && layerData.threeDComp) {
+            this.buildStage(layerData.element.getComposingElement(), layerData.layers);
+        }
+        container.appendChild(layerData.element.mainElement);
+    }
+};
+
+DOMRenderer.prototype.buildItemHierarchy = function (threeItem, layers, parentName) {
+    var i = 0, len = layers.length;
+    while (i < len) {
+        if (layers[i].layerName == parentName) {
+            threeItem.parentHierarchy.push(layers[i]);
+            if (layers[i].parent == undefined) {
+            } else {
+                this.buildItemHierarchy(threeItem, layers, layers[i].parent);
+            }
+            break;
+        }
+        i += 1;
+    }
+};
+
+DOMRenderer.prototype.updateContainerSize = function () {
+};
+
+DOMRenderer.prototype.renderCamera = function(num){
+    //this.camera.prepareFrame(num - this.camera.startTime);
+    this.animationItem.container.style.transform = this.camera.element.currentAnimData.cameraValue;
+};
+
+DOMRenderer.prototype.renderFrame = function(num){
+    var i, len = this.layers.length;
+    for (i = 0; i < len; i++) {
+        this.layers[i].element.prepareFrame(num - this.layers[i].startTime);
+    }
+    for (i = 0; i < len; i++) {
+        this.layers[i].element.renderFrame(num - this.layers[i].startTime);
+    }
+    this.renderCamera(num);
+};
\ No newline at end of file
diff --git a/player/js/renderers/SVGRenderer.js b/player/js/renderers/SVGRenderer.js
index ff7e0eb..886f746 100644
--- a/player/js/renderers/SVGRenderer.js
+++ b/player/js/renderers/SVGRenderer.js
@@ -38,7 +38,7 @@
 
 SVGRenderer.prototype.createComp = function (data) {
     data.element = new ICompElement(data, this.animationItem);
-    this.buildItems(data.layers, data.element.getType());
+    this.buildItems(data.layers);
 };
 
 SVGRenderer.prototype.createSolid = function (data) {
diff --git a/player/js/utils/DataManager.js b/player/js/utils/DataManager.js
index cc50b31..15300a9 100644
--- a/player/js/utils/DataManager.js
+++ b/player/js/utils/DataManager.js
@@ -38,7 +38,7 @@
         }
     }
 
-    function completeLayers(layers){
+    function completeLayers(layers, compWidth,compHeight){
         var layerFrames, offsetFrame, layerData;
         var animArray, lastFrame;
         var shapeItem;
@@ -46,6 +46,8 @@
         var j, jLen, k, kLen;
         for(i=0;i<len;i+=1){
             layerData = layers[i];
+            layerData.compWidth = compWidth;
+            layerData.compHeight = compHeight;
             layerFrames = layerData.outPoint - layerData.startTime;
             offsetFrame = layerData.startTime;
             layerData.layerName = convertLayerNameToID(layerData.layerName);
@@ -74,6 +76,21 @@
             }else{
                 layerData.ks.r *= degToRads;
             }
+            if(layerData.ks.rx instanceof Array){
+                convertNumericValue(layerData.ks.rx,degToRads);
+            }else{
+                layerData.ks.rx *= degToRads;
+            }
+            if(layerData.ks.ry instanceof Array){
+                convertNumericValue(layerData.ks.ry,degToRads);
+            }else{
+                layerData.ks.ry *= degToRads;
+            }
+            if(layerData.ks.rz instanceof Array){
+                convertNumericValue(layerData.ks.rz,degToRads);
+            }else{
+                layerData.ks.rz *= degToRads;
+            }
             if(layerData.hasMask){
                 var maskProps = layerData.masksProperties;
                 jLen = maskProps.length;
@@ -94,7 +111,7 @@
                 }
             }
             if(layerData.type=='PreCompLayer'){
-                completeLayers(layerData.layers);
+                completeLayers(layerData.layers, layerData.width,layerData.height);
             }else if(layerData.type == 'ShapeLayer'){
                 jLen = layerData.shapes.length;
                 for(j=0;j<jLen;j+=1){
@@ -160,7 +177,7 @@
     function completeData(animationData){
         animations[animationData._id] = {data:animationData,renderedFrames:[]};
         frameRate = animationData.animation.frameRate;
-        completeLayers(animationData.animation.layers);
+        completeLayers(animationData.animation.layers,animationData.animation.compWidth,animationData.animation.compHeight);
     }
 
     function convertLayerNameToID(string){
@@ -366,9 +383,15 @@
             if(interpolatedParams.type == 'p'){
                 matrixParams.px = keyframes;
                 matrixParams.py = keyframes;
+                if(interpolatedParams.threed){
+                    matrixParams.pz = keyframes;
+                }
             }else if(interpolatedParams.type == 's'){
                 matrixParams.sx = keyframes;
                 matrixParams.sy = keyframes;
+                if(interpolatedParams.threed){
+                    matrixParams.sz = keyframes;
+                }
             }else if(interpolatedParams.type == 'r'){
                 matrixParams.r = keyframes;
             }
@@ -380,9 +403,15 @@
             if(interpolatedParams.type == 'p'){
                 matrixParams.px = keyframes[0];
                 matrixParams.py = keyframes[1];
+                if(interpolatedParams.threed){
+                    matrixParams.pz = keyframes[2];
+                }
             }else if(interpolatedParams.type == 's'){
                 matrixParams.sx = keyframes[0];
                 matrixParams.sy = keyframes[1];
+                if(interpolatedParams.threed){
+                    matrixParams.sz = keyframes[2];
+                }
             }else if(interpolatedParams.type == 'r'){
                 matrixParams.r = keyframes[0];
             }
@@ -428,9 +457,15 @@
                 if(interpolatedParams.type == 'p'){
                     matrixParams.px = bezierData.points[bezierData.points.length - 1].point[0];
                     matrixParams.py = bezierData.points[bezierData.points.length - 1].point[1];
+                    if(interpolatedParams.threed){
+                        matrixParams.pz = bezierData.points[bezierData.points.length - 1].point[2];
+                    }
                 }else if(interpolatedParams.type == 's'){
                     matrixParams.sx = bezierData.points[bezierData.points.length - 1].point[0];
                     matrixParams.sy = bezierData.points[bezierData.points.length - 1].point[1];
+                    if(interpolatedParams.threed){
+                        matrixParams.pz = bezierData.points[bezierData.points.length - 1].point[2];
+                    }
                 }else if(interpolatedParams.type == 'r'){
                     matrixParams.r = bezierData.points[bezierData.points.length - 1].point[0];
                 }
@@ -439,9 +474,15 @@
                 if(interpolatedParams.type == 'p'){
                     matrixParams.px = bezierData.points[0].point[0];
                     matrixParams.py = bezierData.points[0].point[1];
+                    if(interpolatedParams.threed){
+                        matrixParams.pz = bezierData.points[0].point[2];
+                    }
                 }else if(interpolatedParams.type == 's'){
                     matrixParams.sx = bezierData.points[0].point[0];
                     matrixParams.sy = bezierData.points[0].point[1];
+                    if(interpolatedParams.threed){
+                        matrixParams.sz = bezierData.points[0].point[2];
+                    }
                 }else if(interpolatedParams.type == 'r'){
                     matrixParams.r = bezierData.points[0].point[0];
                 }
@@ -468,9 +509,15 @@
                     if(interpolatedParams.type == 'p'){
                         matrixParams.px = bezierData.points[j].point[0];
                         matrixParams.py = bezierData.points[j].point[1];
+                        if(interpolatedParams.threed){
+                            matrixParams.pz = bezierData.points[j].point[2];
+                        }
                     }else if(interpolatedParams.type == 's'){
                         matrixParams.sx = bezierData.points[j].point[0];
                         matrixParams.sy = bezierData.points[j].point[1];
+                        if(interpolatedParams.threed){
+                            matrixParams.sz = bezierData.points[j].point[2];
+                        }
                     }else if(interpolatedParams.type == 'r'){
                         matrixParams.r = bezierData.points[j].point[0];
                     }else{
@@ -481,9 +528,15 @@
                     if(interpolatedParams.type == 'p'){
                         matrixParams.px = bezierData.points[j].point[0];
                         matrixParams.py = bezierData.points[j].point[1];
+                        if(interpolatedParams.threed){
+                            matrixParams.pz = bezierData.points[j].point[2];
+                        }
                     }else if(interpolatedParams.type == 's'){
                         matrixParams.sx = bezierData.points[j].point[0];
                         matrixParams.sy = bezierData.points[j].point[1];
+                        if(interpolatedParams.threed){
+                            matrixParams.sz = bezierData.points[j].point[2];
+                        }
                     }else if(interpolatedParams.type == 'r'){
                         matrixParams.r = bezierData.points[j].point[0];
                     }else{
@@ -495,9 +548,15 @@
                     if(interpolatedParams.type == 'p'){
                         matrixParams.px = bezierData.points[j].point[0] + (bezierData.points[j+1].point[0] - bezierData.points[j].point[0])*segmentPerc;
                         matrixParams.py = bezierData.points[j].point[1] + (bezierData.points[j+1].point[1] - bezierData.points[j].point[1])*segmentPerc;
+                        if(interpolatedParams.threed){
+                            matrixParams.pz = bezierData.points[j].point[2] + (bezierData.points[j+1].point[2] - bezierData.points[j].point[2])*segmentPerc;
+                        }
                     }else if(interpolatedParams.type == 's'){
                         matrixParams.sx = bezierData.points[j].point[0] + (bezierData.points[j+1].point[0] - bezierData.points[j].point[0])*segmentPerc;
                         matrixParams.sy = bezierData.points[j].point[1] + (bezierData.points[j+1].point[1] - bezierData.points[j].point[1])*segmentPerc;
+                        if(interpolatedParams.threed){
+                            matrixParams.sz = bezierData.points[j].point[2] + (bezierData.points[j+1].point[2] - bezierData.points[j].point[2])*segmentPerc;
+                        }
                     }else if(interpolatedParams.type == 'r'){
                         matrixParams.r = bezierData.points[j].point[0] + (bezierData.points[j+1].point[0] - bezierData.points[j].point[0])*segmentPerc;
                     }else{
@@ -767,22 +826,33 @@
     }
 
     function createPathString(paths,closed){
+        //return '';
         var pathV,pathO,pathI;
         var pathString = '';
         var pathData;
         var k, kLen;
+        var posO,posI,posV;
 
         if(!(paths instanceof Array)){
             pathV = paths.v;
             pathO = paths.o;
             pathI = paths.i;
             kLen = pathV.length;
-            pathString += "M"+pathV[0].join(',');
+            pathString += "M"+pathV[0][0]+','+pathV[0][1];
+            //pathString += "M"+pathV[0].join(',');
             for(k=1;k<kLen;k++){
-                pathString += " C"+pathO[k-1].join(',') + " "+pathI[k].join(',') + " "+pathV[k].join(',');
+                posO =pathO[k-1];
+                posI =pathI[k];
+                posV =pathV[k];
+                pathString += " C"+posO[0]+','+posO[1] + " "+posI[0]+','+posI[1] + " "+posV[0]+','+posV[1];
+                //pathString += " C"+pathO[k-1][0]+','+pathO[k-1][1] + " "+pathI[k][0]+','+pathI[k][1] + " "+pathV[k][0]+','+pathV[k][1];
             }
             if(closed !== false){
-                pathString += " C"+pathO[k-1].join(',') + " "+pathI[0].join(',') + " "+pathV[0].join(',');
+                posO =pathO[k-1];
+                posI =pathI[0];
+                posV =pathV[0];
+                pathString += " C"+posO[0]+','+posO[1] + " "+posI[0]+','+posI[1] + " "+posV[0]+','+posV[1];
+                //pathString += " C"+pathO[k-1][0]+','+pathO[k-1][1] + " "+pathI[0][0]+','+pathI[0][1] + " "+pathV[0][0]+','+pathV[0][1];
             }
             return pathString;
         }
@@ -794,23 +864,40 @@
             pathO = pathData.o;
             pathI = pathData.i;
             kLen = pathV.length;
-            pathString += "M"+pathV[0].join(',');
+            //pathString += "M"+pathV[0].join(',');
+            pathString += "M"+pathV[0][0]+','+pathV[0][1];
             for(k=1;k<kLen;k++){
-                pathString += " C"+pathO[k-1].join(',') + " "+pathI[k].join(',') + " "+pathV[k].join(',');
+                posO =pathO[k-1];
+                posI =pathI[k];
+                posV =pathV[k];
+                pathString += " C"+posO[0]+','+posO[1] + " "+posI[0]+','+posI[1] + " "+posV[0]+','+posV[1];
+                //pathString += " C"+pathO[k-1][0]+','+pathO[k-1][1] + " "+pathI[k][0]+','+pathI[k][1] + " "+pathV[k][0]+','+pathV[k][1];
+                //pathString += " C"+pathO[k-1].join(',') + " "+pathI[k].join(',') + " "+pathV[k].join(',');
             }
             if(closed !== false){
-                pathString += " C"+pathO[k-1].join(',') + " "+pathI[0].join(',') + " "+pathV[0].join(',');
+                posO =pathO[k-1];
+                posI =pathI[0];
+                posV =pathV[0];
+                pathString += " C"+posO[0]+','+posO[1] + " "+posI[0]+','+posI[1] + " "+posV[0]+','+posV[1];
+                //pathString += " C"+pathO[k-1][0]+','+pathO[k-1][1] + " "+pathI[0][0]+','+pathI[0][1] + " "+pathV[0][0]+','+pathV[0][1];
+                //pathString += " C"+pathO[k-1].join(',') + " "+pathI[0].join(',') + " "+pathV[0].join(',');
             }
         }
+        pathsArray.push(pathString);
         return pathString;
     }
 
     var matrixParams = {
         r: 0,
+        rx: 0,
+        ry: 0,
+        rz: 0,
         sx: 1,
         sy: 1,
-        px: 1,
-        py: 1
+        sz: 1,
+        px: 0,
+        py: 0,
+        pz: 0
     };
 
     function iterateLayers(layers, frameNum,renderType){
@@ -833,17 +920,31 @@
             dataOb = {};
             interpolatedParams.arrayFlag = false;
             interpolatedParams.type = 'default';
+            interpolatedParams.threed = renderType == 'threed';
             dataOb.a = getInterpolatedValue(item.ks.a,offsettedFrameNum, item.startTime,interpolatedParams);
             dataOb.o = getInterpolatedValue(item.ks.o,offsettedFrameNum, item.startTime,interpolatedParams);
             interpolatedParams.arrayFlag = false;
             interpolatedParams.type = 'p';
             getInterpolatedValue(item.ks.p,offsettedFrameNum, item.startTime,interpolatedParams);
             interpolatedParams.arrayFlag = true;
-            interpolatedParams.type = 'r';
-            getInterpolatedValue(item.ks.r,offsettedFrameNum, item.startTime,interpolatedParams);
-            interpolatedParams.arrayFlag = true;
             interpolatedParams.type = 's';
             getInterpolatedValue(item.ks.s,offsettedFrameNum, item.startTime,interpolatedParams);
+
+            if(renderType == 'threed' && (item.threeD === true || item.type == 'CameraLayer')){
+
+                interpolatedParams.arrayFlag = true;
+                interpolatedParams.type = 'default';
+                matrixParams.rx = getInterpolatedValue(item.ks.rx,offsettedFrameNum, item.startTime,interpolatedParams);
+                matrixParams.rx = matrixParams.rx instanceof Array ? matrixParams.rx[0] : matrixParams.rx;
+                matrixParams.ry = getInterpolatedValue(item.ks.ry,offsettedFrameNum, item.startTime,interpolatedParams);
+                matrixParams.ry = matrixParams.ry instanceof Array ? matrixParams.ry[0] : matrixParams.ry;
+                matrixParams.rz = getInterpolatedValue(item.ks.rz,offsettedFrameNum, item.startTime,interpolatedParams);
+                matrixParams.rz = matrixParams.rz instanceof Array ? matrixParams.rz[0] : matrixParams.rz;
+            }else{
+                interpolatedParams.arrayFlag = true;
+                interpolatedParams.type = 'r';
+                getInterpolatedValue(item.ks.r,offsettedFrameNum, item.startTime,interpolatedParams);
+            }
             renderedData = {};
             renderedData.an = {
                 tr: dataOb
@@ -852,6 +953,15 @@
             interpolatedParams.type = 'default';
             if(renderType == 'canvas'){
                 renderedData.an.matrixArray = matrixInstance.getMatrixArrayFromParams(matrixParams.r,matrixParams.sx,matrixParams.sy,matrixParams.px,matrixParams.py);
+            }else if(renderType == 'threed'){
+                if(item.type == 'CameraLayer'){
+                    renderedData.an.matrixValue = matrixInstance.getMatrix3FromParams(matrixParams.rx,matrixParams.ry,matrixParams.rz,matrixParams.sx,matrixParams.sy,matrixParams.sz,matrixParams.px,matrixParams.py,-matrixParams.pz) + ' translate3d('+ -dataOb.a[0]+'px, '+ -dataOb.a[1]+'px, 0)';
+                    renderedData.an.cameraValue = matrixInstance.getMatrix3FromParams(-matrixParams.rx,-matrixParams.ry,matrixParams.rz,matrixParams.sx,matrixParams.sy,matrixParams.sz,-matrixParams.px,-matrixParams.py,item.pe+matrixParams.pz) + ' translate3d('+ dataOb.a[0]+'px, '+ dataOb.a[1]+'px, 0)';
+                }else if(item.threeD){
+                    renderedData.an.matrixValue = matrixInstance.getAnchoredMatrix3FromParams(matrixParams.rx,matrixParams.ry,matrixParams.rz,matrixParams.sx,matrixParams.sy,matrixParams.sz,matrixParams.px,matrixParams.py,matrixParams.pz,dataOb.a[0],dataOb.a[1],0);
+                }else{
+                    renderedData.an.matrixArray = matrixInstance.getMatrixArrayFromParams(matrixParams.r,matrixParams.sx,matrixParams.sy,matrixParams.px,matrixParams.py);
+                }
             }else{
                 renderedData.an.matrixValue = matrixInstance.getMatrix2FromParams(matrixParams.r,matrixParams.sx,matrixParams.sy,matrixParams.px,matrixParams.py) + 'translate('+ -dataOb.a[0]+' '+ -dataOb.a[1]+')';
             }
@@ -874,8 +984,10 @@
                continue;
             }
             if(item.type == 'PreCompLayer'){
-                timeRemapped = item.tm ? item.tm[offsettedFrameNum] < 0 ? 0 : item.tm[offsettedFrameNum] : offsettedFrameNum;
-                iterateLayers(item.layers,timeRemapped,renderType);
+                if(!(frameNum < item.inPoint || frameNum > item.outPoint)){
+                    timeRemapped = item.tm ? item.tm[offsettedFrameNum] < 0 ? 0 : item.tm[offsettedFrameNum] : offsettedFrameNum;
+                    iterateLayers(item.layers,timeRemapped,renderType);
+                }
             }else if(item.type == 'ShapeLayer'){
                 len = item.shapes.length;
                 for(i=0;i<len;i+=1){
@@ -908,7 +1020,7 @@
                         shapeData.fill = {
                             opacity : fillOpacity instanceof Array ? fillOpacity[0] : fillOpacity
                         };
-                        if(renderType == 'canvas'){
+                        if(renderType == 'canvas' || (renderType == 'threed' && item.threeD === false)){
                             roundColor(fillColor);
                             shapeData.fill.color = fillColor;
                         }else{
@@ -916,7 +1028,12 @@
                         }
                     }
                     if(shapeItem.ks){
-                        shapeData.path = interpolateShape(shapeItem,offsettedFrameNum, item.startTime,renderType);
+                        //(renderType == 'threed' && item.threeD === true)
+                        var rType = renderType;
+                        if(rType == 'threed'){
+                            rType = item.threeD === true ? 'svg' : 'canvas';
+                        }
+                        shapeData.path = interpolateShape(shapeItem,offsettedFrameNum, item.startTime,rType);
                     }else if(shapeItem.el){
                         elmPos = getInterpolatedValue(shapeItem.el.p,offsettedFrameNum, item.startTime,interpolatedParams);
                         elmSize = getInterpolatedValue(shapeItem.el.s,offsettedFrameNum, item.startTime,interpolatedParams);
@@ -942,7 +1059,7 @@
                             opacity : strokeOpacity instanceof Array ? strokeOpacity[0] : strokeOpacity,
                             width : strokeWidth instanceof Array ? strokeWidth[0] : strokeWidth
                         };
-                        if(renderType == 'canvas'){
+                        if(renderType == 'canvas' || (renderType == 'threed' && item.threeD === false)){
                             roundColor(strokeColor);
                             shapeData.stroke.color = strokeColor;
                         }else{
@@ -966,7 +1083,7 @@
                     //console.log('frameNum: ',frameNum);
                     //console.log('matrixParams.sx: ',matrixParams.sx);
                     //console.log('matrixParams.sy: ',matrixParams.sy);
-                    if(renderType == 'canvas'){
+                    if(renderType == 'canvas' || (renderType == 'threed' && item.threeD === false)){
                         shapeTrOb.mtArr = matrixInstance.getMatrixArrayFromParams(matrixParams.r,matrixParams.sx,matrixParams.sy,matrixParams.px,matrixParams.py);
                     }else{
                         shapeTrOb.mt = matrixInstance.getMatrix2FromParams(matrixParams.r,matrixParams.sx,matrixParams.sy,matrixParams.px,matrixParams.py);
@@ -1065,4 +1182,4 @@
     return moduleOb;
 };
 
-var dataManager = dataFunctionManager();
\ No newline at end of file
+var dataManager = dataFunctionManager();
diff --git a/player/js/utils/MatrixManager.js b/player/js/utils/MatrixManager.js
index fd440d5..da6d6bf 100644
--- a/player/js/utils/MatrixManager.js
+++ b/player/js/utils/MatrixManager.js
@@ -1,44 +1,18 @@
 function matrixManagerFunction(){
 
-    var mat = new Matrix();
+    var mat = new Matrix('2d');
+    var mat3d = new Matrix('3d');
 
-    var returnMatrix3D = function(rX, rY, rZ, scaleX, scaleY, scaleZ, tX, tY, tZ) {
+    var returnMatrix3D = function(rX, rY, rZ, scaleX, scaleY, scaleZ, tX, tY, tZ,aX, aY, aZ) {
+        //return mat3d.reset().translate(-aX,-aY,-aZ).rotateX(rX).rotateY(-rY).rotateZ(-rZ).scale(scaleX,scaleY,scaleZ).translate(tX,tY,-tZ).toCSS();
+        var tocs = mat3d.reset().translate(tX,tY,tZ).rotateX(rX).rotateY(rY).rotateZ(rZ).scale(scaleX,scaleY,scaleZ).toCSS();
+        return tocs;
+    };
 
-        var rotationXMatrix, rotationYMatrix, rotationZMatrix, s, scaleMatrix, transformationMatrix, translationMatrix;
-        rotationXMatrix = $M([
-            [1, 0, 0, 0],
-            [0, Math.cos(rX), Math.sin(-rX), 0],
-            [0, Math.sin(rX), Math.cos(rX), 0],
-            [0, 0, 0, 1]]);
-
-        rotationYMatrix = $M([
-            [Math.cos(rY), 0, Math.sin(rY), 0],
-            [0, 1, 0, 0],
-            [Math.sin(-rY), 0, Math.cos(rY), 0],
-            [0, 0, 0, 1]]);
-
-        rotationZMatrix = $M([
-            [Math.cos(rZ), Math.sin(-rZ), 0, 0],
-            [Math.sin(rZ), Math.cos(rZ), 0, 0],
-            [0, 0, 1, 0],
-            [0, 0, 0, 1]]);
-
-
-        scaleMatrix = $M([[scaleX, 0, 0, 0], [0, scaleY, 0, 0], [0, 0, scaleZ, 0], [0, 0, 0, 1]]);
-
-        transformationMatrix = rotationXMatrix.x(rotationYMatrix).x(rotationZMatrix).x(scaleMatrix);
-        transformationMatrix = transformationMatrix.transpose();
-        translationMatrix = $M([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [tX, tY, tZ, 1]]);
-        transformationMatrix = transformationMatrix.x(translationMatrix); // Apply transformation matrix AFTER transposing rotation and scale
-
-        s = "matrix3d(";
-        s += transformationMatrix.e(1, 1).toFixed(5) + "," + transformationMatrix.e(1, 2).toFixed(5) + "," + transformationMatrix.e(1, 3).toFixed(5) + "," + transformationMatrix.e(1, 4).toFixed(5) + ",";
-        s += transformationMatrix.e(2, 1).toFixed(5) + "," + transformationMatrix.e(2, 2).toFixed(5) + "," + transformationMatrix.e(2, 3).toFixed(5) + "," + transformationMatrix.e(2, 4).toFixed(5) + ",";
-        s += transformationMatrix.e(3, 1).toFixed(5) + "," + transformationMatrix.e(3, 2).toFixed(5) + "," + transformationMatrix.e(3, 3).toFixed(5) + "," + transformationMatrix.e(3, 4).toFixed(5) + ",";
-        s += transformationMatrix.e(4, 1).toFixed(5) + "," + transformationMatrix.e(4, 2).toFixed(5) + "," + transformationMatrix.e(4, 3).toFixed(5) + "," + transformationMatrix.e(4, 4).toFixed(5);
-        s += ")";
-
-        return s;
+    var returnMatrixAnchored3D = function(rX, rY, rZ, scaleX, scaleY, scaleZ, tX, tY, tZ,aX, aY, aZ) {
+        //return mat3d.reset().translate(-aX,-aY,-aZ).rotateX(rX).rotateY(-rY).rotateZ(-rZ).scale(scaleX,scaleY,scaleZ).translate(tX,tY,-tZ).toCSS();
+        var tocs = mat3d.reset().translate(-aX,-aY,-aZ).rotateZ(-rZ).rotateY(rY).rotateX(rX).scale(scaleX,scaleY,scaleZ).translate(tX,tY,-tZ).toCSS();
+        return tocs;
     };
 
     /*var returnMatrix2D = function(rX, scaleX, scaleY, tX, tY){
@@ -114,9 +88,10 @@
                 ,animData.s[0],animData.s[1]
                 ,animData.p[0],animData.p[1]);
         }
-        return returnMatrix3D(-animData.r[0],animData.r[1],animData.r[2]
+        return returnMatrix3D(-animData.rx[0],animData.ry[1],animData.rz[2]
             ,animData.s[0],animData.s[1],animData.s[2]
-            ,animData.p[0],animData.p[1],animData.p[2])
+            ,animData.p[0],animData.p[1],animData.p[2]
+            ,animData.a[0],animData.a[1],animData.a[2])
     };
 
     var getMatrixArray = function(animData, isThreeD){
@@ -134,8 +109,10 @@
         getMatrix2 : getMatrix2,
         getMatrixArray : getMatrixArray,
         getMatrixArrayFromParams : returnMatrix2DArray,
-        getMatrix2FromParams : returnMatrix2D
+        getMatrix2FromParams : returnMatrix2D,
+        getMatrix3FromParams : returnMatrix3D,
+        getAnchoredMatrix3FromParams : returnMatrixAnchored3D
     }
 
 };
-var MatrixManager = matrixManagerFunction;
\ No newline at end of file
+var MatrixManager = matrixManagerFunction;
diff --git a/player/js/utils/common.js b/player/js/utils/common.js
index 88516af..a8d5e5a 100644
--- a/player/js/utils/common.js
+++ b/player/js/utils/common.js
@@ -9,9 +9,7 @@
     element.style.position = 'absolute';
     element.style.top = 0;
     element.style.left = 0;
-    element.style.display = 'block';
-    element.style.verticalAlign = 'top';
-    element.style.backfaceVisibility  = element.style.webkitBackfaceVisibility = 'hidden';
+    element.style.backfaceVisibility  = element.style.webkitBackfaceVisibility = 'visible';
     //element.style.transformStyle = element.style.webkitTransformStyle = "preserve-3d";
     styleUnselectableDiv(element);
 }
@@ -87,4 +85,4 @@
         colorMap[i] = hex.length == 1 ? '0' + hex : hex;
     }
 }
-createColorMap();
\ No newline at end of file
+createColorMap();