0027341: Incorrect exact HLR results
[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   //! @return size of specified GL type
229   static size_t sizeOfGlType (const GLenum theType)
230   {
231     switch (theType)
232     {
233       case GL_BYTE:
234       case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);
235       case GL_SHORT:
236       case GL_UNSIGNED_SHORT: return sizeof(GLushort);
237     #ifdef GL_INT
238       case GL_INT:
239     #endif
240       case GL_UNSIGNED_INT:   return sizeof(GLuint);
241       case GL_FLOAT:          return sizeof(GLfloat);
242     #ifdef GL_DOUBLE
243       case GL_DOUBLE:         return sizeof(GLdouble);
244     #endif
245       default:                return 0;
246     }
247   }
248
249   //! Initialize buffer with new data.
250   Standard_EXPORT virtual bool init (const Handle(OpenGl_Context)& theGlCtx,
251                                      const GLuint   theComponentsNb,
252                                      const GLsizei  theElemsNb,
253                                      const void*    theData,
254                                      const GLenum   theDataType,
255                                      const GLsizei  theStride);
256
257   //! Initialize buffer with new data.
258   bool init (const Handle(OpenGl_Context)& theGlCtx,
259              const GLuint   theComponentsNb,
260              const GLsizei  theElemsNb,
261              const void*    theData,
262              const GLenum   theDataType)
263   {
264     return init (theGlCtx, theComponentsNb, theElemsNb, theData, theDataType, GLsizei(theComponentsNb) * GLsizei(sizeOfGlType (theDataType)));
265   }
266
267   //! Update part of the buffer with new data.
268   Standard_EXPORT virtual bool subData (const Handle(OpenGl_Context)& theGlCtx,
269                                         const GLsizei  theElemFrom,
270                                         const GLsizei  theElemsNb,
271                                         const void*    theData,
272                                         const GLenum   theDataType);
273
274   //! Setup array pointer - either for active GLSL program OpenGl_Context::ActiveProgram()
275   //! or for FFP using bindFixed() when no program bound.
276   static void bindAttribute (const Handle(OpenGl_Context)&   theGlCtx,
277                              const Graphic3d_TypeOfAttribute theMode,
278                              const GLint                     theNbComp,
279                              const GLenum                    theDataType,
280                              const GLsizei                   theStride,
281                              const GLvoid*                   theOffset);
282
283   //! Disable GLSL array pointer - either for active GLSL program OpenGl_Context::ActiveProgram()
284   //! or for FFP using unbindFixed() when no program bound.
285   static void unbindAttribute (const Handle(OpenGl_Context)&   theGlCtx,
286                                const Graphic3d_TypeOfAttribute theMode);
287
288 private:
289 #if !defined(GL_ES_VERSION_2_0)
290   //! Setup FFP array pointer.
291   static void bindFixed (const Handle(OpenGl_Context)&   theGlCtx,
292                          const Graphic3d_TypeOfAttribute theMode,
293                          const GLint                     theNbComp,
294                          const GLenum                    theDataType,
295                          const GLsizei                   theStride,
296                          const GLvoid*                   theOffset);
297
298   //! Disable FFP array pointer.
299   static void unbindFixed (const Handle(OpenGl_Context)&   theGlCtx,
300                            const Graphic3d_TypeOfAttribute theMode);
301 #endif
302 public: //! @name methods for interleaved attributes array
303
304   //! @return true if buffer contains per-vertex color attribute
305   Standard_EXPORT virtual bool HasColorAttribute() const;
306
307   //! @return true if buffer contains per-vertex normal attribute
308   Standard_EXPORT virtual bool HasNormalAttribute() const;
309
310   //! Bind all vertex attributes to active program OpenGl_Context::ActiveProgram() or for FFP.
311   //! Default implementation does nothing.
312   Standard_EXPORT virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const;
313
314   //! Bind vertex position attribute only. Default implementation does nothing.
315   Standard_EXPORT virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const;
316
317   //! Unbind all vertex attributes. Default implementation does nothing.
318   Standard_EXPORT virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const;
319
320 protected:
321
322   GLubyte* myOffset;       //!< offset to data
323   GLuint   myBufferId;     //!< VBO name (index)
324   GLuint   myComponentsNb; //!< Number of components per generic vertex attribute, must be 1, 2, 3, or 4
325   GLsizei  myElemsNb;      //!< Number of vertex attributes / number of vertices
326   GLenum   myDataType;     //!< Data type (GL_FLOAT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE etc.)
327
328 public:
329
330   DEFINE_STANDARD_RTTIEXT(OpenGl_VertexBuffer,OpenGl_Resource) // Type definition
331
332 };
333
334 DEFINE_STANDARD_HANDLE(OpenGl_VertexBuffer, OpenGl_Resource)
335
336 #include <OpenGl_VertexBuffer.lxx>
337
338 #endif // _OpenGl_VertexBuffer_H__