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