improvement of 2d-filter custom shader,
[blender.git] / source / gameengine / BlenderRoutines / KX_BlenderRenderTools.cpp
index 3ce8437a55b8f71cce1bf30cf65481b5fadb6c25..220d174d464c00966be6991a3a28a749cf6a3374 100644 (file)
@@ -1,14 +1,11 @@
 /**
  * $Id$
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include "KX_BlenderRenderTools.h"
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef WIN32
-// OpenGL gl.h needs 'windows.h' on windows platforms 
-#include <windows.h>
-#endif //WIN32
-#ifdef __APPLE__
-#include <OpenGL/gl.h>
-#else
-#include <GL/gl.h>
-#endif
+#include "GL/glew.h"
 
 #include "RAS_IRenderTools.h"
 #include "RAS_IRasterizer.h"
 #include "RAS_LightObject.h"
 #include "RAS_ICanvas.h"
-
+#include "RAS_GLExtensionManager.h"
 
 // next two includes/dependencies come from the shadow feature
 // it needs the gameobject and the sumo physics scene for a raycast
 #include "KX_GameObject.h"
 
 #include "KX_BlenderPolyMaterial.h"
+#include "KX_PolygonMaterial.h"
+#include "KX_BlenderMaterial.h"
+
 #include "Value.h"
 
 #include "KX_BlenderGL.h" // for text printing
 #include "STR_String.h"
 #include "RAS_BucketManager.h" // for polymaterial (needed for textprinting)
 
-#include "SM_Scene.h"
-#include "SumoPhysicsEnvironment.h"
-#include "KX_SumoPhysicsController.h"
+#include "KX_RayCast.h"
+#include "KX_IPhysicsController.h"
+#include "PHY_IPhysicsEnvironment.h"
 #include "KX_Scene.h"
 
 KX_BlenderRenderTools::KX_BlenderRenderTools()
 {
+       glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights);
+       if (m_numgllights < 8)
+               m_numgllights = 8;
 }
 
 /**
@@ -91,8 +82,10 @@ int  KX_BlenderRenderTools::ProcessLighting(int layer)
        {
                if (m_clientobject)
                {
-
-                       
+                       if (layer == RAS_LIGHT_OBJECT_LAYER)
+                       {
+                               layer = static_cast<KX_GameObject*>(m_clientobject)->GetLayer();
+                       }
                        if (applyLights(layer))
                        {
                                EnableOpenGLLights();
@@ -101,9 +94,7 @@ int  KX_BlenderRenderTools::ProcessLighting(int layer)
                        {
                                DisableOpenGLLights();
                                result = false;
-                       }
-
-                       
+                       }                       
                }
        }
        return result;
@@ -124,7 +115,43 @@ void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty)
 
 
 }
+
+void KX_BlenderRenderTools::SetClientObject(void* obj)
+{
+       if (m_clientobject != obj)
+       {
+               if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling())
+               {
+                       glFrontFace(GL_CCW);
+               } else 
+               {
+                       glFrontFace(GL_CW);
+               }
+               m_clientobject = obj;
+               m_modified = true;
+       }
+}
+
+bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+{
+       double* const oglmatrix = (double* const) data;
+       MT_Point3 resultpoint(hit_point);
+       MT_Vector3 resultnormal(hit_normal);
+       MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
+       MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
+       left = (dir.cross(resultnormal)).safe_normalized();
+       // for the up vector, we take the 'resultnormal' returned by the physics
        
+       double maat[16]={
+                       left[0],        left[1],        left[2], 0,
+                               dir[0],         dir[1],         dir[2], 0,
+               resultnormal[0],resultnormal[1],resultnormal[2], 0,
+                               0,              0,              0, 1};
+       glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]);
+       //glMultMatrixd(oglmatrix);
+       glMultMatrixd(maat);
+       return true;
+}
 
 void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode )
 {
@@ -195,44 +222,26 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
                        KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject;
                        MT_Vector3 direction = MT_Vector3(0,0,-1);
 
-                       
                        direction.normalize();
                        direction *= 100000;
 
                        MT_Point3 topoint = frompoint + direction;
-                       MT_Point3 resultpoint;
-                       MT_Vector3 resultnormal;
 
-                       //todo:
-                       //use physics abstraction
                        KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo;
-                       SumoPhysicsEnvironment *spe = dynamic_cast<SumoPhysicsEnvironment *>( kxscene->GetPhysicsEnvironment());
-                       SM_Scene *scene = spe->GetSumoScene();
-                       KX_SumoPhysicsController *spc = dynamic_cast<KX_SumoPhysicsController *>( gameobj->GetPhysicsController());
+                       PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment();
+                       KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController();
+                       
                        KX_GameObject *parent = gameobj->GetParent();
-                       if (!spc && parent)
-                               spc = dynamic_cast<KX_SumoPhysicsController *>(parent->GetPhysicsController());
+                       if (!physics_controller && parent)
+                               physics_controller = parent->GetPhysicsController();
                        if (parent)
                                parent->Release();
-                       SM_Object *thisObj = spc?spc->GetSumoObject():NULL;
-                       
-                       if (scene->rayTest(thisObj, frompoint, topoint, resultpoint, resultnormal))
-                       {
-                               MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
-                               MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
-                               left = (dir.cross(resultnormal)).safe_normalized();
-                               // for the up vector, we take the 'resultnormal' returned by the physics
                                
-                               double maat[16]={
-                                               left[0],        left[1],        left[2], 0,
-                                                dir[0],         dir[1],         dir[2], 0,
-                                       resultnormal[0],resultnormal[1],resultnormal[2], 0,
-                                                     0,              0,              0, 1};
-                               glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]);
-                               //glMultMatrixd(oglmatrix);
-                               glMultMatrixd(maat);
-                       } else
+                       MT_Point3 resultpoint;
+                       MT_Vector3 resultnormal;
+                       if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback<KX_BlenderRenderTools>(this, oglmatrix)))
                        {
+                               // couldn't find something to cast the shadow on...
                                glMultMatrixd(oglmatrix);
                        }
                } else
@@ -254,10 +263,21 @@ void      KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float
                
        STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
        
-       KX_BlenderPolyMaterial* blenderpoly = (KX_BlenderPolyMaterial*)polymat;
-       struct TFace* tface = blenderpoly->GetTFace();
+       const unsigned int flag = polymat->GetFlag();
+       struct MTFace* tface = 0;
+       unsigned int *col = 0;
+
+       if(flag & RAS_BLENDERMAT) {
+               KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(polymat);
+               tface = bl_mat->GetMTFace();
+               col = bl_mat->GetMCol();
+       } else {
+               KX_PolygonMaterial* blenderpoly = static_cast<KX_PolygonMaterial*>(polymat);
+               tface = blenderpoly->GetMTFace();
+               col = blenderpoly->GetMCol();
+       }
        
-       BL_RenderText( mode,mytext,mytext.Length(),tface,v1,v2,v3,v4);
+       BL_RenderText( mode,mytext,mytext.Length(),tface,col,v1,v2,v3,v4);
        
 }
 
@@ -278,9 +298,6 @@ void KX_BlenderRenderTools::DisableOpenGLLights()
 {
        glDisable(GL_LIGHTING);
        glDisable(GL_COLOR_MATERIAL);
-#ifndef SLOWPAINT
-       glDisableClientState(GL_NORMAL_ARRAY);
-#endif //SLOWPAINT
 }
 
        
@@ -288,12 +305,12 @@ void KX_BlenderRenderTools::EnableOpenGLLights()
 {
        glEnable(GL_LIGHTING);
        
-       glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
        glEnable(GL_COLOR_MATERIAL);
-#ifndef SLOWPAINT
-       glEnableClientState(GL_NORMAL_ARRAY);
-#endif //SLOWPAINT
-       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, false);
+       glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true);
+       if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
+               glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+
 }
        
 
@@ -338,36 +355,29 @@ int       KX_BlenderRenderTools::applyLights(int objectlayer)
 {
 // taken from blender source, incompatibility between Blender Object / GameObject      
        
-       int count;
+       unsigned int count;
        float vec[4];
                
        vec[3]= 1.0;
        
-       for(count=0; count<8; count++)
+       for(count=0; count<m_numgllights; count++)
                glDisable((GLenum)(GL_LIGHT0+count));
        
-       count= 0;
-
        //std::vector<struct    RAS_LightObject*> m_lights;
        std::vector<struct      RAS_LightObject*>::iterator lit = m_lights.begin();
-
        
-       for (lit = m_lights.begin(); !(lit==m_lights.end()); ++lit)
+       glPushMatrix();
+       glLoadMatrixf(m_viewmat);
+       for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit)
        {
                RAS_LightObject* lightdata = (*lit);
                if (lightdata->m_layer & objectlayer)
                {
-
-                       glPushMatrix();
-                       glLoadMatrixf(m_viewmat);
-                       
-                       
                        vec[0] = (*(lightdata->m_worldmatrix))(0,3);
                        vec[1] = (*(lightdata->m_worldmatrix))(1,3);
                        vec[2] = (*(lightdata->m_worldmatrix))(2,3);
                        vec[3] = 1;
 
-
                        if(lightdata->m_type==RAS_LightObject::LIGHT_SUN) {
                                
                                vec[0] = (*(lightdata->m_worldmatrix))(0,2);
@@ -384,9 +394,9 @@ int KX_BlenderRenderTools::applyLights(int objectlayer)
                                glLightfv((GLenum)(GL_LIGHT0+count), GL_POSITION, vec); 
                                glLightf((GLenum)(GL_LIGHT0+count), GL_CONSTANT_ATTENUATION, 1.0);
                                glLightf((GLenum)(GL_LIGHT0+count), GL_LINEAR_ATTENUATION, lightdata->m_att1/lightdata->m_distance);
-                                               // without this next line it looks backward compatible.
-                                               //attennuation still is acceptable 
-                                               // glLightf((GLenum)(GL_LIGHT0+count), GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); 
+                               // without this next line it looks backward compatible.
+                               //attennuation still is acceptable 
+                               glLightf((GLenum)(GL_LIGHT0+count), GL_QUADRATIC_ATTENUATION, lightdata->m_att2/(lightdata->m_distance*lightdata->m_distance)); 
                                
                                if(lightdata->m_type==RAS_LightObject::LIGHT_SPOT) {
                                        vec[0] = -(*(lightdata->m_worldmatrix))(0,2);
@@ -402,21 +412,33 @@ int       KX_BlenderRenderTools::applyLights(int objectlayer)
                                else glLightf((GLenum)(GL_LIGHT0+count), GL_SPOT_CUTOFF, 180.0);
                        }
                        
-                       vec[0]= lightdata->m_energy*lightdata->m_red;
-                       vec[1]= lightdata->m_energy*lightdata->m_green;
-                       vec[2]= lightdata->m_energy*lightdata->m_blue;
-                       vec[3]= 1.0;
-                       glLightfv((GLenum)(GL_LIGHT0+count), GL_DIFFUSE, vec); 
+                       if (lightdata->m_nodiffuse)
+                       {
+                               vec[0] = vec[1] = vec[2] = vec[3] = 0.0;
+                       } else {
+                               vec[0]= lightdata->m_energy*lightdata->m_red;
+                               vec[1]= lightdata->m_energy*lightdata->m_green;
+                               vec[2]= lightdata->m_energy*lightdata->m_blue;
+                               vec[3]= 1.0;
+                       }
+                       glLightfv((GLenum)(GL_LIGHT0+count), GL_DIFFUSE, vec);
+                       if (lightdata->m_nospecular)
+                       {
+                               vec[0] = vec[1] = vec[2] = vec[3] = 0.0;
+                       } else if (lightdata->m_nodiffuse) {
+                               vec[0]= lightdata->m_energy*lightdata->m_red;
+                               vec[1]= lightdata->m_energy*lightdata->m_green;
+                               vec[2]= lightdata->m_energy*lightdata->m_blue;
+                               vec[3]= 1.0;
+                       }
                        glLightfv((GLenum)(GL_LIGHT0+count), GL_SPECULAR, vec);
                        glEnable((GLenum)(GL_LIGHT0+count));
 
-                       glPopMatrix();
-
                        count++;
-                       if(count>7) 
-                               break;
+                       
                }
        }
+       glPopMatrix();
 
        return count;
 
@@ -426,12 +448,49 @@ int       KX_BlenderRenderTools::applyLights(int objectlayer)
 
 RAS_IPolyMaterial* KX_BlenderRenderTools::CreateBlenderPolyMaterial(
                const STR_String &texname,
-               bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,int transparant,int lightlayer
+               bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant,bool zsort, int lightlayer
                ,bool bIsTriangle,void* clientobject,void* tface)
 {
-       return new KX_BlenderPolyMaterial(
+       assert(!"Deprecated");
+/*     return new KX_BlenderPolyMaterial(
 
                texname,
-               ba,matname,tile,tilexrep,tileyrep,mode,transparant,lightlayer
-               ,bIsTriangle,clientobject,(struct TFace*)tface);
+               ba,matname,tile,tilexrep,tileyrep,mode,transparant,zsort, lightlayer
+               ,bIsTriangle,clientobject,(struct MTFace*)tface);*/
+       return NULL;
 }
+
+void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
+{
+       int state = rasterizer->GetMotionBlurState();
+       float motionblurvalue;
+       if(state)
+       {
+               motionblurvalue = rasterizer->GetMotionBlurValue();
+               if(state==1)
+               {
+                       //bugfix:load color buffer into accum buffer for the first time(state=1)
+                       glAccum(GL_LOAD, 1.0);
+                       rasterizer->SetMotionBlurState(2);
+               }
+               else if(motionblurvalue>=0.0 && motionblurvalue<=1.0)
+               {
+                       glAccum(GL_MULT, motionblurvalue);
+                       glAccum(GL_ACCUM, 1-motionblurvalue);
+                       glAccum(GL_RETURN, 1.0);
+                       glFlush();
+               }
+       }
+}
+
+void KX_BlenderRenderTools::Update2DFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text)
+{
+       m_filtermanager.EnableFilter(propNames, gameObj, filtermode, pass, text);
+}
+
+void KX_BlenderRenderTools::Render2DFilters(RAS_ICanvas* canvas)
+{
+       m_filtermanager.RenderFilters(canvas);
+}
+
+unsigned int KX_BlenderRenderTools::m_numgllights;