From b89a7ee8b956c96a1dcee995ea840feddc5d4b27 Mon Sep 17 00:00:00 2001 From: Pierre Frisch Date: Thu, 22 Dec 2011 07:25:50 -0800 Subject: First commit of Ninja to ninja-internal Signed-off-by: Valerio Virgillito --- js/helper-classes/RDGE/GLWorld.js | 834 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 834 insertions(+) create mode 100644 js/helper-classes/RDGE/GLWorld.js (limited to 'js/helper-classes/RDGE/GLWorld.js') diff --git a/js/helper-classes/RDGE/GLWorld.js b/js/helper-classes/RDGE/GLWorld.js new file mode 100644 index 00000000..cc44da50 --- /dev/null +++ b/js/helper-classes/RDGE/GLWorld.js @@ -0,0 +1,834 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +// globals +var shaderProgramArray = new Array; +var glContextArray = new Array; + +var vertexShaderSource = ""; +var fragmentShaderSource = ""; + +var rdgeStarted = false; + +var nodeCounter = 0; + + +/////////////////////////////////////////////////////////////////////// +// Class GLWorld +// Manages display in a canvas +/////////////////////////////////////////////////////////////////////// +function GLWorld( canvas, use3D ) +{ + /////////////////////////////////////////////////////////////////////// + // Instance variables + /////////////////////////////////////////////////////////////////////// + + // flag to do the drawing with WebGL + this._useWebGL = false; + if(use3D) + this._useWebGL = use3D; + + this._canvas = canvas; + if (this._useWebGL) + this._glContext = canvas.getContext("experimental-webgl"); + else + this._2DContext = canvas.getContext( "2d" ); + + this._viewportWidth = canvas.width; + this._viewportHeight = canvas.height; + + // view parameters + this._fov = 45.0; + this._zNear = 0.1; + this._zFar = 100.0; + this._viewDist = 5.0; + + // default light parameters + this._ambientLightColor = [0.1, 0.1, 0.1, 1.0]; + this._diffuseLightColor = [0.1, 0.1, 0.1, 1.0]; + this._specularLightColor = [0.6, 0.6, 0.6, 1.0]; + this._pointLightLoc = [0.0, 0.0, 0.05]; + + // default material properties. Material properties should be overridden + // by the materials used by the objects + this._materialShininess = 20.0; + + this._geomRoot = undefined; + + this._cameraMat = Matrix.I(4); + this._cameraMat[14] = 5.0; + this._cameraMatInv = Matrix.I(4); + this._cameraMatInv[14] = -5.0; + + this._camera; + + /////////////////////////////////////////////////////////////////////// + // Property accessors + /////////////////////////////////////////////////////////////////////// + this.getGLContext = function() { return this._glContext; } + this.setGLContext = function(gl) { this._glContext = gl; } + + this.get2DContext = function() { return this._2DContext; } + this.set2DContext = function(c) { this._2DContext = c; } + + this.getCanvas = function() { return this._canvas; } + this.setCanvas = function(c) { this._canvas = c; } + + this.getShaderProgram = function() { return this._shaderProgram; } + + this.getViewportWidth = function() { return this._viewportWidth; } + this.getViewportHeight = function() { return this._viewportHeight; } + + this.getAspect = function() { return this._viewportWidth/this._viewportHeight; } + + this.getGeomRoot = function() { return this._geomRoot; } + this.getZNear = function() { return this._zNear; } + this.getZFar = function() { return this._zFar; } + this.getFOV = function() { return this._fov; } + + this.getCamera = function() { return this._camera; } + + this.getCameraMat = function() { return this._cameraMat.slice(0); } + this.setCameraMat = function(c) { this._cameraMat = c.slice(0); this._cameraMatInv = glmat4.inverse(c, []); } + + this.getCameraMatInverse = function() { return this._cameraMatInv.slice(0); } + + this.getViewDistance = function() { return this._viewDist; } + + this.getRootNode = function() { return this._rootNode; } + this.setRootNode = function(r) { this._rootNode = r; } + + this.isWebGL = function() { return this._useWebGL; } + + //////////////////////////////////////////////////////////////////////////////////// + // RDGE + // local variables + this.myScene = null; + this.elapsed = 0; + this.light = null; + this.light2 = null; + this.fillShader = null; + this.strokeShader = null; + this.renderer = null; + + // this is the node to which objects get hung + this._rootNode; + + // set up the camera matrix + var camMat = Matrix.I(4); + camMat[14] = this.getViewDistance(); + this.setCameraMat( camMat ); + + ////////////////////////////////////////// + // test call to SVG importer +// console.log( "***** SVG TEST *****" ); +// var svgImporter = new SVGParse( this ); +// svgImporter.importSVG(); + ////////////////////////////////////////// + + // post-load processing of the scene + 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.setClearFlags(g_Engine.getContext().DEPTH_BUFFER_BIT); + this.renderer.setClearColor([1.0, 1.0, 1.0, 0.0]); + //this.renderer.NinjaWorld = this; + + // create an empty scene graph + this.myScene = new SceneGraph(); + + // create some lights + // light 1 + this.light = createLightNode("myLight"); + this.light.setPosition([0,0,1.2]); + this.light.setDiffuseColor([0.75,0.9,1.0,1.0]); + + // light 2 + this.light2 = createLightNode("myLight2"); + this.light2.setPosition([-0.5,0,1.2]); + this.light2.setDiffuseColor([1.0,0.9,0.75,1.0]); + + // create a light transform + var lightTr = createTransformNode("lightTr"); + + // create and attach a material - materials hold the light data + lightTr.attachMaterial(createMaterialNode("lights")); + + // enable light channels 1, 2 - channel 0 is used by the default shader + lightTr.materialNode.enableLightChannel(1, this.light); + lightTr.materialNode.enableLightChannel(2, this.light2); + + // all added objects are parented to the light node + this._rootNode = lightTr; + + // add the light node to the scene + this.myScene.addNode(lightTr); + + // Add the scene to the engine - necessary if you want the engine to draw for you + g_Engine.AddScene("myScene" + this._canvas.id, this.myScene); + } + + // main code for handling user interaction and updating the scene + this.update = function(dt) + { + if (!dt) dt = 0.2; + + this.elapsed += dt; + + if (this._useWebGL) + { + // 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( this.getGeomRoot(), this.elapsed ); + + // now update all the nodes in the scene + if (this._useWebGL) + this.myScene.update(dt); + } + + // defining the draw function to control how the scene is rendered + this.draw = function() + { + if (this._useWebGL) + { + var ctx = g_Engine.getContext(); + //console.log( "RDGE state: " + ctx.ctxStateManager.currentState().name); + + var renderer = ctx.renderer; + renderer.disableCulling(); + this.myScene.render(); + } + else + { + this.render(); + } + } + + // END RDGE + //////////////////////////////////////////////////////////////////////////////////// + + + // start RDGE passing your runtime object, and false to indicate we don't need a an initialization state + // in the case of a procedurally built scene an init state is not needed for loading data + //if (this._useWebGL) + { + if (this._useWebGL) + { + rdgeStarted = true; + + // TODO - temporary fix for RDGE id's + this._canvas.id = this._canvas.uuid; + + g_Engine.registerCanvas(this._canvas, this); + RDGEStart( this._canvas ); + + //this._canvas.fpsTracker = new fpsTracker( '0' ); + //this._canvas.task = new RDGETask(this._canvas, true); + //this._canvas.task.stop() + //this._canvas.task.start() + } + } +} + + +/////////////////////////////////////////////////////////////////////// +// Property Accessors +/////////////////////////////////////////////////////////////////////// +GLWorld.prototype.getGeomRoot = function() { return this._geomRoot; } + + +/////////////////////////////////////////////////////////////////////// +// Methods +/////////////////////////////////////////////////////////////////////// +GLWorld.prototype.updateObject = function (obj) +{ + if (!this._useWebGL) return; + + var prims = obj.getPrimitiveArray(); + var materialNodes = obj.getMaterialNodeArray(); + if (prims.length != materialNodes.length) + throw new Error("inconsistent material and primitive counts"); + var nPrims = prims.length; + var ctrTrNode; + if (nPrims > 0) { + ctrTrNode = obj.getTransformNode(); + if (ctrTrNode == null) + { + ctrTrNode = createTransformNode("objRootNode_" + nodeCounter++); + this._rootNode.insertAsChild( ctrTrNode ); + obj.setTransformNode( ctrTrNode ); + } + + ctrTrNode.meshes.forEach(function(thisMesh) { + g_meshMan.deleteMesh(thisMesh.mesh.name); + }); + ctrTrNode.meshes = []; + + ctrTrNode.attachMeshNode(this.renderer.id + "_prim_" + nodeCounter++, prims[0]); + ctrTrNode.attachMaterial(materialNodes[0]); + } + + var children = ctrTrNode.children; + for (var i = 1; i < nPrims; i++) + { + // get the next primitive + var prim = prims[i]; + + // get a previously created transform node. If the transform has not been created, create it + var childTrNode; + if (children && children.length >= i) + { + childTrNode = children[i-1].transformNode; + + childTrNode.meshes.forEach(function(thisMesh) { + g_meshMan.deleteMesh(thisMesh.mesh.name); + }); + childTrNode.meshes = []; + } + else + { + childTrNode = createTransformNode("objNode_" + nodeCounter++); + ctrTrNode.insertAsChild(childTrNode); + } + + // attach the instanced box goe + childTrNode.attachMeshNode(this.renderer.id + "_prim_" + nodeCounter++, prim); + childTrNode.attachMaterial(materialNodes[i]); + } +} + +GLWorld.prototype.addObject = function( obj ) +{ + if (!obj) return; + + try + { + // undefine all the links of the object + obj.setChild( undefined ); + obj.setNext( undefined ); + obj.setPrev( undefined ); + obj.setParent( undefined ); + + obj.setWorld( this ); + + // build the WebGL buffers + if (this._useWebGL) + obj.buildBuffers(); + + if (this._geomRoot == null) + { + this._geomRoot = obj; + } + else + { + var go = this._geomRoot; + while (go.getNext()) go = go.getNext(); + go.setNext( obj ); + obj.setPrev( go ); + } + } + catch(e) + { + alert( "Exception in GLWorld.addObject " + e ); + } +} + +//append to the list of objects if obj doesn't already exist +//if obj exists, then don't add to list of objects +GLWorld.prototype.addIfNewObject = function (obj) { + if (!obj) return; + + try { + obj.setWorld(this); + // build the WebGL buffers + if (this._useWebGL) + obj.buildBuffers(); + + if (this._geomRoot == null) { + this._geomRoot = obj; + } + else if (this._geomRoot !== obj) { + var go = this._geomRoot; + while (go.getNext() && go.getNext() !== obj) { + go = go.getNext(); + } + if (go.getNext() === null) { + // undefine all the links of the object + obj.setChild(undefined); + obj.setNext(undefined); + obj.setPrev(undefined); + obj.setParent(undefined); + + go.setNext(obj); + obj.setPrev(go); + } + } + } + catch (e) { + alert("Exception in GLWorld.addIfNewObject " + e); + } +} + +GLWorld.prototype.clearTree = function() +{ + if (this._useWebGL) + { + var root = this._rootNode; + root.children = new Array(); + g_Engine.unregisterCanvas( this._canvas.id ) + + this.update( 0 ); + this.draw(); + } +} + +GLWorld.prototype.updateMaterials = function( obj, time ) +{ + if (!obj) return; + + var matArray = obj.getMaterialArray(); + if (matArray) + { + var n = matArray.length; + for (var i=0; i 0)) + mat = this._matStack[ this._matStack.length-1]; + + return mat; +} + +GLWorld.prototype.popMatrix = function() + { + if (this._matStack.length == 0) + throw "Invalid popMatrix!"; + var mat = this._matStack.pop(); + return mat; +} + + +GLWorld.prototype.setMVMatrix = function() +{ + var mat = this.stackTop(); + if (mat) + { + var gl = this._glContext; + + //var mvMatrix = this._cameraMatInv.multiply(mat); + var mvMatrix = glmat4.multiply( this._cameraMatInv, mat, []); + //var mat2 = mat.multiply( this._cameraMatInv ); + gl.uniformMatrix4fv(this._shaderProgram.mvMatrixUniform, false, new Float32Array(mvMatrix)); + + var normalMatrix = mat3.create(); + //mat4.toInverseMat3(mvMatrix, normalMatrix); +// mat4.toInverseMat3(new Float32Array(mvMatrix.flatten()), normalMatrix); + mat4.toInverseMat3(new Float32Array(mvMatrix), normalMatrix); + mat3.transpose(normalMatrix); + gl.uniformMatrix3fv(this._shaderProgram.nMatrixUniform, false, normalMatrix); + + } +} + + + +GLWorld.prototype.makePerspectiveMatrix = function() +{ + return makePerspective( this.getFOV(), this.getAspect(), this.getZNear(), this.getZFar() ); +} + + +function perspective(fovy, aspect, znear, zfar) +{ + return makePerspective(fovy, aspect, znear, zfar); +} + +GLWorld.prototype.render = function() +{ + if (!this._useWebGL) + { + // clear the context + var ctx = this.get2DContext(); + if (!ctx) return; + ctx.clearRect(0, 0, this.getViewportWidth(), this.getViewportHeight()); + + // render the geometry + var root = this.getGeomRoot(); + this.hRender( root ); + } + else + { + this.draw(); + } +} + +GLWorld.prototype.hRender = function( obj ) +{ + if (!obj) return; + obj.render(); + + this.hRender( obj.getChild() ); + this.hRender( obj.getNext() ); +} + +GLWorld.prototype.setViewportFromCanvas = function(canvas) +{ + this._viewportWidth = canvas.width; + this._viewportHeight = canvas.height; + + if (this._useWebGL) + { + this._glContext.viewportWidth = canvas.width; + this._glContext.viewportHeight = canvas.height; + + this.getCamera().setPerspective(this.getFOV(), this.getAspect(), this.getZNear(), this.getZFar()); + + this.renderer.setViewPort(0, 0, canvas.width, canvas.height); + } +} + +GLWorld.prototype.getShapeFromPoint = function( offsetX, offsetY ) +{ + var x = offsetX/this._canvas.width; + var y = offsetY/this._canvas.height; + + var go = this._geomRoot; + if(go.collidesWithPoint(x,y)) + { + console.log("collision found"); + return go; + } + while (go.getNext()) + { + go = go.getNext(); + if(go.collidesWithPoint(x,y)) + { + console.log("collision found"); + return go; + } + } +} + +GLWorld.prototype.export = function() +{ + var exportStr = "GLWorld 1.0\n"; + exportStr += "id: " + this._canvas.id + "\n"; + exportStr += "fov: " + this._fov + "\n"; + exportStr += "zNear: " + this._zNear + "\n"; + exportStr += "zFar: " + this._zFar + "\n"; + exportStr += "viewDist: " + this._viewDist + "\n"; + + // we need 2 export modes: One for save/restore, one for publish. + // hardcoding for now + var exportForPublish = false; + exportStr += "publish: " + exportForPublish + "\n"; + + if (exportForPublish) + { + exportStr += "scenedata: " + this.myScene.exportJSON() + "endscene\n"; + } + else + { + // output the material library + exportStr += MaterialsLibrary.export(); + + // write out all of the objects + exportStr += "tree\n"; + exportStr += this.exportObjects( this._geomRoot ); + exportStr += "endtree\n"; + } + + return exportStr; +} + +GLWorld.prototype.exportObjects = function( obj ) +{ + if (!obj) return; + + var rtnStr = "OBJECT\n"; + rtnStr += obj.export(); + + if (obj.getChild()) + rtnStr += this.exportObjects( obj.getChild () ); + + // the end object goes outside the children + rtnStr += "ENDOBJECT\n"; + + if (obj.getNext()) + rtnStr += this.exportObjects( obj.getNext() ); + + return rtnStr; +} + +GLWorld.prototype.findTransformNodeByMaterial = function( materialNode, trNode ) +{ + //if (trNode == null) trNode = this._ctrNode; + if (trNode == null) trNode = this._rootNode; + if ( trNode.transformNode && (materialNode == trNode.transformNode.materialNode)) return trNode; + + var rtnNode; + if (trNode.children != null) + { + var nKids = trNode.children.length; + for (var i=0; i= 0) + { + 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 ); + } + else + { + // load the material library + importStr = MaterialsLibrary.import( importStr ); + + // import the objects + this.importObjects( importStr, this._rootNode ); + } +} + +GLWorld.prototype.importObjects = function( importStr, parentNode ) +{ + 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 + this.importObject( importStr, parentNode ); + + // 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, node ); + 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; +} + +GLWorld.prototype.importObject = function( objStr, parentNode ) +{ + var go = new GLGeomObj(); + var type = Number( go.getPropertyFromString( "type: ", objStr ) ); + + var obj; + switch (type) + { + case 1: + obj = new GLRectangle(); + obj.import( objStr ); + break; + + case 2: // circle + obj = new GLCircle(); + obj.import( objStr ); + break; + + case 3: // line - not implemented + default: + throw new Error( "Unrecognized object type: " + type ); + break; + } + + if (obj) + this.addObject( obj ); +} + +GLWorld.prototype.importSubObject = function( objStr, parentNode ) +{ + // get the mesh text + var i0 = objStr.indexOf( "mesh: " ), + i1 = objStr.indexOf( "endMesh\n" ); + if ((i0 < 0) || (i1 < 0)) throw new Error( "ill-formed sub object" ); + i0 += 6; + var meshText = objStr.substr( i0, i1 - i0 ); + var meshObj = JSON.parse(meshText); + + // get the material text + var i0 = objStr.indexOf( "material: " ), + i1 = objStr.indexOf( "endMat\n" ); + if ((i0 < 0) || (i1 < 0)) throw new Error( "ill-formed sub object" ); + i0 += 10; + var matText = objStr.substr( i0, i1 - i0 ); + var shaderDef = JSON.parse( matText ); + var shader = new jshader(); + shader.def = shaderDef; + shader.init(); + + // set the shader for this material + var matNode = createMaterialNode("objMat") + matNode.setShader(shader); + + // create the transformation node + var trNode = createTransformNode("subObjNode_" ); + trNode.attachMeshNode(this.renderer.id + "_prim_", meshObj); + trNode.attachMaterial(matNode); + parentNode.insertAsChild(trNode); + + return trNode; +} + + -- cgit v1.2.3