0029768: Visualization, TKOpenGl - structure is entirely clipped by suppressed clipping
[occt.git] / src / OpenGl / OpenGl_VertexBuffer.hxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2013-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifndef _OpenGl_VertexBuffer_H__
16 #define _OpenGl_VertexBuffer_H__
17
18 #include <OpenGl_GlCore20.hxx>
19 #include <OpenGl_Resource.hxx>
20 #include <OpenGl_Context.hxx>
21 #include <OpenGl_ShaderProgram.hxx>
22
23 #include <Graphic3d_IndexBuffer.hxx>
24
25 //! Vertex Buffer Object - is a general storage object for vertex attributes (position, normal, color).
26 //! Notice that you should use OpenGl_IndexBuffer specialization for array of indices.
27 class OpenGl_VertexBuffer : public OpenGl_Resource
28 {
29
30 public:
31
32   //! Helpful constants
33   static const GLuint NO_BUFFER = 0;
34
35 public:
36
37   //! Create uninitialized VBO.
38   Standard_EXPORT OpenGl_VertexBuffer();
39
40   //! Destroy object.
41   Standard_EXPORT virtual ~OpenGl_VertexBuffer();
42
43   Standard_EXPORT virtual GLenum GetTarget() const;
44
45   //! @return true if current object was initialized
46   inline bool IsValid() const
47   {
48     return myBufferId != NO_BUFFER;
49   }
50
51   //! @return the number of components per generic vertex attribute.
52   inline GLuint GetComponentsNb() const
53   {
54     return myComponentsNb;
55   }
56
57   //! @return number of vertex attributes / number of vertices.
58   inline GLsizei GetElemsNb() const
59   {
60     return myElemsNb;
61   }
62
63   //! @return data type of each component in the array.
64   inline GLenum GetDataType() const
65   {
66     return myDataType;
67   }
68
69   //! @return offset to data, NULL by default
70   inline GLubyte* GetDataOffset() const
71   {
72     return myOffset;
73   }
74
75   //! Creates VBO name (id) if not yet generated.
76   //! Data should be initialized by another method.
77   Standard_EXPORT virtual bool Create (const Handle(OpenGl_Context)& theGlCtx);
78
79   //! Destroy object - will release GPU memory if any.
80   Standard_EXPORT virtual void Release (OpenGl_Context* theGlCtx) Standard_OVERRIDE;
81
82   //! Bind this VBO.
83   Standard_EXPORT virtual void Bind (const Handle(OpenGl_Context)& theGlCtx) const;
84
85   //! Unbind this VBO.
86   Standard_EXPORT virtual void Unbind (const Handle(OpenGl_Context)& theGlCtx) const;
87
88   //! Notice that VBO will be unbound after this call.
89   //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
90   //! @param theElemsNb      - elements count;
91   //! @param theData         - pointer to GLfloat data (vertices/normals etc.).
92   bool Init (const Handle(OpenGl_Context)& theGlCtx,
93              const GLuint   theComponentsNb,
94              const GLsizei  theElemsNb,
95              const GLfloat* theData)
96   {
97     return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_FLOAT);
98   }
99
100   //! Notice that VBO will be unbound after this call.
101   //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
102   //! @param theElemsNb      - elements count;
103   //! @param theData         - pointer to GLuint data (indices etc.).
104   bool Init (const Handle(OpenGl_Context)& theGlCtx,
105              const GLuint  theComponentsNb,
106              const GLsizei theElemsNb,
107              const GLuint* theData)
108   {
109     return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_INT);
110   }
111
112   //! Notice that VBO will be unbound after this call.
113   //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
114   //! @param theElemsNb      - elements count;
115   //! @param theData         - pointer to GLushort data (indices etc.).
116   bool Init (const Handle(OpenGl_Context)& theGlCtx,
117              const GLuint    theComponentsNb,
118              const GLsizei   theElemsNb,
119              const GLushort* theData)
120   {
121     return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_SHORT);
122   }
123
124   //! Notice that VBO will be unbound after this call.
125   //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
126   //! @param theElemsNb      - elements count;
127   //! @param theData         - pointer to GLubyte data (indices/colors etc.).
128   bool Init (const Handle(OpenGl_Context)& theGlCtx,
129              const GLuint   theComponentsNb,
130              const GLsizei  theElemsNb,
131              const GLubyte* theData)
132   {
133     return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_BYTE);
134   }
135
136   //! Notice that VBO will be unbound after this call.
137   //! Function replaces portion of data within this VBO using glBufferSubData().
138   //! The VBO should be initialized before call.
139   //! @param theElemFrom - element id from which replace buffer data (>=0);
140   //! @param theElemsNb  - elements count (theElemFrom + theElemsNb <= GetElemsNb());
141   //! @param theData     - pointer to GLfloat data.
142   bool SubData (const Handle(OpenGl_Context)& theGlCtx,
143                 const GLsizei  theElemFrom,
144                 const GLsizei  theElemsNb,
145                 const GLfloat* theData)
146   {
147     return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT);
148   }
149
150   //! Notice that VBO will be unbound after this call.
151   //! Function replaces portion of data within this VBO using glBufferSubData().
152   //! The VBO should be initialized before call.
153   //! @param theElemFrom element id from which replace buffer data (>=0);
154   //! @param theElemsNb  elements count (theElemFrom + theElemsNb <= GetElemsNb());
155   //! @param theData     pointer to GLuint data.
156   bool SubData (const Handle(OpenGl_Context)& theGlCtx,
157                 const GLsizei theElemFrom,
158                 const GLsizei theElemsNb,
159                 const GLuint* theData)
160   {
161     return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT);
162   }
163
164   //! Notice that VBO will be unbound after this call.
165   //! Function replaces portion of data within this VBO using glBufferSubData().
166   //! The VBO should be initialized before call.
167   //! @param theElemFrom element id from which replace buffer data (>=0);
168   //! @param theElemsNb  elements count (theElemFrom + theElemsNb <= GetElemsNb());
169   //! @param theData     pointer to GLushort data.
170   bool SubData (const Handle(OpenGl_Context)& theGlCtx,
171                 const GLsizei   theElemFrom,
172                 const GLsizei   theElemsNb,
173                 const GLushort* theData)
174   {
175     return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT);
176   }
177
178   //! Notice that VBO will be unbound after this call.
179   //! Function replaces portion of data within this VBO using glBufferSubData().
180   //! The VBO should be initialized before call.
181   //! @param theElemFrom element id from which replace buffer data (>=0);
182   //! @param theElemsNb  elements count (theElemFrom + theElemsNb <= GetElemsNb());
183   //! @param theData     pointer to GLubyte data.
184   bool SubData (const Handle(OpenGl_Context)& theGlCtx,
185                 const GLsizei  theElemFrom,
186                 const GLsizei  theElemsNb,
187                 const GLubyte* theData)
188   {
189     return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE);
190   }
191
192   //! Bind this VBO to active GLSL program.
193   Standard_EXPORT void BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
194                                          const GLuint                  theAttribLoc) const;
195
196   //! Unbind any VBO from active GLSL program.
197   Standard_EXPORT void UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
198                                            const GLuint                  theAttribLoc) const;
199
200   //! Bind this VBO and enable specified attribute in OpenGl_Context::ActiveProgram() or FFP.
201   //! @param theGlCtx - handle to bound GL context;
202   //! @param theMode  - array mode (GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY).
203   void BindAttribute (const Handle(OpenGl_Context)&   theCtx,
204                       const Graphic3d_TypeOfAttribute theMode) const
205   {
206     if (IsValid())
207     {
208       Bind (theCtx);
209       bindAttribute (theCtx, theMode, static_cast<GLint> (myComponentsNb), myDataType, 0, myOffset);
210     }
211   }
212
213   //! Unbind this VBO and disable specified attribute in OpenGl_Context::ActiveProgram() or FFP.
214   //! @param theCtx handle to bound GL context
215   //! @param theMode  array mode
216   void UnbindAttribute (const Handle(OpenGl_Context)&   theCtx,
217                         const Graphic3d_TypeOfAttribute theMode) const
218   {
219     if (IsValid())
220     {
221       Unbind (theCtx);
222       unbindAttribute (theCtx, theMode);
223     }
224   }
225
226 public: //! @name advanced methods
227
228   //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
229   virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE
230   {
231     return IsValid()
232          ? sizeOfGlType (myDataType) * myComponentsNb * myElemsNb
233          : 0;
234   }
235
236   //! @return size of specified GL type
237   static size_t sizeOfGlType (const GLenum theType)
238   {
239     switch (theType)
240     {
241       case GL_BYTE:
242       case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);
243       case GL_SHORT:
244       case GL_UNSIGNED_SHORT: return sizeof(GLushort);
245     #ifdef GL_INT
246       case GL_INT:
247     #endif
248       case GL_UNSIGNED_INT:   return sizeof(GLuint);
249       case GL_FLOAT:          return sizeof(GLfloat);
250     #ifdef GL_DOUBLE
251       case GL_DOUBLE:         return sizeof(GLdouble);
252     #endif
253       default:                return 0;
254     }
255   }
256
257   //! Initialize buffer with new data.
258   Standard_EXPORT virtual bool init (const Handle(OpenGl_Context)& theGlCtx,
259                                      const GLuint   theComponentsNb,
260                                      const GLsizei  theElemsNb,
261                                      const void*    theData,
262                                      const GLenum   theDataType,
263                                      const GLsizei  theStride);
264
265   //! Initialize buffer with new data.
266   bool init (const Handle(OpenGl_Context)& theGlCtx,
267              const GLuint   theComponentsNb,
268              const GLsizei  theElemsNb,
269              const void*    theData,
270              const GLenum   theDataType)
271   {
272     return init (theGlCtx, theComponentsNb, theElemsNb, theData, theDataType, GLsizei(theComponentsNb) * GLsizei(sizeOfGlType (theDataType)));
273   }
274
275   //! Update part of the buffer with new data.
276   Standard_EXPORT virtual bool subData (const Handle(OpenGl_Context)& theGlCtx,
277                                         const GLsizei  theElemFrom,
278                                         const GLsizei  theElemsNb,
279                                         const void*    theData,
280                                         const GLenum   theDataType);
281
282   //! Setup array pointer - either for active GLSL program OpenGl_Context::ActiveProgram()
283   //! or for FFP using bindFixed() when no program bound.
284   static void bindAttribute (const Handle(OpenGl_Context)&   theGlCtx,
285                              const Graphic3d_TypeOfAttribute theMode,
286                              const GLint                     theNbComp,
287                              const GLenum                    theDataType,
288                              const GLsizei                   theStride,
289                              const GLvoid*                   theOffset);
290
291   //! Disable GLSL array pointer - either for active GLSL program OpenGl_Context::ActiveProgram()
292   //! or for FFP using unbindFixed() when no program bound.
293   static void unbindAttribute (const Handle(OpenGl_Context)&   theGlCtx,
294                                const Graphic3d_TypeOfAttribute theMode);
295
296 private:
297 #if !defined(GL_ES_VERSION_2_0)
298   //! Setup FFP array pointer.
299   static void bindFixed (const Handle(OpenGl_Context)&   theGlCtx,
300                          const Graphic3d_TypeOfAttribute theMode,
301                          const GLint                     theNbComp,
302                          const GLenum                    theDataType,
303                          const GLsizei                   theStride,
304                          const GLvoid*                   theOffset);
305
306   //! Disable FFP array pointer.
307   static void unbindFixed (const Handle(OpenGl_Context)&   theGlCtx,
308                            const Graphic3d_TypeOfAttribute theMode);
309
310   //! Disable FFP color array pointer.
311   Standard_EXPORT static void unbindFixedColor (const Handle(OpenGl_Context)& theCtx);
312
313 #endif
314 public: //! @name methods for interleaved attributes array
315
316   //! @return true if buffer contains per-vertex color attribute
317   Standard_EXPORT virtual bool HasColorAttribute() const;
318
319   //! @return true if buffer contains per-vertex normal attribute
320   Standard_EXPORT virtual bool HasNormalAttribute() const;
321
322   //! Bind all vertex attributes to active program OpenGl_Context::ActiveProgram() or for FFP.
323   //! Default implementation does nothing.
324   Standard_EXPORT virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const;
325
326   //! Bind vertex position attribute only. Default implementation does nothing.
327   Standard_EXPORT virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const;
328
329   //! Unbind all vertex attributes. Default implementation does nothing.
330   Standard_EXPORT virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const;
331
332 protected:
333
334   GLubyte* myOffset;       //!< offset to data
335   GLuint   myBufferId;     //!< VBO name (index)
336   GLuint   myComponentsNb; //!< Number of components per generic vertex attribute, must be 1, 2, 3, or 4
337   GLsizei  myElemsNb;      //!< Number of vertex attributes / number of vertices
338   GLenum   myDataType;     //!< Data type (GL_FLOAT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE etc.)
339
340 public:
341
342   DEFINE_STANDARD_RTTIEXT(OpenGl_VertexBuffer,OpenGl_Resource) // Type definition
343
344 };
345
346 DEFINE_STANDARD_HANDLE(OpenGl_VertexBuffer, OpenGl_Resource)
347
348 #include <OpenGl_VertexBuffer.lxx>
349
350 #endif // _OpenGl_VertexBuffer_H__