normals_helper.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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 util
  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/graphic"
  10. "github.com/g3n/engine/material"
  11. "github.com/g3n/engine/math32"
  12. )
  13. // NormalsHelper is the visual representation of the normals of a target object.
  14. type NormalsHelper struct {
  15. graphic.Lines
  16. size float32
  17. targetNode *core.Node
  18. targetGeometry *geometry.Geometry
  19. }
  20. // NewNormalsHelper creates, initializes and returns a pointer to Normals helper object.
  21. // This helper shows the surface normals of the specified object.
  22. func NewNormalsHelper(ig graphic.IGraphic, size float32, color *math32.Color, lineWidth float32) *NormalsHelper {
  23. // Creates new Normals helper
  24. nh := new(NormalsHelper)
  25. nh.size = size
  26. // Save the object to show the normals
  27. nh.targetNode = ig.GetNode()
  28. // Get the geometry of the target object
  29. nh.targetGeometry = ig.GetGeometry()
  30. // Get the number of target vertex positions
  31. vertices := nh.targetGeometry.VBO(gls.VertexPosition)
  32. n := vertices.Buffer().Size() * 2
  33. // Creates this helper geometry
  34. geom := geometry.NewGeometry()
  35. positions := math32.NewArrayF32(n, n)
  36. geom.AddVBO(gls.NewVBO(positions).AddAttrib(gls.VertexPosition))
  37. // Creates this helper material
  38. mat := material.NewStandard(color)
  39. mat.SetLineWidth(lineWidth)
  40. // Initialize graphic
  41. nh.Lines.Init(geom, mat)
  42. nh.Update()
  43. return nh
  44. }
  45. // Update should be called in the render loop to
  46. // update the normals based on the target object.
  47. func (nh *NormalsHelper) Update() {
  48. var v1 math32.Vector3
  49. var v2 math32.Vector3
  50. var normalMatrix math32.Matrix3
  51. // Updates the target object matrix and get its normal matrix
  52. matrixWorld := nh.targetNode.MatrixWorld()
  53. normalMatrix.GetNormalMatrix(&matrixWorld)
  54. // Get the target positions and normals buffers
  55. tPosVBO := nh.targetGeometry.VBO(gls.VertexPosition)
  56. tPositions := tPosVBO.Buffer()
  57. tNormVBO := nh.targetGeometry.VBO(gls.VertexNormal)
  58. tNormals := tNormVBO.Buffer()
  59. // Get this object positions buffer
  60. geom := nh.GetGeometry()
  61. posVBO := geom.VBO(gls.VertexPosition)
  62. positions := posVBO.Buffer()
  63. // For each target object vertex position:
  64. for pos := 0; pos < tPositions.Size(); pos += 3 {
  65. // Get the target vertex position and apply the current world matrix transform
  66. // to get the base for this normal line segment.
  67. tPositions.GetVector3(pos, &v1)
  68. v1.ApplyMatrix4(&matrixWorld)
  69. // Calculates the end position of the normal line segment
  70. tNormals.GetVector3(pos, &v2)
  71. v2.ApplyMatrix3(&normalMatrix).Normalize().MultiplyScalar(nh.size).Add(&v1)
  72. // Sets the line segment representing the normal of the current target position
  73. // at this helper VBO
  74. positions.SetVector3(2*pos, &v1)
  75. positions.SetVector3(2*pos+3, &v2)
  76. }
  77. posVBO.Update()
  78. }