aboutsummaryrefslogtreecommitdiff
path: root/js/helper-classes/RDGE/GLSubpath.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/helper-classes/RDGE/GLSubpath.js')
-rw-r--r--js/helper-classes/RDGE/GLSubpath.js2317
1 files changed, 887 insertions, 1430 deletions
diff --git a/js/helper-classes/RDGE/GLSubpath.js b/js/helper-classes/RDGE/GLSubpath.js
index 55b7e49a..3200cf59 100644
--- a/js/helper-classes/RDGE/GLSubpath.js
+++ b/js/helper-classes/RDGE/GLSubpath.js
@@ -4,7 +4,7 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot
4(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. 4(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
5</copyright> */ 5</copyright> */
6 6
7// Todo: This shoudl be converted to a module 7// Todo: This entire class should be converted to a module
8var VecUtils = require("js/helper-classes/3D/vec-utils").VecUtils; 8var VecUtils = require("js/helper-classes/3D/vec-utils").VecUtils;
9 9
10 10
@@ -35,6 +35,7 @@ function SegmentIntersections(){
35// representation a sequence of cubic bezier curves. 35// representation a sequence of cubic bezier curves.
36// Derived from class GLGeomObj 36// Derived from class GLGeomObj
37/////////////////////////////////////////////////////////////////////// 37///////////////////////////////////////////////////////////////////////
38
38function GLSubpath() { 39function GLSubpath() {
39 /////////////////////////////////////////////////// 40 ///////////////////////////////////////////////////
40 // Instance variables 41 // Instance variables
@@ -50,14 +51,6 @@ function GLSubpath() {
50 51
51 this._UnprojectedAnchors = []; 52 this._UnprojectedAnchors = [];
52 53
53 //offset path samples and the points on the input path they map to
54 this._offsetPointsLeft = [];
55 this._offsetPointsRight = [];
56
57 //triangles determined by the offset points
58 this._offsetTrianglesLeft = [];
59 this._offsetTrianglesRight = [];
60
61 //initially set the _dirty bit so we will construct samples 54 //initially set the _dirty bit so we will construct samples
62 this._dirty = true; 55 this._dirty = true;
63 56
@@ -88,7 +81,6 @@ function GLSubpath() {
88 this._planeMatInv = null; 81 this._planeMatInv = null;
89 this._planeCenter = null; 82 this._planeCenter = null;
90 83
91 // initialize the inherited members
92 this.inheritedFrom = GLGeomObj; 84 this.inheritedFrom = GLGeomObj;
93 this.inheritedFrom(); 85 this.inheritedFrom();
94 86
@@ -105,681 +97,545 @@ function GLSubpath() {
105 this._DEFAULT_STROKE_WIDTH = 20; //use only if stroke width not specified 97 this._DEFAULT_STROKE_WIDTH = 20; //use only if stroke width not specified
106 this._MAX_OFFSET_ANGLE = 10; //max angle (in degrees) between consecutive vectors from curve to offset path 98 this._MAX_OFFSET_ANGLE = 10; //max angle (in degrees) between consecutive vectors from curve to offset path
107 99
108 ///////////////////////////////////////////////////////// 100 // (current GLGeomObj complains if buildBuffers/render is added to GLSubpath prototype)
109 // Property Accessors/Setters 101 //buildBuffers
110 ///////////////////////////////////////////////////////// 102 // Build the stroke vertices, normals, textures and colors
111 this.setWorld = function (world) { this._world = world; } 103 // Add that array data to the GPU using OpenGL data binding
112 this.getWorld = function () { return this._world; } 104 this.buildBuffers = function () {
113 this.makeDirty = function () {this._dirty = true;} 105 return; //no need to do anything for now
114 this.geomType = function () { return this.GEOM_TYPE_CUBIC_BEZIER; } 106 }//buildBuffers()
115 this.setDrawingTool = function (tool) {this._drawingTool = tool;}
116 this.getDrawingTool = function () {return this._drawingTool;}
117 this.setPlaneMatrix = function(planeMat){this._planeMat = planeMat;}
118 this.setPlaneMatrixInverse = function(planeMatInv){this._planeMatInv = planeMatInv;}
119 this.setPlaneCenter = function(pc){this._planeCenter = pc;}
120
121 this.getCanvasX = function(){return this._canvasX;}
122 this.getCanvasY = function(){return this._canvasY;}
123 this.setCanvasX = function(cx){this._canvasX=cx;}
124 this.setCanvasY = function(cy){this._canvasY=cy;}
125
126 this.getIsClosed = function () {return this._isClosed;}
127 this.setIsClosed = function (isClosed) {
128 if (this._isClosed !== isClosed) {
129 this._isClosed = isClosed;
130 this._dirty = true;
131 }
132 }
133 this.getNumAnchors = function () { return this._Anchors.length; }
134 this.getAnchor = function (index) { return this._Anchors[index]; }
135 this.addAnchor = function (anchorPt) {
136 this._Anchors.push(anchorPt);
137 this._selectedAnchorIndex = this._Anchors.length-1;
138 this._dirty = true;
139 }
140 107
141 this.insertAnchor = function(anchorPt, index){ 108 //render
142 this._Anchors.splice(index, 0, anchorPt); 109 // specify how to render the subpath in Canvas2D
143 } 110 this.render = function () {
111 // get the world
112 var world = this.getWorld();
113 if (!world) throw( "null world in subpath render" );
144 114
145 //remove and return anchor at specified index, return null on error 115 // get the context
146 this.removeAnchor = function (index) { 116 var ctx = world.get2DContext();
147 var retAnchor = null; 117 if (!ctx) throw ("null context in subpath render")
148 if (index < this._Anchors.length) {
149 retAnchor = this._Anchors.splice(index, 1);
150 this._dirty = true;
151 }
152 //deselect the removed anchor if necessary
153 if (this._selectedAnchorIndex === index){
154 this._selectedAnchorIndex = -1;
155 }
156 return retAnchor;
157 }
158 118
159 //remove all the anchor points 119 var numAnchors = this.getNumAnchors();
160 this.clearAllAnchors = function () { 120 if (numAnchors === 0)
161 this._Anchors = []; 121 return; //nothing to do for empty paths
162 this._isClosed = false;
163 this._dirty = true;
164 }
165 122
166 this.insertAnchorAtParameter = function(index, param) { 123 ctx.save();
167 if (index+1 >= this._Anchors.length && !this._isClosed) {
168 return;
169 }
170 //insert an anchor after the specified index using the parameter, using De Casteljau subdivision
171 var nextIndex = (index+1)%this._Anchors.length;
172 124
173 //build the De Casteljau points 125 this.createSamples(); //dirty bit checked in this function...will generate a polyline representation
174 var P0P1 = VecUtils.vecInterpolate(3, this._Anchors[index].getPos(), this._Anchors[index].getNext(), param); 126 var bboxMin = this.getBBoxMin();
175 var P1P2 = VecUtils.vecInterpolate(3, this._Anchors[index].getNext(), this._Anchors[nextIndex].getPrev(), param); 127 var bboxMax = this.getBBoxMax();
176 var P2P3 = VecUtils.vecInterpolate(3, this._Anchors[nextIndex].getPrev(), this._Anchors[nextIndex].getPos(), param); 128 var bboxWidth = bboxMax[0] - bboxMin[0];
129 var bboxHeight = bboxMax[1] - bboxMin[1];
130 var bboxMid = Vector.create([0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])]);
177 131
178 var P0P1P2 = VecUtils.vecInterpolate(3, P0P1, P1P2, param); 132 ctx.clearRect(0, 0, bboxWidth, bboxHeight);
179 var P1P2P3 = VecUtils.vecInterpolate(3, P1P2, P2P3, param);
180 var anchorPos = VecUtils.vecInterpolate(3, P0P1P2, P1P2P3, param);
181 133
182 134
183 //update the next of the anchor at index and prev of anchor at nextIndex 135 ctx.lineWidth = this._strokeWidth;
184 var isPrevCoincident = false; 136 ctx.strokeStyle = "black";
185 var isNextCoincident = false; 137 if (this._strokeColor)
186 if (VecUtils.vecDist( 3, P0P1, this._Anchors[index].getNext()) < this._SAMPLING_EPSILON) { 138 ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor );
187 //no change to the next point 139 ctx.fillStyle = "white";
188 isPrevCoincident = true; 140 if (this._fillColor){
189 } else { 141 //ctx.fillStyle = MathUtils.colorToHex( this._fillColor );
190 this._Anchors[index].setNextPos(P0P1[0], P0P1[1], P0P1[2]); 142 var fillColorStr = "rgba("+parseInt(255*this._fillColor[0])+","+parseInt(255*this._fillColor[1])+","+parseInt(255*this._fillColor[2])+","+this._fillColor[3]+")";
143 ctx.fillStyle = fillColorStr;
191 } 144 }
145 var lineCap = ['butt','round','square'];
146 ctx.lineCap = lineCap[1];
147 ctx.beginPath();
192 148
193 if (VecUtils.vecDist( 3, P2P3, this._Anchors[nextIndex].getPrev()) < this._SAMPLING_EPSILON) { 149 /*
194 //no change to the prev point 150 commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered
195 isNextCoincident = true; 151 var prevAnchor = this.getAnchor(0);
196 } else { 152 ctx.moveTo(prevAnchor.getPosX()-bboxMin[0],prevAnchor.getPosY()-bboxMin[1]);
197 this._Anchors[nextIndex].setPrevPos(P2P3[0], P2P3[1], P2P3[2]); 153 for (var i = 1; i < numAnchors; i++) {
154 var currAnchor = this.getAnchor(i);
155 ctx.bezierCurveTo(prevAnchor.getNextX()-bboxMin[0],prevAnchor.getNextY()-bboxMin[1], currAnchor.getPrevX()-bboxMin[0], currAnchor.getPrevY()-bboxMin[1], currAnchor.getPosX()-bboxMin[0], currAnchor.getPosY()-bboxMin[1]);
156 prevAnchor = currAnchor;
157 }
158 if (this._isClosed === true) {
159 var currAnchor = this.getAnchor(0);
160 ctx.bezierCurveTo(prevAnchor.getNextX()-bboxMin[0],prevAnchor.getNextY()-bboxMin[1], currAnchor.getPrevX()-bboxMin[0], currAnchor.getPrevY()-bboxMin[1], currAnchor.getPosX()-bboxMin[0], currAnchor.getPosY()-bboxMin[1]);
161 prevAnchor = currAnchor;
162 ctx.fill();
198 } 163 }
164 */
199 165
200 //create a new anchor point
201 var newAnchor = new GLAnchorPoint();
202 166
203 if (isPrevCoincident && isNextCoincident){ 167 var numPoints = this._samples.length/3;
204 anchorPos[0]=P1P2[0];anchorPos[1]=P1P2[1];anchorPos[2]=P1P2[2]; 168 ctx.moveTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]);
205 newAnchor.setPos(anchorPos[0],anchorPos[1],anchorPos[2]); 169 for (var i=0;i<numPoints;i++){
206 newAnchor.setPrevPos(anchorPos[0],anchorPos[1],anchorPos[2]); 170 ctx.lineTo(this._samples[3*i]-bboxMin[0],this._samples[3*i + 1]-bboxMin[1]);
207 newAnchor.setNextPos(anchorPos[0],anchorPos[1],anchorPos[2]);
208 } else {
209 newAnchor.setPrevPos(P0P1P2[0], P0P1P2[1], P0P1P2[2]);
210 newAnchor.setNextPos(P1P2P3[0], P1P2P3[1], P1P2P3[2]);
211 newAnchor.setPos(anchorPos[0], anchorPos[1], anchorPos[2]);
212 } 171 }
172 if (this._isClosed === true) {
173 ctx.lineTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]);
174 }
175 ctx.fill();
176 ctx.stroke();
177 ctx.restore();
178 } //render()
179
180 this.geomType = function () { return this.GEOM_TYPE_CUBIC_BEZIER; }
181} //function GLSubpath ...class definition
182
183
184
185
213 186
214