graphic.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. package graphic
  6. import (
  7. "github.com/g3n/engine/core"
  8. "github.com/g3n/engine/geometry"
  9. "github.com/g3n/engine/gls"
  10. "github.com/g3n/engine/material"
  11. )
  12. // Graphic is a Node which has a visible representation in the scene.
  13. // It has an associated geometry and one or more materials.
  14. // It is the base type used by other graphics such as lines, line_strip,
  15. // points and meshes.
  16. type Graphic struct {
  17. core.Node // Embedded Node
  18. igeom geometry.IGeometry // Associated IGeometry
  19. materials []GraphicMaterial // Materials
  20. mode uint32 // OpenGL primitive
  21. renderable bool // Renderable flag
  22. }
  23. // GraphicMaterial specifies the material to be used for
  24. // a subset of vertices from the Graphic geometry
  25. // A Graphic object has at least one GraphicMaterial
  26. type GraphicMaterial struct {
  27. imat material.IMaterial // Associated material
  28. start int // Index of first element in the geometry
  29. count int // Number of elements
  30. igraphic IGraphic // Graphic which contains this GraphicMaterial
  31. }
  32. // Interface for all Graphics
  33. type IGraphic interface {
  34. core.INode
  35. GetGraphic() *Graphic
  36. GetGeometry() *geometry.Geometry
  37. Renderable() bool
  38. SetRenderable(bool)
  39. RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo)
  40. }
  41. // Init initializes a Graphic type embedded in another type
  42. // with the specified geometry and OpenGL mode.
  43. func (gr *Graphic) Init(igeom geometry.IGeometry, mode uint32) *Graphic {
  44. gr.Node.Init()
  45. gr.igeom = igeom
  46. gr.mode = mode
  47. gr.materials = make([]GraphicMaterial, 0)
  48. gr.renderable = true
  49. return gr
  50. }
  51. // GetGraphic satisfies the IGraphic interface and
  52. // returns pointer to the base Graphic
  53. func (gr *Graphic) GetGraphic() *Graphic {
  54. return gr
  55. }
  56. // GetGeometry satisfies the IGraphic interface and returns
  57. // a pointer to the geometry associated with this graphic
  58. func (gr *Graphic) GetGeometry() *geometry.Geometry {
  59. return gr.igeom.GetGeometry()
  60. }
  61. // Dispose overrides the embedded Node Dispose method
  62. func (gr *Graphic) Dispose() {
  63. gr.igeom.Dispose()
  64. for i := 0; i < len(gr.materials); i++ {
  65. gr.materials[i].imat.Dispose()
  66. }
  67. }
  68. // SetRenderable satisfies the IGraphic interface and
  69. // sets the renderable state of this Graphic (default = true)
  70. func (gr *Graphic) SetRenderable(state bool) {
  71. gr.renderable = state
  72. }
  73. // Renderable satisfies the IGraphic interface and
  74. // returns the renderable state of this graphic
  75. func (gr *Graphic) Renderable() bool {
  76. return gr.renderable
  77. }
  78. // Add material for the specified subset of vertices.
  79. // If the material applies to all vertices, start and count must be 0.
  80. func (gr *Graphic) AddMaterial(igr IGraphic, imat material.IMaterial, start, count int) {
  81. gmat := GraphicMaterial{
  82. imat: imat,
  83. start: start,
  84. count: count,
  85. igraphic: igr,
  86. }
  87. gr.materials = append(gr.materials, gmat)
  88. }
  89. // Add group material
  90. func (gr *Graphic) AddGroupMaterial(igr IGraphic, imat material.IMaterial, gindex int) {
  91. geom := gr.igeom.GetGeometry()
  92. if gindex < 0 || gindex >= geom.GroupCount() {
  93. panic("Invalid group index")
  94. }
  95. group := geom.GroupAt(gindex)
  96. gr.AddMaterial(igr, imat, group.Start, group.Count)
  97. }
  98. // Materials returns slice with this graphic materials
  99. func (gr *Graphic) Materials() []GraphicMaterial {
  100. return gr.materials
  101. }
  102. // GetMaterial returns the material associated with the specified vertex position
  103. func (gr *Graphic) GetMaterial(vpos int) material.IMaterial {
  104. for _, gmat := range gr.materials {
  105. // Case for unimaterial
  106. if gmat.count == 0 {
  107. return gmat.imat
  108. }
  109. if gmat.start >= vpos && gmat.start+gmat.count <= vpos {
  110. return gmat.imat
  111. }
  112. }
  113. return nil
  114. }
  115. func (grmat *GraphicMaterial) GetMaterial() material.IMaterial {
  116. return grmat.imat
  117. }
  118. // Render is called by the renderer to render this graphic material
  119. func (grmat *GraphicMaterial) Render(gs *gls.GLS, rinfo *core.RenderInfo) {
  120. // Setup the associated material (set states and transfer material uniforms and textures)
  121. grmat.imat.RenderSetup(gs)
  122. // Setup the associated geometry (set VAO and transfer VBOS)
  123. gr := grmat.igraphic.GetGraphic()
  124. gr.igeom.RenderSetup(gs)
  125. // Setup current graphic (transfer matrices)
  126. grmat.igraphic.RenderSetup(gs, rinfo)
  127. // Get the number of vertices for the current material
  128. count := grmat.count
  129. geom := gr.igeom.GetGeometry()
  130. indices := geom.Indices()
  131. // Indexed geometry
  132. if indices.Size() > 0 {
  133. if count == 0 {
  134. count = indices.Size()
  135. }
  136. gs.DrawElements(gr.mode, int32(count), gls.UNSIGNED_INT, 4 * uint32(grmat.start))
  137. // Non indexed geometry
  138. } else {
  139. if count == 0 {
  140. count = geom.Items()
  141. }
  142. gs.DrawArrays(gr.mode, int32(grmat.start), int32(count))
  143. }
  144. }