/* <copyright> This file contains proprietary software owned by Motorola Mobility, Inc.<br/> No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. </copyright> */ var GeomObj = require("js/lib/geom/geom-obj").GeomObj, RuntimeGeomObj = require("js/lib/rdge/runtime/RuntimeGeomObj"), RuntimeRectangle = RuntimeGeomObj.RuntimeRectangle, RuntimeOval = RuntimeGeomObj.RuntimeOval, getPropertyFromString = require("js/lib/rdge/runtime/RuntimeGeomObj").getPropertyFromString; /////////////////////////////////////////////////////////////////////// // Class GLRuntime // Manages runtime fora WebGL canvas /////////////////////////////////////////////////////////////////////// var GLRuntime = function GLRuntime( canvas, importStr ) { /////////////////////////////////////////////////////////////////////// // Instance variables /////////////////////////////////////////////////////////////////////// this._canvas = canvas; this._context = null; this._importStr = importStr; this.renderer = null; this.myScene = null; this.light = null; this.light2 = null; this._rootNode = null; this._firstRender = true; this._initialized = false; this._useWebGL = false; // view parameters this._fov = 45.0; this._zNear = 0.1; this._zFar = 100.0; this._viewDist = 5.0; this._aspect = canvas.width/canvas.height; this._geomRoot; // all "live" materials this._materials = []; /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// this.getZNear = function() { return this._zNear; } this.getZFar = function() { return this._zFar; } this.getFOV = function() { return this._fov; } this.getAspect = function() { return this._aspect; } this.getViewDistance = function() { return this._viewDist; } this.get2DContext = function() { return this._context; } this.getViewportWidth = function() { return this._canvas.width; } this.getViewportHeight = function() { return this._canvas.height; } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// this.loadScene = function() { // parse the data // the GL runtime must start with a "sceneData: " var index = importStr.indexOf( "scenedata: " ); if (index >= 0) { 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 ); this.myScene.importJSON( rdgeStr ); this.importObjects( importStr ); this.linkMaterials( this._geomRoot ); this.initMaterials(); } else { this._context = this._canvas.getContext( "2d" ); this.importObjects( importStr ); this.render(); } } this.init = function() { var ctx1 = g_Engine.ctxMan.handleToObject(this._canvas.rdgeCtxHandle), ctx2 = g_Engine.getContext(); if (ctx1 != ctx2) console.log( "***** different contexts *****" ); this.renderer = ctx1.renderer; // create a camera, set its perspective, and then point it at the origin var cam = new camera(); this._camera = cam; cam.setPerspective(this.getFOV(), this.getAspect(), this.getZNear(), this.getZFar()); cam.setLookAt([0, 0, this.getViewDistance()], [0, 0, 0], vec3.up()); // make this camera the active camera this.renderer.cameraManager().setActiveCamera(cam); // change clear color this.renderer.setClearColor([1.0, 1.0, 1.0, 0.0]); // create an empty scene graph this.myScene = new SceneGraph(); // load the scene graph data this.loadScene(); // Add the scene to the engine - necessary if you want the engine to draw for you var name = "myScene" + this._canvas.getAttribute( "data-RDGE-id" ); g_Engine.AddScene(name, this.myScene); this._initialized = true; } // main code for handling user interaction and updating the scene this.update = function(dt) { if (this._initialized) { if (!dt) dt = 0.2; dt = 0.01; // use our own internal throttle this.elapsed += dt; // changed the global position uniform of light 0, another way to change behavior of a light rdgeGlobalParameters.u_light0Pos.set( [5*Math.cos(this.elapsed), 5*Math.sin(this.elapsed), 20]); // orbit the light nodes around the boxes //this.light.setPosition([1.2*Math.cos(this.elapsed*2.0), 1.2*Math.sin(this.elapsed*2.0), 1.2*Math.cos(this.elapsed*2.0)]); //this.light2.setPosition([-1.2*Math.cos(this.elapsed*2.0), 1.2*Math.sin(this.elapsed*2.0), -1.2*Math.cos(this.elapsed)]); this.updateMaterials(); // now update all the nodes in the scene this.myScene.update(dt); } } this.updateMaterials = function() { var nMats = this._materials.length; for (var i=0; i<nMats; i++) { var mat = this._materials[i]; mat.update(); } } // defining the draw function to control how the scene is rendered this.draw = function() { if (this._initialized) { g_Engine.setContext( this._canvas.rdgeid ); var ctx = g_Engine.getContext(); var renderer = ctx.renderer; if (renderer.unloadedTextureCount <= 0) { renderer.disableCulling(); renderer._clear(); this.myScene.render(); if (this._firstRender) { if (this._canvas.task) { this._firstRender = false; //this._canvas.task.stop(); } } } } } this.importObjects = function( importStr, 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 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)) { importStr = importStr.substr( childIndex + 7 ); importStr = this.importObjects( importStr, obj ); endIndex = importStr.indexOf( "ENDOBJECT\n" ) } // remove the string for the object(s) just created importStr = importStr.substr( endIndex ); // get the location of the next object index = importStr.indexOf( "OBJECT\n", endIndex ); } return importStr; } this.importObject = function( objStr, parent ) { var type = Number( getPropertyFromString( "type: ", objStr ) ); var obj; switch (type) { case 1: obj = new RuntimeRectangle(); obj.import( objStr, parent ); break; case 2: // circle obj = new RuntimeOval(); obj.import( objStr, parent ); break; case 3: // line obj = new RuntimeLine(); obj.import( objStr, parent ); break; default: throw new Error( "Attempting to load unrecognized object type: " + type ); break; } if (obj) this.addObject( obj ); return obj; } this.addObject = function( obj, parent ) { if (!obj) return; obj.setWorld( this ); if (parent == null) this._geomRoot = obj; else parent.addChild( obj ); } this.linkMaterials = function( obj ) { if (!obj) return; // get the array of materials from the object var matArray = obj._materials; var nMats = matArray.length; for (var i=0; i<nMats; i++) { var mat = matArray[i]; var nodeName = mat._materialNodeName; var matNode = this.findMaterialNode( nodeName, this.myScene.scene ); if (matNode) { mat._materialNode = matNode; mat._shader = matNode.shaderProgram; this._materials.push( mat ); } } } this.initMaterials = function() { var nMats = this._materials.length; for (var i=0; i<nMats; i++) { var mat = this._materials[i]; mat.init(); } } this.findMaterialNode = function( nodeName, node ) { if (node.transformNode) node = node.transformNode; if (node.materialNode) { if (nodeName === node.materialNode.name) return node.materialNode; } if (node.children) { var nKids = node.children.length; for (var i=0; i<nKids; i++) { var child = node.children[i]; var rtnNode = this.findMaterialNode( nodeName, child ); if (rtnNode) return rtnNode; } } } this.render = function( obj ) { if (!obj) obj = this._geomRoot; obj.render(); if (obj.children) { var nKids = obj.children.length; for (var i=0; i<nKids; i++) { var child = obj.children[i]; if (child) this.render( child ); } } } // start RDGE or load Canvas 2D objects var index = importStr.indexOf( "scenedata: " ); this._useWebGL = (index >= 0); if (this._useWebGL) { var id = canvas.getAttribute( "data-RDGE-id" ); canvas.rdgeid = id; g_Engine.registerCanvas(canvas, this); RDGEStart( canvas ); } else { this.loadScene(); } } if (typeof exports === "object") { exports.GLRuntime = GLRuntime; }