Comments
Description
Transcript
第7章 座標変換
7 7.1 7.1.1 OpenGL × × × 6 ± OpenGL API ( 78) × × × ( CPU ) 100 GPU × ( 79) 部品 配置 部品 配置 78 79 80 101 7.1.2 ( ) ( 80) 7.1.3 ( 81) 81 82 × y y y 視点座標系 ローカル座標系 z y z x スクリーン x z x z ローカル座標系 82 102 x ワールド座標系 7.1.4 × (View Volume) × 2 (Canonical View Volume) × ( × ビューボリューム (View Volume) 視野錐台 (View Frustum) 標準ビューボリューム (Canonical View Volume) 1 -1 -1 直交投影 (Orthographic Projection) 1 1 -1 透視投影 (Perspective Projection) 83 × × (Orthogonal Projection) (Perspective Projection) (View Frustum, × ) 84 103 ( 19) 83) 7.2 7.2.1 6 x0 = ax + b x (1) a b x0 = axx x + ayx y + bx y 0 = axy x + ayy y + by (2) x0 = axx x + ayx y + azx z + bx y 0 = axy x + ayy y + azy z + by z 0 = axz x + ayz y + azz z + bz (3) (3) 1 0 axx x0 @ y 0 A = @ axy axz z0 0 ayx ayy ayz 10 1 0 1 bx azx x azy A @ y A + @ by A bz azz z ayx ayy ayz 0 azx azy azz 0 (4) 7.2.2 (4) x, y, z 0 1 0 x0 axx B y 0 C B axy B 0 C=B @ z A @ axz 1 0 x’, y’, z’ 1 C C A (5) (3) ( ( 10 bx x B y by C CB bz A @ z 1 1 ) (5) ) ( ) (x*, y*, z*) (x, y, z, w) x⇤ = y⇤ = z⇤ = x w y w z w (6) 104 (x, y, z) w CG 0 x B y B @ z 1 0 x B y B @ z 0 (x, y, z, 1) 0 (x, y, z) (x, y, z, 0) (x, y, z) 1 (7) 1 (8) C C ) (x, y, z) A C C ) (x, y, z) A 0 1 0 x ax B y C B ay C B aB @ z A = @ az w aw 1 ⇣ ⌘ ⇣ ⌘ C C ) ax , ay , az = x , y , z A aw aw aw w w w (9) CG P 0, P 1 P0 P0 = (x0, y0, z0, w0), P1 = (x1, y1, z1, w1) P1 0 1 x1 /w1 B y1 /w1 C P0 C =B @ z1 /w1 A w0 1 P1 w1 w0 w 0 P1 0 1 0 x0 /w0 x1 /w1 x0 /w0 B y0 /w0 C B y1 /w1 y0 /w0 B C B @ z0 /w0 A = @ z1 /w1 z0 /w0 1 0 w1 0 0 0 1 w 0 x1 B w 0 y1 C C w 1 P0 = B @ w 0 z1 A w0 w1 1 C C A (10) w 0w 1 1 0 1 w 1 x0 w 0 x1 w 1 x0 B w 1 y0 C B w 0 y 1 w 1 y0 C B C B C @ w 1 z 0 A = @ w 0 z1 w 1 z0 A w1 w0 0 (11) (11) 0 P0 P1 0 (11) w 0w 1 N X i=1 1 0 P 1 xi /wi P P ◆ ✓P P xi /wi B yi /wi C B Pi xi yi zi yi /wi C B C B C P = ) , , @ zi /wi A = @ zi /wi A wi N N N i=1 1 N N X 0 105 (12) 7.3 7.3.1 (5) 0 v M v’ = Mv 1 x B y C C v=B @ z A w 0 0 1 x B y0 C 0 C v =B @ z0 A w0 0 m0 m4 B m1 m5 M=B @ m2 m6 m3 m7 0 0 1 0 x m0 B y 0 C B m1 B 0 C=B @ z A @ m2 w0 m3 1 (15) 0 (13) (14) m4 m5 m6 m7 v’ x0 y0 z0 w0 = = = = 1 m12 m13 C C m14 A m15 m8 m9 m10 m11 m8 m9 m10 m11 (15) 10 m12 x B y m13 C CB m14 A @ z m15 w 1 C C A (16) (x’, y’, z’, w’) m0 x m1 x m2 x m3 x + + + + m4 y m5 y m6 y m7 y + + + + m8 z m9 z m10 z m11 z v’ 1 0 x0 m0 B y 0 C B m1 B 0 C=B @ z A @ m2 w0 m3 m4 m5 m6 m7 m12 w m13 w m14 w m15 w (17) M x’ = (m0 m4 m8 m12) 0 + + + + m8 m9 m10 m11 (x y z w) v T 10 m12 x B y m13 C CB m14 A @ z m15 w ((17) 1 C C A ) (18) l OpenGL (16) 4 4 CPU OpenGL GPU 106 GPU 0 m0 B m1 M=B @ m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 1 m12 m13 C C m14 A m15 行列の表記 GLfloat(m[](=({ ((m0, m1, m2, !!m4, m5, m6, m3, m7, !!m8, m9, m10, m11, !!m12, m13, m14, m15 }; 配列の要素の格納順序 85 7.3.2 t = (tx, ty, tz) 0 T(tx, ty, tz) 1 tx ty C C tz A 1 (19) 1 x + tx C B y + ty C C=B C A @ z + tz A 1 (20) 1 B 0 T(t) = T(tx , ty , tz ) = B @ 0 0 0 1 0 0 0 0 1 0 (x, y, z) 0 1 B 0 B @ 0 0 0 1 0 0 0 0 1 0 10 tx x B y ty C CB tz A @ z 1 1 T(7, 8, 0) 1 0 86 y y T(7, 8, 0) O x 8 O x 7 86 0 1 B 0 B @ 0 0 0 1 0 0 0 0 1 0 0 1 10 0 tx x x B y C B y ty C CB C=B tz A @ z A @ z 1 0 0 1 C C A (20) l m 107 // (x, y, z) m GLfloat *loadTranslate(GLfloat x, GLfloat y, GLfloat z, GLfloat *m) { m[12] = x; m[13] = y; m[14] = z; m[ 1] = m[ 2] = m[ 3] = m[ 4] = m[ 6] = m[ 7] = m[ 8] = m[ 9] = m[11] = 0.0f; m[ 0] = m[ 5] = m[10] = m[15] = 1.0f; return m; } x, y, z m 16 (20) m0 m5 m10 m15 1 m12 x m13 y m14 (15) z m l 0 // m GLfloat *loadIdentity(GLfloat *m) { return loadTranslate(0.0f, 0.0f, 0.0f, m); } 7.3.3 s = (sx, sy, sz) 0 sx 0 0 B 0 sy 0 S(s) = S(sx , sy , sz ) = B @ 0 0 sz 0 0 0 S(sx, sy, sz) 1 0 0 C C 0 A 1 (21) y S(2, 2, 1) O x 87 s x, = s y, = s z = a w 1/a 108 0 a B 0 B @ 0 0 0 1 B 0 B @ 0 0 0 a 0 0 0 0 a 0 0 1 0 0 0 0 1 0 10 0 x B y 0 C CB 0 A@ z 1 1 10 0 B 0 C CB 0 A@ 1/a 1 0 1 ax C B ay C C=B C A @ az A ) (ax, ay, az) 1 1 0 1 x x B C y C C = B y C ) (ax, ay, az) z A @ z A 1 1/a (22) (23) l // (x, y, z) m GLfloat *loadScale(GLfloat x, GLfloat y, GLfloat z, GLfloat *m) { m[ 0] = x; m[ 5] = y; m[10] = z; m[ 1] = m[ 2] = m[ 3] = m[ 4] = m[ 6] = m[ 7] = m[ 8] = m[ 9] = m[11] = m[12] = m[13] = m[14] = 0.0f; m[15] = 1.0f; return m; } x, y, z x m (23) y z 16 (15) m0 x m5 y m 7.3.4 y 1 O s 1 88 109 x m10 z m15 1 88 Y 0 s s 1 0 0 0 0 1 0 1 0 0 C C 0 A 1 1 B 0 Hxy (s) = B @ 0 0 s 1 0 0 0 0 1 0 1 0 0 C C 0 A 1 1 B s Hyx (s) = B @ 0 0 0 1 0 0 0 0 1 0 1 B 0 Hxy (s) = B @ 0 0 X (24) (24) x, y, z 0 0 1 0 0 C C 0 A 1 0 1 B 0 Hyz (s) = B @ 0 0 0 1 0 0 0 s 1 0 1 B 0 Hzy (s) = B @ 0 0 0 1 s 0 0 0 1 0 0 1 0 0 C C 0 A 1 1 0 0 C C 0 A 1 0 1 B 0 Hzx (s) = B @ s 0 0 1 0 0 0 0 1 0 1 B 0 Hxz (s) = B @ 0 0 0 1 0 0 s 0 1 0 0 1 0 0 C C 0 A 1 1 0 0 C C 0 A 1 (25) 7.3.5 lX θ! 89 X 0 1 B 0 Rx (✓) = B @ 0 0 0 cos ✓ sin ✓ 0 0 sin ✓ cos ✓ 0 1 0 0 C C 0 A 1 (21) 110 lY θ! 90 Y 0 cos ✓ B 0 Ry (✓) = B @ sin ✓ 0 0 sin ✓ 1 0 0 cos ✓ 0 0 1 0 0 C C 0 A 1 (22) lZ θ! 91 Z 0 cos ✓ B sin ✓ Rz (✓) = B @ 0 0 sin ✓ cos ✓ 0 0 0 0 1 0 1 0 0 C C 0 A 1 (23) l (l, m, n) 111 (l,m,n) θ! 92 R(l, 0 m, n,2 ✓) l + (1 l2 ) cos ✓ B lm(1 cos ✓) + n sin ✓ =B @ ln(1 cos ✓) m sin ✓ 0 lm(1 cos ✓) n sin ✓ m2 + (1 m2 ) cos ✓ mn(1 cos ✓) + l sin ✓ 0 ln(1 cos ✓) + m sin ✓ mn(1 cos ✓) l sin ✓ n2 + (1 n2 ) cos ✓ 0 1 0 0 C C 0 A 1 (24) l (24) x, y, z a m // (x, y, z) a m GLfloat *loadRotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z, GLfloat *m) { const GLfloat d(sqrt(x * x + y * y + z * z)); if (d > { const const const const 0.0f) GLfloat GLfloat GLfloat GLfloat l(x / d), m(y / d), n(z / d); l2(l * l), m2(m * m), n2(n * n); lm(l * m), mn(m * n), nl(n * l); c(cos(a)), c1(1.0f – c), s(sin(a)); m[ 0] = (1.0f - l2) * c + l2; m[ 1] = lm * c1 + n * s; m[ 2] = nl * c1 - m * s; m[ 4] = lm * c1 - n * s; m[ 5] = (1.0f - m2) * c + m2; m[ 6] = mn * c1 + l * s; m[ 8] = nl * c1 + m * s; m[ 9] = mn * c1 - l * s; m[10] = (1.0f - n2) * c + n2; m[ 3] = m[ 7] = m[11] = m[12] = m[13] = m[14] = 0.0f; m[15] = 1.0f; } return m; } 112 7.4 i’, j’, k’ p i, j, k p (x, y, z) p p = xi + yj + zk = x0 i0 + y 0 j0 + z 0 k0 i (x’, y’, z’) j 0 1 x @ y A= z k i0 j0 (30) 1 x0 @ y0 A z0 0 k0 (31) (x, y, z) 0 1 x @ y A= z 1 i j k i0 j0 1 x0 @ y0 A z0 0 k0 (32) (i j k), (i’ j’ k’) 0 1 x @ y A= z i j k T i0 j0 M M= i j k T M i0 j0 k0 1 x0 @ y0 A z0 0 (x’, y’, z’) k0 0 i · i0 = @ j · i0 k · i0 ( (33) (x, y, z) i · j0 j · j0 k · j0 1 i · k0 j · k0 A k · k0 (34) ) r, s, t 0 1 1 0 1 tx rx sx r = @ ry A , s = @ s y A , t = @ ty A tz rz sz 0 X Y (35) Z x, y, z 0 1 1 0 1 0 1 0 x = @ 0 A, y = @ 1 A, z = @ 0 A 1 0 0 0 r, s, t (36) x, y, z M 113 8 < x = Mr y = Ms : z = Mt x y z (37) =M r s t (38) y r M s M x M z t 93 0 1 @ 0 0 0 1 0 1 0 0 rx 0 A = M @ ry 1 rz sx sy sz 1 tx ty A tz (39) M 0 rx M = @ ry rz sx sy sz 1 tx ty A tz 1 0 rx = @ ry rz sx sy sz 1T 0 rx tx ty A = @ s x tz tx ry sy ty 1 0 T 1 r rz sz A = @ sT A tz tT (40) 7.5 7.5.1 94 4 y 3 (41) T(4, 3, 0) T(0, 3, 0) T(4, 0, 0) 94 114 x T(0, 3, 0)T(4, 0, 0) 0 1 B 0 =B @ 0 0 0 1 0 0 0 0 1 0 1 B 0 =B @ 0 0 0 1 0 0 0 0 1 0 0 10 0 1 B 0 3 C CB 0 A@ 0 1 0 0 1 0 0 0 0 1 0 1 4 3 C C = T(4, 3, 0) 0 A 1 1 4 0 C C 0 A 1 (41) l OpenGL // m0 m1 m GLfloat *multiply(const GLfloat *m0, const GLfloat *m1, GLfloat *m) { for (int j = 0; j < 4; ++j) { for (int i = 0; i < 4; ++i) { const int ji(j * 4 + i); m[ji] = 0.0f; for (int k = 0; k < 4; ++k) m[ji] += m0[k * 4 + i] * m1[j * 4 + k]; } } return m; } // m0 m1 m GLfloat *multiply(const GLfloat *m0, const GLfloat *m1, GLfloat *m) { for (int ji = 0; ji < 16; ++ji) { const int i(ji & 3), j(ji & ~3); m[ji] = m0[i] * m1[j] + m0[4 + i] * m1[j + 1] + m0[8 + i] * m1[j + 2] + m0[12 + i] * m1[j + 3]; } return m; } 115 7.5.2 0 r00 B r01 M = T(t)R(l, m, n, ✓) = B @ r02 0 r10 r11 r12 0 r20 r21 r22 0 1 tx ty C C tz A 1 (42) ! M 0 r00 R̄ = @ r01 r02 r10 r11 r12 0 1 0 1 R̄ tx r20 r21 A , t = @ ty A ) M = @ tz r22 0T t 1 t 1 A (43) 7.5.3 7.3.5 M = T(p) Rz(θ) T(−p) y y y p p T( p) O T(p) Rz(θ) θ" x x O M = T(p) Rz(θ) T( p) 95 7.5.4 l 116 O x y (移動) O x 96 M = T(p) S(s) T(−p) y y y p p T(-p) x O T(p) S(s) x O x O M = T(p) S (s) T( p) 97 7.5.5 X Y Z l X Y Z (x y z) (r s t) F sr ss S F= ✓ r s t 0 0 0 0 1 st M = FSF ◆ X Y Z T (44) 117 0 sr B 0 S=B @ 0 0 s 0 ss 0 0 0 0 st 0 y 1 0 0 C C 0 A 1 (45) s s s y r r O x FT r O S O r F O x M = F S FT 98 7.5.6 y O y x R(θ) O y O y x S(s) y x S(s) O 99 7.6 7.6.1 X, Y, Z 118 O x y x R(θ) O x y heading pitch roll z x 100 Z (roll, bank) X (pitch) Y (heading, yaw) r, p, h r: roll, bank (Z ) p: pitch (X ) h: heading, yaw (Y ) E(h, p, r) E(h, p, r) = Ry (h)Rx (p)Rz (r) 0 cos h B 0 =B @ sin h 0 0 1 0 0 sin h 0 cos h 0 0 10 0 1 B 0 0 C CB 0 A@ 0 1 0 sin h sin p sin r + cos h cos r B cos p sin r =B @ cos h sin p sin r sin h cos r 0 0 cos p sin p 0 0 sin p cos p 0 10 0 cos r B sin r 0 C CB 0 A@ 0 1 0 sin h sin p cos r cos h sin r cos p cos r cos h sin p cos r + sin h sin r 0 sin r cos r 0 0 sin h cos p sin p cos h cos p 0 0 0 1 0 1 0 0 C C 0 A 1 (46) 1 0 0 C C 0 A 1 7.6.2 p= /2 sin p = 1, cos p = 0 (46) 0 sin h sin r + cos h cos r B 0 E(h, ⇡/2, r) = B @ cos h sin r sin h cos r 0 sin h cos r cos h sin r 0 cos h cos r + sin h sin r 0 119 0 1 0 0 1 0 0 C C 0 A 1 (47) 0 cos(h r) sin(h B 0 0 E(h, ⇡/2, r) = B @ sin(h r) cos(h 0 0 r) r) 0 1 0 0 1 0 0 C C 0 A 1 (48) (h - r) r h p= r (Z ) /2 h 7.6.3 M 0 m0 B m1 M=B @ m2 m3 m1 m4 m5 m6 m7 m5 (49) ! r = atan2(m5 , m1 ) (50) m10 m8 = sin h cos p m10 = cos h cos p p 1 m12 m13 C C = E(h, p, r) m14 A m15 m8 m9 m10 m11 r m1 = cos p sin r m5 = cos p cos r m8 E(h, p, r) h ! (51) h = atan2(m10 , m8 ) m9 m9 = sin p ! p = asin( m9 ) m1 = m5 = 0 cos p = 0 (50) h=0 m0 = cos(h ⌥ r) m4 = sin(h ⌥ r) (52) m0 ! p= (51) r m14 h = 0, r = /2 h h (53) atan2(m0 , m4 ) 7.7 7.7.1 ( x ) y 120 z x y OpenGL ( 101) z y y z x x z 101 z z y y -z O x O z x z 102 7.7.2 l e = (ex, ey, ez) g = (gx, gy, gz) u = (ux, uy, uz) y (0, 1, 0) 上方向の y ベクトル u = (ux , uy , uz ) 視点の位置 e = (ex , ey , ez ) 目標点の位置 g = (gx , gy , gz ) O z 103 121 x l e = (ex, ey, ez) 0 1 0 B 0 1 Tv = B @ 0 0 0 0 0 0 1 0 Tv ex ey C C ez A 1 r, s, t l O = (0, 0, 0) 1 (54) e g–e u (r s t) y y y u t t t x O r x O r s O x g e z z t=e−g z r=u×t 104 (r s t) z t = (tx, ty, tz) x y r t=e e−g r = (rx, ry, rz) u×t t s=t×r u t s = (sx, sy, sz) t×r 0 ex g = @ ey ez 0 u y tz r = u ⇥ t = @ u z tx u x ty 0 t y rz s = t ⇥ r = @ tz rx tx r y 1 0 1 gx tx g y A = @ ty A gz tz 1 1 0 u z ty rx u x tz A = @ r y A rz u y tx (55) 1 1 0 sx tz ry tx rz A = @ s y A sz t y rx l (r s t) (40) Rv 122 (56) 0 B B B B B Rv = B B B B @ rT |r| sT |s| tT |t| 0 0 1 0 0 C B C B C B B 0 C C B = C B C B C B B 0 C A @ rx |r| sx |s| tx |t| 0 0 1 ry |r| sy |s| ty |t| rz |r| sz |s| tz |t| 0 0 C C C 0 C C C C 0 C C A 1 0 s 1 (56) 0 r 0 4 × 4 = 16 t rv 3×3 l Tv Rv (57) Mv = Rv Tv y z (0, 1, 0) O (1, 0, 0) (0, 0, 1) z 105 l // m GLfloat *loadLookat( GLfloat ex, GLfloat ey, GLfloat gx, GLfloat gy, GLfloat ux, GLfloat uy, GLfloat *m) { // GLfloat tv[16]; loadTranslate(-ex, -ey, GLfloat ez, GLfloat gz, GLfloat uz, -ez, tv); // t = e - g const GLfloat tx(ex - gx); const GLfloat ty(ey - gy); const GLfloat tz(ez - gz); // r = u x t const GLfloat rx(uy * tz - uz * ty); const GLfloat ry(uz * tx - ux * tz); const GLfloat rz(ux * ty - uy * tx); 123 // // // x // s = t x r const GLfloat sx(ty * rz - tz * ry); const GLfloat sy(tz * rx - tx * rz); const GLfloat sz(tx * ry - ty * rx); // s const GLfloat s2(sx * sx + sy * sy + sz * sz); if (s2 == 0.0f) return m; // GLfloat rv[16]; // r const GLfloat rv[ 0] = rx / rv[ 4] = ry / rv[ 8] = rz / r(sqrt(rx * rx + ry * ry + rz * rz)); r; r; r; // s const GLfloat rv[ 1] = sx / rv[ 5] = sy / rv[ 9] = sz / s(sqrt(s2)); s; s; s; // t const GLfloat rv[ 2] = tx / rv[ 6] = ty / rv[10] = tz / t(sqrt(tx * tx + ty * ty + tz * tz)); t; t; t; // rv[ 3] = rv[ 7] = rv[11] = rv[12] = rv[13] = rv[14] = 0.0f; rv[15] = 1.0f; // return multiply(rv, tv, m); } 7.8 7.8.1 ( ) ( 106 [-1, 1] (Canonical View Volume) xy 124 × ) y 1 −1 −1 1 O 1 x −1 z 106 7.8.2 l 2 (left, bottom) (right, top) (near, far) xy z ( near (xy ) far (View Volume) 後方面 (yon) 前方面 (hither) top y 視体積 (view volume) left right bottom 視点 −near −far x z 107 (hither) (yon) z −near z −far 125 ) 2 y y y O O O x x z x z z 中心が原点になるよう平行移動 大きさを正規化 108 l ((right + left) / 2, (top + bottom) / 2, −(far + near) / 2) + 2 + 2 109 (21) (58) far near Z 0 Mcentering 1 0 0 B B B B 0 1 0 =B B B B 0 0 1 @ 0 0 0 right + lef t 2 top + bottom 2 f ar + near 2 1 1 C C C C C C C C A 126 (58) l 2 right – left top – bottom –(far – near) 1 2 1 1 2 1 110 2 (21) (59) far near Z 0 Mscaling 2 B right lef t B B 0 B =B B B 0 @ 0 top 0 0 2 bottom 0 2 0 f ar 0 near 0 1 0 C C C 0 C C C 0 C A 1 (59) l Mo Mo Mcentering Mscaling = Mscaling Mcentering 0 2 B right lef t B B B 0 =B B B B 0 @ 0 top 0 0 2 bottom 0 0 2 f ar 0 near 0 right + lef t right lef t top + bottom top bottom f ar + near f ar near 1 1 C C C C C C C C A l m // m GLfloat *loadOrthogonal(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar, GLfloat *m) { const GLfloat dx(right - left); 127 (60) const GLfloat dy(top - bottom); const GLfloat dz(zFar - zNear); if (dx != { m[ 0] = m[ 5] = m[10] = m[12] = m[13] = m[14] = m[15] = m[ 1] = } 0.0f && dy != 0.0f && dz != 0.0f) 2.0f / dx; 2.0f / dy; -2.0f / dz; -(right + left) / -(top + bottom) / -(zFar + zNear) / 1.0f; m[ 2] = m[ 3] = m[ dx; dy; dz; 4] = m[ 6] = m[ 7] = m[ 8] = m[ 9] = m[11] = 0.0f; return m; } 7.8.3 2 (left, bottom) (right, top) (near, far) ( ) (View Frustum) 後方面 (yon) 前方面 (hither) top y left right bottom 視点 z −near 視錐台 (view frustum) −far x 111 (z 2 128 ) y y y O O x z O x z x z 透視変換して平行移動と正規化 Z軸が中心を通るようにせん断変形 112 l z –near left) / 2, (top + bottom) / 2) ((right + z = –1 ((right + left) / 2near, (top + bottom) / 2 near) − − −1 2 2 113 0 Mshear B 1 0 B B =B B 0 1 B @ 0 0 0 0 right + lef t 2 near top + bottom 2 near 1 0 1 0 C C C 0 C C C 0 A 1 (61) l ( –near ,z ) (–near x / z, –near y / z) l 129 (x, y, z) z y 後方面 (yon) 前方面 (hither) y − near z z y −near z O −far 視錐台 (view frustum) 114 Mperspective 0 near B 0 B =B @ 0 0 0 near 0 0 0 0 f ar + near 2 1 0 0 1 C C C f ar near A (62) 0 l Mp Mperspective Mshear Mscaling Mp = Mscaling Mperspective Mshear 0 2 near B right lef t B B B 0 B =B B B 0 B @ 0 0 2 near top bottom 0 0 right + lef t right lef t top + bottom top bottom f ar + near f ar near 1 0 1 C C C C 0 C C 2 f ar near C C C f ar near A 0 l m // m GLfloat *loadFrustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar, GLfloat *m) { const GLfloat dx(right - left); const GLfloat dy(top - bottom); const GLfloat dz(zFar - zNear); if (dx != { m[ 0] = m[ 5] = m[ 8] = m[ 9] = 0.0f && dy != 0.0f && dz != 0.0f) 2.0f * 2.0f * (right (top + zNear / zNear / + left) bottom) dx; dy; / dx; / dy; 130 (63) m[10] m[11] m[14] m[ 1] = = = = -(zFar + zNear) / dz; -1.0f; -2.0f * zFar * zNear / dz; m[ 2] = m[ 3] = m[ 4] = m[ 6] = m[ 7] = m[12] = m[13] = m[15] = 0.0f; } return m; } 7.8.4 (z 115 xz ) A = (xa, za) C B = (xb, zb) z= near D A = (xa , za ) Q = (xq , zq ) B = (xb , zb ) near C P D t O 1−t x z 115 CD t:1–t Q = (xq, zq) P Q x AB (64) 8 xa xb > (1 t) + t > > z zb > > xq = a > > 1 1 < (1 t) + t za zb > > 1 > > > > zq = 1 1 > : (1 t) + t za zb (64) P Q z zq xq (64) A z za z = 1 Q zq 131 B z zb (z ) −far near (far − near) / 2 (59) Mscaling 0 −2 / (far − near) [-1, 1] far f ar near z f ar near ⇥ 2 2 f ar near far - near 1 2 near z O -far -near -far z - O -near -near -far z O far - near -1 2 116 (62) x⇤ = y⇤ = z⇤ = near x z near y z f ar near z (65) f ar + near 2 (62) (66) (x, y, z) (67) 1 0 near x0 0 B y0 C B B 0 C=B B @ z A @ 0 w0 0 0 Mperspective 0 near 0 0 0 0 f ar + near 2 1 10 1 x CB CB y C C C f ar near A @ z A 1 0 0 0 (66) x0 = near x y 0 = near y f ar + near z0 = z + f ar near 2 w0 = z (x*, y*, z*) (67) (65) 132 7.8.5 y (68) f fovy ) (fovy) aspect ratio 2 ( z = −near −bottom = top = near / f −left = right = aspect near / f (63) (69) y 1 O z fovy −1 y fovy −f O −near x z −near −far −far 117 1 ✓ ◆ = cot f= f ovy tan 2 0 f B aspect B 0 B Mp = B B 0 @ 0 0 f 0 0 ✓ f ovy 2 ◆ (68) 0 0 f ar + near f ar near 1 0 0 2 f ar near f ar near 0 1 C C C C C A l m // m GLfloat *loadPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar, GLfloat *m) { const GLfloat dz(zFar - zNear); if (dz != { m[ 5] = m[ 0] = m[10] = 0.0f) 1.0f / tan(fovy * 0.5f); m[5] / aspect; -(zFar + zNear) / dz; 133 (69) m[11] m[14] m[ 1] m[ 6] m[12] = = = = = -1.0f; -2.0f * m[ 2] = m[ 7] = m[13] = zFar * zNear / dz; m[ 3] = m[ 4] = m[ 8] = m[ 9] = m[15] = 0.0f; } return m; } 134