points.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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 graphic
  5. import (
  6. "github.com/g3n/engine/core"
  7. "github.com/g3n/engine/geometry"
  8. "github.com/g3n/engine/gls"
  9. "github.com/g3n/engine/material"
  10. "github.com/g3n/engine/math32"
  11. )
  12. type Points struct {
  13. Graphic // Embedded graphic
  14. uniMVPM gls.Uniform // Model view projection matrix uniform location cache
  15. }
  16. // NewPoints creates and returns a graphic points object with the specified
  17. // geometry and material.
  18. func NewPoints(igeom geometry.IGeometry, imat material.IMaterial) *Points {
  19. p := new(Points)
  20. p.Graphic.Init(igeom, gls.POINTS)
  21. if imat != nil {
  22. p.AddMaterial(p, imat, 0, 0)
  23. }
  24. p.uniMVPM.Init("MVP")
  25. return p
  26. }
  27. // RenderSetup is called by the engine before rendering this graphic
  28. func (p *Points) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
  29. // Calculates model view projection matrix
  30. mw := p.MatrixWorld()
  31. var mvpm math32.Matrix4
  32. mvpm.MultiplyMatrices(&rinfo.ViewMatrix, &mw)
  33. mvpm.MultiplyMatrices(&rinfo.ProjMatrix, &mvpm)
  34. // Transfer model view projection matrix uniform
  35. location := p.uniMVPM.Location(gs)
  36. gs.UniformMatrix4fv(location, 1, false, &mvpm[0])
  37. }
  38. // Raycast satisfies the INode interface and checks the intersections
  39. // of this geometry with the specified raycaster
  40. func (p *Points) Raycast(rc *core.Raycaster, intersects *[]core.Intersect) {
  41. // Checks intersection with the bounding sphere transformed to world coordinates
  42. geom := p.GetGeometry()
  43. sphere := geom.BoundingSphere()
  44. matrixWorld := p.MatrixWorld()
  45. sphere.ApplyMatrix4(&matrixWorld)
  46. if !rc.IsIntersectionSphere(&sphere) {
  47. return
  48. }
  49. // Copy ray and transforms to model coordinates
  50. var inverseMatrix math32.Matrix4
  51. var ray math32.Ray
  52. inverseMatrix.GetInverse(&matrixWorld)
  53. ray.Copy(&rc.Ray).ApplyMatrix4(&inverseMatrix)
  54. // Checks intersection with all points
  55. scale := p.Scale()
  56. localThreshold := rc.PointPrecision / ((scale.X + scale.Y + scale.Z) / 3)
  57. localThresholdSq := localThreshold * localThreshold
  58. // internal function to check intersection with a point
  59. testPoint := func(point *math32.Vector3, index int) {
  60. // Get distance from ray to point and if greater than threshold,
  61. // nothing to do.
  62. rayPointDistanceSq := ray.DistanceSqToPoint(point)
  63. if rayPointDistanceSq >= localThresholdSq {
  64. return
  65. }
  66. var intersectPoint math32.Vector3
  67. ray.ClosestPointToPoint(point, &intersectPoint)
  68. intersectPoint.ApplyMatrix4(&matrixWorld)
  69. origin := rc.Ray.Origin()
  70. distance := origin.DistanceTo(&intersectPoint)
  71. if distance < rc.Near || distance > rc.Far {
  72. return
  73. }
  74. // Appends intersection of raycaster with this point
  75. *intersects = append(*intersects, core.Intersect{
  76. Distance: distance,
  77. Point: intersectPoint,
  78. Index: uint32(index),
  79. Object: p,
  80. })
  81. }
  82. // Get buffer with position vertices
  83. vbPos := geom.VBO("VertexPosition")
  84. if vbPos == nil {
  85. panic("points.Raycast(): VertexPosition VBO not found")
  86. }
  87. positions := vbPos.Buffer()
  88. var point math32.Vector3
  89. indices := geom.Indices()
  90. // Geometry has indexed vertices
  91. if indices.Size() > 0 {
  92. for i := 0; i < indices.Size(); i++ {
  93. a := indices[i]
  94. positions.GetVector3(int(a*3), &point)
  95. testPoint(&point, i)
  96. }
  97. } else {
  98. for i := 0; i < positions.Size()/3; i++ {
  99. positions.GetVector3(i*3, &point)
  100. testPoint(&point, i)
  101. }
  102. }
  103. }