diff options
author | Erwin Coumans <blender@erwincoumans.com> | 2006-01-06 06:46:54 +0300 |
---|---|---|
committer | Erwin Coumans <blender@erwincoumans.com> | 2006-01-06 06:46:54 +0300 |
commit | 2e6d57618232b8b4ce8e5afe84fd278041cbbbfe (patch) | |
tree | c0f05e6b59aada420dd600f1138e9149b97d9e9d /source/gameengine/Ketsji | |
parent | ef520a8cc9e863aa234be0ee60d1038e7ec8fc44 (diff) |
Sorry to break the cvs-closed status, so if you really need to make a new 2.40 build, just disable the game engine if it doesn't compile for a platform. Again, sorry if this breaks non-windows platforms, but I hope people help to get this amazing fix working for all platforms. Armature-fixing contribution from Snailrose. Also lots of cool things from Snailrose and Lagan.
Armatures are back
Split screen
Double sided lightning
Ambient lighting
Alpha test
Material IPO support (one per object atm)
Blender materials
GLSL shaders - Python access
Up to three texture samplers from the material panel ( 2D & Cube map )
Python access to a second set of uv coordinates
See http://www.elysiun.com/forum/viewtopic.php?t=58057
Diffstat (limited to 'source/gameengine/Ketsji')
21 files changed, 1672 insertions, 75 deletions
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': |