diff options
Diffstat (limited to 'js/lib/geom/brush-stroke.js')
-rwxr-xr-x | js/lib/geom/brush-stroke.js | 482 |
1 files changed, 482 insertions, 0 deletions
diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js new file mode 100755 index 00000000..9a934928 --- /dev/null +++ b/js/lib/geom/brush-stroke.js | |||
@@ -0,0 +1,482 @@ | |||
1 | /* <copyright> | ||
2 | This file contains proprietary software owned by Motorola Mobility, Inc.<br/> | ||
3 | No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> | ||
4 | (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. | ||
5 | </copyright> */ | ||
6 | |||
7 | // Todo: This entire class should be converted to a module | ||
8 | var VecUtils = require("js/helper-classes/3D/vec-utils").VecUtils; | ||
9 | var GeomObj = require("js/lib/geom/geom-obj").GeomObj; | ||
10 | |||
11 | /////////////////////////////////////////////////////////////////////// | ||
12 | // Class GLBrushStroke | ||
13 | // representation a sequence points (polyline) created by brush tool. | ||
14 | // Derived from class GLGeomObj | ||
15 | /////////////////////////////////////////////////////////////////////// | ||
16 | var BrushStroke = function GLBrushStroke() { | ||
17 | /////////////////////////////////////////////////// | ||
18 | // Instance variables | ||
19 | /////////////////////////////////////////////////// | ||
20 | this._Points = []; | ||
21 | this._BBoxMin = [0, 0, 0]; | ||
22 | this._BBoxMax = [0, 0, 0]; | ||
23 | this._dirty = true; | ||
24 | |||
25 | //whether or not to use the canvas drawing to stroke/fill | ||
26 | this._useCanvasDrawing = true; | ||
27 | |||
28 | //the X and Y location of this subpath's canvas in stage world space of Ninja | ||
29 | this._canvasX = 0; | ||
30 | this._canvasY = 0; | ||
31 | |||
32 | //stroke information | ||
33 | this._strokeWidth = 0.0; | ||
34 | this._strokeColor = [0.4, 0.4, 0.4, 1.0]; | ||
35 | this._strokeMaterial = null; | ||
36 | this._strokeStyle = "Solid"; | ||
37 | |||
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 | ||
39 | //smaller value means more samples for the path | ||
40 | this._WETNESS_FACTOR = 0.25; | ||
41 | |||
42 | //prevent extremely long paths that can take a long time to render | ||
43 | this._MAX_ALLOWED_SAMPLES = 500; | ||
44 | |||
45 | //drawing context | ||
46 | this._world = null; | ||
47 | |||
48 | //tool that owns this brushstroke | ||
49 | this._drawingTool = null; | ||
50 | this._planeMat = null; | ||
51 | this._planeMatInv = null; | ||
52 | this._planeCenter = null; | ||
53 | |||
54 | ///////////////////////////////////////////////////////// | ||
55 | // Property Accessors/Setters | ||
56 | ///////////////////////////////////////////////////////// | ||
57 | this.setWorld = function (world) { | ||
58 | this._world = world; | ||
59 | }; | ||
60 | |||
61 | this.getWorld = function () { | ||
62 | return this._world; | ||
63 | }; | ||
64 | |||
65 | this.geomType = function () { | ||
66 | return this.GEOM_TYPE_CUBIC_BEZIER; | ||
67 | }; | ||
68 | |||
69 | this.setDrawingTool = function (tool) { | ||
70 | this._drawingTool = tool; | ||
71 | }; | ||
72 | |||
73 | this.getDrawingTool = function () { | ||
74 | return this._drawingTool; | ||
75 | }; | ||
76 | |||
77 | this.setPlaneMatrix = function(planeMat){ | ||
78 | this._planeMat = planeMat; | ||
79 | }; | ||
80 | |||
81 | this.setPlaneMatrixInverse = function(planeMatInv){ | ||
82 | this._planeMatInv = planeMatInv; | ||
83 | }; | ||
84 | |||
85 | this.setPlaneCenter = function(pc){ | ||
86 | this._planeCenter = pc; | ||
87 | }; | ||
88 | |||
89 | this.getCanvasX = function(){ | ||
90 | return this._canvasX; | ||
91 | }; | ||
92 | |||
93 | this.getCanvasY = function(){ | ||
94 | return this._canvasY; | ||
95 | }; | ||
96 | |||
97 | this.setCanvasX = function(cx){ | ||
98 | this._canvasX=cx; | ||
99 | }; | ||
100 | |||
101 | this.setCanvasY = function(cy){ | ||
102 | this._canvasY=cy; | ||
103 | }; | ||
104 | |||
105 | this.getNumPoints = function () { | ||
106 | return this._Points.length; | ||
107 | }; | ||
108 | |||
109 | this.getPoint = function (index) { | ||
110 | return this._Points[index]; | ||
111 | }; | ||
112 | |||
113 | this.addPoint = function (pt) { | ||
114 | //add the point only if it is some epsilon away from the previous point | ||
115 | var numPoints = this._Points.length; | ||
116 | if (numPoints>0) { | ||
117 | var threshold = this._WETNESS_FACTOR*this._strokeWidth; | ||
118 | var prevPt = this._Points[numPoints-1]; | ||
119 | var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; | ||
120 | var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); | ||
121 | if (diffPtMag>threshold){ | ||
122 | this._Points.push(pt); | ||
123 | this._dirty=true; | ||
124 | } | ||
125 | } else { | ||
126 | this._Points.push(pt); | ||
127 | this._dirty=true; | ||
128 | } | ||
129 | }; | ||
130 | |||
131 | this.insertPoint = function(pt, index){ | ||
132 | this._Points.splice(index, 0, pt); this._dirty=true; | ||
133 | }; | ||
134 | |||
135 | this.isDirty = function(){ | ||
136 | return this._dirty; | ||
137 | }; | ||
138 | |||
139 | this.makeDirty = function(){ | ||
140 | this._dirty=true; | ||
141 | }; | ||
142 | |||
143 | this.getBBoxMin = function () { | ||
144 | return this._BBoxMin; | ||
145 | }; | ||
146 | |||
147 | this.getBBoxMax = function () { | ||
148 | return this._BBoxMax; | ||
149 | }; | ||
150 | |||
151 | this.getStrokeWidth = function () { | ||
152 | return this._strokeWidth; | ||
153 | }; | ||
154 | |||
155 | this.setStrokeWidth = function (w) { | ||
156 | this._strokeWidth = w; | ||
157 | this._dirty=true; | ||
158 | }; | ||
159 | |||
160 | this.getStrokeMaterial = function () { | ||
161 | return this._strokeMaterial; | ||
162 | }; | ||
163 | |||
164 | this.setStrokeMaterial = function (m) { | ||
165 | this._strokeMaterial = m; | ||
166 | }; | ||
167 | |||
168 | this.getStrokeColor = function () { | ||
169 | return this._strokeColor; | ||
170 | }; | ||
171 | |||
172 | this.setStrokeColor = function (c) { | ||
173 | this._strokeColor = c; | ||
174 | }; | ||
175 | |||
176 | this.getStrokeStyle = function () { | ||
177 | return this._strokeStyle; | ||
178 | }; | ||
179 | |||
180 | this.setStrokeStyle = function (s) { | ||
181 | this._strokeStyle = s; | ||
182 | }; | ||
183 | |||
184 | this.setWidth = function () { | ||
185 | |||
186 | };//NO-OP for now | ||
187 | |||
188 | this.setHeight = function () { | ||
189 | |||
190 | };//NO-OP for now | ||
191 | |||
192 | |||
193 | //remove and return anchor at specified index, return null on error | ||
194 | this.removePoint = function (index) { | ||
195 | var retAnchor = null; | ||
196 | if (index < this._Points.length) { | ||
197 | retPt = this._Points.splice(index, 1); | ||
198 | this._dirty=true; | ||
199 | } | ||
200 | return retPoint; | ||
201 | }; | ||
202 | |||
203 | //remove all the points | ||
204 | this.clear = function () { | ||
205 | this._Points = []; | ||
206 | this._dirty=true; | ||
207 | } | ||
208 | |||
209 | this.translate = function (tx, ty, tz) { | ||
210 | for (var i=0;i<this._Points.length;i++){ | ||
211 | this._Points[i][0]+=tx; | ||
212 | this._Points[i][1]+=ty; | ||
213 | this._Points[i][2]+=tz; | ||
214 | } | ||
215 | }; | ||
216 | |||
217 | this.computeMetaGeometry = function() { | ||
218 | if (this._dirty) { | ||
219 | var numPoints = this._Points.length; | ||
220 | |||
221 | //**** add samples to the path if needed...linear interpolation for now | ||
222 | if (numPoints>1) { | ||
223 | var threshold = this._WETNESS_FACTOR*this._strokeWidth; | ||
224 | var prevPt = this._Points[0]; | ||
225 | var prevIndex = 0; | ||
226 | for (var i=1;i<numPoints;i++){ | ||
227 | var pt = this._Points[i]; | ||
228 | var diff = [pt[0]-prevPt[0], pt[1]-prevPt[1]]; | ||
229 | var distance = Math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]); | ||
230 | if (distance>threshold){ | ||
231 | //insert points along the prev. to current point | ||
232 | var numNewPoints = Math.floor(distance/threshold); | ||
233 | for (var j=0;j<numNewPoints;j++){ | ||
234 | var param = (j+1)/(numNewPoints+1); | ||
235 | var newpt = [prevPt[0]+ diff[0]*param, prevPt[1]+ diff[1]*param]; | ||
236 | //insert new point before point i | ||
237 | this._Points.splice(i, 0, [newpt[0], newpt[1], 0]); | ||
238 | i++; | ||
239 | } | ||
240 | this._dirty=true; | ||
241 | } | ||
242 | prevPt=pt; | ||
243 | //update numPoints to match the new length | ||
244 | numPoints = this._Points.length; | ||
245 | |||
246 | //end this function if the numPoints has gone above the max. size specified |