/* <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; var ShapePrimitive = require("js/lib/geom/shape-primitive").ShapePrimitive; var MaterialsModel = require("js/models/materials-model").MaterialsModel; /////////////////////////////////////////////////////////////////////// // Class GLLine // GL representation of a line. // Derived from class GeomObj /////////////////////////////////////////////////////////////////////// exports.Line = Object.create(GeomObj, { /////////////////////////////////////////////////////////////////////// // Instance variables /////////////////////////////////////////////////////////////////////// _width: { value : 2.0, writable: true }, _height: { value : 2.0, writable: true }, _xOffset: { value : 0, writable: true }, _yOffset: { value : 0, writable: true }, // If line doesn't fit in canvas world, we had to grow the canvas by this much on either side _xAdj: { value : 0, writable: true }, _yAdj: { value : 0, writable: true }, _slope: { value : 0, writable: true }, _strokeWidth: { value : 0.25, writable: true }, _strokeStyle: { value : "Solid", writable: true }, _scaleX: { value : 1.0, writable: true }, _scaleY: { value : 1.0, writable: true }, canFill: { value : false, writable: false }, init: { value: function(world, xOffset, yOffset, width, height, slope, strokeSize, strokeColor, strokeMaterial, strokeStyle, xAdj, yAdj) { if (arguments.length > 0) { this._width = width; this._height = height; this._xOffset = xOffset; this._yOffset = yOffset; this._xAdj = xAdj; this._yAdj = yAdj; this._slope = slope; this._strokeWidth = strokeSize; this._strokeColor = strokeColor; this._strokeStyle = strokeStyle; this._scaleX = (world.getViewportWidth())/(world.getViewportHeight()); } this._strokeVerticesLen = 0; this.m_world = world; this._materialAmbient = [0.2, 0.2, 0.2, 1.0]; this._materialDiffuse = [0.4, 0.4, 0.4, 1.0]; this._materialSpecular = [0.4, 0.4, 0.4, 1.0]; if(strokeMaterial) { this._strokeMaterial = strokeMaterial; if (strokeColor && this._strokeMaterial.hasProperty( "color" )) this._strokeMaterial.setProperty( "color", this._strokeColor ); } } }, //////////////////////////////////////////////////////////////////////// // Property Accessors /////////////////////////////////////////////////////////////////////// // TODO - Use getters/setters in the future getStrokeWidth: { value: function() { return this._strokeWidth; } }, setStrokeWidth: { value: function(w) { this._strokeWidth = w; } }, getStrokeMaterial: { value: function() { return this._strokeMaterial; } }, setStrokeMaterial: { value: function(m) { this._strokeMaterial = m; } }, getFillMaterial: { value: function() { return null; } }, getStrokeColor: { value: function() { return this._strokeColor; } }, // setStrokeColor: { // value: function(c) { // this._strokeColor = c; // } // }, getStrokeStyle: { value: function() { return this._strokeStyle; } }, setStrokeStyle: { value: function(s) { this._strokeStyle = s; } }, getWidth: { value: function() { return this._width; } }, setWidth: { value: function(w) { this._width = w; } }, getHeight: { value: function() { return this._height; } }, setHeight: { value: function(h) { this._height = h; } }, getXAdj: { value: function() { return this._xAdj; } }, setXAdj: { value: function(x) { this._xAdj = x; } }, getYAdj: { value: function() { return this._yAdj; } }, setYAdj: { value: function(y) { this._yAdj = y; } }, getSlope: { value: function() { return this._slope; } }, setSlope: { value: function(m) { this._slope = m; } }, geomType: { value: function() { return this.GEOM_TYPE_LINE; } }, /////////////////////////////////////////////////////////////////////// // Methods /////////////////////////////////////////////////////////////////////// exportJSON: { value: function() { var jObj = { 'type' : this.geomType(), 'xoff' : this._xOffset, 'yoff' : this._yOffset, 'width' : this._width, 'height' : this._height, 'xAdj' : this._xAdj, 'yAdj' : this._yAdj, 'slope' : this._slope, 'strokeWidth' : this._strokeWidth, 'strokeColor' : this._strokeColor, 'strokeStyle' : this._strokeStyle, 'strokeMat' : this._strokeMaterial ? this._strokeMaterial.getName() : MaterialsModel.getDefaultMaterialName(), 'materials' : this.exportMaterialsJSON() }; return jObj; } }, importJSON: { value: function(jObj) { this._xOffset = jObj.xoff; this._yOffset = jObj.yoff; this._width = jObj.width; this._height = jObj.height; this._xAdj = jObj.xAdj; this._yAdj = jObj.yAdj; this._strokeWidth = jObj.strokeWidth; this._slope = jObj.slope; this._strokeStyle = jObj.strokeStyle; this._strokeColor = jObj.strokeColor; var strokeMaterialName = jObj.strokeMat; var strokeMat = MaterialsModel.getMaterial( strokeMaterialName ); if (!strokeMat) { console.log( "object material not found in library: " + strokeMaterialName ); strokeMat = MaterialsModel.getMaterial( MaterialsModel.getDefaultMaterialName() ); } this._strokeMaterial = strokeMat; this.importMaterialsJSON( jObj.materials ); } }, buildBuffers: { value: function() { // get the world var world = this.getWorld(); if (!world) throw( "null world in buildBuffers" ); if (!world._useWebGL) return; // make sure RDGE has the correct context RDGE.globals.engine.setContext( world.getCanvas().rdgeid ); // create the gl buffer var gl = world.getGLContext(); this._strokeVerticesLen = 0; var strokeVertices = []; var strokeTextures = []; var strokeNormals = []; var strokeColors = []; // var scaleMat = Matrix.I(3); // scaleMat.elements[0][0] = this._scaleX; // scaleMat.elements[1][1] = this._scaleY; // get the normalized device coordinates (NDC) for // all position and dimensions. var vpw = world.getViewportWidth(), vph = world.getViewportHeight(); var xNDC = 2*this._xOffset/vpw, yNDC = 2*this._yOffset/vph, xFillNDC = this._width/vpw, yFillNDC = this._height/vph, xAdjNDC = this._xAdj/vpw, yAdjNDC = this._yAdj/vph, xStrokeNDC = this._strokeWidth/vpw, yStrokeNDC = this._strokeWidth/vph; var aspect = world.getAspect(); var zn = world.getZNear(), zf = world.getZFar(); var t = zn * Math.tan(world.getFOV() * Math.PI / 360.0), b = -t, r = aspect*t, l = -r; // calculate the object coordinates from their NDC coordinates var z = -world.getViewDistance(); // get the position of the origin var x = -z*(r-l)/(2.0*zn)*xNDC, y = -z*(t-b)/(2.0*zn)*yNDC; // get the x and y fill var xFill = -z*(r-l)/(2.0*zn)*xFillNDC, yFill = -z*(t-b)/(2.0*zn)*yFillNDC; // get the x & y stroke size var xStroke = -z*(r-l)/(2.0*zn)*xStrokeNDC, yStroke = -z*(t-b)/(2.0*zn)*yStrokeNDC; // get the x & y adjustments size var xAdj = -z*(r-l)/(2.0*zn)*xAdjNDC*2, yAdj = -z*(t-b)/(2.0*zn)*yAdjNDC*2; this._primArray = []; this._materialArray = []; this._materialTypeArray = []; this._materialNodeArray = []; this._scaleX = (world._viewportWidth)/(world._viewportHeight); var innerX = xFill-xStroke; var innerY = yFill-yStroke; if(this._slope === "vertical") { strokeVertices = [ -xFill+x, yFill+y, 0.0, xFill+x, yFill+y, 0.0, -xFill+x, -yFill+y, 0.0, xFill+x, -yFill+y, 0.0, -xFill+x, -yFill+y, 0.0, xFill+x, yFill+y, 0.0 ]; strokeTextures = [ 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1 ]; } else if(this._slope === "horizontal") { // right now, this is the same as vertical line because, // our canvas is the same size as us. // But, we will need to use this when drawing in an existing GLWorld with other shapes strokeVertices = [ -xFill+x, yFill+y, 0.0, xFill+x, yFill+y, 0.0, -xFill+x, -yFill+y, 0.0, xFill+x, -yFill+y, 0.0, -xFill+x, -yFill+y, 0.0, xFill+x, yFill+y, 0.0 ]; strokeTextures = [ 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1 ]; } else if(this._slope > 0) { // if slope is positive, draw a line from top-left to bottom-right strokeVertices = [ -xFill+x, yFill-2*yAdj+y, 0.0, -xFill+2*xAdj+x, yFill+y, 0.0, xFill-2*xAdj+x, -yFill+y, 0.0, xFill+x, -yFill+2*yAdj+y, 0.0, xFill-2*xAdj+x, -yFill+y, 0.0, -xFill+2*xAdj+x, yFill+y, 0.0 ]; strokeTextures = [ 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1 ]; } else { // else slope is negative, draw a line from bottom-left to top-right strokeVertices = [ xFill-2*xAdj+x, yFill+y, 0.0, -xFill+2*xAdj+x, -yFill+y, 0.0, -xFill+x, -yFill+2*yAdj+y, 0.0, -xFill+2*xAdj+x, -yFill+y, 0.0, xFill-2*xAdj+x, yFill+y, 0.0, xFill+x, yFill-2*yAdj+y, 0.0 ]; strokeTextures = [ 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0 ]; } var z = 0; var indices = []; var nVerts = strokeVertices.length/3; // stroke normals var index = 0; for (var i=0; i<nVerts; i++) { // push a normal for each vertex in the stroke strokeNormals.push(0.0); strokeNormals.push(0.0); strokeNormals.push(1); indices.push( index ); index++; } var prim = ShapePrimitive.create(strokeVertices, strokeNormals, strokeTextures, indices, RDGE.globals.engine.getContext().renderer.TRIANGLES, indices.length); var strokeMaterial = this.makeStrokeMaterial(); this._primArray.push( prim ); this._materialNodeArray.push( strokeMaterial.getMaterialNode() ); world.updateObject(this); } }, render: { value: function() { // get the world var world = this.getWorld(); if (!world) throw( "null world in rectangle render" ); // get the context var ctx = world.get2DContext(); if (!ctx) return; // set up the stroke style var lineWidth = this._strokeWidth, w = this._width, h = this._height; var c, gradient, colors, len, n, position, cs; ctx.beginPath(); ctx.lineWidth = lineWidth; if (this._strokeColor) { if(this._strokeColor.gradientMode) { if(this._strokeColor.gradientMode === "radial") { gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(w/2, h/2)); } else { gradient = ctx.createLinearGradient(0, h/2, w, h/2); } colors = this._strokeColor.color; len = colors.length; for(n=0; n<len; n++) { position = colors[n].position/100; cs = colors[n].value; gradient.addColorStop(position, "rgba(" + cs.r + "," + cs.g + "," + cs.b + "," + cs.a + ")"); } ctx.strokeStyle = gradient; } else { c = "rgba(" + 255*this._strokeColor[0] + "," + 255*this._strokeColor[1] + "," + 255*this._strokeColor[2] + "," + this._strokeColor[3] + ")"; ctx.strokeStyle = c; } // get the points var p0, p1; if(this._slope === "vertical") { p0 = [0.5*w, 0]; p1 = [0.5*w, h]; } else if(this._slope === "horizontal") { p0 = [0, 0.5*h]; p1 = [w, 0.5*h]; } else if(this._slope > 0) { p0 = [this._xAdj, this._yAdj]; p1 = [w - this._xAdj, h - this._yAdj]; } else { p0 = [this._xAdj, h - this._yAdj]; p1 = [w - this._xAdj, this._yAdj]; } // draw the line ctx.moveTo( p0[0], p0[1] ); ctx.lineTo( p1[0], p1[1] ); ctx.stroke(); } } }, collidesWithPoint: { value: function(x, y) { if(x < this._xOffset) return false; if(x > (this._xOffset + this._width)) return false; if(y < this._yOffset) return false; if(y > (this._yOffset + this._height)) return false; return true; } } });