From 27c1ba250a7db26cf24dd456d20af9ff1649e638 Mon Sep 17 00:00:00 2001 From: hwc487 Date: Mon, 23 Apr 2012 17:04:48 -0700 Subject: canvas interaction --- js/lib/drawing/world.js | 9 ++++++--- js/lib/geom/circle.js | 8 ++++++-- js/lib/geom/rectangle.js | 39 +++++++++++++++++++++++++++------------ 3 files changed, 39 insertions(+), 17 deletions(-) (limited to 'js/lib') diff --git a/js/lib/drawing/world.js b/js/lib/drawing/world.js index 945c9883..8ad4c6f5 100755 --- a/js/lib/drawing/world.js +++ b/js/lib/drawing/world.js @@ -362,9 +362,9 @@ var World = function GLWorld( canvas, use3D, preserveDrawingBuffer ) { // start RDGE passing your runtime object, and false to indicate we don't need a an initialization state // in the case of a procedurally built scene an init state is not needed for loading data + this._canvas.rdgeid = this._canvas.getAttribute( "data-RDGE-id" ); if (this._useWebGL) { rdgeStarted = true; - this._canvas.rdgeid = this._canvas.getAttribute( "data-RDGE-id" ); RDGE.globals.engine.unregisterCanvas( this._canvas ); RDGE.globals.engine.registerCanvas(this._canvas, this); RDGE.RDGEStart( this._canvas ); @@ -835,8 +835,11 @@ World.prototype.importJSON = function (jObj) { // import the objects // there should be exactly one child of the parent object - if (jObj.children && (jObj.children.length === 1)) - this.importObjectsJSON( jObj.children[0] ); + if (jObj.children) + { + for (var i=0; i 0) { - ctx.quadraticCurveTo( inset, height-inset, inset+rad, height-inset ); + ctx.quadraticCurveTo( inset+xOff, height-inset+yOff, inset+rad+xOff, height-inset+yOff ); } // do the bottom of the rectangle @@ -392,11 +407,11 @@ var Rectangle = function GLRectangle() { rad = brRad - inset; if (rad < 0) rad = 0; pt[0] -= rad; - ctx.lineTo( pt[0], pt[1] ); + ctx.lineTo( pt[0]+xOff, pt[1]+yOff ); // get the bottom right arc if (MathUtils.fpSign(rad) > 0) { - ctx.quadraticCurveTo( width-inset, height-inset, width-inset, height-inset-rad ); + ctx.quadraticCurveTo( width-inset+xOff, height-inset+yOff, width-inset+xOff, height-inset-rad+yOff ); } // get the right of the rectangle @@ -404,11 +419,11 @@ var Rectangle = function GLRectangle() { rad = trRad - inset; if (rad < 0) rad = 0; pt[1] += rad; - ctx.lineTo( pt[0], pt[1] ); + ctx.lineTo( pt[0]+xOff, pt[1]+yOff ); // do the top right corner if (MathUtils.fpSign(rad) > 0) { - ctx.quadraticCurveTo( width-inset, inset, width-inset-rad, inset ); + ctx.quadraticCurveTo( width-inset+xOff, inset+yOff, width-inset-rad+xOff, inset+yOff ); } // do the top of the rectangle @@ -416,13 +431,13 @@ var Rectangle = function GLRectangle() { rad = tlRad - inset; if (rad < 0) rad = 0; pt[0] += rad; - ctx.lineTo( pt[0], pt[1] ); + ctx.lineTo( pt[0]+xOff, pt[1]+yOff ); // do the top left corner if (MathUtils.fpSign(rad) > 0) { - ctx.quadraticCurveTo( inset, inset, inset, inset+rad ); + ctx.quadraticCurveTo( inset+xOff, inset+yOff, inset+xOff, inset+rad+yOff ); } else { - ctx.lineTo( inset, 2*inset ); + ctx.lineTo( inset+xOff, 2*inset+yOff ); } } }; @@ -430,7 +445,7 @@ var Rectangle = function GLRectangle() { this.render = function() { // get the world var world = this.getWorld(); - if (!world) throw( "null world in rectangle render" ); + if (!world) throw( "null world in rectangle render" ); // get the context var ctx = world.get2DContext(); -- cgit v1.2.3 From 4290e20e2b2f4536f4365d02e1cd7a1418bc8ea9 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Tue, 24 Apr 2012 15:40:12 -0700 Subject: allow the realtime drawing of brush strokes drawn off the standard XY plane by passing in the transformation matrix --- js/lib/geom/brush-stroke.js | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'js/lib') diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js index efd21c4a..89ef79fb 100755 --- a/js/lib/geom/brush-stroke.js +++ b/js/lib/geom/brush-stroke.js @@ -117,7 +117,7 @@ var BrushStroke = function GLBrushStroke() { }; this.getPoint = function (index) { - return this._Points[index]; + return this._Points[index].slice(0); }; this.addPoint = function (pt) { @@ -399,7 +399,7 @@ var BrushStroke = function GLBrushStroke() { // ***** unproject all the centered points and convert them to 2D (plane space)***** // (undo the projection step performed by the browser) - localPoint = this._unprojectPt(localPoint, 1400); //todo get the perspective distance from the canvas + //localPoint = this._unprojectPt(localPoint, 1400); //todo get the perspective distance from the canvas localPoint = MathUtils.transformPoint(localPoint, this._planeMatInv); //add to the list of local points @@ -572,13 +572,13 @@ var BrushStroke = function GLBrushStroke() { ctx.restore(); } //this.render() - this.drawToContext = function(ctx, origX, origY, drawStageWorldPts){ + this.drawToContext = function(ctx, deltaX, deltaY, drawStageWorldPts, stageWorldToScreenMat){ var points = this._LocalPoints; - if (drawStageWorldPts){ + if (drawStageWorldPts){ //this is usually true when we're drawing the brush stroke on the stage (no canvas yet) points = this._Points; } var numPoints = points.length; - + var tempP, p; if (this._strokeUseCalligraphic) { //build the stamp for the brush stroke var t=0; @@ -623,9 +623,9 @@ var BrushStroke = function GLBrushStroke() { //ctx.strokeStyle="rgba("+parseInt(255*currStrokeColor[0])+","+parseInt(255*currStrokeColor[1])+","+parseInt(255*currStrokeColor[2])+","+alphaVal+")"; ctx.translate(disp[0],disp[1]); ctx.beginPath(); - ctx.moveTo(points[0][0]-origX, points[0][1]-origY); + ctx.moveTo(points[0][0]-deltaX, points[0][1]-deltaY); for (var i=0;i */ -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; +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; +var drawUtils = require("js/helper-classes/3D/draw-utils").DrawUtils; +var vecUtils = require("js/helper-classes/3D/vec-utils").VecUtils; + /////////////////////////////////////////////////////////////////////// // Class GLCircle // GL representation of a circle. @@ -710,6 +713,49 @@ var Circle = function GLCircle() { return (MathUtils.fpCmp(distToPt,distToBoundary) <= 0); }; + this.getNearPoint = function( pt, dir ) + { + var world = this.getWorld(); + if (!world) throw( "null world in getNearPoint" ); + + // the input point and direction are in GL space + // project to the z == 0 plane + var mat = this.getMatrix(); + var plane = [0,0,1,0]; + plane = MathUtils.transformPlane( plane, mat ); + var projPt = MathUtils.vecIntersectPlane ( pt, dir, plane ); + + // get the center of the circle in GL space + var ctr = this.getGLCenter(); + + // transform the projected point to the plane of the circle + var planePt = MathUtils.transformPoint( projPt, mat ); + + // get a matrix mapping the circle to a 2D coordinate system + var normal = [ mat[8], mat[9], mat[10] ]; + var planeMat = drawUtils.getPlaneToWorldMatrix(normal, ctr); + var planeMatInv = glmat4.inverse( planeMat, [] ); + var planePt2D = MathUtils.transformPoint( planePt, planeMatInv ); + + // get 2 points on the axes of the oval + var wPt = this.preViewToGL( [this._xOffset + 0.5*this.getWidth(), this._yOffset, 0] ), + hPt = this.preViewToGL( [this._xOffset, this._yOffset + 0.5*this.getHeight(), 0] ); + var w = vecUtils.vecDist( 2, wPt, ctr ), + h = vecUtils.vecDist( 2, hPt, ctr ); + var aspect = w/h; + + // get the angle of the projected point relative to the circle + var angle = Math.atan2( planePt2D[1], planePt2D[0]/aspect ); + var degrees = angle*180.0/Math.PI; + + // get the corresponding point on the object + var pt = [ Math.cos(angle)*w, Math.sin(angle)*h, 0 ]; + var glPt = MathUtils.transformPoint( pt, planeMat ); + + return glPt; + } + + /* this.getNearPoint = function( pt, dir ) { var world = this.getWorld(); if (!world) throw( "null world in getNearPoint" ); @@ -759,6 +805,7 @@ var Circle = function GLCircle() { return objPt; }; + */ this.recalcTexMapCoords = function( vrts, uvs ) { var n = vrts.length/3; diff --git a/js/lib/geom/geom-obj.js b/js/lib/geom/geom-obj.js index f2991bdb..7cb9b80f 100755 --- a/js/lib/geom/geom-obj.js +++ b/js/lib/geom/geom-obj.js @@ -375,6 +375,65 @@ var GeomObj = function GLGeomObj() { } }; + + this.getGLCenter = function() + { + // get the normalized device coordinates (NDC) for + // all position and dimensions. + var world = this.getWorld(); + var vpw = world.getViewportWidth(), vph = world.getViewportHeight(); + var xNDC = 2*this._xOffset/vpw, yNDC = -2*this._yOffset/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(); + + // unproject to get the position of the origin in GL + var x = -z*(r-l)/(2.0*zn)*xNDC, + y = -z*(t-b)/(2.0*zn)*yNDC; + z = 0.0; + + // transform by the object's transformation matrix + var ctr = MathUtils.transformPoint( [x, y, z], this.getMatrix() ); + + return ctr; + }; + + this.preViewToGL = function( preViewPt ) + { + // get the normalized device coordinates (NDC) for + // all position and dimensions. + var world = this.getWorld(); + var vpw = world.getViewportWidth(), vph = world.getViewportHeight(); + var xNDC = 2*preViewPt[0]/vpw, yNDC = -2*preViewPt[1]/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(); + + // unproject to get the position of the origin in GL + var x = -z*(r-l)/(2.0*zn)*xNDC, + y = -z*(t-b)/(2.0*zn)*yNDC; + z = 0.0; + + // transform by the object's transformation matrix + var glPt = MathUtils.transformPoint( [x, y, z], this.getMatrix() ); + + return glPt; + }; + this.buildBuffers = function () { // this function must be overridden by the base class alert("GLGeomObj.buildBuffers must be overridden by base class"); diff --git a/js/lib/geom/rectangle.js b/js/lib/geom/rectangle.js index d9f1f0b1..41c51e2f 100755 --- a/js/lib/geom/rectangle.js +++ b/js/lib/geom/rectangle.js @@ -693,7 +693,6 @@ var Rectangle = function GLRectangle() { 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 ); -- cgit v1.2.3 From d45b72b0e683d307ce3e798769f19627416015db Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Wed, 25 Apr 2012 10:01:57 -0700 Subject: render the calligraphic brush stroke in realtime on a rotated canvas --- js/lib/geom/brush-stroke.js | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'js/lib') diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js index 89ef79fb..1fae0c1d 100755 --- a/js/lib/geom/brush-stroke.js +++ b/js/lib/geom/brush-stroke.js @@ -568,11 +568,11 @@ var BrushStroke = function GLBrushStroke() { } ctx.save(); ctx.clearRect(0, 0, bboxWidth, bboxHeight); - this.drawToContext(ctx, 0, 0, false); + this.drawToContext(ctx, false); ctx.restore(); } //this.render() - this.drawToContext = function(ctx, deltaX, deltaY, drawStageWorldPts, stageWorldToScreenMat){ + this.drawToContext = function(ctx, drawStageWorldPts, stageWorldDeltaX, stageWorldDeltaY, stageWorldToScreenMat){ var points = this._LocalPoints; if (drawStageWorldPts){ //this is usually true when we're drawing the brush stroke on the stage (no canvas yet) points = this._Points; @@ -623,9 +623,23 @@ var BrushStroke = function GLBrushStroke() { //ctx.strokeStyle="rgba("+parseInt(255*currStrokeColor[0])+","+parseInt(255*currStrokeColor[1])+","+parseInt(255*currStrokeColor[2])+","+alphaVal+")"; ctx.translate(disp[0],disp[1]); ctx.beginPath(); - ctx.moveTo(points[0][0]-deltaX, points[0][1]-deltaY); + if (drawStageWorldPts) { + tempP = points[0].slice(0); + tempP[0]+=stageWorldDeltaX; tempP[1]+=stageWorldDeltaY; + p = MathUtils.transformAndDivideHomogeneousPoint(tempP, stageWorldToScreenMat); + } else { + p = points[0]; + } + ctx.moveTo(p[0],p[1]); for (var i=0;i= 1)) { this.rebuildTree(this._geomRoot); this.restartRenderLoop(); } -- cgit v1.2.3 From 1ccc4d6dcff232b00763a5a49d7ad7a91f78ad3f Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Thu, 26 Apr 2012 13:24:51 -0700 Subject: Fixing the element model and adding get element Signed-off-by: Valerio Virgillito --- js/lib/NJUtils.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'js/lib') diff --git a/js/lib/NJUtils.js b/js/lib/NJUtils.js index 67bb59c4..dae128e4 100755 --- a/js/lib/NJUtils.js +++ b/js/lib/NJUtils.js @@ -94,10 +94,10 @@ exports.NJUtils = Object.create(Object.prototype, { ///// TODO: find a different place for this function makeElementModel: { value: function(el, selection, controller, isShape) { + //el.elementModel = Montage.create(ElementModel).initialize(el.nodeName, selection, controller, isShape); + var p3d = Montage.create(Properties3D); - if(selection === "Stage") { - p3d.init(el, true); - } + var shapeProps = null; var pi = controller + "Pi"; @@ -143,6 +143,7 @@ exports.NJUtils = Object.create(Object.prototype, { isShape: { value: isShape} }); + } }, @@ -167,15 +168,12 @@ exports.NJUtils = Object.create(Object.prototype, { break; case "canvas": isShape = el.getAttribute("data-RDGE-id"); - if(isShape) - { + if(isShape) { // TODO - Need more info about the shape selection = "canvas"; controller = "shape"; isShape = true; - } - else - { + } else { selection = "canvas"; controller = "canvas"; } -- cgit v1.2.3 From d2a5fcbaed6b3c3377edecbc27e6a2818b79be40 Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Wed, 2 May 2012 15:34:49 -0700 Subject: Nesting absolute element in the Tag tool. Refactoring element creation and element models Signed-off-by: Valerio Virgillito --- js/lib/NJUtils.js | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'js/lib') diff --git a/js/lib/NJUtils.js b/js/lib/NJUtils.js index dae128e4..301af3f1 100755 --- a/js/lib/NJUtils.js +++ b/js/lib/NJUtils.js @@ -54,13 +54,25 @@ exports.NJUtils = Object.create(Object.prototype, { return document.createTextNode(text); } }, - + ///// Quick "createElement" function "attr" can be classname or object ///// with attribute key/values - ///// Suppor for data attributes - make : { - value: function(tag, attr) { - var el = document.createElement(tag); + ///// Support for data attributes + ///// Support user/ninja document + make: { + value: function(tag, attr, doc) { + var _doc, el; + + _doc = doc ? doc._document : document; + el = _doc.createElement(tag); + this.decor(el, attr); + + return el; + } + }, + + decor: { + value: function(el, attr) { if (typeof attr === 'object') { for (var a in attr) { if (attr.hasOwnProperty(a)) { @@ -74,8 +86,12 @@ exports.NJUtils = Object.create(Object.prototype, { } else if (typeof attr === 'string') { el.className = (el.className + ' ' + attr).trim(); } - - return el; + } + }, + + createModel: { + value: function(el) { + el.elementModel = Montage.create(ElementModel).initialize(el); } }, @@ -94,8 +110,6 @@ exports.NJUtils = Object.create(Object.prototype, { ///// TODO: find a different place for this function makeElementModel: { value: function(el, selection, controller, isShape) { - //el.elementModel = Montage.create(ElementModel).initialize(el.nodeName, selection, controller, isShape); - var p3d = Montage.create(Properties3D); var shapeProps = null; -- cgit v1.2.3 From a809c6b3ba6f024922dd3f10bbc4ab456de2407e Mon Sep 17 00:00:00 2001 From: Nivesh Rajbhandari Date: Wed, 2 May 2012 15:45:43 -0700 Subject: Converting line, circle and rectangle shapes to object literal notation. Signed-off-by: Nivesh Rajbhandari --- js/lib/geom/circle.js | 1433 ++++++++++++++++++++++++---------------------- js/lib/geom/line.js | 914 +++++++++++++++-------------- js/lib/geom/rectangle.js | 1402 ++++++++++++++++++++++++--------------------- 3 files changed, 1931 insertions(+), 1818 deletions(-) (limited to 'js/lib') diff --git a/js/lib/geom/circle.js b/js/lib/geom/circle.js index 0f1f49a9..425b869a 100755 --- a/js/lib/geom/circle.js +++ b/js/lib/geom/circle.js @@ -4,9 +4,9 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot (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; +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; var drawUtils = require("js/helper-classes/3D/draw-utils").DrawUtils; var vecUtils = require("js/helper-classes/3D/vec-utils").VecUtils; @@ -16,744 +16,790 @@ var vecUtils = require("js/helper-classes/3D/vec-utils").VecUtils; // Derived from class GLGeomObj // The position and dimensions of the stroke, fill, and inner Radius should be in pixels /////////////////////////////////////////////////////////////////////// -var Circle = function GLCircle() { - - this.init = function( world, xOffset, yOffset, width, height, strokeSize, strokeColor, fillColor, innerRadius, strokeMaterial, fillMaterial, strokeStyle) { - /////////////////////////////////////////////////////////////////////// - // Instance variables - /////////////////////////////////////////////////////////////////////// - this._width = 2.0; - this._height = 2.0; - this._xOffset = 0; - this._yOffset = 0; - - this._radius = 2.0; - this._strokeWidth = 0.25; - this._innerRadius = 0; - - this._ovalHeight = this._ovalHeight = 2.0 * this._radius; - - this._strokeStyle = "Solid"; - - this._aspectRatio = 1.0; - - if (arguments.length > 0) { - this._width = width; - this._height = height; - this._xOffset = xOffset; - this._yOffset = yOffset; - - this._strokeWidth = strokeSize; - this._innerRadius = innerRadius; - this._strokeColor = strokeColor; - this._fillColor = fillColor; - - this._strokeStyle = strokeStyle; - - this._matrix = Matrix.I(4); - //this._matrix[12] = xOffset; - //this._matrix[13] = yOffset; - } - - this.m_world = world; - - if(strokeMaterial){ - this._strokeMaterial = strokeMaterial; - } else { - this._strokeMaterial = MaterialsModel.getMaterial( MaterialsModel.getDefaultMaterialName() ); - } +exports.Circle = 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 }, + + _radius: { value : 2.0, writable: true }, + _strokeWidth: { value : 0.25, writable: true }, + _innerRadius: { value : 0, writable: true }, + _ovalHeight: { value : 4.0, writable: true }, + _strokeStyle: { value : "Solid", writable: true }, + _aspectRatio: { value : 1.0, writable: true }, + + init: { + value: function(world, xOffset, yOffset, width, height, strokeSize, strokeColor, fillColor, innerRadius, strokeMaterial, fillMaterial, strokeStyle) { + if(arguments.length > 0) { + this._width = width; + this._height = height; + this._xOffset = xOffset; + this._yOffset = yOffset; + this._ovalHeight = 2.0 * this._radius; + + this._strokeWidth = strokeSize; + this._innerRadius = innerRadius; + this._strokeColor = strokeColor; + this._fillColor = fillColor; + + this._strokeStyle = strokeStyle; + + this._matrix = Matrix.I(4); + //this._matrix[12] = xOffset; + //this._matrix[13] = yOffset; + } + + this.m_world = world; - if(fillMaterial) { - this._fillMaterial = fillMaterial; - } else { - this._fillMaterial = MaterialsModel.getMaterial( MaterialsModel.getDefaultMaterialName() ); + 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; - }; + // TODO - Use getters/setters in the future + getStrokeWidth: { + value: function() { + return this._strokeWidth; + } + }, - this.setStrokeMaterial = function(m) { - this._strokeMaterial = m; - }; + setStrokeWidth: { + value: function(w) { + this._strokeWidth = w; + } + }, - this.getFillMaterial = function() { - return this._fillMaterial; - }; + getStrokeMaterial: { + value: function() { + return this._strokeMaterial; + } + }, - this.setFillMaterial = function(m) { - this._fillMaterial = m; - }; + setStrokeMaterial: { + value: function(m) { + this._strokeMaterial = m; + } + }, - this.getRadius = function() { - return this._radius; - }; + getFillMaterial: { + value: function() { + return this._fillMaterial; + } + }, - this.setRadius = function(r) { - this._radius = r; - }; + setFillMaterial: { + value: function(m) { + this._fillMaterial = m; + } + }, - this.getWorld = function() { - return this._world; - }; + getRadius: { + value: function() { + return this._radius; + } + }, - this.setWorld = function(w) { - this._world = w; - }; + setRadius: { + value: function(r) { + this._radius = r; + } + }, - this.getInnerRadius = function() { - return this._innerRadius; - }; + getInnerRadius: { + value: function() { + return this._innerRadius; + } + }, - this.setInnerRadius = function(r) { - this._innerRadius = r; - }; + setInnerRadius: { + value: function(r) { + this._innerRadius = r; + } + }, - this.getStrokeStyle = function() { - return this._strokeStyle; - }; - this.setStrokeStyle = function(s) { - this._strokeStyle = s; - }; + getStrokeStyle: { + value: function() { + return this._strokeStyle; + } + }, - this.getWidth = function() { - return this._width; - }; + setStrokeStyle: { + value: function(s) { + this._strokeStyle = s; + } + }, - this.setWidth = function(w) { - this._width = w; - }; + getWidth: { + value: function() { + return this._width; + } + }, - this.getHeight = function() { - return this._height; - }; + setWidth: { + value: function(w) { + this._width = w; + } + }, - this.setHeight = function(h) { - this._height = h; - }; + getHeight: { + value: function() { + return this._height; + } + }, - this.geomType = function() { - return this.GEOM_TYPE_CIRCLE; - }; + setHeight: { + value: function(h) { + this._height = h; + } + }, - /////////////////////////////////////////////////////////////////////// - // Methods - /////////////////////////////////////////////////////////////////////// + geomType: { + value: function() { + return this.GEOM_TYPE_CIRCLE; + } + }, /////////////////////////////////////////////////////////////////////// // update the "color of the material - this.getFillColor = function() - { - return this._fillColor; - } - -// this.setFillColor = function(c) -// { -// this._fillColor = c; -// } - - this.getStrokeColor = function() - { - return this._strokeColor; - } - -// this.setStrokeColor = function(c) -// { -// this._strokeColor = c; -// } - /////////////////////////////////////////////////////////////////////// - - this.buildBuffers = 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 ); + getFillColor: { + value: function() { + return this._fillColor; + } + }, - // create the gl buffer - var gl = world.getGLContext(); +// setFillColor: { +// value: function(c) { +// this._fillColor = c; +// } +// }, - // determine the number of triangles to generate - var nTriangles = 60; // yes, we will do better than this + getStrokeColor: { + value: function() { + return this._strokeColor; + } + }, - // 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, - xRadNDC = this._width/vpw, yRadNDC = this._height/vph, - xStrokeNDC = 2*this._strokeWidth/vpw, yStrokeNDC = 2*this._strokeWidth/vph, - xInnRadNDC = this._innerRadius*xRadNDC, yInnRadNDC = this._innerRadius*yRadNDC; +// setStrokeColor: { +// value: function(c) { +// this._strokeColor = c; +// } +// }, + /////////////////////////////////////////////////////////////////////// - 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; + /////////////////////////////////////////////////////////////////////// + // Methods + /////////////////////////////////////////////////////////////////////// + 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(); + + // determine the number of triangles to generate + var nTriangles = 60; // yes, we will do better than this + + // 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, + xRadNDC = this._width/vpw, yRadNDC = this._height/vph, + xStrokeNDC = 2*this._strokeWidth/vpw, yStrokeNDC = 2*this._strokeWidth/vph, + xInnRadNDC = this._innerRadius*xRadNDC, yInnRadNDC = this._innerRadius*yRadNDC; + + 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 radii + var xRad = -z*(r-l)/(2.0*zn)*xRadNDC, + yRad = -z*(t-b)/(2.0*zn)*yRadNDC; + + // save the overall dimensions to be used in the uv calculations + this._ovalWidth = xRad; this._ovalHeight = yRad; + + // 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 inner radius + var xInnRad = -z*(r-l)/(2.0*zn)*xInnRadNDC, + yInnRad = -z*(t-b)/(2.0*zn)*yInnRadNDC; + + // get a matrix to rotate a point around the circle + var angle = 2.0 * Math.PI/Number(nTriangles); + var mat = Matrix.RotationZ( angle ); + var reverseRotMat = Matrix.RotationZ( -angle ); + + // calculate matrices to scale the circle and stroke to fit the bounds of the ellipse + var strokeScaleMat = Matrix.I(4); + strokeScaleMat[0] = xRad; + strokeScaleMat[5] = yRad; + + var fillScaleMat = Matrix.I(4); + fillScaleMat[0] = xRad - xStroke; + fillScaleMat[5] = yRad - yStroke; + + var innerRadiusScaleMat = Matrix.I(4); + innerRadiusScaleMat[0] = xInnRad; + innerRadiusScaleMat[5] = yInnRad; + + var innerStrokeScaleMat = Matrix.I(4); + innerStrokeScaleMat[0] = xInnRad - xStroke; + innerStrokeScaleMat[5] = yInnRad - yStroke; + + var fillPrim, strokePrim0, strokePrim1; + var fillMaterial, strokeMaterial0, strokeMaterial2; + + this._primArray = []; + this._materialArray = []; + this._materialTypeArray = []; + this._materialNodeArray = []; + + ///////////////////////////////////////////////////////////// + // Strokes + if(this._strokeWidth > 0) { + var numStrokes = 1; + if(this._innerRadius !== 0) { + strokePrim0 = this.generateOvalRing(x, y, reverseRotMat, innerStrokeScaleMat, innerRadiusScaleMat, nTriangles); + } - // calculate the object coordinates from their NDC coordinates - var z = -world.getViewDistance(); + strokePrim1 = this.generateOvalRing(x, y, reverseRotMat, fillScaleMat, strokeScaleMat, nTriangles); + } - // 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 radii - var xRad = -z*(r-l)/(2.0*zn)*xRadNDC, - yRad = -z*(t-b)/(2.0*zn)*yRadNDC; - - // save the overall dimensions to be used in the uv calculations - this._ovalWidth = xRad; this._ovalHeight = yRad; - - // 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 inner radius - var xInnRad = -z*(r-l)/(2.0*zn)*xInnRadNDC, - yInnRad = -z*(t-b)/(2.0*zn)*yInnRadNDC; - - // get a matrix to rotate a point around the circle - var angle = 2.0 * Math.PI/Number(nTriangles); - var mat = Matrix.RotationZ( angle ); - var reverseRotMat = Matrix.RotationZ( -angle ); - - // calculate matrices to scale the circle and stroke to fit the bounds of the ellipse - var strokeScaleMat = Matrix.I(4); - strokeScaleMat[0] = xRad; - strokeScaleMat[5] = yRad; - - var fillScaleMat = Matrix.I(4); - fillScaleMat[0] = xRad - xStroke; - fillScaleMat[5] = yRad - yStroke; - - var innerRadiusScaleMat = Matrix.I(4); - innerRadiusScaleMat[0] = xInnRad; - innerRadiusScaleMat[5] = yInnRad; - - var innerStrokeScaleMat = Matrix.I(4); - innerStrokeScaleMat[0] = xInnRad - xStroke; - innerStrokeScaleMat[5] = yInnRad - yStroke; - - var fillPrim, strokePrim0, strokePrim1; - var fillMaterial, strokeMaterial0, strokeMaterial2; - - this._primArray = []; - this._materialArray = []; - this._materialTypeArray = []; - this._materialNodeArray = []; - - ///////////////////////////////////////////////////////////// - // Strokes - if(this._strokeWidth > 0) { - var numStrokes = 1; - if(this._innerRadius !== 0) { - strokePrim0 = this.generateOvalRing(x, y, reverseRotMat, innerStrokeScaleMat, innerRadiusScaleMat, nTriangles); + ///////////////////////////////////////////////////////////// + // Fill + if(this._innerRadius === 0) { + fillPrim = this.generateOval(x, y, mat, fillScaleMat, nTriangles); + } else { + fillPrim = this.generateOvalRing(x, y, reverseRotMat, innerRadiusScaleMat, fillScaleMat, nTriangles); } - strokePrim1 = this.generateOvalRing(x, y, reverseRotMat, fillScaleMat, strokeScaleMat, nTriangles); - } - - ///////////////////////////////////////////////////////////// - // Fill - if(this._innerRadius === 0) { - fillPrim = this.generateOval(x, y, mat, fillScaleMat, nTriangles); - } else { - fillPrim = this.generateOvalRing(x, y, reverseRotMat, innerRadiusScaleMat, fillScaleMat, nTriangles); - } + if (fillPrim) { + fillMaterial = this.makeFillMaterial(); - if (fillPrim) { - fillMaterial = this.makeFillMaterial(); + this._primArray.push( fillPrim ); + this._materialNodeArray.push( fillMaterial.getMaterialNode() ); + } - this._primArray.push( fillPrim ); - this._materialNodeArray.push( fillMaterial.getMaterialNode() ); - } + if (strokePrim0) { + strokeMaterial0 = this.makeStrokeMaterial(); - if (strokePrim0) { - strokeMaterial0 = this.makeStrokeMaterial(); + this._primArray.push( strokePrim0 ); + this._materialNodeArray.push( strokeMaterial0.getMaterialNode() ); + } - this._primArray.push( strokePrim0 ); - this._materialNodeArray.push( strokeMaterial0.getMaterialNode() ); - } + if (strokePrim1) { + strokeMaterial2 = this.makeStrokeMaterial(); - if (strokePrim1) { - strokeMaterial2 = this.makeStrokeMaterial(); + this._primArray.push( strokePrim1 ); + this._materialNodeArray.push( strokeMaterial2.getMaterialNode() ); + } - this._primArray.push( strokePrim1 ); - this._materialNodeArray.push( strokeMaterial2.getMaterialNode() ); - } + world.updateObject(this); + } + }, + + generateOval: { + value: function(xOff, yOff, rotationMat, scaleMat, nTriangles) { + var pt = [1.0, 0.0, 0.0]; + //var pts = scaleMat.multiply(pt); + var pts = glmat4.multiplyVec3( scaleMat, pt, []); + var x = pts[0], y = pts[1], z = 0; + var xs = scaleMat[0], ys = scaleMat[4]; + + var vrts = [], nrms = [], uvs = [], indices = []; + var index = 0; + for (var i=0; i 0) { + xScale = 0.5*innerRad*this._width; + yScale = 0.5*innerRad*this._height; + mat[0] = xScale; + mat[5] = yScale; + + // get the bezier points + var bezPts = MathUtils.circularArcToBezier( [0,0,0], [1,0,0], -2.0*Math.PI ); + if (bezPts) { + var n = bezPts.length; + p = MathUtils.transformPoint( bezPts[0], mat ); + ctx.moveTo( p[0], p[1] ); + index = 1; + while (index < n) { + p0 = MathUtils.transformPoint( bezPts[index], mat ); + p1 = MathUtils.transformPoint( bezPts[index+1], mat ); + + var x0 = p0[0], y0 = p0[1], + x1 = p1[0], y1 = p1[1]; + ctx.quadraticCurveTo( x0, y0, x1, y1 ); + index += 2; + } + } + } - } else { - c = "rgba(" + 255*this._fillColor[0] + "," + 255*this._fillColor[1] + "," + 255*this._fillColor[2] + "," + this._fillColor[3] + ")"; - ctx.fillStyle = c; + // fill the path + ctx.fill(); } - // draw the fill -// ctx.beginPath(); - var p = MathUtils.transformPoint( bezPts[0], mat ); - ctx.moveTo( p[0], p[1] ); - var index = 1; - while (index < n) { - p0 = MathUtils.transformPoint( bezPts[index], mat ); - p1 = MathUtils.transformPoint( bezPts[index+1], mat ); - - x0 = p0[0]; y0 = p0[1]; - x1 = p1[0]; y1 = p1[1]; - ctx.quadraticCurveTo( x0, y0, x1, y1 ); - index += 2; - } - - if (MathUtils.fpSign(innerRad) > 0) { - xScale = 0.5*innerRad*this._width; - yScale = 0.5*innerRad*this._height; - mat[0] = xScale; - mat[5] = yScale; - - // get the bezier points - var bezPts = MathUtils.circularArcToBezier( [0,0,0], [1,0,0], -2.0*Math.PI ); - if (bezPts) { - var n = bezPts.length; - p = MathUtils.transformPoint( bezPts[0], mat ); - ctx.moveTo( p[0], p[1] ); - index = 1; - while (index < n) { - p0 = MathUtils.transformPoint( bezPts[index], mat ); - p1 = MathUtils.transformPoint( bezPts[index+1], mat ); - - var x0 = p0[0], y0 = p0[1], - x1 = p1[0], y1 = p1[1]; - ctx.quadraticCurveTo( x0, y0, x1, y1 ); - index += 2; - } - } - } - - // fill the path - ctx.fill(); - } - - // calculate the stroke matrix - xScale = 0.5*this._width - 0.5*lineWidth; - yScale = 0.5*this._height - 0.5*lineWidth; - mat[0] = xScale; - mat[5] = yScale; - - // set up the stroke style - ctx.beginPath(); - ctx.lineWidth = lineWidth; - if (this._strokeColor) { - if(this._strokeColor.gradientMode) { - if(this._strokeColor.gradientMode === "radial") { - gradient = ctx.createRadialGradient(xCtr, yCtr, Math.min(xScale, yScale), - xCtr, yCtr, 0.5*Math.max(this._height, this._width)); - } else { - gradient = ctx.createLinearGradient(0, this._height/2, this._width, this._height/2); - } - colors = this._strokeColor.color; - len = colors.length; + // calculate the stroke matrix + xS