/* 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.
*/ /* * Creates a unique node id */ nodeIdGen = {}; nodeIdGen.counter = 0; nodeIdGen.getId = function() { return "gen_" + nodeIdGen.counter++; } /* * Constructs a new transform node */ function createTransformNode(nodeName) { node = { 'name': nodeName }; node.transformNodeTemplate = new transformNodeTemplate(node); return node; } /* * Constructs a new material node */ function createMaterialNode(nodeName) { node = { 'name': nodeName }; node.materialNodeTemplate = new materialNodeTemplate(node); return node; } /* * Constructs a new mesh node */ function createMeshNode(nodeName, primitive) { meshNode = { 'mesh':{}, 'meshNodeTemplate':{} }; var renderer = g_Engine.getContext().renderer; if(!primitive.built) { renderer.createPrimitive(primitive); } var model = g_meshMan.getModelByName(nodeName); if(!model) { meshNode.mesh.meshNodeTemplate = new meshNodeTemplate(meshNode.mesh, primitive, nodeName); g_meshMan.modelMap[nodeName] = meshNode.mesh; return meshNode; // --early out-- } else if(!renderer.buffers[model.primitive.buffersID]) { renderer.createPrimitive(model.primitive); } meshNode.mesh.meshNodeTemplate = new meshNodeTemplate(meshNode.mesh, model.primitive, nodeName); return meshNode; } /* * Construct a light node */ function createLightNode(nodeName) { node = { 'name': nodeName }; node.lightNodeTemplate = new lightNodeTemplate(node); return node; } /* * creates a specialized mesh node representing a screen aligned quad with identity transform */ function createScreenQuadNode() { var trNode = createTransformNode(); trNode.attachMeshNode("screenQuad", createScreenAlignedQuad()); return trNode; } function verifyTransformNode( node ) { if(node.transformNodeTemplate == undefined) { node.transformNodeTemplate = new transformNodeTemplate(node); } } function verifyMaterialNode( node ) { if(node.materialNodeTemplate == undefined) { node.materialNodeTemplate = new materialNodeTemplate(node); } } function verifyLightNode( node ) { if(node.lightNodeTemplate == undefined) { node.lightNodeTemplate = new lightNodeTemplate(node); } } /* * Takes an object and attachs transform node * functions and fields if they are not defined */ transformNodeTemplate = function(trNode) { // Lots of checking for things that might exist and adding them when they don't /* ------------------------------------------- */ if(!trNode.children) { trNode.children = []; } if(!trNode.local) { trNode.local = mat4.identity(); } if(!trNode.world) { trNode.world = mat4.identity(); } if(!trNode.id) { trNode.id = nodeIdGen.getId(); } if(!trNode.name) { trNode.name = "xfrmNode" + trNode.id; } if(!trNode.parent) { trNode.parent = null; } if(!trNode.meshes) { trNode.meshes = []; } if(!trNode.nodeType) { trNode.nodeType = rdgeConstants.nodeType.TRNODE; } /* ------------------------------------------- */ // Adding functions to the node none of these exist from export process /* * Attaches a material to a node */ trNode.attachMaterial = function(matNode) { verifyMaterialNode(matNode); this.materialNode = matNode; } /* * @param node - the node to attach, can optionally be a node name paired with a primitive that will be built into a meshNode * @param primitive - an optional parameter that must be supplied if the node is a name and not an object */ trNode.attachMeshNode = function( node, primitive ) { if(typeof node == "string") { node = createMeshNode(node, primitive) } if(trNode.materialNode == undefined) { trNode.materialNode = createMaterialNode(trNode.name + "|defMaterial"); } trNode.meshes.push( {'mesh':{'name':node.mesh.attribs.name, 'id':node.mesh.attribs.id}}); } /* * Inserts a node as a child of this node */ trNode.insertAsChild = function(transNode) { if(this == transNode) return; verifyTransformNode(transNode); transNode.parent = this; this.children.push({transformNode:transNode}); } /* * Inserts a node as the parent of this node */ trNode.insertAsParent = function(transNode) { if(this == transNode) return; verifyTransformNode(transNode); if(this.parent) { // remove this node from current parents list var len = this.parent.children.length; for(var i = 0; i < len; ++i) { if(this.parent.children[i].transformNode != undefined) { tr = this.parent.children[i].transformNode; if(tr.id == this.id) { // removes 1 item starting from i this.parent.children.splice(i,1); break; } } } // set the new parents parent transNode.parent = this.parent; // push passed in node into parents list this.parent.children.push({transformNode:transNode}); // set the passed in node as the current parent this.parent = transNode; } // add this node to the passed in nodes child list transNode.children.push({transformNode:this}); } } // add material handlers to a material node materialNodeTemplate = function(matNode) { // enumerate constants // type definitions TEX_DIF = 0; TEX_SPEC = 1; TEX_NORM = 2; TEX_GLOW = 3; if(!matNode.nodeType) { matNode.nodeType = rdgeConstants.nodeType.MATNODE; } MATERIAL_MAX_LIGHTS = rdgeConstants.MAX_MATERIAL_LIGHTS; if(!matNode.lightChannel) { matNode.lightChannel = [ null, null, null, null ]; } /* * Material categories determine sorting */ if(!matNode.sortCategory) { matNode.sortCategory = rdgeConstants.categoryEnumeration.OPAQUE; } /* * every node has an id either generated by export or generated here */ if(!matNode.id) { matNode.id = nodeIdGen.getId(); } /* * every node has an name either setin art pipeline or generated here */ if(!matNode.name) { matNode.name = "matNode" + matNode.id; } /* * Default list of textures if nothing is set */ if(!matNode.textureList) { var renderer = g_Engine.getContext().renderer; matNode.textureList = [ // {'name':"colMap", 'handle':renderer.getTextureByName("assets/images/white"), 'unit': TEX_DIF, "type":UNIFORMTYPE.TEXTURE2D}, // {'name':"envMap", 'handle':renderer.getTextureByName("assets/images/material_paint"),'unit': TEX_SPEC, "type":UNIFORMTYPE.TEXTURE2D}, // {'name':"normalMap",'handle':renderer.getTextureByName("assets/images/blue"), 'unit': TEX_NORM, "type":UNIFORMTYPE.TEXTURE2D}, // {'name':"glowMap", 'handle':renderer.getTextureByName("assets/images/black"), 'unit': TEX_GLOW, "type":UNIFORMTYPE.TEXTURE2D} ]; } if(!matNode.uniforms) { matNode.uniforms = []; } matNode.setTexture = function(texType, texName) { var renderer = g_Engine.getContext().renderer; this.textureList[texType].handle = renderer.getTextureByName("assets/images/" + texName); this.textureList[texType].unit = texType; this.textureList[texType].type = UNIFORMTYPE.TEXTURE2D; } matNode.setDiffuseTexture = function(texName) { this.setTexture(TEX_DIF, texName); } matNode.setSpecTexture = function(texName) { this.setTexture(TEX_SPEC, texName); } matNode.setNormalTexture = function(texName) { this.setTexture(TEX_NORM, texName); } matNode.setGlowTexture = function(texName) { this.setTexture(TEX_GLOW, texName); } matNode.setUniform = function(name, arrValue) { var len = this.uniforms.length; for(var i = 0; i < len; ++i) { if(this.uniforms[i].name == name) { this.uniforms[i].value = arrValue; return; } } window.console.log("Could not find uniform: " + name); } matNode.setShader = function( jshaderObject ) { this.shaderProgram = jshaderObject; } matNode.setSortCategory = function( materialCat ) { matNode.sortCategory = materialCat; } /* * Sets a light channel reference to a lightNode * @param channelNumber a number indicating whick light to turn on (0 - 3), or an array of numbers if multiple lights being set * @param lightNode - a refernce to a light node object or an array lights */ matNode.enableLightChannel = function( channelNumber, lightNode ) { verifyLightNode(lightNode); // set an array if(typeof channelNumber == "object") { var len = channelNumber.length; var maxLight = lightNode.length != undefined ? lightNode.length : 0; for(var i = 0; i < len; ++i) { matNode.lightChannel[channelNumber] = maxLight > 0 ? lightNode[ Math.min(i, maxLight - 1)] : lightNode; } } else // set an individual light { if(channelNumber < MATERIAL_MAX_LIGHTS) matNode.lightChannel[channelNumber] = lightNode; } } matNode.disableLightChannel = function( channelNumber ) { if(typeof channelNumber != "object") { var len = channelNumber.length; for(var i = 0; i < len; ++i) { if(channelNumber[i] , MATERIAL_MAX_LIGHTS) matNode.lightChannel[channelNumber[i]] = null; } } else { if(channelNumber < MATERIAL_MAX_LIGHTS) matNode.lightChannel[channelNumber] = null; } } matNode.disableAllLights = function() { for(var i = 0; i < MATERIAL_MAX_LIGHTS; ++i) { matNode.lightChannel[i] = null; } } matNode.toJSON = function() { var jsonObj = {'jsonExportName':"materialNode"}; for(var member in this) { jsonObj[member] = this[member]; if(member === "textureList") { var texList = jsonObj[member]; for(var i = 0, len = texList.length; i < len; ++i) { texList[i].handle.image = texList[i].handle.lookUpName; } } else if(member === "shaderProgram") { // test that the shader hasn't already been exported if(typeof jsonObj[member] != "string") { jsonObj[member] = jsonObj[member].exportShader(); } } } return jsonObj; } } meshNodeTemplate = function( meshNode, primitive, meshName ) { if(!primitive.built) { renderer.createPrimitive(primitive); } if(!meshNode.nodeType) { meshNode.nodeType = rdgeConstants.nodeType.MESHNODE; } if(!meshNode.attribs) { var newID = nodeIdGen.getId(); meshNode.attribs = { 'id': newID, 'indexCount': primitive.indexCount, 'name': meshName, 'vertCount': primitive.posCount}; meshNode.name = meshName; } if(!meshNode.bbox) { meshNode.bbox = new box(); } meshNode.data = null; meshNode.primitive = primitive; // setup bounding box var numPositions = primitive.posCount; if(numPositions > 0) { var positions = primitive.positions; var idx = 0; while (idx < numPositions - 2) { var thisPos = [positions[idx+0], positions[idx+1], positions[idx+2]]; meshNode.bbox.addVec3(thisPos); idx += 3; } } else { window.console.error("mesh " + meshNode.attribs.name + ": bounding volume not created"); } } lightNodeTemplate = function(lightNode) { if(!lightNode.nodeType) { lightNode.nodeType = rdgeConstants.nodeType.LIGHTNODE; } if(!lightNode.id) { lightNode.id = nodeIdGen.getId(); } if(!lightNode.name) { lightNode.name = "light_" + lightNode.id; } if(!lightNode.typeName) { lightNode.typeName = "dir_light"; } if(!lightNode.castShadow) { lightNode.castShadow = false; } if(!lightNode.depthMapBias) { lightNode.depthMapBias = 0.0179; } if(!lightNode.depthMapSize) { lightNode.depthMapSize = 1024; } if(!lightNode.coneAngle) { lightNode.coneAngle = 0.707; } if(!lightNode.penumbraAngle) { lightNode.coneAngle = 0.0; } if(!lightNode.dropOff) { lightNode.coneAngle = 0.025; } if(!lightNode.color) { lightNode.color = [1,1,1,1]; } if(!lightNode.dir) { lightNode.dir = [1,-1,1]; } if(!lightNode.links) { lightNode.links = []; } if(!lightNode.position) { lightNode.position = [0,0,0]; } if(!lightNode.lightDiffuse) { lightNode.lightDiffuse = [1,1,1,1]; } if(!lightNode.lightAmbient) { lightNode.lightAmbient = [0.5,0.5,0.5,1.0]; } if(!lightNode.lightSpecular) { lightNode.lightSpecular = [1,1,1,1]; } lightNode.setPosition = function( pos ) { for(var i = 0; i < 3; i++) { this.position[i] = pos[i]; } } lightNode.setDiffuseColor = function( color ) { for(var i = 0; i < 4; i++) { this.lightDiffuse[i] = color[i]; } } lightNode.setAmbientColor = function( color ) { for(var i = 0; i < 4; i++) { this.lightAmbient[i] = color[i]; } } lightNode.setSpecularColor = function( color ) { for(var i = 0; i < 4; i++) { this.lightSpecular[i] = color[i]; } } }