4642ffbaeb89cf1ad2675dfa4850fc2e0faeecef
[blender.git] / source / gameengine / Rasterizer / RAS_MaterialBucket.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "RAS_MaterialBucket.h"
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #ifdef WIN32
36 #pragma warning (disable:4786)
37 #include <windows.h>
38 #endif // WIN32
39
40 #include "RAS_Polygon.h"
41 #include "RAS_TexVert.h"
42 #include "RAS_IRasterizer.h"
43 #include "RAS_IRenderTools.h"
44 #include "RAS_MeshObject.h"
45 #include "RAS_Deformer.h"       // __NLA
46
47
48
49 KX_VertexIndex::KX_VertexIndex(int size)
50 {
51         m_size = size;
52 }
53
54
55
56 void KX_VertexIndex::SetIndex(short loc,unsigned int index)
57 {
58         m_indexarray[loc]=index;
59 }
60
61 bool KX_MeshSlot::Less(const KX_MeshSlot& lhs) const
62 {
63         bool result = ((m_mesh < lhs.m_mesh ) ||
64                 ((m_mesh == lhs.m_mesh)&&(m_OpenGLMatrix < lhs.m_OpenGLMatrix)));
65         
66         return result;
67 }
68
69 KX_MeshSlot::~KX_MeshSlot()
70 {
71         if (m_DisplayList)
72                 m_DisplayList->Release();
73 }
74
75
76 RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat)
77         :m_bModified(true)
78 {
79         m_bScheduled=true;
80         m_material = mat;
81 }
82
83
84
85 void RAS_MaterialBucket::SchedulePolygons(int drawingmode)
86
87         m_bScheduled = true;
88 }
89
90
91
92 void RAS_MaterialBucket::ClearScheduledPolygons()
93
94         m_bScheduled = false;
95 }
96
97         
98
99 RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const
100
101         return m_material;
102 }
103
104
105         
106 void RAS_MaterialBucket::SetMeshSlot(KX_MeshSlot& ms)
107 {
108         m_meshSlots.insert(ms);
109 }
110
111
112
113 void RAS_MaterialBucket::RemoveMeshSlot(KX_MeshSlot& ms)
114 {
115         T_MeshSlotList::iterator it = m_meshSlots.find(ms);
116
117         if (!(it == m_meshSlots.end()))
118                 m_meshSlots.erase(it);
119                         
120 }
121
122
123
124 void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms,
125                                                                                          bool visible,
126                                                                                          bool color,
127                                                                                          const MT_Vector4& rgbavec)
128 {
129         T_MeshSlotList::iterator it = m_meshSlots.find(ms);
130                         
131         assert (!(it == m_meshSlots.end())); 
132         (*it).m_bVisible = visible;
133         (*it).m_bObjectColor = color;
134         (*it).m_RGBAcolor= rgbavec;
135 }
136
137 bool RAS_MaterialBucket::IsTransparant() const
138 {       
139         return (m_material->IsTransparant());
140 }
141
142
143
144 void RAS_MaterialBucket::StartFrame()
145 {
146 }
147
148
149
150 void RAS_MaterialBucket::EndFrame()
151 {
152 }
153
154 unsigned int RAS_MaterialBucket::NumMeshSlots()
155 {
156         return m_meshSlots.size();
157 }
158
159 RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msBegin()
160 {
161         return m_meshSlots.begin();
162 }
163
164 RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msEnd()
165 {
166         return m_meshSlots.end();
167 }
168
169 bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
170         RAS_IRenderTools *rendertools, int &drawmode)
171 {
172         rendertools->SetViewMat(cameratrans);
173
174         if (!rasty->SetMaterial(*m_material))
175                 return false;
176         
177         bool dolights = false;
178         const unsigned int flag = m_material->GetFlag();
179
180
181         if( flag & RAS_BLENDERMAT)
182                 dolights = (flag &RAS_MULTILIGHT)!=0;
183         else
184                 dolights = (m_material->GetDrawingMode()&16)!=0;
185
186         if ((rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID) || !dolights)
187         {
188                 rendertools->ProcessLighting(-1);
189         }
190         else
191         {
192                 rendertools->ProcessLighting(m_material->GetLightLayer());
193         }
194
195         drawmode = (rasty->GetDrawingMode()  < RAS_IRasterizer::KX_SOLID ?      
196                 1:      (m_material->UsesTriangles() ? 0 : 2));
197         
198         return true;
199 }
200
201 void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
202         RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, int drawmode)
203 {
204         if (!ms.m_bVisible)
205                 return;
206         
207         rendertools->SetClientObject(ms.m_clientObj);
208         m_material->ActivateMeshSlot(ms, rasty);
209
210         /* __NLA Do the deformation */
211         if (ms.m_pDeformer)
212         {
213                 ms.m_pDeformer->Apply(m_material);
214         //      KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_)
215         }
216         /* End __NLA */
217         
218         if (rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
219                 ms.m_mesh->SortPolygons(cameratrans*MT_Transform(ms.m_OpenGLMatrix));
220
221         rendertools->PushMatrix();
222         rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode());
223
224         if(rasty->QueryLists())
225         {
226                 if(ms.m_DisplayList)
227                         ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified());
228         }
229
230         // Use the text-specific IndexPrimitives for text faces
231         if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT)
232         {
233                 rasty->IndexPrimitives_3DText(
234                                 ms.m_mesh->GetVertexCache(m_material), 
235                                 ms.m_mesh->GetIndexCache(m_material), 
236                                 drawmode,
237                                 m_material,
238                                 rendertools, // needed for textprinting on polys
239                                 ms.m_bObjectColor,
240                                 ms.m_RGBAcolor);
241
242         }
243
244         // for using glMultiTexCoord
245         else if(m_material->GetFlag() & RAS_MULTITEX )
246         {
247                 rasty->IndexPrimitivesMulti(
248                                 ms.m_mesh->GetVertexCache(m_material), 
249                                 ms.m_mesh->GetIndexCache(m_material), 
250                                 drawmode,
251                                 m_material,
252                                 rendertools,
253                                 ms.m_bObjectColor,
254                                 ms.m_RGBAcolor,
255                                 &ms.m_DisplayList
256                                 );
257         }
258
259         // for using glMultiTexCoord on deformer
260         else if(m_material->GetFlag() & RAS_DEFMULTI )
261         {
262                 rasty->IndexPrimitivesMulti_Ex(
263                                 ms.m_mesh->GetVertexCache(m_material), 
264                                 ms.m_mesh->GetIndexCache(m_material), 
265                                 drawmode,
266                                 m_material,
267                                 rendertools,
268                                 ms.m_bObjectColor,
269                                 ms.m_RGBAcolor
270                                 );
271         }
272
273         // Use the (slower) IndexPrimitives_Ex which can recalc face normals & such
274         //      for deformed objects - eventually should be extended to recalc ALL normals
275         else if (ms.m_pDeformer){
276                 rasty->IndexPrimitives_Ex(
277                                 ms.m_mesh->GetVertexCache(m_material), 
278                                 ms.m_mesh->GetIndexCache(m_material), 
279                                 drawmode,
280                                 m_material,
281                                 rendertools, // needed for textprinting on polys
282                                 ms.m_bObjectColor,
283                                 ms.m_RGBAcolor
284                                 );
285         }
286         // Use the normal IndexPrimitives
287         else
288         {
289                 rasty->IndexPrimitives(
290                                 ms.m_mesh->GetVertexCache(m_material), 
291                                 ms.m_mesh->GetIndexCache(m_material), 
292                                 drawmode,
293                                 m_material,
294                                 rendertools, // needed for textprinting on polys
295                                 ms.m_bObjectColor,
296                                 ms.m_RGBAcolor,
297                                 &ms.m_DisplayList
298                                 );
299         }
300
301         if(rasty->QueryLists()) {
302                 if(ms.m_DisplayList)
303                         ms.m_mesh->SetMeshModified(false);
304         }
305
306         rendertools->PopMatrix();
307 }
308
309 void RAS_MaterialBucket::Render(const MT_Transform& cameratrans,
310                                                                 RAS_IRasterizer* rasty,
311                                                                 RAS_IRenderTools* rendertools)
312 {
313         if (m_meshSlots.begin()== m_meshSlots.end())
314                 return;
315                 
316         //rendertools->SetViewMat(cameratrans);
317
318         //rasty->SetMaterial(*m_material);
319         
320         if (m_meshSlots.size() >0)
321         {
322                 rendertools->SetClientObject((*m_meshSlots.begin()).m_clientObj);
323         }
324         
325         int drawmode;
326         for (T_MeshSlotList::const_iterator it = m_meshSlots.begin();
327         ! (it == m_meshSlots.end()); ++it)
328         {
329                 while (ActivateMaterial(cameratrans, rasty, rendertools, drawmode))
330                         RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode);
331         }
332 }
333
334