diff options
Diffstat (limited to 'libraries/ode-0.9/contrib/dRay/dRay_CCylinder.cpp')
-rw-r--r-- | libraries/ode-0.9/contrib/dRay/dRay_CCylinder.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/libraries/ode-0.9/contrib/dRay/dRay_CCylinder.cpp b/libraries/ode-0.9/contrib/dRay/dRay_CCylinder.cpp new file mode 100644 index 0000000..b9ea0c0 --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/dRay_CCylinder.cpp | |||
@@ -0,0 +1,199 @@ | |||
1 | // Ripped from Magic Software | ||
2 | |||
3 | #include "Include\dRay.h" | ||
4 | #include "dxRay.h" | ||
5 | |||
6 | int Find(const dVector3 Origin, dVector3 Direction, dReal Length, const dVector3 CCPos, const dMatrix3 CCRot, dReal CCRadius, dReal CCLength, dReal T[2]){ | ||
7 | dVector3 U, V, W; | ||
8 | Decompose(CCRot, U, V, W); | ||
9 | |||
10 | dVector3 CCOrigin; | ||
11 | CCOrigin[0] = CCPos[0] - (W[0] * CCLength / 2); | ||
12 | CCOrigin[1] = CCPos[1] - (W[1] * CCLength / 2); | ||
13 | CCOrigin[2] = CCPos[2] - (W[2] * CCLength / 2); | ||
14 | CCOrigin[3] = CCPos[3] - (W[3] * CCLength / 2); | ||
15 | |||
16 | dVector3 D; | ||
17 | D[0] = dDOT(U, Direction); | ||
18 | D[1] = dDOT(V, Direction); | ||
19 | D[2] = dDOT(W, Direction); | ||
20 | |||
21 | dReal DMag = Length; | ||
22 | dReal InvDMag = REAL(1.0) / DMag; | ||
23 | |||
24 | dVector3 Diff; | ||
25 | Diff[0] = Origin[0] - CCOrigin[0]; | ||
26 | Diff[1] = Origin[1] - CCOrigin[1]; | ||
27 | Diff[2] = Origin[2] - CCOrigin[2]; | ||
28 | Diff[3] = Origin[3] - CCOrigin[3]; | ||
29 | |||
30 | dVector3 P; | ||
31 | P[0] = dDOT(U, Diff); | ||
32 | P[1] = dDOT(V, Diff); | ||
33 | P[2] = dDOT(W, Diff); | ||
34 | |||
35 | dReal CCRadiusSq = CCRadius * CCRadius; | ||
36 | |||
37 | dReal Epsilon = 1e-12f; | ||
38 | |||
39 | if (dFabs(D[2]) >= REAL(1.0) - Epsilon){ // line is parallel to capsule axis | ||
40 | dReal Discr = CCRadiusSq - P[0] * P[0] - P[1] * P[1]; | ||
41 | |||
42 | if (Discr >= REAL(0.0)){ | ||
43 | dReal Root = dSqrt(Discr); | ||
44 | T[0] = (-P[2] + Root) * InvDMag; | ||
45 | T[1] = (CCLength - P[2] + Root) * InvDMag; | ||
46 | return 2; | ||
47 | } | ||
48 | else return 0; | ||
49 | } | ||
50 | |||
51 | // test intersection with infinite cylinder | ||
52 | dReal A = D[0] * D[0] + D[1] * D[1]; | ||
53 | dReal B = P[0] * D[0] + P[1] * D[1]; | ||
54 | dReal C = P[0] * P[0] + P[1] * P[1] - CCRadiusSq; | ||
55 | dReal Discr = B * B - A * C; | ||
56 | if (Discr < REAL(0.0)){ // line does not intersect infinite cylinder | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | int Count = 0; | ||
61 | |||
62 | if (Discr > REAL(0.0)){ // line intersects infinite cylinder in two places | ||
63 | dReal Root = dSqrt(Discr); | ||
64 | dReal Inv = REAL(1.0) / A; | ||
65 | |||
66 | dReal TTemp = (-B - Root) * Inv; | ||
67 | |||
68 | dReal Tmp = P[2] + TTemp * D[2]; | ||
69 | if (REAL(0.0) <= Tmp && Tmp <= CCLength){ | ||
70 | T[Count++] = TTemp * InvDMag; | ||
71 | } | ||
72 | |||
73 | |||
74 | TTemp = (-B + Root) * Inv; | ||
75 | Tmp = P[2] + TTemp * D[2]; | ||
76 | if (REAL(0.0) <= Tmp && Tmp <= CCLength){ | ||
77 | T[Count++] = TTemp * InvDMag; | ||
78 | } | ||
79 | |||
80 | if (Count == 2){ // line intersects capsule wall in two places | ||
81 | return 2; | ||
82 | } | ||
83 | } | ||
84 | else{ // line is tangent to infinite cylinder | ||
85 | dReal TTemp = -B / A; | ||
86 | dReal Tmp = P[2] + TTemp * D[2]; | ||
87 | if (REAL(0.0) <= Tmp && Tmp <= CCLength){ | ||
88 | T[0] = TTemp * InvDMag; | ||
89 | return 1; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | // test intersection with bottom hemisphere | ||
94 | // fA = 1 | ||
95 | B += P[2] * D[2]; | ||
96 | C += P[2] * P[2]; | ||
97 | Discr = B * B - C; | ||
98 | if (Discr > REAL(0.0)){ | ||
99 | dReal Root = dSqrt(Discr); | ||
100 | dReal TTemp = -B - Root; | ||
101 | dReal Tmp = P[2] + TTemp * D[2]; | ||
102 | if (Tmp <= REAL(0.0)){ | ||
103 | T[Count++] = TTemp * InvDMag; | ||
104 | if (Count == 2){ | ||
105 | return 2; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | TTemp = -B + Root; | ||
110 | Tmp = P[2] + TTemp * D[2]; | ||
111 | if (Tmp <= REAL(0.0)){ | ||
112 | T[Count++] = TTemp * InvDMag; | ||
113 | if (Count == 2){ | ||
114 | return 2; | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | else if (Discr == REAL(0.0)){ | ||
119 | dReal TTemp = -B; | ||
120 | dReal Tmp = P[2] + TTemp * D[2]; | ||
121 | if (Tmp <= REAL(0.0)){ | ||
122 | T[Count++] = TTemp * InvDMag; | ||
123 | if (Count == 2){ | ||
124 | return 2; | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | // test intersection with top hemisphere | ||
130 | // fA = 1 | ||
131 | B -= D[2] * CCLength; | ||
132 | C += CCLength * (CCLength - REAL(2.0) * P[2]); | ||
133 | |||
134 | Discr = B * B - C; | ||
135 | if (Discr > REAL(0.0)){ | ||
136 | dReal Root = dSqrt(Discr); | ||
137 | dReal TTemp = -B - Root; | ||
138 | dReal Tmp = P[2] + TTemp * D[2]; | ||
139 | if (Tmp >= CCLength){ | ||
140 | |||
141 | T[Count++] = TTemp * InvDMag; | ||
142 | if (Count == 2){ | ||
143 | return 2; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | TTemp = -B + Root; | ||
148 | Tmp = P[2] + TTemp * D[2]; | ||
149 | if (Tmp >= CCLength){ | ||
150 | T[Count++] = TTemp * InvDMag; | ||
151 | if (Count == 2){ | ||
152 | return 2; | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | else if (Discr == REAL(0.0)){ | ||
157 | dReal TTemp = -B; | ||
158 | dReal Tmp = P[2] + TTemp * D[2]; | ||
159 | if (Tmp >= CCLength){ | ||
160 | T[Count++] = TTemp * InvDMag; | ||
161 | if (Count == 2){ | ||
162 | return 2; | ||
163 | } | ||
164 | } | ||
165 | } | ||
166 | return Count; | ||
167 | } | ||
168 | |||
169 | int dCollideCCR(dxGeom* RayGeom, dxGeom* CCGeom, int Flags, dContactGeom* Contacts, int Stride){ | ||
170 | const dVector3& CCPos = *(const dVector3*)dGeomGetPosition(CCGeom); | ||
171 | const dMatrix3& CCRot = *(const dMatrix3*)dGeomGetRotation(CCGeom); | ||
172 | |||
173 | dReal CCRadius, CCLength; | ||
174 | dGeomCCylinderGetParams(CCGeom, &CCRadius, &CCLength); | ||
175 | |||
176 | dVector3 Origin, Direction; | ||
177 | dGeomRayGet(RayGeom, Origin, Direction); | ||
178 | dReal Length = dGeomRayGetLength(RayGeom); | ||
179 | |||
180 | dReal T[2]; | ||
181 | int Count = Find(Origin, Direction, Length, CCPos, CCRot, CCRadius, CCLength, T); | ||
182 | int ContactCount = 0; | ||
183 | for (int i = 0; i < Count; i++){ | ||
184 | if (T[i] >= 0.0){ | ||
185 | dContactGeom* Contact = CONTACT(Flags, Contacts, ContactCount, Stride); | ||
186 | Contact->pos[0] = Origin[0] + T[i] * Direction[0] * Length; | ||
187 | Contact->pos[1] = Origin[1] + T[i] * Direction[1] * Length; | ||
188 | Contact->pos[2] = Origin[2] + T[i] * Direction[2] * Length; | ||
189 | Contact->pos[3] = Origin[3] + T[i] * Direction[3] * Length; | ||
190 | //Contact->normal = 0; | ||
191 | Contact->depth = 0.0f; | ||
192 | Contact->g1 = RayGeom; | ||
193 | Contact->g2 = CCGeom; | ||
194 | |||
195 | ContactCount++; | ||
196 | } | ||
197 | } | ||
198 | return ContactCount; | ||
199 | } \ No newline at end of file | ||