MathJax

2013년 10월 27일 일요일

광선과 삼각형 교차 ( Intersecting ray and triangle )

먼저 무게 중심 좌표(barycentric coordinate)부터 생각해 보자.

무게 중심 좌표는 참조되는 점들의 무게를 조합하는 형식으로 공간을 표현한다.

예를 들어 선분 AB를 생각해 보자

임의의 점 P는  선분  AB 사이에 있는 하나의 점이라고 가정 한다.

그럼 점 P는 아래과 같은 식으로 표현할 수 있다.

P=A + t(B-A)

풀어서 정리하면 다음과 같이 되고

P = A + tB - tA
P = (1-t)A + tB

여기서 표현을 바꾸면





위 식에서 u, v를 무게 중심 좌표(barycentric coordinate)라고 말한다.

참고로 barycentric 이라는 단어에서 bary는 그리스 단어에서 '무게'라는 뜻을 가지고 있다.

삼각형의 경우로 다시 생각하면 삼각형 안의 임의의 점 P 와

동일 선상에 있지 않는 점 A, B, C에 대해서 아래와 같이 나타낼 수 있다.





세번째에 있는 식을 보면 v, w 2개의 변수만 있어도 u를 구할 수가 있다.


그러므로 위 식을 다음과 같이 정리하여 아래에서 계속 사용 한다.


무게 중심 좌표에 따라서 각 u, v, w의 값을 표시 하면 아래과 같은 형태를 생각 할 수 있다.


각 점에서의 u, v, w 값은 아래과 같이 된다.
(u, v, w)
A=(1, 0, 0)
B=(0, 1, 0)
C=(0, 0, 1)

그리고 u, v, w의 값을 확인 하여 임의의 점이 삼각형 안에 있는지 확인할 수 있다.

그럼 이제 삼각형과 교차하는 광선을 생각해 보자.

광선은 아래와 같이 나타낼 수 있다.


o는 광선의 시작점을 나타내고 t는 광선의 길이는 나타내는 스칼라 변수 이다.

그리고  d는 광선의 방향을 나타내는 단위 벡터가 된다.

광선과 삼각형의 교차점은 위에서 설명한 2개의 식을 생각해 본다.

삼각형 안의 임의의 점


광선의 임의의 점

결국 교차점은 삼각형 안의 임의의 점과 광선의 임의의 점이 같을 경우가 된다.


이제 여기서 필요한 t, v, w의 값을 위 식을 계산하여 구해 보자.
 

위 식을 행렬식으로 다시 표현 하면 아래와 같이 된다.



앞쪽에 있는 행렬의 역행렬을 양변에 곱하면 t, v, w의 값을 구할 수 있다.

여기서 역행렬을 구할때는 cramer's rule을 사용 한다.

예를 들어 아래와 같이 3개의 선형 방정식이 있고 원하는 x, y, z 값을 구해야 한다.

 
 


이때 caramer's rule을 적용하면 

,,



식을 간단히 만들기 위해 먼저 d의 determinant식 풀어 본다.

determinant에서는 매트릭스를 전치하여 풀어도 같은 값이 된다. 

위의 d를 아래와 같이 전치하고


d의 determinant 표현을 식으로 풀게 되면 다음과 같다.


위의 식을 정리하면 내적으로 표현할 수 있다.

여기서 각각의 변수를 아래와 같이 벡터로 생각하고

 
 

위 식을 벡터로 표현하면



이제 복잡하게 정리 되었던 x, y, z를 위의 정리를 통해 정리하고




마지막으로 행렬로 다시 표현하면 아래과 같이 표현할 수 있다.



이제 원래대로 돌아가서 t, v, w를 구할 식을 다시 살펴 보자.


식을 간단히 하기 위해 각각의 요소를 아래와 같이 다시 정의 한다.




위 값을 caramer's rule를 사용하여 정리한 식에 대입을 해보자.




여기서 d값이 0이 되면 역행렬은 존재하지 않게 된다. 

그리고 계산량을 줄이기 위해 d값을 먼저 계산하여 변수에 저장하고 다시 사용하도록 한다. 

먼저 - 부호를 제거 하자.

외적의 정의에 따라서 
스칼라 값 r, s이 주어진 경우와 -부호를 적용될 경우 다음과 같다.





또한, Scalar Triple Product 정의에 따라 다음과 같이 된다. 




위의 정의들을 이용하여 식을 정리하면 




계산량 감소 및 재사용을 하기 위해 다음과 같이 정의 한다.




필요에 따라서 t, v, w값을 전부 계산하거나 혹은 부분계산하여 사용하도록 소스를 구현하면 된다.

마지막으로 앞에서 설명하였듯이 t값은 광선을 나타내는 식에 대입하여 사용하고

v, w 값은 삼각형 안의 임의의 점을 나타내는 식에 대입하여 사용하면 된다. 


참고자료
Real-Time Rendering 2판
Real-Time Collision Detection

2013년 9월 26일 목요일

Filling

filling 기능을 이용하여 line을 특정 길이만큼  제한하여 정렬할 수 있다.
 
먼저 원하는 line의 폭을 정하자.
M-x set-fill-column
기본값은 70으로 되어 있으며 원하는 값을 입력하고 enter를 누르면 된다.















입력후에는 변경된 메시지가 표시되게 된다.














또는 현재 fill-column의 값을 다음 명령을 통해 알아볼 수 도 있다.
C-h v fill-column














이제 변경할 문장을 선택하자.














그리고 다음 명령을 사용해서 정렬!
M-x fill-paragraph or M-q















매번 설정하여 사용하기 귀찮으므로 다음 설정을 .emacs에 등록하여 사용한다.
(setq-default fill-column 78)

2013년 9월 16일 월요일

열(column) 편집 하기


1. cua mode 사용하기
cua는 Common User Access system을 뜻 한다.
이 모드를 사용하면 다른 애플리케이션에서 주로 사용되는 키를 사용할 수 있게 만들어 준다.
자르기: C-x
복사하기: C-c
붙이기: C-v
되돌리기: C-z

열 편집을 하기 위해서 먼저 영역을 선택해야 한다.
1. 영역 시작 위치에서 C-return(enter 키) 명령을 실행 한다.
2. 원하는 만큼 이동하면 해당 영역이 사각형 모양으로 선택되어 진다.

3. M-s 명령을 사용하여 원하는 문자를 입력해 준다.

4. 입력을 하고 enter키를 누르면 다음과 같이 수정되어 진다.




2. mark 와 rectangle 사용하기
위의 2가지를 혼합하면 열 편집이 가능하다.

1. 열 편집 하기 위한 위치로 먼저 이동






2. C- 혹은 C-@를 사용하여 현재 위치에서 mark set을 한다.











3. 편집 사각영역이 될 다른 코너까지 커서를 이동 시킨다.
(long을 편집할 예정이므로 마지막 long 다음 까지 이동 시킨다.)
(현재 선택 영역이 열이 아닌 전체로 보이지만 무시 하여도 된다.)
(처음 mark set을 한 위치와 다음에 위치한 커서 사이에 만들어진 사각영역에 대해서
rectangle 관련 명령어를 사용하기 때문이다.)







(빨간색 상자: rectangle 명령어 사용시 적용되는 부분)







4. C-x r t 수정할 문자
위의 명령으로 rectangle에서 replace 명령을 실행 한다.











5. enter키를 눌러 replace 명령 실행 후에는 다음과 같이 수정되어 나타난다.





3. search 와 rectangle 사용하기
위의 2가지를 혼합하면 열 편집이 가능하다.

1. 열 편집 하기 위한 위치로 먼저 이동






2. 영역을 지정하기 위해 정당한 검색어를 입력

3. enter키를 누르면 mark 되었다고 표시 된다.

4. 원하는 열 영역을 만들기 위해 커서를 이동하여 준다.
    (int를  다른 것으로 바꿀 예정 이므로 마지막 int 다음 열에 커서를 위치한다.)

5. C-x r t 수정할 문자 
위의 명령으로 rectangle에서 replace 명령을 실행 한다.

6. replace 명령 완료 후에 다음과 같이 수정되어 나타난다.

2013년 9월 11일 수요일

emacs에 컬러 테마 적용하기


먼저 color-theme를 아래 사이트에 방문하여 다운 로드 받는다.


받은 압축파일을 풀어서 emacs 설정 폴더에 넣어 준다.

Windows 7경우: c:\Users\자신의 계정명\AppData\Roaming\.emacs.d\vendor\color-theme
Mac의 경우: /Users/자신의 계정명/.emacs.d/vendor/color-theme

위 경로가 없으면 만들어 준다.

이제 emacs 설정 파일을 수정하여 해당 라이브러리를 불어오도록 하자.

emacs설정파일 경로:
Windows 7경우: c:\Users\자신의 계정명\AppData\Roaming\.emacs
Mac의 경우: /Users/자신의 계정명/.emacs

이 파일 또한 없으면 만들어 주자.

먼저 color-theme 라이브러리를 불러오기
(add-to-list 'load-path "~/.emacs.d/vendor/color-theme")

~는 홈디렉토리를 뜻한다.

다음은 color-theme 켜기
(require 'color-theme)

다음은 color-theme 초기화 하기
(color-theme-initialize)

그리고 기본 테마 설정 하기
(color-theme-robin-hood)


아래의 총 4줄을 emacs 설정 파일에 추가 및 저장한다.
(add-to-list 'load-path "~/.emacs.d/vendor/color-theme")
(require 'color-theme)
(color-theme-initialize)
(color-theme-robin-hood)

이제 emacs를 다시 시작 하면 기본으로 설정해 놓은 테마가 적용되어 나온다.

만약 제대로 되지 않는 다면 초기화 명령을 다음 명령으로 대체하여 적용한다.
(setq color-theme-is-global t)

다른 테마를 적용하고자 한다면 m-x color-theme-select 명령을 내려 원하는 테마를 선택할 수 있다.

테마 이름 사이에 공백이 있을 경우에는 - 문자를 넣어 설정한다. 





2013년 9월 8일 일요일

Finder를 화면 좌, 우에 배치 하기


윈도우에서는 윈도우키 + 좌우 방향키로 윈도우를 좌우로 배치 할 수 있다.

맥에서는 단축키가 따로 보이지 않는다.

그럼 AppleScript로 만들자.

먼저 파인더에 대해서 AppleScript를 이용해서 만들어 보자.

먼저 현재 디스플레이의 영역 사이즈를 다음 스크립트로 얻어 온다.

global displaySize -- 변수 선언
tell application "Finder"
set displaySize to get the bounds of window of desktop
end tell

그럼 displaySize에 현재 디스플레이 영역이 저장된다.

현재 해상도가 1280 x 800일 경우 다음과 같이 저장이된다.

{0, 0, 1280, 800}

형식: 
{left, top, right, bottom}

(left, top)---------------
|                               |
|                               |
|                               |
|__________(right, bottom)


이제 파인더의 위치를 다음을 통해 이동 시켜보자.

tell application "Finder"
tell front window -- 1. 가장 앞에 있는 파인더에게 명령
set bounds to {0, 0, (item 3 of displaySize) / 2, (item 4 of displaySize)}
(* 2. 왼쪽으로 배치
{ 현재 디스플레이의 가장 좌측
  현재 디스플레이의 가장 위쪽 높이
  현재 디스플레이의 넓이의 중간 위치
  현재 디스플레이의 높이 }
*)
--set bounds to {(item 3 of displaySize) / 2, 0, (item 3 of displaySize), (item 4 of displaySize)}
(* 3. 오른쪽으로 배치
{ 현재 디스플레이의 넓이의 중간 위치,
현재 디스플레이의 가장 위쪽 높이
현재 디스플레이의 넓이
현재 디스플레이의 높이 }
*)
end tell
end tell

위의 스크립트는 가장 위쪽의 파인더를 화면 왼쪽으로 배치하는 내용이다.

오른쪽으로 배치할 경우에는 2번 항목을 주석 처리 하고 3번 항목만을 적용하면 된다.

AppleScript에서 주석을 다음의 2가지가 있다.
1. -- 주석 내용
2. (*  주석 내용 *)

2개의 스크립트 소스를 모두 AppleScript에 차례대로 붙여 넣고 실행하면 적용 된다.

그런데 매번 편집기를 열어서 실행하자니 번거롭다. 

편하게 Dock에 등록해 놓고 사용하자.

[AppleScript 상태 막대] 파일-> 보내기 
메뉴가 나타나면 다음과 같이 설정 하고 저장 한다.

파일 포맷: 응용 프로그램
옵션: 실행 전용


그럼 실행 파일이 만들어 진다.

이제 실행 파일을  Dock에 등록하고 필요할떄 실행하여 사용하면 된다.

2013년 7월 30일 화요일

Picking

마우스 혹은 기타 입력 장치로 모니터 화면의 좌표를 지정하면 3D 세계에 있는 오브젝트를 선택할때 사용된다.


화면의 좌표는 2D, 세계는 3D인 경우 오브젝트의 선택 방법을 만들어야 한다.

먼저 화면에서 지정한 좌표를 이용하여 3D 세계로 광선을 발사하여 교차되는 오브젝트를 찾으면 된다.

간단한 그래픽 파이프라인을 생각해 보자

월드 변환-> 뷰 변환-> 투영 변환-> 화면 변환

이 과정을 거꾸로 거쳐서 화면에서의 점을 월드 좌표계로 만든다.

첫번째로 화면변환(ScreenTransform)-> 투영변환(ProjectionTransform)을 고려해 보자

뷰 공간에서 투영 변환이 끝난 공간은 NDC(Normalized Device Coordinates)가 된다.

잠시 원래 과정인 NDC-> Screen Coordinates을 생각해 보면 아래와 같은 공식이 나오게 된다.





참고: 화면변환


: 화면 좌표계의 좌측 상단 x 좌표
: 화면 좌표계의 좌측 상단 y 좌표

: 화면 좌표계의 화면 Width
: 화면 좌표계의 화면 Height

: 화면 좌표계의  x 좌표
: 화면 좌표계의  y 좌표


위 식에서 필요한것은 NDC의 값이므로 위 식을 ndc에 대해 정리 한다.






두번째로 필요한 것은 NDC에서 ->View frame으로 변환이 필요하다.

먼저 z값을 생각해 보자.

현재 화면 변환-> 투영 변환을 거쳐서 좌표값은 NDC에 있으므로 

z값은 투영 평면(projection plane)위에 놓여진 상태이며

따라서 z값은 투영 평면 거리 값 d를 그대로 사용하면 된다.

,


그리고 좌표 값이 투영 평면에 위에 있으므로  x, y 값은 투영변환이 끝난 상태 이다.

NDC 에서 x의 범위는 [-a, a] 이고 y의 범위는 [-1, 1]이 된다.

여기서 a는 aspect값을 나타낸다.

aspect=(screen_width / screen_height)

이제 투영변환 되기 전의 x, y 값을 구해야 한다.

원래 변환 과정를 생각해 보면 

View Frame에서 NDC로 변환 될때 위에서 나타낸 x, y의 범위로  Scale이 되었다.

그러므로 변환되기전 좌표값을 찾아낼려면 반대로  x, y의 값을 Scale 하면 된다.

먼저 y의 범위는 [-1, 1]이므로  Scale이 필요 없이 그대로 사용하면 되고

x의 범위는 [-a, a]이므로 a의 값 만큼 Scale이 필요하다.

ndc에서의 x, y값을 위의 설명에 따라  Scale을 해주면 다음과 같이 된다.

 

그리고 z값은



(DirectX 의 경우 Z 방향은 화면 안쪽 방향이 되어  +d값이 사용 된다.)

세번째로 월드 좌표에 있는 모델과 충돌 시킬 광선(Ray)을 만든다.

현재까지 구해진 좌표값을 이용하여 광선을 만든다.

먼저, 좌표값은 View Frame에 있으므로 World 좌표계로 변환이 필요하다.

방법은 뷰 변환에 사용하는 뷰 변환 행렬의 역행렬을 곱하면 World 좌표값을 구할 수 있다.





그리고 카메라의 위치값(Eye Position)을 사용한다.

따라서 충돌에 사용할 광선은 다음과 같이 된다.



마지막으로 World 좌표계에서 위의 광선과 충돌 여부를 판단한다.

카메라 위치에서 광선을 만들어 충돌을 판단하게 되므로 여러 개의 모델이 광선과 충돌할 수 있다.

충돌하는 모델 중 광선의 t 값이 가장 작을 경우가 처음으로 광선과 모델이 충돌되는 경우가 되며

이것이 picking 되는 모델이 된다.

상황에 따라 광선을 각 모델 좌표계로 변환하여 해당 모델 좌표계에서 계산할 수도 있다.


참고자료
Essential Mathematics for Games & Interactive Applications Second Edition

2013년 5월 27일 월요일

자주 사용하는 emacs 명령어 정리(1)


문서 편집에 필요한 기본 명령어들을 정리

notepad++ 이나 free commander를 사용하지 않을 만큼 추가 정리 필요

 c: ctrl key
m: alt key or esc key

------------------------------------------------------------------------------
move
c-f: right
c-b: left
c-n: down
c-p: up
c-a: first of the current line
c-e: last of the current line
m-f: forward by word
m-e: back by word
c-v: forward page
m-v: back page
m-<: buffer="" first="" of="" p="">m->: last of buffer

save: c-x c-s
save as: c-x c-w

replace text: m-% (condition: y, n, !(total))

regexp search: esc c-s (forward)
regexp search: esc c-r (back)

------------------------------------------------------------------------------
window

c-x 1: remain only current window
c-x 2: split window horizontal
c-x 3: split window vertical

------------------------------------------------------------------------------
edit

c-x tab: indent current region
c-o: insert blank line after the cursor
c-shift-@: set mark
m-w: copy
c-y: paste
c-w: cut
c-shift-_: undo
c-u nubmer: repeat number time

c-g: cancel current command
c-x k: kill current buffer

------------------------------------------------------------------------------
select rectangle region

1. m-x cua-mode
2. c-return
3. move (using arrow keys or emacs move keys )
4. copy, cut, paste( c-x, c-c, c-v or emacs command keys)

------------------------------------------------------------------------------
mode

m-x column-number-mode: show column number
m-x cua-mode

------------------------------------------------------------------------------
dired mode

c-x c-f: open file
c-x d: open directory
p: up
n: down
C: copy
D: delete
m: set mark
u: disable mark
U: disable all mark