aboutsummaryrefslogtreecommitdiff
path: root/js/lib
diff options
context:
space:
mode:
Diffstat (limited to 'js/lib')
-rwxr-xr-xjs/lib/drawing/world.js18
-rwxr-xr-xjs/lib/geom/brush-stroke.js329
-rwxr-xr-xjs/lib/geom/circle.js95
-rwxr-xr-xjs/lib/geom/geom-obj.js123
-rwxr-xr-xjs/lib/geom/line.js57
-rwxr-xr-xjs/lib/geom/rectangle.js102
-rwxr-xr-xjs/lib/geom/sub-path.js86
7 files changed, 619 insertions, 191 deletions
diff --git a/js/lib/drawing/world.js b/js/lib/drawing/world.js
index 44c9e37d..049145ce 100755
--- a/js/lib/drawing/world.js
+++ b/js/lib/drawing/world.js
@@ -17,7 +17,7 @@ var worldCounter = 0;
17// Class GLWorld 17// Class GLWorld
18// Manages display in a canvas 18// Manages display in a canvas
19/////////////////////////////////////////////////////////////////////// 19///////////////////////////////////////////////////////////////////////
20var World = function GLWorld( canvas, use3D ) { 20var World = function GLWorld( canvas, use3D, preserveDrawingBuffer ) {
21 /////////////////////////////////////////////////////////////////////// 21 ///////////////////////////////////////////////////////////////////////
22 // Instance variables 22 // Instance variables
23 /////////////////////////////////////////////////////////////////////// 23 ///////////////////////////////////////////////////////////////////////
@@ -30,7 +30,11 @@ var World = function GLWorld( canvas, use3D ) {
30 30
31 this._canvas = canvas; 31 this._canvas = canvas;
32 if (this._useWebGL) { 32 if (this._useWebGL) {
33 this._glContext = canvas.getContext("experimental-webgl"); 33 if(preserveDrawingBuffer) {
34 this._glContext = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});
35 } else {
36 this._glContext = canvas.getContext("experimental-webgl");
37 }
34 } else { 38 } else {
35 this._2DContext = canvas.getContext( "2d" ); 39 this._2DContext = canvas.getContext( "2d" );
36 } 40 }
@@ -347,20 +351,18 @@ var World = function GLWorld( canvas, use3D ) {
347 return false; 351 return false;
348 }; 352 };
349 353
350 this.generateUniqueNodeID = function() 354 this.generateUniqueNodeID = function() {
351 {
352 var str = "" + this._nodeCounter; 355 var str = "" + this._nodeCounter;
353 this._nodeCounter++; 356 this._nodeCounter++;
354 return str; 357 return str;
355 } 358 };
356 359
357 360
358 // start RDGE passing your runtime object, and false to indicate we don't need a an initialization state 361 // start RDGE passing your runtime object, and false to indicate we don't need a an initialization state
359 // in the case of a procedurally built scene an init state is not needed for loading data 362 // in the case of a procedurally built scene an init state is not needed for loading data
360 if (this._useWebGL) { 363 if (this._useWebGL) {
361 rdgeStarted = true; 364 rdgeStarted = true;
362 var id = this._canvas.getAttribute( "data-RDGE-id" ); 365 this._canvas.rdgeid = this._canvas.getAttribute( "data-RDGE-id" );
363 this._canvas.rdgeid = id;
364 g_Engine.registerCanvas(this._canvas, this); 366 g_Engine.registerCanvas(this._canvas, this);
365 RDGEStart( this._canvas ); 367 RDGEStart( this._canvas );
366 this._canvas.task.stop() 368 this._canvas.task.stop()
@@ -680,7 +682,7 @@ World.prototype.render = function() {
680 var root = this.getGeomRoot(); 682 var root = this.getGeomRoot();
681 this.hRender( root ); 683 this.hRender( root );
682 } else { 684 } else {
683 g_Engine.setContext( this._canvas.rdgeId ); 685 g_Engine.setContext( this._canvas.rdgeid );
684 //this.draw(); 686 //this.draw();
685 this.restartRenderLoop(); 687 this.restartRenderLoop();
686 } 688 }
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() {
32 //stroke information 32 //stroke information
33 this._strokeWidth = 0.0; 33 this._strokeWidth = 0.0;
34 this._strokeColor = [0.4, 0.4, 0.4, 1.0]; 34 this._strokeColor = [0.4, 0.4, 0.4, 1.0];
35 this._secondStrokeColor = [1, 0.4, 0.4, 1.0];
36 this._strokeHardness = 100;
35 this._strokeMaterial = null; 37 this._strokeMaterial = null;
36 this._strokeStyle = "Solid"; 38 this._strokeStyle = "Solid";
39 this._strokeDoSmoothing = false;
40 this._strokeUseCalligraphic = false;
41 this._strokeAngle = 0;
37 42
38 //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 43 //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
39 //smaller value means more samples for the path 44 //smaller value means more samples for the path
40 this._WETNESS_FACTOR = 0.25; 45 this._WETNESS_FACTOR = 0.25;
41 46
47 //threshold that tells us whether two samples are too far apart
48 this._MAX_SAMPLE_DISTANCE_THRESHOLD = 5;
49
50 //threshold that tells us whether two samples are too close
51 this._MIN_SAMPLE_DISTANCE_THRESHOLD = 2;
52
42 //prevent extremely long paths that can take a long time to render 53 //prevent extremely long paths that can take a long time to render
43 this._MAX_ALLOWED_SAMPLES = 500; 54 this._MAX_ALLOWED_SAMPLES = 500;
44 55
@@ -114,7 +125,7 @@ var BrushStroke = function GLBrushStroke() {
114 //add the point only if it is some epsilon away from the previous point 125 //add the point only if it is some epsilon away from the previous point
115 var numPoints = this._Points.length; 126 var numPoints = this._Points.length;
116 if (numPoints>0) { 127 if (numPoints>0) {
117 var threshold = this._WETNESS_FACTOR*this._strokeWidth; 128 var threshold = this._MIN_SAMPLE_DISTANCE_THRESHOLD;//this._WETNESS_FACTOR*this._strokeWidth;
118 var prevPt = this._Points[numPoints-1]; 129 var prevPt = this._Points[numPoints-1];
119 var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; 130 var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]];
120 var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); 131 var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]);
@@ -173,6 +184,26 @@ var BrushStroke = function GLBrushStroke() {
173 this._strokeColor = c; 184 this._strokeColor = c;
174 }; 185 };
175 186
187 this.setSecondStrokeColor = function(c){
188 this._secondStrokeColor=c;
189 }
190
191 this.setStrokeHardness = function(h){
192 this._strokeHardness=h;
193 }
194
195 this.setDoSmoothing = function(s){
196 this._strokeDoSmoothing = s;
197 }
198
199 this.setStrokeUseCalligraphic = function(c){
200 this._strokeUseCalligraphic = c;
201 }
202
203 this.setStrokeAngle = function(a){
204 this._strokeAngle = a;
205 }
206
176 this.getStrokeStyle = function () { 207 this.getStrokeStyle = function () {
177 return this._strokeStyle; 208 return this._strokeStyle;
178 }; 209 };
@@ -219,7 +250,8 @@ var BrushStroke = function GLBrushStroke() {
219 var numPoints = this._Points.length; 250 var numPoints = this._Points.length;
220 251
221 //**** add samples to the path if needed...linear interpolation for now 252 //**** add samples to the path if needed...linear interpolation for now
222 if (numPoints>1) { 253 //if (numPoints>1) {
254 if (0){
223 var threshold = this._WETNESS_FACTOR*this._strokeWidth; 255 var threshold = this._WETNESS_FACTOR*this._strokeWidth;
224 var prevPt = this._Points[0]; 256 var prevPt = this._Points[0];
225 var prevIndex = 0; 257 var prevIndex = 0;
@@ -251,6 +283,66 @@ var BrushStroke = function GLBrushStroke() {
251 } 283 }
252 } 284 }
253 285
286 //todo 4-point subdivision iterations over continuous regions of 'long' segments
287 // look at http://www.gvu.gatech.edu/~jarek/Split&Tweak/ for formula
288 //**** add samples to the long sections of the path --- Catmull-Rom spline interpolation
289 if (this._strokeDoSmoothing && numPoints>1) {
290 var numInsertedPoints = 0;
291 var newPoints = [];
292 var threshold = this._MAX_SAMPLE_DISTANCE_THRESHOLD;//this determines whether a segment between two sample is long enough to warrant checking for angle
293 var prevPt = this._Points[0];
294 newPoints.push(this._Points[0]);
295 for (var i=1;i<numPoints;i++){
296 var pt = this._Points[i];
297 var diff = [pt[0]-prevPt[0], pt[1]-prevPt[1]];
298 var distance = Math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]);
299 if (distance>threshold){
300 //build the control polygon for the Catmull-Rom spline (prev. 2 points and next 2 points)
301 var prev = (i===1) ? i-1 : i-2;
302 var next = (i===numPoints-1) ? i : i+1;
303 var ctrlPts = [this._Points[prev], this._Points[i-1], this._Points[i], this._Points[next]];
304 //insert points along the prev. to current point
305 var numNewPoints = Math.floor(distance/threshold);
306 for (var j=0;j<numNewPoints;j++){
307 var param = (j+1)/(numNewPoints+1);
308 var newpt = this._CatmullRomSplineInterpolate(ctrlPts, param);
309 //insert new point before point i
310 //this._Points.splice(i, 0, newpt);
311 //i++;
312 newPoints.push(newpt);
313 numInsertedPoints++;
314 }
315 this._dirty=true;
316 }
317 newPoints.push(pt);
318 prevPt=pt;
319 //update numPoints to match the new length
320 numPoints = this._Points.length;
321
322 //end this function if the numPoints has gone above the max. size specified
323 if (numPoints> this._MAX_ALLOWED_SAMPLES){
324 console.log("leaving the resampling because numPoints is greater than limit:"+this._MAX_ALLOWED_SAMPLES);
325 break;
326 }
327 }
328 this._Points = newPoints;
329 numPoints = this._Points.length;
330 console.log("Inserted "+numInsertedPoints+" additional CatmullRom points");
331
332 //now do 3-4 iterations of Laplacian smoothing (setting the points to the average of their neighbors)
333 var numLaplacianIterations = 3; //todo figure out the proper number of Laplacian iterations (perhaps as a function of stroke width)
334 for (var n=0;n<numLaplacianIterations;n++){
335 newPoints = this._Points;
336 for (var i=1;i<numPoints-1;i++){
337 var avgPos = [ 0.5*(this._Points[i-1][0] + this._Points[i+1][0]),
338 0.5*(this._Points[i-1][1] + this._Points[i+1][1]),
339 0.5*(this._Points[i-1][2] + this._Points[i+1][2])] ;
340 newPoints[i] = avgPos;
341 }
342 this._Points = newPoints;
343 }
344 }
345
254 // *** compute the bounding box ********* 346 // *** compute the bounding box *********
255 this._BBoxMin = [Infinity, Infinity, Infinity]; 347