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