1. 게임 엔진
    1. 사용자 입력 (User Input)
    2. 자원 관리 (Resource Management)
    3. 그래픽 로딩과 렌더링 (Loading and Rendering Graphics)
    4. 스크립트 해석과 실행 (Interpreting and Executing Scripts)
    5. 음향 처리 (Playing Sound Effects)
    6. 인공 지능 (Artificial Intelligence)
  2. 기본 요소
          1. 메쉬(모델)
  3. 모델 좌표계
    1. 모델은 각자의 기본 모델 좌표를 가지고 있다. (지역)
    2. 이는 나중에 월드 좌표계로 변환되어야 한다.
      1. 이 때, 월드 변환 행렬이 적용된다.
  4. 와인딩 순서
    1. 메쉬를 구성하는 다각형의 정점들의 나열 순서.
    2. 은면 제거(Back Face Culling)를 위해서 사용.
    3. DirectX는 기본으로 시계 방향이다.
    4. 즉, 카메라가 볼 때 시계 방향이면 보이는 면, 시계 반대 방향이면 은면.
  5. 변환 파이프라인
    1. 월드(World) 변환
      1. 정점(모델 좌표계)을 월드 좌표계로.
    2. 카메라(View) 변환
      1. 월드 좌표계를 카메라(View) 좌표계로.
    3. 투영(Projection) 변환
      1. 카메라(View) 좌표계를 투영 좌표계로.
      2. 이 변환으로 인해 3D -> 2D 가 된다.
    4. 화면(Screen) 변환
      1. 투영 좌표계를 화면 좌표계로.
    5. 정리
      1. 정점 -> 월드 -> 카메라 -> 투영 -> 화면
    6. 모델을 구성하는 모든 정점(모델 좌표)를 변환 파이프라인을 거치면 화면상의 픽셀 좌표를 얻을 수 있다.
    7. 월드 변환
      1. 회전 변환과 평행이동 변환을 수행한 결과.
      2. 그것이 월드 좌표.
    8. 카메라 변환
      1. 카메라 평면
        1. 3차원 공간이 투영되어 가상 카메라에 나타나는 2차원 평면.
      2. 월드 좌표계의 정점들은 카메라의 좌표를 기준으로 다시 정의되어야 함.
      3. 위치, 방향, Field Of View 등의 속성.
        1. FOV(Field Of View)
          1. 카메라에서 보이는 공간.
          2. 이 공간 안에 속한 객체들만 카메라를 통해 볼 수 있다.
          3. 카메라 중심을 기준으로 좌우, 상하 대칭.
          4. 화각(Viewing Angle)
          5. 카메라에서 볼 수 있는 각도.
        2. 방향
          1. 카메라의 회전양.
          2. 회전한 만큼 돌아가니까 방향이 변하는 게 맞지?
        3. 위치
          1. 카메라의 위치.
          2. 좌표.
      4. 과정
        1. 1) 카메라를 월드 좌표계의 원점으로 평행이동.
        2. 2) 같은 변환을 게임 세계의 모든 객체에 적용.
        3. 3) 카메라 좌표계의 축들이 월드 좌표계의 축들과 일치하게 카메라를 회전.
        4. 4) 같은 변환을 게임 세계의 모든 객체에 적용.
      5. 결과로 카메라 좌표가 만들어짐.
    9. 원근 투영 변환
      1. 원근을 2D로 나타내기 위하여.
      2. 객체와의 거리가 증가하면 객체는 카메라의 FOV 중심으로 움직이는 경향. (멀어지니까)
      3. 카메라와 객체까지의 거리는 z좌표의 델타값.
      4. x값과 y값을 상대적인 z값으로 나누면 2차원으로 변환이 가능.
      5. 결과로 투영 좌표(뷰포트(Viewport) 좌표, 클립 공간)가 만들어진다.
      6. 카메라 평면
        1. 투영 윈도우라고도 한다.
        2. FOV 공간에 있는 정점들이 투영되는 공간.
        3. 투영 평면
          1. -1 < x < 1 and -1 < y < 1 인, 카메라의 화각 사이의 평면
        4. FOV 화각이 90도일 때
          1. FOV 정점들을 투영 변환 하면 x좌표와 y좌표는 -1과 1사이의 값을 갖게 된다. (z값으로 나누니까)
          2. FOV 공간에 포함되지 않는 정점들은 x좌표와 y좌표가 -1보다 작거나 1보다 큰 값을 가진다
        5. FOV 화각이 90도가 아닐 때
          1. Xprojected = x / (z / d) Yprojected = y / (z / d)
          2. d는 카메라에서 투영 평면까지의 거리를 의미.
          3. 투영 평면을 카메라에서 멀게 하면 화각이 작아진다. (가깝게 하면 커진다.)
          4. 투영 평면의 크기는 변하지 않기 때문. (언제나 -1보다 크고 1보다 작다)
          5. 즉, d의 크기를 조절하면 FOV 화각의 효과를 만들어 낼 수 있다.
        6. DirectX11 에서는 투영 평면까지의 거리가 항상 1.0이다. (화각이 항상 90도이다.)
        7. 즉, 투영 변환이 일어나기 전에, 계산된 투영 평면의 좌표에 d 값을 임의로 계산시켜서 화각의 효과를 낸다.
        8. 절두체
          1. 카메라가 [ 볼 수 있는 ] 가장 가까운 평면을 근평면, 가장 먼 평면을 원평면이라 한다.
          2. FOV에 따라 정사각뿔 형태의 공간이 생기는데, 이는 근평면과 원평면 사이의 공간만으로 잘리게 된다. ( 볼 수 있는 공간이 근평면 ~ 원평면이니까. )
          3. 이 사이 공간을 절두체라고 한다.
    10. 화면 좌표 변환
      1. 2차원으로 변환된 투영 좌표를 화면 좌표로 바꾸는 변환.
      2. 뷰포트(Viewport)
        1. 렌더링할 대상의 화면 영역. (Render Target?)
        2. 요소
          1. (화면 좌표계에서의) 원점 위치 (Left, Top)
          2. 가로 크기
          3. 세로 크기
      3. 화면 좌표 계산
        1. 투영 좌표계의 한 점
        2. ScreenX = projVertex.x * (뷰포트 가로 / 2) + 뷰포트 원점.x + (뷰포트 가로 / 2) ScreenY = (-1) * projVertex.y * (뷰포트 세로 / 2) + 뷰포트 원점.y + (뷰포트 세로 / 2)
        3. 화면 좌표계는 Y축이 반대 방향이므로 Y좌표에 -1을 곱해 줌.
      4. 이렇게 최종적으로 픽셀로 나타나는 화면 좌표가 만들어진다.
  6. 기본 수학
    1. 벡터의 합
    2. 벡터의 차
      1. 한 점 A에서 점 B로 객체를 이동할 때 이동 방향은 (B벡터 - A벡터)의 단위 벡터이다.
      2. 직접 그려보면 알게 된다.
    3. 스칼라 곱 (실수배)
    4. 벡터의 크기
    5. 벡터의 정규화 (크기를 1로)
      1. 단위 벡터(노멀 벡터) : 방향만을 나타내고자 할 때 사용.
      2. [ 방향을 나타내는 단위 벡터 ]에 이동거리를 곱하여 얻어진 벡터를 [ 물체 위치 벡터 ]에 더하면 최종 위치가 나온다.
      3. 다각형의 방향을 나타낼 때도 사용.
      4. 즉, 메시를 구성하는 면이 어느 방향으로 향하는지를 단위 벡터로 표현.
      5. normal
    6. 벡터의 내적
      1. 정의
        1. 두개의 벡터가 이루는 각도를 구할 수 있다.
        2. 결과값은 실수이다.
        3. 결과값이 0이라면 수직.
        4. 결과값이 0보다 크면 예각.
        5. 결과값이 0보다 작으면 둔각.
      2. 카메라를 보는가?
        1. 메시의 평면 법선 벡터를 알면 그 면이 카메라를 향하는지를 알 수 있다. (은면인가 아닌가)
        2. [ 평면의 법선 벡터 ] 와 [ 카메라에서 평면의 모서리 점 ] 까지의 벡터를 내적.
        3. 예각이면 보는 방향이 비슷한 쪽이다. 즉, 카메라를 보고 있지 않다.
        4. 둔각이면 보는 방향이 다르다. 즉, 카메라를 보고 있다.
      3. 직교 투영 벡터
        1. 한 벡터를 한 단위 벡터에 직교 투영하면
        2. p = ( |v|cosθ )n = ( |v||n|cosθ )n = ( v · n )n
        3. 단위 벡터의 크기( |n| )은 1이니까 맘대로 곱함.
        4. 단위 벡터에 수직인 벡터에 직교 투영을 하면
        5. q = v - ( v · n )n
        6. p와 q는 서로 직교하며, p + q = v가 된다.
      4. dot
    7. 벡터의 외적
      1. 두 개의 벡터에 수직인 벡터를 구할 수 있다.
      2. 왼손 법칙이 적용된다.
        1. 엄지가 A벡터
        2. 검지가 B벡터
        3. 중지가 ( A X B )가 된다.
        4. 엄지 검지 바뀌면 ( B X A )가 되지? 다르지?
      3. ( A X B ) = (-1) * ( B X A)
      4. 법선 벡터
        1. 면의 방향.
        2. 면이 바깥쪽으로 향하는 방향.
        3. 바깥쪽이 무슨 소리여?
        4. 보통 정규화 하여 단위 벡터로 사용한다.
      5. 회전축을 구하기 위해 사용될 수 있다.
      6. 회전 된 위치의 벡터랑 회전하기 전 위치의 벡터를 외적하면 회전축이 나옴.
      7. 그리고 내적을 하면 회전양이 나오겠지?
      8. cross
    8. 평면의 방정식
      1. [ 평면 위의 한 점 ] 과 [ 평면의 법선 벡터 ]로 이루어진다.
      2. 평면 벡터
        1. 법선 벡터 ( a, b, c )에 원점에서 평면까지의 거리 d가 추가 되어 ( a, b, c, d )의 벡터.
      3. 차후 필요하면 공부해서 추가.
    9. 행렬
      1. 차후 필요하면 공부해서 추가.
  7. 행렬을 사용한 변환 파이프라인
    1. 모델 좌표계의 한 점
      1. 모든 변환 행렬은 이 점에다가 곱하는 것이다.
    2. 월드 변환 행렬
      1. 월드 좌표계에서 객체의 위치와 방향을 표현.
      2. 월드 변환 행렬 W
        1. Right x, Right y, Right z, 0 Up x, Up y, Up z, 0 Look x, Look y, Look z, 0 Position x, Position y, Position z, 1
      3. 4번째 행 : 객체의 위치
      4. 1번째 행 : Right 벡터 ( x축 )
      5. 2번째 행 : Up 벡터 ( y축 )
      6. 3번째 행 : Look 벡터 ( z축 )
      7. [ 축이 어떤 방향인가? ] 만을 나타낸다.
      8. ( 1,1 ), ( 2,2 ), ( 3,3 )은 객체의 크기 변환을 나타낼 수 있다. (Right의 x, Up의 y, Look의 z)
      9. 이제 월드 좌표계에서 이동을 하고 싶다면, 행렬의 한 행만을 뽑아서 각 요소에 거리를 곱하면 이동한 좌표가 나온다.
      10. 충돌 검사
        1. 월드 상의 모든 객체들의 좌표가 있기 때문에, 충돌 검사를 여기서 수행한다.
      11. 만드는 법
        1. 우리가 직접 Right, Up, Look 벡터를 만들고 초기화하여 쭉~ 사용한다.
    3. 카메라 변환 행렬
      1. 카메라도 게임의 한 요소이므로, 월드 좌표에서의 위치와 방향을 가진다.
      2. 말하자면, 카메라의 정보는 월드 좌표상의 정보이다.
      3. 이 변환은 카메라를 기준으로 월드를 나타내야하기 때문에 필요.
      4. 카메라 변환 행렬, 또는 뷰 행렬이라고 부른다.
      5. 개념
        1. 월드 좌표를 카메라에 맞춰라?
        2. 카메라가 월드의 한 지점에 위치하려면 카메라의 정보에 월드 변환 행렬을 적용시켜야 한다.
        3. 반대로 말하자면, 카메라의 월드 좌표에 월드 변환 행렬을 적용한 걸 반대로 따라가면 원래 카메라의 정보가 나온다.
        4. 즉, 카메라의 위치, 회전 정보에 월드 변환 행렬의 역행렬을 곱하게 되면, 카메라를 기준으로 좌표가 맞춰지게 된다!!!
      6. 카메라 변환 행렬 V
        1. m_vRight.x, m_vUp.x, m_vLook.x, 0 m_vRight.y, m_vUp.y, m_vLook.y, 0 m_vRight.z, m_vUp.z, m_vLook.z, 0 -(m_vPosition · m_vRight), -(m_vPosition · m_vUp), -(m_vPosition · m_vLook), 1
      7. 월드 변환 행렬 W의 역행렬
      8. 4번째 행은 내적의 결과인 실수값. (회전양)
      9. m_v 라는 접두어는 카메라의 벡터 정보를 뜻한다. (카메라도 월드의 한 좌표니까)
      10. 만드는 법
        1. 월드 변환 행렬의 역행렬
          1. 역행렬 함수. D3DXMatrixInverse
        2. D3DXMatrixLookAtLH 함수 사용
          1. Eye 벡터, At 벡터, Up 벡터가 인자로 들어간다.
          2. Eye 벡터 = 카메라의 위치.
          3. At 벡터 = 카메라가 바라보는 지점.
          4. Up 벡터 = 월드 좌표의 Up 벡터. 보통 ( 0, 1, 0 ) 사용
          5. m_vLook = normal( pAt -pEye ) m_vRight = normal( cross( pUp, m_vLook ) ) m_vUp = cross( m_vLook, m_vRight )
          6. 이런 방법으로 카메라 변환 행렬을 생성.
    4. 투영 변환 행렬
      1. 투영 공식
        1. 2DProjectedX = ViewSpaceX / ViewSpaceZ 2DProjectedY = ViewSpaceY / ViewSpaceZ
        2. 이는 FOV가 90도일 때, ( x, y, z ) 를 ( x/z, y/z, 1 ) 즉, ( x/z, y/z ) 로 만드는 것이다.
      2. 이 변환의 문제점
        1. FOV가 90도인 것은 일반적이지 않다. ( 게임 대부분은 60도나 45도의 화각을 가진다고 함. )
        2. 모니터는 정사각형이 아니라 직사각형이다.
        3. 즉, 투영 좌표계에서 화면 좌표계로 될 때, 늘려져서 보인다는 말이다.
        4. 가로와 세로의 비율이 1:1이 아니기 때문에 왜곡이 발생.
        5. 방법
          1. x와 y를 z로 나누기 전에 미리 왜곡시키자.
          2. 가로가 세로보다 크다면 x를 더 작게.
          3. 이것은 크기 변환에 해당한다.
          4. 이러한 왜곡에 사용되는 변환 행렬을 원근 투영 변환 행렬이라고 한다.
      3. 원근 투영 변환 행렬
        1. R = 종횡비 ( 4:3 = 1.333... , 16:9 = 1.777... )
        2. 카메라 좌표계에 크기 변환 행렬을 곱하여 미리 왜곡시킨다.
        3. x 값의 왜곡이 필요하다면...
        4. 1/R, 0, 0, 0 0, 1, 0, 0 0, 0, 1, 1 0, 0, 0, 0
        5. 이 값을 곱하면 카메라 x가 작아진다.
        6. 이렇게 해서 나온 좌표계를 동차 클립 좌표계라고 한다.
        7. 동차 클립 좌표계를 z로 나눠주면 투영 좌표계가 나온다
        8. ( 4, 4 )에 있던 1이 ( 4, 3 )으로 갔다. 이는 ( x, y, z, 1 )을 ( x, y, z, z )라는 결과로 바꿔준다.
        9. 맨 마지막 z를 w값이라고 하며, 깊이 관련의 계산에 사용 가능하다. (깊이 값을 따로 남겨두는 것)
      4. 투영 변환 행렬
        1. 임의의 FOV 값을 가지는 카메라의 투영 변환 행렬
          1. 1/tan(θ), 0, 0, 0 0, 1/tan(θ), 0, 0 0, 0, 1, 1 0, 0, 0, 0
        2. 종횡비와 FOV 모두 가지는 최종 투영 변환 행렬
          1. { 1/tan(θ) } / R, 0, 0, 0 0, 1/tan(θ), 0, 0 0, 0, 1, 1 0, 0, 0, 0
        3. 이 w값을 사용하여 동차 클립 좌표계의 값도 구할 수 있다.
      5. 만드는 법
        1. D3DXMatrixPerspectiveFovLH 함수 사용
          1. fovy
          2. y축 방향의 FOV각도 (라디안)
          3. r
          4. 종횡비
          5. zn
          6. 근평면의 z값
          7. z-near
          8. zf
          9. 원평면의 z값
          10. z-far
    5. 화면 좌표 변환 행렬
      1. DirectX 11의 뷰포트 구조체
        1. D3D11_VIEWPORT
          1. 왼쪽 위 x
          2. 왼쪽 위 y
          3. 가로
          4. 세로
          5. 최소 깊이
          6. 최대 깊이
      2. 투영 좌표계의 ( x, y )를 화면 좌표계로 변환
        1. xScreen = x * ( 뷰포트 가로 / 2 ) + 왼쪽 위 x + ( 뷰포트 가로 / 2 ) yScreen = y * ( 뷰포트 세로 / 2 ) + 왼쪽 위 y + ( 뷰포트 세로 / 2 )
      3. 화면 좌표 변환 행렬
        1. ( Width / 2 ), 0, 0, 0 0, -( Height / 2), 0, 0 0, 0, ( MaxDepth - MinDepth ), 0 TopLeftX * ( Width / 2 ), TopLeftY * ( Height / 2 ), MinDepth, 1
  8. 변환 파이프라인을 넘나들자
    1. 마우스 픽킹
      1. 마우스를 찍어서 좌표를 알려주거나, 물체와의 충돌을 감지.
      2. 화면 좌표계부터 쭉~ 역변환을 하여 카메라 좌표, 또는 월드 좌표까지 간다.
      3. 그리고 판별.
  9. DirectX11 라이브러리
    1. 벡터
      1. D3DXVECTOR3
        1. (2, 3, 4)가 존재.
        2. x, y, z
    2. 평면
      1. D3DXPLANE
        1. a, b, c, d
    3. 행렬
      1. D3DXMATRIX
        1. 4*4 행렬
    4. 연산
      1. 벡터
        1. D3DXVec3Length
          1. 크기
        2. D3DXVec3Dot
          1. 내적
        3. D3DXVec3Normalize
          1. 정규화
        4. D3DXVec3Scale
          1. 스칼라곱 (실수배)
        5. D3DXAdd
          1. 덧셈
        6. D3DXSubtract
          1. 뺄셈
        7. D3DXVec3Cross
          1. 외적
      2. 행렬
        1. D3DXMatrixIdentity
          1. 단위 행렬
        2. D3DXMatrixInverse
          1. 역행렬
        3. D3DXMatrixMultiply
          1. 행렬곱
        4. D3DXMatrixScaling
          1. 크기 변환
        5. D3DXMatrixTranslation
          1. 평행 이동 변환
        6. D3DXMatrixRotationX
          1. (X, Y, Z)가 존재.
          2. X축을 중심으로 Angle만큼 회전.
          3. 회전 변환
        7. D3DXMatrixRotationAxis
          1. 벡터 하나를 축으로 회전 변환
        8. D3DXMatrixRotationYawPitchRoll
          1. x축을 Pitch, y축을 Yaw, z축을 Roll 만큼 회전 변환.
          2. 회전의 순서는 z축, x축, y축이다.
      3. 평면
        1. D3DXPlaneFromPointNormal
          1. 한 점과 법선 벡터로부터 평면을 반환
        2. D3DXPlaneFromPoints
          1. 세 점으로 평면을 반환
        3. D3DXPlaneDotNormal
          1. 평면 벡터와 한 벡터의 내적값 반환
        4. D3DXPlaneDot
          1. 한 점을 나타내는 벡터를 사용하여 평면 벡터와 내적.
          2. 점과 평면의 위치 관계
          3. 0이면 평면 위에, 음수면 평면 뒤에, 양수면 평면 앞에 존재한다.
        5. D3DXPlaneNormalize
          1. 법선 벡터의 크기로 a, b, c, d를 정규화.
          2. 정규화된 d 값이 원점에서 평면까지의 거리를 나타낸다.
      4. 벡터 변환
        1. D3DXVec3TransformCoord
          1. 벡터를 ( x, y, z, 1 )의 동차 좌표로 바꾸어 행렬과 곱하고, 3차원 벡터로 반환. ( w 나누기를 수행 )
        2. D3DXVec3TransformNormal
          1. 법선 벡터를 ( x, y, z, 0 )의 동차 좌표로 바꾸어 행렬과 곱하고, 정규화하여 3차원 벡터로 반환.
        3. D3DXVec3Transform
          1. 벡터를 ( x, y, z, 1 )의 동차 좌표로 바꾸어 행렬과 곱하고, 4차원 벡터로 반환. ( w 나누기 수행 안 함 )