diff options
author | Pushkar Joshi | 2012-04-17 17:38:36 -0700 |
---|---|---|
committer | Pushkar Joshi | 2012-04-17 17:38:36 -0700 |
commit | 5bac19550ae74bb5561d1e1fbb55bdac8c5e3dd1 (patch) | |
tree | f35c79ef130968360f00c8d015f70141d44fa57d | |
parent | 2165b91022d3585720db881cf97bc971eb7fcce8 (diff) | |
download | ninja-5bac19550ae74bb5561d1e1fbb55bdac8c5e3dd1.tar.gz |
Fairly stable version of polyline drawing code that works for paths on XY, YZ, XZ planes.
Current bugs: if the new point increases the bbox of the canvas, the entire canvas is shifted (due to inconsistency with center of rotation) AND the first two points added to planes other than XY have incorrect local coordinates (due to missing local coordinates)
-rwxr-xr-x | js/tools/PenTool.js | 97 |
1 files changed, 32 insertions, 65 deletions
diff --git a/js/tools/PenTool.js b/js/tools/PenTool.js index 7bc0364e..8abb41ef 100755 --- a/js/tools/PenTool.js +++ b/js/tools/PenTool.js | |||
@@ -735,87 +735,54 @@ exports.PenTool = Montage.create(ShapeTool, { | |||
735 | var currAnchor = null; | 735 | var currAnchor = null; |
736 | var xAdjustment = snapManager.getStageWidth()*0.5; | 736 | var xAdjustment = snapManager.getStageWidth()*0.5; |
737 | var yAdjustment = snapManager.getStageHeight()*0.5; | 737 | var yAdjustment = snapManager.getStageHeight()*0.5; |
738 | var localPos = [[0,0,0,0],[0,0,0,0],[0,0,0,0]]; | 738 | |
739 | //if there already is a subpath canvas, it means the anchor points are in local space | ||
740 | // so convert them to stage world space | ||
741 | var numAnchors = this._selectedSubpath.getNumAnchors(); | 739 | var numAnchors = this._selectedSubpath.getNumAnchors(); |
740 | var bboxMin=null, bboxMax=null; | ||
742 | if (this._selectedSubpathCanvas) { | 741 | if (this._selectedSubpathCanvas) { |
743 | //this transformation will take the path points from local space to stage world space | 742 | //if there already is a subpath canvas, it means the anchor points are in local space |
744 | // *without* taking into account the transformation applied to this canvas | 743 | // so convert them to stage world space |
745 | // (this is because we use the center of the bbox to find a place for the canvas) | 744 | //compute the bbox in local space |
746 | var localToStageWorldMat = ViewUtils.getObjToStageWorldMatrix(this._selectedSubpathCanvas, false);//ViewUtils.getLocalToStageWorldMatrix(this._selectedSubpathCanvas, true, false); | 745 | this._selectedSubpath.createSamples(false); |
747 | for (i=0;i<numAnchors;i++){ | 746 | bboxMin = this._selectedSubpath.getBBoxMin(); |
748 | //convert this anchor from local to stage world | 747 | bboxMax = this._selectedSubpath.getBBoxMax(); |
749 | var currAnchor = this._selectedSubpath.getAnchor(i); | 748 | |
750 | localPos[0] = [currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPrevZ(),1]; | 749 | // *********** Test for Too Large Canvas ************* |
751 | localPos[1] = [currAnchor.getPosX(), currAnchor.getPosY(), currAnchor.getPosZ(),1]; | 750 | //check if the last point added made this canvas is now bigger than the max canvas size |
752 | localPos[2] = [currAnchor.getNextX(), currAnchor.getNextY(), currAnchor.getNextZ(),1]; | 751 | var canvasTooLarge = false; |
753 | for (d=0;d<3;d++) { | 752 | for (d=0;d<3;d++){ |
754 | localPos[d] = MathUtils.transformAndDivideHomogeneousPoint(localPos[d], localToStageWorldMat); | 753 | if (bboxMax[d]-bboxMin[d]>this._MAX_CANVAS_DIMENSION){ |
755 | //add half the stage width and height to the X and Y coord. | 754 | canvasTooLarge = true; |
756 | localPos[d][0]+= xAdjustment; | ||
757 | localPos[d][1]+= yAdjustment; | ||
758 | } | 755 | } |
759 | currAnchor.setPrevPos(localPos[0][0],localPos[0][1],localPos[0][2]); | ||
760 | currAnchor.setPos(localPos[1][0],localPos[1][1],localPos[1][2]); | ||
761 | currAnchor.setNextPos(localPos[2][0],localPos[2][1],localPos[2][2]); | ||
762 | } | 756 | } |
763 | this._selectedSubpath.makeDirty(); | 757 | if (canvasTooLarge){ |
764 | } | ||
765 | |||
766 | //compute the bbox in stage-world space | ||
767 | this._selectedSubpath.createSamples(true); //we need to compute samples to get the bounding box center in stage world space | ||
768 | var bboxMin = this._selectedSubpath.getBBoxMin(); | ||
769 | var bboxMax = this._selectedSubpath.getBBoxMax(); | ||
770 | |||
771 | //check if the last point added made this canvas is now bigger than the max canvas size | ||
772 | for (d=0;d<3;d++){ | ||
773 | if (bboxMax[d]-bboxMin[d]>this._MAX_CANVAS_DIMENSION){ | ||
774 | console.log("PEN: Warning! Ignoring last added point because canvas size too large"); | 758 | console.log("PEN: Warning! Ignoring last added point because canvas size too large"); |
775 | this._selectedSubpath.removeAnchor(numAnchors-1); | 759 | this._selectedSubpath.removeAnchor(numAnchors-1); |
776 | numAnchors--; | 760 | numAnchors--; |
761 | |||
777 | //recompute the bbox of this subpath | 762 | //recompute the bbox of this subpath |
778 | this._selectedSubpath.createSamples(true); | 763 | this._selectedSubpath.createSamples(false); |
779 | bboxMin = this._selectedSubpath.getBBoxMin(); | 764 | bboxMin = this._selectedSubpath.getBBoxMin(); |
780 | bboxMax = this._selectedSubpath.getBBoxMax(); | 765 | bboxMax = this._selectedSubpath.getBBoxMax(); |
781 | break; | ||
782 | } | 766 | } |
783 | } | ||
784 | 767 | ||
768 | //convert the midpoint of this bbox to stage world space | ||
769 | var bboxMid = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); | ||
770 | //this._selectedSubpathCanvasCenter = ViewUtils.localToStageWorld(bboxMid, this._selectedSubpathCanvas); | ||
771 | var localToStageWorldMat = ViewUtils.getLocalToStageWorldMatrix(this._selectedSubpathCanvas, false, false); | ||
772 | this._selectedSubpathCanvasCenter = MathUtils.transformAndDivideHomogeneousPoint(bboxMid, localToStageWorldMat); | ||
773 | this._selectedSubpathCanvasCenter[0]+= xAdjustment; | ||
774 | this._selectedSubpathCanvasCenter[1]+= yAdjustment; | ||
775 | } else { | ||
776 | //compute the bbox in stage-world space (the points are already in stage world space) | ||
777 | this._selectedSubpath.createSamples(true); | ||
778 | bboxMin = this._selectedSubpath.getBBoxMin(); | ||
779 | bboxMax = this._selectedSubpath.getBBoxMax(); | ||
780 | this._selectedSubpathCanvasCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); | ||
785 | 781 | ||
786 | this._selectedSubpathCanvasCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); | 782 | //todo convert the path points into local coordinates |
787 | 783 | ||
788 | //update the plane matrix of this subpath by querying the element mediator | ||
789 | if (this._selectedSubpathCanvas) { | ||
790 | this._selectedSubpathPlaneMat = ElementMediator.getMatrix(this._selectedSubpathCanvas); | ||
791 | } | 784 | } |
792 | var planeMatInv = glmat4.inverse(this._selectedSubpathPlaneMat, []); | ||
793 | |||
794 | // ***** compute local coordinates of the anchor points ***** | ||
795 | for (i=0;i<numAnchors;i++){ | ||
796 | var currAnchor = this._selectedSubpath.getAnchor(i); | ||
797 | |||
798 | localPos[0] = [currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPrevZ(),1]; | ||
799 | localPos[1] = [currAnchor.getPosX(), currAnchor.getPosY(), currAnchor.getPosZ(),1]; | ||
800 | localPos[2] = [currAnchor.getNextX(), currAnchor.getNextY(), currAnchor.getNextZ(),1]; | ||
801 | for (d=0;d<3;d++) { | ||
802 | localPos[d][0]-= this._selectedSubpathCanvasCenter[0]; | ||
803 | localPos[d][1]-= this._selectedSubpathCanvasCenter[1]; | ||
804 | localPos[d][2]-= this._selectedSubpathCanvasCenter[2]; | ||
805 | |||
806 | // ***** unproject all the centered points and convert them to 2D (plane space)***** | ||
807 | // (undo the projection step performed by the browser) | ||
808 | localPos[d] = this._unprojectPt(localPos[d], 1400); //todo get the perspective distance from the canvas | ||
809 | localPos[d] = MathUtils.transformPoint(localPos[d], planeMatInv); | ||
810 | |||
811 | //explicitly remove the third (Z) component since it should always be zero | ||
812 | localPos[d][2]=0; | ||
813 | } | ||
814 | 785 | ||
815 | currAnchor.setPrevPos(localPos[0][0],localPos[0][1],localPos[0][2]); | ||
816 | currAnchor.setPos(localPos[1][0],localPos[1][1],localPos[1][2]); | ||
817 | currAnchor.setNextPos(localPos[2][0],localPos[2][1],localPos[2][2]); | ||
818 | } | ||
819 | this._selectedSubpath.makeDirty(); | 786 | this._selectedSubpath.makeDirty(); |
820 | this._selectedSubpath.createSamples(false); | 787 | this._selectedSubpath.createSamples(false); |
821 | this._selectedSubpath.offsetPerBBoxMin(); | 788 | this._selectedSubpath.offsetPerBBoxMin(); |