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