fix BGE bug #8869: Added objects are not lit correctly
[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(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER/*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         m_material->ActivateMeshSlot(ms, rasty);
208
209         /* __NLA Do the deformation */
210         if (ms.m_pDeformer)
211         {
212                 ms.m_pDeformer->Apply(m_material);
213         //      KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_)
214         }
215         /* End __NLA */
216         
217         if (rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
218                 ms.m_mesh->SortPolygons(cameratrans*MT_Transform(ms.m_OpenGLMatrix));
219
220         rendertools->PushMatrix();
221         rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode());
222
223         if(rasty->QueryLists())
224         {
225                 if(ms.m_DisplayList)
226                         ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified());
227         }
228
229         // Use the text-specific IndexPrimitives for text faces
230         if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT)
231         {
232                 rasty->IndexPrimitives_3DText(
233                                 ms.m_mesh->GetVertexCache(m_material), 
234                                 ms.m_mesh->GetIndexCache(m_material), 
235                                 drawmode,
236                                 m_material,
237                                 rendertools, // needed for textprinting on polys
238                                 ms.m_bObjectColor,
239                                 ms.m_RGBAcolor);
240
241         }
242
243         // for using glMultiTexCoord
244         else if(m_material->GetFlag() & RAS_MULTITEX )
245         {
246                 rasty->IndexPrimitivesMulti(
247                                 ms.m_mesh->GetVertexCache(m_material), 
248                                 ms.m_mesh->GetIndexCache(m_material), 
249                                 drawmode,
250                                 m_material,
251                                 rendertools,
252                                 ms.m_bObjectColor,
253                                 ms.m_RGBAcolor,
254                                 &ms.m_DisplayList
255                                 );
256         }
257
258         // for using glMultiTexCoord on deformer
259         else if(m_material->GetFlag() & RAS_DEFMULTI )
260         {
261                 rasty->IndexPrimitivesMulti_Ex(
262                                 ms.m_mesh->GetVertexCache(m_material), 
263                                 ms.m_mesh->GetIndexCache(m_material), 
264                                 drawmode,
265                                 m_material,
266                                 rendertools,
267                                 ms.m_bObjectColor,
268                                 ms.m_RGBAcolor
269                                 );
270         }
271
272         // Use the (slower) IndexPrimitives_Ex which can recalc face normals & such
273         //      for deformed objects - eventually should be extended to recalc ALL normals
274         else if (ms.m_pDeformer){
275                 rasty->IndexPrimitives_Ex(
276                                 ms.m_mesh->GetVertexCache(m_material), 
277                                 ms.m_mesh->GetIndexCache(m_material), 
278                                 drawmode,
279                                 m_material,
280                                 rendertools, // needed for textprinting on polys
281                                 ms.m_bObjectColor,
282                                 ms.m_RGBAcolor
283                                 );
284         }
285         // Use the normal IndexPrimitives
286         else
287         {
288                 rasty->IndexPrimitives(
289                                 ms.m_mesh->GetVertexCache(m_material), 
290                                 ms.m_mesh->GetIndexCache(m_material), 
291                                 drawmode,
292                                 m_material,
293                                 rendertools, // needed for textprinting on polys
294                                 ms.m_bObjectColor,
295                                 ms.m_RGBAcolor,
296                                 &ms.m_DisplayList
297                                 );
298         }
299
300         if(rasty->QueryLists()) {
301                 if(ms.m_DisplayList)
302                         ms.m_mesh->SetMeshModified(false);
303         }
304
305         rendertools->PopMatrix();
306 }
307
308 void RAS_MaterialBucket::Render(const MT_Transform& cameratrans,
309                                                                 RAS_IRasterizer* rasty,
310                                                                 RAS_IRenderTools* rendertools)
311 {
312         if (m_meshSlots.begin()== m_meshSlots.end())
313                 return;
314                 
315         //rendertools->SetViewMat(cameratrans);
316
317         //rasty->SetMaterial(*m_material);
318         
319         
320         int drawmode;
321         for (T_MeshSlotList::const_iterator it = m_meshSlots.begin();
322         ! (it == m_meshSlots.end()); ++it)
323         {
324                 rendertools->SetClientObject((*it).m_clientObj);
325                 while (ActivateMaterial(cameratrans, rasty, rendertools, drawmode))
326                         RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode);
327         }
328 }
329
330