bzr branch
/browse/iphone/common
| Line | Revision | Contents |
| 1 | 1 | // |
| 2 | // geometry.h |
|
| 3 | // |
|
| 4 | // Created by döme on 26.07.2009. |
|
| 5 | // |
|
| 6 | ||
| 7 | 54 | /* |
| 8 | * Copyright (c) 2009 Doemoetoer Gulyas. |
|
| 9 | * All rights reserved. |
|
| 10 | * |
|
| 11 | * Redistribution and use in source and binary forms, with or without |
|
| 12 | * modification, are permitted provided that the following conditions |
|
| 13 | * are met: |
|
| 14 | * 1. Redistributions of source code must retain the above copyright |
|
| 15 | * notice, this list of conditions and the following disclaimer. |
|
| 16 | * 2. Redistributions in binary form must reproduce the above copyright |
|
| 17 | * notice, this list of conditions and the following disclaimer in the |
|
| 18 | * documentation and/or other materials provided with the distribution. |
|
| 19 | * 3. The name of the author may not be used to endorse or promote products |
|
| 20 | * derived from this software without specific prior written permission. |
|
| 21 | * |
|
| 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|
| 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|
| 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|
| 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
| 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|
| 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
| 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 32 | */ |
|
| 33 | ||
| 34 | 1 | #import <Foundation/Foundation.h> |
| 35 | ||
| 36 | 5 | #import <OpenGLES/ES2/gl.h> |
| 37 | 51 | #import <CoreGraphics/CoreGraphics.h> |
| 38 | 1 | |
| 39 | typedef union v3 |
|
| 40 | { |
|
| 41 | float a[3]; |
|
| 42 | struct {float x,y,z;} v; |
|
| 43 | } v3; |
|
| 44 | ||
| 45 | typedef union m16 |
|
| 46 | { |
|
| 47 | float a[16]; |
|
| 48 | float m[4][4]; |
|
| 49 | } m16; |
|
| 50 | ||
| 51 | 4 | static inline v3 vcreate(const float a, const float b, const float c) |
| 52 | { |
|
| 53 | 42 | return (v3){{a,b,c}}; |
| 54 | 4 | } |
| 55 | ||
| 56 | 1 | static inline v3 vcross(v3 a, v3 b) |
| 57 | { |
|
| 58 | 42 | return (v3){{a.v.y*b.v.z-a.v.z*b.v.y, a.v.z*b.v.x - a.v.x*b.v.z, a.v.x*b.v.y - a.v.y*b.v.x}}; |
| 59 | 1 | } |
| 60 | ||
| 61 | static inline float vdot(v3 a, v3 b) |
|
| 62 | { |
|
| 63 | return a.v.x*b.v.x+a.v.y*b.v.y+a.v.z*b.v.z; |
|
| 64 | } |
|
| 65 | ||
| 66 | static inline float vlength(v3 a) |
|
| 67 | { |
|
| 68 | return sqrtf(vdot(a,a)); |
|
| 69 | } |
|
| 70 | ||
| 71 | static inline v3 vmul(v3 a, float b) |
|
| 72 | { |
|
| 73 | 42 | return (v3){{a.v.x*b, a.v.y*b, a.v.z*b}}; |
| 74 | 1 | } |
| 75 | ||
| 76 | ||
| 77 | static inline v3 vproject(v3 a, v3 b) |
|
| 78 | { |
|
| 79 | return vmul(b, vdot(a,b)/vdot(b,b)); |
|
| 80 | } |
|
| 81 | ||
| 82 | static inline v3 vnormalize(v3 a) |
|
| 83 | { |
|
| 84 | float length = vlength(a); |
|
| 85 | if (length < FLT_EPSILON) |
|
| 86 | return a; |
|
| 87 | |
|
| 88 | a.v.x /= length; |
|
| 89 | a.v.y /= length; |
|
| 90 | a.v.z /= length; |
|
| 91 | |
|
| 92 | return a; |
|
| 93 | } |
|
| 94 | ||
| 95 | static inline v3 vnegate(v3 a) |
|
| 96 | { |
|
| 97 | 42 | return (v3){{-a.v.x,-a.v.y,-a.v.z}}; |
| 98 | 1 | } |
| 99 | ||
| 100 | 2 | static inline v3 vadd(const v3 a, const v3 b) |
| 101 | 1 | { |
| 102 | 42 | return (v3){{a.v.x+b.v.x, a.v.y+b.v.y, a.v.z+b.v.z}}; |
| 103 | 1 | } |
| 104 | ||
| 105 | 2 | static inline v3 vsub(const v3 a, const v3 b) |
| 106 | 1 | { |
| 107 | 42 | return (v3){{a.v.x-b.v.x, a.v.y-b.v.y, a.v.z-b.v.z}}; |
| 108 | 1 | } |
| 109 | ||
| 110 | 33 | static inline float vsum(const v3 a) |
| 111 | { |
|
| 112 | return a.v.x+a.v.y+a.v.z; |
|
| 113 | } |
|
| 114 | ||
| 115 | static inline v3 vfloor(const v3 a) |
|
| 116 | { |
|
| 117 | 42 | return (v3){{floorf(a.v.x), floorf(a.v.y), floorf(a.v.z)}}; |
| 118 | 33 | } |
| 119 | ||
| 120 | 2 | static inline float fclampf(const float a, const float mn, const float mx) |
| 121 | { |
|
| 122 | return fminf(fmaxf(a, mn), mx); |
|
| 123 | } |
|
| 124 | ||
| 125 | 25 | static inline double fclamp(const double a, const double mn, const double mx) |
| 126 | { |
|
| 127 | return fmin(fmax(a, mn), mx); |
|
| 128 | } |
|
| 129 | ||
| 130 | 2 | static inline v3 vclamp(const v3 a, const float mn, const float mx) |
| 131 | { |
|
| 132 | 42 | return (v3){{fclampf(a.v.x,mn,mx), fclampf(a.v.y,mn,mx), fclampf(a.v.z,mn,mx)}}; |
| 133 | 2 | } |
| 134 | ||
| 135 | ||
| 136 | 1 | static inline float sign(float a) |
| 137 | { |
|
| 138 | 42 | return a >= 0.0f ? 1.0f : -1.0f; |
| 139 | 1 | } |
| 140 | ||
| 141 | 89 | static inline float sign3(float a) |
| 142 | { |
|
| 143 | return a > 0.0f ? 1.0f : (a < 0.0f ? -1.0f : 0.0f); |
|
| 144 | } |
|
| 145 | ||
| 146 | ||
| 147 | 2 | static inline m16 midentity(void) |
| 148 | { |
|
| 149 | 42 | m16 m = {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}; |
| 150 | 2 | return m; |
| 151 | } |
|
| 152 | 1 | |
| 153 | 5 | static inline m16 mzero(void) |
| 154 | { |
|
| 155 | 42 | m16 m = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}}; |
| 156 | 5 | return m; |
| 157 | } |
|
| 158 | ||
| 159 | ||
| 160 | 1 | static inline m16 mtranspose(const m16 a) |
| 161 | { |
|
| 162 | m16 m; |
|
| 163 | for (int i = 0; i < 4; ++i) |
|
| 164 | for (int j = 0; j < 4; ++j) |
|
| 165 | m.m[i][j] = a.m[j][i]; |
|
| 166 | return m; |
|
| 167 | } |
|
| 168 | ||
| 169 | 2 | static inline m16 mmul(const m16 a, const m16 b) |
| 170 | { |
|
| 171 | m16 mm; |
|
| 172 | ||
| 173 | for (int i = 0; i < 4; i++) |
|
| 174 | { |
|
| 175 | mm.m[i][0] = b.m[i][0]*a.m[0][0] + b.m[i][1]*a.m[1][0] + b.m[i][2]*a.m[2][0] + b.m[i][3]*a.m[3][0]; |
|
| 176 | mm.m[i][1] = b.m[i][0]*a.m[0][1] + b.m[i][1]*a.m[1][1] + b.m[i][2]*a.m[2][1] + b.m[i][3]*a.m[3][1]; |
|
| 177 | mm.m[i][2] = b.m[i][0]*a.m[0][2] + b.m[i][1]*a.m[1][2] + b.m[i][2]*a.m[2][2] + b.m[i][3]*a.m[3][2]; |
|
| 178 | mm.m[i][3] = b.m[i][0]*a.m[0][3] + b.m[i][1]*a.m[1][3] + b.m[i][2]*a.m[2][3] + b.m[i][3]*a.m[3][3]; |
|
| 179 | } |
|
| 180 | ||
| 181 | return mm; |
|
| 182 | } |
|
| 183 | ||
| 184 | ||
| 185 | 1 | static inline v3 mtransformdir3(const m16 a, const v3 b) |
| 186 | { |
|
| 187 | v3 v; |
|
| 188 | v.v.x = a.a[0]*b.v.x + a.a[4]*b.v.y + a.a[8]*b.v.z; |
|
| 189 | v.v.y = a.a[1]*b.v.x + a.a[5]*b.v.y + a.a[9]*b.v.z; |
|
| 190 | v.v.z = a.a[2]*b.v.x + a.a[6]*b.v.y + a.a[10]*b.v.z; |
|
| 191 | |
|
| 192 | return v; |
|
| 193 | } |
|
| 194 | ||
| 195 | 15 | static inline v3 mtransformpos3(const m16 a, const v3 b) |
| 196 | { |
|
| 197 | v3 v; |
|
| 198 | v.v.x = a.a[0]*b.v.x + a.a[4]*b.v.y + a.a[8]*b.v.z + a.a[12]; |
|
| 199 | v.v.y = a.a[1]*b.v.x + a.a[5]*b.v.y + a.a[9]*b.v.z + a.a[13]; |
|
| 200 | v.v.z = a.a[2]*b.v.x + a.a[6]*b.v.y + a.a[10]*b.v.z + a.a[14]; |
|
| 201 | float w = a.a[3]*b.v.x + a.a[7]*b.v.y + a.a[11]*b.v.z + a.a[15]; |
|
| 202 | return vcreate(v.v.x/w, v.v.y/w, v.v.z/w); |
|
| 203 | } |
|
| 204 | ||
| 205 | 89 | static inline CGRect mtransformrect(const m16 a, const CGRect b) |
| 206 | { |
|
| 207 | CGRect rr; |
|
| 208 | rr.origin.x = a.a[0]*b.origin.x + a.a[4]*b.origin.y + a.a[12]; |
|
| 209 | rr.origin.y = a.a[1]*b.origin.x + a.a[5]*b.origin.y + a.a[13]; |
|
| 210 | rr.size.width = a.a[0]*b.size.width + a.a[4]*b.size.height; |
|
| 211 | rr.size.height = a.a[1]*b.size.width + a.a[5]*b.size.height; |
|
| 212 | ||
| 213 | return rr; |
|
| 214 | } |
|
| 215 | ||
| 216 | 15 | |
| 217 | 1 | static inline m16 mcreatefrombases(const v3 ex, const v3 ey, const v3 ez) |
| 218 | { |
|
| 219 | 42 | return (m16){{ex.v.x, ex.v.y, ex.v.z, 0.0f, |
| 220 | ey.v.x, ey.v.y, ey.v.z, 0.0f, |
|
| 221 | ez.v.x, ez.v.y, ez.v.z, 0.0f, |
|
| 222 | 0.0f, 0.0f, 0.0f, 1.0f}}; |
|
| 223 | 1 | } |
| 224 | ||
| 225 | 5 | static inline m16 madjoint(m16 m) |
| 226 | { |
|
| 227 | float A = m.m[2][2]*m.m[3][3] - m.m[3][2]*m.m[2][3]; |
|
| 228 | float B = m.m[1][2]*m.m[3][3] - m.m[3][2]*m.m[1][3]; |
|
| 229 | float C = m.m[1][2]*m.m[2][3] - m.m[2][2]*m.m[1][3]; |
|
| 230 | float D = m.m[0][2]*m.m[3][3] - m.m[3][2]*m.m[0][3]; |
|
| 231 | float E = m.m[0][2]*m.m[2][3] - m.m[2][2]*m.m[0][3]; |
|
| 232 | float F = m.m[0][2]*m.m[1][3] - m.m[1][2]*m.m[0][3]; |
|
| 233 | ||
| 234 | float A3 = m.m[2][1]*m.m[3][3] - m.m[3][1]*m.m[2][3]; |
|
| 235 | float B3 = m.m[1][1]*m.m[3][3] - m.m[3][1]*m.m[1][3]; |
|
| 236 | float C3 = m.m[1][1]*m.m[2][3] - m.m[2][1]*m.m[1][3]; |
|
| 237 | float D3 = m.m[0][1]*m.m[3][3] - m.m[3][1]*m.m[0][3]; |
|
| 238 | float E3 = m.m[0][1]*m.m[2][3] - m.m[2][1]*m.m[0][3]; |
|
| 239 | float F3 = m.m[0][1]*m.m[1][3] - m.m[1][1]*m.m[0][3]; |
|
| 240 | ||
| 241 | float A4 = m.m[2][1]*m.m[3][2] - m.m[3][1]*m.m[2][2]; |
|
| 242 | float B4 = m.m[1][1]*m.m[3][2] - m.m[3][1]*m.m[1][2]; |
|
| 243 | float C4 = m.m[1][1]*m.m[2][2] - m.m[2][1]*m.m[1][2]; |
|
| 244 | float D4 = m.m[0][1]*m.m[3][2] - m.m[3][1]*m.m[0][2]; |
|
| 245 | float E4 = m.m[0][1]*m.m[2][2] - m.m[2][1]*m.m[0][2]; |
|
| 246 | float F4 = m.m[0][1]*m.m[1][2] - m.m[1][1]*m.m[0][2]; |
|
| 247 | ||
| 248 | float AA = m.m[1][1]*A - m.m[2][1]*B + m.m[3][1]*C; |
|
| 249 | float BB = m.m[0][1]*A - m.m[2][1]*D + m.m[3][1]*E; |
|
| 250 | float CC = m.m[0][1]*B - m.m[1][1]*D + m.m[3][1]*F; |
|
| 251 | float DD = m.m[0][1]*C - m.m[1][1]*E + m.m[2][1]*F; |
|
| 252 | ||
| 253 | float EE = m.m[1][0]*A - m.m[2][0]*B + m.m[3][0]*C; |
|
| 254 | float FF = m.m[0][0]*A - m.m[2][0]*D + m.m[3][0]*E; |
|
| 255 | float GG = m.m[0][0]*B - m.m[1][0]*D + m.m[3][0]*F; |
|
| 256 | float HH = m.m[0][0]*C - m.m[1][0]*E + m.m[2][0]*F; |
|
| 257 | ||
| 258 | float II = m.m[1][0]*A3 - m.m[2][0]*B3 + m.m[3][0]*C3; |
|
| 259 | float JJ = m.m[0][0]*A3 - m.m[2][0]*D3 + m.m[3][0]*E3; |
|
| 260 | float KK = m.m[0][0]*B3 - m.m[1][0]*D3 + m.m[3][0]*F3; |
|
| 261 | float LL = m.m[0][0]*C3 - m.m[1][0]*E3 + m.m[2][0]*F3; |
|
| 262 | ||
| 263 | float MM = m.m[1][0]*A4 - m.m[2][0]*B4 + m.m[3][0]*C4; |
|
| 264 | float NN = m.m[0][0]*A4 - m.m[2][0]*D4 + m.m[3][0]*E4; |
|
| 265 | float OO = m.m[0][0]*B4 - m.m[1][0]*D4 + m.m[3][0]*F4; |
|
| 266 | float PP = m.m[0][0]*C4 - m.m[1][0]*E4 + m.m[2][0]*F4; |
|
| 267 | ||
| 268 | ||
| 269 | 42 | return (m16){{AA, -BB, CC, -DD, -EE, FF, -GG, HH, II, -JJ, KK, -LL, -MM, NN, -OO, PP}}; |
| 270 | 5 | |
| 271 | }; |
|
| 272 | ||
| 273 | static inline float mdeterminant(m16 m) |
|
| 274 | { |
|
| 275 | float A = m.m[2][2]*m.m[3][3] - m.m[3][2]*m.m[2][3]; |
|
| 276 | float B = m.m[1][2]*m.m[3][3] - m.m[3][2]*m.m[1][3]; |
|
| 277 | float C = m.m[1][2]*m.m[2][3] - m.m[2][2]*m.m[1][3]; |
|
| 278 | float D = m.m[0][2]*m.m[3][3] - m.m[3][2]*m.m[0][3]; |
|
| 279 | float E = m.m[0][2]*m.m[2][3] - m.m[2][2]*m.m[0][3]; |
|
| 280 | float F = m.m[0][2]*m.m[1][3] - m.m[1][2]*m.m[0][3]; |
|
| 281 | ||
| 282 | float AA = m.m[1][1]*A - m.m[2][1]*B + m.m[3][1]*C; |
|
| 283 | float BB = m.m[0][1]*A - m.m[2][1]*D + m.m[3][1]*E; |
|
| 284 | float CC = m.m[0][1]*B - m.m[1][1]*D + m.m[3][1]*F; |
|
| 285 | float DD = m.m[0][1]*C - m.m[1][1]*E + m.m[2][1]*F; |
|
| 286 | ||
| 287 | float AAA = m.m[0][0]*AA - m.m[1][0]*BB + m.m[2][0]*CC - m.m[3][0]*DD; |
|
| 288 | ||
| 289 | return AAA; |
|
| 290 | ||
| 291 | }; |
|
| 292 | ||
| 293 | static inline m16 mtranslate(v3 v) |
|
| 294 | { |
|
| 295 | ||
| 296 | m16 m = midentity(); |
|
| 297 | m.m[3][0] = v.a[0]; |
|
| 298 | m.m[3][1] = v.a[1]; |
|
| 299 | m.m[3][2] = v.a[2]; |
|
| 300 | ||
| 301 | return m; |
|
| 302 | }; |
|
| 303 | ||
| 304 | static inline m16 mscale(v3 v) |
|
| 305 | { |
|
| 306 | ||
| 307 | m16 m = midentity(); |
|
| 308 | m.m[0][0] = v.a[0]; |
|
| 309 | m.m[1][1] = v.a[1]; |
|
| 310 | m.m[2][2] = v.a[2]; |
|
| 311 | ||
| 312 | return m; |
|
| 313 | }; |
|
| 314 | ||
| 315 | static inline m16 mperspective(float fovy, float aspect, float zNear, float zFar) |
|
| 316 | { |
|
| 317 | m16 m = mzero(); |
|
| 318 | 42 | float f = 1.0f/tanf(fovy*0.5f); |
| 319 | 5 | |
| 320 | m.m[0][0] = f/aspect; |
|
| 321 | m.m[1][1] = f; |
|
| 322 | m.m[2][2] = (zFar+zNear)/(zNear-zFar); |
|
| 323 | m.m[2][3] = -1; |
|
| 324 | 42 | m.m[3][2] = (2.0f*zFar*zNear)/(zNear-zFar); |
| 325 | 5 | |
| 326 | return m; |
|
| 327 | } |
|
| 328 | ||
| 329 | 7 | static inline m16 mortho(float left, float right, float bottom, float top, float zNear, float zFar) |
| 330 | { |
|
| 331 | m16 m = midentity(); |
|
| 332 | |
|
| 333 | 42 | m.m[0][0] = 2.0f/(right-left); |
| 334 | m.m[1][1] = 2.0f/(top-bottom); |
|
| 335 | m.m[2][2] = -2.0f/(zFar-zNear); |
|
| 336 | 15 | m.m[3][0] = -(right+left)/(right - left); |
| 337 | m.m[3][1] = -(top + bottom)/(top - bottom); |
|
| 338 | 7 | m.m[3][2] = -(zFar + zNear)/(zFar - zNear); |
| 339 | ||
| 340 | return m; |
|
| 341 | } |
|
| 342 | ||
| 343 | ||
| 344 | 5 | static inline m16 mmuls(m16 m, float s) |
| 345 | { |
|
| 346 | for (int i = 0; i < 16; ++i) |
|
| 347 | m.a[i] = m.a[i]*s; |
|
| 348 | return m; |
|
| 349 | } |
|
| 350 | ||
| 351 | static inline m16 minverse(m16 m) |
|
| 352 | { |
|
| 353 | m16 mm = madjoint(m); |
|
| 354 | float d = mdeterminant(m); |
|
| 355 | 42 | return mmuls(mm, 1.0f/d); |
| 356 | 5 | }; |
| 357 | ||
| 358 | ||
| 359 | 2 | m16 computeAlignedBasesFromDownVector(v3 acc); |
| 360 | 6 | m16 computeAlignedBasesFromDownVector2(v3 acc, v3 pf); |
| 361 | 14 | |
| 362 | #pragma mark CG extensions |
|
| 363 | ||
| 364 | 80 | static inline CGSize CGSizeScaleDownIntoSize(CGSize a, CGSize b) |
| 365 | 38 | { |
| 366 | CGSize c = a; |
|
| 367 | float heightR = a.height/b.height; |
|
| 368 | float widthR = a.width/b.width; |
|
| 369 | |
|
| 370 | if (heightR > 1.0f) |
|
| 371 | { |
|
| 372 | c.height = b.height; |
|
| 373 | c.width *= 1.0f/heightR; |
|
| 374 | widthR = c.width/b.width; |
|
| 375 | } |
|
| 376 | ||
| 377 | if (widthR > 1.0f) |
|
| 378 | { |
|
| 379 | c.width = b.width; |
|
| 380 | c.height *= 1.0f/widthR; |
|
| 381 | } |
|
| 382 | return c; |
|
| 383 | } |
|
| 384 | ||
| 385 | 80 | static inline CGSize CGSizeFitToSize(CGSize a, CGSize b) |
| 386 | { |
|
| 387 | float heightR = a.height/b.height; |
|
| 388 | float widthR = a.width/b.width; |
|
| 389 | |
|
| 390 | float minr = fmaxf(heightR,widthR); |
|
| 391 | |
|
| 392 | CGSize c = CGSizeMake(a.width*(1.0f/minr), a.height*(1.0f/minr)); |
|
| 393 | |
|
| 394 | return c; |
|
| 395 | } |
|
| 396 | ||
| 397 | 87 | static inline CGSize CGSizeFloor(CGSize a) |
| 398 | { |
|
| 399 | CGSize c = CGSizeMake(floorf(a.width), floorf(a.height)); |
|
| 400 | |
|
| 401 | return c; |
|
| 402 | } |
|
| 403 | ||
| 404 | 38 | |
| 405 | 74 | static inline CGPoint CGPointMin(CGPoint a, CGPoint b) |
| 406 | { |
|
| 407 | return CGPointMake(fminf(a.x,b.x), fminf(a.y,b.y)); |
|
| 408 | } |
|
| 409 | ||
| 410 | static inline CGPoint CGPointMax(CGPoint a, CGPoint b) |
|
| 411 | { |
|
| 412 | return CGPointMake(fmaxf(a.x,b.x), fmaxf(a.y,b.y)); |
|
| 413 | } |
|
| 414 | ||
| 415 | 14 | static inline CGPoint CGPointAdd(CGPoint a, CGPoint b) |
| 416 | { |
|
| 417 | return CGPointMake(a.x+b.x, a.y+b.y); |
|
| 418 | } |
|
| 419 | ||
| 420 | static inline CGPoint CGPointSub(CGPoint a, CGPoint b) |
|
| 421 | { |
|
| 422 | return CGPointMake(a.x-b.x, a.y-b.y); |
|
| 423 | } |
|
| 424 | ||
| 425 | static inline CGPoint CGPointScale(CGPoint a, float b) |
|
| 426 | { |
|
| 427 | return CGPointMake(a.x*b, a.y*b); |
|
| 428 | } |
|
| 429 | ||
| 430 | 66 | static inline CGSize CGSizeScale(CGSize a, float b) |
| 431 | { |
|
| 432 | return CGSizeMake(a.width*b, a.height*b); |
|
| 433 | } |
|
| 434 | ||
| 435 | 14 | static inline float CGPointDoubleDot(CGPoint a) |
| 436 | { |
|
| 437 | return a.x*a.x+a.y*a.y; |
|
| 438 | } |
|
| 439 | ||
| 440 | static inline float CGPointDot(CGPoint a, CGPoint b) |
|
| 441 | { |
|
| 442 | return (a.x*b.x + a.y*b.y); |
|
| 443 | } |
|
| 444 | ||
| 445 | static inline float CGPointCross(CGPoint a, CGPoint b) |
|
| 446 | { |
|
| 447 | return (a.x*b.y - a.y*b.x); |
|
| 448 | } |
|
| 449 | ||
| 450 | 17 | static inline CGPoint CGPointNormalize(CGPoint a) |
| 451 | { |
|
| 452 | float l1 = 1.0f/sqrtf(a.x*a.x+a.y*a.y); |
|
| 453 | return CGPointMake(a.x*l1, a.y*l1); |
|
| 454 | } |
|
| 455 | ||
| 456 | 24 | static inline CGPoint CGPointNegate(CGPoint a) |
| 457 | { |
|
| 458 | return CGPointMake(-a.x, -a.y); |
|
| 459 | } |
|
| 460 | ||
| 461 | 38 | static inline CGPoint CGPointNormal(CGPoint a) |
| 462 | { |
|
| 463 | return CGPointMake(-a.y, a.x); |
|
| 464 | } |
|
| 465 | ||
| 466 | 24 | static inline float CGPointLength(CGPoint a) |
| 467 | { |
|
| 468 | return sqrtf(a.x*a.x+a.y*a.y); |
|
| 469 | } |
|
| 470 | ||
| 471 | 17 | static inline CGPoint CGPointProject(CGPoint a, CGPoint b) |
| 472 | { |
|
| 473 | return CGPointScale(b, CGPointDot(a,b)/CGPointDot(b,b)); |
|
| 474 | } |
|
| 475 | ||
| 476 | static inline CGPoint CGPointReverseProject(CGPoint a, CGPoint b) |
|
| 477 | { |
|
| 478 | return CGPointScale(b, CGPointDot(a,a)/CGPointDot(a,b)); |
|
| 479 | } |
|
| 480 | ||
| 481 | 66 | static inline CGPoint CGPointLerp(CGPoint a, CGPoint b, float t) |
| 482 | { |
|
| 483 | return CGPointAdd(a, CGPointScale(CGPointSub(b, a), t)); |
|
| 484 | } |
|
| 485 | ||
| 486 | ||
| 487 | static inline CGPoint CGPointRotate(CGPoint a, float w) |
|
| 488 | { |
|
| 489 | float cosa = cosf(w), sina = sin(w); |
|
| 490 | |
|
| 491 | CGPoint r; |
|
| 492 | ||
| 493 | 74 | r.x = a.x*cosa - a.y*sina; |
| 494 | r.y = a.y*cosa + a.x*sina; |
|
| 495 | 66 | |
| 496 | return r; |
|
| 497 | |
|
| 498 | } |
|
| 499 | ||
| 500 | 84 | static inline CGRect CGRectLerp(CGRect a, CGRect b, CGFloat t) |
| 501 | { |
|
| 502 | CGFloat t1 = 1.0 - t; |
|
| 503 | return CGRectMake(a.origin.x*t1 + b.origin.x*t, a.origin.y*t1 + b.origin.y*t, a.size.width*t1 + b.size.width*t, a.size.height*t1 + b.size.height*t); |
|
| 504 | } |
|
| 505 | ||
| 506 | 17 | |
| 507 | 14 | static inline long CGLineSegmentsIntersect2(CGPoint p0, CGPoint p1, CGPoint p2, CGPoint p3) |
| 508 | { |
|
| 509 | float d = (p3.y - p2.y)*(p1.x - p0.x) - (p3.x - p2.x)*(p1.y - p0.y); |
|
| 510 | |
|
| 511 | if (d == 0.0) |
|
| 512 | return 0; |
|
| 513 | |
|
| 514 | float a = (p3.x - p2.x)*(p0.y - p2.y) + (p3.y - p2.y)*(p0.x - p2.x); |
|
| 515 | float b = (p1.x - p0.x)*(p0.y - p2.y) + (p1.y - p0.y)*(p0.x - p2.x); |
|
| 516 | |
|
| 517 | float ta = a/d; |
|
| 518 | float tb = b/d; |
|
| 519 | ||
| 520 | return ((ta > 0.0) && (ta < 1.0) && (tb > 0.0) && (tb < 1.0)); |
|
| 521 | } |
|
| 522 | ||
| 523 | static inline long CGLineSegmentsIntersect(CGPoint p0, CGPoint p1, CGPoint p2, CGPoint p3) |
|
| 524 | { |
|
| 525 | float d = CGPointCross(CGPointSub(p1,p0), CGPointSub(p3,p2)); |
|
| 526 | |
|
| 527 | if (d == 0.0) |
|
| 528 | return 0; |
|
| 529 | |
|
| 530 | float a = CGPointCross(CGPointSub(p2,p0), CGPointSub(p3,p2)); |
|
| 531 | float b = CGPointCross(CGPointSub(p2,p0), CGPointSub(p1,p0)); |
|
| 532 | |
|
| 533 | float ta = a/d; |
|
| 534 | float tb = b/d; |
|
| 535 | ||
| 536 | return ((ta > 0.0) && (ta < 1.0) && (tb > 0.0) && (tb < 1.0)); |
|
| 537 | } |
|
| 538 | ||
| 539 | 23 | static inline CGPoint CGLineIntersectionPoint(CGPoint p0, CGPoint p1, CGPoint p2, CGPoint p3) |
| 540 | { |
|
| 541 | float d = CGPointCross(CGPointSub(p1,p0), CGPointSub(p3,p2)); |
|
| 542 | |
|
| 543 | if (d == 0.0) |
|
| 544 | return CGPointZero; |
|
| 545 | |
|
| 546 | // float a = CGPointCross(CGPointSub(p2,p0), CGPointSub(p3,p2)); |
|
| 547 | float b = CGPointCross(CGPointSub(p2,p0), CGPointSub(p1,p0)); |
|
| 548 | |
|
| 549 | // float ta = a/d; |
|
| 550 | float tb = b/d; |
|
| 551 | ||
| 552 | return CGPointAdd(p2, CGPointScale(CGPointSub(p3,p2), tb)); |
|
| 553 | } |
|
| 554 | ||
| 555 | ||
| 556 | 16 | static inline long CGPointInTriangle(CGPoint p, CGPoint a0, CGPoint a1, CGPoint a2) |
| 557 | { |
|
| 558 | CGPoint v0 = CGPointSub(a1, a0); |
|
| 559 | CGPoint v1 = CGPointSub(a2, a0); |
|
| 560 | CGPoint v2 = CGPointSub(p, a0); |
|
| 561 | ||
| 562 | float dot00 = CGPointDot(v0, v0); |
|
| 563 | float dot01 = CGPointDot(v0, v1); |
|
| 564 | float dot02 = CGPointDot(v0, v2); |
|
| 565 | float dot11 = CGPointDot(v1, v1); |
|
| 566 | float dot12 = CGPointDot(v1, v2); |
|
| 567 | ||
| 568 | 42 | float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01); |
| 569 | 16 | float u = (dot11 * dot02 - dot01 * dot12) * invDenom; |
| 570 | float v = (dot00 * dot12 - dot01 * dot02) * invDenom; |
|
| 571 | ||
| 572 | return (u > 0) && (v > 0) && (u + v < 1.0); |
|
| 573 | ||
| 574 | } |
|
| 575 | 14 | |
| 576 | 17 | static long CGPointInCircumCircule(CGPoint d, CGPoint a, CGPoint b, CGPoint c) |
| 577 | { |
|
| 578 | float m[3][3] = { |
|
| 579 | { a.x-d.x, b.x-d.x, c.x-d.x }, |
|
| 580 | { a.y-d.y, b.y-d.y, c.y-d.y }, |
|
| 581 | { CGPointDoubleDot(a) - CGPointDoubleDot(d), CGPointDoubleDot(b) - CGPointDoubleDot(d), CGPointDoubleDot(a) - CGPointDoubleDot(c), } |
|
| 582 | }; |
|
| 583 | |
|
| 584 | float cof[3] = { |
|
| 585 | m[1][1]*m[2][2] - m[2][1]*m[1][2], |
|
| 586 | m[0][1]*m[2][2] - m[2][1]*m[0][2], |
|
| 587 | m[0][1]*m[1][2] - m[1][1]*m[0][2] |
|
| 588 | }; |
|
| 589 | float det = m[0][0]*cof[0] - m[1][0]*cof[1] + m[2][0]*cof[2]; |
|
| 590 | |
|
| 591 | return det > 0; |
|
| 592 | } |
|
| 593 | ||
| 594 | ||
| 595 | ||
| 596 | 14 | static inline CGPoint cubicPointAtT(CGPoint p0, CGPoint p1, CGPoint p2, CGPoint p3, float t) |
| 597 | { |
|
| 598 | 42 | float t1 = 1.0f-t; |
| 599 | 14 | CGPoint p01 = CGPointAdd(CGPointScale(p0, t1), CGPointScale(p1, t)); |
| 600 | CGPoint p12 = CGPointAdd(CGPointScale(p1, t1), CGPointScale(p2, t)); |
|
| 601 | CGPoint p23 = CGPointAdd(CGPointScale(p2, t1), CGPointScale(p3, t)); |
|
| 602 | CGPoint p02 = CGPointAdd(CGPointScale(p01, t1), CGPointScale(p12, t)); |
|
| 603 | CGPoint p13 = CGPointAdd(CGPointScale(p12, t1), CGPointScale(p23, t)); |
|
| 604 | CGPoint p03 = CGPointAdd(CGPointScale(p02, t1), CGPointScale(p13, t)); |
|
| 605 | return p03; |
|
| 606 | } |
|
| 607 | ||
| 608 | static inline CGPoint quadraticPointAtT(CGPoint p0, CGPoint p1, CGPoint p2, float t) |
|
| 609 | { |
|
| 610 | 42 | float t1 = 1.0f-t; |
| 611 | 14 | CGPoint p01 = CGPointAdd(CGPointScale(p0, t1), CGPointScale(p1, t)); |
| 612 | CGPoint p12 = CGPointAdd(CGPointScale(p1, t1), CGPointScale(p2, t)); |
|
| 613 | CGPoint p02 = CGPointAdd(CGPointScale(p01, t1), CGPointScale(p12, t)); |
|
| 614 | return p02; |
|
| 615 | } |
|
| 616 | ||
| 617 | static inline CGPoint linearPointAtT(CGPoint p0, CGPoint p1, float t) |
|
| 618 | { |
|
| 619 | 42 | float t1 = 1.0f-t; |
| 620 | 14 | CGPoint p01 = CGPointAdd(CGPointScale(p0, t1), CGPointScale(p1, t)); |
| 621 | return p01; |
|
| 622 | } |
|
| 623 | ||
| 624 | 15 | CGPathRef CreateTransformedPathFromCGPath(CGPathRef cpath, CGAffineTransform m); |
| 625 | ||
| 626 | CGPoint CGPointTransform(CGPoint a, CGAffineTransform m); |
Loggerhead 1.17 is a web-based interface for Bazaar branches