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