Three.js: Perspective μΉ΄λ©”λΌμ˜ FOV 계산

에 λ§Œλ“  2012λ…„ 02μ›” 02일  Β·  19μ½”λ©˜νŠΈ  Β·  좜처: mrdoob/three.js

3D에 λŒ€ν•œ 이전 κ²½ν—˜μ΄ μ—†κΈ° λ•Œλ¬Έμ— 3D μ „λ¬Έκ°€μ—κ²Œ 일반적인 지식이 될 μˆ˜μžˆλŠ” λͺ‡ 가지 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.
λ‹€μ–‘ν•œ μž₯λ©΄ 크기 (800x600, 1200x100 λ“±)κ°€ μžˆμŠ΅λ‹ˆλ‹€.
z μœ„μΉ˜κ°€ 0이고 폭과 높이가 μž₯λ©΄κ³Ό λ™μΌν•œ 물체가 전체 μž₯면을 μ±„μš°λ„λ‘ν•˜λ €λ©΄ μ–΄λ–€ 곡식을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

예 : 였브젝트 λ©”μ‹œ AλŠ” 1200x100이고 Z μœ„μΉ˜ 0에 μžˆμŠ΅λ‹ˆλ‹€. μž₯면도 1200x100μž…λ‹ˆλ‹€. μΉ΄λ©”λΌλŠ” z μœ„μΉ˜ 1500에 μžˆμŠ΅λ‹ˆλ‹€. 물체가 μž₯면을 μ±„μš°λ„λ‘ν•˜λŠ” FOVλŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

((A / B) * C) 쀄을 따라 λ­”κ°€ λ‚΄κ°€ μ°Ύκ³ μžˆλŠ” κ²ƒμž…λ‹ˆλ‹€ : D.

λ‚΄ μ§ˆλ¬Έμ— λ‹΅ν•  μˆ˜μžˆμ„λ§ŒνΌ λ›°μ–΄λ‚œ μ‚¬λžŒμ—κ²Œ λ¬΄ν•œν•œ μΉ­μ°¬μ„λ“œλ¦½λ‹ˆλ‹€. :)

Question

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

수직 μ‹œμ•Ό vFOV 및 μΉ΄λ©”λΌλ‘œλΆ€ν„°μ˜ 거리 dist κ³ λ €ν•  λ•Œ λ³΄μ΄λŠ” height λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

height = 2 * Math.tan( ( vFOV / 2 ) ) * dist;

λ³΄μ΄λŠ” width λŠ”

aspect = window_width / window_height;
hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspect );
width  = 2 * Math.tan( ( hFOV / 2 ) ) * dist;

THREE.jsμ—μ„œ μΉ΄λ©”λΌμ˜ μ‹œμ•Όκ° 맀개 λ³€μˆ˜λŠ” 수직 맀개 λ³€μˆ˜μž…λ‹ˆλ‹€.

두 가지 방정식 μ„ΈνŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ ν•„μš”ν•œ vFOVλ₯Ό 두 번 κ³„μ‚°ν•˜κ³  더 큰 닡을 μ„ νƒν•©λ‹ˆλ‹€.

λͺ¨λ“  19 λŒ“κΈ€

수직 μ‹œμ•Ό vFOV 및 μΉ΄λ©”λΌλ‘œλΆ€ν„°μ˜ 거리 dist κ³ λ €ν•  λ•Œ λ³΄μ΄λŠ” height λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

height = 2 * Math.tan( ( vFOV / 2 ) ) * dist;

λ³΄μ΄λŠ” width λŠ”

aspect = window_width / window_height;
hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspect );
width  = 2 * Math.tan( ( hFOV / 2 ) ) * dist;

THREE.jsμ—μ„œ μΉ΄λ©”λΌμ˜ μ‹œμ•Όκ° 맀개 λ³€μˆ˜λŠ” 수직 맀개 λ³€μˆ˜μž…λ‹ˆλ‹€.

두 가지 방정식 μ„ΈνŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ ν•„μš”ν•œ vFOVλ₯Ό 두 번 κ³„μ‚°ν•˜κ³  더 큰 닡을 μ„ νƒν•©λ‹ˆλ‹€.

λ‹΅μž₯ ν•΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€ :)
κ·Έλž˜λ„ μ’€ ν˜Όλž€ μŠ€λŸ¬μ›Œμš”. λ³€μˆ˜ vFOVλŠ” μ–΄λ””μ„œ μ–»μŠ΅λ‹ˆκΉŒ?
μž₯면을 μ±„μ›Œμ•Όν•˜λŠ” 물체의 λ†’μ΄μž…λ‹ˆκΉŒ?
κ·Έλ ‡λ‹€λ©΄ μ΄μƒν•œ 숫자 (1000 λ²”μœ„)κ°€ ν‘œμ‹œλ˜λ―€λ‘œμ΄λ₯Ό μ΅œμ’… FOV둜 λ³€ν™˜ν•˜λ €λ©΄ μ–΄λ–»κ²Œν•΄μ•Όν•©λ‹ˆκΉŒ?

λ‚˜λŠ” Fiddle http://jsfiddle.net/dmYgr/6/을 λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.
μ–΄λ–»κ²Œν•˜λŠ”μ§€ 보여쀄 수 μžˆλ‚˜μš”?

또 λ‹€μ‹œ κ°μ‚¬ν•©λ‹ˆλ‹€. κ·€ν•˜μ˜ κ²Œμ‹œλ¬Όμ—μ„œ λ‚˜λŠ” 이미 당신이 λ‚˜λ³΄λ‹€ 더 천재라고 λŠλ‚„ 수 μžˆμŠ΅λ‹ˆλ‹€.)

첫 번째 방정식을 μ‚¬μš©ν•˜μ—¬ vFOV λ₯Ό κ΅¬ν•œ λ‹€μŒμ΄λ₯Ό μΉ΄λ©”λΌμ˜ fov 맀개 λ³€μˆ˜λ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€.

λ‚΄ μž₯면은 800 * 600μž…λ‹ˆλ‹€.
μΉ΄λ©”λΌμ˜ κ±°λ¦¬λŠ” 1000μž…λ‹ˆλ‹€.

κ³΅μ‹μ—μ„œμ΄ 숫자λ₯Ό μ–΄λ–»κ²Œ μ‚¬μš©ν•©λ‹ˆκΉŒ?
vFOV에 무엇을 μž…λ ₯해야할지 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€.

높이 = 2 * Math.tan ((vFOV / 2)) * dist; <-μ—¬κΈ°μ—μ„œ μ‹œμž‘ν•˜λΌκ³ ν•˜λŠ”λ° vFOVλ₯Ό λŒ€μ²΄ν•΄μ•Όν•˜λŠ” μˆ«μžλŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

첫 번째 방정식을 μ‚¬μš©ν•˜κ³  vFOV ν•˜μ„Έμš”.

vFOV = 2 * Math.atan( height / ( 2 * distance ) );

그런 λ‹€μŒμ΄λ₯Ό μΉ΄λ©”λΌμ˜ fov 맀개 λ³€μˆ˜λ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€.

var renderWidth = 800;
var renderHeight = 600;
var cameraPosition = 1000;
var vFOV = 2 * Math.atan( renderWidth / ( 2 * cameraPosition ) );
var height = 2 * Math.tan( ( vFOV / 2 ) ) * cameraPosition;
var aspect = renderWidth / renderHeight;
var hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspect );
var width  = 2 * Math.tan( ( hFOV / 2 ) ) * cameraPosition;

κ²°κ³Ό:
vFOV = 0.7610127542247298은 μœ νš¨ν•œ FOVκ°€ μ•„λ‹™λ‹ˆλ‹€.

var vFOV = 2 * Math.atan( renderHeight / ( 2 * cameraPosition ) );
var height = 2 * Math.tan( ( vFOV / 2 ) ) * cameraPosition;

var aspect = renderWidth / renderHeight;
var hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspect );
var width  = 2 * Math.tan( ( hFOV / 2 ) ) * cameraPosition;

vFOV = 0.5829135889557342도 μœ νš¨ν•œ FOVκ°€ μ•„λ‹™λ‹ˆλ‹€.

λ‚˜λ₯Ό μœ„ν•΄ 예제λ₯Ό μž‘μ„±ν•˜κ³  μœ νš¨ν•œ FOV 번호λ₯Ό μ œκ³΅ν•˜λŠ” 예제λ₯Ό 보여쀄 수 μžˆμŠ΅λ‹ˆκΉŒ?
μœ„ 예의 μ •ν™•ν•œ μˆ«μžλŠ” μ•½ 37μž…λ‹ˆλ‹€.

λ‹Ήμ‹ μ˜ λ°”μ΄μ˜¬λ¦°μ—μ„œ

높이 = 평면 λ©”μ‰¬μ˜ 높이 = 500.

거리 = camera.z-plane.z = 1000-100 = 900.

vFOV = 2 * Math.atan (높이 / (2 * 거리)) = 0.5419 λΌλ””μ•ˆ λ˜λŠ” 31.04도.

2 * Math.atan (500 / (2 * 900)) = 0.5418937006768411 λ‚΄ λΈŒλΌμš°μ € (ꡬ글 크둬)에 따라

μ£„μ†‘ν•©λ‹ˆλ‹€. λΌλ””μ•ˆμ—μ„œ λ„λ‘œμ˜ λ³€ν™˜ ν‘œμ‹œλ₯Ό λ¬΄μ‹œν–ˆμŠ΅λ‹ˆλ‹€. 이전 κ²Œμ‹œλ¬Όμ„ μ—…λ°μ΄νŠΈν–ˆμŠ΅λ‹ˆλ‹€.

정말 κ³ λ§™μŠ΅λ‹ˆλ‹€! :λ””
ν•˜, 그것은 10 νšŒμ‹ μ²˜λŸΌ 걸렸지 만 μ§€κΈˆμ€ μž‘λ™ν•©λ‹ˆλ‹€ :).
λ‹€μ‹œ ν•œ 번 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€!

@Tobiasartz :-)

μ›¨μŠ€νŠΈ λž­κΈ€λ¦¬. 당신은 μ™•μž…λ‹ˆλ‹€. κ°μ‚¬ν•©λ‹ˆλ‹€.

이것은 맀우 λ„μ›€μ΄λ˜μ—ˆμŠ΅λ‹ˆλ‹€!! @WestLangley 감사

@WestLangley κ°μ‚¬ν•©λ‹ˆλ‹€ !!
λ³΅μ‚¬μ—΄μ—μ„œ κ°λ„λ‘œμ˜ λ³€ν™˜μ„ μΆ”κ°€ν•΄μ•Όν•œλ‹€λŠ” 사싀을 κΉ¨λ‹«λŠ” 데 μ‹œκ°„μ΄ μ’€ κ±Έλ ΈκΈ° λ•Œλ¬Έμ— 여기에 μ΅œμ’… μ½”λ“œλ‘œ 예제λ₯Ό μΆ”κ°€ν•˜κ² μŠ΅λ‹ˆλ‹€.

var distance = 1000;
var FOV = 2 * Math.atan( window.innerHeight / ( 2 * distance ) ) * 180 / Math.PI;
var camera = new THREE.PerspectiveCamera( FOV, window.innerWidth/window.innerHeight, 0.1, distance );
camera.position.z = distance;

@ Emanuele-Spatola 곡식이 μ˜λ―Έκ°€ μ—†μŠ΅λ‹ˆλ‹€. window.innerHeight μ—λŠ” ν”½μ…€ λ‹¨μœ„κ°€ μžˆμŠ΅λ‹ˆλ‹€. distance λŒ€λΆ€λΆ„μ€ 그렇지 μ•ŠμŠ΅λ‹ˆλ‹€. λ³΄μ΄λŠ” λ†’μ΄μ˜ λ‹¨μœ„λŠ” 거리와 λ™μΌν•΄μ•Όν•©λ‹ˆλ‹€.

Tobiasartz의 λ°”μ΄μ˜¬λ¦°μ„ ν•΄λ‹Ή κ³΅μ‹μœΌλ‘œ μ—…λ°μ΄νŠΈν–ˆλŠ”λ° μž‘λ™ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.
http://jsfiddle.net/dmYgr/63/
μΊ”λ²„μŠ€λŠ” 500px, λΉ„ν–‰κΈ°λŠ” 495x495이며 μ£Όμœ„μ—λŠ” μ•½ 5px의 ν…Œλ‘λ¦¬κ°€ μžˆμŠ΅λ‹ˆλ‹€.
1000pxκ°€ μœ νš¨ν•œ 거리가 μ•„λ‹Œ μ΄μœ λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

http://jsfiddle.net/dmYgr/65/

1000pxκ°€ μœ νš¨ν•œ 거리가 μ•„λ‹Œ μ΄μœ λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

피사체 μ•žμ— 카메라λ₯Ό 1000 ν”½μ…€ 배치 ν•œ 적이 μžˆμŠ΅λ‹ˆκΉŒ?

10 ν”ΌνŠΈ λ„ˆλΉ„μ˜ μž₯면을보기 μœ„ν•΄ μ‹€μ œ 카메라λ₯Ό 10 ν”ΌνŠΈ 떨어진 곳에 배치 ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ§ˆμ°¬κ°€μ§€λ‘œ 1000px λ„ˆλΉ„μ˜ μž₯면을보기 μœ„ν•΄ 가상 카메라λ₯Ό 1000px 떨어진 곳에 배치 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

높이, μž₯면의 λ„ˆλΉ„, μΉ΄λ©”λΌμ˜ 거리λ₯Ό μ•Œ λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.

var distance = 1000,height=window.innerHeight,width=window.innerWidth
var diag = Math.sqrt((height*height)+(width*width))
var FOV = 2 * Math.atan( diag / ( 2 * distance ) ) * 180 / Math.PI;
var camera = new THREE.PerspectiveCamera( FOV, window.innerWidth/window.innerHeight, 0.1, distance );
camera.position.z = distance;

μ΄λ ‡κ²Œν•˜λ©΄ 높이> λ„ˆλΉ„μ™€ 같은 상황도 μ²˜λ¦¬λ©λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰