/* <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> */ /////////////////////////////////////////////////////////////////////// // Class GLPath // GL representation of a path. // Derived from class GLGeomObj // The position and dimensions of the stroke, fill, and inner Radius should be in pixels /////////////////////////////////////////////////////////////////////// function GLPath() { // initialize the inherited members this.inheritedFrom = GLGeomObj; this.inheritedFrom(); this.init = function( world, dataArray, typeArray, strokeWidth, strokeColor, strokeMaterial ) { /////////////////////////////////////////////////////////////////////// // Instance variables /////////////////////////////////////////////////////////////////////// // stroke this._strokeWidth = 0.25; this._strokeColor = strokeColor; this._strokeMaterial = strokeMaterial; // data this._dataArray = dataArray.slice(0); this._typeArray = typeArray.slice(0); this._world = world; } /////////////////////////////////////////////////////////////////////// // Property Accessors /////////////////////////////////////////////////////////////////////// this.getStrokeWidth = function() { return this._strokeWidth; } this.setStrokeWidth = function(w) { this._strokeWidth = w; } this.getStrokeMaterial = function() { return this._strokeMaterial; } this.setStrokeMaterial = function(m) { this._strokeMaterial = m; } this.getWorld = function() { return this._world; } this.setWorld = function(w) { this._world = w; } this.geomType = function() { return this.GEOM_TYPE_PATH; } /////////////////////////////////////////////////////////////////////// // Methods /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // update the "color of the material this.getStrokeColor = function() { return this._strokeColor; } // this.setStrokeColor = function(c) // { // this._strokeColor = c; // } /////////////////////////////////////////////////////////////////////// this.buildBuffers = function() { // currently no GL representation } this.render = function() { // get the world var world = this.getWorld(); if (!world) throw( "null world in buildBuffers" ); // get the context var ctx = world.get2DContext(); if (!ctx) return; // create the matrix var lineWidth = this._strokeWidth; // set up the stroke style ctx.beginPath(); ctx.lineWidth = lineWidth; ctx.strokeStyle = "#0000ff"; if (this._strokeColor) ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor ); // declarations var pt, p0, p1, p2; // draw the stroke var index = 0; var dataIndex = 0; var n = this._typeArray.length; while (index < n) { var type = this._typeArray[index]; index++; switch (type) { case 0: // moveTo pt = this._dataArray[dataIndex]; dataIndex++; ctx.moveTo( pt[0], pt[1] ); break; case 1: // line pt = this._dataArray[dataIndex]; dataIndex++; ctx.lineTo( pt[0], pt[1] ); break; case 2: // quadratic Bezier p0 = this._dataArray[dataIndex]; dataIndex++; p1 = this._dataArray[dataIndex]; dataIndex++; ctx.quadraticCurveTo( p0[0], p0[1], p1[0], p1[1] ); break; case 3: // cubic Bezier p0 = this._dataArray[dataIndex]; dataIndex++; p1 = this._dataArray[dataIndex]; dataIndex++; p2 = this._dataArray[dataIndex]; dataIndex++; ctx.bezierCurveTo( p0[0], p0[1], p1[0], p1[1], p2[0], p2[1] ); break; default: console.log( "unsupported path type: " + type ); break; } } // render the stroke ctx.stroke(); } this.export = function() { var rtnStr = "type: " + this.geomType() + "\n"; rtnStr += "strokeWidth: " + this._strokeWidth + "\n"; rtnStr += "strokeMat: "; if (this._strokeMaterial) rtnStr += this._strokeMaterial.getName(); else rtnStr += "flatMaterial"; rtnStr += "\n"; return rtnStr; } this.import = function( importStr ) { this._strokeWidth = this.getPropertyFromString( "strokeWidth: ", importStr ); var strokeMaterialName = this.getPropertyFromString( "strokeMat: ", importStr ); var strokeMat = MaterialsLibrary.getMaterial( strokeMaterialName ); if (!strokeMat) { console.log( "object material not found in library: " + strokeMaterialName ); strokeMat = new FlatMaterial(); } this._strokeMaterial = strokeMat; } this.collidesWithPoint = function( x, y ) { return false; } this.containsPoint = function( pt, dir ) { return false; } this.getNearPoint = function( pt, dir ) { var world = this.getWorld(); if (!world) throw( "null world in getNearPoint" ); // get a point on the plane of the circle // the point is in NDC, as is the input parameters var mat = this.getMatrix(); var plane = [0,0,1,0]; plane = MathUtils.transformPlane( plane, mat ); var projPt = MathUtils.vecIntersectPlane ( pt, dir, plane ); // transform the projected point back to the XY plane //var invMat = mat.inverse(); var invMat = glmat4.inverse( mat, [] ); var planePt = MathUtils.transformPoint( projPt, invMat ); // get the normalized device coordinates (NDC) for // the position and radii. var vpw = world.getViewportWidth(), vph = world.getViewportHeight(); var xNDC = 2*this._xOffset/vpw, yNDC = 2*this._yOffset/vph; var projMat = world.makePerspectiveMatrix(); var z = -world.getViewDistance(); var planePtNDC = planePt.slice(0); planePtNDC[2] = z; planePtNDC = MathUtils.transformHomogeneousPoint( planePtNDC, projMat ); planePtNDC = MathUtils.applyHomogeneousCoordinate( planePtNDC ); // get the gl coordinates 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; // convert to GL coordinates var objPt = [0, 0, 0]; objPt[0] = -z*(r-l)/(2.0*zn)*objPt[0]; objPt[1] = -z*(t-b)/(2.0*zn)*objPt[1]; // re-apply the transform objPt = MathUtils.transformPoint( objPt, mat ); return objPt; } }