py api cleanup, replace use...
[blender.git] / source / gameengine / Ketsji / KX_BlenderMaterial.cpp
1 /** \file gameengine/Ketsji/KX_BlenderMaterial.cpp
2  *  \ingroup ketsji
3  */
4
5 // ------------------------------------
6 // ...
7 // ------------------------------------
8 #include "GL/glew.h"
9
10 #include "KX_BlenderMaterial.h"
11 #include "BL_Material.h"
12 #include "KX_Scene.h"
13 #include "KX_Light.h"
14 #include "KX_GameObject.h"
15 #include "KX_MeshProxy.h"
16
17 #include "MT_Vector3.h"
18 #include "MT_Vector4.h"
19 #include "MT_Matrix4x4.h"
20
21 #include "RAS_BucketManager.h"
22 #include "RAS_MeshObject.h"
23 #include "RAS_IRasterizer.h"
24 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
25
26 #include "GPU_draw.h"
27
28 #include "STR_HashedString.h"
29
30 // ------------------------------------
31 #include "DNA_object_types.h"
32 #include "DNA_material_types.h"
33 #include "DNA_image_types.h"
34 #include "DNA_meshdata_types.h"
35 #include "BKE_mesh.h"
36 // ------------------------------------
37 #include "BLI_utildefines.h"
38
39 #define spit(x) std::cout << x << std::endl;
40
41 BL_Shader *KX_BlenderMaterial::mLastShader = NULL;
42 BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL;
43
44 //static PyObject *gTextureDict = 0;
45
46 KX_BlenderMaterial::KX_BlenderMaterial()
47 :       PyObjectPlus(),
48         RAS_IPolyMaterial(),
49         mMaterial(NULL),
50         mShader(0),
51         mBlenderShader(0),
52         mScene(NULL),
53         mUserDefBlend(0),
54         mModified(0),
55         mConstructed(false),
56         mPass(0)
57 {
58 }
59
60 void KX_BlenderMaterial::Initialize(
61         KX_Scene *scene,
62         BL_Material *data,
63         GameSettings *game)
64 {
65         RAS_IPolyMaterial::Initialize(
66                 data->texname[0],
67                 data->matname,
68                 data->materialindex,
69                 data->tile,
70                 data->tilexrep[0],
71                 data->tileyrep[0],
72                 data->alphablend,
73                 ((data->ras_mode &ALPHA)!=0),
74                 ((data->ras_mode &ZSORT)!=0),
75                 ((data->ras_mode &USE_LIGHT)!=0),
76                 ((data->ras_mode &TEX)),
77                 game
78         );
79         mMaterial = data;
80         mShader = 0;
81         mBlenderShader = 0;
82         mScene = scene;
83         mUserDefBlend = 0;
84         mModified = 0;
85         mConstructed = false;
86         mPass = 0;
87         // --------------------------------
88         // RAS_IPolyMaterial variables...
89         m_flag |= RAS_BLENDERMAT;
90         m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0;
91         m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0;
92         m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0;
93         m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0;
94
95         // figure max
96         int enabled = mMaterial->num_enabled;
97         int max = BL_Texture::GetMaxUnits();
98         mMaterial->num_enabled = enabled>=max?max:enabled;
99
100         // test the sum of the various modes for equality
101         // so we can ether accept or reject this material
102         // as being equal, this is rather important to
103         // prevent material bleeding
104         for (int i=0; i<mMaterial->num_enabled; i++) {
105                 m_multimode     += (mMaterial->flag[i] + mMaterial->blend_mode[i]);
106         }
107         m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT));
108 }
109
110 KX_BlenderMaterial::~KX_BlenderMaterial()
111 {
112         // cleanup work
113         if (mConstructed)
114                 // clean only if material was actually used
115                 OnExit();
116 }
117
118 MTFace* KX_BlenderMaterial::GetMTFace(void) const 
119 {
120         // fonts on polys
121         return &mMaterial->tface;
122 }
123
124 unsigned int* KX_BlenderMaterial::GetMCol(void) const 
125 {
126         // fonts on polys
127         return &mMaterial->m_mcol;
128 }
129
130 void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
131 {
132         if (mMaterial) {
133                 *rgba++ = (unsigned char)(mMaterial->matcolor[0] * 255.0f);
134                 *rgba++ = (unsigned char)(mMaterial->matcolor[1] * 255.0f);
135                 *rgba++ = (unsigned char)(mMaterial->matcolor[2] * 255.0f);
136                 *rgba++ = (unsigned char)(mMaterial->matcolor[3] * 255.0f);
137         } else
138                 RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
139 }
140
141 bool KX_BlenderMaterial::IsMaterial(const BL_Material *bl_mat) const
142 {
143         return (mMaterial == bl_mat);
144 }
145
146 Material *KX_BlenderMaterial::GetBlenderMaterial() const
147 {
148         return mMaterial->material;
149 }
150
151 Scene* KX_BlenderMaterial::GetBlenderScene() const
152 {
153         return mScene->GetBlenderScene();
154 }
155
156 void KX_BlenderMaterial::ReleaseMaterial()
157 {
158         if (mBlenderShader)
159                 mBlenderShader->ReloadMaterial();
160 }
161
162 void KX_BlenderMaterial::InitTextures()
163 {
164         // for each unique material...
165         int i;
166         for (i=0; i<mMaterial->num_enabled; i++) {
167                 if ( mMaterial->mapping[i].mapping & USEENV ) {
168                         if (!GLEW_ARB_texture_cube_map) {
169                                 spit("CubeMap textures not supported");
170                                 continue;
171                         }
172                         if (!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) )
173                                 spit("unable to initialize image("<<i<<") in "<<
174                                      mMaterial->matname<< ", image will not be available");
175                 }
176                 /* If we're using glsl materials, the textures are handled by bf_gpu, so don't load them twice!
177                  * However, if we're using a custom shader, then we still need to load the textures ourselves. */
178                 else if (!mMaterial->glslmat || mShader) {
179                         if ( mMaterial->img[i] ) {
180                                 if ( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 ))
181                                         spit("unable to initialize image("<<i<<") in "<< 
182                                                 mMaterial->matname<< ", image will not be available");
183                         }
184                 }
185         }
186 }
187
188 void KX_BlenderMaterial::OnConstruction(int layer)
189 {
190         if (mConstructed)
191                 // when material are reused between objects
192                 return;
193         
194         if (mMaterial->glslmat)
195                 SetBlenderGLSLShader(layer);
196
197         InitTextures();
198
199         mBlendFunc[0] =0;
200         mBlendFunc[1] =0;
201         mConstructed = true;
202 }
203
204 void KX_BlenderMaterial::EndFrame()
205 {
206         if (mLastBlenderShader) {
207                 mLastBlenderShader->SetProg(false);
208                 mLastBlenderShader = NULL;
209         }
210
211         if (mLastShader) {
212                 mLastShader->SetProg(false);
213                 mLastShader = NULL;
214         }
215 }
216
217 void KX_BlenderMaterial::OnExit()
218 {
219         if ( mShader ) {
220                 //note, the shader here is allocated, per unique material
221                 //and this function is called per face
222                 if (mShader == mLastShader) {
223                         mShader->SetProg(false);
224                         mLastShader = NULL;
225                 }
226
227                 delete mShader;
228                 mShader = 0;
229         }
230
231         if ( mBlenderShader ) {
232                 if (mBlenderShader == mLastBlenderShader) {
233                         mBlenderShader->SetProg(false);
234                         mLastBlenderShader = NULL;
235                 }
236
237                 delete mBlenderShader;
238                 mBlenderShader = 0;
239         }
240
241         BL_Texture::ActivateFirst();
242         for (int i=0; i<mMaterial->num_enabled; i++) {
243                 BL_Texture::ActivateUnit(i);
244                 mTextures[i].DeleteTex();
245                 mTextures[i].DisableUnit();
246         }
247
248         /* used to call with 'mMaterial->tface' but this can be a freed array,
249          * see: [#30493], so just call with NULL, this is best since it clears
250          * the 'lastface' pointer in GPU too - campbell */
251         GPU_set_tpage(NULL, 1, mMaterial->alphablend);
252 }
253
254
255 void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
256 {
257         MT_assert(GLEW_ARB_shader_objects && mShader);
258
259         int i;
260         if ( !enable || !mShader->Ok() ) {
261                 // frame cleanup.
262                 if (mShader == mLastShader) {
263                         mShader->SetProg(false);
264                         mLastShader = NULL;
265                 }
266
267                 ras->SetAlphaBlend(TF_SOLID);
268                 BL_Texture::DisableAllTextures();
269                 return;
270         }
271
272         BL_Texture::DisableAllTextures();
273         mShader->SetProg(true);
274         mLastShader = mShader;
275         
276         BL_Texture::ActivateFirst();
277
278         mShader->ApplyShader();
279
280         // for each enabled unit
281         for (i=0; i<mMaterial->num_enabled; i++) {
282                 if (!mTextures[i].Ok()) continue;
283                 mTextures[i].ActivateTexture();
284                 mTextures[0].SetMapping(mMaterial->mapping[i].mapping);
285         }
286
287         if (!mUserDefBlend) {
288                 ras->SetAlphaBlend(mMaterial->alphablend);
289         }
290         else {
291                 ras->SetAlphaBlend(TF_SOLID);
292                 ras->SetAlphaBlend(-1); // indicates custom mode
293
294                 // tested to be valid enums
295                 glEnable(GL_BLEND);
296                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
297         }
298 }
299
300 void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras)
301 {
302         if ( !enable || !mBlenderShader->Ok() ) {
303                 ras->SetAlphaBlend(TF_SOLID);
304
305                 // frame cleanup.
306                 if (mLastBlenderShader) {
307                         mLastBlenderShader->SetProg(false);
308                         mLastBlenderShader= NULL;
309                 }
310                 else
311                         BL_Texture::DisableAllTextures();
312
313                 return;
314         }
315
316         if (!mBlenderShader->Equals(mLastBlenderShader)) {
317                 ras->SetAlphaBlend(mMaterial->alphablend);
318
319                 if (mLastBlenderShader)
320                         mLastBlenderShader->SetProg(false);
321                 else
322                         BL_Texture::DisableAllTextures();
323
324                 mBlenderShader->SetProg(true, ras->GetTime());
325                 mLastBlenderShader= mBlenderShader;
326         }
327 }
328
329 void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
330 {
331         BL_Texture::DisableAllTextures();
332
333         if ( !enable ) {
334                 ras->SetAlphaBlend(TF_SOLID);
335                 return;
336         }
337
338         BL_Texture::ActivateFirst();
339
340         if ( mMaterial->IdMode == DEFAULT_BLENDER ) {
341                 ras->SetAlphaBlend(mMaterial->alphablend);
342                 return;
343         }
344
345         if ( mMaterial->IdMode == TEXFACE ) {
346                 // no material connected to the object
347                 if ( mTextures[0].Ok() ) {
348                         mTextures[0].ActivateTexture();
349                         mTextures[0].setTexEnv(0, true);
350                         mTextures[0].SetMapping(mMaterial->mapping[0].mapping);
351                         ras->SetAlphaBlend(mMaterial->alphablend);
352                 }
353                 return;
354         }
355
356         int mode = 0,i=0;
357         for (i=0; (i<mMaterial->num_enabled && i<MAXTEX); i++) {
358                 if ( !mTextures[i].Ok() ) continue;
359
360                 mTextures[i].ActivateTexture();
361                 mTextures[i].setTexEnv(mMaterial);
362                 mode = mMaterial->mapping[i].mapping;
363
364                 if (mode &USEOBJ)
365                         setObjectMatrixData(i, ras);
366                 else
367                         mTextures[i].SetMapping(mode);
368                 
369                 if (!(mode &USEOBJ))
370                         setTexMatrixData( i );
371         }
372
373         if (!mUserDefBlend) {
374                 ras->SetAlphaBlend(mMaterial->alphablend);
375         }
376         else {
377                 ras->SetAlphaBlend(TF_SOLID);
378                 ras->SetAlphaBlend(-1); // indicates custom mode
379
380                 glEnable(GL_BLEND);
381                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
382         }
383 }
384
385 void
386 KX_BlenderMaterial::ActivatShaders(
387         RAS_IRasterizer* rasty, 
388         TCachingInfo& cachingInfo)const
389 {
390         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
391
392         // reset... 
393         if (tmp->mMaterial->IsShared()) 
394                 cachingInfo =0;
395
396         if (mLastBlenderShader) {
397                 mLastBlenderShader->SetProg(false);
398                 mLastBlenderShader= NULL;
399         }
400
401         if (GetCachingInfo() != cachingInfo) {
402
403                 if (!cachingInfo)
404                         tmp->setShaderData(false, rasty);
405                 
406                 cachingInfo = GetCachingInfo();
407         
408                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
409                         tmp->setShaderData(true, rasty);
410                 else
411                         tmp->setShaderData(false, rasty);
412
413                 if (mMaterial->ras_mode &TWOSIDED)
414                         rasty->SetCullFace(false);
415                 else
416                         rasty->SetCullFace(true);
417
418                 if ((mMaterial->ras_mode &WIRE) ||
419                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
420                 {
421                         if (mMaterial->ras_mode &WIRE) 
422                                 rasty->SetCullFace(false);
423                         rasty->SetLines(true);
424                 }
425                 else
426                         rasty->SetLines(false);
427                 ActivatGLMaterials(rasty);
428                 ActivateTexGen(rasty);
429         }
430
431         //ActivatGLMaterials(rasty);
432         //ActivateTexGen(rasty);
433 }
434
435 void
436 KX_BlenderMaterial::ActivateBlenderShaders(
437         RAS_IRasterizer* rasty, 
438         TCachingInfo& cachingInfo)const
439 {
440         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
441
442         if (mLastShader) {
443                 mLastShader->SetProg(false);
444                 mLastShader= NULL;
445         }
446
447         if (GetCachingInfo() != cachingInfo) {
448                 if (!cachingInfo)
449                         tmp->setBlenderShaderData(false, rasty);
450                 
451                 cachingInfo = GetCachingInfo();
452         
453                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
454                         tmp->setBlenderShaderData(true, rasty);
455                 else
456                         tmp->setBlenderShaderData(false, rasty);
457
458                 if (mMaterial->ras_mode &TWOSIDED)
459                         rasty->SetCullFace(false);
460                 else
461                         rasty->SetCullFace(true);
462
463                 if ((mMaterial->ras_mode &WIRE) ||
464                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
465                 {
466                         if (mMaterial->ras_mode &WIRE) 
467                                 rasty->SetCullFace(false);
468                         rasty->SetLines(true);
469                 }
470                 else
471                         rasty->SetLines(false);
472
473                 ActivatGLMaterials(rasty);
474                 mBlenderShader->SetAttribs(rasty, mMaterial);
475         }
476 }
477
478 void
479 KX_BlenderMaterial::ActivateMat( 
480         RAS_IRasterizer* rasty,  
481         TCachingInfo& cachingInfo
482         )const
483 {
484         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
485
486         if (mLastShader) {
487                 mLastShader->SetProg(false);
488                 mLastShader= NULL;
489         }
490
491         if (mLastBlenderShader) {
492                 mLastBlenderShader->SetProg(false);
493                 mLastBlenderShader= NULL;
494         }
495
496         if (GetCachingInfo() != cachingInfo) {
497                 if (!cachingInfo) 
498                         tmp->setTexData( false,rasty );
499                 
500                 cachingInfo = GetCachingInfo();
501
502                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
503                         tmp->setTexData( true,rasty  );
504                 else
505                         tmp->setTexData( false,rasty);
506
507                 if (mMaterial->ras_mode &TWOSIDED)
508                         rasty->SetCullFace(false);
509                 else
510                         rasty->SetCullFace(true);
511
512                 if ((mMaterial->ras_mode &WIRE) ||
513                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
514                 {
515                         if (mMaterial->ras_mode &WIRE) 
516                                 rasty->SetCullFace(false);
517                         rasty->SetLines(true);
518                 }
519                 else
520                         rasty->SetLines(false);
521                 ActivatGLMaterials(rasty);
522                 ActivateTexGen(rasty);
523         }
524
525         //ActivatGLMaterials(rasty);
526         //ActivateTexGen(rasty);
527 }
528
529 bool 
530 KX_BlenderMaterial::Activate( 
531         RAS_IRasterizer* rasty,  
532         TCachingInfo& cachingInfo
533         )const
534 {
535         if (GLEW_ARB_shader_objects && (mShader && mShader->Ok())) {
536                 if ((mPass++) < mShader->getNumPass() ) {
537                         ActivatShaders(rasty, cachingInfo);
538                         return true;
539                 }
540                 else {
541                         if (mShader == mLastShader) {
542                                 mShader->SetProg(false);
543                                 mLastShader = NULL;
544                         }
545                         mPass = 0;
546                         return false;
547                 }
548         }
549         else if ( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) {
550                 if (mPass++ == 0) {
551                         ActivateBlenderShaders(rasty, cachingInfo);
552                         return true;
553                 }
554                 else {
555                         mPass = 0;
556                         return false;
557                 }
558         }
559         else {
560                 if (mPass++ == 0) {
561                         ActivateMat(rasty, cachingInfo);
562                         return true;
563                 }
564                 else {
565                         mPass = 0;
566                         return false;
567                 }
568         }
569 }
570
571 bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const
572 {
573         if (!RAS_IPolyMaterial::UsesLighting(rasty))
574                 return false;
575
576         if (mShader && mShader->Ok())
577                 return true;
578         else if (mBlenderShader && mBlenderShader->Ok())
579                 return false;
580         else
581                 return true;
582 }
583
584 void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const
585 {
586         if (mShader && GLEW_ARB_shader_objects) {
587                 mShader->Update(ms, rasty);
588         }
589         else if (mBlenderShader && GLEW_ARB_shader_objects) {
590                 int alphablend;
591
592                 mBlenderShader->Update(ms, rasty);
593
594                 /* we do blend modes here, because they can change per object
595                  * with the same material due to obcolor/obalpha */
596                 alphablend = mBlenderShader->GetAlphaBlend();
597                 if (ELEM3(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID)
598                         alphablend = mMaterial->alphablend;
599
600                 rasty->SetAlphaBlend(alphablend);
601         }
602 }
603
604 void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const
605 {
606         if (mShader || !mBlenderShader) {
607                 rasty->SetSpecularity(
608                         mMaterial->speccolor[0]*mMaterial->spec_f,
609                         mMaterial->speccolor[1]*mMaterial->spec_f,
610                         mMaterial->speccolor[2]*mMaterial->spec_f,
611                         mMaterial->spec_f
612                 );
613
614                 rasty->SetShinyness( mMaterial->hard );
615
616                 rasty->SetDiffuse(
617                         mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, 
618                         mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
619                         mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
620                         1.0f);
621
622                 rasty->SetEmissive(
623                         mMaterial->matcolor[0]*mMaterial->emit,
624                         mMaterial->matcolor[1]*mMaterial->emit,
625                         mMaterial->matcolor[2]*mMaterial->emit,
626                         1.0 );
627
628                 rasty->SetAmbient(mMaterial->amb);
629         }
630
631         if (mMaterial->material)
632                 rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0);
633 }
634
635
636 void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
637 {
638         if (ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
639                 ras->SetAttribNum(0);
640                 if (mShader && GLEW_ARB_shader_objects) {
641                         if (mShader->GetAttribute() == BL_Shader::SHD_TANGENT) {
642                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, 0);
643                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, 1);
644                                 ras->SetAttribNum(2);
645                         }
646                 }
647
648                 ras->SetTexCoordNum(mMaterial->num_enabled);
649
650                 for (int i=0; i<mMaterial->num_enabled; i++) {
651                         int mode = mMaterial->mapping[i].mapping;
652
653                         if (mode &USECUSTOMUV)
654                         {
655                                 if (!mMaterial->mapping[i].uvCoName.IsEmpty())
656                                         ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV2, i);
657                                 continue;
658                         }
659
660                         if ( mode &(USEREFL|USEOBJ))
661                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN, i);
662                         else if (mode &USEORCO)
663                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_ORCO, i);
664                         else if (mode &USENORM)
665                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM, i);
666                         else if (mode &USEUV)
667                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV1, i);
668                         else if (mode &USETANG)
669                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT, i);
670                         else 
671                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
672                 }
673         }
674 }
675
676 void KX_BlenderMaterial::setTexMatrixData(int i)
677 {
678         glMatrixMode(GL_TEXTURE);
679         glLoadIdentity();
680
681         if ( GLEW_ARB_texture_cube_map && 
682                 mTextures[i].GetTextureType() == GL_TEXTURE_CUBE_MAP_ARB && 
683                 mMaterial->mapping[i].mapping & USEREFL) {
684                 glScalef( 
685                         mMaterial->mapping[i].scale[0], 
686                         -mMaterial->mapping[i].scale[1], 
687                         -mMaterial->mapping[i].scale[2]
688                 );
689         }
690         else
691         {
692                 glScalef( 
693                         mMaterial->mapping[i].scale[0], 
694                         mMaterial->mapping[i].scale[1], 
695                         mMaterial->mapping[i].scale[2]
696                 );
697         }
698         glTranslatef(
699                 mMaterial->mapping[i].offsets[0],
700                 mMaterial->mapping[i].offsets[1], 
701                 mMaterial->mapping[i].offsets[2]
702         );
703
704         glMatrixMode(GL_MODELVIEW);
705
706 }
707
708 static void GetProjPlane(BL_Material *mat, int index,int num, float*param)
709 {
710         param[0]=param[1]=param[2]=param[3]=0.f;
711         if ( mat->mapping[index].projplane[num] == PROJX )
712                 param[0] = 1.f;
713         else if ( mat->mapping[index].projplane[num] == PROJY )
714                 param[1] = 1.f;
715         else if ( mat->mapping[index].projplane[num] == PROJZ)
716                 param[2] = 1.f;
717 }
718
719 void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras)
720 {
721         KX_GameObject *obj = 
722                 (KX_GameObject*)
723                 mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame);
724
725         if (!obj) return;
726
727         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
728         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
729         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
730
731         GLenum plane = GL_EYE_PLANE;
732
733         // figure plane gen
734         float proj[4] = {0.f,0.f,0.f,0.f};
735         GetProjPlane(mMaterial, i, 0, proj);
736         glTexGenfv(GL_S, plane, proj);
737         
738         GetProjPlane(mMaterial, i, 1, proj);
739         glTexGenfv(GL_T, plane, proj);
740
741         GetProjPlane(mMaterial, i, 2, proj);
742         glTexGenfv(GL_R, plane, proj);
743
744         glEnable(GL_TEXTURE_GEN_S);
745         glEnable(GL_TEXTURE_GEN_T);
746         glEnable(GL_TEXTURE_GEN_R);
747
748         const MT_Matrix4x4& mvmat = ras->GetViewMatrix();
749
750         glMatrixMode(GL_TEXTURE);
751         glLoadIdentity();
752         glScalef( 
753                 mMaterial->mapping[i].scale[0], 
754                 mMaterial->mapping[i].scale[1], 
755                 mMaterial->mapping[i].scale[2]
756         );
757
758         MT_Point3 pos = obj->NodeGetWorldPosition();
759         MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f);
760         MT_Vector4 t = mvmat*matmul;
761
762         glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) );
763
764         glMatrixMode(GL_MODELVIEW);
765
766 }
767
768 // ------------------------------------
769 void KX_BlenderMaterial::UpdateIPO(
770         MT_Vector4 rgba,
771         MT_Vector3 specrgb,
772         MT_Scalar hard,
773         MT_Scalar spec,
774         MT_Scalar ref,
775         MT_Scalar emit,
776         MT_Scalar alpha
777         )
778 {
779         // only works one deep now
780         mMaterial->speccolor[0] = (float)(specrgb)[0];
781         mMaterial->speccolor[1] = (float)(specrgb)[1];
782         mMaterial->speccolor[2] = (float)(specrgb)[2];
783         mMaterial->matcolor[0]  = (float)(rgba[0]);
784         mMaterial->matcolor[1]  = (float)(rgba[1]);
785         mMaterial->matcolor[2]  = (float)(rgba[2]);
786         mMaterial->alpha                = (float)(alpha);
787         mMaterial->hard                 = (float)(hard);
788         mMaterial->emit                 = (float)(emit);
789         mMaterial->spec_f               = (float)(spec);
790         mMaterial->ref                  = (float)(ref);
791 }
792
793 void KX_BlenderMaterial::SetBlenderGLSLShader(int layer)
794 {
795         if (!mBlenderShader)
796                 mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, layer);
797
798         if (!mBlenderShader->Ok()) {
799                 delete mBlenderShader;
800                 mBlenderShader = 0;
801         }
802 }
803
804 #ifdef WITH_PYTHON
805
806 PyMethodDef KX_BlenderMaterial::Methods[] = 
807 {
808         KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ),
809         KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ),
810         KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ),
811         {NULL,NULL} //Sentinel
812 };
813
814 PyAttributeDef KX_BlenderMaterial::Attributes[] = {
815         KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader),
816         KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex),
817         KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending),
818         { NULL }        //Sentinel
819 };
820
821 PyTypeObject KX_BlenderMaterial::Type = {
822         PyVarObject_HEAD_INIT(NULL, 0)
823         "KX_BlenderMaterial",
824         sizeof(PyObjectPlus_Proxy),
825         0,
826         py_base_dealloc,
827         0,
828         0,
829         0,
830         0,
831         py_base_repr,
832         0,0,0,0,0,0,0,0,0,
833         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
834         0,0,0,0,0,0,0,
835         Methods,
836         0,
837         0,
838         &PyObjectPlus::Type,
839         0,0,0,0,0,0,
840         py_base_new
841 };
842
843 PyObject *KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
844 {
845         KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
846         return self->PygetShader(NULL, NULL);
847 }
848
849 PyObject *KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
850 {
851         KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
852         return PyLong_FromLong(self->GetMaterialIndex());
853 }
854
855 PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
856 {
857         KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
858         unsigned int* bfunc = self->getBlendFunc();
859         return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]);
860 }
861
862 int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
863 {
864         KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
865         PyObject *obj = self->PysetBlending(value, NULL);
866         if (obj)
867         {
868                 Py_DECREF(obj);
869                 return 0;
870         }
871         return -1;
872 }
873
874 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
875 {
876         if ( !GLEW_ARB_fragment_shader) {
877                 if (!mModified)
878                         spit("Fragment shaders not supported");
879         
880                 mModified = true;
881                 Py_RETURN_NONE;
882         }
883
884         if ( !GLEW_ARB_vertex_shader) {
885                 if (!mModified)
886                         spit("Vertex shaders not supported");
887
888                 mModified = true;
889                 Py_RETURN_NONE;
890         }
891
892         if (!GLEW_ARB_shader_objects) {
893                 if (!mModified)
894                         spit("GLSL not supported");
895                 mModified = true;
896                 Py_RETURN_NONE;
897         }
898         else {
899                 // returns Py_None on error
900                 // the calling script will need to check
901
902                 if (!mShader && !mModified) {
903                         mShader = new BL_Shader();
904                         mModified = true;
905
906                         // Using a custom shader, make sure to initialize textures
907                         InitTextures();
908                 }
909
910                 if (mShader && !mShader->GetError()) {
911                         m_flag &= ~RAS_BLENDERGLSL;
912                         mMaterial->SetSharedMaterial(true);
913                         mScene->GetBucketManager()->ReleaseDisplayLists(this);
914                         return mShader->GetProxy();
915                 }
916                 else {
917                         // decref all references to the object
918                         // then delete it!
919                         // We will then go back to fixed functionality
920                         // for this material
921                         if (mShader) {
922                                 delete mShader; /* will handle python de-referencing */
923                                 mShader=0;
924                         }
925                 }
926                 Py_RETURN_NONE;
927         }
928         PyErr_SetString(PyExc_ValueError, "material.getShader(): KX_BlenderMaterial, GLSL Error");
929         return NULL;
930 }
931
932 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
933 {
934         return PyLong_FromLong(GetMaterialIndex());
935 }
936
937 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
938 {
939         // TODO: enable python switching
940         return NULL;
941 }
942
943 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
944 {
945         // TODO: enable python switching
946         return NULL;
947 }
948
949 static unsigned int GL_array[11] = {
950         GL_ZERO,
951         GL_ONE,
952         GL_SRC_COLOR,
953         GL_ONE_MINUS_SRC_COLOR,
954         GL_DST_COLOR,
955         GL_ONE_MINUS_DST_COLOR,
956         GL_SRC_ALPHA,
957         GL_ONE_MINUS_SRC_ALPHA,
958         GL_DST_ALPHA,
959         GL_ONE_MINUS_DST_ALPHA,
960         GL_SRC_ALPHA_SATURATE
961 };
962
963 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( bge.logic.src, bge.logic.dest)")
964 {
965         unsigned int b[2];
966         if (PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1]))
967         {
968                 bool value_found[2] = {false, false};
969                 for (int i=0; i<11; i++)
970                 {
971                         if (b[0] == GL_array[i]) {
972                                 value_found[0] = true;
973                                 mBlendFunc[0] = b[0];
974                         }
975                         if (b[1] == GL_array[i]) {
976                                 value_found[1] = true;
977                                 mBlendFunc[1] = b[1];
978                         }
979                         if (value_found[0] && value_found[1]) break;
980                 }
981                 if (!value_found[0] || !value_found[1]) {
982                         PyErr_SetString(PyExc_ValueError, "material.setBlending(int, int): KX_BlenderMaterial, invalid enum.");
983                         return NULL;
984                 }
985                 mUserDefBlend = true;
986                 Py_RETURN_NONE;
987         }
988         return NULL;
989 }
990
991 #endif // WITH_PYTHON