perspective.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package camera
  5. import (
  6. "github.com/g3n/engine/core"
  7. "github.com/g3n/engine/math32"
  8. )
  9. type Perspective struct {
  10. Camera // Embedded camera
  11. fov float32 // field of view in degrees
  12. aspect float32 // aspect ratio (width/height)
  13. near float32 // near plane z coordinate
  14. far float32 // far plane z coordinate
  15. projChanged bool // camera projection parameters changed (needs to recalculates projection matrix)
  16. projMatrix math32.Matrix4 // last calculated projection matrix
  17. }
  18. // NewPerspective creates and returns a pointer to a new perspective camera with the
  19. // specified parameters.
  20. func NewPerspective(fov, aspect, near, far float32) *Perspective {
  21. cam := new(Perspective)
  22. cam.Camera.Initialize()
  23. cam.fov = fov
  24. cam.aspect = aspect
  25. cam.near = near
  26. cam.far = far
  27. cam.projChanged = true
  28. return cam
  29. }
  30. // SetFov sets the camera field of view in degrees
  31. func (cam *Perspective) SetFov(fov float32) {
  32. cam.fov = fov
  33. cam.projChanged = true
  34. }
  35. // SetAspect sets the camera aspect ratio (width/height)
  36. func (cam *Perspective) SetAspect(aspect float32) {
  37. cam.aspect = aspect
  38. cam.projChanged = true
  39. }
  40. // Fov returns the current camera FOV (field of view) in degrees
  41. func (cam *Perspective) Fov() float32 {
  42. return cam.fov
  43. }
  44. // Aspect returns the current camera aspect ratio
  45. func (cam Perspective) Aspect() float32 {
  46. return cam.aspect
  47. }
  48. // Near returns the current camera near plane Z coordinate
  49. func (cam *Perspective) Near() float32 {
  50. return cam.near
  51. }
  52. // Far returns the current camera far plane Z coordinate
  53. func (cam *Perspective) Far() float32 {
  54. return cam.far
  55. }
  56. // ProjMatrix satisfies the ICamera interface
  57. func (cam *Perspective) ProjMatrix(m *math32.Matrix4) {
  58. cam.updateProjMatrix()
  59. *m = cam.projMatrix
  60. }
  61. // Project transforms the specified position from world coordinates to this camera projected coordinates.
  62. func (cam *Perspective) Project(v *math32.Vector3) *math32.Vector3 {
  63. cam.updateProjMatrix()
  64. var matrix math32.Matrix4
  65. matrixWorld := cam.MatrixWorld()
  66. matrix.MultiplyMatrices(&cam.projMatrix, matrix.GetInverse(&matrixWorld, true))
  67. v.ApplyProjection(&matrix)
  68. return v
  69. }
  70. // Unproject transforms the specified position from camera projected coordinates to world coordinates.
  71. func (cam *Perspective) Unproject(v *math32.Vector3) *math32.Vector3 {
  72. // Get inverted camera view matrix
  73. var viewMatrix math32.Matrix4
  74. cam.ViewMatrix(&viewMatrix)
  75. var invertedViewMatrix math32.Matrix4
  76. invertedViewMatrix.GetInverse(&viewMatrix, true)
  77. // Get inverted camera projection matrix
  78. cam.updateProjMatrix()
  79. var invertedProjMatrix math32.Matrix4
  80. invertedProjMatrix.GetInverse(&cam.projMatrix, true)
  81. // Multiply invertedViewMatrix by invertedProjMatrix
  82. // to get transformation from camera projected coordinates to world coordinates
  83. // and project vector using this transformation
  84. var matrix math32.Matrix4
  85. matrix.MultiplyMatrices(&invertedViewMatrix, &invertedProjMatrix)
  86. v.ApplyProjection(&matrix)
  87. return v
  88. }
  89. // SetRaycaster sets the specified raycaster with this camera position in world coordinates
  90. // pointing to the direction defined by the specified coordinates unprojected using this camera.
  91. func (cam *Perspective) SetRaycaster(rc *core.Raycaster, sx, sy float32) {
  92. var origin, direction math32.Vector3
  93. matrixWorld := cam.MatrixWorld()
  94. origin.SetFromMatrixPosition(&matrixWorld)
  95. direction.Set(sx, sy, 0.5)
  96. cam.Unproject(&direction).Sub(&origin).Normalize()
  97. rc.Set(&origin, &direction)
  98. // Updates the view matrix of the raycaster
  99. cam.ViewMatrix(&rc.ViewMatrix)
  100. }
  101. // updateProjMatrix updates this camera projection matrix if necessary
  102. func (cam *Perspective) updateProjMatrix() {
  103. if cam.projChanged {
  104. cam.projMatrix.MakePerspective(cam.fov, cam.aspect, cam.near, cam.far)
  105. cam.projChanged = false
  106. }
  107. }