/* 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.
*/ // RDGE namespaces var RDGE = RDGE || {}; /* * Creates a unique node id */ RDGE.nodeIdGen = {}; RDGE.nodeIdGen.counter = 0; RDGE.nodeIdGen.getId = function () { return "gen_" + RDGE.nodeIdGen.counter++; }; /* * Constructs a new transform node */ RDGE.createTransformNode = function (nodeName) { node = { 'name': nodeName }; node.transformNodeTemplate = new RDGE.transformNodeTemplate(node); return node; }; /* * Constructs a new material node */ RDGE.createMaterialNode = function (nodeName) { node = { 'name': nodeName }; node.materialNodeTemplate = new RDGE.materialNodeTemplate(node); return node; }; /* * Constructs a new mesh node */ RDGE.createMeshNode = function (nodeName, primitive) { meshNode = { 'mesh':{}, 'meshNodeTemplate':{} }; var renderer = RDGE.globals.engine.getContext().renderer; if (!primitive.built) { renderer.createPrimitive(primitive); } var model = RDGE.globals.meshMan.getModelByName(nodeName); if (!model) { meshNode.mesh.meshNodeTemplate = new RDGE.meshNodeTemplate(meshNode.mesh, primitive, nodeName); RDGE.globals.meshMan.modelMap[nodeName] = meshNode.mesh; return meshNode; // --early out-- } else if (!renderer.buffers[model.primitive.buffersID]) { renderer.createPrimitive(model.primitive); } meshNode.mesh.meshNodeTemplate = new RDGE.meshNodeTemplate(meshNode.mesh, model.primitive, nodeName); return meshNode; }; /* * Construct a light node */ RDGE.createLightNode = function (nodeName) { node = { 'name': nodeName }; node.lightNodeTemplate = new RDGE.lightNodeTemplate(node); return node; }; /* * creates a specialized mesh node representing a screen aligned quad with identity transform */ RDGE.createScreenQuadNode = function () { var trNode = RDGE.createTransformNode(); trNode.attachMeshNode("screenQuad", RDGE.renderUtils.createScreenAlignedQuad()); return trNode; }; RDGE.verifyTransformNode = function (node) { if (node.transformNodeTemplate == undefined) { node.transformNodeTemplate = new RDGE.transformNodeTemplate(node); } }; RDGE.verifyMaterialNode = function (node) { if (node.materialNodeTemplate == undefined) { node.materialNodeTemplate = new RDGE.materialNodeTemplate(node); } }; RDGE.verifyLightNode = function (node) { if (node.lightNodeTemplate == undefined) { node.lightNodeTemplate = new RDGE.lightNodeTemplate(node); } }; /* * Takes an object and attaches transform node * functions and fields if they are not defined */ RDGE.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 = RDGE.mat4.identity(); } if (!trNode.world) { trNode.world = RDGE.mat4.identity(); } if (!trNode.id) { trNode.id = RDGE.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 = RDGE.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) { RDGE.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 = RDGE.createMeshNode(node, primitive) } if (trNode.materialNode == undefined) { trNode.materialNode = RDGE.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; RDGE.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; RDGE.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 RDGE.materialNodeTemplate = function (matNode) { // enumerate constants // type definitions TEX_DIF = 0; TEX_SPEC = 1; TEX_NORM = 2; TEX_GLOW = 3; if (!matNode.nodeType) { matNode.nodeType = RDGE.rdgeConstants.nodeType.MATNODE; } MATERIAL_MAX_LIGHTS = RDGE.rdgeConstants.MAX_MATERIAL_LIGHTS; if (!matNode.lightChannel) { matNode.lightChannel = [ null, null, null, null ]; } /* * Material categories determine sorting */ if (!matNode.sortCategory) { matNode.sortCategory = RDGE.rdgeConstants.categoryEnumeration.OPAQUE; } /* * every node has an id either generated by export or generated here */ if (!matNode.id) { matNode.id = RDGE.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 = RDGE.globals.engine.getContext().renderer; matNode.textureList = [ // {'name':"colMap", 'handle':renderer.getTextureByName("assets/images/white"), 'unit': TEX_DIF, "type":RDGE.UNIFORMTYPE.TEXTURE2D}, // {'name':"envMap", 'handle':renderer.getTextureByName("assets/images/material_paint"),'unit': TEX_SPEC, "type":RDGE.UNIFORMTYPE.TEXTURE2D}, // {'name':"normalMap",'handle':renderer.getTextureByName("assets/images/blue"), 'unit': TEX_NORM, "type":RDGE.UNIFORMTYPE.TEXTURE2D}, // {'name':"glowMap", 'handle':renderer.getTextureByName("assets/images/black"), 'unit': TEX_GLOW, "type":RDGE.UNIFORMTYPE.TEXTURE2D} ]; } if (!matNode.uniforms) { matNode.uniforms = []; } matNode.setTexture = function (texType, texName) { var renderer = RDGE.globals.engine.getContext().renderer; this.textureList[texType].handle = renderer.getTextureByName("assets/images/" + texName); this.textureList[texType].handle = renderer.getTextureByName(RDGE.globals.engine._assetPath+"/images/" + texName); this.textureList[texType].unit = texType; this.textureList[texType].type = RDGE.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) { RDGE.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; }; }; RDGE.meshNodeTemplate = function (meshNode, primitive, meshName) { if (!primitive.built) { renderer.createPrimitive(primitive); } if (!meshNode.nodeType) { meshNode.nodeType = RDGE.rdgeConstants.nodeType.MESHNODE; } if (!meshNode.attribs) { var newID = RDGE.nodeIdGen.getId(); meshNode.attribs = { 'id': newID, 'indexCount': primitive.indexCount, 'name': meshName, 'vertCount': primitive.posCount }; meshNode.name = meshName; } if (!meshNode.bbox) { meshNode.bbox = new RDGE.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"); } } RDGE.lightNodeTemplate = function (lightNode) { if (!lightNode.nodeType) { lightNode.nodeType = RDGE.rdgeConstants.nodeType.LIGHTNODE; } if (!lightNode.id) { lightNode.id = RDGE.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]; } } };