BGE modifier: generate correct physic shape, share static derived mesh, share display...
[blender-staging.git] / source / gameengine / Rasterizer / RAS_OpenGLRasterizer / RAS_ListRasterizer.cpp
1 //
2 #include <iostream>
3
4 #include "RAS_ListRasterizer.h"
5
6 #ifdef WIN32
7 #include <windows.h>
8 #endif // WIN32
9
10 #include "GL/glew.h"
11
12 #include "RAS_MaterialBucket.h"
13 #include "RAS_TexVert.h"
14 #include "MT_assert.h"
15
16 //#ifndef NDEBUG
17 //#ifdef WIN32
18 //#define spit(x) std::cout << x << std::endl;
19 //#endif //WIN32
20 //#else
21 #define spit(x)
22 //#endif
23
24 RAS_ListSlot::RAS_ListSlot(RAS_ListRasterizer* rasty)
25 :       KX_ListSlot(),
26         m_list(0),
27         m_flag(LIST_MODIFY|LIST_CREATE),
28         m_rasty(rasty)
29 {
30 }
31
32 int RAS_ListSlot::Release()
33 {
34         if (--m_refcount > 0)
35                 return m_refcount;
36         m_rasty->RemoveListSlot(this);
37         delete this;
38         return 0;
39 }
40
41 RAS_ListSlot::~RAS_ListSlot()
42 {
43         RemoveList();
44 }
45
46
47 void RAS_ListSlot::RemoveList()
48 {
49         if(m_list != 0) {
50                 spit("Releasing display list (" << m_list << ")");
51                 glDeleteLists((GLuint)m_list, 1);
52                 m_list =0;
53         }
54 }
55
56 void RAS_ListSlot::DrawList()
57 {
58         if(m_flag &LIST_STREAM || m_flag& LIST_NOCREATE) {
59                 RemoveList();
60                 return;
61         }
62         if(m_flag &LIST_MODIFY) {
63                 if(m_flag &LIST_CREATE) {
64                         if(m_list == 0) {
65                                 m_list = (unsigned int)glGenLists(1);
66                                 m_flag =  m_flag &~ LIST_CREATE;
67                                 spit("Created display list (" << m_list << ")");
68                         }
69                 }
70                 if(m_list != 0)
71                         glNewList((GLuint)m_list, GL_COMPILE);
72         
73                 m_flag |= LIST_BEGIN;
74                 return;
75         }
76         glCallList(m_list);
77 }
78
79 void RAS_ListSlot::EndList()
80 {
81         if(m_flag & LIST_BEGIN) {
82                 glEndList();
83                 m_flag = m_flag &~(LIST_BEGIN|LIST_MODIFY);
84                 m_flag |= LIST_END;
85                 glCallList(m_list);
86         }
87 }
88
89 void RAS_ListSlot::SetModified(bool mod)
90 {
91         if(mod && !(m_flag & LIST_MODIFY)) {
92                 spit("Modifying list (" << m_list << ")");
93                 m_flag = m_flag &~ LIST_END;
94                 m_flag |= LIST_STREAM;
95         }
96 }
97
98 bool RAS_ListSlot::End()
99 {
100         return (m_flag &LIST_END)!=0;
101 }
102
103
104
105 RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays, bool lock)
106 :       RAS_VAOpenGLRasterizer(canvas, lock),
107         mUseVertexArrays(useVertexArrays),
108         mATI(false)
109 {
110         if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc."))
111                 mATI = true;
112 }
113
114 RAS_ListRasterizer::~RAS_ListRasterizer() 
115 {
116         ReleaseAlloc();
117 }
118
119 void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list)
120 {
121         if (list->m_flag & LIST_DERIVEDMESH) {
122                 RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin();
123                 while(it != mDerivedMeshLists.end()) {
124                         if (it->second == list) {
125                                 mDerivedMeshLists.erase(it);
126                                 break;
127                         }
128                         it++;
129                 }
130         } else {
131                 RAS_ArrayLists::iterator it = mArrayLists.begin();
132                 while(it != mArrayLists.end()) {
133                         if (it->second == list) {
134                                 mArrayLists.erase(it);
135                                 break;
136                         }
137                         it++;
138                 }
139         }
140 }
141
142 RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms)
143 {
144         /*
145          Keep a copy of constant lists submitted for rendering,
146                 this guards against (replicated)new...delete every frame,
147                 and we can reuse lists!
148                 :: sorted by mesh slot
149         */
150         RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList;
151         if(!localSlot) {
152                 if (ms.m_pDerivedMesh) {
153                         // that means that we draw based on derived mesh, a display list is possible
154                         // Note that we come here only for static derived mesh
155                         RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.find(ms.m_pDerivedMesh);
156                         if(it == mDerivedMeshLists.end()) {
157                                 localSlot = new RAS_ListSlot(this);
158                                 localSlot->m_flag |= LIST_DERIVEDMESH;
159                                 mDerivedMeshLists.insert(std::pair<DerivedMesh*, RAS_ListSlot*>(ms.m_pDerivedMesh, localSlot));
160                         } else {
161                                 localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef());
162                         }
163                 } else {
164                         RAS_ArrayLists::iterator it = mArrayLists.find(ms.m_displayArrays);
165                         if(it == mArrayLists.end()) {
166                                 localSlot = new RAS_ListSlot(this);
167                                 mArrayLists.insert(std::pair<RAS_DisplayArrayList, RAS_ListSlot*>(ms.m_displayArrays, localSlot));
168                         } else {
169                                 localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef());
170                         }
171                 }
172         }
173         MT_assert(localSlot);
174         return localSlot;
175 }
176
177 void RAS_ListRasterizer::ReleaseAlloc()
178 {
179         for(RAS_ArrayLists::iterator it = mArrayLists.begin();it != mArrayLists.end();++it)
180                 delete it->second;
181         mArrayLists.clear();
182         for (RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin();it != mDerivedMeshLists.end();++it)
183                 delete it->second;
184         mDerivedMeshLists.clear();
185 }
186
187 void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
188 {
189         RAS_ListSlot* localSlot =0;
190
191         if(ms.m_bDisplayList) {
192                 localSlot = FindOrAdd(ms);
193                 localSlot->DrawList();
194                 if(localSlot->End()) {
195                         // save slot here too, needed for replicas and object using same mesh
196                         // => they have the same vertexarray but different mesh slot
197                         ms.m_DisplayList = localSlot;
198                         return;
199                 }
200         }
201         // derived mesh cannot use vertex array
202         if (mUseVertexArrays && !ms.m_pDerivedMesh)
203                 RAS_VAOpenGLRasterizer::IndexPrimitives(ms);
204         else
205                 RAS_OpenGLRasterizer::IndexPrimitives(ms);
206
207         if(ms.m_bDisplayList) {
208                 localSlot->EndList();
209                 ms.m_DisplayList = localSlot;
210         }
211 }
212
213
214 void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
215 {
216         RAS_ListSlot* localSlot =0;
217
218         if(ms.m_bDisplayList) {
219                 localSlot = FindOrAdd(ms);
220                 localSlot->DrawList();
221
222                 if(localSlot->End()) {
223                         // save slot here too, needed for replicas and object using same mesh
224                         // => they have the same vertexarray but different mesh slot
225                         ms.m_DisplayList = localSlot;
226                         return;
227                 }
228         }
229
230         // workaround: note how we do not use vertex arrays for making display
231         // lists, since glVertexAttribPointerARB doesn't seem to work correct
232         // in display lists on ATI? either a bug in the driver or in Blender ..
233         if (mUseVertexArrays && !mATI && !ms.m_pDerivedMesh)
234                 RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms);
235         else
236                 RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms);
237
238         if(ms.m_bDisplayList) {
239                 localSlot->EndList();
240                 ms.m_DisplayList = localSlot;
241         }
242 }
243
244 bool RAS_ListRasterizer::Init(void)
245 {
246         if (mUseVertexArrays) {
247                 return RAS_VAOpenGLRasterizer::Init();
248         } else {
249                 return RAS_OpenGLRasterizer::Init();
250         }
251 }
252
253 void RAS_ListRasterizer::SetDrawingMode(int drawingmode)
254 {
255         if (mUseVertexArrays) {
256                 RAS_VAOpenGLRasterizer::SetDrawingMode(drawingmode);
257         } else {
258                 RAS_OpenGLRasterizer::SetDrawingMode(drawingmode);
259         }
260 }
261
262 void RAS_ListRasterizer::Exit()
263 {
264         if (mUseVertexArrays) {
265                 RAS_VAOpenGLRasterizer::Exit();
266         } else {
267                 RAS_OpenGLRasterizer::Exit();
268         }
269 }
270
271 // eof