0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / OpenGl / OpenGl_VertexBufferEditor.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_VertexBufferEditor_H__
16 #define _OpenGl_VertexBufferEditor_H__
17
18 #include <OpenGl_VertexBuffer.hxx>
19 #include <OpenGl_Context.hxx>
20
21 #include <NCollection_Array1.hxx>
22
23 //! Auxiliary class to iteratively modify data of existing VBO.
24 //! It provides iteration interface with delayed CPU->GPU memory transfer to avoid slow per-element data transfer.
25 //! User should explicitly call Flush() method to ensure that all data is transferred to VBO.
26 //! Temporary buffer on CPU side can be initialized with lesser capacity than  VBO
27 //! to allow re-usage of shared buffer with fixed size between VBOs.
28 //!
29 //! You should use NCollection_Vec2/NCollection_Vec3/NCollection_Vec4 with appropriate length
30 //! to instantiate this template and access elements in VBO.
31 //!
32 //! Notice that this technique designed for VBO streaming scenarios (when VBO is modified from time to time).
33 //! Also this class doesn't retrieve existing data from VBO - data transferred only in one direction!
34 //! In case of static data this is preferred to upload it within one call during VBO initialization.
35 template<typename theVec_t>
36 class OpenGl_VertexBufferEditor
37 {
38
39 public:
40
41   //! Creates empty editor
42   //! theTmpBufferLength - temporary buffer length
43   OpenGl_VertexBufferEditor (const Standard_Integer theTmpBufferLength = 0)
44   : myElemFrom (0),
45     myElemsNb (0),
46     myTmpBuffer (0, theTmpBufferLength > 0 ? (theTmpBufferLength - 1) : 2047) {}
47
48   //! Creates empty editor
49   //! theTmpBuffer       - pointer to temporary buffer
50   //! theTmpBufferLength - temporary buffer length
51   OpenGl_VertexBufferEditor (theVec_t*              theTmpBuffer,
52                              const Standard_Integer theTmpBufferLength)
53   : myElemFrom (0),
54     myElemsNb (0),
55     myTmpBuffer (theTmpBuffer[0], 0, theTmpBufferLength - 1) {}
56
57   //! Initialize editor for specified VBO.
58   //! theGlCtx - bound OpenGL context to edit VBO
59   //! theVbo   - VBO to edit
60   Standard_Boolean Init (const Handle(OpenGl_Context)&      theGlCtx,
61                          const Handle(OpenGl_VertexBuffer)& theVbo)
62   {
63     myGlCtx = theGlCtx;
64     myVbo   = theVbo;
65     if (myGlCtx.IsNull() || myVbo.IsNull() || !myVbo->IsValid() || myVbo->GetComponentsNb() != GLuint (theVec_t::Length()))
66     {
67       return Standard_False;
68     }
69
70     myElemFrom = myElemsNb = 0;
71     return Standard_True;
72   }
73
74   //! Modify current element in VBO.
75   theVec_t& Value()
76   {
77     return myTmpBuffer.ChangeValue (myElemsNb);
78   }
79
80   //! Move to the next position in VBO.
81   Standard_Boolean Next()
82   {
83     if (++myElemsNb > myTmpBuffer.Upper())
84     {
85       return Flush();
86     }
87     return Standard_True;
88   }
89
90   //! Push current data from local buffer to VBO.
91   Standard_Boolean Flush()
92   {
93     if (myElemsNb <= 0)
94     {
95       return Standard_True;
96     }
97
98     if (myVbo.IsNull()
99      || !myVbo->SubData (myGlCtx, myElemFrom, myElemsNb, &myTmpBuffer.Value (0)[0]))
100     {
101       // should never happens
102       return Standard_False;
103     }
104     myElemFrom += myElemsNb;
105     myElemsNb = 0;
106
107     return Standard_True;
108   }
109
110   //! @return assigned VBO
111   inline const Handle(OpenGl_VertexBuffer)& GetVBO() const
112   {
113     return myVbo;
114   }
115
116 private:
117
118   Handle(OpenGl_Context)       myGlCtx;     //!< handle to current OpenGL context
119   Handle(OpenGl_VertexBuffer)  myVbo;       //!< edited VBO
120   Standard_Integer             myElemFrom;  //!< element in VBO to upload from
121   Standard_Integer             myElemsNb;   //!< current element in temporary buffer
122   NCollection_Array1<theVec_t> myTmpBuffer; //!< temporary array
123
124 };
125
126 #endif // _OpenGl_VertexBufferEditor_H__