graphic.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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 implements scene objects which have a graphic representation.
  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. "github.com/g3n/engine/math32"
  12. "github.com/g3n/engine/util/logger"
  13. )
  14. // Package logger
  15. var log = logger.New("GRAPHIC", logger.Default)
  16. // IGraphic is the interface for all Graphic objects.
  17. type IGraphic interface {
  18. core.INode
  19. GetGraphic() *Graphic
  20. GetGeometry() *geometry.Geometry
  21. IGeometry() geometry.IGeometry
  22. SetRenderable(bool)
  23. Renderable() bool
  24. SetCullable(bool)
  25. Cullable() bool
  26. RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo)
  27. }
  28. // Graphic is a Node which has a visible representation in the scene.
  29. // It has an associated geometry and one or more materials.
  30. // It is the base type used by other graphics such as lines, line_strip,
  31. // points and meshes.
  32. type Graphic struct {
  33. core.Node // Embedded Node
  34. igeom geometry.IGeometry // Associated IGeometry
  35. materials []GraphicMaterial // Materials
  36. mode uint32 // OpenGL primitive
  37. renderable bool // Renderable flag
  38. cullable bool // Cullable flag
  39. renderOrder int // Render order
  40. ShaderDefines gls.ShaderDefines // Graphic-specific shader defines
  41. mm math32.Matrix4 // Cached Model matrix
  42. mvm math32.Matrix4 // Cached ModelView matrix
  43. mvpm math32.Matrix4 // Cached ModelViewProjection matrix
  44. }
  45. // NewGraphic creates and returns a pointer to a new graphic object with
  46. // the specified geometry and OpenGL primitive.
  47. // The created graphic object, though, has not materials.
  48. func NewGraphic(igr IGraphic, igeom geometry.IGeometry, mode uint32) *Graphic {
  49. gr := new(Graphic)
  50. return gr.Init(igr, igeom, mode)
  51. }
  52. // Init initializes a Graphic type embedded in another type
  53. // with the specified geometry and OpenGL mode.
  54. func (gr *Graphic) Init(igr IGraphic, igeom geometry.IGeometry, mode uint32) *Graphic {
  55. gr.Node.Init(igr)
  56. gr.igeom = igeom
  57. gr.mode = mode
  58. gr.materials = make([]GraphicMaterial, 0)
  59. gr.renderable = true
  60. gr.cullable = true
  61. gr.ShaderDefines = *gls.NewShaderDefines()
  62. return gr
  63. }
  64. // GetGraphic satisfies the IGraphic interface and
  65. // returns pointer to the base Graphic.
  66. func (gr *Graphic) GetGraphic() *Graphic {
  67. return gr
  68. }
  69. // GetGeometry satisfies the IGraphic interface and returns
  70. // a pointer to the geometry associated with this graphic.
  71. func (gr *Graphic) GetGeometry() *geometry.Geometry {
  72. return gr.igeom.GetGeometry()
  73. }
  74. // IGeometry satisfies the IGraphic interface and returns
  75. // a pointer to the IGeometry associated with this graphic.
  76. func (gr *Graphic) IGeometry() geometry.IGeometry {
  77. return gr.igeom
  78. }
  79. // Dispose overrides the embedded Node Dispose method.
  80. func (gr *Graphic) Dispose() {
  81. gr.igeom.Dispose()
  82. for i := 0; i < len(gr.materials); i++ {
  83. gr.materials[i].imat.Dispose()
  84. }
  85. }
  86. // Clone clones the graphic and satisfies the INode interface.
  87. // It should be called by Clone() implementations of IGraphic.
  88. // Note that the topmost implementation calling this method needs
  89. // to call clone.SetIGraphic(igraphic) after calling this method.
  90. func (gr *Graphic) Clone() core.INode {
  91. clone := new(Graphic)
  92. clone.Node = *gr.Node.Clone().(*core.Node)
  93. clone.igeom = gr.igeom
  94. clone.mode = gr.mode
  95. clone.renderable = gr.renderable
  96. clone.cullable = gr.cullable
  97. clone.renderOrder = gr.renderOrder
  98. clone.ShaderDefines = gr.ShaderDefines
  99. clone.materials = make([]GraphicMaterial, len(gr.materials))
  100. for i, grmat := range gr.materials {
  101. clone.materials[i] = grmat
  102. }
  103. return clone
  104. }
  105. // SetRenderable satisfies the IGraphic interface and
  106. // sets the renderable state of this Graphic (default = true).
  107. func (gr *Graphic) SetRenderable(state bool) {
  108. gr.renderable = state
  109. }
  110. // Renderable satisfies the IGraphic interface and
  111. // returns the renderable state of this graphic.
  112. func (gr *Graphic) Renderable() bool {
  113. return gr.renderable
  114. }
  115. // SetCullable satisfies the IGraphic interface and
  116. // sets the cullable state of this Graphic (default = true).
  117. func (gr *Graphic) SetCullable(state bool) {
  118. gr.cullable = state
  119. }
  120. // Cullable satisfies the IGraphic interface and
  121. // returns the cullable state of this graphic.
  122. func (gr *Graphic) Cullable() bool {
  123. return gr.cullable
  124. }
  125. // SetRenderOrder sets the render order of the object.
  126. // All objects have renderOrder of 0 by default.
  127. // To render before renderOrder 0 set a lower renderOrder e.g. -1.
  128. // To render after renderOrder 0 set a higher renderOrder e.g. 1
  129. func (gr *Graphic) SetRenderOrder(order int) {
  130. gr.renderOrder = order
  131. }
  132. // RenderOrder returns the render order of the object.
  133. func (gr *Graphic) RenderOrder() int {
  134. return gr.renderOrder
  135. }
  136. // AddMaterial adds a material for the specified subset of vertices.
  137. // If the material applies to all vertices, start and count must be 0.
  138. func (gr *Graphic) AddMaterial(igr IGraphic, imat material.IMaterial, start, count int) {
  139. gmat := GraphicMaterial{
  140. imat: imat,
  141. start: start,
  142. count: count,
  143. igraphic: igr,
  144. }
  145. gr.materials = append(gr.materials, gmat)
  146. }
  147. // AddGroupMaterial adds a material for the specified geometry group.
  148. func (gr *Graphic) AddGroupMaterial(igr IGraphic, imat material.IMaterial, gindex int) {
  149. geom := gr.igeom.GetGeometry()
  150. if gindex < 0 || gindex >= geom.GroupCount() {
  151. panic("Invalid group index")
  152. }
  153. group := geom.GroupAt(gindex)
  154. gr.AddMaterial(igr, imat, group.Start, group.Count)
  155. }
  156. // Materials returns slice with this graphic materials.
  157. func (gr *Graphic) Materials() []GraphicMaterial {
  158. return gr.materials
  159. }
  160. // GetMaterial returns the material associated with the specified vertex position.
  161. func (gr *Graphic) GetMaterial(vpos int) material.IMaterial {
  162. for _, gmat := range gr.materials {
  163. // Case for unimaterial
  164. if gmat.count == 0 {
  165. return gmat.imat
  166. }
  167. if gmat.start <= vpos && gmat.start+gmat.count >= vpos {
  168. return gmat.imat
  169. }
  170. }
  171. return nil
  172. }
  173. // ClearMaterials removes all the materials from this Graphic.
  174. func (gr *Graphic) ClearMaterials() {
  175. gr.materials = gr.materials[0:0]
  176. }
  177. // SetIGraphic sets the IGraphic on all this Graphic's GraphicMaterials.
  178. func (gr *Graphic) SetIGraphic(igr IGraphic) {
  179. for i := range gr.materials {
  180. gr.materials[i].igraphic = igr
  181. }
  182. }
  183. // BoundingBox recursively calculates and returns the bounding box
  184. // containing this node and all its children.
  185. func (gr *Graphic) BoundingBox() math32.Box3 {
  186. geom := gr.igeom.GetGeometry()
  187. bbox := geom.BoundingBox()
  188. for _, inode := range gr.Children() {
  189. childGraphic, ok := inode.(*Graphic)
  190. if ok {
  191. childBbox := childGraphic.BoundingBox()
  192. bbox.Union(&childBbox)
  193. }
  194. }
  195. return bbox
  196. }
  197. // CalculateMatrices calculates the model view and model view projection matrices.
  198. func (gr *Graphic) CalculateMatrices(gs *gls.GLS, rinfo *core.RenderInfo) {
  199. gr.mm = gr.MatrixWorld()
  200. gr.mvm.MultiplyMatrices(&rinfo.ViewMatrix, &gr.mm)
  201. gr.mvpm.MultiplyMatrices(&rinfo.ProjMatrix, &gr.mvm)
  202. }
  203. // ModelViewMatrix returns the last cached model view matrix for this graphic.
  204. func (gr *Graphic) ModelMatrix() *math32.Matrix4 {
  205. return &gr.mm
  206. }
  207. // ModelViewMatrix returns the last cached model view matrix for this graphic.
  208. func (gr *Graphic) ModelViewMatrix() *math32.Matrix4 {
  209. return &gr.mvm
  210. }
  211. // ModelViewProjectionMatrix returns the last cached model view projection matrix for this graphic.
  212. func (gr *Graphic) ModelViewProjectionMatrix() *math32.Matrix4 {
  213. return &gr.mvpm
  214. }
  215. // GraphicMaterial specifies the material to be used for
  216. // a subset of vertices from the Graphic geometry
  217. // A Graphic object has at least one GraphicMaterial.
  218. type GraphicMaterial struct {
  219. imat material.IMaterial // Associated material
  220. start int // Index of first element in the geometry
  221. count int // Number of elements
  222. igraphic IGraphic // Graphic which contains this GraphicMaterial
  223. }
  224. // IMaterial returns the material associated with the GraphicMaterial.
  225. func (grmat *GraphicMaterial) IMaterial() material.IMaterial {
  226. return grmat.imat
  227. }
  228. // IGraphic returns the graphic associated with the GraphicMaterial.
  229. func (grmat *GraphicMaterial) IGraphic() IGraphic {
  230. return grmat.igraphic
  231. }
  232. // Render is called by the renderer to render this graphic material.
  233. func (grmat *GraphicMaterial) Render(gs *gls.GLS, rinfo *core.RenderInfo) {
  234. // Setup the associated material (set states and transfer material uniforms and textures)
  235. grmat.imat.RenderSetup(gs)
  236. // Setup the associated geometry (set VAO and transfer VBOS)
  237. gr := grmat.igraphic.GetGraphic()
  238. gr.igeom.RenderSetup(gs)
  239. // Setup current graphic (transfer matrices)
  240. grmat.igraphic.RenderSetup(gs, rinfo)
  241. // Get the number of vertices for the current material
  242. count := grmat.count
  243. geom := gr.igeom.GetGeometry()
  244. indices := geom.Indices()
  245. // Indexed geometry
  246. if indices.Size() > 0 {
  247. if count == 0 {
  248. count = indices.Size()
  249. }
  250. gs.DrawElements(gr.mode, int32(count), gls.UNSIGNED_INT, 4*uint32(grmat.start))
  251. // Non indexed geometry
  252. } else {
  253. if count == 0 {
  254. count = geom.Items()
  255. }
  256. gs.DrawArrays(gr.mode, int32(grmat.start), int32(count))
  257. }
  258. }