normals.go 2.8 KB

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