graphic.go 5.8 KB

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