Advertisement
Guest User

Untitled

a guest
Jan 24th, 2017
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.20 KB | None | 0 0
  1. import numpy as np
  2. import math
  3.  
  4. '''
  5. Viewing Tranform:
  6. You need:
  7. - P, camera postition (Px, Py, Pz)
  8. - Direction camera is pointing
  9. - Up direction (if camera is tilted)
  10. - Angle alpha, FOV Viewing Angle
  11. - Two other values, near (n) and far (f)
  12. - The aspect ratio of our screen (r)
  13.  
  14. Frustum Cube
  15.  
  16. /|
  17. / |
  18. | / |
  19. | * | *---|----
  20. |/| | | | |
  21. z <-----|-|---|------ -> ----|----
  22. |\| | | | |
  23. | \ | ----|----
  24. | \ |
  25. \ |
  26. \|
  27. <--> n
  28. <-----> f
  29.  
  30. The first step is to transform the whole view so that the camera is at
  31. the origin and it's pointing towards -z.
  32.  
  33. There's a pyramid coming out the camera, known as the Viewing Pyramid.
  34. Inside the pyramid are the things we care about. Start by transferring
  35. to 'image space' (cube 1 -1 1 -1). We add two planes, one near and one
  36. far. Turning a square frustum into a cube. Matrix that looks something
  37. like this:
  38. Matrix M
  39. [t 0 0 0]
  40. [x y z 1] * [0 rt 0 0] = [tx ty az+b -z]
  41. [0 0 a -1]
  42. [0 0 b 0]
  43.  
  44. Notice we're going to have to divide by -z because of the w dimension,
  45. hence why things far from us appear smaller. Also (0,0,-n) and (0,0,-f)
  46. should come out the same through the matrix. So we can solve this:
  47.  
  48. [0 0 -n 1] * M = [0 0 -an+b n] -- 3D --> (0 0 (-an+b)/n)
  49. [0 0 -f 1] * M = [0 0 -af+b f] -- 3D --> (0 0 (-af+b)/f)
  50.  
  51. But because of the way we defined the cube earlier:
  52.  
  53. (0 0 (-an+b)/n) = (0 0 1)
  54. (0 0 (-af+b)/f) = (0 0 -1)
  55.  
  56. Solve with system of equations:
  57.  
  58. a = (f+n)/(f-n) and b=(2nf)/(f-n)
  59.  
  60. So we can put those values in our matrix. Now we need to determine t.
  61. We can find it by using that '*' point which corresponds to (0, d,-n)
  62. d = n*tan(alpha/2) so we're going to do [0 n*tan(alpha/2) -n 1] * M:
  63.  
  64. [0 n*tan(alpha/2) -n 1] * M = [0 t*n*tan(alpha/2) ... n]
  65.  
  66. [0 t*n*tan(alpha/2) ... n] -- 3D --> (0 t*tan(alpha/2) 1)
  67.  
  68. But we know that point corresponds to (0 1 1), therefore:
  69.  
  70. t*tan(alpha/2) = 1
  71. t = 1/(tan(alpha/2))
  72.  
  73. We also need to multiply by our aspect ratio for the y values.
  74. So if our aspect ratio is r our final matrix is:
  75.  
  76. [1/(tan(alpha/2)) 0 0 0]
  77. [0 r/(tan(alpha/2)) 0 0]
  78. [0 0 (f+n)/(f-n) -1]
  79. [0 0 (2nf)/(f-n) 0]
  80.  
  81. Remember to always redivide by the W component to get back to 3D:
  82. (x y z) -- 4D --> [x y z 1] * M = [x' y' z' w] -- 3D --> (x'/w y'/w z'/w)
  83.  
  84. The function below returns a matrix where FOV is in degrees and the
  85. aspect ratio is w/h. We still need to do clipping and checking what
  86. is visible and what isn't.
  87.  
  88. '''
  89.  
  90. def viewing_transform(fov, aspect, near, far):
  91. """ Returns a numpy matrix that transforms points into image space """
  92. t = 1/tan(alpha * math.pi / 360)
  93. a = (far + near)/(far - near)
  94. b = (2*near*far)/(far-near)
  95.  
  96. return np.matrix([[t, 0, 0, 0],
  97. [0, r*t, 0, 0],
  98. [0, 0, a, -1],
  99. [0, 0, b, 0]])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement