aboutsummaryrefslogtreecommitdiff
path: root/js/lib/geom/brush-stroke.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/lib/geom/brush-stroke.js')
-rwxr-xr-xjs/lib/geom/brush-stroke.js156
1 files changed, 38 insertions, 118 deletions
diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js
index f0925ba5..70429ca9 100755
--- a/js/lib/geom/brush-stroke.js
+++ b/js/lib/geom/brush-stroke.js
@@ -28,20 +28,12 @@ var BrushStroke = function GLBrushStroke() {
28 this._BBoxMax = [0, 0, 0]; 28 this._BBoxMax = [0, 0, 0];
29 this._isDirty = true; 29 this._isDirty = true;
30 this._isInit = false; 30 this._isInit = false;
31 31
32
33 //whether or not to use the canvas drawing to stroke/fill
34 this._useCanvasDrawing = true;
35
36 //the HTML5 canvas that holds this brush stroke 32 //the HTML5 canvas that holds this brush stroke
37 this._canvas = null; 33 this._canvas = null;
38 34
39 //the X and Y location of this brush stroke canvas in stage world space of Ninja
40 this._canvasX = 0;
41 this._canvasY = 0;
42
43 //stroke information 35 //stroke information
44 this._strokeWidth = 0.0; 36 this._strokeWidth = 1.0;
45 this._strokeColor = [0.4, 0.4, 0.4, 1.0]; 37 this._strokeColor = [0.4, 0.4, 0.4, 1.0];
46 this._secondStrokeColor = [1, 0.4, 0.4, 1.0]; 38 this._secondStrokeColor = [1, 0.4, 0.4, 1.0];
47 this._strokeHardness = 100; 39 this._strokeHardness = 100;
@@ -114,22 +106,6 @@ var BrushStroke = function GLBrushStroke() {
114 this._dragPlane = p; 106 this._dragPlane = p;
115 }; 107 };
116 108
117 this.getCanvasX = function(){
118 return this._canvasX;
119 };
120
121 this.getCanvasY = function(){
122 return this._canvasY;
123 };
124
125 this.setCanvasX = function(cx){
126 this._canvasX=cx;
127 };
128
129 this.setCanvasY = function(cy){
130 this._canvasY=cy;
131 };
132
133 this.getNumPoints = function () { 109 this.getNumPoints = function () {
134 return this._Points.length; 110 return this._Points.length;
135 }; 111 };
@@ -190,6 +166,9 @@ var BrushStroke = function GLBrushStroke() {
190 166
191 this.setStrokeWidth = function (w) { 167 this.setStrokeWidth = function (w) {
192 this._strokeWidth = w; 168 this._strokeWidth = w;
169 if (this._strokeWidth<1) {
170 this._strokeWidth = 1;
171 }
193 this._isDirty=true; 172 this._isDirty=true;
194 }; 173 };
195 174
@@ -402,83 +381,37 @@ var BrushStroke = function GLBrushStroke() {
402 this._stageWorldCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); 381 this._stageWorldCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5);
403 382
404 // ***** center the input stageworld data about the center of the bbox ***** 383 // ***** center the input stageworld data about the center of the bbox *****
405 this._LocalPoints = this._Points.slice(0); 384 this._LocalPoints = [];
406 for (i=0;i<numPoints;i++){ 385 for (i=0;i<numPoints;i++){
407 this._LocalPoints[i][0]-= this._stageWorldCenter[0]; 386 var localPoint = [this._Points[i][0],this._Points[i][1],this._Points[i][2]];
408 this._LocalPoints[i][1]-= this._stageWorldCenter[1]; 387 localPoint[0]-= this._stageWorldCenter[0];
409 } 388 localPoint[1]-= this._stageWorldCenter[1];
410 389
411 // ***** unproject all the centered points and convert them to 2D (plane space)***** 390 // ***** unproject all the centered points and convert them to 2D (plane space)*****
412 // (undo the projection step performed by the browser) 391 // (undo the projection step performed by the browser)
413 for (i=0;i<numPoints;i++) { 392 localPoint = this._unprojectPt(localPoint, 1400); //todo get the perspective distance from the canvas
414 this._LocalPoints[i] = this._unprojectPt(this._LocalPoints[i], 1400); //todo get the perspective distance from the canvas 393 localPoint = MathUtils.transformPoint(localPoint, this._planeMatInv);
415 this._LocalPoints[i] = MathUtils.transformPoint(this._LocalPoints[i], this._planeMatInv); 394
395 //add to the list of local points
396 this._LocalPoints.push(localPoint);
416 } 397 }
417 398
418 // ***** compute width, height, and midpoint position (in stage world position) of the canvas 399 // ***** compute width, height, and midpoint position (in stage world position) of the canvas
419 this._updateBoundingBox(); //compute the bbox to obtain the width and height used below 400 this._updateBoundingBox(); //compute the bbox to obtain the width and height used below
420 var halfwidth = 0.5*(this._BBoxMax[0]-this._BBoxMin[0]); 401 var halfwidth = 0.5*(this._BBoxMax[0]-this._BBoxMin[0]);
421 var halfheight = 0.5*(this._BBoxMax[1]-this._BBoxMin[1]); 402 var halfheight = 0.5*(this._BBoxMax[1]-this._BBoxMin[1]);
403 this._OrigPoints = [];
422 for (i=0;i<numPoints;i++) { 404 for (i=0;i<numPoints;i++) {
423 this._LocalPoints[i][0]+= halfwidth; 405 this._LocalPoints[i][0]+= halfwidth;
424 this._LocalPoints[i][1]+= halfheight; 406 this._LocalPoints[i][1]+= halfheight;
425 }
426 //store the original points
427 this._OrigPoints = this._LocalPoints.slice(0);
428
429 //var midPt = stageWorldBBoxCenter; //todo should I compute the instead as the midpoint of the plane-space bbox, transformed by this._planeMat
430 // The following offset seems to not match what was being done successfully for the brush tool, so I'm commenting this out
431 // the mid point is now relative to the center of the 3D space. To
432 // calculate the left and top offsets, this must be offset by the stage dimensions
433 //var wh = ViewUtils.getStageDimension();
434 //midPt[0] += wh[0]/ 2.0;
435 //midPt[1] += wh[1]/ 2.0;
436 };
437 /*this.translate = function (tx, ty, tz) {
438 for (var i=0;i<this._Points.length;i++){
439 this._Points[i][0]+=tx;
440 this._Points[i][1]+=ty;
441 this._Points[i][2]+=tz;
442 }
443 this._isDirty = true;
444 };*/
445
446 //build coordinates for the brush stroke in local space of the canvas...will assume that the canvas width, height, left and top will not be changed now
447 this.buildLocalCoord = function(){
448 /*
449 if (this._isLocalDirty) {
450 //DEBUGGING
451 //confirm that localToStageWorld produces the same coordinates as those I used for rendering currently
452 var numPoints = this._Points.length;
453 var objToStageWorldMat = ViewUtils.getObjToStageWorldMatrix(this._canvas, true);
454 var stageworldToObjMat = glmat4.inverse(objToStageWorldMat, []);
455 var wh = ViewUtils.getStageDimension();
456 for (var i=0;i<numPoints;i++) {
457 var origStageWorldPt = this._Points[i];
458 //var localPt = [origStageWorldPt[0]-bboxMin[0], origStageWorldPt[1]-bboxMin[1],0]; //this is how the brush tool currently renders points in stage world
459
460 //check using ObjToStageWorldMatrix --- works
461 //var tmp = MathUtils.transformHomogeneousPoint(localPt,objToStageWorldMat);
462 //var newStageWorldPt = MathUtils.applyHomogeneousCoordinate(tmp);
463 //newStageWorldPt = VecUtils.vecAdd(3, newStageWorldPt, [wh[0]/2, wh[1]/2, 0]);
464 //var diffPt = VecUtils.vecDist(3,origStageWorldPt,newStageWorldPt);
465
466 //now go the other way, to recover localPt
467 var offsetedStageWorldPt = VecUtils.vecSubtract(3, origStageWorldPt, [wh[0]/2, wh[1]/2, 0]);
468 var tmp = MathUtils.transformHomogeneousPoint(offsetedStageWorldPt,stageworldToObjMat);
469 var newLocalPt = MathUtils.applyHomogeneousCoordinate(tmp);
470 //var diffPt2 = VecUtils.vecDist(3,localPt,newLocalPt);
471 this._LocalPoints[i] = newLocalPt;
472 }
473 407
474 408 //store the original points
475 //end DEBUGGING 409 this._OrigPoints.push([this._LocalPoints[i][0],this._LocalPoints[i][1],this._LocalPoints[i][2]]);
476 this._isLocalDirty=false; 410 }
477 } //if this._isLocalDirty 411 //update the bbox with the same adjustment as was made for the local points above
478 */ 412 this._BBoxMax[0]+= halfwidth;this._BBoxMin[0]+= halfwidth;
413 this._BBoxMax[1]+= halfheight;this._BBoxMin[1]+= halfheight;
479 }; 414 };
480
481
482 415
483 this.update = function() { 416 this.update = function() {
484 if (this._isDirty){ 417 if (this._isDirty){
@@ -486,10 +419,10 @@ var BrushStroke = function GLBrushStroke() {
486 this._doSmoothing(); 419 this._doSmoothing();
487 420
488 // **** recompute the bounding box **** 421 // **** recompute the bounding box ****
489 var deltaWH = this._updateBoundingBox(); 422 this._updateBoundingBox();
490 423
491 // **** offset the local coords to account for the change in bbox **** 424 // **** offset the local coords to account for the change in bbox ****
492 this._offsetLocalCoord(deltaWH[0]*0.5, deltaWH[1]*0.5); 425 this._offsetLocalCoord(-this._BBoxMin[0], -this._BBoxMin[1]);
493 426
494 // **** turn off the dirty flag **** 427 // **** turn off the dirty flag ****
495 this._isDirty = false; 428 this._isDirty = false;
@@ -503,21 +436,30 @@ var BrushStroke = function GLBrushStroke() {
503 this._LocalPoints[i][1]+= deltaH; 436 this._LocalPoints[i][1]+= deltaH;
504 } 437 }
505 }; 438 };
439
440 //I had to write this function to do a deep copy because I think slice(0) creates a copy by reference
441 this._copyCoordinates3D = function(srcCoord, destCoord){
442 var i=0;
443 var numPoints = srcCoord.length;
444 for (i=0;i<numPoints;i++){
445 destCoord[i] = [srcCoord[i][0],srcCoord[i][1],srcCoord[i][2]];
446 }
447 };
506 this._doSmoothing = function() { 448 this._doSmoothing = function() {
507 var numPoints = this._LocalPoints.length; 449 var numPoints = this._LocalPoints.length;
508 if (this._strokeDoSmoothing && numPoints>1) { 450 if (this._strokeDoSmoothing && numPoints>1) {
509 this._LocalPoints = this._OrigPoints.slice(0); 451 this._copyCoordinates3D(this._OrigPoints, this._LocalPoints);
510 //iterations of Laplacian smoothing (setting the points to the average of their neighbors) 452 //iterations of Laplacian smoothing (setting the points to the average of their neighbors)
511 var numLaplacianIterations = this._strokeAmountSmoothing; 453 var numLaplacianIterations = this._strokeAmountSmoothing;
512 for (var n=0;n<numLaplacianIterations;n++){ 454 for (var n=0;n<numLaplacianIterations;n++){
513 var newPoints = this._LocalPoints;//.slice(0); 455 var newPoints = this._LocalPoints.slice(0); //I think this performs a copy by reference, which would make the following a SOR step
514 for (var i=1;i<numPoints-1;i++) { 456 for (var i=1;i<numPoints-1;i++) {
515 var avgPos = [ 0.5*(this._LocalPoints[i-1][0] + this._LocalPoints[i+1][0]), 457 var avgPos = [ 0.5*(this._LocalPoints[i-1][0] + this._LocalPoints[i+1][0]),
516 0.5*(this._LocalPoints[i-1][1] + this._LocalPoints[i+1][1]), 458 0.5*(this._LocalPoints[i-1][1] + this._LocalPoints[i+1][1]),
517 0.5*(this._LocalPoints[i-1][2] + this._LocalPoints[i+1][2])] ; 459 0.5*(this._LocalPoints[i-1][2] + this._LocalPoints[i+1][2])] ;
518 newPoints[i] = avgPos; 460 newPoints[i] = avgPos;
519 } 461 }
520 this._LocalPoints = newPoints;//.slice(0); 462 this._LocalPoints = newPoints.slice(0);
521 }