diff options
Diffstat (limited to 'js/helper-classes/3D/StageLine.js')
-rw-r--r-- | js/helper-classes/3D/StageLine.js | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/js/helper-classes/3D/StageLine.js b/js/helper-classes/3D/StageLine.js new file mode 100644 index 00000000..e0e7a8e3 --- /dev/null +++ b/js/helper-classes/3D/StageLine.js | |||
@@ -0,0 +1,461 @@ | |||
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 | /////////////////////////////////////////////////////////////////////// | ||
8 | // Class StageLine | ||
9 | // The line class represents a line intersected with all planes on the scene | ||
10 | /////////////////////////////////////////////////////////////////////// | ||
11 | var vecUtils = require("js/helper-classes/3D/vec-utils").VecUtils; | ||
12 | var LinePlaneIntersectRec = require("js/helper-classes/3D/LinePlaneIntersectRec").LinePlaneIntersectRec; | ||
13 | |||
14 | var StageLine = exports.StageLine = Object.create(Object.prototype, { | ||
15 | /////////////////////////////////////////////////////////////////////// | ||
16 | // Instance variables | ||
17 | /////////////////////////////////////////////////////////////////////// | ||
18 | |||
19 | // the 2 points of the line | ||
20 | _pt0: { value: null, writable: true }, | ||
21 | _pt1: { value: null, writable: true }, | ||
22 | |||
23 | // cache the 3D min and max points for the line | ||
24 | _minPt: { value: null, writable: true }, | ||
25 | _maxPt: { value: null, writable: true }, | ||
26 | |||
27 | // the visibility at the start point (this._pt0). | ||
28 | _vis: { value: null, writable: true }, | ||
29 | |||
30 | // each line/plane intersection records 2 values: the parameter along | ||
31 | // the line from pt0 to pt1, and the change in visibility (+1 or -1). we | ||
32 | // keep a doubly-linked list of intersection records | ||
33 | _intersectionList: { value: null, writable: true }, | ||
34 | _intersectionCount: { value: 0, writable: true }, | ||
35 | |||
36 | /////////////////////////////////////////////////////////////////////// | ||
37 | // Property accessors | ||
38 | /////////////////////////////////////////////////////////////////////// | ||
39 | getMinPoint: { value: function() { return this._minPt.slice(0); } }, | ||
40 | getMaxPoint: { value: function() { return this._maxPt.slice(0); } }, | ||
41 | |||
42 | getPoint0: { value: function() { return this._pt0.slice(0); } }, | ||
43 | getPoint1: { value: function() { return this._pt1.slice(0); } }, | ||
44 | |||
45 | getIntersectionCount: { value: function() { return this._intersectionCount; } }, | ||
46 | getIntersectionList: { value: function() { return this._intersectionList; } }, | ||
47 | |||
48 | getVisibility: { value: function() { return this._vis; } }, | ||
49 | setVisibility: { value: function(v) { this._vis = v; } }, | ||
50 | |||
51 | /////////////////////////////////////////////////////////////////////// | ||
52 | // Methods | ||
53 | /////////////////////////////////////////////////////////////////////// | ||
54 | |||
55 | intersectWithPlane: { | ||
56 | value: function( plane ) | ||
57 | { | ||
58 | // if the plane is edge-on, ignore it | ||
59 | if ( MathUtils.fpSign( plane.getPlaneEq()[2] ) == 0 ) return; | ||
60 | |||
61 | // do some quick box tests. | ||
62 | var minPt = this.getMinPoint(), | ||
63 | maxPt = this.getMaxPoint(); | ||
64 | |||
65 | if (maxPt[0] < plane._rect.getLeft()) return; | ||
66 | if (minPt[0] > plane._rect.getRight()) return; | ||
67 | |||
68 | if (maxPt[1] < plane._rect.getTop()) return; | ||
69 | if (minPt[1] > plane._rect.getBottom()) return; | ||
70 | |||
71 | if (minPt[2] > plane.getZMax()) return; | ||
72 | |||
73 | // get the boundary points for the plane | ||
74 | var boundaryPts = plane.getBoundaryPoints(); | ||
75 | |||
76 | // get the points and direction vector for the current line | ||
77 | var pt0 = this.getPoint0(), pt1 = this.getPoint1(); | ||
78 | //var lineDir = pt1.subtract( pt0 ); | ||
79 | var lineDir = vecUtils.vecSubtract(3, pt1, pt0); | ||
80 | |||
81 | // intersect with the front plane | ||
82 | var planeEq = plane.getPlaneEq(); | ||
83 | var t = MathUtils.vecIntersectPlaneForParam( pt0, lineDir, planeEq ); | ||
84 | if (t != undefined) | ||
85 | { | ||
86 | if ((MathUtils.fpSign(t) >= 0) && (MathUtils.fpCmp(t,1.0) <= 0)) | ||
87 | { | ||
88 | // get the intersection point | ||
89 | var pt = MathUtils.interpolateLine3D( pt0, pt1, t ); | ||
90 | |||
91 | // see if the intersection point is contained in the bounds | ||
92 | //var contains = this.boundaryContainsPoint( boundaryPts, plane.isBackFacing(), pt ); | ||
93 | var contains = MathUtils.boundaryContainsPoint( boundaryPts, pt, plane.isBackFacing() ); | ||
94 | if (contains == MathUtils.INSIDE) | ||
95 | { | ||
96 | // add the intersection | ||
97 | var dot = MathUtils.dot3( pt0, planeEq ) + planeEq[3]; | ||
98 | var deltaVis = (dot > 0) ? 1 : -1; | ||
99 | // if (plane.isBackFacing()) | ||
100 | // deltaVis = (dot < 0) ? 1 : -1; | ||
101 | |||
102 | this.addIntersection( plane, t, deltaVis ); | ||
103 | } | ||
104 | else if (contains == MathUtils.ON) | ||
105 | { | ||
106 | if (MathUtils.fpCmp(t,1.0) < 0) | ||
107 | { | ||
108 | // take the dot product between the line and the normal to the plane | ||
109 | // to determine the change in visibility | ||
110 | var vec = vecUtils.vecSubtract( 3, pt1, pt0 ); | ||
111 | var dot = vecUtils.vecDot( 3, vec, plane.getPlaneEq() ); | ||
112 | var sign = MathUtils.fpSign( dot ); | ||
113 | if (sign == 0) | ||
114 | throw new Error( "coplanar intersection being treated as not coplanar" ); | ||
115 | if (!plane.isBackFacing()) | ||
116 | { | ||
117 | if (sign < 0) | ||
118 | this.addIntersection( plane, t, 1 ); | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | if (sign > 0) | ||
123 | this.addIntersection( plane, t, -1 ); | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | else | ||
130 | { | ||
131 | // the line must be parallel to the plane. If the line is in the plane, | ||
132 | // we need to do some special processing | ||
133 | var d0 = vecUtils.vecDot(3, planeEq, pt0) + planeEq[3], | ||
134 | d1 = vecUtils.vecDot(3, planeEq, pt1) + planeEq[3]; | ||
135 | if ((MathUtils.fpSign(d0) == 0) && (MathUtils.fpSign(d1) == 0)) | ||
136 | this.doCoplanarIntersection( plane ); | ||
137 | } | ||
138 | |||
139 | // intersect with the 4 planes formed by the edges of the plane, going back in Z | ||
140 | var bPt1 = boundaryPts[3]; | ||
141 | for (var i=0; i<4; i++) | ||
142 | { | ||
143 | // get the 2 points that define the front edge of the plane | ||
144 | var bPt0 = bPt1; | ||
145 | var bPt1 = boundaryPts[i]; | ||
146 | |||
147 | // calculate the plane equation. The normal should point towards the OUTSIDE of the boundary | ||
148 | //var vec = bPt1.subtract( bPt0 ); | ||
149 | var vec = vecUtils.vecSubtract(3, bPt1, bPt0); | ||
150 | if (plane.isBackFacing()) | ||
151 | MathUtils.negate( vec ); | ||
152 | planeEq = Vector.create( [-vec[1], vec[0], 0] ); | ||
153 | var normal = Vector.create( [planeEq[0], planeEq[1], planeEq[2]] ); | ||
154 | // var d = -planeEq.dot(bPt0); | ||
155 | var d = -vecUtils.vecDot(3, planeEq, bPt0); | ||
156 | planeEq[3] = d; | ||
157 | |||
158 | t = MathUtils.vecIntersectPlaneForParam( pt0, lineDir, planeEq ); | ||
159 | if (t) | ||
160 | { | ||
161 | if ((MathUtils.fpSign(t) > 0) && (MathUtils.fpCmp(t,1.0) <= 0)) // the strict vs not-strict inequality comparisons are IMPORTANT! | ||
162 | { | ||
163 | // get the intersection point | ||
164 | var pt = MathUtils.interpolateLine3D( pt0, pt1, t ); | ||
165 | |||
166 | // we need to get the parameter on the edge of the projection | ||
167 | // of the intersection point onto the line. | ||
168 | var index = (Math.abs(vec[0]) > Math.abs(vec[1])) ? 0 : 1; | ||
169 | var tEdge = (pt[index] - bPt0[index])/(bPt1[index] - bPt0[index]); | ||
170 | if ((MathUtils.fpSign(tEdge) > 0) && (MathUtils.fpCmp(tEdge,1.0) <= 0)) | ||
171 | { | ||
172 | var edgePt = MathUtils.interpolateLine3D( bPt0, bPt1, tEdge ); | ||
173 | if (MathUtils.fpCmp(pt[2],edgePt[2]) < 0) | ||
174 | { | ||
175 | // add the intersection | ||
176 | var deltaVis = MathUtils.dot(lineDir,normal) > 0 ? -1 : 1; | ||
177 | this.addIntersection( plane, t, deltaVis ); | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | }, | ||
185 | |||
186 | doCoplanarIntersection: { | ||
187 | value: function( plane ) | ||
188 | { | ||
189 | // get the boundary points for the plane | ||
190 | var boundaryPts = plane.getBoundaryPoints(); | ||
191 | var planeEq = plane.getPlaneEq(); | ||
192 | |||
193 | if (plane.isBackFacing()) | ||
194 | { | ||
195 | var tmp; | ||
196 | tmp = boundaryPts[0]; boundaryPts[0] = boundaryPts[3]; boundaryPts[3] = tmp; | ||
197 | tmp = boundaryPts[1]; boundaryPts[1] = boundaryPts[2]; boundaryPts[2] = tmp; | ||
198 | } | ||
199 | |||
200 | var pt0 = this.getPoint0(), | ||
201 | pt1 = this.getPoint1(); | ||
202 | |||
203 | // keep a couple flags to prevent counting crossings twice in edge cases | ||
204 | var gotEnter = false, | ||
205 | gotExit = false; | ||
206 | |||
207 | var bp1 = boundaryPts[3]; | ||
208 | for (var i=0; i<4; i++) | ||
209 | { | ||
210 | var bp0 = bp1; | ||
211 | bp1 = boundaryPts[i]; | ||
212 | var vec = vecUtils.vecSubtract(3, bp1, bp0); | ||
213 | var nrm = vecUtils.vecCross(3, vec, planeEq); | ||
214 | nrm[3] = -vecUtils.vecDot(3, bp0, nrm); | ||
215 | |||
216 | var d0 = vecUtils.vecDot(3, nrm, pt0) + nrm[3], | ||
217 | d1 = vecUtils.vecDot(3, nrm, pt1) + nrm[3]; | ||
218 | |||
219 | var s0 = MathUtils.fpSign(d0), | ||
220 | s1 = MathUtils.fpSign(d1); | ||
221 | |||
222 | if (s0 != s1) | ||
223 | { | ||
224 | var t = Math.abs(d0)/( Math.abs(d0) + Math.abs(d1) ); | ||
225 | if ( (MathUtils.fpSign(t) >= 0) && (MathUtils.fpCmp(t,1.0) <= 0)) | ||
226 | { | ||