diff options
69 files changed, 6098 insertions, 365 deletions
diff --git a/source/Makefile b/source/Makefile index 732d7fd97f6..f0d0323934e 100644 --- a/source/Makefile +++ b/source/Makefile @@ -110,6 +110,8 @@ ifneq ($(NAN_NO_KETSJI),true) COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a COMLIB += $(OCGDIR)/gameengine/ketsji/$(DEBUG_DIR)libketsji.a + COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a + COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a COMLIB += $(NAN_SOLID)/lib/libsolid.a COMLIB += $(NAN_SOLID)/lib/libsolid_broad.a COMLIB += $(NAN_SOLID)/lib/libsolid_complex.a diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 6ecd3626993..c5afa9a1980 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -192,6 +192,7 @@ typedef struct Global { #define G_FIle_PUBLISH (1 << 9) #define G_FILE_NO_UI (1 << 10) #define G_FILE_GAME_TO_IPO (1 << 11) +#define G_FILE_GAME_MAT (1 << 12) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index 8e6c04c50aa..f5e3b5d16d5 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -1261,6 +1261,7 @@ static void do_info_gamemenu(void *arg, int event) case G_FILE_SHOW_DEBUG_PROPS: case G_FILE_AUTOPLAY: case G_FILE_GAME_TO_IPO: + case G_FILE_GAME_MAT: G.fileflags ^= event; break; default: @@ -1295,7 +1296,12 @@ static uiBlock *info_gamemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Record Game Physics to IPO", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, ""); } - + if(G.fileflags & G_FILE_GAME_MAT) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); + } + if(G.fileflags & G_FILE_SHOW_FRAMERATE) { @@ -1319,7 +1325,7 @@ static uiBlock *info_gamemenu(void *arg_unused) } uiBlockSetDirection(block, UI_DOWN); - uiTextBoundsBlock(block, 50); + uiTextBoundsBlock(block, 70); return block; } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 3325d78eb13..b1dbc61e969 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -362,6 +362,9 @@ void space_set_commmandline_options(void) { a= (G.fileflags & G_FILE_GAME_TO_IPO); SYS_WriteCommandLineInt(syshandle, "game2ipo", a); + a=(G.fileflags & G_FILE_GAME_MAT); + SYS_WriteCommandLineInt(syshandle, "blender_material", a); + } } diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 2948c45de71..028dcbe4601 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -48,6 +48,7 @@ #include "KX_BlenderMouseDevice.h" #include "KX_BlenderRenderTools.h" #include "KX_BlenderSystem.h" +#include "BL_Material.h" #include "KX_KetsjiEngine.h" #include "KX_BlenderSceneConverter.h" @@ -103,7 +104,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, strcpy (pathname, maggie->name); STR_String exitstring = ""; BlendFileData *bfd= NULL; - + bgl::InitExtensions(1); do @@ -117,6 +118,21 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool game2ipo = (SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0); + + bool usemat = false; + + #ifdef GL_ARB_multitexture + if(bgl::RAS_EXT_support._ARB_multitexture && bgl::QueryVersion(1, 1)) { + usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0); + int unitmax=0; + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&unitmax); + bgl::max_texture_units = MAXTEX>unitmax?unitmax:MAXTEX; + //std::cout << "using(" << bgl::max_texture_units << ") of(" << unitmax << ") texture units." << std::endl; + } else { + bgl::max_texture_units = 0; + } + #endif + // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(area); @@ -273,7 +289,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, if (always_use_expand_framing) sceneconverter->SetAlwaysUseExpandFraming(true); - + if(usemat) + sceneconverter->SetMaterials(true); + KX_Scene* startscene = new KX_Scene(keyboarddevice, mousedevice, networkdevice, @@ -400,7 +418,6 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, delete canvas; canvas = NULL; } - SND_DeviceManager::Unsubscribe(); } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index e35ec6f41ef..a100c3aaa0a 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -53,6 +53,8 @@ #include "KX_BlenderPolyMaterial.h" #include "KX_PolygonMaterial.h" +#include "KX_BlenderMaterial.h" + #include "Value.h" #include "KX_BlenderGL.h" // for text printing @@ -256,8 +258,16 @@ void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); - KX_PolygonMaterial* blenderpoly = static_cast<KX_PolygonMaterial*>(polymat); - struct TFace* tface = blenderpoly->GetTFace(); + const unsigned int flag = polymat->GetFlag(); + struct TFace* tface = 0; + + if(flag & RAS_BLENDERMAT) { + KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(polymat); + tface = bl_mat->GetTFace(); + } else { + KX_PolygonMaterial* blenderpoly = static_cast<KX_PolygonMaterial*>(polymat); + tface = blenderpoly->GetTFace(); + } BL_RenderText( mode,mytext,mytext.Length(),tface,v1,v2,v3,v4); @@ -288,8 +298,8 @@ void KX_BlenderRenderTools::EnableOpenGLLights() glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, false); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); if (bgl::QueryExtension(bgl::_GL_EXT_separate_specular_color) || bgl::QueryVersion(1, 2)) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index f0c58f1d989..7497f10724d 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -48,6 +48,24 @@ #include <config.h> #endif + +BL_ArmatureObject::BL_ArmatureObject( + void* sgReplicationInfo, + SG_Callbacks callbacks, + Object *armature ) + +: KX_GameObject(sgReplicationInfo,callbacks), + m_objArma(armature), + m_mrdPose(NULL), + m_lastframe(0.), + m_activeAct(NULL), + m_activePriority(999) +{ + m_armature = get_armature(m_objArma); + m_pose = m_objArma->pose; +} + + CValue* BL_ArmatureObject::GetReplica() { BL_ArmatureObject* replica = new BL_ArmatureObject(*this); @@ -78,10 +96,14 @@ BL_ArmatureObject::~BL_ArmatureObject() void BL_ArmatureObject::ApplyPose() { if (m_pose){ - if (!m_mrdPose) - copy_pose (&m_mrdPose, m_pose, 0); - else - extract_pose_from_pose(m_mrdPose, m_pose); + // copy to armature object + extract_pose_from_pose(m_objArma->pose, m_pose); + + // is this needed anymore? + //if (!m_mrdPose) + // copy_pose (&m_mrdPose, m_pose, 0); + //else + // extract_pose_from_pose(m_mrdPose, m_pose); } } @@ -136,14 +158,15 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose) /* If the caller supplies a null pose, create a new one. */ /* Otherwise, copy the armature's pose channels into the caller-supplied pose */ - if (!m_mrdPose){ - copy_pose (&m_mrdPose, m_pose, 0); - } + // is this needed anymore? + //if (!m_mrdPose){ + // copy_pose (&m_mrdPose, m_pose, 0); + //} if (!*pose) - copy_pose(pose, m_mrdPose, 0); + copy_pose(pose, m_objArma->pose, 0); else - extract_pose_from_pose(*pose, m_mrdPose); + extract_pose_from_pose(*pose, m_objArma->pose); } @@ -171,7 +194,5 @@ bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const float BL_ArmatureObject::GetBoneLength(Bone* bone) const { - return (MT_Point3(bone->head) - MT_Point3(bone->tail)).length(); + return (float)(MT_Point3(bone->head) - MT_Point3(bone->tail)).length(); } - - diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h index 7244d08da76..af0212d77a8 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.h +++ b/source/gameengine/Converter/BL_ArmatureObject.h @@ -39,9 +39,9 @@ struct bArmature; struct Bone; - class BL_ActionActuator; class MT_Matrix4x4; +struct Object; class BL_ArmatureObject : public KX_GameObject { @@ -50,30 +50,26 @@ public: short GetActivePriority(); virtual void ProcessReplica(BL_ArmatureObject *replica); class BL_ActionActuator * GetActiveAction(); - BL_ArmatureObject(void* sgReplicationInfo, SG_Callbacks callbacks, - bArmature *armature, - struct bPose *pose) : - KX_GameObject(sgReplicationInfo,callbacks), - m_armature(armature), - m_pose(pose), - m_mrdPose(NULL), - m_lastframe(0.), - m_activeAct(NULL), - m_activePriority(999) - {} + + BL_ArmatureObject( + void* sgReplicationInfo, + SG_Callbacks callbacks, + Object *armature + ); + virtual ~BL_ArmatureObject(); - virtual CValue* GetReplica(); - virtual ~BL_ArmatureObject(); - void GetMRDPose(bPose **pose); - void GetPose(struct bPose **pose); + virtual CValue* GetReplica(); + void GetMRDPose(struct bPose **pose); + void GetPose(struct bPose **pose); void SetPose (struct bPose *pose); void ApplyPose(); bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime); struct bArmature * GetArmature() { return m_armature; } - const struct bArmature * GetArmature() const { return m_armature; } + Object* GetArmatureObject() {return m_objArma;} + /// Retrieve the pose matrix for the specified bone. /// Returns true on success. bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const; @@ -82,6 +78,7 @@ public: float GetBoneLength(Bone* bone) const; protected: + Object *m_objArma; struct bArmature *m_armature; struct bPose *m_pose; struct bPose *m_mrdPose; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index fe0cf281a1a..368fe6f9a31 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -83,6 +83,9 @@ #include "RAS_TexVert.h" #include "RAS_BucketManager.h" #include "RAS_IRenderTools.h" +#include "BL_Material.h" +#include "KX_BlenderMaterial.h" +#include "BL_Texture.h" #include "DNA_action_types.h" #include "BKE_main.h" @@ -108,6 +111,7 @@ /* This list includes only data type definitions */ #include "DNA_object_types.h" #include "DNA_material_types.h" +#include "DNA_texture_types.h" #include "DNA_image_types.h" #include "DNA_lamp_types.h" #include "DNA_group_types.h" @@ -217,6 +221,339 @@ static void SetDefaultFaceType(Scene* scene) } } + +// -- +static void GetRGB(short type, + MFace* mface, + MCol* mmcol, + Material *mat, + TFace *tface, + unsigned int &c0, + unsigned int &c1, + unsigned int &c2, + unsigned int &c3) +{ + unsigned int colour = 0xFFFFFFFFL; + switch(type) + { + case 0: // vertex colors? + { + if(mmcol) { + c0 = KX_Mcol2uint_new(mmcol[0]); + c1 = KX_Mcol2uint_new(mmcol[1]); + c2 = KX_Mcol2uint_new(mmcol[2]); + if (mface->v4) + c3 = KX_Mcol2uint_new(mmcol[3]); + mmcol += 4; + }else // backup white + { + c0 = KX_rgbaint2uint_new(colour); + c1 = KX_rgbaint2uint_new(colour); + c2 = KX_rgbaint2uint_new(colour); + if (mface->v4) + c3 = KX_rgbaint2uint_new( colour ); + } + } break; + + + case 1: // material rgba + { + if (mat) { + union { + unsigned char cp[4]; + unsigned int integer; + } col_converter; + col_converter.cp[3] = (unsigned char) (mat->r*255.0); + col_converter.cp[2] = (unsigned char) (mat->g*255.0); + col_converter.cp[1] = (unsigned char) (mat->b*255.0); + col_converter.cp[0] = (unsigned char) (mat->alpha*255.0); + colour = col_converter.integer; + } + c0 = KX_rgbaint2uint_new(colour); + c1 = KX_rgbaint2uint_new(colour); + c2 = KX_rgbaint2uint_new(colour); + if (mface->v4) + c3 = KX_rgbaint2uint_new(colour); + } break; + + case 2: // vertex colors + { + if(tface ) { + c0 = KX_rgbaint2uint_new(tface->col[0]); + c1 = KX_rgbaint2uint_new(tface->col[1]); + c2 = KX_rgbaint2uint_new(tface->col[2]); + + if (mface->v4) { + c3 = KX_rgbaint2uint_new(tface->col[3]); + } + }else { + c0 = KX_rgbaint2uint_new(colour); + c1 = KX_rgbaint2uint_new(colour); + c2 = KX_rgbaint2uint_new(colour); + if (mface->v4) + c3 = KX_rgbaint2uint_new( colour ); + } + } break; + + case 3: // white + { + c0 = KX_rgbaint2uint_new(colour); + c1 = KX_rgbaint2uint_new(colour); + c2 = KX_rgbaint2uint_new(colour); + if (mface->v4) + c3 = KX_rgbaint2uint_new(colour); + } break; + } +} + +// ------------------------------------ +BL_Material* ConvertMaterial( Mesh* mesh, Material *mat, TFace* tface, MFace* mface, MCol* mmcol, int lightlayer, Object* blenderobj ) +{ + BL_Material *material = new BL_Material(); + //initBL_Material(material); + int numchan = -1; + bool validmat = (mat!=0); + bool using_facetexture = false; + + short type = 0; + if( validmat ) + type = 1; // material color + else if(mesh->tface && tface) + type = 2; // vertex colors + + material->IdMode = DEFAULT_BLENDER; + + // -------------------------------- + if(validmat) { + + // use vertex colors by explicitly setting + if(mat->mode &MA_VERTEXCOLP) + type = 2; + + // use lighting? + material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT; + MTex *mttmp = 0; + numchan = getNumTexChannels(mat); + int valid_index = 0; + + bool facetex = ((mat->mode & MA_FACETEXTURE) && (mesh->tface && tface) ); + + numchan = numchan>MAXTEX?MAXTEX:(numchan>=0&& facetex)?numchan+1:numchan; + + // foreach MTex + for(int i=0; i<numchan; i++) { + // use face tex + if(i==0 && facetex ) { + Image*tmp = (Image*)(tface->tpage); + if(tmp) { + material->img[i] = tmp; + material->texname[i] = material->img[i]->id.name; + material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; + material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0; + material->ras_mode|= ( tface->transp &(TF_ADD | TF_ALPHA))?TRANSP:0; + material->mapping[i].mapping |= ( (material->img[i]->flag & IMA_REFLECT)!=0 )?USEREFL:0; + material->blend_mode[i] = BLEND_MUL; + i++;// skip to the next image + valid_index++; + } + } + + mttmp = getImageFromMaterial( mat, i ); + if( mttmp ) { + if( mttmp->tex ) { + if( mttmp->tex->type == TEX_IMAGE ) { + material->mtexname[i] = mttmp->tex->id.name; + material->img[i] = mttmp->tex->ima; + if( material->img[i] ) { + + material->texname[i] = material->img[i]->id.name; + material->flag[i] |= ( mttmp->tex->imaflag &TEX_MIPMAP )?MIPMAP:0; + // ----------------------- + if( mttmp->tex->imaflag &TEX_USEALPHA ) { + material->flag[i] |= USEALPHA; + material->ras_mode |= TRANSP; + } + // ----------------------- + else if( mttmp->tex->imaflag &TEX_CALCALPHA ) { + material->flag[i] |= CALCALPHA; + material->ras_mode |= TRANSP; + } + + material->color_blend[i] = mttmp->colfac; + material->flag[i] |= ( mttmp->mapto & MAP_ALPHA )?TEXALPHA:0; + material->flag[i] |= ( mttmp->texflag& MTEX_NEGATIVE )?TEXNEG:0; + + } + } + else if(mttmp->tex->type == TEX_ENVMAP) { + if( mttmp->tex->env->stype == ENV_LOAD ) { + + material->mtexname[i]= mttmp->tex->id.name; + material->cubemap[i] = mttmp->tex->env; + if(material->cubemap[i]->ima) { + material->texname[i] = material->cubemap[i]->ima->id.name; + material->mapping[i].mapping |= USEENV; + } + else { + // in the player, we need to split it our self + material->cubemap[i]->ima = mttmp->tex->ima; + if(material->cubemap[i]->ima) { + material->texname[i] = material->cubemap[i]->ima->id.name; + material->mapping[i].mapping |= USEENV; + } + // + } + } + } + material->flag[i] |= (mat->ipo!=0)?HASIPO:0; + /// -------------------------------- + // mapping methods + material->mapping[i].mapping |= ( mttmp->texco & TEXCO_REFL )?USEREFL:0; + + if(mttmp->texco & TEXCO_OBJECT) { + material->mapping[i].mapping |= USEOBJ; + if(mttmp->object) + material->mapping[i].objconame = mttmp->object->id.name; + } + + material->mapping[i].scale[0] = mttmp->size[0]; + material->mapping[i].scale[1] = mttmp->size[1]; + material->mapping[i].scale[2] = mttmp->size[2]; + material->mapping[i].offsets[0] = mttmp->ofs[0]; + material->mapping[i].offsets[1] = mttmp->ofs[1]; + material->mapping[i].offsets[2] = mttmp->ofs[2]; + + material->mapping[i].projplane[0] = mttmp->projx; + material->mapping[i].projplane[1] = mttmp->projy; + material->mapping[i].projplane[2] = mttmp->projz; + /// -------------------------------- + + switch( mttmp->blendtype ) { + case MTEX_BLEND: + material->blend_mode[i] = BLEND_MIX; + break; + case MTEX_MUL: + material->blend_mode[i] = BLEND_MUL; + break; + case MTEX_ADD: + material->blend_mode[i] = BLEND_ADD; + break; + case MTEX_SUB: + material->blend_mode[i] = BLEND_SUB; + break; + case MTEX_SCREEN: + material->blend_mode[i] = BLEND_SCR; + break; + } + valid_index++; + } + } + } + // above one tex the switches here + // are not used + switch(valid_index) { + case 0: + material->IdMode = DEFAULT_BLENDER; + break; + case 1: + material->IdMode = ONETEX; + break; + default: + material->IdMode = GREATERTHAN2; + break; + } + + material->num_enabled = valid_index; + + material->speccolor[0] = mat->specr; + material->speccolor[1] = mat->specg; + material->speccolor[2] = mat->specb; + material->hard = (float)mat->har/4.0f; + material->matcolor[0] = mat->r; + material->matcolor[1] = mat->g; + material->matcolor[2] = mat->b; + material->matcolor[3] = mat->alpha; + material->alpha = mat->alpha; + material->emit = mat->emit; + material->spec_f = mat->spec; + material->ref = mat->ref; + material->amb = mat->amb; + material->ras_mode |= ((mat->mode & MA_ZTRA) != 0)?ZSORT:0; + } + else { + int valid = 0; + // check for tface tex to fallback on + if( mesh->tface && tface ){ + material->img[0] = (Image*)(tface->tpage); + // ------------------------ + if(material->img[0]) { + material->texname[0] = material->img[0]->id.name; + material->mapping[0].mapping |= ( (material->img[0]->flag & IMA_REFLECT)!=0 )?USEREFL:0; + material->flag[0] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; + material->flag[0] |= ( tface->transp &TF_ADD )?CALCALPHA:0; + material->ras_mode|= ( tface->transp & (TF_ADD|TF_ALPHA))?TRANSP:0; + valid++; + } + } + material->num_enabled = valid; + material->IdMode = TEXFACE; + material->speccolor[0] = 1.f; + material->speccolor[1] = 1.f; + material->speccolor[2] = 1.f; + material->hard = 35.f; + material->matcolor[0] = 0.5f; + material->matcolor[1] = 0.5f; + material->matcolor[2] = 0.5f; + material->spec_f = 0.5f; + material->ref = 0.8f; + } + MT_Point2 uv[4]; + + if( mesh->tface && tface ) { + + material->ras_mode |= !( + (tface->flag & TF_HIDE) || + (tface->mode & TF_INVISIBLE) + )?POLY_VIS:0; + + material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0; + material->transp = tface->transp; + + if(tface->transp) + material->ras_mode |= TRANSP; + + material->tile = tface->tile; + material->mode = tface->mode; + + uv[0] = MT_Point2(tface->uv[0]); + uv[1] = MT_Point2(tface->uv[1]); + uv[2] = MT_Point2(tface->uv[2]); + + if (mface->v4) + uv[3] = MT_Point2(tface->uv[3]); + } + else { + // nothing at all + material->ras_mode |= (COLLIDER|POLY_VIS| (validmat?0:USE_LIGHT)); + material->mode = default_face_mode; + material->transp = TF_SOLID; + material->tile = 0; + } + unsigned int rgb[4]; + GetRGB(type,mface,mmcol,mat,tface,rgb[0],rgb[1],rgb[2], rgb[3]); + material->SetConversionRGB(rgb); + material->SetConversionUV(uv); + + material->ras_mode |= (mface->v4==0)?TRIANGLE:0; + if(validmat) + material->matname =(mat->id.name); + + material->tface = tface; + material->material = mat; + return material; +} + + RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rendertools, KX_Scene* scene, KX_BlenderSceneConverter *converter) { RAS_MeshObject *meshobj; @@ -283,127 +620,163 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } { - Image* bima = ((mesh->tface && tface) ? (Image*) tface->tpage : NULL); - - STR_String imastr = - ((mesh->tface && tface) ? - (bima? (bima)->id.name : "" ) : "" ); - - char transp=0; - short mode=0, tile=0; - int tilexrep=4,tileyrep = 4; - - if (bima) - { - tilexrep = bima->xrep; - tileyrep = bima->yrep; - - } - - Material* ma = give_current_material(blenderobj, 1 /* mface->mat_nr */); - //const char* matnameptr = (ma ? ma->id.name : ""); /*unused*/ - + Material* ma = 0; bool polyvisible = true; - if (mesh->tface && tface) - { - // Use texface colors if available - //TF_DYNAMIC means the polygon is a collision face - collider = (tface->mode & TF_DYNAMIC != 0); - transp = tface->transp; - tile = tface->tile; - mode = tface->mode; + RAS_IPolyMaterial* polymat = NULL; + + if(converter->GetMaterials()) + { + if(mesh->totcol > 1) + ma = mesh->mat[mface->mat_nr]; + else + ma = give_current_material(blenderobj, 1); + + BL_Material *bl_mat = ConvertMaterial(mesh, ma, tface, mface, mmcol, lightlayer, blenderobj); + // set the index were dealing with + bl_mat->material_index = (int)mface->mat_nr; + + polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); + collider = ((bl_mat->ras_mode & COLLIDER)!=0); - polyvisible = !((tface->flag & TF_HIDE)||(tface->mode & TF_INVISIBLE)); + polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); + converter->RegisterBlenderMaterial(bl_mat); - uv0 = MT_Point2(tface->uv[0]); - uv1 = MT_Point2(tface->uv[1]); - uv2 = MT_Point2(tface->uv[2]); - rgb0 = KX_rgbaint2uint_new(tface->col[0]); - rgb1 = KX_rgbaint2uint_new(tface->col[1]); - rgb2 = KX_rgbaint2uint_new(tface->col[2]); - - if (mface->v4) - { - uv3 = MT_Point2(tface->uv[3]); - rgb3 = KX_rgbaint2uint_new(tface->col[3]); - } - } + unsigned int rgb[4]; + bl_mat->GetConversionRGB(rgb); + rgb0 = rgb[0]; + rgb1 = rgb[1]; + rgb2 = rgb[2]; + rgb3 = rgb[3]; + MT_Point2 uv[4]; + bl_mat->GetConversionUV(uv); + uv0 = uv[0]; + uv1 = uv[1]; + uv2 = uv[2]; + uv3 = uv[3]; + // this is needed to free up memory afterwards + converter->RegisterPolyMaterial(polymat); + } else { - // - if (mmcol) + ma = give_current_material(blenderobj, 1); + + Image* bima = ((mesh->tface && tface) ? (Image*) tface->tpage : NULL); + + STR_String imastr = + ((mesh->tface && tface) ? + (bima? (bima)->id.name : "" ) : "" ); + + char transp=0; + short mode=0, tile=0; + int tilexrep=4,tileyrep = 4; + + if (bima) + { + tilexrep = bima->xrep; + tileyrep = bima->yrep; + + } + + if (mesh->tface && tface) { - // Use vertex colours - rgb0 = KX_Mcol2uint_new(mmcol[0]); - rgb1 = KX_Mcol2uint_new(mmcol[1]); - rgb2 = KX_Mcol2uint_new(mmcol[2]); + // Use texface colors if available + //TF_DYNAMIC means the polygon is a collision face + collider = ((tface->mode & TF_DYNAMIC) != 0); + transp = tface->transp; + tile = tface->tile; + mode = tface->mode; + polyvisible = !((tface->flag & TF_HIDE)||(tface->mode & TF_INVISIBLE)); + uv0 = MT_Point2(tface->uv[0]); + uv1 = MT_Point2(tface->uv[1]); + uv2 = MT_Point2(tface->uv[2]); + rgb0 = KX_rgbaint2uint_new(tface->col[0]); + rgb1 = KX_rgbaint2uint_new(tface->col[1]); + rgb2 = KX_rgbaint2uint_new(tface->col[2]); + if (mface->v4) { - rgb3 = KX_Mcol2uint_new(mmcol[3]); - - } - - mmcol += 4; - } + uv3 = MT_Point2(tface->uv[3]); + rgb3 = KX_rgbaint2uint_new(tface->col[3]); + } + } else { - // If there are no vertex colors OR texfaces, - // Initialize face to white and set COLLSION true and everything else FALSE - unsigned int colour = 0xFFFFFFFFL; - mode = default_face_mode; - transp = TF_SOLID; - tile = 0; - if (ma) + // + if (mmcol) { - // If we have a material, take the default colour from the material. - union + // Use vertex colours + rgb0 = KX_Mcol2uint_new(mmcol[0]); + rgb1 = KX_Mcol2uint_new(mmcol[1]); + rgb2 = KX_Mcol2uint_new(mmcol[2]); + + + if (mface->v4) { - unsigned char cp[4]; - unsigned int integer; - } col_converter; + rgb3 = KX_Mcol2uint_new(mmcol[3]); + + } + + mmcol += 4; + } + else + { + // If there are no vertex colors OR texfaces, + // Initialize face to white and set COLLSION true and everything else FALSE + unsigned int colour = 0xFFFFFFFFL; + mode = default_face_mode; + transp = TF_SOLID; + tile = 0; + if (ma) + { + // If we have a material, take the default colour from the material. + union + { + unsigned char cp[4]; + unsigned int integer; + } col_converter; + + col_converter.cp[3] = (unsigned char) (ma->r*255.0); + col_converter.cp[2] = (unsigned char) (ma->g*255.0); + col_converter.cp[1] = (unsigned char) (ma->b*255.0); + col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); + + colour = col_converter.integer; + } - col_converter.cp[3] = (unsigned char) (ma->r*255.0); - col_converter.cp[2] = (unsigned char) (ma->g*255.0); - col_converter.cp[1] = (unsigned char) (ma->b*255.0); - col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); + rgb0 = KX_rgbaint2uint_new(colour); + rgb1 = KX_rgbaint2uint_new(colour); + rgb2 = KX_rgbaint2uint_new(colour); - colour = col_converter.integer; + if (mface->v4) + rgb3 = KX_rgbaint2uint_new(colour); } - - rgb0 = KX_rgbaint2uint_new(colour); - rgb1 = KX_rgbaint2uint_new(colour); - rgb2 = KX_rgbaint2uint_new(colour); - - if (mface->v4) - rgb3 = KX_rgbaint2uint_new(colour); } - } + - - bool istriangle = (mface->v4==0); - bool zsort = ma?(ma->mode & MA_ZTRA) != 0:false; - - RAS_IPolyMaterial* polymat = new KX_PolygonMaterial(imastr, ma, - tile, tilexrep, tileyrep, - mode, transp, zsort, lightlayer, istriangle, blenderobj, tface); - - if (ma) - { - polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; - polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512 - polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); + bool istriangle = (mface->v4==0); + bool zsort = ma?(ma->mode & MA_ZTRA) != 0:false; + + polymat = new KX_PolygonMaterial(imastr, ma, + tile, tilexrep, tileyrep, + mode, transp, zsort, lightlayer, istriangle, blenderobj, tface); + + if (ma) + { + polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; + polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512 + polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); - } else - { - polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); - polymat->m_shininess = 35.0; - } + } else + { + polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); + polymat->m_shininess = 35.0; + } + // this is needed to free up memory afterwards + converter->RegisterPolyMaterial(polymat); - - // this is needed to free up memory afterwards - converter->RegisterPolyMaterial(polymat); + } RAS_MaterialBucket* bucket = scene->FindBucket(polymat); @@ -466,7 +839,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* tface++; } meshobj->UpdateMaterialList(); - + + + + // ----------------------------------- + // pre calculate texture generation + for(int matid=0; matid<meshobj->NumMaterials(); matid++) + meshobj->GetMaterialBucket(matid)->GetPolyMaterial()->OnConstruction(); + // ----------------------------------- + + return meshobj; } @@ -961,11 +1343,11 @@ static KX_GameObject *gameobject_from_blenderobject( // If this is a skin object, make Skin Controller if (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && ((Mesh*)ob->data)->dvert){ - BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj,ob->parent); + BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj ); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } else if (((Mesh*)ob->data)->dvert){ - BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj,ob->parent); + BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj ); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } @@ -980,10 +1362,11 @@ static KX_GameObject *gameobject_from_blenderobject( case OB_ARMATURE: { - gameobj = new BL_ArmatureObject (kxscene, KX_Scene::m_callbacks, - get_armature(ob), - ob->pose); - + gameobj = new BL_ArmatureObject( + kxscene, + KX_Scene::m_callbacks, + ob // handle + ); /* Get the current pose from the armature object and apply it as the rest pose */ break; } @@ -1018,6 +1401,7 @@ static struct Scene *GetSceneForName(struct Main *maggie, const STR_String& scen return (Scene*) maggie->scene.first; } + // convert blender objects into ketsji gameobjects void BL_ConvertBlenderObjects(struct Main* maggie, const STR_String& scenename, @@ -1103,7 +1487,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { logicmgr->RegisterActionName(curAct->id.name, curAct); } - + SetDefaultFaceType(blenderscene); Base *base = static_cast<Base*>(blenderscene->base.first); @@ -1141,6 +1525,9 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); BL_ConvertIpos(blenderobject,gameobj,converter); + // TODO: expand to multiple ipos per mesh + Material *mat = give_current_material(blenderobject, 1); + if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter); bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0; diff --git a/source/gameengine/Converter/BL_Material.cpp b/source/gameengine/Converter/BL_Material.cpp new file mode 100644 index 00000000000..fd4f0f13989 --- /dev/null +++ b/source/gameengine/Converter/BL_Material.cpp @@ -0,0 +1,131 @@ +// ------------------------------------ +#ifdef WIN32 +#include <windows.h> +#endif // WIN32 +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif + +#include <iostream> + +#include "BL_Material.h" +#include "MT_assert.h" + +#include "DNA_material_types.h" +#include "DNA_texture_types.h" +#include "DNA_image_types.h" +#include "DNA_mesh_types.h" +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +MTex* getImageFromMaterial(Material *mat, int index) +{ + if(!mat) return 0; + + if(!(index >=0 && index <=10) ) return 0; + + MTex *m = mat->mtex[index]; + return m?m:0; +} + +int getNumTexChannels( Material *mat ) +{ + int count = -1; + if(!mat) return -1; + + for(count =0; (count < 10) && mat->mtex[count] != 0; count++) {} + return count; +} + +BL_Material::BL_Material() +{ + rgb[0] = 0; + rgb[1] = 0; + rgb[2] = 0; + rgb[3] = 0; + IdMode = 0; + ras_mode = 0; + tile = 0; + matname = "NoMaterial"; + matcolor[0] = 0.5f; + matcolor[1] = 0.5f; + matcolor[2] = 0.5f; + matcolor[3] = 0.5f; + speccolor[0] = 1.f; + speccolor[1] = 1.f; + speccolor[2] = 1.f; + transp = 0; + hard = 50.f; + spec_f = 0.5f; + alpha = 1.f; + emit = 0.f; + mode = 0; + material = 0; + tface = 0; + material_index = 0; + amb=0.5f; + num_enabled = 0; + + int i; + for(i=0; i<4; i++) + uv[i] = MT_Point2(0.f,1.f); + + for(i=0; i<MAXTEX; i++) // :( + { + mapping[i].mapping = 0; + mapping[i].offsets[0] = 0.f; + mapping[i].offsets[1] = 0.f; + mapping[i].offsets[2] = 0.f; + mapping[i].scale[0] = 1.f; + mapping[i].scale[1] = 1.f; + mapping[i].scale[2] = 1.f; + mapping[i].projplane[0] = PROJX; + mapping[i].projplane[1] = PROJY; + mapping[i].projplane[2] = PROJZ; + mapping[i].objconame = ""; + mtexname[i] = "NULL"; + imageId[i]="NULL"; + flag[i] = 0; + texname[i] = "NULL"; + tilexrep[i] = 1; + tileyrep[i] = 1; + color_blend[i] = 1.f; + blend_mode[i] = 0; + img[i] = 0; + cubemap[i] = 0; + } +} + +void BL_Material::SetConversionRGB(unsigned int *nrgb) { + rgb[0]=*nrgb++; + rgb[1]=*nrgb++; + rgb[2]=*nrgb++; + rgb[3]=*nrgb; +} + +void BL_Material::GetConversionRGB(unsigned int *nrgb) { + *nrgb++ = rgb[0]; + *nrgb++ = rgb[1]; + *nrgb++ = rgb[2]; + *nrgb = rgb[3]; +} + +void BL_Material::SetConversionUV(MT_Point2 *nuv) { + uv[0] = *nuv++; + uv[1] = *nuv++; + uv[2] = *nuv++; + uv[3] = *nuv; +} + +void BL_Material::GetConversionUV(MT_Point2 *nuv){ + *nuv++ = uv[0]; + *nuv++ = uv[1]; + *nuv++ = uv[2]; + *nuv = uv[3]; +} + + diff --git a/source/gameengine/Converter/BL_Material.h b/source/gameengine/Converter/BL_Material.h new file mode 100644 index 00000000000..a55756addb8 --- /dev/null +++ b/source/gameengine/Converter/BL_Material.h @@ -0,0 +1,155 @@ +#ifndef __BL_MATERIAL_H__ +#define __BL_MATERIAL_H__ + +#include "STR_String.h" +#include "MT_Point2.h" + +// -- +struct MTex; +struct Material; +struct Image; +struct TFace; +struct MTex; +struct Material; +struct EnvMap; +// -- + +/** max units + this will default to users available units + to build with more available, just increment this value + although the more you add the slower the search time will be. + we will go for three, which should be enough +*/ +#define MAXTEX 3//match in RAS_TexVert + +// different mapping modes +class BL_Mapping +{ +public: + int mapping; + float scale[3]; + float offsets[3]; + int projplane[3]; + STR_String objconame; +}; + +// base material struct +class BL_Material +{ +private: + unsigned int rgb[4]; + MT_Point2 uv[4]; +public: + // ----------------------------------- + BL_Material(); + + int IdMode; + unsigned int ras_mode; + + STR_String texname[MAXTEX]; + unsigned int flag[MAXTEX]; + int tile,tilexrep[MAXTEX],tileyrep[MAXTEX]; + STR_String matname; + STR_String mtexname[MAXTEX]; + + float matcolor[4]; + float speccolor[3]; + short transp, pad; + + float hard, spec_f; + float alpha, emit, color_blend[MAXTEX], ref; + float amb; + + int blend_mode[MAXTEX]; + + int mode; + int num_enabled; + + int material_index; + + BL_Mapping mapping[MAXTEX]; + STR_String imageId[MAXTEX]; + + + Material* material; + TFace* tface; + Image* img[MAXTEX]; + EnvMap* cubemap[MAXTEX]; + + void SetConversionRGB(unsigned int *rgb); + void GetConversionRGB(unsigned int *rgb); + + void SetConversionUV(MT_Point2 *uv); + void GetConversionUV(MT_Point2 *uv); + +}; + +// BL_Material::IdMode +enum BL_IdMode { + DEFAULT_BLENDER=-1, + TEXFACE, + ONETEX, + TWOTEX, + GREATERTHAN2 +}; + +// BL_Material::blend_mode[index] +enum BL_BlendMode +{ + BLEND_MIX=1, + BLEND_ADD, + BLEND_SUB, + BLEND_MUL, + BLEND_SCR +}; + +// ------------------------------------- +// BL_Material::flag[index] +enum BL_flag +{ + MIPMAP=1, // set to use mipmaps + CALCALPHA=2, // additive + USEALPHA=4, // use actual alpha channel + TEXALPHA=8, // use alpha combiner functions + TEXNEG=16, // negate blending + HASIPO=32 +}; + +// BL_Material::ras_mode +enum BL_ras_mode +{ + POLY_VIS=1, + COLLIDER=2, + ZSORT=4, + TRANSP=8, + TRIANGLE=16, + USE_LIGHT=32 +}; + +// ------------------------------------- +// BL_Material::mapping[index]::mapping +enum BL_MappingFlag +{ + USEREFL=1, + USEENV=2, + USEOBJ=4 +}; + +// BL_Material::BL_Mapping::projplane +enum BL_MappingProj +{ + PROJN=0, + PROJX, + PROJY, + PROJZ +}; + +// ------------------------------------ +//extern void initBL_Material(BL_Material* mat); +extern MTex* getImageFromMaterial(Material *mat, int index); +extern int getNumTexChannels( Material *mat ); +// ------------------------------------ + +#endif + + diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index 7a469c668eb..4555e81254a 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -128,9 +128,7 @@ void BL_MeshDeformer::RecalcNormals() m_transnors[mf->v3]+=MT_Point3(fnor); if (mf->v4) m_transnors[mf->v4]+=MT_Point3(fnor); - } - } for (v =0; v<m_bmesh->totvert; v++){ @@ -154,7 +152,7 @@ void BL_MeshDeformer::VerifyStorage() delete []m_transnors; m_transnors =new MT_Point3[m_bmesh->totvert+m_bmesh->totface]; - m_transverts=new MT_Point3[m_bmesh->totvert]; + m_transverts=new float[(sizeof(*m_transverts)*m_bmesh->totvert)][3]; m_tvtot = m_bmesh->totvert; } } diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index c9030ceca36..adeffd632e7 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -48,14 +48,13 @@ public: void VerifyStorage(); void RecalcNormals(); virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map){}; - BL_MeshDeformer(struct Object* obj, class BL_SkinMeshObject *meshobj,struct Object* armatureObj): + BL_MeshDeformer(struct Object* obj, class BL_SkinMeshObject *meshobj ): m_pMeshObject(meshobj), m_bmesh((struct Mesh*)(obj->data)), + m_objMesh(obj), m_transnors(NULL), m_transverts(NULL), - m_tvtot(0), - m_blenderMeshObject(obj), - m_blenderArmatureObj(armatureObj) + m_tvtot(0) {}; virtual ~BL_MeshDeformer(); virtual void SetSimulatedTime(double time){}; @@ -64,14 +63,17 @@ public: virtual RAS_Deformer* GetReplica(){return NULL;}; // virtual void InitDeform(double time){}; protected: - class BL_SkinMeshObject *m_pMeshObject; - struct Mesh *m_bmesh; - MT_Point3 *m_transnors; - MT_Point3 *m_transverts; - int m_tvtot; - Object* m_blenderMeshObject; - Object* m_blenderArmatureObj; - + class BL_SkinMeshObject* m_pMeshObject; + struct Mesh* m_bmesh; + MT_Point3* m_transnors; + + //MT_Point3* m_transverts; + // this is so m_transverts doesn't need to be converted + // before deformation + float (*m_transverts)[3]; + struct Object* m_objMesh; + // -- + int m_tvtot; }; #endif diff --git a/source/gameengine/Converter/BL_Shader.cpp b/source/gameengine/Converter/BL_Shader.cpp new file mode 100644 index 00000000000..c957241b5e4 --- /dev/null +++ b/source/gameengine/Converter/BL_Shader.cpp @@ -0,0 +1,907 @@ +// ------------------------------------ +#ifdef WIN32 +#include <windows.h> +#endif // WIN32 +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif + +#include <iostream> +#include "BL_Shader.h" +#include "BL_Material.h" + +#include "MT_assert.h" +#include "MT_Matrix4x4.h" +#include "MT_Matrix3x3.h" +#include "KX_PyMath.h" + +#include "RAS_GLExtensionManager.h" + +using namespace bgl; +#define spit(x) std::cout << x << std::endl; + + +BL_Shader::BL_Shader(int n, PyTypeObject *T) +: PyObjectPlus(T), + mShader(0), + mVert(0), + mFrag(0), + mPass(1), + vertProg(""), + fragProg(""), + mOk(0), + mUse(0) +{ + // if !RAS_EXT_support._ARB_shader_objects this class will not be used + + mBlending.src = -1; + mBlending.dest = -1; + mBlending.const_color[0] = 0.0; + mBlending.const_color[1] = 0.0; + mBlending.const_color[2] = 0.0; + mBlending.const_color[3] = 1.0; + + for (int i=0; i<MAXTEX; i++) + { + mSampler[i].type = 0; + mSampler[i].pass = 0; + mSampler[i].unit = -1; + mSampler[i].loc = -1; + mSampler[i].glTexture =0; + } +} + +BL_Shader::~BL_Shader() +{ +#ifdef GL_ARB_shader_objects + if( mShader ) { + glDeleteObjectARB(mShader); + mShader = 0; + } + if( mFrag ) { + glDeleteObjectARB(mFrag); + mFrag = 0; + } + if( mVert ) { + glDeleteObjectARB(mVert); + mVert = 0; + } + + vertProg = 0; + fragProg = 0; + mOk = 0; + + glUseProgramObjectARB(0); +#endif//GL_ARB_shader_objects +} + + +bool BL_Shader::LinkProgram() +{ +#ifdef GL_ARB_shader_objects + if(!vertProg || !fragProg ) return false; + + int vertstat,fragstat,progstat; + + // vertex prog + unsigned int vert = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); + glShaderSourceARB(vert, 1, (const char**) &vertProg, 0); + glCompileShaderARB(vert); + glGetObjectParameterivARB(vert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &vertstat); + // errors if any + printInfo(vert); + + // fragment prog + unsigned int frag = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + glShaderSourceARB(frag, 1,(const char**) &fragProg, 0); + glCompileShaderARB(frag); + glGetObjectParameterivARB(frag, GL_OBJECT_INFO_LOG_LENGTH_ARB, &fragstat); + // errors if any + printInfo(frag); + + if(!vertstat || !fragstat) return false; + + // main prog + unsigned int prog = glCreateProgramObjectARB(); + glAttachObjectARB(prog,vert); + glAttachObjectARB(prog,frag); + + glLinkProgramARB(prog); + glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &progstat); + // info on how it compiled &| linked + printInfo(prog); + + if(!progstat) + return false; + + // assign + mShader = prog; + mVert = vert; + mFrag = frag; + mOk = 1; + return true; +#else + return false; +#endif//GL_ARB_shader_objects +} + +void BL_Shader::printInfo(unsigned int pr) +{ +#ifdef GL_ARB_shader_objects + int length=0; + glGetObjectParameterivARB(pr, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + + if(length > 1) + { + GLcharARB*logger = (GLcharARB*)malloc(sizeof(GLcharARB)*length); + int chars=0; + + glGetInfoLogARB(pr, length, &chars, logger); + if(chars>0) + std::cout << (logger) << std::endl; + + if(logger) + free(logger); + } +#endif//GL_ARB_shader_objects +} + +char *BL_Shader::GetVertPtr() +{ + return vertProg?vertProg:0; +} + +char *BL_Shader::GetFragPtr() +{ + return fragProg?fragProg:0; +} + +void BL_Shader::SetVertPtr( char *vert ) +{ + vertProg = vert; +} + +void BL_Shader::SetFragPtr( char *frag ) +{ + fragProg = frag; +} + +unsigned int BL_Shader::GetProg() +{ + return mShader; +} + +unsigned int BL_Shader::GetVertexShader() +{ + return mVert; +} + +unsigned int BL_Shader::GetFragmentShader() +{ + return mFrag; +} + +const uSampler* BL_Shader::getSampler(int i) +{ + MT_assert(i<=MAXTEX); + return &mSampler[i]; +} + +const uBlending *BL_Shader::getBlending( int pass ) +{ + return &mBlending; +} + +const bool BL_Shader::Ok()const +{ + return (mShader !=0 && mOk && mUse); +} + + +void BL_Shader::InitializeSampler( + int type, + int unit, + int pass, + unsigned int texture) +{ + MT_assert(unit<=MAXTEX); + mSampler[unit].glTexture = texture; + mSampler[unit].loc =-1; + mSampler[unit].pass=0; + mSampler[unit].type=type; + mSampler[unit].unit=unit; +} + +PyObject* BL_Shader::_getattr(const STR_String& attr) +{ + _getattr_up(PyObjectPlus); +} + + +PyMethodDef BL_Shader::Methods[] = +{ + // creation + KX_PYMETHODTABLE( BL_Shader, setSource ), + KX_PYMETHODTABLE( BL_Shader, delSource ), + KX_PYMETHODTABLE( BL_Shader, getVertexProg ), + KX_PYMETHODTABLE( BL_Shader, getFragmentProg ), + KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ), + KX_PYMETHODTABLE( BL_Shader, validate), + /// access functions + KX_PYMETHODTABLE( BL_Shader, isValid), + KX_PYMETHODTABLE( BL_Shader, setUniform1f ), + KX_PYMETHODTABLE( BL_Shader, setUniform2f ), + KX_PYMETHODTABLE( BL_Shader, setUniform3f ), + KX_PYMETHODTABLE( BL_Shader, setUniform4f ), + KX_PYMETHODTABLE( BL_Shader, setUniform1i ), + KX_PYMETHODTABLE( BL_Shader, setUniform2i ), + KX_PYMETHODTABLE( BL_Shader, setUniform3i ), + KX_PYMETHODTABLE( BL_Shader, setUniform4i ), + + KX_PYMETHODTABLE( BL_Shader, setUniformfv ), + KX_PYMETHODTABLE( BL_Shader, setUniformiv ), + + KX_PYMETHODTABLE( BL_Shader, setSampler ), + KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ), + KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ), + // KX_PYMETHODTABLE( BL_Shader, setBlending ), + + {NULL,NULL} //Sentinel +}; + + +PyTypeObject BL_Shader::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "BL_Shader", + sizeof(BL_Shader), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, + __repr, + 0 +}; + + +PyParentObject BL_Shader::Parents[] = { + &PyObjectPlus::Type, + &BL_Shader::Type, + NULL +}; + + +KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" ) +{ +#ifdef GL_ARB_shader_objects + if(mShader !=0 && mOk ) + { + // already set... + Py_Return; + } + + char *v,*f; + int apply=0; + if( PyArg_ParseTuple(args, "ssi", &v, &f, &apply) ) + { + vertProg = v; + fragProg = f; + if( LinkProgram() ) + { + glUseProgramObjectARB( mShader ); + mUse = apply!=0; + Py_Return; + } + else + { + vertProg = 0; + fragProg = 0; + mUse = 0; + glUseProgramObjectARB( 0 ); + } + } + return NULL; +#else + Py_Return; +#endif +} + + +KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" ) +{ +#ifdef GL_ARB_shader_objects + glDeleteObjectARB(mShader); + glDeleteObjectARB(mFrag); + glDeleteObjectARB(mVert); + mShader = 0; + mFrag = 0; + mVert = 0; + vertProg = 0; + fragProg = 0; + mOk = 0; + mUse = 0; + glUseProgramObjectARB(0); +#endif + Py_Return; + +} + + +KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" ) +{ + return PyInt_FromLong( ( mShader !=0 && mOk ) ); +} + +KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" ) +{ + return PyString_FromString(vertProg?vertProg:""); +} + +KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" ) +{ + return PyString_FromString(fragProg?fragProg:""); +} + + +KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()") +{ +#ifdef GL_ARB_shader_objects + if(mShader==0) + { + PyErr_Format(PyExc_TypeError, "invalid shader object"); + return NULL; + } + + int stat = 0; + glValidateProgramARB(mShader); + glGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB, &stat); + printInfo(mShader); + + return PyInt_FromLong((stat!=0)); +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" ) +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + int index=-1; + if(PyArg_ParseTuple(args, "si", &uniform, &index)) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader, uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + if(index <= MAXTEX) + { + mSampler[index].loc = loc; + }else + { + spit("Invalid texture sample index: " << index); + } + Py_Return; + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + +KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" ) +{ + int pass = 1; + if(!PyArg_ParseTuple(args, "i", &pass)) + return NULL; + + mPass = pass; + Py_Return; +} + +/// access functions +KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + float value=0; + if(PyArg_ParseTuple(args, "sf", &uniform, &value )) + { + if( mShader==0 ) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader, uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + glUseProgramObjectARB( mShader ); + glUniform1fARB( loc, value ); + Py_Return; + } + + } + return NULL; +#else + Py_Return; +#endif +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)") +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + float array[2]={ 0,0 }; + if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] )) + { + if( mShader==0 ) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + glUseProgramObjectARB( mShader ); + glUniform2fARB(loc, array[0],array[1] ); + Py_Return; + } + + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + float array[3]={0,0,0}; + if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2])) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + glUseProgramObjectARB(mShader); + glUniform3fARB(loc, array[0],array[1],array[2]); + Py_Return; + } + + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ") +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + float array[4]={0,0,0,0}; + if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3])) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + glUseProgramObjectARB(mShader); + glUniform4fARB(loc, array[0],array[1],array[2], array[3]); + Py_Return; + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" ) +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + int value=0; + if(PyArg_ParseTuple(args, "si", &uniform, &value )) + { + if( mShader==0 ) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader, uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + glUseProgramObjectARB( mShader ); + glUniform1iARB( loc, value ); + Py_Return; + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)") +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + int array[2]={ 0,0 }; + if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] )) + { + if( mShader==0 ) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + glUseProgramObjectARB( mShader ); + glUniform2iARB(loc, array[0],array[1] ); + Py_Return; + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + int array[3]={0,0,0}; + if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2])) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + glUseProgramObjectARB(mShader); + glUniform3iARB(loc, array[0],array[1],array[2]); + Py_Return; + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + +KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ") +{ +#ifdef GL_ARB_shader_objects + char *uniform=""; + int array[4]={0,0,0, 0}; + if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] )) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + glUseProgramObjectARB(mShader); + glUniform4iARB(loc, array[0],array[1],array[2], array[3]); + Py_Return; + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + +KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )") +{ +#ifdef GL_ARB_shader_objects + char*uniform = ""; + PyObject *listPtr =0; + float array_data[4] = {0.f,0.f,0.f,0.f}; + + if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr)) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + if(PySequence_Check(listPtr)) + { + unsigned int list_size = PySequence_Size(listPtr); + + for(unsigned int i=0; (i<list_size && i<=4); i++) + { + PyObject *item = PySequence_GetItem(listPtr, i); + array_data[i] = (float)PyFloat_AsDouble(item); + Py_DECREF(item); + } + switch(list_size) + { + case 2: + { + glUseProgramObjectARB(mShader); + glUniform2fARB(loc, array_data[0],array_data[1]); + Py_Return; + } break; + case 3: + { + glUseProgramObjectARB(mShader); + glUniform3fARB(loc, array_data[0],array_data[1], array_data[2]); + Py_Return; + }break; + case 4: + { + glUseProgramObjectARB(mShader); + glUniform4fARB(loc, array_data[0],array_data[1], array_data[2], array_data[3]); + Py_Return; + }break; + default: + { + PyErr_Format(PyExc_TypeError, "Invalid list size"); + return NULL; + }break; + } + } + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects + +} + +KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )") +{ +#ifdef GL_ARB_shader_objects + char*uniform = ""; + PyObject *listPtr =0; + int array_data[4] = {0,0,0,0}; + + if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr)) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + if(PySequence_Check(listPtr)) + { + unsigned int list_size = PySequence_Size(listPtr); + + for(unsigned int i=0; (i<list_size && i<=4); i++) + { + PyObject *item = PySequence_GetItem(listPtr, i); + array_data[i] = PyInt_AsLong(item); + Py_DECREF(item); + } + switch(list_size) + { + case 2: + { + glUseProgramObjectARB(mShader); + glUniform2iARB(loc, array_data[0],array_data[1]); + Py_Return; + } break; + case 3: + { + glUseProgramObjectARB(mShader); + glUniform3iARB(loc, array_data[0],array_data[1], array_data[2]); + Py_Return; + }break; + case 4: + { + glUseProgramObjectARB(mShader); + glUniform4iARB(loc, array_data[0],array_data[1], array_data[2], array_data[3]); + Py_Return; + }break; + default: + { + PyErr_Format(PyExc_TypeError, "Invalid list size"); + return NULL; + }break; + } + } + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, +"setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" ) +{ +#ifdef GL_ARB_shader_objects + float matr[16] = { + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1 + }; + + char *uniform=""; + PyObject *matrix=0; + int transp=1; // MT_ is row major so transpose by default.... + if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp)) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + if (PyObject_IsMT_Matrix(matrix, 4)) + { + MT_Matrix4x4 mat; + if (PyMatTo(matrix, mat)) + { + mat.getValue(matr); + glUseProgramObjectARB(mShader); + glUniformMatrix4fvARB(loc, 1, (transp!=0)?GL_TRUE:GL_FALSE, matr); + Py_Return; + } + } + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3, +"setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" ) +{ +#ifdef GL_ARB_shader_objects + float matr[9] = { + 1,0,0, + 0,1,0, + 0,0,1, + }; + + char *uniform=""; + PyObject *matrix=0; + int transp=1; // MT_ is row major so transpose by default.... + if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp)) + { + if(mShader==0) + { + PyErr_Format(PyExc_ValueError, "invalid shader object"); + return NULL; + } + int loc= glGetUniformLocationARB(mShader , uniform); + if( loc==-1 ) + { + spit("Invalid uniform value: " << uniform << "."); + Py_Return; + }else + { + if (PyObject_IsMT_Matrix(matrix, 3)) + { + MT_Matrix3x3 mat; + if (PyMatTo(matrix, mat)) + { + mat.getValue(matr); + glUseProgramObjectARB(mShader); + glUniformMatrix3fvARB(loc, 1, (transp!=0)?GL_TRUE:GL_FALSE, matr); + Py_Return; + } + } + } + } + return NULL; +#else + Py_Return; +#endif//GL_ARB_shader_objects +} + + +KX_PYMETHODDEF_DOC( BL_Shader, setBlending, "setBlending(src, dest)" ) +{ + int src, dest; + if(PyArg_ParseTuple(args, "ii", &src, &dest)) + { + mBlending.src = src; + mBlending.dest = dest; + Py_Return; + } + return NULL; +} diff --git a/source/gameengine/Converter/BL_Shader.h b/source/gameengine/Converter/BL_Shader.h new file mode 100644 index 00000000000..19e0cb8e9b3 --- /dev/null +++ b/source/gameengine/Converter/BL_Shader.h @@ -0,0 +1,117 @@ +#ifndef __BL_SHADER_H__ +#define __BL_SHADER_H__ + +#include "PyObjectPlus.h" +#include "BL_Material.h" + +// ----------------------------------- +// user state management +typedef struct uSampler +{ + unsigned int type; + int pass; + int unit; + int loc; + unsigned int glTexture; +}uSampler; + +#define SAMP_2D 1 +#define SAMP_CUBE 2 + + +// ----------------------------------- +typedef struct uBlending +{ + unsigned int pass; + int src; // GL_ blend func values + int dest; + float const_color[4]; +}uBlending; +// ----------------------------------- + +// ---------------- +class BL_Shader : public PyObjectPlus +{ + Py_Header; +private: + unsigned int mShader, + mVert, + mFrag; + int mPass; + bool mOk; + bool mUse; + uSampler mSampler[MAXTEX]; + uBlending mBlending; + char* vertProg; + char* fragProg; + bool LinkProgram(); + void printInfo(unsigned int pr); + +public: + BL_Shader(int n, PyTypeObject *T=&Type); + virtual ~BL_Shader(); + + char* GetVertPtr(); + char* GetFragPtr(); + void SetVertPtr( char *vert ); + void SetFragPtr( char *frag ); + + // --- + int getNumPass() {return mPass;} + bool use() {return mUse;} + + // --- + // access + const uSampler* getSampler(int i); + const uBlending* getBlending( int pass ); + const bool Ok()const; + + unsigned int GetProg(); + unsigned int GetVertexShader(); + unsigned int GetFragmentShader(); + + void InitializeSampler( + int type, + int unit, + int pass, + unsigned int texture + ); + + // ----------------------------------- + // python interface + virtual PyObject* _getattr(const STR_String& attr); + + KX_PYMETHOD_DOC( BL_Shader, setSource ); + KX_PYMETHOD_DOC( BL_Shader, delSource ); + KX_PYMETHOD_DOC( BL_Shader, getVertexProg ); + KX_PYMETHOD_DOC( BL_Shader, getFragmentProg ); + KX_PYMETHOD_DOC( BL_Shader, setNumberOfPasses ); + + // ----------------------------------- + KX_PYMETHOD_DOC( BL_Shader, isValid); + KX_PYMETHOD_DOC( BL_Shader, validate); + KX_PYMETHOD_DOC( BL_Shader, setUniform4f ); + KX_PYMETHOD_DOC( BL_Shader, setUniform3f ); + KX_PYMETHOD_DOC( BL_Shader, setUniform2f ); + KX_PYMETHOD_DOC( BL_Shader, setUniform1f ); + KX_PYMETHOD_DOC( BL_Shader, setUniform4i ); + KX_PYMETHOD_DOC( BL_Shader, setUniform3i ); + KX_PYMETHOD_DOC( BL_Shader, setUniform2i ); + KX_PYMETHOD_DOC( BL_Shader, setUniform1i ); + + KX_PYMETHOD_DOC( BL_Shader, setUniformfv ); + KX_PYMETHOD_DOC( BL_Shader, setUniformiv ); + + KX_PYMETHOD_DOC( BL_Shader, setUniformMatrix4 ); + KX_PYMETHOD_DOC( BL_Shader, setUniformMatrix3 ); + + // these come from within the material buttons + // sampler2d/samplerCube work + KX_PYMETHOD_DOC( BL_Shader, setSampler); + // user blending funcs + KX_PYMETHOD_DOC( BL_Shader, setBlending ); +}; + + + +#endif//__BL_SHADER_H__ diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index 01997e85e42..dc35221335a 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -49,6 +49,11 @@ #include "BKE_action.h" #include "MT_Point3.h" +extern "C"{ + #include "BKE_lattice.h" +} + #include "BKE_utildefines.h" + #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -57,6 +62,8 @@ BL_SkinDeformer::~BL_SkinDeformer() { + if(m_releaseobject && m_armobj) + m_armobj->Release(); }; /* XXX note, this __NLA_OLDDEFORM define seems to be obsolete */ @@ -147,11 +154,8 @@ void BL_SkinDeformer::ProcessReplica() //void where_is_pose (Object *ob); //void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag); -extern "C" void armature_deform_verts(struct Object *armOb, struct Object *target, float (*vertexCos)[3], int numVerts, int deformflag); - void BL_SkinDeformer::Update(void) { - /* See if the armature has been updated for this frame */ if (m_lastUpdate!=m_armobj->GetLastFrame()){ @@ -161,32 +165,28 @@ void BL_SkinDeformer::Update(void) /* XXX note: where_is_pose() (from BKE_armature.h) calculates all matrices needed to start deforming */ /* but it requires the blender object pointer... */ //void where_is_pose (Object *ob); - where_is_pose (m_blenderArmatureObj); +// where_is_pose (m_blenderArmatureObj); /* store verts locally */ - for (int v =0; v<m_bmesh->totvert; v++){ +// for (int v =0; v<m_bmesh->totvert; v++){ /* XXX note, dunno about this line */ - m_transverts[v]=MT_Point3(m_bmesh->mvert[v].co); - } +// m_transverts[v]=MT_Point3(m_bmesh->mvert[v].co); +// } - float test[1000][3]; +// float test[1000][3]; - armature_deform_verts(m_blenderArmatureObj,m_blenderMeshObject,test,m_bmesh->totvert,ARM_DEF_VGROUP); +// armature_deform_verts(m_blenderArmatureObj,m_blenderMeshObject,test,m_bmesh->totvert,ARM_DEF_VGROUP); - /* XXX note: now use this call instead */ -// void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag) - // - armOb = armature object - // - target = Mesh - // - vertexCos[3] = array of numVerts float vectors (3 floats) - // - set deformflag to ARM_DEF_VGROUP - // example (after having filled the m_transverts array): - // armature_deform_verts(m_armobj, m_meshobj, m_transverts, m_bmesh->totvert, ARM_DEF_VGROUP); - + Object* par_arma = m_armobj->GetArmatureObject(); + where_is_pose( par_arma ); + /* store verts locally */ VerifyStorage(); - + for (int v =0; v<m_bmesh->totvert; v++) + VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); + + armature_deform_verts( par_arma, m_objMesh,m_transverts, m_bmesh->totvert, ARM_DEF_VGROUP ); RecalcNormals(); - /* Update the current frame */ m_lastUpdate=m_armobj->GetLastFrame(); @@ -194,16 +194,9 @@ void BL_SkinDeformer::Update(void) } /* XXX note: I propose to drop this function */ - void BL_SkinDeformer::SetArmature(BL_ArmatureObject *armobj) { -// m_armobj = armobj; - -// for (bDeformGroup *dg=(bDeformGroup*)m_defbase->first; dg; dg=(bDeformGroup*)dg->next) { - -/* dg->data no longer exists needs update - dg->data = (void*)get_named_bone(m_armobj->GetArmature(), dg->name); */ -// } - -// GB_validate_defgroups(m_bmesh, m_defbase); + // -- + // only used to set the object now + m_armobj = armobj; } diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index 49c69298336..74adc6c2943 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -64,37 +64,31 @@ public: } void SetArmature (class BL_ArmatureObject *armobj); - BL_SkinDeformer( struct Object *bmeshobj, - class BL_SkinMeshObject *mesh,struct Object* blenderArmatureObj) - :BL_MeshDeformer(bmeshobj, mesh,blenderArmatureObj), - m_armobj(NULL), + BL_SkinDeformer(struct Object *bmeshobj, + class BL_SkinMeshObject *mesh, + BL_ArmatureObject* arma = NULL) + : // + BL_MeshDeformer(bmeshobj, mesh), + m_armobj(arma), m_lastUpdate(-1), - m_defbase(&bmeshobj->defbase) + m_defbase(&bmeshobj->defbase), + m_releaseobject(false) { - /* Build all precalculatable matrices for bones */ -/* XXX note: obsolete */ -// GB_build_mats(bmeshobj->parent->obmat, bmeshobj->obmat, m_premat, m_postmat); -// GB_validate_defgroups((Mesh*)bmeshobj->data, m_defbase); - // Validate bone data in bDeformGroups -/* - for (bDeformGroup *dg=(bDeformGroup*)m_defbase->first; dg; dg=(bDeformGroup*)dg->next) - dg->data = (void*)get_named_bone(barm, dg->name); -*/ }; /* this second constructor is needed for making a mesh deformable on the fly. */ - - BL_SkinDeformer( struct Object *bmeshobj_old, - struct Object *bmeshobj_new, - class BL_SkinMeshObject *mesh,struct Object *bArmatureObj) - :BL_MeshDeformer(bmeshobj_old, mesh,bArmatureObj), - m_armobj(NULL), + BL_SkinDeformer(struct Object *bmeshobj_old, + struct Object *bmeshobj_new, + class BL_SkinMeshObject *mesh, + bool release_object, + BL_ArmatureObject* arma = NULL) + : // + BL_MeshDeformer(bmeshobj_old, mesh), + m_armobj(arma), m_lastUpdate(-1), - m_defbase(&bmeshobj_old->defbase) + m_defbase(&bmeshobj_old->defbase), + m_releaseobject(release_object) { -/* XXX note: obsolete */ -// GB_build_mats(bmeshobj_new->parent->obmat, bmeshobj_new->obmat, m_premat, m_postmat); -// GB_validate_defgroups((Mesh*)bmeshobj_old->data, m_defbase); }; virtual void ProcessReplica(); @@ -104,13 +98,12 @@ public: bool Apply (class RAS_IPolyMaterial *polymat); protected: - BL_ArmatureObject *m_armobj; // Our parent object -/* XXX note obsolete */ -// float m_premat[4][4]; -// float m_postmat[4][4]; + BL_ArmatureObject* m_armobj; // Our parent object float m_time; double m_lastUpdate; - ListBase *m_defbase; + ListBase* m_defbase; + bool m_releaseobject; + }; #endif diff --git a/source/gameengine/Converter/BL_Texture.cpp b/source/gameengine/Converter/BL_Texture.cpp new file mode 100644 index 00000000000..dec76ac42bf --- /dev/null +++ b/source/gameengine/Converter/BL_Texture.cpp @@ -0,0 +1,387 @@ +// ------------------------------------ +#ifdef WIN32 +#include <windows.h> +#endif // WIN32 +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif + +#include <iostream> + +#include "BL_Material.h" +#include "BL_Texture.h" +#include "MT_assert.h" + +#include "DNA_texture_types.h" +#include "DNA_image_types.h" +#include "IMB_imbuf_types.h" +#include "BKE_image.h" +//#include "IMB_imbuf.h" +#include "BLI_blenlib.h" + +#include "RAS_GLExtensionManager.h" +using namespace bgl; + +#define spit(x) std::cout << x << std::endl; + +#include "MEM_guardedalloc.h" + +extern "C" { + // envmaps + #include "IMB_imbuf.h" + void my_envmap_split_ima(EnvMap *env); + void my_free_envmapdata(EnvMap *env); +} + +// (n&(n-1)) zeros the least significant bit of n +static int is_pow2(int num) { + return ((num)&(num-1))==0; +} +static int smaller_pow2(int num) { + while (!is_pow2(num)) + num= num&(num-1); + return num; +} + + + +BL_Texture::BL_Texture() +: mTexture(0), + mError(0), + mOk(0), + mNeedsDeleted(0), + mType(0), + mName("") +{ + // -- +} + +BL_Texture::~BL_Texture() +{ + // -- +} + +void BL_Texture::DeleteTex() +{ + if( mNeedsDeleted ) { + glDeleteTextures(1, (GLuint*)&(*mTexture)); + mNeedsDeleted = 0; + mOk = 0; + } +} + + +bool BL_Texture::InitFromImage( Image *img, bool mipmap) +{ + if(!img || img->ok==0 ) { + mError = true; + mOk = false; + return mOk; + } + if( img->ibuf==0 ) { + load_image(img, IB_rect, "", 0); + if(img->ibuf==0) { + img->ok = 0; + mError = true; + mOk = false; + return mOk; + } + } + mTexture = &img->bindcode; + mName = img->id.name; + mType = BL_TEX2D; + + // smoke em if we got em + if (*mTexture != 0) { + glBindTexture(GL_TEXTURE_2D, *mTexture ); + Validate(); + return mOk; + } + glGenTextures(1, (GLuint*)mTexture); + InitGLTex(img->ibuf->rect, img->ibuf->x, img->ibuf->y, mipmap); + Validate(); + return mOk; +} + +void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) +{ + if (!is_pow2(x) || !is_pow2(y) ) { + InitNonPow2Tex(pix, x,y,mipmap); + return; + } + + glBindTexture(GL_TEXTURE_2D, *mTexture ); + if( mipmap ) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix ); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix ); + } + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + + +void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) +{ + int nx= smaller_pow2(x); + int ny= smaller_pow2(y); + + unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int)); + + gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels); + glBindTexture(GL_TEXTURE_2D, *mTexture ); + + if( mipmap ) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels ); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels ); + } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + free(newPixels); +} + + +bool BL_Texture::InitCubeMap( EnvMap *cubemap ) +{ +#ifdef GL_ARB_texture_cube_map + if(!RAS_EXT_support._ARB_texture_cube_map) { + spit("cubemaps not supported"); + mError = true; + mOk = false; + return mOk; + } + + else if(!cubemap || cubemap->ima->ok==0 ) { + mError = true; + mOk = false; + return mOk; + } + + if( cubemap->ima->ibuf==0 ) { + load_image(cubemap->ima, IB_rect, "", 0); + if(cubemap->ima->ibuf==0) { + cubemap->ima->ok = 0; + mError = true; + mOk = false; + return mOk; + } + } + + EnvMap *CubeMap = cubemap; + mNeedsDeleted = 1; + mBlankTexture = 0; + mType = BL_TEXCUBE; + mTexture = &mBlankTexture; + mName = CubeMap->ima->id.name; + + glGenTextures(1, (GLuint*)(mTexture)); + glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, *mTexture ); + bool needs_split = false; + + if(!CubeMap->cube[0]) needs_split = true; + + if(needs_split){ + // split it + my_envmap_split_ima(CubeMap); + } + + int x = cubemap->ima->ibuf->x; + int y = cubemap->ima->ibuf->y; + unsigned int *data= (unsigned int *)malloc(x*y*sizeof(unsigned int)); + + // ----------------------------------- + x = CubeMap->cube[0]->ibuf->x; + y = CubeMap->cube[0]->ibuf->y; + + // check the first image, and assume the rest + if (!is_pow2(x) || !is_pow2(y)) + { + spit("invalid envmap size please render with CubeRes @ power of two"); + free(data); + data = 0; + mError = true; + mOk = false; + return mOk; + } + memcpy(data, CubeMap->cube[0]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[1]->ibuf->x; + y = CubeMap->cube[1]->ibuf->y; + memcpy(data, CubeMap->cube[1]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[2]->ibuf->x; + y = CubeMap->cube[2]->ibuf->y; + memcpy(data, CubeMap->cube[2]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[3]->ibuf->x; + y = CubeMap->cube[3]->ibuf->y; + memcpy(data, CubeMap->cube[3]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[4]->ibuf->x; + y = CubeMap->cube[4]->ibuf->y; + memcpy(data, CubeMap->cube[4]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[5]->ibuf->x; + y = CubeMap->cube[5]->ibuf->y; + memcpy(data, CubeMap->cube[5]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT ); + + if(data) { + free(data); + data = 0; + } + + if(needs_split) { + // okay we allocated, swap back to orig and free used + cubemap->ima = CubeMap->ima; + my_free_envmapdata(CubeMap); + } + mOk = IsValid(); + return mOk; + +#else + + mError = true; + mOk = false; + return mOk; + +#endif//GL_ARB_texture_cube_map +} + + +STR_String BL_Texture::GetName() const +{ + return mName; +} + + +bool BL_Texture::IsValid() +{ + return (mTexture && *mTexture!= 0)?glIsTexture(*mTexture)!=0:false; +} + + +void BL_Texture::Validate() +{ + mOk = IsValid(); +} + + +bool BL_Texture::Ok() +{ + return ( mTexture?((!mError || mOk ) && *mTexture!= 0):0 ); +} + + +unsigned int BL_Texture::GetTextureType() const +{ + return mType; +} + + +BL_Texture::operator const unsigned int () const +{ + return mTexture? *mTexture:0; +} + +bool BL_Texture::SetGLTex(unsigned int tex) +{ + return false; +} + +extern "C" { + +void my_envmap_split_ima(EnvMap *env) +{ + ImBuf *ibuf; + Image *ima; + int dx, part; + + my_free_envmapdata(env); + + dx= env->ima->ibuf->y; + dx/= 2; + if(3*dx != env->ima->ibuf->x) { + printf("Incorrect envmap size\n"); + env->ok= 0; + env->ima->ok= 0; + } + else { + for(part=0; part<6; part++) { + ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0); + ima= (Image*)MEM_callocN(sizeof(Image), "image"); + ima->ibuf= ibuf; + ima->ok= 1; + env->cube[part]= ima; + } + IMB_rectop(env->cube[0]->ibuf, env->ima->ibuf, + 0, 0, 0, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[1]->ibuf, env->ima->ibuf, + 0, 0, dx, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[2]->ibuf, env->ima->ibuf, + 0, 0, 2*dx, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[3]->ibuf, env->ima->ibuf, + 0, 0, 0, dx, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[4]->ibuf, env->ima->ibuf, + 0, 0, dx, dx, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[5]->ibuf, env->ima->ibuf, + 0, 0, 2*dx, dx, dx, dx, IMB_rectcpy, 0); + env->ok= 2; + } +} + + +void my_free_envmapdata(EnvMap *env) +{ + Image *ima; + unsigned int a, part; + + for(part=0; part<6; part++) { + ima= env->cube[part]; + if(ima) { + if(ima->ibuf) IMB_freeImBuf(ima->ibuf); + + for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) { + if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); + } + MEM_freeN(ima); + env->cube[part]= 0; + } + } + env->ok= 0; +} + + +} + +unsigned int BL_Texture::mBlankTexture = 0; + diff --git a/source/gameengine/Converter/BL_Texture.h b/source/gameengine/Converter/BL_Texture.h new file mode 100644 index 00000000000..51bf7270d2d --- /dev/null +++ b/source/gameengine/Converter/BL_Texture.h @@ -0,0 +1,53 @@ +#ifndef __BL_TEXTURE_H__ +#define __BL_TEXTURE_H__ +#include <vector> +// -- +struct Image; +struct EnvMap; +// -- +#include "STR_String.h" + +class BL_Texture +{ +private: + // ----------------------------------- + unsigned int* mTexture; + bool mError; + bool mOk; + bool mNeedsDeleted; + unsigned int mType; + STR_String mName; + static unsigned int mBlankTexture; + std::vector<EnvMap*>mCubeMem; + // ----------------------------------- + void InitNonPow2Tex(unsigned int *p,int x,int y,bool mipmap ); + void InitGLTex(unsigned int *p,int x,int y,bool mipmap ); + +public: + BL_Texture(); + ~BL_Texture( ); + + operator const unsigned int () const; + bool Ok(); + + STR_String GetName() const; + + unsigned int GetTextureType() const; + void DeleteTex(); + bool InitFromImage( Image *img, bool mipmap); + bool InitCubeMap( EnvMap *cubemap ); + // + bool SetGLTex(unsigned int tex); + + void PopCubeMap(); + bool IsValid(); + void Validate(); +}; + +enum TexType{ + BL_TEX2D = 1, + BL_TEXCUBE = 2 +}; + + +#endif//__BL_TEXTURE_H__ diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp index b388af9ad8a..eb03a3c2a38 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ b/source/gameengine/Converter/BlenderWorldInfo.cpp @@ -95,6 +95,10 @@ BlenderWorldInfo::BlenderWorldInfo(struct World* blenderworld) m_backgroundred = blenderworld->horr; m_backgroundgreen = blenderworld->horg; m_backgroundblue = blenderworld->horb; + + m_ambientred = blenderworld->ambr; + m_ambientgreen = blenderworld->ambg; + m_ambientblue = blenderworld->ambb; } else { @@ -144,6 +148,20 @@ float BlenderWorldInfo::getBackColorBlue() } +float BlenderWorldInfo::getAmbientColorRed() +{ + return m_ambientred; +} + +float BlenderWorldInfo::getAmbientColorGreen() +{ + return m_ambientgreen; +} + +float BlenderWorldInfo::getAmbientColorBlue() +{ + return m_ambientblue; +} float BlenderWorldInfo::getMistStart() { diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h index 059942edbec..35e47bbf9b8 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ b/source/gameengine/Converter/BlenderWorldInfo.h @@ -48,7 +48,11 @@ class BlenderWorldInfo : public KX_WorldInfo float m_mistred; float m_mistgreen; float m_mistblue; - + + float m_ambientred; + float m_ambientgreen; + float m_ambientblue; + public: BlenderWorldInfo(struct World* blenderworld); ~BlenderWorldInfo(); @@ -58,6 +62,10 @@ public: float getBackColorRed(); float getBackColorGreen(); float getBackColorBlue(); + + float getAmbientColorRed(); + float getAmbientColorGreen(); + float getAmbientColorBlue(); float getMistStart(); float getMistDistance(); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 34b9b065c12..28af414de83 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -42,6 +42,7 @@ #include "PHY_IPhysicsEnvironment.h" #include "KX_KetsjiEngine.h" #include "KX_IPhysicsController.h" +#include "BL_Material.h" #include "DummyPhysicsEnvironment.h" @@ -98,7 +99,8 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter( : m_maggie(maggie), m_sipo(sipo), m_ketsjiEngine(engine), - m_alwaysUseExpandFraming(false) + m_alwaysUseExpandFraming(false), + m_usemat(false) { m_newfilename = ""; } @@ -129,7 +131,15 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() delete (*itp); itp++; } - + + // delete after RAS_IPolyMaterial + vector<BL_Material *>::iterator itmat = m_materials.begin(); + while (itmat != m_materials.end()) { + delete (*itmat); + itmat++; + } + + vector<RAS_MeshObject*>::iterator itm = m_meshobjects.begin(); while (itm != m_meshobjects.end()) { delete (*itm); @@ -345,6 +355,24 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, } +// use blender materials +void KX_BlenderSceneConverter::SetMaterials(bool val) +{ + m_usemat = val; +} + +bool KX_BlenderSceneConverter::GetMaterials() +{ + return m_usemat; +} + + +void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat) +{ + m_materials.push_back(mat); +} + + void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming( bool to_what) diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index bdaa8448f6d..db2090aa470 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -44,6 +44,7 @@ class SCA_IController; class RAS_MeshObject; class RAS_IPolyMaterial; class BL_InterpolatorList; +class BL_Material; struct IpoCurve; struct Main; struct SpaceIpo; @@ -53,6 +54,7 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter vector<KX_WorldInfo*> m_worldinfos; vector<RAS_IPolyMaterial*> m_polymaterials; vector<RAS_MeshObject*> m_meshobjects; + vector<BL_Material *> m_materials; GEN_Map<CHashedPtr,struct Object*> m_map_gameobject_to_blender; GEN_Map<CHashedPtr,KX_GameObject*> m_map_blender_to_gameobject; @@ -71,7 +73,8 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter STR_String m_newfilename; class KX_KetsjiEngine* m_ketsjiEngine; bool m_alwaysUseExpandFraming; - + bool m_usemat; + void localDel_ipoCurve ( IpoCurve * icu ,struct SpaceIpo* sipo); struct Ipo* findIpoForName(char* objName); @@ -113,6 +116,8 @@ public: // DT_ShapeHandle FindSumoShape(RAS_MeshObject *for_gamemesh); void RegisterPolyMaterial(RAS_IPolyMaterial *polymat); + + void RegisterBlenderMaterial(BL_Material *mat); void RegisterInterpolatorList(BL_InterpolatorList *ipoList, struct Ipo *for_ipo); BL_InterpolatorList *FindInterpolatorList(struct Ipo *for_ipo); @@ -131,7 +136,9 @@ public: virtual void WritePhysicsObjectToAnimationIpo(int frameNumber); virtual void TestHandlesPhysicsObjectToAnimationIpo(); - + // use blender materials + virtual void SetMaterials(bool val); + virtual bool GetMaterials(); }; diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index 56eda51384b..defcdffb6fc 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -59,6 +59,7 @@ #include "DNA_lamp_types.h" #include "DNA_world_types.h" #include "DNA_camera_types.h" +#include "DNA_material_types.h" /* end of blender include block */ #include "KX_IPO_SGController.h" @@ -66,6 +67,7 @@ #include "KX_CameraIpoSGController.h" #include "KX_WorldIpoController.h" #include "KX_ObColorIpoSGController.h" +#include "KX_MaterialIpoController.h" #include "SG_Node.h" @@ -561,3 +563,195 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co } } + +void BL_ConvertMaterialIpos( + Material* blendermaterial, + KX_GameObject* gameobj, + KX_BlenderSceneConverter *converter + ) +{ + if (blendermaterial->ipo) { + + KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + + BL_InterpolatorList *ipoList= GetIpoList(blendermaterial->ipo, converter); + + + ipocontr->m_rgba[0] = blendermaterial->r; + ipocontr->m_rgba[1] = blendermaterial->g; + ipocontr->m_rgba[2] = blendermaterial->b; + ipocontr->m_rgba[3] = blendermaterial->alpha; + + ipocontr->m_specrgb[0] = blendermaterial->specr; + ipocontr->m_specrgb[1] = blendermaterial->specg; + ipocontr->m_specrgb[2] = blendermaterial->specb; + + ipocontr->m_hard = blendermaterial->har; + ipocontr->m_spec = blendermaterial->spec; + ipocontr->m_ref = blendermaterial->ref; + ipocontr->m_emit = blendermaterial->emit; + ipocontr->m_alpha = blendermaterial->alpha; + KX_IScalarInterpolator *ipo; + + // -- + ipo = ipoList->GetScalarInterpolator(MA_COL_R); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_rgba[0], + ipo); + ipocontr->AddInterpolator(interpolator); + } + + ipo = ipoList->GetScalarInterpolator(MA_COL_G); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_rgba[1], + ipo); + ipocontr->AddInterpolator(interpolator); + } + + ipo = ipoList->GetScalarInterpolator(MA_COL_B); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_rgba[2], + ipo); + ipocontr->AddInterpolator(interpolator); + } + + ipo = ipoList->GetScalarInterpolator(MA_ALPHA); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_rgba[3], + ipo); + ipocontr->AddInterpolator(interpolator); + } + // -- + + ipo = ipoList->GetScalarInterpolator(MA_SPEC_R ); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_specrgb[0], + ipo); + ipocontr->AddInterpolator(interpolator); + } + + ipo = ipoList->GetScalarInterpolator(MA_SPEC_G); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_specrgb[1], + ipo); + ipocontr->AddInterpolator(interpolator); + } + + ipo = ipoList->GetScalarInterpolator(MA_SPEC_B); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_specrgb[2], + ipo); + ipocontr->AddInterpolator(interpolator); + } + + // -- + ipo = ipoList->GetScalarInterpolator(MA_HARD); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_hard, + ipo); + ipocontr->AddInterpolator(interpolator); + } + + ipo = ipoList->GetScalarInterpolator(MA_SPEC); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_spec, + ipo); + ipocontr->AddInterpolator(interpolator); + } + + + ipo = ipoList->GetScalarInterpolator(MA_REF); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_ref, + ipo); + ipocontr->AddInterpolator(interpolator); + } + + ipo = ipoList->GetScalarInterpolator(MA_EMIT); + if (ipo) { + if (!ipocontr) { + ipocontr = new KX_MaterialIpoController(); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } + KX_IInterpolator *interpolator = + new KX_ScalarInterpolator( + &ipocontr->m_emit, + ipo); + ipocontr->AddInterpolator(interpolator); + } + } +} + diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h index e04f33f76fe..e901ae9b3e7 100644 --- a/source/gameengine/Converter/KX_IpoConvert.h +++ b/source/gameengine/Converter/KX_IpoConvert.h @@ -49,6 +49,10 @@ void BL_ConvertCameraIpos(struct Camera* blendercamera, class KX_GameObject* cameraobj, class KX_BlenderSceneConverter *converter); +void BL_ConvertMaterialIpos(struct Material* blendermaterial, + class KX_GameObject* materialobj, + class KX_BlenderSceneConverter *converter); + #endif //__KX_IPOCONVERT_H diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index 00908defdff..40c51da47c3 100755 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -18,7 +18,10 @@ source_files = ['KX_IpoConvert.cpp', 'BL_DeformableGameObject.cpp', 'BL_BlenderDataConversion.cpp', 'BL_ArmatureObject.cpp', - 'BL_ActionActuator.cpp' + 'BL_ActionActuator.cpp', + 'BL_Material.cpp', + 'BL_Texture.cpp', + 'BL_Shader.cpp' ] kx_converter_env.Append (CPPPATH = ['.', diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index bb9ad81f245..48898dfc1f5 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -14,7 +14,6 @@ * purpose. It is provided "as is" without express or implied warranty. * */ - #include "Value.h" #include "FloatValue.h" #include "IntValue.h" @@ -497,9 +496,6 @@ double* CValue::GetVector3(bool bGetTransformedVec) /*--------------------------------------------------------------------------------------------------------------------- Reference Counting ---------------------------------------------------------------------------------------------------------------------*/ - - - // // Add a reference to this value // diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index d49c8debfdc..ccb9c34749d 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -184,6 +184,7 @@ public: + #ifndef NO_EXP_PYTHON_EMBEDDING #include "PyObjectPlus.h" #include "object.h" @@ -339,7 +340,7 @@ protected: virtual void DisableRefCount(); // Disable reference counting for this value virtual void AddDataToReplica(CValue* replica); virtual ~CValue(); -private: +private: // Member variables std::map<STR_String,CValue*>* m_pNamedPropertyArray; // Properties for user/game etc ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage) diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 2be5af034c9..b1d210fd1c1 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -28,6 +28,7 @@ * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ +#include <iostream> #include "SCA_IObject.h" #include "SCA_ISensor.h" @@ -40,7 +41,6 @@ #include <config.h> #endif - MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T) diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index 262f458abb2..8b79703a6fc 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -60,7 +60,6 @@ SCA_LogicManager::~SCA_LogicManager() (*gameobjptr)->Release(); } - /*for (int i=0;i<m_sensorcontrollermap.size();i++) { vector<SCA_IController*>* controllerarray = *(m_sensorcontrollermap[i]); @@ -175,7 +174,6 @@ void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor) void SCA_LogicManager::RemoveDestroyedActuator(SCA_IActuator* actuator) { - m_removedActuators.push_back(SmartActuatorPtr(actuator,0)); // take care that no controller can use this actuator again ! diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index 6e1ddd652cb..2eee2129665 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -96,8 +96,6 @@ public: }; - - class SCA_LogicManager { vector<class SCA_EventManager*> m_eventmanagers; @@ -117,7 +115,6 @@ class SCA_LogicManager GEN_Map<CHashedPtr,void*> m_map_gameobj_to_blendobj; vector<SmartActuatorPtr> m_removedActuators; - public: SCA_LogicManager(); virtual ~SCA_LogicManager(); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 01afd16e963..a5360d99a8b 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -144,8 +144,7 @@ PyObject* SCA_PythonController::sPyGetCurrentController(PyObject* self, #if 0 static char* sPyAddActiveActuator__doc__; #endif - - + PyObject* SCA_PythonController::sPyAddActiveActuator( PyObject* self, @@ -156,18 +155,27 @@ PyObject* SCA_PythonController::sPyAddActiveActuator( PyObject* ob1; int activate; if (!PyArg_ParseTuple(args, "Oi", &ob1,&activate)) - { return NULL; - - } + // for safety, todo: only allow for registered actuators (pointertable) // we don't want to crash gameengine/blender by python scripts + std::vector<SCA_IActuator*> lacts = m_sCurrentController->GetLinkedActuators(); - CValue* ac = (CValue*)ob1; - CValue* boolval = new CBoolValue(activate!=0); - m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)ac,boolval); - boolval->Release(); - + std::vector<SCA_IActuator*>::iterator it; + bool found = false; + CValue* act = (CValue*)ob1; + + for(it = lacts.begin(); it!= lacts.end(); it++) { + if( static_cast<SCA_IActuator*>(act) == (*it) ) { + found=true; + break; + } + } + if(found){ + CValue* boolval = new CBoolValue(activate!=0); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)act,boolval); + boolval->Release(); + } Py_INCREF(Py_None); return Py_None; } @@ -268,12 +276,24 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) ); PyDict_Clear(excdict); Py_DECREF(excdict);*/ - + +// FIXME:: still happining, will try to fix. snailrose... + PyObject *excdict= PyDict_Copy(m_pythondictionary); + PyObject* resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode, + excdict, + excdict + ); + PyDict_Clear(excdict); + Py_DECREF(excdict); + + +#if 0 PyObject* resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode, m_pythondictionary, m_pythondictionary ); - +#endif + if (resultobj) { Py_DECREF(resultobj); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index b1c4a4d6d25..c5324776edb 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -62,6 +62,8 @@ extern "C" #endif // __cplusplus #include "BLI_blenlib.h" #include "BLO_readfile.h" +#include "BKE_global.h" +#include "BKE_main.h" #ifdef __cplusplus } #endif // __cplusplus @@ -82,6 +84,7 @@ extern "C" #include "RAS_GLExtensionManager.h" #include "KX_PythonInit.h" #include "KX_PyConstraintBinding.h" +#include "BL_Material.h" // MAXTEX #include "KX_BlenderSceneConverter.h" #include "NG_LoopBackNetworkDeviceInterface.h" @@ -126,7 +129,8 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR m_rasterizer(0), m_sceneconverter(0), m_networkdevice(0), - m_audiodevice(0) + m_audiodevice(0), + m_blendermat(0) { fSystem = system; } @@ -147,6 +151,7 @@ bool GPG_Application::SetGameEngineData(struct Main* maggie, STR_String startSce if (maggie != NULL && startSceneName != "") { + G.scene = (Scene*)maggie->scene.first; m_maggie = maggie; m_startSceneName = startSceneName; result = true; @@ -488,6 +493,23 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool useVertexArrays = SYS_GetCommandLineInt(syshandle,"vertexarrays",1) != 0; + +#ifdef GL_ARB_multitexture + // ---------------------------------- + if(bgl::RAS_EXT_support._ARB_multitexture && bgl::QueryVersion(1, 1)) { + m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0); + int unitmax=0; + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&unitmax); + bgl::max_texture_units = MAXTEX>unitmax?unitmax:MAXTEX; + //std::cout << "using(" << bgl::max_texture_units << ") of(" << unitmax << ") texture units." << std::endl; + } else { + bgl::max_texture_units = 0; + } +#else + m_blendermat=0; +#endif//GL_ARB_multitexture + // ---------------------------------- + // create the canvas, rasterizer and rendertools m_canvas = new GPG_Canvas(window); if (!m_canvas) @@ -606,7 +628,8 @@ bool GPG_Application::startEngine(void) // if (always_use_expand_framing) // sceneconverter->SetAlwaysUseExpandFraming(true); - + if(m_blendermat) + m_sceneconverter->SetMaterials(true); KX_Scene* startscene = new KX_Scene(m_keyboard, m_mouse, diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 2724b5ac2e3..11ede4d51ca 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -142,5 +142,8 @@ protected: NG_LoopBackNetworkDeviceInterface* m_networkdevice; /** Sound device. */ SND_IAudioDevice* m_audiodevice; + + bool m_blendermat; + }; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index d7a9ad2b41d..5b67f8b8029 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -194,6 +194,7 @@ void usage(char* program) printf(" show_properties 0 Show debug properties\n"); printf(" show_profile 0 Show profiling information\n"); printf(" vertexarrays 1 Enable vertex arrays\n"); + printf(" blender_material 0 Enable material settings\n"); printf("\n"); printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program); printf("example: %s -g vertexarrays = 0 c:\\loadtest.blend\n", program); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp new file mode 100644 index 00000000000..472acc5d5dd --- /dev/null +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -0,0 +1,975 @@ +// ------------------------------------ +// ... +// ------------------------------------ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef WIN32 +#include <windows.h> +#endif // WIN32 +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif + +#include "KX_BlenderMaterial.h" +#include "BL_Material.h" +#include "KX_Scene.h" +#include "KX_Light.h" +#include "KX_GameObject.h" + +#include "MT_Vector3.h" +#include "MT_Vector4.h" +#include "MT_Matrix4x4.h" + +#include "RAS_MeshObject.h" +#include "RAS_IRasterizer.h" +#include "RAS_GLExtensionManager.h" +#include "ARB_multitexture.h" + +extern "C" { +#include "BDR_drawmesh.h" +} + +#include "STR_HashedString.h" + +// ------------------------------------ +#include "DNA_object_types.h" +#include "DNA_material_types.h" +#include "DNA_image_types.h" +#include "DNA_mesh_types.h" +#include "BKE_mesh.h" +// ------------------------------------ +using namespace bgl; +#define spit(x) std::cout << x << std::endl; + +static PyObject *gTextureDict = 0; + +KX_BlenderMaterial::KX_BlenderMaterial( + KX_Scene *scene, + BL_Material *data, + bool skin, + int lightlayer, + void *clientobject, + PyTypeObject *T + ) +: PyObjectPlus(T), + RAS_IPolyMaterial( + STR_String( data->texname[0] ), + STR_String( data->matname ), // needed for physics! + data->tile, + data->tilexrep[0], + data->tileyrep[0], + data->mode, + ((data->ras_mode &TRANSP)!=0), + ((data->ras_mode &ZSORT)!=0), + lightlayer, + ((data->ras_mode &TRIANGLE)!=0), + clientobject + ), + mMaterial(data), + mScene(scene), + mShader(0), + mUseShader(0), + mPass(0) +{ + ///RAS_EXT_support._ARB_multitexture == true if were here + + // -------------------------------- + // RAS_IPolyMaterial variables... + m_flag |=RAS_BLENDERMAT; + m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0; + m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0; + + // figure max + #ifdef GL_ARB_multitexture + int enabled = mMaterial->num_enabled; + mMaterial->num_enabled = enabled>=bgl::max_texture_units?bgl::max_texture_units:enabled; + #else + mMaterial->num_enabled=0; + #endif + + m_enabled = mMaterial->num_enabled; + + // test the sum of the various modes for equality + // so we can ether accept or reject this material + // as being equal, this is rather important to + // prevent material bleeding + for(int i=0; i<mMaterial->num_enabled; i++) { + m_multimode += + (mMaterial->flag[i] + + mMaterial->blend_mode[i] + ); + } + m_multimode += mMaterial->IdMode+mMaterial->ras_mode; + +} + + +KX_BlenderMaterial::~KX_BlenderMaterial() +{ + // cleanup work + OnExit(); +} + + +TFace* KX_BlenderMaterial::GetTFace(void) const +{ + // fonts on polys + MT_assert(mMaterial->tface); + return mMaterial->tface; +} + +void KX_BlenderMaterial::OnConstruction() +{ + // for each unique material... + #ifdef GL_ARB_multitexture + if(!gTextureDict) + gTextureDict = PyDict_New(); + + #ifdef GL_ARB_shader_objects + if( RAS_EXT_support._ARB_shader_objects ) + mShader = new BL_Shader( mMaterial->num_enabled ); + #endif + + int i; + for(i=0; i<mMaterial->num_enabled; i++) { + glActiveTextureARB(GL_TEXTURE0_ARB+i); + + #ifdef GL_ARB_texture_cube_map + if( mMaterial->mapping[i].mapping & USEENV ) { + if(!RAS_EXT_support._ARB_texture_cube_map) { + spit("CubeMap textures not supported"); + continue; + } + if(!mTextures[i].InitCubeMap( mMaterial->cubemap[i] ) ) + spit("unable to initialize image("<<i<<") in "<< + mMaterial->matname<< ", image will not be available"); + + if( RAS_EXT_support._ARB_shader_objects ) + mShader->InitializeSampler(SAMP_CUBE, i, 0, mTextures[i]); + } + + else { + #endif//GL_ARB_texture_cube_map + if( mMaterial->img[i] ) { + if( ! mTextures[i].InitFromImage(mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 )) + spit("unable to initialize image("<<i<<") in "<< + mMaterial->matname<< ", image will not be available"); + + if( RAS_EXT_support._ARB_shader_objects ) + mShader->InitializeSampler(SAMP_2D, i, 0, mTextures[i]); + } + #ifdef GL_ARB_texture_cube_map + } + #endif//GL_ARB_texture_cube_map + PyDict_SetItemString(gTextureDict, mTextures[i].GetName().Ptr(), PyInt_FromLong(mTextures[i])); + } + #endif//GL_ARB_multitexture +} + +void KX_BlenderMaterial::OnExit() +{ + #ifdef GL_ARB_multitexture + + #ifdef GL_ARB_shader_objects + if( RAS_EXT_support._ARB_shader_objects && mShader ) { + //note, the shader here is allocated, per unique material + //and this function is called per face + glUseProgramObjectARB(0); + delete mShader; + mShader = 0; + } + #endif //GL_ARB_shader_objects + + for(int i=0; i<mMaterial->num_enabled; i++) { + glActiveTextureARB(GL_TEXTURE0_ARB+i); + + mTextures[i].DeleteTex(); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + + #ifdef GL_ARB_texture_cube_map + if(RAS_EXT_support._ARB_texture_cube_map) + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + #endif//GL_ARB_texture_cube_map + + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + } + + if (gTextureDict) { + PyDict_Clear(gTextureDict); + Py_DECREF(gTextureDict); + gTextureDict = 0; + } + + glActiveTextureARB(GL_TEXTURE0_ARB); + + #ifdef GL_ARB_texture_cube_map + if(RAS_EXT_support._ARB_texture_cube_map) + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + #endif//GL_ARB_texture_cube_map + + glDisable(GL_TEXTURE_2D); + + #endif//GL_ARB_multitexture + + // make sure multi texture units + // revert back to blender... + // -- + if( mMaterial->tface ) + set_tpage(mMaterial->tface); +} + + +void KX_BlenderMaterial::DisableTexData() +{ + glDisable(GL_BLEND); + #ifdef GL_ARB_multitexture + int i=(MAXTEX>=bgl::max_texture_units?bgl::max_texture_units:MAXTEX)-1; + for(; i>=0; i--) { + glActiveTextureARB(GL_TEXTURE0_ARB+i); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + + #ifdef GL_ARB_texture_cube_map + if(RAS_EXT_support._ARB_texture_cube_map) + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + #endif//GL_ARB_texture_cube_map + + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + } + #endif//GL_ARB_multitexture +} + + +void KX_BlenderMaterial::setShaderData( bool enable ) +{ + #ifdef GL_ARB_multitexture + #ifdef GL_ARB_shader_objects + + MT_assert(RAS_EXT_support._ARB_shader_objects && mShader); + + int i; + if( !enable || !mShader->Ok() ) { + // frame cleanup. + glUseProgramObjectARB( 0 ); + DisableTexData(); + return; + } + + DisableTexData(); + glUseProgramObjectARB( mShader->GetProg() ); + + // for each enabled unit + for(i=0; i<mMaterial->num_enabled; i++) { + + const uSampler *samp = mShader->getSampler(i); + if( samp->loc == -1 || samp->glTexture == 0 ) continue; + + glActiveTextureARB(GL_TEXTURE0_ARB+i); + + #ifdef GL_ARB_texture_cube_map + if( mMaterial->mapping[i].mapping &USEENV ) { + glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, samp->glTexture /* mTextures[i]*/ ); + glEnable( GL_TEXTURE_CUBE_MAP_ARB ); + } + else { + #endif//GL_ARB_texture_cube_map + glBindTexture( GL_TEXTURE_2D, samp->glTexture /*mTextures[i]*/ ); + glEnable( GL_TEXTURE_2D ); + #ifdef GL_ARB_texture_cube_map + } + #endif//GL_ARB_texture_cube_map + // use a sampler + glUniform1iARB(samp->loc, i ); + } + glDisable(GL_BLEND); + + #endif//GL_ARB_shader_objects + #endif//GL_ARB_multitexture +} + + +void KX_BlenderMaterial::setTexData( bool enable ) +{ + #ifdef GL_ARB_multitexture + int i; + + #ifdef GL_ARB_shader_objects + if(RAS_EXT_support._ARB_shader_objects) { + // switch back to fixed func + glUseProgramObjectARB( 0 ); + } + #endif//GL_ARB_shader_objects + + if( !enable ) { + // frame cleanup. + DisableTexData(); + return; + } + + DisableTexData(); + + if( mMaterial->IdMode == DEFAULT_BLENDER ) { + setDefaultBlending(); + return; + } + + if( mMaterial->IdMode == TEXFACE ) { + + // no material connected to the object + if( mTextures[0] ) { + if( !mTextures[0].Ok() ) return; + glActiveTextureARB(GL_TEXTURE0_ARB); + glBindTexture( GL_TEXTURE_2D, mTextures[0] ); + glEnable(GL_TEXTURE_2D); + setTextureEnvironment( -1 ); // modulate + setEnvMap( (mMaterial->mapping[0].mapping &USEREFL)!=0 ); + setDefaultBlending(); + } + return; + } + + int lastblend = 0; + + // for each enabled unit + for(i=0; (i<mMaterial->num_enabled); i++) { + if( !mTextures[i].Ok() ) continue; + + glActiveTextureARB(GL_TEXTURE0_ARB+i); + + #ifdef GL_ARB_texture_cube_map + // use environment maps + if( mMaterial->mapping[i].mapping &USEENV && RAS_EXT_support._ARB_texture_cube_map ) { + // should not happen + // if(mTextures[i].GetTextureType() & BL_TEX2D) continue; + + glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTextures[i] ); + glEnable(GL_TEXTURE_CUBE_MAP_ARB); + setTextureEnvironment( i ); + + if( mMaterial->mapping[i].mapping &USEREFL ) + setEnvMap( true, true ); + else if(mMaterial->mapping[i].mapping &USEOBJ) + setObjectMatrixData(i); + else + setTexMatrixData( i ); + } + // 2d textures + else { + #endif//GL_ARB_texture_cube_map + + // should not happen + //if(mTextures[i].GetTextureType() & BL_TEXCUBE) continue; + // + MT_assert(!(mTextures[i].GetTextureType() & BL_TEXCUBE)); + + glBindTexture( GL_TEXTURE_2D, mTextures[i] ); + glEnable( GL_TEXTURE_2D ); + setTextureEnvironment( i ); + + if( mMaterial->mapping[i].mapping &USEREFL ){ + setEnvMap( true ); + } + else if(mMaterial->mapping[i].mapping &USEOBJ){ + setObjectMatrixData(i); + } + else { + setTexMatrixData( i ); + } + + #ifdef GL_ARB_texture_cube_map + } + #endif//GL_ARB_texture_cube_map + + // if either unit has set blending + // and its the last pass + lastblend += setBlending( i ); // dry run + if(lastblend >0 && i==mMaterial->num_enabled-1) + setBlending( i, true ); + else if(lastblend == 0 && i==mMaterial->num_enabled-1) + glDisable(GL_BLEND); + } + #endif//GL_ARB_multitexture +} + +void +KX_BlenderMaterial::ActivatShaders( + RAS_IRasterizer* rasty, + TCachingInfo& cachingInfo)const +{ + if (GetCachingInfo() != cachingInfo) { + KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); + + if (!cachingInfo) + tmp->setShaderData( false ); + + cachingInfo = GetCachingInfo(); + + if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED ) { + tmp->setShaderData( true ); + rasty->EnableTextures(true); + } + else { + tmp->setShaderData( false ); + rasty->EnableTextures(false); + } + + if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) + rasty->SetCullFace(false); + else + rasty->SetCullFace(true); + + if (mMaterial->mode & RAS_IRasterizer::KX_LINES) + rasty->SetLines(true); + else + rasty->SetLines(false); + } + + // shaders have access to the variables set here + // via builtin GLSL variables + // eg: gl_FrontMaterial.diffuse + // -- + rasty->SetSpecularity( + mMaterial->speccolor[0]*mMaterial->spec_f, + mMaterial->speccolor[1]*mMaterial->spec_f, + mMaterial->speccolor[2]*mMaterial->spec_f, + mMaterial->spec_f + ); + + rasty->SetShinyness( mMaterial->hard ); + + rasty->SetDiffuse( + mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, + mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit, + mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit, + 1.0f); + + rasty->SetEmissive( + mMaterial->matcolor[0]*mMaterial->emit, + mMaterial->matcolor[1]*mMaterial->emit, + mMaterial->matcolor[2]*mMaterial->emit, + 1.0 + ); + + // Lagan's patch... + // added material factor + rasty->SetAmbient(mMaterial->amb); + + if (mMaterial->material) + rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0); +} + +void +KX_BlenderMaterial::ActivateMat( + RAS_IRasterizer* rasty, + TCachingInfo& cachingInfo + )const +{ + if (GetCachingInfo() != cachingInfo) { + KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); + + if (!cachingInfo) + tmp->setTexData( false ); + + cachingInfo = GetCachingInfo(); + + if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { + tmp->setTexData( true ); + rasty->EnableTextures(true); + } + else{ + tmp->setTexData( false ); + rasty->EnableTextures(false); + } + + if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) + rasty->SetCullFace(false); + else + rasty->SetCullFace(true); + + if (mMaterial->mode & RAS_IRasterizer::KX_LINES) + rasty->SetLines(true); + else + rasty->SetLines(false); + } + + rasty->SetSpecularity( + mMaterial->speccolor[0]*mMaterial->spec_f, + mMaterial->speccolor[1]*mMaterial->spec_f, + mMaterial->speccolor[2]*mMaterial->spec_f, + mMaterial->spec_f + ); + + rasty->SetShinyness( mMaterial->hard ); + + rasty->SetDiffuse( + mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, + mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit, + mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit, + 1.0f); + + rasty->SetEmissive( + mMaterial->matcolor[0]*mMaterial->emit, + mMaterial->matcolor[1]*mMaterial->emit, + mMaterial->matcolor[2]*mMaterial->emit, + 1.0 + ); + + // Lagan's patch... + // added material factor + rasty->SetAmbient(mMaterial->amb); + + if (mMaterial->material) + rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0); +} + +bool +KX_BlenderMaterial::Activate( + RAS_IRasterizer* rasty, + TCachingInfo& cachingInfo + )const +{ + bool dopass = false; + #ifdef GL_ARB_shader_objects + if( RAS_EXT_support._ARB_shader_objects && + ( mShader && mShader->Ok() ) ) { + + if( (mPass++) < mShader->getNumPass() ) { + ActivatShaders(rasty, cachingInfo); + dopass = true; + return dopass; + } + else { + glUseProgramObjectARB( 0 ); + mPass = 0; + dopass = false; + return dopass; + } + } + else { + #endif//GL_ARB_shader_objects + switch (mPass++) + { + case 0: + ActivateMat(rasty, cachingInfo); + dopass = true; + break; + default: + mPass = 0; + dopass = false; + break; + } + #ifdef GL_ARB_shader_objects + } + #endif//GL_ARB_shader_objects + return dopass; +} + +void KX_BlenderMaterial::setTextureEnvironment( int textureIndex ) +{ +#ifndef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + return; +#else + if(textureIndex == -1 || !RAS_EXT_support._ARB_texture_env_combine){ + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + return; + } + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); + + GLfloat blend_operand = GL_SRC_COLOR; + GLfloat blend_operand_prev = GL_SRC_COLOR; + + // all sources here are RGB by default + GLenum combiner = GL_COMBINE_RGB_ARB; + GLenum source0 = GL_SOURCE0_RGB_ARB; + GLenum source1 = GL_SOURCE1_RGB_ARB; + GLenum source2 = GL_SOURCE2_RGB_ARB; + GLenum op0 = GL_OPERAND0_RGB_ARB; + GLenum op1 = GL_OPERAND1_RGB_ARB; + GLenum op2 = GL_OPERAND2_RGB_ARB; + + // switch to alpha combiners + if( (mMaterial->flag[textureIndex] &TEXALPHA) ) { + combiner = GL_COMBINE_ALPHA_ARB; + source0 = GL_SOURCE0_ALPHA_ARB; + source1 = GL_SOURCE1_ALPHA_ARB; + source2 = GL_SOURCE2_ALPHA_ARB; + op0 = GL_OPERAND0_ALPHA_ARB; + op1 = GL_OPERAND1_ALPHA_ARB; + op2 = GL_OPERAND2_ALPHA_ARB; + blend_operand = GL_SRC_ALPHA; + blend_operand_prev = GL_SRC_ALPHA; + + // invert + if(mMaterial->flag[textureIndex] &TEXNEG) { + blend_operand_prev = GL_ONE_MINUS_SRC_ALPHA; + blend_operand = GL_ONE_MINUS_SRC_ALPHA; + } + } + else { + if(mMaterial->flag[textureIndex] &TEXNEG) { + blend_operand_prev = GL_ONE_MINUS_SRC_COLOR; + blend_operand = GL_ONE_MINUS_SRC_COLOR; + } + } + // on Texture0 GL_PREVIOUS_ARB is the primary color + // on Texture1 GL_PREVIOUS_ARB is Texture0 env + switch( mMaterial->blend_mode[textureIndex] ) { + case BLEND_MIX: + { + // ------------------------------ + GLfloat base_col[4]; + base_col[0] = base_col[1] = base_col[2] = 0.f; + base_col[3] = 1.f-mMaterial->color_blend[textureIndex]; + glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,base_col ); + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_INTERPOLATE_ARB); + glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB); + glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); + glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); + glTexEnvf( GL_TEXTURE_ENV, source2, GL_CONSTANT_ARB ); + glTexEnvf( GL_TEXTURE_ENV, op2, GL_SRC_ALPHA); + }break; + case BLEND_MUL: + { + // ------------------------------ + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_MODULATE); + glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB); + glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev); + glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); + }break; + case BLEND_ADD: + { + // ------------------------------ + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_ADD_SIGNED_ARB); + glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB ); + glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); + glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand ); + }break; + case BLEND_SUB: + { + // ------------------------------ + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_SUBTRACT_ARB); + glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB ); + glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); + glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); + }break; + case BLEND_SCR: + { + // ------------------------------ + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_ADD); + glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB ); + glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); + glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); + } break; + } +#endif //!GL_ARB_texture_env_combine +} + +bool KX_BlenderMaterial::setBlending( int ind, bool enable) +{ + if(!enable) { + if(mMaterial->flag[ind] &CALCALPHA ) return true; + else if(mMaterial->flag[ind] &USEALPHA ) return true; + return false; + } + else { + // additive + if(mMaterial->flag[ind] &CALCALPHA ) { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + return true; + } + + // use alpha channel + else if(mMaterial->flag[ind] &USEALPHA ) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + return true; + } + } + return false; +} + +bool KX_BlenderMaterial::setDefaultBlending() +{ + if( mMaterial->transp &TF_ADD) { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + return true; + } + + if( mMaterial->transp & TF_ALPHA ) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + return true; + } + + glDisable(GL_BLEND); + return false; +} + +void KX_BlenderMaterial::setEnvMap(bool val, bool cube) +{ + #ifdef GL_ARB_texture_cube_map + if( cube && RAS_EXT_support._ARB_texture_cube_map ) + { + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB ); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + } + else { + #endif//GL_ARB_texture_cube_map + if( val ) { + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + } + else { + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + } + #ifdef GL_ARB_texture_cube_map + } + #endif//GL_ARB_texture_cube_map +} + + +void KX_BlenderMaterial::setTexMatrixData(int i) +{ + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + glScalef( + mMaterial->mapping[i].scale[0], + mMaterial->mapping[i].scale[1], + mMaterial->mapping[i].scale[2] + ); + glTranslatef( + mMaterial->mapping[i].offsets[0], + mMaterial->mapping[i].offsets[1], + mMaterial->mapping[i].offsets[2] + ); + + glMatrixMode(GL_MODELVIEW); + +} + +static void GetProjPlane(BL_Material *mat, int index,int num, float*param) +{ + param[0]=param[1]=param[2]=param[3]=0.f; + if( mat->mapping[index].projplane[num] == PROJX ) + param[0] = 1.f; + else if( mat->mapping[index].projplane[num] == PROJY ) + param[1] = 1.f; + else if( mat->mapping[index].projplane[num] == PROJZ) + param[2] = 1.f; +} + + +void KX_BlenderMaterial::setObjectMatrixData(int i) +{ + // will work without cubemaps + // but a cubemap will look the best + KX_GameObject *obj = + (KX_GameObject*) + mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame); + + if(!obj) + return; + + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); + + GLenum plane = GL_EYE_PLANE; + + // figure plane gen + float proj[4]= {0.f,0.f,0.f,0.f}; + GetProjPlane(mMaterial, i, 0, proj); + glTexGenfv(GL_S, plane, proj); + + GetProjPlane(mMaterial, i, 1, proj); + glTexGenfv(GL_T, plane, proj); + + GetProjPlane(mMaterial, i, 2, proj); + glTexGenfv(GL_R, plane, proj); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + + float matr[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, matr); + MT_Matrix4x4 mvmat(matr); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef( + mMaterial->mapping[i].scale[0], + mMaterial->mapping[i].scale[1], + mMaterial->mapping[i].scale[2] + ); + + MT_Point3 pos = obj->NodeGetWorldPosition(); + MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f); + MT_Vector4 t = mvmat*matmul; + + glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) ); + + glMatrixMode(GL_MODELVIEW); + +} + + +// ------------------------------------ +void KX_BlenderMaterial::UpdateIPO( + MT_Vector4 rgba, + MT_Vector3 specrgb, + MT_Scalar hard, + MT_Scalar spec, + MT_Scalar ref, + MT_Scalar emit, + MT_Scalar alpha + ) +{ + // only works one deep now + mMaterial->speccolor[0] = (float)(specrgb)[0]; + mMaterial->speccolor[1] = (float)(specrgb)[1]; + mMaterial->speccolor[2] = (float)(specrgb)[2]; + mMaterial->matcolor[0] = (float)(rgba[0]); + mMaterial->matcolor[1] = (float)(rgba[1]); + mMaterial->matcolor[2] = (float)(rgba[2]); + mMaterial->alpha = (float)(alpha); + mMaterial->hard = (float)(hard); + mMaterial->emit = (float)(emit); + mMaterial->spec_f = (float)(spec); +} + + +PyMethodDef KX_BlenderMaterial::Methods[] = +{ + KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ), + KX_PYMETHODTABLE( KX_BlenderMaterial, useShader ), + KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ), + KX_PYMETHODTABLE( KX_BlenderMaterial, getTexture ), + KX_PYMETHODTABLE( KX_BlenderMaterial, setTexture ), + + {NULL,NULL} //Sentinel +}; + + +PyTypeObject KX_BlenderMaterial::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "KX_BlenderMaterial", + sizeof(KX_BlenderMaterial), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, + __repr, + 0 +}; + + +PyParentObject KX_BlenderMaterial::Parents[] = { + &PyObjectPlus::Type, + &KX_BlenderMaterial::Type, + NULL +}; + + +PyObject* KX_BlenderMaterial::_getattr(const STR_String& attr) +{ + // nodda ? + _getattr_up(PyObjectPlus); +} + +int KX_BlenderMaterial::_setattr(const STR_String& attr, PyObject *pyvalue) +{ + return PyObjectPlus::_setattr(attr, pyvalue); +} + +KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") +{ + #ifdef GL_ARB_shader_objects + if(!RAS_EXT_support._ARB_shader_objects) { + PyErr_Format(PyExc_SystemError, "GLSL not supported"); + return NULL; + } + else { + Py_INCREF(mShader); + return mShader; + } + #else + Py_Return; + #endif//GL_ARB_shader_objects +} + +KX_PYMETHODDEF_DOC( KX_BlenderMaterial, useShader, "useShader(1:0)" ) +{ + #ifdef GL_ARB_shader_objects + if(!RAS_EXT_support._ARB_shader_objects) { + PyErr_Format(PyExc_SystemError, "GLSL not supported"); + return NULL; + } + int use =0; + if(PyArg_ParseTuple(args, "i", &use)) { + mUseShader = (use!= 0); + Py_Return; + } + return NULL; + #else + Py_Return; + #endif//GL_ARB_shader_objects +} + +KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") +{ + return PyInt_FromLong( mMaterial->material_index ); +} + +KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" ) +{ + return NULL; +} + +KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)") +{ + return NULL; +} + diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h new file mode 100644 index 00000000000..012bbef2795 --- /dev/null +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -0,0 +1,108 @@ +#ifndef __KX_BLENDER_MATERIAL_H__ +#define __KX_BLENDER_MATERIAL_H__ + +#include <vector> + + +#include "RAS_IPolygonMaterial.h" +#include "BL_Material.h" +#include "BL_Texture.h" +#include "BL_Shader.h" + +#include "PyObjectPlus.h" + +#include "MT_Vector3.h" +#include "MT_Vector4.h" + +struct TFace; +class KX_Scene; + +class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial +{ + Py_Header; +public: + // -------------------------------- + KX_BlenderMaterial( + class KX_Scene* scene, // light/obj list + BL_Material* mat, + bool skin, + int lightlayer, + void* clientobject, + PyTypeObject* T=&Type + ); + + virtual ~KX_BlenderMaterial(); + + // -------------------------------- + virtual TCachingInfo GetCachingInfo(void) const + { + // -- + return (void*) this; + } + + // -------------------------------- + virtual bool Activate( + RAS_IRasterizer* rasty, + TCachingInfo& cachingInfo) const; + + void ActivateMat( + RAS_IRasterizer* rasty, + TCachingInfo& cachingInfo)const; + + void ActivatShaders( + RAS_IRasterizer* rasty, + TCachingInfo& cachingInfo)const; + // -------------------------------- + + TFace* GetTFace(void) const; + + // for ipos + void UpdateIPO( + MT_Vector4 rgba, MT_Vector3 specrgb, + MT_Scalar hard, MT_Scalar spec, + MT_Scalar ref, MT_Scalar emit, MT_Scalar alpha + ); + + // -------------------------------- + virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + + KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader ); + KX_PYMETHOD_DOC( KX_BlenderMaterial, useShader ); + KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex ); + KX_PYMETHOD_DOC( KX_BlenderMaterial, getTexture ); + KX_PYMETHOD_DOC( KX_BlenderMaterial, setTexture ); + + // -------------------------------- + // pre calculate to avoid pops/lag at startup + virtual void OnConstruction( ); + +private: + BL_Material* mMaterial; + BL_Shader* mShader; + bool mUseShader; + KX_Scene* mScene; + BL_Texture mTextures[MAXTEX]; // texture array + + // message centers + void setTexData( bool enable ); + void setShaderData( bool enable ); + + void setTextureEnvironment( int textureIndex ); + void setEnvMap( bool val, bool cube=false); + void setTexMatrixData(int i); + bool setDefaultBlending(); + bool setBlending( int ind, bool enable=false ); + void setObjectMatrixData(int i); + + // cleanup stuff + void DisableTexData(); + void OnExit(); + + //void DisableNonEnabled(); + // -- + mutable int mPass; +}; + + +#endif diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 009ea4ac617..674528f719c 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -338,6 +338,44 @@ bool KX_Camera::GetFrustumCulling() const { return m_frustum_culling; } + +void KX_Camera::EnableViewport(bool viewport) +{ + m_camdata.m_viewport = viewport; +} + +void KX_Camera::SetViewport(int left, int bottom, int right, int top) +{ + m_camdata.m_viewportleft = left; + m_camdata.m_viewportbottom = bottom; + m_camdata.m_viewportright = right; + m_camdata.m_viewporttop = top; +} + +bool KX_Camera::GetViewport() const +{ + return m_camdata.m_viewport; +} + +int KX_Camera::GetViewportLeft() const +{ + return m_camdata.m_viewportleft; +} + +int KX_Camera::GetViewportBottom() const +{ + return m_camdata.m_viewportbottom; +} + +int KX_Camera::GetViewportRight() const +{ + return m_camdata.m_viewportright; +} + +int KX_Camera::GetViewportTop() const +{ + return m_camdata.m_viewporttop; +} //---------------------------------------------------------------------------- //Python @@ -351,6 +389,8 @@ PyMethodDef KX_Camera::Methods[] = { KX_PYMETHODTABLE(KX_Camera, getWorldToCamera), KX_PYMETHODTABLE(KX_Camera, getProjectionMatrix), KX_PYMETHODTABLE(KX_Camera, setProjectionMatrix), + KX_PYMETHODTABLE(KX_Camera, enableViewport), + KX_PYMETHODTABLE(KX_Camera, setViewport), {NULL,NULL} //Sentinel }; @@ -691,3 +731,31 @@ KX_PYMETHODDEF_DOC(KX_Camera, setProjectionMatrix, PyErr_SetString(PyExc_TypeError, "setProjectionMatrix: Expected 4x4 list as matrix argument."); return NULL; } + +KX_PYMETHODDEF_DOC(KX_Camera, enableViewport, +"enableViewport(viewport)\n" +"Sets this camera's viewport status\n" +) +{ + int viewport; + if (PyArg_ParseTuple(args,"i",&viewport)) + { + if(viewport) + EnableViewport(true); + else + EnableViewport(false); + } + Py_Return; +} + +KX_PYMETHODDEF_DOC(KX_Camera, setViewport, +"setViewport(left, bottom, right, top)\n" +"Sets this camera's viewport\n") +{ + int left, bottom, right, top; + if (PyArg_ParseTuple(args,"iiii",&left, &bottom, &right, &top)) + { + SetViewport(left, bottom, right, top); + } + Py_Return; +} diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 52ae64efbfb..ed926f12123 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -203,6 +203,42 @@ public: * Gets this camera's culling status. */ bool GetFrustumCulling() const; + + /** + * Sets this camera's viewport status. + */ + void EnableViewport(bool viewport); + + /** + * Sets this camera's viewport. + */ + void SetViewport(int left, int bottom, int right, int top); + + /** + * Gets this camera's viewport status. + */ + bool GetViewport() const; + + /** + * Gets this camera's viewport left. + */ + int GetViewportLeft() const; + + /** + * Gets this camera's viewport bottom. + */ + int GetViewportBottom() const; + + /** + * Gets this camera's viewport right. + */ + int GetViewportRight() const; + + /** + * Gets this camera's viewport top. + */ + int GetViewportTop() const; + KX_PYMETHOD_DOC(KX_Camera, sphereInsideFrustum); KX_PYMETHOD_DOC(KX_Camera, boxInsideFrustum); @@ -213,6 +249,9 @@ public: KX_PYMETHOD_DOC(KX_Camera, getProjectionMatrix); KX_PYMETHOD_DOC(KX_Camera, setProjectionMatrix); + KX_PYMETHOD_DOC(KX_Camera, enableViewport); + KX_PYMETHOD_DOC(KX_Camera, setViewport); + virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ virtual int _setattr(const STR_String& attr, PyObject *pyvalue); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 93917151932..42e5d550e57 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -50,6 +50,7 @@ typedef unsigned long uint_ptr; #define KX_INERTIA_INFINITE 10000 #include "RAS_IPolygonMaterial.h" +#include "KX_BlenderMaterial.h" #include "KX_GameObject.h" #include "RAS_MeshObject.h" #include "KX_MeshProxy.h" @@ -367,6 +368,34 @@ void KX_GameObject::UpdateIPO(float curframetime, UpdateTransform(); } +// IPO update +void +KX_GameObject::UpdateMaterialData( + MT_Vector4 rgba, + MT_Vector3 specrgb, + MT_Scalar hard, + MT_Scalar spec, + MT_Scalar ref, + MT_Scalar emit, + MT_Scalar alpha + + ) +{ + int mesh = 0; + if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { + RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial(); + for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit) + { + RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial(); + if(poly->GetFlag() & RAS_BLENDERMAT ) + { + SetObjectColor(rgba); + KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly); + m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); + } + } + } +} bool KX_GameObject::GetVisible( void @@ -605,7 +634,6 @@ PyMethodDef KX_GameObject::Methods[] = { {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS}, {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS}, KX_PYMETHODTABLE(KX_GameObject, getDistanceTo), - {NULL,NULL} //Sentinel }; @@ -937,7 +965,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* kwds) { int mesh = 0; - + if (PyArg_ParseTuple(args, "|i", &mesh)) { if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) @@ -950,7 +978,6 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, } - PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args, PyObject* kwds) diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 34628897af7..98544cf14d0 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -420,6 +420,19 @@ public: bool ipo_as_force, bool force_ipo_local ); + /** + * Updates Material Ipo data + */ + void + UpdateMaterialData( + MT_Vector4 rgba, + MT_Vector3 specrgb, + MT_Scalar hard, + MT_Scalar spec, + MT_Scalar ref, + MT_Scalar emit, + MT_Scalar alpha + ); /** * @section Mesh accessor functions. diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h index 5cb445a6dc4..52a65791885 100644 --- a/source/gameengine/Ketsji/KX_ISceneConverter.h +++ b/source/gameengine/Ketsji/KX_ISceneConverter.h @@ -67,6 +67,9 @@ public: virtual void WritePhysicsObjectToAnimationIpo(int frameNumber) = 0; virtual void TestHandlesPhysicsObjectToAnimationIpo() = 0; + // use blender materials + virtual void SetMaterials(bool val) =0; + virtual bool GetMaterials()=0; }; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index bd7ce6cc36d..022c5d0c3ee 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -555,20 +555,47 @@ void KX_KetsjiEngine::Render() // for each scene, call the proceed functions { KX_Scene* scene = *sceneit; - + KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer SetWorldSettings(scene->GetWorldInfo()); - - if (scene->IsClearingZBuffer()) - m_rasterizer->ClearDepthBuffer(); - - m_rendertools->SetAuxilaryClientInfo(scene); - - //Initialize scene viewport. - SetupRenderFrame(scene); - // do the rendering - RenderFrame(scene); + // Avoid drawing the scene with the active camera twice when it's viewport is enabled + if(!cam->GetViewport()) + { + if (scene->IsClearingZBuffer()) + m_rasterizer->ClearDepthBuffer(); + + m_rendertools->SetAuxilaryClientInfo(scene); + + //Initialize scene viewport. + SetupRenderFrame(scene, cam); + + // do the rendering + RenderFrame(scene, cam); + } + + set<class KX_Camera*>* cameras = scene->GetCameras(); + + // Draw the scene once for each camera with an enabled viewport + set<KX_Camera*>::iterator it = cameras->begin(); + while(it != cameras->end()) + { + if((*it)->GetViewport()) + { + if (scene->IsClearingZBuffer()) + m_rasterizer->ClearDepthBuffer(); + + m_rendertools->SetAuxilaryClientInfo(scene); + + //Initialize scene viewport. + SetupRenderFrame(scene, (*it)); + + // do the rendering + RenderFrame(scene, (*it)); + } + + it++; + } } // only one place that checks for stereo @@ -584,6 +611,7 @@ void KX_KetsjiEngine::Render() // for each scene, call the proceed functions { KX_Scene* scene = *sceneit; + KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer SetWorldSettings(scene->GetWorldInfo()); @@ -595,10 +623,12 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); //Initialize scene viewport. - SetupRenderFrame(scene); + //SetupRenderFrame(scene); + SetupRenderFrame(scene, cam); // do the rendering - RenderFrame(scene); + //RenderFrame(scene); + RenderFrame(scene, cam); } } // if(m_rasterizer->Stereo()) @@ -686,6 +716,13 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) { if (wi->hasWorld()) { + // ... + m_rasterizer->SetAmbientColor( + wi->getAmbientColorRed(), + wi->getAmbientColorGreen(), + wi->getAmbientColorBlue() + ); + if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED) { if (wi->hasMist()) @@ -749,7 +786,7 @@ void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat) } -void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene) +void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) { // In this function we make sure the rasterizer settings are upto // date. We compute the viewport so that logic @@ -760,11 +797,13 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene) RAS_Rect viewport; - if ( - m_overrideCam || - (scene->GetName() != m_overrideSceneName) || - m_overrideCamUseOrtho - ) { + if (cam->GetViewport()) { + viewport.SetLeft(cam->GetViewportLeft()); + viewport.SetBottom(cam->GetViewportBottom()); + viewport.SetRight(cam->GetViewportRight()); + viewport.SetTop(cam->GetViewportTop()); + } + else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) || m_overrideCamUseOrtho ) { RAS_FramingManager::ComputeViewport( scene->GetFramingType(), m_canvas->GetDisplayArea(), @@ -792,21 +831,23 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene) // update graphics -void KX_KetsjiEngine::RenderFrame(KX_Scene* scene) +void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { float left, right, bottom, top, nearfrust, farfrust; const float ortho = 100.0; - KX_Camera* cam = scene->GetActiveCamera(); +// KX_Camera* cam = scene->GetActiveCamera(); if (!cam) return; - + + // see KX_BlenderMaterial::Activate + //m_rasterizer->SetAmbient(); m_rasterizer->DisplayFog(); if (m_overrideCam && (scene->GetName() == m_overrideSceneName) && m_overrideCamUseOrtho) { MT_CmMatrix4x4 projmat = m_overrideCamProjMat; m_rasterizer->SetProjectionMatrix(projmat); - } else if (cam->hasValidProjectionMatrix()) + } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() ) { m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix()); } else @@ -865,7 +906,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene) // redrawn. There is a cache between the actual rescheduling // and this call though. Visibility is imparted when this call // runs through the individual objects. - scene->CalculateVisibleMeshes(m_rasterizer); + scene->CalculateVisibleMeshes(m_rasterizer,cam); scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); } @@ -958,6 +999,10 @@ void KX_KetsjiEngine::RenderDebugProperties() if (tottime < 1e-6f) { tottime = 1e-6f; } + + // Set viewport to entire canvas + RAS_Rect viewport; + m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight())); /* Framerate display */ if (m_show_framerate) { diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index f7c919e19d5..bea558e4427 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -173,8 +173,8 @@ private: /** Blue component of framing bar color. */ float m_overrideFrameColorB; - void SetupRenderFrame(KX_Scene *scene); - void RenderFrame(KX_Scene* scene); + void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); + void RenderFrame(KX_Scene* scene, KX_Camera* cam); void RenderDebugProperties(); void SetBackGround(KX_WorldInfo* worldinfo); void SetWorldSettings(KX_WorldInfo* worldinfo); diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp new file mode 100644 index 00000000000..d7a1406b507 --- /dev/null +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp @@ -0,0 +1,97 @@ + +#include "KX_MaterialIpoController.h" +#include "KX_ScalarInterpolator.h" +#include "KX_GameObject.h" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +bool KX_MaterialIpoController::Update(double currentTime) +{ + if (m_modified) + { + m_rgba[0]=0; + m_rgba[1]=0; + m_rgba[2]=0; + m_rgba[3]=0; + + m_specrgb[0] =0; + m_specrgb[1] =0; + m_specrgb[2] =0; + m_hard =0; + m_spec=0; + m_ref=0; + m_emit=0; + m_alpha = 0; + + + T_InterpolatorList::iterator i; + for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { + (*i)->Execute(m_ipotime); + } + + + SG_Spatial* ob = (SG_Spatial*)m_pObject; + KX_GameObject* kxgameobj= (KX_GameObject*) ob->GetSGClientObject(); + + //kxgameobj->SetObjectColor(m_rgba); + kxgameobj->UpdateMaterialData( + m_rgba, + m_specrgb, + m_hard, + m_spec, + m_ref, + m_emit, + m_alpha + ); + + m_modified=false; + } + return false; +} + + +void KX_MaterialIpoController::AddInterpolator(KX_IInterpolator* interp) +{ + this->m_interpolators.push_back(interp); +} + +SG_Controller* KX_MaterialIpoController::GetReplica(class SG_Node* destnode) +{ + KX_MaterialIpoController* iporeplica = new KX_MaterialIpoController(*this); + // clear object that ipo acts on + iporeplica->ClearObject(); + + // dirty hack, ask Gino for a better solution in the ipo implementation + // hacken en zagen, in what we call datahiding, not written for replication :( + + T_InterpolatorList oldlist = m_interpolators; + iporeplica->m_interpolators.clear(); + + T_InterpolatorList::iterator i; + for (i = oldlist.begin(); !(i == oldlist.end()); ++i) { + KX_ScalarInterpolator* copyipo = new KX_ScalarInterpolator(*((KX_ScalarInterpolator*)*i)); + iporeplica->AddInterpolator(copyipo); + + MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget(); + int orgbase = (int)this; + int orgloc = (int)scaal; + int offset = orgloc-orgbase; + int newaddrbase = (int)iporeplica + offset; + MT_Scalar* blaptr = (MT_Scalar*) newaddrbase; + copyipo->SetNewTarget((MT_Scalar*)blaptr); + } + + return iporeplica; +} + +KX_MaterialIpoController::~KX_MaterialIpoController() +{ + + T_InterpolatorList::iterator i; + for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { + delete (*i); + } + +}
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.h b/source/gameengine/Ketsji/KX_MaterialIpoController.h new file mode 100644 index 00000000000..e76ddeefb04 --- /dev/null +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.h @@ -0,0 +1,54 @@ +#ifndef __KX_MATERIALIPOCONTROLLER_H__ +#define __KX_MATERIALIPOCONTROLLER_H__ + + + +#include "SG_Controller.h" +#include "SG_Spatial.h" +#include "KX_IInterpolator.h" + +class KX_MaterialIpoController : public SG_Controller +{ +public: + MT_Vector4 m_rgba; + MT_Vector3 m_specrgb; + MT_Scalar m_hard; + MT_Scalar m_spec; + MT_Scalar m_ref; + MT_Scalar m_emit; + MT_Scalar m_alpha; + +private: + T_InterpolatorList m_interpolators; + bool m_modified; + + double m_ipotime; +public: + KX_MaterialIpoController() : + m_modified(true), + m_ipotime(0.0) + {} + virtual ~KX_MaterialIpoController(); + virtual SG_Controller* GetReplica(class SG_Node* destnode); + virtual bool Update(double time); + virtual void SetSimulatedTime(double time) { + m_ipotime = time; + m_modified = true; + } + + void + SetOption( + int option, + int value + ){ + // intentionally empty + }; + + + void AddInterpolator(KX_IInterpolator* interp); +}; + + + + +#endif//__KX_MATERIALIPOCONTROLLER_H__ diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index b4b3cea8c8a..f6505c2965f 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -40,6 +40,7 @@ #include "KX_VertexProxy.h" #include "KX_PolygonMaterial.h" +#include "KX_BlenderMaterial.h" #include "KX_PyMath.h" #include "KX_ConvertPhysicsObject.h" @@ -67,6 +68,7 @@ PyParentObject KX_MeshProxy::Parents[] = { &KX_MeshProxy::Type, &SCA_IObject::Type, &CValue::Type, + &PyObjectPlus::Type, NULL }; @@ -87,27 +89,34 @@ KX_MeshProxy::_getattr(const STR_String& attr) { if (attr == "materials") { - PyObject *materials = PyList_New(0); /* new ref */ + PyObject *materials = PyList_New(0); RAS_MaterialBucket::Set::iterator mit = m_meshobj->GetFirstMaterial(); for(; mit != m_meshobj->GetLastMaterial(); ++mit) - PyList_Append(materials, static_cast<KX_PolygonMaterial*>((*mit)->GetPolyMaterial())); + { + RAS_IPolyMaterial *polymat = (*mit)->GetPolyMaterial(); + if(polymat->GetFlag() & RAS_BLENDERMAT) + { + KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat); + PyList_Append(materials, mat); + }else + { + PyList_Append(materials, static_cast<KX_PolygonMaterial*>(polymat)); + } + } return materials; } - _getattr_up(SCA_IObject); } KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh) - : m_meshobj(mesh) + : m_meshobj(mesh) { - } KX_MeshProxy::~KX_MeshProxy() { - } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 14071ae6fc5..46c60cab1f7 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -111,7 +111,7 @@ public: KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial); KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram); - + virtual PyObject* _getattr(const STR_String& attr); virtual int _setattr(const STR_String& attr, PyObject *pyvalue); }; diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 63896b063ee..ca2939f344e 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -36,6 +36,17 @@ #endif #ifdef WIN32 +#include <windows.h> +#endif // WIN32 +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif + +#ifdef WIN32 #pragma warning (disable : 4786) #endif //WIN32 @@ -60,6 +71,8 @@ #include "KX_Scene.h" #include "SND_DeviceManager.h" +#include "RAS_GLExtensionManager.h" + #include "KX_PyMath.h" #include "PHY_IPhysicsEnvironment.h" @@ -258,7 +271,51 @@ static PyObject* gPyGetCurrentScene(PyObject* self, Py_INCREF(gp_KetsjiScene); return (PyObject*) gp_KetsjiScene; } - + +static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) +{ +#define pprint(x) std::cout << x << std::endl; + bgl::BL_EXTInfo ext = bgl::RAS_EXT_support; + bool count=0; + pprint("Supported Extensions..."); + #ifdef GL_ARB_shader_objects + pprint(" GL_ARB_shader_objects supported? "<< (ext._ARB_shader_objects? "yes.":"no.")); + count = 1; + #endif + #ifdef GL_ARB_vertex_shader + pprint(" GL_ARB_vertex_shader supported? "<< (ext._ARB_vertex_shader? "yes.":"no.")); + count = 1; + #endif + #ifdef GL_ARB_fragment_shader + pprint(" GL_ARB_fragment_shader supported? "<< (ext._ARB_fragment_shader? "yes.":"no.")); + count = 1; + #endif + #ifdef GL_ARB_texture_cube_map + pprint(" GL_ARB_texture_cube_map supported? "<< (ext._ARB_texture_cube_map? "yes.":"no.")); + count = 1; + #endif + #ifdef GL_EXT_texture3D + pprint(" GL_EXT_texture3D supported? "<< (ext._EXT_texture3D? "yes.":"no.")); + count = 1; + #endif + #ifdef GL_EXT_blend_color + pprint(" GL_EXT_blend_color supported? "<< (ext._EXT_blend_color? "yes.":"no.")); + count = 1; + #endif + #ifdef GL_ARB_multitexture + pprint(" GL_ARB_multitexture supported? "<< (ext._ARB_multitexture? "yes.":"no.")); + count = 1; + #endif + #ifdef GL_ARB_texture_env_combine + pprint(" GL_ARB_texture_env_combine supported? "<< (ext._ARB_texture_env_combine? "yes.":"no.")); + count = 1; + #endif + if(!count) + pprint("No extenstions are used in this build"); + + Py_INCREF(Py_None); + return Py_None; +} static struct PyMethodDef game_methods[] = { @@ -278,6 +335,7 @@ static struct PyMethodDef game_methods[] = { {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, "Sets the logic tic rate"}, {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_VARARGS, "Gets the physics tic rate"}, {"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, "Sets the physics tic rate"}, + {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, "Prints GL Extension Info"}, {NULL, (PyCFunction) NULL, 0, NULL } }; @@ -487,6 +545,26 @@ static PyObject* gPySetMistEnd(PyObject*, } +static PyObject* gPySetAmbientColor(PyObject*, + PyObject* args, + PyObject*) +{ + + MT_Vector3 vec = MT_Vector3(0., 0., 0.); + if (PyVecArgTo(args, vec)) + { + if (gp_Rasterizer) + { + gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]); + } + Py_Return; + } + + return NULL; +} + + + static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args, @@ -526,7 +604,8 @@ static struct PyMethodDef rasterizer_methods[] = { {"setMousePosition",(PyCFunction) gPySetMousePosition, METH_VARARGS, gPySetMousePosition__doc__.Ptr()}, {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_VARARGS,"set Background Color (rgb)"}, - {"setMistColor",(PyCFunction)gPySetMistColor,METH_VARARGS,"set Mist Color (rgb)"}, + {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_VARARGS,"set Ambient Color (rgb)"}, + {"setMistColor",(PyCFunction)gPySetMistColor,METH_VARARGS,"set Mist Color (rgb)"}, {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index f13df6bfa44..1f37f07902e 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -54,6 +54,8 @@ #include "SCA_JoystickManager.h" #include "RAS_MeshObject.h" +#include "BL_SkinMeshObject.h" + #include "RAS_IRasterizer.h" #include "RAS_BucketManager.h" @@ -259,6 +261,13 @@ SCA_TimeEventManager* KX_Scene::GetTimeEventManager() + +set<class KX_Camera*>* KX_Scene::GetCameras() +{ + return &m_cameras; +} + + void KX_Scene::SetFramingType(RAS_FrameSettings & frame_settings) { @@ -714,6 +723,7 @@ void KX_Scene::NewRemoveObject(class CValue* gameobj) if (newobj == m_active_camera) { + m_active_camera->Release(); m_active_camera = NULL; } } @@ -731,21 +741,30 @@ void KX_Scene::ReplaceMesh(class CValue* gameobj,void* meshobj) if (newobj->m_isDeformable && mesh->m_class == 1) { Object* blendobj = (struct Object*)m_logicmgr->FindBlendObjByGameObj(newobj); Object* oldblendobj = (struct Object*)m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName()); - if (blendobj->parent && blendobj->parent->type == OB_ARMATURE && blendobj->partype==PARSKEL && ((Mesh*)blendobj->data)->dvert) { - BL_SkinDeformer* skindeformer = new BL_SkinDeformer(oldblendobj, blendobj, (BL_SkinMeshObject*)mesh,blendobj->parent); - skindeformer->SetArmature((BL_ArmatureObject*) newobj->GetParent()); - + + if (blendobj->parent && blendobj->parent->type == OB_ARMATURE && + blendobj->partype==PARSKEL && + ((Mesh*)blendobj->data)->dvert) + { // FIXME: should the old m_pDeformer be deleted? - // delete ((BL_DeformableGameObject*)newobj)->m_pDeformer + // it shouldn't be a problem to delete it now. + // if we are constructing this on the fly like here, + // make sure to release newobj->GetParent(), and things will run shipshape + delete static_cast<BL_DeformableGameObject*>( newobj )->m_pDeformer; - ((BL_DeformableGameObject*)newobj)->m_pDeformer = skindeformer; + BL_SkinDeformer* skindeformer = new BL_SkinDeformer( + oldblendobj, blendobj, + static_cast<BL_SkinMeshObject*>(mesh), + true, // release ref count to BL_ArmatureObject, leak otherwise + static_cast<BL_ArmatureObject*>(newobj->GetParent()) + ); + static_cast<BL_DeformableGameObject*>( newobj )->m_pDeformer = skindeformer; } else if (((Mesh*)blendobj->data)->dvert) { - BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(oldblendobj, (BL_SkinMeshObject*)mesh,oldblendobj->parent); - + BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(oldblendobj, (BL_SkinMeshObject*)mesh ); + // FIXME: should the old m_pDeformer be deleted? // delete ((BL_DeformableGameObject*)newobj)->m_pDeformer - ((BL_DeformableGameObject*)newobj)->m_pDeformer = meshdeformer; } } @@ -832,48 +851,48 @@ void KX_Scene::UpdateMeshTransformations() } } -void KX_Scene::MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty) +void KX_Scene::MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera* cam) { int intersect = KX_Camera::INTERSECT; KX_GameObject *gameobj = node->Client()?(KX_GameObject*) node->Client()->GetSGClientObject():NULL; bool dotest = (gameobj && gameobj->GetVisible()) || node->Left() || node->Right(); /* If the camera is inside the box, assume intersect. */ - if (dotest && !node->inside(GetActiveCamera()->NodeGetWorldPosition())) + if (dotest && !node->inside( cam->NodeGetWorldPosition())) { MT_Scalar radius = node->Radius(); MT_Point3 centre = node->Centre(); - intersect = GetActiveCamera()->SphereInsideFrustum(centre, radius); + intersect = cam->SphereInsideFrustum(centre, radius); if (intersect == KX_Camera::INTERSECT) { MT_Point3 box[8]; node->get(box); - intersect = GetActiveCamera()->BoxInsideFrustum(box); + intersect = cam->BoxInsideFrustum(box); } } switch (intersect) { case KX_Camera::OUTSIDE: - MarkSubTreeVisible(node, rasty, false); + MarkSubTreeVisible(node, rasty, false, cam); break; case KX_Camera::INTERSECT: if (gameobj) - MarkVisible(rasty, gameobj); + MarkVisible(rasty, gameobj,cam); if (node->Left()) - MarkVisible(node->Left(), rasty); + MarkVisible(node->Left(), rasty,cam); if (node->Right()) - MarkVisible(node->Right(), rasty); + MarkVisible(node->Right(), rasty,cam); break; case KX_Camera::INSIDE: - MarkSubTreeVisible(node, rasty, true); + MarkSubTreeVisible(node, rasty, true,cam); break; } } -void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible) +void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible,KX_Camera* cam) { if (node->Client()) { @@ -883,7 +902,7 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi if (visible) { int nummeshes = gameobj->GetMeshCount(); - MT_Transform t( GetActiveCamera()->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); + MT_Transform t( cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); for (int m=0;m<nummeshes;m++) @@ -896,18 +915,18 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi } } if (node->Left()) - MarkSubTreeVisible(node->Left(), rasty, visible); + MarkSubTreeVisible(node->Left(), rasty, visible,cam); if (node->Right()) - MarkSubTreeVisible(node->Right(), rasty, visible); + MarkSubTreeVisible(node->Right(), rasty, visible,cam); } -void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj) +void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Camera* cam) { // User (Python/Actuator) has forced object invisible... if (!gameobj->GetVisible()) return; // If Frustum culling is off, the object is always visible. - bool vis = !GetActiveCamera()->GetFrustumCulling(); + bool vis = !cam->GetFrustumCulling(); // If the camera is inside this node, then the object is visible. if (!vis) @@ -920,7 +939,7 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj) { MT_Vector3 scale = gameobj->GetSGNode()->GetWorldScaling(); MT_Scalar radius = fabs(scale[scale.closestAxis()] * gameobj->GetSGNode()->Radius()); - switch (GetActiveCamera()->SphereInsideFrustum(gameobj->NodeGetWorldPosition(), radius)) + switch (cam->SphereInsideFrustum(gameobj->NodeGetWorldPosition(), radius)) { case KX_Camera::INSIDE: vis = true; @@ -932,7 +951,7 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj) // Test the object's bound box against the view frustum. MT_Point3 box[8]; gameobj->GetSGNode()->getBBox(box); - vis = GetActiveCamera()->BoxInsideFrustum(box) != KX_Camera::OUTSIDE; + vis = cam->BoxInsideFrustum(box) != KX_Camera::OUTSIDE; break; } } @@ -940,7 +959,7 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj) if (vis) { int nummeshes = gameobj->GetMeshCount(); - MT_Transform t(GetActiveCamera()->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); + MT_Transform t(cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); for (int m=0;m<nummeshes;m++) { @@ -955,20 +974,20 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj) } } -void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty) +void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam) { // FIXME: When tree is operational #if 1 // do this incrementally in the future for (int i = 0; i < m_objectlist->GetCount(); i++) { - MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i))); + MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam); } #else - if (GetActiveCamera()->GetFrustumCulling()) - MarkVisible(m_objecttree, rasty); + if (cam->GetFrustumCulling()) + MarkVisible(m_objecttree, rasty, cam); else - MarkSubTreeVisible(m_objecttree, rasty, true); + MarkSubTreeVisible(m_objecttree, rasty, true, cam); #endif } diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 7203fa87acc..4bcfb3ee194 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -248,9 +248,9 @@ protected: /** * Visibility testing functions. */ - void MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty); - void MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible); - void MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj); + void MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera*cam); + void MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible, KX_Camera*cam); + void MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj, KX_Camera*cam); double m_suspendedtime; double m_suspendeddelta; @@ -322,6 +322,10 @@ public: GetTimeEventManager( ); + set<class KX_Camera*>* + GetCameras( + ); + /** Find a camera in the scene by pointer. */ KX_Camera* @@ -450,7 +454,7 @@ public: void SetNetworkScene(NG_NetworkScene *newScene); void SetWorldInfo(class KX_WorldInfo* wi); KX_WorldInfo* GetWorldInfo(); - void CalculateVisibleMeshes(RAS_IRasterizer* rasty); + void CalculateVisibleMeshes(RAS_IRasterizer* rasty, KX_Camera *cam); void UpdateMeshTransformations(); KX_Camera* GetpCamera(); SND_Scene* GetSoundScene(); diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 7683ce19f19..b06e9ee8529 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -70,6 +70,10 @@ PyMethodDef KX_VertexProxy::Methods[] = { {"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_VARARGS}, {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_VARARGS}, {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_VARARGS}, + +{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_VARARGS}, +{"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, + {"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_VARARGS}, {"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_VARARGS}, {"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_VARARGS}, @@ -216,6 +220,22 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) m_vertex->SetUV(uv); return 0; } + + // uv + MT_Point2 uv2 = m_vertex->getUV2(); + if (attr == "u2") + { + uv[0] = val; + m_vertex->SetUV2(uv); + return 0; + } + + if (attr == "v2") + { + uv[1] = val; + m_vertex->SetUV2(uv); + return 0; + } // col unsigned int icol = *((const unsigned int *)m_vertex->getRGBA()); @@ -373,5 +393,31 @@ PyObject* KX_VertexProxy::PySetUV(PyObject*, return NULL; } +PyObject* KX_VertexProxy::PyGetUV2(PyObject*, + PyObject*, + PyObject*) +{ + return PyObjectFrom(MT_Vector2(m_vertex->getUV2())); +} + +PyObject* KX_VertexProxy::PySetUV2(PyObject*, + PyObject* args, + PyObject*) +{ + MT_Point2 vec; + unsigned int unit=0; + PyObject* list=0; + if(PyArg_ParseTuple(args, "Oi", &list, &unit)) + { + if (PyVecTo(list, vec)) + { + m_vertex->SetFlag((m_vertex->getFlag()|TV_2NDUV)); + m_vertex->SetUnit(unit); + m_vertex->SetUV2(vec); + Py_Return; + } + } + return NULL; +} diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index bf3e1982c8c..49fa8ca88c9 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -63,6 +63,10 @@ public: KX_PYMETHOD(KX_VertexProxy,SetXYZ); KX_PYMETHOD(KX_VertexProxy,GetUV); KX_PYMETHOD(KX_VertexProxy,SetUV); + + KX_PYMETHOD(KX_VertexProxy,GetUV2); + KX_PYMETHOD(KX_VertexProxy,SetUV2); + KX_PYMETHOD(KX_VertexProxy,GetRGBA); KX_PYMETHOD(KX_VertexProxy,SetRGBA); KX_PYMETHOD(KX_VertexProxy,GetNormal); diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 6b8eac9ff35..ecc0c04a17b 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -53,6 +53,10 @@ public: virtual float getMistColorGreen()=0; virtual float getMistColorBlue()=0; + virtual float getAmbientColorRed()=0; + virtual float getAmbientColorGreen()=0; + virtual float getAmbientColorBlue()=0; + virtual void setMistStart(float)=0; virtual void setMistDistance(float)=0; virtual void setMistColorRed(float)=0; diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile index 4f6d19a8df0..6bcbab59da4 100644 --- a/source/gameengine/Ketsji/Makefile +++ b/source/gameengine/Ketsji/Makefile @@ -45,6 +45,7 @@ CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include CPPFLAGS += -I$(NAN_SOLID)/include CPPFLAGS += -I$(NAN_BULLET)/include +CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer CPPFLAGS += -I../Rasterizer -I../GameLogic -I../SceneGraph CPPFLAGS += -I../BlenderRoutines -I../Expressions CPPFLAGS += -I../../kernel/gen_system diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 7051f7e5541..39a74083ff4 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -58,7 +58,9 @@ source_files = ['KX_WorldIpoController.cpp', 'KX_CameraIpoSGController.cpp', 'KX_CameraActuator.cpp', 'KX_Camera.cpp', - 'KX_BulletPhysicsController.cpp' + 'KX_BulletPhysicsController.cpp', + 'KX_BlenderMaterial.cpp', + 'KX_MaterialIpoController.cpp', ] if user_options_dict['USE_PHYSICS'] == 'solid': diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 4ce072dd7cc..091e78c7b28 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -141,10 +141,17 @@ void RAS_BucketManager::Renderbuckets( } for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) + { + if((*bucket)->GetPolyMaterial()->IsZSort()) + rasty->SetAlphaTest(true); + else + rasty->SetAlphaTest(false); + (*bucket)->Render(cameratrans,rasty,rendertools); - + } + rasty->SetAlphaTest(false); + RenderAlphaBuckets(cameratrans, rasty, rendertools); - RAS_MaterialBucket::EndFrame(); } diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h index a4245025f2a..69a43dd64e9 100644 --- a/source/gameengine/Rasterizer/RAS_CameraData.h +++ b/source/gameengine/Rasterizer/RAS_CameraData.h @@ -38,12 +38,23 @@ struct RAS_CameraData float m_clipstart; float m_clipend; bool m_perspective; - - RAS_CameraData(float lens = 35., float clipstart = 0.1, float clipend = 100., bool perspective = true) : + bool m_viewport; + int m_viewportleft; + int m_viewportbottom; + int m_viewportright; + int m_viewporttop; + + RAS_CameraData(float lens = 35., float clipstart = 0.1, float clipend = 100., bool perspective = true, + bool viewport = false, int viewportleft = 0, int viewportbottom = 0, int viewportright = 0, int viewporttop = 0) : m_lens(lens), m_clipstart(clipstart), m_clipend(clipend), - m_perspective(perspective) + m_perspective(perspective), + m_viewport(viewport), + m_viewportleft(viewportleft), + m_viewportbottom(viewportbottom), + m_viewportright(viewportright), + m_viewporttop(viewporttop) { } }; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 330f964de7b..b5882bd48c4 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -57,7 +57,10 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_zsort(zsort), m_lightlayer(lightlayer), m_bIsTriangle(bIsTriangle), - m_polymatid(m_newpolymatid++) + m_polymatid(m_newpolymatid++), + m_flag(0), + m_enabled(0), + m_multimode(0) { m_shininess = 35.0; m_specular = MT_Vector3(0.5,0.5,0.5); @@ -68,18 +71,32 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const { - return ( - this->m_tile == lhs.m_tile && - this->m_tilexrep == lhs.m_tilexrep && - this->m_tileyrep == lhs.m_tileyrep && - this->m_transparant == lhs.m_transparant && - this->m_zsort == lhs.m_zsort && - this->m_drawingmode == lhs.m_drawingmode && - this->m_bIsTriangle == lhs.m_bIsTriangle && - this->m_lightlayer == lhs.m_lightlayer && + if(m_flag &RAS_BLENDERMAT) + { + return ( + this->m_multimode == lhs.m_multimode && + this->m_flag == lhs.m_flag && + this->m_drawingmode == lhs.m_drawingmode && + this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() - ); + ); + } + else + { + return ( + this->m_tile == lhs.m_tile && + this->m_tilexrep == lhs.m_tilexrep && + this->m_tileyrep == lhs.m_tileyrep && + this->m_transparant == lhs.m_transparant && + this->m_zsort == lhs.m_zsort && + this->m_drawingmode == lhs.m_drawingmode && + this->m_bIsTriangle == lhs.m_bIsTriangle && + this->m_lightlayer == lhs.m_lightlayer && + this->m_texturename.hash() == lhs.m_texturename.hash() && + this->m_materialname.hash() == lhs.m_materialname.hash() + ); + } } bool RAS_IPolyMaterial::Less(const RAS_IPolyMaterial& rhs) const @@ -130,4 +147,14 @@ const STR_String& RAS_IPolyMaterial::GetTextureName() const return m_texturename; } +const unsigned int RAS_IPolyMaterial::GetFlag() const +{ + return m_flag; +} +const unsigned int RAS_IPolyMaterial::GetEnabled() const +{ + return m_enabled; +} + + unsigned int RAS_IPolyMaterial::m_newpolymatid = 0; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index b039b51dd8b..3e296c2b88b 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -43,6 +43,20 @@ class RAS_IRasterizer; +enum MaterialProps +{ + RAS_ZSORT =1, + RAS_TRANSPARENT =2, + RAS_TRIANGLE =4, + RAS_MULTITEX =8, + RAS_MULTILIGHT =16, + RAS_BLENDERMAT =32, + RAS_GLSHADER =64, + RAS_AUTOGEN =128, + RAS_NORMAL =256, + RAS_DEFMULTI =512 +}; + /** * Material properties. */ @@ -52,18 +66,21 @@ class RAS_IPolyMaterial protected: STR_HashedString m_texturename; STR_HashedString m_materialname; //also needed for touchsensor - int m_tile; - int m_tilexrep,m_tileyrep; - int m_drawingmode; // tface->mode - bool m_transparant; - bool m_zsort; - int m_lightlayer; - bool m_bIsTriangle; + int m_tile; + int m_tilexrep,m_tileyrep; + int m_drawingmode; // tface->mode + bool m_transparant; + bool m_zsort; + int m_lightlayer; + bool m_bIsTriangle; unsigned int m_polymatid; - static unsigned int m_newpolymatid; - + + // will move... + unsigned int m_flag;//MaterialProps + unsigned int m_enabled;// enabled for this mat + int m_multimode; // sum of values public: MT_Vector3 m_diffuse; @@ -124,6 +141,14 @@ public: int GetDrawingMode() const; const STR_String& GetMaterialName() const; const STR_String& GetTextureName() const; + const unsigned int GetFlag() const; + const unsigned int GetEnabled() const; + + /* + * PreCalculate texture gen + */ + virtual void OnConstruction(){} + }; inline bool operator ==( const RAS_IPolyMaterial & rhs,const RAS_IPolyMaterial & lhs) diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 03c7e1d5116..68a9429d066 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -219,6 +219,25 @@ public: bool useObjectColor, const MT_Vector4& rgbacolor)=0; + virtual void IndexPrimitivesMulti( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + int mode, + class RAS_IPolyMaterial* polymat, + class RAS_IRenderTools* rendertools, + bool useObjectColor, + const MT_Vector4& rgbacolor)=0; + + virtual void IndexPrimitivesMulti_Ex( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + int mode, + class RAS_IPolyMaterial* polymat, + class RAS_IRenderTools* rendertools, + bool useObjectColor, + const MT_Vector4& rgbacolor)=0; + + virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat)=0; /* This one should become our final version, methinks. */ /** @@ -329,6 +348,22 @@ public: float difZ, float diffuse)=0; /** + * Sets the emissive colour component of the lighting equation. + */ + virtual void SetEmissive(float eX, + float eY, + float eZ, + float e + )=0; + + virtual void SetAmbientColor(float red, float green, float blue)=0; + virtual void SetAmbient(float factor)=0; + /** + * Sets alpha testing + */ + virtual void SetAlphaTest(bool enable)=0; + + /** * Sets a polygon offset. z depth will be: z1 = mult*z0 + add */ virtual void SetPolygonOffset(float mult, float add) = 0; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 7f9f5b455ba..b1d32326048 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -177,7 +177,13 @@ bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_I if (!rasty->SetMaterial(*m_material)) return false; - bool dolights = m_material->GetDrawingMode()&16; + bool dolights = false; + const unsigned int flag = m_material->GetFlag(); + + if( flag & RAS_BLENDERMAT) + dolights = flag &RAS_MULTILIGHT; + else + dolights = m_material->GetDrawingMode()&16; if ((rasty->GetDrawingMode() <= RAS_IRasterizer::KX_SOLID) || !dolights) { @@ -229,6 +235,35 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa ms.m_RGBAcolor); } + + // for using glMultiTexCoord + else if(m_material->GetFlag() & RAS_MULTITEX ) + { + rasty->IndexPrimitivesMulti( + ms.m_mesh->GetVertexCache(m_material), + ms.m_mesh->GetIndexCache(m_material), + drawmode, + m_material, + rendertools, + ms.m_bObjectColor, + ms.m_RGBAcolor + ); + } + + // for using glMultiTexCoord on deformer + else if(m_material->GetFlag() & RAS_DEFMULTI ) + { + rasty->IndexPrimitivesMulti( + ms.m_mesh->GetVertexCache(m_material), + ms.m_mesh->GetIndexCache(m_material), + drawmode, + m_material, + rendertools, + ms.m_bObjectColor, + ms.m_RGBAcolor + ); + } + // Use the (slower) IndexPrimitives_Ex which can recalc face normals & such // for deformed objects - eventually should be extended to recalc ALL normals else if (ms.m_pDeformer){ diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/ARB_multitexture.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/ARB_multitexture.h new file mode 100644 index 00000000000..acb16cf046f --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/ARB_multitexture.h @@ -0,0 +1,164 @@ +#ifndef __ARB_MULTITEXTURE_H__ +#define __ARB_MULTITEXTURE_H__ + +/** + Comment out defines GL_... 1, to disable compilation of each extension. + GL_ARB_multitexture is the minimum for using blender material settings. + For best functionality (GL_ARB_multitexture & GL_ARB_texture_env_combine) are needed. +*/ + +/* ---------------------------------------------------------------------------- + GL_ARB_multitexture +---------------------------------------------------------------------------- */ +#ifndef GL_ARB_multitexture + #define GL_ARB_multitexture 1 +#endif + +#ifdef GL_ARB_multitexture + #define GL_TEXTURE0_ARB 0x84C0 + #define GL_TEXTURE1_ARB 0x84C1 + #define GL_TEXTURE2_ARB 0x84C2 + #define GL_TEXTURE3_ARB 0x84C3 + #define GL_TEXTURE4_ARB 0x84C4 + #define GL_TEXTURE5_ARB 0x84C5 + #define GL_TEXTURE6_ARB 0x84C6 + #define GL_TEXTURE7_ARB 0x84C7 + #define GL_TEXTURE8_ARB 0x84C8 + #define GL_TEXTURE9_ARB 0x84C9 + #define GL_TEXTURE10_ARB 0x84CA + #define GL_ACTIVE_TEXTURE_ARB 0x84E0 + #define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 + #define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +#endif + + +/* ---------------------------------------------------------------------------- + GL_ARB_texture_env_combine +---------------------------------------------------------------------------- */ +#ifndef GL_ARB_texture_env_combine + #define GL_ARB_texture_env_combine 1 +#endif + +#ifdef GL_ARB_texture_env_combine + #define GL_COMBINE_ARB 0x8570 + #define GL_COMBINE_RGB_ARB 0x8571 + #define GL_COMBINE_ALPHA_ARB 0x8572 + #define GL_SOURCE0_RGB_ARB 0x8580 + #define GL_SOURCE1_RGB_ARB 0x8581 + #define GL_SOURCE2_RGB_ARB 0x8582 + #define GL_SOURCE0_ALPHA_ARB 0x8588 + #define GL_SOURCE1_ALPHA_ARB 0x8589 + #define GL_SOURCE2_ALPHA_ARB 0x858A + #define GL_OPERAND0_RGB_ARB 0x8590 + #define GL_OPERAND1_RGB_ARB 0x8591 + #define GL_OPERAND2_RGB_ARB 0x8592 + #define GL_OPERAND0_ALPHA_ARB 0x8598 + #define GL_OPERAND1_ALPHA_ARB 0x8599 + #define GL_OPERAND2_ALPHA_ARB 0x859A + #define GL_RGB_SCALE_ARB 0x8573 + #define GL_ADD_SIGNED_ARB 0x8574 + #define GL_INTERPOLATE_ARB 0x8575 + #define GL_SUBTRACT_ARB 0x84E7 + #define GL_CONSTANT_ARB 0x8576 + #define GL_PRIMARY_COLOR_ARB 0x8577 + #define GL_PREVIOUS_ARB 0x8578 +#endif + +/* ---------------------------------------------------------------------------- + GL_ARB_texture_cube_map +---------------------------------------------------------------------------- */ +#ifndef GL_ARB_texture_cube_map + #define GL_ARB_texture_cube_map 1 +#endif + +#ifdef GL_ARB_texture_cube_map + #define GL_NORMAL_MAP_ARB 0x8511 + #define GL_REFLECTION_MAP_ARB 0x8512 + #define GL_TEXTURE_CUBE_MAP_ARB 0x8513 + #define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 + #define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 + #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 + #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 + #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 + #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 + #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A + #define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B + #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C +#endif + +/* ---------------------------------------------------------------------------- + GL_ARB_shader_objects +---------------------------------------------------------------------------- */ +#ifndef GL_ARB_shader_objects + #define GL_ARB_shader_objects 1 +#endif + +#ifdef GL_ARB_shader_objects + #define GL_PROGRAM_OBJECT_ARB 0x8B40 + #define GL_SHADER_OBJECT_ARB 0x8B48 + #define GL_OBJECT_TYPE_ARB 0x8B4E + #define GL_OBJECT_SUBTYPE_ARB 0x8B4F + #define GL_FLOAT_VEC2_ARB 0x8B50 + #define GL_FLOAT_VEC3_ARB 0x8B51 + #define GL_FLOAT_VEC4_ARB 0x8B52 + #define GL_INT_VEC2_ARB 0x8B53 + #define GL_INT_VEC3_ARB 0x8B54 + #define GL_INT_VEC4_ARB 0x8B55 + #define GL_BOOL_ARB 0x8B56 + #define GL_BOOL_VEC2_ARB 0x8B57 + #define GL_BOOL_VEC3_ARB 0x8B58 + #define GL_BOOL_VEC4_ARB 0x8B59 + #define GL_FLOAT_MAT2_ARB 0x8B5A + #define GL_FLOAT_MAT3_ARB 0x8B5B + #define GL_FLOAT_MAT4_ARB 0x8B5C + #define GL_SAMPLER_1D_ARB 0x8B5D + #define GL_SAMPLER_2D_ARB 0x8B5E + #define GL_SAMPLER_3D_ARB 0x8B5F + #define GL_SAMPLER_CUBE_ARB 0x8B60 + #define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 + #define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 + #define GL_SAMPLER_2D_RECT_ARB 0x8B63 + #define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 + #define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 + #define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 + #define GL_OBJECT_LINK_STATUS_ARB 0x8B82 + #define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 + #define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 + #define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 + #define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 + #define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 + #define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 +#endif + +/* ---------------------------------------------------------------------------- + GL_ARB_vertex_shader +---------------------------------------------------------------------------- */ +#ifndef GL_ARB_vertex_shader + #define GL_ARB_vertex_shader 1 +#endif + +#ifdef GL_ARB_vertex_shader + #define GL_VERTEX_SHADER_ARB 0x8B31 + #define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A + #define GL_MAX_VARYING_FLOATS_ARB 0x8B4B + #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C + #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D + #define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 + #define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A +#endif + + +/* ---------------------------------------------------------------------------- + GL_ARB_fragment_shader +---------------------------------------------------------------------------- */ +#ifndef GL_ARB_fragment_shader + #define GL_ARB_fragment_shader 1 +#endif + +#ifdef GL_ARB_fragment_shader + #define GL_FRAGMENT_SHADER_ARB 0x8B30 + #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 + #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B +#endif + +#endif//__ARB_MULTITEXTURE_H__ diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp index cd37fbec502..71b68815c15 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp @@ -317,7 +317,99 @@ PFNGLPNTRIANGLESIATIPROC glPNTrianglesiATI; PFNGLPNTRIANGLESFATIPROC glPNTrianglesfATI; #endif +BL_EXTInfo RAS_EXT_support; + + +#if defined(GL_ARB_multitexture) +int max_texture_units = 2; + +PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; +PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB; +PFNGLMULTITEXCOORD1DARBPROC glMultiTexCoord1dARB; +PFNGLMULTITEXCOORD1DVARBPROC glMultiTexCoord1dvARB; +PFNGLMULTITEXCOORD1FARBPROC glMultiTexCoord1fARB; +PFNGLMULTITEXCOORD1FVARBPROC glMultiTexCoord1fvARB; +PFNGLMULTITEXCOORD1IARBPROC glMultiTexCoord1iARB; +PFNGLMULTITEXCOORD1IVARBPROC glMultiTexCoord1ivARB; +PFNGLMULTITEXCOORD1SARBPROC glMultiTexCoord1sARB; +PFNGLMULTITEXCOORD1SVARBPROC glMultiTexCoord1svARB; +PFNGLMULTITEXCOORD2DARBPROC glMultiTexCoord2dARB; +PFNGLMULTITEXCOORD2DVARBPROC glMultiTexCoord2dvARB; +PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB; +PFNGLMULTITEXCOORD2FVARBPROC glMultiTexCoord2fvARB; +PFNGLMULTITEXCOORD2IARBPROC glMultiTexCoord2iARB; +PFNGLMULTITEXCOORD2IVARBPROC glMultiTexCoord2ivARB; +PFNGLMULTITEXCOORD2SARBPROC glMultiTexCoord2sARB; +PFNGLMULTITEXCOORD2SVARBPROC glMultiTexCoord2svARB; +PFNGLMULTITEXCOORD3DARBPROC glMultiTexCoord3dARB; +PFNGLMULTITEXCOORD3DVARBPROC glMultiTexCoord3dvARB; +PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3fARB; +PFNGLMULTITEXCOORD3FVARBPROC glMultiTexCoord3fvARB; +PFNGLMULTITEXCOORD3IARBPROC glMultiTexCoord3iARB; +PFNGLMULTITEXCOORD3IVARBPROC glMultiTexCoord3ivARB; +PFNGLMULTITEXCOORD3SARBPROC glMultiTexCoord3sARB; +PFNGLMULTITEXCOORD3SVARBPROC glMultiTexCoord3svARB; +PFNGLMULTITEXCOORD4DARBPROC glMultiTexCoord4dARB; +PFNGLMULTITEXCOORD4DVARBPROC glMultiTexCoord4dvARB; +PFNGLMULTITEXCOORD4FARBPROC glMultiTexCoord4fARB; +PFNGLMULTITEXCOORD4FVARBPROC glMultiTexCoord4fvARB; +PFNGLMULTITEXCOORD4IARBPROC glMultiTexCoord4iARB; +PFNGLMULTITEXCOORD4IVARBPROC glMultiTexCoord4ivARB; +PFNGLMULTITEXCOORD4SARBPROC glMultiTexCoord4sARB; +PFNGLMULTITEXCOORD4SVARBPROC glMultiTexCoord4svARB; +#endif + +#if defined(GL_ARB_shader_objects) +PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; +PFNGLGETHANDLEARBPROC glGetHandleARB; +PFNGLDETACHOBJECTARBPROC glDetachObjectARB; +PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; +PFNGLSHADERSOURCEARBPROC glShaderSourceARB; +PFNGLCOMPILESHADERARBPROC glCompileShaderARB; +PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; +PFNGLATTACHOBJECTARBPROC glAttachObjectARB; +PFNGLLINKPROGRAMARBPROC glLinkProgramARB; +PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; +PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB; +PFNGLUNIFORM1FARBPROC glUniform1fARB; +PFNGLUNIFORM2FARBPROC glUniform2fARB; +PFNGLUNIFORM3FARBPROC glUniform3fARB; +PFNGLUNIFORM4FARBPROC glUniform4fARB; +PFNGLUNIFORM1IARBPROC glUniform1iARB; +PFNGLUNIFORM2IARBPROC glUniform2iARB; +PFNGLUNIFORM3IARBPROC glUniform3iARB; +PFNGLUNIFORM4IARBPROC glUniform4iARB; +PFNGLUNIFORM1FVARBPROC glUniform1fvARB; +PFNGLUNIFORM2FVARBPROC glUniform2fvARB; +PFNGLUNIFORM3FVARBPROC glUniform3fvARB; +PFNGLUNIFORM4FVARBPROC glUniform4fvARB; +PFNGLUNIFORM1IVARBPROC glUniform1ivARB; +PFNGLUNIFORM2IVARBPROC glUniform2ivARB; +PFNGLUNIFORM3IVARBPROC glUniform3ivARB; +PFNGLUNIFORM4IVARBPROC glUniform4ivARB; +PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB; +PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB; +PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB; +PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB; +PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; +PFNGLGETINFOLOGARBPROC glGetInfoLogARB; +PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB; +PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; +PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB; +PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB; +PFNGLGETUNIFORMIVARBPROC glGetUniformivARB; +PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB; +#endif + +#if defined(GL_ARB_vertex_shader) +PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB; +PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB; +PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; +#endif +#if defined(GL_EXT_blend_color) +PFNGLBLENDCOLOREXTPROC glBlendColorEXT; +#endif } // namespace bgl @@ -335,6 +427,7 @@ static void LinkExtensions() { static bool doDebugMessages = m_debug; extensions = STR_String((const char *) glGetString(GL_EXTENSIONS)).Explode(' '); + RAS_EXT_support = BL_EXTInfo(); #if defined(PFNGLPNTRIANGLESIATIPROC) if (QueryExtension("GL_ATI_pn_triangles")) @@ -351,12 +444,191 @@ static void LinkExtensions() } #endif - if (QueryExtension("GL_EXT_separate_specular_color")) - { - EnableExtension(_GL_EXT_separate_specular_color); - if (doDebugMessages) - std::cout << "Detected GL_EXT_separate_specular_color" << std::endl; - } +#ifdef GL_ARB_texture_env_combine + if (QueryExtension("GL_ARB_texture_env_combine")) + { + EnableExtension(_GL_ARB_texture_env_combine); + RAS_EXT_support._ARB_texture_env_combine = 1; + if (doDebugMessages) + { + std::cout << "Detected GL_ARB_texture_env_combine" << std::endl; + } + } +#endif + +#ifdef GL_ARB_texture_cube_map + if (QueryExtension("GL_ARB_texture_cube_map")) + { + EnableExtension(_GL_ARB_texture_cube_map); + RAS_EXT_support._ARB_texture_cube_map = 1; + if (doDebugMessages) + std::cout << "Detected GL_ARB_texture_cube_map" << std::endl; + } +#endif + +#ifdef GL_ARB_multitexture + if (QueryExtension("GL_ARB_multitexture")) + { + glActiveTextureARB = reinterpret_cast<PFNGLACTIVETEXTUREARBPROC>(bglGetProcAddress((const GLubyte *) "glActiveTextureARB")); + glClientActiveTextureARB = reinterpret_cast<PFNGLCLIENTACTIVETEXTUREARBPROC>(bglGetProcAddress((const GLubyte *) "glClientActiveTextureARB")); + glMultiTexCoord1dARB = reinterpret_cast<PFNGLMULTITEXCOORD1DARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord1dARB")); + glMultiTexCoord1dvARB = reinterpret_cast<PFNGLMULTITEXCOORD1DVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord1dvARB")); + glMultiTexCoord1fARB = reinterpret_cast<PFNGLMULTITEXCOORD1FARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord1fARB")); + glMultiTexCoord1fvARB = reinterpret_cast<PFNGLMULTITEXCOORD1FVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord1fvARB")); + glMultiTexCoord1iARB = reinterpret_cast<PFNGLMULTITEXCOORD1IARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord1iARB")); + glMultiTexCoord1ivARB = reinterpret_cast<PFNGLMULTITEXCOORD1IVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord1ivARB")); + glMultiTexCoord1sARB = reinterpret_cast<PFNGLMULTITEXCOORD1SARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord1sARB")); + glMultiTexCoord1svARB = reinterpret_cast<PFNGLMULTITEXCOORD1SVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord1svARB")); + glMultiTexCoord2dARB = reinterpret_cast<PFNGLMULTITEXCOORD2DARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord2dARB")); + glMultiTexCoord2dvARB = reinterpret_cast<PFNGLMULTITEXCOORD2DVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord2dvARB")); + glMultiTexCoord2fARB = reinterpret_cast<PFNGLMULTITEXCOORD2FARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord2fARB")); + glMultiTexCoord2fvARB = reinterpret_cast<PFNGLMULTITEXCOORD2FVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord2fvARB")); + glMultiTexCoord2iARB = reinterpret_cast<PFNGLMULTITEXCOORD2IARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord2iARB")); + glMultiTexCoord2ivARB = reinterpret_cast<PFNGLMULTITEXCOORD2IVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord2ivARB")); + glMultiTexCoord2sARB = reinterpret_cast<PFNGLMULTITEXCOORD2SARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord2sARB")); + glMultiTexCoord2svARB = reinterpret_cast<PFNGLMULTITEXCOORD2SVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord2svARB")); + glMultiTexCoord3dARB = reinterpret_cast<PFNGLMULTITEXCOORD3DARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord3dARB")); + glMultiTexCoord3dvARB = reinterpret_cast<PFNGLMULTITEXCOORD3DVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord3dvARB")); + glMultiTexCoord3fARB = reinterpret_cast<PFNGLMULTITEXCOORD3FARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord3fARB")); + glMultiTexCoord3fvARB = reinterpret_cast<PFNGLMULTITEXCOORD3FVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord3fvARB")); + glMultiTexCoord3iARB = reinterpret_cast<PFNGLMULTITEXCOORD3IARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord3iARB")); + glMultiTexCoord3ivARB = reinterpret_cast<PFNGLMULTITEXCOORD3IVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord3ivARB")); + glMultiTexCoord3sARB = reinterpret_cast<PFNGLMULTITEXCOORD3SARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord3sARB")); + glMultiTexCoord3svARB = reinterpret_cast<PFNGLMULTITEXCOORD3SVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord3svARB")); + glMultiTexCoord4dARB = reinterpret_cast<PFNGLMULTITEXCOORD4DARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord4dARB")); + glMultiTexCoord4dvARB = reinterpret_cast<PFNGLMULTITEXCOORD4DVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord4dvARB")); + glMultiTexCoord4fARB = reinterpret_cast<PFNGLMULTITEXCOORD4FARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord4fARB")); + glMultiTexCoord4fvARB = reinterpret_cast<PFNGLMULTITEXCOORD4FVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord4fvARB")); + glMultiTexCoord4iARB = reinterpret_cast<PFNGLMULTITEXCOORD4IARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord4iARB")); + glMultiTexCoord4ivARB = reinterpret_cast<PFNGLMULTITEXCOORD4IVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord4ivARB")); + glMultiTexCoord4sARB = reinterpret_cast<PFNGLMULTITEXCOORD4SARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord4sARB")); + glMultiTexCoord4svARB = reinterpret_cast<PFNGLMULTITEXCOORD4SVARBPROC>(bglGetProcAddress((const GLubyte *) "glMultiTexCoord4svARB")); + if (glActiveTextureARB && glClientActiveTextureARB && glMultiTexCoord1dARB && glMultiTexCoord1dvARB && glMultiTexCoord1fARB && glMultiTexCoord1fvARB && glMultiTexCoord1iARB && glMultiTexCoord1ivARB && glMultiTexCoord1sARB && glMultiTexCoord1svARB && glMultiTexCoord2dARB && glMultiTexCoord2dvARB && glMultiTexCoord2fARB && glMultiTexCoord2fvARB && glMultiTexCoord2iARB && glMultiTexCoord2ivARB && glMultiTexCoord2sARB && glMultiTexCoord2svARB && glMultiTexCoord3dARB && glMultiTexCoord3dvARB && glMultiTexCoord3fARB && glMultiTexCoord3fvARB && glMultiTexCoord3iARB && glMultiTexCoord3ivARB && glMultiTexCoord3sARB && glMultiTexCoord3svARB && glMultiTexCoord4dARB && glMultiTexCoord4dvARB && glMultiTexCoord4fARB && glMultiTexCoord4fvARB && glMultiTexCoord4iARB && glMultiTexCoord4ivARB && glMultiTexCoord4sARB && glMultiTexCoord4svARB) { + EnableExtension(_GL_ARB_multitexture); + RAS_EXT_support._ARB_multitexture = 1; + if (doDebugMessages) + std::cout << "Enabled GL_ARB_multitexture" << std::endl; + } else { + std::cout << "ERROR: GL_ARB_multitexture implementation is broken!" << std::endl; + } + } +#endif + + + +#ifdef GL_EXT_blend_color + if (QueryExtension("GL_EXT_blend_color")) + { + glBlendColorEXT = reinterpret_cast<PFNGLBLENDCOLOREXTPROC>(bglGetProcAddress((const GLubyte *) "glBlendColorEXT")); + if (glBlendColorEXT) { + EnableExtension(_GL_EXT_blend_color); + RAS_EXT_support._EXT_blend_color = 1; + if (doDebugMessages) + std::cout << "Enabled GL_EXT_blend_color" << std::endl; + } else { + std::cout << "ERROR: GL_EXT_blend_color implementation is broken!" << std::endl; + } + } +#endif + +#ifdef GL_ARB_shader_objects + if (QueryExtension("GL_ARB_shader_objects")) + { + glDeleteObjectARB = reinterpret_cast<PFNGLDELETEOBJECTARBPROC>(bglGetProcAddress((const GLubyte *) "glDeleteObjectARB")); + glGetHandleARB = reinterpret_cast<PFNGLGETHANDLEARBPROC>(bglGetProcAddress((const GLubyte *) "glGetHandleARB")); + glDetachObjectARB = reinterpret_cast<PFNGLDETACHOBJECTARBPROC>(bglGetProcAddress((const GLubyte *) "glDetachObjectARB")); + glCreateShaderObjectARB = reinterpret_cast<PFNGLCREATESHADEROBJECTARBPROC>(bglGetProcAddress((const GLubyte *) "glCreateShaderObjectARB")); + glShaderSourceARB = reinterpret_cast<PFNGLSHADERSOURCEARBPROC>(bglGetProcAddress((const GLubyte *) "glShaderSourceARB")); + glCompileShaderARB = reinterpret_cast<PFNGLCOMPILESHADERARBPROC>(bglGetProcAddress((const GLubyte *) "glCompileShaderARB")); + glCreateProgramObjectARB = reinterpret_cast<PFNGLCREATEPROGRAMOBJECTARBPROC>(bglGetProcAddress((const GLubyte *) "glCreateProgramObjectARB")); + glAttachObjectARB = reinterpret_cast<PFNGLATTACHOBJECTARBPROC>(bglGetProcAddress((const GLubyte *) "glAttachObjectARB")); + glLinkProgramARB = reinterpret_cast<PFNGLLINKPROGRAMARBPROC>(bglGetProcAddress((const GLubyte *) "glLinkProgramARB")); + glUseProgramObjectARB = reinterpret_cast<PFNGLUSEPROGRAMOBJECTARBPROC>(bglGetProcAddress((const GLubyte *) "glUseProgramObjectARB")); + glValidateProgramARB = reinterpret_cast<PFNGLVALIDATEPROGRAMARBPROC>(bglGetProcAddress((const GLubyte *) "glValidateProgramARB")); + glUniform1fARB = reinterpret_cast<PFNGLUNIFORM1FARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform1fARB")); + glUniform2fARB = reinterpret_cast<PFNGLUNIFORM2FARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform2fARB")); + glUniform3fARB = reinterpret_cast<PFNGLUNIFORM3FARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform3fARB")); + glUniform4fARB = reinterpret_cast<PFNGLUNIFORM4FARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform4fARB")); + glUniform1iARB = reinterpret_cast<PFNGLUNIFORM1IARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform1iARB")); + glUniform2iARB = reinterpret_cast<PFNGLUNIFORM2IARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform2iARB")); + glUniform3iARB = reinterpret_cast<PFNGLUNIFORM3IARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform3iARB")); + glUniform4iARB = reinterpret_cast<PFNGLUNIFORM4IARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform4iARB")); + glUniform1fvARB = reinterpret_cast<PFNGLUNIFORM1FVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform1fvARB")); + glUniform2fvARB = reinterpret_cast<PFNGLUNIFORM2FVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform2fvARB")); + glUniform3fvARB = reinterpret_cast<PFNGLUNIFORM3FVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform3fvARB")); + glUniform4fvARB = reinterpret_cast<PFNGLUNIFORM4FVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform4fvARB")); + glUniform1ivARB = reinterpret_cast<PFNGLUNIFORM1IVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform1ivARB")); + glUniform2ivARB = reinterpret_cast<PFNGLUNIFORM2IVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform2ivARB")); + glUniform3ivARB = reinterpret_cast<PFNGLUNIFORM3IVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform3ivARB")); + glUniform4ivARB = reinterpret_cast<PFNGLUNIFORM4IVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniform4ivARB")); + glUniformMatrix2fvARB = reinterpret_cast<PFNGLUNIFORMMATRIX2FVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniformMatrix2fvARB")); + glUniformMatrix3fvARB = reinterpret_cast<PFNGLUNIFORMMATRIX3FVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniformMatrix3fvARB")); + glUniformMatrix4fvARB = reinterpret_cast<PFNGLUNIFORMMATRIX4FVARBPROC>(bglGetProcAddress((const GLubyte *) "glUniformMatrix4fvARB")); + glGetObjectParameterfvARB = reinterpret_cast<PFNGLGETOBJECTPARAMETERFVARBPROC>(bglGetProcAddress((const GLubyte *) "glGetObjectParameterfvARB")); + glGetObjectParameterivARB = reinterpret_cast<PFNGLGETOBJECTPARAMETERIVARBPROC>(bglGetProcAddress((const GLubyte *) "glGetObjectParameterivARB")); + glGetInfoLogARB = reinterpret_cast<PFNGLGETINFOLOGARBPROC>(bglGetProcAddress((const GLubyte *) "glGetInfoLogARB")); + glGetAttachedObjectsARB = reinterpret_cast<PFNGLGETATTACHEDOBJECTSARBPROC>(bglGetProcAddress((const GLubyte *) "glGetAttachedObjectsARB")); + glGetUniformLocationARB = reinterpret_cast<PFNGLGETUNIFORMLOCATIONARBPROC>(bglGetProcAddress((const GLubyte *) "glGetUniformLocationARB")); + glGetActiveUniformARB = reinterpret_cast<PFNGLGETACTIVEUNIFORMARBPROC>(bglGetProcAddress((const GLubyte *) "glGetActiveUniformARB")); + glGetUniformfvARB = reinterpret_cast<PFNGLGETUNIFORMFVARBPROC>(bglGetProcAddress((const GLubyte *) "glGetUniformfvARB")); + glGetUniformivARB = reinterpret_cast<PFNGLGETUNIFORMIVARBPROC>(bglGetProcAddress((const GLubyte *) "glGetUniformivARB")); + glGetShaderSourceARB = reinterpret_cast<PFNGLGETSHADERSOURCEARBPROC>(bglGetProcAddress((const GLubyte *) "glGetShaderSourceARB")); + if (glDeleteObjectARB && glGetHandleARB && glDetachObjectARB && glCreateShaderObjectARB && glShaderSourceARB && glCompileShaderARB && glCreateProgramObjectARB && glAttachObjectARB && glLinkProgramARB && glUseProgramObjectARB && glValidateProgramARB && glUniform1fARB && glUniform2fARB && glUniform3fARB && glUniform4fARB && glUniform1iARB && glUniform2iARB && glUniform3iARB && glUniform4iARB && glUniform1fvARB && glUniform2fvARB && glUniform3fvARB && glUniform4fvARB && glUniform1ivARB && glUniform2ivARB && glUniform3ivARB && glUniform4ivARB && glUniformMatrix2fvARB && glUniformMatrix3fvARB && glUniformMatrix4fvARB && glGetObjectParameterfvARB && glGetObjectParameterivARB && glGetInfoLogARB && glGetAttachedObjectsARB && glGetUniformLocationARB && glGetActiveUniformARB && glGetUniformfvARB && glGetUniformivARB && glGetShaderSourceARB) { + EnableExtension(_GL_ARB_shader_objects); + RAS_EXT_support._ARB_shader_objects =1; + if (doDebugMessages) + std::cout << "Enabled GL_ARB_shader_objects" << std::endl; + } else { + std::cout << "ERROR: GL_ARB_shader_objects implementation is broken!" << std::endl; + } + } +#endif + +#ifdef GL_ARB_vertex_shader + if (QueryExtension("GL_ARB_vertex_shader")) + { + glBindAttribLocationARB = reinterpret_cast<PFNGLBINDATTRIBLOCATIONARBPROC>(bglGetProcAddress((const GLubyte *) "glBindAttribLocationARB")); + glGetActiveAttribARB = reinterpret_cast<PFNGLGETACTIVEATTRIBARBPROC>(bglGetProcAddress((const GLubyte *) "glGetActiveAttribARB")); + glGetAttribLocationARB = reinterpret_cast<PFNGLGETATTRIBLOCATIONARBPROC>(bglGetProcAddress((const GLubyte *) "glGetAttribLocationARB")); + if (glBindAttribLocationARB && glGetActiveAttribARB && glGetAttribLocationARB) { + EnableExtension(_GL_ARB_vertex_shader); + RAS_EXT_support._ARB_vertex_shader = 1; + if (doDebugMessages) + std::cout << "Enabled GL_ARB_vertex_shader" << std::endl; + } else { + std::cout << "ERROR: GL_ARB_vertex_shader implementation is broken!" << std::endl; + } + } +#endif + +#ifdef GL_ARB_fragment_shader + if (QueryExtension("GL_ARB_fragment_shader")) + { + EnableExtension(_GL_ARB_fragment_shader); + RAS_EXT_support._ARB_fragment_shader = 1; + if (doDebugMessages) + std::cout << "Detected GL_ARB_fragment_shader" << std::endl; + } +#endif + + +#ifdef GL_EXT_texture3D + if (QueryExtension("GL_EXT_texture3D")) + { + /* not using 3d textures... but, using GL_TEXTURE_WRAP_R_EXT*/ + EnableExtension(_GL_EXT_texture3D); + RAS_EXT_support._EXT_texture3D = 1; + if (doDebugMessages) + std::cout << "Enabled GL_EXT_texture3D" << std::endl; + } +#endif + + if (QueryExtension("GL_EXT_separate_specular_color")) + { + EnableExtension(_GL_EXT_separate_specular_color); + if (doDebugMessages) + std::cout << "Detected GL_EXT_separate_specular_color" << std::endl; + } doDebugMessages = false; } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.h index a8ca69950af..5fd94ae53b7 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.h @@ -32,6 +32,10 @@ #ifndef __RAS_GLEXTENSIONMANAGER_H__ #define __RAS_GLEXTENSIONMANAGER_H__ +#ifndef APIENTRY +#define APIENTRY +#endif + #ifdef __APPLE__ #include <OpenGL/gl.h> #else @@ -39,6 +43,7 @@ #endif #include "EXT_separate_specular_color.h" +#include "ARB_Multitexture.h" namespace bgl { @@ -369,6 +374,209 @@ extern PFNGLPNTRIANGLESIATIPROC glPNTrianglesiATI; extern PFNGLPNTRIANGLESFATIPROC glPNTrianglesfATI; #endif + +// quick runtime checks +typedef struct BL_EXTInfo +{ + BL_EXTInfo(): + _ARB_multitexture(0), + _ARB_texture_env_combine(0), + _EXT_blend_color(0), + _ARB_texture_cube_map(0), + _ARB_shader_objects(0), + _ARB_vertex_shader(0), + _ARB_fragment_shader(0), + _EXT_texture3D(0) + { + // + } + bool _ARB_multitexture; + bool _ARB_texture_env_combine; + bool _EXT_blend_color; + bool _ARB_texture_cube_map; + bool _ARB_shader_objects; + bool _ARB_vertex_shader; + bool _ARB_fragment_shader; + bool _EXT_texture3D; +}BL_EXTInfo; + +extern BL_EXTInfo RAS_EXT_support; + + +#ifdef GL_EXT_blend_color +typedef void (APIENTRY* PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +extern PFNGLBLENDCOLOREXTPROC glBlendColorEXT; +#endif + +#ifdef GL_ARB_multitexture +extern int max_texture_units; +typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); + + +extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; +extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB; +extern PFNGLMULTITEXCOORD1DARBPROC glMultiTexCoord1dARB; +extern PFNGLMULTITEXCOORD1DVARBPROC glMultiTexCoord1dvARB; +extern PFNGLMULTITEXCOORD1FARBPROC glMultiTexCoord1fARB; +extern PFNGLMULTITEXCOORD1FVARBPROC glMultiTexCoord1fvARB; +extern PFNGLMULTITEXCOORD1IARBPROC glMultiTexCoord1iARB; +extern PFNGLMULTITEXCOORD1IVARBPROC glMultiTexCoord1ivARB; +extern PFNGLMULTITEXCOORD1SARBPROC glMultiTexCoord1sARB; +extern PFNGLMULTITEXCOORD1SVARBPROC glMultiTexCoord1svARB; +extern PFNGLMULTITEXCOORD2DARBPROC glMultiTexCoord2dARB; +extern PFNGLMULTITEXCOORD2DVARBPROC glMultiTexCoord2dvARB; +extern PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB; +extern PFNGLMULTITEXCOORD2FVARBPROC glMultiTexCoord2fvARB; +extern PFNGLMULTITEXCOORD2IARBPROC glMultiTexCoord2iARB; +extern PFNGLMULTITEXCOORD2IVARBPROC glMultiTexCoord2ivARB; +extern PFNGLMULTITEXCOORD2SARBPROC glMultiTexCoord2sARB; +extern PFNGLMULTITEXCOORD2SVARBPROC glMultiTexCoord2svARB; +extern PFNGLMULTITEXCOORD3DARBPROC glMultiTexCoord3dARB; +extern PFNGLMULTITEXCOORD3DVARBPROC glMultiTexCoord3dvARB; +extern PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3fARB; +extern PFNGLMULTITEXCOORD3FVARBPROC glMultiTexCoord3fvARB; +extern PFNGLMULTITEXCOORD3IARBPROC glMultiTexCoord3iARB; +extern PFNGLMULTITEXCOORD3IVARBPROC glMultiTexCoord3ivARB; +extern PFNGLMULTITEXCOORD3SARBPROC glMultiTexCoord3sARB; +extern PFNGLMULTITEXCOORD3SVARBPROC glMultiTexCoord3svARB; +extern PFNGLMULTITEXCOORD4DARBPROC glMultiTexCoord4dARB; +extern PFNGLMULTITEXCOORD4DVARBPROC glMultiTexCoord4dvARB; +extern PFNGLMULTITEXCOORD4FARBPROC glMultiTexCoord4fARB; +extern PFNGLMULTITEXCOORD4FVARBPROC glMultiTexCoord4fvARB; +extern PFNGLMULTITEXCOORD4IARBPROC glMultiTexCoord4iARB; +extern PFNGLMULTITEXCOORD4IVARBPROC glMultiTexCoord4ivARB; +extern PFNGLMULTITEXCOORD4SARBPROC glMultiTexCoord4sARB; +extern PFNGLMULTITEXCOORD4SVARBPROC glMultiTexCoord4svARB; +#endif + + +#ifdef GL_ARB_shader_objects +typedef char GLcharARB; +typedef unsigned int GLhandleARB; +typedef void (APIENTRY* PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef GLhandleARB (APIENTRY* PFNGLGETHANDLEARBPROC) (GLenum pname); +typedef void (APIENTRY* PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); +typedef GLhandleARB (APIENTRY* PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (APIENTRY* PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); +typedef void (APIENTRY* PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef GLhandleARB (APIENTRY* PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef void (APIENTRY* PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (APIENTRY* PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (APIENTRY* PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (APIENTRY* PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (APIENTRY* PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); +typedef void (APIENTRY* PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRY* PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRY* PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRY* PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); +typedef void (APIENTRY* PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); +typedef void (APIENTRY* PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRY* PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRY* PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRY* PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRY* PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRY* PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRY* PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRY* PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRY* PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRY* PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRY* PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRY* PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRY* PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRY* PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params); +typedef void (APIENTRY* PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); +typedef void (APIENTRY* PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); +typedef void (APIENTRY* PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); +typedef GLint (APIENTRY* PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); +typedef void (APIENTRY* PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +typedef void (APIENTRY* PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params); +typedef void (APIENTRY* PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params); +typedef void (APIENTRY* PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); + +extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; +extern PFNGLGETHANDLEARBPROC glGetHandleARB; +extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB; +extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; +extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB; +extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB; +extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; +extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB; +extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB; +extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; +extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB; +extern PFNGLUNIFORM1FARBPROC glUniform1fARB; +extern PFNGLUNIFORM2FARBPROC glUniform2fARB; +extern PFNGLUNIFORM3FARBPROC glUniform3fARB; +extern PFNGLUNIFORM4FARBPROC glUniform4fARB; +extern PFNGLUNIFORM1IARBPROC glUniform1iARB; +extern PFNGLUNIFORM2IARBPROC glUniform2iARB; +extern PFNGLUNIFORM3IARBPROC glUniform3iARB; +extern PFNGLUNIFORM4IARBPROC glUniform4iARB; +extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB; +extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB; +extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB; +extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB; +extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB; +extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB; +extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB; +extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB; +extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB; +extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB; +extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB; +extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB; +extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; +extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB; +extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB; +extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; +extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB; +extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB; +extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB; +extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB; +#endif + +#ifdef GL_ARB_vertex_shader +typedef void (APIENTRY* PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name); +typedef void (APIENTRY* PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +typedef GLint (APIENTRY* PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); + +extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB; +extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB; +extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; +#endif + } /* namespace bgl */ diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 47c4c4c3e66..fa507b85b1b 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -177,6 +177,10 @@ bool RAS_OpenGLRasterizer::Init() m_blueback = 0.4375; m_alphaback = 0.0; + m_ambr = 0.0f; + m_ambg = 0.0f; + m_ambb = 0.0f; + glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -187,6 +191,32 @@ bool RAS_OpenGLRasterizer::Init() } +void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) +{ + m_ambr = red; + m_ambg = green; + m_ambb = blue; +} + + +void RAS_OpenGLRasterizer::SetAlphaTest(bool enable) +{ + if (enable) + { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.6f); + } + else glDisable(GL_ALPHA_TEST); +} + + + +void RAS_OpenGLRasterizer::SetAmbient(float factor) +{ + float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); +} + void RAS_OpenGLRasterizer::SetBackColor(float red, float green, @@ -1160,6 +1190,768 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(const vecVertexArray & vertexa } //for each vertexarray } +void RAS_OpenGLRasterizer::IndexPrimitivesMulti( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + int mode, + class RAS_IPolyMaterial* polymat, + class RAS_IRenderTools* rendertools, + bool useObjectColor, + const MT_Vector4& rgbacolor + ) +{ +#ifdef GL_ARB_multitexture + + GLenum drawmode; + switch (mode) + { + case 0: + drawmode = GL_TRIANGLES; + break; + case 1: + drawmode = GL_LINES; + break; + case 2: + drawmode = GL_QUADS; + break; + default: + drawmode = GL_LINES; + break; + } + + const RAS_TexVert* vertexarray ; + unsigned int numindices,vt; + + for (vt=0;vt<vertexarrays.size();vt++) + { + vertexarray = &((*vertexarrays[vt]) [0]); + const KX_IndexArray & indexarray = (*indexarrays[vt]); + numindices = indexarray.size(); + const unsigned int enabled = polymat->GetEnabled(); + unsigned int unit; + + if (!numindices) + break; + + int vindex=0; + switch (mode) + { + case 1: + { + glBegin(GL_LINES); + vindex=0; + for (unsigned int i=0;i<numindices;i+=2) + { + glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ()); + glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ()); + } + glEnd(); + } + break; + case 2: + { + glBegin(GL_QUADS); + vindex=0; + if (useObjectColor) + { + for (unsigned int i=0;i<numindices;i+=4) + { + + glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); + + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + } + } + else + { + for (unsigned int i=0;i<numindices;i+=4) + { + // This looks curiously endian unsafe to me. + // However it depends on the way the colors are packed into + // the m_rgba field of RAS_TexVert + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + } + } + glEnd(); + break; + } + case 0: + { + glBegin(GL_TRIANGLES); + vindex=0; + if (useObjectColor) + { + for (unsigned int i=0;i<numindices;i+=3) + { + + glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); + + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + } + } + else + { + for (unsigned int i=0;i<numindices;i+=3) + { + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + } + } + glEnd(); + break; + } + default: + { + } + } // switch + } // for each vertexarray +#endif// GL_ARB_multitexture + +} + +void RAS_OpenGLRasterizer::IndexPrimitivesMulti_Ex(const vecVertexArray & vertexarrays, + const vecIndexArrays & indexarrays, + int mode, + class RAS_IPolyMaterial* polymat, + class RAS_IRenderTools* rendertools, + bool useObjectColor, + const MT_Vector4& rgbacolor + ) +{ +#ifdef GL_ARB_multitexture + bool recalc; + GLenum drawmode; + switch (mode) + { + case 0: + drawmode = GL_TRIANGLES; + break; + case 1: + drawmode = GL_LINES; + break; + case 2: + drawmode = GL_QUADS; + break; + default: + drawmode = GL_LINES; + break; + } + + const RAS_TexVert* vertexarray ; + unsigned int numindices,vt; + + for (vt=0;vt<vertexarrays.size();vt++) + { + vertexarray = &((*vertexarrays[vt]) [0]); + const KX_IndexArray & indexarray = (*indexarrays[vt]); + numindices = indexarray.size(); + const unsigned int enabled = polymat->GetEnabled(); + unsigned int unit; + + if (!numindices) + continue; + + int vindex=0; + switch (mode) + { + case 1: + { + glBegin(GL_LINES); + vindex=0; + for (unsigned int i=0;i<numindices;i+=2) + { + glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ()); + glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ()); + } + glEnd(); + } + break; + case 2: + { + glBegin(GL_QUADS); + vindex=0; + if (useObjectColor) + { + for (unsigned int i=0;i<numindices;i+=4) + { + MT_Point3 mv1, mv2, mv3, mv4, fnor; + /* Calc a new face normal */ + + if (vertexarray[(indexarray[vindex])].getFlag() & TV_CALCFACENORMAL) + recalc= true; + else + recalc=false; + + if (recalc){ + mv1 = MT_Point3(vertexarray[(indexarray[vindex])].getLocalXYZ()); + mv2 = MT_Point3(vertexarray[(indexarray[vindex+1])].getLocalXYZ()); + mv3 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ()); + mv4 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ()); + + fnor = (((mv2-mv1).cross(mv3-mv2))+((mv4-mv3).cross(mv1-mv4))).safe_normalized(); + + glNormal3f(fnor[0], fnor[1], fnor[2]); + } + + glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); + + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + } + } + else + { + for (unsigned int i=0;i<numindices;i+=4) + { + // This looks curiously endian unsafe to me. + // However it depends on the way the colors are packed into + // the m_rgba field of RAS_TexVert + MT_Point3 mv1, mv2, mv3, mv4, fnor; + /* Calc a new face normal */ + + if (vertexarray[(indexarray[vindex])].getFlag() & TV_CALCFACENORMAL) + recalc= true; + else + recalc=false; + + + if (recalc){ + mv1 = MT_Point3(vertexarray[(indexarray[vindex])].getLocalXYZ()); + mv2 = MT_Point3(vertexarray[(indexarray[vindex+1])].getLocalXYZ()); + mv3 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ()); + mv4 = MT_Point3(vertexarray[(indexarray[vindex+3])].getLocalXYZ()); + + fnor = (((mv2-mv1).cross(mv3-mv2))+((mv4-mv3).cross(mv1-mv4))).safe_normalized(); + + glNormal3f(fnor[0], fnor[1], fnor[2]); + } + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + } + } + glEnd(); + break; + } + case 0: + { + glBegin(GL_TRIANGLES); + vindex=0; + if (useObjectColor) + { + for (unsigned int i=0;i<numindices;i+=3) + { + MT_Point3 mv1, mv2, mv3, fnor; + /* Calc a new face normal */ + + if (vertexarray[(indexarray[vindex])].getFlag() & TV_CALCFACENORMAL) + recalc= true; + else + recalc=false; + + if (recalc){ + mv1 = MT_Point3(vertexarray[(indexarray[vindex])].getLocalXYZ()); + mv2 = MT_Point3(vertexarray[(indexarray[vindex+1])].getLocalXYZ()); + mv3 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ()); + + fnor = ((mv2-mv1).cross(mv3-mv2)).safe_normalized(); + glNormal3f(fnor[0], fnor[1], fnor[2]); + } + + glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); + + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + } + } + else + { + for (unsigned int i=0;i<numindices;i+=3) + { + MT_Point3 mv1, mv2, mv3, fnor; + /* Calc a new face normal */ + + if (vertexarray[(indexarray[vindex])].getFlag() & TV_CALCFACENORMAL) + recalc= true; + else + recalc=false; + + + if (recalc){ + mv1 = MT_Point3(vertexarray[(indexarray[vindex])].getLocalXYZ()); + mv2 = MT_Point3(vertexarray[(indexarray[vindex+1])].getLocalXYZ()); + mv3 = MT_Point3(vertexarray[(indexarray[vindex+2])].getLocalXYZ()); + + fnor = ((mv2-mv1).cross(mv3-mv2)).safe_normalized(); + glNormal3f(fnor[0], fnor[1], fnor[2]); + } + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + + glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA())); + if (!recalc) + glNormal3fv(vertexarray[(indexarray[vindex])].getNormal()); + // ------------------------------ + for(unit =0; unit<enabled; unit++) { + if( vertexarray[(indexarray[vindex])].getFlag() & TV_2NDUV && + vertexarray[(indexarray[vindex])].getUnit() == unit ) + { + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV2()); + continue; + } + bgl::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, vertexarray[(indexarray[vindex])].getUV1()); + } + // ------------------------------ + glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ()); + vindex++; + } + } + glEnd(); + break; + } + default: + { + } + + } // switch + } // for each vertexarray +#endif +} + void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) @@ -1347,6 +2139,13 @@ void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float dif glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); } +void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e) +{ + GLfloat mat_emit [] = {eX,eY,eZ,e}; + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit); +} + + double RAS_OpenGLRasterizer::GetTime() { return m_time; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index ad6bdf8c1d1..7e45b1c434b 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -71,6 +71,10 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer float m_greenback; float m_blueback; float m_alphaback; + + float m_ambr; + float m_ambg; + float m_ambb; double m_time; MT_CmMatrix4x4 m_viewmatrix; @@ -130,6 +134,8 @@ public: virtual void SetFocalLength(const float focallength); virtual float GetFocalLength(); + virtual void SetAlphaTest(bool enable); + virtual void SwapBuffers(); virtual void IndexPrimitives( const vecVertexArray& vertexarrays, @@ -161,6 +167,25 @@ public: const MT_Vector4& rgbacolor ); + virtual void IndexPrimitivesMulti( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + int mode, + class RAS_IPolyMaterial* polymat, + class RAS_IRenderTools* rendertools, + bool useObjectColor, + const MT_Vector4& rgbacolor); + + virtual void IndexPrimitivesMulti_Ex( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + int mode, + class RAS_IPolyMaterial* polymat, + class RAS_IRenderTools* rendertools, + bool useObjectColor, + const MT_Vector4& rgbacolor); + + virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat); virtual void SetProjectionMatrix(const MT_Matrix4x4 & mat); virtual void SetViewMatrix( @@ -231,6 +256,15 @@ public: float difZ, float diffuse ); + virtual void SetEmissive(float eX, + float eY, + float eZ, + float e + ); + + virtual void SetAmbientColor(float red, float green, float blue); + virtual void SetAmbient(float factor); + virtual void SetPolygonOffset(float mult, float add); virtual void DrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color) diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index c68806d500c..9e9b5725b6b 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -45,9 +45,11 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, { xyz.getValue(m_localxyz); uv.getValue(m_uv1); + uv.getValue(m_uv2); // ..py access SetRGBA(rgba); SetNormal(normal); m_flag = flag; + m_unit = 2; } const MT_Point3& RAS_TexVert::xyz() @@ -78,6 +80,10 @@ void RAS_TexVert::SetUV(const MT_Point2& uv) uv.getValue(m_uv1); } +void RAS_TexVert::SetUV2(const MT_Point2& uv) +{ + uv.getValue(m_uv2); +} void RAS_TexVert::SetRGBA(const unsigned int rgba) @@ -90,6 +96,12 @@ void RAS_TexVert::SetFlag(const short flag) { m_flag = flag; } + +void RAS_TexVert::SetUnit(const unsigned int u) +{ + m_unit = u<=TV_MAX?u:TV_MAX; +} + void RAS_TexVert::SetNormal(const MT_Vector3& normal) { normal.getValue(m_normal); @@ -103,6 +115,12 @@ const float* RAS_TexVert::getUV1 () const return m_uv1; } +const float* RAS_TexVert::getUV2 () const +{ + return m_uv2; +} + + const float* RAS_TexVert::getNormal() const { @@ -137,6 +155,13 @@ short RAS_TexVert::getFlag() const return m_flag; } + +unsigned int RAS_TexVert::getUnit() const +{ + return m_unit; +} + + void RAS_TexVert::getOffsets(void* &xyz, void* &uv1, void* &rgba, void* &normal) const { xyz = (void *) m_localxyz; diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index 650618e1dc1..f58eca7637f 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -40,7 +40,10 @@ static MT_Point3 g_pt3; static MT_Point2 g_pt2; -#define TV_CALCFACENORMAL 0x0001 +#define TV_CALCFACENORMAL 0x0001 +#define TV_2NDUV 0x0002 + +#define TV_MAX 3//match Def in BL_Material.h #define RAS_TexVert_INLINE 1 @@ -48,19 +51,21 @@ class RAS_TexVert { float m_localxyz[3]; // 3*4 = 12 - float m_uv1[2]; // 2*4 = 8 + float m_uv1[2]; // 2*4 = 8 + float m_uv2[2]; // 2*4 = 8 ... python access to this set unsigned int m_rgba; // 4 float m_tangent[4]; // 4*2 = 8 float m_normal[3]; // 3*2 = 6 - short m_flag; // 2 - //--------- - // 40 + short m_flag; // 2 + unsigned int m_unit; // 4 + //--------- + // 52 //32 bytes total size, fits nice = 52 = not fit nice. // We'll go for 64 bytes total size - 24 bytes left. - public: short getFlag() const; + unsigned int getUnit() const; RAS_TexVert()// :m_xyz(0,0,0),m_uv(0,0),m_rgba(0) {} @@ -76,7 +81,11 @@ public: const float* getUV1 () const { return m_uv1; }; - + + const float* getUV2 () const { + return m_uv2; + }; + const float* getLocalXYZ() const { return m_localxyz; }; @@ -90,15 +99,19 @@ public: } #else const float* getUV1 () const; + const float* getUV2 () const; const float* getNormal() const; const float* getLocalXYZ() const; const unsigned char* getRGBA() const; #endif void SetXYZ(const MT_Point3& xyz); void SetUV(const MT_Point2& uv); + void SetUV2(const MT_Point2& uv); + void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); void SetFlag(const short flag); + void SetUnit(const unsigned u); void SetRGBA(const MT_Vector4& rgba); const MT_Point3& xyz(); |