From e065244ac75d1d0f25fd5c75cb58e714a13fe16b Mon Sep 17 00:00:00 2001 From: Jonathan Duran Date: Wed, 14 Mar 2012 08:59:17 -0700 Subject: Squashed commit of the following: merge master into timeline Signed-off-by: Jonathan Duran --- js/lib/NJUtils.js | 34 ++- js/lib/drawing/world.js | 102 ++++--- js/lib/geom/brush-stroke.js | 329 +++++++++++++--------- js/lib/geom/circle.js | 103 ++++++- js/lib/geom/geom-obj.js | 210 ++++++++++++-- js/lib/geom/line.js | 57 +++- js/lib/geom/rectangle.js | 111 +++++++- js/lib/geom/sub-path.js | 86 +++++- js/lib/rdge/materials/bump-metal-material.js | 10 +- js/lib/rdge/materials/deform-material.js | 2 +- js/lib/rdge/materials/flat-material.js | 41 +-- js/lib/rdge/materials/fly-material.js | 2 +- js/lib/rdge/materials/julia-material.js | 2 +- js/lib/rdge/materials/keleidoscope-material.js | 2 +- js/lib/rdge/materials/linear-gradient-material.js | 2 +- js/lib/rdge/materials/mandel-material.js | 2 +- js/lib/rdge/materials/plasma-material.js | 37 +-- js/lib/rdge/materials/pulse-material.js | 11 +- js/lib/rdge/materials/radial-blur-material.js | 9 +- js/lib/rdge/materials/radial-gradient-material.js | 7 +- js/lib/rdge/materials/relief-tunnel-material.js | 2 +- js/lib/rdge/materials/square-tunnel-material.js | 2 +- js/lib/rdge/materials/star-material.js | 2 +- js/lib/rdge/materials/taper-material.js | 8 +- js/lib/rdge/materials/tunnel-material.js | 2 +- js/lib/rdge/materials/twist-material.js | 2 +- js/lib/rdge/materials/twist-vert-material.js | 6 +- js/lib/rdge/materials/uber-material.js | 109 ++++++- js/lib/rdge/materials/water-material.js | 2 +- js/lib/rdge/materials/z-invert-material.js | 2 +- 30 files changed, 998 insertions(+), 298 deletions(-) (limited to 'js/lib') diff --git a/js/lib/NJUtils.js b/js/lib/NJUtils.js index e16715a4..4f1082f9 100755 --- a/js/lib/NJUtils.js +++ b/js/lib/NJUtils.js @@ -116,7 +116,39 @@ exports.NJUtils = Object.create(Object.prototype, { ///// TODO: Selection and model should be based on the element type makeModelFromElement: { value: function(el) { - this.makeElementModel(el, "Div", "block", false); + var selection = "div", + controller = "block", + isShape = false; + switch(el.nodeName.toLowerCase()) + { + case "div": + break; + case "img": + selection = "image"; + controller = "image"; + break; + case "video": + selection = "video"; + controller = "video"; + break; + case "canvas": + isShape = el.getAttribute("data-RDGE-id"); + if(isShape) + { + // TODO - Need more info about the shape + selection = "canvas"; + controller = "shape"; + } + else + { + selection = "canvas"; + controller = "canvas"; + } + break; + case "shape": + break; + } + this.makeElementModel(el, selection, controller, isShape); } }, diff --git a/js/lib/drawing/world.js b/js/lib/drawing/world.js index 3d6c6fc4..df24f556 100755 --- a/js/lib/drawing/world.js +++ b/js/lib/drawing/world.js @@ -4,17 +4,6 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. */ -// Useless Global variables. -// TODO: Remove this as soon as QE test pass -/* -var shaderProgramArray = new Array; -var glContextArray = new Array; -var vertexShaderSource = ""; -var fragmentShaderSource = ""; -var rdgeStarted = false; -*/ - -var nodeCounter = 0; var GeomObj = require("js/lib/geom/geom-obj").GeomObj; var Line = require("js/lib/geom/line").Line; @@ -22,11 +11,13 @@ var Rectangle = require("js/lib/geom/rectangle").Rectangle; var Circle = require("js/lib/geom/circle").Circle; var MaterialsModel = require("js/models/materials-model").MaterialsModel; +var worldCounter = 0; + /////////////////////////////////////////////////////////////////////// // Class GLWorld // Manages display in a canvas /////////////////////////////////////////////////////////////////////// -var World = function GLWorld( canvas, use3D ) { +var World = function GLWorld( canvas, use3D, preserveDrawingBuffer ) { /////////////////////////////////////////////////////////////////////// // Instance variables /////////////////////////////////////////////////////////////////////// @@ -39,7 +30,11 @@ var World = function GLWorld( canvas, use3D ) { this._canvas = canvas; if (this._useWebGL) { - this._glContext = canvas.getContext("experimental-webgl"); + if(preserveDrawingBuffer) { + this._glContext = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true}); + } else { + this._glContext = canvas.getContext("experimental-webgl"); + } } else { this._2DContext = canvas.getContext( "2d" ); } @@ -76,6 +71,12 @@ var World = function GLWorld( canvas, use3D ) { // no animated materials this._firstRender = true; + this._worldCount = worldCounter; + worldCounter++; + + // keep a counter for generating node names + this._nodeCounter = 0; + /////////////////////////////////////////////////////////////////////// // Property accessors /////////////////////////////////////////////////////////////////////// @@ -350,9 +351,12 @@ var World = function GLWorld( canvas, use3D ) { return false; }; - - // END RDGE - //////////////////////////////////////////////////////////////////////////////////// + this.generateUniqueNodeID = function() + { + var str = "" + this._nodeCounter; + this._nodeCounter++; + return str; + } // start RDGE passing your runtime object, and false to indicate we don't need a an initialization state @@ -391,7 +395,7 @@ World.prototype.updateObject = function (obj) { if (nPrims > 0) { ctrTrNode = obj.getTransformNode(); if (ctrTrNode == null) { - ctrTrNode = createTransformNode("objRootNode_" + nodeCounter++); + ctrTrNode = createTransformNode("objRootNode_" + this._nodeCounter++); this._rootNode.insertAsChild( ctrTrNode ); obj.setTransformNode( ctrTrNode ); } @@ -401,7 +405,7 @@ World.prototype.updateObject = function (obj) { }); ctrTrNode.meshes = []; - ctrTrNode.attachMeshNode(this.renderer.id + "_prim_" + nodeCounter++, prims[0]); + ctrTrNode.attachMeshNode(this.renderer.id + "_prim_" + this._nodeCounter++, prims[0]); ctrTrNode.attachMaterial(materialNodes[0]); } @@ -420,12 +424,12 @@ World.prototype.updateObject = function (obj) { }); childTrNode.meshes = []; } else { - childTrNode = createTransformNode("objNode_" + nodeCounter++); + childTrNode = createTransformNode("objNode_" + this._nodeCounter++); ctrTrNode.insertAsChild(childTrNode); } // attach the instanced box goe - childTrNode.attachMeshNode(this.renderer.id + "_prim_" + nodeCounter++, prim); + childTrNode.attachMeshNode(this.renderer.id + "_prim_" + this._nodeCounter++, prim); childTrNode.attachMaterial(materialNodes[i]); } }; @@ -680,7 +684,7 @@ World.prototype.render = function() { var root = this.getGeomRoot(); this.hRender( root ); } else { - g_Engine.setContext( this._canvas.rdgeId ); + g_Engine.setContext( this._canvas.rdgeid ); //this.draw(); this.restartRenderLoop(); } @@ -727,7 +731,8 @@ World.prototype.getShapeFromPoint = function( offsetX, offsetY ) { } }; -World.prototype.export = function() { +World.prototype.export = function() +{ var exportStr = "GLWorld 1.0\n"; var id = this.getCanvas().getAttribute( "data-RDGE-id" ); exportStr += "id: " + id + "\n"; @@ -736,17 +741,29 @@ World.prototype.export = function() { exportStr += "zNear: " + this._zNear + "\n"; exportStr += "zFar: " + this._zFar + "\n"; exportStr += "viewDist: " + this._viewDist + "\n"; + if (this._useWebGL) + exportStr += "webGL: true\n"; // we need 2 export modes: One for save/restore, one for publish. // hardcoding for now - var exportForPublish = false; + //var exportForPublish = false; + //if (!exportForPublish) exportForPublish = false; + var exportForPublish = true; exportStr += "publish: " + exportForPublish + "\n"; - if (exportForPublish) { + if (exportForPublish && this._useWebGL) + { exportStr += "scenedata: " + this.myScene.exportJSON() + "endscene\n"; - } else { + + // write out all of the objects + exportStr += "tree\n"; + exportStr += this.exportObjects( this._geomRoot ); + exportStr += "endtree\n"; + } + else + { // output the material library - exportStr += MaterialsModel.exportMaterials(); + //exportStr += MaterialsLibrary.export(); // THIS NEEDS TO BE DONE AT THE DOC LEVEL // write out all of the objects exportStr += "tree\n"; @@ -800,21 +817,26 @@ World.prototype.import = function( importStr ) { // determine if the data was written for export (no Ninja objects) // or for save/restore - var index = importStr.indexOf( "scenedata: " ); - if (index >= 0) { - var rdgeStr = importStr.substr( index+11 ); - var endIndex = rdgeStr.indexOf( "endscene\n" ); - if (endIndex < 0) throw new Error( "ill-formed WebGL data" ); - var len = endIndex - index + 11; - rdgeStr = rdgeStr.substr( 0, endIndex ); - - this.myScene.importJSON( rdgeStr ); - } else { - // load the material library - importStr = MaterialsModel.importMaterials( importStr ); + //var index = importStr.indexOf( "scenedata: " ); + var index = importStr.indexOf( "webGL: " ); + this._useWebGL = (index >= 0) + if (this._useWebGL) + { + // start RDGE + rdgeStarted = true; + var id = this._canvas.getAttribute( "data-RDGE-id" ); + this._canvas.rdgeid = id; + g_Engine.registerCanvas(this._canvas, this); + RDGEStart( this._canvas ); + this._canvas.task.stop() + } + + this.importObjects( importStr, this._rootNode ); - // import the objects - this.importObjects( importStr, this._rootNode ); + if (!this._useWebGL) + { + // render using canvas 2D + this.render(); } }; diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js index 9a934928..4c42539a 100755 --- a/js/lib/geom/brush-stroke.js +++ b/js/lib/geom/brush-stroke.js @@ -32,13 +32,24 @@ var BrushStroke = function GLBrushStroke() { //stroke information this._strokeWidth = 0.0; this._strokeColor = [0.4, 0.4, 0.4, 1.0]; + this._secondStrokeColor = [1, 0.4, 0.4, 1.0]; + this._strokeHardness = 100; this._strokeMaterial = null; this._strokeStyle = "Solid"; + this._strokeDoSmoothing = false; + this._strokeUseCalligraphic = false; + this._strokeAngle = 0; //the wetness of the brush (currently this is multiplied to the square of the stroke width, but todo should be changed to not depend on stroke width entirely //smaller value means more samples for the path this._WETNESS_FACTOR = 0.25; + //threshold that tells us whether two samples are too far apart + this._MAX_SAMPLE_DISTANCE_THRESHOLD = 5; + + //threshold that tells us whether two samples are too close + this._MIN_SAMPLE_DISTANCE_THRESHOLD = 2; + //prevent extremely long paths that can take a long time to render this._MAX_ALLOWED_SAMPLES = 500; @@ -114,7 +125,7 @@ var BrushStroke = function GLBrushStroke() { //add the point only if it is some epsilon away from the previous point var numPoints = this._Points.length; if (numPoints>0) { - var threshold = this._WETNESS_FACTOR*this._strokeWidth; + var threshold = this._MIN_SAMPLE_DISTANCE_THRESHOLD;//this._WETNESS_FACTOR*this._strokeWidth; var prevPt = this._Points[numPoints-1]; var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); @@ -173,6 +184,26 @@ var BrushStroke = function GLBrushStroke() { this._strokeColor = c; }; + this.setSecondStrokeColor = function(c){ + this._secondStrokeColor=c; + } + + this.setStrokeHardness = function(h){ + this._strokeHardness=h; + } + + this.setDoSmoothing = function(s){ + this._strokeDoSmoothing = s; + } + + this.setStrokeUseCalligraphic = function(c){ + this._strokeUseCalligraphic = c; + } + + this.setStrokeAngle = function(a){ + this._strokeAngle = a; + } + this.getStrokeStyle = function () { return this._strokeStyle; }; @@ -219,7 +250,8 @@ var BrushStroke = function GLBrushStroke() { var numPoints = this._Points.length; //**** add samples to the path if needed...linear interpolation for now - if (numPoints>1) { + //if (numPoints>1) { + if (0){ var threshold = this._WETNESS_FACTOR*this._strokeWidth; var prevPt = this._Points[0]; var prevIndex = 0; @@ -251,6 +283,66 @@ var BrushStroke = function GLBrushStroke() { } } + //todo 4-point subdivision iterations over continuous regions of 'long' segments + // look at http://www.gvu.gatech.edu/~jarek/Split&Tweak/ for formula + //**** add samples to the long sections of the path --- Catmull-Rom spline interpolation + if (this._strokeDoSmoothing && numPoints>1) { + var numInsertedPoints = 0; + var newPoints = []; + var threshold = this._MAX_SAMPLE_DISTANCE_THRESHOLD;//this determines whether a segment between two sample is long enough to warrant checking for angle + var prevPt = this._Points[0]; + newPoints.push(this._Points[0]); + for (var i=1;ithreshold){ + //build the control polygon for the Catmull-Rom spline (prev. 2 points and next 2 points) + var prev = (i===1) ? i-1 : i-2; + var next = (i===numPoints-1) ? i : i+1; + var ctrlPts = [this._Points[prev], this._Points[i-1], this._Points[i], this._Points[next]]; + //insert points along the prev. to current point + var numNewPoints = Math.floor(distance/threshold); + for (var j=0;j this._MAX_ALLOWED_SAMPLES){ + console.log("leaving the resampling because numPoints is greater than limit:"+this._MAX_ALLOWED_SAMPLES); + break; + } + } + this._Points = newPoints; + numPoints = this._Points.length; + console.log("Inserted "+numInsertedPoints+" additional CatmullRom points"); + + //now do 3-4 iterations of Laplacian smoothing (setting the points to the average of their neighbors) + var numLaplacianIterations = 3; //todo figure out the proper number of Laplacian iterations (perhaps as a function of stroke width) + for (var n=0;n0) { + alphaVal = 1.0 - distFromOpaqueRegion/maxTransparentRegionHalfWidth; + alphaVal *= 1.0/ctx.lineWidth; //factor that accounts for lineWidth !== 1 + } - var R2 = this._strokeWidth; - var R = R2*0.5; - var hardness = 0; //for a pencil, this is always 1 //TODO get hardness parameter from user interface - var innerRadius = (hardness*R)-1; - if (innerRadius<1) - innerRadius=1; + ctx.save(); - var r = ctx.createRadialGradient(0,0,innerRadius, 0,0,R); - var midColor = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+",1)"; - r.addColorStop(0, midColor); - var endColor = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+",0.0)"; - r.addColorStop(1, endColor); - ctx.fillStyle = r; + ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; + //linearly interpolate between the two stroke colors + var currStrokeColor = VecUtils.vecInterpolate(4, this._strokeColor, this._secondStrokeColor, t/numTraces); + //ctx.strokeStyle="rgba("+parseInt(255*currStrokeColor[0])+","+parseInt(255*currStrokeColor[1])+","+parseInt(255*currStrokeColor[2])+","+alphaVal+")"; - for (var i = 0; i < numPoints; i++) { - var pt = this._Points[i]; - ctx.globalCompositeOperation = 'source-over'; - var x = pt[0]-bboxMin[0]; - var y = pt[1]-bboxMin[1]; - ctx.save(); - ctx.translate(x,y); - ctx.arc(0, 0, R, 0, 2 * Math.PI, false); - ctx.fill(); - ctx.restore(); - //ctx.globalCompositeOperation = 'source-in'; - //ctx.rect(x-R, y-R, R2, R2); + ctx.translate(disp[0],disp[1]); + ctx.beginPath(); + ctx.moveTo(this._Points[0][0]-bboxMin[0], this._Points[0][1]-bboxMin[1]); + for (var i=0;i */ var MaterialsModel = require("js/models/materials-model").MaterialsModel; +var FlatMaterial = require("js/lib/rdge/materials/flat-material").FlatMaterial; +var LinearGradientMaterial = require("js/lib/rdge/materials/linear-gradient-material").LinearGradientMaterial; +var RadialGradientMaterial = require("js/lib/rdge/materials/radial-gradient-material").RadialGradientMaterial; +var BumpMetalMaterial = require("js/lib/rdge/materials/bump-metal-material").BumpMetalMaterial; +var UberMaterial = require("js/lib/rdge/materials/uber-material").UberMaterial; +var RadialBlurMaterial = require("js/lib/rdge/materials/radial-blur-material").RadialBlurMaterial; +var PlasmaMaterial = require("js/lib/rdge/materials/plasma-material").PlasmaMaterial; +var PulseMaterial = require("js/lib/rdge/materials/pulse-material").PulseMaterial; +var TunnelMaterial = require("js/lib/rdge/materials/tunnel-material").TunnelMaterial; +var ReliefTunnelMaterial = require("js/lib/rdge/materials/relief-tunnel-material").ReliefTunnelMaterial; +var SquareTunnelMaterial = require("js/lib/rdge/materials/square-tunnel-material").SquareTunnelMaterial; +var FlyMaterial = require("js/lib/rdge/materials/fly-material").FlyMaterial; +var WaterMaterial = require("js/lib/rdge/materials/water-material").WaterMaterial; +var ZInvertMaterial = require("js/lib/rdge/materials/z-invert-material").ZInvertMaterial; +var DeformMaterial = require("js/lib/rdge/materials/deform-material").DeformMaterial; +var StarMaterial = require("js/lib/rdge/materials/star-material").StarMaterial; +var TwistMaterial = require("js/lib/rdge/materials/twist-material").TwistMaterial; +var JuliaMaterial = require("js/lib/rdge/materials/julia-material").JuliaMaterial; +var KeleidoscopeMaterial = require("js/lib/rdge/materials/keleidoscope-material").KeleidoscopeMaterial; +var MandelMaterial = require("js/lib/rdge/materials/mandel-material").MandelMaterial; + /////////////////////////////////////////////////////////////////////// // Class GLGeomObj // Super class for all geometry classes @@ -138,22 +159,61 @@ var GeomObj = function GLGeomObj() { // Methods /////////////////////////////////////////////////////////////////////// this.setMaterialColor = function(c, type) { - if (type == "fill") { - this._fillColor = c.slice(0); + var i = 0, + nMats = 0; + if(c.gradientMode) { + // Gradient support + if (this._materialArray && this._materialTypeArray) { + nMats = this._materialArray.length; + } + + var stops = [], + colors = c.color; + + var len = colors.length; + // TODO - Current shaders only support 4 color stops + if(len > 4) { + len = 4; + } + + for(var n=0; nx || this._BBoxMin[1]>y || this._BBoxMin[2]>z){ + return false; + } + if (this._BBoxMax[0]=0 && this._selectedAnchorIndex=0 && selAnchorIndex === -1) { + var distSq = this._Anchors[this._selectedAnchorIndex].getPrevDistanceSq(pickX, pickY, pickZ); + if (distSq < minDistance && distSq < radSq){ + selAnchorIndex = this._selectedAnchorIndex; + minDistance = distSq; + } else { + //check the next for this anchor point + distSq = this._Anchors[this._selectedAnchorIndex].getNextDistanceSq(pickX, pickY, pickZ); + if (distSq