Merged 15170:15635 from trunk (no conflicts or even merges)
[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, RAS_IRasterizer::DrawMode &drawmode)
171 {
172         rendertools->SetViewMat(cameratrans);
173
174         if (!rasty->SetMaterial(*m_material))
175                 return false;
176         
177         if (m_material->UsesLighting(rasty))
178                 rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER/*m_material->GetLightLayer()*/);
179         else
180                 rendertools->ProcessLighting(-1);
181
182         if(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID)
183                 drawmode = RAS_IRasterizer::KX_MODE_LINES;
184         else if(m_material->UsesTriangles())
185                 drawmode = RAS_IRasterizer::KX_MODE_TRIANGLES;
186         else
187                 drawmode = RAS_IRasterizer::KX_MODE_QUADS;
188         
189         return true;
190 }
191
192 void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
193         RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode)
194 {
195         if (!ms.m_bVisible)
196                 return;
197         
198         m_material->ActivateMeshSlot(ms, rasty);
199
200         /* __NLA Do the deformation */
201         if (ms.m_pDeformer)
202         {
203                 ms.m_pDeformer->Apply(m_material);
204         //      KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_)
205         }
206         /* End __NLA */
207         
208         if (rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
209                 ms.m_mesh->SortPolygons(cameratrans*MT_Transform(ms.m_OpenGLMatrix));
210
211         rendertools->PushMatrix();
212         rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode());
213
214         if(rasty->QueryLists())
215         {
216                 if(ms.m_DisplayList)
217                         ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified());
218         }
219
220         // verify if we can use display list, not for deformed object, and
221         // also don't create a new display list when drawing shadow buffers,
222         // then it won't have texture coordinates for actual drawing
223         KX_ListSlot **displaylist;
224         if(ms.m_pDeformer)
225                 displaylist = 0;
226         else if(!ms.m_DisplayList && rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW)
227                 displaylist = 0;
228         else
229                 displaylist = &ms.m_DisplayList;
230
231         // Use the text-specific IndexPrimitives for text faces
232         if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT)
233         {
234                 rasty->IndexPrimitives_3DText(
235                                 ms.m_mesh->GetVertexCache(m_material), 
236                                 ms.m_mesh->GetIndexCache(m_material), 
237                                 drawmode,
238                                 m_material,
239                                 rendertools, // needed for textprinting on polys
240                                 ms.m_bObjectColor,
241                                 ms.m_RGBAcolor);
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                                 ms.m_bObjectColor,
252                                 ms.m_RGBAcolor,
253                                 displaylist);
254         }
255
256         // Use the normal IndexPrimitives
257         else
258         {
259                 rasty->IndexPrimitives(
260                                 ms.m_mesh->GetVertexCache(m_material), 
261                                 ms.m_mesh->GetIndexCache(m_material), 
262                                 drawmode,
263                                 ms.m_bObjectColor,
264                                 ms.m_RGBAcolor,
265                                 displaylist);
266         }
267
268         if(rasty->QueryLists()) {
269                 if(ms.m_DisplayList)
270                         ms.m_mesh->SetMeshModified(false);
271         }
272
273         rendertools->PopMatrix();
274 }
275
276 void RAS_MaterialBucket::Render(const MT_Transform& cameratrans,
277                                                                 RAS_IRasterizer* rasty,
278                                                                 RAS_IRenderTools* rendertools)
279 {
280         if (m_meshSlots.begin()== m_meshSlots.end())
281                 return;
282                 
283         //rendertools->SetViewMat(cameratrans);
284
285         //rasty->SetMaterial(*m_material);
286         
287         RAS_IRasterizer::DrawMode drawmode;
288         for (T_MeshSlotList::const_iterator it = m_meshSlots.begin();
289         ! (it == m_meshSlots.end()); ++it)
290         {
291                 rendertools->SetClientObject((*it).m_clientObj);
292                 while (ActivateMaterial(cameratrans, rasty, rendertools, drawmode)) {
293                         RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode);
294                 }
295         }
296         // to reset the eventual GL_CW mode
297         rendertools->SetClientObject(NULL);
298 }
299
300