|
2 | 2 | #define TINYC2_IMPLEMENTATION
|
3 | 3 | #include "tinyc2.h"
|
4 | 4 |
|
5 |
| -void handleResult(const c2Manifold&, Manifold&); |
6 |
| -void handleResult(const c2Raycast&, const c2Ray&, Raycast&); |
7 |
| -c2AABB shapeToc2(const Aabb&, const sf::Vector2f); |
8 |
| -c2Circle shapeToc2(const Circle&, const sf::Vector2f); |
9 |
| -c2Ray rayToc2(const Ray&, const sf::Vector2f); |
10 |
| -c2v toc2v(const sf::Vector2f&); |
11 |
| -sf::Vector2f tosfv(const c2v&); |
| 5 | +namespace priv |
| 6 | +{ |
| 7 | +template <typename T> |
| 8 | +struct Helper |
| 9 | +{ |
| 10 | + Helper(const T& shape, sf::Vector2f position); |
| 11 | + |
| 12 | + const T& shape; |
| 13 | + sf::Vector2f position; |
| 14 | +}; |
| 15 | + |
| 16 | +Manifold calculate(Helper<Aabb> a, Helper<Aabb> b); |
| 17 | +Manifold calculate(Helper<Circle> a, Helper<Circle> b); |
| 18 | +Manifold calculate(Helper<Aabb> a, Helper<Circle> b); |
| 19 | +Manifold calculate(Helper<Circle> a, Helper<Aabb> b); |
| 20 | +Raycast calculate(Helper<Ray> a, Helper<Aabb> b); |
| 21 | +Raycast calculate(Helper<Ray> a, Helper<Circle> b); |
| 22 | + |
| 23 | +Manifold toManifold(const c2Manifold& m); |
| 24 | +Raycast toRaycast(const c2Raycast& r, const c2Ray& ray); |
| 25 | + |
| 26 | +c2AABB toc2AABB(Helper<Aabb> aabb); |
| 27 | +c2Circle toc2Circle(Helper<Circle> circle); |
| 28 | +c2Ray toc2Ray(Helper<Ray> ray); |
| 29 | +c2v toc2v(const sf::Vector2f& v); |
| 30 | +sf::Vector2f tosfv(const c2v& v); |
| 31 | +} |
12 | 32 |
|
13 | 33 | Shape::Shape(Type type)
|
14 | 34 | : mType(type)
|
@@ -110,187 +130,202 @@ Manifold::Manifold()
|
110 | 130 | {
|
111 | 131 | }
|
112 | 132 |
|
113 |
| -void Manifold::solve(const Shape& a, const sf::Vector2f positionA, |
114 |
| - const Shape& b, const sf::Vector2f positionB) |
| 133 | +Raycast::Raycast() |
| 134 | + : hit(false) |
| 135 | + , normal(0, 0) |
| 136 | + , contact(0, 0) |
| 137 | + , t(0) |
115 | 138 | {
|
116 |
| - mPositionA = positionA; |
117 |
| - mPositionB = positionB; |
| 139 | +} |
118 | 140 |
|
119 |
| - dispatch(a, b); |
| 141 | +template <typename T> |
| 142 | +priv::Helper<T>::Helper(const T& shape, sf::Vector2f position) |
| 143 | + : shape(shape) |
| 144 | + , position(position) |
| 145 | +{ |
120 | 146 | }
|
121 | 147 |
|
122 |
| -void Manifold::dispatch(const Shape& a, const Shape& b) |
| 148 | +Manifold solve(const Shape& a, sf::Vector2f posA, const Shape& b, |
| 149 | + sf::Vector2f posB) |
123 | 150 | {
|
| 151 | + Manifold m; |
| 152 | + |
124 | 153 | if (a.getType() == Type::Aabb)
|
125 | 154 | {
|
126 |
| - const Aabb& aChild = castShape<Aabb>(a); |
| 155 | + priv::Helper<Aabb> ha(castShape<Aabb>(a), posA); |
127 | 156 |
|
128 | 157 | if (b.getType() == Type::Aabb)
|
129 | 158 | {
|
130 |
| - const Aabb& bChild = castShape<Aabb>(b); |
131 |
| - collide(aChild, bChild); |
| 159 | + priv::Helper<Aabb> hb(castShape<Aabb>(b), posB); |
| 160 | + m = priv::calculate(ha, hb); |
132 | 161 | }
|
133 | 162 | else if (b.getType() == Type::Circle)
|
134 | 163 | {
|
135 |
| - const Circle& bChild = castShape<Circle>(b); |
136 |
| - collide(aChild, bChild); |
| 164 | + priv::Helper<Circle> hb(castShape<Circle>(b), posB); |
| 165 | + m = priv::calculate(ha, hb); |
137 | 166 | }
|
138 | 167 | }
|
139 | 168 | else if (a.getType() == Type::Circle)
|
140 | 169 | {
|
141 |
| - const Circle& aChild = castShape<Circle>(a); |
| 170 | + priv::Helper<Circle> ha(castShape<Circle>(a), posA); |
142 | 171 |
|
| 172 | + // Could use a function castOther<T>() to avoid duplicating this |
143 | 173 | if (b.getType() == Type::Aabb)
|
144 | 174 | {
|
145 |
| - const Aabb& bChild = castShape<Aabb>(b); |
146 |
| - collide(aChild, bChild); |
| 175 | + priv::Helper<Aabb> hb(castShape<Aabb>(b), posB); |
| 176 | + m = priv::calculate(ha, hb); |
147 | 177 | }
|
148 | 178 | else if (b.getType() == Type::Circle)
|
149 | 179 | {
|
150 |
| - const Circle& bChild = castShape<Circle>(b); |
151 |
| - collide(aChild, bChild); |
| 180 | + priv::Helper<Circle> hb(castShape<Circle>(b), posB); |
| 181 | + m = priv::calculate(ha, hb); |
152 | 182 | }
|
153 | 183 | }
|
154 |
| -} |
155 | 184 |
|
156 |
| -void Manifold::collide(const Aabb& a, const Aabb& b) |
157 |
| -{ |
158 |
| - c2AABB shapeA = shapeToc2(a, mPositionA); |
159 |
| - c2AABB shapeB = shapeToc2(b, mPositionB); |
160 |
| - c2Manifold m; |
161 |
| - c2AABBtoAABBManifold(shapeA, shapeB, &m); |
162 |
| - |
163 |
| - handleResult(m, *this); |
| 185 | + return m; |
164 | 186 | }
|
165 | 187 |
|
166 |
| -void Manifold::collide(const Circle& a, const Circle& b) |
| 188 | +Raycast solve(const Ray& a, sf::Vector2f posA, const Shape& b, |
| 189 | + sf::Vector2f posB) |
167 | 190 | {
|
168 |
| - c2Circle shapeA = shapeToc2(a, mPositionA); |
169 |
| - c2Circle shapeB = shapeToc2(b, mPositionB); |
170 |
| - c2Manifold m; |
171 |
| - c2CircletoCircleManifold(shapeA, shapeB, &m); |
| 191 | + Raycast r; |
| 192 | + priv::Helper<Ray> ha(a, posA); |
172 | 193 |
|
173 |
| - handleResult(m, *this); |
174 |
| -} |
| 194 | + if (b.getType() == Type::Aabb) |
| 195 | + { |
| 196 | + priv::Helper<Aabb> hb(castShape<Aabb>(b), posB); |
| 197 | + r = priv::calculate(ha, hb); |
| 198 | + } |
| 199 | + else if (b.getType() == Type::Circle) |
| 200 | + { |
| 201 | + priv::Helper<Circle> hb(castShape<Circle>(b), posB); |
| 202 | + r = priv::calculate(ha, hb); |
| 203 | + } |
175 | 204 |
|
176 |
| -void Manifold::collide(const Aabb& a, const Circle& b) |
177 |
| -{ |
178 |
| - collide(b, a); |
179 |
| - normal = -normal; |
| 205 | + return r; |
180 | 206 | }
|
181 | 207 |
|
182 |
| -void Manifold::collide(const Circle& a, const Aabb& b) |
| 208 | +Manifold priv::calculate(Helper<Aabb> a, Helper<Aabb> b) |
183 | 209 | {
|
184 |
| - c2Circle shapeA = shapeToc2(a, mPositionA); |
185 |
| - c2AABB shapeB = shapeToc2(b, mPositionB); |
| 210 | + c2AABB shapeA = priv::toc2AABB(a); |
| 211 | + c2AABB shapeB = priv::toc2AABB(b); |
186 | 212 | c2Manifold m;
|
187 |
| - c2CircletoAABBManifold(shapeA, shapeB, &m); |
| 213 | + c2AABBtoAABBManifold(shapeA, shapeB, &m); |
188 | 214 |
|
189 |
| - handleResult(m, *this); |
| 215 | + return priv::toManifold(m); |
190 | 216 | }
|
191 | 217 |
|
192 |
| -Raycast::Raycast() |
193 |
| - : hit(false) |
194 |
| - , normal(0, 0) |
195 |
| - , t(0) |
| 218 | +Manifold priv::calculate(Helper<Circle> a, Helper<Circle> b) |
196 | 219 | {
|
| 220 | + c2Circle shapeA = priv::toc2Circle(a); |
| 221 | + c2Circle shapeB = priv::toc2Circle(b); |
| 222 | + c2Manifold m; |
| 223 | + c2CircletoCircleManifold(shapeA, shapeB, &m); |
| 224 | + |
| 225 | + return priv::toManifold(m); |
197 | 226 | }
|
198 | 227 |
|
199 |
| -void Raycast::solve(const Ray& a, const sf::Vector2f positionA, |
200 |
| - const Shape& b, const sf::Vector2f positionB) |
| 228 | +Manifold priv::calculate(Helper<Aabb> a, Helper<Circle> b) |
201 | 229 | {
|
202 |
| - mPositionA = positionA; |
203 |
| - mPositionB = positionB; |
| 230 | + Manifold m = priv::calculate(b, a); |
| 231 | + m.normal = -m.normal; |
204 | 232 |
|
205 |
| - dispatch(a, b); |
| 233 | + return m; |
206 | 234 | }
|
207 | 235 |
|
208 |
| -void Raycast::dispatch(const Ray& a, const Shape& b) |
| 236 | +Manifold priv::calculate(Helper<Circle> a, Helper<Aabb> b) |
209 | 237 | {
|
210 |
| - if (b.getType() == Type::Aabb) |
211 |
| - { |
212 |
| - const Aabb& bChild = castShape<Aabb>(b); |
213 |
| - calculate(a, bChild); |
214 |
| - } |
215 |
| - else if (b.getType() == Type::Circle) |
216 |
| - { |
217 |
| - const Circle& bChild = castShape<Circle>(b); |
218 |
| - calculate(a, bChild); |
219 |
| - } |
| 238 | + c2Circle shapeA = priv::toc2Circle(a); |
| 239 | + c2AABB shapeB = priv::toc2AABB(b); |
| 240 | + c2Manifold m; |
| 241 | + c2CircletoAABBManifold(shapeA, shapeB, &m); |
| 242 | + |
| 243 | + return priv::toManifold(m); |
220 | 244 | }
|
221 | 245 |
|
222 |
| -void Raycast::calculate(const Ray& a, const Aabb& b) |
| 246 | +Raycast priv::calculate(Helper<Ray> a, Helper<Aabb> b) |
223 | 247 | {
|
224 |
| - c2Ray ray = rayToc2(a, mPositionA); |
225 |
| - c2AABB shape = shapeToc2(b, mPositionB); |
| 248 | + Raycast tmp; |
| 249 | + c2Ray ray = priv::toc2Ray(a); |
| 250 | + c2AABB shape = priv::toc2AABB(b); |
226 | 251 | c2Raycast r;
|
227 |
| - hit = false; |
228 | 252 |
|
229 | 253 | if (c2RaytoAABB(ray, shape, &r))
|
230 |
| - handleResult(r, ray, *this); |
| 254 | + tmp = priv::toRaycast(r, ray); |
| 255 | + |
| 256 | + return tmp; |
231 | 257 | }
|
232 | 258 |
|
233 |
| -void Raycast::calculate(const Ray& a, const Circle& b) |
| 259 | +Raycast priv::calculate(Helper<Ray> a, Helper<Circle> b) |
234 | 260 | {
|
235 |
| - c2Ray ray = rayToc2(a, mPositionA); |
236 |
| - c2Circle shape = shapeToc2(b, mPositionB); |
| 261 | + Raycast tmp; |
| 262 | + c2Ray ray = priv::toc2Ray(a); |
| 263 | + c2Circle shape = priv::toc2Circle(b); |
237 | 264 | c2Raycast r;
|
238 |
| - hit = false; |
239 | 265 |
|
240 | 266 | if (c2RaytoCircle(ray, shape, &r))
|
241 |
| - handleResult(r, ray, *this); |
| 267 | + tmp = priv::toRaycast(r, ray); |
| 268 | + |
| 269 | + return tmp; |
242 | 270 | }
|
243 | 271 |
|
244 |
| -void handleResult(const c2Manifold& manifold, Manifold& m) |
| 272 | +Manifold priv::toManifold(const c2Manifold& m) |
245 | 273 | {
|
246 |
| - m.colliding = manifold.count > 0; |
247 |
| - if (m.colliding) |
| 274 | + Manifold tmp; |
| 275 | + tmp.colliding = m.count > 0; |
| 276 | + |
| 277 | + if (tmp.colliding) |
248 | 278 | {
|
249 |
| - m.normal = tosfv(manifold.normal); |
250 |
| - m.contact = tosfv(manifold.contact_points[0]); |
251 |
| - m.depth = manifold.depths[0]; |
| 279 | + tmp.normal = tosfv(m.normal); |
| 280 | + tmp.contact = tosfv(m.contact_points[0]); |
| 281 | + tmp.depth = m.depths[0]; |
252 | 282 | }
|
| 283 | + |
| 284 | + return tmp; |
253 | 285 | }
|
254 | 286 |
|
255 |
| -void handleResult(const c2Raycast& raycast, const c2Ray& ray, Raycast& r) |
| 287 | +Raycast priv::toRaycast(const c2Raycast& r, const c2Ray& ray) |
256 | 288 | {
|
257 |
| - r.hit = true; |
258 |
| - r.normal = tosfv(raycast.n); |
259 |
| - r.contact = tosfv(c2Impact(ray, raycast.t)); |
260 |
| - r.t = raycast.t; |
| 289 | + Raycast tmp; |
| 290 | + tmp.hit = true; |
| 291 | + tmp.normal = tosfv(r.n); |
| 292 | + tmp.contact = tosfv(c2Impact(ray, r.t)); |
| 293 | + tmp.t = r.t; |
| 294 | + |
| 295 | + return tmp; |
261 | 296 | }
|
262 | 297 |
|
263 |
| -c2AABB shapeToc2(const Aabb& aabb, const sf::Vector2f position) |
| 298 | +c2AABB priv::toc2AABB(Helper<Aabb> aabb) |
264 | 299 | {
|
265 | 300 | c2AABB tmp;
|
266 |
| - tmp.min = toc2v(position); |
267 |
| - tmp.max = toc2v(position + aabb.getSize()); |
| 301 | + tmp.min = toc2v(aabb.position); |
| 302 | + tmp.max = toc2v(aabb.position + aabb.shape.getSize()); |
268 | 303 | return tmp;
|
269 | 304 | }
|
270 | 305 |
|
271 |
| -c2Circle shapeToc2(const Circle& circle, const sf::Vector2f position) |
| 306 | +c2Circle priv::toc2Circle(Helper<Circle> circle) |
272 | 307 | {
|
273 | 308 | c2Circle tmp;
|
274 |
| - tmp.p = toc2v(position); |
275 |
| - tmp.r = circle.getRadius(); |
| 309 | + tmp.p = toc2v(circle.position); |
| 310 | + tmp.r = circle.shape.getRadius(); |
276 | 311 | return tmp;
|
277 | 312 | }
|
278 | 313 |
|
279 |
| -c2Ray rayToc2(const Ray& ray, const sf::Vector2f position) |
| 314 | +c2Ray priv::toc2Ray(Helper<Ray> ray) |
280 | 315 | {
|
281 | 316 | c2Ray tmp;
|
282 |
| - tmp.p = toc2v(position); |
283 |
| - tmp.d = toc2v(ray.getDirection()); |
284 |
| - tmp.t = ray.getLength(); |
| 317 | + tmp.p = toc2v(ray.position); |
| 318 | + tmp.d = toc2v(ray.shape.getDirection()); |
| 319 | + tmp.t = ray.shape.getLength(); |
285 | 320 | return tmp;
|
286 | 321 | }
|
287 | 322 |
|
288 |
| -c2v toc2v(const sf::Vector2f& v) |
| 323 | +c2v priv::toc2v(const sf::Vector2f& v) |
289 | 324 | {
|
290 | 325 | return c2V(v.x, v.y);
|
291 | 326 | }
|
292 | 327 |
|
293 |
| -sf::Vector2f tosfv(const c2v& v) |
| 328 | +sf::Vector2f priv::tosfv(const c2v& v) |
294 | 329 | {
|
295 | 330 | return sf::Vector2f(v.x, v.y);
|
296 | 331 | }
|
0 commit comments