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