raycaster.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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 core
  5. import (
  6. "github.com/g3n/engine/math32"
  7. "sort"
  8. )
  9. // Raycaster represents an empty object that can cast rays and check for ray intersections.
  10. type Raycaster struct {
  11. // The distance from the ray origin to the intersected points
  12. // must be greater than the value of this field to be considered.
  13. // The defaul value is 0.0
  14. Near float32
  15. // The distance from the ray origin to the intersected points
  16. // must be less than the value of this field to be considered.
  17. // The defaul value is +Infinity.
  18. Far float32
  19. // Minimum distance in world coordinates between the ray and
  20. // a line segment when checking intersects with lines.
  21. // The default value is 0.1
  22. LinePrecision float32
  23. // Minimum distance in world coordinates between the ray and
  24. // a point when checking intersects with points.
  25. // The default value is 0.1
  26. PointPrecision float32
  27. // This field must be set with the camera view matrix used
  28. // when checking for sprite intersections.
  29. // It is set automatically when using camera.SetRaycaster
  30. ViewMatrix math32.Matrix4
  31. // Embedded ray
  32. math32.Ray
  33. }
  34. // Intersect describes the intersection between a ray and an object
  35. type Intersect struct {
  36. // Distance between the origin of the ray and the intersect
  37. Distance float32
  38. // Point of intersection in world coordinates
  39. Point math32.Vector3
  40. // Intersected node
  41. Object INode
  42. // If the geometry has indices, this field is the
  43. // index in the Indices buffer of the vertex intersected
  44. // or the first vertex of the intersected face.
  45. // If the geometry doesn't have indices, this field is the
  46. // index in the positions buffer of the vertex intersected
  47. // or the first vertex of the insersected face.
  48. Index uint32
  49. }
  50. // NewRaycaster creates and returns a pointer to a new raycaster object
  51. // with the specified origin and direction.
  52. func NewRaycaster(origin, direction *math32.Vector3) *Raycaster {
  53. rc := new(Raycaster)
  54. rc.Ray.Set(origin, direction)
  55. rc.Near = 0
  56. rc.Far = math32.Inf(1)
  57. rc.LinePrecision = 0.1
  58. rc.PointPrecision = 0.1
  59. return rc
  60. }
  61. // IntersectObject checks intersections between this raycaster and
  62. // and the specified node. If recursive is true, it also checks
  63. // the intersection with the node's children.
  64. // Intersections are returned sorted by distance, closest first.
  65. func (rc *Raycaster) IntersectObject(inode INode, recursive bool) []Intersect {
  66. intersects := []Intersect{}
  67. rc.intersectObject(inode, &intersects, recursive)
  68. sort.Slice(intersects, func(i, j int) bool {
  69. return intersects[i].Distance < intersects[j].Distance
  70. })
  71. return intersects
  72. }
  73. // IntersectObjects checks intersections between this raycaster and
  74. // the specified array of scene nodes. If recursive is true, it also checks
  75. // the intersection with each nodes' children.
  76. // Intersections are returned sorted by distance, closest first.
  77. func (rc *Raycaster) IntersectObjects(inodes []INode, recursive bool) []Intersect {
  78. intersects := []Intersect{}
  79. for _, inode := range inodes {
  80. rc.intersectObject(inode, &intersects, recursive)
  81. }
  82. sort.Slice(intersects, func(i, j int) bool {
  83. return intersects[i].Distance < intersects[j].Distance
  84. })
  85. return intersects
  86. }
  87. func (rc *Raycaster) intersectObject(inode INode, intersects *[]Intersect, recursive bool) {
  88. node := inode.GetNode()
  89. if !node.Visible() {
  90. return
  91. }
  92. inode.Raycast(rc, intersects)
  93. if recursive {
  94. for _, child := range node.Children() {
  95. rc.intersectObject(child, intersects, true)
  96. }
  97. }
  98. return
  99. }