diff options
author | Pierre Frisch | 2011-12-22 07:25:50 -0800 |
---|---|---|
committer | Valerio Virgillito | 2012-01-27 11:18:17 -0800 |
commit | b89a7ee8b956c96a1dcee995ea840feddc5d4b27 (patch) | |
tree | 0f3136ab0ecdbbbed6a83576581af0a53124d6f1 /js/helper-classes/RDGE/GLSubpath.js | |
parent | 2401f05d1f4b94d45e4568b81fc73e67b969d980 (diff) | |
download | ninja-b89a7ee8b956c96a1dcee995ea840feddc5d4b27.tar.gz |
First commit of Ninja to ninja-internal
Signed-off-by: Valerio Virgillito <rmwh84@motorola.com>
Diffstat (limited to 'js/helper-classes/RDGE/GLSubpath.js')
-rw-r--r-- | js/helper-classes/RDGE/GLSubpath.js | 1671 |
1 files changed, 1671 insertions, 0 deletions
diff --git a/js/helper-classes/RDGE/GLSubpath.js b/js/helper-classes/RDGE/GLSubpath.js new file mode 100644 index 00000000..25b12093 --- /dev/null +++ b/js/helper-classes/RDGE/GLSubpath.js | |||
@@ -0,0 +1,1671 @@ | |||
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 | var VecUtils = require("js/helper-classes/3D/vec-utils").VecUtils; | ||
8 | |||
9 | |||
10 | function SubpathOffsetPoint(pos, mapPos) { | ||
11 | this.Pos = Vector.create([pos[0],pos[1],pos[2]]); | ||
12 | this.CurveMapPos = Vector.create([mapPos[0], mapPos[1], mapPos[2]]); | ||
13 | } | ||
14 | |||
15 | function SubpathOffsetTriangle(v0, v1, v2) { | ||
16 | this.v0 = v0; | ||
17 | this.v1 = v1; | ||
18 | this.v2 = v2; | ||
19 | this.n = Vector.create([0,0,1]); //replace with the actual cross product later | ||
20 | } | ||
21 | |||
22 | function sortNumberAscending(a,b){ | ||
23 | return a-b; | ||
24 | } | ||
25 | function sortNumberDescending(a,b){ | ||
26 | return b-a; | ||
27 | } | ||
28 | function SegmentIntersections(){ | ||
29 | this.paramArray = []; | ||
30 | } | ||
31 | |||
32 | /////////////////////////////////////////////////////////////////////// | ||
33 | // Class GLSubpath | ||
34 | // representation a sequence of cubic bezier curves. | ||
35 | // Derived from class GLGeomObj | ||
36 | /////////////////////////////////////////////////////////////////////// | ||
37 | function GLSubpath() { | ||
38 | /////////////////////////////////////////////////// | ||
39 | // Instance variables | ||
40 | /////////////////////////////////////////////////// | ||
41 | this._Anchors = []; | ||
42 | this._BBoxMin = [0, 0, 0]; | ||
43 | this._BBoxMax = [0, 0, 0]; | ||
44 | this._isClosed = false; | ||
45 | |||
46 | this._samples = []; //polyline representation of this curve | ||
47 | this._sampleParam = []; //parametric distance of samples, within [0, N], where N is # of Bezier curves (=# of anchor points if closed, =#anchor pts -1 if open) | ||
48 | this._anchorSampleIndex = []; //index within _samples corresponding to anchor points | ||
49 | |||
50 | this._UnprojectedAnchors = []; | ||
51 | |||
52 | //offset path samples and the points on the input path they map to | ||
53 | this._offsetPointsLeft = []; | ||
54 | this._offsetPointsRight = []; | ||
55 | |||
56 | //triangles determined by the offset points | ||
57 | this._offsetTrianglesLeft = []; | ||
58 | this._offsetTrianglesRight = []; | ||
59 | |||
60 | //initially set the _dirty bit so we will construct samples | ||
61 | this._dirty = true; | ||
62 | |||
63 | //whether or not to use the canvas drawing to stroke/fill | ||
64 | this._useCanvasDrawing = true; | ||
65 | |||
66 | //the X and Y location of this subpath's canvas in stage world space of Ninja | ||
67 | this._canvasX = 0; | ||
68 | this._canvasY = 0; | ||
69 | |||
70 | //stroke information | ||
71 | this._strokeWidth = 0.0; | ||
72 | this._strokeColor = [0.4, 0.4, 0.4, 1.0]; | ||
73 | this._strokeMaterial; | ||
74 | this._strokeStyle = "Solid"; | ||
75 | this._materialAmbient = [0.2, 0.2, 0.2, 1.0]; | ||
76 | this._materialDiffuse = [0.4, 0.4, 0.4, 1.0]; | ||
77 | this._materialSpecular = [0.4, 0.4, 0.4, 1.0]; | ||
78 | this._fillColor = [0.4, 0.4, 0.4, 1.0]; | ||
79 | this._fillMaterial; | ||
80 | this._DISPLAY_ANCHOR_RADIUS = 5; | ||
81 | //drawing context | ||
82 | this._world = null; | ||
83 | |||
84 | //tool that owns this subpath | ||
85 | this._drawingTool = null; | ||
86 | this._planeMat = null; | ||
87 | this._planeMatInv = null; | ||
88 | this._planeCenter = null; | ||
89 | |||
90 | // initialize the inherited members | ||
91 | this.inheritedFrom = GLGeomObj; | ||
92 | this.inheritedFrom(); | ||
93 | |||
94 | //used to query what the user selected, OR-able for future extensions | ||
95 | this.SEL_NONE = 0; //nothing was selected | ||
96 | this.SEL_ANCHOR = 1; //anchor point was selected | ||
97 | this.SEL_PREV = 2; //previous handle of anchor point was selected | ||
98 | this.SEL_NEXT = 4; //next handle of anchor point was selected | ||
99 | this.SEL_PATH = 8; //the path itself was selected | ||
100 | this._selectMode = this.SEL_NONE; | ||
101 | this._selectedAnchorIndex = -1; | ||
102 | |||
103 | this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve | ||
104 | this._DEFAULT_STROKE_WIDTH = 20; //use only if stroke width not specified | ||
105 | this._MAX_OFFSET_ANGLE = 10; //max angle (in degrees) between consecutive vectors from curve to offset path | ||
106 | |||
107 | ///////////////////////////////////////////////////////// | ||
108 | // Property Accessors/Setters | ||
109 | ///////////////////////////////////////////////////////// | ||
110 | this.setWorld = function (world) { this._world = world; } | ||
111 | this.getWorld = function () { return this._world; } | ||
112 | this.makeDirty = function () {this._dirty = true;} | ||
113 | this.geomType = function () { return this.GEOM_TYPE_CUBIC_BEZIER; } | ||
114 | this.setDrawingTool = function (tool) {this._drawingTool = tool;} | ||
115 | this.getDrawingTool = function () {return this._drawingTool;} | ||
116 | this.setPlaneMatrix = function(planeMat){this._planeMat = planeMat;} | ||
117 | this.setPlaneMatrixInverse = function(planeMatInv){this._planeMatInv = planeMatInv;} | ||
118 | this.setPlaneCenter = function(pc){this._planeCenter = pc;} | ||
119 | |||
120 | this.getCanvasX = function(){return this._canvasX;} | ||
121 | this.getCanvasY = function(){return this._canvasY;} | ||
122 | this.setCanvasX = function(cx){this._canvasX=cx;} | ||
123 | this.setCanvasY = function(cy){this._canvasY=cy;} | ||
124 | |||
125 | this.getIsClosed = function () {return this._isClosed;} | ||
126 | this.setIsClosed = function (isClosed) { | ||
127 | if (this._isClosed !== isClosed) { | ||
128 | this._isClosed = isClosed; | ||
129 | this._dirty = true; | ||
130 | } | ||
131 | } | ||
132 | this.getNumAnchors = function () { return this._Anchors.length; } | ||
133 | this.getAnchor = function (index) { return this._Anchors[index]; } | ||
134 | this.addAnchor = function (anchorPt) { | ||
135 | this._Anchors.push(anchorPt); | ||
136 | this._selectedAnchorIndex = this._Anchors.length-1; | ||
137 | this._dirty = true; | ||
138 | } | ||
139 | |||
140 | this.insertAnchor = function(anchorPt, index){ | ||
141 | this._Anchors.splice(index, 0, anchorPt); | ||
142 | } | ||
143 | |||
144 | //remove and return anchor at specified index, return null on error | ||
145 | this.removeAnchor = function (index) { | ||
146 | var retAnchor = null; | ||
147 | if (index < this._Anchors.length) { | ||
148 | retAnchor = this._Anchors.splice(index, 1); | ||
149 | this._dirty = true; | ||
150 | } | ||
151 | //deselect the removed anchor if necessary | ||
152 | if (this._selectedAnchorIndex === index){ | ||
153 | this._selectedAnchorIndex = -1; | ||
154 | } | ||
155 | return retAnchor; | ||
156 | } | ||
157 | |||
158 | //remove all the anchor points | ||
159 | this.clearAllAnchors = function () { | ||
160 | this._Anchors = []; | ||
161 | this._isClosed = false; | ||
162 | this._dirty = true; | ||
163 | } | ||
164 | |||
165 | this.insertAnchorAtParameter = function(index, param) { | ||
166 | if (index+1 >= this._Anchors.length && !this._isClosed) { | ||
167 | return; | ||
168 | } | ||
169 | //insert an anchor after the specified index using the parameter, using De Casteljau subdivision | ||
170 | var nextIndex = (index+1)%this._Anchors.length; | ||
171 | |||
172 | //build the De Casteljau points | ||
173 | var P0P1 = VecUtils.vecInterpolate(3, this._Anchors[index].getPos(), this._Anchors[index].getNext(), param); | ||
174 | var P1P2 = VecUtils.vecInterpolate(3, this._Anchors[index].getNext(), this._Anchors[nextIndex].getPrev(), param); | ||
175 | var P2P3 = VecUtils.vecInterpolate(3, this._Anchors[nextIndex].getPrev(), this._Anchors[nextIndex].getPos(), param); | ||
176 | |||
177 | var P0P1P2 = VecUtils.vecInterpolate(3, P0P1, P1P2, param); | ||
178 | var P1P2P3 = VecUtils.vecInterpolate(3, P1P2, P2P3, param); | ||
179 | var anchorPos = VecUtils.vecInterpolate(3, P0P1P2, P1P2P3, param); | ||
180 | |||
181 | |||
182 | //update the next of the anchor at index and prev of anchor at nextIndex | ||
183 | var isPrevCoincident = false; | ||
184 | var isNextCoincident = false; | ||
185 | if (VecUtils.vecDist( 3, P0P1, this._Anchors[index].getNext()) < this._SAMPLING_EPSILON) { | ||
186 | //no change to the next point | ||
187 | isPrevCoincident = true; | ||
188 | } else { | ||
189 | this._Anchors[index].setNextPos(P0P1[0], P0P1[1], P0P1[2]); | ||
190 | } | ||
191 | |||
192 | if (VecUtils.vecDist( 3, P2P3, this._Anchors[nextIndex].getPrev()) < this._SAMPLING_EPSILON) { | ||
193 | //no change to the prev point | ||
194 | isNextCoincident = true; | ||
195 | } else { | ||
196 | this._Anchors[nextIndex].setPrevPos(P2P3[0], P2P3[1], P2P3[2]); | ||
197 | } | ||
198 | |||
199 | //create a new anchor point | ||
200 | var newAnchor = new GLAnchorPoint(); | ||
201 | |||
202 | if (isPrevCoincident && isNextCoincident){ | ||
203 | anchorPos[0]=P1P2[0];anchorPos[1]=P1P2[1];anchorPos[2]=P1P2[2]; | ||
204 | newAnchor.setPos(anchorPos[0],anchorPos[1],anchorPos[2]); | ||
205 | newAnchor.setPrevPos(anchorPos[0],anchorPos[1],anchorPos[2]); | ||
206 | newAnchor.setNextPos(anchorPos[0],anchorPos[1],anchorPos[2]); | ||
207 | } else { | ||
208 | newAnchor.setPrevPos(P0P1P2[0], P0P1P2[1], P0P1P2[2]); | ||
209 | newAnchor.setNextPos(P1P2P3[0], P1P2P3[1], P1P2P3[2]); | ||
210 | newAnchor.setPos(anchorPos[0], anchorPos[1], anchorPos[2]); | ||
211 | } | ||
212 | |||
213 | //insert the new anchor point at the correct index and set it as the selected anchor | ||
214 | this._Anchors.splice(nextIndex, 0, newAnchor); | ||
215 | this._selectedAnchorIndex = nextIndex; | ||
216 | this._dirty = true; | ||
217 | } | ||
218 | |||
219 | this._checkIntersectionWithSamples = function(startIndex, endIndex, point, radius){ | ||
220 | //check whether the point is within the radius distance from the curve represented as a polyline in _samples | ||
221 | //return the parametric distance along the curve if there is an intersection, else return null | ||
222 | //will assume that the BBox test is performed outside this function | ||
223 | |||