perspective.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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, error) {
  63. cam.updateProjMatrix()
  64. var matrix math32.Matrix4
  65. matrixWorld := cam.MatrixWorld()
  66. err := matrix.GetInverse(&matrixWorld)
  67. if err != nil {
  68. return nil, err
  69. }
  70. matrix.MultiplyMatrices(&cam.projMatrix, &matrix)
  71. v.ApplyProjection(&matrix)
  72. return v, nil
  73. }
  74. // Unproject transforms the specified position from camera projected coordinates to world coordinates.
  75. func (cam *Perspective) Unproject(v *math32.Vector3) (*math32.Vector3, error) {
  76. // Get inverted camera view matrix
  77. var viewMatrix math32.Matrix4
  78. cam.ViewMatrix(&viewMatrix)
  79. var invertedViewMatrix math32.Matrix4
  80. err := invertedViewMatrix.GetInverse(&viewMatrix)
  81. if err != nil {
  82. return nil, err
  83. }
  84. // Get inverted camera projection matrix
  85. cam.updateProjMatrix()
  86. var invertedProjMatrix math32.Matrix4
  87. err = invertedProjMatrix.GetInverse(&cam.projMatrix)
  88. if err != nil {
  89. return nil, err
  90. }
  91. // Multiply invertedViewMatrix by invertedProjMatrix
  92. // to get transformation from camera projected coordinates to world coordinates
  93. // and project vector using this transformation
  94. var matrix math32.Matrix4
  95. matrix.MultiplyMatrices(&invertedViewMatrix, &invertedProjMatrix)
  96. v.ApplyProjection(&matrix)
  97. return v, nil
  98. }
  99. // SetRaycaster sets the specified raycaster with this camera position in world coordinates
  100. // pointing to the direction defined by the specified coordinates unprojected using this camera.
  101. func (cam *Perspective) SetRaycaster(rc *core.Raycaster, sx, sy float32) error {
  102. var origin, direction math32.Vector3
  103. matrixWorld := cam.MatrixWorld()
  104. origin.SetFromMatrixPosition(&matrixWorld)
  105. direction.Set(sx, sy, 0.5)
  106. unproj, err := cam.Unproject(&direction)
  107. if err != nil {
  108. return err
  109. }
  110. unproj.Sub(&origin).Normalize()
  111. rc.Set(&origin, &direction)
  112. // Updates the view matrix of the raycaster
  113. cam.ViewMatrix(&rc.ViewMatrix)
  114. return nil
  115. }
  116. // updateProjMatrix updates this camera projection matrix if necessary
  117. func (cam *Perspective) updateProjMatrix() {
  118. if cam.projChanged {
  119. cam.projMatrix.MakePerspective(cam.fov, cam.aspect, cam.near, cam.far)
  120. cam.projChanged = false
  121. }
  122. }