/*
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.
*/
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 GLRectangle
// GL representation of a rectangle.
// Derived from class GeomObj
///////////////////////////////////////////////////////////////////////
var Rectangle = function GLRectangle()
{
if (!MaterialsModel)
MaterialsModel = require("js/models/materials-model").MaterialsModel;
// CONSTANTS
this.N_TRIANGLES = 15;
///////////////////////////////////////////////////////////////////////
// Instance variables
///////////////////////////////////////////////////////////////////////
this._width = 2.0;
this._height = 2.0;
this._xOffset = 0;
this._yOffset = 0;
this._tlRadius = 0;
this._trRadius = 0;
this._blRadius = 0;
this._brRadius = 0;
this._strokeWidth = 0.25;
this._strokeStyle = "Solid";
this.init = function(world, xOffset, yOffset, width, height, strokeSize, strokeColor, fillColor,
tlRadius, trRadius, blRadius, brRadius, strokeMaterial, fillMaterial, strokeStyle) {
this.m_world = world;
if (arguments.length > 0) {
this._width = width;
this._height = height;
this._xOffset = xOffset;
this._yOffset = yOffset;
this._strokeWidth = strokeSize;
this._strokeColor = strokeColor;
this._fillColor = fillColor;
this.setTLRadius(tlRadius);
this.setTRRadius(trRadius);
this.setBLRadius(blRadius);
this.setBRRadius(brRadius);
this._strokeStyle = strokeStyle;
}
// the overall radius includes the fill and the stroke. separate the two based onthe stroke width
// this._fillRad = this._radius - this._strokeWidth;
// var err = 0.05;
var err = 0;
this._fillWidth = this._width - this._strokeWidth + err;
this._fillHeight = this._height - this._strokeWidth + err;
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;
} else {
this._strokeMaterial = MaterialsModel.getMaterial( MaterialsModel.getDefaultMaterialName() );
}
if(fillMaterial) {
this._fillMaterial = fillMaterial;
} else {
this._fillMaterial = MaterialsModel.getMaterial( MaterialsModel.getDefaultMaterialName() );
}
};
///////////////////////////////////////////////////////////////////////
// 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.getFillMaterial = function() {
return this._fillMaterial;
};
this.setFillMaterial = function(m) {
this._fillMaterial = m;
};
this.getStrokeColor = function() {
return this._strokeColor;
};
//this.setStrokeColor = function(c) {
// this._strokeColor = c;
// };
this.getFillColor = function() {
return this._fillColor;
};
//this.setFillColor = function(c) {
// this._fillColor = c.slice(0);
// };
this.getTLRadius = function() {
return this._tlRadius;
};
this.setTLRadius = function(r) {
this._tlRadius = Math.min(r, (this._height - this._strokeWidth)/2, (this._width - this._strokeWidth)/2);
};
this.getTRRadius = function() {
return this._trRadius;
};
this.setTRRadius = function(r) {
this._trRadius = Math.min(r, (this._height - this._strokeWidth)/2, (this._width - this._strokeWidth)/2);
};
this.getBLRadius = function() {
return this._blRadius;
};
this.setBLRadius = function(r) {
this._blRadius = Math.min(r, (this._height - this._strokeWidth)/2, (this._width - this._strokeWidth)/2);
};
this.getBRRadius = function() {
return this._brRadius;
};
this.setBRRadius = function(r) {
this._brRadius = Math.min(r, (this._height - this._strokeWidth)/2, (this._width - this._strokeWidth)/2);
};
this.getStrokeStyle = function() {
return this._strokeStyle;
};
this.setStrokeStyle = function(s) {
this._strokeStyle = s;
};
this.getWidth = function() {
return this._width;
};
this.setWidth = function(w) {
this._width = w;
};
this.getHeight = function() {
return this._height;
};
this.setHeight = function(h) {
this._height = h;
};
this.geomType = function() {
return this.GEOM_TYPE_RECTANGLE;
};
///////////////////////////////////////////////////////////////////////
// Methods
///////////////////////////////////////////////////////////////////////
// JSON export
this.exportJSON = function()
{
var jObj =
{
'type' : this.geomType(),
'xoff' : this._xOffset,
'yoff' : this._yOffset,
'width' : this._width,
'height' : this._height,
'strokeWidth' : this._strokeWidth,
'strokeColor' : this._strokeColor,
'fillColor' : this._fillColor,
'tlRadius' : this._tlRadius,
'trRadius' : this._trRadius,
'blRadius' : this._blRadius,
'brRadius' : this._brRadius,
'innerRadius' : this._innerRadius,
'strokeStyle' : this._strokeStyle,
'strokeMat' : this._strokeMaterial ? this._strokeMaterial.getName() : MaterialsModel.getDefaultMaterialName(),
'fillMat' : this._fillMaterial ? this._fillMaterial.getName() : MaterialsModel.getDefaultMaterialName(),
'materials' : this.exportMaterialsJSON()
};
return jObj;
};
this.importJSON = function( jObj )
{
this._xOffset = jObj.xoff;
this._yOffset = jObj.yoff;
this._width = jObj.width;
this._height = jObj.height;
this._strokeWidth = jObj.strokeWidth;
this._strokeColor = jObj.strokeColor;
this._fillColor = jObj.fillColor;
this._tlRadius = jObj.tlRadius;
this._trRadius = jObj.trRadius;
this._blRadius = jObj.blRadius;
this._brRadius = jObj.brRadius;
this._innerRadius = jObj.innerRadius;
this._strokeStyle = jObj.strokeStyle;
var strokeMaterialName = jObj.strokeMat;
var fillMaterialName = jObj.fillMat;
var strokeMat = MaterialsModel.getMaterial( strokeMaterialName );
if (!strokeMat) {
console.log( "object material not found in library: " + strokeMaterialName );
strokeMat = MaterialsModel.getMaterial( MaterialsModel.getDefaultMaterialName() );
}
this._strokeMaterial = strokeMat;
var fillMat = MaterialsModel.getMaterial( fillMaterialName );
if (!fillMat) {
console.log( "object material not found in library: " + fillMaterialName );
fillMat = MaterialsModel.getMaterial( MaterialsModel.getDefaultMaterialName() );
}
this._fillMaterial = fillMat;
this.importMaterialsJSON( jObj.materials );
};
this.buildBuffers = function() {
// get the world
var world = this.getWorld();
if (!world) throw( "null world in buildBuffers" );
//console.log( "GLRectangle.buildBuffers " + world._worldCount );
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();
var tlRadius = this._tlRadius; //top-left radius
var trRadius = this._trRadius;
var blRadius = this._blRadius;
var brRadius = this._brRadius;
// declare the arrays to hold the parts
this._primArray = [];
this._materialArray = [];
this._materialTypeArray = [];
this._materialNodeArray = [];
// 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,
strokeSizeNDC = 2*this._strokeWidth/vpw,
tlRadiusNDC = 2*tlRadius/vpw, yTLRadiusNDC = 2*tlRadius/vph,
trRadiusNDC = 2*trRadius/vpw, yTRRadiusNDC = 2*trRadius/vph,
blRadiusNDC = 2*blRadius/vpw, yBLRadiusNDC = 2*blRadius/vph,
brRadiusNDC = 2*brRadius/vpw, yBRRadiusNDC = 2*brRadius/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;
// keep some variables giving the overall dimensions of the
// rectangle. These values are used to calculate consistent
// texture map coordinates across all pieces.
this._rectWidth = xFill; this._rectHeight = yFill;
// get the stroke size
var strokeSize = -z*(r-l)/(2.0*zn)*strokeSizeNDC;
// get the absolute corner radii
tlRadius = -z*(r-l)/(2.0*zn)*tlRadiusNDC,
trRadius = -z*(r-l)/(2.0*zn)*trRadiusNDC,
blRadius = -z*(r-l)/(2.0*zn)*blRadiusNDC,
brRadius = -z*(r-l)/(2.0*zn)*brRadiusNDC;
// stroke
var strokeMaterial = this.makeStrokeMaterial();
var strokePrim = this.createStroke([x,y], 2*xFill, 2*yFill, strokeSize, tlRadius, blRadius, brRadius, trRadius, strokeMaterial);
this._primArray.push( strokePrim );
this._materialNodeArray.push( strokeMaterial.getMaterialNode() );
// fill
tlRadius -= strokeSize; if (tlRadius < 0) tlRadius = 0.0;
blRadius -= strokeSize; if (blRadius < 0) blRadius = 0.0;
brRadius -= strokeSize; if (brRadius < 0) brRadius = 0.0;
trRadius -= strokeSize; if (trRadius < 0) trRadius = 0.0;
xFill -= strokeSize;
yFill -= strokeSize;
var fillMaterial = this.makeFillMaterial();
//console.log( "fillMaterial: " + fillMaterial.getName() );
var fillPrim = this.createFill([x,y], 2*xFill, 2*yFill, tlRadius, blRadius, brRadius, trRadius, fillMaterial);
this._primArray.push( fillPrim );
this._materialNodeArray.push( fillMaterial.getMaterialNode() );
world.updateObject(this);
};
this.renderQuadraticBezier = function( bPts, ctx ) {
if (!bPts) return;
var nSegs = (bPts.length - 1)/2.0;
if (nSegs <= 0) return;
var index = 1;
for (var i=0; i 0) {
ctx.quadraticCurveTo( inset, height-inset, inset+rad, height-inset );
}
// do the bottom of the rectangle
pt = [width - inset, height - inset];
rad = brRad - inset;
if (rad < 0) rad = 0;
pt[0] -= rad;
ctx.lineTo( pt[0], pt[1] );
// get the bottom right arc
if (MathUtils.fpSign(rad) > 0) {
ctx.quadraticCurveTo( width-inset, height-inset, width-inset, height-inset-rad );
}
// get the right of the rectangle
pt = [width - inset, inset];
rad = trRad - inset;
if (rad < 0) rad = 0;
pt[1] += rad;
ctx.lineTo( pt[0], pt[1] );
// do the top right corner
if (MathUtils.fpSign(rad) > 0) {
ctx.quadraticCurveTo( width-inset, inset, width-inset-rad, inset );
}
// do the top of the rectangle
pt = [inset, inset];
rad = tlRad - inset;
if (rad < 0) rad = 0;
pt[0] += rad;
ctx.lineTo( pt[0], pt[1] );
// do the top left corner
if (MathUtils.fpSign(rad) > 0) {
ctx.quadraticCurveTo( inset, inset, inset, inset+rad );
} else {
ctx.lineTo( inset, 2*inset );
}
}
};
this.render = 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;
// get some dimensions
var lw = this._strokeWidth;
var w = world.getViewportWidth(),
h = world.getViewportHeight();
var c,
inset,
gradient,
colors,
len,
n,
position,
cs;
// render the fill
ctx.beginPath();
if (this._fillColor) {
inset = Math.ceil( lw ) + 0.5;
if(this._fillColor.gradientMode) {
if(this._fillColor.gradientMode === "radial") {
gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(w/2, h/2)-inset);
} else {
gradient = ctx.createLinearGradient(inset, h/2, w-2*inset, h/2);
}
colors = this._fillColor.color;
len = colors.length;
for(n=0; n (this._xOffset + this._width)) return false;
if(y < this._yOffset) return false;
if(y > (this._yOffset + this._height)) return false;
return true;
};
this.containsPoint = function( pt, dir ) {
var world = this.getWorld();
if (!world) throw( "null world in containsPoint" );
// 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,
xRadNDC = this._width/vpw, yRadNDC = this._height/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 center and dimensions of the rect in NDC
var vpw = world.getViewportWidth(), vph = world.getViewportHeight();
var xNDC = 2*this._xOffset/vpw, yNDC = 2*this._yOffset/vph,
hw = this._width/vpw, hh = this._height/vph;
var x = planePtNDC[0], y = planePtNDC[1];
if (x < (xNDC - hw)) return false;
if (x > (xNDC + hw)) return false;
if (y < (yNDC - hh)) return false;
if (y > (yNDC + hh)) return false;
return true;
};
this.getNearVertex = 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,
hwNDC = this._width/vpw, hhNDC = this._height/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 near point in NDC
var x = planePtNDC[0], y = planePtNDC[1];
var xMin = xNDC - hwNDC, xMax = xNDC + hwNDC,
yMin = yNDC - hhNDC, yMax = yNDC + hhNDC;
// compare the point against the 4 corners
var pt, dist;
pt = [xMin, yMin, 0];
dist = VecUtils.vecDist(2, pt, planePtNDC);
var minPt = pt, minDist = dist;
pt = [xMin, yMax, 0];
dist = VecUtils.vecDist(2, pt, planePtNDC);
if (dist < minDist) {
minDist = dist;
minPt = pt;
}
pt = [xMax, yMax, 0];
dist = VecUtils.vecDist(2, pt, planePtNDC);
if (dist < minDist) {
minDist = dist;
minPt = pt;
}
pt = [xMax, yMin, 0];
dist = VecUtils.vecDist(2, pt, planePtNDC);
if (dist < minDist) {
minDist = dist;
minPt = pt;
}
// convert to GL coordinates
x = minPt[0]; y = minPt[1];
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;
var objPt = [0,0,0];
objPt[0] = -z*(r-l)/(2.0*zn)*x;
objPt[1] = -z*(t-b)/(2.0*zn)*y;
// re-apply the transform
objPt = MathUtils.transformPoint( objPt, mat );
return objPt;
};
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,
hwNDC = this._width/vpw, hhNDC = this._height/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 near point in NDC
var x = planePtNDC[0], y = planePtNDC[1];
var xMin = xNDC - hwNDC, xMax = xNDC + hwNDC,
yMin = yNDC - hhNDC, yMax = yNDC + hhNDC;
// compare the point against the near point on the 4 sides
var pt, dist;
pt = [xMin, y, 0];
if (pt[1] < yMin) pt[1] = yMin;
else if (pt[1] > yMax) pt[1] = yMax;
dist = VecUtils.vecDist(2, pt, planePtNDC);
var minPt = pt, minDist = dist;
pt = [x, yMax, 0];
if (pt[0] < xMin) pt[0] = xMin;
else if (pt[0] > xMax) pt[0] = xMax;
dist = VecUtils.vecDist(2, pt, planePtNDC);
if (dist < minDist) {
minDist = dist;
minPt = pt;
}
pt = [xMax, y, 0];
if (pt[1] < yMin) pt[1] = yMin;
else if (pt[1] > yMax) pt[1] = yMax;
dist = VecUtils.vecDist(2, pt, planePtNDC);
if (dist < minDist) {
minDist = dist;
minPt = pt;
}
pt = [x, yMin, 0];
if (pt[0] < xMin) pt[0] = xMin;
else if (pt[0] > xMax) pt[0] = xMax;
dist = VecUtils.vecDist(2, pt, planePtNDC);
if (dist < minDist) {
minDist = dist;
minPt = pt;
}
// convert to GL coordinates
x = minPt[0]; y = minPt[1];
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;
var objPt = [0,0,0];
objPt[0] = -z*(r-l)/(2.0*zn)*x;
objPt[1] = -z*(t-b)/(2.0*zn)*y;
// re-apply the transform
objPt = MathUtils.transformPoint( objPt, mat );
return objPt;
};
this.recalcTexMapCoords = function( vrts, uvs ) {
var n = vrts.length/3;
var ivrt = 0, iuv = 0;
for (var i=0; i minDimen) tlRad = minDimen;
if (blRad > minDimen) blRad = minDimen;
if (brRad > minDimen) brRad = minDimen;
if (trRad > minDimen) trRad = minDimen;
// define some local variables
this.vertices = [];
this.normals = [];
this.uvs = [];
this.indices = [];
// the center of the rectangle is the first vertex
RectangleFill.pushVertex( x, y, z );
// traverse the perimiter of the rectangle
// push the starting point
RectangleFill.pushVertex( x-hw, y+hh-tlRad, z);
// do the left side
var ctr;
if (blRad <= 0){
RectangleFill.pushVertex( x-hw, y-hh, z);
} else {
ctr = [x - hw + blRad, y - hh + blRad, z];
RectangleFill.getRoundedCorner( ctr, [x-hw, y-hh+blRad, z], this.vertices );
}
// do the bottom
if (brRad <= 0) {
RectangleFill.pushVertex( x+hw, y-hh, z);
} else {
ctr = [x + hw - brRad, y - hh + brRad, z];
RectangleFill.getRoundedCorner( ctr, [x+hw-brRad, y-hh, z], this.vertices );
}
// do the right
if (trRad <= 0) {
RectangleFill.pushVertex( x+hw, y+hh, z);
} else {
ctr = [x + hw - trRad, y + hh - trRad, z];
RectangleFill.getRoundedCorner( ctr, [x+hw, y+hh-trRad, z], this.vertices );
}
// do the top
if (tlRad <= 0) {
RectangleFill.pushVertex( x-hw, y+hh, z);
} else {
ctr = [x - hw + tlRad, y + hh - tlRad, z];
RectangleFill.getRoundedCorner( ctr, [x-hw+tlRad, y+hh, z], this.vertices );
}
// get the normals and uvs
var vrt, uv;
var xMin = x - hw,
yMin = y - hh;
var n = [0, 0, 1];
var nVertices = this.vertices.length / 3;
for (var i=0; i minDimen) tlRad = minDimen;
if (blRad > minDimen) blRad = minDimen;
if (brRad > minDimen) brRad = minDimen;
if (trRad > minDimen) trRad = minDimen;
// define some local variables
this.vertices = [];
this.normals = [];
this.uvs = [];
this.indices = [];
// get the starting points
if (tlRad == 0) {
RectangleStroke.pushVertex( x-hw+sw, y+hh-sw, z);
RectangleStroke.pushVertex( x-hw, y+hh, z);
} else {
if (tlRad > sw) {
RectangleStroke.pushVertex( x-hw+sw, y+hh-tlRad, z);
RectangleStroke.pushVertex( x-hw, y+hh-tlRad, z);
} else {
RectangleStroke.pushVertex( x-hw+tlRad, y+hh-tlRad, z);
RectangleStroke.pushVertex( x-hw, y+hh-tlRad, z);
RectangleStroke.pushVertex( x-hw+sw, y+hh-sw, z);
RectangleStroke.pushVertex( x-hw, y+hh-sw, z);
}
}
// get the left side
if (blRad == 0) {
RectangleStroke.pushVertex( x-hw+sw, y-hh+sw, z);
RectangleStroke.pushVertex( x-hw, y-hh, z);
} else {
if (blRad >= sw) {
RectangleStroke.pushVertex( x-hw+sw, y-hh+blRad, z);
RectangleStroke.pushVertex( x-hw, y-hh+blRad, z);
var ctr = [x-hw+blRad, y-hh+blRad, z],
insidePt = [x-hw+sw, y-hh+blRad, z],
outsidePt = [x-hw, y-hh+blRad, z];
RectangleStroke.getRoundedCorner( ctr, insidePt, outsidePt, this.vertices );
} else {
RectangleStroke.pushVertex( x-hw+sw, y-hh+sw, z);
RectangleStroke.pushVertex( x-hw, y-hh+blRad, z);
var ctr = [x-hw+blRad, y-hh+blRad, z],
insidePt = [x-hw+blRad, y-hh+blRad, z],
outsidePt = [x-hw, y-hh+blRad, z];
RectangleStroke.getRoundedCorner( ctr, insidePt, outsidePt, this.vertices );
RectangleStroke.pushVertex( x-hw+sw, y-hh+sw, z);
RectangleStroke.pushVertex( x-hw+sw, y-hh, z);
}
}
// get the bottom
if (brRad == 0) {
RectangleStroke.pushVertex( x+hw-sw, y-hh+sw, z);
RectangleStroke.pushVertex( x+hw, y-hh, z);
} else {
RectangleStroke.pushVertex( x+hw-brRad, y-hh+sw, z);
RectangleStroke.pushVertex( x+hw-brRad, y-hh, z);
if (brRad >= sw) {
var ctr = [x+hw-brRad, y-hh+brRad, z],
insidePt = [x+hw-brRad, y-hh+sw, z],
outsidePt = [x+hw-brRad, y-hh, z];
RectangleStroke.getRoundedCorner( ctr, insidePt, outsidePt, this.vertices );
} else {
RectangleStroke.pushVertex( x+hw-sw, y-hh+sw, z);
RectangleStroke.pushVertex( x+hw-brRad, y-hh, z);
var ctr = [x+hw-brRad, y-hh+brRad, z],
insidePt = [x+hw-brRad, y-hh+brRad, z],
outsidePt = [x+hw-brRad, y-hh, z];
RectangleStroke.getRoundedCorner( ctr, insidePt, outsidePt, this.vertices );
RectangleStroke.pushVertex( x+hw-sw, y-hh+sw, z);
RectangleStroke.pushVertex( x+hw, y-hh+sw, z);
}
}
// get the right
if (trRad == 0) {
RectangleStroke.pushVertex( x+hw-sw, y+hh-sw, z);
RectangleStroke.pushVertex( x+hw, y+hh, z);
} else {
if (trRad >= sw) {
RectangleStroke.pushVertex( x+hw-sw, y+hh-trRad, z);
RectangleStroke.pushVertex( x+hw, y+hh-trRad, z);
var ctr = [x+hw-trRad, y+hh-trRad, z],
insidePt = [x+hw-sw, y+hh-trRad, z],
outsidePt = [x+hw, y+hh-trRad, z];
RectangleStroke.getRoundedCorner( ctr, insidePt, outsidePt, this.vertices );
} else {
RectangleStroke.pushVertex( x+hw-sw, y+hh-sw, z);
RectangleStroke.pushVertex( x+hw, y+hh-trRad, z);
var ctr = [x+hw-trRad, y+hh-trRad, z],
insidePt = [x+hw-trRad, y+hh-trRad, z],
outsidePt = [x+hw, y+hh-trRad, z];
RectangleStroke.getRoundedCorner( ctr, insidePt, outsidePt, this.vertices );
RectangleStroke.pushVertex( x+hw-sw, y+hh-sw, z);
RectangleStroke.pushVertex( x+hw-sw, y+hh, z);
}
}
// get the top
if (tlRad == 0) {
RectangleStroke.pushVertex( x-hw+sw, y+hh-sw, z);
RectangleStroke.pushVertex( x-hw, y+hh, z);
} else {
if (tlRad >= sw) {
RectangleStroke.pushVertex( x-hw+tlRad, y+hh-sw, z);
RectangleStroke.pushVertex( x-hw+tlRad, y+hh, z);
var ctr = [x-hw+tlRad, y+hh-tlRad, z],
insidePt = [x-hw+tlRad, y+hh-sw, z],
outsidePt = [x-hw+tlRad, y+hh, z];
RectangleStroke.getRoundedCorner( ctr, insidePt, outsidePt, this.vertices );
} else {
RectangleStroke.pushVertex( x-hw+sw, y+hh-sw, z);
RectangleStroke.pushVertex( x-hw+tlRad, y+hh, z);
var ctr = [x-hw+tlRad, y+hh-tlRad, z],
insidePt = [x-hw+tlRad, y+hh-tlRad, z],
outsidePt = [x-hw+tlRad, y+hh, z];
RectangleStroke.getRoundedCorner( ctr, insidePt, outsidePt, this.vertices );
}
}
// get the normals and uvs
var vrt, uv;
var xMin = x - hw,
yMin = y - hh;
var n = [0, 0, 1];
var nVertices = this.vertices.length / 3;
for (var i=0; i