├── LICENSE ├── README.md ├── MetalMatrix.h └── MetalMatrix.m /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MetalMatrix 2 | 3 | Metal matrices for 3D-Transformation.Including Scale / Translate / Rotate / LookAt / Projection / Orthographic / Frustum, and some Off-Center versions. 4 | 5 | Each matrix api will return a `simd_float4x4` structure. 6 | 7 | You can found the example usage in [my another repo](https://github.com/SourceKim/MetalTest),just run and search "mm_",check the code and do tests yourself. 8 | 9 | ## Convert degrees to radians (Macro) 10 | 11 | ```objc 12 | MM_RADIANS(degrees) 13 | ``` 14 | 15 | ## Matrix Size 16 | 17 | ```objc 18 | + (NSUInteger)mm_matrixSize; 19 | ``` 20 | 21 | ## Identity Matrix 22 | 23 | ```objc 24 | + (simd_float4x4)mm_identity; 25 | ``` 26 | 27 | ## Scale Matrix 28 | 29 | ```objc 30 | + (simd_float4x4)mm_scale: (simd_float3)vector; 31 | 32 | + (simd_float4x4)mm_scaleWithX: (float)x 33 | withY: (float)y 34 | withZ: (float)z; 35 | ``` 36 | 37 | ## Translate Matrix 38 | 39 | ```objc 40 | + (simd_float4x4)mm_translate: (simd_float3)vector; 41 | 42 | + (simd_float4x4)mm_translateWithX: (float)x 43 | withY: (float)y 44 | withZ: (float)z; 45 | ``` 46 | 47 | ## Rotate Matrix 48 | 49 | + (simd_float4x4)mm_rotate: (float)angle 50 | axis: (simd_float3)axis; 51 | 52 | + (simd_float4x4)mm_rotate: (float)angle 53 | withX: (float)x 54 | withY: (float)y 55 | withZ: (float)z; 56 | 57 | 58 | ## Perspective Matrix 59 | 60 | ```objc 61 | + (simd_float4x4)mm_perspectiveWithWidth: (float)width 62 | withHeight: (float)height 63 | withNear: (float)near 64 | withFar: (float)far; 65 | 66 | + (simd_float4x4)mm_perspectiveWithFovy: (float)fovy 67 | withAspect: (float)aspect 68 | withNear: (float)near 69 | withFar: (float)far; 70 | 71 | + (simd_float4x4)mm_perspectiveWithFovy: (float)fovy 72 | withWidth: (float)width 73 | withHeight: (float)height 74 | withNear: (float)near 75 | withFar: (float)far; 76 | ``` 77 | 78 | 79 | ## LookAt Matrix 80 | 81 | ```objc 82 | + (simd_float4x4)mm_lookAtWithEye: (simd_float3)eye 83 | withCenter: (simd_float3)center 84 | withUp: (simd_float3)up; 85 | 86 | + (simd_float4x4)mm_lookAtWithEyeX: (float)eyeX 87 | withEyeY: (float)eyeY 88 | withEyeZ: (float)eyeZ 89 | withCenterX: (float)centerX 90 | withCenterY: (float)centerY 91 | withCenterZ: (float)centerZ 92 | withUpX: (float)upX 93 | withUpY: (float)upY 94 | withUpZ: (float)upZ; 95 | ``` 96 | 97 | ## Orthographic Matrix 98 | 99 | ```objc 100 | + (simd_float4x4)mm_orthoWithLeft: (float)left 101 | withRight: (float)right 102 | withBottom: (float)bottom 103 | withTop: (float)top 104 | withNear: (float)near 105 | withFar: (float)far; 106 | 107 | + (simd_float4x4)mm_orthoWithOrigin: (simd_float3)origin 108 | withSize: (simd_float3)size; 109 | ``` 110 | 111 | 112 | ## Off-Center Orthographic Matrix 113 | 114 | ```objc 115 | + (simd_float4x4)mm_ortho_ocWithLeft: (float)left 116 | withRight: (float)right 117 | withBottom: (float)bottom 118 | withTop: (float)top 119 | withNear: (float)near 120 | withFar: (float)far; 121 | 122 | + (simd_float4x4)mm_ortho_ocWithOrigin: (simd_float3)origin 123 | withSize: (simd_float3)size; 124 | ``` 125 | 126 | ## Frustum Matrix 127 | 128 | ```objc 129 | + (simd_float4x4)mm_frustumWithFovH: (float)fovH 130 | withFovV: (float)fovV 131 | withNear: (float)near 132 | withFar: (float)far; 133 | 134 | + (simd_float4x4)mm_frustumWithLeft: (float)left 135 | withRight: (float)right 136 | withBotoom: (float)bottom 137 | withTop: (float)top 138 | withNear: (float)near 139 | withFar: (float)far; 140 | ``` 141 | 142 | ## Off-Center Frustum Matrix 143 | 144 | ```objc 145 | + (simd_float4x4)mm_frustum_ocWithLeft: (float)left 146 | withRight: (float)right 147 | withBotoom: (float)bottom 148 | withTop: (float)top 149 | withNear: (float)near 150 | withFar: (float)far; 151 | ``` -------------------------------------------------------------------------------- /MetalMatrix.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalMatrix.h 3 | // MetalTest 4 | // 5 | // Created by 苏金劲 on 2020/6/8. 6 | // Copyright © 2020 苏金劲. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | 13 | #define MM_kRADIANS (1.0f / 180.0f * M_PI) 14 | 15 | // Convert degrees to radians 16 | #define MM_RADIANS(degrees) degrees * MM_kRADIANS 17 | 18 | #define MM_RADIANS_OVER_PI(degrees) degrees * (1.f / 180.f) 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | @interface MetalMatrix : NSObject 23 | 24 | #pragma mark Public - MatrixSize 25 | 26 | + (NSUInteger)mm_matrixSize; 27 | 28 | 29 | #pragma mark Public - Identity 30 | 31 | + (simd_float4x4)mm_identity; 32 | 33 | 34 | #pragma mark Public - Transformations - Scale 35 | 36 | + (simd_float4x4)mm_scale: (simd_float3)vector; 37 | 38 | + (simd_float4x4)mm_scaleWithX: (float)x 39 | withY: (float)y 40 | withZ: (float)z; 41 | 42 | 43 | #pragma mark Public - Transformations - Translate 44 | 45 | + (simd_float4x4)mm_translate: (simd_float3)vector; 46 | 47 | + (simd_float4x4)mm_translateWithX: (float)x 48 | withY: (float)y 49 | withZ: (float)z; 50 | 51 | 52 | #pragma mark Public - Transformations - Rotate 53 | 54 | + (simd_float4x4)mm_rotate: (float)angle 55 | axis: (simd_float3)axis; 56 | 57 | + (simd_float4x4)mm_rotate: (float)angle 58 | withX: (float)x 59 | withY: (float)y 60 | withZ: (float)z; 61 | 62 | 63 | #pragma mark Public - Transformations - Perspective 64 | 65 | + (simd_float4x4)mm_perspectiveWithWidth: (float)width 66 | withHeight: (float)height 67 | withNear: (float)near 68 | withFar: (float)far; 69 | 70 | + (simd_float4x4)mm_perspectiveWithFovy: (float)fovy 71 | withAspect: (float)aspect 72 | withNear: (float)near 73 | withFar: (float)far; 74 | 75 | + (simd_float4x4)mm_perspectiveWithFovy: (float)fovy 76 | withWidth: (float)width 77 | withHeight: (float)height 78 | withNear: (float)near 79 | withFar: (float)far; 80 | 81 | 82 | #pragma mark Public - Transformations - LookAt 83 | 84 | + (simd_float4x4)mm_lookAtWithEye: (simd_float3)eye 85 | withCenter: (simd_float3)center 86 | withUp: (simd_float3)up; 87 | 88 | + (simd_float4x4)mm_lookAtWithEyeX: (float)eyeX 89 | withEyeY: (float)eyeY 90 | withEyeZ: (float)eyeZ 91 | withCenterX: (float)centerX 92 | withCenterY: (float)centerY 93 | withCenterZ: (float)centerZ 94 | withUpX: (float)upX 95 | withUpY: (float)upY 96 | withUpZ: (float)upZ; 97 | 98 | 99 | #pragma mark Public - Transformations - Orthographic 100 | 101 | + (simd_float4x4)mm_orthoWithLeft: (float)left 102 | withRight: (float)right 103 | withBottom: (float)bottom 104 | withTop: (float)top 105 | withNear: (float)near 106 | withFar: (float)far; 107 | 108 | + (simd_float4x4)mm_orthoWithOrigin: (simd_float3)origin 109 | withSize: (simd_float3)size; 110 | 111 | 112 | #pragma mark Public - Transformations - Off-Center Orthographic 113 | 114 | + (simd_float4x4)mm_ortho_ocWithLeft: (float)left 115 | withRight: (float)right 116 | withBottom: (float)bottom 117 | withTop: (float)top 118 | withNear: (float)near 119 | withFar: (float)far; 120 | 121 | + (simd_float4x4)mm_ortho_ocWithOrigin: (simd_float3)origin 122 | withSize: (simd_float3)size; 123 | 124 | 125 | #pragma mark Public - Transformations - frustum 126 | 127 | + (simd_float4x4)mm_frustumWithFovH: (float)fovH 128 | withFovV: (float)fovV 129 | withNear: (float)near 130 | withFar: (float)far; 131 | 132 | + (simd_float4x4)mm_frustumWithLeft: (float)left 133 | withRight: (float)right 134 | withBotoom: (float)bottom 135 | withTop: (float)top 136 | withNear: (float)near 137 | withFar: (float)far; 138 | 139 | 140 | #pragma mark Public - Transformations - Off-Center frustum 141 | 142 | + (simd_float4x4)mm_frustum_ocWithLeft: (float)left 143 | withRight: (float)right 144 | withBotoom: (float)bottom 145 | withTop: (float)top 146 | withNear: (float)near 147 | withFar: (float)far; 148 | @end 149 | 150 | NS_ASSUME_NONNULL_END 151 | -------------------------------------------------------------------------------- /MetalMatrix.m: -------------------------------------------------------------------------------- 1 | // 2 | // MetalMatrix.m 3 | // MetalTest 4 | // 5 | // Created by 苏金劲 on 2020/6/8. 6 | // Copyright © 2020 苏金劲. All rights reserved. 7 | // 8 | 9 | #import "MetalMatrix.h" 10 | 11 | @implementation MetalMatrix 12 | 13 | #pragma mark Public - MatrixSize 14 | 15 | + (NSUInteger)mm_matrixSize { 16 | 17 | return sizeof(simd_float4x4); 18 | } 19 | 20 | #pragma mark Public - Identity 21 | 22 | + (simd_float4x4)mm_identity { 23 | 24 | return matrix_identity_float4x4; 25 | } 26 | 27 | #pragma mark Public - Transformations - Scale 28 | 29 | + (simd_float4x4)mm_scale: (simd_float3)vector { 30 | 31 | simd_float4 v = simd_make_float4(vector, 1); 32 | 33 | return simd_diagonal_matrix(v); 34 | } 35 | 36 | + (simd_float4x4)mm_scaleWithX: (float)x 37 | withY: (float)y 38 | withZ: (float)z { 39 | 40 | simd_float3 v = simd_make_float3(x, y, z); 41 | 42 | return [self mm_scale: v]; 43 | } 44 | 45 | #pragma mark Public - Transformations - Translate 46 | 47 | + (simd_float4x4)mm_translate: (simd_float3)vector { 48 | 49 | simd_float4x4 M = matrix_identity_float4x4; 50 | 51 | M.columns[3].xyz = vector; 52 | return M; 53 | } 54 | 55 | + (simd_float4x4)mm_translateWithX: (float)x 56 | withY: (float)y 57 | withZ: (float)z { 58 | 59 | simd_float3 v = simd_make_float3(x, y, z); 60 | 61 | return [self mm_translate: v]; 62 | } 63 | 64 | #pragma mark Public - Transformations - Rotate 65 | 66 | + (simd_float4x4)mm_rotate: (float)angle 67 | axis: (simd_float3)axis { 68 | 69 | float a = MM_RADIANS_OVER_PI(angle); 70 | float c = 0.0f; 71 | float s = 0.0f; 72 | 73 | // Computes the sine and cosine of pi times angle (measured in radians) 74 | // faster and gives exact results for angle = 90, 180, 270, etc. 75 | __sincospif(a, &s, &c); 76 | 77 | float k = 1.0f - c; 78 | 79 | simd_float3 u = simd_normalize(axis); 80 | simd_float3 v = s * u; 81 | simd_float3 w = k * u; 82 | 83 | simd_float4 P; 84 | simd_float4 Q; 85 | simd_float4 R; 86 | simd_float4 S; 87 | 88 | P.x = w.x * u.x + c; 89 | P.y = w.x * u.y + v.z; 90 | P.z = w.x * u.z - v.y; 91 | P.w = 0.0f; 92 | 93 | Q.x = w.x * u.y - v.z; 94 | Q.y = w.y * u.y + c; 95 | Q.z = w.y * u.z + v.x; 96 | Q.w = 0.0f; 97 | 98 | R.x = w.x * u.z + v.y; 99 | R.y = w.y * u.z - v.x; 100 | R.z = w.z * u.z + c; 101 | R.w = 0.0f; 102 | 103 | S.x = 0.0f; 104 | S.y = 0.0f; 105 | S.z = 0.0f; 106 | S.w = 1.0f; 107 | 108 | return simd_matrix(P, Q, R, S); 109 | } 110 | 111 | + (simd_float4x4)mm_rotate: (float)angle 112 | withX: (float)x 113 | withY: (float)y 114 | withZ: (float)z { 115 | 116 | simd_float3 v = simd_make_float3(x, y, z); 117 | 118 | return [self mm_rotate: angle axis: v]; 119 | } 120 | 121 | #pragma mark Public - Transformations - Perspective 122 | 123 | + (simd_float4x4)mm_perspectiveWithWidth: (float)width 124 | withHeight: (float)height 125 | withNear: (float)near 126 | withFar: (float)far { 127 | 128 | float zNear = 2.0f * near; 129 | float zFar = far / (far - near); 130 | 131 | simd_float4 P; 132 | simd_float4 Q; 133 | simd_float4 R; 134 | simd_float4 S; 135 | 136 | P.x = zNear / width; 137 | P.y = 0.0f; 138 | P.z = 0.0f; 139 | P.w = 0.0f; 140 | 141 | Q.x = 0.0f; 142 | Q.y = zNear / height; 143 | Q.z = 0.0f; 144 | Q.w = 0.0f; 145 | 146 | R.x = 0.0f; 147 | R.y = 0.0f; 148 | R.z = zFar; 149 | R.w = 1.0f; 150 | 151 | S.x = 0.0f; 152 | S.y = 0.0f; 153 | S.z = -near * zFar; 154 | S.w = 0.0f; 155 | 156 | return simd_matrix(P, Q, R, S); 157 | } 158 | 159 | + (simd_float4x4)mm_perspectiveWithFovy: (float)fovy 160 | withAspect: (float)aspect 161 | withNear: (float)near 162 | withFar: (float)far { 163 | 164 | float angle = MM_RADIANS(0.5 * fovy); 165 | float yScale = 1.0f / tanf(angle); 166 | float xScale = yScale / aspect; 167 | float zScale = far / (far - near); 168 | 169 | simd_float4 P; 170 | simd_float4 Q; 171 | simd_float4 R; 172 | simd_float4 S; 173 | 174 | P.x = xScale; 175 | P.y = 0.0f; 176 | P.z = 0.0f; 177 | P.w = 0.0f; 178 | 179 | Q.x = 0.0f; 180 | Q.y = yScale; 181 | Q.z = 0.0f; 182 | Q.w = 0.0f; 183 | 184 | R.x = 0.0f; 185 | R.y = 0.0f; 186 | R.z = zScale; 187 | R.w = 1.0f; 188 | 189 | S.x = 0.0f; 190 | S.y = 0.0f; 191 | S.z = -near * zScale; 192 | S.w = 0.0f; 193 | 194 | return simd_matrix(P, Q, R, S); 195 | } 196 | 197 | + (simd_float4x4)mm_perspectiveWithFovy: (float)fovy 198 | withWidth: (float)width 199 | withHeight: (float)height 200 | withNear: (float)near 201 | withFar: (float)far { 202 | 203 | float aspect = width / height; 204 | 205 | return [self mm_perspectiveWithFovy: fovy 206 | withAspect: aspect 207 | withNear: near 208 | withFar: far]; 209 | } 210 | 211 | #pragma mark Public - Transformations - LookAt 212 | 213 | + (simd_float4x4)mm_lookAtWithEye: (simd_float3)eye 214 | withCenter: (simd_float3)center 215 | withUp: (simd_float3)up { 216 | 217 | 218 | simd_float3 zAxis = simd_normalize(center - eye); 219 | simd_float3 xAxis = simd_normalize(simd_cross(up, zAxis)); 220 | simd_float3 yAxis = simd_cross(zAxis, xAxis); 221 | 222 | simd_float4 P; 223 | simd_float4 Q; 224 | simd_float4 R; 225 | simd_float4 S; 226 | 227 | P.x = xAxis.x; 228 | P.y = yAxis.x; 229 | P.z = zAxis.x; 230 | P.w = 0.0f; 231 | 232 | Q.x = xAxis.y; 233 | Q.y = yAxis.y; 234 | Q.z = zAxis.y; 235 | Q.w = 0.0f; 236 | 237 | R.x = xAxis.z; 238 | R.y = yAxis.z; 239 | R.z = zAxis.z; 240 | R.w = 0.0f; 241 | 242 | S.x = -simd_dot(xAxis, eye); 243 | S.y = -simd_dot(yAxis, eye); 244 | S.z = -simd_dot(zAxis, eye); 245 | S.w = 1.0f; 246 | 247 | return simd_matrix(P, Q, R, S); 248 | } 249 | 250 | + (simd_float4x4)mm_lookAtWithEyeX: (float)eyeX 251 | withEyeY: (float)eyeY 252 | withEyeZ: (float)eyeZ 253 | withCenterX: (float)centerX 254 | withCenterY: (float)centerY 255 | withCenterZ: (float)centerZ 256 | withUpX: (float)upX 257 | withUpY: (float)upY 258 | withUpZ: (float)upZ { 259 | 260 | return [self mm_lookAtWithEye: simd_make_float3(eyeX, eyeY, eyeZ) 261 | withCenter: simd_make_float3(centerX, centerY, centerZ) 262 | withUp: simd_make_float3(upX, upY, upZ)]; 263 | } 264 | 265 | #pragma mark Public - Transformations - Orthographic 266 | 267 | + (simd_float4x4)mm_orthoWithLeft: (float)left 268 | withRight: (float)right 269 | withBottom: (float)bottom 270 | withTop: (float)top 271 | withNear: (float)near 272 | withFar: (float)far { 273 | 274 | float sLength = 1.0f / (right - left); 275 | float sHeight = 1.0f / (top - bottom); 276 | float sDepth = 1.0f / (far - near); 277 | 278 | simd_float4 P; 279 | simd_float4 Q; 280 | simd_float4 R; 281 | simd_float4 S; 282 | 283 | P.x = 2.0f * sLength; 284 | P.y = 0.0f; 285 | P.z = 0.0f; 286 | P.w = 0.0f; 287 | 288 | Q.x = 0.0f; 289 | Q.y = 2.0f * sHeight; 290 | Q.z = 0.0f; 291 | Q.w = 0.0f; 292 | 293 | R.x = 0.0f; 294 | R.y = 0.0f; 295 | R.z = sDepth; 296 | R.w = 0.0f; 297 | 298 | S.x = 0.0f; 299 | S.y = 0.0f; 300 | S.z = -near * sDepth; 301 | S.w = 1.0f; 302 | 303 | return simd_matrix(P, Q, R, S); 304 | } 305 | 306 | + (simd_float4x4)mm_orthoWithOrigin: (simd_float3)origin 307 | withSize: (simd_float3)size { 308 | 309 | return [self mm_orthoWithLeft: origin.x 310 | withRight: origin.y 311 | withBottom: origin.z 312 | withTop: size.x 313 | withNear: size.y 314 | withFar: size.z]; 315 | } 316 | 317 | #pragma mark Public - Transformations - Off-Center Orthographic 318 | 319 | + (simd_float4x4)mm_ortho_ocWithLeft: (float)left 320 | withRight: (float)right 321 | withBottom: (float)bottom 322 | withTop: (float)top 323 | withNear: (float)near 324 | withFar: (float)far { 325 | 326 | float sLength = 1.0f / (right - left); 327 | float sHeight = 1.0f / (top - bottom); 328 | float sDepth = 1.0f / (far - near); 329 | 330 | simd_float4 P; 331 | simd_float4 Q; 332 | simd_float4 R; 333 | simd_float4 S; 334 | 335 | P.x = 2.0f * sLength; 336 | P.y = 0.0f; 337 | P.z = 0.0f; 338 | P.w = 0.0f; 339 | 340 | Q.x = 0.0f; 341 | Q.y = 2.0f * sHeight; 342 | Q.z = 0.0f; 343 | Q.w = 0.0f; 344 | 345 | R.x = 0.0f; 346 | R.y = 0.0f; 347 | R.z = sDepth; 348 | R.w = 0.0f; 349 | 350 | S.x = -sLength * (left + right); 351 | S.y = -sHeight * (top + bottom); 352 | S.z = -sDepth * near; 353 | S.w = 1.0f; 354 | 355 | return simd_matrix(P, Q, R, S); 356 | } 357 | 358 | + (simd_float4x4)mm_ortho_ocWithOrigin: (simd_float3)origin 359 | withSize: (simd_float3)size { 360 | 361 | return [self mm_ortho_ocWithLeft: origin.x 362 | withRight: origin.y 363 | withBottom: origin.z 364 | withTop: size.x 365 | withNear: size.y 366 | withFar: size.z]; 367 | } 368 | 369 | #pragma mark Public - Transformations - frustum 370 | 371 | + (simd_float4x4)mm_frustumWithFovH: (float)fovH 372 | withFovV: (float)fovV 373 | withNear: (float)near 374 | withFar: (float)far { 375 | 376 | float width = 1.0f / tanf(MM_RADIANS(0.5f * fovH)); 377 | float height = 1.0f / tanf(MM_RADIANS(0.5f * fovV)); 378 | float sDepth = far / ( far - near ); 379 | 380 | simd_float4 P; 381 | simd_float4 Q; 382 | simd_float4 R; 383 | simd_float4 S; 384 | 385 | P.x = width; 386 | P.y = 0.0f; 387 | P.z = 0.0f; 388 | P.w = 0.0f; 389 | 390 | Q.x = 0.0f; 391 | Q.y = height; 392 | Q.z = 0.0f; 393 | Q.w = 0.0f; 394 | 395 | R.x = 0.0f; 396 | R.y = 0.0f; 397 | R.z = sDepth; 398 | R.w = 1.0f; 399 | 400 | S.x = 0.0f; 401 | S.y = 0.0f; 402 | S.z = -sDepth * near; 403 | S.w = 0.0f; 404 | 405 | return simd_matrix(P, Q, R, S); 406 | } 407 | 408 | + (simd_float4x4)mm_frustumWithLeft: (float)left 409 | withRight: (float)right 410 | withBotoom: (float)bottom 411 | withTop: (float)top 412 | withNear: (float)near 413 | withFar: (float)far { 414 | 415 | float width = right - left; 416 | float height = top - bottom; 417 | float depth = far - near; 418 | float sDepth = far / depth; 419 | 420 | simd_float4 P; 421 | simd_float4 Q; 422 | simd_float4 R; 423 | simd_float4 S; 424 | 425 | P.x = width; 426 | P.y = 0.0f; 427 | P.z = 0.0f; 428 | P.w = 0.0f; 429 | 430 | Q.x = 0.0f; 431 | Q.y = height; 432 | Q.z = 0.0f; 433 | Q.w = 0.0f; 434 | 435 | R.x = 0.0f; 436 | R.y = 0.0f; 437 | R.z = sDepth; 438 | R.w = 1.0f; 439 | 440 | S.x = 0.0f; 441 | S.y = 0.0f; 442 | S.z = -sDepth * near; 443 | S.w = 0.0f; 444 | 445 | return simd_matrix(P, Q, R, S); 446 | } 447 | 448 | #pragma mark Public - Transformations - Off-Center frustum 449 | 450 | + (simd_float4x4)mm_frustum_ocWithLeft: (float)left 451 | withRight: (float)right 452 | withBotoom: (float)bottom 453 | withTop: (float)top 454 | withNear: (float)near 455 | withFar: (float)far { 456 | 457 | float sWidth = 1.0f / (right - left); 458 | float sHeight = 1.0f / (top - bottom); 459 | float sDepth = far / (far - near); 460 | float dNear = 2.0f * near; 461 | 462 | simd_float4 P; 463 | simd_float4 Q; 464 | simd_float4 R; 465 | simd_float4 S; 466 | 467 | P.x = dNear * sWidth; 468 | P.y = 0.0f; 469 | P.z = 0.0f; 470 | P.w = 0.0f; 471 | 472 | Q.x = 0.0f; 473 | Q.y = dNear * sHeight; 474 | Q.z = 0.0f; 475 | Q.w = 0.0f; 476 | 477 | R.x = -sWidth * (right + left); 478 | R.y = -sHeight * (top + bottom); 479 | R.z = sDepth; 480 | R.w = 1.0f; 481 | 482 | S.x = 0.0f; 483 | S.y = 0.0f; 484 | S.z = -sDepth * near; 485 | S.w = 0.0f; 486 | 487 | return simd_matrix(P, Q, R, S); 488 | } 489 | 490 | @end 491 | --------------------------------------------------------------------------------