Search
🌎

miniRT

Created
2021/03/23
tag
42μ„œμšΈ
42Seoul
miniRT
Ray Tracing
math.h
mlx.h

Subjects

β€’
β€’
λ³Έ 글은 Mac OS X μƒμ—μ„œ μ§„ν–‰λœ λ‚΄μš©μ„ λ‹€λ€˜λ‹€λŠ” 것을 미리 λ°νž™λ‹ˆλ‹€.

1. External Functions

1) perror

1. μ˜μ‘΄μ„±

#include <stdio.h>
C

2. ν•¨μˆ˜ μ›ν˜•

void perror(const char *s);
C

3. ν•¨μˆ˜ μ„€λͺ…

perrorλΌλŠ” 말은 print a system error messageλΌλŠ” μ˜λ―Έμ΄λ‹€. sκ°€ 널이 μ•„λ‹ˆκ³ , *sκ°€ 널 λ¬Έμžκ°€ 아닐 λ•Œ perror ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜λ©΄, 인자둜 λ“€μ–΄μ˜¨ λ¬Έμžμ—΄μ„ ν‘œμ€€ μ—λŸ¬λ₯Ό μ΄μš©ν•˜μ—¬ 좜λ ₯ν•΄μ€€λ‹€. 인자둜 λ„˜κΈ΄ λ¬Έμžμ—΄μ„ 좜λ ₯ν•˜κ³  끝이 μ•„λ‹ˆλΌ, ν˜„μž¬ μ„€μ •λœ errno 에 ν•΄λ‹Ήν•˜λŠ” 메세지λ₯Ό 콜둠과 곡백 문자λ₯Ό μ•žμ— λΆ™μ—¬ 좜λ ₯ν•œλ‹€. μ˜ˆμ‹œλ₯Ό μ°Έκ³ ν•˜μž.
errnoλŠ” errno.h에 맀크둜 μ„ μ–ΈμœΌλ‘œ μ‘΄μž¬ν•œλ‹€. 별 λ‹€λ₯Έ Errorκ°€ λ°œμƒν•˜μ§€ μ•Šμ•˜λ‹€λ©΄, κΈ°λ³Έ 값은 0이닀. Error에 λŒ€ν•œ indexκ°€ κΆκΈˆν•˜λ‹€λ©΄ errno.h에 μ „μ—­μ μœΌλ‘œ κ΄€λ¦¬λ˜λŠ” 리슀트인 sys_errlistλ₯Ό 톡해 μ—¬λŸ¬ Error듀을 μ°Ύμ•„λ³Ό 수 μžˆλ‹€. κ°€μž₯ 큰 수의 indexλŠ” sys_nerr κ°’ - 1이닀. 직접 μ •μ˜ν•œ μƒˆλ‘œμš΄ Error 값은 sys_errlist에 μΆ”κ°€λ˜μ§€ μ•Šμ•˜μ„ μˆ˜λ„ μžˆμœΌλ―€λ‘œ sys_errlist에 λŒ€ν•œ 직접적인 μ‚¬μš©μ€ μ£Όμ˜ν•  ν•„μš”κ°€ μžˆλ‹€. λ˜ν•œ sys_errlistλŠ” ν˜„μž¬ deprecated이고, strerrorλ₯Ό 주둜 μ‚¬μš©ν•œλ‹€. 일반적으둜 μ‹œμŠ€ν…œ 콜이 μ‹€νŒ¨ν•˜λ©΄ -1을 λ¦¬ν„΄ν•˜λŠ”λ°, 이 값을 λ°›κ²Œ 되면 λ°œμƒν•œ 증상에 λ§žλŠ” index둜 errnoκ°€ μ„€μ •λœλ‹€. μ‹œμŠ€ν…œ 콜이 μ„±κ³΅ν•˜κ²Œ 되면 errnoλŠ” undefined의 μƒνƒœλ‘œ μ‘΄μž¬ν•œλ‹€. errnoλŠ” ν˜ΈμΆœν•œ μ‹œμŠ€ν…œ 콜의 성곡 여뢀에 λ”°λΌμ„œ κ·Έ 값이 κ°±μ‹ λ˜κΈ° λ•Œλ¬Έμ— μ‹œμŠ€ν…œ μ½œμ— λŒ€ν•œ 호좜 직후 perrorλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠμœΌλ©΄ errnoκ°€ λ‹€λ₯Έ μ‹œμŠ€ν…œ μ½œμ— μ˜ν•΄ 갱신될 수 μžˆμœΌλ―€λ‘œ errno에 λŒ€ν•œ 값을 μ €μž₯해둬야 ν•  μˆ˜λ„ μžˆλ‹€. λ”°λΌμ„œ μ‹œμŠ€ν…œ 콜이 μ‹€νŒ¨ν–ˆλ‹€λ©΄ 이λ₯Ό λ°˜λ“œμ‹œ μ‚¬λžŒμ΄ 읽을 수 μžˆλŠ” ν˜•νƒœλ‘œ 좜λ ₯ν•˜λ„λ‘ perrorλ₯Ό ν˜ΈμΆœν•˜λŠ” 것이 ꢌμž₯λœλ‹€.

4. μ˜ˆμ‹œ

#include <stdio.h> #include <errno.h> int main(void) { printf("current errno: %d\n", errno); printf("current sys_nerr: %d\n", sys_nerr); perror("intentioned error"); return (0); }
C

2) strerror

1. μ˜μ‘΄μ„±

#include <string.h>
C

2. ν•¨μˆ˜ μ›ν˜•

char * strerror(int errnum);
C

3. ν•¨μˆ˜ μ„€λͺ…

perror에 λŒ€ν•œ μ„€λͺ…을 ν•˜λ©΄μ„œ μ§€λ§‰ν•˜κ²Œ strerror에 λŒ€ν•΄μ„œ μ„€λͺ…을 ν–ˆλ‹€. sys_errlistκ°€ deprecatedμ—¬μ„œ strerrorλ₯Ό μ‚¬μš©ν•œλ‹€κ³  ν–ˆλ‹€. errno.hμ—λŠ” Error λ°œμƒ μ‹œ μ„€μ •λ˜λŠ” index듀이 μ •μ˜λ˜μ–΄ μžˆλŠ”λ°, 이 index듀은 Error λ°œμƒ μ‹œ errno에 μ„€μ •λœλ‹€. Error에 λŒ€ν•œ index 값을 strerror에 λ„£κ²Œ 되면, index에 ν•΄λ‹Ήν•˜λŠ” λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•˜κ²Œ λœλ‹€. (μ •ν™•νžˆλŠ” ν•΄λ‹Ή λ¬Έμžμ—΄μ„ μ°Έμ‘°ν•˜λŠ” 포인터λ₯Ό λ°˜ν™˜ν•œλ‹€.) 기본적으둜 λ°˜ν™˜λ˜λŠ” λ¬Έμžμ—΄μ€ μ˜μ–΄λ‘œ λ˜μ–΄ μžˆμ§€λ§Œ, λ‘œμΌ€μΌμ— λ”°λΌμ„œ λ‹€λ₯Έ μ–Έμ–΄λ‘œ 된 λ¬Έμžμ—΄μ„ μ°Έμ‘°ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€. λ°˜ν™˜λ˜λŠ” λ¬Έμžμ—΄μ€ λ¬Έμžμ—΄ λ¦¬ν„°λŸ΄μ„ μ°Έμ‘°ν•˜κ³  있기 λ•Œλ¬Έμ— λ³„λ„μ˜ μˆ˜μ •μ€ 일어날 수 μ—†λ‹€.
strerror에 μ˜ν•΄ λ°˜ν™˜λ˜λŠ” λ¬Έμžμ—΄μ€ ν˜„μž¬ μ‚¬μš© 쀑인 λ‘œμΌ€μΌ, 컴파일러, ν”Œλž«νΌμ— λ”°λΌμ„œ λ‹€λ₯Ό 수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄ ν˜„μž¬ μ‚¬μš©μ€‘μΈ 운영 μ²΄μ œκ°€ Mac OS X라면 μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 _DARWIN_ALIASλ˜μ–΄ μ‚¬μš©λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. (Mac OS XλŠ” BSD κ³„μ—΄μ˜ Darwin μš΄μ˜μ²΄μ œμ— κΈ°μ΄ˆν•œλ‹€.)

4. μ˜ˆμ‹œ

#include <errno.h> #include <stdio.h> #include <string.h> int main(void) { printf("current error: %s\n", strerror(errno)); return (0); }
C

3) exit

1. μ˜μ‘΄μ„±

#include <stdlib.h>
C

2. ν•¨μˆ˜ μ›ν˜•

noreturn void exit(int status);
C
noreturn μ΄λž€? C11λΆ€ν„° 제곡된 _Noretrunμ΄λΌλŠ” ν‚€μ›Œλ“œλ₯Ό νŽΈλ¦¬ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλŠ” λ§€ν¬λ‘œμ΄λ‹€. noreturnμ΄λΌλŠ” 맀크둜λ₯Ό μ΄μš©ν•˜κΈ° μœ„ν•΄μ„  _Noreturn을 Mappingν•˜κ³  μžˆλŠ” <stdnoreturn.h>λΌλŠ” λΌμ΄λΈŒλŸ¬λ¦¬κ°€ ν•„μš”ν•˜λ‹€. _Noreturn은 ν˜ΈμΆœν•œ ν•¨μˆ˜μ—κ²Œ μ•„λ¬΄λŸ° 값을 λ°˜ν™˜ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€λŠ” 것을 μ»΄νŒŒμΌλŸ¬μ—κ²Œ 미리 μ•Œλ¦¬λŠ” ν‚€μ›Œλ“œμ΄λ‹€. μ΄λ ‡κ²Œ 되면 μ»΄νŒŒμΌλŸ¬λŠ” _Noreturn ν•¨μˆ˜μ˜ 호좜 μ΄ν›„μ˜ μ½”λ“œμ— μ ‘κ·Όν•  수 μ—†λ‹€λŠ” 사싀을 μΈμ‹ν•˜κ²Œ λœλ‹€. noreturn이 ν‘œκΈ°λœ ν•¨μˆ˜λŠ” ν˜ΈμΆœμžμ—κ²Œ μ–΄λ– ν•œ 값도 λ°˜ν™˜ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— λ°˜ν™˜ ν˜•μ‹μ„ ν¬ν•¨ν•΄μ„œλŠ” μ•ˆ λ˜λ―€λ‘œ voidμ—¬μ•Ό ν•œλ‹€. ν˜ΈμΆœμžμ—κ²Œ λ°˜ν™˜λ˜λŠ” μ–΄λ–€ 흐름을 μ‘°μž‘ν•΄μ•Όν•  κ°€λŠ₯성이 μžˆλ‹€λ©΄ μ ˆλŒ€λ‘œ _Noreturn ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„  μ•ˆλœλ‹€. noreturn의 μ£Όμš” 이점이라 함은 ν•¨μˆ˜μ˜ μ˜λ„λ₯Ό 더 λͺ…ν™•νžˆ ν•  수 μžˆλ‹€λŠ” 것과 μ ‘κ·Ό λΆˆκ°€λŠ₯ν•œ μ½”λ“œμ— λŒ€ν•΄ μžμ—°μŠ€λŸ½κ²Œ μΊμΉ˜μ‹œν‚¨λ‹€λŠ” 것이닀. λŒ€ν‘œμ μΈ μ˜ˆμ‹œλ‘œλŠ” exit ν•¨μˆ˜μ™€ abort ν•¨μˆ˜κ°€ μžˆλ‹€.

3. ν•¨μˆ˜ μ„€λͺ…

exit ν•¨μˆ˜λŠ” ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•΄μ„œ μ •μƒμ μœΌλ‘œ μ’…λ£Œν•  수 있게 ν•΄μ€€λ‹€. exit ν•¨μˆ˜μ—μ„œμ˜ 정상적인 μ’…λ£ŒλΌλŠ” 말은 C μ–Έμ–΄λ‘œ λ§Œλ“€μ–΄μ§„ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ‚¬μš© 쀑인 파일 μž…μΆœλ ₯을 μ €μž₯함과 λ™μ‹œμ— ν”„λ‘œμ„ΈμŠ€λ₯Ό μ’…λ£Œν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€μ˜ κΆŒν•œμ„ μš΄μ˜μ²΄μ œμ— λ„˜κΈ°λŠ” 것을 λ§ν•œλ‹€. μ‚¬μš© 쀑인 파일 μž…μΆœλ ₯을 μ €μž₯ν•œλ‹€λŠ” 것은 λͺ¨λ“  열렀진 νŒŒμΌμ„ λ‹«κ³ , 좜λ ₯ 버퍼에 데이터가 있으면 ν•΄λ‹Ή λ‚΄μš©μ„ write ν•˜μ—¬ μž‘μ—…μ„ μ™„λ£Œν•œλ‹€λŠ” 것이닀.
exit은 ν”„λ‘œμ„ΈμŠ€μ˜ μ’…λ£Œλ₯Ό μ˜λ―Έν–ˆλ‹€λ©΄, return은 ν•¨μˆ˜μ˜ μ’…λ£Œλ₯Ό μ˜λ―Έν•œλ‹€. λ”°λΌμ„œ main ν•¨μˆ˜μ—μ„œμ˜ return은 exitκ³Ό λ™μΌν•œ λ™μž‘μ„ λ§Œλ“€μ–΄λ‚Έλ‹€.
exit의 statusλŠ” μ •μˆ˜λ₯Ό λ°›κ²Œλ˜λŠ”λ°, λ³„λ„μ˜ λ°˜ν™˜ 값이 μ—†λ‹€κ³  λͺ…μ‹œλ˜μ–΄ μžˆμŒμ—λ„ 인자둜 받은 μ •μˆ˜λ₯Ό μš΄μ˜μ²΄μ œμ— λ°˜ν™˜ν•˜κ²Œ λœλ‹€. 이λ₯Ό EXITCODE라 ν•œλ‹€. 일반적으둜 였λ₯˜κ°€ μ—†λŠ” μ’…λ£Œ μ‹œμ—λŠ” 0을 status둜 λ„£κ²Œ 되고, 였λ₯˜κ°€ μžˆλ‹€λ©΄ κ·Έ μ™Έμ˜ 값을 인자둜 (λŒ€μ²΄μ μœΌλ‘œ 1을 μ‚¬μš©) λ„£κ²Œ λœλ‹€. λ”°λΌμ„œ exit의 status둜 0을 μ‚¬μš©ν•˜λ©΄ SUCCESS, 1을 μ‚¬μš©ν•˜λ©΄ FAILUREλ₯Ό μ˜λ―Έν•˜κ²Œ λœλ‹€. (λ‚΄λΆ€μ μœΌλ‘œ 0이 EXIT_SUCCESS, 1이 EXIT_FAILURE둜 μ •μ˜ λ˜μ–΄ μžˆλ‹€.) λ°˜ν™˜λœ EXITCODEλŠ” Parentκ°€ μ‘΄μž¬ν•œλ‹€λ©΄ Parent ν”„λ‘œμ„ΈμŠ€μ—κ²Œ μ „λ‹¬λœλ‹€. (exit ν•¨μˆ˜μ— λŒ€ν•œ linux manual의 Least Significant Byteλ₯Ό Parent둜 λ³΄λ‚Έλ‹€λŠ” 것이 EXITCODEλ₯Ό λ³΄λ‚΄λŠ” 것을 μ˜λ―Έν•œλ‹€. wait ν•¨μˆ˜λ₯Ό 찾아보면 ν•΄λ‹Ή λ‚΄μš©μ— λŒ€ν•΄ μžμ„Ένžˆ μ•Œ 수 μžˆλ‹€.)
일반적으둜 EXITCODEλŠ” 16λΉ„νŠΈλ‘œ ν‘œν˜„λ˜κ³ , μ˜λ―Έν•˜λŠ” 바에 따라 μƒμœ„ 8λΉ„νŠΈμ™€ ν•˜μœ„ 8λΉ„νŠΈλ‘œ λ‚˜λ‰˜κ²Œ λœλ‹€. μƒμœ„ 8λΉ„νŠΈλŠ” exit ν•¨μˆ˜μ˜ statusλ₯Ό μ˜λ―Έν•œλ‹€. exit의 statusκ°€ 0을 λ°›μ•„μ„œ 였λ₯˜ 없이 μ’…λ£Œκ°€ λ˜μ—ˆλŠ”μ§€ νŒλ³„ν•˜μ—¬, 였λ₯˜κ°€ μ—†λ‹€λ©΄ μƒμœ„ 8λΉ„νŠΈλŠ” 0으둜 μ±„μ›Œμ§„λ‹€. (λ°˜λŒ€λ‘œ 였λ₯˜κ°€ μžˆλŠ” μ±„λ‘œ μ’…λ£Œλ˜λ©΄ μƒμœ„ 8λΉ„νŠΈλŠ” 0이 μ•„λ‹Œ κ°’μœΌλ‘œ μ±„μ›Œμ§„λ‹€.) ν•˜μœ„ 8λΉ„νŠΈλŠ” 였λ₯˜ 없이 μ’…λ£Œλœ κ²½μš°μ—” 0으둜 μ±„μ›Œμ§€λ©°, 였λ₯˜κ°€ μžˆλŠ”μ±„λ‘œ μ’…λ£Œλ˜λ©΄ μ–΄λ–€ SIGNAL에 μ˜ν•œ 것인지 κ·Έ 값이 μ±„μ›Œμ§„λ‹€. 이에 λŒ€ν•œ λ‚΄μš©μ€ <sys/wait.h>의 EXITCODE 계산 방법과 그에 따라 λ‚˜μ—΄λœ SIGNAL듀을 확인해보면 μ‰½κ²Œ μ•Œ 수 μžˆλ‹€.
만일 waitpid ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ statusλ₯Ό 인자둜 μ‚¬μš©ν•  λ•Œ, Child ν”„λ‘œμ„ΈμŠ€κ°€ exit으둜 μ’…λ£Œλ¨κ³Ό λ™μ‹œμ— 이에 λŒ€ν•œ μ˜¬λ°”λ₯Έ statusλ₯Ό μ–»κ³  μ‹Άλ‹€λ©΄ λ‹€μŒκ³Ό 같이 WIFEXITEDλΌλŠ” 맀크둜 ν•¨μˆ˜λ‘œ 쑰건 검사λ₯Ό ν•˜κ³  WEXITSTATUS둜 μ˜¬λ°”λ₯Έ status 값을 얻을 수 μžˆλ‹€. 비정상 μ’…λ£Œ μ‹œμ—λŠ” SIGNAL 값을 μ–»μ–΄μ•Όν•˜λ―€λ‘œ WIFSIGNALED둜 SIGNAL λ°œμƒ 검사 ν›„, WTERMSIG둜 μ˜¬λ°”λ₯Έ SIGNAL 값을 μ–»μ–΄λ‚Ό 수 μžˆλ‹€.
#include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main() { int pid; int status; pid = fork(); if (pid < 0) { perror("fork error : "); exit(0); } if (pid == 0) { printf("Child\n"); sleep(10); return (2); } else { printf("Parent: wait (%d)\n", pid); waitpid(pid, &status, 0); if (WIFEXITED(status)) { printf("Normally Terminated\n"); printf("Exit Status : %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("Abnormally Terminated\n"); printf("Exit Signal : %d\n", WTERMSIG(status)); } } exit(0); }
C

4. μ˜ˆμ‹œ

#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { if (argc == 1) { printf("invalid args: %d\n", argc); printf("detail: %s\n", *argv); exit(1); } else { printf("valid args: %d\n", argc); while (*argv) printf("detail: %s\n", *argv++); exit(0); } }
C

2. <math.h>

miniRTλŠ” <math.h>λ₯Ό μ „λ©΄ ν—ˆμš©ν•œλ‹€. μ–΄λ–€ ν•¨μˆ˜λ“€μ΄ μžˆλŠ”μ§€ μž‘μ„±ν•΄λ‘μ—ˆμœΌλ‹ˆ μ•„λž˜ λ§ν¬μ—μ„œ μ•Œμ•„λ³΄μž.

3. "mlx.h"

cub3d와 miniRT λ‘˜ 쀑 무엇을 μ„ νƒν•˜λ”λΌλ„ "mlx.h"λ₯Ό μ‚¬μš©ν•˜κ²Œ λœλ‹€. Mac OS X의 κ·Έλž˜ν”½μ„ μ²˜λ¦¬ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μ— μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ“±λ‘ν•¨μœΌλ‘œμ¨ κ·Έλž˜ν”½ μš”μ†Œμ— λŒ€ν•œ 접근이 κ°€λŠ₯ν•΄μ‘Œμ„ λ•Œ, "mlx.h"λŠ” 이λ₯Ό μ²˜λ¦¬ν•΄μ£ΌλŠ” Small Home-Made Library이닀. μ‚¬μš© 방법은 intraμ—μ„œ 짧은 λ™μ˜μƒ κ°•μ˜λ₯Ό μ œκ³΅ν•œλ‹€.
42 Docsμ—μ„œλŠ” 이에 λŒ€ν•œ μƒμ„Έν•œ Documentλ₯Ό μ œκ³΅ν•˜κΈ°λ„ ν•œλ‹€.
ν”„λ‘œμ νŠΈλ₯Ό λ“±λ‘ν•˜λ©΄ Subject 파일과 ν•¨κ»˜ minilibx_mms와 minilibx_opengl을 μ΄μš©ν•  수 μžˆλ„λ‘ ν•΄λ’€λŠ”λ°, mms와 opengl을 λ‹€μš΄λ‘œλ“œ 해보면 μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 μ••μΆ• 파일둜 λ˜μ–΄ μžˆλŠ” 것을 확인할 수 μžˆλ‹€.
각 νŒŒμΌμ„ μ••μΆ• ν•΄μ œν•˜μ—¬ mlx에 넣은 ν›„ λ‚΄λΆ€ μ†ŒμŠ€λ“€μ„ ν™•μΈν•΄λ³΄μž.
κ°€μž₯ λˆˆμ— λ„λŠ” 것은 각 디렉토리 λ‚΄λΆ€μ˜ Makefileκ³Ό mms λ‚΄λΆ€μ˜ man인데 이에 λŒ€ν•΄μ„œ 각각 ν™•μΈν•΄λ³΄μž.

1) man

man 디렉토리λ₯Ό 타고 λκΉŒμ§€ 듀어가보면, μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 5개의 맀뉴얼 파일이 μ‘΄μž¬ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.
λ§€λ‰΄μ–Όμ˜ 확인은 μ•„λž˜ λͺ…령어에 기재된 κ²ƒμ²˜λŸΌ μƒλŒ€ κ²½λ‘œλ‘œλ„ μ—΄ 수 있고, μ ˆλŒ€ κ²½λ‘œλ‘œλ„ μ—΄ 수 μžˆλ‹€.
νŠΉμ • νŒŒμΌμ„ man으둜 μ—΄ 수 μžˆλ„λ‘ ν•˜λ €λ©΄ νŠΉμ • 양식에 맞좰 μž‘μ„±λ˜μ–΄μ•Ό ν•˜κ³ , νŠΉμ • 양식에 맞좰 μž‘μ„±λ˜μ–΄ 있기 떄문에 vim으둜 μ—¬λŠ” 것보닀 man으둜 νŒŒμΌμ„ ν™•μΈν–ˆμ„ λ•Œ 쑰금 더 높은 가독성이 보μž₯λœλ‹€.
man ./mlx.3 man /Users/bigpel/Downloads/mlx/minilibx_mms_20200219/man/man3/mlx.3
제곡된 5개의 맀뉴얼 파일 덕뢄에 "mlx.h"μ—μ„œ μ–΄λ–€ ν•¨μˆ˜λ“€μ„ μ œκ³΅ν•˜λŠ”μ§€ 쑰금 더 νŽΈλ¦¬ν•˜κ²Œ μ•Œ 수 있게 λ˜μ—ˆλ‹€. 쑰금 λΆˆνŽΈν•œ 점이 μžˆλ‹€λ©΄ 각 맀뉴얼 νŒŒμΌμ„ ν™•μΈν•˜κΈ° μœ„ν•΄μ„œ μƒλŒ€ κ²½λ‘œλ“  μ ˆλŒ€ κ²½λ‘œλ“  경둜λ₯Ό μ•Œκ³  μžˆμ–΄μ•Ό man을 μ‚¬μš©ν•  수 μžˆλ‹€λŠ” 점인데, man에 λŒ€ν•œ 섀정을 쑰금만 λ°”κΏ”μ£Όλ©΄ 경둜 없이 νŽΈλ¦¬ν•˜κ²Œ μ΄μš©ν•  수 μžˆλ‹€.
μš°μ„  맀뉴얼 νŒŒμΌλ“€μ΄ μ‘΄μž¬ν•˜λŠ” μœ„μΉ˜λ₯Ό μ•Œμ•„μ•Ό ν•˜λŠ”λ°, μ•„λž˜μ˜ λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•΄λ„ μ’‹κ³  ν˜Ήμ€ /private/etc/man.confλ₯Ό vim으둜 μ—΄μ–΄μ„œ 확인할 수 μžˆλ‹€.
manpath
manpath의 μˆ˜ν–‰κ²°κ³ΌλŠ” μ•„λž˜ κ·Έλ¦Όκ³Ό κ°™λ‹€.
/private/etc/man.confλ₯Ό 열어보면 man에 λŒ€ν•œ Pathκ°€ μ•„λž˜ 그림처럼 λͺ…μ‹œλ˜μ–΄ μžˆλŠ”κ±Έ λ³Ό 수 μžˆλ‹€.
제곡 받은 맀뉴얼 νŒŒμΌμ„ μœ„μΉ˜μ‹œν‚€κΈ° μœ„ν•΄, 이 κΈ€μ—μ„œλŠ” /usr/local/share/manμ΄λΌλŠ” 경둜λ₯Ό μ΄μš©ν•  것이닀. μˆ˜λ™μœΌλ‘œ 맀뉴얼 νŒŒμΌμ„ ν•΄λ‹Ή κ²½λ‘œμ— λ„£μœΌλ €κ³  ν•˜λ©΄ μˆ˜ν–‰μ΄ λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ—, 터미널 ν™˜κ²½μ—μ„œ sudo λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜μ—¬ 볡사할 것이닀.
주어진 λͺ…λ Ήμ–΄λ₯Ό μžμ‹ μ˜ κ²½λ‘œμ— 맞게 μˆ˜μ •ν•˜μ—¬, μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 man3 λ””λ ‰ν† λ¦¬μ˜ νŒŒμΌλ“€μ„ /usr/local/share/man/man3둜 λ³΅μ‚¬ν•˜λ©΄ λœλ‹€.
sudo cp ./* /usr/local/share/man/man3
μœ„ λͺ…λ Ήμ–΄λ₯Ό 톡해 맀뉴얼 νŒŒμΌλ“€μ˜ 볡사가 끝났닀면, man λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜λŠ”λ° μžˆμ–΄μ„œ μ΄μ „μ²˜λŸΌ 경둜둜 인자λ₯Ό 쀄 ν•„μš”κ°€ μ—†κΈ° λ•Œλ¬Έμ— νŽΈν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄, μ΄μ „μ—λŠ” man ./mlx.3둜 μ³€μ—ˆλ‹€λ©΄ ν™•μž₯자λͺ…도 ν•„μš”μ—†μ΄ man mlx만으둜 맀뉴얼을 읽을 수 있게 된 것이닀.
man3μ—μ„œ 3은 라이브러리 λ‚΄λΆ€μ˜ ν•¨μˆ˜ ν˜ΈμΆœμ— λŒ€ν•œ 맀뉴얼을 μ˜λ―Έν•œλ‹€. man에 λŒ€ν•œ λ‹€λ₯Έ index듀도 의미 λ³„λ‘œ λ‹€λ₯΄κ²Œ μ‘΄μž¬ν•˜λŠ”λ°, ν•΄λ‹Ή λ‚΄μš©μ€ μ•„λž˜ λ§ν¬μ—μ„œ 확인할 수 μžˆλ‹€.
man λͺ…λ Ήμ–΄ κ΄€λ ¨ 섀정에 λŒ€ν•œ λ‚΄μš©μ€ μ•„λž˜ λ§ν¬μ—μ„œ 쑰금 더 μžμ„Έν•˜κ²Œ μ•Œμ•„λ³Ό 수 μžˆλ‹€.

2) Makefile

맀뉴얼 νŒŒμΌλ“€μ„ 읽어보면 "mlx.h"μ—μ„œ κ½€ λ§Žμ€ ν•¨μˆ˜λ“€μ„ μ œκ³΅ν•΄μ£ΌλŠ” 것을 확인할 수 μžˆλ‹€. μ œκ³΅λ˜λŠ” ν•¨μˆ˜λ“€μ„ μ‚¬μš©ν•˜μ—¬ ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€κΈ° μœ„ν•΄μ„  "mlx.h"에 λŒ€ν•œ 라이브러리λ₯Ό λ¨Όμ € 생성해야 ν•œλ‹€. opengl와 mms 디렉토리λ₯Ό 열어보면 λͺ¨λ‘ Makefile이 μ‘΄μž¬ν•˜λŠ” 것을 확인할 수 있고, 이λ₯Ό μ΄μš©ν•˜μ—¬ μ»΄νŒŒμΌν•˜λ©΄ λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μƒμ„±λ˜λŠ” 것을 확인할 수 μžˆλ‹€.
opengl λ””λ ‰ν† λ¦¬μ—μ„œ make λͺ…λ Ήμ–΄λ‘œ 컴파일 ν•˜κ³  λ‚˜λ©΄ μ•„λž˜μ˜ 그림처럼 libmlx.aλΌλŠ” 정적 λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μƒμ„±λ˜λŠ” 것을 확인할 수 μžˆλ‹€.
opengl의 Makefile을 μ΄μš©ν•œ 컴파일 μ΄μ „μ˜ νŒŒμΌλ“€
opengl의 Makefile을 μ΄μš©ν•œ 컴파일 μ΄ν›„μ˜ νŒŒμΌλ“€
mms λ””λ ‰ν† λ¦¬μ—μ„œ make λͺ…λ Ήμ–΄λ‘œ μ»΄νŒŒμΌμ„ ν•˜κ³  λ‚˜λ©΄ μ•„λž˜ 그림처럼 libmlx.dylibλΌλŠ” 동적 λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μƒμ„±λ˜λŠ” 것을 확인할 수 μžˆλ‹€.
mms의 Makefile을 μ΄μš©ν•œ 컴파일 μ΄μ „μ˜ νŒŒμΌλ“€
mms의 Makefile을 μ΄μš©ν•œ 컴파일 μ΄ν›„μ˜ νŒŒμΌλ“€
두 라이브러리λ₯Ό λͺ¨λ‘ μ΄μš©ν•  ν•„μš”λŠ” μ—†κ³ , λ‘˜ 쀑 ν•˜λ‚˜λ§Œ μ„ νƒν•˜μ—¬ μž‘μ„±ν•œ μ½”λ“œμ™€ ν•¨κ»˜ μ»΄νŒŒμΌν•˜λ©΄ λœλ‹€. 정적 λΌμ΄λΈŒλŸ¬λ¦¬μ™€ 동적 λΌμ΄λΈŒλŸ¬λ¦¬μ— λŒ€ν•΄μ„œλŠ” ν”Œλž«νΌ λ§ˆλ‹€ 이λ₯Ό μ§€μΉ­ν•˜λŠ” ν™•μž₯μžκ°€ λͺ¨λ‘ λ‹€λ₯΄λ‹€.
정적 라이브러리 νŠΉμ • κΈ°λŠ₯을 ν•˜λŠ” 라이브러리λ₯Ό 정적 (static)으둜 μƒμ„±ν•œλ‹€λŠ” 것은 μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“œλŠ” Link λ‹¨κ³„μ—μ„œ 라이브러리λ₯Ό ν¬ν•¨μ‹œν‚€κ² λ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€. λ”°λΌμ„œ 라이브러리 λ‚΄λΆ€μ˜ μ½”λ“œκ°€ 이λ₯Ό μ‚¬μš©ν•˜λŠ” μ‹€ν–‰ νŒŒμΌμ— ν•¨κ»˜ ν¬ν•¨λ˜κΈ° λ•Œλ¬Έμ—, λ³„λ„μ˜ μž‘μ—… 없이 μ‹€ν–‰ 파일만으둜 라이브러리 λ‚΄λΆ€μ˜ μ½”λ“œλ₯Ό μ΄μš©ν•  수 있게 λœλ‹€. ν•˜μ§€λ§Œ Multiple-Caller Program이 μ‘΄μž¬ν•˜λŠ” 경우, 즉 λ™μ‹œμ— λ™μΌν•œ 정적 라이브러리λ₯Ό μ΄μš©ν•˜λŠ” ν”„λ‘œμ„ΈμŠ€κ°€ μ‘΄μž¬ν•˜κ²Œ 되면 λ©”λͺ¨λ¦¬μ˜ 곡간 효율이 λ–¨μ–΄μ§€λŠ” ν˜„μƒμ΄ λ°œμƒν•  수 μžˆλ‹€. 정적 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” λ¨Έμ‹  간에 ν”„λ‘œκ·Έλž¨μ˜ 이동이 λ°œμƒν–ˆμ„ λ•Œ 쑰금 더 ꡬ동이 쉽도둝 λ§Œλ“€μ–΄μ£Όκ³ , 보닀 μž‘μ€ ν”„λ‘œκ·Έλž¨μ„ λΉ λ₯΄κ²Œ λ§Œλ“€κ³  싢을 λ•Œ 주둜 μ΄μš©ν•˜κ²Œ λœλ‹€.
동적 라이브러리 라이브러리λ₯Ό 동적 (dynamic)으둜 μƒμ„±ν•œλ‹€λŠ” 것은 μ‹€ν–‰ νŒŒμΌμ— 라이브러리의 μ½”λ“œκ°€ 직접 λ“€μ–΄κ°€λŠ” 것이 μ•„λ‹ˆλΌ ν•„μš” μ‹œμ— 라이브러리 μ½”λ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” μ΅œμ†Œν•œμ˜ μ •λ³΄λ§Œμ΄ ν¬ν•¨λ˜μ–΄ Link λ˜λŠ” 것을 μ˜λ―Έν•œλ‹€. λ”°λΌμ„œ 정적 라이브러리λ₯Ό μ΄μš©ν•  λ•Œλ³΄λ‹€ μ‹€ν–‰ 파일의 크기가 μž‘μ€ 편이고, 라이브러리 μžμ²΄λŠ” ν”„λ‘œκ·Έλž¨μ΄ 싀행될 λ•Œ Link λœλ‹€κ³  보면 λœλ‹€. μ΄λŸ¬ν•œ 동적인 LinkλŠ” μ‹œμŠ€ν…œμ˜ 가상 λ©”λͺ¨λ¦¬λ₯Ό μ΅œλŒ€ν•œ ν™œμš©ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” μ΅œμ ν™” 기술이라고 λ³Ό 수 μžˆλŠ”λ°, 라이브러리의 μ½”λ“œκ°€ μ‚¬μš©λ˜κ³  μžˆλŠ” νŽ˜μ΄μ§€λŠ” μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€λ“€μ΄ κ³΅μœ ν•˜κ²Œ λœλ‹€. λ”°λΌμ„œ Multiple-Caller Program이 μ‘΄μž¬ν•˜λ”λΌλ„ λ©”λͺ¨λ¦¬ κ³΅κ°„μ˜ 효율이 크게 떨어지지 μ•ŠλŠ”λ‹€. 예λ₯Ό λ“€μ–΄, libc++은 λͺ¨λ“  C++ ν”„λ‘œκ·Έλž¨μ— Link λ˜μ–΄μ•Ό ν•˜λŠ”λ° 라이브러리 μ½”λ“œλ₯Ό λͺ¨λ“  ν”„λ‘œκ·Έλž¨μ— λ³΅μ‚¬ν•˜λŠ” λŒ€μ‹  κ°€μƒμ˜ νŽ˜μ΄μ§€λ₯Ό 톡해 μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€μ™€ λ™μ μœΌλ‘œ μ—°κ²°ν•  수 μžˆλ‹€. μ‹€ν–‰ νŒŒμΌμ„ λ§Œλ“œλŠ” κ³Όμ •μ—μ„œ μ–΄λ–€ 동적 라이브러리λ₯Ό μ΄μš©ν• μ§€ λͺ…μ‹œν•΄μ£Όκ²Œ 되면, ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜μ—ˆμ„ λ•Œ λ™μ μœΌλ‘œ κ°€μƒμ˜ νŽ˜μ΄μ§€ μœ„μ—μ„œ λ™μž‘ν•˜κ³  μžˆλŠ” 라이브러리 λ‚΄λΆ€μ˜ μ½”λ“œλ₯Ό μ°Έμ‘°ν•˜κ²Œ λœλ‹€. λ”°λΌμ„œ μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€κ°€ λ™μ μœΌλ‘œ ν•˜λ‚˜μ˜ 라이브러리 μ½”λ“œλ₯Ό μ°Έμ‘°ν•˜κ²Œ λ˜λ―€λ‘œ, ν”„λ‘œκ·Έλž¨μ΄ λ™μž‘ν•˜λŠ” ν™˜κ²½ 변경이 ν•„μš”ν•œ 경우 μΌκ΄„μ μœΌλ‘œ 이λ₯Ό 적용 μ‹œν‚€λŠ” 것이 κ°€λŠ₯ν•˜λ‹€.
두 λΌμ΄λΈŒλŸ¬λ¦¬μ— λŒ€ν•΄ μ‚¬μš©ν•  예제 μ½”λ“œ test.cλŠ” μ•„λž˜μ™€ κ°™λ‹€.
#include "mlx.h" int main(void) { void *m_ptr; void *w_ptr; m_ptr = mlx_init(); w_ptr = mlx_new_window(m_ptr, 1200, 800, "test window"); mlx_loop(m_ptr); return (0); }
C

[1] 정적 라이브러리λ₯Ό μ΄μš©ν•œ 컴파일

정적 라이브러리둜 컴파일 ν•˜μ—¬ test windowλ₯Ό λ„μ›Œλ³΄μž.
test.cλ₯Ό λͺ©μ  파일인 test.o둜 λ¨Όμ € λ§Œλ“€μ–΄μ€˜μ•Ό ν•˜λ―€λ‘œ gcc -c μ˜΅μ…˜μ„ 톡해 컴파일 ν•΄μ€˜μ•Ό ν•œλ‹€. 이 λ•Œ, μ½”λ“œ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•˜κ³  μžˆλŠ” "mlx.h"의 μœ„μΉ˜λ₯Ό μž‘μ•„μ£Όμ§€ μ•ŠμœΌλ©΄ μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 "mlx.h"λ₯Ό 찾지 λͺ»ν–ˆλ‹€λŠ” μ—λŸ¬λ₯Ό λ³Ό 수 μžˆλ‹€.
정적 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” opengl 디렉토리에 μœ„μΉ˜ν•΄ 있고, opengl λ””λ ‰ν† λ¦¬μ—λŠ” mlx.hλΌλŠ” 파일이 μ‘΄μž¬ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. λ”°λΌμ„œ gcc -c둜 컴파일 ν•  λ•Œ, opengl 디렉토리λ₯Ό -I μ˜΅μ…˜μœΌλ‘œ λͺ…μ‹œν•˜μ—¬ Header의 μœ„μΉ˜λ₯Ό μž‘μ•„μ£Όλ„λ‘ ν•œλ‹€. μ•„λž˜ 그림처럼 test.oλΌλŠ” λͺ©μ  파일이 μƒμ„±λœ 것을 확인할 수 μžˆλ‹€.
μƒμ„±λœ λͺ©μ  νŒŒμΌμ„ μ‹€ν–‰ 파일둜 λ§Œλ“€κΈ° μœ„ν•΄, -L μ˜΅μ…˜μ„ 톡해 라이브러리의 μœ„μΉ˜λ₯Ό λͺ…μ‹œν•˜κ³  -l μ˜΅μ…˜μ„ 톡해 μ‚¬μš©ν•˜λ €λŠ” 라이브러리λ₯Ό λͺ…μ‹œν•˜μ—¬ μ»΄νŒŒμΌμ„ μˆ˜ν–‰ν•œλ‹€. λ˜ν•œ "mlx.h"λ₯Ό μ΄μš©ν•˜μ—¬ 컴파일 ν•  λ•ŒλŠ” -framework OpenGL -framework AppKitμ΄λΌλŠ” μ˜΅μ…˜μ„ ν•¨κ»˜ λͺ…μ‹œν•΄μ€˜μ•Ό ν•œλ‹€. μ•„λž˜ 그림처럼 testλΌλŠ” μ‹€ν–‰ 파일이 μ •μƒμ μœΌλ‘œ μƒμ„±λœ 것을 확인할 수 μžˆλ‹€.
test νŒŒμΌμ„ 싀행해보면 test windowκ°€ μ‹€ν–‰λ˜λŠ” 것도 확인할 수 μžˆλ‹€.

[2] 동적 라이브러리λ₯Ό μ΄μš©ν•œ 컴파일

동적 라이브러리둜 컴파일 ν•˜μ—¬ test windowλ₯Ό λ„μ›Œλ³΄μž. 정적 라이브러리둜 μ»΄νŒŒμΌν•˜λŠ” 것과 크게 λ‹€λ₯Ό 것은 μ—†μ§€λ§Œ 좔가적인 μž‘μ—…μ΄ ν•˜λ‚˜ 더 ν•„μš”ν•˜λ‹€.
test.cλ₯Ό λͺ©μ  파일인 test.o둜 λ¨Όμ € λ§Œλ“€μ–΄μ€˜μ•Ό ν•˜λ―€λ‘œ gcc -c μ˜΅μ…˜μ„ 톡해 컴파일 ν•΄μ€˜μ•Ό ν•œλ‹€. 이 λ•Œ, μ½”λ“œ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•˜κ³  μžˆλŠ” "mlx.h"의 μœ„μΉ˜λ₯Ό μž‘μ•„μ£Όμ§€ μ•ŠμœΌλ©΄ μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 "mlx.h"λ₯Ό 찾지 λͺ»ν–ˆλ‹€λŠ” μ—λŸ¬λ₯Ό λ³Ό 수 μžˆλ‹€.
동적 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” mms 디렉토리에 μœ„μΉ˜ν•΄ 있고, mms λ””λ ‰ν† λ¦¬μ—λŠ” mlx.hλΌλŠ” 파일이 μ‘΄μž¬ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. λ”°λΌμ„œ gcc -c둜 컴파일 ν•  λ•Œ, mms 디렉토리λ₯Ό -I μ˜΅μ…˜μœΌλ‘œ λͺ…μ‹œν•˜μ—¬ Header의 μœ„μΉ˜λ₯Ό μž‘μ•„μ£Όλ„λ‘ ν•œλ‹€. μ•„λž˜ 그림처럼 test.oλΌλŠ” λͺ©μ  파일이 μƒμ„±λœ 것을 확인할 수 μžˆλ‹€.
μƒμ„±λœ λͺ©μ  νŒŒμΌμ„ μ‹€ν–‰ 파일둜 λ§Œλ“€κΈ° μœ„ν•΄, -L μ˜΅μ…˜μ„ 톡해 라이브러리의 μœ„μΉ˜λ₯Ό λͺ…μ‹œν•˜κ³  -l μ˜΅μ…˜μ„ 톡해 μ‚¬μš©ν•˜λ €λŠ” 라이브러리λ₯Ό λͺ…μ‹œν•˜μ—¬ μ»΄νŒŒμΌμ„ μˆ˜ν–‰ν•œλ‹€. λ˜ν•œ "mlx.h"λ₯Ό μ΄μš©ν•˜μ—¬ 컴파일 ν•  λ•ŒλŠ” -framework OpenGL -framework AppKitμ΄λΌλŠ” μ˜΅μ…˜μ„ ν•¨κ»˜ λͺ…μ‹œν•΄μ€˜μ•Ό ν•œλ‹€. μ•„λž˜ 그림처럼 testλΌλŠ” μ‹€ν–‰ 파일이 μ •μƒμ μœΌλ‘œ μƒμ„±λœ 것을 확인할 수 μžˆλ‹€.
test νŒŒμΌμ„ 싀행해보면 test windowκ°€ μ‹€ν–‰λ˜μ§€ μ•Šκ³  dyld: Library not loadedλΌλŠ” 였λ₯˜λ₯Ό λ³Ό 수 μžˆλ‹€. μ΄λŠ” Mac OS Xμ—μ„œ dylibλΌλŠ” ν™•μž₯자λ₯Ό κ°–λŠ” 동적 라이브러리λ₯Ό μ΄μš©ν•  λ•Œ 경둜 섀정이 λ˜μ–΄ μžˆμ§€ μ•Šμ•„μ„œ λ°œμƒν•˜λŠ” 였λ₯˜μ΄λ‹€. 이λ₯Ό μ²˜λ¦¬ν•˜λŠ” 방법은 μ§μ ‘μ μœΌλ‘œ 경둜λ₯Ό μˆ˜μ •ν•˜λŠ” 방법과 λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜μ—¬ 경둜λ₯Ό μˆ˜μ •ν•˜λŠ” λ°©λ²•μœΌλ‘œ 2가지가 μ‘΄μž¬ν•œλ‹€.
μ§μ ‘μ μœΌλ‘œ 경둜λ₯Ό μˆ˜μ •ν•˜λŠ” 방법
이 방법을 μ΄μš©ν•  λ•ŒλŠ” DYLD_LIBRARY_PATHλ₯Ό μ„€μ • ν•΄μ€˜μ•Ό ν•˜λŠ”λ° 확인해보면 μ•„λ¬΄λŸ° 값도 μ„€μ •λ˜μ–΄ μžˆμ§€ μ•Šμ€ 것을 확인할 수 μžˆλ‹€.
동적 λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μœ„μΉ˜ν•œ 곳의 μ ˆλŒ€ 경둜λ₯Ό ν™•μΈν•œ ν›„ 이λ₯Ό DYLD_LIBRARY_PATH둜 등둝해쀀닀.
만일 기쑴에 동적 라이브러리λ₯Ό μœ„ν•œ DYLD_LIBRARY_PATHλ₯Ό 이용 쀑이라면, κΈ°μ‘΄ κ²½λ‘œμ— μΆ”κ°€ν•΄μ•Όν•˜λ―€λ‘œ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$newPath와 같이 λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜λ©΄ λœλ‹€.
DYLD_LIBRARY_PATH에 λŒ€ν•œ 섀정이 λ˜μ—ˆλ‹€λ©΄ testλ₯Ό λ‹€μ‹œ 싀행해보면 test windowκ°€ μ‹€ν–‰λ˜λŠ” 것을 확인할 수 μžˆλ‹€.
λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜μ—¬ 경둜λ₯Ό μˆ˜μ •ν•˜λŠ” 방법
이 방법은 install_name_toolμ΄λΌλŠ” λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜μ—¬ μ‹€ν–‰ νŒŒμΌμ—μ„œ μš”κ΅¬ν•˜λŠ” 동적 λΌμ΄λΈŒλŸ¬λ¦¬μ— λŒ€ν•œ 경둜 섀정을 μ„€μ •ν•˜λŠ” 것이닀. man을 μ΄μš©ν•˜μ—¬ install_name_tool을 μ‚΄νŽ΄λ³΄λ©΄ 곡유되고 μžˆλŠ” 동적 λΌμ΄λΈŒλŸ¬λ¦¬μ— λŒ€ν•œ 파일 이름 μ‘°μž‘ ν˜Ήμ€ κ²½λ‘œμ— λŒ€ν•œ μ‘°μž‘μ΄ κ°€λŠ₯ν•œ 것을 λ³Ό 수 μžˆλ‹€.
μ•„λž˜ λͺ…λ Ήμ–΄μ²˜λŸΌ λ§€λ‰΄μ–Όμ—μ„œ μ œμ‹œν•œ μˆœμ„œλ‘œ 인자λ₯Ό λ„£μ–΄ μ‚¬μš©ν•˜λ©΄ λœλ‹€.
❯ install_name_tool -change libmlx.dylib ./minilibx_mms_20200219/libmlx.dylib test
testλ₯Ό 싀행해보면 test windowκ°€ μ‹€ν–‰λ˜λŠ” 것을 확인할 수 μžˆλ‹€.

[3] μ–΄λ–€ 라이브러리λ₯Ό μ΄μš©ν•΄μ•Ό λ˜λŠ”κ°€?

정적 λΌμ΄λΈŒλŸ¬λ¦¬μ™€ 동적 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” 각각의 νŠΉμ„±μ΄ 있기 λ•Œλ¬Έμ—, ν”„λ‘œκ·Έλž¨ μž‘μ„±μ— μžˆμ–΄μ„œ μ–΄λ–€ 라이브러리λ₯Ό μ΄μš©ν• μ§€λŠ” νŠΉμ„±μ„ κ³ λ €ν•˜μ—¬ μ„ νƒν•˜λ©΄ λœλ‹€. ν•˜μ§€λ§Œ cub3d ν˜Ήμ€ miniRT ν”„λ‘œμ νŠΈλ₯Ό λ¨Όμ € 끝낸 μ‚¬λžŒλ“€μ˜ μ–˜κΈ°λ₯Ό 듀어보면 opengl을 μ΄μš©ν•œ 정적 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” κ½€λ‚˜ μ΄μŠˆκ°€ μžˆλŠ” κ²ƒμœΌλ‘œ ν™•μΈλ˜λ―€λ‘œ 동적 라이브러리λ₯Ό μ΄μš©ν•˜μ—¬ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λŠ” 것이 ꢌμž₯λ˜μ–΄ 보인닀. 동적 라이브러리λ₯Ό μ΄μš©ν•˜λŠ” 경우 μœ„μ—μ„œ λ³Έ λŒ€λ‘œ DYLD_LIBRARY_PATH에 λŒ€ν•œ 섀정을 ν•˜λ„λ‘ Makefile에 κΌ­ λͺ…μ‹œν•˜λ„λ‘ ν•˜μž.
λ˜ν•œ μœ„ λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ„ μ΄μš©ν•˜κΈ° μœ„ν•΄μ„œ, ν”„λ‘œμ νŠΈμ˜ Makefileμ—μ„œ λΌμ΄λΈŒλŸ¬λ¦¬μ— λŒ€ν•œ Makefile을 λ¨Όμ € μˆ˜ν–‰ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€. 즉, ν”„λ‘œμ νŠΈμ˜ Makefileμ—μ„œ make λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜μ—¬ 라이브러리 μ»΄νŒŒμΌμ„ λ¨Όμ € ν•΄μ€˜μ•Όν•˜λŠ”λ° 이 λ•Œ -C μ˜΅μ…˜μ„ 톡해 μˆœν™˜ makeλ₯Ό μˆ˜ν–‰ν•  수 μžˆλ„λ‘ ν•΄μ£Όλ©΄ λœλ‹€. 기본적으둜 makeλŠ” μ‹€ν–‰λ˜λŠ” λͺ¨λ“  λͺ…λ Ήμ–΄λ₯Ό 터미널 μƒμ—μ„œ 좜λ ₯ν•΄μ£ΌλŠ”λ°, λΌμ΄λΈŒλŸ¬λ¦¬μ— λŒ€ν•œ λͺ…λ Ήμ–΄ μˆ˜ν–‰μ„ 터미널 μƒμ—μ„œ 보고 싢지 μ•Šλ‹€λ©΄ @λ₯Ό λΆ™μ—¬ μˆ˜ν–‰μ‹œν‚€λ©΄ λ˜λ―€λ‘œ 이λ₯Ό 적극 ν™œμš©ν•΄λ³΄μž. μ•„λž˜ ꡬ문을 Makefile에 λ„£μ–΄μ„œ 적절히 ν™œμš©ν•˜λ©΄ λ˜κ² λ‹€.
@make -C $dirname
μˆœν™˜ make에 λŒ€ν•œ λ‚΄μš©μ€ μ•„λž˜ 링크의 Documentλ₯Ό 톡해 더 μžμ„Ένžˆ μ•Œ 수 μžˆλ‹€.
make λͺ…λ Ήμ–΄μ˜ μ€‘μš” μ˜΅μ…˜λ“€μ€ μ•„λž˜ 링크λ₯Ό μ°Έκ³ ν•˜μž.

3) 라이브러리 ν•¨μˆ˜ (첨뢀 링크 μž‘μ„± 쀑)

man을 ν†΅ν•΄μ„œ "mlx.h"μ—μ„œ μ§€μ›ν•˜λŠ” ν•¨μˆ˜λ“€μ„ μ΄ν•΄ν•˜λŠ” 것이 μ–΄λ ΅λ‹€λ©΄, MiniLibX에 λŒ€ν•œ λ‚΄μš©λ“€κ³Ό ν•¨κ»˜ 라이브러리 ν•¨μˆ˜λ“€μ— λŒ€ν•΄ μž‘μ„±ν•΄λ‘μ—ˆλ‹€.

4) μ°Έκ³  사항

opengl을 μ΄μš©ν–ˆμ„ λ•Œ, hanλ‹˜μ˜ κ²½μš°μ—λŠ” illegal hardware instructionμ΄λΌλŠ” 였λ₯˜κ°€ λ°œμƒν–ˆμ—ˆκ³  youleeλ‹˜μ˜ κ²½μš°μ—λŠ” ν™”λ©΄ 깨짐 ν˜„μƒμ΄ λ°œμƒν–ˆμ—ˆλ‹€.
opengl을 μ΄μš©ν•˜κ³  μ‹Άλ‹€λ©΄ Mac OS X의 Cocoa APIκ°€ μžˆμ–΄μ•Όν•˜λ―€λ‘œ Mac OS Xμ™Έμ˜ ν™˜κ²½μ—μ„œλŠ” 이용이 λΆˆκ°€λŠ₯ν•˜λ‹€.
gcc의 -frameworkλΌλŠ” μ˜΅μ…˜μ€ Mac OS Xμ—μ„œλ§Œ μ΄μš©ν•  수 μžˆλŠ” μ˜΅μ…˜μ΄λ‹€.
intraμ—μ„œ μ œκ³΅ν•˜λŠ” "mlx.h"λ₯Ό μ΄μš©ν•  λ•Œ Mac OS Xκ°€ μ•„λ‹ˆλΌ linux ν™˜κ²½μ΄λΌλ©΄, μ•„λž˜ 링크에 μžˆλŠ” MiniLibXλ₯Ό μ΄μš©ν•˜λ„λ‘ ν•œλ‹€.
"mlx.h"λ₯Ό μ΄μš©ν•œ ν…ŒμŠ€νŠΈ μ½”λ“œλ“€μ€ μ•„λž˜ λ§ν¬μ—μ„œλ„ ν•™μŠ΅ν•  수 μžˆλ‹€.

4. Ray Tracingμ΄λž€ 무엇인가?

Ray Tracerλ₯Ό 직접 λ§Œλ“€μ–΄λ³΄λ©° RTλ₯Ό μ΄ν•΄ν•˜κ³  μ‹Άλ‹€λ©΄, κ·Έ 방법을 μ•„λž˜ 링크에 μž‘μ„±ν•΄λ‘μ—ˆλ‹€.

5. Ray Intersection

Ray Tracerλ₯Ό λ§Œλ“€λ‹€λ³΄λ©΄, Object의 Hit μ—¬λΆ€λ₯Ό ν†΅ν•΄μ„œ Hit Point 및 Colorλ₯Ό κΈ°λ‘ν•˜μ—¬ μ²˜λ¦¬ν•˜κ²Œ λœλ‹€. λ”°λΌμ„œ Object의 Hit μ—¬λΆ€λ₯Ό νŒλ³„ν•˜λŠ” 것이 κ°€μž₯ μ€‘μš”ν•˜λ‹€κ³  λ³Ό 수 μžˆλŠ”λ°, 각 물체 λ³„λ‘œ Hit νŒλ³„μ„ μœ„ν•œ μˆ˜μ‹μ΄ λ‹€λ₯΄κ³  Hit Pointλ₯Ό κ΅¬ν•˜λŠ” 방법이 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— 이에 λŒ€ν•΄μ„œ μ•Œμ•„λ³΄λ € ν•œλ‹€.

1) Sphere Intersection

Sphere의 HitλŠ” Ray Tracing in One Weekend의 자료λ₯Ό μ°Έκ³ ν•˜λ„λ‘ ν•œλ‹€.

2 ) Plane Intersection

μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 Plane μƒμ˜ ν•œ 점을 PP라고 ν•˜κ³ , 이 λ•Œμ˜ Normal을 nn이라고 ν•΄λ³΄μž. 그리고 Ray의 Origin을 ee라 ν•˜κ³  Ray의 Direction을 ΞΌ\mu라고 ν•œλ‹€λ©΄, Rayλ₯Ό e+ΞΌte + \mu t둜 ν‘œν˜„ν•  수 μžˆλ‹€. Rayκ°€ Plane을 Hit ν•œλ‹€λ©΄ e+ΞΌte + \mu tκ°€ 곧 Hit Pointκ°€ λœλ‹€.

Hit Determinant

Rayκ°€ Plane을 Hitν•˜λŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄μ„œ, Ray와 Plane이 ν‰ν–‰ν•˜λŠ”μ§€ ν™•μΈν•˜λŠ” 것이 μš°μ„ μ΄λ‹€. μ΄λŠ” Ray의 Directionκ³Ό Plane의 Normal이 μ„œλ‘œ 수직인 κ²½μš°μ— ν•΄λ‹Ήν•˜λ―€λ‘œ 두 Vectorλ₯Ό λ‚΄μ ν–ˆμ„ λ•Œ 0이라면 Hit Pointλ₯Ό ꡬ할 ν•„μš”κ°€ 없어진닀. λ”°λΌμ„œ ΞΌβ‹…n=ΜΈ0\mu \cdot n \not = 0 이라면 ΞΌβ‹…n\mu \cdot n을 λΆ„λͺ¨ (Denominator)둜써 μ΄μš©ν•  κ²ƒμ΄λ―€λ‘œ 잘 기둝해두면 λœλ‹€.

Hit Point

Plane의 방정식은 ax+by+cz+d=0ax + by + cz + d = 0인데, 이 λ•Œ 각 κ³„μˆ˜ (Coefficient) aa, bb, ccλŠ” Normal nn의 각 xx, yy, zz에 ν•΄λ‹Ήν•œλ‹€. λ˜ν•œ λ°©μ •μ‹μ—μ„œ μ‚¬μš©λ˜κ³  μžˆλŠ” λ―Έμ§€μˆ˜ xx, yy, zzλŠ” Plane μƒμ˜ 점을 μ˜λ―Έν•˜κΈ° λ•Œλ¬Έμ— 주어진 점 PP의 μ’Œν‘œλ₯Ό μ΄μš©ν•˜λ©΄λœλ‹€. λ”°λΌμ„œ Plane λ°©μ •μ‹μ˜ ddλŠ” λ‹€μŒκ³Ό 같이 μ •λ¦¬λœλ‹€.
nβ‹…P+d=0n \cdot P + d = 0 nβ‹…P=βˆ’dn \cdot P = -d d=βˆ’nβ‹…Pd = -n \cdot P
dd 에 λŒ€ν•΄ 정리가 λ˜μ—ˆκ³  Ray의 Hit Pointκ°€ e+ΞΌte + \mu t라면, ax+by+cz+d=0ax + by + cz + d = 0은 μ•„λž˜μ™€ 같이 tt에 λŒ€ν•΄μ„œ 정리할 수 μžˆλ‹€.
ax+by+cz+d=0ax + by + cz + d = 0 nβ‹…(e+ΞΌt)+d=0n \cdot (e + \mu t) + d = 0 nβ‹…(e+ΞΌt)=βˆ’dn \cdot (e + \mu t) = -d nβ‹…(e+ΞΌt)=nβ‹…pn \cdot (e + \mu t) = n \cdot p
nβ‹…e+nβ‹…ΞΌt=nβ‹…pn \cdot e + n \cdot \mu t = n \cdot p
t=nβ‹…pβˆ’nβ‹…enβ‹…ΞΌt = \frac{n \cdot p - n \cdot e}{n \cdot \mu}
이 λ•Œ tt 값을 κ²°μ • μ§“λŠ” nβ‹…ΞΌn \cdot \muλŠ” Hit Determinantμ—μ„œ κ΅¬ν–ˆλ˜ λΆ„λͺ¨μ— ν•΄λ‹Ήν•˜λ―€λ‘œ κ·ΈλŒ€λ‘œ μ΄μš©ν•˜λ©΄ λœλ‹€.

3) Square Intersection

Rayλ₯Ό e+ΞΌte + \mu t둜 ν‘œν˜„ν•œλ‹€κ³  ν•˜μž. Square은 2D Figure μ΄λ―€λ‘œ 기본적으둜 Plane에 κΈ°λ°˜ν•œλ‹€. λ”°λΌμ„œ Hit νŒλ³„μ— λŒ€ν•œ 1차적인 μˆ˜μ‹μ€ Plane의 Hit Determinantλ₯Ό λ”°λ₯Έλ‹€. Plane의 PPκ°€ 곧 Square의 μ€‘μ‹¬μœΌλ‘œ 주어진 점 PPκ°€ 되고, Plane의 nn을 곧 Square의 λ°©ν–₯을 λ‚˜νƒ€λ‚΄λŠ” nn으둜써 μ΄μš©ν•˜λ©΄ λœλ‹€.

Hit Determinant

1차적인 Hit νŒλ³„ μ—¬λΆ€κ°€ Planeκ³Ό λ™μΌν•˜κΈ° λ•Œλ¬Έμ— ΞΌβ‹…n=ΜΈ0\mu \cdot n \not = 0 인지 ν™•μΈν•œλ‹€. 그리고 Square와 λ™μΌν•œ Plane μƒμ˜ 점이 λ§žλ‹€λ©΄, Ray의 e+ΞΌte + \mu tμ—μ„œμ˜ ttλ₯Ό ꡬ할 수 있기 λ•Œλ¬Έμ— ttλ₯Ό μ΄μš©ν•˜μ—¬ Square의 크기 λ‚΄μ—λ§Œ μ‘΄μž¬ν•˜λŠ”μ§€ 확인해주면 λœλ‹€. 이 과정이 Hit Determinant이자 곧 Hit Pointλ₯Ό κ΅¬ν•˜λŠ” 과정이 λœλ‹€.

Hit Point

Square 크기 내에 μ‘΄μž¬ν•˜λŠ”μ§€μ— λŒ€ν•œ νŒλ³„μ„ μœ„ν•΄μ„  3D κ³΅κ°„μ—μ„œ Square의 ν•œ 변에 λŒ€ν•œ λͺ…ν™•ν•œ λ°©ν–₯만 μž‘μ•„λ‚΄λ©΄ μˆ˜ν›¨ν•˜κ²Œ 진행할 수 μžˆλ‹€. Square의 Side Vectorλ₯Ό μ°Ύμ•„λ‚΄κΈ° μœ„ν•΄μ„  Square의 nnκ³Ό μž„μ˜μ˜ Vector rrλ₯Ό μ™Έμ ν•˜μ—¬ μ°Ύμ•„λ‚Ό 수 μžˆλ‹€. λ‚΄ κ²½μš°μ—λŠ” Square의 nn의 yyκ°€ 1이라면 rr을 (1,0,0)(1, 0, 0)으둜 λ‘μ—ˆκ³ , 그렇지 μ•Šλ‹€λ©΄ rr을 (0,1,0)(0, 1, 0)으둜 두어 μ§„ν–‰ν•˜μ˜€λ‹€. 즉, Side VectorλŠ” nΓ—rn \times r이 λœλ‹€λŠ” 것이닀.
2D κ³΅κ°„μ—μ„œλŠ” Square의 κΈ°μšΈμ–΄μ§ 등을 λ³Ό ν•„μš”κ°€ μ—†κΈ° λ•Œλ¬Έμ— λ‹¨μˆœνžˆ 크기 비ꡐλ₯Ό 톡해 Square λ‚΄λΆ€μ˜ 점인지 확인할 수 μžˆμ§€λ§Œ, 3Dμ—μ„œλŠ” 좔가적인 μž‘μ—…μ΄ ν•„μš”ν•˜λ‹€. 3D μƒμ—μ„œ Square의 λ‚΄λΆ€μ˜ 점인지 λ‹¨μˆœνžˆ 크기λ₯Ό ν†΅ν•΄μ„œ λ³΄λ €ν•œλ‹€λ©΄ μ΄λŠ” μ •ν™•ν•œ ν˜•νƒœλ₯Ό μ•Œ 수 μ—†κΈ° λ•Œλ¬Έμ— 팽이처럼 원을 κ·Έλ¦¬λ©΄μ„œ λ„λŠ” ν˜•νƒœκ°€ λ˜μ–΄ μ •ν™•ν•œ νŒλ³„μ΄ λΆˆκ°€λŠ₯해진닀. λ”°λΌμ„œ ν•œ 변이 ν–₯ν•˜κ³  μžˆλŠ” 벑터에 λŒ€ν•΄μ„œ μ•Œμ•„λ‚΄μ•Ό μ •ν™•ν•œ Hit Determinantλ₯Ό μˆ˜ν–‰ν•  수 μžˆλ‹€.
μœ„ κ·Έλ¦Όμ—μ„œ λ³΄λŠ” κ²ƒμ²˜λŸΌ ΞΈ\thetaλ₯Ό μ°Ύμ•„λ‚΄κΈ° μœ„ν•΄μ„  내적을 μ΄μš©ν•˜λ©΄ λ˜λŠ”λ°, μ΄λŠ” Rayκ°€ Plane에 닿은 Hit Point e+ΞΌte + \mu t와 쀑심점 PPλ₯Ό λΊ€ Vector와 Side Vector rr을 λ‚΄μ ν•œ ν›„, 각 Vector의 크기둜 λ‚˜λˆ μ£Όλ©΄ λœλ‹€. cosΞΈ=((e+ΞΌt)βˆ’P)β‹…r∣∣(e+ΞΌt)βˆ’Pβˆ£βˆ£β‹…βˆ£βˆ£r∣∣cos\theta = \frac {((e + \mu t) - P) \cdot r} {||(e + \mu t) - P|| \cdot ||r||}μ΄λ―€λ‘œ Squareλ‚΄μ—μ„œμ˜ ν•œκ³„μΉ˜ mm을 λΉ„λ‘€ κ΄€κ³„λ‘œ μ°Ύμ•„λ‚Ό 수 μžˆλ‹€.
m=∣∣r∣∣cosΞΈm = \frac {||r||} {cos\theta} (단, cosθ≀22cos\theta \le \frac{\sqrt{2}}{2})
단, μ£Όμ˜ν•΄μ•Όν•  것이 μžˆλŠ”λ°, 이런 λΉ„λ‘€ 관계λ₯Ό μ΄μš©ν•˜κΈ° μœ„ν•΄μ„  ΞΈ\thetaκ°€ Ο€2\frac {\pi}{2}λ₯Ό λ„˜μ–΄μ„  μ•ˆ λœλ‹€. μœ„ κ·Έλ¦Όμ—μ„œ ?에 ν•΄λ‹Ήν•˜λŠ” 뢀뢄을 λͺ¨λ₯΄κΈ° λ•Œλ¬Έμ— λΉ„λ‘€ 관계λ₯Ό μ΄μš©ν•  수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€. λ”°λΌμ„œ cosΞΈ>22cos\theta > \frac {\sqrt2}{2}라면 이λ₯Ό 적절히 μ‘°μ •ν•΄μ€˜μ•Όν•œλ‹€. cosΞΈcos\theta에 ν•΄λ‹Ήν•˜λŠ” Radian을 acosacos으둜 μ°Ύμ•„λ‚Έ ν›„, Ο€2\frac{\pi}{2}μ—μ„œ λΉΌλ‚Έ ν›„ coscos을 μ·¨ν•˜λŠ” 것이닀. 이λ₯Ό 톡해 μ μ ˆν•œ mm을 μ°Ύμ•„λ‚Όμˆ˜ μžˆλ‹€.
m=∣∣r∣∣cos(Ο€2βˆ’acos(cosΞΈ))m = \frac {||r||} { cos(\frac{\pi}{2} - acos(cos\theta))} (단, cosΞΈ>22cos\theta \gt \frac {\sqrt{2}}{2})
mβ‰₯(e+ΞΌt)βˆ’Pm β‰₯ (e + \mu t) - P 라면 Square λ‚΄λΆ€μ˜ 점이라고 λ³Ό 수 있고, e+ΞΌte + \mu tκ°€ 곧 Hit Pointκ°€ λœλ‹€.

4) Cylinder Intersection with Cap

μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 Cylinder의 쀑심점을 PP라고 ν•˜κ³ , 이 λ•Œ Cylinderκ°€ ν–₯ν•˜κ³  μžˆλŠ” Direction을 oo라고 ν•΄λ³΄μž. 그리고 Ray의 Origin을 ee라 ν•˜κ³  Ray의 Direction을 ΞΌ\mu라고 ν•œλ‹€λ©΄, Rayλ₯Ό e+ΞΌte + \mu t둜 ν‘œν˜„ν•  수 μžˆλ‹€. Rayκ°€ Cylinder을 Hit ν•œλ‹€λ©΄ e+ΞΌte + \mu tκ°€ 곧 Hit Pointκ°€ λœλ‹€. Cylinder의 경우 μœ—λ©΄κ³Ό μ•„λž«λ©΄μ„ λκ³  μžˆλŠ” Cap이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” Infinite Cylinderκ°€ κΈ°λ³Έ ν˜•νƒœμ΄λ©°, Cap을 λ§Œλ“€κΈ° μœ„ν•΄μ„  λ³„λ„μ˜ Hit Determinantκ°€ μš”κ΅¬λœλ‹€. λ”°λΌμ„œ Finite Cylinder κ΅¬ν˜„ μ‹œμ—λŠ” μ˜†λ©΄μ— λŒ€ν•œ Hit Determinant κ·Ό μ΅œλŒ€ 2개, 그리고 μœ—λ©΄κ³Ό μ•„λž«λ©΄μ— λŒ€ν•œ Hit Determinant κ·Ό μ΅œλŒ€ 2개 쀑 ν•˜λ‚˜μ˜ Hit Pointλ₯Ό μ°Ύμ•„λ‚΄λŠ” 것이 ν•„μš”ν•˜λ‹€.

Hit Determinant on Rectangle

μ˜†λ©΄μ€ Cylinder의 곡식을 ν†΅ν•΄μ„œ tt값을 ν’€μ–΄λ‚Ό 수 μžˆλ‹€. Cylinder의 일반 곡식은 P+qoP + qoλΌλŠ” 좕을 κΈ°μ€€μœΌλ‘œ, ((e+ΞΌtβˆ’P)Γ—o)2βˆ’r2=0((e + \mu t - P) \times o)^2 - r^2 = 0 μ΄λ―€λ‘œ 이λ₯Ό at2+bt+c=0at^2 + bt + c = 0 꼴둜 ν’€μ–΄λ‚Ό 수 μžˆλ‹€. 이λ₯Ό ν’€μ–΄μ„œ 각 κ³„μˆ˜ aa, bb, cc값을 μ •λ¦¬ν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€. 이 λ•Œ Ξ”P\Delta PλŠ” eβˆ’Pe - P이닀.
a=(ΞΌΓ—o)2a = (\mu \times o)^2 b2=(ΞΌΓ—o)β‹…(Ξ”PΓ—o)\frac {b}{2} = (\mu \times o) \cdot (\Delta P \times o) c=(Ξ”PΓ—o)2βˆ’r2c = (\Delta P \times o)^2 - r^2
이λ₯Ό μ΄μš©ν•˜μ—¬ 짝수 νŒλ³„μ‹μ„ 톡해 근의 개수λ₯Ό κ΅¬ν•˜μ—¬, 근이 0개면 Hit Pointκ°€ μ‘΄μž¬ν•˜μ§€ μ•Šκ³ , 근이 1개면 1개의 Hit Point, 근이 2개면 2개의 Hit Pointκ°€ μ‘΄μž¬ν•˜λŠ” 것이 λœλ‹€. 근이 2개인 κ²½μš°μ—λŠ” 더 μž‘μ€ 값이 μœ λ§ν•œ Hit Pointκ°€ λœλ‹€.

Hit Determinant on Circle

Ray의 Direction ΞΌ\muκ³Ό Cylinder의 Direction ooλ₯Ό λ‚΄μ ν•˜μ—¬ κ·Έ 값이 0 이 λ‚˜μ˜¨ κ²½μš°μ—λŠ” Cylinder와 Rayκ°€ ν‰ν–‰ν•˜κΈ° λ•Œλ¬Έμ— μœ—λ©΄ ν˜Ήμ€ μ•„λž«λ©΄μ—μ„œλŠ” Hit Pointκ°€ 생기지 μ•ŠλŠ”λ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. Hit Pointκ°€ μƒκΈ°λŠ” κ²½μš°μ—λŠ” μœ—λ©΄κ³Ό μ•„λž«λ©΄μ˜ 각 ttκ°’ 비ꡐλ₯Ό ν†΅ν•΄μ„œ 더 μœ λ§ν•œ Hit Pointλ₯Ό κ²°μ •ν•˜κ²Œ λœλ‹€. 이 λ•Œ μœ—λ©΄μ˜ ttκ°’κ³Ό μ•„λž«λ©΄μ˜ tt값을 κ΅¬ν•˜λŠ” 방식은 같은데, 두 κ°’ 쀑 더 μž‘μ€ 값이 μœ λ§ν•œ Hit Pointκ°€ λœλ‹€.
μœ—λ©΄ ν˜Ήμ€ μ•„λž«λ©΄μ˜ tt값을 κ΅¬ν•˜λŠ” 방식은 λ™μΌν•˜λ―€λ‘œ μœ—λ©΄μ„ κΈ°μ€€μœΌλ‘œ 풀어보겠닀. Ray의 Originμ—μ„œ μœ—λ©΄μ˜ μ€‘μ‹¬μ κΉŒμ§€μ˜ Vectorλ₯Ό FF라고 ν–ˆμ„ λ•Œ, FF와 Cylinder의 Direction인 ooμ™€μ˜ 내적을 ν†΅ν•΄μ„œ ttλ₯Ό ꡬ할 수 μžˆλ‹€.
μœ„ 그림처럼 μ‹€μ œλ‘œ Rayκ°€ 닿은 지점은 λͺ¨λ₯΄κΈ° λ•Œλ¬Έμ— 이 점을 직접 μ΄μš©ν•˜μ—¬ ttλ₯Ό κ΅¬ν•˜λŠ” κ²ƒμ—λŠ” 어렀움이 μžˆμ§€λ§Œ, Rayκ°€ 닿은 지점과 ooλ₯Ό λ‚΄μ ν•œ 값은 ꡬ할 수 있기 λ•Œλ¬Έμ— 이 내적 값을 κΈ°μ€€ κ°’μœΌλ‘œ μ‚¬μš©ν•˜λ©΄ λœλ‹€. 이 내적 값을 cosΞΈcos \theta라고 ν–ˆμ„ λ•Œ 이λ₯Ό λΆ„λͺ¨ (Denominator)둜 μ΄μš©ν•œλ‹€. λΆ„μž (Numerator)둜 μ΄μš©ν•˜λŠ” 값은 Ray의 Originμ—μ„œλΆ€ν„° μ‹€μ œ μ’Œν‘œλ₯Ό μ•Œκ³  μžˆλŠ” μœ—λ©΄μ˜ μ€‘μ‹¬μ κΉŒμ§€ Vector인 FF와 Cylinder의 Direction인 ooμ™€μ˜ 내적 값인 cosΞΈβ€²cos \theta'이닀. cosΞΈβ€²cosΞΈ\frac {cos \theta'} {cos \theta}κ°€ λ°”λ‘œ ttκ°€ λ˜λ―€λ‘œ Hit Point e+ΞΌte + \mu tλ₯Ό ꡬ할 수 있게 λœλ‹€.

Hit Point

ꡬ해진 4개의 Hit Point μ€‘μ—μ„œ κ°€μž₯ μž‘μ€ ttλ₯Ό 가진 e+ΞΌte + \mu tκ°€ κ°€μž₯ μœ λ§ν•œ Hit Pointκ°€ λœλ‹€. 이 λ•Œ, μœ—λ©΄κ³Ό μ•„λž«λ©΄μ˜ 평행성은 κ²€μ¦ν–ˆλŠ”λ°, μ˜†λ©΄μ˜ 평행성은 κ²€μ¦ν•˜μ§€ μ•Šμ•˜λ‹€. μ΄λŠ” Finite Cylinderλ₯Ό κ·Έλ¦¬λ €λŠ” κ²½μš°μ—λ§Œ 검사λ₯Ό ν•΄μ£Όλ©΄ λœλ‹€. μœ—λ©΄μ˜ 쀑심점 TCTC은 P+h2β‹…oP + \frac{h}{2} \cdot o 이고, μ•„λž«λ©΄μ˜ 쀑심점 BCBC은 Pβˆ’h2β‹…oP - \frac{h}{2} \cdot o이닀. TCβˆ’(e+ΞΌt)β‹…o=0TC - (e + \mu t) \cdot o = 0μ΄κ±°λ‚˜ BCβˆ’(e+ΞΌt)β‹…o=0BC - (e + \mu t) \cdot o = 0이라면 Finite Cylinder의 μ˜†λ©΄κ³Ό Rayκ°€ ν‰ν–‰ν•˜λ―€λ‘œ μ˜†λ©΄μ— λŒ€ν•œ ttλŠ” μœ λ§ν•˜μ§€ μ•Šκ²Œ λœλ‹€.

5) Triangle Intersection

Rayλ₯Ό e+ΞΌte + \mu t둜 ν‘œν˜„ν•œλ‹€κ³  ν•˜μž. Triangle은 2D Figure μ΄λ―€λ‘œ 기본적으둜 Plane에 κΈ°λ°˜ν•œλ‹€. λ”°λΌμ„œ Hit νŒλ³„μ— λŒ€ν•œ 1차적인 μˆ˜μ‹μ€ Plane의 Hit Determinantλ₯Ό λ”°λ₯Έλ‹€. Plane의 PPκ°€ 곧 Triangle의 ν•œ 점 PPκ°€ 되고, Plane의 nn을 곧 Triangle의 λ°©ν–₯을 λ‚˜νƒ€λ‚΄λŠ” nn으둜써 μ΄μš©ν•˜λ©΄ λœλ‹€.
Triangle의 PPλŠ” 주어진 점 P1P1, P2P2, P3P3 쀑 P1P1으둜 μ΄μš©ν•˜λ©΄ 되고, Triangle의 nn은 외적을 ν†΅ν•΄μ„œ μ°Ύμ•„λ‚Ό 수 μžˆλ‹€.
n=(P2βˆ’P1)Γ—(P3βˆ’P1)n = (P2 - P1) \times (P3 - P1)

Hit Determinant

1차적인 Hit νŒλ³„ μ—¬λΆ€κ°€ Planeκ³Ό λ™μΌν•˜κΈ° λ•Œλ¬Έμ— ΞΌβ‹…n=ΜΈ0\mu \cdot n \not = 0 인지 ν™•μΈν•œλ‹€. 그리고 Triangle와 λ™μΌν•œ Plane μƒμ˜ 점이 λ§žλ‹€λ©΄, Ray의 e+ΞΌte + \mu tμ—μ„œμ˜ ttλ₯Ό ꡬ할 수 있기 λ•Œλ¬Έμ— ttλ₯Ό μ΄μš©ν•˜μ—¬ Triangle의 크기 λ‚΄μ—λ§Œ μ‘΄μž¬ν•˜λŠ”μ§€ 확인해주면 λœλ‹€. 이 과정이 Hit Determinant이자 곧 Hit Pointλ₯Ό κ΅¬ν•˜λŠ” 과정이 λœλ‹€.

Hit Point

Triangle λ‚΄λΆ€μ˜ 점인지 ν™•μΈν•˜λŠ” 방법은 그리 어렡지 μ•Šλ‹€. P1P1μ—μ„œ e+ΞΌte +\mu tκΉŒμ§€μ˜ Vectorλ₯Ό ww라고 ν•˜κ³ , P1P1μ—μ„œ P2P2λ₯Ό uu, P1P1μ—μ„œ P3P3λ₯Ό vv라고 ν•˜μž. wwλŠ” uu와 vvλ₯Ό ν†΅ν•΄μ„œ w=xu+yvw = xu + yv둜 ν‘œν˜„ν•  수 있게 λœλ‹€.
wwλ₯Ό κ΅¬μ„±ν•˜λŠ” xx, yyκ°€ 0≀x,y≀10 ≀ x, y ≀ 1μ΄λ©΄μ„œ λ™μ‹œμ— x+y≀1x +y ≀ 1λ₯Ό λ§Œμ‘±ν•˜κ²Œ 되면 e+ΞΌte + \mu tλŠ” Triangle λ‚΄λΆ€μ˜ 점이 λœλ‹€. xx, yyλŠ” uu와 μˆ˜μ§μ„ μ΄λ£¨λŠ” upup, vv와 μˆ˜μ§μ„ μ΄λ£¨λŠ” vpvpλ₯Ό ν†΅ν•΄μ„œ ꡬ할 수 μžˆλ‹€. upupλŠ” nΓ—un \times u이고 vpvpλŠ” nΓ—vn \times v둜 ꡬ할 수 μžˆλ‹€.
upup와 vpvp에 λŒ€ν•΄μ„œ μ •μ˜ν–ˆμœΌλ―€λ‘œ w=xu+yvw = xu + yv의 양변에 upupλ₯Ό κ³±ν•˜μ—¬ μ •λ¦¬ν•΄λ³΄μž.
wβ‹…up=xuβ‹…up+yvβ‹…upw \cdot up = xu \cdot up + yv \cdot up wβ‹…up=yvβ‹…upw \cdot up = yv \cdot up (uu와 upupλŠ” μˆ˜μ§μ΄λ―€λ‘œ 내적 μ‹œ 0이 λœλ‹€.) y=wβ‹…upvβ‹…upy = \frac {w \cdot up}{v \cdot up}
upup와 vpvp에 λŒ€ν•΄μ„œ μ •μ˜ν–ˆμœΌλ―€λ‘œ w=xu+yvw = xu + yv의 양변에 vpvpλ₯Ό κ³±ν•˜μ—¬ μ •λ¦¬ν•΄λ³΄μž.
wβ‹…vp=xuβ‹…vp+yvβ‹…vpw \cdot vp = xu \cdot vp + yv \cdot vp wβ‹…vp=xuβ‹…vpw \cdot vp = xu \cdot vp (vv와 vpvpλŠ” μˆ˜μ§μ΄λ―€λ‘œ 내적 μ‹œ 0이 λœλ‹€.) x=wβ‹…vpuβ‹…vpx = \frac {w \cdot vp}{u \cdot vp}
이와 같이 xx, yyλ₯Ό κ΅¬ν–ˆμœΌλ―€λ‘œ 0≀x,y≀10 ≀ x, y ≀ 1 이고 x+y≀1x + y ≀ 1을 λ§Œμ‘±ν•˜κ²Œ 되면 e+ΞΌte+ \mu tκ°€ 곧 Hit Pointκ°€ λœλ‹€.
xx, yyλ₯Ό ꡬ할 λ•Œ 쑰금 더 μ΅œμ ν™”ν•  수 μžˆλ‹€. vpvpλŠ” nnκ³Ό vvλ₯Ό μ™Έμ ν•˜μ—¬ λ§Œλ“  Vectorμ΄λ―€λ‘œ uβ‹…vp=uβ‹…(nΓ—v)u \cdot vp = u \cdot (n \times v)둜 ν‘œν˜„ν•  수 μžˆλŠ”λ° Vector의 외적 μ„±μ§ˆ 쀑에 aβ‹…(bΓ—c)=(aΓ—b)β‹…ca \cdot (b \times c) = (a \times b) \cdot c 덕뢄에 uβ‹…(nΓ—v)=vβ‹…(uΓ—n)u \cdot (n \times v) = v \cdot (u \times n)이 λœλ‹€. Vector의 외적은 κ΅ν™˜ 법칙이 μ„±λ¦½ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ vβ‹…(uΓ—n)=vβ‹…(βˆ’nΓ—u)=βˆ’v(nΓ—u)=βˆ’vβ‹…upv \cdot (u \times n) = v \cdot (-n \times u) = -v (n \times u) = -v \cdot up κ°€ λœλ‹€. λ”°λΌμ„œ xx, yy의 곡톡 λΆ„λͺ¨λ‘œμ¨ vβ‹…upv \cdot upλ₯Ό 계산해두면 쑰금 더 μˆ˜ν›¨ν•˜κ²Œ 이λ₯Ό 계산할 수 있게 λœλ‹€.

6) Cone Intersection with Cap

μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 Cone의 λ°‘λ©΄μ˜ 쀑심점을 PP라 ν•˜κ³ , 이 λ•Œ Cone이 ν–₯ν•˜κ³  μžˆλŠ” Direction을 oo라고 ν•΄λ³΄μž. 그리고 Ray의 Origin을 eeλΌν•˜κ³  Ray의 Direction을 ΞΌ\mu라고 ν•œλ‹€λ©΄, Rayλ₯Ό e+ΞΌte + \mu t둜 ν‘œν˜„ν•  수 μžˆλ‹€. Rayκ°€ Cone을 Hit ν•œλ‹€λ©΄ e+ΞΌte + \mu tκ°€ 곧 Hit Pointκ°€ λœλ‹€. Cone의 κ²½μš°μ—λŠ” 밑면이 λ³„λ„λ‘œ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” λͺ¨λž˜ μ‹œκ³„ ν˜•νƒœμΈ Infinite Cone이 κΈ°λ³Έ ν˜•νƒœμ΄λ©°, 밑면을 λ§Œλ“€κΈ° μœ„ν•΄μ„  λ³„λ„μ˜ Hit Determinantκ°€ μš”κ΅¬λœλ‹€. λ”°λΌμ„œ Finite Cone κ΅¬ν˜„ μ‹œμ—λŠ” μ˜†λ©΄μ— λŒ€ν•œ Hit Determinant κ·Ό μ΅œλŒ€ 2개, 그리고 밑면에 λŒ€ν•œ Hit Determinant κ·Ό μ΅œλŒ€ 1개 쀑 κ°€μž₯ μœ λ§ν•œ ν•˜λ‚˜μ˜ Hit Pointλ₯Ό μ°Ύμ•„λ‚΄λŠ” 것이 ν•„μš”ν•˜λ‹€.

Hit Determinant on Circular Sector

μ˜†λ©΄μ€ Cone의 곡식을 ν†΅ν•΄μ„œ tt값을 ν’€μ–΄λ‚Ό 수 μžˆλ‹€. Cone의 일반 곡식은 P+qoP + qoλΌλŠ” 좕을 κΈ°μ€€μœΌλ‘œ, cos2Ξ±β‹…((e+ΞΌt)βˆ’PΓ—o)2βˆ’sin2Ξ±β‹…(oβ‹…((e+ΞΌt)βˆ’P))2=0cos^2\alpha \cdot ((e + \mu t) - P \times o)^2 - sin^2\alpha \cdot (o \cdot ((e + \mu t) - P))^2 = 0이닀. λ”°λΌμ„œ 주어진 식을 μœ„ κ·Έλ¦Όμ—μ„œ μ œμ‹œν•œ 값듀을 적절히 ν™œμš©ν•˜μ—¬ at2+bt+c=0at^2 + bt + c = 0꼴둜 ν’€μ–΄λ‚Ό 수 μžˆλ‹€. 이λ₯Ό ν’€μ–΄μ„œ 각 κ³„μˆ˜ aa, bb, cc값을 μ •λ¦¬ν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.
a=cos2Ξ±β‹…(ΞΌβˆ’c2)2βˆ’sin2Ξ±β‹…(c1β‹…c1)a = cos^2\alpha \cdot (\mu - c2)^2 - sin^2 \alpha \cdot(c1 \cdot c1) b2=cos2Ξ±β‹…(ΞΌβˆ’c2)β‹…(Ξ”Pβˆ’c4)βˆ’sin2Ξ±β‹…(c1β‹…c3)\frac {b}{2} = cos^2 \alpha \cdot (\mu - c2) \cdot (\Delta P - c4) - sin^2 \alpha \cdot (c1 \cdot c3) c=cos2Ξ±β‹…(Ξ”Pβˆ’c4)2βˆ’sin2Ξ±β‹…(c3β‹…c3)c = cos^2 \alpha \cdot (\Delta P -c4)^2 - sin^2 \alpha \cdot (c3 \cdot c3)
이λ₯Ό μ΄μš©ν•˜μ—¬ 짝수 νŒλ³„μ‹μ„ 톡해 근의 개수λ₯Ό κ΅¬ν•˜μ—¬, 근이 0개면 Hit Pointκ°€ μ‘΄μž¬ν•˜μ§€ μ•Šκ³ , 근이 1개면 1개의 Hit Point, 근이 2개면 2개의 Hit Pointκ°€ μ‘΄μž¬ν•˜λŠ” 것이 λœλ‹€. 근이 2개인 κ²½μš°μ—λŠ” 더 μœ λ§ν•œ Hit Pointλ₯Ό 골라내야 ν•œλ‹€.

Hit Determinant on Cap

Cap의 Hit DeterminantλŠ” Cylinder의 방식과 λ™μΌν•˜λ‹€. λ‹€λ§Œ Cone의 κ²½μš°μ—λŠ” λ°‘λ©΄λ§Œ μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— 1회만 μˆ˜ν–‰ν•˜λ©΄ λœλ‹€. λΆ„λͺ¨ (Denominator)λŠ” ΞΌβ‹…o\mu \cdot oκ°€ λ˜λŠ”λ° 이 값이 0인 κ²½μš°μ—λŠ” λ°‘λ©΄κ³Ό ν‰ν–‰ν•˜κΈ° λ•Œλ¬Έμ— Ray와 Hit λ˜μ§€ μ•Šμ•„ μœ λ§ν•˜μ§€ μ•Šμ€ ttκ°€ λœλ‹€. ΞΌβ‹…o=ΜΈ0 \mu \cdot o \not = 0이라면 이 λ•Œμ˜ ttλŠ” Cylinder의 Capμ—μ„œ ttλ₯Ό κ΅¬ν–ˆλ˜ 것과 λ§ˆμ°¬κ°€μ§€λ‘œ (Pβˆ’e)β‹…oΞΌβ‹…o\frac {(P - e) \cdot o} {\mu \cdot o}κ°€ tt값이 λ˜μ–΄, 이λ₯Ό μ΄μš©ν•œ e+ΞΌte + \mu tκ°€ Hit Point의 후보 쀑 ν•˜λ‚˜κ°€ λœλ‹€.

Hit Point

μ˜†λ©΄μ˜ 후보 2개, λ°‘λ©΄μ˜ 후보 1개 쀑 κ°€μž₯ μœ λ§ν•œ ttλ₯Ό μ°Ύμ•„λ‚΄λ©΄, 이 값을 μ΄μš©ν•œ e+ΞΌte + \mu tκ°€ Hit Pointκ°€ λœλ‹€. μ˜†λ©΄ ν›„λ³΄μ˜ μœ νš¨μ„±μ„ κ²€μ‚¬ν•˜λŠ” 방식과 λ°‘λ©΄ ν›„λ³΄μ˜ μœ νš¨μ„±μ„ κ²€μ‚¬ν•˜λŠ” 방식이 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— λ‚˜λˆ μ„œ ν™•μΈν•΄λ³΄μž.
μ˜†λ©΄μ˜ 경우 후보λ₯Ό 각각 t1t1, t2t2라고 ν•΄λ³΄μž. t1t1의 κ²½μš°μ—λŠ” t1β‰₯0t1 β‰₯ 0 μ΄λ©΄μ„œ oβ‹…(Ξ”P+(ΞΌβ‹…t1))>0o \cdot (\Delta P + (\mu \cdot t1)) > 0이라면 t1t1은 μœ νš¨ν•œ tt이며 μœ λ§μ„±μ„ λ”°μ§ˆ 수 있게 λœλ‹€. t2t2의 κ²½μš°λ„ t1t1의 방식과 λ™μΌν•˜κ²Œ μœ νš¨μ„± 검사λ₯Ό ν•˜λ©΄λœλ‹€. t2β‰₯0t2 β‰₯ 0 μ΄λ©΄μ„œ oβ‹…(Ξ”P+(ΞΌβ‹…t2))>0o \cdot (\Delta P + (\mu \cdot t2)) > 0이라면 t2t2λŠ” μœ νš¨ν•œ tt이며 μœ λ§μ„±μ„ λ”°μ§ˆ 수 있게 λœλ‹€.
λ°‘λ©΄μ˜ 후보λ₯Ό t3t3라고 ν•΄λ³΄μž. t3t3λŠ” t3β‰₯0t3 β‰₯ 0μ΄λ©΄μ„œ (ΞΌβ‹…t3+Ξ”P)2≀r2(\mu \cdot t3 + \Delta P)^2 ≀ r^2이면 μœ νš¨ν•œ tt이며 μœ λ§μ„±μ„ λ”°μ§ˆ 수 있게 λœλ‹€.
μ΄λ ‡κ²Œ 찾은 t1t1, t2t2, t3t3 3개의 후보듀 μ€‘μ—μ„œ 검증을 마친 μœ νš¨ν•œ tt값듀에 ν•œν•˜μ—¬ κ°€μž₯ μž‘μ€ 값이 κ°€μž₯ μœ λ§ν•œ ttκ°€ λœλ‹€. 이 λ•Œ Hit PointλŠ” e+ΞΌte + \mu tκ°€ μ•„λ‹ˆλΌ κ°€μž₯ μœ λ§ν•œ tt에 λŒ€ν•΄ Scale을 ν•΄μ€˜μ•Ό ν•œλ‹€. κ°€μž₯ μœ λ§ν•œ ttλ₯Ό ∣∣μ∣∣||\mu||둜 λ‚˜λˆˆ 값이 곧 Hit Pointλ₯Ό κ³„μ‚°ν•˜λŠ”λ° μ‚¬μš©λ˜λŠ” ttκ°€ λœλ‹€.

6. Bitmap Image File Format

1) BMP

Image File Format Image File Format은 Imageλ₯Ό λ””μ§€ν„Έλ‘œ κ΅¬μ„±ν•˜κ³  μ €μž₯ν•˜λŠ” ν‘œμ€€ν™”λœ 방법을 μ˜λ―Έν•˜λŠ”λ°, 이 ν˜•μ‹μ— λ”°λΌμ„œ μ‹€μ œ 데이터λ₯Ό μ••μΆ•λ˜μ§€ μ•Šμ€ ν˜•μ‹, μ••μΆ•λœ ν˜•μ‹, 벑터 ν˜•μ‹ λ“±μœΌλ‘œ μ €μž₯ν•  수 μžˆλ‹€. ν˜•μ‹μ— 맞게 갖좰진 Image νŒŒμΌμ€ 컴퓨터 λ””μŠ€ν”Œλ ˆμ΄ ν˜Ήμ€ ν”„λ¦°ν„°μ—μ„œ 파일 λ‚΄μ˜ 데이터λ₯Ό Rasteringν•˜μ—¬ μ‚¬μš©ν•˜κ²Œ λœλ‹€. Rastering을 ν•˜λŠ” 것을 Rasterization이라 ν•˜λŠ”λ°, μ΄λŠ” Image의 데이터λ₯Ό Pixel Grid둜 λ³€ν™˜ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€. 각 Pixel은 색상을 지정할 수 μžˆλ„λ‘ μ—¬λŸ¬ λΉ„νŠΈλ“€μ„ κ°–κ³  μžˆλŠ”λ°, νŠΉμ • μž₯μΉ˜μ—μ„œ Rasterization을 ν•˜κ²Œ 되면 μž₯치 λ‚΄μ˜ bits_per_pixel을 읽어 Pixel을 μ˜¬λ°”λ₯΄κ²Œ μ²˜λ¦¬ν•˜κ²Œ λœλ‹€.
Bitmap으둜 이뀄진 Image File Format을 곧 BMP라고 λΆ€λ₯Έλ‹€. μ••μΆ•ν•˜μ§€ μ•Šμ€ μ±„λ‘œ Image의 RowΓ—ColRow \times Col 만큼의 Pixel 정보λ₯Ό λͺ¨λ‘ μ €μž₯ν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμ— Vector λ°©μ‹μ˜ Image ν˜Ήμ€ Text에 λΉ„ν•΄ μš©λŸ‰μ΄ κ½€ 크고 그만큼 처리 속도가 느린 νŽΈμ΄λ‹€. 이λ₯Ό κ°œμ„ ν•˜κΈ° μœ„ν•΄ GIF, JPEG, PNGλ“± λ‹€μ–‘ν•œ Image File Format이 κ°œλ°œλ˜μ—ˆκ³ , 이와 λ™μ‹œμ— BMP μžμ²΄λ„ RLE μ••μΆ• 방식을 μ§€μ›ν•˜λŠ” μͺ½μœΌλ‘œ λ°œμ „ν–ˆλ‹€. BMP의 ν™•μž₯μžλŠ” .BMP이며 λ‹€λ₯Έ Image File Format을 μ΄μš©ν•˜λŠ” 파일처럼 λ””μ§€ν„Έλ‘œ 된 Imageλ₯Ό λ‚˜νƒ€λ‚΄κΈ° μœ„ν•΄ μ΄μš©λœλ‹€. BMPλŠ” PNG와 λ§ˆμ°¬κ°€μ§€λ‘œ 16777216κ°€μ§€μ˜ 색을 ν‘œν˜„ν•  수 μžˆλ„λ‘ μ§€μ›ν•œλ‹€. μƒλŒ€μ μœΌλ‘œ νŠΉν—ˆμ—μ„œ 자유둭기 λ•Œλ¬Έμ— λ§Žμ€ μš΄μ˜μ²΄μ œμ—μ„œ μ œκ³΅ν•˜λŠ” Image Reader듀이 κ³΅ν†΅μ μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆλŠ” Image File Format이 λ˜μ—ˆλ‹€.

2) 데이터 블둝

BMP νŒŒμΌμ€ λ‚΄λΆ€μ μœΌλ‘œ BMP 헀더, DIB 헀더, Bitmap λ°μ΄ν„°λ‘œ κ΅¬λΆ„λœλ‹€. DIB ν—€λ”μ˜ κ²½μš°μ—λŠ” ν˜Έν™˜μ„± λ•Œλ¬Έμ— 였래된 DIB 헀더λ₯Ό μ΄μš©ν•˜λŠ” 것이 μΌλ°˜μ μ΄μ—ˆμ§€λ§Œ, ν˜„μž¬λŠ” BITMAPINFOHEADER ν˜Ήμ€ BITMAPCOREHEADERλ₯Ό 주둜 μ΄μš©ν•œλ‹€. BITMAPINFOHEADERλŠ” 크기가 40 λ°”μ΄νŠΈμ΄κ³ , BITMAPCOREHEADERλŠ” 크기가 12 λ°”μ΄νŠΈμ΄λ‹€. μ±„μš°κ²Œ λ˜λŠ” 값듀에 λŒ€ν•΄μ„œ, λ¬Έμžμ—΄μ„ μ œμ™Έν•œ λͺ¨λ“  값듀은 μ‚¬μš©ν•˜κ³  μžˆλŠ” Endian에 λ§žμΆ°μ„œ 기둝해야 ν•œλ‹€.
Endian (Endianness) λ©”λͺ¨λ¦¬μ²˜λŸΌ 1차원 곡간이 μ£Όμ–΄μ‘Œμ„ λ•Œ, μš”μ†Œλ“€μ„ μ—°μ†μ μœΌλ‘œ λ°°μΉ˜ν•˜λŠ” 방법을 Endian이라고 ν•œλ‹€. 이 λ•Œ λ°”μ΄νŠΈ λ‹¨μœ„λ‘œ λ°°μΉ˜ν•˜λŠ” 것을 Byte Order라고 ν•œλ‹€. Byte Order둜 λ©”λͺ¨λ¦¬ 상에 μš”μ†Œλ“€μ„ 두렀고 ν•  λ•Œ, 큰 λ‹¨μœ„κ°€ λ¨Όμ € ν‘œν˜„λ˜λŠ” 것이 Big Endian이고 μž‘μ€ λ‹¨μœ„κ°€ λ¨Όμ € ν‘œν˜„λ˜λŠ” 것이 Little Endian이 λœλ‹€. λ‘˜ λ‹€ 지원을 ν•˜κ±°λ‚˜ λ‘˜ λ‹€ μ§€μ›ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ—λŠ” Middle Endian이라 λΆ€λ₯Έλ‹€. 일반적으둜 μ‚¬λžŒλ“€μ΄ 숫자λ₯Ό ν‘œκΈ°ν•  λ•Œ μ‚¬μš©ν•˜λŠ” 방법이 Big Endian이닀. Byte Order에 λ”°λ₯Έ Big Endianκ³Ό Little Endian의 예λ₯Ό μ‚΄νŽ΄λ³΄μž. Big Endian 0x1234 β†’ 12 34 0x12345678 β†’ 12 34 56 78 Little Endian 0x1234 β†’ 34 12 0x12345678 β†’ 78 56 34 12
β€’
BMP 헀더 β†’ BMP νŒŒμΌμ— λŒ€ν•œ μ „λ°˜μ μΈ 정보λ₯Ό λ‹΄κ³  μžˆλ‹€.
β€’
DIB 헀더 β†’ Bitmap에 λŒ€ν•œ μžμ„Έν•œ 정보λ₯Ό λ‹΄κ³  μžˆλ‹€.
β€’
Bitmap 데이터 β†’ Image에 λŒ€ν•œ μ‹€μ œ 데이터λ₯Ό λ‹΄κ³  μžˆλ‹€.
Search
BMP 헀더
Offset
Size
Description
2
BMP 파일 식별을 μœ„ν•œ Magic Numberλ₯Ό κΈ°λ‘ν•œλ‹€. BMP νŒŒμΌμ„ μΈμ‹ν•˜λŠ” 2개의 μˆ˜λŠ” B와 M을 μ˜λ―Έν•˜λŠ” 0x42와 0x4Dλ₯Ό μ΄μš©ν•˜κ²Œ λœλ‹€.
4
BMP 파일의 크기λ₯Ό Byte둜 λͺ…μ‹œν•œλ‹€.
2
μ‘μš© ν”„λ‘œκ·Έλž¨ ν˜Ήμ€ ν”Œλž«νΌμ— 따라 μ‚¬μš©λ˜λŠ” 값이 λ‹¬λΌμ§€λŠ”λ°, λŒ€μ²΄μ μœΌλ‘œ μ‚¬μš©λ˜μ§€ μ•ŠλŠ”λ‹€.
2
μ‘μš© ν”„λ‘œκ·Έλž¨ ν˜Ήμ€ ν”Œλž«νΌμ— 따라 μ‚¬μš©λ˜λŠ” 값이 λ‹¬λΌμ§€λŠ”λ°, λŒ€μ²΄μ μœΌλ‘œ μ‚¬μš©λ˜μ§€ μ•ŠλŠ”λ‹€.
4
Bitmap λ°μ΄ν„°μ˜ μ‹œμž‘ Offset을 μ˜λ―Έν•œλ‹€.
COUNT5
Search
Offset
Size
Description
4
DIB ν—€λ”μ˜ 크기λ₯Ό μ˜λ―Έν•œλ‹€.
4
Bitmap의 κ°€λ‘œ Pixel 수λ₯Ό Signed Integer둜 λͺ…μ‹œν•œλ‹€.
4
Bitmap의 μ„Έλ‘œ Pixel 수λ₯Ό Signed Integer둜 λͺ…μ‹œν•œλ‹€.
2
μ‚¬μš©ν•˜λŠ” Color Pane의 수λ₯Ό μ˜λ―Έν•˜κ³  일반적으둜 1둜 μ„€μ •ν•œλ‹€.
2
bits_per_pixel (Depth of the Image)λ₯Ό μ˜λ―Έν•œλ‹€. 1, 4, 8, 16, 24, 32 쀑 ν•˜λ‚˜μ˜ κ°’μœΌλ‘œ μ΄μš©ν•˜λŠ” 것이 μΌλ°˜μ μ΄λ‹€.
4
μ••μΆ• 방식을 λͺ…μ‹œν•œ 값이닀. <κ°’> <μ‹λ³„μž> <μ••μΆ• 방식> 0 BI_RGB μ••μΆ• μ—†μŒ 1 BI_RLE8 RLE 8-bit/pixel 2 BI_RLE4 RLE 4-bit/pixel 3 BI_FITFIELDS Huffman1D 4 BI_JPEG RLE-24 5 BI_PNG 6 BI_ALPHABITFILEDS RGBA bit field masks 11 BI_CMYK μ••μΆ• μ—†μŒ 12 BI_CMYKRLE8 RLE-8 13 BI_CMYKRLE4 RLE-4
4
μ••μΆ•ν•˜μ§€ μ•Šμ€ Bitmap λ°μ΄ν„°μ˜ 크기λ₯Ό μ˜λ―Έν•œλ‹€. 파일의 ν¬κΈ°μ™€λŠ” λ‹€λ₯΄λ‹€. (μ••μΆ• 방식 0인 BI_RGBλ₯Ό μ΄μš©ν•˜λŠ” κ²½μš°μ—λŠ” 이 ν•„λ“œμ˜ 값이 0이 될 수 μžˆλ‹€.)
4
Image의 κ°€λ‘œ 해상도λ₯Ό Pixels/Meter둜 μ€€ 값이닀. μΌλ°˜μ μœΌλ‘œλŠ” Dots Per InchλΌλŠ” DPIλ₯Ό 계산 ν•œ λ’€, Inch Per Meter 값인 39.3701λ₯Ό κ³±ν•˜λŠ” μ‹μœΌλ‘œ κ³„μ‚°ν•œλ‹€. DPI 계산 μ˜ˆμ œλŠ” λ‹€μŒκ³Ό κ°™λ‹€. 1200Γ—18001200 \times 1800 Pixel (Dot)의 Imageκ°€ μ‘΄μž¬ν•˜κ³ , 이λ₯Ό 4Γ—64 \times 6 (λ‹¨μœ„λŠ” Inch)의 크기둜 λ‚˜νƒ€λ‚΄λ € ν•œλ‹€. ImageλŠ” 12001200의 Pixel 높이와 18001800의 Pixel λ„ˆλΉ„λΌκ³  ν•œλ‹€λ©΄, μ΄λŠ” 곧 4 Inch의 높이와 6 Inch의 λ„ˆλΉ„λ₯Ό μ˜λ―Έν•œλ‹€. λ”°λΌμ„œ 이 λ•Œ ImageλŠ” 300 DPIλ₯Ό κ°–λŠ”λ‹€. 1800dots6inch=300dots1inch=300DPI\frac {1800 dots} {6 inch} = \frac {300 dots} {1 inch} = 300 DPI 이 λ•Œμ˜ Pixels/MeterλŠ” 300Γ—39.3701300 \times 39.3701이 λœλ‹€.
4
Image의 μ„Έλ‘œ 해상도λ₯Ό Pixels/Meter둜 μ€€ 값이닀. μΌλ°˜μ μœΌλ‘œλŠ” Dots Per InchλΌλŠ” DPIλ₯Ό 계산 ν•œ λ’€, Inch Per Meter 값인 39.3701λ₯Ό κ³±ν•˜λŠ” μ‹μœΌλ‘œ κ³„μ‚°ν•œλ‹€. DPI 계산 μ˜ˆμ œλŠ” λ‹€μŒκ³Ό κ°™λ‹€. 1200Γ—18001200 \times 1800 Pixel (Dot)의 Imageκ°€ μ‘΄μž¬ν•˜κ³ , 이λ₯Ό 4Γ—64 \times 6 (λ‹¨μœ„λŠ” Inch)의 크기둜 λ‚˜νƒ€λ‚΄λ € ν•œλ‹€. ImageλŠ” 12001200의 Pixel 높이와 18001800의 Pixel λ„ˆλΉ„λΌκ³  ν•œλ‹€λ©΄, μ΄λŠ” 곧 4 Inch의 높이와 6 Inch의 λ„ˆλΉ„λ₯Ό μ˜λ―Έν•œλ‹€. λ”°λΌμ„œ 이 λ•Œ ImageλŠ” 300 DPIλ₯Ό κ°–λŠ”λ‹€. 1800dots6inch=300dots1inch=300DPI\frac {1800 dots} {6 inch} = \frac {300 dots} {1 inch} = 300 DPI 이 λ•Œμ˜ Pixels/MeterλŠ” 300Γ—39.3701300 \times 39.3701이 λœλ‹€.
4
νŒ”λ ˆνŠΈκ°€ κ°–κ³  μžˆλŠ” μƒ‰μ˜ 수둜 2n2^n ν˜•νƒœμ˜ 값을 κ°–λŠ”λ‹€.
4
μ€‘μš”ν•œ μƒ‰μ˜ 수λ₯Ό λͺ…μ‹œν•œλ‹€. λͺ¨λ“  색이 μ€‘μš”ν•œ κ²½μš°μ—λŠ” 0으둜 μ‚¬μš©ν•˜λŠ”λ°, λŒ€μ²΄μ μœΌλ‘œ λ¬΄μ‹œν•˜λŠ” ν•„λ“œμ΄λ‹€.
COUNT11

Bitmap 데이터

Pixel을 λ‚˜νƒ€λ‚΄κΈ° μœ„ν•΄μ„œ 1개의 Pixel λ‹Ή 3 λ°”μ΄νŠΈλ₯Ό μ΄μš©ν•˜μ—¬ 색상을 ν‘œν˜„ν•œλ‹€. Imageλ₯Ό ν‘œν˜„ν•  λ•ŒλŠ” 제일 우츑 Column의 상단뢀터 ν•˜λ‹¨μœΌλ‘œ 처리λ₯Ό ν•˜κ²Œ 되고, 이 λ•Œ μ‚¬μš©λœ λ°”μ΄νŠΈ 크기가 4 λ°”μ΄νŠΈ λ‹¨μœ„κ°€ λ˜λ„λ‘ Column의 λ§ˆμ§€λ§‰ Pixel ν‘œν˜„ 이후에 Padding을 λΆ™μ΄κ²Œ λœλ‹€. Padding의 값은 0으둜 μ΄μš©ν•˜κΈ°λ„ ν•˜κ³  μ‚¬μš© λͺ©μ μ— 따라 λ‹€λ₯Έ 값이 될 μˆ˜λ„ μžˆλ‹€. (예λ₯Ό λ“€μ–΄, 5개의 Rowκ°€ μ‘΄μž¬ν•˜μ—¬ 1개의 Column을 μ²˜λ¦¬ν•  λ•Œ 5개의 Pixel을 λͺ…μ‹œν•΄μ•Ό ν•œλ‹€λ©΄, 3Γ—5=153 \times 5 = 15μ΄λ―€λ‘œ 4 λ°”μ΄νŠΈ λ‹¨μœ„λ‘œ λ§Œλ“œλŠ” Padding은 1 λ°”μ΄νŠΈκ°€ λœλ‹€.)
Bitmap 데이터 λͺ…μ‹œ μˆœμ„œ (0,0)(0, 0) (0,1)(0, 1) (1,0)(1, 0) (1,1)(1, 1) κ³Ό 같은 μ’Œν‘œλ‘œ μœ μ§€λœλ‹€κ³  ν•  λ•Œ, Bitmap λ°μ΄ν„°λŠ” (0,1)(0,1) β†’ (1,1)(1, 1) β†’ (0,0)(0, 0) β†’ (1,0)(1, 0)의 순으둜 μ²˜λ¦¬ν•˜κ²Œ λœλ‹€.

3) μ˜ˆμ‹œ

μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 2Γ—22 \times 2 크기의 Pixel이 μ£Όμ–΄μ Έ 있고 bits_per_pixel이 24일 λ•Œ, μœ„μ—μ„œ μ„€λͺ…ν•œ BMP 헀더, DIB 헀더, Bitmap 데이터λ₯Ό μ΄μš©ν•˜μ—¬ BMP 파일의 각 μ˜μ—­λ“€μ„ μ±„μ›Œλ³΄μž. (단, DIB ν—€λ”λŠ” BITMAPINFOHEADERλ₯Ό μ΄μš©ν•œλ‹€.)
Search
Offset
Size
Hex Value
Value
Description
2
42 4D
"BM"
BMP 파일 식별을 μœ„ν•œ Magic Number (B, M)
4
46 00 00 00
70 Bytes
BMP 헀더 크기 (14) + DIB 헀더 크기 (40) + Bitmap 데이터 크기 (16)
2
00 00
Unused
.
2
00 00
Unused
.
4
36 00 00 00
54 Bytes
Bitmap λ°μ΄ν„°μ˜ μ‹œμž‘ Offset인 BMP 헀더 크기 (14) + DIB 헀더 크기 (40)
COUNT5
Search
Offset
Size
Hex Value
Value
Description
4
28 00 00 00
40 Bytes
DIB 헀더 크기 (40)
4
02 00 00 00
2 Pixels
κ°€λ‘œ Pixel의 수
4
02 00 00 00
2 Pixels
μ„Έλ‘œ Pixel의 수
2
01 00
1 Plane
일반적으둜 μ‚¬μš©λ˜λŠ” Color Pane κ°’ (1)
2
18 00
24 Bits
bits_per_pixel κ°’ (24)
4
00 00 00 00
0
Pixel μš”μ†Œλ“€μ„ μ••μΆ•ν•˜μ§€ μ•ŠλŠ” BI_RGB (0)
4
10 00 00 00
16 Bytes
μ••μΆ•λ˜μ§€ μ•Šμ€ Bitmap λ°μ΄ν„°μ˜ 크기 (16)
4
13 0B 00 00
2835 Pixels/Meter
Image의 해상도 κ°’μœΌλ‘œ 72DPIΓ—39.3701=2834.647272 DPI \times 39.3701 = 2834.6472
4
13 0B 00 00
2835 Pixels/Meter
Image의 해상도 κ°’μœΌλ‘œ 72DPIΓ—39.3701=2834.647272 DPI \times 39.3701 = 2834.6472
4
00 00 00 00
0 Colors
νŒ”λ ˆνŠΈκ°€ κ°–κ³  μžˆλŠ” μƒ‰μ˜ 수 (0)
4
00 00 00 00
0 Important Colors
μ€‘μš”ν•œ μƒ‰μ˜ 수 (0)
COUNT11
Search
Offset
Size
Hex Value
Value
Description
3
00 00 FF
0 0 255
(0,1)(0, 1)에 μœ„μΉ˜ν•œ Pixel의 색상 (Red)
3
FF FF FF
255 255 255
(1,1)(1, 1)에 μœ„μΉ˜ν•œ Pixel의 색상 (White)
2
00 00
0 0
4 λ°”μ΄νŠΈ λ‹¨μœ„λ₯Ό λ§Œλ“€κΈ° μœ„ν•œ Padding
3
FF 00 00
255 0 0
(0,0)(0, 0)에 μœ„μΉ˜ν•œ Pixel의 색상 (Blue)
3
00 FF 00
0 255 0
(1,0)(1, 0)에 μœ„μΉ˜ν•œ Pixel의 색상 (Green)
2
00 00
0 0
4 λ°”μ΄νŠΈ λ‹¨μœ„λ₯Ό λ§Œλ“€κΈ° μœ„ν•œ Padding
COUNT6
BMP νŒŒμΌμ„ κ΅¬μ„±ν•˜λŠ” μš”μ†Œμ— λŒ€ν•΄μ„œ μ΄ν•΄ν–ˆκ³  κ·Έ 값을 μ±„μšΈ 수 있게 λ˜μ—ˆλ‹€λ©΄, μœ„ μ˜ˆμ‹œ 값을 μ΄μš©ν•˜μ—¬ 직접 BMP νŒŒμΌμ„ λ§Œλ“€μ–΄λ³΄μž. μ˜ˆμ‹œ μ½”λ“œλŠ” μ•„λž˜μ™€ κ°™λ‹€. 값을 미리 1 λ°”μ΄νŠΈ λ‹¨μœ„λ‘œ λ§Œλ“€μ–΄ λ°°μ—΄ 내에 기둝을 ν–ˆκ³ , 색상 κ°’ 같은 κ²½μš°μ—λŠ” 255κΉŒμ§€ μ‚¬μš©ν•  수 있기 λ•Œλ¬Έμ— unsigned char νƒ€μž…μœΌλ‘œ 배열을 λ§Œλ“€μ—ˆλ‹€.
#include <iostream> unsigned char data[] = { 0x42, 0x4d, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, }; int main(void) { int i; i = -1; while (++i < 70) std::cout << data[i]; return (0); }
C++
μœ„ 그림처럼 컴파일 ν•˜μ—¬ μ‹€ν–‰ν•œ λ’€, stdin으둜 Redirection ν•˜μ—¬ test.bmpλ₯Ό λ§Œλ“ λ‹€. 이λ₯Ό μ‹€ν–‰κΉŒμ§€ ν•˜κ²Œ 되면, 아무것도 μ—†λŠ” κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ μžμ„Ένžˆ μ‚΄νŽ΄λ³΄λ©΄ 그렇지 μ•Šλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. λ§Œλ“  BMP νŒŒμΌμ€ 2Γ—22 \times 2 Pixelμ§œλ¦¬λ―€λ‘œ ꡉμž₯히 μž‘μ€ νŒŒμΌμ΄λ‹€. ν™•λŒ€ν•΄λ³΄λ©΄ μ˜ˆμ‹œμ™€ 같은 Imageλ₯Ό 얻은 것을 확인할 수 μžˆλ‹€.
결둠적으둜 BMP νŒŒμΌμ„ μ„±κ³΅μ μœΌλ‘œ μž‘μ„±ν•˜κΈ° μœ„ν•΄μ„  Endian 값에 λ§žμΆ°μ„œ λ°”μ΄νŠΈ λ‹¨μœ„λ‘œ μ“Έ 수 μžˆμ–΄μ•Ό ν•œλ‹€λŠ” 것을 μ•Œ 수 μžˆμ—ˆκ³ , 값을 미리 정해두지 μ•Šμ€ μ±„λ‘œ BMP νŒŒμΌμ„ λ§Œλ“€κ³  μ‹Άλ‹€λ©΄ μ œλ„€λ¦­ν•˜κ²Œ λ™μž‘ν•  수 μžˆλ„λ‘ ν•΄λ‹Ή λͺ¨λ“ˆμ„ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€λŠ” 것을 μ•”μ‹œν•œλ‹€.

7. Multi-Threading

ν”„λ‘œκ·Έλž¨μ΄ Stateλ₯Ό κ°–κ²Œ λ˜μ–΄ ν”„λ‘œμ„ΈμŠ€λ‘œμ¨ λ™μž‘ν•˜κ³  μžˆλ‹€λ©΄ μ΄λŠ” Thread λ‹¨μœ„λ‘œ 처리 되기 λ•Œλ¬Έμ— ν”„λ‘œμ„ΈμŠ€λŠ” 적어도 ν•˜λ‚˜μ˜ Main Threadλ₯Ό κ°–κ³  μžˆλ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€. μ—¬κΈ°μ„œ μ œμ‹œν•  Thread λ‚΄μš©μ€ pthread_tλ₯Ό μ–΄λ–»κ²Œ μ‚¬μš©ν•˜λŠ”μ§€ λ³΄λ‹€λŠ” pthread_tλ₯Ό μ΄μš©ν•  λ•Œ ν•¨κ»˜ μ“°μ΄λŠ” pthread_mutex_t의 μ΄ˆκΈ°ν™” 방법과 Main Threadμ—μ„œ pthread_t둜 μš΄μš©λ˜λŠ” Sub Threadλ“€μ˜ 처리λ₯Ό κΈ°λ‹€λ¦¬λŠ” 방법에 λŒ€ν•΄μ„œ λ‹€λ£° 것이닀. 그리고 μ–Όλ§ŒνΌμ˜ Threadλ₯Ό μš΄μš©ν•  수 μžˆλŠ”μ§€μ— λŒ€ν•΄μ„œλ„ 닀뀄볼 것이닀.

1) pthread_mutex_t μ΄ˆκΈ°ν™”

Thread κ°„ μž‘μ—…μ— μžˆμ–΄μ„œ λ©”λͺ¨λ¦¬ μƒμ˜ 곡동 μžμ›μ„ κ±΄λ“œλ¦¬κ²Œ 되면 μ›μΉ˜ μ•ŠλŠ” κ²°κ³Όλ₯Ό 얻을 수 있기 λ•Œλ¬Έμ— ν•΄λ‹Ή μ˜μ—­μ„ μž„κ³„ μ˜μ—­(Critical Section)으둜 두고 κΆŒν•œμ„ 얻은 Thread만이 μ ‘κ·Όν•  수 μžˆλ„λ‘ λ§Œλ“œλŠ” 것이 μ€‘μš”ν•˜λ‹€. μž„κ³„ μ˜μ—­μ— μ ‘κ·Όν•˜κΈ° μœ„ν•œ μ—¬λŸ¬ 방법 쀑 Mutexλ₯Ό μ΄μš©ν•˜κΈ° μœ„ν•΄μ„  pthread_mutex_tλ₯Ό μ΄μš©ν•΄μ•Όν•˜κ³ , 이에 λŒ€ν•œ μ΄ˆκΈ°ν™”κ°€ ν•„μˆ˜μ μœΌλ‘œ μˆ˜λ°˜λœλ‹€. pthread_mutex_tλ₯Ό μ΄ˆκΈ°ν™” ν•˜λŠ”λ° μžˆμ–΄μ„œλŠ” 정적인 방식과 동적인 방식이 μ‘΄μž¬ν•œλ‹€.

정적 μ΄ˆκΈ°ν™”

pthread_mutext_t의 정적 μ΄ˆκΈ°ν™”λŠ” 맀크둜둜 μ •μ˜λœ ν•¨μˆ˜λ₯Ό μ΄μš©ν•¨μœΌλ‘œμ¨ κ°€λŠ₯ν•˜λ‹€. <pthread.h>λ₯Ό μ‚΄νŽ΄λ³΄λ©΄ PTHREAD_MUTEX_INITIALIZERλΌλŠ” 맀크둜 μ •μ˜λ¬Έμ„ λ³Ό 수 μžˆλŠ”λ° 이λ₯Ό μ΄μš©ν•˜λŠ” 것이닀. μ£Όμ˜ν•΄μ•Ό ν•  점은 PTHREAD_MUTEX_INITIALIZERλŠ” Constant Initializer μ΄λ―€λ‘œ μ›μΉ™μ μœΌλ‘œλŠ” μ΄ˆκΈ°ν™” κ΅¬λ¬Έμ—μ„œλ§Œ μ΄μš©ν•  수 μžˆλ‹€. λ”°λΌμ„œ μ•„λž˜ μ½”λ“œλŠ” μ»΄νŒŒμΌμ„ μˆ˜ν–‰ν•˜μ§€ μ•ŠλŠ”λ‹€.
int main(void) { pthread_mutex_t lock; lock = PTHREAD_MUTEX_INITIALIZER; return (0); }
C
Constant Initializerλ₯Ό μ˜¬λ°”λ₯΄κ²Œ μž‘μ„±ν•œκ΅¬λ¬Έμ€ μ•„λž˜μ™€ κ°™λ‹€.
int main(void) { pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; return (0); }
C
μΌλ°˜μ μœΌλ‘œλŠ” μœ„μ²˜λŸΌ μ΄μš©ν•˜λ©΄ λ˜μ§€λ§Œ, 42λ₯Ό 진행할 λ•ŒλŠ” λ³€μˆ˜ μ„ μ–Έκ³Ό ν•¨κ»˜ μ΄ˆκΈ°ν™”λ₯Ό ν•  수 μ—†κΈ° λ•Œλ¬Έμ΄ 이 방법을 μ΄μš©ν•  μˆ˜λŠ” μ—†λ‹€. 이 λ•ŒλŠ” Constant둜 μ΄μš©λ˜λŠ” 값을 적절히 ν˜• λ³€ν™˜ν•˜κ²Œ 되면 ν• λ‹Ήλ¬Έμ—μ„œ Constant Initializerλ₯Ό μ΄μš©ν•  수 μžˆλ‹€.
int main(void) { pthread_mutex_t lock; lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; return (0); }
C

동적 μ΄ˆκΈ°ν™”

일반적으둜 pthread_mutex_tλŠ” attributeλΌλŠ” μ„€μ • 값에 λ”°λΌμ„œ 각기 λ‹€λ₯Έ 속성을 κ°–κ²Œ λœλ‹€. κΈ°λ³Έμ μœΌλ‘œλŠ” 0 (NULL)이 ν• λ‹Ήλ˜μ–΄ 이용되고, PTHREAD_MUTEX_INITIALIZERκ°€ 이 방법에 ν•΄λ‹Ήν•œλ‹€. 이 ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λŠ”λ° μžˆμ–΄μ„œ pthread_mutex_t에 λ³„λ„λ‘œ 속성 값을 맀길 ν•„μš”κ°€ μ—†κΈ°λŠ” ν•˜μ§€λ§Œ λ‹€λ₯Έ ν”„λ‘œμ νŠΈμ—μ„œλŠ” μ—¬λŸ¬ 속성을 띈 pthread_mutex_tλ₯Ό μ΄μš©ν•΄μ•Όν•  μˆ˜λ„ μžˆλ‹€. λ˜ν•œ 상황에 따라 Run Time에 각기 λ‹€λ₯Έ μ†μ„±μœΌλ‘œ μ΄μš©ν•΄μ•Ό ν•  μˆ˜λ„ μžˆμ„ 것인데, ν•΄λ‹Ή κ²½μš°μ— μ΄μš©ν•˜λŠ” 방식이 동적 μ΄ˆκΈ°ν™”μ΄λ‹€. μ΄λŠ” pthread_mutex_initμ΄λΌλŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•¨μœΌλ‘œμ¨ pthread_mutex_tλ₯Ό μ΄ˆκΈ°ν™” ν•  수 μžˆλ‹€. <pthread.h>λ₯Ό μ‚΄νŽ΄λ³΄λ©΄ μ•„λž˜μ™€ 같이 ν•¨μˆ˜ μ›ν˜•μ΄ 주어진 것을 확인할 수 μžˆλ‹€.
__API_AVAILABLE(macos(10.4), ios(2.0)) int pthread_mutex_init(pthread_mutex_t * __restrict, const pthread_mutexattr_t * _Nullable __restrict);
C
λ”°λΌμ„œ μ•„λž˜ μ½”λ“œμ™€ 같이 μ΄μš©ν•˜λ©΄ 되고, λ‚΄ κ²½μš°μ—λŠ” 정적 μ΄ˆκΈ°ν™” λŒ€μ‹  동적 μ΄ˆκΈ°ν™”λ₯Ό μ΄μš©ν•˜μ—¬ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν–ˆλ‹€.
#include <pthread.h> int main(void) { pthread_mutex_t lock; pthread_mutex_init(&lock, NULL); return (0); }
C

2) pthread_join

pthread_create ν•¨μˆ˜λ₯Ό ν†΅ν•΄μ„œ Sub Threadλ₯Ό μƒμ„±ν•˜κ²Œ 되면, μ΄λŠ” Main Threadμ™€λŠ” λ³„κ°œμ˜ Context둜 λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— Sub Threadλ“€μ˜ μž‘μ—…μ΄ 끝내기도 전에 Main Thread의 μž‘μ—…μ΄ 끝날 μˆ˜λ„ 있고 Sub Thread의 μž‘μ—… κ²°κ³Όλ₯Ό μ΄μš©ν•΄μ•Όν•˜λŠ” κ²½μš°μ—λŠ” 예기치 λͺ»ν•œ 접근이 일어날 μˆ˜λ„ μžˆλ‹€. λ”°λΌμ„œ μ΄λ ‡κ²Œ Sub Thread의 κ²°κ³Όλ₯Ό κΈ°λ‹€λ €μ•Ό ν•˜λŠ” κ²½μš°μ— μ΄μš©ν•˜λŠ” 것이 pthread_join ν•¨μˆ˜μ΄λ‹€. <pthread.h>μ—μ„œ pthread_join의 ν•¨μˆ˜ μ›ν˜•μ„ 확인해보면 μ•„λž˜μ™€ κ°™λ‹€.
__API_AVAILABLE(macos(10.4), ios(2.0)) int pthread_join(pthread_t , void * _Nullable * _Nullable) __DARWIN_ALIAS_C(pthread_join);
C
μ•„λž˜μ™€ 같이 10개의 Sub Threadλ₯Ό μƒμ„±ν•˜κ³ , Threadλ₯Ό λ™μž‘μ‹œν‚€λŠ” ν•¨μˆ˜μ—μ„œλŠ” μžμ‹ μ˜ μΈλ±μŠ€μ— ν•΄λ‹Ήν•˜λŠ” 수λ₯Ό 좜λ ₯ν•˜λ„λ‘ λ§Œλ“€μ—ˆλ‹€. ν•΄λ‹Ή μ½”λ“œλŠ” Sub Thread의 μž‘μ—… μ™„λ£Œλ₯Ό 보μž₯ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— Main Thread의 싀행이 μ’…λ£Œλ˜λ©΄ μž‘μ—… μ€‘μ—λ˜ Sub ThreadλŠ” κ·Έ λ™μž‘μ„ λ©ˆμΆ”κ²Œ λœλ‹€. λ”°λΌμ„œ 좜λ ₯ κ²°κ³Όλ₯Ό 보면 0~9κΉŒμ§€μ˜ 좜λ ₯이 보μž₯λ˜μ§€ μ•ŠλŠ” 것을 확인할 수 μžˆλ‹€.
#include <pthread.h> #include <stdio.h> void *thread_function(void *idx) { printf("%d\n", *(int *)idx); return (NULL); } int main(void) { int i; int n[10]; pthread_t threads[10]; i = -1; while (++i < 10) { n[i] = i; if (pthread_create(&(threads[i]), NULL, thread_function, &(n[i]))) return (1); } return (0); }
C
Sub Threadλ“€μ˜ μž‘μ—… μ™„λ£Œλ₯Ό 보μž₯ν•˜κΈ° μœ„ν•΄μ„œ pthread_join ν•¨μˆ˜λ₯Ό μΆ”κ°€ν•œ μ½”λ“œλŠ” μ•„λž˜μ™€ κ°™κ³ , pthread_create λ•Œμ™€λŠ” 달리 각 Sub Thread의 Referenceλ₯Ό λ„˜κΈ°λŠ” 것이 μ•„λ‹ˆλΌ Valueλ₯Ό λ„˜κΈ°λŠ” 것을 확인할 수 μžˆλ‹€. 좜λ ₯ κ²°κ³Όλ₯Ό 확인해보면, 0~9κΉŒμ§€μ˜ 좜λ ₯이 보μž₯λ˜λŠ” 것도 확인할 수 μžˆλ‹€.
#include <pthread.h> #include <stdio.h> void *thread_function(void *idx) { printf("%d\n", *(int *)idx); return (NULL); } int main(void) { int i; int n[10]; pthread_t threads[10]; i = -1; while (++i < 10) { n[i] = i; if (pthread_create(&(threads[i]), NULL, thread_function, &(n[i]))) return (1); } while (i--) if (pthread_join(threads[i], NULL)) return (1); return (0); }
C

3) sysctl kern

μœ„μ˜ μ˜ˆμ‹œλ₯Ό 톡해 pthreadλ₯Ό μƒμ„±ν•˜κ³  이 μž‘μ—…μ— λŒ€ν•œ μ™„λ£Œλ₯Ό 보μž₯ν•˜λŠ” κ²ƒκΉŒμ§€ 확인할 수 μžˆμ—ˆλŠ”λ°, κ·Έλ ‡λ‹€λ©΄ 이런 Sub Thread듀은 λͺ‡ κ°œκΉŒμ§€ 생성이 κ°€λŠ₯ν• κΉŒ? μ‹œμŠ€ν…œ λ‹¨μ—μ„œ μœ μ§€ν•˜κ³  μžˆλŠ” 이런 정보듀은 νŠΉμ • νŒŒμΌμ— λͺ¨λ‘ κΈ°λ‘λ˜μ–΄ μžˆλ‹€. Linuxμ—μ„œλŠ” /proc 경둜의 νŒŒμΌλ“€μ—μ„œ 확인할 수 μžˆλŠ”λ°, Mac OS Xμ—μ„œλŠ” /proc이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ Mac OS Xμƒμ—μ„œλŠ” sysctlμ΄λΌλŠ” λͺ…λ Ήμ–΄λ₯Ό ν†΅ν•΄μ„œ μ‹œμŠ€ν…œ λ‹¨μ˜ 정보듀을 확인할 수 μžˆλ‹€.
sysctl λͺ…λ Ήμ–΄μ˜ 맀뉴얼을 μ‚΄νŽ΄λ³΄λ©΄ μ»€λ„μ˜ μƒνƒœλ₯Ό μ°Ύμ•„λ‚΄κ³ , 이λ₯Ό μ΄μš©ν•  수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ€€λ‹€. sysctl의 인자 ν˜•νƒœλŠ” $(MIBλ₯Ό λ”°λ₯΄λŠ” 이름).$(μš”μ†Œ 이름)인 것을 확인할 수 μžˆλ‹€. (.$(μš”μ†Œ 이름)은 μƒλž΅ κ°€λŠ₯ν•˜λ©°, 이 λ•ŒλŠ” $(MIBλ₯Ό λ”°λ₯΄λŠ” 이름)에 ν•΄λ‹Ήν•˜λŠ” λͺ¨λ“  정보듀을 좜λ ₯ν•΄μ€€λ‹€.)
Thread κ΄€λ ¨ 정보듀 μ—­μ‹œ 컀널 μƒμ˜ μ •λ³΄μ΄λ―€λ‘œ μ•„λž˜ λͺ…λ Ήμ–΄λ₯Ό ν†΅ν•΄μ„œ 확인할 수 μžˆλ‹€.
μžμ„Ένžˆ μ‚΄νŽ΄λ³΄λ©΄ Thread의 μˆ˜μ™€ κ΄€λ ¨λœ ν•­λͺ©μœΌλ‘œ kern.num_threads와 kern.num_taskthreadsκ°€ μžˆλŠ” 것을 확인할 수 μžˆλ‹€. num_threadsλŠ” μ‹œμŠ€ν…œμ—μ„œ ν˜„μž¬ μ‹€ν–‰ 쀑인 λͺ¨λ“  ν”„λ‘œμ„ΈμŠ€ (Task)듀이 λ™μ‹œμ— μœ μ§€ν•  수 μžˆλŠ” μ΅œλŒ€ Thread 수λ₯Ό μ˜λ―Έν•˜κ³ , num_taskthreadsλŠ” ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€ (Task)κ°€ λ™μ‹œμ— μœ μ§€ν•  수 μžˆλŠ” μ΅œλŒ€ Thread 수λ₯Ό μ˜λ―Έν•œλ‹€. sysctl λ‚΄μ˜ 파일 μ‹œμŠ€ν…œ κ΄€λ ¨ 정보듀과 같은 νŠΉμ • 정보듀은 μˆ˜μ •μ΄ κ°€λŠ₯ν•˜μ§€λ§Œ, Thread와 같은 μˆ˜μΉ˜λŠ” 변경이 λΆˆκ°€λŠ₯ν•˜λ‹€.
이λ₯Ό ν†΅ν•΄μ„œ μ•Œ 수 μžˆλŠ” 것은, μž‘μ—…μ΄ μΆ©λΆ„νžˆ 가볍닀면 4096개 μ΄μƒμ˜ Threadλ₯Ό μƒμ„±ν•˜μ—¬ μš΄μš©ν•˜λŠ” 것도 κ°€λŠ₯ν•˜κ² μ§€λ§Œ 그렇지 μ•Šμ€ κ²½μš°μ—λŠ” ν˜„μž¬ 운용이 κ°€λŠ₯ν•œ Thread μˆ˜μ— μœ μ˜ν•˜μ—¬ μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ•Ό ν•œλ‹€λŠ” 것이닀. 이와 λ³„κ°œλ‘œ λ¬΄μž‘μ • Threadλ₯Ό λŠ˜λ €μ„œ μž‘μ—…ν•˜λŠ” 것이 더 λ‚˜μ€ μ„±λŠ₯을 보μž₯ν•˜λŠ” 것은 μ•„λ‹ˆλΌλŠ” 점도 μ•Œμ•„λ‘¬μ•Ό ν•œλ‹€.

8. Random Function Implementation

Ray Tracing in One Weekendλ₯Ό λ²ˆμ—­ν•˜λ©΄μ„œ Anti-Aliasing κ΅¬ν˜„μ— μš”κ΅¬λ˜λŠ” Random을 κΈ°μž¬ν•œ 적이 μžˆλ‹€. ν•΄λ‹Ή 책은 C++둜 μ§„ν–‰λ˜κΈ° λ•Œλ¬Έμ— C++의 Random을 C μ–Έμ–΄μ—μ„œμ˜ Randomκ³Ό λΉ„κ΅ν•˜μ—¬ μ„€λͺ…ν–ˆμ—ˆλ‹€. κ°„λ‹¨ν•˜κ²Œ μš”μ•½ν•˜μžλ©΄, C μ–Έμ–΄μ—μ„œμ˜ Random은 μ„ ν˜• 합동(Linear Congruential)μ΄λΌλŠ” λ°©μ‹μœΌλ‘œ λ§Œλ“€μ–΄μ§„λ‹€. 직접 Random ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•ŠλŠ” 이상 μ„ ν˜• ν•©λ™μ˜ Random을 μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— κ·Έ μ„±λŠ₯이 C++의 Random 보닀 μ’‹κΈ°λŠ” νž˜λ“€λ‹€. ν•˜μ§€λ§Œ 이번 ν”„λ‘œμ νŠΈμ—μ„œλŠ” λ›°μ–΄λ‚œ μ„±λŠ₯을 가진 Random을 μš”κ΅¬ν•˜λŠ” 것이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— κ°„λ‹¨ν•œ λ°©μ‹μœΌλ‘œ Random ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄ μ΄μš©ν•  것이닀. (rand와 srandκ°€ ν—ˆμš© ν•¨μˆ˜κ°€ μ•„λ‹ˆλ―€λ‘œ)
κ°€μž₯ λ§Œλ“€κΈ° μ‰¬μš΄ 방법은 μ„ ν˜• ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜λŠ” 것이닀. ν”ν•˜κ²Œ μ ‘ν•  수 μžˆλŠ” μ„ ν˜• ν•¨μˆ˜μ˜ ν˜•νƒœλŠ” y=ax+by = ax + b인데, Seed 값을 ν†΅ν•΄μ„œ 맀 ν•¨μˆ˜ ν˜ΈμΆœλ§ˆλ‹€ λ°”λ€ŒλŠ” Random ν•¨μˆ˜λ₯Ό λ§Œλ“€ 수 μžˆλ‹€. ν•¨μˆ˜ κ΅¬ν˜„μ— μ•ž μ„œ, 결과둜 얻을 값은 int νƒ€μž…μœΌλ‘œ ν•œλ‹€λŠ” 것을 μ „μ œν•œλ‹€.
ax+bax + b의 κ²°κ³Όκ°€ int νƒ€μž…μ˜ μ΅œλŒ€ λ²”μœ„μΈ 214783647을 λ„˜μ§€ μ•ŠλŠ”λ‹€λ©΄ ν•¨μˆ˜ μˆ˜ν–‰μœΌλ‘œ 얻은 Random은 ax+bax+bλΌλŠ” 상관 관계λ₯Ό κ°–κΈ° λ•Œλ¬Έμ— Randomκ³ΌλŠ” 거리가 멀어진닀. λ”°λΌμ„œ ax+bax+b의 κ²°κ³Όκ°€ Overflowκ°€ λ‚˜λ„λ‘ μ„€κ³„ν•˜κ³  이λ₯Ό μ–‘μˆ˜λ‘œ μ΄μš©ν•  수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ€˜μ•Ό ν•œλ‹€.
Overflowκ°€ λ‚˜λ„λ‘ λ§Œλ“œλŠ”λ°λŠ” λ§μ…ˆμœΌλ‘œ μ΄μš©λ˜λŠ” bbλ₯Ό μ΄μš©ν•  μˆ˜λ„ μžˆκ² μ§€λ§Œ, λͺ‡ νšŒμ— 걸쳐 Overflowλ₯Ό λ‚Ό 수 μžˆλŠ” aa에 쑰금 더 μ‹ κ²½ μ“°λŠ” 것이 μ’‹λ‹€. aaλ₯Ό μΆ©λΆ„νžˆ 큰 κ°’μœΌλ‘œ λ§Œλ“€μ–΄ μ—¬λŸ¬ μ°¨λ‘€μ˜ Overflowλ₯Ό λ‚Ό 수 μžˆλ„λ‘ λ§Œλ“€μ—ˆλ‹€λ©΄ bbλŠ” κ·Έ 값이 크든 μž‘λ“  상관 μ—†λ‹€. μ΄λ ‡κ²Œ λ§Œλ“€μ–΄μ§„ 값은 λΆ€ν˜Έ λΉ„νŠΈκ°€ 1인 음수일 수 있기 λ•Œλ¬Έμ— 항상 κ²°κ³Ό 값이 μ–‘μˆ˜κ°€ λ˜λ„λ‘ ν•΄μ•Όν•œλ‹€. 값이 0보닀 μž‘μ€μ§€ νŒλ³„ν•˜μ—¬ -1을 κ³±ν•˜λŠ” κ²ƒλ³΄λ‹€λŠ” &λ₯Ό 톡해 0x7FFFFFFF을 논리 κ³±μ…ˆμ„ μˆ˜ν–‰ν•˜λŠ” 것이 더 λ‚«λ‹€. (μ΄λ ‡κ²Œ ν•˜λ©΄ μŒμˆ˜κ°€ λ‚˜μ™”μ„ λ•ŒλŠ” λΆ€ν˜Έ λΉ„νŠΈ 값이 0으둜 λ‚˜μ˜€κΈ° λ•Œλ¬Έμ— μ–‘μˆ˜κ°€ 될 뿐 μ•„λ‹ˆλΌ, λΆ€ν˜Έ λΉ„νŠΈκ°€ 잘렸기 λ•Œλ¬Έμ— ax+bax + b의 κ²°κ³Όμ™€λŠ” 쑰금 더 λ©€μ–΄μ§ˆ 수 μžˆλ‹€.)
aa와 bb의 값을 μ •ν–ˆλ‹€λ©΄ 인자둜 λ“€μ–΄κ°ˆ xx값에 λŒ€ν•΄μ„œ 생각해봐야 ν•œλ‹€. μ„€κ³„ν•œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•ŒλŠ” 항상 인자 xxλ₯Ό λ„£μ–΄ ν˜ΈμΆœν•˜λŠ” 방식이 μ•„λ‹ˆλΌ μΈμžκ°€ μ—†λŠ” ν˜•νƒœλ‘œ ν˜ΈμΆœν•  것이기 λ•Œλ¬Έμ΄λ‹€. 이에 λŒ€ν•΄μ„œλŠ” 초기 Seed값을 정해두고, 이λ₯Ό ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ κ°±μ‹ ν•˜λŠ” μ‹μœΌλ‘œ μ΄μš©ν•˜λ©΄ λ˜λŠ”λ° 이에 μ ν•©ν•œ 것이 Seed값을 ν•¨μˆ˜μ˜ 정적 λ³€μˆ˜λ‘œ μ„ μ–Έν•˜λŠ” 것이닀. 이λ₯Ό μ½”λ“œλ‘œ λ‚˜νƒ€λ‚΄λ©΄ μ•„λž˜μ™€ 같이 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€.
int randv(void) { static int seed; seed = (seed * 1103515245 + 12345) & 0x7FFFFFFF; return (seed); }
C
μž‘μ„±λœ ν•¨μˆ˜λ₯Ό κ·ΈλŒ€λ‘œ μ΄μš©ν•˜λŠ” κ²ƒλ³΄λ‹€λŠ” 0≀result<10 ≀ result < 1 λ²”μœ„λ₯Ό κ°–λŠ” κ°’μœΌλ‘œ λ°˜ν™˜ν™”λ„λ‘ λ§Œλ“€μ–΄μ£Όλ©΄ int νƒ€μž…λ§ŒνΌμ˜ λ²”μœ„ μ œν•œ λŠͺμ—μ„œ λ²—μ–΄λ‚  수 μžˆλ‹€. 결과둜 얻은 값은 0≀result≀21474836470 ≀ result ≀ 2147483647의 λ²”μœ„λ₯Ό κ°–κΈ° λ•Œλ¬Έμ— 각 항을 2147483648둜 λ‚˜λˆ„μ–΄μ£Όλ©΄ μ›ν•˜λŠ” λ²”μœ„μ˜ κ°’μœΌλ‘œ Scaling ν•  수 μžˆλ‹€. μ½”λ“œλŠ” μ•„λž˜μ™€ κ°™λ‹€.
double randv(void) { static int seed; seed = (seed * 1103515245 + 12345) & 0x7fffffff; return ((double)seed / (double)0x80000000); }
C
0≀result<10 ≀ result < 1의 값을 갖도둝 Random ν•¨μˆ˜λ₯Ό λ§Œλ“€μ—ˆκΈ° λ•Œλ¬Έμ— νŠΉμ • λ²”μœ„μ— μ‘΄μž¬ν•˜λŠ” Random ν•¨μˆ˜λ₯Ό λ§Œλ“œλŠ” 것은 그리 어렡지 μ•Šλ‹€.
double randr(double min, double max) { return ((randv() * (max - min)) + min); }
C
main ν•¨μˆ˜μ—μ„œ randr ν•¨μˆ˜λ₯Ό μ—¬λŸ¬ μ°¨λ‘€ ν˜ΈμΆœν•˜μ—¬ 0 ~ 100 μ‚¬μ΄μ˜ κ²°κ³Όκ°€ λ‚˜μ˜€λŠ”μ§€ ν™•μΈν•΄λ³΄μž. 첫 값이 항상 0으둜 κ³ μ •λ˜λŠ” 것과 항상 정해진 Random 값이 λ‚˜μ˜¨λ‹€λŠ” 것을 μœ μ˜ν•˜μ—¬ μ‚¬μš©ν•˜λ©΄ λœλ‹€. 이 방법 말고도 Shift Rotating λ°©μ‹μœΌλ‘œ κ°„λ‹¨ν•œ μ„ ν˜• 합동 Random을 λ§Œλ“€ μˆ˜λ„ μžˆμœΌλ‹ˆ μ œμ‹œλœ 방법이 λ§ˆμŒμ— 듀지 μ•ŠλŠ”λ‹€λ©΄ 이λ₯Ό μ°Ύμ•„λ³΄λŠ” 것도 쒋을 것이닀.
#include <stdio.h> double randv(void) { static int seed; seed = (seed * 1103515245 + 12345) & 0x7fffffff; return ((double)seed / (double)0x80000000); } double randr(double min, double max) { return ((randv() * (max - min)) + min); } int main(void) { int i; i = -1; while (++i < 10) printf("%d\n", (int)(randr(0, 100))); return (0); }
C

9. Reference

10. Code of Jseo