From a0d23354802ebc6b437698acb4b18d3395d47cd1 Mon Sep 17 00:00:00 2001 From: hwc487 Date: Fri, 16 Mar 2012 12:26:30 -0700 Subject: Conversion to JSON based file IO for canvas2D and WebGL rendering --- assets/canvas-runtime.js | 388 +++++++++------------- js/document/html-document.js | 43 ++- js/lib/drawing/world.js | 128 +++++++ js/lib/geom/circle.js | 72 +++- js/lib/geom/geom-obj.js | 79 +++++ js/lib/geom/line.js | 53 ++- js/lib/geom/rectangle.js | 87 ++++- js/lib/rdge/materials/bump-metal-material.js | 44 +++ js/lib/rdge/materials/flat-material.js | 21 ++ js/lib/rdge/materials/linear-gradient-material.js | 53 +++ js/lib/rdge/materials/pulse-material.js | 32 ++ js/lib/rdge/materials/radial-blur-material.js | 36 ++ js/lib/rdge/materials/radial-gradient-material.js | 54 ++- js/lib/rdge/materials/taper-material.js | 27 ++ js/lib/rdge/materials/twist-vert-material.js | 28 ++ js/lib/rdge/materials/uber-material.js | 185 ++++++++++- js/models/materials-model.js | 32 +- 17 files changed, 1075 insertions(+), 287 deletions(-) diff --git a/assets/canvas-runtime.js b/assets/canvas-runtime.js index fd823f35..dd4ad6f9 100644 --- a/assets/canvas-runtime.js +++ b/assets/canvas-runtime.js @@ -37,18 +37,15 @@ function CanvasDataManager() for (var i=0; i= 0) + var jObj = JSON.parse( importStr ); + + var id = jObj.id; + if (id) { - var endIndex = importStr.indexOf( "\n", startIndex ); - if (endIndex > 0) + var canvas = this.findCanvasWithID( id, root ); + if (canvas) { - var id = importStr.substring( startIndex+4, endIndex ); - var canvas = this.findCanvasWithID( id, root ); - if (canvas) - { - var rt = new GLRuntime( canvas, importStr, assetPath ); - } + new GLRuntime( canvas, jObj, assetPath ); } } } @@ -95,14 +92,15 @@ function CanvasDataManager() // Class GLRuntime // Manages runtime fora WebGL canvas /////////////////////////////////////////////////////////////////////// -function GLRuntime( canvas, importStr, assetPath ) +function GLRuntime( canvas, jObj, assetPath ) { /////////////////////////////////////////////////////////////////////// // Instance variables /////////////////////////////////////////////////////////////////////// this._canvas = canvas; this._context = null; - this._importStr = importStr; + //this._importStr = importStr; + this._jObj = jObj; this.renderer = null; this.myScene = null; @@ -157,21 +155,19 @@ function GLRuntime( canvas, importStr, assetPath ) /////////////////////////////////////////////////////////////////////// this.loadScene = function() { + var jObj = this._jObj; + if (!jObj.children || (jObj.children.length != 1)) + throw new Error( "ill-formed JSON for runtime load: " + jObj ); + var root = jObj.children[0]; + // parse the data - // the GL runtime must start with a "sceneData: " - var index = importStr.indexOf( "scenedata: " ); - if (index >= 0) + if (jObj.scenedata) { this._useWebGL = true; - var rdgeStr = importStr.substr( index+11 ); - var endIndex = rdgeStr.indexOf( "endscene\n" ); - if (endIndex < 0) throw new Error( "ill-formed WebGL data" ); - var len = endIndex - index + 11; - rdgeStr = rdgeStr.substr( 0, endIndex ); - + var rdgeStr = jObj.scenedata; this.myScene.importJSON( rdgeStr ); - this.importObjects( importStr ); + this.importObjects( root ); this.linkMaterials( this._geomRoot ); this.initMaterials(); this.linkLights(); @@ -179,7 +175,7 @@ function GLRuntime( canvas, importStr, assetPath ) else { this._context = this._canvas.getContext( "2d" ); - this.importObjects( importStr ); + this.importObjects( root ); this.render(); } } @@ -277,58 +273,42 @@ function GLRuntime( canvas, importStr, assetPath ) } } - this.importObjects = function( importStr, parent ) + this.importObjects = function( jObj, parent ) { - var index = importStr.indexOf( "OBJECT\n", 0 ); - while (index >= 0) - { - // update the string to the current object - importStr = importStr.substr( index+7 ); + // read the next object + var gObj = this.importObject( jObj, parent ); - // read the next object - var obj = this.importObject( importStr, parent ); - - // determine if we have children - var endIndex = importStr.indexOf( "ENDOBJECT\n" ), - childIndex = importStr.indexOf( "OBJECT\n" ); - if (endIndex < 0) throw new Error( "ill-formed object data" ); - if ((childIndex >= 0) && (childIndex < endIndex)) + // load the children + if (jObj.children) + { + var nKids = jObj.children.length; + for (var i=0; i= 0) - { - rtnPath = url.substr( index + searchStr.length ); - rtnPath = this._assetPath + rtnPath; - } - return rtnPath; - */ +// var searchStr = "assets/"; +// var index = url.indexOf( searchStr ); +// var rtnPath = url; +// if (index >= 0) +// { +// rtnPath = url.substr( index + searchStr.length ); +// rtnPath = this._assetPath + rtnPath; +// } +// return rtnPath; + return url; } @@ -450,8 +429,7 @@ function GLRuntime( canvas, importStr, assetPath ) } // start RDGE or load Canvas 2D objects - var index = importStr.indexOf( "scenedata: " ); - this._useWebGL = (index >= 0); + if (jObj.scenedata) this._useWebGL = true; if (this._useWebGL) { var id = canvas.getAttribute( "data-RDGE-id" ); @@ -515,16 +493,17 @@ function RuntimeGeomObj() { } - this.importMaterials = function(importStr) + this.importMaterials = function(jObj) { - var nMaterials = Number( getPropertyFromString( "nMaterials: ", importStr ) ); + var nMaterials = jObj.nMaterials; + var matArray = jObj.materials; for (var i=0; i= 0) - rtnStr = rtnStr.substr(0, index); - - return rtnStr; -} - /////////////////////////////////////////////////////////////////////// // Class RuntimeRectangle /////////////////////////////////////////////////////////////////////// @@ -685,26 +646,24 @@ function RuntimeRectangle() this.inheritedFrom = RuntimeGeomObj; this.inheritedFrom(); - this.import = function( importStr ) + this.import = function( jObj ) { - this._xOffset = Number( getPropertyFromString( "xoff: ", importStr ) ); - this._yOffset = Number( getPropertyFromString( "yoff: ", importStr ) ); - this._width = Number( getPropertyFromString( "width: ", importStr ) ); - this._height = Number( getPropertyFromString( "height: ", importStr ) ); - this._strokeWidth = Number( getPropertyFromString( "strokeWidth: ", importStr ) ); - this._innerRadius = Number( getPropertyFromString( "innerRadius: ", importStr ) ); - this._strokeStyle = Number( getPropertyFromString( "strokeStyle: ", importStr ) ); - var strokeMaterialName = getPropertyFromString( "strokeMat: ", importStr ); - var fillMaterialName = getPropertyFromString( "fillMat: ", importStr ); - this._strokeStyle = getPropertyFromString( "strokeStyle: ", importStr ); - this._fillColor = eval( "[" + getPropertyFromString( "fillColor: ", importStr ) + "]" ); - this._strokeColor = eval( "[" + getPropertyFromString( "strokeColor: ", importStr ) + "]" ); - this._tlRadius = Number( getPropertyFromString( "tlRadius: ", importStr ) ); - this._trRadius = Number( getPropertyFromString( "trRadius: ", importStr ) ); - this._blRadius = Number( getPropertyFromString( "blRadius: ", importStr ) ); - this._brRadius = Number( getPropertyFromString( "brRadius: ", importStr ) ); - - this.importMaterials( importStr ); + this._xOffset = jObj.xoff; + this._yOffset = jObj.yoff; + this._width = jObj.width; + this._height = jObj.height; + this._strokeWidth = jObj.strokeWidth; + this._strokeColor = jObj.strokeColor; + this._fillColor = jObj.fillColor; + this._tlRadius = jObj.tlRadius; + this._trRadius = jObj.trRadius; + this._blRadius = jObj.blRadius; + this._brRadius = jObj.brRadius; + this._innerRadius = jObj.innerRadius; + this._strokeStyle = jObj.strokeStyle; + var strokeMaterialName = jObj.strokeMat; + var fillMaterialName = jObj.fillMat; + this.importMaterials( jObj.materials ); } this.renderPath = function( inset, ctx ) @@ -836,21 +795,20 @@ function RuntimeOval() this.inheritedFrom = RuntimeGeomObj; this.inheritedFrom(); - this.import = function( importStr ) + this.import = function( jObj ) { - this._xOffset = Number( getPropertyFromString( "xoff: ", importStr ) ); - this._yOffset = Number( getPropertyFromString( "yoff: ", importStr ) ); - this._width = Number( getPropertyFromString( "width: ", importStr ) ); - this._height = Number( getPropertyFromString( "height: ", importStr ) ); - this._strokeWidth = Number( getPropertyFromString( "strokeWidth: ", importStr ) ); - this._innerRadius = Number( getPropertyFromString( "innerRadius: ", importStr ) ); - this._strokeStyle = getPropertyFromString( "strokeStyle: ", importStr ); - var strokeMaterialName = getPropertyFromString( "strokeMat: ", importStr ); - var fillMaterialName = getPropertyFromString( "fillMat: ", importStr ); - this._fillColor = eval( "[" + getPropertyFromString( "fillColor: ", importStr ) + "]" ); - this._strokeColor = eval( "[" + getPropertyFromString( "strokeColor: ", importStr ) + "]" ); - - this.importMaterials( importStr ); + this._xOffset = jObj.xoff; + this._yOffset = jObj.yoff; + this._width = jObj.width; + this._height = jObj.height; + this._strokeWidth = jObj.strokeWidth; + this._strokeColor = jObj.strokeColor; + this._fillColor = jObj.fillColor; + this._innerRadius = jObj.innerRadius; + this._strokeStyle = jObj.strokeStyle; + var strokeMaterialName = jObj.strokeMat; + var fillMaterialName = jObj.fillMat; + this.importMaterials( jObj.materials ); } this.render = function() @@ -1098,23 +1056,9 @@ function RuntimeMaterial( world ) { } - this.import = function( importStr ) - { - } - - this.getPropertyFromString = function( prop, str ) + this.import = function( jObj ) { - var index = str.indexOf( prop ); - if (index < 0) throw new Error( "property " + prop + " not found in string: " + str); - - var rtnStr = str.substr( index+prop.length ); - index = rtnStr.indexOf( "\n" ); - if (index >= 0) - rtnStr = rtnStr.substr(0, index); - - return rtnStr; } - } function RuntimeFlatMaterial() @@ -1129,14 +1073,11 @@ function RuntimeFlatMaterial() // assign a default color this._color = [1,0,0,1]; - this.import = function( importStr ) + this.import = function( jObj ) { - var colorStr = this.getPropertyFromString( "color: ", importStr ); - if (colorStr) - this._color = eval( "[" + colorStr + "]" ); + this._color = jObj.color; }; - this.init = function( world ) { if (this._shader) @@ -1160,9 +1101,9 @@ function RuntimePulseMaterial() this.isAnimated = function() { return true; } - this.import = function( importStr ) + this.import = function( jObj ) { - this._texMap = this.getPropertyFromString( "texture: ", importStr ); + this._texMap = jObj.texture; } this.init = function( world ) @@ -1254,25 +1195,19 @@ function RuntimeRadialGradientMaterial() } } - this.import = function( importStr ) + this.import = function( jObj ) { - var colorStr; - colorStr = this.getPropertyFromString( "color1: ", importStr ); - this._color1 = eval( "[" + colorStr + "]" ); - colorStr = this.getPropertyFromString( "color2: ", importStr ); - this._color2 = eval( "[" + colorStr + "]" ); - colorStr = this.getPropertyFromString( "color3: ", importStr ); - this._color3 = eval( "[" + colorStr + "]" ); - colorStr = this.getPropertyFromString( "color4: ", importStr ); - this._color4 = eval( "[" + colorStr + "]" ); - - this._colorStop1 = Number( this.getPropertyFromString( "colorStop1: ", importStr ) ); - this._colorStop2 = Number( this.getPropertyFromString( "colorStop2: ", importStr ) ); - this._colorStop3 = Number( this.getPropertyFromString( "colorStop3: ", importStr ) ); - this._colorStop4 = Number( this.getPropertyFromString( "colorStop4: ", importStr ) ); + var color1 = jObj.color1, + color2 = jObj.color2, + color3 = jObj.color3, + color4 = jObj.color4, + colorStop1 = jObj.colorStop1, + colorStop2 = jObj.colorStop2, + colorStop3 = jObj.colorStop3, + colorStop4 = jObj.colorStop4; if (this._angle !== undefined) - this._angle = this.getPropertyFromString( "angle: ", importStr ); + this._angle = jObj.angle; } } @@ -1304,12 +1239,12 @@ function RuntimeBumpMetalMaterial() this._specularTexture = "assets/images/silver.png"; this._normalTexture = "assets/images/normalMap.png"; - this.import = function( importStr ) + this.import = function( jObj ) { - this._lightDiff = eval( "[" + this.getPropertyFromString( "lightDiff: ", importStr ) + "]" ); - this._diffuseTexture = this.getPropertyFromString( "diffuseTexture: ", importStr ); - this._specularTexture = this.getPropertyFromString( "specularTexture: ", importStr ); - this._normalTexture = this.getPropertyFromString( "normalMap: ", importStr ); + this._lightDiff = jObj.lightDiff; + this._diffuseTexture = jObj.diffuseTexture; + this._specularTexture = jObj.specularTexture; + this._normalTexture = jObj.normalMap; } this.init = function( world ) @@ -1445,91 +1380,70 @@ function RuntimeUberMaterial() { } - this.import = function( importStr ) + this.import = function( jObj ) { - // limit the key searches to this material - var endKey = "endMaterial\n"; - var index = importStr.indexOf( endKey ); - index += endKey.length; - importStr = importStr.slice( 0, index ); - - var matProps = getPropertyFromString( "materialProps: ", importStr ); - if (matProps) + if (jObj.materialProps) { - this._ambientColor = eval( "[" + getPropertyFromString("ambientColor: ", importStr) + ']' ); - this._diffuseColor = eval( "[" + getPropertyFromString( "diffuseColor: ", importStr) + ']' ); - this._specularColor = eval( "[" + getPropertyFromString( "specularColor: ", importStr) + ']' ); - this._specularPower = Number( getPropertyFromString( "specularPower: ", importStr) ); + var ambientColor = jObj.materialProps.ambientColor; this.setProperty( "ambientColor", ambientColor ); + var diffuseColor = jObj.materialProps.diffuseColor; this.setProperty( "diffuseColor", diffuseColor ); + var specularColor = jObj.materialProps.specularColor; this.setProperty( "specularColor", specularColor ); + var specularPower = jObj.materialProps.specularPower; this.setProperty( "specularPower", specularPower ); } - var lightProps = getPropertyFromString( "lightProps: ", importStr ); - if (lightProps) + var lightArray = jObj.lights; + if (lightArray) { this._lights = []; - var lightStr; for (var i=0; i= 0) { - var endIndex = importStr.indexOf( "\n", startIndex ); - if (endIndex > 0) { - var id = importStr.substring( startIndex+4, endIndex ); - if (id) { - var canvas = this.findCanvasWithID( id, elt ); - if (canvas) { - if (!canvas.elementModel) { - NJUtils.makeElementModel(canvas, "Canvas", "shape", true); + var jObj = JSON.parse( importStr ); + if (jObj) + { + var id = jObj.id; + if (id) + { + var canvas = this.findCanvasWithID( id, elt ); + if (canvas) { + if (!canvas.elementModel) { + NJUtils.makeElementModel(canvas, "Canvas", "shape", true); + } + if (canvas.elementModel) { + if (canvas.elementModel.shapeModel.GLWorld) { + canvas.elementModel.shapeModel.GLWorld.clearTree(); } - if (canvas.elementModel) { - if (canvas.elementModel.shapeModel.GLWorld) { - canvas.elementModel.shapeModel.GLWorld.clearTree(); - } - var index = importStr.indexOf( "webGL: " ); - var useWebGL = (index >= 0) + if (jObj) + { + var useWebGL = jObj.webGL; var world = new GLWorld( canvas, useWebGL ); - world.import( importStr ); + world.importJSON( jObj ); this.buildShapeModel( canvas.elementModel, world ); } } @@ -382,7 +379,7 @@ exports.HTMLDocument = Montage.create(TextDocument, { { if (elt.elementModel && elt.elementModel.shapeModel && elt.elementModel.shapeModel.GLWorld) { - var data = elt.elementModel.shapeModel.GLWorld.export(); + var data = elt.elementModel.shapeModel.GLWorld.exportJSON(); dataArray.push( data ); } diff --git a/js/lib/drawing/world.js b/js/lib/drawing/world.js index 44c9e37d..9e502c3e 100755 --- a/js/lib/drawing/world.js +++ b/js/lib/drawing/world.js @@ -727,6 +727,57 @@ World.prototype.getShapeFromPoint = function( offsetX, offsetY ) { } }; +World.prototype.exportJSON = function() +{ + // world properties + var worldObj = + { + 'version' : 1.1, + 'id' : this.getCanvas().getAttribute( "data-RDGE-id" ), + 'fov' : this._fov, + 'zNear' : this._zNear, + 'zFar' : this._zFar, + 'viewDist' : this._viewDist, + 'webGL' : this._useWebGL + }; + + // RDGE scenegraph + if (this._useWebGL) + worldObj.scenedata = this.myScene.exportJSON(); + + // object data + var strArray = []; + this.exportObjectsJSON( this._geomRoot, worldObj ); + + // convert the object to a string + var jStr = JSON.stringify( worldObj ); + + // the RDGE export function corrupts the data. + // rebuild the tree + var root = this._rootNode; + root.children = new Array(); + if (worldObj.children && (worldObj.children.length === 1)) + this.importObjectsJSON( worldObj.children[0] ); + + return jStr; +} + +World.prototype.exportObjectsJSON = function( obj, parentObj ) +{ + if (!obj) return; + + var jObj = obj.exportJSON(); + if (!parentObj.children) parentObj.children = []; + parentObj.children.push( jObj ); + + if (obj.getChild()) { + this.exportObjects( obj.getChild (), jObj ); + } + + if (obj.getNext()) + this.exportObjects( obj.getNext(), parentObj ); +} + World.prototype.export = function() { var exportStr = "GLWorld 1.0\n"; @@ -808,6 +859,83 @@ World.prototype.findTransformNodeByMaterial = function( materialNode, trNode ) return rtnNode; }; +World.prototype.importJSON = function( jObj ) +{ + if (jObj.webGL) + { + // start RDGE + rdgeStarted = true; + var id = this._canvas.getAttribute( "data-RDGE-id" ); + this._canvas.rdgeid = id; + g_Engine.registerCanvas(this._canvas, this); + RDGEStart( this._canvas ); + this._canvas.task.stop() + } + + // import the objects + // there should be exactly one child of the parent object + if (jObj.children && (jObj.children.length === 1)) + this.importObjectsJSON( jObj.children[0] ); + else + throw new Error ("unrecoverable canvas import error - inconsistent root object: " + jObj.children ); + + if (!this._useWebGL) + { + // render using canvas 2D + this.render(); + } +} + +World.prototype.importObjectsJSON = function( jObj, parentGeomObj ) +{ + // read the next object + var gObj = this.importObjectJSON( jObj, parentGeomObj ); + + // determine if we have children + if (jObj.children) + { + var nKids = ojObjbj.chilodren.length; + for (var i=0; i */ var MaterialsModel = require("js/models/materials-model").MaterialsModel; +/* var FlatMaterial = require("js/lib/rdge/materials/flat-material").FlatMaterial; var LinearGradientMaterial = require("js/lib/rdge/materials/linear-gradient-material").LinearGradientMaterial; var RadialGradientMaterial = require("js/lib/rdge/materials/radial-gradient-material").RadialGradientMaterial; @@ -25,6 +26,7 @@ var TwistMaterial = require("js/lib/rdge/materials/twist-material").TwistMateria var JuliaMaterial = require("js/lib/rdge/materials/julia-material").JuliaMaterial; var KeleidoscopeMaterial = require("js/lib/rdge/materials/keleidoscope-material").KeleidoscopeMaterial; var MandelMaterial = require("js/lib/rdge/materials/mandel-material").MandelMaterial; +*/ /////////////////////////////////////////////////////////////////////// // Class GLGeomObj @@ -225,6 +227,83 @@ var GeomObj = function GLGeomObj() { return fillMaterial; }; + this.exportMaterialsJSON = function() + { + var jObj; + if (this._materialArray && this._materialNodeArray) + { + var nMats = this._materialArray.length; + if (nMats > 0) + { + var arr = []; + + for (var i=0; i 0) + { + this._ubershaderCaps.lighting = + { + 'light0' : this._lights[0], + 'light1' : this._lights[1], + 'light2' : this._lights[2], + 'light3' : this._lights[3] + } + } + } + + var diffuseMap = jObj['diffuseMap']; + if(diffuseMap) + this.setProperty( "diffuseMap", diffuseMap ); + + var normalMap = jObj['normalMap']; + if(normalMap) + this.setProperty( "normalMap", normalMap ); + + var specularMap = jObj['specularMap']; + if(specularMap) + this.setProperty( "specularMap", specularMap ); + + var environmentMap = jObj['environmentMap']; + if(environmentMap) + { + this.setProperty( "environmentMap", environmentMap ); + this.setProperty( "environmentAmount", jObj['environmentAmount'] ); + } + + this.rebuildShader(); + } + + this.exportJSON = function() + { + // we will be needing the world. Make sure it is there + var world = this.getWorld(); + if (!world) + throw new Error( "no world in material.export, " + this.getName() ); + + // every material needs the base type and instance name + var caps = this._ubershaderCaps; + var jObj = + { + 'material' : this.getShaderName(), + 'name' : this.getName() + }; + + // export the material properties + if (typeof caps.material != 'undefined') + { + jObj.materialProps = + { + 'ambientColor' : this._ambientColor, + 'diffuseColor' : this._diffuseColor, + 'specularColor' : this._specularColor, + 'specularPower' : this._specularPower + }; + + } + + if (typeof caps.lighting != 'undefined') + { + var lightArray = []; + for (var i=0; i 0) + jObj.lights = lightArray; + } + + if(typeof caps.diffuseMap != 'undefined') + jObj['diffuseMap'] = caps.diffuseMap.texture; + + if(typeof caps.normalMap != 'undefined') + jObj['normalMap'] = caps.normalMap.texture; + + if(typeof caps.specularMap != 'undefined') + jObj['specularMap'] = caps.specularMap.texture; + + if(typeof caps.environmentMap != 'undefined') + { + jObj['environmentMap'] = caps.environmentMap.texture; + jObj['environmentAmount'] = caps.environmentMap.envReflection; + } + + return jObj; + } + + this.export = function() { // every material needs the base type and instance name @@ -539,10 +720,6 @@ var UberMaterial = function UberMaterial() { } } -// this._diffuseMapOb = { 'texture' : 'assets/images/rocky-diffuse.jpg', 'wrap' : 'REPEAT' }; -// this._normalMapOb = { 'texture' : 'assets/images/rocky-normal.jpg', 'wrap' : 'REPEAT' }; -// this._specularMapOb = { 'texture' : 'assets/images/rocky-spec.jpg', 'wrap' : 'REPEAT' }; -// this._environmentMapOb = { 'texture' : 'assets/images/silver.png', 'wrap' : 'CLAMP', 'envReflection' : this._environmentAmount }; var world = this.getWorld(); if (!world) throw new Error( "no world in material.export, " + this.getName() ); diff --git a/js/models/materials-model.js b/js/models/materials-model.js index d8fb4016..a45b0c72 100755 --- a/js/models/materials-model.js +++ b/js/models/materials-model.js @@ -115,7 +115,31 @@ exports.MaterialsModel = Montage.create(Component, { return this._materials[index]; } } - }, + }, + + getMaterialByShader: + { + value: function( shaderName ) + { + var index = this.getIndexOfMaterialByShader( shaderName ); + if (index >= 0) + return this._materials[index]; + } + }, + + getIndexOfMaterialByShader: { + value: function (shaderName) { + var len = this._materials.length; + for(var i=0; i= 0) { + var endIndex = importStr.indexOf( "\n", startIndex ); + if (endIndex > 0) + id = importStr.substring( startIndex+4, endIndex ); + } + } + + if (id != null) + { + var canvas = this.findCanvasWithID( id, elt ); + if (canvas) { - var canvas = this.findCanvasWithID( id, elt ); - if (canvas) { - if (!canvas.elementModel) { - NJUtils.makeElementModel(canvas, "Canvas", "shape", true); + if (!canvas.elementModel) + { + NJUtils.makeElementModel(canvas, "Canvas", "shape", true); + } + if (canvas.elementModel) + { + if (canvas.elementModel.shapeModel.GLWorld) + canvas.elementModel.shapeModel.GLWorld.clearTree(); + + if (jObj) + { + var useWebGL = jObj.webGL; + var world = new GLWorld( canvas, useWebGL ); + world.importJSON( jObj ); } - if (canv