circle.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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 geometry
  5. import (
  6. "github.com/g3n/engine/gls"
  7. "github.com/g3n/engine/math32"
  8. "math"
  9. )
  10. // Circle represents the geometry of a filled circle (i.e. a disk)
  11. // The center of the circle is at the origin, and theta runs counter-clockwise
  12. // on the XY plane, starting at (x,y,z)=(1,0,0).
  13. type Circle struct {
  14. Geometry
  15. Radius float64
  16. Segments int // >= 3
  17. ThetaStart float64
  18. ThetaLength float64
  19. }
  20. // NewCircle creates a new circle geometry with the specified radius
  21. // and number of radial segments/triangles (minimum 3).
  22. func NewCircle(radius float64, segments int) *Circle {
  23. return NewCircleSector(radius, segments, 0, 2*math.Pi)
  24. }
  25. // NewCircleSector creates a new circle or circular sector geometry with the specified radius,
  26. // number of radial segments/triangles (minimum 3), sector start angle in radians (thetaStart),
  27. // and sector size angle in radians (thetaLength). This is the Circle constructor with most tunable parameters.
  28. func NewCircleSector(radius float64, segments int, thetaStart, thetaLength float64) *Circle {
  29. circ := new(Circle)
  30. circ.Geometry.Init()
  31. // Validate arguments
  32. if segments < 3 {
  33. panic("Invalid argument: segments. The number of segments needs to be greater or equal to 3.")
  34. }
  35. circ.Radius = radius
  36. circ.Segments = segments
  37. circ.ThetaStart = thetaStart
  38. circ.ThetaLength = thetaLength
  39. // Create buffers
  40. positions := math32.NewArrayF32(0, 16)
  41. normals := math32.NewArrayF32(0, 16)
  42. uvs := math32.NewArrayF32(0, 16)
  43. indices := math32.NewArrayU32(0, 16)
  44. // Append circle center position
  45. center := math32.NewVector3(0, 0, 0)
  46. positions.AppendVector3(center)
  47. // Append circle center normal
  48. var normal math32.Vector3
  49. normal.Z = 1
  50. normals.AppendVector3(&normal)
  51. // Append circle center uv coordinate
  52. centerUV := math32.NewVector2(0.5, 0.5)
  53. uvs.AppendVector2(centerUV)
  54. // Generate the segments
  55. for i := 0; i <= segments; i++ {
  56. segment := thetaStart + float64(i)/float64(segments)*thetaLength
  57. vx := float32(radius * math.Cos(segment))
  58. vy := float32(radius * math.Sin(segment))
  59. // Appends vertex position, normal and uv coordinates
  60. positions.Append(vx, vy, 0)
  61. normals.AppendVector3(&normal)
  62. uvs.Append((vx/float32(radius)+1)/2, (vy/float32(radius)+1)/2)
  63. }
  64. for i := 1; i <= segments; i++ {
  65. indices.Append(uint32(i), uint32(i)+1, 0)
  66. }
  67. circ.SetIndices(indices)
  68. circ.AddVBO(gls.NewVBO().AddAttrib("VertexPosition", 3).SetBuffer(positions))
  69. circ.AddVBO(gls.NewVBO().AddAttrib("VertexNormal", 3).SetBuffer(normals))
  70. circ.AddVBO(gls.NewVBO().AddAttrib("VertexTexcoord", 2).SetBuffer(uvs))
  71. // Update volume
  72. circ.volume = 0
  73. circ.volumeValid = true
  74. return circ
  75. }